feat: 线程等待与状态读取 8 项(wait/read/message/handoff/worktree/pr-checks/automation/sleep)
对照 Codex app:wait_threads 首变+afterCursor+8上限、 read_thread 详情摘要、send_message_to_thread 复活失败任务、 handoff 登记与上报轮询、worktree 派生状态、PR checks JSON+ check-runs 日志与注释、automation GET/PATCH、clock.sleep (API+host)。诚实边界见 docs/thread-wait-ops.md:无 worktree 阶段流、无 automation 变化静默、无独立测试结果 记录、handoff 服务端不执行迁移、wait 仅数据库级变化检测。 三套件:cloud 940 OK(4 跳过)、host 91 OK、deploy 29 OK
This commit is contained in:
1 parent
38c0797cb3
commit
755029f220
8 files changed
+2535
No files matched your search
@@ -0,0 +1,180 @@
|
||||
# 线程等待与状态读取:与 Codex app 的对照
|
||||
|
||||
本批实现把 Codex app 的 8 个线程/等待类工具落到本控制面。
|
||||
原则:只读的绝不写(不重跑、不批准、不合并),等待的绝不
|
||||
创建任务或发指令;所有“状态”都来自已有记录(任务行、
|
||||
trace、审批表、后续表、git 目录),没有的字段明说没有,
|
||||
不编造。
|
||||
|
||||
## 三类
|
||||
|
||||
| 类 | 官方工具 | 本端点 | 说明 |
|
||||
|---|---|---|---|
|
||||
| 管理并行 Agent | wait_threads | POST /tasks/{id}/wait | 等一批线程的首个重要变化 |
|
||||
| 管理并行 Agent | read_thread | GET /tasks/{id}/thread/read | 深入查看单个线程的摘要 |
|
||||
| 管理并行 Agent | send_message_to_thread | POST /tasks/{id}/thread/message | 向已授权线程发后续指令 |
|
||||
| 读取任务状态 | get_handoff_status | GET /tasks/{id}/handoff | 移交到另一主机后的进度 |
|
||||
| 读取任务状态 | get_worktree_creation_status | GET /tasks/{id}/worktree | worktree 准备状态 |
|
||||
| 读取任务状态 | read_pull_request_check_diagnostics | GET /tasks/{id}/pr/checks | PR 的 CI 诊断 |
|
||||
| 持续监控/等待 | automation_update | GET/PATCH /projects/{id}/automations/{aid} | 长期自动化的查看与修改 |
|
||||
| 持续监控/等待 | clock.sleep | POST /tasks/{id}/sleep,host sleep | 一次性等待后继续 |
|
||||
|
||||
配套:POST /tasks/{id}/handoff 与 POST /tasks/{id}/handoff/{hid}/report
|
||||
是移交的登记与上报口(官方是“先发起 handoff 再轮询”,
|
||||
本批把发起与上报也补齐,否则 GET 无数据可轮询)。
|
||||
|
||||
## 对照表
|
||||
|
||||
### wait_threads — POST /tasks/{id}/wait
|
||||
|
||||
- 入参:`task_ids`(可选,缺省取锚任务的 coordinator 子任务),
|
||||
`timeout_seconds`(缺省 30,上限 120),`after_cursor`(可选)。
|
||||
- 一次最多 8 个线程,超了回 400(不静默截断)。
|
||||
- 只返回第一个发生重要变化的线程:完成/失败等终态、
|
||||
需要用户输入(elicitation 审批)、需要审批(其它审批)、
|
||||
需要继续处理(待后续消息)。变化判断按 task_ids 顺序,
|
||||
不是按真实时间戳排序。
|
||||
- 无变化时超时回当前进度(progress 全量 + timed_out=true)。
|
||||
- `after_cursor`:上一次返回的 cursor 只含各任务的状态计数,
|
||||
不含正文;带它再等时,已报过的变化不再重复报。
|
||||
- 它不创建任务、不发指令,只等和收集状态。
|
||||
- 诚实边界:变化检测只读数据库(任务行、审批表、后续表),
|
||||
不轮询 trace 文件;跨任务顺序是调用方给的顺序。
|
||||
|
||||
### read_thread — GET /tasks/{id}/thread/read
|
||||
|
||||
- 返回:状态映射(queued→waiting,completed/merged→completed,
|
||||
failed/merge-failed→failed,interrupted→interrupted)、
|
||||
线程摘要、最近活动(trace 末 10 条)、改动文件(trace 里
|
||||
kind=file 的路径去重,上限 50)、执行命令(kind=exec 的
|
||||
命令与退出码,末 20 条)、待审批、待后续、Agent 链、
|
||||
阻塞/需要决策/需要处理/需要指令的 attention 汇总。
|
||||
- 线程取不到时 thread=null + note,仍回 200(与 /thread 的
|
||||
409/502 不同:读摘要不该因为线程缺失而全单失败)。
|
||||
- `test_results` 恒为 null + 说明:trace 里没有独立的测试
|
||||
结果记录,测试只能从命令退出码与 Agent 消息里看,不编
|
||||
“测试通过”。
|
||||
- docker 执行器任务没有本机线程,thread=null(这是预期,
|
||||
不是故障)。
|
||||
|
||||
### send_message_to_thread — POST /tasks/{id}/thread/message
|
||||
|
||||
- 入参:`body`(必填,上限 20000 字),`mode`(queued|direct,
|
||||
缺省 queued)。
|
||||
- 授权模型:API 侧要求 API key + 项目 create_task 权限,
|
||||
并记审计 thread_message_sent;“用户在聊天里让我协调”
|
||||
本身不是 API 权限,调用方必须持 key。
|
||||
- 排队/运行中任务:写入 task_followups(pending),direct
|
||||
模式同时追加一条直接 trace。
|
||||
- 已完成/失败/中断的任务:不是 409,而是复活——用 CAS
|
||||
把状态改回 queued、清空旧结果与旧错误、写入 resume_message;
|
||||
若已有待复活消息或状态已变,回 409(不双重复活)。
|
||||
- 已合并任务回 409:worktree 已删,应 fork 新任务而不是复活。
|
||||
- 目标任务(goal/verify)回 409:目标任务不接受后续消息。
|
||||
- 发给其它任务的消息需要用户明确授权;本任务内按用户指令
|
||||
协调。跨项目发消息不在本端点(走 peer_messages 的
|
||||
/messages,跨项目会被拒绝)。
|
||||
|
||||
### get_handoff_status — GET /tasks/{id}/handoff
|
||||
|
||||
- 移交状态:pending / accepted / running / completed / failed;
|
||||
终态不可再变,同态重报只算进度更新;进度 0–100,不因
|
||||
终态强制改成 100。
|
||||
- 同一任务同一时间只能有一个未关闭移交,否则建移交回 409。
|
||||
- 响应含 current_host 与 arrived(当前主机是否等于目标主机):
|
||||
这是“到了”的证据。
|
||||
- 诚实边界:服务端只登记意图与轮询上报,不执行 SSH 迁移、
|
||||
不搬文件;实际迁移由目标主机的 worker 执行并回 report。
|
||||
|
||||
### get_worktree_creation_status — GET /tasks/{id}/worktree
|
||||
|
||||
- 状态:remote(worktree 在别机)/ ready(目录 + .git)/
|
||||
present_no_git / creating(排队或运行中且目录未建)/
|
||||
missing(终态且目录未建;已合并任务删 worktree 是设计,
|
||||
不是丢失)/ unknown。
|
||||
- 本机且已就绪时附带当前分支(git branch --show-current,
|
||||
失败则 null,不阻塞整单)。
|
||||
- 诚实边界:worktree 创建在本系统是同步的,没有可观测的
|
||||
“接收对象 / 更新文件”阶段流,不编百分比。
|
||||
|
||||
### read_pull_request_check_diagnostics — GET /tasks/{id}/pr/checks
|
||||
|
||||
- 只读:不重跑检查、不批准、不合并。
|
||||
- 两层取数:`gh pr checks --json`(workflow、link、description
|
||||
即哪个 Action 失败与失败摘要),JSON 失败时回落制表符解析;
|
||||
有仓库 + head sha 且有失败项时,再走 check-runs API 拿
|
||||
失败日志原文(output.text,截 4000 字)与文件行号注释
|
||||
(annotations:path / start_line / message,上限 20 条,
|
||||
失败 run 上限 5 个)。
|
||||
- check-runs 一层失败时不 502 整单:checks 本身已够回答
|
||||
“哪个检查失败”,此时 check_runs 回 available=False + note。
|
||||
- 无 PR 时 409;worktree 在别机时 409(gh 必须在 worktree
|
||||
所在主机跑;诊断是只读拉取,不排队等对方 worker)。
|
||||
|
||||
### automation_update — GET/PATCH /projects/{id}/automations/{aid}
|
||||
|
||||
- GET 回定义 + 近期运行(运行取不到时 runs=[] + note,
|
||||
不 502 定义本身)。
|
||||
- PATCH 只接受 name / prompt / interval_seconds / repo_url,
|
||||
其它键静默忽略;无可更新字段回 400;已取消的自动化
|
||||
回 409(取消是终态,更新不能复活);同项目同名冲突回 400。
|
||||
- 更新不重置 last_run_at:改间隔只影响下一次到期,绝不
|
||||
触发一次立即运行。
|
||||
- 诚实边界:“变化才通知”未实现:每次运行终态仍按现有
|
||||
worker 推送通道通知,没有“与上次输出比对、无变化静默”
|
||||
的抑制逻辑。
|
||||
|
||||
### clock.sleep — POST /tasks/{id}/sleep 与 host sleep
|
||||
|
||||
- API:read 权限;seconds 缺省 5,只接受 0–60 的数,超出
|
||||
回 400(API 层不静默截断);睡的是调用方的等待,不暂停、
|
||||
不加速、不改动任务本身;返回时重读任务状态。
|
||||
- host:`host.py sleep --seconds N`,0–60,超了退出码 1;
|
||||
Ctrl-C 打印已睡秒数 + interrupted=true,退出码 130。
|
||||
|
||||
## 10 步协调流程(映射到端点)
|
||||
|
||||
1. 主 Agent 明确需求、影响客户端、验收标准
|
||||
→ 写进 POST /tasks 的 prompt(目标任务用 verify_command)。
|
||||
2. 为 Android、iOS、macOS、Web 或后端分别派发子任务
|
||||
→ POST /tasks,parent_task_id 指向主任务(coordinator)。
|
||||
3. 每个子任务在独立 worktree 或明确分支中开发
|
||||
→ 任务 worktree 由 worker 分配;GET /tasks/{id}/worktree 查。
|
||||
4. 使用 wait_threads 等待任务完成或遇到阻塞
|
||||
→ POST /tasks/{主}/wait(缺省即等 coordinator 子任务)。
|
||||
5. 使用 read_thread 查看详细结果
|
||||
→ GET /tasks/{子}/thread/read。
|
||||
6. 对失败任务使用 send_message_to_thread 要求修复
|
||||
→ POST /tasks/{子}/thread/message(失败任务会复活续跑)。
|
||||
7. 汇总各客户端改动并检查共享 API、事件和数据结构
|
||||
→ 各子任务的 read_thread 摘要 + result_text 人工/主 Agent 对照。
|
||||
8. 运行跨客户端构建、测试和集成验证
|
||||
→ 新建验证任务(或目标任务的 verify_command),再走 4–6。
|
||||
9. 读取 PR 的 CI 诊断并继续修复
|
||||
→ POST /tasks/{id}/pr 建 PR 后,GET /tasks/{id}/pr/checks,
|
||||
失败项用 thread/message 发回修复。
|
||||
10. 最后由主 Agent 汇总变更、证据和剩余风险
|
||||
→ 各任务 result_text + trace + 本对照表的诚实边界。
|
||||
|
||||
## 派发模板(映射到 POST /tasks 字段)
|
||||
|
||||
- 任务:prompt 首行写清任务名与一句话目标。
|
||||
- 客户端:prompt 内写明(Android / iOS / macOS / Web / 后端),
|
||||
本系统没有独立的客户端字段,不要另建字段。
|
||||
- 仓库:项目 repo_url(建项目时定);子任务不另设仓库。
|
||||
- 基线提交:写进 prompt(如“基线 abc123”),或 environment
|
||||
的分支字段;没有独立的基线字段。
|
||||
- 要求:写进 prompt(复用现有组件、不新建导航页等约束)。
|
||||
- 验收:写进 prompt;目标任务另用 verify_command 做自动验收。
|
||||
- 返回:任务完成时 result_text + trace;read_thread 再给出
|
||||
改动文件、命令与退出码、待处理项。主 Agent 按“改动文件 /
|
||||
执行命令与结果 / 未解决问题”三项核对,不只看一句“已做完”。
|
||||
|
||||
## 未实现 / 未宣称
|
||||
|
||||
- worktree 创建阶段流(接收对象、更新文件百分比):无。
|
||||
- automation 的“无变化静默”抑制:无。
|
||||
- 测试结果独立记录:无(只有命令退出码与 Agent 消息)。
|
||||
- handoff 的实际迁移执行:服务端不做,靠目标主机 worker 上报。
|
||||
- wait 的 trace 级变化检测:无,只有数据库级变化。
|
||||
- 自动注入身份/记忆上下文到任务:不在本批(见 identity-memory)。
|
||||
Reference in new issue
Block a user