Repository navigation
Fix Grok CLI billing: use _x.ai/billing ACP extension method - #4595
Conversation
Grok's ACP server exposes billing as the extension method `_x.ai/billing`; `x.ai/billing` returns JSON-RPC -32601 on Grok CLI 1.0.60 and 1.0.62. Request the underscore name first and retry the legacy name once when the method is unavailable. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
🦞👀 Pull request received. I will update this pull request when review starts. ClawSweeper review completeClawSweeper finished reviewing this revision. The review result is being finalized. |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 16ace1a66d
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| let message = try await self.request(method: "x.ai/billing", params: [:]) | ||
| let message: [String: Any] | ||
| do { | ||
| message = try await self.request(method: "_x.ai/billing", params: [:]) |
There was a problem hiding this comment.
Decode the nested
_x.ai/billing result before accepting it
For current Grok CLI builds, this new method returns {config:{creditUsagePercent,currentPeriod,...}, subscription_tier:...} rather than the legacy top-level monthlyLimit/usage schema. decodeResult still decodes that payload as GrokBillingResponse, whose fields are all optional, so it silently creates a non-nil empty billing object; GrokStatusProbe.fetch then considers the CLI strategy successful, Auto never reaches the OAuth/web fallbacks, and toUsageSnapshot() emits no primary usage or reset. Parse/map the nested config (the existing GrokCreditsProxyFetcher already handles this shape) before returning success.
Useful? React with 👍 / 👎.
| message = try await self.request(method: "_x.ai/billing", params: [:]) | ||
| } catch { | ||
| guard GrokStatusProbe.isBillingMethodUnavailable(error) else { throw error } | ||
| message = try await self.request(method: "x.ai/billing", params: [:]) |
There was a problem hiding this comment.
Teach the account fixture to answer the fallback request
When _x.ai/billing returns -32601, this new request is now always sent, but the fixture in Tests/CodexBarTests/GrokAccountContextTests.swift:282-286 emits only response id 2 and immediately exits. The retry therefore fails with closed stdin/EOF instead of the original “Method not found”, making that suite's errorDescription assertion at line 314 fail on every run; have the fixture read id 3 and return a second -32601, as the changed scenario fixture does.
AGENTS.md reference: AGENTS.md:L5-L5
Useful? React with 👍 / 👎.
|
Codex review: needs changes before merge. What this changesThis PR requests Grok billing through Example: Grok CLI 1.0.62 returns 5% weekly usage through
Review scores
ProductKind: Bug fix · Worth it: Yes · Fix scope: Partial Merge readiness⛔ Needs changes before merge - 2 items remain Keep open: this PR addresses a real billing-method mismatch, but accepting the new response can suppress working quota fallbacks, and the retry breaks an existing test fixture. Priority: P2 Before merge
Findings
Tests
Agent review detailsHow this fits togetherThe Grok RPC client exchanges JSON-RPC with a local CLI subprocess, then supplies billing to the usage snapshot and provider fallback pipeline. flowchart TD
A[App or usage CLI] --> B[Grok provider pipeline]
B --> C[Grok RPC client]
C --> D[Local Grok subprocess]
D --> E[Billing decoder]
E --> F[Usage snapshot]
B --> G[OAuth and browser fallbacks]
Technical reviewBest possible solution: Decode the nested billing response through shared parsing, preserve legacy and Auto fallbacks, and update the existing subprocess fixture. Do we have a high-confidence way to reproduce the issue? The contributor supplies affected-release and live CLI results, and source inspection establishes both introduced failure paths; this review executed no target code. Is this the best way to solve the issue? The method fallback is appropriately narrow, but dispatch and decoding must change together so a successful RPC preserves usable quota and fallback behavior. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning medium; reviewed against a91669f2ff97. Provenance checked
TestingProof path: shipped entry point. SecurityNone. EvidenceAcceptance criteria:
What I checked:
Likely related people:
LabelsLabel changes:
Label justifications:
Rating scale6/6 🦀 challenger crab · 5/6 🦞 diamond lobster · 4/6 🐚 platinum hermit · 3/6 🦐 gold shrimp · 2/6 🦪 silver shellfish · 1/6 🧂 unranked krab. Overall follows the weaker of proof and patch quality; ✨ marks media proof (a screenshot, video, or linked artifact) that directly shows the changed behavior. WorkflowClawSweeper edits this one comment on every review. Comment Reviewed October 16, 2026, 4:42 PM ET / 20:42 UTC. |
`_x.ai/billing` returns `{config: {creditUsagePercent, currentPeriod, ...}}`.
Reuse the nested credits parser for it, keep the legacy top-level decoder,
and reject results with no usage percentage so the pipeline can fall back.
Teach the account-context fixture to answer the legacy retry.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks for the review — both findings are addressed in the latest commit.
New synthetic scenarios: nested 5% usage with reset Live check (Grok CLI 1.0.62, SuperGrok),
Commands run: 🤖 Generated with Claude Code |
Refs steipete#4595 Co-authored-by: noisy <noisy.pl@gmail.com>
# Conflicts: # CHANGELOG.md
|
Merged in d82bddb, thanks @noisy! Grok CLI billing now works through the |
Summary
codexbar usage --provider grok --source clifails withGrok request failed: Method not foundon current Grok CLI builds. Grok's ACP server exposes billing as the extension method_x.ai/billing(leading underscore, per the ACP extension-method convention);x.ai/billingreturns JSON-RPC-32601.This PR requests
_x.ai/billingfirst and retries the legacyx.ai/billingonce, only when the existingGrokStatusProbe.isBillingMethodUnavailableclassifier reports-32601, so older CLIs keep working.Refs #3716 (the 2026-10-09 comment there reports the same
-32601on CodexBar 0.73 / Grok 1.0.50).Evidence
Driving
grok agent stdiodirectly on Grok CLI 1.0.60 and 1.0.62, after the sameinitialize:x.ai/billing→{"error":{"code":-32601,"message":"Method not found"}}_x.ai/billing→ success (~0.25 s):{"config":{"creditUsagePercent":5.0,"currentPeriod":{"type":"USAGE_PERIOD_TYPE_WEEKLY","start":"2026-10-15T17:24:18Z","end":"2026-10-22T17:24:18Z"},"onDemandCap":{"val":0},"onDemandUsed":{"val":0},"prepaidBalance":{"val":0},"isUnifiedBillingUser":true,"billingPeriodStart":"…","billingPeriodEnd":"…"},"subscription_tier":"SuperGrok"}Live CLI check, same account,
usage --provider grok --source cli --format json:error: "Grok request failed: Method not found"source: grok-cli,loginMethod: SuperGrokKnown gap (not addressed here)
With the call now succeeding,
primaryis stillnull: the RPC result is shaped as{config: {creditUsagePercent, currentPeriod, …}, subscription_tier}— the same shapeGrokCreditsProxyFetcheralready parses forGetGrokCreditsConfig— butGrokBillingResponse(RPC path) doesn't map it. Routing the RPCconfigthrough the proxy parsing would surface the weekly percent and reset. Kept out of this PR to keep it minimal; happy to follow up.Changes
GrokRPCClient.fetchBilling():_x.ai/billingfirst, legacy fallback on-32601; doc comments updated.GrokFailedBillingWorkTests: newlegacyBillingSuccessscenario plus assertions on the ordered billing methods sent (underscore success sends no legacy request;-32601retries once; non--32601errors don't retry; existing method-unavailable behavior unchanged).Commands run
swift build --target CodexBarCore✅swift build --product CodexBarCLI✅ + the live check aboveswift test --filter 'GrokFailedBillingWorkTests|…'SwiftUIMacros/PreviewsMacrosplugins require Xcode). Relying on PR CI.swiftformat/swiftlintnot installed locally;git diff --checkclean, lines ≤ 120 cols.🤖 Generated with Claude Code