Skip to content

Replace wpcom model choices with fast/balanced/strong capability tiers - #4727

Open
youknowriad wants to merge 8 commits into
trunkfrom
claude/wpcom-model-choices-refactor-4771d0
Open

Replace wpcom model choices with fast/balanced/strong capability tiers#4727
youknowriad wants to merge 8 commits into
trunkfrom
claude/wpcom-model-choices-refactor-4771d0

Conversation

@youknowriad

Copy link
Copy Markdown
Contributor

Related issues

How AI was used in this PR

Built end-to-end with Claude Code (Fable 5) in a pair-programming session: I directed the design decisions (tier names, defaults, proxy lane, gating and nudge behavior) turn by turn and reviewed each step. The agent wrote the implementation and tests, verified requests on the wire against the AI proxy, and checked the browser UI in light and dark themes.

Proposed Changes

The WordPress.com provider no longer exposes concrete model names. It now offers three capability tiers — Fast, Balanced, and Strong — sent verbatim to the proxy's studio-agent lane, which resolves each alias to an upstream model server-side. This lets us retune what backs each tier without a client release, and replaces a picker full of vendor names with a choice users can actually reason about.

  • Quota-based default: fresh sessions default to Balanced when purchased AI credits remain, Fast otherwise (also the fail-open floor when the quota can't be fetched). Sessions that already recorded a model keep it; sessions pinned to removed models (Sonnet/GPT/Kimi…) snap to the tier default on resume.
  • Paid-tier gating: Balanced and Strong render disabled in the desktop and browser pickers (withheld from the CLI /model list) unless purchased credits remain. Automatticians are exempt (email heuristic, show-only — the proxy stays the real access control).
  • Upsell nudges (experimental): free-allowance accounts get a footer item in the model picker under the disabled tiers, plus a dismissible muted line above the composer ("Add AI credits to unlock stronger models."). Both open the existing purchase flow; dismissal is remembered per renderer.
  • Wire formats: Fast/Balanced ride Chat Completions; Strong rides the Responses path because its upstream is a reasoning model that rejects tools-plus-reasoning on Completions. Sonnet 5 / Opus 5 remain available only on the Anthropic API-key provider, so every provider switch now crosses model families and starts a fresh conversation (same UX as cross-family model switches).
  • The Automattician-only hosted models (Kimi, GLM, DeepSeek) and GPT 5.6 Sol are removed from the picker.

Server-side dependency: the proxy's studio-agent feature lane must be allowlisted and accept both /v1/chat/completions and /v1/responses. Without it, wpcom turns fail (this is also why the identity eval couldn't pass from the dev machine — flagging for a human eval run once the lane is fully live).

Testing Instructions

  1. npm run cli:build && node apps/cli/dist/cli/main.mjs code — a fresh session on a free-allowance account shows Fast in the composer pill; /model lists only Fast (paid tiers hidden with an info line). With purchased credits, the default is Balanced and all tiers are listed.
  2. Browser UI (npm run cli:build:ui && node apps/cli/dist/cli/main.mjs ui --no-open): on a free account, open the model picker — Balanced/Strong disabled with the "Add AI credits…" footer item; the dismissible nudge line sits above the composer and stays dismissed after the ×. With an @automattic.com/@a8c.com account everything is unlocked and no nudge shows.
  3. Run a turn on each tier and confirm responses stream; Strong should go out over /v1/responses.
  4. Desktop app: same picker/nudge checks.

⚠️ Visual change: the desktop composer (banner + menu footer) needs human review in light + dark mode — verified headless only for the browser UI.

Pre-merge Checklist

  • Have you checked for TypeScript, React or other console errors?

youknowriad and others added 8 commits August 29, 2026 14:20
The WordPress.com provider now offers three capability tiers resolved to
upstream models by the proxy's studio-agent lane over the Chat Completions
API. Accounts with purchased AI credits default to balanced; free-allowance
accounts default to fast. Sonnet 5 / Opus 5 remain available only on the
Anthropic API-key provider.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The strong tier's upstream errors when the reasoning switch is left
implicit; fast and balanced keep sending no reasoning field at all.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Its upstream is a reasoning model that rejects the Chat Completions
dialect's tools-plus-reasoning combination; fast and balanced stay on
Chat Completions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Balanced and Strong are marked requiresPaidAiCredits and shown disabled
in the desktop and browser pickers (withheld from the CLI /model list)
unless purchased credits remain. UI gating only — the proxy enforces
access, and sessions already pinned to a paid tier keep showing it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two subtle surfaces sharing one line of copy: a footer item in the model
picker under the disabled tiers, and a dismissible muted line above the
composer (dismissal remembered per renderer via localStorage). Both open
the existing AI-credits purchase flow. Shown only once the quota
definitively reports a free-allowance account.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Balanced and Strong stay enabled for Automattician accounts regardless
of purchased credits, and the credits nudges disappear with the lock.
Show-only heuristic (a8c.com / automattic.com email) — the proxy remains
the real access control.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Validated session-model reads collapse into readRecordedSessionModel,
the nudge dismissal helpers move to packages/common, and narrating
comments shrink. Drops a duplicate credential-error test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@youknowriad
youknowriad force-pushed the claude/wpcom-model-choices-refactor-4771d0 branch from 05f7ab7 to bb57db3 Compare August 29, 2026 12:21
@wpmobilebot

Copy link
Copy Markdown
Collaborator

📊 Performance Test Results

Comparing bb57db3 vs trunk

app-size

Metric trunk bb57db3 Diff Change
App Size (Mac) 1422.63 MB 1422.65 MB +0.02 MB ⚪ 0.0%

site-editor

Metric trunk bb57db3 Diff Change
load 1186 ms 1184 ms 2 ms ⚪ 0.0%

site-startup

Metric trunk bb57db3 Diff Change
siteCreation 7513 ms 7535 ms +22 ms ⚪ 0.0%
siteStartup 3371 ms 3371 ms 0 ms ⚪ 0.0%

Results are median values from multiple test runs.

Legend: 🟢 Improvement (faster) | 🔴 Regression (slower) | ⚪ No change (<50ms diff)

// can't block the first turn — the free-tier default is the safe floor.
const QUOTA_FETCH_TIMEOUT_MS = 3_000;

async function resolveWpcomDefaultModel(): Promise< AiModelId > {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this lookup fails, a paid account runs on the fast tier and the persistSessionContext writes that into the session. When the session resumes, it never re-checks the quota. Can we skip persisting the model when the quota resolution did not succeed?

// only applies while nothing else picked a model.
let wpcomDefaultModel: AiModelId = getAiProviderDefaultModel( DEFAULT_AI_PROVIDER );
let quotaDefaultApplicable = ! recordedModel && currentProvider === DEFAULT_AI_PROVIDER;
const wpcomDefaultModelResolution = resolveWpcomDefaultModel()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default is resolved once at startup, so starting logged out settles it on Fast and when user logs in again, it does not re-resolve it. A user with purchased credits keeps running on Fast until they change it by hand. Can we re-resolve after a successful login?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A user with purchased credits keeps running on Fast until they change it by hand. Can we re-resolve after a successful login?

IMO that's the right thing to do, I don't think we should update the model randomly mid session even if the user purchase credits.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants