Skip to content

Commit 7710513

Browse files
authored
refactor(shared): use canonical profile provider identifiers (#1019)
* refactor(shared): use canonical profile provider identifiers * test(shared): strengthen profile validator coverage * test(shared): avoid mutating provider identifiers * chore(lint): prune profile validator suppressions
1 parent 2db2af0 commit 7710513

3 files changed

Lines changed: 107 additions & 45 deletions

File tree

src/eslint-suppressions.json

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1684,11 +1684,6 @@
16841684
"count": 2
16851685
}
16861686
},
1687-
"shared/__tests__/ProfileValidator.spec.ts": {
1688-
"@typescript-eslint/no-explicit-any": {
1689-
"count": 2
1690-
}
1691-
},
16921687
"shared/__tests__/api.spec.ts": {
16931688
"@typescript-eslint/no-explicit-any": {
16941689
"count": 8

src/shared/ProfileValidator.ts

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { ProviderSettings, OrganizationAllowList } from "@roo-code/types"
1+
import { providerIdentifiers, type ProviderSettings, type OrganizationAllowList } from "@roo-code/types"
22

33
export class ProfileValidator {
44
public static isProfileAllowed(profile: ProviderSettings, allowList: OrganizationAllowList): boolean {
@@ -51,36 +51,36 @@ export class ProfileValidator {
5151

5252
private static getModelIdFromProfile(profile: ProviderSettings): string | undefined {
5353
switch (profile.apiProvider) {
54-
case "openai":
54+
case providerIdentifiers.openai:
5555
return profile.openAiModelId
56-
case "anthropic":
57-
case "openai-native":
58-
case "bedrock":
59-
case "vertex":
60-
case "gemini":
61-
case "mistral":
62-
case "deepseek":
63-
case "xai":
64-
case "sambanova":
65-
case "fireworks":
66-
case "friendli":
56+
case providerIdentifiers.anthropic:
57+
case providerIdentifiers.openaiNative:
58+
case providerIdentifiers.bedrock:
59+
case providerIdentifiers.vertex:
60+
case providerIdentifiers.gemini:
61+
case providerIdentifiers.mistral:
62+
case providerIdentifiers.deepseek:
63+
case providerIdentifiers.xai:
64+
case providerIdentifiers.sambanova:
65+
case providerIdentifiers.fireworks:
66+
case providerIdentifiers.friendli:
6767
return profile.apiModelId
68-
case "litellm":
68+
case providerIdentifiers.litellm:
6969
return profile.litellmModelId
70-
case "lmstudio":
70+
case providerIdentifiers.lmstudio:
7171
return profile.lmStudioModelId
72-
case "vscode-lm":
72+
case providerIdentifiers.vscodeLm:
7373
// We probably need something more flexible for this one, if we need to really support it here.
7474
return profile.vsCodeLmModelSelector?.id
75-
case "openrouter":
75+
case providerIdentifiers.openrouter:
7676
return profile.openRouterModelId
77-
case "ollama":
77+
case providerIdentifiers.ollama:
7878
return profile.ollamaModelId
79-
case "requesty":
79+
case providerIdentifiers.requesty:
8080
return profile.requestyModelId
81-
case "unbound":
81+
case providerIdentifiers.unbound:
8282
return profile.unboundModelId
83-
case "fake-ai":
83+
case providerIdentifiers.fakeAi:
8484
default:
8585
return undefined
8686
}

src/shared/__tests__/ProfileValidator.spec.ts

Lines changed: 86 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,78 @@
11
// npx vitest run src/shared/__tests__/ProfileValidator.spec.ts
22

3-
import type { ProviderSettings, OrganizationAllowList } from "@roo-code/types"
3+
import { providerIdentifiers, type ProviderSettings, type OrganizationAllowList } from "@roo-code/types"
44

55
import { ProfileValidator } from "../ProfileValidator"
66

77
describe("ProfileValidator", () => {
88
describe("isProfileAllowed", () => {
9+
it.each([
10+
["openai", { openAiModelId: "model" }],
11+
["anthropic", { apiModelId: "model" }],
12+
["openaiNative", { apiModelId: "model" }],
13+
["bedrock", { apiModelId: "model" }],
14+
["vertex", { apiModelId: "model" }],
15+
["gemini", { apiModelId: "model" }],
16+
["mistral", { apiModelId: "model" }],
17+
["deepseek", { apiModelId: "model" }],
18+
["xai", { apiModelId: "model" }],
19+
["sambanova", { apiModelId: "model" }],
20+
["fireworks", { apiModelId: "model" }],
21+
["friendli", { apiModelId: "model" }],
22+
["litellm", { litellmModelId: "model" }],
23+
["lmstudio", { lmStudioModelId: "model" }],
24+
["vscodeLm", { vsCodeLmModelSelector: { id: "model" } }],
25+
["openrouter", { openRouterModelId: "model" }],
26+
["ollama", { ollamaModelId: "model" }],
27+
["requesty", { requestyModelId: "model" }],
28+
["unbound", { unboundModelId: "model" }],
29+
])("resolves %s model fields through canonical identifiers", (identifierKey, profileSettings) => {
30+
const canonicalIdentifier = providerIdentifiers[identifierKey as keyof typeof providerIdentifiers]
31+
const modelId = "model"
32+
33+
const profile = {
34+
apiProvider: canonicalIdentifier,
35+
...profileSettings,
36+
} as ProviderSettings
37+
const allowList: OrganizationAllowList = {
38+
allowAll: false,
39+
providers: {
40+
[canonicalIdentifier]: { allowAll: false, models: [modelId] },
41+
},
42+
}
43+
44+
expect(ProfileValidator.isProfileAllowed(profile, allowList)).toBe(true)
45+
46+
const negativeAllowList: OrganizationAllowList = {
47+
allowAll: false,
48+
providers: {
49+
[canonicalIdentifier]: { allowAll: false, models: ["other-model"] },
50+
},
51+
}
52+
53+
expect(ProfileValidator.isProfileAllowed(profile, negativeAllowList)).toBe(false)
54+
})
55+
56+
it.each([
57+
{ providerAllowAll: false, expected: false },
58+
{ providerAllowAll: true, expected: true },
59+
])(
60+
"preserves missing-model fallback behavior when provider allowAll is $providerAllowAll",
61+
({ providerAllowAll, expected }) => {
62+
const profile: ProviderSettings = {
63+
apiProvider: providerIdentifiers.openai,
64+
}
65+
const allowList: OrganizationAllowList = {
66+
allowAll: false,
67+
providers: {
68+
[providerIdentifiers.openai]: { allowAll: providerAllowAll },
69+
},
70+
}
71+
72+
expect(ProfileValidator.isProfileAllowed(profile, allowList)).toBe(expected)
73+
},
74+
)
75+
976
it("should allow any profile when allowAll is true", () => {
1077
const allowList: OrganizationAllowList = {
1178
allowAll: true,
@@ -168,17 +235,17 @@ describe("ProfileValidator", () => {
168235

169236
// Test specific providers that use apiModelId
170237
const apiModelProviders = [
171-
"anthropic",
172-
"openai-native",
173-
"bedrock",
174-
"vertex",
175-
"gemini",
176-
"mistral",
177-
"deepseek",
178-
"xai",
179-
"sambanova",
180-
"fireworks",
181-
"friendli",
238+
providerIdentifiers.anthropic,
239+
providerIdentifiers.openaiNative,
240+
providerIdentifiers.bedrock,
241+
providerIdentifiers.vertex,
242+
providerIdentifiers.gemini,
243+
providerIdentifiers.mistral,
244+
providerIdentifiers.deepseek,
245+
providerIdentifiers.xai,
246+
providerIdentifiers.sambanova,
247+
providerIdentifiers.fireworks,
248+
providerIdentifiers.friendli,
182249
]
183250

184251
apiModelProviders.forEach((provider) => {
@@ -190,7 +257,7 @@ describe("ProfileValidator", () => {
190257
},
191258
}
192259
const profile: ProviderSettings = {
193-
apiProvider: provider as any, // Type assertion needed here
260+
apiProvider: provider,
194261
apiModelId: "test-model",
195262
}
196263

@@ -203,11 +270,11 @@ describe("ProfileValidator", () => {
203270
const allowList: OrganizationAllowList = {
204271
allowAll: false,
205272
providers: {
206-
litellm: { allowAll: false, models: ["test-model"] },
273+
[providerIdentifiers.litellm]: { allowAll: false, models: ["test-model"] },
207274
},
208275
}
209276
const profile: ProviderSettings = {
210-
apiProvider: "litellm" as any,
277+
apiProvider: providerIdentifiers.litellm,
211278
litellmModelId: "test-model",
212279
}
213280

@@ -218,11 +285,11 @@ describe("ProfileValidator", () => {
218285
const allowList: OrganizationAllowList = {
219286
allowAll: false,
220287
providers: {
221-
"vscode-lm": { allowAll: false, models: ["copilot-gpt-3.5"] },
288+
[providerIdentifiers.vscodeLm]: { allowAll: false, models: ["copilot-gpt-3.5"] },
222289
},
223290
}
224291
const profile: ProviderSettings = {
225-
apiProvider: "vscode-lm",
292+
apiProvider: providerIdentifiers.vscodeLm,
226293
vsCodeLmModelSelector: { id: "copilot-gpt-3.5" },
227294
}
228295

@@ -278,11 +345,11 @@ describe("ProfileValidator", () => {
278345
const allowList: OrganizationAllowList = {
279346
allowAll: false,
280347
providers: {
281-
"fake-ai": { allowAll: false },
348+
[providerIdentifiers.fakeAi]: { allowAll: false },
282349
},
283350
}
284351
const profile: ProviderSettings = {
285-
apiProvider: "fake-ai",
352+
apiProvider: providerIdentifiers.fakeAi,
286353
}
287354

288355
expect(ProfileValidator.isProfileAllowed(profile, allowList)).toBe(false)

0 commit comments

Comments
 (0)