fix(eval): thread python.interpreter from session settings and expand ~

Resolve the explicit interpreter from the session's Settings instance
(ToolSession.settings / AgentSession.settings) instead of re-reading the
process-global Settings.init() singleton, so project-scoped and cloned
session settings take effect. The availability cache is now keyed by
cwd + interpreter, and PythonKernel.start/executePython accept the
resolved interpreter as an option. Also expand home-relative paths
(~/...) before resolving against cwd, and document the contract of
resolveExplicitPythonRuntime.

Addresses review feedback on #2204.
This commit is contained in:
can1357
2026-06-10 08:26:00 +02:00
parent caff395d07
commit 24cbc93913
7 changed files with 87 additions and 20 deletions
@@ -1,5 +1,6 @@
import { afterEach, describe, expect, it, vi } from "bun:test";
import * as fs from "node:fs";
import * as os from "node:os";
import * as path from "node:path";
import {
enumeratePythonRuntimes,
@@ -126,6 +127,29 @@ describe("enumeratePythonRuntimes", () => {
expect(runtime.env.VIRTUAL_ENV).toBe(venvDir);
expect(runtime.env.PATH).toBe(`${binDir}${path.delimiter}${path.join(path.sep, "usr", "bin")}`);
});
it("expands a home-relative explicit interpreter instead of resolving against cwd", () => {
const home = path.join(path.sep, "home", "tester");
vi.spyOn(os, "homedir").mockReturnValue(home);
vi.spyOn(fs, "existsSync").mockReturnValue(false);
const runtime = resolveExplicitPythonRuntime("~/venvs/py/bin/python", path.join(path.sep, "work"), {});
expect(runtime.pythonPath).toBe(path.join(home, "venvs", "py", "bin", "python"));
});
it("resolves a relative explicit interpreter against cwd", () => {
vi.spyOn(fs, "existsSync").mockReturnValue(false);
const runtime = resolveExplicitPythonRuntime(
path.join(".venv", "bin", "python"),
path.join(path.sep, "work"),
{},
);
expect(runtime.pythonPath).toBe(path.join(path.sep, "work", ".venv", "bin", "python"));
});
it("throws from resolvePythonRuntime when no interpreter can be found", () => {
vi.spyOn(piUtils, "getPythonEnvDir").mockReturnValue(managedDir);
vi.spyOn(piUtils, "$which").mockReturnValue(null);