From f3875759aced242e0f8dbd2f6ec0c9d904e56077 Mon Sep 17 00:00:00 2001 From: ggdayup Date: Sun, 23 Aug 2026 08:51:16 +0800 Subject: [PATCH] fix(memory): treat TokenRouter as system-must-be-first (live HTTP 400 confirmed) (#11114) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Validated on the combined batch board over tip 92ef3c71: static gates clean (changelog, file-size, complexity 2624<=2774, cognitive 1182<=1223, dead-code 411<=416), typecheck:core clean, focused tests green. Companion to #11113 (consumer side): tokenrouter joins BUILTIN_PROVIDERS_SYSTEM_MUST_BE_FIRST — memory-system-first-6135 suite green. Live-confirmed 400 class documented in the body. Thank you @ggdayup! --- src/lib/memory/injection.ts | 8 ++++++-- tests/unit/memory-system-first-6135.test.ts | 5 +++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/lib/memory/injection.ts b/src/lib/memory/injection.ts index 9fdd2bbbf1..d4d8ead7f7 100644 --- a/src/lib/memory/injection.ts +++ b/src/lib/memory/injection.ts @@ -65,7 +65,11 @@ export function providerSupportsSystemMessage(provider: string | null | undefine * * Populated with the Xiaomi MiMo endpoint (provider id `xiaomi-mimo`, registry * alias `mimo`, serving mimo-v2.5) confirmed live to 400 on a non-first system - * message. Add other providers here only when they are documented as strict. + * message, and the TokenRouter gateway (provider id `tokenrouter`), confirmed + * live on 2026-08-22 to reject mid-array system messages — including the + * compression notice spliced by purifyHistory() before that splice was fixed to + * merge into the leading system message. Add other providers here only when + * they are documented as strict. * * Self-hosted deployments can extend this list without a source change via * OMNIROUTE_STRICT_SYSTEM_PROVIDERS (comma-separated provider ids, @@ -73,7 +77,7 @@ export function providerSupportsSystemMessage(provider: string | null | undefine * self-hosted Qwen3.5+/3.6 model, whose chat template enforces the same * single-leading-system-message constraint as xiaomi-mimo. */ -const BUILTIN_PROVIDERS_SYSTEM_MUST_BE_FIRST = new Set(["xiaomi-mimo", "mimo"]); +const BUILTIN_PROVIDERS_SYSTEM_MUST_BE_FIRST = new Set(["xiaomi-mimo", "mimo", "tokenrouter"]); /** * Parses OMNIROUTE_STRICT_SYSTEM_PROVIDERS into a normalized id list. diff --git a/tests/unit/memory-system-first-6135.test.ts b/tests/unit/memory-system-first-6135.test.ts index 7104007ae6..339f83792c 100644 --- a/tests/unit/memory-system-first-6135.test.ts +++ b/tests/unit/memory-system-first-6135.test.ts @@ -49,6 +49,11 @@ describe("injectMemory system-must-be-first (#6135)", () => { it("flags xiaomi-mimo (and alias mimo) as system-must-be-first", () => { assert.equal(systemMessageMustBeFirst("xiaomi-mimo"), true); assert.equal(systemMessageMustBeFirst("mimo"), true); + // tokenrouter: confirmed live 2026-08-22 — mid-array system message + // (e.g. the purifyHistory compression notice) -> HTTP 400 + // "System message must be at the beginning". + assert.equal(systemMessageMustBeFirst("tokenrouter"), true); + assert.equal(systemMessageMustBeFirst("TokenRouter"), true); // case-insensitive // default: unlisted providers keep current (non-first-constrained) behavior assert.equal(systemMessageMustBeFirst("anthropic"), false); assert.equal(systemMessageMustBeFirst(null), false);