diff --git a/packages/coding-agent/src/cli/setup-cli.ts b/packages/coding-agent/src/cli/setup-cli.ts index 24d9cbb73..1b4493112 100644 --- a/packages/coding-agent/src/cli/setup-cli.ts +++ b/packages/coding-agent/src/cli/setup-cli.ts @@ -83,7 +83,7 @@ function managedPythonPath(): string { * Check Python environment and kernel dependencies. */ async function checkPythonSetup(cwd: string, interpreter?: string): Promise { - const availability = await checkPythonKernelAvailability(cwd, interpreter); + const availability = await checkPythonKernelAvailability(cwd, interpreter, { forceProbe: true }); return { available: availability.ok, pythonPath: availability.pythonPath, diff --git a/packages/coding-agent/src/eval/py/kernel.ts b/packages/coding-agent/src/eval/py/kernel.ts index 945db5561..82b19a1e9 100644 --- a/packages/coding-agent/src/eval/py/kernel.ts +++ b/packages/coding-agent/src/eval/py/kernel.ts @@ -82,8 +82,9 @@ const availabilityCache = new Map>(); export async function checkPythonKernelAvailability( cwd: string, interpreter?: string, + options?: { forceProbe?: boolean }, ): Promise { - if (isBunTestRuntime() || $flag("PI_PYTHON_SKIP_CHECK")) { + if (!options?.forceProbe && (isBunTestRuntime() || $flag("PI_PYTHON_SKIP_CHECK"))) { return { ok: true }; } const resolvedCwd = path.resolve(cwd); diff --git a/packages/coding-agent/test/setup-cli.test.ts b/packages/coding-agent/test/setup-cli.test.ts index 92834855a..c1a35a18f 100644 --- a/packages/coding-agent/test/setup-cli.test.ts +++ b/packages/coding-agent/test/setup-cli.test.ts @@ -11,11 +11,12 @@ interface CliProcessResult { error: string; } -async function runSetupPython(cwd: string): Promise { +async function runSetupPython(cwd: string, envOverrides?: NodeJS.ProcessEnv): Promise { const env: NodeJS.ProcessEnv = { ...process.env, NO_COLOR: "1", PI_CODING_AGENT_DIR: path.join(cwd, "agent"), + ...envOverrides, }; delete env.VIRTUAL_ENV; delete env.CONDA_DEFAULT_ENV; @@ -78,4 +79,22 @@ describe("omp setup python", () => { usingManagedEnv: false, }); }); + it.skipIf(process.platform === "win32")("does not let the global probe bypass skip setup validation", async () => { + projectDir = TempDir.createSync("@omp-setup-python-"); + const cwd = projectDir.path(); + const interpreter = path.join(cwd, "configured-python"); + await Bun.write(interpreter, "#!/bin/sh\nexit 23\n"); + await fs.chmod(interpreter, 0o755); + await Bun.write(path.join(cwd, ".omp", "config.yml"), `python:\n interpreter: ${interpreter}\n`); + + const result = await runSetupPython(cwd, { PI_PYTHON_SKIP_CHECK: "1" }); + + expect(result.error).toBe(""); + expect(result.exitCode).toBe(1); + expect(JSON.parse(result.output)).toMatchObject({ + available: false, + pythonPath: interpreter, + usingManagedEnv: false, + }); + }); });