fix(claude): preserve configured env through current launch handling

Keep the finalized provider environment when applying the launch-only client identity. Cover configured runtime controls in actual diagnostic and SDK child processes.

Co-authored-by: Okan YILDIRIM <63511519+ragokan@users.noreply.github.com>
This commit is contained in:
paseo-bot[bot]
2026-11-02 15:08:07 +00:00
co-authored by Okan YILDIRIM
parent 2857aeb13d
commit 8854cd4c3b
3 changed files with 59 additions and 6 deletions
@@ -4,7 +4,8 @@ import { join } from "node:path";
import { AgentStorage } from "./agent-storage.js";
import { createIdleRuntimeCleanup } from "./idle-runtime-cleanup/index.js";
import { relative } from "node:path";
import { execFileSync } from "node:child_process";
import { promisify } from "node:util";
import { execFile, execFileSync } from "node:child_process";
import { fileURLToPath } from "node:url";
import type {
ProviderConnection,
@@ -1858,6 +1859,48 @@ describe("pending provider responses", () => {
});
describe("plugin provider launch and status", () => {
test("passes configured Electron mode to a real diagnostic child process", async () => {
const logger = createTestLogger();
const registry = new PluginAgentClientRegistry(logger);
registry.replace([
{
id: "environment-probe",
label: "Environment probe",
command: [
process.execPath,
"-e",
"console.log(JSON.stringify({ mode: process.env.ELECTRON_RUN_AS_NODE ?? null, internal: process.env.PASEO_NODE_ENV ?? null, parent: process.env.CLAUDECODE ?? null }))",
],
async status({ launch }) {
if (!launch) throw new Error("Missing provider launch");
const { stdout } = await promisify(execFile)(launch.command, launch.args, {
env: launch.env,
timeout: 5000,
});
return { available: true, diagnostic: stdout.trim() };
},
async connect() {
throw new Error("A diagnostic does not need a provider connection");
},
},
]);
const definition = registry.definitions()["environment-probe"]!;
const client = definition.createClient(
logger,
ProviderOverrideSchema.parse({ env: { ELECTRON_RUN_AS_NODE: "1" } }),
);
try {
const diagnostic = await client.getDiagnostic!();
expect(JSON.parse(diagnostic.diagnostic)).toEqual({
mode: "1",
internal: null,
parent: null,
});
} finally {
await registry.shutdown();
}
});
test("resolves the executable against the provider's PATH override", async () => {
const harness = createProviderHarness();
const registration: ProviderRegistration = { ...harness.registration, command: ["node"] };
@@ -42,7 +42,13 @@ describe("Claude SDK env", () => {
const query = claudeQuery(
{ prompt: "", options: {} },
{
runtimeSettings: { env: { CLAUDE_CODE_ENTRYPOINT: "sdk-ts" } },
runtimeSettings: {
env: {
CLAUDE_CODE_ENTRYPOINT: "sdk-ts",
ELECTRON_RUN_AS_NODE: "1",
ESBUILD_BINARY_PATH: "/configured/esbuild",
},
},
launchEnv: entrypoint === undefined ? {} : { CLAUDE_CODE_ENTRYPOINT: entrypoint },
queryFactory: ({ options }) => {
if (!options.spawnClaudeCodeProcess) {
@@ -52,7 +58,7 @@ describe("Claude SDK env", () => {
command,
args: [
"-e",
"process.stdout.write(JSON.stringify({ entrypoint: process.env.CLAUDE_CODE_ENTRYPOINT, parentSession: process.env.CLAUDECODE ?? null }))",
"process.stdout.write(JSON.stringify({ entrypoint: process.env.CLAUDE_CODE_ENTRYPOINT, parentSession: process.env.CLAUDECODE ?? null, electronMode: process.env.ELECTRON_RUN_AS_NODE ?? null, esbuild: process.env.ESBUILD_BINARY_PATH ?? null }))",
],
cwd: process.cwd(),
env: { ...process.env, CLAUDE_CODE_ENTRYPOINT: "sdk-ts", CLAUDECODE: "1" },
@@ -72,6 +78,8 @@ describe("Claude SDK env", () => {
expect(JSON.parse(output)).toEqual({
...(entrypoint === undefined ? {} : { entrypoint }),
parentSession: null,
electronMode: "1",
esbuild: "/configured/esbuild",
});
} finally {
query.close();
@@ -5,7 +5,7 @@ import {
createProviderEnvSpec,
type ProviderRuntimeSettings,
} from "../../provider-launch-config.js";
import { buildSelfNodeCommand, createExternalProcessEnv } from "../../../paseo-env.js";
import { buildSelfNodeCommand } from "../../../paseo-env.js";
import { spawnProcess } from "../../../../utils/spawn.js";
// Keep the raw SDK query import in this module only. Claude process launch behavior
@@ -75,8 +75,10 @@ function applyRuntimeSettingsToClaudeOptions(
});
// Session-open hooks may explicitly supply a client identity. Keep inherited
// SDK/parent identities cleared while honoring this launch-only contribution.
providerEnvSpec.envOverlay.CLAUDE_CODE_ENTRYPOINT = launchEnv?.CLAUDE_CODE_ENTRYPOINT;
const providerEnv = createExternalProcessEnv(spawnOptions.env, providerEnvSpec.envOverlay);
const providerEnv = providerEnvSpec.env;
if (launchEnv?.CLAUDE_CODE_ENTRYPOINT !== undefined) {
providerEnv.CLAUDE_CODE_ENTRYPOINT = launchEnv.CLAUDE_CODE_ENTRYPOINT;
}
const selfNodeCommand = isDefaultRuntime
? buildSelfNodeCommand(resolved.args, providerEnv)
: null;