diff --git a/src/local-agent-config.test.ts b/src/local-agent-config.test.ts index 6cf19515a..d8de6f2ea 100644 --- a/src/local-agent-config.test.ts +++ b/src/local-agent-config.test.ts @@ -61,6 +61,19 @@ assert.deepEqual(inherited, { OPENAI_API_KEY: "inherited", UNCHANGED: "yes", }); +{ + // Windows environment blocks commonly store "Path"; a spread drops the + // case-insensitive process.env.PATH lookup that command resolution relies on. + const windowsInherited = { Path: "C:\\tools;C:\\Windows", Other: "kept" }; + const providerEnv = localAgentProviderEnvironment( + subagentsConfigSchema.parse({ enabled: true, providers: [{ id: "codex", enabled: true }] }), + "codex", + windowsInherited, + ); + assert.equal(providerEnv.PATH, "C:\\tools;C:\\Windows"); + assert.equal(providerEnv.Path, "C:\\tools;C:\\Windows"); + assert.equal(providerEnv.Other, "kept"); +} assert.equal( localAgentProviderConfigRevision(config), localAgentProviderConfigRevision(subagentsConfigSchema.parse({ diff --git a/src/local-agent-config.ts b/src/local-agent-config.ts index 39d42f09d..93e21744d 100644 --- a/src/local-agent-config.ts +++ b/src/local-agent-config.ts @@ -82,12 +82,24 @@ export function localAgentProviderEnvironment( ): NodeJS.ProcessEnv { const providerConfig = subagentProviderConfig(config, provider); const env = { ...inherited, ...providerConfig?.env }; + // process.env lookups are case-insensitive on Windows, but spreading copies + // only the original key casing (commonly "Path"); consumers reading the + // plain object's env.PATH then miss. Restore the canonical keys. + const pathValue = environmentValueCaseInsensitive(inherited, "PATH"); + if (env.PATH === undefined && pathValue !== undefined) env.PATH = pathValue; + const pathExtValue = environmentValueCaseInsensitive(inherited, "PATHEXT"); + if (env.PATHEXT === undefined && pathExtValue !== undefined) env.PATHEXT = pathExtValue; const commandVariable = providerCommandVariable(provider); const command = providerConfig && "command" in providerConfig ? providerConfig.command : undefined; if (commandVariable && command) env[commandVariable] = command; return env; } +function environmentValueCaseInsensitive(env: NodeJS.ProcessEnv, key: string): string | undefined { + const found = Object.keys(env).find((entry) => entry.toUpperCase() === key); + return found === undefined ? undefined : env[found]; +} + export function localAgentProviderEnvironmentOverrides( config: SubagentsConfig, provider: LocalAgentProvider,