Skip to content

Commit 070ee98

Browse files
authored
[refactor] Move default provider ID functionality into provider definition (#2233)
* refactor(types): move provider-settings into providers Merge packages/types/src/provider-settings/*.ts into packages/types/src/providers/, appending each source file's code to the end of the same-named destination file and combining their imports. Files without a same-named counterpart (common, fake-ai, gemini-cli, litellm, openai-native, vscode-lm) move over unchanged. The providerDefinitionList registry from provider-settings/index.ts is appended to providers/index.ts, and all import sites now point at the new location. * refactor(types): move provider default model data into provider definitions Each provider definition now declares its own `getDefaultModelId`, mirroring `getModelId`, so per-provider default-model data lives next to the rest of that provider's configuration instead of in a central switch. - Add `getDefaultModelId` to `ProviderDefinition`/`createProviderDefinition` and a shared `NO_DEFAULT_MODEL_ID` constant. - Move every provider's default into its definition; Z.ai keeps its region-dependent logic by reading `zaiApiLine` from settings. - Remove the `getProviderDefaultModelId` switch from `providers/index.ts`. - Re-add `getProviderDefaultModelId(provider, settings)` in `provider-settings.ts`, resolving the definition and falling back to the Anthropic default. - Update webview callers to pass `apiConfiguration` and drop the duplicated Z.ai region logic in `providerModelConfig.ts`. - Extend tests to cover the new accessor and the Z.ai API-line defaults.
1 parent 57307f6 commit 070ee98

79 files changed

Lines changed: 1010 additions & 993 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎packages/types/src/__tests__/io-intelligence.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ describe("IO Intelligence shared contract", () => {
1212
it("registers the stable dynamic-provider identity and default model", () => {
1313
expect(providerIdentifiers.ioIntelligence).toBe("io-intelligence")
1414
expect(dynamicProviders).toContain(providerIdentifiers.ioIntelligence)
15-
expect(getProviderDefaultModelId(providerIdentifiers.ioIntelligence)).toBe(ioIntelligenceDefaultModelId)
15+
expect(getProviderDefaultModelId(providerIdentifiers.ioIntelligence, {})).toBe(ioIntelligenceDefaultModelId)
1616
})
1717

1818
it("classifies the API key as secret and resolves the configured model", () => {

‎packages/types/src/__tests__/nanogpt.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ describe("NanoGPT shared contract", () => {
1414
it("registers the stable dynamic-provider identity and default model", () => {
1515
expect(providerIdentifiers.nanogpt).toBe("nanogpt")
1616
expect(dynamicProviders).toContain(providerIdentifiers.nanogpt)
17-
expect(getProviderDefaultModelId(providerIdentifiers.nanogpt)).toBe(nanoGptDefaultModelId)
17+
expect(getProviderDefaultModelId(providerIdentifiers.nanogpt, {})).toBe(nanoGptDefaultModelId)
1818
})
1919

2020
it("classifies the API key as secret and resolves missing routing to auto", () => {

‎packages/types/src/__tests__/provider-default-model.test.ts‎

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ vi.mock("../provider-identifiers.js", async (importOriginal) => {
1515
import { providerIdentifiers } from "../provider-identifiers.js"
1616
import {
1717
anthropicDefaultModelId,
18-
getProviderDefaultModelId,
18+
getZAiDefaultModelId,
1919
internationalZAiDefaultModelId,
2020
kimiCodeDefaultModelId,
2121
mainlandZAiDefaultModelId,
@@ -24,49 +24,79 @@ import {
2424
vscodeLlmDefaultModelId,
2525
zooGatewayDefaultModelId,
2626
} from "../providers/index.js"
27+
import { getProviderDefaultModelId } from "../provider-settings.js"
28+
29+
const zaiApiLineCases = [
30+
["china_coding", "china"],
31+
["china_api", "china"],
32+
["international_coding", "international"],
33+
["international_api", "international"],
34+
] as const
2735

2836
describe("getProviderDefaultModelId", () => {
2937
it("selects a static default through the canonical provider identifier", () => {
30-
expect(getProviderDefaultModelId(providerIdentifiers.openrouter as ProviderName)).toBe(openRouterDefaultModelId)
38+
expect(getProviderDefaultModelId(providerIdentifiers.openrouter as ProviderName, {})).toBe(
39+
openRouterDefaultModelId,
40+
)
3141
})
3242

3343
it("triangulates static selection with another provider category", () => {
34-
expect(getProviderDefaultModelId(providerIdentifiers.vscodeLm)).toBe(vscodeLlmDefaultModelId)
44+
expect(getProviderDefaultModelId(providerIdentifiers.vscodeLm, {})).toBe(vscodeLlmDefaultModelId)
3545
})
3646

3747
it("gives GitHub Copilot the same default as the VS Code LM provider", () => {
38-
expect(getProviderDefaultModelId(providerIdentifiers.githubCopilot)).toBe(vscodeLlmDefaultModelId)
48+
expect(getProviderDefaultModelId(providerIdentifiers.githubCopilot, {})).toBe(vscodeLlmDefaultModelId)
3949
})
4050

4151
it("uses the canonical OpenAI Native default model", () => {
42-
expect(getProviderDefaultModelId(providerIdentifiers.openaiNative)).toBe(openAiNativeDefaultModelId)
52+
expect(getProviderDefaultModelId(providerIdentifiers.openaiNative, {})).toBe(openAiNativeDefaultModelId)
4353
})
4454

4555
it.each([
4656
[providerIdentifiers.kimiCode, kimiCodeDefaultModelId],
4757
[providerIdentifiers.zooGateway, zooGatewayDefaultModelId],
4858
])("preserves the %s default added on main", (provider, expectedModelId) => {
49-
expect(getProviderDefaultModelId(provider)).toBe(expectedModelId)
59+
expect(getProviderDefaultModelId(provider, {})).toBe(expectedModelId)
60+
})
61+
62+
it.each(zaiApiLineCases)("resolves the %s Z.ai default through the provider definition", (zaiApiLine, region) => {
63+
const expected = region === "china" ? mainlandZAiDefaultModelId : internationalZAiDefaultModelId
64+
65+
expect(getProviderDefaultModelId(providerIdentifiers.zai, { zaiApiLine })).toBe(expected)
5066
})
5167

52-
it("preserves region-dependent defaults", () => {
53-
// These defaults currently share the same model ID, so the assertions document
54-
// both branches but cannot detect swapped ternary arms until the IDs diverge.
55-
expect(getProviderDefaultModelId(providerIdentifiers.zai, { isChina: true })).toBe(mainlandZAiDefaultModelId)
56-
expect(getProviderDefaultModelId(providerIdentifiers.zai)).toBe(internationalZAiDefaultModelId)
68+
it("falls back to the international Z.ai default when the API line is unset", () => {
69+
expect(getProviderDefaultModelId(providerIdentifiers.zai, {})).toBe(internationalZAiDefaultModelId)
70+
})
71+
72+
describe("Z.ai region mapping", () => {
73+
// Both regional catalogs currently share a default model ID, so inject
74+
// distinct values to prove the mainland/international arms are not swapped.
75+
const distinctDefaults = { china: "test-china-model", international: "test-international-model" }
76+
77+
it.each(zaiApiLineCases)("maps %s to the %s default", (zaiApiLine, region) => {
78+
expect(getZAiDefaultModelId(zaiApiLine, distinctDefaults)).toBe(distinctDefaults[region])
79+
})
80+
81+
it.each([undefined, null, "bogus"])(
82+
"falls back to the international default for the invalid API line %s",
83+
(zaiApiLine) => {
84+
expect(getZAiDefaultModelId(zaiApiLine, distinctDefaults)).toBe(distinctDefaults.international)
85+
},
86+
)
5787
})
5888

5989
it.each([providerIdentifiers.openai, providerIdentifiers.ollama, providerIdentifiers.lmstudio])(
6090
"returns an empty default for custom or locally selected models from %s",
6191
(provider) => {
62-
expect(getProviderDefaultModelId(provider)).toBe("")
92+
expect(getProviderDefaultModelId(provider, {})).toBe("")
6393
},
6494
)
6595

6696
it.each([providerIdentifiers.anthropic, providerIdentifiers.geminiCli, providerIdentifiers.fakeAi])(
6797
"preserves the Anthropic fallback for %s",
6898
(provider) => {
69-
expect(getProviderDefaultModelId(provider)).toBe(anthropicDefaultModelId)
99+
expect(getProviderDefaultModelId(provider, {})).toBe(anthropicDefaultModelId)
70100
},
71101
)
72102
})

‎packages/types/src/__tests__/provider-settings.test.ts‎

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
providerSettingsSchemaDiscriminated,
99
} from "../provider-settings.js"
1010
import { OpenAiCodexServiceTier, OpenAiServiceTier } from "../model.js"
11-
import { providerDefinitionList } from "../provider-settings/index.js"
11+
import { providerDefinitionList } from "../providers/index.js"
1212

1313
describe("provider settings discriminated union", () => {
1414
it("composes exactly one provider-specific definition for every provider", () => {
@@ -18,6 +18,16 @@ describe("provider settings discriminated union", () => {
1818
expect(new Set(registeredProviders).size).toBe(providerNames.length)
1919
})
2020

21+
it.each(providerDefinitionList.map((definition) => definition.apiProvider))(
22+
"exposes a default model accessor for %s",
23+
(apiProvider) => {
24+
const definition = providerDefinitionList.find((candidate) => candidate.apiProvider === apiProvider)
25+
26+
expect(typeof definition?.getDefaultModelId).toBe("function")
27+
expect(typeof definition?.getDefaultModelId({})).toBe("string")
28+
},
29+
)
30+
2131
it.each(providerNames)("accepts the %s provider branch", (apiProvider) => {
2232
expect(providerSettingsSchemaDiscriminated.safeParse({ apiProvider }).success).toBe(true)
2333
})

‎packages/types/src/provider-settings.ts‎

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { z } from "zod"
22

3-
import { providerDefinitionList, type ProviderDefinition } from "./provider-settings/index.js"
4-
import { API_PROVIDER_FIELD, SETTINGS_SHAPE_FIELD } from "./provider-settings/common.js"
3+
import { providerDefinitionList, type ProviderDefinition } from "./providers/index.js"
4+
import { API_PROVIDER_FIELD, SETTINGS_SHAPE_FIELD } from "./providers/common.js"
55
export {
66
DEFAULT_OPEN_AI_STRICT_TOOL_SCHEMAS,
77
OPEN_AI_CODEX_SERVICE_TIER_KEY,
@@ -14,7 +14,7 @@ export {
1414
type NanoGptRoutingPreference,
1515
zaiApiLineSchema,
1616
type ZaiApiLine,
17-
} from "./provider-settings/index.js"
17+
} from "./providers/index.js"
1818

1919
import { codebaseIndexProviderSchema } from "./codebase-index.js"
2020
import type { UnionToIntersection } from "./type-fu.js"
@@ -25,6 +25,7 @@ import {
2525
type RetiredProviderIdentifier,
2626
} from "./provider-identifiers.js"
2727
import {
28+
anthropicDefaultModelId,
2829
anthropicModels,
2930
basetenModels,
3031
bedrockModels,
@@ -359,6 +360,14 @@ export function getModelId(settings: ProviderSettings): string | undefined {
359360
return undefined
360361
}
361362

363+
/**
364+
* Get the provider's default model ID, ignoring any configured model selection.
365+
* Used as a fallback while provider models are still loading.
366+
*/
367+
export function getProviderDefaultModelId(provider: ProviderName, settings: ProviderSettings): string {
368+
return providerDefinitions[provider]?.getDefaultModelId(settings) ?? anthropicDefaultModelId
369+
}
370+
362371
/**
363372
* ANTHROPIC_STYLE_PROVIDERS
364373
*/

‎packages/types/src/provider-settings/anthropic.ts‎

Lines changed: 0 additions & 22 deletions
This file was deleted.

‎packages/types/src/provider-settings/baseten.ts‎

Lines changed: 0 additions & 19 deletions
This file was deleted.

‎packages/types/src/provider-settings/bedrock.ts‎

Lines changed: 0 additions & 36 deletions
This file was deleted.

‎packages/types/src/provider-settings/deepseek.ts‎

Lines changed: 0 additions & 20 deletions
This file was deleted.

‎packages/types/src/provider-settings/fireworks.ts‎

Lines changed: 0 additions & 19 deletions
This file was deleted.

0 commit comments

Comments
 (0)