fix(agent): address initial review findings
This commit is contained in:
@@ -144,10 +144,10 @@ export class ReactLoopAgent implements Agent {
|
||||
}
|
||||
|
||||
private async admit(onTurnBoundary: boolean): Promise<Admission> {
|
||||
if (this.phase.kind !== 'running') throw new Error()
|
||||
if (this.phase.kind !== 'running') throw new Error(`agent "${this.id}": admit outside running phase`)
|
||||
const signal = this.phase.abort.signal
|
||||
const claimed = [...this.inbox.nextStep]
|
||||
const outboxLength = this.inbox.nextStep.length
|
||||
const outboxLength = claimed.length
|
||||
const queued = onTurnBoundary ? this.inbox.nextTurn[0] : undefined
|
||||
if (queued !== undefined) claimed.push(queued)
|
||||
if (claimed.length === 0) return { kind: 'empty' }
|
||||
@@ -167,7 +167,7 @@ export class ReactLoopAgent implements Agent {
|
||||
|
||||
/** Admitted input stays unowned until `turn/start` commits. */
|
||||
private async turn(): Promise<boolean> {
|
||||
if (this.phase.kind === 'idle') throw new Error()
|
||||
if (this.phase.kind === 'idle') throw new Error(`agent "${this.id}": turn without driver reservation`)
|
||||
const abort = this.phase.kind === 'collecting' ? this.phase.abort : new AbortController()
|
||||
const { signal } = abort
|
||||
const lastTurn = this.phase.kind === 'collecting' ? this.phase.lastTurn : this.phase.turn
|
||||
@@ -227,7 +227,7 @@ export class ReactLoopAgent implements Agent {
|
||||
}
|
||||
|
||||
private async step(): Promise<TurnEndReason | null> {
|
||||
if (this.phase.kind !== 'running') throw new Error()
|
||||
if (this.phase.kind !== 'running') throw new Error(`agent "${this.id}": step outside running phase`)
|
||||
const { turn, step, abort: { signal } } = this.phase
|
||||
signal.throwIfAborted()
|
||||
await this.loopCtx.serial(agentCarrier(this), 'agent/step', this, turn, step, signal)
|
||||
|
||||
@@ -44,6 +44,9 @@ export class Inbox {
|
||||
|
||||
/**
|
||||
* Apply standard splice semantics and durably record the normalized result.
|
||||
* The durable event commits before the live projection mutates, so synchronous
|
||||
* `session/event` observers see the pre-splice lists and can reconstruct the
|
||||
* removed messages from the normalized coordinates.
|
||||
* @param target - pending list to mutate.
|
||||
* @param start - splice position.
|
||||
* @param deleteCount - maximum number of messages to remove.
|
||||
@@ -59,12 +62,14 @@ export class Inbox {
|
||||
outcome?: 'admitted' | 'canceled',
|
||||
): UserMessage[] {
|
||||
const inbox = this.state[target]
|
||||
const offset = Math.trunc(start) || 0
|
||||
const truncatedStart = Math.trunc(start)
|
||||
const offset = Number.isNaN(truncatedStart) ? 0 : truncatedStart
|
||||
const actualStart = offset < 0
|
||||
? Math.max(inbox.length + offset, 0)
|
||||
: Math.min(offset, inbox.length)
|
||||
const truncatedDeleteCount = Math.trunc(deleteCount)
|
||||
const actualDeleteCount = Math.min(
|
||||
Math.max(Math.trunc(deleteCount) || 0, 0),
|
||||
Math.max(Number.isNaN(truncatedDeleteCount) ? 0 : truncatedDeleteCount, 0),
|
||||
inbox.length - actualStart,
|
||||
)
|
||||
if (actualDeleteCount === 0 && inserted.length === 0) return []
|
||||
|
||||
@@ -264,7 +264,11 @@ declare module 'cordis' {
|
||||
|
||||
declare module '@deepseek-ai/dsh-session' {
|
||||
interface SessionEventMap {
|
||||
/** One normalized mutation of an agent's durable pending-message lists. */
|
||||
/**
|
||||
* One normalized mutation of an agent's durable pending-message lists.
|
||||
* Live dispatch precedes projection mutation, so synchronous observers may
|
||||
* read the pre-splice inbox to recover the removed messages.
|
||||
*/
|
||||
'agent/inbox/spliced': {
|
||||
target: InboxTarget
|
||||
start: number
|
||||
|
||||
Reference in New Issue
Block a user