Skip to content

104. CC App Server 设计

状态:stdio MVP 已随 chainlesschain@0.166.0 发布(2026-08-24)|协议版本:v1|默认存储:hash-chained JSONL|网络传输:未开放

1. 定位

CC App Server 是 ChainlessChain 面向桌面端、IDE、CI 与自定义宿主的统一产品集成边界。它把原本散落在 CLI 参数、NDJSON 流和各端私有状态里的会话语义收敛为 Thread / Turn / Item / Approval 模型,并通过版本化 JSON-RPC 协议提供能力协商、恢复、分支、背压与确定性终态证据。

它不替代:

  • cc agent -p / cc exec 的一次性自动化入口;
  • Agent SDK AgentSession 的轻量 stream-json 会话;
  • cc serve 原有 WebSocket Gateway;
  • Graph Kernel 的任务图运行时。

App Server 负责把宿主接入 Agent Kernel,并把权威生命周期持久化;Graph Kernel 负责多 Agent 图执行。两者通过 adapter 协作,不合并成一个状态机。

2. 目标与非目标

2.1 目标

  • 用单一协议描述 initialize、Thread、Turn、Item、Tool、Approval 与终态;
  • 允许宿主在进程重启后 read/resume/fork,不依赖内存中的客户端对象;
  • 输入、输出、服务端请求和客户端 pending request 全部有界;
  • 未初始化、过载、冲突、超时和未知结果使用稳定错误码;
  • 复用真实 CLI Agent loop、权限门、沙箱与工具执行权威;
  • 从 canonical Schema 生成 TypeScript、Python、Kotlin 与 Swift 类型。

2.2 非目标

  • v1 不提供 TCP/WebSocket/公网监听;
  • 不承诺外部副作用 exactly-once;
  • 不允许 App Server 绕过 CLI 的审批、预算、sandbox 或 egress policy;
  • 不声称 Desktop/IDE 已经全部迁移;
  • 不把私有 @chainlesschain/agent-protocol 当作公开 npm 依赖。

3. 分层架构

text
Host application
  └─ @chainlesschain/agent-sdk AppServerClient
       ├─ bounded pending requests
       ├─ generated protocol validation
       └─ approval/decide handler (default decline)
             │ stdin/stdout · one JSON-RPC object per line

       StdioAppServerTransport
       ├─ 1 MiB input line cap
       ├─ bounded output queue
       └─ stdout protocol / stderr diagnostics split

       CcAppServer
       ├─ initialize + feature negotiation
       ├─ request idempotency cache
       ├─ Thread / Turn state machines
       ├─ Item / Tool / Approval notifications
       └─ interrupt physical-settlement gate
          │                         │
          ▼                         ▼
 CliAgentKernelAdapter        RolloutStore
 (real agent loop)            JSONL / capability-gated SQLite

4. 启动与传输

公开入口:

bash
cc serve --app-server \
  --app-server-state-dir <private-directory> \
  --app-server-queue-cap 256 \
  --project <workspace>

启用 --app-server 后,serve 不再启动旧 WebSocket 服务,--port--host--allow-remote 不参与 App Server 传输。v1 仅使用 stdio:stdin 接收 UTF-8 JSONL,stdout 只输出 JSON-RPC,stderr 只承载诊断信息。

Transport 默认约束:

约束默认值行为
输入单行1 MiB超限返回 -32600,不解析、不执行
输出队列512 条 / 8 MiB超限终止 transport,防止慢消费者拖垮进程
Server 请求队列256 条 / 4 MiB返回 -32001retry_after_ms
SDK pending 请求256客户端本地返回 -32001
SDK 请求超时120 秒返回 -32010,不把超时解释为成功

5. 协议协商

第一条有效请求必须是 initialize

json
{
  "jsonrpc": "2.0",
  "id": "1",
  "method": "initialize",
  "params": {
    "protocolVersion": 1,
    "minimumProtocolVersion": 1,
    "client": { "name": "example-host", "version": "1.0.0" },
    "features": ["thread_turn_item", "structured_approval"]
  }
}

Server 选择双方版本区间的最高交集,只返回双方都支持的 feature,并用 downgraded 指示降级。版本区间无交集时返回 -32602;initialize 前的其他请求返回 -32002;同一连接重复 initialize 返回 -32009

v1 feature:thread_turn_itemstructured_approvaltyped_graphcausal_messagesdurable_human_taskbounded_transportgraph_effect_receiptsdeterministic_trace

6. 请求、通知与服务端请求

6.1 客户端请求

Method作用关键约束
thread/start新建线程可声明 threadId、title、metadata、agentOptions
thread/read只读线程和事件支持 afterEventSeq 与有界 limit
thread/resume恢复线程并返回增量事件archived 线程不可开始新 Turn
thread/fork从既有线程分支新线程必须有独立身份;支持 idempotency key
thread/list列出线程archived 默认隐藏
thread/archive归档线程活跃 Turn 存在时拒绝
turn/start提交文本输入并异步执行同一 Thread 同时只允许一个 active Turn
turn/interrupt请求中断并等待物理结算未物理停止时返回 -32010,不能冒充已取消

6.2 Server 通知

