From cced263f8425e4ce52ccd8b52b62a446a9c0e919 Mon Sep 17 00:00:00 2001 From: mldangelo-oai <269034524+mldangelo-oai@users.noreply.github.com> Date: Mon, 9 Nov 2026 20:35:44 +0000 Subject: [PATCH] fix(sdk): defer home lookup for explicitly configured Linux runtimes --- sdk/typescript/src/runtime.ts | 19 +++++++------- .../tests-ts/api-runtime-storage.test.ts | 26 +++++++++++++++++++ sdk/typescript/tests-ts/runtime.test.ts | 6 ++++- 3 files changed, 41 insertions(+), 10 deletions(-) diff --git a/sdk/typescript/src/runtime.ts b/sdk/typescript/src/runtime.ts index 5b4a8b2f8a..b3157d1147 100644 --- a/sdk/typescript/src/runtime.ts +++ b/sdk/typescript/src/runtime.ts @@ -3399,12 +3399,13 @@ export async function resolvePluginPython( ); } - const home = options.homeDirectory ?? homedir(); - const cacheDirectory = - environmentValue(environment, "XDG_CACHE_HOME", true) || - join(home, ".cache"); const managedRoots = options.managedRuntimeRoots ?? [ - join(cacheDirectory, "codex-runtimes", "codex-primary-runtime"), + join( + environmentValue(environment, "XDG_CACHE_HOME", true) || + join(options.homeDirectory ?? homedir(), ".cache"), + "codex-runtimes", + "codex-primary-runtime", + ), ]; const relativeCandidates = process.platform === "win32" @@ -3872,16 +3873,16 @@ export function expandHome( value: string, environment: ProcessEnvironment = process.env, ): string { - const home = + const home = () => (process.platform === "win32" ? (environmentValue(environment, "USERPROFILE") ?? environmentValue(environment, "HOME")) : (environmentValue(environment, "HOME") ?? environmentValue(environment, "USERPROFILE"))) ?? homedir(); - if (value === "~") return home; - if (value.startsWith("~/")) return join(home, value.slice(2)); + if (value === "~") return home(); + if (value.startsWith("~/")) return join(home(), value.slice(2)); if (value.startsWith("~\\")) { - return join(home, ...value.slice(2).split("\\")); + return join(home(), ...value.slice(2).split("\\")); } return value; } diff --git a/sdk/typescript/tests-ts/api-runtime-storage.test.ts b/sdk/typescript/tests-ts/api-runtime-storage.test.ts index 2550fb9838..8f01a3e3a1 100644 --- a/sdk/typescript/tests-ts/api-runtime-storage.test.ts +++ b/sdk/typescript/tests-ts/api-runtime-storage.test.ts @@ -23,6 +23,32 @@ import { PLUGIN_ROOT } from "./plugin-root.js"; const { temporaryDirectory, cleanup } = createApiTestFixtures(); afterEach(cleanup); +test("preflights with explicit storage paths when the account has no home directory", async () => { + const root = await temporaryDirectory(); + const repository = join(root, "repository"); + await mkdir(repository); + await writeFile(join(repository, "source.py"), "value = 1\n"); + const client = new TestClient( + {}, + { + environment: { + CODEX_HOME: join(root, "codex"), + CODEX_SECURITY_STATE_DIR: join(root, "state"), + }, + }, + ); + const home = spyOn(os, "homedir").mockImplementation(() => { + throw new Error("No home directory for this account"); + }); + try { + const scan = await client.preflight(repository, { target: ["source.py"] }); + expect(scan.target.paths).toEqual(["source.py"]); + } finally { + home.mockRestore(); + await client.close(); + } +}); + function stubPluginInstall() { return spyOn(runtime, "bootstrapPlugin").mockImplementation( async (_home, pluginRoot) => ({ diff --git a/sdk/typescript/tests-ts/runtime.test.ts b/sdk/typescript/tests-ts/runtime.test.ts index a996d793b8..db0508e9ae 100644 --- a/sdk/typescript/tests-ts/runtime.test.ts +++ b/sdk/typescript/tests-ts/runtime.test.ts @@ -6861,6 +6861,11 @@ describe("runtime directories and plugin Python boundary", () => { testPosix("uses configured, inherited, and managed Python", async () => { const root = await temporaryDirectory(); + using _home = spyOn(await import("node:os"), "homedir").mockImplementation( + () => { + throw new Error("No home directory for this account"); + }, + ); const configured = join(root, "configured-python"); await writeFile( configured, @@ -6914,7 +6919,6 @@ describe("runtime directories and plugin Python boundary", () => { expect( await resolvePluginPython({ environment: { PATH: "", XDG_CACHE_HOME: cacheDirectory }, - homeDirectory: join(root, "unused-home"), }), ).toBe(cachedPython); }