From dbc3b36f6d94d719cb1a07074e5d74ce22d2fad3 Mon Sep 17 00:00:00 2001 From: Adam Malczewski Date: Mon, 1 Jun 2026 07:51:23 +0900 Subject: fix(queue): consume queued messages after a turn ends (start a new turn) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A message queued while the agent was mid-turn was only handled if it arrived DURING a tool batch (injected as a [USER INTERRUPT]). If it landed after the last tool call — or the turn had no tools — the agent silently appended it to history and ended the turn with no response, so it sat there unanswered. This affected both user-queued messages and agent-queued ones (send_to_tab). - agent.ts: stop the end-of-turn drain that swallowed trailing queued messages into history. They now stay on the queue. - agent-manager: after a CLEAN turn settles, continueFromQueue() drains the queue and starts a fresh turn to answer it. Skipped on a user-stopped or errored turn (queue preserved for the next send). - Loop safety: continuation draws from the existing autoWakeBudget, so a runaway agent<->agent chain is bounded; human sends refill it, so human conversations are never throttled. - dequeueMessages now tags message-consumed with reason "interrupt" | "continuation"; the frontend collapses continuation- consumed queued bubbles into the next turn's initiator row (avoids the linger/dup traps documented in queue-interrupt-reconcile-edge-cases.md). - Tests: agent (no-swallow + interrupt regression), agent-manager (continuation, no-op when empty, user-stop preserves queue, bounded loop), frontend (continuation bubble becomes next initiator). - wishlist: remove the now-fixed item. --- packages/core/src/agent/agent.ts | Bin 57628 -> 57720 bytes packages/core/src/types/index.ts | 16 +++++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'packages/core/src') diff --git a/packages/core/src/agent/agent.ts b/packages/core/src/agent/agent.ts index c2dfef1..c6f1322 100644 Binary files a/packages/core/src/agent/agent.ts and b/packages/core/src/agent/agent.ts differ diff --git a/packages/core/src/types/index.ts b/packages/core/src/types/index.ts index a4230ca..ced3dc2 100644 --- a/packages/core/src/types/index.ts +++ b/packages/core/src/types/index.ts @@ -275,7 +275,21 @@ export type AgentEvent = agentModels?: Array<{ key_id: string; model_id: string }> | null; } | { type: "message-queued"; tabId: string; messageId: string; message: string } - | { type: "message-consumed"; tabId: string; messageIds: string[] } + | { + type: "message-consumed"; + tabId: string; + messageIds: string[]; + /** + * Why the queue was drained: + * - "interrupt": consumed mid-turn, folded into a running turn's tool + * result as a [USER INTERRUPT]. The optimistic bubble collapses into + * that sealed turn. + * - "continuation": consumed between turns to START a new turn. The + * optimistic bubble becomes that new turn's initiating user row. + * Absent ⇒ treat as "interrupt" (back-compat). + */ + reason?: "interrupt" | "continuation"; + } | { type: "message-cancelled"; tabId: string; messageId: string }; // ─── Tool Types ────────────────────────────────────────────────── -- cgit v1.2.3