mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-26 09:52:11 +03:00
Merge pull request #2370 from thepigdestroyer/fix/claude-oauth-systemtransforms-billing-gate
fix(claude-oauth): enable system-transforms pipeline for native claude executor (closes 400 billing-gate)
This commit is contained in:
@@ -34,6 +34,7 @@ import {
|
||||
} from "./ccBridgeTransforms.ts";
|
||||
import type {
|
||||
CcBridgeTransformsConfig,
|
||||
ReplaceTextOp,
|
||||
TransformOp as BaseTransformOp,
|
||||
} from "./ccBridgeTransforms.ts";
|
||||
|
||||
@@ -132,23 +133,46 @@ export const PROVIDER_CC_BRIDGE = "anthropic-compatible-cc";
|
||||
/**
|
||||
* Default pipeline for the native `claude` provider path.
|
||||
*
|
||||
* Cosmetic ops only — native executor already injects billing+sentinel.
|
||||
* Obfuscates sensitive words (Open WebUI etc.) and drops Open WebUI
|
||||
* paragraph anchors. Does NOT inject billing header (would conflict
|
||||
* with native code at executors/base.ts:753-782).
|
||||
* Cosmetic ops only — native executor already injects billing+sentinel
|
||||
* (`executors/base.ts:759-784`), so this pipeline deliberately OMITS
|
||||
* `prepend_system_block` and `inject_billing_header` to avoid double-prepend
|
||||
* and prompt-cache prefix breakage (see issue #1712, native comment block
|
||||
* `executors/base.ts:624-631`).
|
||||
*
|
||||
* Plugin parity (`@ex-machina/opencode-anthropic-auth`): drops 3rd-party-agent
|
||||
* anchor paragraphs (anomalyco/opencode, cline, getcursor/cursor, continue.dev,
|
||||
* Open WebUI), drops "You are OpenCode" / "You are Open WebUI" identity
|
||||
* paragraphs, replaces the "Here is some useful information about the
|
||||
* environment you are running in:" billing-gate trigger phrase, and ZWJ
|
||||
* obfuscates sensitive client words. Without these, the native OAuth path
|
||||
* leaks third-party-agent signals into `/v1/messages` and Anthropic returns
|
||||
* `[400] Third-party apps now draw from extra usage, not plan limits.` —
|
||||
* verified against opencode→OmniRoute→Anthropic with claude-opus-4-7 OAuth.
|
||||
*/
|
||||
export const DEFAULT_CLAUDE_PIPELINE: TransformOp[] = [
|
||||
// Open WebUI paragraph anchors (Gap 2 from comment 4459544580).
|
||||
// Drop paragraphs containing 3rd-party-agent anchor URLs (anomalyco/opencode,
|
||||
// opencode.ai/docs, cline, getcursor/cursor, continue.dev) and Open WebUI URLs.
|
||||
{
|
||||
kind: "drop_paragraph_if_contains",
|
||||
needles: [...OPENWEBUI_PARAGRAPH_ANCHORS],
|
||||
needles: [...DEFAULT_PARAGRAPH_REMOVAL_ANCHORS, ...OPENWEBUI_PARAGRAPH_ANCHORS],
|
||||
},
|
||||
// Open WebUI identity prefixes.
|
||||
// Drop "You are OpenCode" + "You are Open WebUI" identity paragraphs.
|
||||
{
|
||||
kind: "drop_paragraph_if_starts_with",
|
||||
prefixes: [...OPENWEBUI_IDENTITY_PREFIXES],
|
||||
prefixes: [...DEFAULT_IDENTITY_PREFIXES, ...OPENWEBUI_IDENTITY_PREFIXES],
|
||||
},
|
||||
// ZWJ obfuscation of sensitive words (closes Gap 1 + Gap 3).
|
||||
// Replace the "Here is some useful information about the environment you are
|
||||
// running in:" billing-gate trigger phrase + the "if OpenCode honestly"
|
||||
// phrase-shape filter (DEFAULT_TEXT_REPLACEMENTS from ccBridgeTransforms.ts).
|
||||
...DEFAULT_TEXT_REPLACEMENTS.map<ReplaceTextOp>((r) => ({
|
||||
kind: "replace_text" as const,
|
||||
match: r.match,
|
||||
replacement: r.replacement,
|
||||
allOccurrences: true,
|
||||
})),
|
||||
// ZWJ obfuscation of sensitive client words (opencode, cline, cursor, …,
|
||||
// openwebui). Layers on top of the legacy `obfuscateInBody` pass at
|
||||
// `executors/base.ts:622` (which only covers `DEFAULT_SENSITIVE_WORDS`).
|
||||
{
|
||||
kind: "obfuscate_words",
|
||||
words: [...DEFAULT_OBFUSCATE_WORDS],
|
||||
@@ -188,7 +212,13 @@ export const DEFAULT_CC_BRIDGE_PROVIDER_PIPELINE: TransformOp[] = [
|
||||
export const DEFAULT_SYSTEM_TRANSFORMS_CONFIG: SystemTransformsConfig = {
|
||||
providers: {
|
||||
[PROVIDER_CLAUDE]: {
|
||||
enabled: false,
|
||||
// Enabled by default — matches the module-level docstring ("claude:
|
||||
// obfuscate_words ON …") and closes the native-OAuth third-party-agent
|
||||
// leak that surfaces as `[400] Third-party apps now draw from extra
|
||||
// usage` when opencode (or any non-claude-cli client) hits OmniRoute's
|
||||
// `/v1/chat/completions` endpoint with a `claude/*` model slug. User
|
||||
// overrides via Settings UI (setSystemTransformsConfig) still win.
|
||||
enabled: true,
|
||||
pipeline: DEFAULT_CLAUDE_PIPELINE,
|
||||
},
|
||||
[PROVIDER_CC_BRIDGE]: {
|
||||
|
||||
@@ -38,6 +38,26 @@ const OPENWEBUI_PARAGRAPH_ANCHORS = [
|
||||
"docs.openwebui.com",
|
||||
];
|
||||
|
||||
// Mirrors of ccBridgeTransforms.ts constants used by the native `claude` and
|
||||
// CC-bridge default pipelines.
|
||||
const DEFAULT_PARAGRAPH_REMOVAL_ANCHORS = [
|
||||
"github.com/anomalyco/opencode",
|
||||
"opencode.ai/docs",
|
||||
"github.com/cline/cline",
|
||||
"github.com/getcursor/cursor",
|
||||
"continue.dev",
|
||||
];
|
||||
|
||||
const DEFAULT_IDENTITY_PREFIXES = ["You are OpenCode"];
|
||||
|
||||
const DEFAULT_TEXT_REPLACEMENTS = [
|
||||
{ match: "if OpenCode honestly", replacement: "if the assistant honestly" },
|
||||
{
|
||||
match: "Here is some useful information about the environment you are running in:",
|
||||
replacement: "Environment context you are running in:",
|
||||
},
|
||||
];
|
||||
|
||||
const DEFAULT_OBFUSCATE_WORDS = [
|
||||
"opencode",
|
||||
"open-code",
|
||||
@@ -61,16 +81,22 @@ const DEFAULT_OBFUSCATE_WORDS = [
|
||||
const DEFAULT_SYSTEM_TRANSFORMS_CLIENT = {
|
||||
providers: {
|
||||
[PROVIDER_CLAUDE]: {
|
||||
enabled: false,
|
||||
enabled: true,
|
||||
pipeline: [
|
||||
{
|
||||
kind: "drop_paragraph_if_contains",
|
||||
needles: [...OPENWEBUI_PARAGRAPH_ANCHORS],
|
||||
needles: [...DEFAULT_PARAGRAPH_REMOVAL_ANCHORS, ...OPENWEBUI_PARAGRAPH_ANCHORS],
|
||||
},
|
||||
{
|
||||
kind: "drop_paragraph_if_starts_with",
|
||||
prefixes: ["You are Open WebUI"],
|
||||
prefixes: [...DEFAULT_IDENTITY_PREFIXES, "You are Open WebUI"],
|
||||
},
|
||||
...DEFAULT_TEXT_REPLACEMENTS.map((r) => ({
|
||||
kind: "replace_text" as const,
|
||||
match: r.match,
|
||||
replacement: r.replacement,
|
||||
allOccurrences: true,
|
||||
})),
|
||||
{
|
||||
kind: "obfuscate_words",
|
||||
words: [...DEFAULT_OBFUSCATE_WORDS],
|
||||
|
||||
@@ -402,15 +402,36 @@ test("idempotency: full claude pipeline running twice does not duplicate blocks"
|
||||
const UI_DEFAULTS_SNAPSHOT = {
|
||||
providers: {
|
||||
claude: {
|
||||
enabled: false,
|
||||
enabled: true,
|
||||
pipeline: [
|
||||
{
|
||||
kind: "drop_paragraph_if_contains",
|
||||
needles: ["github.com/open-webui/open-webui", "openwebui.com", "docs.openwebui.com"],
|
||||
needles: [
|
||||
"github.com/anomalyco/opencode",
|
||||
"opencode.ai/docs",
|
||||
"github.com/cline/cline",
|
||||
"github.com/getcursor/cursor",
|
||||
"continue.dev",
|
||||
"github.com/open-webui/open-webui",
|
||||
"openwebui.com",
|
||||
"docs.openwebui.com",
|
||||
],
|
||||
},
|
||||
{
|
||||
kind: "drop_paragraph_if_starts_with",
|
||||
prefixes: ["You are Open WebUI"],
|
||||
prefixes: ["You are OpenCode", "You are Open WebUI"],
|
||||
},
|
||||
{
|
||||
kind: "replace_text",
|
||||
match: "if OpenCode honestly",
|
||||
replacement: "if the assistant honestly",
|
||||
allOccurrences: true,
|
||||
},
|
||||
{
|
||||
kind: "replace_text",
|
||||
match: "Here is some useful information about the environment you are running in:",
|
||||
replacement: "Environment context you are running in:",
|
||||
allOccurrences: true,
|
||||
},
|
||||
{
|
||||
kind: "obfuscate_words",
|
||||
|
||||
Reference in New Issue
Block a user