import { mkdirSync, rmSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { getModel } from "@earendil-works/pi-ai"; import { describe, expect, it } from "vitest"; import { parseArgs } from "../src/cli/args.js"; import { mergeAgentSessionRuntimeConfig } from "../src/core/agent-session-config.js"; import { AuthStorage } from "../src/core/auth-storage.js"; import { createAgentSession } from "../src/core/sdk.js"; import { SessionManager } from "../src/core/session-manager.js"; import { SettingsManager } from "../src/core/settings-manager.js"; import { createAgentConnectionState } from "../src/modes/agent-connection/snapshot.js"; describe("remote python host configuration", () => { it("reads remotePythonHost and remotePython from settings", () => { const settings = SettingsManager.inMemory({ remotePythonHost: "chernobog", remotePython: "/opt/venv/bin/python", }); expect(settings.getRemotePythonHost()).toBe("chernobog"); expect(settings.getRemotePython()).toBe("/opt/venv/bin/python"); }); it("defaults remotePythonHost and remotePython to undefined when unset", () => { const settings = SettingsManager.inMemory({}); expect(settings.getRemotePythonHost()).toBeUndefined(); expect(settings.getRemotePython()).toBeUndefined(); }); it("parses --remote-python-host from CLI args", () => { const parsed = parseArgs(["--remote-python-host", "chernobog"]); expect(parsed.remotePythonHost).toBe("chernobog"); expect(parsed.diagnostics).toEqual([]); }); it("parses --remote-host alias from CLI args", () => { const parsed = parseArgs(["--remote-host", "mayer@chernobog"]); expect(parsed.remotePythonHost).toBe("mayer@chernobog"); expect(parsed.diagnostics).toEqual([]); }); it("merges remoteHost in runtime config", () => { const base = { remoteHost: "chernobog" }; const override = { cwd: "/new/cwd" }; const merged = mergeAgentSessionRuntimeConfig(base, override); expect(merged.remoteHost).toBe("chernobog"); const hostOverride = mergeAgentSessionRuntimeConfig(base, { remoteHost: "perun" }); expect(hostOverride.remoteHost).toBe("perun"); }); it("configures AgentSession with remoteHost via createAgentSession", async () => { const tempDir = join(tmpdir(), `pi-remote-test-${Date.now()}`); mkdirSync(tempDir, { recursive: true }); try { const authStorage = AuthStorage.create(join(tempDir, "auth.json")); authStorage.setRuntimeApiKey("anthropic", "test-key"); const { session } = await createAgentSession({ cwd: tempDir, agentDir: tempDir, model: getModel("anthropic", "claude-sonnet-4-5")!, settingsManager: SettingsManager.inMemory({}), sessionManager: SessionManager.inMemory(tempDir), authStorage, remoteHost: "chernobog", }); expect(session.remoteHost).toBe("chernobog"); expect(session.systemPrompt).toContain("Remote execution host: chernobog"); expect(session.systemPrompt).toContain( "The `ipython` tool and `bash()` execute on remote host chernobog over SSH.", ); const connectionState = createAgentConnectionState({ session } as any); expect(connectionState.remoteHost).toBe("chernobog"); session.dispose(); } finally { rmSync(tempDir, { recursive: true, force: true }); } }); });