Module Structure
该域是 Blade 的运行边界层:各表面负责接收用户或宿主输入、建立 Session 运行环境并投影 统一事件,但不拥有 Agent 决策或 durable transcript 的权威状态。
Directory Layout
packages/cli/src/blade.tsx— 统一进程入口与运行表面分流packages/cli/src/cli/— 全局参数、设置覆盖和 yargs 中间件packages/cli/src/commands/— Headless、Print、Serve、Web 与管理命令packages/cli/src/ui/— React + Ink 终端交互与本地事件投影packages/cli/src/server/— Hono HTTP、SSE、WebSocket 终端和服务端资源所有权packages/cli/web/src/— React Web、Zustand 投影、导航和预览工作区packages/cli/src/acp/— ACP Agent、Session、远程文件系统与终端能力适配packages/vscode/src/— VS Code WebSocket 桥
Key Entry Points
main()inpackages/cli/src/blade.tsx— 按 Headless、Print、ACP、子命令和默认 TUI 的优先级启动表面AppWrapperinpackages/cli/src/ui/App.tsx— TUI 的信任判断、资源初始化和主界面入口BladeServer.listenAsync()inpackages/cli/src/server/server.ts— Web/API 服务启动与关闭入口Appinpackages/cli/web/src/App.tsx— Web 导航恢复、任务流订阅和页面分流入口runAcpIntegration()inpackages/cli/src/acp/index.ts— ACP stdio/NDJSON 连接入口activate()inpackages/vscode/src/extension.ts— VS Code 桥激活入口
Gotchas
- 各表面只是同一 Runtime 事实的投影,不能把 TUI Store、Web Zustand、ACP update 或 Headless 输出当作持久化权威;恢复必须重新读取 Session 数据或 committed event (
packages/cli/src/store/slices/sessionSlice.ts,packages/cli/web/src/store/session/slices/sessionSlice.ts,packages/cli/src/acp/Session.ts) - 远端表面中的 Session 身份是
projectPath + sessionId,只按 session ID 过滤或缓存会把不同工作区的同名 Session 串在一起 (packages/cli/src/server/sessionRef.ts,packages/cli/web/src/store/session/sessionIdentity.ts) - committed event 带单调
seq并可重放,流式 delta、heartbeat 和瞬时工具活动不带seq;让 ephemeral 事件推进恢复游标会造成重连丢事件 (packages/cli/src/server/bus.ts,packages/cli/src/server/routes/session.ts,git:c776d496) - Headless、Web SSE 与 ACP 都必须有界且串行输出,但失败语义不同:Headless 取消当前运行,Web 逐出单个订阅者,ACP 中止当前 Session 操作;不能用一个表面的断连策略推断另一个表面 (
packages/cli/src/commands/HeadlessOutputEgress.ts,packages/cli/src/server/OrderedSseEgress.ts,packages/cli/src/acp/Session.ts) - 工具结果先经过统一展示投影和表面字符预算,再映射成卡片、JSONL、SSE 或 ACP content;直接发送原始工具输出会绕过敏感元数据清理与有界输出规则 (
packages/cli/src/tools/display/ToolResultProjector.ts,packages/cli/src/server/routes/session.ts) ! <command>在各表面共享 Session-owned 持久语义,但终端后端由表面决定;尤其 ACP 是否远程执行取决于宿主声明的 terminal capability (packages/cli/src/services/UserShellCommandService.ts,packages/cli/src/acp/AcpServiceContext.ts)
Architecture
- CLI/TUI 直接在当前进程消费
Agent.chatStream(),Web 通过 Hono + SSE 控制 server-owned run,ACP 将同一 LoopEvent 映射为协议 update,VS Code 则是独立的轻量 WebSocket 编辑器桥 (packages/cli/src/commands/headless.ts,packages/cli/src/server/routes/session.ts,packages/cli/src/acp/Session.ts,packages/vscode/src/extension.ts) - 每个长生命周期表面都把
SessionRuntime作为资源所有权边界:TUI Hook 持有一个活动 Runtime,Server 与 ACP 再用 residency 管理多个 Runtime;视图组件不能自行复制 Runtime 生命周期 (packages/cli/src/ui/hooks/useAgent.ts,packages/cli/src/server/routes/session.ts,packages/cli/src/acp/BladeAgent.ts) - Web 的单 Session SSE 与全局任务 SSE 是两条不同通道:前者承载完整会话投影和 durable replay,后者只发布看板安全元数据,避免跨 Session 泄露 prompt 与执行细节 (
packages/cli/src/server/routes/session.ts,packages/cli/src/server/routes/events.ts) - TUI 是本地 Ink 投影,不经过远端 egress 队列;远端 viewer 变慢不会阻塞 TUI,而 raw PTY 自身的背压由终端进程处理 (
docs/reference/surface-egress.md)
Decisions
- 统一事件溯源改造后,CLI、Web 与 ACP 都围绕 committed/ephemeral 两层事件工作,新增跨端状态应先定义 canonical Runtime 事件,再分别补投影,而不是在各 UI 自建事实 (
packages/cli/src/context/events/SessionEventLog.ts,git:c776d496) - 运行表面统一采用有界串行 egress,是为了让慢消费者无法造成无界内存,同时保留 canonical Session 供 reload/resume;普通事件不会为保活而静默丢弃 (
docs/reference/surface-egress.md,git:1af43232) - Web Server 与 Web Client 通过
packages/cli/src/api/的 TypeBox schema 共享契约,ACP 和 Headless 保留各自外部协议形状;不要强行把 ACP 或 JSONL wire 格式复用为 HTTP schema (packages/cli/src/api/schemas.ts,packages/cli/src/commands/headlessEvents.ts)
Patterns
- 终态投影采用“先排空增量,再发布终态,再按需重读权威历史”的顺序,避免最后一个 delta 被异步缓冲器留在终态之后 (
packages/cli/web/src/store/session/handlers/eventHandlers.ts,packages/cli/src/ui/utils/loopEventHandler.ts) - 表面切换或 Session 替换都先停止旧输入/订阅并释放旧 Runtime,再提交新身份;迟到结果必须以 generation 或精确 SessionRef 丢弃 (
packages/cli/src/ui/utils/sessionActivation.ts,packages/cli/web/src/store/session/slices/sessionSlice.ts,packages/cli/src/acp/BladeAgent.ts) - 用户可见的 Provider、Goal、Subagent、Team 和 Tool 状态都来自事件映射;增加新的 LoopEvent 时应检查 Headless exhaustive switch、TUI handler、Server emitter、Web dispatcher 与 ACP update (
packages/cli/src/commands/headless.ts,packages/cli/src/ui/utils/loopEventHandler.ts,packages/cli/src/server/routes/session.ts,packages/cli/web/src/store/session/handlers/eventHandlers.ts,packages/cli/src/acp/Session.ts)
Child Knowledge Nodes
./cli-bootstrap-headless-and-print/SKILL.md— 进入时机:修改 CLI 启动优先级、全局参数、Headless/Print 输入输出、信号处理或管理子命令./terminal-ui/SKILL.md— 进入时机:修改 Ink 输入、消息渲染、确认流程、Session 切换、流式缓冲或 TUI Runtime 生命周期./hono-server-api-and-streaming/SKILL.md— 进入时机:修改 Hono 路由、Session/Task API、SSE replay、WebSocket 终端、认证或服务关闭./web-client/SKILL.md— 进入时机:修改 React Web、Zustand Session 投影、SSE 重连、导航、草稿、布局、预览或任务看板./acp-host-integration/SKILL.md— 进入时机:修改 ACP 能力协商、Session load/fork、远程 FS/Terminal、权限、流式 update 或宿主展示./vscode-bridge/SKILL.md— 进入时机:修改 VS Code 扩展激活、端口发现、WebSocket RPC、编辑器/诊断/Diff 操作或扩展打包