Files
oh-my-pi/packages/coding-agent/test/core/python-modules.test.ts
T
can1357 cb5bbbf382 refactor(coding-agent): flattened directory structure, eliminated core/ folder
- Eliminated core/ directory (252 files, 23 subdirs → distributed)
- Reduced max nesting from 9 levels to 5 levels
- Promoted tool subdirs to top level: exa/, lsp/, patch/, task/, web/
- Merged web-scrapers/ + web-search/ into web/{scrapers,search}/
- Flattened modes/interactive/ to modes/
- Split execution/ into: ipy/ (python), exec/ (bash), ssh/
- Renamed ipy/python-*.ts to ipy/*.ts (executor, kernel, etc.)
- Flattened cursor/exec-bridge.ts to cursor.ts
- Created logical groupings: config/, session/, extensibility/, export/
- Updated all imports across 500+ files
2026-01-23 12:24:47 +01:00

101 lines
4.0 KiB
TypeScript

import { afterEach, describe, expect, it } from "bun:test";
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
import { basename, join, resolve } from "node:path";
import { createTempDirSync } from "@oh-my-pi/pi-utils";
import { discoverPythonModules, loadPythonModules, type PythonModuleExecutor } from "$c/ipy/modules";
const fixturesDir = resolve(import.meta.dir, "../../test/fixtures/python-modules");
const readFixture = (name: string): string => readFileSync(join(fixturesDir, name), "utf-8");
const writeModule = (dir: string, name: string, tag: string) => {
mkdirSync(dir, { recursive: true });
const base = readFixture(name);
writeFileSync(join(dir, name), `${base}\n# ${tag}`);
};
describe("python modules", () => {
let tempRoot: ReturnType<typeof createTempDirSync> | null = null;
afterEach(() => {
if (tempRoot) {
tempRoot.remove();
}
tempRoot = null;
});
it("discovers modules with project override and sorted order", async () => {
tempRoot = createTempDirSync("@omp-python-modules-");
const homeDir = join(tempRoot.path, "home");
const cwd = join(tempRoot.path, "project");
writeModule(join(homeDir, ".omp", "agent", "modules"), "alpha.py", "user-omp");
writeModule(join(homeDir, ".pi", "agent", "modules"), "beta.py", "user-pi");
writeModule(join(homeDir, ".pi", "agent", "modules"), "delta.py", "user-pi");
writeModule(join(cwd, ".omp", "modules"), "alpha.py", "project-omp");
writeModule(join(cwd, ".omp", "modules"), "beta.py", "project-omp");
writeModule(join(cwd, ".pi", "modules"), "gamma.py", "project-pi");
const modules = await discoverPythonModules({ cwd, homeDir });
const names = modules.map((module) => basename(module.path));
expect(names).toEqual(["alpha.py", "beta.py", "delta.py", "gamma.py"]);
expect(modules.map((module) => ({ name: basename(module.path), source: module.source }))).toEqual([
{ name: "alpha.py", source: "project" },
{ name: "beta.py", source: "project" },
{ name: "delta.py", source: "user" },
{ name: "gamma.py", source: "project" },
]);
expect(modules.find((module) => module.path.endsWith("alpha.py"))?.content).toContain("project-omp");
expect(modules.find((module) => module.path.endsWith("delta.py"))?.content).toContain("user-pi");
});
it("loads modules in sorted order with silent execution", async () => {
tempRoot = createTempDirSync("@omp-python-modules-");
const homeDir = join(tempRoot.path, "home");
const cwd = join(tempRoot.path, "project");
writeModule(join(homeDir, ".omp", "agent", "modules"), "beta.py", "user-omp");
writeModule(join(homeDir, ".omp", "agent", "modules"), "alpha.py", "user-omp");
const calls: Array<{ name: string; options?: { silent?: boolean; storeHistory?: boolean } }> = [];
const executor: PythonModuleExecutor = {
execute: async (code: string, options?: { silent?: boolean; storeHistory?: boolean }) => {
const name = code.includes("def alpha") ? "alpha" : "beta";
calls.push({ name, options });
return { status: "ok", cancelled: false };
},
};
await loadPythonModules(executor, { cwd, homeDir });
expect(calls.map((call) => call.name)).toEqual(["alpha", "beta"]);
for (const call of calls) {
expect(call.options).toEqual({ silent: true, storeHistory: false });
}
});
it("fails fast when a module fails to execute", async () => {
tempRoot = createTempDirSync("@omp-python-modules-");
const homeDir = join(tempRoot.path, "home");
const cwd = join(tempRoot.path, "project");
writeModule(join(homeDir, ".omp", "agent", "modules"), "alpha.py", "user-omp");
writeModule(join(cwd, ".omp", "modules"), "beta.py", "project-omp");
const executor: PythonModuleExecutor = {
execute: async (code: string) => {
if (code.includes("def beta")) {
return {
status: "error",
cancelled: false,
error: { name: "Error", value: "boom", traceback: [] },
};
}
return { status: "ok", cancelled: false };
},
};
await expect(loadPythonModules(executor, { cwd, homeDir })).rejects.toThrow("Failed to load Python module");
});
});