feat: dedupe model picker and gate premium models behind upgrade prompt - #1906
feat: dedupe model picker and gate premium models behind upgrade prompt#1906sweetmantech wants to merge 1 commit into
Conversation
The AI Gateway model list exposes alias ids that render as duplicate rows in the picker; dedupe by id and normalized display name. Badge every premium model with a small achromatic Pro chip (derived from gateway pricing metadata via the existing isFreeModel threshold) and, when a non-subscribed user selects a premium model, keep the current selection and trigger the Stripe upgrade flow instead of dead-ending on an error toast. Part of #1902 (item C6). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Review limit reached
Next review available in: 55 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (2)
📒 Files selected for processing (4)
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 |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 710182f53e
ℹ️ 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".
| const isPremium = selectedModel ? isPremiumModel(selectedModel) : true; | ||
| if (isPremium && !isSubscribed) { | ||
| toast.info("Upgrade to Pro to use this model."); | ||
| handleSubscribeClick(); |
There was a problem hiding this comment.
Avoid launching checkout while subscription status is loading
When a signed-in Pro user opens the picker before useProStatus finishes, usePayment still reports isSubscribed as false, so this new branch treats a premium model as gated and calls handleSubscribeClick(). That hook uses the same still-loading subscription state and can start a checkout session instead of letting the paying user select the model; consider gating on the payment loading state or waiting for subscription status before opening checkout.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
1 issue found across 6 files
Confidence score: 3/5
- In
components/ModelSelect/ModelSelect.tsx, the Pro-model selection path can run before subscription status finishes loading, so subscribed users may be incorrectly sent to checkout instead of getting the model, creating a clear user-flow regression at point of use — gate the checkout branch on resolved payment status or disable the picker until status is loaded.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="components/ModelSelect/ModelSelect.tsx">
<violation number="1" location="components/ModelSelect/ModelSelect.tsx:37">
P2: Subscribed users selecting a Pro model before subscription status finishes loading are routed to checkout instead of selecting it. Gate this branch only after payment status has resolved (or disable the picker while it loads).</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| "This model is not free. Please upgrade to a paid plan or select a free model." | ||
| ); | ||
| const isPremium = selectedModel ? isPremiumModel(selectedModel) : true; | ||
| if (isPremium && !isSubscribed) { |
There was a problem hiding this comment.
P2: Subscribed users selecting a Pro model before subscription status finishes loading are routed to checkout instead of selecting it. Gate this branch only after payment status has resolved (or disable the picker while it loads).
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At components/ModelSelect/ModelSelect.tsx, line 37:
<comment>Subscribed users selecting a Pro model before subscription status finishes loading are routed to checkout instead of selecting it. Gate this branch only after payment status has resolved (or disable the picker while it loads).</comment>
<file context>
@@ -30,11 +33,10 @@ const ModelSelect = () => {
- "This model is not free. Please upgrade to a paid plan or select a free model."
- );
+ const isPremium = selectedModel ? isPremiumModel(selectedModel) : true;
+ if (isPremium && !isSubscribed) {
+ toast.info("Upgrade to Pro to use this model.");
+ handleSubscribeClick();
</file context>
What
Cleans up the chat model picker for anonymous and free users (item C6 of the web UX conversion audit):
alibaba/qwen3-235b-a22b-thinkingandalibaba/qwen3-vl-thinkingboth display as "Qwen3 VL 235B A22B Thinking"). Newlib/ai/dedupeModels.tsdedupes by id and by normalized display name (trim, lowercase, collapse whitespace), keeping the first occurrence. Ids in the live list are unique; the duplicates differ only by alias id, so normalized name is the effective dedupe key.lib/ai/isPremiumModel.tsbadges every premium model with a small achromatic pill chip (matches the existing featured-pill styling and the DESIGN.md badge spec). Replaces the previous Lock/Crown icons, so the picker now visibly matches the sidebar's "premium AI models" pitch.useSubscribeClick.handleClick, the same Stripe checkout the sidebar "Start Free Trial" card uses).How premium is derived
Tier metadata already exists on the gateway model objects:
pricing.input/pricing.output.isPremiumModelis the negation of the existingisFreeModelpricing threshold (input <= $0.50/M and output <= $2.50/M is free), so no curated model-id list was needed. Models with missing or unparseable pricing are treated as premium, matching the previous lock behavior.Files changed
lib/ai/dedupeModels.ts(new)lib/ai/isPremiumModel.ts(new)lib/ai/__tests__/dedupeModels.test.ts(new, 5 tests)lib/ai/__tests__/isPremiumModel.test.ts(new, 4 tests)components/ModelSelect/ModelSelect.tsx(dedupe + gate to upgrade flow)components/ModelSelect/ModelSelectItem.tsx(Pro chip, drop Lock/Crown icons)How to test
pnpm exec vitest run: 76 files / 285 tests passing.pnpm exec tsc --noEmit: no errors in changed files.Part of #1902.
Preview verification to follow in a PR comment.
🤖 Generated with Claude Code
Summary by cubic
Dedupes the chat model picker and gates premium models behind an upgrade prompt to improve clarity for anonymous and free users. Adds a "Pro" chip and routes gated selections to the existing upgrade flow; addresses C6 in #1902.
isPremiumModel(missing/unparseable pricing is treated as premium).useSubscribeClick(Stripe checkout).Written for commit 710182f. Summary will update on new commits.