Skip to content

feat(fx): choose a backend per thread - #26994

Closed
jakeleventhal wants to merge 2 commits into
pingdotgg:mainfrom
jakeleventhal:fx-backend-picker
Closed

jakeleventhal wants to merge 2 commits into
pingdotgg:mainfrom
jakeleventhal:fx-backend-picker

Conversation

@jakeleventhal

@jakeleventhal jakeleventhal commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Continued in #29388. GitHub refused reopening this PR after the branch rebase, including after restoring its closing head. The replacement carries the validated rebased head, this history, and all prior evidence links.

fx can run on Vercel AI Gateway, a Codex or Grok subscription, or a configured OpenAI-compatible endpoint, but T3 Code only offers the machine's active backend. This adds per-thread backend selection and restores Default as a valid backend/model pair, using the thread's folder configuration.

Scope and reconsideration

Reconsidering the closure explanation and closed event 34691805908. Upstream still exposes only the machine-default fx backend; per-backend catalogs, grouping, switching, and folder-aware Default remain absent.

Backend selection and resetting Default share a concrete invariant: restore a backend and a model that belong together. After a thread switches from Gateway to Codex, selecting Default must restore the default backend before its model; writing the Gateway model on Codex can fail or leave the previous model running. The adapter replay test covers both switching backends in one session and restoring a loaded session to the default backend, with the provider write before the model write.

Folder-aware lookup is independently separable. It is retained here deliberately because the same Default resolution path returns that backend/model pair in the thread's folder; it is not a required technical dependency of backend grouping. This is a request to reconsider the combined scope, not a claim that maintainers approved it. The closure's missing before/native visual evidence remains a limitation, explicitly recorded below.

The rebase preserves upstream's compact picker, trailing Show more/less control, effort column and IME handling (#28057/#28076/#28409), mobile policy and reduced-motion behavior, and the longer fx version-probe timeout (#28400). It also retains the final auth fallback correction: unknown Gateway sign-in cannot hide a signed-in Codex backend.

Fix

  • Probing: the fx snapshot runs fx status --json (sign-in) and fx models --json (catalog) once per backend with FX_PROVIDER. Custom endpoints come from the providers keys in ~/.fx/settings.json. Nothing opens an ACP session, which fx would save. Models are listed as <backend>:<model> (fx backend ids never contain :).
  • Contracts: a new optional ServerProvider.subProviders (name plus optional unavailableReason) tells clients how to group a provider's models by subProvider. Only fx sets it, so other providers are unchanged.
  • Web picker: the fx tab shows Default, then one collapsible heading per backend. The thread's backend opens by default. A signed-out backend is a disabled heading with the fx login <backend> hint. Search and Favorites stay flat, retaining upstream's compact rows and inline backend labels.
  • Mobile thread settings: the same grouping, reusing the collapsible provider header (nested, no icon). The grouping helper in client-runtime is shared with web.
  • Per thread, not per machine: the adapter writes fx's session-only provider option before model, so each thread keeps its own backend and fx's global default is never changed. Logins stay machine-wide, which is why signed-out backends show as unavailable everywhere. A model id with no backend prefix (existing threads) still runs on the session's current backend.
  • Default: it now resolves with fx status --json run in the thread's folder, so a per-project model in fx's settings is used there. On a session that is on another backend, Default now moves it to the default backend rather than staying put.
  • Docs: docs/user/providers-fx.md is updated.

Prior visual evidence (2026-10-29)

These are historical captures of the original implementation, before upstream's later compact picker changes; they are not refreshed screenshots of this rebased head. Web, against a scripted fake fx (Codex and Gateway signed in, Grok signed out).

Before: the fx tab was a flat list of Default plus the models of the machine's active backend, with no way to switch backends.

Picker open, Grok signed out:

Switching backend: open Vercel AI Gateway from a thread on Codex:

The same thread ran one turn on Codex and the next on the gateway (the fake echoes the backend and model the session ran on):

Search across backends:

There is no before screenshot or interaction recording in the prior evidence. Mobile has no device capture: the remote iOS simulators were either owned by other sessions or stuck on the dev client's "Open in" prompt. The mobile grouping is covered by a unit test and typecheck only.

Prior validation

Original implementation attribution: Claude Opus 5.5 in Claude Code. This revival and rebase used GPT-6.1 Sol through Codex.

  • Original final head: 5a4461a033b56a3b866e6a6d9bfb14e593ad3e6a. CI run 40894823238 completed successfully on that head; this is prior CI, not a result for the rebased head.
  • The original implementation reported real fx 0.0.15 probes in a throwaway HOME for FX_PROVIDER/FX_MODEL, a custom endpoint, and a per-folder model. Those probes were not rerun during revival.
  • The original local check:changed report noted unrelated macOS /var versus /private/var failures in ServerEnvironment.test.ts and build-npm-launcher.test.ts. Current results are listed separately below.

