File size: 4,091 Bytes
96e86e5 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { afterEach, describe, expect, it } from "vitest";
import {
discoverCodeBuddyModels,
listCodeBuddyModels,
resetCodeBuddyModelsCacheForTests,
} from "@penclipai/adapter-codebuddy-local/server";
async function writeFakeCodeBuddyCommand(root: string, scriptBody: string): Promise<string> {
if (process.platform === "win32") {
const scriptPath = path.join(root, "codebuddy.js");
const commandPath = path.join(root, "codebuddy.cmd");
await fs.writeFile(scriptPath, scriptBody, "utf8");
await fs.writeFile(commandPath, `@echo off\r\n"${process.execPath}" "${scriptPath}" %*\r\n`, "utf8");
return commandPath;
}
const commandPath = path.join(root, "codebuddy");
await fs.writeFile(commandPath, `#!/usr/bin/env node\n${scriptBody}`, "utf8");
await fs.chmod(commandPath, 0o755);
return commandPath;
}
describe("codebuddy model discovery", () => {
const cleanupDirs = new Set<string>();
afterEach(async () => {
delete process.env.PAPERCLIP_CODEBUDDY_COMMAND;
resetCodeBuddyModelsCacheForTests();
await Promise.all(Array.from(cleanupDirs).map((dir) => fs.rm(dir, { recursive: true, force: true })));
cleanupDirs.clear();
});
it("parses the currently supported model list from codebuddy --help", async () => {
const root = await fs.mkdtemp(path.join(os.tmpdir(), "paperclip-codebuddy-models-"));
cleanupDirs.add(root);
const command = await writeFakeCodeBuddyCommand(
root,
`
if (process.argv.includes("--help")) {
console.log([
"Usage: codebuddy [options]",
" --model <model> Select model. Currently supported: (glm-5.0, glm-4.7, minimax-m2.7, glm-5.0, deepseek-v3-2-volc)",
].join("\\n"));
process.exit(0);
}
process.exit(0);
`,
);
const models = await discoverCodeBuddyModels({ command, cwd: root });
expect(models.map((model) => model.id)).toEqual([
"deepseek-v3-2-volc",
"glm-4.7",
"glm-5.0",
"minimax-m2.7",
]);
});
it("caches model discovery for repeated listCodeBuddyModels calls", async () => {
const root = await fs.mkdtemp(path.join(os.tmpdir(), "paperclip-codebuddy-models-cache-"));
cleanupDirs.add(root);
const hitsPath = path.join(root, "hits.txt");
process.env.PAPERCLIP_CODEBUDDY_COMMAND = await writeFakeCodeBuddyCommand(
root,
`
const fs = require("node:fs");
const hitsPath = ${JSON.stringify(hitsPath)};
if (process.argv.includes("--help")) {
const hits = fs.existsSync(hitsPath) ? Number(fs.readFileSync(hitsPath, "utf8")) : 0;
fs.writeFileSync(hitsPath, String(hits + 1), "utf8");
console.log("Usage: codebuddy [options]\\n --model <model> Select model. Currently supported: (glm-5.0, kimi-k2.5)");
process.exit(0);
}
process.exit(0);
`,
);
const first = await listCodeBuddyModels();
const second = await listCodeBuddyModels();
expect(first).toEqual(second);
expect(Number(await fs.readFile(hitsPath, "utf8"))).toBe(1);
});
it("returns an empty list when help output omits the supported-model section", async () => {
const root = await fs.mkdtemp(path.join(os.tmpdir(), "paperclip-codebuddy-models-empty-"));
cleanupDirs.add(root);
process.env.PAPERCLIP_CODEBUDDY_COMMAND = await writeFakeCodeBuddyCommand(
root,
`
if (process.argv.includes("--help")) {
console.log("Usage: codebuddy [options]\\n --model <model> Select model.");
process.exit(0);
}
process.exit(0);
`,
);
await expect(listCodeBuddyModels()).resolves.toEqual([]);
});
it("returns an empty list when the codebuddy help command fails", async () => {
const root = await fs.mkdtemp(path.join(os.tmpdir(), "paperclip-codebuddy-models-fail-"));
cleanupDirs.add(root);
process.env.PAPERCLIP_CODEBUDDY_COMMAND = await writeFakeCodeBuddyCommand(
root,
`
if (process.argv.includes("--help")) {
console.error("boom");
process.exit(1);
}
process.exit(0);
`,
);
await expect(listCodeBuddyModels()).resolves.toEqual([]);
});
});
|