refactor(agent): expose mutable inbox state

This commit is contained in:
_Kerman
2026-07-30 15:35:18 +08:00
parent c0ef93efc8
commit 4370004360
52 changed files with 534 additions and 913 deletions
+7 -36
View File
@@ -324,37 +324,6 @@ export function apply(ctx: Context): void {
requestDrive(state)
}
})
ctx.on('agent/inbox/enqueue', (agent, item) => {
const state = stateFor(agent)
const attempt = state.attempt
if (attempt !== undefined && sameQueued(item.message.content, item.message.source, attempt)) return
state.competingQueued = true
if (attempt?.phase === 'queued') attempt.stale = true
})
ctx.on('agent/cancel-requested', (agent, cause) => {
const state = stateFor(agent)
const attempt = state.attempt
state.competingQueued = false
const goal = currentGoal(state)
if (goal?.phase === 'active' && goal.activation === 'armed') {
if (attempt === undefined) {
disarm(state)
return
}
// An admitted round closes durably as aborted; retain it so the normal
// turn outcome path appends pause after cancellation reaches idle.
// Pausing here would stage context into the active outbox only for this
// same cancel() call to discard it.
if (attempt.turn !== undefined || attempt.phase === 'admitted') return
state.attempt = undefined
try {
applyOutcome(state, goal, { kind: 'pause', reason: cause.kind })
} catch (error: unknown) {
ctx.logger.warn(`goal-session: could not pause cancelled goal for agent "${agent.id}": ${renderThrown(error)}`)
disarm(state)
}
}
})
ctx.on('goal/changed', (agent) => {
const state = stateFor(agent)
state.needsCheckpoint = true
@@ -366,12 +335,14 @@ export function apply(ctx: Context): void {
if (agent === undefined || agent.session !== session) return
const state = stateFor(agent)
switch (event.type) {
case 'agent/inbox/added': {
case 'agent/inbox/spliced': {
if (event.data.target !== 'next-turn') return
const attempt = state.attempt
const { content, source } = event.data
if (attempt !== undefined && sameQueued(content, source, attempt)) return
state.competingQueued = true
if (attempt?.phase === 'queued') attempt.stale = true
for (const message of event.data.inserted) {
if (attempt !== undefined && sameQueued(message.content, message.source, attempt)) continue
state.competingQueued = true
if (attempt?.phase === 'queued') attempt.stale = true
}
return
}
case 'turn/start': {