Files
OmniRoute/open-sse/utils/bypassHandler.ts
Diego Rodrigues de Sa e Souza b9433fd03a fix(sse): reconstruct Claude-format content in synthetic bypass responses (#7248)
* fix(sse): reconstruct Claude-format content in synthetic bypass responses

handleBypassRequest() returns a canned response for CLI warmup/title-
extraction patterns without calling the provider. For Claude-format
clients (e.g. Claude Code CLI), the non-streaming path merged translated
SSE chunks by taking message_start.message as-is — but the
openai-to-claude translator always initializes that message with
content: [] and streams the actual text via separate
content_block_start/delta events. Every synthetic Claude-format
bypass response therefore silently returned empty content.

mergeChunksToResponse() now rebuilds the content array from
content_block_start/delta events (mirroring the streaming path) and
carries over stop_reason/stop_sequence from message_delta. Extracted
the response-builder helpers (createOpenAIResponse,
create{Non}StreamingResponse, mergeChunksToResponse) out of
bypassHandler.ts into a new open-sse/utils/bypassResponse.ts module so
this logic has a single owner instead of being duplicated inline.

Co-authored-by: KunN-21 <kunn21.nv@gmail.com>
Inspired-by: https://github.com/decolua/9router/pull/2404

* chore(changelog): fragment for #7248

* refactor(sse): extract Claude chunk-merge helpers to fix complexity ratchet

mergeChunksToResponse() regressed both quality ratchets by +1
(complexity 2057>2056, cognitive 891>890). Split the Claude-format
reconstruction into buildClaudeContentBlocks(), applyClaudeMessageDelta()
and mergeClaudeChunks() — same behavior, verified by the existing
bypass-response-claude-merge.test.ts (4/4 passing unchanged).

---------

Co-authored-by: KunN-21 <kunn21.nv@gmail.com>
2026-07-17 10:40:56 -03:00

91 lines
2.9 KiB
TypeScript

import { CORS_HEADERS } from "./cors.ts";
import { detectFormat } from "../services/provider.ts";
import { SKIP_PATTERNS } from "../config/constants.ts";
import { createNonStreamingResponse, createStreamingResponse } from "./bypassResponse.ts";
/**
* Check for bypass patterns — return fake response without calling provider.
*
* Intentionally limited to Claude CLI requests only because:
* 1. The bypass patterns (title extraction, warmup, count) are specific to
* Claude CLI's internal protocol — other clients don't send these patterns.
* 2. False-positive bypasses would silently break real requests.
* 3. The SKIP_PATTERNS config allows user-defined patterns for every client.
*
* @param {object} body - Request body
* @param {string} model - Model name
* @param {string} userAgent - User-Agent header
* @returns {object|null} Bypass response or null to proceed normally
*/
export function handleBypassRequest(body, model, userAgent = "") {
const normalizedUserAgent = typeof userAgent === "string" ? userAgent : "";
if (!normalizedUserAgent.includes("claude-cli")) return null;
if (!body.messages?.length) return null;
const messages = body.messages;
const getText = (content) => {
if (typeof content === "string") return content;
if (Array.isArray(content)) {
return content
.filter((c) => c.type === "text")
.map((c) => c.text)
.join(" ");
}
return "";
};
let shouldBypass = false;
// Pattern 1: Title extraction (assistant message = "{")
const lastMsg = messages[messages.length - 1];
if (lastMsg?.role === "assistant" && lastMsg.content?.[0]?.text === "{") {
shouldBypass = true;
}
// Pattern 2: Warmup
if (!shouldBypass) {
const firstText = getText(messages[0]?.content);
if (firstText === "Warmup") {
shouldBypass = true;
}
}
// Pattern 3: Count
if (!shouldBypass && messages.length === 1 && messages[0]?.role === "user") {
const firstText = getText(messages[0]?.content);
if (firstText === "count") {
shouldBypass = true;
}
}
// Pattern 4: Skip patterns
if (!shouldBypass && SKIP_PATTERNS?.length) {
const userMessages = messages.filter((m) => m.role === "user");
const userText = userMessages.map((m) => getText(m.content)).join(" ");
if (SKIP_PATTERNS.some((p) => userText.includes(p))) {
shouldBypass = true;
}
}
// Pattern 5: Quota probe — max_tokens=1 + "quota" keyword (FCC try_quota_mock).
if (!shouldBypass && body.max_tokens === 1) {
const userText = messages
.filter((m) => m.role === "user")
.map((m) => getText(m.content))
.join(" ")
.toLowerCase();
if (userText.includes("quota")) {
shouldBypass = true;
}
}
if (!shouldBypass) return null;
const sourceFormat = detectFormat(body);
const stream = body.stream !== false;
return stream
? createStreamingResponse(sourceFormat, model)
: createNonStreamingResponse(sourceFormat, model);
}