From dc45a2658d59c0d37e299b2d5540ab4db5bba2b3 Mon Sep 17 00:00:00 2001 From: Roo Code Date: Fri, 25 Jul 2025 14:33:34 +0000 Subject: [PATCH] fix: remove stream_options from xAI provider to fix Grok 4 API errors - Removed stream_options: { include_usage: true } from XAIHandler - Grok models do not support the stream_options parameter - This fixes API errors when using Grok 4 model - Updated tests to reflect the change Fixes #6211 --- src/api/providers/__tests__/xai.spec.ts | 1 - src/api/providers/xai.ts | 13 ++++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/api/providers/__tests__/xai.spec.ts b/src/api/providers/__tests__/xai.spec.ts index 1d3d4a15093..b8302e26d24 100644 --- a/src/api/providers/__tests__/xai.spec.ts +++ b/src/api/providers/__tests__/xai.spec.ts @@ -276,7 +276,6 @@ describe("XAIHandler", () => { temperature: 0, messages: expect.arrayContaining([{ role: "system", content: systemPrompt }]), stream: true, - stream_options: { include_usage: true }, }), ) }) diff --git a/src/api/providers/xai.ts b/src/api/providers/xai.ts index 596c9e89b8c..17dd4c05056 100644 --- a/src/api/providers/xai.ts +++ b/src/api/providers/xai.ts @@ -48,13 +48,13 @@ export class XAIHandler extends BaseProvider implements SingleCompletionHandler const { id: modelId, info: modelInfo, reasoning } = this.getModel() // Use the OpenAI-compatible API. + // Note: Grok models don't support stream_options parameter const stream = await this.client.chat.completions.create({ model: modelId, max_tokens: modelInfo.maxTokens, temperature: this.options.modelTemperature ?? XAI_DEFAULT_TEMPERATURE, messages: [{ role: "system", content: systemPrompt }, ...convertToOpenAiMessages(messages)], stream: true, - stream_options: { include_usage: true }, ...(reasoning && reasoning), }) @@ -78,12 +78,15 @@ export class XAIHandler extends BaseProvider implements SingleCompletionHandler if (chunk.usage) { // Extract detailed token information if available // First check for prompt_tokens_details structure (real API response) - const promptDetails = "prompt_tokens_details" in chunk.usage ? chunk.usage.prompt_tokens_details : null; - const cachedTokens = promptDetails && "cached_tokens" in promptDetails ? promptDetails.cached_tokens : 0; + const promptDetails = "prompt_tokens_details" in chunk.usage ? chunk.usage.prompt_tokens_details : null + const cachedTokens = promptDetails && "cached_tokens" in promptDetails ? promptDetails.cached_tokens : 0 // Fall back to direct fields in usage (used in test mocks) - const readTokens = cachedTokens || ("cache_read_input_tokens" in chunk.usage ? (chunk.usage as any).cache_read_input_tokens : 0); - const writeTokens = "cache_creation_input_tokens" in chunk.usage ? (chunk.usage as any).cache_creation_input_tokens : 0; + const readTokens = + cachedTokens || + ("cache_read_input_tokens" in chunk.usage ? (chunk.usage as any).cache_read_input_tokens : 0) + const writeTokens = + "cache_creation_input_tokens" in chunk.usage ? (chunk.usage as any).cache_creation_input_tokens : 0 yield { type: "usage",