diff --git a/apps/vscode/webview-ui/src/components/onboarding/__tests__/data-models.test.ts b/apps/vscode/webview-ui/src/components/onboarding/__tests__/data-models.test.ts index 10978dfbd2..90087792bc 100644 --- a/apps/vscode/webview-ui/src/components/onboarding/__tests__/data-models.test.ts +++ b/apps/vscode/webview-ui/src/components/onboarding/__tests__/data-models.test.ts @@ -1,6 +1,6 @@ import type { OnboardingModel, OnboardingModelGroup } from "@shared/proto/cline/state" import { describe, expect, it } from "vitest" -import { getClineUIOnboardingGroups, getRecommendedModelsData } from "../data-models" +import { CLINEPASS_GROUP, getClineUIOnboardingGroups, getRecommendedModelsData } from "../data-models" function model(id: string, group: string): OnboardingModel { return { @@ -22,7 +22,7 @@ describe("getClineUIOnboardingGroups", () => { it("buckets ClinePass models into the clinePass group", () => { const result = getClineUIOnboardingGroups( groupOf([ - model("cline-pass/glm-5.1", "clinepass"), + model("cline-pass/glm-5.1", CLINEPASS_GROUP), model("free-model", "free"), model("anthropic/claude", "frontier"), model("z-ai/glm", "open source"), @@ -30,12 +30,18 @@ describe("getClineUIOnboardingGroups", () => { ) expect(result.clinePass).toHaveLength(1) - expect(result.clinePass[0].group).toBe("clinepass") + expect(result.clinePass[0].group).toBe(CLINEPASS_GROUP) expect(result.clinePass[0].models.map((m) => m.id)).toEqual(["cline-pass/glm-5.1"]) expect(result.free[0].models.map((m) => m.id)).toEqual(["free-model"]) expect(result.power.flatMap((g) => g.models.map((m) => m.id))).toEqual(["anthropic/claude", "z-ai/glm"]) }) + it("does not bucket cline-pass ids without a ClinePass group label", () => { + const result = getClineUIOnboardingGroups(groupOf([model("cline-pass/glm-5.2", "frontier")])) + + expect(result.clinePass).toEqual([]) + }) + it("returns an empty clinePass group when no ClinePass models are present", () => { const result = getClineUIOnboardingGroups(groupOf([model("free-model", "free")])) expect(result.clinePass).toEqual([]) diff --git a/apps/vscode/webview-ui/src/components/onboarding/data-models.ts b/apps/vscode/webview-ui/src/components/onboarding/data-models.ts index dca5624bbd..df986a4ff7 100644 --- a/apps/vscode/webview-ui/src/components/onboarding/data-models.ts +++ b/apps/vscode/webview-ui/src/components/onboarding/data-models.ts @@ -1,6 +1,8 @@ import type { ClineRecommendedModel, OpenRouterModelInfo } from "@shared/proto/cline/models" import type { OnboardingModel, OnboardingModelGroup } from "@shared/proto/cline/state" +export const CLINEPASS_GROUP = "cline-pass" + export interface RecommendedModelsData { recommended: ClineRecommendedModel[] free: ClineRecommendedModel[] @@ -39,16 +41,20 @@ interface ModelGroup { models: OnboardingModel[] } +function isClinePassOnboardingModel(model: OnboardingModel): boolean { + return model.group === CLINEPASS_GROUP +} + export function getClineUIOnboardingGroups(groupedModels: OnboardingModelGroup): OnboardingModelsByGroup { const { models } = groupedModels - const clinePassModels = models.filter((m) => m.group === "clinepass") + const clinePassModels = models.filter(isClinePassOnboardingModel) const freeModels = models.filter((m) => m.group === "free") const frontierModels = models.filter((m) => m.group === "frontier") const openSourceModels = models.filter((m) => m.group === "open source") return { - clinePass: clinePassModels.length > 0 ? [{ group: "clinepass", models: clinePassModels }] : [], + clinePass: clinePassModels.length > 0 ? [{ group: CLINEPASS_GROUP, models: clinePassModels }] : [], free: freeModels.length > 0 ? [{ group: "free", models: freeModels }] : [], power: [ ...(frontierModels.length > 0 ? [{ group: "frontier", models: frontierModels }] : []), diff --git a/apps/vscode/webview-ui/src/components/onboarding/useOnboardingModels.ts b/apps/vscode/webview-ui/src/components/onboarding/useOnboardingModels.ts index e4d796aacb..ccbcb2267d 100644 --- a/apps/vscode/webview-ui/src/components/onboarding/useOnboardingModels.ts +++ b/apps/vscode/webview-ui/src/components/onboarding/useOnboardingModels.ts @@ -8,7 +8,7 @@ import { CLINE_PASS_FEATURE_FLAG } from "@/constants/featureFlags" import { useExtensionState } from "@/context/ExtensionStateContext" import { useHasFeatureFlag } from "@/hooks/useFeatureFlag" import { ModelsServiceClient } from "@/services/grpc-client" -import { getRecommendedModelsData, type RecommendedModelsData } from "./data-models" +import { CLINEPASS_GROUP, getRecommendedModelsData, type RecommendedModelsData } from "./data-models" export type OnboardingModelsStatus = "loading" | "success" | "empty" @@ -107,7 +107,7 @@ export function useOnboardingModels(): UseOnboardingModelsResult { const clinePassCatalog = Object.fromEntries( data.clinePass.map((rec) => [rec.id, resolveClinePassModelInfo(rec.id, openRouterModelsByName)]), ) - const clinePassModels = data.clinePass.map((rec) => toOnboardingModel(rec, "clinepass", "", clinePassCatalog)) + const clinePassModels = data.clinePass.map((rec) => toOnboardingModel(rec, CLINEPASS_GROUP, "", clinePassCatalog)) return { status: "success", models: { models: [...clinePassModels, ...freeModels, ...frontierModels] } } }, [fetchState, modelCatalog, openRouterModelsByName])