mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-26 09:52:11 +03:00
fix(sse): strip third-party-agent signals from the Hermes system prompt that trigger Anthropic 400 extra-usage (#8350) (#8358)
This commit is contained in:
committed by
GitHub
parent
70275be59b
commit
493708f575
1
changelog.d/fixes/8350-hermes-oauth-usage-400.md
Normal file
1
changelog.d/fixes/8350-hermes-oauth-usage-400.md
Normal file
@@ -0,0 +1 @@
|
||||
- fix(sse): strip third-party-agent signals from the Hermes system prompt that trigger Anthropic 400 extra-usage (#8350)
|
||||
@@ -96,6 +96,9 @@ export const DEFAULT_OBFUSCATE_WORDS = [
|
||||
// Open WebUI additions
|
||||
"openwebui",
|
||||
"open-webui",
|
||||
// Hermes additions (#8350)
|
||||
"hermes-agent",
|
||||
"hermes",
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -118,6 +121,19 @@ export const PI_PARAGRAPH_ANCHORS = [
|
||||
"Pi documentation (read only when the user asks about pi itself",
|
||||
];
|
||||
|
||||
/**
|
||||
* Hermes (NousResearch/hermes-agent) paragraph anchors — the doc-link
|
||||
* paragraph injected by `agent/prompt_builder.py` on the upstream CLI.
|
||||
* Added on top of the other anchor lists for #8350.
|
||||
*/
|
||||
export const HERMES_PARAGRAPH_ANCHORS = [
|
||||
"hermes-agent.nousresearch.com",
|
||||
"github.com/NousResearch/hermes-agent",
|
||||
];
|
||||
|
||||
/** Hermes identity paragraph prefixes ("You are Hermes Agent, ..."). */
|
||||
export const HERMES_IDENTITY_PREFIXES = ["You are Hermes Agent"];
|
||||
|
||||
// ────────────────────────────────────────────────────────────────────────────
|
||||
// Per-provider defaults.
|
||||
// ────────────────────────────────────────────────────────────────────────────
|
||||
@@ -164,12 +180,18 @@ export const DEFAULT_CLAUDE_PIPELINE: TransformOp[] = [
|
||||
...DEFAULT_PARAGRAPH_REMOVAL_ANCHORS,
|
||||
...OPENWEBUI_PARAGRAPH_ANCHORS,
|
||||
...PI_PARAGRAPH_ANCHORS,
|
||||
...HERMES_PARAGRAPH_ANCHORS,
|
||||
],
|
||||
},
|
||||
// Drop "You are OpenCode" + "You are Open WebUI" identity paragraphs.
|
||||
// Drop "You are OpenCode" + "You are Open WebUI" + "You are Hermes Agent"
|
||||
// identity paragraphs.
|
||||
{
|
||||
kind: "drop_paragraph_if_starts_with",
|
||||
prefixes: [...DEFAULT_IDENTITY_PREFIXES, ...OPENWEBUI_IDENTITY_PREFIXES],
|
||||
prefixes: [
|
||||
...DEFAULT_IDENTITY_PREFIXES,
|
||||
...OPENWEBUI_IDENTITY_PREFIXES,
|
||||
...HERMES_IDENTITY_PREFIXES,
|
||||
],
|
||||
},
|
||||
// Replace the "Here is some useful information about the environment you are
|
||||
// running in:" billing-gate trigger phrase + the "if OpenCode honestly"
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
} from "@/shared/constants/cliCompatProviders";
|
||||
import { AI_PROVIDERS } from "@/shared/constants/providers";
|
||||
import { compareTr } from "@/shared/utils/turkishText";
|
||||
import { HERMES } from "./systemTransformsHermesDefaults";
|
||||
|
||||
// Provider keys (mirror of open-sse/services/systemTransforms.ts).
|
||||
const PROVIDER_CLAUDE = "claude";
|
||||
@@ -80,6 +81,8 @@ const DEFAULT_OBFUSCATE_WORDS = [
|
||||
"codecompanion",
|
||||
"openwebui",
|
||||
"open-webui",
|
||||
"hermes-agent",
|
||||
"hermes",
|
||||
];
|
||||
|
||||
// Mirror of DEFAULT_SYSTEM_TRANSFORMS_CONFIG from open-sse/services/systemTransforms.ts.
|
||||
@@ -96,11 +99,12 @@ const DEFAULT_SYSTEM_TRANSFORMS_CLIENT = {
|
||||
...DEFAULT_PARAGRAPH_REMOVAL_ANCHORS,
|
||||
...OPENWEBUI_PARAGRAPH_ANCHORS,
|
||||
...PI_PARAGRAPH_ANCHORS,
|
||||
...HERMES.anchors,
|
||||
],
|
||||
},
|
||||
{
|
||||
kind: "drop_paragraph_if_starts_with",
|
||||
prefixes: [...DEFAULT_IDENTITY_PREFIXES, "You are Open WebUI"],
|
||||
prefixes: [...DEFAULT_IDENTITY_PREFIXES, "You are Open WebUI", ...HERMES.prefixes],
|
||||
},
|
||||
...DEFAULT_TEXT_REPLACEMENTS.map((r) => ({
|
||||
kind: "replace_text" as const,
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Hermes (NousResearch/hermes-agent) system-transform anchors — client-side
|
||||
* mirror constant shared by RoutingTab.tsx and tests/unit/system-transforms.test.ts's
|
||||
* UI-parity snapshot. Extracted to a standalone module to keep RoutingTab.tsx
|
||||
* under its frozen file-size baseline (#8350).
|
||||
*
|
||||
* Server source of truth: open-sse/services/systemTransforms.ts
|
||||
* (HERMES_PARAGRAPH_ANCHORS / HERMES_IDENTITY_PREFIXES).
|
||||
*/
|
||||
export const HERMES = {
|
||||
anchors: ["hermes-agent.nousresearch.com", "github.com/NousResearch/hermes-agent"],
|
||||
prefixes: ["You are Hermes Agent"],
|
||||
};
|
||||
70
tests/unit/8350-hermes-oauth-usage-400.test.ts
Normal file
70
tests/unit/8350-hermes-oauth-usage-400.test.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
// Regression test for #8350 — Hermes (NousResearch/hermes-agent) system-prompt
|
||||
// signals reach Anthropic's native Claude OAuth path untouched, tripping
|
||||
// `[400] Third-party apps now draw from extra usage, not plan limits.`
|
||||
//
|
||||
// Mirrors the "OpenWebUI fixture" / "Pi documentation" style tests in
|
||||
// tests/unit/system-transforms.test.ts. Fixture text matches the real
|
||||
// identity + doc-link paragraphs injected by
|
||||
// NousResearch/hermes-agent/agent/prompt_builder.py (verified via WebFetch
|
||||
// against the upstream repo during triage).
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
const { applySystemTransformPipeline, DEFAULT_SYSTEM_TRANSFORMS_CONFIG, PROVIDER_CLAUDE } =
|
||||
await import("../../open-sse/services/systemTransforms.ts");
|
||||
|
||||
test("Hermes fixture: claude provider drops Hermes identity + doc-link paragraphs (#8350)", () => {
|
||||
const body = {
|
||||
system: [
|
||||
{
|
||||
type: "text",
|
||||
text: [
|
||||
"You are Hermes Agent, an intelligent AI assistant created by Nous Research.",
|
||||
"Guidelines:\n- Be concise.",
|
||||
"For more information, see the documentation at https://hermes-agent.nousresearch.com/docs.",
|
||||
].join("\n\n"),
|
||||
},
|
||||
],
|
||||
messages: [{ role: "user", content: "hi" }],
|
||||
};
|
||||
const result = applySystemTransformPipeline(
|
||||
PROVIDER_CLAUDE,
|
||||
body,
|
||||
DEFAULT_SYSTEM_TRANSFORMS_CONFIG
|
||||
);
|
||||
const out = (body.system as Array<{ text: string }>)[0].text;
|
||||
|
||||
assert.ok(
|
||||
!out.includes("You are Hermes Agent"),
|
||||
"Hermes identity paragraph should be dropped by the default claude pipeline"
|
||||
);
|
||||
assert.ok(
|
||||
!out.includes("hermes-agent.nousresearch.com"),
|
||||
"Hermes doc-link paragraph should be dropped by the default claude pipeline"
|
||||
);
|
||||
// Unrelated legitimate content survives untouched.
|
||||
assert.ok(out.includes("Guidelines:"));
|
||||
assert.ok(out.includes("Be concise."));
|
||||
assert.ok(result.appliedOpKinds.includes("drop_paragraph_if_contains"));
|
||||
// No billing header injected on the native OAuth path (native code handles that).
|
||||
assert.ok(!result.appliedOpKinds.includes("inject_billing_header"));
|
||||
});
|
||||
|
||||
test("non-Hermes system prompt passes through byte-identical through the claude pipeline (no drive-by regression)", () => {
|
||||
const body = {
|
||||
system: [
|
||||
{
|
||||
type: "text",
|
||||
text: "You are a helpful operator-configured assistant. Follow company policy X and always answer in English.",
|
||||
},
|
||||
],
|
||||
messages: [{ role: "user", content: "hi" }],
|
||||
};
|
||||
const before = JSON.stringify(body);
|
||||
applySystemTransformPipeline(PROVIDER_CLAUDE, body, DEFAULT_SYSTEM_TRANSFORMS_CONFIG);
|
||||
assert.equal(
|
||||
JSON.stringify(body),
|
||||
before,
|
||||
"a normal operator system prompt with no third-party-agent anchors must pass through untouched"
|
||||
);
|
||||
});
|
||||
@@ -446,11 +446,13 @@ const UI_DEFAULTS_SNAPSHOT = {
|
||||
"@earendil-works/pi-coding-agent",
|
||||
"/.pi/",
|
||||
"Pi documentation (read only when the user asks about pi itself",
|
||||
"hermes-agent.nousresearch.com",
|
||||
"github.com/NousResearch/hermes-agent",
|
||||
],
|
||||
},
|
||||
{
|
||||
kind: "drop_paragraph_if_starts_with",
|
||||
prefixes: ["You are OpenCode", "You are Open WebUI"],
|
||||
prefixes: ["You are OpenCode", "You are Open WebUI", "You are Hermes Agent"],
|
||||
},
|
||||
{
|
||||
kind: "replace_text",
|
||||
@@ -481,6 +483,8 @@ const UI_DEFAULTS_SNAPSHOT = {
|
||||
"codecompanion",
|
||||
"openwebui",
|
||||
"open-webui",
|
||||
"hermes-agent",
|
||||
"hermes",
|
||||
],
|
||||
targets: ["system", "messages", "tools"],
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user