fix(terminal): unset NODE_CHANNEL_FD for PTY shells on every POSIX host
The PTY runtime exported an empty NODE_CHANNEL_FD to override the daemon's IPC descriptor, because bun-pty merges the native environ back into the child and a JS-only delete does not stick. Node CLIs launched from the shell (opencode, claude) then printed "warn: Failed to parse IPC channel number ''" on exit. The Linux-only env -u ARGV0 wrapper now applies on macOS and Linux and also unsets NODE_CHANNEL_FD, so the variable is gone instead of empty. Testing: runtime and inherited-env tests updated for the POSIX wrapper; verified in the running app that exiting opencode no longer prints the warning.
This commit is contained in:
@@ -12,7 +12,9 @@
|
||||
import { createRequire } from 'node:module';
|
||||
import { existsSync } from 'node:fs';
|
||||
|
||||
const LINUX_ENV_BINARIES = ['/usr/bin/env', '/bin/env'];
|
||||
const POSIX_ENV_BINARIES = ['/usr/bin/env', '/bin/env'];
|
||||
/** Variables a PTY shell must never inherit from the OpenChamber host process. */
|
||||
const PTY_HOST_PRIVATE_VARIABLES = Object.freeze(['ARGV0', 'NODE_CHANNEL_FD']);
|
||||
|
||||
/**
|
||||
* Remove AppImage `ARGV0` from a mutable env object (or `process.env`).
|
||||
@@ -49,26 +51,31 @@ export function clearAppImageArgv0FromProcessEnv() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a Linux PTY launch that drops native `ARGV0` before the shell starts.
|
||||
* Resolve a POSIX PTY launch that unsets host-private variables before the
|
||||
* shell starts.
|
||||
*
|
||||
* `bun-pty` merges the OS environ into the child, so deleting `ARGV0` from the
|
||||
* JS env object alone is not enough. Wrapping with `env -u ARGV0` unsets it
|
||||
* before execing the real shell. No-op on non-Linux platforms.
|
||||
* `bun-pty` merges the OS environ into the child, so deleting a variable from
|
||||
* the JS env object alone is not enough: AppImage `ARGV0` came back on Linux,
|
||||
* and the daemon's `NODE_CHANNEL_FD` came back everywhere (Node then warns
|
||||
* "Failed to parse IPC channel number" when a CLI such as opencode exits).
|
||||
* Wrapping with `env -u NAME ...` unsets them before execing the real shell.
|
||||
* No-op on Windows and when no `env` binary is found.
|
||||
*
|
||||
* @param {string} executable
|
||||
* @param {string[]} args
|
||||
* @param {readonly string[]} variables
|
||||
* @returns {{ executable: string, args: string[] }}
|
||||
*/
|
||||
export function resolveLinuxPtyLaunch(executable, args = []) {
|
||||
if (process.platform !== 'linux') {
|
||||
export function resolvePosixPtyLaunch(executable, args = [], variables = PTY_HOST_PRIVATE_VARIABLES) {
|
||||
if (process.platform === 'win32' || variables.length === 0) {
|
||||
return { executable, args };
|
||||
}
|
||||
const envBinary = LINUX_ENV_BINARIES.find((candidate) => existsSync(candidate));
|
||||
const envBinary = POSIX_ENV_BINARIES.find((candidate) => existsSync(candidate));
|
||||
if (!envBinary) {
|
||||
return { executable, args };
|
||||
}
|
||||
return {
|
||||
executable: envBinary,
|
||||
args: ['-u', 'ARGV0', executable, ...args],
|
||||
args: [...variables.flatMap((name) => ['-u', name]), executable, ...args],
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user