mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-05 14:52:09 +03:00
Rebuilt onto release/v3.8.33. Integrated into release/v3.8.33.
This commit is contained in:
committed by
GitHub
parent
ac7779e760
commit
aef00dded5
@@ -71,11 +71,8 @@ import {
|
||||
import { createRequestLogger } from "../utils/requestLogger.ts";
|
||||
import { createPreparedRequestLogger, runWithCapture } from "../utils/providerRequestLogging.ts";
|
||||
import { applyResponsesPreviousResponseIdPolicy } from "../utils/responsesStatePolicy.ts";
|
||||
import {
|
||||
getModelTargetFormat,
|
||||
PROVIDER_ID_TO_ALIAS,
|
||||
splitClaudeEffortSuffix,
|
||||
} from "../config/providerModels.ts";
|
||||
import { getModelTargetFormat, PROVIDER_ID_TO_ALIAS } from "../config/providerModels.ts";
|
||||
import { applyClaudeEffortVariant } from "./chatCore/claudeEffortVariant.ts";
|
||||
import { DEFAULT_THINKING_CLAUDE_SIGNATURE } from "../config/defaultThinkingSignature.ts";
|
||||
import {
|
||||
getStripTypesForProviderModel,
|
||||
@@ -928,30 +925,18 @@ export async function handleChatCore({
|
||||
// it into Claude thinking/effort config. An explicit client-supplied effort always
|
||||
// wins; native Claude passthrough is left untouched (it carries its own `thinking`),
|
||||
// and non-thinking base models are cleaned up later by normalizeThinkingForModel().
|
||||
if (
|
||||
(provider === "claude" || isClaudeCodeCompatibleProvider(provider)) &&
|
||||
typeof effectiveModel === "string"
|
||||
) {
|
||||
const { baseModel, effort } = splitClaudeEffortSuffix(effectiveModel);
|
||||
if (effort) {
|
||||
effectiveModel = baseModel;
|
||||
if (body && typeof body === "object" && !Array.isArray(body)) {
|
||||
const claudeBody = body as Record<string, unknown>;
|
||||
claudeBody.model = baseModel;
|
||||
if (sourceFormat !== FORMATS.CLAUDE) {
|
||||
const explicitEffort =
|
||||
claudeBody.reasoning_effort ??
|
||||
(claudeBody.reasoning as Record<string, unknown> | undefined)?.effort ??
|
||||
(claudeBody.output_config as Record<string, unknown> | undefined)?.effort;
|
||||
if (explicitEffort === undefined || explicitEffort === null || explicitEffort === "") {
|
||||
claudeBody.reasoning_effort = effort;
|
||||
}
|
||||
}
|
||||
}
|
||||
log?.info?.(
|
||||
"PARAMS",
|
||||
`Claude effort variant: stripped "-${effort}" → ${baseModel} (reasoning_effort=${effort})`
|
||||
);
|
||||
// Extracted to chatCore/claudeEffortVariant.ts (#3501); mutates body in place and returns the
|
||||
// stripped model + an optional log line, keeping behaviour byte-identical.
|
||||
{
|
||||
const effortVariant = applyClaudeEffortVariant({
|
||||
provider,
|
||||
effectiveModel,
|
||||
body,
|
||||
sourceFormat,
|
||||
});
|
||||
effectiveModel = effortVariant.effectiveModel;
|
||||
if (effortVariant.log) {
|
||||
log?.info?.("PARAMS", effortVariant.log);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
62
open-sse/handlers/chatCore/claudeEffortVariant.ts
Normal file
62
open-sse/handlers/chatCore/claudeEffortVariant.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* chatCore Claude effort-variant normalizer (Quality Gate v2 / Fase 9 — chatCore god-file
|
||||
* decomposition, #3501).
|
||||
*
|
||||
* The Claude / Claude-Code model picker (e.g. VS Code's "Effort" slider) advertises
|
||||
* claude-...-{low,medium,high,xhigh,max}. Anthropic has no such model, so the suffixed id 404s
|
||||
* upstream. This strips it back to the real base id and surfaces the level as reasoning_effort so
|
||||
* the OpenAI→Claude translator / Claude-Code bridge can turn it into Claude thinking/effort config.
|
||||
* An explicit client-supplied effort always wins; native Claude passthrough (sourceFormat === claude)
|
||||
* is left untouched (it carries its own `thinking`). The body is mutated in place (model +
|
||||
* reasoning_effort), byte-identical to the previous inline block; the new effectiveModel and an
|
||||
* optional log line are returned for the handler to apply.
|
||||
*/
|
||||
|
||||
import { splitClaudeEffortSuffix } from "../../config/providerModels.ts";
|
||||
import { isClaudeCodeCompatibleProvider } from "../../services/claudeCodeCompatible.ts";
|
||||
import { FORMATS } from "../../translator/formats.ts";
|
||||
|
||||
/**
|
||||
* True when the client already supplied an explicit reasoning effort (top-level reasoning_effort,
|
||||
* reasoning.effort, or output_config.effort) — in which case the stripped suffix must not overwrite
|
||||
* it. A blank string counts as "not supplied".
|
||||
*/
|
||||
function hasExplicitClaudeEffort(claudeBody: Record<string, unknown>): boolean {
|
||||
const explicitEffort =
|
||||
claudeBody.reasoning_effort ??
|
||||
(claudeBody.reasoning as Record<string, unknown> | undefined)?.effort ??
|
||||
(claudeBody.output_config as Record<string, unknown> | undefined)?.effort;
|
||||
return !(explicitEffort === undefined || explicitEffort === null || explicitEffort === "");
|
||||
}
|
||||
|
||||
export function applyClaudeEffortVariant(opts: {
|
||||
provider: string | null | undefined;
|
||||
effectiveModel: string;
|
||||
/** Mutated in place (model + reasoning_effort) when an effort suffix is stripped. */
|
||||
body: unknown;
|
||||
sourceFormat: string;
|
||||
}): { effectiveModel: string; log: string | null } {
|
||||
const { provider, body, sourceFormat } = opts;
|
||||
let effectiveModel = opts.effectiveModel;
|
||||
let log: string | null = null;
|
||||
|
||||
if (
|
||||
(provider === "claude" || isClaudeCodeCompatibleProvider(provider)) &&
|
||||
typeof effectiveModel === "string"
|
||||
) {
|
||||
const { baseModel, effort } = splitClaudeEffortSuffix(effectiveModel);
|
||||
if (effort) {
|
||||
effectiveModel = baseModel;
|
||||
if (body && typeof body === "object" && !Array.isArray(body)) {
|
||||
const claudeBody = body as Record<string, unknown>;
|
||||
claudeBody.model = baseModel;
|
||||
if (sourceFormat !== FORMATS.CLAUDE && !hasExplicitClaudeEffort(claudeBody)) {
|
||||
claudeBody.reasoning_effort = effort;
|
||||
}
|
||||
}
|
||||
log = `Claude effort variant: stripped "-${effort}" → ${baseModel} (reasoning_effort=${effort})`;
|
||||
}
|
||||
}
|
||||
|
||||
return { effectiveModel, log };
|
||||
}
|
||||
107
tests/unit/chatcore-claude-effort-variant.test.ts
Normal file
107
tests/unit/chatcore-claude-effort-variant.test.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
// tests/unit/chatcore-claude-effort-variant.test.ts
|
||||
// Characterization of applyClaudeEffortVariant — the Claude effort-suffix normalization extracted
|
||||
// from handleChatCore (chatCore god-file decomposition, #3501). The VS Code "Effort" slider
|
||||
// advertises claude-...-{low,medium,high,xhigh,max}; Anthropic has no such model, so the suffix is
|
||||
// stripped to the base id and surfaced as reasoning_effort. Locks: the provider gate (claude /
|
||||
// claude-code-compatible only), the in-place body mutation (model + reasoning_effort), the
|
||||
// sourceFormat==="claude" skip, the explicit-effort-wins rule, and the returned effectiveModel/log.
|
||||
import { test } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { applyClaudeEffortVariant } from "../../open-sse/handlers/chatCore/claudeEffortVariant.ts";
|
||||
import { FORMATS } from "../../open-sse/translator/formats.ts";
|
||||
|
||||
test("claude provider + effort suffix → strips to base, mutates body model + reasoning_effort, returns log", () => {
|
||||
const body: Record<string, unknown> = { model: "claude-sonnet-4-high", messages: [] };
|
||||
const r = applyClaudeEffortVariant({
|
||||
provider: "claude",
|
||||
effectiveModel: "claude-sonnet-4-high",
|
||||
body,
|
||||
sourceFormat: FORMATS.OPENAI,
|
||||
});
|
||||
assert.equal(r.effectiveModel, "claude-sonnet-4");
|
||||
assert.equal(body.model, "claude-sonnet-4");
|
||||
assert.equal(body.reasoning_effort, "high");
|
||||
assert.match(String(r.log), /stripped "-high" → claude-sonnet-4 \(reasoning_effort=high\)/);
|
||||
});
|
||||
|
||||
test("claude-code-compatible provider triggers the same stripping", () => {
|
||||
const body: Record<string, unknown> = { model: "claude-opus-4-xhigh", messages: [] };
|
||||
const r = applyClaudeEffortVariant({
|
||||
provider: "anthropic-compatible-cc-default",
|
||||
effectiveModel: "claude-opus-4-xhigh",
|
||||
body,
|
||||
sourceFormat: FORMATS.OPENAI,
|
||||
});
|
||||
assert.equal(r.effectiveModel, "claude-opus-4");
|
||||
assert.equal(body.model, "claude-opus-4");
|
||||
assert.equal(body.reasoning_effort, "xhigh");
|
||||
});
|
||||
|
||||
test("sourceFormat 'claude' strips the model but does NOT inject reasoning_effort", () => {
|
||||
const body: Record<string, unknown> = { model: "claude-sonnet-4-medium", messages: [] };
|
||||
const r = applyClaudeEffortVariant({
|
||||
provider: "claude",
|
||||
effectiveModel: "claude-sonnet-4-medium",
|
||||
body,
|
||||
sourceFormat: FORMATS.CLAUDE,
|
||||
});
|
||||
assert.equal(r.effectiveModel, "claude-sonnet-4");
|
||||
assert.equal(body.model, "claude-sonnet-4");
|
||||
assert.equal(body.reasoning_effort, undefined);
|
||||
});
|
||||
|
||||
test("an explicit client reasoning_effort wins (not overwritten)", () => {
|
||||
const body: Record<string, unknown> = { model: "claude-sonnet-4-low", reasoning_effort: "high", messages: [] };
|
||||
const r = applyClaudeEffortVariant({
|
||||
provider: "claude",
|
||||
effectiveModel: "claude-sonnet-4-low",
|
||||
body,
|
||||
sourceFormat: FORMATS.OPENAI,
|
||||
});
|
||||
assert.equal(r.effectiveModel, "claude-sonnet-4");
|
||||
assert.equal(body.reasoning_effort, "high"); // unchanged
|
||||
});
|
||||
|
||||
test("explicit effort nested under reasoning.effort also wins", () => {
|
||||
const body: Record<string, unknown> = {
|
||||
model: "claude-sonnet-4-low",
|
||||
reasoning: { effort: "medium" },
|
||||
messages: [],
|
||||
};
|
||||
const r = applyClaudeEffortVariant({
|
||||
provider: "claude",
|
||||
effectiveModel: "claude-sonnet-4-low",
|
||||
body,
|
||||
sourceFormat: FORMATS.OPENAI,
|
||||
});
|
||||
assert.equal(body.reasoning_effort, undefined); // explicit reasoning.effort present → no injection
|
||||
assert.equal(r.effectiveModel, "claude-sonnet-4");
|
||||
});
|
||||
|
||||
test("no effort suffix → no change, no log", () => {
|
||||
const body: Record<string, unknown> = { model: "claude-sonnet-4", messages: [] };
|
||||
const r = applyClaudeEffortVariant({
|
||||
provider: "claude",
|
||||
effectiveModel: "claude-sonnet-4",
|
||||
body,
|
||||
sourceFormat: FORMATS.OPENAI,
|
||||
});
|
||||
assert.equal(r.effectiveModel, "claude-sonnet-4");
|
||||
assert.equal(body.model, "claude-sonnet-4");
|
||||
assert.equal(body.reasoning_effort, undefined);
|
||||
assert.equal(r.log, null);
|
||||
});
|
||||
|
||||
test("non-claude provider is a no-op even with an effort suffix", () => {
|
||||
const body: Record<string, unknown> = { model: "gpt-5-high", messages: [] };
|
||||
const r = applyClaudeEffortVariant({
|
||||
provider: "openai",
|
||||
effectiveModel: "gpt-5-high",
|
||||
body,
|
||||
sourceFormat: FORMATS.OPENAI,
|
||||
});
|
||||
assert.equal(r.effectiveModel, "gpt-5-high");
|
||||
assert.equal(body.model, "gpt-5-high");
|
||||
assert.equal(body.reasoning_effort, undefined);
|
||||
assert.equal(r.log, null);
|
||||
});
|
||||
Reference in New Issue
Block a user