Repository navigation
Conversation
The task service now publishes onDidChangeTask whenever a task is registered (foreground tasks included), moved to the background, ended, or marked lost after a restart, and refresh(taskId) republishes a running task whose details changed. Clients get live task state straight from the engine instead of folding wire records. Each swarm member is registered as a foreground agent task of the caller when the swarm starts. The task records the member's child agent, spawning tool call and swarm index, its suspension reason while rate limited, and its result summary when it settles. Stopping a member stops the whole swarm, which is the only cancellation the swarm supports. Foreground tasks are not persisted and send no notifications, so the model and the disk see nothing new. Background task output is read by range instead of loading the whole file, readOutputTail and onDidAppendOutput serve task output streaming, and task.terminated records no longer carry outputTail.
Tasks are not conversation content, so the transcript no longer models them: TranscriptTask, taskref items, the task.upsert / taskref.upsert / task output append ops, AgentTranscriptSnapshot.tasks, the projection of task / subagent / shell events into task rows, the subagent task seeding on bind, and the lost marking on cold reads are all removed. The REST transcript endpoints no longer return tasks. The one task fact that belongs to the conversation stays visible: the injected reminder about background tasks lost when the app exited is now shown as a warning notice marker instead of being hidden with other injected messages.
…sk API A connection that starts receiving an agent (its grade in subscribe_v2 is not off) gets one task.list frame with every task that agent is running right now, foreground commands and swarm members included, and then a task frame on every change straight from the engine's task service. Ended tasks are not resent: the last task frame of a task reports its outcome, the outcome stays in the session history, and task.watch replies with the task's state. The per connection list state no longer borrows the transcript's seeded flag, so a re-subscribe that raises one agent's grade neither drops nor resends the other agents' tasks. task.stop and task.background join task.watch / task.unwatch as flat requests on the same per-task queue, and every reply can carry the task's current state. They replace the REST task endpoints, which are removed together with their schemas: list, detail, :cancel and :detach. task.watch keeps the fixes made during review: queued watches are skipped after the connection closes, setup errors reply 50001 and release the watch, success is sent only once the first chunk is ready, and a chunk the tail read caught mid-write is forwarded instead of dropped.
The notice for background tasks that lost contact when the app exited now carries lostTasks, one { taskId, description, kind } entry per task line of the reminder, so clients can show which tasks were lost without displaying the model-facing reminder text.
|
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
commit: |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 90230d2a06
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| registerSearchRoutes(apiV1 as unknown as Parameters<typeof registerSearchRoutes>[0], core); | ||
| registerTasksRoutes(apiV1 as unknown as Parameters<typeof registerTasksRoutes>[0], core); | ||
| registerInteractionsRoutes( |
There was a problem hiding this comment.
Ship the matching web bundle with the new task protocol
Removing the REST task route and transcript task fields without updating the tracked apps/kimi-code/dist-web bundle leaves the web UI shipped by kimi web on the old contract: its task list becomes empty and stop/background actions fail as soon as this server is released. The changed-file list contains no bundle assets, so sync and commit the compatible code-app build in this change rather than relying on a later PR.
AGENTS.md reference: AGENTS.md:L18-L18
Useful? React with 👍 / 👎.
| const task = new SwarmMemberTask(member, cancelSwarm); | ||
| try { | ||
| this.members.set(member, { task, taskId: tasks.registerTask(task, { detached: member.runInBackground }) }); |
There was a problem hiding this comment.
Release the swarm tool call when backgrounding a member
When a client sends task.background for one of these foreground AgentSwarm members, tasks.detach() only flips this registered task's detached state. Unlike the regular Agent tool, AgentSwarmTool directly awaits swarmService.run() and never observes this task's foreground-release promise, so the WebSocket request reports success while the parent tool call and turn remain blocked until the entire swarm completes.
Useful? React with 👍 / 👎.
| registerSearchRoutes(apiV1 as unknown as Parameters<typeof registerSearchRoutes>[0], core); | ||
| registerTasksRoutes(apiV1 as unknown as Parameters<typeof registerTasksRoutes>[0], core); | ||
| registerInteractionsRoutes( |
There was a problem hiding this comment.
Add a changeset for the removed task contracts
This commit removes user-visible REST endpoints and transcript fields but adds no .changeset entry, so the next CLI release will omit the breaking loss from its changelog and versioning flow. Add a CLI changeset that explicitly names the removed behavior and replacement; if a major bump is considered necessary, obtain the required explicit confirmation instead of selecting it here.
AGENTS.md reference: AGENTS.md:L90-L92
Useful? React with 👍 / 👎.
| subagentType: this.member.profileName, | ||
| parentToolCallId: this.member.parentToolCallId, | ||
| model: this.member.kind === 'spawn' ? this.member.plan.model : undefined, | ||
| swarmIndex: this.member.swarmIndex, | ||
| stateReason: this.stateReason, |
There was a problem hiding this comment.
Populate model metadata for every swarm member task
For thinking-enabled AgentSwarm members, this projection never sets thinkingEffort, and for resumed members it also forces model to undefined even though resumeAttempt resolves the effective profile and model. Consequently the new task.list and task frames omit the advertised thinking field for spawned members and both model and thinking for resumed members, so clients cannot render the same model metadata they receive for ordinary subagent tasks.
Useful? React with 👍 / 👎.
…k fields SubagentTaskInfo gained the optional swarmIndex, stateReason and resultSummary fields; only foreground swarm member tasks set them, and foreground tasks are never written to disk, so stored task records keep their shape.
|
CI 说明:剩下的失败只有 |
Requirement or Bug
任务改为只同步正在跑的:每个 agent 的运行中任务通过 WebSocket
task.list/task帧同步,状态直接来自引擎的任务服务;停止任务和转后台改为 WebSocket 请求task.stop/task.background;REST 任务接口删除。已结束任务的结果留在会话历史里(工具结果和完成通知),不再作为任务列表推送。取代 #4362(随后关闭)。客户端配套:MoonshotAI/kimi-code-app#1057。
Bug Reproduction Steps
N/A
Root Cause
N/A
Code Changes
核心思路
task.list里。结果交给等它的一方:前台任务的结果是工具结果,后台任务的结果是完成通知,两者都在会话历史里。detached。前台 bash、前台 subagent、swarm 成员都是detached: false的任务,也都推送task帧;转后台就是把detached变成true。SessionTasks把引擎事件和 wire 记录折叠成任务状态,现在改为订阅引擎任务服务的变化事件,SessionTasks删掉。swarm 成员在创建时就登记为任务,不再由服务端从subagent.*事件拼出来。源码(不含测试和文档)+971 / −1195:agent-core-v2 +253 / −22,transcript +47 / −346,kap-server +671 / −827(其中删掉 REST 任务路由 341 行、
coreEventMap的任务投影 319 行)。协议
和 #4362 相比:去掉
usage,加swarm_index;已结束任务不再补发;新增task.list、task.stop、task.background,以及应答里的task。task.list:连接开始接收某个 agent 时发一次(subscribe_v2里该 agent 的粒度从off或未订阅变为非off),内容是该 agent 此刻正在跑的全部任务,客户端用它整份替换本地列表。之后加入会话的 agent 直接从task帧开始。task:任务每次变化发一帧完整状态,发给所有对该 agent 粒度不为off的连接。task:task.watch成功、task.stop/task.background成功时带上任务当前状态。需要已结束任务的最终状态(例如重启后恢复一个输出面板)时,对它发task.watch即可。task.stop/task.background和task.watch/task.unwatch走同一个按任务排队的处理器:同一任务的请求按到达顺序执行,不同任务互不等待。会话不存在回 40401,该 agent 下没有这个任务回 40406,内部错误回 50001;停止或转后台一个已结束的任务回 0 并带上它的最终状态。level: "warning"的noticemarker,lostTasks列出每个失联任务{ taskId, description, kind },客户端据此渲染,不必显示写给模型的提醒原文。结构
task.list的 agent,和 transcript 的 seeded 状态无关。所以再次订阅(例如调高某个 subagent 的粒度)只给新收到的 agent 发task.list,其他 agent 的task帧照常流动,不会丢也不会重复。wire.jsonl仍只追加,后台任务仍写tasks/<id>.json和tasks/<id>/output.log;前台任务仍不落盘,所以 swarm 成员的结果摘要只在内存里,不会把长文本写进任务文件。/init(CLI 生成 AGENTS.md)起的 subagent 没有登记为任务:它的parentToolCallId是占位值generate-agents-md,会话评分依赖这个值;desktop / web 也没有消费它的地方。task.watch修复都保留:连接关闭后跳过排队中的 watch;建立推送出错时回 50001 并释放 watch;首段准备好之后才回复成功;尾部读取遇到写到一半的字符时把这段留给下一段。提交
feat(agent-core):任务变化事件,swarm 成员登记为任务。refactor(transcript):任务从转录里去掉(来自 feat(kap-server): send tasks as task events and stream task output #4362),失联提醒显示为 warning notice。feat(kap-server):实时任务帧、task.stop/task.background,删除 REST 任务接口和SessionTasks,更新 API 文档。feat(transcript):失联提醒带上lostTasks。chore(agent-core):按新的任务字段重新生成docs/state-manifest.d.ts。Behavior Changes and Affected Users
snapshot.tasks、taskref、task.upsert等 op)GET /sessions/{id}/tasks、GET …/tasks/{task_id}、…:cancel、…:detachtask.list/task帧和task.stop/task.background。changeset 写明了接口删除,bump 级别待维护者确认transcript.ops里task.list+task帧task.list里task.watch的应答带最终状态task帧(detached: false)apps/kimi-code/dist-web)kimi web的任务栏在新产物同步前是空的,停止 / 转后台按钮报错kimi web用户lostTasksdocs/state-manifest.d.ts里的SubagentTaskInfoswarmIndex、stateReason、resultSummaryTaskListTaskList时能看到运行中的成员TaskList才会看到受影响的模块与测试:
taskManager.test.ts(注册、刷新、转后台、结束都发布变化,前台任务也发布);sessionSwarm.test.ts(每个成员登记为调用方的前台任务,跟随挂起和完成);swarm、task、tools 相关测试 21 个文件 475 条通过。layers.test.ts(失联提醒显示为 warning notice,lostTasks按引擎的行格式解析,描述里带引号也能解析);119 条通过。sessionEventBroadcaster.test.ts(先发task.list再发变化;再次订阅只给新 agent 发列表且不打断已有的流;后加入的 agent 直接收到变化);wsConnectionV1.test.ts(watch 应答带状态;stop / background 各自应答,任务不存在回 40406;缺request_id以 1008 断开);transcript.test.ts(任务事件不进转录和日志);apiSurface快照去掉三条任务路由;72 个文件 1436 条通过。docs/{en,zh}/reference/server-api.md删掉 REST 任务一节,补上task.list、task.stop、task.background和应答的task。tsc、pnpm lint(0 error)通过。端到端在 code-app 配套分支上跑:desktop e2e 的后台 bash、后台 subagent、任务与待办三个流程在本地连续两次全部通过,帧序列(前台任务帧 →task.background→ 带状态的应答 →task.watch→ 输出 → 结束帧)在 trace 里核对过。Checklist
/approve).gen-changesetsskill, or this PR needs no changeset.gen-docsskill, or this PR needs no doc update.(只有 server API 参考文档受影响,已手动更新中英两份;CLI 用户文档里的后台任务描述没有变化)