From ea222a1f729f15efb1cbd210b40c535a9111b7d7 Mon Sep 17 00:00:00 2001 From: _Kerman Date: Thu, 27 Aug 2026 13:26:43 +0800 Subject: [PATCH] fix(agent): report missing inbox projection --- packages/core/agent/src/inbox.ts | 10 +++++++--- packages/core/agent/tests/agent.spec.ts | 11 +++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/packages/core/agent/src/inbox.ts b/packages/core/agent/src/inbox.ts index 2ffc4bed39..5487a843c9 100644 --- a/packages/core/agent/src/inbox.ts +++ b/packages/core/agent/src/inbox.ts @@ -128,9 +128,13 @@ export class Inbox { /** Read the current durable projection state. */ private current(): InboxState { - // AgentLoop requires sessionProjections; AgentRegistry contributes this unit to it. - // oxlint-disable-next-line typescript/no-non-null-assertion - return this.ctx.sessionProjections.stateOf(this.session, 'inbox')! + const state = this.ctx.sessionProjections.stateOf(this.session, 'inbox') + if (state === undefined) { + throw new Error( + `agent "${this.session.id}" cannot read inbox state: session projection "inbox" is not registered; load AgentRegistry with SessionProjectionRegistry before constructing Inbox`, + ) + } + return state } /** Commit one normalized mutation and publish its live events. */ diff --git a/packages/core/agent/tests/agent.spec.ts b/packages/core/agent/tests/agent.spec.ts index f6a82a7a7d..a6e8e68659 100644 --- a/packages/core/agent/tests/agent.spec.ts +++ b/packages/core/agent/tests/agent.spec.ts @@ -74,6 +74,17 @@ async function reconstructPersistedInbox( } describe('Inbox', () => { + it('reports a missing Inbox projection as a composition error', async () => { + const ctx = new Context() + await ctx.plugin(SessionProjectionRegistry) + const agent = stubAgent('missing-inbox-projection', { ctx }) + const inbox = new Inbox(ctx, agent.session, agentEvents(ctx, agent)) + + expect(() => inbox.nextTurn).toThrow( + 'agent "missing-inbox-projection" cannot read inbox state: session projection "inbox" is not registered; load AgentRegistry with SessionProjectionRegistry before constructing Inbox', + ) + }) + it('rejects invalid durable coordinates and duplicate identities during reconstruction', async () => { const outOfRange = await reconstructPersistedInbox('invalid-inbox-range', (session) => { session.append('agent/inbox/spliced', {