From 987a08ad78ae1a5c04a798efef830c06e9c2266f Mon Sep 17 00:00:00 2001 From: mesalogo Date: Thu, 3 Sep 2026 15:59:05 +0800 Subject: [PATCH] fix: allow remote Execute without bubblewrap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remote Hosts without the Ask-only bubblewrap tool could report matching Agent and Runtime versions but fail project creation because the Agent hid the Runtime ACP capability entirely. The Agent now advertises a verified Runtime independently of bubblewrap, so Execute can start directly while Ask keeps its existing read-only bubblewrap boundary. Release note: 修复远程 Host 缺少 bubblewrap 时 Execute 项目无法创建的问题;更新到 Agent 0.11.16 后,Execute 不再受 Ask 专用系统工具影响。 --- agent-runtime-lock.json | 2 +- docs/features/remote-host/technical-design.md | 12 +++++++++--- src/agent-daemon/runtime-composition.test.ts | 6 ++---- src/agent-daemon/runtime-composition.ts | 18 +----------------- 4 files changed, 13 insertions(+), 25 deletions(-) diff --git a/agent-runtime-lock.json b/agent-runtime-lock.json index 4d12223e..89b93232 100644 --- a/agent-runtime-lock.json +++ b/agent-runtime-lock.json @@ -1,6 +1,6 @@ { "formatVersion": 1, - "agentVersion": "0.11.15", + "agentVersion": "0.11.16", "protocol": { "major": 2, "minor": 0 diff --git a/docs/features/remote-host/technical-design.md b/docs/features/remote-host/technical-design.md index 9b3a7d8a..21d21ad2 100644 --- a/docs/features/remote-host/technical-design.md +++ b/docs/features/remote-host/technical-design.md @@ -12,7 +12,7 @@ Linux x64/arm64、取消和离线 GoodBuddy 传输的真实 Host 验收。 Windows 到 Linux x64 的安装、Agent-owned Prompt、Agent 本地模型 gateway、断线恢复、 同一 OpenCode Session 续接、取消和终态清理已经使用真实模型与工具验证。Agent `0.11.14` 已通过独立 workflow 发布 Linux x64/arm64 复合包和签名累计目录;当前未发布 -Agent 源码 lock 为 `0.11.15`,Desktop 恢复候选为 `0.12.2`,等待各自独立发布审批。 +Agent 源码 lock 为 `0.11.16`,Desktop 恢复候选为 `0.12.2`,等待各自独立发布审批。 现有源码显示本地与远端 OpenCode 原生 Task,并取消 GoodBuddy 对生产 Prompt 的 固定墙钟总时限。失败的 `agent-v0.11.3` 保持不可变且未发布。 @@ -192,7 +192,8 @@ Ask 使用系统 `bwrap`: search、edit、execute、未知工具以及只提供持久授权的请求全部拒绝。 `allow_once` 只解决 OpenCode 发起原生读取前的 ACP 协商,真正的文件系统边界仍是只读 -`bwrap` bind。Host 缺少 `bwrap` 时 Ask 不可用。 +`bwrap` bind。Host 缺少 `bwrap` 时 Ask 启动失败,但不影响 Runtime 能力声明或 Execute +直接启动。 ### Execute @@ -349,7 +350,7 @@ model bridge,以及生命周期和恢复逻辑。单元测试、mock、fixture - 2026-08 的本地 fixture 完整验证 Linux x64 Agent `0.11.2-e2e.12`、Node `24.19.0` 和 Agent protocol `2.0`;当时没有 arm64 fixture,因此该记录不能作为当前独立发布 的双架构验收。Agent `0.11.10` 后续已由原生 workflow 发布并公开验证双架构工件; - 当前源码 lock 固定为 `0.11.15`;正式发布状态以独立 Agent Release 与签名 catalog 为准。 + 当前源码 lock 固定为 `0.11.16`;正式发布状态以独立 Agent Release 与签名 catalog 为准。 - 2026-08-30 在共享 Linux x64 Host 的隔离测试 HOME 中验证当前 `0.11.13` 源码候选: 签名 Runtime 清单的测试墙钟上限为 1 秒,模型桥首轮故意延迟 2.515 秒后 Prompt 仍在 5.770 秒正常完成;随后 OpenCode 原生 Task 依次产生 `running`、`completed` 子 Agent @@ -397,6 +398,11 @@ model bridge,以及生命周期和恢复逻辑。单元测试、mock、fixture workflow 与 Release Notes 聚焦测试 `106/106` 通过、1 项平台用例跳过;全量 `npm test` 为 `3478` 通过、`51` 跳过,typecheck 与 lint 通过。本轮没有新增模型调用, 也未在本地运行 production build、package 或安装探针。 +- 2026-09-03 使用包含当前 Runtime capability 修复的源码 harness,在共享 Linux x64 Host + 的唯一 `/tmp/goodbuddy-e2e-runtime-capability-*` 隔离 HOME 中读取签名 Runtime 副本。 + Agent 成功报告已登记 OpenCode Runtime,Execute 随后直接启动 OpenCode 而未经过 + `bwrap`;Runtime owner 和隔离目录均已清理,未修改 Host current Agent/Runtime。 + 本次只验证能力声明和真实进程启动,没有发送 Prompt,真实文本模型调用 0 次。 - 正常 Host 更新路径把 Linux x64 Host 的 Agent 更新为 `0.11.2-e2e.12`,并确认 OpenCode Runtime 已安装版本与所需版本均为 `1.18.9`。 - 一条新的 Ask 用户操作只提交一次。OpenCode 先在 build 模型轮次请求一个原生 diff --git a/src/agent-daemon/runtime-composition.test.ts b/src/agent-daemon/runtime-composition.test.ts index 21b42cb0..faeebde8 100644 --- a/src/agent-daemon/runtime-composition.test.ts +++ b/src/agent-daemon/runtime-composition.test.ts @@ -37,7 +37,7 @@ afterEach(() => { }) describe('production Runtime composition', () => { - it('loads metadata installed after startup and caches the registered Runtime identity', async () => { + it('loads Runtime metadata independently of Ask-only Host prerequisites', async () => { const fixture = await createRuntimeBundleTestFixture() const root = fixture.root temporaryPaths.push(root) @@ -62,7 +62,6 @@ describe('production Runtime composition', () => { blobSink: async () => {}, agentExecutablePath, reportError, - prerequisitesAvailable: async () => true, verificationEnvironment: 'test', filesystemPlatform: 'win32' }) @@ -128,7 +127,7 @@ describe('production Runtime composition', () => { events.close() }) - it('composes all autonomous ACP methods but advertises no Runtime when prerequisites fail', async () => { + it('composes all autonomous ACP methods when no Runtime is installed', async () => { const root = temporaryDirectory() const runtimeRoot = resolve(root, 'runtimes') const stateDirectory = resolve(root, 'state') @@ -155,7 +154,6 @@ describe('production Runtime composition', () => { releaseKeyRegistry, runtimeLock: {} as RemoteRuntimeLock, registry, - prerequisitesAvailable: async () => false, verificationEnvironment: 'test', filesystemPlatform: 'win32' }) diff --git a/src/agent-daemon/runtime-composition.ts b/src/agent-daemon/runtime-composition.ts index 8e537e97..271b23b1 100644 --- a/src/agent-daemon/runtime-composition.ts +++ b/src/agent-daemon/runtime-composition.ts @@ -46,8 +46,6 @@ import { } from './agent-model-gateway' import type { AgentDiagnosticLog } from './diagnostic-log' -const BWRAP_EXECUTABLE = '/usr/bin/bwrap' - export type ProductionRuntimeProtocol = { runtimes: ReturnType methods: RuntimeAcpBackend['methods'] @@ -85,7 +83,6 @@ export type ProductionRuntimeCompositionOptions = { releaseKeyRegistry?: AgentReleaseKeyRegistry runtimeLock?: RemoteRuntimeLock registry?: RuntimeBundleRegistry - prerequisitesAvailable?: () => boolean | Promise launchProcess?: typeof launchDirectLinuxStdioProcessOwner reconcileOrphanedProcesses?: ( installationId: string @@ -222,9 +219,6 @@ export async function createProductionRuntimeProtocol( }) return await source() } - const prerequisites = - options.prerequisitesAvailable ?? - productionRuntimePrerequisitesAvailable const launchProcess = options.launchProcess ?? launchDirectLinuxStdioProcessOwner let backend: RuntimeAcpBackend @@ -328,8 +322,7 @@ export async function createProductionRuntimeProtocol( options.agentExecutablePath === undefined || !(await executableAvailable( resolve(options.agentExecutablePath) - )) || - !(await prerequisites()) + )) ) { return [] } @@ -540,12 +533,3 @@ function bindingDirectoryDigest( ])) .digest('hex') } - -async function productionRuntimePrerequisitesAvailable(): Promise { - try { - await access(BWRAP_EXECUTABLE, constants.X_OK) - return true - } catch { - return false - } -}