Skip to content

feat(app): show the Go limit in a tray that grows out of the composer - #58008

Draft
kitlangton wants to merge 3 commits into
betafrom
go-limit-composer-tray
Draft

kitlangton wants to merge 3 commits into
betafrom
go-limit-composer-tray

Conversation

@kitlangton

@kitlangton kitlangton commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

▶ Pitch (phone, 64 s):

pr-58008-phone.mp4

Desktop: https://github.com/user-attachments/assets/ae325f30-6f7a-4279-94ba-4b03f88d4e5f

Head: c70d6f28190466e8d187d4fdbd5facbc99a4f96e

Confidence Size Affects API change Undo Reviewed by
Medium · Go-limit e2e passes, no outside review yet +290/−39 · 5 files, on #57897's 2 commits desktop No: app UI only One revert Opus → none yet

Risk: Based on beta (where the grow animation lives) with #57897's commits underneath. I'd merge #57897 first. The Go limit is kept in memory, so after a reload a free-limit error opens the Subscribe dialog again. Beta's app e2e legs and typecheck were already red, and build (windows) failed on a pkg.pr.new 404.

Not verified: Use credits opening the Console (not clicked on camera). Recorded against a mock gateway that returns GoUsageLimitError and FreeUsageLimitError, not the real Go service. Also, on a brand-new session's first message the error can arrive before the session screen mounts, so neither the old dialog nor the tray shows. That was already true before this change.

What it does. When a Go subscriber hits their Go limit, Desktop no longer opens a dialog. A tray grows out from under the composer instead. It says when Go is back, with two buttons: Use credits and Switch to a free model, which keeps the prompt. If they switch to a free model and run out of free messages too, the tray says both limits are reached, shows when each comes back, and leaves only Use credits.

Stacks on #57897's two commits (typed Go and ChatGPT limit errors), cherry-picked onto beta because the grow animation (#57559) only exists there.

How it works.

  1. session.step.failed with provider.go-limit opens SessionGoLimitTray and records the session in goLimited with its reset time.
  2. The tray uses the same Grow (fade) as the queue panel and tucks under the composer the same way. A small ring empties as the reset nears.
  3. Switch to a free model picks the first free OpenCode model from the composer's model list and closes the tray.
  4. A provider.free-limit in a session whose Go limit still holds goes to the tray (both limits) instead of the free-tier Subscribe dialog.
  5. The muted timeline line from fix(app): type the Go and ChatGPT usage limits so their dialogs fire #57897 stays.

Risk. Desktop UI only. The Go-limit dialog and its "don't show again" state are gone for this path. Free-tier users without Go still get the free-limit dialog. goLimited lives in memory, so after a reload a free-limit error shows the normal dialog until the next Go-limit error.

Proof.

  • Recorded in the real app against a hermetic server and a mock gateway (Go limit, then free limit), see the pitch above.
  • bunx playwright test e2e/regression/composer.spec.ts -g 'Go usage limit': pass. Covers the tray, the free-model switch keeping the prompt, and the both-limits state.
  • bun test src/session/usage-exceeded-dialogs.test.ts: 4 pass.
  • tsc -b in packages/app: clean except activity-chips.fixture.tsx (@opencode/ui/context/marked), which already fails on beta.
  • Known red, not from this PR: the free usage limit opens the Go dialog once… also fails on the untouched base (it times out waiting for "Continue in the browser"). Running e2e locally on beta also needs a one-line fix in packages/app/vite.js: bundleNestedWorkerDeps only matches bare @pierre/highlights, so @pierre/highlights/themes/loader from feat(app): highlight code with @pierre/highlights instead of Shiki #57937 fails to resolve in the dev server. That fix isn't in this PR.

core now classifies the Console's GoUsageLimitError 429 as provider.go-limit (keeping retryAfterMs) and ChatGPT's subscription_sharing_usage_limit_exceeded as provider.chatgpt-limit. Desktop opens 'Go limit reached' with the reset time, leaves a muted timeline line and hands the prompt back; the ChatGPT dialog matches the typed error instead of a stale copied string. The TUI restores the prompt and shows a muted Go-limit notice instead of a red error and failure toast.
Replaces the Go limit dialog with a tray above the composer: when Go is back, Use credits, and Switch to a free model, which keeps the prompt. If free models run out too while the Go limit holds, the tray says so with both reset times instead of opening the free-tier upsell.

This branch has not been deployed

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant