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.
Root-prompt blobs used contentText(), which dropped image-only turns. Use historyContentText so external models still see [image attached].
Prepare already JPEG-caps active-turn images. Pass those bytes to resolve so live transport does not decode and encode the same PNG twice.
Image prep reused the name already used for the protobuf payload, so the module failed to parse and the CLI could not start. Co-authored-by: Cursor <cursoragent@cursor.com>
Keep the glm-5.3 blind-model comment in sync with CURSOR_NO_VISION_MODELS, and round oversized base64 fixtures to a multiple of four so the decode guards stay pinned if the byte caps change. Co-authored-by: Cursor <cursoragent@cursor.com>
Omit images when dimension sniffing cannot produce trusted bounds before Bun.Image decode, and when the JPEG shrink ladder still exceeds the detail soft cap. Adds named regressions for truncated headers and documents glm-5.3 alongside glm-5.2 in provider examples. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…rding Co-authored-by: Cursor <cursoragent@cursor.com>
`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.
`an accepted override still resolves through the route` hard-coded "/tmp/opencodex-pi-route-fixture/models.json". The resolver builds that destination with `join`, which is `\` on win32, so the case asserted the host's path separator rather than the override taking effect and was red on every Windows run: Expected: "/tmp/opencodex-pi-route-fixture/models.json" Received: "\tmp\opencodex-pi-route-fixture\models.json" Build the expectation with `join` from one binding shared with the env value. `join` is identity for this input on POSIX, so Linux and macOS are unchanged. The assertion still pins what it was written for: making `piAgentDir` ignore the override fails this case, so it did not become a tautology. Refs #2152.
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
…tchdog fix(cursor): inbound stream-health watchdog fails silent/heartbeat-only turns at the transport
…covery H2 pool down at lifecycle exit Two small hardenings from devlog 260822_senpi_cursor_transfer/120: - T07 (senpi PR #905): pollCursorAuth now fails on the FIRST 400/401/403/410 with a typed CursorAuthTerminalError naming the status, instead of burning the 3-strike retry budget and masking the reason behind "Too many consecutive errors". 5xx/network keep the existing retry path. - 120b: CursorH2SessionPool lazily registers a "cursor-h2-pool" teardown in the core-owned optional-shutdown-hooks registry on first request(), so lifecycle drainAndShutdown closes pooled discovery sessions. The pool doc comment no longer overclaims Run-path reuse (Run deliberately dials its own session; see 190 roadmap lock).
…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. |
|
Caution Review failedFailed to post review comments. We encountered an issue with GitHub. Use ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (4)
📒 Files selected for processing (220)
Included review availability: Your plan provides up to 10 included reviews per hour; 4 remain after this review. ⏰ Context from checks skipped due to timeout. (3)
|
| Layer / File(s) | Summary |
|---|---|
Repository Bun setup .github/actions/setup-project-bun/action.yml, .github/workflows/*, package.json, scripts/ci/* |
CI, release, and lifecycle workflows resolve Bun from package.json. Bun dependencies move to 1.4.0. Test batches accept OPENCODEX_BUN_PATH. |
Bun qualification documentation devlog/_fin/260814_bun14-preview-dev/*, README.md |
The Bun 1.4 qualification plan, canary findings, runtime gates, and promotion documentation are added. Source-install instructions no longer upgrade to Canary. |
Cursor and provider behavior
| Layer / File(s) | Summary |
|---|---|
Cursor transport and request handling src/adapters/cursor/*, tests/cursor-* |
Cursor gains pooled HTTP/2 discovery, stream-health watchdogs, clean EOF settlement, typed unknown-exec responses, image preparation, selected-image serialization, tool-marker normalization, and size-aware error classification. |
Vision routing src/vision/*, src/server/management/*, gui/src/pages/*, src/types/config.ts, tests/vision-* |
Vision sidecars support a routed backend with namespaced models. The loopback describe flow validates images, applies recursion protection, and returns generated captions. |
Provider metadata and pricing src/providers/*, src/codex/catalog/*, src/usage/*, src/adapters/google.ts, tests/* |
Provider capability metadata, xAI Priority pricing, Z.AI quota formats, Cursor model catalogs, Google thought signatures, and Responses tool compatibility are updated. |
CLI and release flows
| Layer / File(s) | Summary |
|---|---|
Coordinator diagnosis and recovery src/codex/coordinator-doctor.ts, src/codex/inject-coordination.ts, src/cli/doctor.ts, tests/codex-* |
ocx doctor inspects coordinator state and can recover verified stable zero-byte remnants into timestamped backups. Fresh or unsafe states remain protected. |
Service command planning src/service.ts, src/cli/registry.ts, tests/service.test.ts, docs-site/src/content/docs/*/reference/cli/lifecycle.md |
Bare service commands select install or repair from installation probes. restart aliases repair. Windows registration stops when status is unknown. |
Release and desktop helpers scripts/release.ts, scripts/restart-codex-desktop-app.ps1, tests/release-helper.test.ts |
Release pushes support validated deploy-key SSH targets. A PowerShell helper safely restarts the Codex MSIX application. |
Estimated code review effort: 5 (Critical) | ~120 minutes
Merge Risk: 🟠 High · up to ced9a
This release promotion brings unresolved runtime changes to main that can reuse stale image context, abort active model discovery, fail routed vision on non-loopback binds, and accept oversized image payloads, causing incorrect results, failed requests, or resource pressure; the release is not merge-ready until these high-impact issues are fixed or explicitly accepted.
Possibly related PRs
- lidge-jun/opencodex#1228: Related Cursor vision and image-handling changes.
- lidge-jun/opencodex#1900: Related Cursor transport, discovery, and tool-definition changes.
- lidge-jun/opencodex#1993: Related Cursor terminal settlement and image serialization changes.
🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
| Check name | Status | Explanation | Resolution |
|---|---|---|---|
| Docstring Coverage | Docstring coverage is 37.07% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 116 functions across 50 files. (170 skipped: 92 unsupported, 78 over the file limit.) | 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 accurately identifies the dev-to-main release promotion for v2.31.0, which matches the pull request objective. |
| 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 💡 2
📝 Generate docstrings 💡
- Create stacked PR
- Commit on current branch
🛠️ Fix failing CI checks 💡
- Create stacked PR
- Commit on current branch
🧪 Generate unit tests (beta)
- Create PR with unit tests
- Commit unit tests in branch
dev
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 @coderabbitai help to get the list of available commands.
⏳ DRAFT
What to do
Its title has been prefixed with |
리뷰 · 우선순위 31 / 80설명: 이 PR은 PR base main / head dev - 기여자 게이트는 dev 만 받는다. main 타깃은 승격용으로 맞지만 이 워크플로 PR 로는 통과하지 못한다 메인테이너의 판단이 필요한 지점
너의 추천 이 댓글은 grok-bot이 작성했습니다 |
Summary
Promote dev (ced9a85) into main for the v2.31.0 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
ocx service restartand safer automatic service installation checks.ocx doctordiagnostics and guarded recovery for zero-byte coordinator remnants.Bug Fixes
Documentation