Repository navigation
cmux NEXT: offer Add Credits when the cmux model router refuses a turn - #27058
Conversation
…annot use Leo, 2026-10-26: "if user picks a model they don't have api key, we offer them to add credits or add their own api key" Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6
|
Owned by an agent session · took over from an earlier session · session |
|
Bead |
…credits Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6
Default changesThis pull request changes 1 default at
Signed off on this commit by Merge receipt: merged as Regenerate the snapshot with |
|
cmux status (one comment, edited in place; each line is updated by the job that owns it) Review App of this head (app.zip, kept 1 day)
Unclear: CI failed on
Not re-run automatically: Written by web and size checks: green Gallery before/after for
States
Pick other states with a |
|
Review (codex gpt-6-astra): SHIP at f77d043 Codex gpt-6-astra, high effort, fast mode, reviewed the full diff and all changed files over five rounds; every finding was settled before this SHIP:
Checks at this head:
|
teamleaderleo
left a comment
There was a problem hiding this comment.
Review (codex gpt-6-astra): SHIP at f77d043
Codex gpt-6-astra, high effort, fast mode, reviewed the full diff and all changed files over five rounds; every finding was settled before this SHIP:
- Round 1 (FIX): the router's typed
errorCode(inference.plan_required,credits.insufficient) was not classified. Fixed, with tests. - Round 2: SHIP (before a formatting-only commit).
- Round 3 (FIX): matching any mention of "cmux credits" was too broad. Narrowed to the router's two exact sentences plus its codes, with a negative test.
- Round 4 (FIX), answered rather than changed:
- "Enum cases cannot have default associated values": Swift allows them since 5.1. The line compiled and its tests passed on the Mac fleet.
- "Typed
credits.insufficientneeds a route check": these are the router's own namespaced codes, and a route check would drop the offer for Claude Code chats bound to thecmuxroute.
- Round 5: SHIP with those answers.
Checks at this head:
- Linux via cmux-ci: 46 webview tests pass, 0 fail;
vp fmt --check,vp lint(0 warnings, 0 errors),vp checkandcheck:catalog-keyspass. - Swift on the Mac fleet: AgentPaneAccessActionTests 5/5, AgentPaneConnectActionTests 6/6 and PaidPlanUpgradeTests 10/10 passed at e56d855, which has the same Swift tree as this head.
Resolves the App.tsx conflict with #26643 (session auth preflight): keep both the access offer memo and the session-auth fields on SignIn. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6
|
Review (codex gpt-6-astra): SHIP at a178851 |
|
Found 1 test failure on Blacksmith runners: Failure
|
|
Orphaned: no activity for 14 h, and no lane holds a lease on it. The orphan sweep could not merge |
…ffer # Conflicts: # webviews/src/agent-session/acpmux/Localizable.xcstrings # webviews/src/agent-session/acpmux/conversation/TurnRows.tsx # webviews/src/agent-session/acpmux/failureCopy.ts
|
Review (codex gpt-6-astra high fast, review-router): BLOCK at 8f2a0d6
VERDICT: BLOCK (Repair note, checked against the code: both hold. In backend/apps/api/src/inference/route.ts, |
…where Red at 8f2a0d6: credits.insufficient offers Add API Key… and no Add Credits…, and the pane still runs accounts.show. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-766f2935b39ba914eb08
Leo, 2026-10-26: "if user picks a model they don't have api key, we offer them to add credits or add their own api key" No placement makes a key saved from the pane usable today (acpmux passes no provider key to a built-in harness, and the model router uses only server keys), so Add API Key… leaves this PR; manaflow-ai/cmuxterm-hq#5411 tracks it. Both router refusals (inference.plan_required and credits.insufficient) offer Add Credits…, which opens the paid-plan upgrade, plus Retry and Switch model. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-766f2935b39ba914eb08
|
Review (codex gpt-6-astra high fast, review-router): BLOCK at 96baf37
The turn card's Add Credits… on the router's two refusals drew no finding. |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-766f2935b39ba914eb08
Credits pay only for the cmux model router: buying a plan signs no local harness in, so Add Credits… stays on the router's turn refusal only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-766f2935b39ba914eb08
Bugbot needs on-demand usage enabledBugbot uses usage-based billing for this team and requires on-demand usage to be enabled. A team admin can enable on-demand usage in the Cursor dashboard. |
|
Review (codex gpt-6-astra high fast, review-router): SHIP at 45b5e31 No findings. The reviewer's output at this head was the verdict alone. VERDICT: SHIP |
…ffer # Conflicts: # Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/AgentPaneModel+Actions.swift # webviews/src/agent-session/acpmux/Localizable.xcstrings
|
Review (codex gpt-6-astra high fast, review-router): SHIP at b8bfe52 No findings. This head is 45b5e31 (SHIP above) merged with feat-cmux-next; the only hand-resolved conflicts were the VERDICT: SHIP |
|
Shipped in:
|
…r Codex is not signed in (#31517) Leo, 2026-10-26: "if user picks a model they don't have api key, we offer them to add credits or add their own api key" #27058 shipped the Add Credits half (the router's plan and credit refusals). The key half waited on key plumbing (manaflow-ai/cmuxterm-hq#5411); #30188 has since given acpmux `_acpmux/agent_login/api_key`, which saves a key where the agent's own CLI reads it (Claude's settings.json env.ANTHROPIC_API_KEY, `codex login --with-api-key`) and restarts the chat on it. Only Cloud chats offered it. A chat on this Mac whose built-in `claude` or `codex` fails a turn for want of a sign-in now shows Use an API key after Sign in again; Save stores the key and Send again resends the failed prompt on the person's click. Routes (claude-cr, claude-sr) set their own key and endpoint, so they get no key field. Tests: bun test test/cloud-signin-card.test.tsx test/access-offer.test.tsx test/signed-out-rail.test.tsx -> 30 pass. Agent-Session: https://cmux.com/deeplink/agent?id=aid-60c63e855fe3c933a547 Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
![Fix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/fix-with-codesmith-light-3x.png)
Leo, 2026-10-26: "if user picks a model they don't have api key, we offer them to add credits or add their own api key"
This PR ships the Add Credits… half of that. The Add API Key… half is split out to manaflow-ai/cmuxterm-hq#5411: no placement makes a key saved from the pane usable today, so a button for it would be a dead end (details below and in the issue).
What changed
A turn the cmux model router refused for want of credits is no longer a dead end.
inference.plan_requiredorcredits.insufficient, and its Messages endpoint passes only the text on to Claude Code.needs-credits, from the router's words or its typed code. The cause line reads " needs cmux credits or your own API key for this model." (the router's own words). The card leads with Add Credits… (filled), then Retry and Switch model, on both refusals.Why Add Credits… fixes both refusals. In the router,
resolveCaller(backend/apps/api/src/inference/route.ts) sends every caller without a paid plan (!plan.paid) down the credits path:inference.plan_requiredwhen that caller has no credits either, andcredits.insufficientwhen a credit-funded caller's balance is short for the call. A paid-plan caller never reaches either. So the paid plan lifts both refusals. (An earlier revision of this PR assumedcredits.insufficientmeant "already on a plan"; that was wrong, and the card no longer treats the two differently.)Add Credits… runs
palette.pro.upgrade, the one paid-plan path from 6b30f93 (PaidPlanUpgrade: Checkout that returns to this app, else pricing), withsource: inference. That source was declared for the model router's paywall but had no caller. No new pricing, no Stripe copy, no money flow. The app has no credit top-up (PLAN.md: top-ups are test mode only, refused on production), so this PR doesn't offer one.The model picker keeps Log In alone. A signed-out local harness (Claude Code, Codex, Gemini) still lists only its own Log In in place of its models, as on base. An earlier revision also listed Add Credits… there, but cmux credits only help once the chat routes through the cmux model router: buying a plan doesn't sign the local harness in, add its key, or move the chat to the router, so after Checkout the tab would still be signed out with no models. That case is recorded on manaflow-ai/cmuxterm-hq#5411 with the key half.
Native gate.
AgentPaneModel.runActionadmitspalette.pro.upgradethe same way it admits the existing connect actions: only on the person's fresh gesture in the pane. Itssourcecomes from native code, never from the page. Settings > Accounts and every other app action stay out of the pane's reach.Why no Add API Key… here (manaflow-ai/cmuxterm-hq#5411)
Two review findings:
_meta.acpmux.env) passes only allow-listed keys (session_env.rsALLOWED_KEYS), and_acpmux/harness/secret/setwrites a${keychain:…}reference only into user profile files; for the built-in profiles it edits nothing. The app'sProviderKeyStoreitem is read only by CodeRouter Connect.INFERENCE_*_KEY, plans/cmux-next/paid-plan.md §2), so a person's key has nowhere to go there either.The issue names the two ways to make it real: a key sheet whose key reaches the harness env through acpmux, or a router BYOK path.
Gallery (
agent-pane.access-offer)Variants: a refused turn with no credits (
inference.plan_required), one short of credits (credits.insufficient), and a pane that cannot run app actions (no buttons, the cause line still names the way out). There are no arms: with one action there is no order to pick.Before / after
No capture: the Swift side adds no native UI. It only lets the agent pane run the existing paid-plan Checkout (
palette.pro.upgrade) on the person's click, and that Checkout surface is unchanged. The visible change is the agent pane webview, captured below.Gallery entry
agent-pane.access-offer, rendered in Chromium on Linux at the same fixture and size.A turn the cmux model router refused for want of credits
inference.plan_requiredorcredits.insufficient; the two render the same card)Risk
Low.
needs-creditsmatch is narrow ("cmux credits" or the router's two codes), so other quota failures read as before.action.runby one id behind the existing gesture gate, with a fixed native argument.palette.pro.upgradekeeps its behavior when invoked without arguments (palette, menu, CLI).signed-out-rail.test.tsx).Tests
Red first, then green, at this scope:
test/access-offer.test.tsx(classification from text and typed code;ACCESS_ACTIONSis only Add Credits…; on both refusals the card is Add Credits…, Retry, Switch model with one filled button and no Add API Key…; no buttons without the pane's actions; no offer on other failures) andtest/signed-out-rail.test.tsx(a signed-out harness's picker tab lists its own Log In alone: no Add Credits…, no Add API Key…, even where the pane can run Add Credits…). Red at 52b6851 (3 fail: the old card offered Add API Key… and a "ran out / top-ups" line): run 41115963774. Green with the fix, plusturn-error-card,signed-out-harness,failure-copy-team-account,vp fmt(no changes) andbun run check(0 warnings, 0 errors): 41 pass, 0 fail, run 41116488039. Picker: red at 66a7ab8 (the tab listed "Add Credits…"): run 41120778276; green with the fix, the same suites andbun run check: 41 pass, 0 fail, run 41121779463, and at the head 45b5e31 (format check, the same suites andbun run check): 41 pass, 0 fail, run 41122952653. After merging feat-cmux-next (head b8bfe52): webview suites andbun run check41 pass, 0 fail, run 41125914318; SwiftAgentPaneAccessActionTests2/2,AgentPaneConnectActionTests14/14,PaidPlanUpgradeTests10/10.AgentPaneAccessActionTests: Add Credits… needs a gesture and passes the fixedsource: inference;accounts.showandaccounts.removestay refused even with a gesture. Red at 52b6851 (accounts.showstill reachable). Green at 96baf37 withAgentPaneConnectActionTestsandPaidPlanUpgradeTests: 2/2, 13/13 and 10/10 passed (Xcode 26.6).needs_reviewoutside English).Observed / Not run
AgentPaneAccessActionTests; the last picker commit changes no Swift, and the Swift suites were rerun at the merged head.Agent session: agent session
🤖 Generated with Claude Code