Merge remote-tracking branch 'origin/farm/5ff08fcf/fix-kimi-title-thinking'

This commit is contained in:
can1357
2026-06-30 04:46:18 +02:00
9 changed files with 397 additions and 212 deletions
+3
View File
@@ -18,6 +18,9 @@
- Fixed safety setting application for Google Vertex AI models
- Ensured Gemini service tier is correctly passed through to the API
- Corrected priority request accounting for supported providers
### Fixed
- Fixed Kimi Code's Anthropic-compatible request path to keep thinking enabled and downgrade forced tool choice for Kimi K2.7 Code title generation. ([#3852](https://github.com/can1357/oh-my-pi/issues/3852))
## [16.2.6] - 2026-06-29
@@ -0,0 +1,112 @@
import { describe, expect, it } from "bun:test";
import { getBundledModel } from "@oh-my-pi/pi-catalog";
import type { Context } from "../../types";
import type { MessageCreateParamsStreaming } from "../anthropic-wire";
import { streamOpenAIAnthropicShim } from "../openai-anthropic-shim";
import {
applyChatCompletionsCompatPolicy,
type OpenAICompletionsParams,
resolveOpenAICompatPolicy,
} from "../openai-shared";
const BASE_CHAT_COMPLETIONS_PARAMS: OpenAICompletionsParams = { messages: [], model: "unused", stream: true };
const TITLE_CONTEXT: Context = {
systemPrompt: ["Generate a title."],
messages: [{ role: "user", content: "Explain the login failure", timestamp: 0 }],
tools: [
{
name: "set_title",
description: "Set title",
parameters: {
type: "object",
properties: { title: { type: "string" } },
required: ["title"],
additionalProperties: false,
},
},
],
};
describe("Kimi K2.7 Code thinking policy", () => {
it("omits disabled thinking for title-generator-style Kimi Code requests", () => {
const model = getBundledModel<"openai-completions">("kimi-code", "kimi-for-coding");
const policy = resolveOpenAICompatPolicy(model, {
endpoint: "chat-completions",
disableReasoning: true,
toolChoice: { type: "tool", name: "set_title" },
});
const params = { ...BASE_CHAT_COMPLETIONS_PARAMS };
applyChatCompletionsCompatPolicy(params, policy);
expect("thinking" in params).toBe(false);
expect(model.compat.supportsForcedToolChoice).toBe(false);
});
it("enables thinking and downgrades forced tool choice on Kimi Code's Anthropic endpoint", async () => {
const model = getBundledModel<"openai-completions">("kimi-code", "kimi-for-coding");
let payload: MessageCreateParamsStreaming | undefined;
const stream = streamOpenAIAnthropicShim(
model,
TITLE_CONTEXT,
{
apiKey: "test-key",
maxTokens: 1024,
disableReasoning: true,
toolChoice: { type: "tool", name: "set_title" },
onPayload: body => {
payload = body as MessageCreateParamsStreaming;
throw new Error("stop after payload capture");
},
},
{
anthropicBaseUrl: "https://api.kimi.com/coding",
defaultFormat: "anthropic",
},
);
await stream.result();
expect(payload?.thinking?.type).toBe("enabled");
expect(payload?.tool_choice).toEqual({ type: "auto" });
});
it("omits disabled thinking for native Moonshot Kimi K2.7 Code variants", () => {
for (const modelId of ["kimi-k2.7-code", "kimi-k2.7-code-highspeed"]) {
const model = getBundledModel<"openai-completions">("moonshot", modelId);
const policy = resolveOpenAICompatPolicy(model, {
endpoint: "chat-completions",
disableReasoning: true,
});
const params = { ...BASE_CHAT_COMPLETIONS_PARAMS };
applyChatCompletionsCompatPolicy(params, policy);
expect("thinking" in params).toBe(false);
expect(model.compat.supportsForcedToolChoice).toBe(false);
}
});
it("keeps the openai disable shape for non-native Kimi K2.7 Code aliases", () => {
for (const { provider, id } of [
{ provider: "fireworks", id: "kimi-k2.7-code" },
{ provider: "openrouter", id: "moonshotai/kimi-k2.7-code" },
] as const) {
const model = getBundledModel<"openai-completions">(provider, id);
expect(model.compat.supportsForcedToolChoice).toBe(true);
expect(model.compat.reasoningDisableMode).not.toBe("omit");
}
});
it("keeps explicit disabled thinking for Kimi K2.6", () => {
const model = getBundledModel<"openai-completions">("moonshot", "kimi-k2.6");
const policy = resolveOpenAICompatPolicy(model, {
endpoint: "chat-completions",
disableReasoning: true,
});
const params = { ...BASE_CHAT_COMPLETIONS_PARAMS };
applyChatCompletionsCompatPolicy(params, policy);
expect(params.thinking).toEqual({ type: "disabled" });
});
});
+6 -5
View File
@@ -2876,9 +2876,10 @@ function buildParams(
let thinking: MessageCreateParamsStreaming["thinking"] | undefined;
let outputConfigEffort: AnthropicOutputEffort | undefined;
if (model.reasoning) {
if (options?.thinkingEnabled) {
if (options?.thinkingEnabled || model.compat.requiresThinkingEnabled) {
const thinkingOptions = options ?? {};
const mode = model.thinking?.mode;
const effort = resolveAnthropicAdaptiveEffort(model, options);
const effort = resolveAnthropicAdaptiveEffort(model, thinkingOptions);
const compat = model.compat;
if (mode === "anthropic-adaptive" && !compat.disableAdaptiveThinking) {
const adaptive: { type: "adaptive"; display?: AnthropicThinkingDisplay } = { type: "adaptive" };
@@ -2889,15 +2890,15 @@ function buildParams(
// support: Opus 4.6 / Sonnet 4.6+ reject it with a 400, so an explicit
// `thinkingDisplay` MUST NOT force it onto a model that can't accept it.
if (model.thinking?.supportsDisplay) {
adaptive.display = options.thinkingDisplay ?? "summarized";
adaptive.display = thinkingOptions.thinkingDisplay ?? "summarized";
}
thinking = adaptive;
if (effort && effort !== "adaptive") outputConfigEffort = effort;
} else {
thinking = {
type: "enabled",
budget_tokens: options.thinkingBudgetTokens || 1024,
display: options.thinkingDisplay ?? "summarized",
budget_tokens: thinkingOptions.thinkingBudgetTokens || 1024,
display: thinkingOptions.thinkingDisplay ?? "summarized",
};
if (mode === "anthropic-budget-effort" && effort && effort !== "adaptive") outputConfigEffort = effort;
}
+4
View File
@@ -2,6 +2,10 @@
## [Unreleased]
### Fixed
- Fixed Kimi K2.7 Code compatibility to avoid disabled thinking and forced tool choice on native Kimi endpoints that require thinking mode. ([#3852](https://github.com/can1357/oh-my-pi/issues/3852))
## [16.2.6] - 2026-06-29
### Fixed
+11 -1
View File
@@ -28,6 +28,14 @@ export function isOfficialAnthropicApiUrl(baseUrl?: string): boolean {
return lower === OFFICIAL_ANTHROPIC_URL || lower.startsWith(`${OFFICIAL_ANTHROPIC_URL}/`);
}
/** Mirrors `compat/openai.ts`; native-only host gating is the caller's responsibility. */
const KIMI_K27_CODE_MODEL_PATTERN = /(?:^|\/)kimi[-._]?k2(?:[._-]?|p)7[-._]?code(?:[-._]?highspeed)?$/i;
function matchesKimiK27CodeFamily(spec: ModelSpec<"anthropic-messages">): boolean {
if (KIMI_K27_CODE_MODEL_PATTERN.test(spec.id)) return true;
return spec.id === "kimi-for-coding" && /k2\.?7 code/i.test(spec.name ?? "");
}
/** Build the resolved anthropic-messages compat record for a model spec. */
export function buildAnthropicCompat(spec: ModelSpec<"anthropic-messages">): ResolvedAnthropicCompat {
const baseUrl = spec.baseUrl;
@@ -40,6 +48,7 @@ export function buildAnthropicCompat(spec: ModelSpec<"anthropic-messages">): Res
// doesn't whitelist the `fine-grained-tool-streaming-2025-05-14` beta either
// (issue #2558), so eager tool-input streaming is unavailable on this host.
const isCopilot = modelMatchesHost(spec, "githubCopilot");
const requiresThinkingEnabled = modelMatchesHost(spec, "moonshotNative") && matchesKimiK27CodeFamily(spec);
const compat: ResolvedAnthropicCompat = {
officialEndpoint: official,
disableStrictTools: false,
@@ -53,12 +62,13 @@ export function buildAnthropicCompat(spec: ModelSpec<"anthropic-messages">): Res
// detection requires the canonical api.anthropic.com host plus a
// supported model id.
supportsMidConversationSystem: official && supportsMidConversationSystemMessages(spec.id),
supportsForcedToolChoice: !isAnthropicFableOrMythosModel(spec.id),
supportsForcedToolChoice: !requiresThinkingEnabled && !isAnthropicFableOrMythosModel(spec.id),
// Opus 4.7+ and Fable/Mythos reject temperature/top_p/top_k with a 400.
supportsSamplingParams: !hasOpus47ApiRestrictions(spec.id),
// Z.AI workaround (issue #814): its proxy deserializes tool_result blocks
// into a class that reads `.id`.
requiresToolResultId: isZai,
requiresThinkingEnabled,
// Official Anthropic enforces signature-based thinking-chain integrity, so
// unsigned thinking blocks must stay text there. Anthropic-compatible
// reasoning endpoints commonly emit unsigned thinking blocks while still
+19 -2
View File
@@ -39,6 +39,20 @@ const GLM_CODING_PLAN_STREAM_IDLE_TIMEOUT_MS = 600_000;
const DEEPSEEK_REASONING_STREAM_IDLE_TIMEOUT_MS = 300_000;
/** Kimi K2.6 can spend several minutes reasoning before the first visible token. */
const KIMI_K26_REASONING_STREAM_IDLE_TIMEOUT_MS = 300_000;
/**
* Native Kimi K2.7 Code requires `thinking.type: "enabled"` and rejects
* disabled thinking. Match the public id, its Fast variant, and the
* `kimi-code/kimi-for-coding` alias (which keeps the family name).
* Caller-disabled requests on non-native dialects (Fireworks `openai`,
* OpenRouter `openrouter`, …) MUST keep their per-dialect disable shape —
* gating on `isMoonshotKimi` is the caller's responsibility.
*/
const KIMI_K27_CODE_MODEL_PATTERN = /(?:^|\/)kimi[-._]?k2(?:[._-]?|p)7[-._]?code(?:[-._]?highspeed)?$/i;
function matchesKimiK27CodeFamily(spec: ModelSpec<"openai-completions">): boolean {
if (KIMI_K27_CODE_MODEL_PATTERN.test(spec.id)) return true;
return spec.id === "kimi-for-coding" && /k2\.?7 code/i.test(spec.name ?? "");
}
/** Xiaomi MiMo Pro on api.xiaomimimo.com can stall ~2min before the first event (issue #1770). */
const XIAOMI_MIMO_STREAM_IDLE_TIMEOUT_MS = 300_000;
/** Alibaba Coding Plan (coding-intl.dashscope) qwen models idle before the first event (issue #1770). */
@@ -231,6 +245,7 @@ export function buildOpenAICompat(spec: ModelSpec<"openai-completions">): Resolv
const isKimiModel = isKimiModelId(spec.id);
const isMoonshotNative = modelMatchesHost(hostModel, "moonshotNative");
const isMoonshotKimi = isKimiModel && isMoonshotNative;
const requiresEnabledThinking = isMoonshotKimi && matchesKimiK27CodeFamily(spec);
const usesMoonshotKimiPreservedThinking = isMoonshotKimi && isKimiK26ModelId(spec.id);
const isAnthropicModel =
modelMatchesHost(hostModel, "anthropic") || isClaudeModelId(spec.id) || isAnthropicNamespacedModelId(spec.id);
@@ -403,7 +418,7 @@ export function buildOpenAICompat(spec: ModelSpec<"openai-completions">): Resolv
disableReasoningOnForcedToolChoice: isKimiModel || isAnthropicModel,
disableReasoningOnToolChoice: isDeepseekFamily && Boolean(spec.reasoning) && !isOpenRouter,
supportsToolChoice: !isDirectDeepseekReasoning,
supportsForcedToolChoice: true,
supportsForcedToolChoice: !requiresEnabledThinking,
supportsNamedToolChoice: provider !== "llama.cpp",
maxTokensField: useMaxTokens ? "max_tokens" : "max_completion_tokens",
requiresToolResultName: isMistral,
@@ -509,7 +524,9 @@ export function buildOpenAICompat(spec: ModelSpec<"openai-completions">): Resolv
applyCompatOverrides(compat, spec.compat);
if (spec.compat?.reasoningDisableMode === undefined) {
compat.reasoningDisableMode = resolveReasoningDisableMode(compat.thinkingFormat);
compat.reasoningDisableMode = requiresEnabledThinking
? "omit"
: resolveReasoningDisableMode(compat.thinkingFormat);
}
if (spec.compat?.omitReasoningEffort === undefined && !compat.supportsReasoningEffort) {
compat.omitReasoningEffort = true;
+236 -203
View File
@@ -2476,7 +2476,7 @@
"api": "openai-completions",
"provider": "aimlapi",
"baseUrl": "https://api.aimlapi.com/v1",
"reasoning": true,
"reasoning": false,
"input": [
"text"
],
@@ -2487,24 +2487,7 @@
"cacheWrite": 0
},
"contextWindow": 163840,
"maxTokens": 16384,
"thinking": {
"mode": "effort",
"efforts": [
"minimal",
"low",
"medium",
"high",
"xhigh"
],
"effortMap": {
"minimal": "high",
"low": "high",
"medium": "high",
"high": "high",
"xhigh": "max"
}
}
"maxTokens": 16384
},
"deepseek/deepseek-chat-v3.1": {
"id": "deepseek/deepseek-chat-v3.1",
@@ -10620,6 +10603,35 @@
]
}
},
"xai.grok-4.3": {
"id": "xai.grok-4.3",
"name": "Grok 4.3",
"api": "bedrock-converse-stream",
"provider": "amazon-bedrock",
"baseUrl": "https://bedrock-runtime.us-east-1.amazonaws.com",
"reasoning": true,
"input": [
"text",
"image"
],
"cost": {
"input": 1.25,
"output": 2.5,
"cacheRead": 0.2,
"cacheWrite": 0
},
"contextWindow": 1000000,
"maxTokens": 131072,
"thinking": {
"mode": "budget",
"efforts": [
"minimal",
"low",
"medium",
"high"
]
}
},
"zai.glm-4.7": {
"id": "zai.glm-4.7",
"name": "GLM-4.7",
@@ -13672,7 +13684,7 @@
"api": "openai-completions",
"provider": "coreweave",
"baseUrl": "https://api.inference.wandb.ai/v1",
"reasoning": true,
"reasoning": false,
"input": [
"text"
],
@@ -13683,17 +13695,7 @@
"cacheWrite": 0
},
"contextWindow": 128000,
"maxTokens": 128000,
"thinking": {
"mode": "effort",
"efforts": [
"minimal",
"low",
"medium",
"high",
"xhigh"
]
}
"maxTokens": 128000
},
"meta-llama/Llama-3.3-70B-Instruct": {
"id": "meta-llama/Llama-3.3-70B-Instruct",
@@ -13701,7 +13703,7 @@
"api": "openai-completions",
"provider": "coreweave",
"baseUrl": "https://api.inference.wandb.ai/v1",
"reasoning": true,
"reasoning": false,
"input": [
"text"
],
@@ -13712,17 +13714,7 @@
"cacheWrite": 0
},
"contextWindow": 128000,
"maxTokens": 128000,
"thinking": {
"mode": "effort",
"efforts": [
"minimal",
"low",
"medium",
"high",
"xhigh"
]
}
"maxTokens": 128000
},
"meta-llama/Llama-4-Scout-17B-16E-Instruct": {
"id": "meta-llama/Llama-4-Scout-17B-16E-Instruct",
@@ -13730,7 +13722,7 @@
"api": "openai-completions",
"provider": "coreweave",
"baseUrl": "https://api.inference.wandb.ai/v1",
"reasoning": true,
"reasoning": false,
"input": [
"text",
"image"
@@ -13742,17 +13734,7 @@
"cacheWrite": 0
},
"contextWindow": 64000,
"maxTokens": 64000,
"thinking": {
"mode": "effort",
"efforts": [
"minimal",
"low",
"medium",
"high",
"xhigh"
]
}
"maxTokens": 64000
},
"microsoft/Phi-4-mini-instruct": {
"id": "microsoft/Phi-4-mini-instruct",
@@ -13760,7 +13742,7 @@
"api": "openai-completions",
"provider": "coreweave",
"baseUrl": "https://api.inference.wandb.ai/v1",
"reasoning": true,
"reasoning": false,
"input": [
"text"
],
@@ -13771,17 +13753,7 @@
"cacheWrite": 0
},
"contextWindow": 128000,
"maxTokens": 128000,
"thinking": {
"mode": "effort",
"efforts": [
"minimal",
"low",
"medium",
"high",
"xhigh"
]
}
"maxTokens": 128000
},
"MiniMaxAI/MiniMax-M2.5": {
"id": "MiniMaxAI/MiniMax-M2.5",
@@ -13789,7 +13761,7 @@
"api": "openai-completions",
"provider": "coreweave",
"baseUrl": "https://api.inference.wandb.ai/v1",
"reasoning": false,
"reasoning": true,
"input": [
"text"
],
@@ -13800,7 +13772,16 @@
"cacheWrite": 0
},
"contextWindow": 196608,
"maxTokens": 196608
"maxTokens": 196608,
"thinking": {
"mode": "effort",
"efforts": [
"low",
"medium",
"high"
],
"requiresEffort": true
}
},
"moonshotai/Kimi-K2.5": {
"id": "moonshotai/Kimi-K2.5",
@@ -13898,7 +13879,7 @@
"api": "openai-completions",
"provider": "coreweave",
"baseUrl": "https://api.inference.wandb.ai/v1",
"reasoning": false,
"reasoning": true,
"input": [
"text"
],
@@ -13909,7 +13890,17 @@
"cacheWrite": 0
},
"contextWindow": 262144,
"maxTokens": 262144
"maxTokens": 262144,
"thinking": {
"mode": "effort",
"efforts": [
"minimal",
"low",
"medium",
"high",
"xhigh"
]
}
},
"nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B": {
"id": "nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B",
@@ -21734,7 +21725,7 @@
"cost": {
"input": 0.075,
"output": 0.3,
"cacheRead": 0.037,
"cacheRead": 0,
"cacheWrite": 0
},
"contextWindow": 131072,
@@ -22420,13 +22411,13 @@
"text"
],
"cost": {
"input": 0,
"output": 0,
"input": 0.25,
"output": 0.69,
"cacheRead": 0,
"cacheWrite": 0
},
"contextWindow": 131072,
"maxTokens": 65536,
"maxTokens": 32768,
"thinking": {
"mode": "effort",
"efforts": [
@@ -25048,7 +25039,7 @@
"api": "openai-completions",
"provider": "kilo",
"baseUrl": "https://api.kilo.ai/api/gateway",
"reasoning": true,
"reasoning": false,
"input": [
"text"
],
@@ -25059,24 +25050,7 @@
"cacheWrite": 0
},
"contextWindow": 163840,
"maxTokens": 65536,
"thinking": {
"mode": "effort",
"efforts": [
"minimal",
"low",
"medium",
"high",
"xhigh"
],
"effortMap": {
"minimal": "high",
"low": "high",
"medium": "high",
"high": "high",
"xhigh": "max"
}
}
"maxTokens": 65536
},
"deepseek/deepseek-chat-v3.1": {
"id": "deepseek/deepseek-chat-v3.1",
@@ -30816,6 +30790,7 @@
"supportsStrictMode": false,
"toolStrictMode": "mixed",
"stripDeepseekSpecialTokens": false,
"streamMarkupHealingPattern": "thinking",
"reasoningDeltasMayBeCumulative": false,
"emptyLengthFinishIsContextError": false,
"usesOpenAIToolCallIdLimit": false,
@@ -54444,6 +54419,36 @@
"requiresEffort": true
}
},
"minimaxai/minimax-m3": {
"id": "minimaxai/minimax-m3",
"name": "MiniMax-M3",
"api": "openai-completions",
"provider": "nvidia",
"baseUrl": "https://integrate.api.nvidia.com/v1",
"reasoning": true,
"input": [
"text",
"image"
],
"cost": {
"input": 0,
"output": 0,
"cacheRead": 0,
"cacheWrite": 0
},
"contextWindow": 1000000,
"maxTokens": 16384,
"thinking": {
"mode": "effort",
"efforts": [
"minimal",
"low",
"medium",
"high",
"xhigh"
]
}
},
"mistralai/codestral-22b-instruct-v0.1": {
"id": "mistralai/codestral-22b-instruct-v0.1",
"name": "Codestral 22b Instruct V0.1",
@@ -62195,9 +62200,9 @@
"image"
],
"cost": {
"input": 0.66,
"output": 3.41,
"cacheRead": 0.144,
"input": 0.55,
"output": 3.1999999999999997,
"cacheRead": 0.11,
"cacheWrite": 0
},
"contextWindow": 262144,
@@ -63522,7 +63527,7 @@
"api": "openrouter",
"baseUrl": "https://openrouter.ai/api/v1",
"provider": "openrouter",
"reasoning": true,
"reasoning": false,
"input": [
"text"
],
@@ -63533,22 +63538,7 @@
"cacheWrite": 0
},
"contextWindow": 163840,
"maxTokens": 16384,
"thinking": {
"mode": "effort",
"efforts": [
"minimal",
"low",
"medium",
"high"
],
"effortMap": {
"minimal": "high",
"low": "high",
"medium": "high",
"high": "high"
}
}
"maxTokens": 16384
},
"deepseek/deepseek-chat-v3.1": {
"id": "deepseek/deepseek-chat-v3.1",
@@ -65751,7 +65741,7 @@
"cacheWrite": 0
},
"contextWindow": 131072,
"maxTokens": 32768
"maxTokens": 100352
},
"moonshotai/kimi-k2-0905": {
"id": "moonshotai/kimi-k2-0905",
@@ -65770,7 +65760,7 @@
"cacheWrite": 0
},
"contextWindow": 262144,
"maxTokens": 262144
"maxTokens": 100352
},
"moonshotai/kimi-k2-0905:exacto": {
"id": "moonshotai/kimi-k2-0905:exacto",
@@ -65861,9 +65851,9 @@
"image"
],
"cost": {
"input": 0.66,
"output": 3.41,
"cacheRead": 0.144,
"input": 0.55,
"output": 3.1999999999999997,
"cacheRead": 0.11,
"cacheWrite": 0
},
"contextWindow": 262144,
@@ -69347,8 +69337,8 @@
"image"
],
"cost": {
"input": 0.28850000000000003,
"output": 2.65,
"input": 0.2596,
"output": 2.3850000000000002,
"cacheRead": 0.15,
"cacheWrite": 0
},
@@ -69758,13 +69748,13 @@
"text"
],
"cost": {
"input": 0.09,
"input": 0.09999999999999999,
"output": 0.3,
"cacheRead": 0.02,
"cacheWrite": 0
},
"contextWindow": 262144,
"maxTokens": 16384,
"maxTokens": 65536,
"thinking": {
"mode": "effort",
"efforts": [
@@ -70846,8 +70836,8 @@
"text"
],
"cost": {
"input": 0.98,
"output": 3.08,
"input": 0.975,
"output": 4.300000000000001,
"cacheRead": 0.182,
"cacheWrite": 0
},
@@ -70874,7 +70864,7 @@
"text"
],
"cost": {
"input": 0.95,
"input": 0.94,
"output": 3,
"cacheRead": 0.18,
"cacheWrite": 0
@@ -71096,7 +71086,7 @@
"synthetic": {
"hf:MiniMaxAI/MiniMax-M3": {
"id": "hf:MiniMaxAI/MiniMax-M3",
"name": "MiniMaxAI/MiniMax-M3",
"name": "MiniMax-M3",
"api": "openai-completions",
"provider": "synthetic",
"baseUrl": "https://api.synthetic.new/openai/v1",
@@ -71111,7 +71101,7 @@
"cacheRead": 0.6,
"cacheWrite": 0
},
"contextWindow": 262144,
"contextWindow": 524288,
"maxTokens": 65536,
"thinking": {
"mode": "effort",
@@ -71126,7 +71116,7 @@
},
"hf:moonshotai/Kimi-K2.6": {
"id": "hf:moonshotai/Kimi-K2.6",
"name": "moonshotai/Kimi-K2.6",
"name": "Kimi K2.6",
"api": "openai-completions",
"provider": "synthetic",
"baseUrl": "https://api.synthetic.new/openai/v1",
@@ -71156,7 +71146,7 @@
},
"hf:nvidia/NVIDIA-Nemotron-3-Super-120B-A12B-NVFP4": {
"id": "hf:nvidia/NVIDIA-Nemotron-3-Super-120B-A12B-NVFP4",
"name": "nvidia/NVIDIA-Nemotron-3-Super-120B-A12B-NVFP4",
"name": "Nemotron 3 Super 120B A12B",
"api": "openai-completions",
"provider": "synthetic",
"baseUrl": "https://api.synthetic.new/openai/v1",
@@ -71185,7 +71175,7 @@
},
"hf:openai/gpt-oss-120b": {
"id": "hf:openai/gpt-oss-120b",
"name": "openai/gpt-oss-120b",
"name": "GPT OSS 120B",
"api": "openai-completions",
"provider": "synthetic",
"baseUrl": "https://api.synthetic.new/openai/v1",
@@ -71196,7 +71186,7 @@
"cost": {
"input": 0.1,
"output": 0.1,
"cacheRead": 0,
"cacheRead": 0.1,
"cacheWrite": 0
},
"contextWindow": 131072,
@@ -71212,7 +71202,7 @@
},
"hf:Qwen/Qwen3.5-397B-A17B": {
"id": "hf:Qwen/Qwen3.5-397B-A17B",
"name": "Qwen/Qwen3.5-397B-A17B",
"name": "Qwen3.5 397B-A17B",
"api": "openai-completions",
"provider": "synthetic",
"baseUrl": "https://api.synthetic.new/openai/v1",
@@ -71223,7 +71213,7 @@
],
"cost": {
"input": 0.6,
"output": 3,
"output": 3.6,
"cacheRead": 0.6,
"cacheWrite": 0
},
@@ -71241,26 +71231,36 @@
},
"hf:Qwen/Qwen3.6-27B": {
"id": "hf:Qwen/Qwen3.6-27B",
"name": "Qwen/Qwen3.6-27B",
"name": "Qwen3.6 27B",
"api": "openai-completions",
"provider": "synthetic",
"baseUrl": "https://api.synthetic.new/openai/v1",
"reasoning": false,
"reasoning": true,
"input": [
"text"
"text",
"image"
],
"cost": {
"input": 0,
"output": 0,
"cacheRead": 0,
"input": 0.45,
"output": 3.6,
"cacheRead": 0.45,
"cacheWrite": 0
},
"contextWindow": 262144,
"maxTokens": 8192
"maxTokens": 65536,
"thinking": {
"mode": "effort",
"efforts": [
"minimal",
"low",
"medium",
"high"
]
}
},
"hf:zai-org/GLM-4.7": {
"id": "hf:zai-org/GLM-4.7",
"name": "zai-org/GLM-4.7",
"name": "GLM-4.7",
"api": "openai-completions",
"provider": "synthetic",
"baseUrl": "https://api.synthetic.new/openai/v1",
@@ -71269,13 +71269,13 @@
"text"
],
"cost": {
"input": 0.55,
"input": 0.45,
"output": 2.19,
"cacheRead": 0,
"cacheRead": 0.45,
"cacheWrite": 0
},
"contextWindow": 202752,
"maxTokens": 64000,
"maxTokens": 65536,
"thinking": {
"mode": "effort",
"efforts": [
@@ -71289,7 +71289,7 @@
},
"hf:zai-org/GLM-4.7-Flash": {
"id": "hf:zai-org/GLM-4.7-Flash",
"name": "zai-org/GLM-4.7-Flash",
"name": "GLM-4.7-Flash",
"api": "openai-completions",
"provider": "synthetic",
"baseUrl": "https://api.synthetic.new/openai/v1",
@@ -71298,9 +71298,9 @@
"text"
],
"cost": {
"input": 0.06,
"output": 0.4,
"cacheRead": 0.06,
"input": 0.1,
"output": 0.5,
"cacheRead": 0.1,
"cacheWrite": 0
},
"contextWindow": 196608,
@@ -71318,7 +71318,7 @@
},
"hf:zai-org/GLM-5.1": {
"id": "hf:zai-org/GLM-5.1",
"name": "zai-org/GLM-5.1",
"name": "GLM-5.1",
"api": "openai-completions",
"provider": "synthetic",
"baseUrl": "https://api.synthetic.new/openai/v1",
@@ -71347,22 +71347,32 @@
},
"hf:zai-org/GLM-5.2": {
"id": "hf:zai-org/GLM-5.2",
"name": "zai-org/GLM-5.2",
"name": "GLM-5.2",
"api": "openai-completions",
"provider": "synthetic",
"baseUrl": "https://api.synthetic.new/openai/v1",
"reasoning": false,
"reasoning": true,
"input": [
"text"
],
"cost": {
"input": 0,
"output": 0,
"cacheRead": 0,
"input": 1.4,
"output": 4.4,
"cacheRead": 1.4,
"cacheWrite": 0
},
"contextWindow": 524288,
"maxTokens": 8192
"maxTokens": 65536,
"thinking": {
"mode": "effort",
"efforts": [
"minimal",
"low",
"medium",
"high",
"xhigh"
]
}
},
"syn:large:text": {
"id": "syn:large:text",
@@ -71682,7 +71692,7 @@
"api": "openai-completions",
"provider": "together",
"baseUrl": "https://api.together.xyz/v1",
"reasoning": true,
"reasoning": false,
"input": [
"text",
"image"
@@ -71694,17 +71704,7 @@
"cacheWrite": 0.18
},
"contextWindow": 10000000,
"maxTokens": 32768,
"thinking": {
"mode": "effort",
"efforts": [
"minimal",
"low",
"medium",
"high",
"xhigh"
]
}
"maxTokens": 32768
},
"MiniMaxAI/MiniMax-M2.5": {
"id": "MiniMaxAI/MiniMax-M2.5",
@@ -72381,6 +72381,38 @@
"escapeBuiltinToolNames": true
}
},
"umans-glm-5.2-nvfp4": {
"id": "umans-glm-5.2-nvfp4",
"name": "Umans GLM 5.2 NVFP4 (experimental, short test from Jun 29)",
"api": "anthropic-messages",
"provider": "umans",
"baseUrl": "https://api.code.umans.ai",
"reasoning": true,
"thinking": {
"mode": "anthropic-budget-effort",
"efforts": [
"high",
"xhigh"
],
"effortMap": {
"xhigh": "max"
}
},
"input": [
"text"
],
"cost": {
"input": 0,
"output": 0,
"cacheRead": 0,
"cacheWrite": 0
},
"contextWindow": 405504,
"maxTokens": 131071,
"compat": {
"escapeBuiltinToolNames": true
}
},
"umans-kimi-k2.7": {
"id": "umans-kimi-k2.7",
"name": "Umans Kimi K2.7 Code",
@@ -75747,6 +75779,7 @@
"supportsForcedToolChoice": true,
"supportsSamplingParams": true,
"requiresToolResultId": false,
"requiresThinkingEnabled": false,
"replayUnsignedThinking": false,
"escapeBuiltinToolNames": false
}
@@ -80633,7 +80666,7 @@
},
"zai/glm-4.5": {
"id": "zai/glm-4.5",
"name": "GLM-4.5",
"name": "GLM 4.5",
"api": "anthropic-messages",
"baseUrl": "https://ai-gateway.vercel.sh",
"provider": "vercel-ai-gateway",
@@ -82062,6 +82095,14 @@
},
"contextWindow": 2000000,
"maxTokens": 2000000,
"compat": {
"reasoningEffortMap": {
"minimal": "low"
},
"includeEncryptedReasoning": false,
"filterReasoningHistory": true,
"omitReasoningEffort": false
},
"thinking": {
"mode": "effort",
"efforts": [
@@ -82074,14 +82115,6 @@
"effortMap": {
"minimal": "low"
}
},
"compat": {
"reasoningEffortMap": {
"minimal": "low"
},
"includeEncryptedReasoning": false,
"filterReasoningHistory": true,
"omitReasoningEffort": false
}
},
"grok-4.3": {
@@ -82103,6 +82136,14 @@
},
"contextWindow": 1000000,
"maxTokens": 1000000,
"compat": {
"reasoningEffortMap": {
"minimal": "low"
},
"includeEncryptedReasoning": false,
"filterReasoningHistory": true,
"omitReasoningEffort": false
},
"thinking": {
"mode": "effort",
"efforts": [
@@ -82115,14 +82156,6 @@
"effortMap": {
"minimal": "low"
}
},
"compat": {
"reasoningEffortMap": {
"minimal": "low"
},
"includeEncryptedReasoning": false,
"filterReasoningHistory": true,
"omitReasoningEffort": false
}
},
"grok-build": {
@@ -82174,12 +82207,12 @@
"contextWindow": 256000,
"maxTokens": 256000,
"compat": {
"includeEncryptedReasoning": false,
"filterReasoningHistory": true,
"omitReasoningEffort": true,
"reasoningEffortMap": {
"minimal": "low"
},
"includeEncryptedReasoning": false,
"filterReasoningHistory": true,
"omitReasoningEffort": true,
"supportsReasoningEffort": false
}
},
@@ -82223,9 +82256,9 @@
"text"
],
"cost": {
"input": 0.1,
"output": 0.3,
"cacheRead": 0.01,
"input": 0.14,
"output": 0.28,
"cacheRead": 0.0028,
"cacheWrite": 0
},
"contextWindow": 262144,
@@ -82259,9 +82292,9 @@
"image"
],
"cost": {
"input": 0.4,
"output": 2,
"cacheRead": 0.08,
"input": 0.14,
"output": 0.28,
"cacheRead": 0.0028,
"cacheWrite": 0
},
"contextWindow": 262144,
@@ -82294,9 +82327,9 @@
"text"
],
"cost": {
"input": 1,
"output": 3,
"cacheRead": 0.2,
"input": 0.435,
"output": 0.87,
"cacheRead": 0.0036,
"cacheWrite": 0
},
"contextWindow": 1048576,
@@ -82330,9 +82363,9 @@
"image"
],
"cost": {
"input": 0.4,
"output": 2,
"cacheRead": 0.08,
"input": 0.14,
"output": 0.28,
"cacheRead": 0.0028,
"cacheWrite": 0
},
"contextWindow": 1048576,
@@ -82365,9 +82398,9 @@
"text"
],
"cost": {
"input": 1,
"output": 3,
"cacheRead": 0.2,
"input": 0.435,
"output": 0.87,
"cacheRead": 0.0036,
"cacheWrite": 0
},
"contextWindow": 1048576,
@@ -1294,7 +1294,7 @@ export function clampFireworksKimiMaxTokens(modelId: string, candidate: number |
export const KIMI_K27_CODE_RECOMMENDED_MAX_TOKENS = 32_768;
export function isKimiK27CodeModelId(modelId: string): boolean {
return /(?:^|\/)kimi[-._]?k2(?:[._-]?|p)7[-._]?code$/i.test(modelId);
return /(?:^|\/)kimi[-._]?k2(?:[._-]?|p)7[-._]?code(?:[-._]?highspeed)?$/i.test(modelId);
}
export function clampKimiK27CodeMaxTokens(modelId: string, candidate: number): number;
+5
View File
@@ -420,6 +420,11 @@ export interface AnthropicCompat {
* Default: auto-detected from provider/baseUrl and `model.reasoning`.
*/
replayUnsignedThinking?: boolean;
/**
* Whether the endpoint requires `thinking.type: "enabled"` whenever the
* model reasons. Use for models that reject omitted or disabled thinking.
*/
requiresThinkingEnabled?: boolean;
/**
* Prefix Anthropic built-in tool names (`web_search`, `code_execution`, ...)
* when they are ordinary client tools. Some Anthropic-compatible gateways