import { describe, expect, test } from "bun:test" import { AGENT_MODEL_REQUIREMENTS, CATEGORY_MODEL_REQUIREMENTS, type FallbackEntry, type ModelRequirement, } from "./model-requirements" describe("AGENT_MODEL_REQUIREMENTS", () => { test("oracle has valid fallbackChain with gpt-5.2 as primary", () => { // given - oracle agent requirement const oracle = AGENT_MODEL_REQUIREMENTS["oracle"] // when - accessing oracle requirement // then - fallbackChain exists with gpt-5.2 as first entry expect(oracle).toBeDefined() expect(oracle.fallbackChain).toBeArray() expect(oracle.fallbackChain.length).toBeGreaterThan(0) const primary = oracle.fallbackChain[0] expect(primary.providers).toContain("openai") expect(primary.model).toBe("gpt-5.2") expect(primary.variant).toBe("high") }) test("sisyphus has claude-opus-4-6 as primary and requiresAnyModel", () => { // #given - sisyphus agent requirement const sisyphus = AGENT_MODEL_REQUIREMENTS["sisyphus"] // #when - accessing Sisyphus requirement // #then - fallbackChain has claude-opus-4-6 first, big-pickle last expect(sisyphus).toBeDefined() expect(sisyphus.fallbackChain).toBeArray() expect(sisyphus.fallbackChain).toHaveLength(5) expect(sisyphus.requiresAnyModel).toBe(true) const primary = sisyphus.fallbackChain[0] expect(primary.providers).toEqual(["anthropic", "github-copilot", "opencode"]) expect(primary.model).toBe("claude-opus-4-6") expect(primary.variant).toBe("max") const last = sisyphus.fallbackChain[4] expect(last.providers[0]).toBe("opencode") expect(last.model).toBe("big-pickle") }) test("librarian has valid fallbackChain with glm-5 as primary", () => { // given - librarian agent requirement const librarian = AGENT_MODEL_REQUIREMENTS["librarian"] // when - accessing librarian requirement // then - fallbackChain exists with glm-5 as first entry expect(librarian).toBeDefined() expect(librarian.fallbackChain).toBeArray() expect(librarian.fallbackChain.length).toBeGreaterThan(0) const primary = librarian.fallbackChain[0] expect(primary.providers[0]).toBe("zai-coding-plan") expect(primary.model).toBe("glm-5") }) test("explore has valid fallbackChain with grok-code-fast-1 as primary", () => { // given - explore agent requirement const explore = AGENT_MODEL_REQUIREMENTS["explore"] // when - accessing explore requirement // then - fallbackChain exists with grok-code-fast-1 as first entry, claude-haiku-4-5 as second expect(explore).toBeDefined() expect(explore.fallbackChain).toBeArray() expect(explore.fallbackChain).toHaveLength(3) const primary = explore.fallbackChain[0] expect(primary.providers).toContain("github-copilot") expect(primary.model).toBe("grok-code-fast-1") const secondary = explore.fallbackChain[1] expect(secondary.providers).toContain("anthropic") expect(secondary.providers).toContain("opencode") expect(secondary.model).toBe("claude-haiku-4-5") const tertiary = explore.fallbackChain[2] expect(tertiary.providers).toContain("opencode") expect(tertiary.model).toBe("gpt-5-nano") }) test("multimodal-looker has valid fallbackChain with gemini-3-flash as primary", () => { // given - multimodal-looker agent requirement const multimodalLooker = AGENT_MODEL_REQUIREMENTS["multimodal-looker"] // when - accessing multimodal-looker requirement // then - fallbackChain exists with gemini-3-flash as first entry expect(multimodalLooker).toBeDefined() expect(multimodalLooker.fallbackChain).toBeArray() expect(multimodalLooker.fallbackChain.length).toBeGreaterThan(0) const primary = multimodalLooker.fallbackChain[0] expect(primary.providers[0]).toBe("google") expect(primary.model).toBe("gemini-3-flash") }) test("prometheus has claude-opus-4-6 as primary", () => { // #given - prometheus agent requirement const prometheus = AGENT_MODEL_REQUIREMENTS["prometheus"] // #when - accessing Prometheus requirement // #then - claude-opus-4-6 is first expect(prometheus).toBeDefined() expect(prometheus.fallbackChain).toBeArray() expect(prometheus.fallbackChain.length).toBeGreaterThan(1) const primary = prometheus.fallbackChain[0] expect(primary.model).toBe("claude-opus-4-6") expect(primary.providers).toEqual(["anthropic", "github-copilot", "opencode"]) expect(primary.variant).toBe("max") }) test("metis has claude-opus-4-6 as primary", () => { // #given - metis agent requirement const metis = AGENT_MODEL_REQUIREMENTS["metis"] // #when - accessing Metis requirement // #then - claude-opus-4-6 is first expect(metis).toBeDefined() expect(metis.fallbackChain).toBeArray() expect(metis.fallbackChain.length).toBeGreaterThan(1) const primary = metis.fallbackChain[0] expect(primary.model).toBe("claude-opus-4-6") expect(primary.providers).toEqual(["anthropic", "github-copilot", "opencode"]) expect(primary.variant).toBe("max") }) test("momus has valid fallbackChain with gpt-5.2 as primary", () => { // given - momus agent requirement const momus = AGENT_MODEL_REQUIREMENTS["momus"] // when - accessing Momus requirement // then - fallbackChain exists with gpt-5.2 as first entry, variant medium expect(momus).toBeDefined() expect(momus.fallbackChain).toBeArray() expect(momus.fallbackChain.length).toBeGreaterThan(0) const primary = momus.fallbackChain[0] expect(primary.model).toBe("gpt-5.2") expect(primary.variant).toBe("medium") expect(primary.providers[0]).toBe("openai") }) test("atlas has valid fallbackChain with k2p5 as primary (kimi-for-coding prioritized)", () => { // given - atlas agent requirement const atlas = AGENT_MODEL_REQUIREMENTS["atlas"] // when - accessing Atlas requirement // then - fallbackChain exists with k2p5 as first entry (kimi-for-coding prioritized) expect(atlas).toBeDefined() expect(atlas.fallbackChain).toBeArray() expect(atlas.fallbackChain.length).toBeGreaterThan(0) const primary = atlas.fallbackChain[0] expect(primary.model).toBe("k2p5") expect(primary.providers[0]).toBe("kimi-for-coding") }) test("hephaestus requires openai/github-copilot/opencode provider", () => { // #given - hephaestus agent requirement const hephaestus = AGENT_MODEL_REQUIREMENTS["hephaestus"] // #when - accessing hephaestus requirement // #then - requiresProvider is set to openai, github-copilot, opencode (not requiresModel) expect(hephaestus).toBeDefined() expect(hephaestus.requiresProvider).toEqual(["openai", "github-copilot", "opencode"]) expect(hephaestus.requiresModel).toBeUndefined() }) test("all 10 builtin agents have valid fallbackChain arrays", () => { // #given - list of 10 agent names const expectedAgents = [ "sisyphus", "hephaestus", "oracle", "librarian", "explore", "multimodal-looker", "prometheus", "metis", "momus", "atlas", ] // when - checking AGENT_MODEL_REQUIREMENTS const definedAgents = Object.keys(AGENT_MODEL_REQUIREMENTS) // #then - all agents present with valid fallbackChain expect(definedAgents).toHaveLength(10) for (const agent of expectedAgents) { const requirement = AGENT_MODEL_REQUIREMENTS[agent] expect(requirement).toBeDefined() expect(requirement.fallbackChain).toBeArray() expect(requirement.fallbackChain.length).toBeGreaterThan(0) for (const entry of requirement.fallbackChain) { expect(entry.providers).toBeArray() expect(entry.providers.length).toBeGreaterThan(0) expect(typeof entry.model).toBe("string") expect(entry.model.length).toBeGreaterThan(0) } } }) }) describe("CATEGORY_MODEL_REQUIREMENTS", () => { test("ultrabrain has valid fallbackChain with gpt-5.3-codex as primary", () => { // given - ultrabrain category requirement const ultrabrain = CATEGORY_MODEL_REQUIREMENTS["ultrabrain"] // when - accessing ultrabrain requirement // then - fallbackChain exists with gpt-5.3-codex as first entry expect(ultrabrain).toBeDefined() expect(ultrabrain.fallbackChain).toBeArray() expect(ultrabrain.fallbackChain.length).toBeGreaterThan(0) const primary = ultrabrain.fallbackChain[0] expect(primary.variant).toBe("xhigh") expect(primary.model).toBe("gpt-5.3-codex") expect(primary.providers[0]).toBe("openai") }) test("deep has valid fallbackChain with gpt-5.3-codex as primary", () => { // given - deep category requirement const deep = CATEGORY_MODEL_REQUIREMENTS["deep"] // when - accessing deep requirement // then - fallbackChain exists with gpt-5.3-codex as first entry, medium variant expect(deep).toBeDefined() expect(deep.fallbackChain).toBeArray() expect(deep.fallbackChain.length).toBeGreaterThan(0) const primary = deep.fallbackChain[0] expect(primary.variant).toBe("medium") expect(primary.model).toBe("gpt-5.3-codex") expect(primary.providers[0]).toBe("openai") }) test("visual-engineering has valid fallbackChain with gemini-3-pro high as primary", () => { // given - visual-engineering category requirement const visualEngineering = CATEGORY_MODEL_REQUIREMENTS["visual-engineering"] // when - accessing visual-engineering requirement // then - fallbackChain: gemini-3-pro(high) → glm-5 → opus-4-6(max) → k2p5 expect(visualEngineering).toBeDefined() expect(visualEngineering.fallbackChain).toBeArray() expect(visualEngineering.fallbackChain).toHaveLength(4) const primary = visualEngineering.fallbackChain[0] expect(primary.providers[0]).toBe("google") expect(primary.model).toBe("gemini-3-pro") expect(primary.variant).toBe("high") const second = visualEngineering.fallbackChain[1] expect(second.providers[0]).toBe("zai-coding-plan") expect(second.model).toBe("glm-5") const third = visualEngineering.fallbackChain[2] expect(third.model).toBe("claude-opus-4-6") expect(third.variant).toBe("max") const fourth = visualEngineering.fallbackChain[3] expect(fourth.providers[0]).toBe("kimi-for-coding") expect(fourth.model).toBe("k2p5") }) test("quick has valid fallbackChain with claude-haiku-4-5 as primary", () => { // given - quick category requirement const quick = CATEGORY_MODEL_REQUIREMENTS["quick"] // when - accessing quick requirement // then - fallbackChain exists with claude-haiku-4-5 as first entry expect(quick).toBeDefined() expect(quick.fallbackChain).toBeArray() expect(quick.fallbackChain.length).toBeGreaterThan(0) const primary = quick.fallbackChain[0] expect(primary.model).toBe("claude-haiku-4-5") expect(primary.providers[0]).toBe("anthropic") }) test("unspecified-low has valid fallbackChain with claude-sonnet-4-6 as primary", () => { // given - unspecified-low category requirement const unspecifiedLow = CATEGORY_MODEL_REQUIREMENTS["unspecified-low"] // when - accessing unspecified-low requirement // then - fallbackChain exists with claude-sonnet-4-6 as first entry expect(unspecifiedLow).toBeDefined() expect(unspecifiedLow.fallbackChain).toBeArray() expect(unspecifiedLow.fallbackChain.length).toBeGreaterThan(0) const primary = unspecifiedLow.fallbackChain[0] expect(primary.model).toBe("claude-sonnet-4-6") expect(primary.providers[0]).toBe("anthropic") }) test("unspecified-high has claude-opus-4-6 as primary", () => { // #given - unspecified-high category requirement const unspecifiedHigh = CATEGORY_MODEL_REQUIREMENTS["unspecified-high"] // #when - accessing unspecified-high requirement // #then - claude-opus-4-6 is first expect(unspecifiedHigh).toBeDefined() expect(unspecifiedHigh.fallbackChain).toBeArray() expect(unspecifiedHigh.fallbackChain.length).toBeGreaterThan(1) const primary = unspecifiedHigh.fallbackChain[0] expect(primary.model).toBe("claude-opus-4-6") expect(primary.variant).toBe("max") expect(primary.providers).toEqual(["anthropic", "github-copilot", "opencode"]) }) test("artistry has valid fallbackChain with gemini-3-pro as primary", () => { // given - artistry category requirement const artistry = CATEGORY_MODEL_REQUIREMENTS["artistry"] // when - accessing artistry requirement // then - fallbackChain exists with gemini-3-pro as first entry expect(artistry).toBeDefined() expect(artistry.fallbackChain).toBeArray() expect(artistry.fallbackChain.length).toBeGreaterThan(0) const primary = artistry.fallbackChain[0] expect(primary.model).toBe("gemini-3-pro") expect(primary.variant).toBe("high") expect(primary.providers[0]).toBe("google") }) test("writing has valid fallbackChain with k2p5 as primary (kimi-for-coding)", () => { // given - writing category requirement const writing = CATEGORY_MODEL_REQUIREMENTS["writing"] // when - accessing writing requirement // then - fallbackChain: k2p5 → gemini-3-flash → claude-sonnet-4-6 expect(writing).toBeDefined() expect(writing.fallbackChain).toBeArray() expect(writing.fallbackChain).toHaveLength(3) const primary = writing.fallbackChain[0] expect(primary.model).toBe("k2p5") expect(primary.providers[0]).toBe("kimi-for-coding") const second = writing.fallbackChain[1] expect(second.model).toBe("gemini-3-flash") expect(second.providers[0]).toBe("google") }) test("all 8 categories have valid fallbackChain arrays", () => { // given - list of 8 category names const expectedCategories = [ "visual-engineering", "ultrabrain", "deep", "artistry", "quick", "unspecified-low", "unspecified-high", "writing", ] // when - checking CATEGORY_MODEL_REQUIREMENTS const definedCategories = Object.keys(CATEGORY_MODEL_REQUIREMENTS) // then - all categories present with valid fallbackChain expect(definedCategories).toHaveLength(8) for (const category of expectedCategories) { const requirement = CATEGORY_MODEL_REQUIREMENTS[category] expect(requirement).toBeDefined() expect(requirement.fallbackChain).toBeArray() expect(requirement.fallbackChain.length).toBeGreaterThan(0) for (const entry of requirement.fallbackChain) { expect(entry.providers).toBeArray() expect(entry.providers.length).toBeGreaterThan(0) expect(typeof entry.model).toBe("string") expect(entry.model.length).toBeGreaterThan(0) } } }) }) describe("FallbackEntry type", () => { test("FallbackEntry structure is correct", () => { // given - a valid FallbackEntry object const entry: FallbackEntry = { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-6", variant: "high", } // when - accessing properties // then - all properties are accessible expect(entry.providers).toEqual(["anthropic", "github-copilot", "opencode"]) expect(entry.model).toBe("claude-opus-4-6") expect(entry.variant).toBe("high") }) test("FallbackEntry variant is optional", () => { // given - a FallbackEntry without variant const entry: FallbackEntry = { providers: ["opencode", "anthropic"], model: "big-pickle", } // when - accessing variant // then - variant is undefined expect(entry.variant).toBeUndefined() }) }) describe("ModelRequirement type", () => { test("ModelRequirement structure with fallbackChain is correct", () => { // given - a valid ModelRequirement object const requirement: ModelRequirement = { fallbackChain: [ { providers: ["anthropic", "github-copilot"], model: "claude-opus-4-6", variant: "max" }, { providers: ["openai", "github-copilot"], model: "gpt-5.2", variant: "high" }, ], } // when - accessing properties // then - fallbackChain is accessible with correct structure expect(requirement.fallbackChain).toBeArray() expect(requirement.fallbackChain).toHaveLength(2) expect(requirement.fallbackChain[0].model).toBe("claude-opus-4-6") expect(requirement.fallbackChain[1].model).toBe("gpt-5.2") }) test("ModelRequirement variant is optional", () => { // given - a ModelRequirement without top-level variant const requirement: ModelRequirement = { fallbackChain: [{ providers: ["opencode"], model: "big-pickle" }], } // when - accessing variant // then - variant is undefined expect(requirement.variant).toBeUndefined() }) test("no model in fallbackChain has provider prefix", () => { // given - all agent and category requirements const allRequirements = [ ...Object.values(AGENT_MODEL_REQUIREMENTS), ...Object.values(CATEGORY_MODEL_REQUIREMENTS), ] // when - checking each model in fallbackChain // then - none contain "/" (provider prefix) for (const req of allRequirements) { for (const entry of req.fallbackChain) { expect(entry.model).not.toContain("/") } } }) test("all fallbackChain entries have non-empty providers array", () => { // given - all agent and category requirements const allRequirements = [ ...Object.values(AGENT_MODEL_REQUIREMENTS), ...Object.values(CATEGORY_MODEL_REQUIREMENTS), ] // when - checking each entry in fallbackChain // then - all have non-empty providers array for (const req of allRequirements) { for (const entry of req.fallbackChain) { expect(entry.providers).toBeArray() expect(entry.providers.length).toBeGreaterThan(0) } } }) }) describe("requiresModel field in categories", () => { test("deep category has requiresModel set to gpt-5.3-codex", () => { // given const deep = CATEGORY_MODEL_REQUIREMENTS["deep"] // when / #then expect(deep.requiresModel).toBe("gpt-5.3-codex") }) test("artistry category has requiresModel set to gemini-3-pro", () => { // given const artistry = CATEGORY_MODEL_REQUIREMENTS["artistry"] // when / #then expect(artistry.requiresModel).toBe("gemini-3-pro") }) })