Skip to content

Commit d25f8b7

Browse files
committed
refactor(api): use canonical provider identifiers
1 parent d5a8c4a commit d25f8b7

2 files changed

Lines changed: 93 additions & 37 deletions

File tree

src/api/__tests__/index.spec.ts

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// npx vitest run src/api/__tests__/index.spec.ts
22

3+
import fs from "node:fs"
4+
35
// Mock vscode first to avoid import errors
46
vitest.mock("vscode", () => ({
57
workspace: {
@@ -9,15 +11,22 @@ vitest.mock("vscode", () => ({
911
},
1012
}))
1113

12-
import type { ProviderSettings } from "@roo-code/types"
14+
import {
15+
providerIdentifiers,
16+
retiredProviderIdentifiers,
17+
type ProviderSettings,
18+
type ProviderNameWithRetired,
19+
} from "@roo-code/types"
1320

1421
import { buildApiHandler } from "../index"
22+
import { AnthropicHandler } from "../providers/anthropic"
1523
import { KenariHandler } from "../providers/kenari"
24+
import { OpenRouterHandler } from "../providers/openrouter"
1625

1726
describe("buildApiHandler", () => {
1827
it("returns a KenariHandler for the kenari provider", () => {
1928
const configuration: ProviderSettings = {
20-
apiProvider: "kenari",
29+
apiProvider: providerIdentifiers.kenari,
2130
kenariApiKey: "test-key",
2231
kenariModelId: "glm-5-2",
2332
}
@@ -26,4 +35,45 @@ describe("buildApiHandler", () => {
2635

2736
expect(handler).toBeInstanceOf(KenariHandler)
2837
})
38+
39+
it.each([
40+
[providerIdentifiers.anthropic, AnthropicHandler],
41+
[providerIdentifiers.openrouter, OpenRouterHandler],
42+
] as const)("returns the expected handler for %s", (apiProvider, Handler) => {
43+
const handler = buildApiHandler({ apiProvider })
44+
45+
expect(handler).toBeInstanceOf(Handler)
46+
})
47+
48+
it("preserves the dedicated removal error for the retired Roo provider", () => {
49+
expect(() =>
50+
buildApiHandler({
51+
apiProvider: retiredProviderIdentifiers.roo,
52+
}),
53+
).toThrow("Roo Code Router has been removed")
54+
})
55+
56+
it("rejects other retired providers", () => {
57+
expect(() =>
58+
buildApiHandler({
59+
apiProvider: retiredProviderIdentifiers.cerebras,
60+
}),
61+
).toThrow("this provider is no longer supported")
62+
})
63+
64+
it("falls back to Anthropic for an unsupported provider value", () => {
65+
const handler = buildApiHandler({
66+
apiProvider: "unsupported-provider" as ProviderNameWithRetired,
67+
})
68+
69+
expect(handler).toBeInstanceOf(AnthropicHandler)
70+
})
71+
72+
it("uses canonical identifiers instead of provider literals in the handler factory", () => {
73+
const factorySource = fs.readFileSync(new URL("../index.ts", import.meta.url), "utf8")
74+
75+
expect(factorySource).toContain("providerIdentifiers.anthropic")
76+
expect(factorySource).toContain("retiredProviderIdentifiers.roo")
77+
expect(factorySource).not.toMatch(/case\s+["']/)
78+
})
2979
})

src/api/index.ts

Lines changed: 41 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
import { Anthropic } from "@anthropic-ai/sdk"
22
import OpenAI from "openai"
33

4-
import { isRetiredProvider, type ProviderSettings, type ModelInfo } from "@roo-code/types"
4+
import {
5+
isRetiredProvider,
6+
providerIdentifiers,
7+
retiredProviderIdentifiers,
8+
type ProviderSettings,
9+
type ModelInfo,
10+
} from "@roo-code/types"
511

612
import { getRouterRemovalMessage } from "../core/config/routerRemoval"
713
import { ApiStream } from "./transform/stream"
@@ -140,7 +146,7 @@ export interface ApiHandler {
140146
export function buildApiHandler(configuration: ProviderSettings): ApiHandler {
141147
const { apiProvider, ...options } = configuration
142148

143-
if (apiProvider === "roo") {
149+
if (apiProvider === retiredProviderIdentifiers.roo) {
144150
throw new Error(getRouterRemovalMessage())
145151
}
146152

@@ -151,73 +157,73 @@ export function buildApiHandler(configuration: ProviderSettings): ApiHandler {
151157
}
152158

153159
switch (apiProvider) {
154-
case "anthropic":
160+
case providerIdentifiers.anthropic:
155161
return new AnthropicHandler(options)
156-
case "openrouter":
162+
case providerIdentifiers.openrouter:
157163
return new OpenRouterHandler(options)
158-
case "bedrock":
164+
case providerIdentifiers.bedrock:
159165
return new AwsBedrockHandler(options)
160-
case "vertex":
166+
case providerIdentifiers.vertex:
161167
return options.apiModelId?.startsWith("claude")
162168
? new AnthropicVertexHandler(options)
163169
: new VertexHandler(options)
164-
case "openai":
170+
case providerIdentifiers.openai:
165171
return new OpenAiHandler(options)
166-
case "ollama":
172+
case providerIdentifiers.ollama:
167173
return new NativeOllamaHandler(options)
168-
case "lmstudio":
174+
case providerIdentifiers.lmstudio:
169175
return new LmStudioHandler(options)
170-
case "gemini":
176+
case providerIdentifiers.gemini:
171177
return new GeminiHandler(options)
172-
case "openai-codex":
178+
case providerIdentifiers.openaiCodex:
173179
return new OpenAiCodexHandler(options)
174-
case "openai-native":
180+
case providerIdentifiers.openaiNative:
175181
return new OpenAiNativeHandler(options)
176-
case "deepseek":
182+
case providerIdentifiers.deepseek:
177183
return new DeepSeekHandler(options)
178-
case "qwen-code":
184+
case providerIdentifiers.qwenCode:
179185
return new QwenCodeHandler(options)
180-
case "moonshot":
186+
case providerIdentifiers.moonshot:
181187
return new MoonshotHandler(options)
182-
case "kimi-code":
188+
case providerIdentifiers.kimiCode:
183189
return new KimiCodeHandler(options)
184-
case "vscode-lm":
190+
case providerIdentifiers.vscodeLm:
185191
return new VsCodeLmHandler(options)
186-
case "mistral":
192+
case providerIdentifiers.mistral:
187193
return new MistralHandler(options)
188-
case "requesty":
194+
case providerIdentifiers.requesty:
189195
return new RequestyHandler(options)
190-
case "unbound":
196+
case providerIdentifiers.unbound:
191197
return new UnboundHandler(options)
192-
case "fake-ai":
198+
case providerIdentifiers.fakeAi:
193199
return new FakeAIHandler(options)
194-
case "xai":
200+
case providerIdentifiers.xai:
195201
return new XAIHandler(options)
196-
case "litellm":
202+
case providerIdentifiers.litellm:
197203
return new LiteLLMHandler(options)
198-
case "sambanova":
204+
case providerIdentifiers.sambanova:
199205
return new SambaNovaHandler(options)
200-
case "mimo":
206+
case providerIdentifiers.mimo:
201207
return new MimoHandler(options)
202-
case "zai":
208+
case providerIdentifiers.zai:
203209
return new ZAiHandler(options)
204-
case "fireworks":
210+
case providerIdentifiers.fireworks:
205211
return new FireworksHandler(options)
206-
case "friendli":
212+
case providerIdentifiers.friendli:
207213
return new FriendliHandler(options)
208-
case "vercel-ai-gateway":
214+
case providerIdentifiers.vercelAiGateway:
209215
return new VercelAiGatewayHandler(options)
210-
case "opencode-go":
216+
case providerIdentifiers.opencodeGo:
211217
return new OpencodeGoHandler(options)
212-
case "kenari":
218+
case providerIdentifiers.kenari:
213219
return new KenariHandler(options)
214-
case "zoo-gateway":
220+
case providerIdentifiers.zooGateway:
215221
return new ZooGatewayHandler(options)
216-
case "minimax":
222+
case providerIdentifiers.minimax:
217223
return new MiniMaxHandler(options)
218-
case "baseten":
224+
case providerIdentifiers.baseten:
219225
return new BasetenHandler(options)
220-
case "poe":
226+
case providerIdentifiers.poe:
221227
return new PoeHandler(options)
222228
default:
223229
return new AnthropicHandler(options)

0 commit comments

Comments
 (0)