fix(agent-loop): balance inbox invariant on continuation-reason steer

The FIFO-conservation invariant fired on the loop-authored continuation
reason path: a continue-with-reason decision entered the steering FIFO
without an agent/inbox/enqueue, so its later dequeue/discard had no
matching enqueue. Emit the enqueue for that steer too, add a regression
test that mounts the invariant over a continue-with-reason turn and a
cancel, and hoist the duplicated inboxInfo helper into inbox.ts.

Found by fresh-eye review.
This commit is contained in:
Turtle
2026-07-23 19:37:21 +08:00
parent 44fd93fd06
commit 95e75ba3e0
7 changed files with 128 additions and 33 deletions
+11 -1
View File
@@ -7,7 +7,7 @@
*/
import type { ContentBlock, MessageSource } from '@deepseek-ai/dsh-llm'
import type { HookContext } from '@deepseek-ai/dsh-agent'
import type { HookContext, InboxItemInfo } from '@deepseek-ai/dsh-agent'
/** One message waiting in an agent's inbox. */
export interface InboxMessage {
@@ -18,6 +18,16 @@ export interface InboxMessage {
wakeup: boolean
}
/**
* Build the `agent/inbox/*` event payload for one inbox item.
* @param message - the accepted inbox record.
* @param steering - whether the item is in the steering FIFO (`next-step`).
* @returns the live-event facts for enqueue/dequeue/discard.
*/
export function inboxInfo(message: InboxMessage, steering: boolean): InboxItemInfo {
return { content: message.content, source: message.source, contexts: message.contexts, steering, wakeup: message.wakeup }
}
/**
* Per-agent inbox: a queued FIFO (dequeued once per turn start) and a steering FIFO
* (drained between steps of a running turn). Purely an in-memory mechanism of