import assert from "node:assert/strict"; import { describe, it } from "node:test"; import { MODELS, modelIds, isClineFreeGatewayModelId, fetchRemoteModels, resolveModels, GLM_FLASH_THINKING_LEVEL_MAP, } from "../src/models.ts"; describe("modelIds", () => { it("returns static fallback model IDs", () => { const ids = modelIds(); assert.equal(ids.length, MODELS.length); assert.ok(ids.includes("z-ai/glm-5.3-flash")); assert.ok(ids.includes("z-ai/glm-5.2:free")); assert.ok(ids.includes("z-ai/glm-4.7-flash")); }); it("all static IDs are z-ai gateway models", () => { for (const id of modelIds()) { assert.ok(isClineFreeGatewayModelId(id)); } }); }); describe("isClineFreeGatewayModelId", () => { it("accepts z-ai models", () => { assert.equal(isClineFreeGatewayModelId("z-ai/glm-5.3-flash"), true); assert.equal(isClineFreeGatewayModelId("z-ai/glm-5.2:free"), true); }); it("rejects batch and alias models", () => { assert.equal(isClineFreeGatewayModelId("z-ai/glm-5.3-flash:batch"), false); assert.equal(isClineFreeGatewayModelId("~z-ai/glm-latest"), false); assert.equal(isClineFreeGatewayModelId("cline-pass/glm-5.3"), false); }); }); describe("fetchRemoteModels", () => { it("filters remote list to z-ai gateway models", async () => { const fetch = async () => ({ ok: true, json: async () => ({ data: [ { id: "z-ai/glm-5.3-flash", name: "GLM 5.3 Flash" }, { id: "z-ai/glm-5.3-flash:batch", name: "batch" }, { id: "~z-ai/glm-latest", name: "alias" }, { id: "cline-pass/glm-5.3", name: "paid" }, ], }), }) as Response; const models = await fetchRemoteModels({ apiKey: "test-key", fetch }); assert.ok(models); assert.equal(models.length, 1); assert.equal(models[0]?.id, "z-ai/glm-5.3-flash"); }); it("returns undefined when fetch fails", async () => { const fetch = async () => ({ ok: false }) as Response; const models = await fetchRemoteModels({ apiKey: "test-key", fetch }); assert.equal(models, undefined); }); }); describe("resolveModels", () => { it("falls back to static catalog without an API key", async () => { const models = await resolveModels(undefined); assert.equal(models.length, MODELS.length); assert.equal(models[0]?.id, "z-ai/glm-5.3-flash"); }); it("uses remote models when available", async () => { const fetch = async () => ({ ok: true, json: async () => ({ data: [{ id: "z-ai/glm-5.3-flash", name: "GLM 5.3 Flash" }], }), }) as Response; const models = await resolveModels("test-key", { fetch }); assert.equal(models.length, 1); assert.equal(models[0]?.thinkingLevelMap.low, GLM_FLASH_THINKING_LEVEL_MAP.low); }); });