ACP Bridge 与执行队列
理解工作区 child 复用、prompt FIFO、模型切换和早期事件缓冲。
@qwen-code/acp-bridge 在 HTTP 层与 qwen --acp child 之间维护逻辑会话、事件与审批。一个工作区 runtime 拥有自己的 bridge;多个逻辑 session 可以共享同一个 child,但不同 workspace runtimes 不共享 bridge 或 child。
核心对象
| 对象 | 责任 |
|---|---|
| HttpAcpBridge | spawn/attach、load/resume、prompt/cancel、审批与工作区 RPC |
| AcpChannel | stream、kill、killSync、exited,抽象 child 传输 |
| BridgeClient | ACP ClientSideConnection 与 permission/file/session 回调 |
| SessionEntry | 会话、事件总线、prompt/model 队列、client 与恢复状态 |
| ChannelInfo | channel、关联 session、待恢复 ID 和 isDying |
默认 ChannelFactory 启动 qwen --acp 子进程,测试可注入 inMemoryChannel。构造 bridge 是同步操作;child 可由预热提前建立,也可在首次使用时启动。
创建与附加
spawnOrAttach 检查 cwd 是否匹配绑定的 canonical workspace。single scope 已有 defaultEntry 时增加 attachCount、登记 clientId,并返回 attached:true;需要新 session 时使用 ACP newSession。
首次 child 连接需 ACP initialize,默认期限 10 秒。clientId 格式为 [A-Za-z0-9._:-]{1,128};格式合法不代表拥有独立身份认证。
maxSessions 默认 32;内部 BridgeOptions 中 0/Infinity 表示不限,NaN 或负数拒绝。HTTP/CLI 可有自己的验证和能力边界,不应将内部 TypeScript 取值直接当作所有 CLI 参数值。
两条串行队列
同一 session 的 promptQueue 保证 ACP 一次只有一个 active prompt。前一个 prompt 的错误不会污染队尾而阻止后续请求,但原调用方仍收到自己的 rejection。
modelChangeQueue 对同一会话的模型切换按序处理,避免并发 attach 指定不同模型时竞态。prompt originator 用于审批上下文;不能只根据当前任意 SSE 连接猜测发起人。
child 退出与 prompt promise 竞争结算,使进程崩溃能及时向调用方传播,而不是无限等待模型返回。
创建期间的早期事件
newSession 尚未返回时,MCP discovery 可能已经发出扩展通知。BridgeClient 为未登记的 session 暂存早期事件,避免 session 建立后回放缺少创建期警告。
缓冲最多 64 个 session、每 session 32 个事件,TTL 为 60000ms。它是有限创建期缓冲,不是持久消息队列或完整恢复日志。
文件与资源引用
BridgeFileSystem 可代理 ACP 文本读写。通用 bridge 的 delegateReadTextFileToClient 默认 true;同主机 runtime 设为 false,让普通文本读取留在 child,最终文本写入仍委派。具体路径策略要结合文件服务判断,不能由这一开关推断任意路径可写。
非 file:// 的 resource_link 转换为模型文本时保留 @URI;若客户端提供 name,还附上 JSON 引号包裹的 original filename,避免引号和换行混淆。没有 name 时保留 URI-only;这一转换本身不下载资源,也不从 URL 路径猜测文件名。
公开入口与扩展方法
使用 @qwen-code/acp-bridge 及其 eventBus/status 子路径,CLI 的 serve/acp-session-bridge.ts 是兼容门面。工作区状态、MCP restart、recap、btw、context usage、tasks 和工具快照通过 bridge 对应方法接入。
可选 externalToolGuard 只接受所属 channel 对当前 active prompt 的调用;它不是全部进程行为的通用拦截器。使用范围见Tool Guard。