deepseek-harness/.agents/notes/implemented/feature/2026-08-22-standard-acp-automation-controls.zh.md
2026-08-22 19:44:00 +08:00

9.8 KiB
Raw Blame History

Agent Note:标准 ACP v1 自动化控制

状态:已实现

English | 中文

本说明仅取代 ACP 作为纯自动化协议 中仅支持提示词的协议清单。该决策关于禁止 ACP 成为第二套产品 UI 的规定仍具权威性。

问题

纯自动化 ACP 桥接层可以创建新会话、一次提交一个提示词、取消提示词、接收已提交 assistant 消息,并回答一次性权限请求。通用外部自动化控制器仍需依赖私有进程知识,才能发现模型、挂载 MCP 服务器、在重启后找到持久会话、恢复会话、独立关闭一个会话,以及观察 reasoning、工具或上下文压力进度。如果在集成专用 runtime 中复制这些控制,ACP 只会名义上可互操作,而 DSH 自动化仍依赖私有旁路协议。

稳定 ACP v1 协议已经定义所需的控制词汇。增加私有 _meta、自定义方法、用例专用环境处理或展示投影会割裂该词汇,并重新引入纯自动化决策已经移除的 UI 耦合。

决策

@deepseek-ai/dsh-acp 实现通用控制器需要的完整标准 ACP v1 自动化子集:session/new、session/list、session/resume、session/close、session/prompt、session/cancel、session/set_config_option、JSON-RPC $/cancel_request、session/update 和 session/request_permission。仓库内每条连接的两端都使用 @agentclientprotocol/sdk 1.4 的 app/context 接口。

能力会省略未支持的方法和功能。DSH 不增加自定义方法、能力标记或 _meta,也不为客户端元数据赋予私有含义。session/load、session/delete、session/fork、附加目录、SSE 和 ACP 传输 MCP、模式、命令、计划、终端、客户端文件系统操作和 elicitation 仍不受支持。会话控制和语义更新是自动化协议数据;它们不会使 ACP 成为人工 UI。

Per-session 所有权

每个已公布 Agent 由一个 AcpSession 模块拥有,该模块同时拥有所选模型状态、请求 MCP 挂载、单提示词槽位、有序更新链和记忆化关闭操作。全局事件监听器只识别确切 Agent 或 Session,再委托给该模块。模块会在内存中把准入快照与已识别消息关联到 inbox claim 时刻,再将其固定到已准入轮次。因此,图片能力检查、提示词变量、请求 header 和每个模型步骤都使用同一个提供方/模型/reasoning tuple,而普通持久用户 source 保持不变。并发配置变更从下一个 ACP 轮次开始生效。

显式 session/close、连接丢失和插件释放调用同一个关闭操作。它会先取消准入和 Agent 工作,再等待;随后 drain 已提交更新和可继续后代、flush 持久化,并释放 Agent scope 及其 MCP 客户端。关闭流程会保留事件路由直到 drain 完成。只有所有自有会话 teardown 都完成后才报告失败,其他前端的 Agent 和后代不受影响。

持久会话控制

完整 ACP 生命周期支持要求挂载会话持久化。session/list 读取已实体化的顶层 header,排除活动会话和后代会话,按规范物理 cwd 过滤,按创建时间和 id 排序,并通过不透明 keyset cursor 返回有界页面。摘要有意省略标题和展示元数据。

session/new 会显式要求持久化在不虚构会话事件的情况下实体化 live session header,因此即使空会话也可以关闭、列出和恢复。其他前端仍保留持久化 seam 的惰性默认行为,不会实体化被放弃的空会话。session/resume 拒绝活动 id,以及非顶层或未知的持久 id;在组合 Agent 前校验请求的规范 cwd;恢复持久日志但不向客户端重放;挂载该请求提供的 MCP 声明。session/close 让持久日志可供后续进程使用。

持久化有意把 create(meta) 视为 live registration:JSONL 在首次追加事件前不创建 artifact,SQLite 在此之前不创建 row。该默认行为会移除被放弃的空会话,但 ACP 不能继承它,因为 session/new 会在任何提示词出现前公布会话身份,而进程可能在返回成功响应后、收到 session/close 前停止。桥接层只在 Agent 和 MCP 组合成功后、返回 session/new 前执行实体化;组合失败仍不留下残留物,每个已返回 id 则都能在重启后继续存在。

ensureMaterialized(session) 接收确切 live Session,使 coordinator 先 flush 该会话,再通过现有 per-session 写入链,使用已注册的不可变 header 串行执行仅 header 实体化。JSONL 写入一个 header frame,SQLite 写入一条 metadata row;重复调用幂等,不支持该能力的 backend 会让会话创建失败,而不会承诺无法提供的可恢复性。让 create 全面 eager 会改变所有前端放弃会话的行为;追加 synthetic event 会仅为触发存储而虚构 sequence 与 replay 事实;等到关闭时再写入则会让持久性与进程丢失竞争。

