feat: add JavaScript session orchestration runtime
This commit is contained in:
39
.planning/2026-08-26-standard-javascript-session/findings.md
Normal file
39
.planning/2026-08-26-standard-javascript-session/findings.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# 标准 JavaScript 会话编排发现
|
||||
|
||||
## Requirements
|
||||
|
||||
- 提供 `@ccweb/session`,支持 `getCurrentConversationId`、`createConversation`、`sendMessage`、`selectSemanticBranch`、`getLastMessage`。
|
||||
- 脚本位于当前来源对话 cwd 下 `.ccweb/scripts/`,只允许 `.js`,目录使用 ESM。
|
||||
- MCP 提供 create/write/run/get_run/stop 以及 `ccweb_javascript_session_api` manifest。
|
||||
- 异步脚本通过 `runId` 查询;主动 stop 不插入来源消息;异常结束向来源对话插入通知。
|
||||
|
||||
## Research Findings
|
||||
|
||||
- `lib/ccweb-mcp-server.js` 已有 HTTP MCP 客户端,使用 `CC_WEB_MCP_URL`、`CC_WEB_MCP_TOKEN`、`CC_WEB_SOURCE_SESSION_ID`。
|
||||
- `server.js` 的 `/api/internal/mcp` 会鉴权后调用 `callInternalMcpTool`。
|
||||
- 现有会话入口为 `createMcpConversation`、`sendCrossConversationMessage` 和 `handleCodexAppSteerMessage`。
|
||||
- Codex App 完成路径 `handleCodexAppTurnComplete` 会持久化 assistant 消息并完成跨会话回复;需要复用其完成点实现脚本等待。
|
||||
- `killProcess` 与 `handleCodexAppAbortSession` 可作为停止行为的参考,但脚本子进程需要独立 PID/日志/状态管理。
|
||||
- codebase-memory 项目 `home-cc-web` 索引状态为 ready(7740 nodes/17835 edges)。
|
||||
|
||||
## Technical Decisions
|
||||
|
||||
| Decision | Rationale |
|
||||
|----------|-----------|
|
||||
| 脚本包通过本地 `node_modules/@ccweb/session` 注入 | Node ESM 对裸包名解析稳定,不依赖不可靠的 `NODE_PATH` |
|
||||
| 脚本运行凭据按 runId 绑定 | 避免把全局内部 MCP token 长期暴露给用户脚本 |
|
||||
| 日志追加落盘,get_run 分段读取 | 支持用户确认的无限输出,同时保护 MCP 响应大小 |
|
||||
| 判断器一次性只读 Codex App turn | 不污染目标会话、工作区和普通 MCP 能力 |
|
||||
|
||||
## Issues Encountered
|
||||
|
||||
| Issue | Resolution |
|
||||
|-------|------------|
|
||||
| 根目录计划属于此前 hooks 验证任务 | 使用 scoped plan,保留原有计划文件 |
|
||||
|
||||
## Resources
|
||||
|
||||
- `server.js`
|
||||
- `lib/ccweb-mcp-server.js`
|
||||
- `lib/codex-app-server-client.js`
|
||||
- `.codex/skills/planning-with-files/`
|
||||
85
.planning/2026-08-26-standard-javascript-session/progress.md
Normal file
85
.planning/2026-08-26-standard-javascript-session/progress.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# 标准 JavaScript 会话编排进度
|
||||
|
||||
## Session: 2026-08-26
|
||||
|
||||
### Phase 1:需求与代码链路确认
|
||||
|
||||
- **Status:** complete
|
||||
- **Started:** 2026-08-26
|
||||
- Actions taken:
|
||||
- 完成 grilling 需求对齐,共确认 23 项决策。
|
||||
- 读取项目 AGENTS.md 和相关技能说明。
|
||||
- 使用 codebase-memory 确认索引 ready,并核对 MCP/会话/steer 入口。
|
||||
- 创建本任务 scoped planning 文件。
|
||||
- Files created/modified:
|
||||
- `.planning/2026-08-26-standard-javascript-session/task_plan.md`
|
||||
- `.planning/2026-08-26-standard-javascript-session/findings.md`
|
||||
- `.planning/2026-08-26-standard-javascript-session/progress.md`
|
||||
|
||||
### Phase 2:MCP 契约与脚本运行基础
|
||||
|
||||
- **Status:** complete
|
||||
- Actions taken:
|
||||
- 新增 6 个脚本 MCP 工具定义,并接入 stdio/HTTP `tools/list`。
|
||||
- 在来源对话 cwd 下创建 `.ccweb/scripts/`,注入根 `package.json` 和 `node_modules/@ccweb/session` ESM 包。
|
||||
- 增加脚本名、符号链接、脚本源代码大小校验和原子写入。
|
||||
- 增加独立 Node 子进程、run.json、stdout/stderr 完整落盘、尾部/范围读取、重复启动拒绝、优雅停止/强制终止和重启恢复。
|
||||
- Files created/modified:
|
||||
- `lib/javascript-session-runtime.js`
|
||||
- `lib/ccweb-mcp-server.js`
|
||||
- `server.js`
|
||||
|
||||
### Phase 3:会话标准包与服务端编排
|
||||
|
||||
- **Status:** complete
|
||||
- Actions taken:
|
||||
- 标准包 5 个函数通过短期 run token 调用现有 ccweb `/api/internal/mcp`,不重复实现会话。
|
||||
- 创建/发送服务端等待目标助手消息完成;当前 Codex App 对话复用 steer。
|
||||
- 语义分支使用一次性只读 Codex App 判断 turn,严格候选匹配,最多重试 3 次。
|
||||
- 脚本异常结束/服务重启向来源对话插入带 runId、状态、原因和 stderr 尾部的通知;主动 stop 不插入。
|
||||
- Files created/modified:
|
||||
- `lib/javascript-session-runtime.js`
|
||||
- `server.js`
|
||||
|
||||
### Phase 4:测试与回归
|
||||
|
||||
- **Status:** complete
|
||||
- Actions taken:
|
||||
- 新增 `scripts/javascript-session-runtime-unit.js`,覆盖 ESM 裸包导入、目录边界、重复启动、状态查询、异常通知、主动停止和重启恢复。
|
||||
- 真实服务验证 `tools/list`、API manifest、脚本执行和 `getCurrentConversationId()`。
|
||||
- 修复 Node 18 对 node_modules ESM 包边界的解析问题。
|
||||
- Test results:
|
||||
- `node scripts/javascript-session-runtime-unit.js`:通过
|
||||
- `node scripts/regression.js`:通过
|
||||
- `node --check server.js`:通过
|
||||
- `node --check lib/javascript-session-runtime.js`:通过
|
||||
- `node --check lib/ccweb-mcp-server.js`:通过
|
||||
- `git diff --check`:通过
|
||||
- 项目回归首次运行遇到既有 Codex App steer 模拟的时序抖动,立即重跑通过;未产生源码或运行态残留。
|
||||
|
||||
### Phase 5:交付
|
||||
|
||||
- **Status:** complete
|
||||
- 已清理根目录临时脚本测试产物和 TODO CSV;保留源码、单测与 scoped planning 记录。
|
||||
|
||||
## Test Results
|
||||
|
||||
| Test | Input | Expected | Actual | Status |
|
||||
|------|-------|----------|--------|--------|
|
||||
| 代码索引状态 | `home-cc-web` | ready | ready | ✓ |
|
||||
|
||||
## Error Log
|
||||
|
||||
| Timestamp | Error | Attempt | Resolution |
|
||||
|-----------|-------|---------|------------|
|
||||
| 2026-08-26 | 用户级 planning-with-files 路径不存在 | 1 | 改用项目内技能路径 |
|
||||
|
||||
## 5-Question Reboot Check
|
||||
|
||||
| Question | Answer |
|
||||
|----------|--------|
|
||||
| Where am I? | Phase 2:MCP 契约与脚本运行基础 |
|
||||
| Where am I going? | 完成脚本工具、运行注册表、标准包和回归 |
|
||||
| What's the goal? | 为 cc-web 提供标准 JavaScript 会话编排能力 |
|
||||
| What have I learned? | 现有 MCP/会话/steer 入口可复用,完成点需接入服务端等待 |
|
||||
| What have I done? | 完成需求收敛、代码索引核验和 scoped planning 文件 |
|
||||
@@ -0,0 +1,68 @@
|
||||
# 标准 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 凭据生命周期和运行记录归属。
|
||||
Reference in New Issue
Block a user