Current validation

  • Rebased onto upstream ac8dce0cc3abd8a337f2d806b5082a6834b9b81a.
  • vp test run packages/provider-fx/src/server/status.test.ts apps/server/src/orchestration-v2/Adapters/FxAdapterV2.test.ts apps/mobile/src/lib/modelOptions.test.ts: 43 tests passed across three files. Covers per-backend catalogs/auth, unreadable-sign-in fallback, folder-aware defaults, provider-before-model writes, same-session backend switching, loaded-session Default reset, and grouping with a signed-out backend. The upstream six-second/hung-version probe cases are preserved using TestClock.
  • vp run check:changed upstream/main --concurrency 2: passed. Format, lint, unused patches, both knip passes, GraphQL generation, 39 selected package typechecks, 54 tests in seven adjacent files, and nine selected React Compiler cases for four changed client files passed. CI still owns the full suites, builds, Rust, and release smoke.
  • git diff --check: passed.
  • No browser, desktop, native-device, or real-provider turn was run during revival. No current visual/CLI runtime validation is claimed. The shared web picker covers web and desktop; mobile uses the same grouping helper and separate native rendering. The optional contract carries backend metadata across local, remote, and tunnel connections; other adapters do not set it.

GPT-6.1 Sol through Codex.

fx can run on Vercel AI Gateway, a Codex or Grok subscription, or a
configured OpenAI-compatible endpoint, but T3 Code only offered the
backend `fx provider` had set, so switching meant a terminal.

The fx snapshot now probes every backend with `FX_PROVIDER` (`fx status`
for sign-in, `fx models` for its catalog) and lists models as
`<backend>:<model>`. A new `subProviders` field on the provider snapshot
lets the web picker and the mobile thread settings group them under
collapsible backend headings; signed-out backends stay listed as
unavailable with the `fx login` command to run. The adapter writes fx's
per-session `provider` option before `model`, so each thread keeps its
own backend without touching fx's global default.

"Default" now resolves with `fx status` in the thread's folder, so a model
fx's settings give one project is picked up there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XL 500-999 changed lines (additions + deletions). labels Oct 29, 2026
@macroscopeapp

macroscopeapp Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs Human Approval

Macroscope's review found this PR requires human approval — The picker adds explicit, session-local fx backend selection. Default also changes to use the project's backend and model settings, so existing Default threads may route differently; that behavior change needs human confirmation.

Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more.

…n one

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
Commits

Reviewing files that changed from the base of the PR and between 37fbefd and 5a4461a.

Files selected for processing: 15
  • apps/mobile/src/features/threads/ThreadSettingsSheet.tsx
  • apps/mobile/src/lib/modelOptions.test.ts
  • apps/mobile/src/lib/modelOptions.ts
  • apps/server/src/orchestration-v2/Adapters/FxAdapterV2.test.ts
  • apps/web/src/components/chat/ModelPickerContent.tsx
  • apps/web/src/components/chat/modelPickerKeys.ts
  • docs/user/providers-fx.md
  • packages/client-runtime/package.json
  • packages/client-runtime/src/providerSubProviders.ts
  • packages/contracts/src/server.ts
  • packages/provider-fx/src/server/acpSupport.ts
  • packages/provider-fx/src/server/adapter.ts
  • packages/provider-fx/src/server/driver.ts
  • packages/provider-fx/src/server/status.test.ts
  • packages/provider-fx/src/server/status.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 7 remain after this review.

Walkthrough

The fx provider now discovers models and availability across built-in and configured backends. Model choices can target a backend and use project-folder defaults. Web and mobile model pickers display models in collapsible sub-provider sections.

Changes: fx Backend Selection and Model Picker

