Conversation
Phase B2 of the FastWire umbrella (#1886), closing the request in #1875. Fast now works end to end for xAI, and only where xAI documents it. Capability follows the transport. The registry gains a key-auth service-tier overlay applied only when a preset allows the key override and the captured effective auth transport is key-based; xAI declares Fast there and stays unclassified on OAuth, because Priority Processing is documented for the public api.x.ai endpoints and not for the Grok CLI subscription gateway. The overlay resolves inside the shared FastPolicyAuthority capture, so the catalog and the runtime cannot disagree — and the runtime only rewrites the base URL to that gateway when authMode is "oauth", exactly when the overlay withholds the capability, so Fast can never be injected into the unverified endpoint. The catalog stops telling every provider OpenAI's story. Fast tier copy is now per-provider, and xAI's says what xAI actually charges: priority processing at 2x token price, not "1.5x speed". Providers that declare nothing keep their current bytes. Pricing is declared rather than hardcoded to one vendor. The OpenAI-only provider gate becomes exact (provider, model) priority rules, so xAI gets its documented flat 2x while routed resellers sharing the grok slug inherit nothing. The long-context relationship is likewise a declaration: OpenAI publishes that Fast and long context are exclusive regimes, while xAI publishes neither a combined rate nor an exclusion — so a confirmed-priority request above 200k prices at the published long-context rate and is marked a known lower bound, surfaced in the dashboard as "≥$" rather than an invented stacked multiplier. Billing still follows the response echo, which matches xAI's rule that the priority rate applies only when the response confirms it. NOTE — beyond the Fast path: xAI's bundled cached-input price for grok-4.6 was $0.30 against an official $0.50, so every xai cost estimate (not just Fast) was low. A verified-override layer corrects it ahead of the bundled row, which the existing expected-price overlays sit behind and could not reach. The Fast multiplier applies on top of the base price, so shipping the premium without this correction would have compounded the error. Full suite at this commit: 13330 pass / 10 skip / 1 fail — the one failure is the pre-existing dev-side key-login-live-update regression, confirmed to reproduce on this branch's own base commit (bcc77c0) with none of these changes applied. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The readiness checklist requires a screenshot for GUI changes. Three seeded grok-4.6 rows exercise every branch of the new pricing path in one view: standard, a response-confirmed priority request at exactly the documented 2x premium, and a confirmed-priority request above the long-context threshold rendering as "≥$" because xAI publishes no combined rate. Captured against a local proxy with a seeded usage log; no live xAI request was billed to produce it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts: # docs-site/src/content/docs/reference/configuration/providers.md # gui/src/i18n/de.ts # gui/src/i18n/en.ts # gui/src/i18n/fr.ts # gui/src/i18n/ja.ts # gui/src/i18n/ko.ts # gui/src/i18n/ru.ts # gui/src/i18n/tr.ts # gui/src/i18n/zh-TW.ts # gui/src/i18n/zh.ts # gui/src/pages/Logs.tsx # gui/src/pages/logs-cost-format.ts # src/codex/catalog/provider-fetch.ts # src/providers/registry.ts # src/providers/service-tier.ts # tests/service-tier-capability.test.ts
33e1c3e split the OAuth subscription gateway from the API-key endpoint in the provider table for en, ja, ko, ru, and zh-cn, but zh-tw, fr, and tr kept https://api.x.ai/v1 as the base URL. OAuth routes through the Grok CLI gateway at https://cli-chat-proxy.grok.com/v1; only the API-key override targets api.x.ai, and only that transport injects Priority Processing. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017zpLCh4eEms6un3VjapRgL
Claude Code's Anthropic Messages path never received a reasoning-replay scope because it does not send the Codex parent-thread header. Derive one from the stable per-session prompt_cache_key (metadata.user_id) so Gemini/Antigravity thought signatures are remembered by call_id and survive history replay. Also read nested extra_content.google.thought_signature when parsing Google responses.
Adds regression coverage for the Anthropic Messages reasoning-replay scope and for reading nested extra_content.google.thought_signature from Google response parts.
`ROUTED_CUSTOM_TOOL_PASSTHROUGH` exempted `apply_patch` from routed
custom-tool lowering unconditionally, so it reached every routed destination
as a `type: "custom"` tool with `custom_tool_call` items. xAI's Responses
endpoint rejects that item type:
422 Failed to deserialize the JSON body into the target type:
input[5]: invalid "custom_tool_call" item: missing field `id`
The message is misleading — the id is present. Instrumenting the adapter
showed the item leaving as
`{"type":"custom_tool_call","id":"ctc_abc123","call_id":"c1",...}`; xAI
reports the first field its own parser cannot satisfy rather than the real
problem, which is that it does not accept the item type. Same class as its
"Could not decode the compaction blob" message for a reasoning field, so the
fix is not to generate or preserve ids.
Live A/B against the endpoint — identical body, identical id, only the tool
name differs:
apply_patch (exempt from lowering) -> 422
my_custom_thing (lowered to a function) -> 200
Lowering is what makes it work; the exemption is what breaks it. It surfaces
on Codex's compact turn because a real session always contains apply_patch
calls, but a plain replay reproduces it too.
The exemption is not wrong everywhere — the canonical ChatGPT surface speaks
custom_tool_call natively and lowering there would regress it. The defect is
that one unconditional rule about "routed providers" encoded a claim about a
single destination's capability. Add `supportsResponsesCustomTools`,
following the existing `supportsOpenAiWebSearchToolFields` shape: declared on
the registry row and the provider config, filled only when unset, and
consumed as an explicit denial. Absent or true keeps today's behaviour
byte-identical; only xAI declares false.
The response path needed no special case: it is name-generic, so once
apply_patch joins the converted set the existing repair restores the
function_call and its streaming argument events to a custom_tool_call with
the original call id.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Every routed lowering step derives its plan from the tool declarations, and
the compaction body build deletes them. It ran first, so on a compaction turn
the plan was empty and replayed call items reached the wire in their private
shapes. Against xAI:
422 Failed to deserialize the JSON body into the target type:
input[5]: invalid "custom_tool_call" item: missing field `id`
The id is present; xAI reports the first field its own parser cannot satisfy
rather than the real problem, which is that it does not accept the item type.
Instrumented the adapter to pin the mechanism: with declarations present the
call item is converted; with them absent, or on a compaction turn, it goes out
raw. Reordering locally produced `function_call` / `function_call_output` with
`tools` still absent and the compact prompt still appended.
This is the second time this exact shape has been fixed here — a replayed
namespace key survived for the same reason. That fix taught one lowering step
to cope; this one fixes the pipeline, so the next private field added does not
need its own workaround. The invariant is now stated at the call site: the
compaction body build removes the tool surface and must be the last routed
transform.
Two effects beyond the call items, both improvements: `promoteClientLoadedTools`
could previously reintroduce top-level `tools` after compaction had removed
them, which running compaction last now prevents; and namespace-collision
validation runs before the declarations are deleted. Non-compaction output is
byte-identical, pinned by an exact comparison test.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit 59d0cde7f75f0e645a12ec44a388609dfba50ce6)
The namespace-replay restore test verified the restored custom_tool_call events but never checked that the stream still ends with data: [DONE], so a regression that drops the terminal marker would have passed. The sibling lowering test already asserts it; match that. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017zpLCh4eEms6un3VjapRgL
Forward auth is not an OpenAI-destination identity. A noncanonical forward provider that denies native custom tools must still convert apply_patch. Pin the adapter serialization and the handleResponses path.
Refresh B2 onto current dev without rewriting contributor history. Keep the xAI Priority response-confirmation boundary and the grok-4.6 cached-input $0.50 correction. Resolve the leftover privacy:scan example using the wording already on dev. # Conflicts: # devlog/_plan/260820_bug_pr_backlog_consolidation/100_release_safety_audit.md
#2255's wire/tier matrix assumed API-key Grok chat does not forward service_tier. B2 documents Priority Processing on that transport, so the key-auth chat row must now match the Responses key-auth row. OAuth remains unclassified.
scripts: add Windows Codex desktop full-restart helper
…s, audited disposition order
…ds (#2188 roadmap 170) Any picker-visible, non-provably-text-only provider row can now be offered as the vision describer through the new 'routed' backend. Adds the VISION_BACKENDS descriptor table, namespaced routed option values, the four-family + namespaced provably-blind probe, PUT coherence rules (namespaced <-> routed), and claude-code override parity. Docs 170/180 revised with three audit rounds folded in.
…roadmap 180) The routed backend describes images by POSTing the proxy's own /v1/chat/completions with the namespaced describer model, so every provider wire the router speaks is a valid describer. Recursion fence: the request carries x-opencodex-vision-describe, detected at the chat surface (bridge rebuilds headers) and honored at the Responses plan site — marked requests strip instead of describing (depth cap 1). Native chat fast path now defers image-bearing text-only-model requests to the Responses pipeline so vision coverage is symmetric. Admission ladder: env token, service token file, first apiKeys entry, sent as x-opencodex-api-key.
…ber verbatim Splits VisionBackend from the legacy SidecarBackend pair (web-search keeps its own union), infers routed for namespaced values in the GUI fallback so a working describer is never rewritten on save, widens the claude-code override select, updates the CLI usage line, and makes GET report a routed backend's namespaced model instead of collapsing to the legacy default.
…2-shutdown fix(cursor): OAuth poll fail-fast on terminal statuses + discovery H2 pool shutdown hook
devlog: round-3 Cursor live-probe evidence and lock (docs-only)
… back to wire names #2305 (devlog 260822_senpi_cursor_transfer/230): some Cursor models emit a TEXTUAL pseudo tool call ("[TOOL_CALL]mcp_opencodex-responses_grep[ARGS]{...}") instead of a real frame. Text-mode clients (Pi) parse that text and cannot dispatch the undeclared display name, so the turn dies after display. Normalize the display alias to the advertised wire name at the textDelta mapping boundary — marker-scoped (both [TOOL_CALL] and [ARGS] required), guarded to the exact mcp_opencodex-responses_ prefix. Prose mentions and other providers' names stay untouched; real frames were already normalized structurally via mcpWireNameFromArgs. Split-marker streaming deltas are a recorded non-goal until a live trace shows them (doc 230). Closes #2305.
fix(cursor): normalize display aliases in textual pseudo tool-call markers (#2305)
…lass Live probe evidence (devlog 260822_senpi_cursor_transfer/210, 260): a plan-gated model (claude-opus-4-7-low-fast without -fast entitlement) returns the SAME bare 0-token resource_exhausted shape on a ~20-token prompt that a real payload overflow produces. #2320's overflow mapping then makes Codex compact a tiny turn — the wrong remedy for an entitlement rejection, and the retry can never succeed. Add a size prior to classifyCursorError: when the caller can prove the request was small relative to the model's context window (estimate < 50% of window), a bare RE keeps the 429-class mapping; large or unknown sizes keep today's overflow mapping, so the prior only ever removes false overflows it can prove. The adapter supplies the estimate from the outgoing request text and the static context-window table at its single error-mapping seam. Explicit quota cues and size phrases are unaffected (they classify before the prior). senpi's T01 (#1009/#1036) shares this false-overflow bug; this is a beyond-parity refinement.
fix(cursor): size prior keeps provably-small bare resource_exhausted on the 429 class
devlog: 290 post-landing status (docs-only)
… corrections and 300/310 docs
devlog: release-readiness unit + probe corrections and 300/310 roadmap (docs-only)
… tiers
Live GetUsableModels (260822, devlog 300) lists the Opus Fast wire ids ONLY
in effort-suffixed form ({base-without-fast}-{effort}-fast); the bare id
returns not_found — which is exactly what cursor/claude-opus-4-7-fast did
through the proxy, because the static catalog sent it bare ("tiers
unverified"). A live turn on claude-opus-4-8-high-fast succeeded, so the
families are callable on this plan.
- discovery.ts: claude-opus-4-7-fast gains its tier picker; add
claude-opus-4-8-fast and claude-opus-5-fast.
- effort-map.ts: tier ladders per the dump — 4-7/4-8: low..max;
opus-5-fast: low/medium/high (no xhigh/max non-thinking yet).
- No-effort requests still resolve to a suffix (max) via codexEffortRank,
so a bare -fast id can never reach the wire; no registry default needed.
- Tests pin family presence, ladders, wire-id derivation, no-bare rule,
and out-of-ladder clamping.
feat(cursor): expose Opus Fast families with live-verified effort tiers
… and server-side history truncation
devlog: 310 maxMode big-context A/B results (NOOP, docs-only)
devlog: WP4 regression-audit findings (docs-only)
devlog: release-readiness GO verdict (docs-only)
|
✅ Deterministic PR hygiene checks passed. |
⏳ DRAFT
What to do
Its title has been prefixed with |
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (2)
📒 Files selected for processing (174)
📝 WalkthroughWalkthroughThis pull request adds routed vision support, Cursor transport and authentication hardening, coordinator diagnosis and recovery, service lifecycle planning, provider capability handling, pricing updates, release validation, and related documentation and tests. ChangesApplication behavior
Documentation and release records
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
리뷰 · 우선순위 34 / 80설명: 이 PR은 PR base preview / head dev - 기여자 게이트는 dev 만 받는다. 승격 PR 이라서 타깃이 preview 인 것은 맞다 메인테이너의 판단이 필요한 지점
너의 추천 이 댓글은 grok-bot이 작성했습니다 |
Summary
Promote dev (ced9a85) into preview for the v2.31.0-preview.20260822 release train.
This is a maintainer promotion merge, not a feature PR. No code is authored here: the merge brings the 114 non-merge commits that accumulated on dev since v2.29.0 (224 files, +12000/-539).
Release readiness was certified in devlog/_plan/260822_dev_release_readiness/090_go_verdict.md (GO verdict) and re-verified locally at head ced9a85.
Verification
Checklist
Summary by CodeRabbit
New Features
provider/modelselection for image-capable models.ocx service restartand guardedocx doctorcoordinator recovery.Bug Fixes
Documentation