标准配置选项

建议性 LLM catalog 现在服务于另一个自动化 consumer,但不会成为请求校验。ACP 公开按提供方分组的 model select,其不透明值保留提供方/模型对;还会公开来自已解析确切模型的依赖 reasoning_effort select。具有 efforts 但没有 adapter 配置默认值的模型会包含 Provider default,以保留省略状态并让提供方自行选择。新建、恢复和设置响应都返回完整状态。Adapter 拓扑事件发出 config_option_update;每个会话按接收顺序串行处理变更。配置的 ACP 提供方/模型仍是初始选择;未列出的配置路由会合成到返回选项中,而不会被拒绝。

标准 MCP 映射

session/new 和 session/resume 接受标准 stdio 和 Streamable HTTP MCP 声明。Stdio 使用会话 cwd;HTTP 使用已声明 URL 和 header;两者都保留 dsh-mcp-client 的超时和重连默认值。名称、命令、URL、环境项、header 和重复的规范化 namespace 都会在 Agent 公布前校验。初始连接或发现失败会回滚尚未公布的 Agent。

MCP namespace reservation 跟随最近的 DSH registration scope,而不是进程 root。独立 Agent scope 可以使用同一服务器名,同一 Agent 内的重复名称仍会失败。Scoped disposal 会释放工具、传输和 reservation。

ACP 客户端是受信任的控制器:stdio 声明授权执行进程,HTTP 声明授权携带其 header 发起请求。DSH 不增加每服务器私有 cwd 或超时字段。工具挂载后,普通 DSH 工具策略仍然约束调用。

语义更新投影

只有已提交的持久事实会进入 session/update。Assistant 文本/图片变成 agent_message_chunk;reasoning 变成 agent_thought_chunk;工具调用/结果变成通用 tool_call 和 tool_call_update;已知的测量上下文压力与容量变成 usage_update;adapter 拓扑变化变成 config_option_update。持久消息 id 和工具调用 id 保留关联。规范 DSH 工具名作为标准工具调用 title。

Per-session 链会串行处理所有更新,并在提示词完成前 drain。引用工具调用的权限请求只会在该工具调用通知 drain 后发送。原始模型 delta、重试尝试、卡片、终端状态、diff、位置、计划、标题、todo 和不受支持内容不会进入 wire。

session/cancel 和 $/cancel_request 进入同一个提示词自有取消路径。关联结尾只映射到标准 stop reason 和 JSON-RPC error;模型输出达到上限时报告 max_tokens。ACP 不返回额外 DSH 结果结构。

考虑过的替代方案

增加私有控制器扩展。 已拒绝,因为标准 ACP v1 已经承载所需生命周期、配置、MCP、取消、权限和语义更新概念。私有扩展会使通用 SDK 客户端不完整。

恢复之前的编辑器投影。 已拒绝,因为计划、终端、diff、卡片、导航和人工 elicitation 属于展示职责。语义工具和 reasoning 事实可以作为有用的自动化遥测,而无需导入展示模块。

实现所有 ACP 会话方法。 已拒绝。列出、恢复和关闭已经完成持久自动化生命周期。加载/重放、删除和 fork 会引入本用例不需要的独立 transcript、破坏性存储和 lineage 语义。

使用不稳定 provider 方法发现模型。 已拒绝,因为标准会话配置选项可以表达该选择,并保持会话 scope。

把每个 DSH runtime 字段复制到 ACP 元数据。 已拒绝,因为精确 token 明细、私有结果状态、程序化展示名称和每 MCP tunable 没有稳定 ACP v1 对应项。

验证

聚焦测试覆盖:无私有元数据的确切能力公布;模型/reasoning 选择、无效和并发变更、拓扑更新以及图片路由固定;stdio/HTTP MCP 设置、声明回滚、scope 隔离、恢复和释放;列表分页、规范 workspace 校验、活动冲突、关闭/恢复和重启恢复;消息/思考/工具/用量顺序与 id;工具先于权限;标准 stop reason;请求和会话取消;连接丢失 teardown。

通用 keyless conformance 测试会启动真实 ACP demo 两次,并且只使用公开 ACP SDK:选择模型和 reasoning effort、挂载 MCP 服务器、执行工具轮次、观察标准更新、关闭、重启、列出、恢复和取消。它不包含集成专用名称、依赖、元数据或环境行为。

后果

外部自动化项目可以通过稳定 ACP v1 使用 DSH,而无需维护 DSH 专用 runtime 协议。桥接层的控制接口变大,但仍小于 UI:它拥有生命周期和语义互操作,而人工展示和交互仍属于产品客户端。

持久生命周期和请求 MCP 挂载让会话创建更严格。配置错误和初始 MCP 失败会在公布前拒绝,关闭会等待真实完全停稳和持久化。这是避免部分 Agent、泄漏工具或孤儿进程所需的所有权证明。