3.7 KiB
3.7 KiB
标准 JavaScript 会话编排实施计划
Goal
为 cc-web 增加受控的 JavaScript 脚本编排能力:通过 MCP 创建、写入、异步启动和停止脚本,并注入 @ccweb/session 标准包,让脚本 Promise 化调用现有 ccweb 会话。
Current Phase
Phase 5:交付收尾
Phases
Phase 1:需求与代码链路确认
- 汇总已确认的 API、脚本生命周期、异常通知和错误协议
- 使用 codebase-memory 确认现有 MCP、会话创建、消息发送和 steer 入口
- Status: complete
Phase 2:MCP 契约与脚本运行基础
- 新增脚本 MCP 工具定义和 API manifest;验收:tools/list 能发现 create/write/run/get_run/stop/api 工具,工具输入 schema 和 manifest 可 JSON 序列化
- 新增脚本目录、ESM 标准包注入和路径校验;验收:只能访问当前 cwd/.ccweb/scripts 下的 .js,包可被裸名 import
- 新增异步脚本运行注册表、日志落盘、停止和重启恢复;验收:runId 查询、stdout/stderr 分段读取、stop 吊销凭据、重启标记 killed
- Status: complete
Phase 3:会话标准包与服务端编排
- 实现 Promise 化的当前会话、创建、发送、最后消息和语义分支能力;验收:每个 API 返回约定字符串/ID,错误携带稳定 code/details
- 接入现有 ccweb 会话状态、Codex App steer 和异常来源会话通知;验收:同对话复用 steer,不重复运行同脚本,异常才插入来源通知
- Status: complete
Phase 4:测试与回归
- 编写脚本 MCP、标准包和异常通知回归测试
- 运行语法检查、单元回归和项目 regression
- 修复发现的问题并记录验证结果
- Status: complete
Phase 5:交付
- 清理临时 TODO CSV 和本计划状态
- 汇总变更、测试结果、风险和未覆盖边界
- Status: complete
Key Questions
- 如何在不让脚本轮询的情况下等待现有会话完成?——由服务端等待会话状态和持久化消息变化。
- 如何让同对话消息复用现有 steer,且不重复启动同一脚本?——调用现有 handleMessage/steer,并按来源+脚本路径拒绝并发重复运行。
- 如何在脚本异常结束时通知来源对话,同时区分主动 stop?——运行注册表记录 stopRequested,只有非主动失败插入通知。
Decisions Made
| Decision | Rationale |
|---|---|
| 独立 Node 子进程运行脚本 | 隔离脚本异常并支持异步执行 |
.js + type=module,注入 @ccweb/session |
保持用户示例并支持显式 ESM import/顶层 await |
| 服务端实现 Promise 等待 | 脚本不实现监听、轮询和等待封装 |
| 同对话发送复用现有 steer/插入 | 避免并行 turn 和递归死锁 |
| 运行记录和 stdout/stderr 持久化 | 支持异步 runId 查询、重启标记和长输出分段读取 |
| 主动 stop 不插入来源对话 | MCP 成功/失败结果已经是调用反馈 |
| 非正常结束插入来源对话通知 | 让启动脚本的 Agent 感知异常并继续处理 |
Errors Encountered
| Error | Attempt | Resolution |
|---|---|---|
| 用户级 planning-with-files 技能路径不存在 | 1 | 改用项目内 .codex/skills/planning-with-files/ 版本 |
Notes
- 不覆盖根目录已有的旧
task_plan.md、findings.md、progress.md,本任务使用 scoped planning 目录。 - 按已确认需求不设置运行时长、输出和并发硬上限;完整日志落盘,单次 get_run 只返回尾部或显式范围,避免无限响应。
- 脚本按受信代码执行,不伪造 JavaScript 沙箱;仍限制脚本路径、MCP 凭据生命周期和运行记录归属。