lib/agent-launch.mjs
Rama main · réplica de lectura del repositorio original.
// How the core starts an agent CLI. Kept apart from lib/agent-cli.mjs, which
// loads dotenv, so a script that only launches a CLI (batch-tailor.mjs) needs
// no npm package to do it.
import { statSync } from 'fs';
import { extname, join, win32 } from 'path';
import { prepareCliLaunch } from './cli-launch.mjs';
const WIN_EXTS = ['.com', '.exe', '.bat', '.cmd'];
// Find `bin` the way cmd.exe does: each PATH directory in order, each PATHEXT
// extension in order. A name with a directory in it is taken as given.
function findOnWindowsPath(bin, env) {
const isFile = (p) => { try { return statSync(p).isFile(); } catch { return false; } };
if (/[\\/]/.test(bin)) return isFile(bin) ? bin : null;
const exts = (env.PATHEXT || '.COM;.EXE;.BAT;.CMD').split(';')
.map(e => e.trim().toLowerCase()).filter(e => WIN_EXTS.includes(e));
const names = WIN_EXTS.includes(extname(bin).toLowerCase()) ? [bin] : exts.map(e => bin + e);
// win32.delimiter, not the host's: the test simulates Windows on POSIX too.
for (const dir of (env.PATH ?? env.Path ?? '').split(win32.delimiter).filter(Boolean)) {
for (const name of names) {
if (isFile(join(dir, name))) return join(dir, name);
}
}
return null;
}
/**
* The command and argv that run `bin` with `args`.
*
* On Windows an npm-installed CLI is a `.cmd` shim (with a `.ps1` and an
* extensionless POSIX script beside it). execFileSync('codex') runs none of
* them: CreateProcess only adds `.exe`, and a `.cmd` needs a shell, which would
* split the prompt at its spaces and run whatever follows an `&` in a posting
* as a command. So the binary is found on PATH and the `.js` or `.exe` the shim
* wraps is launched directly, as the web UI does (lib/cli-launch.mjs is a copy
* of web/src/lib/cli-launch.mjs). Elsewhere the bare name is passed through.
*
* @param {string} bin
* @param {string[]} args
* @param {{platform?: string, env?: NodeJS.ProcessEnv}} [opts]
* @returns {{command: string, args: string[]}}
*/
export function resolveCliLaunch(bin, args, { platform = process.platform, env = process.env } = {}) {
if (platform !== 'win32') return { command: bin, args };
const found = findOnWindowsPath(bin, env);
if (!found) return { command: bin, args };
try {
return prepareCliLaunch(found, args, platform);
} catch (err) {
err.code = 'ERR_CLI_LAUNCH';
throw err;
}
}