claw-code ACP/Zed 与 JSON-RPC 状态契约解析:以 truthful unsupported 契约服务编辑器生态探测
2026/9/18 7:26:18 网站建设 项目流程

claw-code ACP/Zed 与 JSON-RPC 状态契约解析:以 truthful unsupported 契约服务编辑器生态探测

【免费下载链接】claw-codeAn agent-managed museum exhibit, built in Rust with Gajae-Code / LazyCodex — developed and maintained with no human intervention.项目地址: https://gitcode.com/gh_mirrors/claudeco/claw-code

本篇文章基于仓库契约文档 docs/g011-acp-json-rpc-status-contract.md,系统讲解 claw-code 2.0 如何将 ACP/Zed 与 JSON-RPC 能力面收敛为稳定的"状态查询契约":哪些命令被定义为合法状态查询、它们返回什么样的机器可读 JSON 信封、错误调用如何被归类,以及真实协议服务为何被推迟(deferral gate)。读完本文,你将掌握如何用claw acp系列命令在编辑器探针(editor probes)与 CI 检查中正确探测能力状态,并理解这套"诚实的不支持"(truthful unsupported)设计背后的契约纪律。

为什么需要一份"状态契约"而非隐藏的守护进程

在 claw-code 的演进中,ACP(Agent Client Protocol)与 Zed 编辑器集成、JSON-RPC 服务这类能力,容易让外部系统误以为存在一个"隐藏的守护进程"(hidden daemon)。G011 契约的核心立场是:当前公共能力面(public surface)是一个诚实报告"不支持"的状态面,而不是一个未暴露的常驻服务。也就是说,claw acp这一系列命令存在的意义不是假装提供协议服务,而是为桌面端、市场(marketplace)与编辑器集成提供稳定、可探测、不会误导消费者的能力声明。

从仓库实现看,这一设计贯穿 CLI 解析层:rust/crates/rusty-claude-cli/src/main.rs 中parse_acp_args对 ACP 子命令做了白名单式解析,只接受空参数与serve,其余一律拒绝(详见下文"不支持的调用"一节);而状态输出本身则通过CliAction::Acp分发到print_acp_status,以纯文本或 JSON 两种格式打印状态。整条路径没有任何 socket 绑定、没有 daemon 进程,也没有 JSON-RPC endpoint——这与文档声明的"不启动 daemon、不暴露端点"完全一致。

支持的状态查询命令

按照契约文档,以下命令是合法的状态查询(status queries),均以退出码0结束

claw acp claw acp serve claw --acp claw -acp claw acp --output-format json claw acp serve --output-format json
命令形式说明
claw acp基础状态查询,纯文本输出
claw acp serveserve当前刻意作为 status 的别名,不绑定 socket、不启动 daemon、不暴露 JSON-RPC endpoint
claw --acp/claw -acp等价的别名形式,便于不同习惯的调用方
claw acp --output-format json状态查询 + 机器可读 JSON 信封(见下节)
claw acp serve --output-format jsonserve别名的 JSON 形态

源码层面,--acp-acp两个别名在参数归一化阶段被转换为acp子命令(见 rust/crates/rusty-claude-cli/src/main.rs 中"--acp" | "-acp"的分支处理),因此它们与claw acp走完全相同的分发路径,保证六种写法的行为一致。帮助文本同样只宣传claw acp [serve]这一种可发现形式,并在--help中明确标注"currently unsupported"(见该文件claw acp [serve]的 help 条目),避免用户产生能力幻觉。

JSON 信封:稳定的机器可读状态面

claw acp --output-format json返回一个为编辑器探针与 CI 检查设计的稳定信封,契约文档给出的完整示例为:

{ "schema_version": "1.0", "kind": "acp", "status": "unsupported", "phase": "discoverability_only", "supported": false, "exit_code": 0, "serve_alias_only": true, "protocol": { "name": "ACP/Zed", "json_rpc": false, "daemon": false, "endpoint": null, "serve_starts_daemon": false } }

信封字段语义如下:

字段类型含义
schema_versionstring信封自身的模式版本,当前为"1.0",作为向后兼容的判据
kindstring固定为"acp",用于标识该信封属于 ACP 状态面
statusstring能力状态;文档以"unsupported"作为契约目标形态
phasestring"discoverability_only",说明当前仅处于"可发现性"阶段
supportedbooleanfalse,明确声明协议未被支持
exit_codenumber0,与状态查询退出码一致,便于 shell 层直接透传
serve_alias_onlybooleantrue,声明serve仅是指令别名而非真实服务
protocol.namestring"ACP/Zed"
protocol.json_rpcbooleanfalse,明确无 JSON-RPC 能力
protocol.daemonbooleanfalse,明确无守护进程
protocol.endpointnull无监听端点
protocol.serve_starts_daemonbooleanfalseserve不会拉起 daemon

需要指出的是,仓库当前源码 rust/crates/rusty-claude-cli/src/main.rs 中acp_status_json()实现的信封在稳定字段上保持一致(schema_version: "1.0"kind: "acp"supported: falseprotocol.json_rpc/daemon/endpoint/serve_starts_daemon等),同时额外携带status: "not_implemented"actionmessagelaunch_commandcontractsaliases等运行时信息,并在contracts.blocking_gates中列出阻塞真实实现的契约门(详见"推迟门(Deferral Gate)"一节)。这意味着契约文档描述的是稳定消费面,而源码实现是这一消费面的运行时投影——两者在核心判据字段上保持一致,这正是下面要强调的防御性消费原则。

消费者应如何校验

