From 9ab675a843ea96a289451a1983aef868e02b7262 Mon Sep 17 00:00:00 2001 From: Tibsfox Date: Sun, 5 Apr 2026 10:24:52 -0700 Subject: [PATCH] fix(gsd): disable dynamic model routing for flat-rate providers --- .../extensions/gsd/auto-model-selection.ts | 23 +++++++++++ .../gsd/tests/flat-rate-routing-guard.test.ts | 40 +++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts diff --git a/src/resources/extensions/gsd/auto-model-selection.ts b/src/resources/extensions/gsd/auto-model-selection.ts index 544a97857..6b8aabe70 100644 --- a/src/resources/extensions/gsd/auto-model-selection.ts +++ b/src/resources/extensions/gsd/auto-model-selection.ts @@ -31,6 +31,9 @@ export function resolvePreferredModelConfig( const routingConfig = resolveDynamicRoutingConfig(); if (!routingConfig.enabled || !routingConfig.tier_models) return undefined; + // Don't synthesize a routing config for flat-rate providers (#3453). + if (autoModeStartModel && isFlatRateProvider(autoModeStartModel.provider)) return undefined; + const ceilingModel = routingConfig.tier_models.heavy ?? (autoModeStartModel ? `${autoModeStartModel.provider}/${autoModeStartModel.id}` : undefined); if (!ceilingModel) return undefined; @@ -71,6 +74,16 @@ export async function selectAndApplyModel( let effectiveModelConfig = modelConfig; let routingTierLabel = ""; + // Disable routing for flat-rate providers like GitHub Copilot (#3453). + // All models cost the same per request, so downgrading to a cheaper + // model provides no cost benefit — it only degrades quality. + if (routingConfig.enabled) { + const primaryModel = resolveModelId(modelConfig.primary, availableModels, ctx.model?.provider); + if (primaryModel && isFlatRateProvider(primaryModel.provider)) { + routingConfig.enabled = false; + } + } + if (routingConfig.enabled) { let budgetPct: number | undefined; if (routingConfig.budget_pressure !== false) { @@ -320,3 +333,13 @@ export function resolveModelId( // Fall back to first non-extension candidate, or any candidate return candidates.find(m => !EXTENSION_PROVIDERS.has(m.provider)) ?? candidates[0]; } + +/** + * Flat-rate providers charge the same per request regardless of model. + * Dynamic routing provides no cost benefit — it only degrades quality (#3453). + */ +const FLAT_RATE_PROVIDERS = new Set(["github-copilot"]); + +export function isFlatRateProvider(provider: string): boolean { + return FLAT_RATE_PROVIDERS.has(provider); +} diff --git a/src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts b/src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts new file mode 100644 index 000000000..a02b0b9f6 --- /dev/null +++ b/src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts @@ -0,0 +1,40 @@ +/** + * Regression test for #3453: dynamic model routing must be disabled for + * flat-rate providers like GitHub Copilot where all models cost the same + * per request — routing only degrades quality with no cost benefit. + */ + +import { describe, test } from "node:test"; +import assert from "node:assert/strict"; +import { isFlatRateProvider, resolvePreferredModelConfig } from "../auto-model-selection.ts"; + +describe("flat-rate provider routing guard (#3453)", () => { + + test("isFlatRateProvider returns true for github-copilot", () => { + assert.equal(isFlatRateProvider("github-copilot"), true); + }); + + test("isFlatRateProvider returns false for anthropic", () => { + assert.equal(isFlatRateProvider("anthropic"), false); + }); + + test("isFlatRateProvider returns false for openai", () => { + assert.equal(isFlatRateProvider("openai"), false); + }); + + test("resolvePreferredModelConfig returns undefined for copilot start model", () => { + // When the user's start model is on a flat-rate provider, + // resolvePreferredModelConfig should not synthesize a routing + // config from tier_models — it should return undefined so the + // user's selected model is preserved. + const result = resolvePreferredModelConfig("execute-task", { + provider: "github-copilot", + id: "claude-sonnet-4", + }); + + // Should be undefined (no routing config created for flat-rate) + // Note: this only tests the guard — if explicit per-unit config exists + // in preferences, that takes precedence regardless. + assert.equal(result, undefined, "Should not create routing config for copilot"); + }); +});