fix(memory): treat TokenRouter as system-must-be-first (live HTTP 400 confirmed) (#11114)

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!
This commit is contained in:
ggdayup
2026-08-23 08:51:16 +08:00
committed by GitHub
parent 92ef3c71ea
commit f3875759ac
2 changed files with 11 additions and 2 deletions

View File

@@ -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.

View File

@@ -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);