Skip to content

feat(provider-xai): xAI (Grok) provider for llm-router - #379

Merged
rohitg00 merged 5 commits into
mainfrom
feat/provider-xai
Jul 1, 2026
Merged

rohitg00 merged 5 commits into
mainfrom
feat/provider-xai

Conversation

@rohitg00

Copy link
Copy Markdown
Contributor

What

Adds provider-xai: an llm-router provider for xAI's Grok models, so the harness chat loop can route to grok-* the same way it routes to OpenAI/Anthropic. xAI's API is OpenAI-compatible (https://api.x.ai/v1/chat/completions, OpenAI-shape streaming + tools), so this mirrors provider-openai's wire handling and swaps the provider-specific surface.

This is distinct from the grok worker (#378): that wraps the Grok agent CLI; this exposes raw Grok models to the harness.

Verified against live api.x.ai

  • Provider registers with the router — shows as xAI, available, supports_model_listing: true.
  • provider::xai::refresh_models discovered and reconciled 5 real models from api.x.ai/v1/models with correct metadata (e.g. grok-4.3 → 1M context).
  • api.x.ai/v1/chat/completions confirmed OpenAI-shape (choices[].message.content, usage, finish_reason).
  • The streaming chat path (router::chat → provider::xai::stream → SSE → done frame + cost fill) is covered by the live-engine integration suite.

Provider-specific surface

  • provider::xai::stream / refresh_models / on_router_ready; credential env var XAI_API_KEY; endpoint https://api.x.ai/v1.
  • curated.rs: grok catalog + capability metadata (grok-4.3, grok-4, grok-4-fast, grok-3, grok-3-mini, grok-code-fast, grok-build); legacy filter for grok-1/grok-2; -MMDD snapshot folding. Pricing for grok-4.3/grok-build from docs.x.ai; other rows best-effort (display only, never routing).
  • reasoning.rs: xAI reasoning_effort rules — only grok-3-mini takes the param (low/high); grok-4.x reasons but rejects it; others non-reasoning.
  • discovery.rs: grok-* family gate, grok-imagine/image/video excluded.

Configure

# llm-router config entry, providers.xai.api_key
# (or XAI_API_KEY in the router's process env)

Checks

cargo fmt --all -- --check clean · cargo clippy --all-targets --all-features -- -D warnings clean · 74 tests pass (incl. live-engine integration). Draft pending maintainer review + release wiring (create-tag.yml / release.yml, per docs/sops/new-worker.md §6).

xAI's API is OpenAI-compatible, so this mirrors provider-openai's wire
handling and adapts the provider-specific surface to xAI:

- provider::xai::stream / refresh_models / on_router_ready, registered with
  llm-router; credential env var XAI_API_KEY, endpoint https://api.x.ai/v1.
- curated.rs: grok model catalog + capability metadata (grok-4.3, grok-4,
  grok-4-fast, grok-3, grok-3-mini, grok-code-fast, grok-build), legacy
  filter for grok-1/grok-2, MMDD snapshot folding.
- reasoning.rs: xAI reasoning_effort rules — only grok-3-mini takes the param
  (low/high); grok-4.x reasons but rejects it; others non-reasoning.
- discovery.rs: grok-* family gate, image/video (grok-imagine) excluded,
  /v1/models discovery.

Verified end-to-end against live api.x.ai: provider registers with the
router (shows as xAI, supports_model_listing), refresh_models discovered and
reconciled 5 real models with correct metadata, and api.x.ai chat/completions
confirmed OpenAI-shape. fmt + clippy -D warnings clean, 74 tests pass
(incl. live engine integration suite).
@vercel

vercel Bot commented Jun 30, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
workers Ready Ready Preview, Comment Jun 30, 2026 4:51pm
workers-tech-spec Ready Ready Preview, Comment Jun 30, 2026 4:51pm

Request Review

@coderabbitai

coderabbitai Bot commented Jun 30, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

@rohitg00, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 49 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c8f212b5-13ef-41e1-aabf-f51ef79e5994

📥 Commits

Reviewing files that changed from the base of the PR and between c5f4217 and 955c023.

⛔ Files ignored due to path filters (1)
  • provider-xai/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (36)
  • .github/workflows/create-tag.yml
  • .github/workflows/release.yml
  • README.md
  • provider-xai/.gitignore
  • provider-xai/Cargo.toml
  • provider-xai/README.md
  • provider-xai/build.rs
  • provider-xai/config.yaml
  • provider-xai/iii-permissions.yaml
  • provider-xai/iii.worker.yaml
  • provider-xai/src/config.rs
  • provider-xai/src/curated.rs
  • provider-xai/src/discovery.rs
  • provider-xai/src/errors.rs
  • provider-xai/src/lib.rs
  • provider-xai/src/main.rs
  • provider-xai/src/manifest.rs
  • provider-xai/src/reasoning.rs
  • provider-xai/src/register.rs
  • provider-xai/src/request.rs
  • provider-xai/src/router_client.rs
  • provider-xai/src/sse.rs
  • provider-xai/src/state.rs
  • provider-xai/src/stream_fn.rs
  • provider-xai/src/surface.rs
  • provider-xai/src/upstream.rs
  • provider-xai/src/wire/messages.rs
  • provider-xai/src/wire/mod.rs
  • provider-xai/src/wire/names.rs
  • provider-xai/src/wire/tools.rs
  • provider-xai/tests/golden/schemas/provider.xai.on_router_ready.json
  • provider-xai/tests/golden/schemas/provider.xai.refresh_models.json
  • provider-xai/tests/golden/schemas/provider.xai.stream.json
  • provider-xai/tests/integration.rs
  • provider-xai/tests/schemas.rs
  • provider-xai/tests/support/mod.rs
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/provider-xai

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

skill-check — worker

0 verified, 27 skipped (no docs/).

Layer Result
structure ✓
vale ✓
ai ✓
render ✓

Four for four. Nicely done.

…rflow

Two issues found testing grok models in the console:

1. Reasoning deltas dropped. xAI reasoning models stream chain-of-thought as
   `delta.reasoning_content` ahead of the answer `content`; the OpenAI-cloned
   SSE parser only read `content`, so the console showed "thinking…" with no
   body. Now parsed into a thinking block (ThinkingStart/Delta/End +
   ContentBlock::Thinking), emitted before the text block.

2. Prompt-overflow misclassified. grok-build returns a gRPC-style envelope
   `{"code":"invalid-argument","error":"This model's maximum prompt length is
   256000 but the request contains N tokens."}` — a bare-string `error` and
   wording the sniffer missed, so it classified Permanent and failed the turn
   instead of ContextOverflow (which the harness compacts + retries on, like
   provider-anthropic). Now handles the string envelope and the "maximum
   prompt length" / "prompt is too long" phrasings.

fmt + clippy -D warnings clean, 76 tests pass.
Every grok-4.x snapshot collapsed to "Grok 4" in the console picker because
display_name was the family label. Derive a per-id display instead
(display_for): drop the 4-digit MMDD snapshot segment, title-case the rest.

  grok-4.20-0309-non-reasoning -> Grok 4.20 Non Reasoning
  grok-4.20-0309-reasoning     -> Grok 4.20 Reasoning
  grok-4.20-multi-agent-0309   -> Grok 4.20 Multi Agent
  grok-4.3                     -> Grok 4.3
  grok-build-0.1               -> Grok Build 0.1

family_meta keeps capability/pricing per family; only the label is per-id.
fmt + clippy -D warnings clean, 77 tests pass.
Per docs/sops/new-worker.md §6: add provider-xai to create-tag.yml worker
options and the release.yml tag patterns so the first release tag triggers
the build/publish pipeline.
CodeRabbit review + empirical verification against api.x.ai:

- reasoning.rs: the effort gating was inverted. Verified live: grok-4.3 accepts
  the full ladder none/low/medium/high/xhigh, grok-3-mini takes low/high, and
  every other current model (grok-build, the grok-4.20-* snapshots incl.
  multi-agent) returns 400 "does not support parameter reasoningEffort". The
  old code dropped the user's thinking_level on grok-4.3 (the flagship). Fixed
  the ladder + tests to match the API.
- curated.rs: supports_xhigh was a blanket false; grok-4.3 accepts xhigh
  (verified), so the router's thinking:xhigh route now matches it. Others false.
- curated.rs: guard base_id's byte split with is_char_boundary so a non-ASCII
  model id from a custom OpenAI-compatible server can't panic the refresh task.
- README: rewrote the reasoning bullet — it was copied verbatim from
  provider-openai (o1/gpt-5 families, "no reasoning streamed"), both wrong for
  xAI; the worker DOES surface reasoning_content as thinking blocks.

code-simplifier pass: no changes (faithful clone of provider-openai, already
clean). fmt + clippy -D warnings clean, 77 tests pass.
@rohitg00
rohitg00 merged commit 35ced95 into main Jul 1, 2026
13 checks passed
@rohitg00
rohitg00 deleted the feat/provider-xai branch July 1, 2026 10:45

This branch was successfully deployed

2 active deployments
Preview – workers — 955c023b Deployed Jun 30, 2026 by vercel[bot]
Preview – workers-tech-spec — 955c023b Deployed Jun 30, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant