fix(openrouter): skip reasoning.effort injection for x-ai/grok models

x-ai/grok models on OpenRouter do not support the reasoning.effort
parameter and reject payloads containing it with "Invalid arguments
passed to the model." Skip reasoning injection for these models, the
same way we already skip it for the dynamic "auto" routing model.

Closes #32039

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
scoootscooob
2026-03-02 10:52:32 -08:00
committed by Peter Steinberger
parent 0956b599e1
commit 6c7d012320
2 changed files with 48 additions and 1 deletions

View File

@@ -317,6 +317,38 @@ describe("applyExtraParamsToAgent", () => {
expect(payloads[0]).toEqual({ reasoning: { max_tokens: 256 } });
});
it("does not inject reasoning.effort for x-ai/grok models on OpenRouter (#32039)", () => {
const payloads: Record<string, unknown>[] = [];
const baseStreamFn: StreamFn = (_model, _context, options) => {
const payload: Record<string, unknown> = {};
options?.onPayload?.(payload);
payloads.push(payload);
return {} as ReturnType<StreamFn>;
};
const agent = { streamFn: baseStreamFn };
applyExtraParamsToAgent(
agent,
undefined,
"openrouter",
"x-ai/grok-4.1-fast",
undefined,
"medium",
);
const model = {
api: "openai-completions",
provider: "openrouter",
id: "x-ai/grok-4.1-fast",
} as Model<"openai-completions">;
const context: Context = { messages: [] };
void agent.streamFn?.(model, context, {});
expect(payloads).toHaveLength(1);
expect(payloads[0]).not.toHaveProperty("reasoning");
expect(payloads[0]).not.toHaveProperty("reasoning_effort");
});
it("normalizes thinking=off to null for SiliconFlow Pro models", () => {
const payloads: Record<string, unknown>[] = [];
const baseStreamFn: StreamFn = (_model, _context, options) => {

View File

@@ -620,6 +620,15 @@ function createOpenRouterWrapper(
};
}
/**
* Models on OpenRouter that do not support the `reasoning.effort` parameter.
* Injecting it causes "Invalid arguments passed to the model" errors.
*/
function isOpenRouterReasoningUnsupported(modelId: string): boolean {
const id = modelId.toLowerCase();
return id.startsWith("x-ai/");
}
function isGemini31Model(modelId: string): boolean {
const normalized = modelId.toLowerCase();
return normalized.includes("gemini-3.1-pro") || normalized.includes("gemini-3.1-flash");
@@ -807,7 +816,13 @@ export function applyExtraParamsToAgent(
// which would cause a 400 on models where reasoning is mandatory.
// Users who need reasoning control should target a specific model ID.
// See: openclaw/openclaw#24851
const openRouterThinkingLevel = modelId === "auto" ? undefined : thinkingLevel;
//
// x-ai/grok models do not support OpenRouter's reasoning.effort parameter
// and reject payloads containing it with "Invalid arguments passed to the
// model." Skip reasoning injection for these models.
// See: openclaw/openclaw#32039
const skipReasoningInjection = modelId === "auto" || isOpenRouterReasoningUnsupported(modelId);
const openRouterThinkingLevel = skipReasoningInjection ? undefined : thinkingLevel;
agent.streamFn = createOpenRouterWrapper(agent.streamFn, openRouterThinkingLevel);
agent.streamFn = createOpenRouterSystemCacheWrapper(agent.streamFn);
}