fix(ai): use OpenRouter reasoning payload (#2298)
* fix(ai): use OpenRouter reasoning payload * fix(coding-agent): stop updating packages on startup closes #1963 * fix(ai): add openrouter thinkingFormat compat --------- Co-authored-by: Mario Zechner <badlogicgames@gmail.com>
This commit is contained in:
@@ -408,6 +408,12 @@ function buildParams(model: Model<"openai-completions">, context: Context, optio
|
|||||||
(params as any).enable_thinking = !!options?.reasoningEffort;
|
(params as any).enable_thinking = !!options?.reasoningEffort;
|
||||||
} else if (compat.thinkingFormat === "qwen-chat-template" && model.reasoning) {
|
} else if (compat.thinkingFormat === "qwen-chat-template" && model.reasoning) {
|
||||||
(params as any).chat_template_kwargs = { enable_thinking: !!options?.reasoningEffort };
|
(params as any).chat_template_kwargs = { enable_thinking: !!options?.reasoningEffort };
|
||||||
|
} else if (compat.thinkingFormat === "openrouter" && options?.reasoningEffort && model.reasoning) {
|
||||||
|
// OpenRouter normalizes reasoning across providers via a nested reasoning object.
|
||||||
|
const openRouterParams = params as typeof params & { reasoning?: { effort?: string } };
|
||||||
|
openRouterParams.reasoning = {
|
||||||
|
effort: mapReasoningEffort(options.reasoningEffort, compat.reasoningEffortMap),
|
||||||
|
};
|
||||||
} else if (options?.reasoningEffort && model.reasoning && compat.supportsReasoningEffort) {
|
} else if (options?.reasoningEffort && model.reasoning && compat.supportsReasoningEffort) {
|
||||||
// OpenAI-style reasoning_effort
|
// OpenAI-style reasoning_effort
|
||||||
(params as any).reasoning_effort = mapReasoningEffort(options.reasoningEffort, compat.reasoningEffortMap);
|
(params as any).reasoning_effort = mapReasoningEffort(options.reasoningEffort, compat.reasoningEffortMap);
|
||||||
@@ -816,7 +822,11 @@ function detectCompat(model: Model<"openai-completions">): Required<OpenAIComple
|
|||||||
requiresToolResultName: false,
|
requiresToolResultName: false,
|
||||||
requiresAssistantAfterToolResult: false,
|
requiresAssistantAfterToolResult: false,
|
||||||
requiresThinkingAsText: false,
|
requiresThinkingAsText: false,
|
||||||
thinkingFormat: isZai ? "zai" : "openai",
|
thinkingFormat: isZai
|
||||||
|
? "zai"
|
||||||
|
: provider === "openrouter" || baseUrl.includes("openrouter.ai")
|
||||||
|
? "openrouter"
|
||||||
|
: "openai",
|
||||||
openRouterRouting: {},
|
openRouterRouting: {},
|
||||||
vercelGatewayRouting: {},
|
vercelGatewayRouting: {},
|
||||||
supportsStrictMode: true,
|
supportsStrictMode: true,
|
||||||
|
|||||||
@@ -271,8 +271,8 @@ export interface OpenAICompletionsCompat {
|
|||||||
requiresAssistantAfterToolResult?: boolean;
|
requiresAssistantAfterToolResult?: boolean;
|
||||||
/** Whether thinking blocks must be converted to text blocks with <thinking> delimiters. Default: auto-detected from URL. */
|
/** Whether thinking blocks must be converted to text blocks with <thinking> delimiters. Default: auto-detected from URL. */
|
||||||
requiresThinkingAsText?: boolean;
|
requiresThinkingAsText?: boolean;
|
||||||
/** Format for reasoning/thinking parameter. "openai" uses reasoning_effort, "zai" uses top-level enable_thinking: boolean, "qwen" uses top-level enable_thinking: boolean, and "qwen-chat-template" uses chat_template_kwargs.enable_thinking. Default: "openai". */
|
/** Format for reasoning/thinking parameter. "openai" uses reasoning_effort, "openrouter" uses reasoning: { effort }, "zai" uses top-level enable_thinking: boolean, "qwen" uses top-level enable_thinking: boolean, and "qwen-chat-template" uses chat_template_kwargs.enable_thinking. Default: "openai". */
|
||||||
thinkingFormat?: "openai" | "zai" | "qwen" | "qwen-chat-template";
|
thinkingFormat?: "openai" | "openrouter" | "zai" | "qwen" | "qwen-chat-template";
|
||||||
/** OpenRouter-specific routing preferences. Only used when baseUrl points to OpenRouter. */
|
/** OpenRouter-specific routing preferences. Only used when baseUrl points to OpenRouter. */
|
||||||
openRouterRouting?: OpenRouterRouting;
|
openRouterRouting?: OpenRouterRouting;
|
||||||
/** Vercel AI Gateway routing preferences. Only used when baseUrl points to Vercel AI Gateway. */
|
/** Vercel AI Gateway routing preferences. Only used when baseUrl points to Vercel AI Gateway. */
|
||||||
|
|||||||
@@ -233,4 +233,36 @@ describe("openai-completions tool_choice", () => {
|
|||||||
expect(response.stopReason).toBe("error");
|
expect(response.stopReason).toBe("error");
|
||||||
expect(response.errorMessage).toBe("Provider finish_reason: network_error");
|
expect(response.errorMessage).toBe("Provider finish_reason: network_error");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("uses OpenRouter reasoning object instead of reasoning_effort", async () => {
|
||||||
|
const model = getModel("openrouter", "deepseek/deepseek-r1")!;
|
||||||
|
let payload: unknown;
|
||||||
|
|
||||||
|
await streamSimple(
|
||||||
|
model,
|
||||||
|
{
|
||||||
|
messages: [
|
||||||
|
{
|
||||||
|
role: "user",
|
||||||
|
content: "Hi",
|
||||||
|
timestamp: Date.now(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
apiKey: "test",
|
||||||
|
reasoning: "high",
|
||||||
|
onPayload: (params: unknown) => {
|
||||||
|
payload = params;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
).result();
|
||||||
|
|
||||||
|
const params = (payload ?? mockState.lastParams) as {
|
||||||
|
reasoning?: { effort?: string };
|
||||||
|
reasoning_effort?: string;
|
||||||
|
};
|
||||||
|
expect(params.reasoning).toEqual({ effort: "high" });
|
||||||
|
expect(params.reasoning_effort).toBeUndefined();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ const OpenAICompletionsCompatSchema = Type.Object({
|
|||||||
thinkingFormat: Type.Optional(
|
thinkingFormat: Type.Optional(
|
||||||
Type.Union([
|
Type.Union([
|
||||||
Type.Literal("openai"),
|
Type.Literal("openai"),
|
||||||
|
Type.Literal("openrouter"),
|
||||||
Type.Literal("zai"),
|
Type.Literal("zai"),
|
||||||
Type.Literal("qwen"),
|
Type.Literal("qwen"),
|
||||||
Type.Literal("qwen-chat-template"),
|
Type.Literal("qwen-chat-template"),
|
||||||
|
|||||||
Reference in New Issue
Block a user