Upsell ai reasoning effort#8648
Merged
Merged
Conversation
Collaborator
Author
This stack of pull requests is managed by Graphite. Learn more about stacking. |
2 tasks
Base automatically changed from
feature/youssef/ai_reasoning_effort_tier
to
develop
May 20, 2026 23:28
67285ec to
43beb24
Compare
43beb24 to
c92886a
Compare
3 tasks
malmstein
approved these changes
May 21, 2026
Contributor
malmstein
left a comment
There was a problem hiding this comment.
nice refactor pulling routeUpsell and PickerSurface into a shared file — the reasoning picker now mirrors the model picker pattern cleanly, and the test coverage for the new per-effort gating is solid (the ReasoningResolverTest cases are particularly thorough). couple of small things: the hardcoded gpt-5.2 gate overwrites rather than merges and has no test of its own, and the silent else -> null in routeUpsell loses a useful debug log.
2 tasks
YoussefKeyrouz
added a commit
that referenced
this pull request
May 21, 2026
Task/Issue URL: https://app.asana.com/1/137249556945/project/488551667048375/task/1214635053937863?focus=true ### Description Addressing comments from #8648 ### Steps to test this PR - [ ] Sign in with a PLUS account -> Try to select GPT 5.2 with extended reasoning —> Upsell flow should trigger - [ ] All other models should behave as expected. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Touches model/effort access gating and persistence used to drive upsell behavior, so mistakes could incorrectly block or unlock reasoning modes; changes are small and backed by new targeted tests. > > **Overview** > Prevents the temporary hardcoded `gpt-5.2` EXTENDED reasoning effort gate from **overwriting backend-provided** `reasoningEffortAccess` by merging: server entries are preserved and hardcoding only fills missing effort IDs. > > Tightens reasoning-mode persistence by comparing `ReasoningMode` values directly (avoids unnecessary writes when raw values match), and adds a defensive log breadcrumb when an upsell is requested for a tier transition that has no native flow. > > Adds unit tests to lock in the new merge behavior and ensure EXTENDED reasoning candidates remain hardcoded to `pro` until the backend gate is removed. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit ae9b8f4. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Task/Issue URL: https://app.asana.com/1/137249556945/project/1212810093780571/task/1214635053937863?focus=true
Description
Part 2 of 2 — Subscription upsell trigger for gated reasoning efforts.
Part 1 added schema support for the new
reasoningEffortAccessfield on the/duckchat/v1/modelsresponse. This PR wires the user-facing upsell: tapping a gated reasoning mode on an accessible model now routes the user into the nativeSubscriptionPurchase(FREE → PLUS/PRO) orSubscriptionUpgrade(PLUS → PRO) flow, mirroring the model-level upsell already shipped on #8625.What changed:
AvailableReasoningModenow carries an optionalaccess: ReasoningEffortAccess?plus a derivedisAccessibleflag.ReasoningResolver.availableModes(supported, effortAccess)picks the first candidate effort per mode that is supported and accessible; if none are accessible, it falls back to the first supported one so the row still renders for upsell routing. Missing per-effort access metadata is treated as accessible.ReasoningModePickerViewModel.onModeTapped(mode, surface)runs the same decision table as the model picker: accessible → select; gated → route toLaunchPurchase/LaunchUpgradebased onaccess.requiredTier+ currentuserTier.PickerSurfaceandUpsellCommandlive in a new shared file. The model picker was re-pointed to use these instead of its previously nested types.Notes:
Steps to test this PR
SubscriptionPurchaseopens with the model-picker funnel origin.SubscriptionUpgradeopens.UI changes
screen-20260520-202439-1779319456993.mp4
Note
Medium Risk
Introduces new per-effort accessibility logic for reasoning modes and routes users into purchase/upgrade flows, which can affect subscription funnel behavior and persisted selection state. Also adds a temporary hardcoded gate for
gpt-5.2that could mis-gate if model IDs or backend behavior change.Overview
Adds per-reasoning-effort access awareness and upsell routing:
AvailableReasoningModenow carries optional access metadata andReasoningResolver.availableModesselects the first supported + accessible effort per mode (falling back to a gated effort so the row can still render for upsell).Updates
RealDuckAiModelManagerto validate persisted reasoning selections against accessibility (auto-selecting/persisting the first accessible mode, refusing gated selections, and allowingselectedReasoningModeto becomenullwhen all efforts are gated). The reasoning-mode picker now triggers the nativeSubscriptionPurchase/SubscriptionUpgradeflows when a user taps a gated mode, using sharedPickerSurface/UpsellCommandtypes (also adopted by the model picker).Includes a temporary, hardcoded PRO-only gate for
gpt-5.2EXTENDED_REASONINGuntil backend per-effort gating ships, and expands tests to cover gating/auto-promotion/upsell behavior.Reviewed by Cursor Bugbot for commit c92886a. Bugbot is set up for automated code reviews on this repo. Configure here.