diff --git a/src/agents/types.test.ts b/src/agents/types.test.ts index ad39fb538..dd6b1fe54 100644 --- a/src/agents/types.test.ts +++ b/src/agents/types.test.ts @@ -47,8 +47,8 @@ describe("isGptModel", () => { }); test("gemini models are not gpt", () => { - expect(isGptModel("google/gemini-3-pro")).toBe(false); - expect(isGptModel("litellm/gemini-3-pro")).toBe(false); + expect(isGptModel("google/gemini-3.1-pro")).toBe(false); + expect(isGptModel("litellm/gemini-3.1-pro")).toBe(false); }); test("opencode provider is not gpt", () => { @@ -58,29 +58,29 @@ describe("isGptModel", () => { describe("isGeminiModel", () => { test("#given google provider models #then returns true", () => { - expect(isGeminiModel("google/gemini-3-pro")).toBe(true); + expect(isGeminiModel("google/gemini-3.1-pro")).toBe(true); expect(isGeminiModel("google/gemini-3-flash")).toBe(true); expect(isGeminiModel("google/gemini-2.5-pro")).toBe(true); }); test("#given google-vertex provider models #then returns true", () => { - expect(isGeminiModel("google-vertex/gemini-3-pro")).toBe(true); + expect(isGeminiModel("google-vertex/gemini-3.1-pro")).toBe(true); expect(isGeminiModel("google-vertex/gemini-3-flash")).toBe(true); }); test("#given github copilot gemini models #then returns true", () => { - expect(isGeminiModel("github-copilot/gemini-3-pro")).toBe(true); + expect(isGeminiModel("github-copilot/gemini-3.1-pro")).toBe(true); expect(isGeminiModel("github-copilot/gemini-3-flash")).toBe(true); }); test("#given litellm proxied gemini models #then returns true", () => { - expect(isGeminiModel("litellm/gemini-3-pro")).toBe(true); + expect(isGeminiModel("litellm/gemini-3.1-pro")).toBe(true); expect(isGeminiModel("litellm/gemini-3-flash")).toBe(true); expect(isGeminiModel("litellm/gemini-2.5-pro")).toBe(true); }); test("#given other proxied gemini models #then returns true", () => { - expect(isGeminiModel("custom-provider/gemini-3-pro")).toBe(true); + expect(isGeminiModel("custom-provider/gemini-3.1-pro")).toBe(true); expect(isGeminiModel("ollama/gemini-3-flash")).toBe(true); }); diff --git a/src/agents/utils.test.ts b/src/agents/utils.test.ts index fc15d9d48..129329afa 100644 --- a/src/agents/utils.test.ts +++ b/src/agents/utils.test.ts @@ -988,7 +988,7 @@ describe("buildAgent with category and skills", () => { const agent = buildAgent(source["test-agent"], TEST_MODEL) // #then - category's built-in model is applied - expect(agent.model).toBe("google/gemini-3-pro") + expect(agent.model).toBe("google/gemini-3.1-pro") }) test("agent with category and existing model keeps existing model", () => { diff --git a/src/cli/__snapshots__/model-fallback.test.ts.snap b/src/cli/__snapshots__/model-fallback.test.ts.snap index df91e07b8..a8c3e9112 100644 --- a/src/cli/__snapshots__/model-fallback.test.ts.snap +++ b/src/cli/__snapshots__/model-fallback.test.ts.snap @@ -325,7 +325,7 @@ exports[`generateModelConfig single native provider uses Gemini models when only "$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-opencode/master/assets/oh-my-opencode.schema.json", "agents": { "atlas": { - "model": "google/gemini-3-pro-preview", + "model": "google/gemini-3.1-pro-preview", }, "explore": { "model": "opencode/gpt-5-nano", @@ -334,34 +334,34 @@ exports[`generateModelConfig single native provider uses Gemini models when only "model": "opencode/glm-4.7-free", }, "metis": { - "model": "google/gemini-3-pro-preview", + "model": "google/gemini-3.1-pro-preview", "variant": "high", }, "momus": { - "model": "google/gemini-3-pro-preview", + "model": "google/gemini-3.1-pro-preview", "variant": "high", }, "multimodal-looker": { "model": "google/gemini-3-flash-preview", }, "oracle": { - "model": "google/gemini-3-pro-preview", + "model": "google/gemini-3.1-pro-preview", "variant": "high", }, "prometheus": { - "model": "google/gemini-3-pro-preview", + "model": "google/gemini-3.1-pro-preview", }, }, "categories": { "artistry": { - "model": "google/gemini-3-pro-preview", + "model": "google/gemini-3.1-pro-preview", "variant": "high", }, "quick": { "model": "google/gemini-3-flash-preview", }, "ultrabrain": { - "model": "google/gemini-3-pro-preview", + "model": "google/gemini-3.1-pro-preview", "variant": "high", }, "unspecified-high": { @@ -371,7 +371,7 @@ exports[`generateModelConfig single native provider uses Gemini models when only "model": "google/gemini-3-flash-preview", }, "visual-engineering": { - "model": "google/gemini-3-pro-preview", + "model": "google/gemini-3.1-pro-preview", "variant": "high", }, "writing": { @@ -386,7 +386,7 @@ exports[`generateModelConfig single native provider uses Gemini models with isMa "$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-opencode/master/assets/oh-my-opencode.schema.json", "agents": { "atlas": { - "model": "google/gemini-3-pro-preview", + "model": "google/gemini-3.1-pro-preview", }, "explore": { "model": "opencode/gpt-5-nano", @@ -395,44 +395,44 @@ exports[`generateModelConfig single native provider uses Gemini models with isMa "model": "opencode/glm-4.7-free", }, "metis": { - "model": "google/gemini-3-pro-preview", + "model": "google/gemini-3.1-pro-preview", "variant": "high", }, "momus": { - "model": "google/gemini-3-pro-preview", + "model": "google/gemini-3.1-pro-preview", "variant": "high", }, "multimodal-looker": { "model": "google/gemini-3-flash-preview", }, "oracle": { - "model": "google/gemini-3-pro-preview", + "model": "google/gemini-3.1-pro-preview", "variant": "high", }, "prometheus": { - "model": "google/gemini-3-pro-preview", + "model": "google/gemini-3.1-pro-preview", }, }, "categories": { "artistry": { - "model": "google/gemini-3-pro-preview", + "model": "google/gemini-3.1-pro-preview", "variant": "high", }, "quick": { "model": "google/gemini-3-flash-preview", }, "ultrabrain": { - "model": "google/gemini-3-pro-preview", + "model": "google/gemini-3.1-pro-preview", "variant": "high", }, "unspecified-high": { - "model": "google/gemini-3-pro-preview", + "model": "google/gemini-3.1-pro-preview", }, "unspecified-low": { "model": "google/gemini-3-flash-preview", }, "visual-engineering": { - "model": "google/gemini-3-pro-preview", + "model": "google/gemini-3.1-pro-preview", "variant": "high", }, "writing": { @@ -485,7 +485,7 @@ exports[`generateModelConfig all native providers uses preferred models from fal }, "categories": { "artistry": { - "model": "google/gemini-3-pro-preview", + "model": "google/gemini-3.1-pro-preview", "variant": "high", }, "deep": { @@ -506,7 +506,7 @@ exports[`generateModelConfig all native providers uses preferred models from fal "model": "anthropic/claude-sonnet-4-5", }, "visual-engineering": { - "model": "google/gemini-3-pro-preview", + "model": "google/gemini-3.1-pro-preview", "variant": "high", }, "writing": { @@ -559,7 +559,7 @@ exports[`generateModelConfig all native providers uses preferred models with isM }, "categories": { "artistry": { - "model": "google/gemini-3-pro-preview", + "model": "google/gemini-3.1-pro-preview", "variant": "high", }, "deep": { @@ -581,7 +581,7 @@ exports[`generateModelConfig all native providers uses preferred models with isM "model": "anthropic/claude-sonnet-4-5", }, "visual-engineering": { - "model": "google/gemini-3-pro-preview", + "model": "google/gemini-3.1-pro-preview", "variant": "high", }, "writing": { @@ -634,7 +634,7 @@ exports[`generateModelConfig fallback providers uses OpenCode Zen models when on }, "categories": { "artistry": { - "model": "opencode/gemini-3-pro", + "model": "opencode/gemini-3.1-pro", "variant": "high", }, "deep": { @@ -655,7 +655,7 @@ exports[`generateModelConfig fallback providers uses OpenCode Zen models when on "model": "opencode/claude-sonnet-4-5", }, "visual-engineering": { - "model": "opencode/gemini-3-pro", + "model": "opencode/gemini-3.1-pro", "variant": "high", }, "writing": { @@ -708,7 +708,7 @@ exports[`generateModelConfig fallback providers uses OpenCode Zen models with is }, "categories": { "artistry": { - "model": "opencode/gemini-3-pro", + "model": "opencode/gemini-3.1-pro", "variant": "high", }, "deep": { @@ -730,7 +730,7 @@ exports[`generateModelConfig fallback providers uses OpenCode Zen models with is "model": "opencode/claude-sonnet-4-5", }, "visual-engineering": { - "model": "opencode/gemini-3-pro", + "model": "opencode/gemini-3.1-pro", "variant": "high", }, "writing": { @@ -779,14 +779,14 @@ exports[`generateModelConfig fallback providers uses GitHub Copilot models when }, "categories": { "artistry": { - "model": "github-copilot/gemini-3-pro-preview", + "model": "github-copilot/gemini-3.1-pro-preview", "variant": "high", }, "quick": { "model": "github-copilot/claude-haiku-4.5", }, "ultrabrain": { - "model": "github-copilot/gemini-3-pro-preview", + "model": "github-copilot/gemini-3.1-pro-preview", "variant": "high", }, "unspecified-high": { @@ -796,7 +796,7 @@ exports[`generateModelConfig fallback providers uses GitHub Copilot models when "model": "github-copilot/claude-sonnet-4.5", }, "visual-engineering": { - "model": "github-copilot/gemini-3-pro-preview", + "model": "github-copilot/gemini-3.1-pro-preview", "variant": "high", }, "writing": { @@ -845,14 +845,14 @@ exports[`generateModelConfig fallback providers uses GitHub Copilot models with }, "categories": { "artistry": { - "model": "github-copilot/gemini-3-pro-preview", + "model": "github-copilot/gemini-3.1-pro-preview", "variant": "high", }, "quick": { "model": "github-copilot/claude-haiku-4.5", }, "ultrabrain": { - "model": "github-copilot/gemini-3-pro-preview", + "model": "github-copilot/gemini-3.1-pro-preview", "variant": "high", }, "unspecified-high": { @@ -863,7 +863,7 @@ exports[`generateModelConfig fallback providers uses GitHub Copilot models with "model": "github-copilot/claude-sonnet-4.5", }, "visual-engineering": { - "model": "github-copilot/gemini-3-pro-preview", + "model": "github-copilot/gemini-3.1-pro-preview", "variant": "high", }, "writing": { @@ -1026,7 +1026,7 @@ exports[`generateModelConfig mixed provider scenarios uses Claude + OpenCode Zen }, "categories": { "artistry": { - "model": "opencode/gemini-3-pro", + "model": "opencode/gemini-3.1-pro", "variant": "high", }, "deep": { @@ -1047,7 +1047,7 @@ exports[`generateModelConfig mixed provider scenarios uses Claude + OpenCode Zen "model": "anthropic/claude-sonnet-4-5", }, "visual-engineering": { - "model": "opencode/gemini-3-pro", + "model": "opencode/gemini-3.1-pro", "variant": "high", }, "writing": { @@ -1100,7 +1100,7 @@ exports[`generateModelConfig mixed provider scenarios uses OpenAI + Copilot comb }, "categories": { "artistry": { - "model": "github-copilot/gemini-3-pro-preview", + "model": "github-copilot/gemini-3.1-pro-preview", "variant": "high", }, "deep": { @@ -1121,7 +1121,7 @@ exports[`generateModelConfig mixed provider scenarios uses OpenAI + Copilot comb "model": "github-copilot/claude-sonnet-4.5", }, "visual-engineering": { - "model": "github-copilot/gemini-3-pro-preview", + "model": "github-copilot/gemini-3.1-pro-preview", "variant": "high", }, "writing": { @@ -1217,7 +1217,7 @@ exports[`generateModelConfig mixed provider scenarios uses Gemini + Claude combi "model": "google/gemini-3-flash-preview", }, "oracle": { - "model": "google/gemini-3-pro-preview", + "model": "google/gemini-3.1-pro-preview", "variant": "high", }, "prometheus": { @@ -1231,14 +1231,14 @@ exports[`generateModelConfig mixed provider scenarios uses Gemini + Claude combi }, "categories": { "artistry": { - "model": "google/gemini-3-pro-preview", + "model": "google/gemini-3.1-pro-preview", "variant": "high", }, "quick": { "model": "anthropic/claude-haiku-4-5", }, "ultrabrain": { - "model": "google/gemini-3-pro-preview", + "model": "google/gemini-3.1-pro-preview", "variant": "high", }, "unspecified-high": { @@ -1248,7 +1248,7 @@ exports[`generateModelConfig mixed provider scenarios uses Gemini + Claude combi "model": "anthropic/claude-sonnet-4-5", }, "visual-engineering": { - "model": "google/gemini-3-pro-preview", + "model": "google/gemini-3.1-pro-preview", "variant": "high", }, "writing": { @@ -1301,7 +1301,7 @@ exports[`generateModelConfig mixed provider scenarios uses all fallback provider }, "categories": { "artistry": { - "model": "github-copilot/gemini-3-pro-preview", + "model": "github-copilot/gemini-3.1-pro-preview", "variant": "high", }, "deep": { @@ -1322,7 +1322,7 @@ exports[`generateModelConfig mixed provider scenarios uses all fallback provider "model": "github-copilot/claude-sonnet-4.5", }, "visual-engineering": { - "model": "github-copilot/gemini-3-pro-preview", + "model": "github-copilot/gemini-3.1-pro-preview", "variant": "high", }, "writing": { @@ -1375,7 +1375,7 @@ exports[`generateModelConfig mixed provider scenarios uses all providers togethe }, "categories": { "artistry": { - "model": "google/gemini-3-pro-preview", + "model": "google/gemini-3.1-pro-preview", "variant": "high", }, "deep": { @@ -1396,7 +1396,7 @@ exports[`generateModelConfig mixed provider scenarios uses all providers togethe "model": "anthropic/claude-sonnet-4-5", }, "visual-engineering": { - "model": "google/gemini-3-pro-preview", + "model": "google/gemini-3.1-pro-preview", "variant": "high", }, "writing": { @@ -1449,7 +1449,7 @@ exports[`generateModelConfig mixed provider scenarios uses all providers with is }, "categories": { "artistry": { - "model": "google/gemini-3-pro-preview", + "model": "google/gemini-3.1-pro-preview", "variant": "high", }, "deep": { @@ -1471,7 +1471,7 @@ exports[`generateModelConfig mixed provider scenarios uses all providers with is "model": "anthropic/claude-sonnet-4-5", }, "visual-engineering": { - "model": "google/gemini-3-pro-preview", + "model": "google/gemini-3.1-pro-preview", "variant": "high", }, "writing": { diff --git a/src/cli/config-manager.test.ts b/src/cli/config-manager.test.ts index ad73c3d44..67571185a 100644 --- a/src/cli/config-manager.test.ts +++ b/src/cli/config-manager.test.ts @@ -178,7 +178,7 @@ describe("config-manager ANTIGRAVITY_PROVIDER_CONFIG", () => { expect(models).toBeTruthy() const required = [ - "antigravity-gemini-3-pro", + "antigravity-gemini-3.1-pro", "antigravity-gemini-3-flash", "antigravity-claude-sonnet-4-6", "antigravity-claude-sonnet-4-6-thinking", @@ -206,7 +206,7 @@ describe("config-manager ANTIGRAVITY_PROVIDER_CONFIG", () => { const models = (ANTIGRAVITY_PROVIDER_CONFIG as any).google.models as Record // #when checking Gemini Pro variants - const pro = models["antigravity-gemini-3-pro"] + const pro = models["antigravity-gemini-3.1-pro"] // #then should have low and high variants expect(pro.variants).toBeTruthy() expect(pro.variants.low).toBeTruthy() diff --git a/src/cli/config-manager/antigravity-provider-configuration.ts b/src/cli/config-manager/antigravity-provider-configuration.ts index 5559d0919..6d847ac5d 100644 --- a/src/cli/config-manager/antigravity-provider-configuration.ts +++ b/src/cli/config-manager/antigravity-provider-configuration.ts @@ -4,10 +4,10 @@ * IMPORTANT: Model names MUST use `antigravity-` prefix for stability. * * Since opencode-antigravity-auth v1.3.0, models use a variant system: - * - `antigravity-gemini-3-pro` with variants: low, high + * - `antigravity-gemini-3.1-pro` with variants: low, high * - `antigravity-gemini-3-flash` with variants: minimal, low, medium, high * - * Legacy tier-suffixed names (e.g., `antigravity-gemini-3-pro-high`) still work + * Legacy tier-suffixed names (e.g., `antigravity-gemini-3.1-pro-high`) still work * but variants are the recommended approach. * * @see https://github.com/NoeFabris/opencode-antigravity-auth#models @@ -16,7 +16,7 @@ export const ANTIGRAVITY_PROVIDER_CONFIG = { google: { name: "Google", models: { - "antigravity-gemini-3-pro": { + "antigravity-gemini-3.1-pro": { name: "Gemini 3 Pro (Antigravity)", limit: { context: 1048576, output: 65535 }, modalities: { input: ["text", "image", "pdf"], output: ["text"] }, diff --git a/src/cli/doctor/checks/model-resolution.test.ts b/src/cli/doctor/checks/model-resolution.test.ts index cca2f58b5..e311076a8 100644 --- a/src/cli/doctor/checks/model-resolution.test.ts +++ b/src/cli/doctor/checks/model-resolution.test.ts @@ -26,7 +26,7 @@ describe("model-resolution check", () => { // then: Should have category entries const visual = info.categories.find((c) => c.name === "visual-engineering") expect(visual).toBeDefined() - expect(visual!.requirement.fallbackChain[0]?.model).toBe("gemini-3-pro") + expect(visual!.requirement.fallbackChain[0]?.model).toBe("gemini-3.1-pro") expect(visual!.requirement.fallbackChain[0]?.providers).toContain("google") }) }) diff --git a/src/cli/model-fallback-requirements.ts b/src/cli/model-fallback-requirements.ts index f3f43e60b..0ff625005 100644 --- a/src/cli/model-fallback-requirements.ts +++ b/src/cli/model-fallback-requirements.ts @@ -24,7 +24,7 @@ export const CLI_AGENT_MODEL_REQUIREMENTS: Record = { oracle: { fallbackChain: [ { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" }, - { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "high" }, + { providers: ["google", "github-copilot", "opencode"], model: "gemini-3.1-pro", variant: "high" }, { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-6", variant: "max" }, ], }, @@ -59,7 +59,7 @@ export const CLI_AGENT_MODEL_REQUIREMENTS: Record = { { providers: ["kimi-for-coding"], model: "k2p5" }, { providers: ["opencode"], model: "kimi-k2.5-free" }, { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" }, - { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }, + { providers: ["google", "github-copilot", "opencode"], model: "gemini-3.1-pro" }, ], }, metis: { @@ -68,14 +68,14 @@ export const CLI_AGENT_MODEL_REQUIREMENTS: Record = { { providers: ["kimi-for-coding"], model: "k2p5" }, { providers: ["opencode"], model: "kimi-k2.5-free" }, { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" }, - { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "high" }, + { providers: ["google", "github-copilot", "opencode"], model: "gemini-3.1-pro", variant: "high" }, ], }, momus: { fallbackChain: [ { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "medium" }, { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-6", variant: "max" }, - { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "high" }, + { providers: ["google", "github-copilot", "opencode"], model: "gemini-3.1-pro", variant: "high" }, ], }, atlas: { @@ -84,7 +84,7 @@ export const CLI_AGENT_MODEL_REQUIREMENTS: Record = { { providers: ["opencode"], model: "kimi-k2.5-free" }, { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-5" }, { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2" }, - { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }, + { providers: ["google", "github-copilot", "opencode"], model: "gemini-3.1-pro" }, ], }, } @@ -92,7 +92,7 @@ export const CLI_AGENT_MODEL_REQUIREMENTS: Record = { export const CLI_CATEGORY_MODEL_REQUIREMENTS: Record = { "visual-engineering": { fallbackChain: [ - { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "high" }, + { providers: ["google", "github-copilot", "opencode"], model: "gemini-3.1-pro", variant: "high" }, { providers: ["zai-coding-plan"], model: "glm-5" }, { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-6", variant: "max" }, { providers: ["kimi-for-coding"], model: "k2p5" }, @@ -101,7 +101,7 @@ export const CLI_CATEGORY_MODEL_REQUIREMENTS: Record = ultrabrain: { fallbackChain: [ { providers: ["openai", "opencode"], model: "gpt-5.3-codex", variant: "xhigh" }, - { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "high" }, + { providers: ["google", "github-copilot", "opencode"], model: "gemini-3.1-pro", variant: "high" }, { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-6", variant: "max" }, ], }, @@ -109,17 +109,17 @@ export const CLI_CATEGORY_MODEL_REQUIREMENTS: Record = fallbackChain: [ { providers: ["openai", "opencode"], model: "gpt-5.3-codex", variant: "medium" }, { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-6", variant: "max" }, - { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "high" }, + { providers: ["google", "github-copilot", "opencode"], model: "gemini-3.1-pro", variant: "high" }, ], requiresModel: "gpt-5.3-codex", }, artistry: { fallbackChain: [ - { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "high" }, + { providers: ["google", "github-copilot", "opencode"], model: "gemini-3.1-pro", variant: "high" }, { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-6", variant: "max" }, { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2" }, ], - requiresModel: "gemini-3-pro", + requiresModel: "gemini-3.1-pro", }, quick: { fallbackChain: [ @@ -139,7 +139,7 @@ export const CLI_CATEGORY_MODEL_REQUIREMENTS: Record = fallbackChain: [ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-6", variant: "max" }, { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" }, - { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }, + { providers: ["google", "github-copilot", "opencode"], model: "gemini-3.1-pro" }, ], }, writing: { diff --git a/src/cli/provider-model-id-transform.test.ts b/src/cli/provider-model-id-transform.test.ts index e13c7846a..17cb9dfb1 100644 --- a/src/cli/provider-model-id-transform.test.ts +++ b/src/cli/provider-model-id-transform.test.ts @@ -40,16 +40,16 @@ describe("transformModelForProvider", () => { expect(result).toBe("claude-haiku-4.5") }) - test("transforms gemini-3-pro to gemini-3-pro-preview", () => { - // #given github-copilot provider and gemini-3-pro model + test("transforms gemini-3.1-pro to gemini-3.1-pro-preview", () => { + // #given github-copilot provider and gemini-3.1-pro model const provider = "github-copilot" - const model = "gemini-3-pro" + const model = "gemini-3.1-pro" // #when transformModelForProvider is called const result = transformModelForProvider(provider, model) - // #then should transform to gemini-3-pro-preview - expect(result).toBe("gemini-3-pro-preview") + // #then should transform to gemini-3.1-pro-preview + expect(result).toBe("gemini-3.1-pro-preview") }) test("transforms gemini-3-flash to gemini-3-flash-preview", () => { @@ -64,16 +64,16 @@ describe("transformModelForProvider", () => { expect(result).toBe("gemini-3-flash-preview") }) - test("prevents double transformation of gemini-3-pro-preview", () => { - // #given github-copilot provider and gemini-3-pro-preview model (already transformed) + test("prevents double transformation of gemini-3.1-pro-preview", () => { + // #given github-copilot provider and gemini-3.1-pro-preview model (already transformed) const provider = "github-copilot" - const model = "gemini-3-pro-preview" + const model = "gemini-3.1-pro-preview" // #when transformModelForProvider is called const result = transformModelForProvider(provider, model) - // #then should NOT become gemini-3-pro-preview-preview - expect(result).toBe("gemini-3-pro-preview") + // #then should NOT become gemini-3.1-pro-preview-preview + expect(result).toBe("gemini-3.1-pro-preview") }) test("prevents double transformation of gemini-3-flash-preview", () => { @@ -102,16 +102,16 @@ describe("transformModelForProvider", () => { expect(result).toBe("gemini-3-flash-preview") }) - test("transforms gemini-3-pro to gemini-3-pro-preview", () => { - // #given google provider and gemini-3-pro model + test("transforms gemini-3.1-pro to gemini-3.1-pro-preview", () => { + // #given google provider and gemini-3.1-pro model const provider = "google" - const model = "gemini-3-pro" + const model = "gemini-3.1-pro" // #when transformModelForProvider is called const result = transformModelForProvider(provider, model) - // #then should transform to gemini-3-pro-preview - expect(result).toBe("gemini-3-pro-preview") + // #then should transform to gemini-3.1-pro-preview + expect(result).toBe("gemini-3.1-pro-preview") }) test("passes through other gemini models unchanged", () => { @@ -138,16 +138,16 @@ describe("transformModelForProvider", () => { expect(result).toBe("gemini-3-flash-preview") }) - test("prevents double transformation of gemini-3-pro-preview", () => { - // #given google provider and gemini-3-pro-preview model (already transformed) + test("prevents double transformation of gemini-3.1-pro-preview", () => { + // #given google provider and gemini-3.1-pro-preview model (already transformed) const provider = "google" - const model = "gemini-3-pro-preview" + const model = "gemini-3.1-pro-preview" // #when transformModelForProvider is called const result = transformModelForProvider(provider, model) - // #then should NOT become gemini-3-pro-preview-preview - expect(result).toBe("gemini-3-pro-preview") + // #then should NOT become gemini-3.1-pro-preview-preview + expect(result).toBe("gemini-3.1-pro-preview") }) test("does not transform claude models for google provider", () => { diff --git a/src/features/background-agent/concurrency.test.ts b/src/features/background-agent/concurrency.test.ts index 102076eef..682d6029a 100644 --- a/src/features/background-agent/concurrency.test.ts +++ b/src/features/background-agent/concurrency.test.ts @@ -34,7 +34,7 @@ describe("ConcurrencyManager.getConcurrencyLimit", () => { test("should return provider limit even when modelConcurrency exists but doesn't match", () => { // given const config: BackgroundTaskConfig = { - modelConcurrency: { "google/gemini-3-pro": 5 }, + modelConcurrency: { "google/gemini-3.1-pro": 5 }, providerConcurrency: { anthropic: 3 } } const manager = new ConcurrencyManager(config) @@ -95,7 +95,7 @@ describe("ConcurrencyManager.getConcurrencyLimit", () => { // when const modelLimit = manager.getConcurrencyLimit("anthropic/claude-sonnet-4-6") const providerLimit = manager.getConcurrencyLimit("anthropic/claude-opus-4-6") - const defaultLimit = manager.getConcurrencyLimit("google/gemini-3-pro") + const defaultLimit = manager.getConcurrencyLimit("google/gemini-3.1-pro") // then expect(modelLimit).toBe(10) diff --git a/src/features/task-toast-manager/manager.test.ts b/src/features/task-toast-manager/manager.test.ts index 323792815..a490f894b 100644 --- a/src/features/task-toast-manager/manager.test.ts +++ b/src/features/task-toast-manager/manager.test.ts @@ -162,7 +162,7 @@ describe("TaskToastManager", () => { description: "Task with category default model", agent: "sisyphus-junior", isBackground: false, - modelInfo: { model: "google/gemini-3-pro", type: "category-default" as const }, + modelInfo: { model: "google/gemini-3.1-pro", type: "category-default" as const }, } // when - addTask is called diff --git a/src/hooks/runtime-fallback/index.test.ts b/src/hooks/runtime-fallback/index.test.ts index 7660f1954..d9c873f16 100644 --- a/src/hooks/runtime-fallback/index.test.ts +++ b/src/hooks/runtime-fallback/index.test.ts @@ -125,7 +125,7 @@ describe("runtime-fallback", () => { await hook.event({ event: { type: "session.created", - properties: { info: { id: sessionID, model: "google/gemini-3-pro" } }, + properties: { info: { id: sessionID, model: "google/gemini-3.1-pro" } }, }, }) @@ -1841,7 +1841,7 @@ describe("runtime-fallback", () => { test("should apply fallback model on next chat.message after error", async () => { const hook = createRuntimeFallbackHook(createMockPluginInput(), { config: createMockConfig({ notify_on_fallback: false }), - pluginConfig: createMockPluginConfigWithCategoryFallback(["openai/gpt-5.2", "google/gemini-3-pro"]), + pluginConfig: createMockPluginConfigWithCategoryFallback(["openai/gpt-5.2", "google/gemini-3.1-pro"]), }) const sessionID = "test-session-switch" SessionCategoryRegistry.register(sessionID, "test") @@ -1916,7 +1916,7 @@ describe("runtime-fallback", () => { const input = createMockPluginInput() const hook = createRuntimeFallbackHook(input, { config: createMockConfig({ notify_on_fallback: false }), - pluginConfig: createMockPluginConfigWithAgentFallback("oracle", ["openai/gpt-5.2", "google/gemini-3-pro"]), + pluginConfig: createMockPluginConfigWithAgentFallback("oracle", ["openai/gpt-5.2", "google/gemini-3.1-pro"]), }) const sessionID = "test-agent-fallback" diff --git a/src/hooks/think-mode/index.test.ts b/src/hooks/think-mode/index.test.ts index 480eaf30b..b0d744738 100644 --- a/src/hooks/think-mode/index.test.ts +++ b/src/hooks/think-mode/index.test.ts @@ -109,7 +109,7 @@ describe("createThinkModeHook", () => { const input = createHookInput({ sessionID, providerID: "google", - modelID: "gemini-3-pro", + modelID: "gemini-3.1-pro", }) const output = createHookOutput("Please solve this directly") diff --git a/src/hooks/think-mode/switcher.test.ts b/src/hooks/think-mode/switcher.test.ts index 65fa5cde3..bf20122fd 100644 --- a/src/hooks/think-mode/switcher.test.ts +++ b/src/hooks/think-mode/switcher.test.ts @@ -49,8 +49,8 @@ describe("think-mode switcher", () => { it("should handle Gemini preview variants", () => { // given Gemini preview model IDs - expect(getHighVariant("gemini-3-pro")).toBe( - "gemini-3-pro-high" + expect(getHighVariant("gemini-3.1-pro")).toBe( + "gemini-3-1-pro-high" ) expect(getHighVariant("gemini-3-flash")).toBe( "gemini-3-flash-high" @@ -61,7 +61,7 @@ describe("think-mode switcher", () => { // given model IDs that are already high variants expect(getHighVariant("claude-opus-4-6-high")).toBeNull() expect(getHighVariant("gpt-5-2-high")).toBeNull() - expect(getHighVariant("gemini-3-pro-high")).toBeNull() + expect(getHighVariant("gemini-3-1-pro-high")).toBeNull() }) it("should return null for unknown models", () => { @@ -77,7 +77,7 @@ describe("think-mode switcher", () => { // given model IDs with -high suffix expect(isAlreadyHighVariant("claude-opus-4-6-high")).toBe(true) expect(isAlreadyHighVariant("gpt-5-2-high")).toBe(true) - expect(isAlreadyHighVariant("gemini-3-pro-high")).toBe(true) + expect(isAlreadyHighVariant("gemini-3.1-pro-high")).toBe(true) }) it("should detect -high suffix after normalization", () => { @@ -90,7 +90,7 @@ describe("think-mode switcher", () => { expect(isAlreadyHighVariant("claude-opus-4-6")).toBe(false) expect(isAlreadyHighVariant("claude-opus-4.6")).toBe(false) expect(isAlreadyHighVariant("gpt-5.2")).toBe(false) - expect(isAlreadyHighVariant("gemini-3-pro")).toBe(false) + expect(isAlreadyHighVariant("gemini-3.1-pro")).toBe(false) }) it("should return false for models with 'high' in name but not suffix", () => { @@ -129,7 +129,7 @@ describe("think-mode switcher", () => { // given various custom prefixes expect(getHighVariant("azure/gpt-5")).toBe("azure/gpt-5-high") expect(getHighVariant("bedrock/claude-sonnet-4-6")).toBe("bedrock/claude-sonnet-4-6-high") - expect(getHighVariant("custom-llm/gemini-3-pro")).toBe("custom-llm/gemini-3-pro-high") + expect(getHighVariant("custom-llm/gemini-3.1-pro")).toBe("custom-llm/gemini-3-1-pro-high") }) it("should return null for prefixed models without high variant mapping", () => { @@ -150,7 +150,7 @@ describe("think-mode switcher", () => { // given prefixed model IDs with -high suffix expect(isAlreadyHighVariant("vertex_ai/claude-opus-4-6-high")).toBe(true) expect(isAlreadyHighVariant("openai/gpt-5-2-high")).toBe(true) - expect(isAlreadyHighVariant("custom/gemini-3-pro-high")).toBe(true) + expect(isAlreadyHighVariant("custom/gemini-3.1-pro-high")).toBe(true) }) it("should return false for prefixed base models", () => { @@ -167,4 +167,3 @@ describe("think-mode switcher", () => { }) }) }) - diff --git a/src/hooks/think-mode/switcher.ts b/src/hooks/think-mode/switcher.ts index 273019d93..0a1a1dd38 100644 --- a/src/hooks/think-mode/switcher.ts +++ b/src/hooks/think-mode/switcher.ts @@ -62,8 +62,8 @@ const HIGH_VARIANT_MAP: Record = { "claude-sonnet-4-6": "claude-sonnet-4-6-high", "claude-opus-4-6": "claude-opus-4-6-high", // Gemini - "gemini-3-pro": "gemini-3-pro-high", - "gemini-3-pro-low": "gemini-3-pro-high", + "gemini-3-1-pro": "gemini-3-1-pro-high", + "gemini-3-1-pro-low": "gemini-3-1-pro-high", "gemini-3-flash": "gemini-3-flash-high", // GPT-5 "gpt-5": "gpt-5-high", @@ -82,7 +82,7 @@ const HIGH_VARIANT_MAP: Record = { "gpt-5-2-chat-latest": "gpt-5-2-chat-latest-high", "gpt-5-2-pro": "gpt-5-2-pro-high", // Antigravity (Google) - "antigravity-gemini-3-pro": "antigravity-gemini-3-pro-high", + "antigravity-gemini-3-1-pro": "antigravity-gemini-3-1-pro-high", "antigravity-gemini-3-flash": "antigravity-gemini-3-flash-high", } @@ -114,4 +114,3 @@ export function isAlreadyHighVariant(modelID: string): boolean { return ALREADY_HIGH.has(base) || base.endsWith("-high") } - diff --git a/src/plugin-config.test.ts b/src/plugin-config.test.ts index 9404f7095..1802f00c8 100644 --- a/src/plugin-config.test.ts +++ b/src/plugin-config.test.ts @@ -27,7 +27,7 @@ describe("mergeConfigs", () => { temperature: 0.3, }, visual: { - model: "google/gemini-3-pro", + model: "google/gemini-3.1-pro", }, }, } as unknown as OhMyOpenCodeConfig; @@ -41,7 +41,7 @@ describe("mergeConfigs", () => { // then quick should be preserved from base expect(result.categories?.quick?.model).toBe("anthropic/claude-haiku-4-5"); // then visual should be added from override - expect(result.categories?.visual?.model).toBe("google/gemini-3-pro"); + expect(result.categories?.visual?.model).toBe("google/gemini-3.1-pro"); }); it("should preserve base categories when override has no categories", () => { diff --git a/src/plugin-handlers/config-handler.test.ts b/src/plugin-handlers/config-handler.test.ts index 875a8cee2..7b735afe4 100644 --- a/src/plugin-handlers/config-handler.test.ts +++ b/src/plugin-handlers/config-handler.test.ts @@ -570,7 +570,7 @@ describe("Prometheus category config resolution", () => { // then expect(config).toBeDefined() - expect(config?.model).toBe("google/gemini-3-pro") + expect(config?.model).toBe("google/gemini-3.1-pro") }) test("user categories override default categories", () => { diff --git a/src/shared/migration.test.ts b/src/shared/migration.test.ts index 7846cc725..eb3d1d101 100644 --- a/src/shared/migration.test.ts +++ b/src/shared/migration.test.ts @@ -774,7 +774,7 @@ describe("migrateAgentConfigToCategory", () => { test("migrates model to category when mapping exists", () => { // given: Config with a model that has a category mapping const config = { - model: "google/gemini-3-pro", + model: "google/gemini-3.1-pro", temperature: 0.5, top_p: 0.9, } @@ -823,7 +823,7 @@ describe("migrateAgentConfigToCategory", () => { test("handles all mapped models correctly", () => { // given: Configs for each mapped model const configs = [ - { model: "google/gemini-3-pro" }, + { model: "google/gemini-3.1-pro" }, { model: "google/gemini-3-flash" }, { model: "openai/gpt-5.2" }, { model: "anthropic/claude-haiku-4-5" }, @@ -893,7 +893,7 @@ describe("shouldDeleteAgentConfig", () => { // given: Config with fields matching category defaults const config = { category: "visual-engineering", - model: "google/gemini-3-pro", + model: "google/gemini-3.1-pro", } // when: Check if config should be deleted @@ -1021,7 +1021,7 @@ describe("migrateConfigFile with backup", () => { agents: { "multimodal-looker": { model: "anthropic/claude-haiku-4-5" }, oracle: { model: "openai/gpt-5.2" }, - "my-custom-agent": { model: "google/gemini-3-pro" }, + "my-custom-agent": { model: "google/gemini-3.1-pro" }, }, } @@ -1037,7 +1037,7 @@ describe("migrateConfigFile with backup", () => { const agents = rawConfig.agents as Record> expect(agents["multimodal-looker"].model).toBe("anthropic/claude-haiku-4-5") expect(agents.oracle.model).toBe("openai/gpt-5.2") - expect(agents["my-custom-agent"].model).toBe("google/gemini-3-pro") + expect(agents["my-custom-agent"].model).toBe("google/gemini-3.1-pro") }) test("preserves category setting when explicitly set", () => { diff --git a/src/shared/migration/agent-category.ts b/src/shared/migration/agent-category.ts index 51aac23d7..8b7df75a4 100644 --- a/src/shared/migration/agent-category.ts +++ b/src/shared/migration/agent-category.ts @@ -12,7 +12,7 @@ * This map will be removed in a future major version once migration period ends. */ export const MODEL_TO_CATEGORY_MAP: Record = { - "google/gemini-3-pro": "visual-engineering", + "google/gemini-3.1-pro": "visual-engineering", "google/gemini-3-flash": "writing", "openai/gpt-5.2": "ultrabrain", "anthropic/claude-haiku-4-5": "quick", diff --git a/src/shared/model-availability.test.ts b/src/shared/model-availability.test.ts index 23a3f00f6..cb469b960 100644 --- a/src/shared/model-availability.test.ts +++ b/src/shared/model-availability.test.ts @@ -63,7 +63,7 @@ describe("fetchAvailableModels", () => { writeModelsCache({ openai: { id: "openai", models: { "gpt-5.2": { id: "gpt-5.2" } } }, anthropic: { id: "anthropic", models: { "claude-opus-4-6": { id: "claude-opus-4-6" } } }, - google: { id: "google", models: { "gemini-3-pro": { id: "gemini-3-pro" } } }, + google: { id: "google", models: { "gemini-3.1-pro": { id: "gemini-3.1-pro" } } }, }) const result = await fetchAvailableModels(undefined, { @@ -74,7 +74,7 @@ describe("fetchAvailableModels", () => { expect(result.size).toBe(3) expect(result.has("openai/gpt-5.2")).toBe(true) expect(result.has("anthropic/claude-opus-4-6")).toBe(true) - expect(result.has("google/gemini-3-pro")).toBe(true) + expect(result.has("google/gemini-3.1-pro")).toBe(true) }) it("#given connectedProviders unknown #when fetchAvailableModels called without options #then returns empty Set", async () => { @@ -97,7 +97,7 @@ describe("fetchAvailableModels", () => { list: async () => ({ data: [ { id: "gpt-5.3-codex", provider: "openai" }, - { id: "gemini-3-pro", provider: "google" }, + { id: "gemini-3.1-pro", provider: "google" }, ], }), }, @@ -107,7 +107,7 @@ describe("fetchAvailableModels", () => { expect(result).toBeInstanceOf(Set) expect(result.has("openai/gpt-5.3-codex")).toBe(true) - expect(result.has("google/gemini-3-pro")).toBe(false) + expect(result.has("google/gemini-3.1-pro")).toBe(false) }) it("#given cache file not found #when fetchAvailableModels called with connectedProviders #then returns empty Set", async () => { @@ -126,7 +126,7 @@ describe("fetchAvailableModels", () => { list: async () => ({ data: [ { id: "gpt-5.3-codex", provider: "openai" }, - { id: "gemini-3-pro", provider: "google" }, + { id: "gemini-3.1-pro", provider: "google" }, ], }), }, @@ -136,7 +136,7 @@ describe("fetchAvailableModels", () => { expect(result).toBeInstanceOf(Set) expect(result.has("openai/gpt-5.3-codex")).toBe(true) - expect(result.has("google/gemini-3-pro")).toBe(true) + expect(result.has("google/gemini-3.1-pro")).toBe(true) }) it("#given cache read twice #when second call made with same providers #then reads fresh each time", async () => { @@ -515,7 +515,7 @@ describe("fetchAvailableModels with connected providers filtering", () => { writeModelsCache({ openai: { models: { "gpt-5.2": { id: "gpt-5.2" } } }, anthropic: { models: { "claude-opus-4-6": { id: "claude-opus-4-6" } } }, - google: { models: { "gemini-3-pro": { id: "gemini-3-pro" } } }, + google: { models: { "gemini-3.1-pro": { id: "gemini-3.1-pro" } } }, }) const result = await fetchAvailableModels(undefined, { @@ -525,7 +525,7 @@ describe("fetchAvailableModels with connected providers filtering", () => { expect(result.size).toBe(1) expect(result.has("anthropic/claude-opus-4-6")).toBe(true) expect(result.has("openai/gpt-5.2")).toBe(false) - expect(result.has("google/gemini-3-pro")).toBe(false) + expect(result.has("google/gemini-3.1-pro")).toBe(false) }) // given cache with multiple providers @@ -535,7 +535,7 @@ describe("fetchAvailableModels with connected providers filtering", () => { writeModelsCache({ openai: { models: { "gpt-5.2": { id: "gpt-5.2" } } }, anthropic: { models: { "claude-opus-4-6": { id: "claude-opus-4-6" } } }, - google: { models: { "gemini-3-pro": { id: "gemini-3-pro" } } }, + google: { models: { "gemini-3.1-pro": { id: "gemini-3.1-pro" } } }, }) const result = await fetchAvailableModels(undefined, { @@ -544,7 +544,7 @@ describe("fetchAvailableModels with connected providers filtering", () => { expect(result.size).toBe(2) expect(result.has("anthropic/claude-opus-4-6")).toBe(true) - expect(result.has("google/gemini-3-pro")).toBe(true) + expect(result.has("google/gemini-3.1-pro")).toBe(true) expect(result.has("openai/gpt-5.2")).toBe(false) }) @@ -759,7 +759,7 @@ describe("fetchAvailableModels with provider-models cache (whitelist-filtered)", models: { opencode: ["big-pickle"], anthropic: ["claude-opus-4-6"], - google: ["gemini-3-pro"] + google: ["gemini-3.1-pro"] }, connected: ["opencode", "anthropic", "google"] }) @@ -771,7 +771,7 @@ describe("fetchAvailableModels with provider-models cache (whitelist-filtered)", expect(result.size).toBe(1) expect(result.has("opencode/big-pickle")).toBe(true) expect(result.has("anthropic/claude-opus-4-6")).toBe(false) - expect(result.has("google/gemini-3-pro")).toBe(false) + expect(result.has("google/gemini-3.1-pro")).toBe(false) }) it("should handle object[] format with metadata (Ollama-style)", async () => { @@ -953,7 +953,7 @@ describe("fallback model availability", () => { { providers: ["openai"], model: "gpt-5.2" }, { providers: ["anthropic"], model: "claude-opus-4-6" }, ] - const availableModels = new Set(["google/gemini-3-pro"]) + const availableModels = new Set(["google/gemini-3.1-pro"]) // when const result = resolveFirstAvailableFallback(fallbackChain, availableModels) diff --git a/src/shared/model-requirements.test.ts b/src/shared/model-requirements.test.ts index 112b2b774..df4cd696a 100644 --- a/src/shared/model-requirements.test.ts +++ b/src/shared/model-requirements.test.ts @@ -248,19 +248,19 @@ describe("CATEGORY_MODEL_REQUIREMENTS", () => { expect(primary.providers[0]).toBe("openai") }) - test("visual-engineering has valid fallbackChain with gemini-3-pro high as primary", () => { + test("visual-engineering has valid fallbackChain with gemini-3.1-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) + // then - fallbackChain: gemini-3.1-pro(high) → glm-5 → opus-4-6(max) expect(visualEngineering).toBeDefined() expect(visualEngineering.fallbackChain).toBeArray() expect(visualEngineering.fallbackChain).toHaveLength(3) const primary = visualEngineering.fallbackChain[0] expect(primary.providers[0]).toBe("google") - expect(primary.model).toBe("gemini-3-pro") + expect(primary.model).toBe("gemini-3.1-pro") expect(primary.variant).toBe("high") const second = visualEngineering.fallbackChain[1] @@ -319,39 +319,43 @@ describe("CATEGORY_MODEL_REQUIREMENTS", () => { expect(primary.providers).toEqual(["anthropic", "github-copilot", "opencode"]) }) - test("artistry has valid fallbackChain with gemini-3-pro as primary", () => { + test("artistry has valid fallbackChain with gemini-3.1-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 + // then - fallbackChain exists with gemini-3.1-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.model).toBe("gemini-3.1-pro") expect(primary.variant).toBe("high") expect(primary.providers[0]).toBe("google") }) - test("writing has valid fallbackChain with gemini-3-flash as primary", () => { + test("writing has valid fallbackChain with kimi-k2.5-free as primary", () => { // given - writing category requirement const writing = CATEGORY_MODEL_REQUIREMENTS["writing"] // when - accessing writing requirement - // then - fallbackChain: gemini-3-flash → claude-sonnet-4-6 + // then - fallbackChain: kimi-k2.5-free -> gemini-3-flash -> claude-sonnet-4-6 expect(writing).toBeDefined() expect(writing.fallbackChain).toBeArray() - expect(writing.fallbackChain).toHaveLength(2) + expect(writing.fallbackChain).toHaveLength(3) const primary = writing.fallbackChain[0] - expect(primary.model).toBe("gemini-3-flash") - expect(primary.providers[0]).toBe("google") + expect(primary.model).toBe("kimi-k2.5-free") + expect(primary.providers[0]).toBe("opencode") const second = writing.fallbackChain[1] - expect(second.model).toBe("claude-sonnet-4-6") - expect(second.providers[0]).toBe("anthropic") + expect(second.model).toBe("gemini-3-flash") + expect(second.providers[0]).toBe("google") + + const third = writing.fallbackChain[2] + expect(third.model).toBe("claude-sonnet-4-6") + expect(third.providers[0]).toBe("anthropic") }) test("all 8 categories have valid fallbackChain arrays", () => { @@ -489,12 +493,12 @@ describe("requiresModel field in categories", () => { expect(deep.requiresModel).toBe("gpt-5.3-codex") }) - test("artistry category has requiresModel set to gemini-3-pro", () => { + test("artistry category has requiresModel set to gemini-3.1-pro", () => { // given const artistry = CATEGORY_MODEL_REQUIREMENTS["artistry"] // when / #then - expect(artistry.requiresModel).toBe("gemini-3-pro") + expect(artistry.requiresModel).toBe("gemini-3.1-pro") }) }) diff --git a/src/shared/model-requirements.ts b/src/shared/model-requirements.ts index 42a860b96..f8e197ea8 100644 --- a/src/shared/model-requirements.ts +++ b/src/shared/model-requirements.ts @@ -32,7 +32,7 @@ export const AGENT_MODEL_REQUIREMENTS: Record = { oracle: { fallbackChain: [ { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" }, - { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "high" }, + { providers: ["google", "github-copilot", "opencode"], model: "gemini-3.1-pro", variant: "high" }, { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-6", variant: "max" }, ], }, @@ -65,7 +65,7 @@ export const AGENT_MODEL_REQUIREMENTS: Record = { { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-6", variant: "max" }, { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" }, { providers: ["opencode"], model: "kimi-k2.5-free" }, - { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }, + { providers: ["google", "github-copilot", "opencode"], model: "gemini-3.1-pro" }, ], }, metis: { @@ -73,14 +73,14 @@ export const AGENT_MODEL_REQUIREMENTS: Record = { { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-6", variant: "max" }, { providers: ["opencode"], model: "kimi-k2.5-free" }, { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" }, - { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "high" }, + { providers: ["google", "github-copilot", "opencode"], model: "gemini-3.1-pro", variant: "high" }, ], }, momus: { fallbackChain: [ { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "medium" }, { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-6", variant: "max" }, - { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "high" }, + { providers: ["google", "github-copilot", "opencode"], model: "gemini-3.1-pro", variant: "high" }, ], }, atlas: { @@ -95,7 +95,7 @@ export const AGENT_MODEL_REQUIREMENTS: Record = { export const CATEGORY_MODEL_REQUIREMENTS: Record = { "visual-engineering": { fallbackChain: [ - { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "high" }, + { providers: ["google", "github-copilot", "opencode"], model: "gemini-3.1-pro", variant: "high" }, { providers: ["zai-coding-plan", "opencode"], model: "glm-5" }, { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-6", variant: "max" }, ], @@ -103,7 +103,7 @@ export const CATEGORY_MODEL_REQUIREMENTS: Record = { ultrabrain: { fallbackChain: [ { providers: ["openai", "opencode"], model: "gpt-5.3-codex", variant: "xhigh" }, - { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "high" }, + { providers: ["google", "github-copilot", "opencode"], model: "gemini-3.1-pro", variant: "high" }, { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-6", variant: "max" }, ], }, @@ -111,17 +111,17 @@ export const CATEGORY_MODEL_REQUIREMENTS: Record = { fallbackChain: [ { providers: ["openai", "opencode"], model: "gpt-5.3-codex", variant: "medium" }, { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-6", variant: "max" }, - { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "high" }, + { providers: ["google", "github-copilot", "opencode"], model: "gemini-3.1-pro", variant: "high" }, ], requiresModel: "gpt-5.3-codex", }, artistry: { fallbackChain: [ - { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "high" }, + { providers: ["google", "github-copilot", "opencode"], model: "gemini-3.1-pro", variant: "high" }, { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-6", variant: "max" }, { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2" }, ], - requiresModel: "gemini-3-pro", + requiresModel: "gemini-3.1-pro", }, quick: { fallbackChain: [ @@ -141,11 +141,12 @@ export const CATEGORY_MODEL_REQUIREMENTS: Record = { fallbackChain: [ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-6", variant: "max" }, { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" }, - { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }, + { providers: ["google", "github-copilot", "opencode"], model: "gemini-3.1-pro" }, ], }, writing: { fallbackChain: [ + { providers: ["opencode"], model: "kimi-k2.5-free" }, { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-flash" }, { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-6" }, ], diff --git a/src/shared/model-resolver.test.ts b/src/shared/model-resolver.test.ts index fc828f340..d18b46f5a 100644 --- a/src/shared/model-resolver.test.ts +++ b/src/shared/model-resolver.test.ts @@ -10,7 +10,7 @@ describe("resolveModel", () => { const input: ModelResolutionInput = { userModel: "anthropic/claude-opus-4-6", inheritedModel: "openai/gpt-5.2", - systemDefault: "google/gemini-3-pro", + systemDefault: "google/gemini-3.1-pro", } // when @@ -25,7 +25,7 @@ describe("resolveModel", () => { const input: ModelResolutionInput = { userModel: undefined, inheritedModel: "openai/gpt-5.2", - systemDefault: "google/gemini-3-pro", + systemDefault: "google/gemini-3.1-pro", } // when @@ -40,14 +40,14 @@ describe("resolveModel", () => { const input: ModelResolutionInput = { userModel: undefined, inheritedModel: undefined, - systemDefault: "google/gemini-3-pro", + systemDefault: "google/gemini-3.1-pro", } // when const result = resolveModel(input) // then - expect(result).toBe("google/gemini-3-pro") + expect(result).toBe("google/gemini-3.1-pro") }) }) @@ -57,7 +57,7 @@ describe("resolveModel", () => { const input: ModelResolutionInput = { userModel: "", inheritedModel: "openai/gpt-5.2", - systemDefault: "google/gemini-3-pro", + systemDefault: "google/gemini-3.1-pro", } // when @@ -72,14 +72,14 @@ describe("resolveModel", () => { const input: ModelResolutionInput = { userModel: " ", inheritedModel: "", - systemDefault: "google/gemini-3-pro", + systemDefault: "google/gemini-3.1-pro", } // when const result = resolveModel(input) // then - expect(result).toBe("google/gemini-3-pro") + expect(result).toBe("google/gemini-3.1-pro") }) }) @@ -89,7 +89,7 @@ describe("resolveModel", () => { const input: ModelResolutionInput = { userModel: "anthropic/claude-opus-4-6", inheritedModel: "openai/gpt-5.2", - systemDefault: "google/gemini-3-pro", + systemDefault: "google/gemini-3.1-pro", } // when @@ -123,7 +123,7 @@ describe("resolveModelWithFallback", () => { { providers: ["anthropic", "github-copilot"], model: "claude-opus-4-6" }, ], availableModels: new Set(["anthropic/claude-opus-4-6", "github-copilot/claude-opus-4-6-preview"]), - systemDefaultModel: "google/gemini-3-pro", + systemDefaultModel: "google/gemini-3.1-pro", } // when @@ -141,7 +141,7 @@ describe("resolveModelWithFallback", () => { uiSelectedModel: "opencode/big-pickle", userModel: "anthropic/claude-opus-4-6", availableModels: new Set(["anthropic/claude-opus-4-6"]), - systemDefaultModel: "google/gemini-3-pro", + systemDefaultModel: "google/gemini-3.1-pro", } // when @@ -158,7 +158,7 @@ describe("resolveModelWithFallback", () => { uiSelectedModel: " ", userModel: "anthropic/claude-opus-4-6", availableModels: new Set(["anthropic/claude-opus-4-6"]), - systemDefaultModel: "google/gemini-3-pro", + systemDefaultModel: "google/gemini-3.1-pro", } // when @@ -175,7 +175,7 @@ describe("resolveModelWithFallback", () => { uiSelectedModel: "", userModel: "anthropic/claude-opus-4-6", availableModels: new Set(["anthropic/claude-opus-4-6"]), - systemDefaultModel: "google/gemini-3-pro", + systemDefaultModel: "google/gemini-3.1-pro", } // when @@ -195,7 +195,7 @@ describe("resolveModelWithFallback", () => { { providers: ["anthropic", "github-copilot"], model: "claude-opus-4-6" }, ], availableModels: new Set(["anthropic/claude-opus-4-6", "github-copilot/claude-opus-4-6-preview"]), - systemDefaultModel: "google/gemini-3-pro", + systemDefaultModel: "google/gemini-3.1-pro", } // when @@ -215,7 +215,7 @@ describe("resolveModelWithFallback", () => { { providers: ["anthropic"], model: "claude-opus-4-6" }, ], availableModels: new Set(["anthropic/claude-opus-4-6"]), - systemDefaultModel: "google/gemini-3-pro", + systemDefaultModel: "google/gemini-3.1-pro", } // when @@ -234,7 +234,7 @@ describe("resolveModelWithFallback", () => { { providers: ["anthropic"], model: "claude-opus-4-6" }, ], availableModels: new Set(["anthropic/claude-opus-4-6"]), - systemDefaultModel: "google/gemini-3-pro", + systemDefaultModel: "google/gemini-3.1-pro", } // when @@ -252,7 +252,7 @@ describe("resolveModelWithFallback", () => { { providers: ["anthropic"], model: "claude-opus-4-6" }, ], availableModels: new Set(["anthropic/claude-opus-4-6"]), - systemDefaultModel: "google/gemini-3-pro", + systemDefaultModel: "google/gemini-3.1-pro", } // when @@ -271,7 +271,7 @@ describe("resolveModelWithFallback", () => { { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-6" }, ], availableModels: new Set(["github-copilot/claude-opus-4-6-preview", "opencode/claude-opus-4-7"]), - systemDefaultModel: "google/gemini-3-pro", + systemDefaultModel: "google/gemini-3.1-pro", } // when @@ -294,8 +294,8 @@ describe("resolveModelWithFallback", () => { fallbackChain: [ { providers: ["openai", "anthropic", "google"], model: "gpt-5.2" }, ], - availableModels: new Set(["openai/gpt-5.2", "anthropic/claude-opus-4-6", "google/gemini-3-pro"]), - systemDefaultModel: "google/gemini-3-pro", + availableModels: new Set(["openai/gpt-5.2", "anthropic/claude-opus-4-6", "google/gemini-3.1-pro"]), + systemDefaultModel: "google/gemini-3.1-pro", } // when @@ -313,7 +313,7 @@ describe("resolveModelWithFallback", () => { { providers: ["anthropic", "opencode"], model: "gpt-5-nano" }, ], availableModels: new Set(["opencode/gpt-5-nano"]), - systemDefaultModel: "google/gemini-3-pro", + systemDefaultModel: "google/gemini-3.1-pro", } // when @@ -331,7 +331,7 @@ describe("resolveModelWithFallback", () => { { providers: ["anthropic", "github-copilot"], model: "claude-opus" }, ], availableModels: new Set(["anthropic/claude-opus-4-6", "github-copilot/claude-opus-4-6-preview"]), - systemDefaultModel: "google/gemini-3-pro", + systemDefaultModel: "google/gemini-3.1-pro", } // when @@ -346,7 +346,7 @@ describe("resolveModelWithFallback", () => { // given const input: ExtendedModelResolutionInput = { availableModels: new Set(["anthropic/claude-opus-4-6"]), - systemDefaultModel: "google/gemini-3-pro", + systemDefaultModel: "google/gemini-3.1-pro", } // when @@ -361,7 +361,7 @@ describe("resolveModelWithFallback", () => { const input: ExtendedModelResolutionInput = { fallbackChain: [], availableModels: new Set(["anthropic/claude-opus-4-6"]), - systemDefaultModel: "google/gemini-3-pro", + systemDefaultModel: "google/gemini-3.1-pro", } // when @@ -378,7 +378,7 @@ describe("resolveModelWithFallback", () => { { providers: ["anthropic"], model: "CLAUDE-OPUS" }, ], availableModels: new Set(["anthropic/claude-opus-4-6"]), - systemDefaultModel: "google/gemini-3-pro", + systemDefaultModel: "google/gemini-3.1-pro", } // when @@ -397,7 +397,7 @@ describe("resolveModelWithFallback", () => { { providers: ["anthropic"], model: "claude-sonnet-4-6" }, ], availableModels: new Set(["opencode/glm-5", "anthropic/claude-sonnet-4-6"]), - systemDefaultModel: "google/gemini-3-pro", + systemDefaultModel: "google/gemini-3.1-pro", } // when @@ -420,7 +420,7 @@ describe("resolveModelWithFallback", () => { { providers: ["zai-coding-plan"], model: "glm-5" }, ], availableModels: new Set(["zai-coding-plan/glm-5", "opencode/glm-5"]), - systemDefaultModel: "google/gemini-3-pro", + systemDefaultModel: "google/gemini-3.1-pro", } // when @@ -438,7 +438,7 @@ describe("resolveModelWithFallback", () => { { providers: ["zai-coding-plan"], model: "glm-5", variant: "high" }, ], availableModels: new Set(["opencode/glm-5"]), - systemDefaultModel: "google/gemini-3-pro", + systemDefaultModel: "google/gemini-3.1-pro", } // when @@ -457,7 +457,7 @@ describe("resolveModelWithFallback", () => { { providers: ["anthropic"], model: "claude-sonnet-4-6" }, ], availableModels: new Set(["anthropic/claude-sonnet-4-6"]), - systemDefaultModel: "google/gemini-3-pro", + systemDefaultModel: "google/gemini-3.1-pro", } // when @@ -477,14 +477,14 @@ describe("resolveModelWithFallback", () => { { providers: ["anthropic"], model: "nonexistent-model" }, ], availableModels: new Set(["openai/gpt-5.2", "anthropic/claude-opus-4-6"]), - systemDefaultModel: "google/gemini-3-pro", + systemDefaultModel: "google/gemini-3.1-pro", } // when const result = resolveModelWithFallback(input) // then - expect(result!.model).toBe("google/gemini-3-pro") + expect(result!.model).toBe("google/gemini-3.1-pro") expect(result!.source).toBe("system-default") expect(logSpy).toHaveBeenCalledWith("No available model found in fallback chain, falling through to system default") }) @@ -516,7 +516,7 @@ describe("resolveModelWithFallback", () => { { providers: ["anthropic", "openai"], model: "claude-opus-4-6" }, ], availableModels: new Set(), - systemDefaultModel: "google/gemini-3-pro", + systemDefaultModel: "google/gemini-3.1-pro", } // when @@ -533,7 +533,7 @@ describe("resolveModelWithFallback", () => { const cacheSpy = spyOn(connectedProvidersCache, "readConnectedProvidersCache").mockReturnValue(["github-copilot"]) const input: ExtendedModelResolutionInput = { fallbackChain: [ - { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }, + { providers: ["google", "github-copilot", "opencode"], model: "gemini-3.1-pro" }, ], availableModels: new Set(), systemDefaultModel: "anthropic/claude-sonnet-4-6", @@ -544,7 +544,7 @@ describe("resolveModelWithFallback", () => { // then - should use github-copilot (second provider) since google not connected // model name is transformed to preview variant for github-copilot provider - expect(result!.model).toBe("github-copilot/gemini-3-pro-preview") + expect(result!.model).toBe("github-copilot/gemini-3.1-pro-preview") expect(result!.source).toBe("provider-fallback") cacheSpy.mockRestore() }) @@ -577,14 +577,14 @@ describe("resolveModelWithFallback", () => { { providers: ["anthropic"], model: "claude-opus-4-6" }, ], availableModels: new Set(), - systemDefaultModel: "google/gemini-3-pro", + systemDefaultModel: "google/gemini-3.1-pro", } // when const result = resolveModelWithFallback(input) // then - should fall through to system default - expect(result!.model).toBe("google/gemini-3-pro") + expect(result!.model).toBe("google/gemini-3.1-pro") expect(result!.source).toBe("system-default") cacheSpy.mockRestore() }) @@ -593,14 +593,14 @@ describe("resolveModelWithFallback", () => { // given const input: ExtendedModelResolutionInput = { availableModels: new Set(["openai/gpt-5.2"]), - systemDefaultModel: "google/gemini-3-pro", + systemDefaultModel: "google/gemini-3.1-pro", } // when const result = resolveModelWithFallback(input) // then - expect(result!.model).toBe("google/gemini-3-pro") + expect(result!.model).toBe("google/gemini-3.1-pro") expect(result!.source).toBe("system-default") }) }) @@ -627,20 +627,20 @@ describe("resolveModelWithFallback", () => { test("tries all providers in first entry before moving to second entry", () => { // given - const availableModels = new Set(["google/gemini-3-pro"]) + const availableModels = new Set(["google/gemini-3.1-pro"]) // when const result = resolveModelWithFallback({ fallbackChain: [ { providers: ["openai", "anthropic"], model: "gpt-5.2" }, - { providers: ["google"], model: "gemini-3-pro" }, + { providers: ["google"], model: "gemini-3.1-pro" }, ], availableModels, systemDefaultModel: "system/default", }) // then - expect(result!.model).toBe("google/gemini-3-pro") + expect(result!.model).toBe("google/gemini-3.1-pro") expect(result!.source).toBe("provider-fallback") }) @@ -675,7 +675,7 @@ describe("resolveModelWithFallback", () => { fallbackChain: [ { providers: ["openai"], model: "gpt-5.2" }, { providers: ["anthropic"], model: "claude-opus-4-6" }, - { providers: ["google"], model: "gemini-3-pro" }, + { providers: ["google"], model: "gemini-3.1-pro" }, ], availableModels, systemDefaultModel: "system/default", @@ -693,7 +693,7 @@ describe("resolveModelWithFallback", () => { const input: ExtendedModelResolutionInput = { userModel: "anthropic/claude-opus-4-6", availableModels: new Set(), - systemDefaultModel: "google/gemini-3-pro", + systemDefaultModel: "google/gemini-3.1-pro", } // when @@ -708,32 +708,32 @@ describe("resolveModelWithFallback", () => { describe("categoryDefaultModel (fuzzy matching for category defaults)", () => { test("applies fuzzy matching to categoryDefaultModel when userModel not provided", () => { - // given - gemini-3-pro is the category default, but only gemini-3-pro-preview is available + // given - gemini-3.1-pro is the category default, but only gemini-3.1-pro-preview is available const input: ExtendedModelResolutionInput = { - categoryDefaultModel: "google/gemini-3-pro", + categoryDefaultModel: "google/gemini-3.1-pro", fallbackChain: [ - { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }, + { providers: ["google", "github-copilot", "opencode"], model: "gemini-3.1-pro" }, ], - availableModels: new Set(["google/gemini-3-pro-preview", "anthropic/claude-opus-4-6"]), + availableModels: new Set(["google/gemini-3.1-pro-preview", "anthropic/claude-opus-4-6"]), systemDefaultModel: "anthropic/claude-sonnet-4-6", } // when const result = resolveModelWithFallback(input) - // then - should fuzzy match gemini-3-pro → gemini-3-pro-preview - expect(result!.model).toBe("google/gemini-3-pro-preview") + // then - should fuzzy match gemini-3.1-pro → gemini-3.1-pro-preview + expect(result!.model).toBe("google/gemini-3.1-pro-preview") expect(result!.source).toBe("category-default") }) test("categoryDefaultModel uses exact match when available", () => { // given - exact match exists const input: ExtendedModelResolutionInput = { - categoryDefaultModel: "google/gemini-3-pro", + categoryDefaultModel: "google/gemini-3.1-pro", fallbackChain: [ - { providers: ["google"], model: "gemini-3-pro" }, + { providers: ["google"], model: "gemini-3.1-pro" }, ], - availableModels: new Set(["google/gemini-3-pro", "google/gemini-3-pro-preview"]), + availableModels: new Set(["google/gemini-3.1-pro", "google/gemini-3.1-pro-preview"]), systemDefaultModel: "anthropic/claude-sonnet-4-6", } @@ -741,14 +741,14 @@ describe("resolveModelWithFallback", () => { const result = resolveModelWithFallback(input) // then - should use exact match - expect(result!.model).toBe("google/gemini-3-pro") + expect(result!.model).toBe("google/gemini-3.1-pro") expect(result!.source).toBe("category-default") }) test("categoryDefaultModel falls through to fallbackChain when no match in availableModels", () => { // given - categoryDefaultModel has no match, but fallbackChain does const input: ExtendedModelResolutionInput = { - categoryDefaultModel: "google/gemini-3-pro", + categoryDefaultModel: "google/gemini-3.1-pro", fallbackChain: [ { providers: ["anthropic"], model: "claude-opus-4-6" }, ], @@ -768,11 +768,11 @@ describe("resolveModelWithFallback", () => { // given - both userModel and categoryDefaultModel provided const input: ExtendedModelResolutionInput = { userModel: "anthropic/claude-opus-4-6", - categoryDefaultModel: "google/gemini-3-pro", + categoryDefaultModel: "google/gemini-3.1-pro", fallbackChain: [ - { providers: ["google"], model: "gemini-3-pro" }, + { providers: ["google"], model: "gemini-3.1-pro" }, ], - availableModels: new Set(["google/gemini-3-pro-preview", "anthropic/claude-opus-4-6"]), + availableModels: new Set(["google/gemini-3.1-pro-preview", "anthropic/claude-opus-4-6"]), systemDefaultModel: "system/default", } @@ -788,7 +788,7 @@ describe("resolveModelWithFallback", () => { // given - no availableModels but connected provider cache exists const cacheSpy = spyOn(connectedProvidersCache, "readConnectedProvidersCache").mockReturnValue(["google"]) const input: ExtendedModelResolutionInput = { - categoryDefaultModel: "google/gemini-3-pro", + categoryDefaultModel: "google/gemini-3.1-pro", availableModels: new Set(), systemDefaultModel: "anthropic/claude-sonnet-4-6", } @@ -797,7 +797,7 @@ describe("resolveModelWithFallback", () => { const result = resolveModelWithFallback(input) // then - should use transformed categoryDefaultModel since google is connected - expect(result!.model).toBe("google/gemini-3-pro-preview") + expect(result!.model).toBe("google/gemini-3.1-pro-preview") expect(result!.source).toBe("category-default") cacheSpy.mockRestore() }) @@ -824,7 +824,7 @@ describe("resolveModelWithFallback", () => { // given - category default already has -preview suffix const cacheSpy = spyOn(connectedProvidersCache, "readConnectedProvidersCache").mockReturnValue(["google"]) const input: ExtendedModelResolutionInput = { - categoryDefaultModel: "google/gemini-3-pro-preview", + categoryDefaultModel: "google/gemini-3.1-pro-preview", availableModels: new Set(), systemDefaultModel: "anthropic/claude-sonnet-4-5", } @@ -832,18 +832,18 @@ describe("resolveModelWithFallback", () => { // when const result = resolveModelWithFallback(input) - // then - should NOT become gemini-3-pro-preview-preview - expect(result!.model).toBe("google/gemini-3-pro-preview") + // then - should NOT become gemini-3.1-pro-preview-preview + expect(result!.model).toBe("google/gemini-3.1-pro-preview") expect(result!.source).toBe("category-default") cacheSpy.mockRestore() }) - test("transforms gemini-3-pro in fallback chain for google connected provider", () => { - // given - google connected, fallback chain has gemini-3-pro + test("transforms gemini-3.1-pro in fallback chain for google connected provider", () => { + // given - google connected, fallback chain has gemini-3.1-pro const cacheSpy = spyOn(connectedProvidersCache, "readConnectedProvidersCache").mockReturnValue(["google"]) const input: ExtendedModelResolutionInput = { fallbackChain: [ - { providers: ["google", "github-copilot"], model: "gemini-3-pro" }, + { providers: ["google", "github-copilot"], model: "gemini-3.1-pro" }, ], availableModels: new Set(), systemDefaultModel: "anthropic/claude-sonnet-4-5", @@ -853,7 +853,7 @@ describe("resolveModelWithFallback", () => { const result = resolveModelWithFallback(input) // then - should transform to preview variant for google provider - expect(result!.model).toBe("google/gemini-3-pro-preview") + expect(result!.model).toBe("google/gemini-3.1-pro-preview") expect(result!.source).toBe("provider-fallback") cacheSpy.mockRestore() }) diff --git a/src/shared/provider-model-id-transform.ts b/src/shared/provider-model-id-transform.ts index 5b8c810bb..0cf8eb801 100644 --- a/src/shared/provider-model-id-transform.ts +++ b/src/shared/provider-model-id-transform.ts @@ -6,12 +6,12 @@ export function transformModelForProvider(provider: string, model: string): stri .replace("claude-sonnet-4-5", "claude-sonnet-4.5") .replace("claude-haiku-4-5", "claude-haiku-4.5") .replace("claude-sonnet-4", "claude-sonnet-4") - .replace(/gemini-3-pro(?!-)/g, "gemini-3-pro-preview") + .replace(/gemini-3\.1-pro(?!-)/g, "gemini-3.1-pro-preview") .replace(/gemini-3-flash(?!-)/g, "gemini-3-flash-preview") } if (provider === "google") { return model - .replace(/gemini-3-pro(?!-)/g, "gemini-3-pro-preview") + .replace(/gemini-3\.1-pro(?!-)/g, "gemini-3.1-pro-preview") .replace(/gemini-3-flash(?!-)/g, "gemini-3-flash-preview") } return model diff --git a/src/tools/delegate-task/constants.ts b/src/tools/delegate-task/constants.ts index 146838a42..ecf37135f 100644 --- a/src/tools/delegate-task/constants.ts +++ b/src/tools/delegate-task/constants.ts @@ -208,10 +208,10 @@ You are NOT an interactive assistant. You are an autonomous problem-solver. export const DEFAULT_CATEGORIES: Record = { - "visual-engineering": { model: "google/gemini-3-pro", variant: "high" }, + "visual-engineering": { model: "google/gemini-3.1-pro", variant: "high" }, ultrabrain: { model: "openai/gpt-5.3-codex", variant: "xhigh" }, deep: { model: "openai/gpt-5.3-codex", variant: "medium" }, - artistry: { model: "google/gemini-3-pro", variant: "high" }, + artistry: { model: "google/gemini-3.1-pro", variant: "high" }, quick: { model: "anthropic/claude-haiku-4-5" }, "unspecified-low": { model: "anthropic/claude-sonnet-4-6" }, "unspecified-high": { model: "anthropic/claude-opus-4-6", variant: "max" }, diff --git a/src/tools/delegate-task/tools.test.ts b/src/tools/delegate-task/tools.test.ts index b9b1274bc..8c0b01acf 100644 --- a/src/tools/delegate-task/tools.test.ts +++ b/src/tools/delegate-task/tools.test.ts @@ -17,7 +17,7 @@ const TEST_AVAILABLE_MODELS = new Set([ "anthropic/claude-opus-4-6", "anthropic/claude-sonnet-4-6", "anthropic/claude-haiku-4-5", - "google/gemini-3-pro", + "google/gemini-3.1-pro", "google/gemini-3-flash", "openai/gpt-5.2", "openai/gpt-5.3-codex", @@ -52,7 +52,7 @@ describe("sisyphus-task", () => { providerModelsSpy = spyOn(connectedProvidersCache, "readProviderModelsCache").mockReturnValue({ models: { anthropic: ["claude-opus-4-6", "claude-sonnet-4-6", "claude-haiku-4-5"], - google: ["gemini-3-pro", "gemini-3-flash"], + google: ["gemini-3.1-pro", "gemini-3-flash"], openai: ["gpt-5.2", "gpt-5.3-codex"], }, connected: ["anthropic", "google", "openai"], @@ -73,7 +73,7 @@ describe("sisyphus-task", () => { // when / #then expect(category).toBeDefined() - expect(category.model).toBe("google/gemini-3-pro") + expect(category.model).toBe("google/gemini-3.1-pro") expect(category.variant).toBe("high") }) @@ -781,7 +781,7 @@ describe("sisyphus-task", () => { // then expect(result).not.toBeNull() - expect(result!.config.model).toBe("google/gemini-3-pro") + expect(result!.config.model).toBe("google/gemini-3.1-pro") expect(result!.promptAppend).toContain("VISUAL/UI") }) @@ -805,7 +805,7 @@ describe("sisyphus-task", () => { const categoryName = "visual-engineering" const userCategories = { "visual-engineering": { - model: "google/gemini-3-pro", + model: "google/gemini-3.1-pro", prompt_append: "Custom instructions here", }, } @@ -845,7 +845,7 @@ describe("sisyphus-task", () => { const categoryName = "visual-engineering" const userCategories = { "visual-engineering": { - model: "google/gemini-3-pro", + model: "google/gemini-3.1-pro", temperature: 0.3, }, } @@ -868,7 +868,7 @@ describe("sisyphus-task", () => { // then - category's built-in model wins over inheritedModel expect(result).not.toBeNull() - expect(result!.config.model).toBe("google/gemini-3-pro") + expect(result!.config.model).toBe("google/gemini-3.1-pro") }) test("systemDefaultModel is used as fallback when custom category has no model", () => { @@ -910,7 +910,7 @@ describe("sisyphus-task", () => { // then expect(result).not.toBeNull() - expect(result!.config.model).toBe("google/gemini-3-pro") + expect(result!.config.model).toBe("google/gemini-3.1-pro") }) }) @@ -1738,7 +1738,7 @@ describe("sisyphus-task", () => { const mockClient = { app: { agents: async () => ({ data: [] }) }, config: { get: async () => ({ data: { model: SYSTEM_DEFAULT_MODEL } }) }, - model: { list: async () => [{ provider: "google", id: "gemini-3-pro" }] }, + model: { list: async () => [{ provider: "google", id: "gemini-3.1-pro" }] }, session: { get: async () => ({ data: { directory: "/project" } }), create: async () => ({ data: { id: "ses_unstable_gemini" } }), @@ -2001,7 +2001,7 @@ describe("sisyphus-task", () => { const mockClient = { app: { agents: async () => ({ data: [] }) }, config: { get: async () => ({ data: { model: SYSTEM_DEFAULT_MODEL } }) }, - model: { list: async () => [{ provider: "google", id: "gemini-3-pro" }] }, + model: { list: async () => [{ provider: "google", id: "gemini-3.1-pro" }] }, session: { get: async () => ({ data: { directory: "/project" } }), create: async () => ({ data: { id: "ses_artistry_gemini" } }), @@ -2028,7 +2028,7 @@ describe("sisyphus-task", () => { abort: new AbortController().signal, } - // when - artistry category (gemini-3-pro with high variant) + // when - artistry category (gemini-3.1-pro with high variant) const result = await tool.execute( { description: "Test artistry forced background", @@ -3026,9 +3026,9 @@ describe("sisyphus-task", () => { // when resolveCategoryConfig is called const resolved = resolveCategoryConfig(categoryName, { userCategories, inheritedModel, systemDefaultModel: SYSTEM_DEFAULT_MODEL }) - // then should use category's built-in model (gemini-3-pro for visual-engineering) + // then should use category's built-in model (gemini-3.1-pro for visual-engineering) expect(resolved).not.toBeNull() - expect(resolved!.model).toBe("google/gemini-3-pro") + expect(resolved!.model).toBe("google/gemini-3.1-pro") }) test("systemDefaultModel is used when no other model is available", () => { @@ -3522,7 +3522,7 @@ describe("sisyphus-task", () => { ) // then - should resolve via AGENT_MODEL_REQUIREMENTS fallback chain for oracle - // oracle fallback chain: gpt-5.2 (openai) > gemini-3-pro (google) > claude-opus-4-6 (anthropic) + // oracle fallback chain: gpt-5.2 (openai) > gemini-3.1-pro (google) > claude-opus-4-6 (anthropic) // Since openai is in connectedProviders, should resolve to openai/gpt-5.2 expect(promptBody.model).toBeDefined() expect(promptBody.model.providerID).toBe("openai")