Skip to content

fix(router): backfill the xAI web-search capability into routed provider config - #2283

Merged
lidge-jun merged 1 commit into
devfrom
codex/backfill-xai-web-search-capability
Aug 21, 2026
Merged

fix(router): backfill the xAI web-search capability into routed provider config#2283
lidge-jun merged 1 commit into
devfrom
codex/backfill-xai-web-search-capability

Conversation

@lidge-jun

@lidge-jun lidge-jun commented Aug 21, 2026

Copy link
Copy Markdown
Owner

Summary

Routed Grok turns on the Responses lane died with 400 Argument not supported: external_web_access before inference, so every tool-use turn failed.

routedProviderConfig() backfills every other registry-only scalar (supportsServiceTier, preserveResponsesReasoningContent, fastWire) but not supportsOpenAiWebSearchToolFields. enrichProviderFromRegistry() does fill it — and the request path never calls that function. So a saved xai row reached the Responses adapter with the flag undefined, the #2262 capability gate read that as "unclassified upstream, keep the fields", and Codex's OpenAI-only web_search config went to the wire.

A live probe against the OAuth Grok endpoint (2026-08-21) isolates the cause: bare {type:"web_search"} returns 200, +external_web_access returns 400, +search_context_size returns 400 — each individually, before inference.

The fix is one backfill entry next to the existing registry-only scalars. An explicit saved user value still wins, and only providers whose registry entry declares the capability are affected (today: xai).

Verification

  • bun run typecheck — exit 0
  • bun run test — 14090 pass / 0 fail across 887 files
  • bun run privacy:scan — passed
  • bun test --isolate tests/responses-routed-web-search-fields.test.ts — 7 pass / 0 fail
  • New tests driven red against the unfixed router (2 fail), then green with the fix — they are not vacuous.
  • End-to-end on a remote macOS host running this dev head: with the GUI Responses opt-in on and no hand-written capability in config.json, a multi-step codex exec tool-use turn (mkdir, write, cat, uname) completed over adapter "openai-responses" with status: 200 in usage.jsonl. The same turn 400'd on the same host before the fix.

The existing tests could not catch this: they hand-build a provider with the flag already set, or call enrichProviderFromRegistry() directly, so both start downstream of the break. The new tests assert on routedProviderConfig() output.

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed.
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults.

Summary by CodeRabbit

  • Bug Fixes

    • Improved routed provider configuration to correctly apply web-search capability defaults when saved settings omit them.
    • Preserved explicitly configured provider capabilities.
    • Prevented unsupported web-search fields from being sent to providers that do not support them.
  • Tests

    • Added coverage for default capability handling, explicit overrides, and request-field filtering.

…der config

Routed Grok turns on the Responses lane died with
`400 Argument not supported: external_web_access` before inference.

routedProviderConfig() backfills every other registry-only scalar
(supportsServiceTier, preserveResponsesReasoningContent, fastWire) but not
supportsOpenAiWebSearchToolFields. enrichProviderFromRegistry() does fill it,
and the request path never calls that function -- so a saved xai row reached
the Responses adapter with the flag undefined. The #2262 capability gate reads
undefined as "unclassified upstream, keep the fields", so Codex's OpenAI-only
web_search config went to the wire and xAI rejected the whole request.

Live probe against the OAuth Grok endpoint (2026-08-21) isolates the cause:
bare {type:"web_search"} returns 200, +external_web_access returns 400, and
+search_context_size returns 400 -- individually, before inference.

Verified end-to-end on a remote macOS host running this dev head: with the
GUI Responses opt-in on and NO hand-written capability in config.json, a
multi-step codex exec tool-use turn now completes over adapter
"openai-responses" with status 200, where the same turn 400'd before.

The existing tests could not catch this: they hand-build a provider with the
flag already set, or call enrichProviderFromRegistry() directly, so both start
downstream of the break. The new tests assert on routedProviderConfig() output
and were driven red against the unfixed router.
@lidge-jun
lidge-jun requested a review from Ingwannu as a code owner August 21, 2026 07:54
@github-actions github-actions Bot added the bug Something isn't working label Aug 21, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

@coderabbitai

coderabbitai Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 5e000394-042a-44db-bba6-f8ceeec70873

📥 Commits

Reviewing files that changed from the base of the PR and between e3b2136 and d5ea14a.

📒 Files selected for processing (2)
  • src/router.ts
  • tests/responses-routed-web-search-fields.test.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

routedProviderConfig now backfills the registry web-search capability when saved provider data omits it. Tests verify xAI field filtering and preservation of explicit capability values.

Changes

Web-search capability routing

Layer / File(s) Summary
Capability backfill and request validation
src/router.ts, tests/responses-routed-web-search-fields.test.ts
routedProviderConfig copies the registry capability when the saved value is unspecified. Tests verify that xAI removes unsupported OpenAI-only fields and that an explicit true value remains unchanged.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to d5ea1

This change prevents unsupported web-search fields from being sent to routed xAI Responses requests while preserving explicit saved settings; the focused tests and verification pass, so no actionable merge-blocking risk remains.

Suggested reviewers: ingwannu

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: backfilling the xAI web-search capability in routed provider configuration.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/backfill-xai-web-search-capability

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.

@Ingwannu Ingwannu left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved exact head d5ea14a2d522b428ff5b13d011bdf9e376b41358.

I independently verified the request-path gap and the fix. routedProviderConfig() was the missing registry-enrichment boundary: a saved xAI row could reach the Responses adapter with supportsOpenAiWebSearchToolFields unset even though the registry declares false. The new fill-only backfill matches the established enrichProviderFromRegistry() contract, applies only to registry-owned transport rows, and preserves an explicit saved override.

The focused request/router and passthrough suites pass locally (105/105), as do bun run typecheck and bun run privacy:scan. The new tests cover the saved-row path that the older adapter-only tests missed, including actual field stripping and explicit-value precedence.

No blocking issue found. Merge should wait for the remaining exact-head macOS job to finish green.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants