fix: allow slower OpenCode startup on Linux ARM
OpenCode health polling restored a ten-second startup limit, causing Linux ARM systems and QEMU environments that became healthy just after that boundary to be reported unavailable. Managed local OpenCode now retains health-based readiness detection while allowing up to thirty seconds for startup. Release note: 修复部分 Linux ARM 设备切换 OpenCode 时因启动超过 10 秒而误报超时的问题;健康检查现在最多等待 30 秒。
This commit is contained in:
@@ -212,6 +212,9 @@ package format v1 归档已经包含固定 Agent 和 Node,可直接用于 Host
|
|||||||
|
|
||||||
跨架构打包前,确认目标架构的 OpenCode 资源已经准备完成。不要用其他架构的二进制替代目标资源。
|
跨架构打包前,确认目标架构的 OpenCode 资源已经准备完成。不要用其他架构的二进制替代目标资源。
|
||||||
|
|
||||||
|
GoodBuddy 管理的本机 OpenCode 启动后会轮询已认证的 loopback health 接口,最多等待
|
||||||
|
30 秒。该窗口用于兼容 Linux ARM 等较慢环境;不要改回依赖 stdout 文案或 10 秒固定上限。
|
||||||
|
|
||||||
## GoodBuddy Agent 工件
|
## GoodBuddy Agent 工件
|
||||||
|
|
||||||
面向用户发布的是按远端 Host 架构区分的复合 `.gbagent`,每个包同时包含签名
|
面向用户发布的是按远端 Host 架构区分的复合 `.gbagent`,每个包同时包含签名
|
||||||
|
|||||||
@@ -969,6 +969,37 @@ describe('OpenCodeRuntime embedded launcher', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('allows ARM-class startup to become healthy after ten seconds', async () => {
|
||||||
|
vi.useFakeTimers()
|
||||||
|
try {
|
||||||
|
const child = fakeChild()
|
||||||
|
let healthy = false
|
||||||
|
const checkServerHealth = vi.fn(async () => healthy)
|
||||||
|
const { deps } = dependencies(child, {
|
||||||
|
checkServerHealth
|
||||||
|
})
|
||||||
|
const runtime = new OpenCodeRuntime(options(), deps)
|
||||||
|
let settled = false
|
||||||
|
const statusPromise = runtime.getStatus().finally(() => {
|
||||||
|
settled = true
|
||||||
|
})
|
||||||
|
|
||||||
|
await vi.advanceTimersByTimeAsync(10_100)
|
||||||
|
expect(settled).toBe(false)
|
||||||
|
|
||||||
|
healthy = true
|
||||||
|
await vi.advanceTimersByTimeAsync(100)
|
||||||
|
await expect(statusPromise).resolves.toMatchObject({
|
||||||
|
available: true
|
||||||
|
})
|
||||||
|
expect(checkServerHealth).toHaveBeenCalled()
|
||||||
|
|
||||||
|
await runtime.dispose()
|
||||||
|
} finally {
|
||||||
|
vi.useRealTimers()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
it('times out, terminates the process tree, and does not expose stderr', async () => {
|
it('times out, terminates the process tree, and does not expose stderr', async () => {
|
||||||
const child = fakeChild()
|
const child = fakeChild()
|
||||||
const secret = 'private-config-token'
|
const secret = 'private-config-token'
|
||||||
@@ -983,7 +1014,7 @@ describe('OpenCodeRuntime embedded launcher', () => {
|
|||||||
|
|
||||||
expect(status).toMatchObject({
|
expect(status).toMatchObject({
|
||||||
available: false,
|
available: false,
|
||||||
detail: 'OpenCode Server 启动超时(10 秒)'
|
detail: 'OpenCode Server 启动超时(30 秒)'
|
||||||
})
|
})
|
||||||
expect(status.detail).not.toContain(secret)
|
expect(status.detail).not.toContain(secret)
|
||||||
expect(child.kill).toHaveBeenCalledWith('SIGTERM')
|
expect(child.kill).toHaveBeenCalledWith('SIGTERM')
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ import {
|
|||||||
import { toOpenCodeSubagentEvent } from './opencode-subagent'
|
import { toOpenCodeSubagentEvent } from './opencode-subagent'
|
||||||
import { promptWithUntrustedConversationHistory } from './runtime-conversation-history'
|
import { promptWithUntrustedConversationHistory } from './runtime-conversation-history'
|
||||||
|
|
||||||
const STARTUP_TIMEOUT_MS = 10_000
|
const STARTUP_TIMEOUT_MS = 30_000
|
||||||
const STARTUP_POLL_INTERVAL_MS = 100
|
const STARTUP_POLL_INTERVAL_MS = 100
|
||||||
const STARTUP_PROBE_TIMEOUT_MS = 500
|
const STARTUP_PROBE_TIMEOUT_MS = 500
|
||||||
const CONTROL_REQUEST_TIMEOUT_MS = 30_000
|
const CONTROL_REQUEST_TIMEOUT_MS = 30_000
|
||||||
@@ -1079,7 +1079,7 @@ export class OpenCodeRuntime implements AgentRuntime {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const timeout = setTimeout(() => {
|
const timeout = setTimeout(() => {
|
||||||
fail('OpenCode Server 启动超时(10 秒)')
|
fail('OpenCode Server 启动超时(30 秒)')
|
||||||
}, this.dependencies.startupTimeoutMs)
|
}, this.dependencies.startupTimeoutMs)
|
||||||
|
|
||||||
if (!stdout || !stderr) {
|
if (!stdout || !stderr) {
|
||||||
|
|||||||
Reference in New Issue
Block a user