diff --git a/src/main/agent-hooks/server-ingest-terminal-status.test.ts b/src/main/agent-hooks/server-ingest-terminal-status.test.ts index 1d9fb46736c..1d45ce84e90 100644 --- a/src/main/agent-hooks/server-ingest-terminal-status.test.ts +++ b/src/main/agent-hooks/server-ingest-terminal-status.test.ts @@ -215,7 +215,31 @@ describe('AgentHookServer ingestTerminalStatus', () => { } ) - it('drops the cached provider session when an OSC status starts a new turn', () => { + // Claude reports hookless slash commands (`/context`) as OSC 7501 working then done; the session lives on (#36033). + it('keeps the cached provider session when an OSC status starts a turn after done', () => { + const server = new AgentHookServer() + const providerSession = { key: 'session_id' as const, id: 'claude-session-1' } + + server.ingestRemote( + { + paneKey: PANE, + providerSession, + payload: { state: 'done', prompt: 'first', agentType: 'claude' } + }, + 'conn-1' + ) + for (const state of ['working', 'done'] as const) { + server.ingestTerminalStatus({ + paneKey: PANE, + connectionId: 'conn-1', + payload: { state, prompt: '', agentType: 'claude' } + }) + } + + expect(server.getStatusSnapshot()[0]).toMatchObject({ state: 'done', providerSession }) + }) + + it('drops the cached provider session when a relaunched agent starts a turn after the old one exited', () => { const server = new AgentHookServer() server.ingestRemote( @@ -226,10 +250,12 @@ describe('AgentHookServer ingestTerminalStatus', () => { }, 'conn-1' ) + server.reconcileEndedProcessForPaneKeys([PANE], { preserveResumeIdentity: true }) + expect(server.getStatusSnapshot()[0]).toMatchObject({ providerSessionOnly: true }) server.ingestTerminalStatus({ paneKey: PANE, connectionId: 'conn-1', - payload: { state: 'working', prompt: 'second', agentType: 'claude' } + payload: { state: 'working', prompt: '', agentType: 'claude' } }) expect(server.getStatusSnapshot()[0]?.providerSession).toBeUndefined() diff --git a/src/main/agent-hooks/server/server-ingest-terminal.ts b/src/main/agent-hooks/server/server-ingest-terminal.ts index 245bc92c6fa..6859fa3ee26 100644 --- a/src/main/agent-hooks/server/server-ingest-terminal.ts +++ b/src/main/agent-hooks/server/server-ingest-terminal.ts @@ -280,13 +280,14 @@ export abstract class AgentHookServerIngestTerminal extends AgentHookServerInges event.payload.agentType && event.payload.agentType !== 'unknown' ? event.payload.agentType : undefined - // Launch seeds are not completed turns; real completed sessions must not leak into reused panes. + // A live agent's turn after `done` keeps its session (OSC 7501 reports hookless slash commands); a new run or an exited agent's resume-only row does not. Launch seeds are not completed turns. const preservedProviderSession = previous?.providerSession && (claimedAgentType === undefined || claimedAgentType === previous.payload.agentType) && (previous.payload.state !== 'done' || event.payload.state === 'done' || - previous.observation?.origin === 'launch') + previous.observation?.origin === 'launch' || + (!newRun && previous.providerSessionOnly !== true)) ? previous.providerSession : undefined // Without a new main-agent fact, preserve it only while the row's state and agent still match.