diff --git a/src/main/daemon/daemon-pty-adapter-wsl-sleep-cwd.test.ts b/src/main/daemon/daemon-pty-adapter-wsl-sleep-cwd.test.ts index 613cf816ef3..78c90ed8be9 100644 --- a/src/main/daemon/daemon-pty-adapter-wsl-sleep-cwd.test.ts +++ b/src/main/daemon/daemon-pty-adapter-wsl-sleep-cwd.test.ts @@ -184,6 +184,28 @@ describe('a sleeping bridge WSL pane keeps its shell folder', () => { expect(checkpointCwd(id)).toBe(`${WSL_CWD}\\deep\\er`) }) + // awin verify-11, 5e: a pane the relaunched window reattached (no spawn env, so no pane key) + // slept at its spawn folder. + it('reads it for a pane a relaunched app reattached without its spawn environment', async () => { + const before = new DaemonPtyAdapter({ socketPath, tokenPath, historyPath: historyDir() }) + const { id } = await before.spawn({ + cols: 80, + rows: 24, + cwd: WSL_CWD, + env: { ORCA_PANE_KEY: PANE_KEY }, + sessionId: 'repo::/repo@@reattached' + }) + lastSubprocess._simulateData('$ cd deep/er\r\n') + await before.disconnectOnly() + adapter = new DaemonPtyAdapter({ socketPath, tokenPath, historyPath: historyDir() }) + await adapter.attach(id) + + await adapter.shutdown(id, { immediate: true, keepHistory: true }) + + expect(readRows).toHaveBeenCalledWith('Ubuntu', expect.any(Number), { running: true }) + expect(checkpointCwd(id)).toBe(`${WSL_CWD}\\deep\\er`) + }) + it('keeps the spawn folder when the distro cannot be read', async () => { readRows.mockResolvedValue(null) adapter = new DaemonPtyAdapter({ socketPath, tokenPath, historyPath: historyDir() }) diff --git a/src/main/daemon/daemon-pty-process-inspection.ts b/src/main/daemon/daemon-pty-process-inspection.ts index a1f9caeca23..65f221a4584 100644 --- a/src/main/daemon/daemon-pty-process-inspection.ts +++ b/src/main/daemon/daemon-pty-process-inspection.ts @@ -138,8 +138,10 @@ export abstract class DaemonPtyProcessInspection extends DaemonPtyBufferSnapshot } /** - * A session this client never spawned or reattached, such as one a relaunched app's window has - * not reopened: adopted before its Sleep, or that Sleep writes no checkpoint and keeps no folder. + * Before a Sleep, what only the daemon still knows about a session: one this client never + * spawned or reattached (a relaunched window has not reopened it) is adopted, or that Sleep + * writes no checkpoint; one it reattached has no spawn environment, so no pane key to read its + * WSL shell's folder by. */ protected async adoptListedSessionForSleep( sessionId: string, @@ -147,11 +149,16 @@ export abstract class DaemonPtyProcessInspection extends DaemonPtyBufferSnapshot ): Promise { // Why active too: a session this client suspended after a seed failure must stay suspended, // or its fresh-only screen would replace the history it was restored from. - if ( - !this.historyManager || - this.historyManager.hasWriter(sessionId) || - this.activeSessionIds.has(sessionId) - ) { + const needsAdoption = + !!this.historyManager && + !this.historyManager.hasWriter(sessionId) && + !this.activeSessionIds.has(sessionId) + const needsPaneKey = + process.platform === 'win32' && + !needsAdoption && + !this.wslPaneKeysBySessionId.has(sessionId) && + this.wslDistrosBySessionId.get(sessionId) !== undefined + if (!needsAdoption && !needsPaneKey) { return } const result = await this.client.request( @@ -160,8 +167,10 @@ export abstract class DaemonPtyProcessInspection extends DaemonPtyBufferSnapshot remainingDaemonRequestTimeoutMs(deadlineMs) ) const session = result.sessions.find((entry) => entry.sessionId === sessionId && entry.isAlive) - if (session) { + if (session && needsAdoption) { await this.adoptLiveSession(session, { activeOnlyIfReconciled: true }) + } else if (session?.wslDistro && session.paneKey) { + this.wslPaneKeysBySessionId.set(sessionId, session.paneKey) } }