diff --git a/src/main/ipc/pty.test.ts b/src/main/ipc/pty.test.ts index 8f69a265023..a7cb4b1c9e2 100644 --- a/src/main/ipc/pty.test.ts +++ b/src/main/ipc/pty.test.ts @@ -1750,6 +1750,39 @@ describe('registerPtyHandlers', () => { } }) + it('strips the daemon-inherited Orca-owned CODEX_HOME for real-home routing', async () => { + const spawnOptions = await daemonSpawnAndGetOptions( + {}, + () => null, + () => ({ codexSystemDefaultRealHomeEnabled: true }) as never, + { CODEX_HOME: '/managed/home', ORCA_CODEX_HOME: '/managed/home' } + ) + expect(spawnOptions.env.CODEX_HOME).toBeUndefined() + expect(spawnOptions.env.ORCA_CODEX_HOME).toBeUndefined() + expect(spawnOptions.envToDelete).toEqual( + expect.arrayContaining(['CODEX_HOME', 'ORCA_CODEX_HOME']) + ) + }) + + it('preserves a daemon-inherited user CODEX_HOME for real-home routing', async () => { + const spawnOptions = await daemonSpawnAndGetOptions( + {}, + () => null, + () => ({ codexSystemDefaultRealHomeEnabled: true }) as never, + { CODEX_HOME: '/home/me/.config/codex', ORCA_CODEX_HOME: undefined } + ) + expect(spawnOptions.envToDelete).toEqual(expect.arrayContaining(['ORCA_CODEX_HOME'])) + expect(spawnOptions.envToDelete).not.toEqual(expect.arrayContaining(['CODEX_HOME'])) + }) + + it('does not strip the daemon-inherited CODEX_HOME when the flag is OFF', async () => { + const spawnOptions = await daemonSpawnAndGetOptions({}, () => null, undefined, { + CODEX_HOME: '/managed/home', + ORCA_CODEX_HOME: '/managed/home' + }) + expect(spawnOptions.envToDelete ?? []).not.toEqual(expect.arrayContaining(['CODEX_HOME'])) + }) + it('prepends the bare-orca CLI shim dir to PATH for packaged Linux spawns', async () => { const originalPlatform = process.platform Object.defineProperty(process, 'platform', { diff --git a/src/main/ipc/pty.ts b/src/main/ipc/pty.ts index a2cff121876..72e499001c0 100644 --- a/src/main/ipc/pty.ts +++ b/src/main/ipc/pty.ts @@ -647,12 +647,23 @@ const CODEX_HOME_ENV_KEYS = ['CODEX_HOME', 'ORCA_CODEX_HOME'] as const // the marker so a shell-ready wrapper cannot restore the managed home. A // user-set CODEX_HOME with no Orca marker is preserved untouched (see #8606). function stripInheritedOrcaCodexHomeOverride(baseEnv: Record): void { - const inheritedOrcaOverride = baseEnv.ORCA_CODEX_HOME ?? process.env.ORCA_CODEX_HOME - const inheritedCodexHome = baseEnv.CODEX_HOME ?? process.env.CODEX_HOME - if (inheritedOrcaOverride && inheritedCodexHome === inheritedOrcaOverride) { - delete baseEnv.CODEX_HOME + for (const key of getInheritedOrcaCodexHomeEnvKeysToDelete(baseEnv)) { + delete baseEnv[key] } - delete baseEnv.ORCA_CODEX_HOME +} + +// Why: the daemon spawns the PTY from its own inherited environment and honors +// only spawnOptions.envToDelete, so mutating the sparse env object is not enough +// to strip an Orca-owned CODEX_HOME the daemon already carries. Return the exact +// keys to delete, preserving a user-owned CODEX_HOME. +function getInheritedOrcaCodexHomeEnvKeysToDelete(env: Record): string[] { + const inheritedOrcaOverride = env.ORCA_CODEX_HOME ?? process.env.ORCA_CODEX_HOME + const inheritedCodexHome = env.CODEX_HOME ?? process.env.CODEX_HOME + const keysToDelete = ['ORCA_CODEX_HOME'] + if (inheritedOrcaOverride && inheritedCodexHome === inheritedOrcaOverride) { + keysToDelete.push('CODEX_HOME') + } + return keysToDelete } type GetSelectedCodexHomePath = (target?: CodexAccountSelectionTarget) => string | null @@ -3082,6 +3093,12 @@ export function registerPtyHandlers( isDaemonHostSpawn && shouldSkipCodexHomeEnvForWindowsShell(daemonShellOverride, cwd) && !selectedCodexHomePath + const stripInheritedOrcaCodexHome = shouldStripInheritedOrcaCodexHome({ + target: codexSelectionTarget, + selectedCodexHomePath, + skipCodexHomeEnv, + settings: getSettings?.() + }) if (isDaemonHostSpawn && sessionId) { if (!isSafePtySessionId(sessionId, app.getPath('userData'))) { throw new Error('Invalid PTY session id') @@ -3091,12 +3108,7 @@ export function registerPtyHandlers( userDataPath: app.getPath('userData'), selectedCodexHomePath, skipCodexHomeEnv, - stripInheritedOrcaCodexHome: shouldStripInheritedOrcaCodexHome({ - target: codexSelectionTarget, - selectedCodexHomePath, - skipCodexHomeEnv, - settings: getSettings?.() - }), + stripInheritedOrcaCodexHome, githubAttributionEnabled: getSettings?.()?.enableGitHubAttribution ?? false, launchCommand: args.command, launchAgent: isTuiAgent(args.launchAgent) ? args.launchAgent : undefined, @@ -3129,6 +3141,13 @@ export function registerPtyHandlers( spawnOptions.envToDelete, CODEX_HOME_ENV_KEYS ) + } else if (stripInheritedOrcaCodexHome) { + // Why: the daemon inherits its own CODEX_HOME; strip the Orca-owned + // override there too, preserving a user-set CODEX_HOME. + spawnOptions.envToDelete = mergePtyEnvDeletions( + spawnOptions.envToDelete, + getInheritedOrcaCodexHomeEnvKeysToDelete(env ?? {}) + ) } deleteRequestedEnvKeys(env, spawnOptions.envToDelete) promoteAgentTeamsShimPath(env, requestedAgentTeamsPath) @@ -3955,6 +3974,12 @@ export function registerPtyHandlers( isDaemonHostSpawn && shouldSkipCodexHomeEnvForWindowsShell(effectiveShellOverride, cwd) && !selectedCodexHomePath + const stripInheritedOrcaCodexHome = shouldStripInheritedOrcaCodexHome({ + target: codexSelectionTarget, + selectedCodexHomePath, + skipCodexHomeEnv, + settings: getSettings?.() + }) if (isDaemonHostSpawn) { if (effectiveSessionId === undefined) { // Should be unreachable: the expression above returns a string when @@ -3979,12 +4004,7 @@ export function registerPtyHandlers( userDataPath: app.getPath('userData'), selectedCodexHomePath, skipCodexHomeEnv, - stripInheritedOrcaCodexHome: shouldStripInheritedOrcaCodexHome({ - target: codexSelectionTarget, - selectedCodexHomePath, - skipCodexHomeEnv, - settings: getSettings?.() - }), + stripInheritedOrcaCodexHome, githubAttributionEnabled: getSettings?.()?.enableGitHubAttribution ?? false, launchCommand: args.command, launchAgent: isTuiAgent(args.launchAgent) ? args.launchAgent : undefined, @@ -4023,12 +4043,17 @@ export function registerPtyHandlers( const combinedEnvToDelete = mergePtyEnvDeletions( mergePtyEnvDeletions( mergePtyEnvDeletions( - mergePtyEnvDeletions(envToDelete, args.envToDelete ?? []), - agentTeamsEnvToDelete ?? [] + mergePtyEnvDeletions( + mergePtyEnvDeletions(envToDelete, args.envToDelete ?? []), + agentTeamsEnvToDelete ?? [] + ), + isDaemonHostSpawn ? getInheritedAgentHookEnvKeysToDelete(spawnEnv) : [] ), - isDaemonHostSpawn ? getInheritedAgentHookEnvKeysToDelete(spawnEnv) : [] + skipCodexHomeEnv ? CODEX_HOME_ENV_KEYS : [] ), - skipCodexHomeEnv ? CODEX_HOME_ENV_KEYS : [] + // Why: real-home routing strips the Orca-owned override the daemon + // inherits, while preserving a user-set CODEX_HOME. + stripInheritedOrcaCodexHome ? getInheritedOrcaCodexHomeEnvKeysToDelete(spawnEnv ?? {}) : [] ) deleteRequestedEnvKeys(spawnEnv, combinedEnvToDelete) promoteAgentTeamsShimPath(spawnEnv, requestedAgentTeamsPath)