diff --git a/packages/coding-agent/test/core/python-kernel-env.test.ts b/packages/coding-agent/test/core/python-kernel-env.test.ts index bc7dc0931..1d56f0f46 100644 --- a/packages/coding-agent/test/core/python-kernel-env.test.ts +++ b/packages/coding-agent/test/core/python-kernel-env.test.ts @@ -11,6 +11,7 @@ describe("Python gateway environment filtering", () => { UNSAFE_TOKEN: "nope", PI_CUSTOM: "1", LC_ALL: "en_US.UTF-8", + LD_LIBRARY_PATH: "/opt/conda/lib", }; const filtered = filterEnv(env); @@ -19,6 +20,7 @@ describe("Python gateway environment filtering", () => { expect(filtered.HOME).toBe("/home/test"); expect(filtered.PI_CUSTOM).toBe("1"); expect(filtered.LC_ALL).toBe("en_US.UTF-8"); + expect(filtered.LD_LIBRARY_PATH).toBe("/opt/conda/lib"); expect(filtered.OPENAI_API_KEY).toBeUndefined(); expect(filtered.ANTHROPIC_API_KEY).toBeUndefined(); expect(filtered.UNSAFE_TOKEN).toBeUndefined(); diff --git a/packages/utils/src/dirs.ts b/packages/utils/src/dirs.ts index 0dce3c2aa..690310a27 100644 --- a/packages/utils/src/dirs.ts +++ b/packages/utils/src/dirs.ts @@ -281,9 +281,9 @@ export function getPythonEnvDir(): string { return dirs.rootSubdir("python-env", "data"); } -/** Get the shared Python gateway state directory (~/.omp/python-gateway). */ +/** Get the shared Python gateway state directory (~/.omp/agent/python-gateway; XDG default: $XDG_STATE_HOME/omp/python-gateway). */ export function getPythonGatewayDir(): string { - return dirs.rootSubdir("python-gateway", "state"); + return dirs.agentSubdir(undefined, "python-gateway", "state"); } /** Get the puppeteer sandbox directory (~/.omp/puppeteer). */ diff --git a/packages/utils/test/dirs-python-gateway.test.ts b/packages/utils/test/dirs-python-gateway.test.ts new file mode 100644 index 000000000..d0791a15b --- /dev/null +++ b/packages/utils/test/dirs-python-gateway.test.ts @@ -0,0 +1,61 @@ +import { afterEach, beforeEach, describe, expect, it } from "bun:test"; +import * as fs from "node:fs/promises"; +import * as os from "node:os"; +import * as path from "node:path"; +import { getAgentDir, getConfigDirName, getPythonGatewayDir, setAgentDir } from "../src/dirs"; +import { Snowflake } from "../src/snowflake"; + +describe("python gateway directory", () => { + let tempRoot = ""; + let originalAgentDir = ""; + let originalConfigDir: string | undefined; + let originalXdgStateHome: string | undefined; + + beforeEach(async () => { + originalAgentDir = getAgentDir(); + originalConfigDir = process.env.PI_CONFIG_DIR; + originalXdgStateHome = process.env.XDG_STATE_HOME; + tempRoot = path.join(os.tmpdir(), "pi-utils-python-gateway", Snowflake.next()); + await fs.mkdir(tempRoot, { recursive: true }); + }); + + afterEach(async () => { + if (originalConfigDir === undefined) { + delete process.env.PI_CONFIG_DIR; + } else { + process.env.PI_CONFIG_DIR = originalConfigDir; + } + if (originalXdgStateHome === undefined) { + delete process.env.XDG_STATE_HOME; + } else { + process.env.XDG_STATE_HOME = originalXdgStateHome; + } + setAgentDir(originalAgentDir); + await fs.rm(tempRoot, { recursive: true, force: true }); + }); + + it("uses XDG state for the default agent profile", async () => { + if (process.platform === "win32") return; + + process.env.PI_CONFIG_DIR = `.omp-test-${Snowflake.next()}`; + process.env.XDG_STATE_HOME = path.join(tempRoot, "state"); + await fs.mkdir(path.join(process.env.XDG_STATE_HOME, "omp"), { recursive: true }); + + const defaultAgentDir = path.join(os.homedir(), getConfigDirName(), "agent"); + setAgentDir(defaultAgentDir); + + expect(getPythonGatewayDir()).toBe(path.join(process.env.XDG_STATE_HOME, "omp", "python-gateway")); + }); + + it("keeps custom agent profiles isolated from XDG shared state", async () => { + if (process.platform === "win32") return; + + process.env.XDG_STATE_HOME = path.join(tempRoot, "state"); + await fs.mkdir(path.join(process.env.XDG_STATE_HOME, "omp"), { recursive: true }); + const customAgentDir = path.join(tempRoot, "custom-agent"); + + setAgentDir(customAgentDir); + + expect(getPythonGatewayDir()).toBe(path.join(customAgentDir, "python-gateway")); + }); +});