refactor(agent-loop): clarify pending message flow
This commit is contained in:
@@ -13,7 +13,6 @@ import { createScope } from '@deepseek-ai/dsh-scope'
|
||||
import type { Scope } from '@deepseek-ai/dsh-scope'
|
||||
import type {
|
||||
AgentMessage,
|
||||
AgentMessageId as AgentMessageIdType,
|
||||
CancelOptions,
|
||||
AgentInterruptReason,
|
||||
AgentOptions,
|
||||
@@ -92,7 +91,7 @@ export class ReactLoopAgent extends Agent {
|
||||
send(
|
||||
content: ContentBlock[],
|
||||
options: SendOptions = { target: 'next-turn', wakeup: true, source: { kind: 'user' } },
|
||||
): AgentMessageIdType {
|
||||
): AgentMessageId {
|
||||
const id = AgentMessageId(randomUUID())
|
||||
const { target, wakeup, source } = options
|
||||
if (target === 'next-step' && !wakeup) {
|
||||
@@ -135,10 +134,10 @@ export class ReactLoopAgent extends Agent {
|
||||
if (cause.kind !== 'disposed') emitAgentEvent(this.loopCtx, this, 'agent/cancel-requested', cause)
|
||||
}
|
||||
if (!options.keepInbox) {
|
||||
const discarded = [
|
||||
...this.queued,
|
||||
...this.outbox.filter((item): item is PendingMessage => 'id' in item),
|
||||
]
|
||||
const discarded: AgentMessage[] = [...this.queued]
|
||||
for (const message of this.outbox) {
|
||||
if ('id' in message) discarded.push(message)
|
||||
}
|
||||
// Clear before abort observers run: replacement work belongs to the next turn.
|
||||
this.queued.length = 0
|
||||
this.outbox.length = 0
|
||||
@@ -429,18 +428,18 @@ export class ReactLoopAgent extends Agent {
|
||||
/** Commit the outbox and report whether it contained steering. */
|
||||
private drainOutbox(turn: number): boolean {
|
||||
let steered = false
|
||||
for (const item of this.outbox.splice(0)) {
|
||||
if (!('id' in item)) {
|
||||
this.session.append('user/message', item, { surfaceOp: 'append' })
|
||||
continue
|
||||
for (const message of this.outbox.splice(0)) {
|
||||
if ('id' in message) {
|
||||
steered = true
|
||||
emitAgentEvent(this.loopCtx, this, 'agent/inbox/dequeue', message)
|
||||
this.session.append(
|
||||
'steering/message',
|
||||
{ turn, content: message.content, source: message.source },
|
||||
{ surfaceOp: 'append' },
|
||||
)
|
||||
} else {
|
||||
this.session.append('user/message', message, { surfaceOp: 'append' })
|
||||
}
|
||||
steered = true
|
||||
emitAgentEvent(this.loopCtx, this, 'agent/inbox/dequeue', item)
|
||||
this.session.append(
|
||||
'steering/message',
|
||||
{ turn, content: item.content, source: item.source },
|
||||
{ surfaceOp: 'append' },
|
||||
)
|
||||
}
|
||||
return steered
|
||||
}
|
||||
|
||||
@@ -158,7 +158,7 @@ export abstract class Agent {
|
||||
|
||||
/**
|
||||
* The unified delivery primitive over the (`target` × `wakeup`) matrix.
|
||||
* Detaches, validates, and freezes one lossless-JSON item, then routes it:
|
||||
* It routes the caller's typed content and source as follows:
|
||||
*
|
||||
* - `next-turn` (default) queues an item that becomes the sole ordinary
|
||||
* message of its own FIFO-ordered turn; `wakeup` (default `true`) wakes a
|
||||
@@ -169,8 +169,6 @@ export abstract class Agent {
|
||||
* without running the model: an open turn stages it for the next safe log
|
||||
* position, while an idle injection appends it immediately without opening
|
||||
* a turn.
|
||||
*
|
||||
* Invalid input throws synchronously before any notification, enqueue, or append.
|
||||
* @param content - the model-facing content blocks to deliver.
|
||||
* @param options - target queue, wakeup decision, and source.
|
||||
* @returns the accepted message's {@link AgentMessageId}, stable across its `agent/inbox/*` events.
|
||||
@@ -289,7 +287,7 @@ declare module 'cordis' {
|
||||
*/
|
||||
'agent/status'(this: Scoped<Agent>, agent: Agent, status: AgentStatus): void
|
||||
/**
|
||||
* A frozen item entered the queued or steering inbox.
|
||||
* An item entered the queued or steering inbox.
|
||||
* @param agent - the owning agent.
|
||||
* @param message - accepted content, source, and correlation identity.
|
||||
* Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.
|
||||
|
||||
Reference in New Issue
Block a user