285 lines · 8.9 KB · TypeScript
RawDownload
import { describe, expect, it } from "vitest";import { DEFAULT_MODEL_BY_PROVIDER, type ModelCapabilities } from "@t3tools/contracts"; import {  applyClaudePromptEffortPrefix,  getDefaultContextWindow,  getDefaultEffort,  hasContextWindowOption,  hasEffortLevel,  isClaudeUltrathinkPrompt,  normalizeClaudeModelOptionsWithCapabilities,  normalizeCodexModelOptionsWithCapabilities,  normalizeModelSlug,  resolveApiModelId,  resolveContextWindow,  resolveEffort,  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,  contextWindowOptions: [],  promptInjectedEffortLevels: [],}; const claudeCaps: ModelCapabilities = {  reasoningEffortLevels: [    { value: "medium", label: "Medium" },    { value: "high", label: "High", isDefault: true },    { value: "ultrathink", label: "Ultrathink" },  ],  supportsFastMode: false,  supportsThinkingToggle: false,  contextWindowOptions: [    { value: "200k", label: "200k" },    { value: "1m", label: "1M", isDefault: true },  ],  promptInjectedEffortLevels: ["ultrathink"],}; describe("normalizeModelSlug", () => {  it("maps known aliases to canonical slugs", () => {    expect(normalizeModelSlug("gpt-5-codex")).toBe("gpt-5.4");    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, "codex")).toBe(DEFAULT_MODEL_BY_PROVIDER.codex);     expect(resolveModelSlugForProvider("claudeAgent", undefined)).toBe(      DEFAULT_MODEL_BY_PROVIDER.claudeAgent,    );  });   it("preserves normalized unknown models", () => {    expect(resolveModelSlug("custom/internal-model", "codex")).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("resolveEffort", () => {  it("returns the explicit value when supported and not prompt-injected", () => {    expect(resolveEffort(codexCaps, "xhigh")).toBe("xhigh");    expect(resolveEffort(codexCaps, "high")).toBe("high");    expect(resolveEffort(claudeCaps, "medium")).toBe("medium");  });   it("falls back to default when value is unsupported", () => {    expect(resolveEffort(codexCaps, "bogus")).toBe("high");    expect(resolveEffort(claudeCaps, "bogus")).toBe("high");  });   it("returns the default when no value is provided", () => {    expect(resolveEffort(codexCaps, undefined)).toBe("high");    expect(resolveEffort(codexCaps, null)).toBe("high");    expect(resolveEffort(codexCaps, "")).toBe("high");    expect(resolveEffort(codexCaps, "  ")).toBe("high");  });   it("excludes prompt-injected efforts and falls back to default", () => {    expect(resolveEffort(claudeCaps, "ultrathink")).toBe("high");  });   it("returns undefined for models with no effort levels", () => {    const noCaps: ModelCapabilities = {      reasoningEffortLevels: [],      supportsFastMode: false,      supportsThinkingToggle: false,      contextWindowOptions: [],      promptInjectedEffortLevels: [],    };    expect(resolveEffort(noCaps, undefined)).toBeUndefined();    expect(resolveEffort(noCaps, "high")).toBeUndefined();  });}); 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();  });}); describe("context window helpers", () => {  it("reads default context window", () => {    expect(getDefaultContextWindow(claudeCaps)).toBe("1m");  });   it("returns null for models without context window options", () => {    expect(getDefaultContextWindow(codexCaps)).toBeNull();  });   it("checks context window support", () => {    expect(hasContextWindowOption(claudeCaps, "1m")).toBe(true);    expect(hasContextWindowOption(claudeCaps, "200k")).toBe(true);    expect(hasContextWindowOption(claudeCaps, "bogus")).toBe(false);    expect(hasContextWindowOption(codexCaps, "1m")).toBe(false);  });}); describe("resolveContextWindow", () => {  it("returns the explicit value when supported", () => {    expect(resolveContextWindow(claudeCaps, "200k")).toBe("200k");    expect(resolveContextWindow(claudeCaps, "1m")).toBe("1m");  });   it("falls back to default when value is unsupported", () => {    expect(resolveContextWindow(claudeCaps, "bogus")).toBe("1m");  });   it("returns the default when no value is provided", () => {    expect(resolveContextWindow(claudeCaps, undefined)).toBe("1m");    expect(resolveContextWindow(claudeCaps, null)).toBe("1m");    expect(resolveContextWindow(claudeCaps, "")).toBe("1m");  });   it("returns undefined for models with no context window options", () => {    expect(resolveContextWindow(codexCaps, undefined)).toBeUndefined();    expect(resolveContextWindow(codexCaps, "1m")).toBeUndefined();  });}); describe("resolveApiModelId", () => {  it("appends [1m] suffix for 1m context window", () => {    expect(      resolveApiModelId({        provider: "claudeAgent",        model: "claude-opus-4-6",        options: { contextWindow: "1m" },      }),    ).toBe("claude-opus-4-6[1m]");  });   it("returns the model as-is for 200k context window", () => {    expect(      resolveApiModelId({        provider: "claudeAgent",        model: "claude-opus-4-6",        options: { contextWindow: "200k" },      }),    ).toBe("claude-opus-4-6");  });   it("returns the model as-is when no context window is set", () => {    expect(resolveApiModelId({ provider: "claudeAgent", model: "claude-opus-4-6" })).toBe(      "claude-opus-4-6",    );    expect(      resolveApiModelId({ provider: "claudeAgent", model: "claude-opus-4-6", options: {} }),    ).toBe("claude-opus-4-6");  });   it("returns the model as-is for Codex selections", () => {    expect(resolveApiModelId({ provider: "codex", model: "gpt-5.4" })).toBe("gpt-5.4");  });}); describe("normalize*ModelOptionsWithCapabilities", () => {  it("preserves explicit false codex fast mode", () => {    expect(      normalizeCodexModelOptionsWithCapabilities(codexCaps, {        reasoningEffort: "high",        fastMode: false,      }),    ).toEqual({      reasoningEffort: "high",      fastMode: false,    });  });   it("preserves the default Claude context window explicitly", () => {    expect(      normalizeClaudeModelOptionsWithCapabilities(        {          ...claudeCaps,          contextWindowOptions: [            { value: "200k", label: "200k", isDefault: true },            { value: "1m", label: "1M" },          ],        },        {          effort: "high",          contextWindow: "200k",        },      ),    ).toEqual({      effort: "high",      contextWindow: "200k",    });  });   it("omits unsupported Claude context window options", () => {    expect(      normalizeClaudeModelOptionsWithCapabilities(        {          ...claudeCaps,          reasoningEffortLevels: [],          supportsThinkingToggle: true,          contextWindowOptions: [],        },        {          thinking: true,          contextWindow: "1m",        },      ),    ).toEqual({      thinking: true,    });  });});