41 lines
4.5 KiB
Markdown
41 lines
4.5 KiB
Markdown
# Codex App 任务状态自动分类发现
|
||
|
||
## 已确认事实
|
||
|
||
- 真实 tracked 会话能够看到并调用 `ccweb_task_update`,但多数主模型不会主动维护任务列,因此工具可见不等于自动机制有效。
|
||
- 用户明确拒绝新增“任务分类模型”配置,也拒绝 Hook 和 MCP reload。
|
||
- 最终方向是服务端复用当前 Codex App 会话已经解析的 Provider、模型和现有认证,发起一次无工具结构化分类请求。
|
||
- 当前 Provider 若只有 Codex/ChatGPT 登录态而没有普通 API 凭据,则分类应安全跳过并保持原状态,不能提取或冒用登录令牌。
|
||
- 输出必须经过 JSON 解析、严格 Schema、动态启用列、expectedVersion 四层校验;任何失败都保持状态。
|
||
|
||
## 已落地结论
|
||
|
||
- 当前会话模型由 `codexAppModelSettings()` 解析;local 模式读取当前 `model_provider` 的 Responses 配置及其普通 API Key,custom 模式只读激活 Profile。
|
||
- 分类客户端独立实现 `/responses` 严格 JSON 请求,不复用只支持 Chat Completions 的摘要客户端;请求明确 `tools: []`、`tool_choice: none`。
|
||
- 分类事件只接在持久化成功的用户消息与成功主轮次完成;运行事件、失败、中断和回滚不分类。
|
||
- `TaskBoardService.updateStatus(expectedVersion)` 负责动态列验证和最终写入,actor 使用独立 `classifier` 审计来源。
|
||
- 自动 turn 前 reload 已删除;人工 reload API 和动态任务 MCP 继续作为人工/调试能力存在。
|
||
- 普通会话保存必须保护磁盘上版本更高的 `taskTracking`,否则异步分类结果会被持有旧 session 的主轮次覆盖。
|
||
- 严格输出的长度限制由本地解析器执行,发给 Provider 的 JSON Schema 避免可选字符串长度关键字,以提升 OpenAI-compatible Responses 实现的兼容性。
|
||
- 当前环境的实际 `cch` Provider 支持普通 API Key 与 Responses SSE;分类请求必须解析 `response.output_text.done/delta`,不能假定完成事件的 `output` 一定含文本,也不能等待服务端主动断开连接。
|
||
- 当前对话的一次真实请求已验证完整 Provider 链路:使用当前模型 `gpt-5.6-sol`、低推理强度和动态任务快照,1465ms 返回严格结果并判定仍为 `in_progress / 处理中`;验收过程未写生产 session。
|
||
|
||
## 第一轮代码定位
|
||
|
||
- `session.model` 经 `codexAppModelSettings()` 解析为模型名与推理强度;这应作为分类请求的模型来源。
|
||
- Codex App custom Profile 可直接提供 `apiBase/apiKey`;local 模式只有在当前 Responses Provider 存在普通 API Key 时才可分类,纯 OAuth/token 登录态安全跳过。
|
||
- 现有 `callSummaryApi()` 只实现 `/v1/chat/completions` 且没有严格 Schema,不能直接拿来当分类器,但其超时/HTTP 请求框架可参考。
|
||
- 当前 `startCodexAppTurn()` 仍在每轮调用 `ensureTaskBoardMcpToolsFresh()`,旧自动状态方案的 reload 接线确实存在。
|
||
- `TaskBoardService.updateStatus()` 已支持 `expectedVersion` 乐观并发与动态启用列校验,但 actor 目前只允许 `user/mcp`;分类器需要独立审计来源或明确复用内部来源契约。
|
||
- 生命周期服务目前只记录事件;需要继续确认轮次完成事件携带的最终助手文本入口,分类不应继续借生命周期事件自动迁移固定列。
|
||
|
||
## 触发与并发接线结论
|
||
|
||
- 普通用户消息在 `handleMessage()` 持久化后进入 Codex App;分类可在保存后异步入队,不阻塞主轮次。
|
||
- 运行中插入消息由 `handleCodexAppSteerMessage()` 异步持久化,只有 `turn/steer` 成功或旧 turn 已结束并转为新 turn 时才应入队;失败回滚的消息不得分类。
|
||
- 成功轮次的最终助手文本与清洗后的工具调用在 `handleCodexAppTurnComplete()` 已完整可用;仅 `!completionError && !interrupted && !userAborted` 时触发完成分类。
|
||
- `TaskBoardService.getTask()` 提供当前状态、摘要、version;`getStatusDefinitions()` 提供动态列;`updateStatus(expectedVersion)` 可承担最终原子写入。
|
||
- 当前 actor source 允许 `user/mcp/hook/default`。自动分类需要新增明确的 `classifier` 审计来源,不能伪装成 MCP。
|
||
- 旧生命周期服务不自动迁移任务列,只负责反归档等确定性元数据;可以保留,但 `startCodexAppTurn()` 中的 MCP fingerprint/reload 必须从自动主链路移除。
|
||
- 分类请求使用当前 Codex `custom` 激活 profile 的 `apiBase/apiKey` 与 `session.model`。`local` 登录态没有普通 API 凭据时记录 unavailable 并保持状态。
|