Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions apps/vscode-e2e/src/suite/providers/xai.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const XAI_API_KEY = process.env.XAI_API_KEY
const XAI_BASE_URL = "https://api.x.ai/v1"
const XAI_RESPONSES_URL = `${XAI_BASE_URL}/responses`
// Primary model for the full round-trip test (completion-text assertion included).
const XAI_MODEL_ID = "grok-4.20"
const XAI_MODEL_ID = "grok-4.5"
// Fast variants: tested for API parameter contract only. They consistently call
// attempt_completion with an empty result field after a no-tool-error recovery
// loop, so they cannot satisfy the completion-text assertion at this time.
Expand Down Expand Up @@ -492,7 +492,7 @@ suite("xAI provider", function () {
const readCallId = modelFixture?.readCallId ?? "call_xai_read_001"

if (request.functionCallOutputIds.some((id) => id === readCallId)) {
// Use recorded turn2 when it contains a function_call (grok-4.20).
// Use recorded turn2 when it contains a function_call (grok-4.5).
// Fast models return plain text in turn2 — hand-craft attempt_completion
// so the task can reach completion.
const turn2HasFunctionCall = (modelFixture?.turn2 as ResponsesStreamEvent[] | undefined)?.some(
Expand Down
18 changes: 17 additions & 1 deletion packages/types/src/providers/xai.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,25 @@ import type { ModelInfo } from "../model.js"
// https://docs.x.ai/docs/api-reference
export type XAIModelId = keyof typeof xaiModels

export const xaiDefaultModelId: XAIModelId = "grok-4.20"
export const xaiDefaultModelId: XAIModelId = "grok-4.5"

export const xaiModels = {
"grok-4.5": {
maxTokens: 65_536,
contextWindow: 500_000,
supportsImages: true,
supportsPromptCache: true,
inputPrice: 2.0,
outputPrice: 6.0,
cacheWritesPrice: 0.5,
cacheReadsPrice: 0.5,
description:
"xAI's flagship Grok 4.5 model with 500K context, configurable reasoning (low/medium/high), and agentic tool calling via Responses API.",
supportsReasoningEffort: ["low", "medium", "high"],
reasoningEffort: "high",
includedTools: ["search_replace"],
excludedTools: ["apply_diff"],
},
"grok-4.20": {
maxTokens: 65_536,
contextWindow: 2_000_000,
Expand Down
45 changes: 43 additions & 2 deletions src/api/providers/__tests__/xai.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ describe("XAIHandler", () => {
await expect(handler.completePrompt("test prompt")).rejects.toThrow(`xAI completion error: ${errorMessage}`)
})

it("should include reasoning_effort for mini models", async () => {
it("should include reasoning effort for mini models in Responses API format", async () => {
const miniModelHandler = new XAIHandler({
apiModelId: "grok-3-mini",
reasoningEffort: "high",
Expand All @@ -269,7 +269,48 @@ describe("XAIHandler", () => {
expect(mockResponsesCreate).toHaveBeenCalledWith(
expect.objectContaining({
reasoning: expect.objectContaining({
reasoning_effort: "high",
effort: "high",
}),
}),
)
})

it("should include reasoning effort for grok-4.5 with default high effort", async () => {
const grok45Handler = new XAIHandler({
apiModelId: "grok-4.5",
})

mockResponsesCreate.mockResolvedValueOnce(mockStream([]))

const stream = grok45Handler.createMessage("test prompt", [])
await stream.next()

expect(mockResponsesCreate).toHaveBeenCalledWith(
expect.objectContaining({
model: "grok-4.5",
reasoning: expect.objectContaining({
effort: "high",
}),
}),
)
})

it("should include reasoning effort for grok-4.5 with custom low effort", async () => {
const grok45Handler = new XAIHandler({
apiModelId: "grok-4.5",
reasoningEffort: "low",
})

mockResponsesCreate.mockResolvedValueOnce(mockStream([]))

const stream = grok45Handler.createMessage("test prompt", [])
await stream.next()

expect(mockResponsesCreate).toHaveBeenCalledWith(
expect.objectContaining({
model: "grok-4.5",
reasoning: expect.objectContaining({
effort: "low",
}),
}),
)
Expand Down
6 changes: 4 additions & 2 deletions src/api/providers/xai.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,11 @@ export class XAIHandler extends BaseProvider implements SingleCompletionHandler
requestBody.parallel_tool_calls = metadata?.parallelToolCalls ?? true
}

// Pass reasoning effort for models that support it (e.g., mini models)
// Pass reasoning effort for models that support it (e.g., grok-4.5, grok-3-mini).
// The xAI Responses API uses `reasoning: { effort }` format (not `reasoning_effort`
// which is the Chat Completions format), so we convert from the OpenAI params shape.
if (model.reasoning) {
requestBody.reasoning = model.reasoning
requestBody.reasoning = { effort: model.reasoning.reasoning_effort }
}

let stream: AsyncIterable<any>
Expand Down
Loading