diff --git a/src/renderer/src/components/terminal-pane/pty-connection.test.ts b/src/renderer/src/components/terminal-pane/pty-connection.test.ts index 1a2a9b77574..cd43a1757a9 100644 --- a/src/renderer/src/components/terminal-pane/pty-connection.test.ts +++ b/src/renderer/src/components/terminal-pane/pty-connection.test.ts @@ -708,7 +708,8 @@ describe('connectPanePty', () => { restoreTerminalFit: vi.fn().mockResolvedValue({ restored: true }) }, agentStatus: { - inferInterrupt: vi.fn().mockResolvedValue(false) + inferInterrupt: vi.fn().mockResolvedValue(false), + drop: vi.fn() } } } @@ -1497,6 +1498,7 @@ describe('connectPanePty', () => { }), 'Codex ready' ) + expect(window.api.agentStatus.drop).toHaveBeenCalledWith(paneKey) }) it('does not complete a non-Codex row from Codex stream-disconnect text', async () => { @@ -10423,6 +10425,7 @@ describe('connectPanePty', () => { agentType: 'codex', lastAssistantMessage: 'Usage limit reached.' }) + expect(window.api.agentStatus.drop).toHaveBeenCalledWith(paneKey) vi.advanceTimersByTime(AGENT_TASK_COMPLETE_NOTIFICATION_GRACE_MS) expect(deps.dispatchNotification).toHaveBeenCalledWith( @@ -10491,6 +10494,7 @@ describe('connectPanePty', () => { agentType: 'codex', lastAssistantMessage: 'Connection failed.' }) + expect(window.api.agentStatus.drop).toHaveBeenCalledWith(paneKey) }) it('does not dispatch generic spinner completions when process inspection finds no agent', async () => { diff --git a/src/renderer/src/components/terminal-pane/pty-connection.ts b/src/renderer/src/components/terminal-pane/pty-connection.ts index 3b804d63443..2d509f77607 100644 --- a/src/renderer/src/components/terminal-pane/pty-connection.ts +++ b/src/renderer/src/components/terminal-pane/pty-connection.ts @@ -1476,6 +1476,11 @@ export function connectPanePty( activePanePtyBindingBoundAt = null delete pane.container.dataset.ptyId } + const dropMainAgentStatusCacheAfterSyntheticCompletion = (): void => { + // Why: title/output/process repairs are renderer-synthesized; remove any + // stale main-hook working snapshot so reloads cannot resurrect it. + window.api?.agentStatus?.drop?.(cacheKey) + } const completeWorkingStatusFromCompletionSignal = ( signal: AgentCompletionStatusRepairSignal @@ -1511,6 +1516,7 @@ export function connectPanePty( // Why: title/process completion can prove a turn ended even when the agent // missed its final hook; keep the explicit row in sync before dedupe gates. currentState.setAgentStatus(cacheKey, statusPayload, statusTitle) + dropMainAgentStatusCacheAfterSyntheticCompletion() const storedStatus = useAppStore.getState().agentStatusByPaneKey[cacheKey] return typeof storedStatus?.stateStartedAt === 'number' ? { ...statusPayload, stateStartedAt: storedStatus.stateStartedAt } @@ -1841,6 +1847,7 @@ export function connectPanePty( // Why: Codex failed turns can finalize the TUI without emitting the managed // Stop hook Orca normally uses to clear an explicit working row. currentState.setAgentStatus(cacheKey, statusPayload, statusTitle) + dropMainAgentStatusCacheAfterSyntheticCompletion() } const shouldObserveCodexStreamErrorOutput = (): boolean => { const currentEntry = useAppStore.getState().agentStatusByPaneKey[cacheKey]