Repository navigation
Conversation
- loop submit reports acceptedAs (turn / steer / queue); prompt route, prompt channel and skill submit use it instead of pre-submit snapshots
- engine emits queueChanged when queue ids or the starting entry change; loop exposes onDidChangeQueue, moveQueued and startingPromptId
- requeue a head the machine started early at the front of the queue, not the end
- kap-server: delivery and accepted_as on submit, per-agent queue frame, queue/{prompt_id}:move route
- docs: server API reference (en / zh)
🦋 Changeset detectedLatest commit: 01235b2 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Codex Review Summary: ✅ CompletedThis 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: 7b48ae4acb
ℹ️ 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".
# Conflicts: # docs/en/reference/server-api.md # docs/zh/reference/server-api.md
…ts as queued - declare the move route params and optional body so OpenAPI exposes them - a prompt submitted while an earlier one waits for the engine to attach is accepted as queued - document the steer fallback as it behaves: queued only when no user turn is running
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8a32de1b94
ℹ️ 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".
# Conflicts: # packages/agent-core-v2/src/features/skill/skillService.ts
…arked prompts from queue frames - a prompt submitted with delivery steer materializes its daemon file refs before it reaches the running turn, so the prepared upload cleanup cannot drop them - the loop snapshot reports whether the machine engine is attached; queue frames list no inputs until it is, since parked submissions cannot be moved yet
|
@codex review |
|
Codex Review: Didn't find any major issues. Another round soon, please! Reviewed commit: ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
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". |
… settle The machine started the queued head as soon as its run ended, while the loop was still deciding whether the turn continues. The loop then pushed the head back into the queue, so it flickered out and in and its submit hooks ran twice. The gate now waits for the loop's settle decision. A continuing turn with pending notifications defers the head and runs the notifications in the same turn; otherwise the head starts normally. The requeue path is removed, and the starting marker is owned by the loop while submit hooks run.
…ompts Queued prompts are pending work: the session keeps its run lock, reports running, and is skipped by idle reclaim until every agent's queue drains. :reload now refuses with 40901 while prompts are queued instead of silently dropping the in-memory queue.
… prompts A user steer that cannot join a running user turn (idle with queued work, a system-triggered turn, or a paused queue) now waits in the queue marked as a steer: after earlier steers and before queued prompts, never ahead of a head whose submit hooks are already running. When a user turn starts, the remaining steer entries steer into it at once. :steer on a queued prompt moves it into the slot when no user turn is running. Steer entries cannot be moved and cannot be a move target (40001). Internal callers keep steerIfActive unchanged; the submit routes use the new user-only steer option, and queue frames report delivery: steer for slot entries.
:compact now answers { accepted_as, prompt_id }. An idle agent with an empty
queue compacts at once (compact); otherwise a compact entry with the
instruction joins the end of the agent's queue (queue), and 40910 is returned
while a compaction is running or already queued. When the entry reaches the
head, the prompt gate runs the compaction instead of a turn and then drops the
entry; a failure leaves an error notice and the queue moves on. Queued
compactions can be moved and withdrawn but not steered (40001); once started,
withdrawing returns 40402 and the existing compaction cancel applies.
…t id
Prompts are now submitted with PUT /sessions/{session_id}/prompts/{prompt_id}.
The body is unchanged except that prompt_id moves into the path, where it must
be 1-128 letters, digits, _ or - (40001 otherwise); idempotency is unchanged.
POST /sessions/{session_id}/prompts is removed. The response adds turn_id, the
conversation turn the prompt started, when accepted_as is turn. The server
accepts path parameters up to 256 characters so the longest prompt ids also
work with the :abort, :steer and :move actions. Server API docs cover the
submit route, the steer slot, queued compaction and the queue frame.
…he queue fold The session activity fold now reads each agent's queue, so the subagent loop fake exposes an empty queue and a queue change event, and the state manifest lists the new queued flag.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 01235b2ef2
ℹ️ 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".
| method: 'PUT', | ||
| path: '/sessions/{session_id}/prompts/{prompt_id}', |
There was a problem hiding this comment.
Preserve the existing POST prompt endpoint
Existing desktop, web, and external API clients submit prompts with POST /sessions/{session_id}/prompts and an optional body prompt_id, but this change replaces that registration with a PUT-only path and the repo-wide route search finds no compatibility alias. After upgrading the server, every previous client still using the documented POST request receives a 404 and cannot submit prompts; retain the POST route while adding the idempotent PUT form, or explicitly version this breaking contract change.
AGENTS.md reference: AGENTS.md:L121-L123
Useful? React with 👍 / 👎.
| if (this.engine !== undefined) this.machineEngine().submit(entry); | ||
| else this.pendingSubmissions.push(entry); |
There was a problem hiding this comment.
Retain queued compactions until the engine attaches
When an ordinary prompt is parked before the machine engine attaches and a concurrent :compact request is accepted behind it, this branch parks the compaction in pendingSubmissions, but drainPendingToMachine() later forwards only entries with a promptWaiter; compactions never create one. The API therefore returns accepted_as: "queue" and a prompt id, then silently discards the compaction during attach, so it never runs or produces an error. Preserve kind: "compact" entries when draining, or give them equivalent pending bookkeeping.
AGENTS.md reference: AGENTS.md:L129-L131
Useful? React with 👍 / 👎.
| } else if (slotted) { | ||
| const index = this.pendingSubmissions.findIndex((item) => item.meta?.delivery !== 'steer'); | ||
| this.pendingSubmissions.splice(index === -1 ? this.pendingSubmissions.length : index, 0, entry); |
There was a problem hiding this comment.
Keep the parked starting prompt ahead of pre-attach steers
When a normal prompt is parked before the machine engine attaches, it is reported as acceptedAs: "turn"; if a delivery: "steer" prompt arrives in the same startup window, this insertion treats the first prompt as an ordinary queue entry and places the steer before it. Once the engine attaches, the later steer starts the first turn and the original turn prompt runs afterward, contradicting both responses and reversing submission order. Preserve the first parked turn candidate ahead of the steer slot, matching the startingPromptId handling used after attachment.
Useful? React with 👍 / 👎.
| const steersActive = | ||
| (options?.steerIfActive === true || (options?.steer === true && !this.machinePaused())) && | ||
| this.active !== undefined && | ||
| this.active.prompt.tracked && | ||
| this.engine !== undefined; |
There was a problem hiding this comment.
Require a live machine turn before accepting an immediate steer
During turn teardown, the state machine can already be idle or gating the next queued prompt while this.active still refers to the previous turn—this is the ordering gap that continuesActiveTurn() handles elsewhere. A delivery: "steer" submission in that window satisfies this condition, so promptSteered associates its handle, completion, and events with the already-finished turn even though the machine carries the notification into the next turn. This can report the prompt completed with the previous turn before it is actually consumed; require the engine snapshot to still be running, otherwise place the prompt in the steer slot.
AGENTS.md reference: AGENTS.md:L121-L123
Useful? React with 👍 / 👎.
| for (const id of promptIds) { | ||
| const queue = engine.snapshot().queue; | ||
| const starting = this.snapshot().startingPromptId; | ||
| const index = queue.findIndex((item) => item.meta?.promptId === id); | ||
| const before = | ||
| id === starting | ||
| ? queue[index + 1]?.meta?.promptId | ||
| : steerSlotBefore(queue.filter((item) => item.meta?.promptId !== id), starting); | ||
| engine.move(id, before, 'steer'); |
There was a problem hiding this comment.
Leave an already-slotted steer in place
When no user turn is active and a client calls :steer again for a prompt already in the steer slot, this loop removes that entry and reinserts it immediately before the first ordinary queued prompt. For a queue such as [s1, s2, q1], steering s1 again silently changes the priority to [s2, s1, q1], even though the public contract says an existing steer keeps its place. Detect meta.delivery === "steer" and leave that entry untouched in the no-active-turn path.
AGENTS.md reference: AGENTS.md:L121-L123
Useful? React with 👍 / 👎.
| @@ -0,0 +1,5 @@ | |||
| --- | |||
| "@moonshot-ai/kimi-code": patch | |||
There was a problem hiding this comment.
Use a minor bump for the new queue API
This changeset introduces capabilities users could not use before—streaming queues, reordering queued inputs, and selecting steer delivery—but marks the CLI release as patch. The repository changeset rules classify real new capabilities as minor, so leaving this as a patch publishes the feature under the wrong semantic version; change this entry to a minor bump while keeping the separate ordering bug fix as patch.
AGENTS.md reference: AGENTS.md:L89-L90
Useful? React with 👍 / 👎.
Requirement or Bug
客户端需要以服务端为准显示和操作 agent 的排队输入:知道一次提交是开启了新一轮、插进了当前轮还是在排队,收到每个 agent 排队区的实时内容,并能调整排队顺序。本 PR 是服务端第一阶段;暂停排队、排队中的
/compact、插话优先级留到第二阶段。同时修复一个已有问题:插话之后,排在队列里的输入会乱序执行。
配套客户端 PR:MoonshotAI/kimi-code-app#1203。
Bug Reproduction Steps
delivery: "steer",或 TUI 里的插话)。Root Cause
一轮结束时,状态机比 loop 先进入下一轮:它把队首取出、开始新一轮,而 loop 还在处理上一轮的收尾(插话会让收尾变慢,所以插话后必现)。loop 发现自己还有活动轮次,就把这条输入重新
submit给引擎,而submit追加到队尾,顺序因此被打乱。本 PR 让重新入队的输入回到队首,属于根本修复:顺序保持正确,代价是插话过的轮结束时,队首这条会在
queue帧里短暂消失又出现。Code Changes
核心思路:排队 / 插话 / 新开一轮只由 loop 的
submit()决定一次,调用方读它的返回值,不再自己根据提交前的快照推断;队列变化只有一个信号来源:引擎订阅状态机快照,队列 id 或正在启动的条目变了就发出。flowchart LR route["POST /prompts<br/>delivery"] -->|steerIfActive| submit["loop.submit()<br/>→ acceptedAs"] submit --> machine[(状态机 queue)] move["POST .../queue/{id}:move"] -->|moveQueued| machine machine -->|快照变化| engine["engine: queueChanged"] engine --> loop["loop.onDidChangeQueue"] loop --> feed["SessionAgentFeed<br/>微任务合并 + 去重"] feed -->|queue 帧| ws((WebSocket 订阅者))agent-core-v2:
promptChannel.submit/submitSteer、skillService.promptWithSkills和提交路由都改为读acceptedAs。kap-server:
POST /sessions/{id}/prompts:新增delivery: "queue" | "steer"(默认queue),响应新增accepted_as。两个分支(普通提交、带skills的提交)都支持。POST /sessions/{id}/agents/{agent_id}/queue/{prompt_id}:move,可带before_prompt_id,省略时移到末尾;不在队列里返回 40402。queue帧{ type, session_id, agent_id, event_created_at, paused, inputs },挂在已有的SessionAgentFeed上:订阅时随agent/todo等帧一起发送,之后队列变化时推送,内容不变时不发。条目形状按 KAP 草案的QueuedInput;正在启动的条目和系统内部的(untracked)条目不列出。与 KAP 草案的差异(第一阶段有意简化):
delivery: "steer"遇到没有可插话的轮时直接退化为普通排队(accepted_as: "queue"),不实现“插话排在普通排队之前”。paused固定为false;提交仍走POST /prompts,响应暂不带turn_id。建议阅读顺序:
loopService.ts的submit/moveQueued/bindMachineTurn→engine.ts的快照订阅 →sessionAgentFeed.ts→routes/prompts.ts。Behavior Changes and Affected Users
{ prompt_id, user_message_id, status, content, created_at, metadata? }accepted_asdeliverysteer时在有运行中轮次时插话agent/usage/goal/todoqueue帧type分发的客户端会忽略未知帧;严格白名单的客户端会看到新类型promptChannel.submitSteer的steeredtrue改为falsePOST /api/v1/sessions/{session_id}/agents/{agent_id}/queue/{tail}受影响模块与测试:
loop.test.ts:新增prompt queue用例。acceptedAs)、调序与拒绝,以及正在启动的条目不可调序。sessionEventBroadcaster.test.ts:queue帧在订阅时发送、内容不变不重发,并过滤正在启动和系统内部的条目。prompts.test.ts:accepted_as: turn,以及:move的 40402 / 40001 / 40401。conversationContract.e2e.test.tsS11:用 mock 模型完整跑一遍排队、调序、插话,核对queue帧内容和各轮实际执行顺序(这个用例最先暴露了上面的乱序问题)。docs/{en,zh}/reference/server-api.md。Checklist
/approve).gen-changesetsskill, or this PR needs no changeset.gen-docsskill, or this PR needs no doc update.