From a51b8ba563598b5b2884cdc6c92cda7bae107eb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rouzbeh=E2=80=A0?= <78313022+rqzbeh@users.noreply.github.com> Date: Sat, 22 Aug 2026 22:22:13 +0330 Subject: [PATCH] fix(cline): use valid modelType/model format for Cline provider models (#11099) (#11132) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cherry-picked the value commit (ac09b6b5) onto the current release tip, dropping the stale base-red sync commits that no longer apply. Focused test cline-model-format-11099 2/2 green; check:provider-consistency OK (267/348/0). Fixes #11099 — the zai→z-ai namespace typo. Thank you @rqzbeh! --- .../config/providers/registry/cline/index.ts | 2 +- tests/unit/cline-model-format-11099.test.ts | 39 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 tests/unit/cline-model-format-11099.test.ts diff --git a/open-sse/config/providers/registry/cline/index.ts b/open-sse/config/providers/registry/cline/index.ts index 21e8c600ed..aecf811f19 100644 --- a/open-sse/config/providers/registry/cline/index.ts +++ b/open-sse/config/providers/registry/cline/index.ts @@ -27,7 +27,7 @@ export const clineProvider: RegistryEntry = { // the official free bucket and text-output models advertised as zero-cost. models: [ { - id: "zai/glm-5.2", + id: "z-ai/glm-5.2", name: "GLM 5.2", toolCalling: true, supportsReasoning: true, diff --git a/tests/unit/cline-model-format-11099.test.ts b/tests/unit/cline-model-format-11099.test.ts new file mode 100644 index 0000000000..3e5a87de43 --- /dev/null +++ b/tests/unit/cline-model-format-11099.test.ts @@ -0,0 +1,39 @@ +import test from "node:test"; +import assert from "node:assert/strict"; + +import { getModelsByProviderId } from "../../open-sse/config/providerModels.ts"; +import { parseClineRecommendedModels } from "../../open-sse/services/clinepassModels.ts"; + +test("#11099: Cline provider catalog model IDs use valid modelType/model format", () => { + const models = getModelsByProviderId("cline"); + assert.ok(models.length > 0, "cline provider must expose models"); + + for (const model of models) { + assert.match( + model.id, + /^[a-z0-9-]+-?[a-z0-9-]*\/[a-z0-9._:-]+$/i, + `Model ID '${model.id}' must follow provider/model format` + ); + assert.notEqual( + model.id.split("/")[0], + "zai", + "Model ID must use 'z-ai' instead of invalid 'zai'" + ); + } +}); + +test("#11099: parseClineRecommendedModels correctly extracts recommended/free models", () => { + const mockPayload = { + recommended: [ + { id: "moonshotai/kimi-k3", name: "kimi-k3" }, + { id: "x-ai/grok-4.5", name: "grok-4.5" }, + ], + free: [{ id: "deepseek/deepseek-v4-flash", name: "deepseek-v4-flash" }], + }; + + const parsed = parseClineRecommendedModels(mockPayload); + assert.equal(parsed.length, 3); + assert.equal(parsed[0].id, "moonshotai/kimi-k3"); + assert.equal(parsed[1].id, "x-ai/grok-4.5"); + assert.equal(parsed[2].id, "deepseek/deepseek-v4-flash"); +});