Layer / File(s) Summary
Sub-provider contract and grouping
packages/contracts/src/server.ts, packages/client-runtime/src/providerSubProviders.ts, packages/client-runtime/package.json, apps/mobile/src/lib/modelOptions.ts, apps/mobile/src/lib/modelOptions.test.ts
The server contract adds ordered sub-provider metadata. Client utilities group models by sub-provider, and mobile model options carry that metadata.
Backend status and default discovery
packages/provider-fx/src/server/status.ts, packages/provider-fx/src/server/status.test.ts, packages/provider-fx/src/server/driver.ts
The status check reads configured backends, probes their status and model listings, and creates backend-qualified model entries with availability details. It also reads a default backend and model in a specified working directory.
Backend-aware model selection
packages/provider-fx/src/server/acpSupport.ts, packages/provider-fx/src/server/adapter.ts, packages/provider-fx/src/server/driver.ts, apps/server/src/orchestration-v2/Adapters/FxAdapterV2.test.ts, docs/user/providers-fx.md
Model selection accepts backend-qualified choices and applies the provider before the model. The adapter resolves defaults by runtime working directory. Tests cover backend changes, and the documentation describes the selection behavior.
Sub-provider picker sections
apps/web/src/components/chat/ModelPickerContent.tsx, apps/web/src/components/chat/modelPickerKeys.ts, apps/mobile/src/features/threads/ThreadSettingsSheet.tsx
The web and mobile pickers group models under collapsible backend headings. They retain flat Search and Favorites views, and show unavailable reasons for unavailable backends.

Priority: Normal

Estimated code review effort: 4 (Complex) | ~45 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  participant FxDriver
  participant checkFxProviderStatus
  participant FxCLI
  participant ProviderSnapshot
  FxDriver->>checkFxProviderStatus: Request provider status
  checkFxProviderStatus->>FxCLI: Probe each backend status and models
  FxCLI-->>checkFxProviderStatus: Return backend status and model listings
  checkFxProviderStatus->>ProviderSnapshot: Build models and availability metadata
Loading

Possibly related PRs

  • pingdotgg/t3code#18277: Introduces the fx provider and its status probes, model selection, and ACP adapter, which this change extends with multiple backends.
  • pingdotgg/t3code#25914: Changes model-row rendering for sub-provider data, which relates to the grouped model presentation added here.

Suggested reviewers: agadzik, maria-rcks, juliusmarminge

Merge Risk: Minimal · up to 5a446

No actionable merge-blocking issue is established. The remaining backend-compatibility uncertainty can be checked during normal validation.

Pre-merge checks: Passed 4
Check name Status Explanation
Title check Passed The title clearly and concisely describes the main change: selecting an fx backend from the model picker.
Description check Passed The description clearly covers the problem, implementation, affected clients, evidence, tests, limitations, and known unrelated failures. It omits the template's explicit Scope and approval section, b…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Description check

Explanation

The description clearly covers the problem, implementation, affected clients, evidence, tests, limitations, and known unrelated failures. It omits the template's explicit Scope and approval section, but the substantive description is mostly complete.

Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@t3-code-bot

t3-code-bot Bot commented Oct 30, 2026

Copy link
Copy Markdown
Contributor

closing at @StiensWout's request under Solve one underlying problem per PR.

The fx backend picker also repairs the independent folder-aware Default-model resolution, and its changed mobile picker has no visual verification. The supplied web images show only the new UI.

Separate the folder-aware Default-model repair from backend selection/grouping, or establish their necessary causal relationship. Supply clear before/after visual evidence for the changed web and native mobile picker states, including signed-out and expanded backend behavior; preserve the reported inability to choose an fx backend in T3.

thanks for trying to help improve t3 code. if you think this closure was a mistake, please open a fresh pr addressing the requirement above, and link back to this one.

@t3-code-bot t3-code-bot Bot closed this Oct 30, 2026
@jakeleventhal jakeleventhal changed the title feat(fx): pick fx's backend in the model picker feat(fx): choose a backend per thread Nov 2, 2026
@jakeleventhal

Copy link
Copy Markdown
Contributor Author

Note

🤖 GPT-6.1 Sol responding on behalf of Jake

Continued in #29388 for reconsideration of the closure. GitHub refused to reopen this PR through GraphQL and REST because the branch was force-pushed or recreated; restoring its closing head also failed. The replacement preserves this history and all evidence links. The underlying problem remains: upstream offers only the machine-default fx backend.

Backend switching and resetting Default belong together because the adapter must restore a valid backend/model pair. A thread switched to Codex cannot safely reset to a Gateway default by writing only the model; the provider must change first. The adapter replay tests exercise that ordering and switching within one session.

Folder-aware Default lookup can be separated technically. I am retaining it in the same default-resolution path and requesting reconsideration of that combined scope; I am not claiming it is required for grouping or that maintainers approved it.

The description preserves all four prior fake-fx web captures and the reported real fx 0.0.15 probes and prior successful CI. It labels them historical. There is still no before screenshot, native capture, or interaction recording, and no fresh UI or real-provider runtime claim. The rebase preserves upstream picker, mobile policy/animation, and probe-timeout changes, plus the final auth fallback fix.

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

Labels

size:XL 500-999 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant