Merge remote-tracking branch 'origin/master' into gitea/feature/end

Resolved conflicts taking origin/master (v0.5.55) as canonical, with local
features re-applied:
- runtime log level (LOG_LEVEL env + dashboard Settings → Logging, applied
  immediately and persisted across restarts)
- free/noAuth provider enable/disable toggle via providerStrategies.enabled
- parallel model testing (Test All Models / Test Selected Keys)
This commit is contained in:
2026-08-17 00:38:31 +07:00
parent e7470e955e
commit 7e45ead2ac
557 changed files with 53396 additions and 6935 deletions

View File

@@ -6,6 +6,7 @@ import { safeParseJSON } from "../concerns/json.js";
import { parseDataUri } from "../concerns/image.js";
import { extractTextContent } from "../formats/gemini.js";
import { ROLE, OPENAI_BLOCK, CLAUDE_BLOCK } from "../schema/index.js";
import { getCapabilitiesForModel } from "../../providers/capabilities.js";
// Empty prefix matches real Claude Code behavior (no tool name prefix).
// Previously "proxy_" was used but this is a detectable fingerprint difference.
@@ -15,9 +16,13 @@ const CLAUDE_OAUTH_TOOL_PREFIX = "";
export function openaiToClaudeRequest(model, body, stream) {
// Tool name mapping for Claude OAuth (capitalizedName → originalName)
const toolNameMap = new Map();
// Cap max_tokens at the model's real output ceiling (e.g. Opus 4.8 = 128000),
// not the conservative 64000 default — otherwise a high-output model is
// pre-clamped here before prepareClaudeRequest's model-aware step runs.
const modelCeiling = getCapabilitiesForModel(null, model).maxOutput || undefined;
const result = {
model: model,
max_tokens: adjustMaxTokens(body),
max_tokens: adjustMaxTokens(body, modelCeiling),
stream: stream
};
@@ -148,7 +153,15 @@ Respond ONLY with the JSON object, no other text.`);
continue;
}
const toolData = toolType === OPENAI_BLOCK.FUNCTION && tool.function ? tool.function : tool;
// Function-shaped tools arrive in two flavors from real clients:
// (a) openai-spec: { type: "function", function: { name, ... } }
// (b) legacy/loose: { function: { name, ... } } (no parent `type`)
// Both must yield toolData.name = "echo". Treat the bare-function shape
// as a function tool too — Anthropic-compatible gateways (notably
// MiniMax M3 at api.minimaxi.com) reject payloads where this branch
// falls through with `toolData.name === undefined`, returning their
// upstream code (2013) "invalid tool type". See #2435.
const toolData = tool.function ?? tool;
const originalName = toolData.name;
// Claude OAuth requires prefixed tool names to avoid conflicts