fix(daemon): strip Electron node flag from PTYs

Strip ELECTRON_RUN_AS_NODE from daemon-spawned PTY environments so user shells do not inherit Electron's internal Node-mode flag. Adds regression coverage for the daemon PTY env boundary.

Fixes #2414.
This commit is contained in:
AIEPhoenix 2026-05-22 15:12:54 +08:00 committed by GitHub
parent 426272e94c
commit bd6139878c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 29 additions and 0 deletions

View File

@ -214,6 +214,28 @@ describe('createPtySubprocess', () => {
expect(env.ORCA_WORKTREE_ID).toBe('child-worktree')
})
it('does not inherit ELECTRON_RUN_AS_NODE from the daemon process env', () => {
// Why: the daemon is forked with ELECTRON_RUN_AS_NODE=1. If that flag
// reaches user shells, nested Electron commands run as plain Node.
const proc = mockPtyProcess()
spawnMock.mockReturnValue(proc)
const previous = process.env.ELECTRON_RUN_AS_NODE
process.env.ELECTRON_RUN_AS_NODE = '1'
try {
createPtySubprocess({ sessionId: 'test', cols: 80, rows: 24 })
} finally {
if (previous === undefined) {
delete process.env.ELECTRON_RUN_AS_NODE
} else {
process.env.ELECTRON_RUN_AS_NODE = previous
}
}
const env = spawnMock.mock.calls.at(-1)?.[2].env
expect(env.ELECTRON_RUN_AS_NODE).toBeUndefined()
})
it('does not inherit parent agent hook endpoint for development hook env', () => {
const proc = mockPtyProcess()
spawnMock.mockReturnValue(proc)

View File

@ -79,6 +79,12 @@ function removeInheritedDevAgentHookEndpoint(
}
}
function removeInheritedElectronRunAsNode(env: Record<string, string>): void {
// Why: the daemon needs ELECTRON_RUN_AS_NODE=1 internally, but user shells
// must not inherit it or nested Electron commands run as plain Node.
delete env.ELECTRON_RUN_AS_NODE
}
function formatMissingDaemonPathError(kind: 'helper' | 'cwd', path: string): DaemonProtocolError {
const detailName = kind === 'helper' ? 'helper' : 'cwd'
const step = kind === 'helper' ? 'posix_spawn' : 'daemon_cwd'
@ -182,6 +188,7 @@ export function createPtySubprocess(opts: PtySubprocessOptions): SubprocessHandl
// of the terminal that launched `pn dev`; each PTY must opt into its own.
removeUnspecifiedPaneIdentityEnv(env, opts.env)
removeInheritedDevAgentHookEndpoint(env, opts.env)
removeInheritedElectronRunAsNode(env)
removeInheritedNoColor(env)
env.LANG ??= 'en_US.UTF-8'