refactor(agent): publish agent/inbox/claimed from Inbox.claim

Move the claimed-message notification loop out of the loop's pre-step
into Inbox.claim(target, turn), so the step-boundary operation publishes
its own claimed notifications like insertions and discards do.
This commit is contained in:
_Kerman
2026-08-05 21:36:51 +08:00
parent 488b8df547
commit d3249f096b
24 changed files with 60 additions and 50 deletions
@@ -20,7 +20,7 @@ interface Harness {
function stubAgent(ctx: Context, id: string): { agent: Agent; session: Session } {
// Store-created: the command executor durably logs lifecycle events on it.
const session = ctx.sessions.create(SessionId(id))
const inbox = new Inbox(session, { inserted: () => {}, discarded: () => {} })
const inbox = new Inbox(session, { inserted: () => {}, discarded: () => {}, claimed: () => {} })
let status: AgentStatus = 'idle'
const agent: Agent = {
id: session.id,
+3 -3
View File
@@ -24,13 +24,13 @@ function nextTurn(session: Session): number {
/** Mirror the public Agent.inject contract for domain tests. */
function appendInjection(session: Session, input: UserMessage): void {
new Inbox(session, { inserted: () => {}, discarded: () => {} }).append('next-step', input)
new Inbox(session, { inserted: () => {}, discarded: () => {}, claimed: () => {} }).append('next-step', input)
}
/** Build a registry-compatible agent around one concrete session. */
function stubAgentForSession(session: Session): StubAgent {
const id = session.id
const inbox = new Inbox(session, { inserted: () => {}, discarded: () => {} })
const inbox = new Inbox(session, { inserted: () => {}, discarded: () => {}, claimed: () => {} })
const agent: Agent = {
id,
options: {},
@@ -554,7 +554,7 @@ describe('goal replay validation', () => {
content: [{ type: 'text', text: 'unrelated pending context' }],
source: { kind: 'plugin', plugin: 'test' },
})
const inbox = new Inbox(session, { inserted: () => {}, discarded: () => {} })
const inbox = new Inbox(session, { inserted: () => {}, discarded: () => {}, claimed: () => {} })
inbox.append('next-step', message)
expect(inbox.remove(message.id)).toBe(true)
expect(foldGoal(session.events)).toMatchObject({ goal: { id: change.goal.id, revision: 1 } })
+1 -1
View File
@@ -31,7 +31,7 @@ interface Bench {
/** Register a minimal registry-compatible live agent over a store session. */
function liveAgent(ctx: Context, session: Session): Agent {
const status: AgentStatus = 'idle'
const inbox = new Inbox(session, { inserted: () => {}, discarded: () => {} })
const inbox = new Inbox(session, { inserted: () => {}, discarded: () => {}, claimed: () => {} })
const agent: Agent = {
id: session.id,
options: {},
@@ -29,7 +29,7 @@ function stubAgent(rawId: string, supplied?: Session): StubAgent {
id: session.id,
options: {},
session,
inbox: new Inbox(session, { inserted: () => {}, discarded: () => {} }),
inbox: new Inbox(session, { inserted: () => {}, discarded: () => {}, claimed: () => {} }),
get status() { return status },
ctx: new Context(),
send: () => {},
@@ -55,7 +55,7 @@ function openTurn(stub: StubAgent, source: MessageSource, text = 'prompt'): numb
source,
})
stub.agent.inbox.append('next-turn', message)
const claimed = stub.agent.inbox.claim('next-turn')
const claimed = stub.agent.inbox.claim('next-turn', turn)
if (claimed.length === 0) throw new Error('expected queued turn input')
stub.session.append('turn/start', { turn })
for (const admitted of claimed) {