Files
OmniRoute/open-sse/handlers/chatCore/upstreamBody.ts
backryun 65e0aeda79 [Part 1/3]refactor(qwen): replace legacy Qwen Code and remove OAuth provider (#7866)
* refactor(cli): remove legacy Qwen Code integration

* refactor(qwen): remove deprecated Qwen OAuth provider

* feat(cli): rebuild Qwen Code integration for upstream V4

* fix(qwen): clear stale CLI auth on reset

* test(qwen): align retired provider coverage

* fix(db): renumber qwen-cleanup migration 129 -> 130

release/v3.8.49 tip took slot 129 via #7843 (usage_history_codex_strong_identity,
itself renumbered from 128 during the #7838/#7840 base-red cleanup) after this
branch forked; renumber remove_unregistered_qwen_data to 130.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

---------

Co-authored-by: Diego Rodrigues de Sa e Souza <8016841+diegosouzapw@users.noreply.github.com>
2026-07-20 17:53:04 -03:00

171 lines
5.6 KiB
TypeScript

/**
* chatCore upstream body preparation (Quality Gate v2 / Fase 9 — chatCore god-file decomposition,
* #3501 — first internal sub-slice of executeProviderRequest).
*
* Extracted from handleChatCore's execute() closure: prepares the body actually sent upstream for a
* given target model. Pins the model id, applies the configured payload rules, truncates the tool
* list to the provider's effective limit and injects an OpenAI `prompt_cache_key` for
* caching-capable providers. Pure with respect to handler
* state (returns a fresh body, only logs as a side effect); behaviour is byte-identical to the
* previous inline block. Split into small private steps so each stays under the complexity cap.
*/
import {
applyConfiguredPayloadRules,
resolvePayloadRuleProtocols,
} from "../../services/payloadRules.ts";
import { getEffectiveToolLimit, getKnownToolLimit } from "../../services/toolLimitDetector.ts";
import {
providerSupportsCaching,
resolveConnectionCacheOverride,
type ConnectionCacheOverride,
} from "../../utils/cacheControlPolicy.ts";
import { FORMATS } from "../../translator/formats.ts";
import { sanitizeRequestForResolvedTarget } from "../../services/targetRequestSanitizer.ts";
type LoggerLike = { debug?: (...args: unknown[]) => void } | null | undefined;
type Body = Record<string, unknown>;
type CredentialsLike =
| {
apiKey?: unknown;
accessToken?: unknown;
providerSpecificData?: Record<string, unknown> | null;
}
| null
| undefined;
function buildAppliedRulesSummary(
applied: Array<{ type: string; path: string; value?: unknown }>
): string {
return applied
.map((rule) => {
if (rule.type === "filter") return `${rule.type}:${rule.path}`;
const serializedValue = JSON.stringify(rule.value);
const safeValue =
typeof serializedValue === "string" && serializedValue.length > 80
? `${serializedValue.slice(0, 77)}...`
: serializedValue;
return `${rule.type}:${rule.path}=${safeValue}`;
})
.join(", ");
}
function truncateToolList(
bodyToSend: Body,
provider: string | null | undefined,
bypassDefaultToolLimit: boolean,
log?: LoggerLike
): Body {
if (!Array.isArray(bodyToSend.tools)) return bodyToSend;
const knownLimit = getKnownToolLimit(provider);
if (knownLimit !== null) {
if (bodyToSend.tools.length > knownLimit) {
const originalCount = bodyToSend.tools.length;
const truncatedTools = bodyToSend.tools.slice(0, knownLimit);
bodyToSend = { ...bodyToSend, tools: truncatedTools };
log?.debug?.(
"TOOL_LIMIT",
`Truncated ${originalCount} tools to ${knownLimit} for ${provider}`
);
}
return bodyToSend;
}
if (bypassDefaultToolLimit === true) return bodyToSend;
const effectiveToolLimit = getEffectiveToolLimit(provider);
if (bodyToSend.tools.length > effectiveToolLimit) {
const originalCount = bodyToSend.tools.length;
const truncatedTools = bodyToSend.tools.slice(0, effectiveToolLimit);
bodyToSend = { ...bodyToSend, tools: truncatedTools };
log?.debug?.(
"TOOL_LIMIT",
`Truncated ${originalCount} tools to ${effectiveToolLimit} for ${provider}`
);
}
return bodyToSend;
}
// Inject prompt_cache_key only for providers that support it.
async function injectPromptCacheKey(
bodyToSend: Body,
provider: string | null | undefined,
targetFormat: string,
connectionCacheOverride: ConnectionCacheOverride | null
): Promise<Body> {
if (
targetFormat === FORMATS.OPENAI &&
providerSupportsCaching(provider, undefined, connectionCacheOverride) &&
!bodyToSend.prompt_cache_key &&
Array.isArray(bodyToSend.messages) &&
!["nvidia", "codex", "xai"].includes(provider)
) {
const { generatePromptCacheKey } = await import("@/lib/promptCache");
const cacheKey = generatePromptCacheKey(bodyToSend.messages);
if (cacheKey) {
bodyToSend = { ...bodyToSend, prompt_cache_key: cacheKey };
}
}
return bodyToSend;
}
export async function prepareUpstreamBody(opts: {
translatedBody: Body;
modelToCall: string;
provider: string | null | undefined;
targetFormat: string;
credentials: CredentialsLike;
bypassDefaultToolLimit?: boolean;
log?: LoggerLike;
}): Promise<Body> {
const {
translatedBody,
modelToCall,
provider,
targetFormat,
credentials,
bypassDefaultToolLimit = false,
log,
} = opts;
let bodyToSend: Body =
translatedBody.model === modelToCall
? translatedBody
: { ...translatedBody, model: modelToCall };
const payloadRuleModel =
typeof bodyToSend.model === "string" && bodyToSend.model.length > 0
? bodyToSend.model
: modelToCall;
const payloadRuleProtocols = resolvePayloadRuleProtocols({ provider, targetFormat });
const payloadRuleResult = await applyConfiguredPayloadRules(
bodyToSend,
payloadRuleModel,
payloadRuleProtocols
);
bodyToSend = payloadRuleResult.payload;
if (payloadRuleResult.applied.length > 0) {
log?.debug?.(
"PAYLOAD_RULES",
`Applied ${payloadRuleResult.applied.length} rule(s) for ${payloadRuleModel} (${payloadRuleProtocols.join(", ")}): ${buildAppliedRulesSummary(payloadRuleResult.applied)}`
);
}
bodyToSend = sanitizeRequestForResolvedTarget(bodyToSend, {
provider,
model: payloadRuleModel,
log,
});
bodyToSend = truncateToolList(bodyToSend, provider, bypassDefaultToolLimit ?? false, log);
const connectionCacheOverride = resolveConnectionCacheOverride(credentials?.providerSpecificData);
bodyToSend = await injectPromptCacheKey(
bodyToSend,
provider,
targetFormat,
connectionCacheOverride
);
return bodyToSend;
}