refactor(chatCore): extrai extractSystemRoleMessages + buildUpstreamHeadersForExecute para leaves puros (#3501) (#4548)

Integrated into release/v3.8.33
This commit is contained in:
Diego Rodrigues de Sa e Souza
2026-06-21 19:13:56 -03:00
committed by GitHub
parent 69c35bd342
commit 4b34a75fe3
4 changed files with 207 additions and 82 deletions

View File

@@ -1,6 +1,8 @@
import { injectMemoryAndSkills } from "./chatCore/memorySkillsInjection.ts";
import { resolveChatCoreRequestSetup } from "./chatCore/requestSetup.ts";
import { buildFailureUsageRecord } from "./chatCore/failureUsage.ts";
import { extractSystemRoleMessages } from "./chatCore/claudeSystemRole.ts";
export { extractSystemRoleMessages } from "./chatCore/claudeSystemRole.ts";
import { checkIdempotencyCache } from "./chatCore/idempotency.ts";
import { checkSemanticCache } from "./chatCore/semanticCache.ts";
import { sanitizeChatRequestBody } from "./chatCore/sanitization.ts";
@@ -164,7 +166,6 @@ import {
import {
getModelNormalizeToolCallId,
getModelPreserveOpenAIDeveloperRole,
getModelUpstreamExtraHeaders,
} from "@/lib/localDb";
import { getProviderCredentials, extractSessionAffinityKey } from "@/sse/services/auth";
import { deleteSessionAccountAffinity } from "@/lib/db/sessionAccountAffinity";
@@ -181,10 +182,7 @@ import {
} from "../utils/cacheControlPolicy.ts";
import { getCachedSettings } from "@/lib/db/readCache";
import { applyCodexGlobalFastServiceTier } from "@/lib/providers/codexFastTier";
import {
CPA_FORCE_FAST_MODE_HEADER,
shouldRequestClaudeFastMode,
} from "@/lib/providers/claudeFastMode";
import { buildUpstreamHeadersForExecute as buildUpstreamHeadersForExecuteFor } from "./chatCore/upstreamExecuteHeaders.ts";
import {
resolveEffectiveServiceTier as resolveEffectiveServiceTierFor,
resolveReportedServiceTier as resolveReportedServiceTierFor,
@@ -542,43 +540,8 @@ function buildExecutorClientHeaders(
return Object.keys(normalized).length > 0 ? normalized : null;
}
export function extractSystemRoleMessages(payload: Record<string, unknown>): void {
if (!Array.isArray(payload.messages)) return;
const messages = payload.messages as Array<{ role?: unknown; content?: unknown }>;
// Treat both `system` and `developer` as system-equivalent (OpenAI's Responses
// API renamed system → developer). Anthropic rejects either as a chat role, so
// both must be lifted into the top-level `system` field — parity with the
// normal-path extractSystemMessagesToBody closure.
const isSystemRole = (role: unknown): boolean =>
typeof role === "string" &&
(role.toLowerCase() === "system" || role.toLowerCase() === "developer");
const systemMessages = messages.filter((m) => isSystemRole(m.role));
if (systemMessages.length === 0) return;
const extraBlocks: Array<Record<string, unknown>> = [];
for (const sm of systemMessages) {
if (typeof sm.content === "string" && sm.content.length > 0) {
extraBlocks.push({ type: "text", text: sm.content });
} else if (Array.isArray(sm.content)) {
for (const block of sm.content as Array<Record<string, unknown>>) {
if (block?.type === "text" && typeof block.text === "string" && block.text.length > 0) {
extraBlocks.push({ ...block });
}
}
}
}
if (extraBlocks.length > 0) {
const existingSystem = payload.system;
if (typeof existingSystem === "string" && existingSystem.length > 0) {
payload.system = [{ type: "text", text: existingSystem }, ...extraBlocks];
} else if (Array.isArray(existingSystem)) {
payload.system = [...(existingSystem as Array<Record<string, unknown>>), ...extraBlocks];
} else {
payload.system = extraBlocks;
}
}
payload.messages = messages.filter((m) => !isSystemRole(m.role));
}
// extractSystemRoleMessages extracted to chatCore/claudeSystemRole.ts (#3501); re-exported above so
// existing importers (e.g. tests/unit/system-role-extraction.test.ts) keep resolving it from here.
export async function handleChatCore({
body,
@@ -1100,46 +1063,19 @@ export async function handleChatCore({
? credentials.providerSpecificData.customUserAgent.trim()
: "";
const buildUpstreamHeadersForExecute = (modelToCall: string): Record<string, string> => {
const upstreamHeaders =
modelToCall === effectiveModel
? {
...getModelUpstreamExtraHeaders(provider || "", model || "", sourceFormat),
...getModelUpstreamExtraHeaders(provider || "", resolvedModel || "", sourceFormat),
}
: (() => {
const r = resolveModelAlias(modelToCall);
return {
...getModelUpstreamExtraHeaders(provider || "", modelToCall || "", sourceFormat),
...getModelUpstreamExtraHeaders(provider || "", r || "", sourceFormat),
};
})();
if (connectionCustomUserAgent) {
upstreamHeaders["User-Agent"] = connectionCustomUserAgent;
if ("user-agent" in upstreamHeaders) {
upstreamHeaders["user-agent"] = connectionCustomUserAgent;
}
}
// Claude Fast Mode opt-in. When the user has enabled this in
// Settings > AI AND the target provider is the canonical Anthropic
// `claude` provider (Claude Code-compatible CPA bridges are excluded
// since they already select their own entrypoint) AND the model id
// matches the configured list, signal to a paired CLIProxyAPI build to
// rewrite the cc_entrypoint so the request can reach Anthropic Fast
// Mode (speed:"fast"). CPA builds that do not understand the header
// forward it harmlessly.
if (
provider === "claude" &&
typeof settings !== "undefined" &&
shouldRequestClaudeFastMode(settings, modelToCall)
) {
upstreamHeaders[CPA_FORCE_FAST_MODE_HEADER] = "1";
}
return upstreamHeaders;
};
// Upstream extra-header building extracted to chatCore/upstreamExecuteHeaders.ts (#3501); bind the
// per-request inputs once and delegate so the existing call sites stay byte-identical.
const buildUpstreamHeadersForExecute = (modelToCall: string): Record<string, string> =>
buildUpstreamHeadersForExecuteFor({
modelToCall,
effectiveModel,
provider,
model,
resolvedModel,
sourceFormat,
connectionCustomUserAgent,
settings,
});
// Default to false unless client explicitly sets stream: true (OpenAI spec compliant)
const acceptHeader =

View File

@@ -0,0 +1,48 @@
/**
* chatCore Claude system-role lifter (Quality Gate v2 / Fase 9 — chatCore god-file
* decomposition, #3501).
*
* Pure helper extracted from chatCore.ts: lifts any `system`/`developer` role messages out of the
* messages[] array into the top-level `system` field. Anthropic's Messages API rejects either as a
* chat role, so they must be hoisted. `developer` is OpenAI's Responses-API rename of `system` and
* is treated identically. Mutates the payload in place; behaviour is byte-identical to the previous
* top-level definition (still re-exported from chatCore.ts for existing importers/tests).
*/
export function extractSystemRoleMessages(payload: Record<string, unknown>): void {
if (!Array.isArray(payload.messages)) return;
const messages = payload.messages as Array<{ role?: unknown; content?: unknown }>;
// Treat both `system` and `developer` as system-equivalent (OpenAI's Responses
// API renamed system → developer). Anthropic rejects either as a chat role, so
// both must be lifted into the top-level `system` field — parity with the
// normal-path extractSystemMessagesToBody closure.
const isSystemRole = (role: unknown): boolean =>
typeof role === "string" &&
(role.toLowerCase() === "system" || role.toLowerCase() === "developer");
const systemMessages = messages.filter((m) => isSystemRole(m.role));
if (systemMessages.length === 0) return;
const extraBlocks: Array<Record<string, unknown>> = [];
for (const sm of systemMessages) {
if (typeof sm.content === "string" && sm.content.length > 0) {
extraBlocks.push({ type: "text", text: sm.content });
} else if (Array.isArray(sm.content)) {
for (const block of sm.content as Array<Record<string, unknown>>) {
if (block?.type === "text" && typeof block.text === "string" && block.text.length > 0) {
extraBlocks.push({ ...block });
}
}
}
}
if (extraBlocks.length > 0) {
const existingSystem = payload.system;
if (typeof existingSystem === "string" && existingSystem.length > 0) {
payload.system = [{ type: "text", text: existingSystem }, ...extraBlocks];
} else if (Array.isArray(existingSystem)) {
payload.system = [...(existingSystem as Array<Record<string, unknown>>), ...extraBlocks];
} else {
payload.system = extraBlocks;
}
}
payload.messages = messages.filter((m) => !isSystemRole(m.role));
}

View File

@@ -0,0 +1,71 @@
/**
* chatCore per-model upstream extra-header builder (Quality Gate v2 / Fase 9 — chatCore god-file
* decomposition, #3501).
*
* Pure builder extracted from handleChatCore: assembles the per-model upstream extra headers for an
* execute() call. Merges the configured per-model headers (for the resolved model and its alias),
* applies a connection's custom User-Agent override, and opts into Claude Fast Mode (CPA bridge
* header) when enabled in settings for the canonical `claude` provider and a supported model.
* Side-effect-free; behaviour is byte-identical to the previous inline closure.
*/
import { getModelUpstreamExtraHeaders } from "@/lib/db/models";
import { resolveModelAlias } from "../../services/modelDeprecation.ts";
import { CPA_FORCE_FAST_MODE_HEADER, shouldRequestClaudeFastMode } from "@/lib/providers/claudeFastMode";
export function buildUpstreamHeadersForExecute(opts: {
modelToCall: string;
effectiveModel: string;
provider: string | null | undefined;
model: string | null | undefined;
resolvedModel: string;
sourceFormat: string;
connectionCustomUserAgent: string;
settings: unknown;
}): Record<string, string> {
const {
modelToCall,
effectiveModel,
provider,
model,
resolvedModel,
sourceFormat,
connectionCustomUserAgent,
settings,
} = opts;
const upstreamHeaders: Record<string, string> =
modelToCall === effectiveModel
? {
...getModelUpstreamExtraHeaders(provider || "", model || "", sourceFormat),
...getModelUpstreamExtraHeaders(provider || "", resolvedModel || "", sourceFormat),
}
: (() => {
const r = resolveModelAlias(modelToCall);
return {
...getModelUpstreamExtraHeaders(provider || "", modelToCall || "", sourceFormat),
...getModelUpstreamExtraHeaders(provider || "", r || "", sourceFormat),
};
})();
if (connectionCustomUserAgent) {
upstreamHeaders["User-Agent"] = connectionCustomUserAgent;
if ("user-agent" in upstreamHeaders) {
upstreamHeaders["user-agent"] = connectionCustomUserAgent;
}
}
// Claude Fast Mode opt-in. When enabled in Settings > AI AND the target provider is the canonical
// Anthropic `claude` provider (Claude Code-compatible CPA bridges are excluded since they select
// their own entrypoint) AND the model id matches the configured list, signal to a paired
// CLIProxyAPI build to rewrite the cc_entrypoint so the request reaches Anthropic Fast Mode.
if (
provider === "claude" &&
typeof settings !== "undefined" &&
shouldRequestClaudeFastMode(settings, modelToCall)
) {
upstreamHeaders[CPA_FORCE_FAST_MODE_HEADER] = "1";
}
return upstreamHeaders;
}

View File

@@ -0,0 +1,70 @@
// tests/unit/chatcore-upstream-execute-headers.test.ts
// Characterization of buildUpstreamHeadersForExecute — the per-model upstream extra-header builder
// extracted from handleChatCore (chatCore god-file decomposition, #3501). Locks: the
// connection custom User-Agent override, the Claude Fast Mode opt-in (claude provider + enabled
// settings + supported model only), and the modelToCall===effectiveModel vs alias branches.
import { test } from "node:test";
import assert from "node:assert/strict";
import { buildUpstreamHeadersForExecute } from "../../open-sse/handlers/chatCore/upstreamExecuteHeaders.ts";
import { CPA_FORCE_FAST_MODE_HEADER } from "../../src/lib/providers/claudeFastMode.ts";
const base = {
modelToCall: "some-model",
effectiveModel: "some-model",
provider: "openai",
model: "some-model",
resolvedModel: "some-model",
sourceFormat: "openai",
connectionCustomUserAgent: "",
settings: {},
};
test("no custom UA / non-claude / no fast settings → no UA and no fast-mode header", () => {
const h = buildUpstreamHeadersForExecute({ ...base });
assert.equal(h["User-Agent"], undefined);
assert.equal(h[CPA_FORCE_FAST_MODE_HEADER], undefined);
});
test("connection custom User-Agent overrides the upstream User-Agent", () => {
const h = buildUpstreamHeadersForExecute({ ...base, connectionCustomUserAgent: "MyAgent/1.0" });
assert.equal(h["User-Agent"], "MyAgent/1.0");
});
test("claude provider + enabled fast-mode settings + supported model → CPA header set", () => {
const h = buildUpstreamHeadersForExecute({
...base,
provider: "claude",
modelToCall: "claude-fast-x",
effectiveModel: "claude-fast-x",
settings: { claudeFastMode: { enabled: true, supportedModels: ["claude-fast-x"] } },
});
assert.equal(h[CPA_FORCE_FAST_MODE_HEADER], "1");
});
test("fast-mode header is NOT set when the model is not in the supported list", () => {
const h = buildUpstreamHeadersForExecute({
...base,
provider: "claude",
modelToCall: "claude-other",
effectiveModel: "claude-other",
settings: { claudeFastMode: { enabled: true, supportedModels: ["claude-fast-x"] } },
});
assert.equal(h[CPA_FORCE_FAST_MODE_HEADER], undefined);
});
test("fast-mode header is NOT set for non-claude providers even with fast settings", () => {
const h = buildUpstreamHeadersForExecute({
...base,
provider: "openai",
modelToCall: "claude-fast-x",
effectiveModel: "claude-fast-x",
settings: { claudeFastMode: { enabled: true, supportedModels: ["claude-fast-x"] } },
});
assert.equal(h[CPA_FORCE_FAST_MODE_HEADER], undefined);
});
test("returns a plain object (no per-model extra headers configured for unknown models)", () => {
const h = buildUpstreamHeadersForExecute({ ...base, modelToCall: "totally-unknown", effectiveModel: "x" });
assert.equal(typeof h, "object");
assert.equal(h[CPA_FORCE_FAST_MODE_HEADER], undefined);
});