40 lines
3.5 KiB
Markdown
40 lines
3.5 KiB
Markdown
# 调查发现
|
||
|
||
## 用户现象
|
||
|
||
- ccweb MCP 创建对话有时失败。
|
||
- 创建失败后重载 MCP 也挂载不上,导致当前对话不可继续使用。
|
||
- 截图中的 `$log-ccweb-title` 提示显示:当前会话没有提供 `ccweb_list_conversations`、`ccweb_set_title` 或 `wiznote_mcp_wiz_*` 工具,因此无法获取对话 ID,无法安全写入 `/coding` 日志。
|
||
|
||
## 代码与运行证据
|
||
|
||
### 1. MCP 冷启动窗口固定为 10 秒
|
||
|
||
- `server.js:3528-3572` 的 `buildCcwebMcpRuntimeConfig()` 在 streamable HTTP 和 stdio 两条路径都固定写入 `startup_timeout_sec: 10`,工具调用窗口为 60 秒。
|
||
- 历史会话 `723ffd3f-71fc-42ee-87b6-768836316099`、`4c0f6be3-b46c-4ec0-b6f5-03c31188b7d8`、`5ed15712-312c-4d1b-b629-3d3a3c0d06a7` 均持久化了:`MCP client for ccweb timed out after 10 seconds`。
|
||
- 同一批历史记录随后出现 `ccweb_list_conversations` 60 秒工具调用超时,说明客户端失败后仍可能继续尝试调用失效连接。
|
||
|
||
### 2. 创建对话成功不等于目标 MCP 已就绪
|
||
|
||
- `createMcpConversation()` 先通过 `createPersistentConversationSession()` 写入会话文件,再调用 `sendCrossConversationMessage()` 投递首条消息。
|
||
- `sendCrossConversationMessage()` 调用 `handleMessage()`;Codex App 分支的 `handleCodexAppMessage()` 只登记 active turn 并异步执行 `startCodexAppTurn(...).catch(...)`,立即返回 `{ ok: true }`。
|
||
- 因此创建接口返回的 `ok/status=running` 只表示“会话已落盘、首轮已开始”,不保证首轮完成,更不保证 ccweb MCP 已 ready。MCP 启动失败会在返回之后发生。
|
||
|
||
### 3. 重载状态关联存在 threadId 严格匹配竞态
|
||
|
||
- `handleReloadMcpApi()` 在 `markCodexAppMcpReloadPending()` 后调用无 thread 参数的 `config/mcpServer/reload`,并只等待 `CODEX_APP_MCP_RELOAD_STATUS_WAIT_MS = 1200` 毫秒。
|
||
- `codexAppMcpStatusTargetSessionIds()` 对 pending 会话要求 `statusRecord.threadId === pending.threadId`;不一致时直接跳过。
|
||
- `logs/process.old.log:6713-6721` 中,重载请求针对 `019ff161-...`,随后上报的是 `019fef64-...` 与 `019fef0f-...`,且全部 `targetSessions=0`。对应会话 `b73e4b07-4aaa-43d5-906b-413747a09f4b` 最终仍持久化为 `ccweb.status=starting/rawStatus=pending`。
|
||
- `cleanupExpiredCodexAppMcpReloads()` 只删除内存 pending 映射,不会把持久化状态从 `starting/pending` 改成失败或可重试,因此会话在 UI 上长期像“挂载中”。
|
||
|
||
### 4. 当前环境可复现“并发启动时序差异”
|
||
|
||
- 当前调查会话的 `ccweb` 最终为 `ready`,但同一线程的 `playwright` 在 20 秒后失败,说明多个 MCP 并发启动时不同服务的 ready/fail 到达时间并不一致;固定 10 秒窗口和 1.2 秒重载等待会放大这个时序问题。
|
||
|
||
## 已实施修复
|
||
|
||
- `server.js` 和 `lib/agent-runtime.js`:ccweb MCP 默认启动超时提高到 30 秒,工具超时和 reload 等待窗口支持环境变量覆盖;reload 默认等待 35 秒。
|
||
- `server.js`:reload pending 记录允许同一 app-server 的全局 reload 通知跨 threadId 关联;等待窗口结束仍未收到 ready/failed/cancelled 时,将持久化状态收敛为 `failed` 并标记可重试。
|
||
- `server.js`:Codex App 创建对话结果附带当前 `mcpStatus`;首条消息投递失败时保留会话 ID、失败阶段和可重试标记,避免“已创建的会话”被误认为完全不存在。
|
||
- `scripts/mock-codex-app-server.js`、`scripts/regression.js`:新增无关 threadId 和无最终状态通知的回归场景。
|