From 8cf5b474e86e2958bf302ccaed884b1c1d31d421 Mon Sep 17 00:00:00 2001 From: Dingding-leo <193228693+Dingding-leo@users.noreply.github.com> Date: Tue, 28 Jul 2026 02:17:05 +0930 Subject: [PATCH 1/2] fix(open-sse): filter non-numeric values in comboTargetLimits before min calculation When combo targets are passed as objects, Array.prototype.map can yield undefined or non-number elements, causing Math.min to evaluate to NaN and logging 'Failed to resolve combo limits for compression: TypeError: Cannot read properties of undefined'. This fix ensures comboTargetLimits are filtered to valid numbers before calling resolveComboContextLimit and adds defense-in-depth in resolveComboContextLimit. --- open-sse/handlers/chatCore.ts | 21 +++++++++++++-------- tests/unit/resolveComboContextLimit.test.ts | 21 +++++++++++++++++++++ 2 files changed, 34 insertions(+), 8 deletions(-) create mode 100644 tests/unit/resolveComboContextLimit.test.ts diff --git a/open-sse/handlers/chatCore.ts b/open-sse/handlers/chatCore.ts index 941a5e9b4541..8a4282d040c5 100644 --- a/open-sse/handlers/chatCore.ts +++ b/open-sse/handlers/chatCore.ts @@ -1705,14 +1705,19 @@ export async function handleChatCore({ comboConfig as unknown as { name: string; models: unknown[] }, allCombosData as unknown as { name: string; models: unknown[] }[] ); - comboTargetLimits = targets.map((t: { modelStr?: string; provider?: string }) => - // Fall back to ResolvedComboTarget.provider when modelStr lacks a - // provider/ prefix — parseModel alone returns provider:null (#8716). - getComboTargetTokenLimit({ - modelStr: t.modelStr, - provider: t.provider, - }) - ); + comboTargetLimits = targets + .map((t: { modelStr?: string; provider?: string }) => + // Fall back to ResolvedComboTarget.provider when modelStr lacks a + // provider/ prefix — parseModel alone returns provider:null (#8716). + getComboTargetTokenLimit({ + modelStr: t.modelStr, + provider: t.provider, + }) + ) + .filter( + (limit): limit is number => + typeof limit === "number" && Number.isFinite(limit) && limit > 0 + ); } // chatCore executes per concrete target (handleSingleModel resolves // provider/effectiveModel before delegating). Compress against THIS diff --git a/tests/unit/resolveComboContextLimit.test.ts b/tests/unit/resolveComboContextLimit.test.ts new file mode 100644 index 000000000000..94673ba55e3f --- /dev/null +++ b/tests/unit/resolveComboContextLimit.test.ts @@ -0,0 +1,21 @@ +import test from "node:test"; +import assert from "node:assert/strict"; +import { resolveComboContextLimit } from "../../open-sse/services/contextManager.ts"; + +test("resolveComboContextLimit handles array of combo target objects ({ name, models }) in comboTargetLimits", () => { + const result = resolveComboContextLimit({ + provider: "unknown_provider", + model: "unknown_model", + comboTargetLimits: [ + { name: "subcombo1", models: [{ provider: "openai", model: "gpt-4" }] }, + { name: "subcombo2", models: [{ provider: "anthropic", model: "claude-3-5-sonnet" }] }, + ] as unknown as number[], + }); + + // Default fallback limit for unknown provider should be returned without throwing NaN or crash + assert.equal(typeof result.limit, "number"); + assert.ok(!Number.isNaN(result.limit)); + assert.ok(result.limit > 0); + assert.equal(result.source, "fallback"); +}); + From 1da3c48a874c6178ba75025cb5847ab468254764 Mon Sep 17 00:00:00 2001 From: diegosouzapw Date: Wed, 5 Aug 2026 20:28:58 -0300 Subject: [PATCH 2/2] fix(open-sse): compact comboTargetLimits mapping to stay under chatCore.ts file-size cap Co-authored-by: Dingding-leo --- open-sse/handlers/chatCore.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/open-sse/handlers/chatCore.ts b/open-sse/handlers/chatCore.ts index 8a4282d040c5..1bb9b995ffee 100644 --- a/open-sse/handlers/chatCore.ts +++ b/open-sse/handlers/chatCore.ts @@ -1705,14 +1705,11 @@ export async function handleChatCore({ comboConfig as unknown as { name: string; models: unknown[] }, allCombosData as unknown as { name: string; models: unknown[] }[] ); + // Fall back to ResolvedComboTarget.provider when modelStr lacks a + // provider/ prefix — parseModel alone returns provider:null (#8716). comboTargetLimits = targets .map((t: { modelStr?: string; provider?: string }) => - // Fall back to ResolvedComboTarget.provider when modelStr lacks a - // provider/ prefix — parseModel alone returns provider:null (#8716). - getComboTargetTokenLimit({ - modelStr: t.modelStr, - provider: t.provider, - }) + getComboTargetTokenLimit({ modelStr: t.modelStr, provider: t.provider }) ) .filter( (limit): limit is number =>