mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-05 23:02:10 +03:00
committed by
GitHub
parent
806d1f650b
commit
9be5528548
@@ -10,6 +10,8 @@
|
||||
|
||||
### 🔧 Bug Fixes
|
||||
|
||||
- **providers (GLM):** GLM **5.1 / 5.2** now keep the `system` role instead of having the system prompt folded into the first user turn. `roleNormalizer.ts` matched every `glm*` id with a blanket `startsWith("glm")` / `startsWith("glm-")` prefix, so the next-generation models — which z.ai documents as supporting the `system` role (GLM > 5.0) — were normalized as if they rejected it, degrading instruction-following. The matcher is now version-aware: it strips the system role only for bare `glm`, the 4.x family, and the 5.0 generation, and preserves it for `glm-5.1`/`glm-5.2` (and the Fireworks `glm-5p1` point alias). The ZenMux vendor-prefixed `z-ai/glm-*` compressed-history rule and the ERNIE rule are unchanged. Regression guards in `tests/unit/role-normalizer.test.ts`. ([#5610](https://github.com/diegosouzapw/OmniRoute/issues/5610))
|
||||
|
||||
- **Security hardening follow-ups (v3.8.15):** the `auth_token` cookie now sets an explicit 30-day `maxAge` so sessions persist as intended (Seg3); the management bootstrap warns at boot when `INITIAL_PASSWORD` is left at the insecure `CHANGEME` default (Seg2); VS Code path-token endpoints (`/api/v1/vscode/raw/[token]`) emit a once-per-process security warning since the API key travels in the URL and can leak via logs/proxies (Seg4); the system version route resolves the real global install path via `npm root -g` instead of a hardcoded `/app` (Bug3); and auto-update mode detection segment-matches `node_modules` instead of substring-matching, eliminating false "global install" positives (Bug1).
|
||||
|
||||
### 📝 Maintenance
|
||||
|
||||
@@ -49,14 +49,30 @@ function defaultPreserveDeveloperForProvider(provider: string): boolean {
|
||||
|
||||
/**
|
||||
* Models that are known to reject the `system` role regardless of provider.
|
||||
* Uses prefix matching (e.g., "glm-" matches "glm-4.7", "glm-4.5", etc.)
|
||||
* Uses prefix matching (e.g., "ernie-" matches "ernie-4.0").
|
||||
*/
|
||||
const MODELS_WITHOUT_SYSTEM_ROLE = [
|
||||
"glm-", // ZhipuAI GLM models (prefix: glm-5.1, glm-4.7, etc.)
|
||||
"glm", // Exact match for model id "glm" (e.g., Pollinations)
|
||||
"ernie-", // Baidu ERNIE models
|
||||
];
|
||||
|
||||
/**
|
||||
* ZhipuAI GLM rejects the `system` role EXCEPT generation > 5.0: per z.ai docs,
|
||||
* GLM 5.1 / 5.2 (and newer) accept it, so their system prompt must NOT be folded
|
||||
* into the first user turn (#5610). Everything else GLM — bare "glm" (Pollinations),
|
||||
* the 4.x family, and the 5.0 generation — still needs the fold. The version is read
|
||||
* from "glm-<major>.<minor>" or the Fireworks "glm-5p1" point alias.
|
||||
*/
|
||||
function isGlmWithoutSystemRole(modelLower: string): boolean {
|
||||
if (!modelLower.startsWith("glm")) return false;
|
||||
const match = modelLower.match(/glm-?(\d+)(?:[.p](\d+))?/);
|
||||
if (match) {
|
||||
const major = Number(match[1]);
|
||||
const minor = match[2] ? Number(match[2]) : 0;
|
||||
if (major > 5 || (major === 5 && minor >= 1)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const PROVIDER_SCOPED_MODELS_WITHOUT_SYSTEM_ROLE: Record<string, RegExp[]> = {
|
||||
// ZenMux exposes Z.AI GLM through OpenAI-compatible model ids such as
|
||||
// "z-ai/glm-5.2". Z.AI rejects compressed histories that start with a
|
||||
@@ -106,6 +122,8 @@ function supportsSystemRole(provider: string, model: string): boolean {
|
||||
if (pattern.test(modelLower)) return false;
|
||||
}
|
||||
|
||||
if (isGlmWithoutSystemRole(modelLower)) return false;
|
||||
|
||||
for (const prefix of MODELS_WITHOUT_SYSTEM_ROLE) {
|
||||
if (modelLower.startsWith(prefix)) return false;
|
||||
}
|
||||
|
||||
@@ -84,6 +84,44 @@ test("normalizeSystemRole merges system and developer content into the first use
|
||||
]);
|
||||
});
|
||||
|
||||
test("normalizeSystemRole preserves the system role for GLM > 5.0 (glm-5.1/5.2 support it, #5610)", () => {
|
||||
const messages = [
|
||||
{ role: "system", content: "be helpful" },
|
||||
{ role: "user", content: "hello" },
|
||||
];
|
||||
for (const model of [
|
||||
"glm-5.1",
|
||||
"glm-5.2",
|
||||
"glm-5.1-precision",
|
||||
"glm-5.2-high",
|
||||
"glm-5.2-max",
|
||||
"glm-5p1",
|
||||
]) {
|
||||
assert.deepEqual(
|
||||
normalizeSystemRole(messages, "glm", model),
|
||||
messages,
|
||||
`expected system role preserved for ${model}`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test("normalizeSystemRole still strips the system role for pre-5.1 GLM and bare glm (#5610 guard)", () => {
|
||||
const messages = [
|
||||
{ role: "system", content: "policy" },
|
||||
{ role: "user", content: "ok" },
|
||||
];
|
||||
const merged = [
|
||||
{ role: "user", content: "[System Instructions]\npolicy\n\n[User Message]\nok" },
|
||||
];
|
||||
for (const model of ["glm", "glm-4.7", "glm-5", "glm-5-turbo", "glm-5.0", "glm-5.0-turbo"]) {
|
||||
assert.deepEqual(
|
||||
normalizeSystemRole(messages, "openai", model),
|
||||
merged,
|
||||
`expected system role stripped for ${model}`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test("normalizeSystemRole inserts a user message when no user exists and drops empty system payloads", () => {
|
||||
const messages = [
|
||||
{ role: "system", content: [{ type: "image_url", image_url: { url: "ignored" } }] },
|
||||
|
||||
Reference in New Issue
Block a user