生命周期通知包括 thread/updatedturn/startedturn/completeditem/starteditem/deltaitem/completedtool/requestedtool/resultapproval/requestedapproval/resolved

通知同时写入 rollout;终态通知只有在 terminal event 与 evidence 已落账后才发送。客户端断线后可以用 thread/readthread/resumeafterEventSeq 补读,而不是相信内存中最后一帧。

6.3 服务端请求

工具需要审批时,Server 向客户端发送 approval/decide 请求。binding 包含 thread、turn、item、operation digest、policy digest、workspace digest、nonce 与 expiry。客户端只能返回:

  • acceptOnce
  • acceptForTurn
  • acceptForSession
  • decline
  • cancel

缺少 handler、handler 抛错、响应超时、binding 过期或 decision 非法均失败闭合。

7. 状态机

7.1 Thread

text
active ── archive ──► archived

   ├─ resume/read ──► active projection
   └─ fork ─────────► new active thread (independent identity)

7.2 Turn

text
queued → running ⇄ waiting_approval

             ├─ completed
             ├─ failed
             └─ interrupted

终态不可逆。turn/interrupt 只在 Agent Kernel 真正停止后返回 physicallySettled: true;超时返回可重试错误,不提前写“已取消”。

8. Rollout 与恢复

默认 JsonlRolloutStore 为每个 Thread 保存 append-only 事件,事件包含单调序号、前序 hash、当前 hash、时间、trace/parent/idempotency 标识与 payload。它支持:

  • start / append / read / list;
  • checkpoint;
  • compact(summary 必填);
  • resume / fork / archive;
  • migration 与 terminal evidence。

SQLite store 使用 node:sqlite,只有运行时能力存在时才能选择;能力缺失时默认 JSONL 仍须可启动。存储切换不得改变协议层 Thread/Turn/Item 语义。

9. 幂等、恢复与未知结果

  • idempotencyKey 的完成请求进入有界结果缓存,重试返回同一逻辑结果;
  • fork 的 source thread 与 destination thread 分离,分支不能复用父线程存储身份;
  • Item/Tool/Approval 通知使用稳定幂等键,重放不能重复结算工具;
  • 断线、客户端超时或 response loss 不代表请求未执行,宿主必须 read/resume 后对账;
  • 外部副作用使用 Effect/receipt/reconcile 语义,不能以 JSON-RPC 返回丢失为由盲目重放。

10. 错误模型

Code名称典型含义
-32700Parse error非法 JSON
-32600Invalid requestenvelope/line 大小不合法
-32601Method not found未知 method
-32602Invalid params参数或协议区间不合法
-32603Internal error对外隐藏内部细节
-32001Overloaded队列已满,读取 retry_after_ms
-32002Not initialized未先 initialize
-32004Not foundThread/Turn 不存在
-32009Conflictactive Turn、重复 initialize、归档冲突
-32010Interrupted请求超时或中断尚未物理结算

11. 安全设计

  • v1 仅 stdio,避免在尚无 TLS/auth 设计时暴露网络监听;
  • state directory 由宿主显式控制,必须使用当前用户私有权限;
  • stdout 只输出协议,日志和模型诊断必须走 stderr;
  • Schema validator 在 dispatch 前拒绝非法 envelope;
  • approval binding 与工作区、策略和操作摘要绑定,客户端显示的信息必须来自该 binding;
  • App Server 复用 CLI Process Broker、sandbox、SecretStore、MCP egress 与审计策略;
  • response/error message 有长度上限,内部异常统一映射,不回显秘密或堆栈。

12. 迁移计划

  1. 自定义宿主先通过 AppServerClient 试点,不直接手写 transport;
  2. IDE/Desktop 以 feature flag 双读 App Server 与现有会话投影;
  3. 对 frozen fixture 做事件、终态、Artifact 与审批 shadow diff;
  4. 完成 30 分钟 overload/RSS 门、断线恢复、crash cut-point 与回滚演练;
  5. 每个产品单独切换 writer,旧路径清零后才宣称 authoritative;
  6. 网络传输如需加入,另立协议与威胁模型,不复用旧 WS 的安全假设。

13. 验证与未决边界

已完成:协议 codegen/兼容性、App Server lifecycle、rollout hash chain/恢复/分支、客户端 bounded pending、队列过载、Codex adapter 与三平台 CLI/Strict 发布矩阵。

未完成:Desktop/IDE 全量迁移、30 分钟过载 soak、真实 provider 三平台 Graph Agent journey、网络 transport、全产品 crash/recovery conformance 与签名 native 发行。

14. 关键文件

路径说明
packages/agent-protocol/schema/cc-agent-protocol.schema.jsoncanonical v1 Schema
packages/cli/src/lib/app-server/protocol.js协商、validator 与错误模型
packages/cli/src/lib/app-server/server.jsThread/Turn/Item/Approval 状态机
packages/cli/src/lib/app-server/stdio-transport.jsJSONL framing 与输出背压
packages/cli/src/lib/app-server/rollout-store.jsJSONL/SQLite rollout
packages/cli/src/lib/app-server/cli-agent-kernel-adapter.js真实 CLI Agent loop 适配器
packages/agent-sdk/src/app-server-client.tsTypeScript 宿主客户端

15. 相关文档

基于 MIT 许可发布