From 599c10b048ac463caf020588ac59e15c83a00fda Mon Sep 17 00:00:00 2001 From: Diego Rodrigues de Sa e Souza <8016841+diegosouzapw@users.noreply.github.com> Date: Tue, 16 Jun 2026 16:36:42 -0300 Subject: [PATCH] fix(sse): guard model-less registry entries in getUnsupportedParams (mimocode) (#4015) Real bugfix: guard model-less registry entries (mimocode) in getUnsupportedParams so handleChatCore no longer throws 'entry.models is not iterable' / reports 'All models failed' for unrelated requests. Includes a regression test. Fast QG green. --- open-sse/config/providerRegistry.ts | 5 ++-- .../provider-registry-models-guard.test.ts | 23 +++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 tests/unit/provider-registry-models-guard.test.ts diff --git a/open-sse/config/providerRegistry.ts b/open-sse/config/providerRegistry.ts index f300f022aa..85403fdec9 100644 --- a/open-sse/config/providerRegistry.ts +++ b/open-sse/config/providerRegistry.ts @@ -189,7 +189,8 @@ function ensureUnsupportedParamsPopulated(): void { if (_unsupportedParamsPopulated) return; _unsupportedParamsPopulated = true; for (const entry of Object.values(REGISTRY)) { - for (const model of entry.models) { + // Some entries (e.g. the `mimocode` proxy) legitimately have no model catalogue. + for (const model of entry.models ?? []) { if (model.unsupportedParams && !_unsupportedParamsMap.has(model.id)) { _unsupportedParamsMap.set(model.id, model.unsupportedParams); } @@ -207,7 +208,7 @@ export function getUnsupportedParams(provider: string, modelId: string): readonl ensureUnsupportedParamsPopulated(); // 1. Check current provider's registry (exact match) const entry = getRegistryEntry(provider); - const modelEntry = entry?.models.find((m) => m.id === modelId); + const modelEntry = entry?.models?.find((m) => m.id === modelId); if (modelEntry?.unsupportedParams) return modelEntry.unsupportedParams; // 2. O(1) lookup in precomputed map (handles cross-provider routing) diff --git a/tests/unit/provider-registry-models-guard.test.ts b/tests/unit/provider-registry-models-guard.test.ts new file mode 100644 index 0000000000..fccef44235 --- /dev/null +++ b/tests/unit/provider-registry-models-guard.test.ts @@ -0,0 +1,23 @@ +import { test } from "node:test"; +import assert from "node:assert/strict"; +import { getUnsupportedParams } from "../../open-sse/config/providerRegistry.ts"; + +// Regression guard for `TypeError: entry.models is not iterable`. +// +// A registry entry can legitimately have no static model catalogue — e.g. the +// `mimocode` proxy provider, whose `models` is `undefined`. The byModelId map +// builder already tolerates this (`if (entry.models && entry.models.length > 0)`), +// but `getUnsupportedParams` had two unguarded accesses: +// - `ensureUnsupportedParamsPopulated()` iterated `entry.models` for EVERY entry, +// - the per-provider lookup did `entry?.models.find(...)`. +// Either one threw on the first call once a model-less entry existed, which made +// `handleChatCore` report "All models failed" for unrelated requests. + +test("getUnsupportedParams does not throw when a registry entry has no models (mimocode regression)", () => { + // This call triggers ensureUnsupportedParamsPopulated() which walks ALL entries. + assert.doesNotThrow(() => getUnsupportedParams("openai", "gpt-4o")); +}); + +test("getUnsupportedParams returns [] for a model-less proxy provider", () => { + assert.deepEqual(getUnsupportedParams("mimocode", "anything"), []); +});