import { describe, it, expect } from "vitest"; import { getRegistryEntry } from "../../config/providerRegistry.ts"; import { PROVIDER_ID_TO_ALIAS, getModelsByProviderId, getProviderModels, } from "../../config/providerModels.ts"; import { buildGlmAnthropicMessagesUrl, buildGlmOpenAIChatUrl } from "../../config/glmProvider.ts"; import { getPricingForModel } from "../../../src/shared/constants/pricing.ts"; describe("GLM Coding provider registry surfaces", () => { it("registers the GLM Coding provider with the expected transport metadata", () => { const entry = getRegistryEntry("glm"); expect(entry).toBeDefined(); expect(entry?.id).toBe("glm"); expect(entry?.alias).toBe("glm"); expect(entry?.format).toBe("openai"); expect(entry?.executor).toBe("glm"); expect(entry?.baseUrl).toBe("https://api.z.ai/api/coding/paas/v4/chat/completions"); expect(entry?.authType).toBe("apikey"); expect(entry?.authHeader).toBe("bearer"); expect(entry?.headers?.["Anthropic-Version"]).toBeUndefined(); expect(entry?.requestDefaults).toEqual({ maxTokens: 16384 }); expect(entry?.timeoutMs).toBe(3000000); }); it("preserves custom GLM base URL query parameters while deriving transport endpoints", () => { const providerSpecificData = { baseUrl: "https://proxy.example/glm/api/coding/paas/v4/chat/completions?tenant=alpha&route=glm", }; expect(buildGlmOpenAIChatUrl(providerSpecificData)).toBe( "https://proxy.example/glm/api/coding/paas/v4/chat/completions?tenant=alpha&route=glm" ); expect( buildGlmAnthropicMessagesUrl({ anthropicBaseUrl: "https://proxy.example/glm/api/anthropic/v1/messages?tenant=alpha&route=glm", }) ).toBe("https://proxy.example/glm/api/anthropic/v1/messages?tenant=alpha&route=glm&beta=true"); }); it("registers GLMT as an explicit high-budget preset over the dual GLM transport", () => { const entry = getRegistryEntry("glmt"); expect(entry).toBeDefined(); expect(entry?.id).toBe("glmt"); expect(entry?.alias).toBe("glmt"); expect(entry?.format).toBe("openai"); expect(entry?.executor).toBe("glm"); expect(entry?.baseUrl).toBe("https://api.z.ai/api/coding/paas/v4/chat/completions"); expect(entry?.authType).toBe("apikey"); expect(entry?.authHeader).toBe("bearer"); expect(entry?.headers?.["Anthropic-Version"]).toBeUndefined(); expect(entry?.requestDefaults).toEqual({ maxTokens: 65536, temperature: 0.2, thinkingBudgetTokens: 24576, thinkingType: "adaptive", }); expect(entry?.timeoutMs).toBe(900000); }); it("registers GLM China on the same executor and capability surface", () => { const entry = getRegistryEntry("glm-cn"); expect(entry).toBeDefined(); expect(entry?.id).toBe("glm-cn"); expect(entry?.alias).toBe("glmcn"); expect(entry?.format).toBe("openai"); expect(entry?.executor).toBe("glm"); expect(entry?.baseUrl).toBe("https://open.bigmodel.cn/api/coding/paas/v4/chat/completions"); expect(entry?.requestDefaults).toEqual({ maxTokens: 16384 }); expect(entry?.timeoutMs).toBe(3000000); expect(getProviderModels("glmcn").map((model) => model.id)).toEqual( getProviderModels("glm").map((model) => model.id) ); }); it("exposes the same GLM model inventory through registry-derived model helpers", () => { const byProviderId = getModelsByProviderId("glm"); const byAlias = getProviderModels("glm"); expect(PROVIDER_ID_TO_ALIAS.glm).toBe("glm"); expect(byProviderId).toEqual(byAlias); expect(byProviderId.map((model) => model.id)).toEqual([ "glm-5.2", "glm-5.2-high", "glm-5.2-max", "glm-5.1", "glm-5", "glm-5-turbo", "glm-4.7-flash", "glm-4.7", "glm-4.6v", "glm-4.6", "glm-4.5v", "glm-4.5", "glm-4.5-air", ]); }); it("registers GLM-5.2 with correct specs and effort tier aliases", () => { const models = getModelsByProviderId("glm"); const get = (id: string) => models.find((m) => m.id === id); // Base model const base = get("glm-5.2"); expect(base).toBeDefined(); expect(base?.contextLength).toBe(1000000); expect(base?.maxOutputTokens).toBe(131072); expect(base?.supportsReasoning).toBe(true); expect(base?.toolCalling).toBe(true); // Effort tier aliases share the same specs const high = get("glm-5.2-high"); expect(high).toBeDefined(); expect(high?.contextLength).toBe(1000000); expect(high?.maxOutputTokens).toBe(131072); const max = get("glm-5.2-max"); expect(max).toBeDefined(); expect(max?.contextLength).toBe(1000000); expect(max?.maxOutputTokens).toBe(131072); }); it("applies doc-backed context window overrides for GLM models", () => { const models = getModelsByProviderId("glm"); const get = (id: string) => models.find((m) => m.id === id); // Models with explicit overrides (Z.AI docs) expect(get("glm-5.1")?.contextLength).toBe(204800); expect(get("glm-4.6v")?.contextLength).toBe(128000); expect(get("glm-4.5v")?.contextLength).toBe(16000); expect(get("glm-4.5")?.contextLength).toBe(128000); expect(get("glm-4.5-air")?.contextLength).toBe(128000); expect(get("glm-5.1")?.maxOutputTokens).toBe(131072); expect(get("glm-4.6")?.maxOutputTokens).toBe(32768); // Models with explicit 200K defaults to avoid null capabilities in direct routes. expect(get("glm-5")?.contextLength).toBe(200000); expect(get("glm-5-turbo")?.contextLength).toBe(200000); expect(get("glm-4.7-flash")?.contextLength).toBe(200000); expect(get("glm-4.7")?.contextLength).toBe(200000); expect(get("glm-4.6")?.contextLength).toBe(200000); }); it("keeps representative GLM Coding models tool-call capable and priced", () => { const models = getModelsByProviderId("glm"); const get = (id: string) => models.find((m) => m.id === id); expect(get("glm-5")?.toolCalling).toBe(true); expect(get("glm-4.7-flash")?.toolCalling).toBe(true); expect(get("glm-4.5-air")?.toolCalling).toBe(true); expect(get("glm-5.2")?.toolCalling).toBe(true); expect(get("glm-5.2-high")?.toolCalling).toBe(true); expect(get("glm-5.2-max")?.toolCalling).toBe(true); expect(getPricingForModel("glm", "glm-5")).toEqual({ input: 1.0, output: 3.2, cached: 0.2, reasoning: 4.8, cache_creation: 1.0, }); expect(getPricingForModel("glm", "glm-4.7-flash")).toEqual({ input: 0, output: 0, cached: 0, reasoning: 0, cache_creation: 0, }); expect(getPricingForModel("glm", "glm-4.5-air")).toEqual({ input: 0.2, output: 1.1, cached: 0.03, reasoning: 1.1, cache_creation: 0.2, }); expect(getPricingForModel("glm", "glm-5.2")).toEqual({ input: 1.2, output: 5, cached: 0.3, reasoning: 5, cache_creation: 1.2, }); expect(getPricingForModel("glm", "glm-5.2-max")).toEqual({ input: 1.2, output: 5, cached: 0.3, reasoning: 5, cache_creation: 1.2, }); }); it("keeps the repo-derived GLM inventory internally aligned across registry and pricing surfaces", () => { const modelIds = getModelsByProviderId("glm").map((model) => model.id); for (const modelId of modelIds) { expect(getPricingForModel("glm", modelId), `missing pricing for ${modelId}`).toBeTruthy(); } }); });