From c9775366f9b5c911344ac131e84d6d2de6e735bd Mon Sep 17 00:00:00 2001 From: Dizzle <112548150+maxmad64bis@users.noreply.github.com> Date: Sat, 22 Aug 2026 01:55:21 +0200 Subject: [PATCH] refactor(providers): dedupe identical opencode-zen/opencode-go model entries (#11051) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ⭐5 — Dedupe dos 3 entries byte-idênticos (kimi-k2.7-code, qwen3.5-plus, qwen3.6-plus) entre opencode-zen e opencode-go via OPENCODE_ZEN_GO_SHARED_MODELS (padrão GLM_SHARED_MODELS), frozen e testado por deep-equal. Pure move, sem mudança de comportamento; check:provider-consistency OK (267 entries, 348 providers). TDD 3/3. Follow-up de #11049/#11048. Base-red #9985 inherited. --- open-sse/config/opencodeZenGoSharedModels.ts | 16 ++++++++++++ .../providers/registry/opencode/go/index.ts | 9 ++++--- .../providers/registry/opencode/zen/index.ts | 9 ++++--- open-sse/config/providers/shared.ts | 2 ++ .../opencode-zen-go-shared-models.test.ts | 26 +++++++++++++++++++ 5 files changed, 56 insertions(+), 6 deletions(-) create mode 100644 open-sse/config/opencodeZenGoSharedModels.ts create mode 100644 tests/unit/opencode-zen-go-shared-models.test.ts diff --git a/open-sse/config/opencodeZenGoSharedModels.ts b/open-sse/config/opencodeZenGoSharedModels.ts new file mode 100644 index 0000000000..9f9d6628e9 --- /dev/null +++ b/open-sse/config/opencodeZenGoSharedModels.ts @@ -0,0 +1,16 @@ +/** + * Models declared identically in both the `opencode-zen` and `opencode-go` provider + * registries (same upstream family, opencode.ai/zen/*). Mirrors the GLM_SHARED_MODELS + * pattern in glmProvider.ts: one array, spread into each sibling RegistryEntry, so a + * metadata fix (targetFormat, supportsReasoning, ...) only has to land in one file + * instead of drifting out of sync across registries. + * + * Only entries that are byte-identical across both registries belong here — a model + * with tier-specific flags (e.g. go's effort variants, or a flag only one tier needs) + * stays local to that registry's own `models` array. + */ +export const OPENCODE_ZEN_GO_SHARED_MODELS = Object.freeze([ + { id: "kimi-k2.7-code", name: "Kimi K2.7 Code" }, + { id: "qwen3.5-plus", name: "Qwen3.5 Plus", targetFormat: "claude", supportsVision: false }, + { id: "qwen3.6-plus", name: "Qwen3.6 Plus", targetFormat: "claude", supportsVision: false }, +]); diff --git a/open-sse/config/providers/registry/opencode/go/index.ts b/open-sse/config/providers/registry/opencode/go/index.ts index e0ab4a05f5..14304426c5 100644 --- a/open-sse/config/providers/registry/opencode/go/index.ts +++ b/open-sse/config/providers/registry/opencode/go/index.ts @@ -1,4 +1,5 @@ import type { RegistryEntry } from "../../../shared.ts"; +import { OPENCODE_ZEN_GO_SHARED_MODELS } from "../../../shared.ts"; export const opencode_goProvider: RegistryEntry = { id: "opencode-go", @@ -13,6 +14,8 @@ export const opencode_goProvider: RegistryEntry = { authPrefix: "Bearer", defaultContextLength: 200000, models: [ + ...OPENCODE_ZEN_GO_SHARED_MODELS, + // Port from decolua/9router 8efacc11: align with official Go endpoints — // glm-5.2 is now advertised and Kimi chat traffic must route through // `kimi-k2.7-code` (the live API rejects the plain `kimi-k2.7` alias for @@ -25,7 +28,7 @@ export const opencode_goProvider: RegistryEntry = { { id: "glm-5.2-max", name: "GLM-5.2 (max effort)", supportsReasoning: true }, { id: "glm-5.1", name: "GLM-5.1" }, { id: "glm-5", name: "GLM-5" }, - { id: "kimi-k2.7-code", name: "Kimi K2.7 Code" }, + // kimi-k2.7-code declared identically on opencode-zen — see OPENCODE_ZEN_GO_SHARED_MODELS. { id: "kimi-k2.6", name: "Kimi K2.6" }, { id: "kimi-k2.5", name: "Kimi K2.5" }, // #8353: Kimi K3 base + max-effort alias from the OpenCode Go registry. @@ -89,7 +92,8 @@ export const opencode_goProvider: RegistryEntry = { supportsVision: false, supportsReasoning: true, }, - { id: "qwen3.6-plus", name: "Qwen3.6 Plus", targetFormat: "claude", supportsVision: false }, + // qwen3.6-plus / qwen3.5-plus base ids declared identically on opencode-zen — see + // OPENCODE_ZEN_GO_SHARED_MODELS. { id: "qwen3.6-plus-high", name: "Qwen3.6 Plus (high effort)", @@ -104,7 +108,6 @@ export const opencode_goProvider: RegistryEntry = { supportsVision: false, supportsReasoning: true, }, - { id: "qwen3.5-plus", name: "Qwen3.5 Plus", targetFormat: "claude", supportsVision: false }, // #8353: hy3 is the Go-tier base id (distinct from hy3-preview / hy3-free). { id: "hy3", name: "Hunyuan3", contextLength: 256000, supportsReasoning: true }, { diff --git a/open-sse/config/providers/registry/opencode/zen/index.ts b/open-sse/config/providers/registry/opencode/zen/index.ts index fb53b90a62..76b3811e39 100644 --- a/open-sse/config/providers/registry/opencode/zen/index.ts +++ b/open-sse/config/providers/registry/opencode/zen/index.ts @@ -1,4 +1,5 @@ import type { RegistryEntry } from "../../../shared.ts"; +import { OPENCODE_ZEN_GO_SHARED_MODELS } from "../../../shared.ts"; export const opencode_zenProvider: RegistryEntry = { id: "opencode-zen", @@ -15,6 +16,8 @@ export const opencode_zenProvider: RegistryEntry = { // from the live API response so new models work without a code deploy. passthroughModels: true, models: [ + ...OPENCODE_ZEN_GO_SHARED_MODELS, + // ── Chat / Coding ────────────────────────────────────────── // #2900: big-pickle's upstream runs DeepSeek thinking mode — declare the // interleaved reasoning_content contract so follow-up/tool-use turns replay @@ -84,7 +87,7 @@ export const opencode_zenProvider: RegistryEntry = { // ── Kimi / Moonshot ──────────────────────────────────────── { id: "kimi-k3", name: "Kimi K3" }, - { id: "kimi-k2.7-code", name: "Kimi K2.7 Code" }, + // kimi-k2.7-code declared identically on opencode-go — see OPENCODE_ZEN_GO_SHARED_MODELS. // ── Qwen ─────────────────────────────────────────────────── // Issue #2292: Qwen models return Claude-format SSE bodies even @@ -92,8 +95,8 @@ export const opencode_zenProvider: RegistryEntry = { // through /messages and the Claude translator. // Issue #2822: These models are text-only — supportsVision: false // ensures combo routing skips them on image-bearing requests. - { id: "qwen3.5-plus", name: "Qwen3.5 Plus", targetFormat: "claude", supportsVision: false }, - { id: "qwen3.6-plus", name: "Qwen3.6 Plus", targetFormat: "claude", supportsVision: false }, + // qwen3.5-plus / qwen3.6-plus declared identically on opencode-go — see + // OPENCODE_ZEN_GO_SHARED_MODELS. // ── Free Tier ────────────────────────────────────────────── // #6998 (2026-07-14): upstream free tier rotated — minimax-m2.5-free, diff --git a/open-sse/config/providers/shared.ts b/open-sse/config/providers/shared.ts index d87250644d..62909a528d 100644 --- a/open-sse/config/providers/shared.ts +++ b/open-sse/config/providers/shared.ts @@ -25,6 +25,7 @@ import { GLMT_TIMEOUT_MS, GLM_SHARED_MODELS, } from "../glmProvider.ts"; +import { OPENCODE_ZEN_GO_SHARED_MODELS } from "../opencodeZenGoSharedModels.ts"; import { MARITALK_DEFAULT_BASE_URL } from "../maritalk.ts"; import { CURSOR_REGISTRY_VERSION, @@ -719,6 +720,7 @@ export { GLM_TIMEOUT_MS, GLMT_TIMEOUT_MS, GLM_SHARED_MODELS, + OPENCODE_ZEN_GO_SHARED_MODELS, MARITALK_DEFAULT_BASE_URL, CURSOR_REGISTRY_VERSION, getAntigravityProviderHeaders, diff --git a/tests/unit/opencode-zen-go-shared-models.test.ts b/tests/unit/opencode-zen-go-shared-models.test.ts new file mode 100644 index 0000000000..8c3079ad15 --- /dev/null +++ b/tests/unit/opencode-zen-go-shared-models.test.ts @@ -0,0 +1,26 @@ +import assert from "node:assert/strict"; +import test from "node:test"; + +import { OPENCODE_ZEN_GO_SHARED_MODELS } from "../../open-sse/config/opencodeZenGoSharedModels.ts"; +import { opencode_zenProvider } from "../../open-sse/config/providers/registry/opencode/zen/index.ts"; +import { opencode_goProvider } from "../../open-sse/config/providers/registry/opencode/go/index.ts"; + +test("every OPENCODE_ZEN_GO_SHARED_MODELS entry is present, unmodified, exactly once in opencode-zen", () => { + for (const shared of OPENCODE_ZEN_GO_SHARED_MODELS) { + const matches = opencode_zenProvider.models.filter((m) => m.id === shared.id); + assert.equal(matches.length, 1, `${shared.id} must appear exactly once in opencode-zen`); + assert.deepEqual(matches[0], shared, `${shared.id} must match the shared definition exactly`); + } +}); + +test("every OPENCODE_ZEN_GO_SHARED_MODELS entry is present, unmodified, exactly once in opencode-go", () => { + for (const shared of OPENCODE_ZEN_GO_SHARED_MODELS) { + const matches = opencode_goProvider.models.filter((m) => m.id === shared.id); + assert.equal(matches.length, 1, `${shared.id} must appear exactly once in opencode-go`); + assert.deepEqual(matches[0], shared, `${shared.id} must match the shared definition exactly`); + } +}); + +test("OPENCODE_ZEN_GO_SHARED_MODELS is frozen (no accidental cross-registry mutation)", () => { + assert.ok(Object.isFrozen(OPENCODE_ZEN_GO_SHARED_MODELS)); +});