Skip to content

Commit c24a8c5

Browse files
authored
feat(types): centralize provider identifiers (#952)
1 parent a7d7968 commit c24a8c5

4 files changed

Lines changed: 192 additions & 37 deletions

File tree

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import {
2+
isProviderName,
3+
isRetiredProvider,
4+
providerIdentifiers,
5+
providerNames,
6+
providerNamesSchema,
7+
providerNamesWithRetiredSchema,
8+
retiredProviderIdentifiers,
9+
retiredProviderNames,
10+
retiredProviderNamesSchema,
11+
} from "../index.js"
12+
13+
const expectedProviderIdentifiers = [
14+
"openrouter",
15+
"vercel-ai-gateway",
16+
"zoo-gateway",
17+
"litellm",
18+
"requesty",
19+
"unbound",
20+
"poe",
21+
"deepseek",
22+
"opencode-go",
23+
"kenari",
24+
"ollama",
25+
"lmstudio",
26+
"vscode-lm",
27+
"openai",
28+
"fake-ai",
29+
"anthropic",
30+
"bedrock",
31+
"baseten",
32+
"fireworks",
33+
"friendli",
34+
"gemini",
35+
"gemini-cli",
36+
"mistral",
37+
"moonshot",
38+
"minimax",
39+
"mimo",
40+
"openai-codex",
41+
"openai-native",
42+
"qwen-code",
43+
"sambanova",
44+
"vertex",
45+
"xai",
46+
"zai",
47+
]
48+
49+
const expectedRetiredProviderIdentifiers = [
50+
"cerebras",
51+
"chutes",
52+
"deepinfra",
53+
"doubao",
54+
"featherless",
55+
"groq",
56+
"huggingface",
57+
"io-intelligence",
58+
"roo",
59+
]
60+
61+
describe("provider identifiers", () => {
62+
it("preserves active provider serialized values", () => {
63+
const identifiers = Object.values(providerIdentifiers)
64+
65+
expect(identifiers).toEqual(expectedProviderIdentifiers)
66+
expect(new Set(identifiers).size).toBe(identifiers.length)
67+
})
68+
69+
it("preserves retired provider serialized values", () => {
70+
const identifiers = Object.values(retiredProviderIdentifiers)
71+
72+
expect(identifiers).toEqual(expectedRetiredProviderIdentifiers)
73+
expect(new Set(identifiers).size).toBe(identifiers.length)
74+
})
75+
76+
it("preserves provider-settings compatibility exports", () => {
77+
const identifiers = Object.values(providerIdentifiers)
78+
const retiredIdentifiers = Object.values(retiredProviderIdentifiers)
79+
80+
expect(providerNames).toEqual(identifiers)
81+
expect(retiredProviderNames).toEqual(retiredIdentifiers)
82+
})
83+
84+
it("keeps active and retired providers separate", () => {
85+
const activeIdentifiers = new Set<string>(Object.values(providerIdentifiers))
86+
const retiredIdentifiers = Object.values(retiredProviderIdentifiers)
87+
88+
expect(retiredIdentifiers.every((identifier) => !activeIdentifiers.has(identifier))).toBe(true)
89+
})
90+
91+
it("derives runtime validation from the canonical registries", () => {
92+
for (const identifier of expectedProviderIdentifiers) {
93+
expect(providerNamesSchema.safeParse(identifier).success).toBe(true)
94+
expect(providerNamesWithRetiredSchema.safeParse(identifier).success).toBe(true)
95+
}
96+
97+
for (const identifier of expectedRetiredProviderIdentifiers) {
98+
expect(providerNamesSchema.safeParse(identifier).success).toBe(false)
99+
expect(retiredProviderNamesSchema.safeParse(identifier).success).toBe(true)
100+
expect(providerNamesWithRetiredSchema.safeParse(identifier).success).toBe(true)
101+
}
102+
103+
expect(providerNamesSchema.safeParse("unknown-provider").success).toBe(false)
104+
expect(retiredProviderNamesSchema.safeParse("unknown-provider").success).toBe(false)
105+
expect(providerNamesWithRetiredSchema.safeParse("unknown-provider").success).toBe(false)
106+
})
107+
108+
it("preserves provider-settings type guards", () => {
109+
for (const identifier of expectedProviderIdentifiers) {
110+
expect(isProviderName(identifier)).toBe(true)
111+
expect(isRetiredProvider(identifier)).toBe(false)
112+
}
113+
114+
for (const identifier of expectedRetiredProviderIdentifiers) {
115+
expect(isProviderName(identifier)).toBe(false)
116+
expect(isRetiredProvider(identifier)).toBe(true)
117+
}
118+
119+
expect(isProviderName("unknown-provider")).toBe(false)
120+
expect(isProviderName(undefined)).toBe(false)
121+
expect(isRetiredProvider("unknown-provider")).toBe(false)
122+
})
123+
})

packages/types/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export * from "./mcp.js"
1818
export * from "./message.js"
1919
export * from "./mode.js"
2020
export * from "./model.js"
21+
export * from "./provider-identifiers.js"
2122
export * from "./provider-settings.js"
2223
export * from "./task.js"
2324
export * from "./todo.js"
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/**
2+
* Canonical provider identifiers.
3+
*
4+
* Values in this registry are persisted in settings and must remain stable.
5+
*/
6+
export const providerIdentifiers = {
7+
openrouter: "openrouter",
8+
vercelAiGateway: "vercel-ai-gateway",
9+
zooGateway: "zoo-gateway",
10+
litellm: "litellm",
11+
requesty: "requesty",
12+
unbound: "unbound",
13+
poe: "poe",
14+
deepseek: "deepseek",
15+
opencodeGo: "opencode-go",
16+
kenari: "kenari",
17+
ollama: "ollama",
18+
lmstudio: "lmstudio",
19+
vscodeLm: "vscode-lm",
20+
openai: "openai",
21+
fakeAi: "fake-ai",
22+
anthropic: "anthropic",
23+
bedrock: "bedrock",
24+
baseten: "baseten",
25+
fireworks: "fireworks",
26+
friendli: "friendli",
27+
gemini: "gemini",
28+
geminiCli: "gemini-cli",
29+
mistral: "mistral",
30+
moonshot: "moonshot",
31+
minimax: "minimax",
32+
mimo: "mimo",
33+
openaiCodex: "openai-codex",
34+
openaiNative: "openai-native",
35+
qwenCode: "qwen-code",
36+
sambanova: "sambanova",
37+
vertex: "vertex",
38+
xai: "xai",
39+
zai: "zai",
40+
} as const
41+
42+
export type ProviderIdentifier = (typeof providerIdentifiers)[keyof typeof providerIdentifiers]
43+
44+
/** Provider identifiers retained only for compatibility with existing settings. */
45+
export const retiredProviderIdentifiers = {
46+
cerebras: "cerebras",
47+
chutes: "chutes",
48+
deepinfra: "deepinfra",
49+
doubao: "doubao",
50+
featherless: "featherless",
51+
groq: "groq",
52+
huggingface: "huggingface",
53+
ioIntelligence: "io-intelligence",
54+
roo: "roo",
55+
} as const
56+
57+
export type RetiredProviderIdentifier = (typeof retiredProviderIdentifiers)[keyof typeof retiredProviderIdentifiers]

packages/types/src/provider-settings.ts

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

33
import { modelInfoSchema, reasoningEffortSettingSchema, verbosityLevelsSchema, serviceTierSchema } from "./model.js"
44
import { codebaseIndexProviderSchema } from "./codebase-index.js"
5+
import {
6+
providerIdentifiers,
7+
retiredProviderIdentifiers,
8+
type ProviderIdentifier,
9+
type RetiredProviderIdentifier,
10+
} from "./provider-identifiers.js"
511
import {
612
anthropicModels,
713
basetenModels,
@@ -111,32 +117,7 @@ export const isFauxProvider = (key: string): key is FauxProvider => fauxProvider
111117
* ProviderName
112118
*/
113119

114-
export const providerNames = [
115-
...dynamicProviders,
116-
...localProviders,
117-
...internalProviders,
118-
...customProviders,
119-
...fauxProviders,
120-
"anthropic",
121-
"bedrock",
122-
"baseten",
123-
"deepseek",
124-
"fireworks",
125-
"friendli",
126-
"gemini",
127-
"gemini-cli",
128-
"mistral",
129-
"moonshot",
130-
"minimax",
131-
"mimo",
132-
"openai-codex",
133-
"openai-native",
134-
"qwen-code",
135-
"sambanova",
136-
"vertex",
137-
"xai",
138-
"zai",
139-
] as const
120+
export const providerNames = Object.values(providerIdentifiers) as [ProviderIdentifier, ...ProviderIdentifier[]]
140121

141122
export const providerNamesSchema = z.enum(providerNames)
142123

@@ -149,17 +130,10 @@ export const isProviderName = (key: unknown): key is ProviderName =>
149130
* RetiredProviderName
150131
*/
151132

152-
export const retiredProviderNames = [
153-
"cerebras",
154-
"chutes",
155-
"deepinfra",
156-
"doubao",
157-
"featherless",
158-
"groq",
159-
"huggingface",
160-
"io-intelligence",
161-
"roo",
162-
] as const
133+
export const retiredProviderNames = Object.values(retiredProviderIdentifiers) as [
134+
RetiredProviderIdentifier,
135+
...RetiredProviderIdentifier[],
136+
]
163137

164138
export const retiredProviderNamesSchema = z.enum(retiredProviderNames)
165139

0 commit comments

Comments
 (0)