Imported as a linear vendor commit so forge rebases do not replay the upstream root tree. git-subtree-dir: third_party/pi git-subtree-split: d981de1229ef899957bbe968bc8dcda02a21f477
88 lines
3.0 KiB
TypeScript
88 lines
3.0 KiB
TypeScript
import { spawnSync } from "node:child_process";
|
|
import { cpSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
import { tmpdir } from "node:os";
|
|
import { join } from "node:path";
|
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
import { afterEach, describe, expect, it } from "vitest";
|
|
|
|
const packageRoot = fileURLToPath(new URL("..", import.meta.url));
|
|
const temporaryRoots: string[] = [];
|
|
|
|
afterEach(() => {
|
|
for (const root of temporaryRoots.splice(0)) rmSync(root, { force: true, recursive: true });
|
|
});
|
|
|
|
describe("strict model generation", () => {
|
|
it("fails before mutating generated data when an Individual model loses tool support", () => {
|
|
const fixtureRoot = mkdtempSync(join(tmpdir(), "pi-generate-models-"));
|
|
temporaryRoots.push(fixtureRoot);
|
|
const isolatedPackageRoot = join(fixtureRoot, "package");
|
|
mkdirSync(isolatedPackageRoot);
|
|
for (const entry of ["package.json", "scripts", "src"]) {
|
|
cpSync(join(packageRoot, entry), join(isolatedPackageRoot, entry), { recursive: true });
|
|
}
|
|
const preloadPath = join(fixtureRoot, "mock-models-dev.mjs");
|
|
const modelIds = [
|
|
"deepseek-v4-flash-0731",
|
|
"deepseek-v4-pro",
|
|
"deepseek-v4-pro-0813",
|
|
"glm-5.2",
|
|
"qwen3.6-flash",
|
|
"qwen3.7-max",
|
|
"qwen3.7-plus",
|
|
"qwen3.8-flash",
|
|
"qwen3.8-max",
|
|
"qwen3.8-max-preview",
|
|
];
|
|
const sourceModels = Object.fromEntries(
|
|
modelIds.map((id) => [
|
|
id,
|
|
{
|
|
id,
|
|
name: id,
|
|
tool_call: id !== "deepseek-v4-flash-0731",
|
|
},
|
|
]),
|
|
);
|
|
const catalog = { "alibaba-token-plan": { models: sourceModels } };
|
|
writeFileSync(
|
|
preloadPath,
|
|
`const catalog = ${JSON.stringify(catalog)};\n` +
|
|
`globalThis.fetch = async (input) => {\n` +
|
|
` if (String(input) === "https://models.dev/api.json") {\n` +
|
|
` return new Response(JSON.stringify(catalog), { status: 200 });\n` +
|
|
` }\n` +
|
|
` throw new Error(\`Unexpected fetch: \${String(input)}\`);\n` +
|
|
`};\n`,
|
|
);
|
|
|
|
const generatedPaths = [
|
|
"src/models.generated.ts",
|
|
"src/providers/qwen-token-plan-individual.models.ts",
|
|
"src/providers/data/qwen-token-plan-individual.json",
|
|
"src/providers/data/.manifest.json",
|
|
];
|
|
const sourceBefore = generatedPaths.map((path) => readFileSync(join(packageRoot, path), "utf8"));
|
|
const isolatedBefore = generatedPaths.map((path) => readFileSync(join(isolatedPackageRoot, path), "utf8"));
|
|
|
|
const result = spawnSync(
|
|
process.execPath,
|
|
["--import", pathToFileURL(preloadPath).href, "scripts/generate-models.ts", "--strict"],
|
|
{
|
|
cwd: isolatedPackageRoot,
|
|
encoding: "utf8",
|
|
timeout: 10_000,
|
|
},
|
|
);
|
|
|
|
expect(result.status).toBe(1);
|
|
expect(`${result.stdout}\n${result.stderr}`).toContain(
|
|
"qwen-token-plan-individual model IDs do not match (missing: deepseek-v4-flash-0731)",
|
|
);
|
|
expect(generatedPaths.map((path) => readFileSync(join(isolatedPackageRoot, path), "utf8"))).toEqual(
|
|
isolatedBefore,
|
|
);
|
|
expect(generatedPaths.map((path) => readFileSync(join(packageRoot, path), "utf8"))).toEqual(sourceBefore);
|
|
});
|
|
});
|