From ef30558f7cf7c7647700da9d7801b371afd75f77 Mon Sep 17 00:00:00 2001 From: host Date: Tue, 27 Oct 2026 14:12:28 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BB=BB=E5=8A=A1=E9=97=B4=E4=BA=92?= =?UTF-8?q?=E5=8F=91=E6=B6=88=E6=81=AF=EF=BC=88API=20+=20agent=20=E6=A0=87?= =?UTF-8?q?=E8=AE=B0=E5=9D=97=EF=BC=8C=E4=B8=8D=E4=B8=AD=E6=96=AD=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 同项目任务互发消息、对方做完可回消息:API POST /tasks/<目标>/messages (from_task_id,目标项目 create_task + 发送项目 read 鉴权)与 agent 回合输出标记块(worker 回合后解析投递,不用联网、不用凭证,本地 与 Docker 都通)。投递不中断任务:对方运行中/排队中排成后续消息 (轮次边界执行,direct 优先);对方终态则续跑复活(resume_message + queued),A→B→A 往返不受回合时序影响。拒绝项:自己、跨项目、goal 目标、已合并、复活位被占;每轮最多 5 块,仅 completed 轮次投递; 目标执行时配额门照常生效。控制台后续消息列显示发送方,新增给 其他任务发消息框(落已代理的 /tasks 下,不用改 nginx)。 测试:新增 test_peer_messages(15)、test_peer_messages_server(8)、 test_worker_peer(4);全量 cloud 654、host 64、deploy 19 全过(cloud 4 跳过)。 --- cloud/README.md | 43 ++++ cloud/console.html | 43 +++- cloud/peer_messages.py | 215 ++++++++++++++++++++ cloud/sandbox.py | 14 +- cloud/server.py | 133 ++++++++++-- cloud/tests/test_console.py | 3 +- cloud/tests/test_peer_messages.py | 219 ++++++++++++++++++++ cloud/tests/test_peer_messages_server.py | 248 +++++++++++++++++++++++ cloud/tests/test_worker_peer.py | 192 ++++++++++++++++++ cloud/worker.py | 57 +++++- examples/peer-message-prompt.txt | 27 +++ 11 files changed, 1171 insertions(+), 23 deletions(-) create mode 100644 cloud/peer_messages.py create mode 100644 cloud/tests/test_peer_messages.py create mode 100644 cloud/tests/test_peer_messages_server.py create mode 100644 cloud/tests/test_worker_peer.py create mode 100644 examples/peer-message-prompt.txt diff --git a/cloud/README.md b/cloud/README.md index cfe629b..00b4c26 100644 --- a/cloud/README.md +++ b/cloud/README.md @@ -512,6 +512,49 @@ goal 模式的继续:server 把任务转成新 goal 语义(goal=新消息、 合并任务 worktree 已删、请分支(merged 409);冲突与新建一致 (plan + approval=full、plan + goal 各 400)。 +## 任务间互发消息(peer messages,Muse 式通用互发) + +任意两个同项目任务可以互发消息、对方做完可以回消息,不 +用经过用户中转。两个发送方: + +- API:`POST /tasks/<目标>/messages`,body + `{from_task_id, body, mode}`(mode 缺省 queued);调用方 + 须对目标项目有 create_task、对发送任务项目有 read(防冒 + 名)。`GET /tasks/<任务>/messages` 列出该任务发出的消息 + (收到的在 `/followups` 里,带 sender_task_id)。 +- Agent:任务里跑的 agent 在回合输出里写标记块,worker 在 + 回合结束后解析并投递——agent 不用联网、不用凭证,本地 + 与 Docker 执行器都通。块格式见 + `examples/peer-message-prompt.txt`;每轮最多 5 块。 + +投递语义(核心约束:互发消息不中断任务): + +- 目标排队中 / 运行中:消息排成一条后续消息(带 + sender_task_id),worker 排空循环在轮次边界执行——direct + 优先、队内 FIFO,与用户后续消息同款,当前轮绝不被打断。 + 接收方 agent 看到的 prompt 带发送方前缀 + `[来自任务 的消息]`,凭此知道回给哪个任务。 +- 目标已终态(completed / failed / interrupted):消息复活 + 它——把带前缀的正文写进 resume_message 并把状态置回 + queued,下次认领按续跑跑这一轮。没有复活,B 回给已结束 + 的 A 的消息会直接丢失,A→B→A 的往返没法成立。 +- 一律拒绝(409 或投递层跳过,只记审计):发给自己、跨 + 项目、目标是 goal 任务、目标已合并、目标已有待续跑消息 + (复活位被占)、目标不存在。 +- 只有 completed 轮次的标记块被投递(失败 / 超时 / 取消 / + 配额中断的轮次不投递);goal 任务的回合不解析标记块,且 + 目标是 goal 时直接拒绝——所以 goal 任务既不收也不发。 +- 投递不查发送方配额(发送本身不花钱),但目标任务执行时 + 的配额门照常生效:排空前查配额,超限时该条回 pending、 + 任务走配额中断;复活任务认领时认领门同样生效。互发消息 + 不构成配额绕过。 +- 边界:标记块正文不能含围栏(非贪婪匹配会把块截断成非法 + JSON 而被跳过);worker 投递的 direct 消息只有排空优先 + 权,没有 API 直接发送那种“立即进链路”的标记(worker 侧 + 链路目录不一定在本机);复活投递的消息没有 followup 行, + 发出列表里查不到,查审计 peer_message_sent 与目标的续跑 + 轮次;控制台“给其他任务发消息”框走 /tasks 下的 + /messages,不用新增 nginx location。 ## 测试 diff --git a/cloud/console.html b/cloud/console.html index a5f34c8..c84942d 100644 --- a/cloud/console.html +++ b/cloud/console.html @@ -263,6 +263,17 @@
+

给其他任务发消息

+
+ + +
+ + + +
+
+