mirror of
https://github.com/stablyai/orca.git
synced 2026-10-31 09:07:40 +00:00
fix(codex): pair structured launches with the CLI runtime (#32061)
* fix(codex): pair structured launches with the CLI runtime * test(codex): align launch snapshots with runtime pairing * fix(agent-session): keep this app's CLI ahead of the paired runtime dir Pairing ran after the Orca CLI prepend, so a runtime dir that also holds an `orca` (e.g. /usr/local/bin with node+codex+orca) shadowed this app's launcher for the child. Pair first; the CLI dir stays first on PATH. Drops a PATH-shape test the parity snapshots already cover. Co-Authored-By: Claude <noreply@anthropic.com> * fix(cli-runtime): skip compiled CLIs and keep inherited PATH when pairing a sibling node A native codex/claude beside a node (Homebrew, /usr/bin) never runs on it, so pairing only reordered PATH. An env naming no PATH now pairs over the PATH the child inherits instead of replacing it with the CLI dir alone. Co-Authored-By: Claude <noreply@anthropic.com> * test(cli-runtime): type the PATH-less env fixture Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { accessSync, constants, existsSync, readFileSync, readdirSync, statSync } from 'node:fs'
|
||||
import { homedir } from 'node:os'
|
||||
import { delimiter, dirname, isAbsolute, join } from 'node:path'
|
||||
import { firstWindowsPathEnvKey, isNativeExecutable } from './cli-runtime-pairing-inputs'
|
||||
import { getSystemCliInstallDirectories } from './system-cli-install-dirs'
|
||||
|
||||
type ResolveCommandOptions = {
|
||||
@@ -329,21 +330,6 @@ export function resolveClaudeCommand(options: ResolveCommandOptions = {}): strin
|
||||
return resolveCliCommand('claude', options)
|
||||
}
|
||||
|
||||
// Why: Win32 resolves env names case-insensitively and object order preserves
|
||||
// the block order, so the entry the child will actually read is the FIRST
|
||||
// case-insensitive match — not necessarily `Path` or `PATH`. Reading a narrower
|
||||
// set than the dedupe below deletes would destroy a third spelling unread.
|
||||
// Mirrors resolvePathEnvKey in src/main/pty/windows-path-segment-merge.ts, which
|
||||
// src/shared must not import.
|
||||
function firstWindowsPathEnvKey(env: NodeJS.ProcessEnv): string {
|
||||
for (const key of Object.keys(env)) {
|
||||
if (key.toLowerCase() === 'path' && env[key] !== undefined) {
|
||||
return key
|
||||
}
|
||||
}
|
||||
return 'Path'
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a resolved CLI's own directory ahead of PATH when that directory ships a
|
||||
* sibling `node`.
|
||||
@@ -355,8 +341,8 @@ function firstWindowsPathEnvKey(env: NodeJS.ProcessEnv): string {
|
||||
* require (stablyai/orca#10932). Pair the binary with the runtime it was
|
||||
* installed against instead.
|
||||
*
|
||||
* Only prepends when the sibling `node` really exists, so a CLI resolved from a
|
||||
* directory that ships no node is left alone.
|
||||
* Only prepends when the sibling `node` really exists and the CLI is not a
|
||||
* compiled binary, so a native CLI or one beside no node is left alone.
|
||||
*/
|
||||
export function withCliRuntimeOnPath<T extends NodeJS.ProcessEnv>(
|
||||
commandPath: string,
|
||||
@@ -368,12 +354,16 @@ export function withCliRuntimeOnPath<T extends NodeJS.ProcessEnv>(
|
||||
return env
|
||||
}
|
||||
const commandDirectory = dirname(commandPath)
|
||||
if (!findFirstExecutable(platform, [commandDirectory], getExecutableNames(platform, 'node'))) {
|
||||
if (
|
||||
!findFirstExecutable(platform, [commandDirectory], getExecutableNames(platform, 'node')) ||
|
||||
isNativeExecutable(commandPath)
|
||||
) {
|
||||
return env
|
||||
}
|
||||
const pathKey = platform === 'win32' ? firstWindowsPathEnvKey(env) : 'PATH'
|
||||
const pathDelimiter = platform === 'win32' ? ';' : delimiter
|
||||
const segments = splitPath(env[pathKey], pathDelimiter)
|
||||
// Why: the child inherits Orca's PATH when `env` names none, so pair over that, not over nothing.
|
||||
const segments = splitPath(env[pathKey] ?? process.env[pathKey], pathDelimiter)
|
||||
if (segments[0] === commandDirectory) {
|
||||
return env
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user