diff --git a/src/renderer/src/components/terminal-pane/agent-pre-ready-typed-draft.test.ts b/src/renderer/src/components/terminal-pane/agent-pre-ready-typed-draft.test.ts index c2e6c3795fb..dae4141200a 100644 --- a/src/renderer/src/components/terminal-pane/agent-pre-ready-typed-draft.test.ts +++ b/src/renderer/src/components/terminal-pane/agent-pre-ready-typed-draft.test.ts @@ -55,6 +55,15 @@ vi.mock('@/runtime/sync-runtime-graph', () => ({ scheduleRuntimeGraphSync })) vi.mock('@/lib/agent-draft-readiness', () => ({ waitForAgentDraftInputReady })) +const { requestTerminalPaneRecovery } = vi.hoisted(() => ({ + requestTerminalPaneRecovery: vi.fn(async () => undefined) +})) + +vi.mock('./terminal-pane-recovery', async (importOriginal) => ({ + ...(await importOriginal>()), + requestTerminalPaneRecovery +})) + const pairedRoute = vi.hoisted(() => { const route: { runtimeEnvironmentId: string | null } = { runtimeEnvironmentId: null } return route @@ -492,6 +501,25 @@ describe('agent pane keys typed before its PTY binds', () => { pane.dispose() }) + // Why: a first connect hung past its grace must still let typing arm recovery. + it('still requests recovery for keys held while the first connect hangs past its grace', async () => { + const pane = connectAgentPane() + await flushAsyncTicks(20) + + pane.type('a') + expect(requestTerminalPaneRecovery).not.toHaveBeenCalled() + + const now = Date.now() + const clock = vi.spyOn(Date, 'now').mockReturnValue(now + 61_000) + try { + pane.type('b') + expect(requestTerminalPaneRecovery).toHaveBeenCalledTimes(1) + } finally { + clock.mockRestore() + } + pane.dispose() + }) + it('keeps a startup-command pane that runs no agent on today’s drop', async () => { const pane = connectAgentPane({ startup: { command: 'pnpm install' } }) await flushAsyncTicks(20) diff --git a/src/renderer/src/components/terminal-pane/pty-connection/agent-pre-ready-typed-draft.ts b/src/renderer/src/components/terminal-pane/pty-connection/agent-pre-ready-typed-draft.ts index 2d97ca81151..3c71fba38ce 100644 --- a/src/renderer/src/components/terminal-pane/pty-connection/agent-pre-ready-typed-draft.ts +++ b/src/renderer/src/components/terminal-pane/pty-connection/agent-pre-ready-typed-draft.ts @@ -100,6 +100,8 @@ export function installAgentPreReadyTypedDraft(session: ConnectPanePtySession): } if (wasUserInput) { draft = appendTypedDraftText(draft, data, PTY_PRECONNECT_INPUT_MAX_CODE_UNITS) + // Why: a connect hung past its grace still needs typing to arm recovery; its guards stay quiet before then. + session.requestRecoveryForUndeliverableInput() } // Pre-bind focus reports have no terminal to reach. return true