import { describe, expect, it } from "vitest"; import { DEFAULT_MODEL, DEFAULT_MODEL_BY_PROVIDER, type ModelCapabilities, } from "@t3tools/contracts"; import { applyClaudePromptEffortPrefix, getDefaultEffort, hasEffortLevel, isClaudeUltrathinkPrompt, normalizeModelSlug, resolveModelSlug, resolveModelSlugForProvider, resolveSelectableModel, trimOrNull, } from "./model"; const codexCaps: ModelCapabilities = { reasoningEffortLevels: [ { value: "xhigh", label: "Extra High" }, { value: "high", label: "High", isDefault: true }, ], supportsFastMode: true, supportsThinkingToggle: false, promptInjectedEffortLevels: [], }; const claudeCaps: ModelCapabilities = { reasoningEffortLevels: [ { value: "medium", label: "Medium" }, { value: "high", label: "High", isDefault: true }, { value: "ultrathink", label: "Ultrathink" }, ], supportsFastMode: false, supportsThinkingToggle: false, promptInjectedEffortLevels: ["ultrathink"], }; describe("normalizeModelSlug", () => { it("maps known aliases to canonical slugs", () => { expect(normalizeModelSlug("5.3")).toBe("gpt-5.3-codex"); expect(normalizeModelSlug("sonnet", "claudeAgent")).toBe("claude-sonnet-4-6"); }); it("returns null for empty or missing values", () => { expect(normalizeModelSlug("")).toBeNull(); expect(normalizeModelSlug(" ")).toBeNull(); expect(normalizeModelSlug(null)).toBeNull(); expect(normalizeModelSlug(undefined)).toBeNull(); }); }); describe("resolveModelSlug", () => { it("returns defaults when the model is missing", () => { expect(resolveModelSlug(undefined)).toBe(DEFAULT_MODEL); expect(resolveModelSlugForProvider("claudeAgent", undefined)).toBe( DEFAULT_MODEL_BY_PROVIDER.claudeAgent, ); }); it("preserves normalized unknown models", () => { expect(resolveModelSlug("custom/internal-model")).toBe("custom/internal-model"); }); }); describe("resolveSelectableModel", () => { it("resolves exact slugs, labels, and aliases", () => { const options = [ { slug: "gpt-5.3-codex", name: "GPT-5.3 Codex" }, { slug: "claude-sonnet-4-6", name: "Claude Sonnet 4.6" }, ]; expect(resolveSelectableModel("codex", "gpt-5.3-codex", options)).toBe("gpt-5.3-codex"); expect(resolveSelectableModel("codex", "gpt-5.3 codex", options)).toBe("gpt-5.3-codex"); expect(resolveSelectableModel("claudeAgent", "sonnet", options)).toBe("claude-sonnet-4-6"); }); }); describe("capability helpers", () => { it("reads default efforts", () => { expect(getDefaultEffort(codexCaps)).toBe("high"); expect(getDefaultEffort(claudeCaps)).toBe("high"); }); it("checks effort support", () => { expect(hasEffortLevel(codexCaps, "xhigh")).toBe(true); expect(hasEffortLevel(codexCaps, "max")).toBe(false); }); }); describe("misc helpers", () => { it("detects ultrathink prompts", () => { expect(isClaudeUltrathinkPrompt("Ultrathink:\nInvestigate")).toBe(true); expect(isClaudeUltrathinkPrompt("Investigate")).toBe(false); }); it("prefixes ultrathink prompts once", () => { expect(applyClaudePromptEffortPrefix("Investigate", "ultrathink")).toBe( "Ultrathink:\nInvestigate", ); expect(applyClaudePromptEffortPrefix("Ultrathink:\nInvestigate", "ultrathink")).toBe( "Ultrathink:\nInvestigate", ); }); it("trims strings to null", () => { expect(trimOrNull(" hi ")).toBe("hi"); expect(trimOrNull(" ")).toBeNull(); }); });