# 标准 JavaScript 会话编排实施计划 ## Goal 为 cc-web 增加受控的 JavaScript 脚本编排能力:通过 MCP 创建、写入、异步启动和停止脚本,并注入 `@ccweb/session` 标准包,让脚本 Promise 化调用现有 ccweb 会话。 ## Current Phase Phase 5:交付收尾 ## Phases ### Phase 1:需求与代码链路确认 - [x] 汇总已确认的 API、脚本生命周期、异常通知和错误协议 - [x] 使用 codebase-memory 确认现有 MCP、会话创建、消息发送和 steer 入口 - **Status:** complete ### Phase 2:MCP 契约与脚本运行基础 - [x] 新增脚本 MCP 工具定义和 API manifest;验收:tools/list 能发现 create/write/run/get_run/stop/api 工具,工具输入 schema 和 manifest 可 JSON 序列化 - [x] 新增脚本目录、ESM 标准包注入和路径校验;验收:只能访问当前 cwd/.ccweb/scripts 下的 .js,包可被裸名 import - [x] 新增异步脚本运行注册表、日志落盘、停止和重启恢复;验收:runId 查询、stdout/stderr 分段读取、stop 吊销凭据、重启标记 killed - **Status:** complete ### Phase 3:会话标准包与服务端编排 - [x] 实现 Promise 化的当前会话、创建、发送、最后消息和语义分支能力;验收:每个 API 返回约定字符串/ID,错误携带稳定 code/details - [x] 接入现有 ccweb 会话状态、Codex App steer 和异常来源会话通知;验收:同对话复用 steer,不重复运行同脚本,异常才插入来源通知 - **Status:** complete ### Phase 4:测试与回归 - [x] 编写脚本 MCP、标准包和异常通知回归测试 - [x] 运行语法检查、单元回归和项目 regression - [x] 修复发现的问题并记录验证结果 - **Status:** complete ### Phase 5:交付 - [x] 清理临时 TODO CSV 和本计划状态 - [x] 汇总变更、测试结果、风险和未覆盖边界 - **Status:** complete ## Key Questions 1. 如何在不让脚本轮询的情况下等待现有会话完成?——由服务端等待会话状态和持久化消息变化。 2. 如何让同对话消息复用现有 steer,且不重复启动同一脚本?——调用现有 handleMessage/steer,并按来源+脚本路径拒绝并发重复运行。 3. 如何在脚本异常结束时通知来源对话,同时区分主动 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 凭据生命周期和运行记录归属。