fix: skip repeated OpenCode binary validation

OpenCode startup on Linux ARM could run a --version probe before launching the configured Runtime and recheck registered remote binary metadata. Execution now trusts the selected path and registered manifest identity after setup-time verification, so switching and cold launch avoid duplicate binary work.

Release note: 优化 Linux ARM 上切换 OpenCode 的启动速度;已安装或已登记的 Runtime 在执行时不再重复启动或检查二进制。
This commit is contained in:
mesalogo
2026-09-02 22:41:50 +08:00
parent cdecb584d5
commit dc36e7a967
6 changed files with 119 additions and 13 deletions
+1
View File
@@ -678,6 +678,7 @@ async function defaultDetectBinary(
return detectRuntimeBinary({
binaryPath: configuredPath,
bundledPath,
validation: 'path-only',
binaryNames: [runtime],
label: 'OpenCode CLI'
})
+24 -1
View File
@@ -1,6 +1,6 @@
import { EventEmitter } from 'node:events'
import { realpath } from 'node:fs/promises'
import { basename, dirname } from 'node:path'
import { basename, dirname, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import { afterEach, describe, expect, it, vi } from 'vitest'
import {
@@ -93,6 +93,29 @@ describe('runtime discovery', () => {
expect(detection.version).toMatch(/^\d+\.\d+\.\d+/u)
})
it('trusts a configured execution path without reading or launching it', async () => {
process.env.PATH = ''
process.env.Path = ''
const candidate = resolve(
dirname(fileURLToPath(import.meta.url)),
'runtime-that-does-not-exist'
)
const detection = await detectRuntimeBinary({
binaryPath: candidate,
validation: 'path-only',
binaryNames: ['binary-that-does-not-exist'],
label: 'Managed Runtime'
})
expect(detection).toEqual({
available: true,
path: candidate,
source: 'configured',
detail: 'Managed Runtime 已就绪'
})
})
it('rejects relative configured paths without resolving them from cwd', async () => {
process.env.PATH = ''
process.env.Path = ''
+38 -1
View File
@@ -25,6 +25,7 @@ const VERSION_TERMINATION_WAIT_MS = 500
export type RuntimeBinaryDiscoveryInput = {
binaryPath: string
bundledPath?: string
validation?: 'execute' | 'canonical-file' | 'path-only'
bundledValidation?: 'execute' | 'canonical-file'
bundledVersion?: string
allowAutomaticDiscovery?: boolean
@@ -333,11 +334,24 @@ export async function detectRuntimeBinary(
if (!bundledPath) {
return undefined
}
if (input.validation === 'path-only') {
return isAbsolute(bundledPath)
? availableDetection(
input.label,
normalize(bundledPath),
input.bundledVersion,
'bundled'
)
: undefined
}
const canonicalPath = await canonicalFile(bundledPath)
if (!canonicalPath) {
return undefined
}
if (input.bundledValidation === 'canonical-file') {
if (
(input.bundledValidation ?? input.validation) ===
'canonical-file'
) {
return availableDetection(
input.label,
canonicalPath,
@@ -359,10 +373,24 @@ export async function detectRuntimeBinary(
if (configuredPath) {
if (!isAbsolute(configuredPath)) {
configuredPathProblem = 'relative'
} else if (input.validation === 'path-only') {
return availableDetection(
input.label,
normalize(configuredPath),
undefined,
'configured'
)
} else {
const canonicalPath = await canonicalFile(configuredPath)
if (!canonicalPath) {
configuredPathProblem = 'invalid'
} else if (input.validation === 'canonical-file') {
return availableDetection(
input.label,
canonicalPath,
undefined,
'configured'
)
} else {
const validation = await validateRuntimeVersion(canonicalPath)
if (validation.valid) {
@@ -391,6 +419,15 @@ export async function detectRuntimeBinary(
continue
}
foundAutomaticCandidate = true
if (
input.validation === 'canonical-file' ||
input.validation === 'path-only'
) {
return availableDetection(
input.label,
canonicalPath
)
}
const validation = await validateRuntimeVersion(canonicalPath)
if (validation.valid) {
return availableDetection(