文档明确要求:消费方应检查kind == "acp"supported == falseprotocol.json_rpc == false,而不是根据命令是否存在来推断能力支持。这一原则至关重要:

  • 命令存在 ≠ 能力可用,claw acp存在恰恰是为了诚实地声明"暂不支持";
  • 只检查supported可能遗漏协议细节(例如未来supported: truejson_rpc: false的中间态);
  • 三字段联合判断才能覆盖"命令存在但协议未就绪"的所有组合。

集成方在 CI 或编辑器插件里做能力探测时,应解析该 JSON 而非正则抓取帮助文本,这正是--output-format json信封存在的意义。仓库测试 rust/crates/rusty-claude-cli/tests/output_format_contract.rs 中acp_guidance_emits_json_when_requested对上述核心字段逐一断言(kindschema_versionsupportedprotocol.json_rpcprotocol.daemonendpoint为 null 等),并验证内部追踪 ID(如discoverability_trackingtrackingrecommended_workflows)不会泄漏进公开 JSON——公开面只暴露契约允许的字段。

不支持的调用:错误信封与退出码 1

形如claw acp start的畸形 ACP 调用会被拒绝:以退出码1结束。在--output-format json模式下,stderr 走 CLI 通用错误信封,设置如下判据:

{ "type": "error", "kind": "unsupported_acp_invocation", "exit_code": 1 }

这一行为在源码中非常清晰:parse_acp_args(rust/crates/rusty-claude-cli/src/main.rs)只放行[](即claw acp)与["serve"](即claw acp serve),其余参数一律返回Err,错误消息以unsupported_acp_invocation前缀开头并附带\n分隔的修复提示(提示用户改用claw acpclaw acp serve)。该Err最终被顶层错误处理捕获:在--output-format json激活时,rust/crates/rusty-claude-cli/src/main.rs 的main/run错误路径会调用classify_error_kind将消息归类为unsupported_acp_invocation,并组装包含type: "error"error_kindhintexit_code: 1的 JSON 错误信封输出。同一归类逻辑的单元测试也覆盖了"unsupported ACP invocation. Use claw acp."这类消息的分类结果。

契约文档强调这种"白名单拒绝"的价值:畸形调用不静默、不假装成功,而是给出可机器判别的错误类别可人类阅读的修复提示。集成方在探测脚本中遇到unsupported_acp_invocation时,应当将其视为"调用方式错误"而非"服务故障",并可以据hint字段向用户展示修复建议。

推迟门(Deferral Gate):真实协议服务何时落地

契约文档明确:真实的 ACP/Zed 或 JSON-RPC serve 工作,在路线图中 task packets、session control、event/report schemas 等契约稳定之前保持推迟。源码中这一决定被显式编码进 JSON 信封的contracts.blocking_gates字段:

"contracts": { "blocking_gates": [ "task_packet_schema", "session_control_schema", "event_report_schema" ], "stable_status_surface": "claw acp [serve] --output-format json", "unsupported_invocation_kind": "unsupported_acp_invocation" }

这一设计的动机在文档中表述为:防止桌面端、市场与编辑器集成在 CLI/文件/API 契约就绪之前,成为另一种"事实来源"(alternate sources of truth)。换言之,claw-code 不希望编辑器插件先于核心契约锁定行为语义,否则后续契约演进会撕裂生态。推迟门的实质是一种契约纪律——能力面的开放顺序必须与数据面契约(任务包、会话控制、事件/报告)的成熟度对齐。

从仓库路线图 ROADMAP.md 的演进记录看,这一顺序是有据可循的:结构化任务包(typed task packet format)已由 rust/crates/runtime/src/task_packet.rs 实现(TaskPacket结构、校验、序列化与TaskScope解析),会话控制(session_control)在 rust/crates/runtime/src/session_control.rs 中提供SessionStore等实现,事件/报告 schema 则由 rust/crates/runtime/src/report_schema.rs 承担。这三者正是blocking_gates列出的三份契约——它们先稳定,ACP/Zed 的真实服务才有资格开闸。对读者而言,这意味着:blocking_gates对应的契约在路线图中转为稳定之前,任何依赖claw acp serve提供真实 JSON-RPC 能力的集成都应当把该命令当作状态探针而非服务入口

实践建议:如何正确消费这套契约

综合文档、源码与测试,面向编辑器插件、CI 或脚本的推荐做法可归纳为:

  1. 探测状态一律用 JSON 形态:执行claw acp --output-format json(或claw acp serve --output-format json),解析 stdout 信封,而不是抓取帮助文本或依赖命令存在性。
  2. 三字段联合判据:以kind == "acp"supported == falseprotocol.json_rpc == false判定"当前不支持",未来契约演进时再按schema_version做兼容分支。
  3. 区分两类失败:状态查询成功应退出码为0;畸形调用(如claw acp start)退出码为1kind/error_kindunsupported_acp_invocation,此时应展示hint中的修复建议,而非当作系统故障告警。
  4. 不要把serve当服务serve_alias_only/protocol.serve_starts_daemonfalse意味着它永不绑定端口、永不启动 daemon;集成方不应尝试连接任何 ACP/Zed 端点。
  5. 留意契约演进:文档信封与源码运行时信封的字段集存在演进差异(例如文档的status: "unsupported"phase: "discoverability_only"与源码当前的status: "not_implemented"),消费方应以文档强调的稳定判据字段为准,不依赖单字段的精确字符串。

这套"诚实的不支持"契约体现了 claw-code 在能力面管理上的克制:与其让编辑器生态误探测出一个不存在的 daemon,不如用稳定、可校验、可演进的 JSON 状态面把"尚未支持"这一事实说得明明白白,同时为真实协议服务预留清晰的解锁条件。

【免费下载链接】claw-codeAn agent-managed museum exhibit, built in Rust with Gajae-Code / LazyCodex — developed and maintained with no human intervention.项目地址: https://gitcode.com/gh_mirrors/claudeco/claw-code

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询