diff --git a/packages/api/session-controller/src/agent.ts b/packages/api/session-controller/src/agent.ts index 9e916d03bb..2836289e37 100644 --- a/packages/api/session-controller/src/agent.ts +++ b/packages/api/session-controller/src/agent.ts @@ -10,7 +10,7 @@ import type {} from '@deepseek-ai/dsh-agent-default-model' import type {} from '@deepseek-ai/dsh-agent-presets' import { ReasoningEffortId } from '@deepseek-ai/dsh-llm' import type { Session, SessionId } from '@deepseek-ai/dsh-session' -import { SessionAlreadyOwnedError, type SessionInspection } from '@deepseek-ai/dsh-session-persistence' +import type { SessionInspection } from '@deepseek-ai/dsh-session-persistence' import { SessionQueryError, type SessionObservation } from '@deepseek-ai/dsh-session-query' import { RemoteError } from '@deepseek-ai/dsh-typert-protocol' import type {} from '@deepseek-ai/dsh-typert-registry' @@ -215,9 +215,12 @@ export class ApiSessionAgentController { if (racedSession !== undefined && hasApiSessionSubagentOwner(this.ctx, racedSession, undefined)) { return { error: apiSessionSubagentOwnershipError(sessionId) } } - if (error instanceof SessionAlreadyOwnedError) { - return { - error: new RemoteError('session/agent-busy', error.message, { reason: 'session-already-owned' }), + if (this.ctx.get('sessionPersistence') !== undefined) { + const { SessionAlreadyOwnedError } = await import('@deepseek-ai/dsh-session-persistence') + if (error instanceof SessionAlreadyOwnedError) { + return { + error: new RemoteError('session/agent-busy', error.message, { reason: 'session-already-owned' }), + } } } return { diff --git a/packages/api/session-controller/tests/agent.host.spec.ts b/packages/api/session-controller/tests/agent.host.spec.ts index a202d9281f..7861f324d7 100644 --- a/packages/api/session-controller/tests/agent.host.spec.ts +++ b/packages/api/session-controller/tests/agent.host.spec.ts @@ -255,6 +255,16 @@ describe('ApiSession Agent lookup and recovery', () => { }) }) + it('retains resume diagnostics without a persistence service', async () => { + const { ctx, agents } = await harness() + const meta = header('memory-only-resume') + ctx.sessions.create(meta.id, { meta }) + vi.spyOn(ctx.agents, 'resume').mockRejectedValue(new Error('factory unavailable')) + await expect(agents.resolveAgent(meta.id)).resolves.toMatchObject({ + error: { code: 'gateway/internal', message: expect.stringContaining('factory unavailable') as string }, + }) + }) + it('requires projected observations before activation', async () => { const { agents } = await harness() const meta = header('unprojected-observation')