feat(web): split provider settings into list and editor - #125
Merged
Conversation
Provider settings spread status, switches, and detailed controls down one long page, so scanning providers or moving between configurations was hard. The page becomes two columns: the left keeps every provider and its on/off switch visible, the right edits one provider through Models and Configuration tabs. Device selection moves to compact tabs and the health check interval moves under Advanced. The commit also carries a real fix that was bundled with the redesign: `ProviderEnvironmentSection` never resynced its draft rows when the `environment` prop changed, so environment-variable edits made elsewhere did not appear. It now resyncs, with equality checks so a resync cannot stomp in-flight typing. Disabled providers get a muted status dot instead of an amber one, which no longer reads as a warning. Adapted for Pylon, which had diverged in both files: - The new device tab bar called `connectionPhaseDotClassName` and `connectionPhasePingClassName`, which Pylon does not have — it replaced `ConnectionStatusDot` with a DotMatrix-backed component taking a `state`. Rewritten against Pylon's API. - Upstream deleted `ProviderAuthEmail` and left the account email nowhere on the page. Upstream can: it has one account per driver. Pylon has several per driver with an explicit drain order, so the redacted email is what tells two Claude accounts apart. It is restored in the editor header, and `showEditorStatus` now covers any account with an email or a sign-in to offer rather than only warning and error states. - Drain-order controls and the account reset join delete in the editor header. Reordering is visible in the list as it happens. - The usage summary stays on every list row, not just the selected account. Comparing quota across accounts is the reason it exists, and selecting each one in turn to read it would have defeated that. `ProviderUsageSummary` became a block span so it is valid inside the row's select button. - The detailed usage rows follow the collapsible they lived in, to the top of the Configuration tab. - The sign-in dialog is now a sibling of the editor rather than the old card, so it renders once for the selected account. Adds a focused test that the editor receives drain-order controls for a driver with several accounts, that the list rows do not, that read-only sessions get none, and that a move writes the expected priority patch — the grafts most likely to vanish quietly in a future upstream merge. (cherry picked from commit e2d4d12a81516b55abbecdc64794971f781cacd8)
Two change sets through `e2d4d12a8`, both adopted with adaptation: the Android adaptive launcher icon (#124) and the provider settings split (#125). Cursor advances to `e2d4d12a8`. DEF-7 was re-checked against the current upstream head and stays open — no commits touch `desktop-macos-preview.yml` in this range and its earliest revisit date is 2026-11-01. No new register entries.
Thread transfer impact✅ Thread transfer remains within every enforced ceiling.
Baseline: Scenario and decoded snapshot size10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.
Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed. |
Found in the live app: a Claude account reports three usage windows, and the summary line for it is wider than the 20rem provider column. Each window is `whitespace-nowrap`, so the row's select button could not shrink below its min-content width and the text painted under the enable switch beside it, then wrapped "used" onto a fourth line. `ProviderUsageSummary` now truncates, which both clips the overflow to an ellipsis and lets the flex row shrink. Single-window accounts such as Codex are unaffected.
Four defects from review of the split. Reordering swapped the editor onto a different account. The editor falls back to `rows[0]` while nothing has been clicked, and a move rewrites the priorities `rows` is sorted by, so clicking "use this account later" on the first account made `rows[0]` the account that took its place — remounting the editor onto it, resetting the tab and discarding environment-variable drafts, and pointing the next click at the wrong account. The selection is pinned before the patch now. The new test reproduces it: it applies the emitted patch, re-renders, and fails without the pin. An outdated provider was invisible from the list. The advisory popover moved to the editor, which only ever shows the selected account, so finding any of them meant clicking each in turn — and Pylon's bounce cue on the icon was dropped with it. The list rows carry a marker again, as static text inside the row's existing button rather than a nested control. A disabled account showed nothing in the editor: `showEditorStatus` required `enabled`, so it hid the account email — the thing the graft exists to preserve — exactly when you are deciding which of two disabled accounts to re-enable. It also discarded the server's reason for the provider, which `getProviderSummary` already supplies, so a disabled provider whose CLI is missing said only "Disabled". The environment resync cleared its one-shot echo guard on every effect run, including the runs that changed nothing. Since the card passes `instance.environment ?? []`, an instance with no variables allocates a new array every render, so a publish's echo routinely arrived with the guard already spent and was treated as an external edit — resyncing mid-edit and remounting the inputs. The guard is only consumed now when the environment actually changed. Also anchors two assertions that passed vacuously when their element was absent.
The batch recorded both adoptions against open pull requests as though they had landed. It now says so explicitly, and says what to do if either is closed unmerged — an advanced cursor will not surface the upstream commit again. The U1 detail also stated the wrong mechanism. The universal channel icons are rounded squares, but their corners fall outside the 72dp visible window, so "an icon composited inside the launcher mask" was never the defect: a full-bleed layer is scaled to 108dp and cropped to its centre 72dp. Records the corrected mark size and the monochrome layer that the first commit missed.
This was referenced Aug 28, 2026
rynfar
added a commit
that referenced
this pull request
Aug 29, 2026
Selecting a different provider account resized the whole settings panel, because the master-detail grid had no height of its own and the editor pane grew to fit whichever account was open. The models list was also capped at a 40-unit scroll box regardless of available space. Gives the grid a fixed height, lets the list and editor panes scroll independently, and lets the models list grow to fill the editor instead of scrolling inside a stub. Adopted from T3 Code f276e632c5a7952655e2455aef3b86c08164b988 (pingdotgg/t3code#8472), the follow-up to the provider settings split Pylon took in #125. Adaptation: upstream also re-added the account email as a labelled "Account email" field in the Configuration tab. Pylon already shows it in the editor header, so that half is deliberately not adopted — taking both would render the same redacted address twice in one panel. Upstream's test for the Configuration placement is retargeted at Pylon's header placement and gains a guard asserting the Configuration field stays absent; it also needed Pylon's required timestampFormat prop, which upstream's card does not have. Four conflicts resolved Pylon-first, preserving the richer ProviderAuthEmail, the widened showEditorStatus, the disabled-account detail message, and the Provider usage block.
rynfar
added a commit
that referenced
this pull request
Aug 29, 2026
Seventeen upstream commits, thirteen change sets, all decided: ten adopted (six with adaptation), three skipped, none deferred. Advances reviewed-through to f94a0d646. Closes the previous batch's open-pull-request caveat, since #124 and #125 have both merged. Records three findings carried forward rather than fixed: Pylon still reports telemetry into T3 Code's PostHog project, Codex plan decode fails the whole provider probe on any unrecognised plan, and schema.gen.ts cannot be verified by regeneration in either fork. Also records that scripts/build-desktop-artifact.test.ts already fails on pylon, confirmed against origin/pylon's own copies.
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.
Provider settings spread status, switches, and detailed controls down one long page, so scanning providers or moving between configurations was hard. The page becomes two columns: the left keeps every provider and its on/off switch visible, the right edits one provider through Models and Configuration tabs. Device selection moves to compact tabs, and the health check interval moves under Advanced.
Bundled with the redesign upstream, and worth having on its own:
ProviderEnvironmentSectionnever resynced its draft rows when theenvironmentprop changed, so environment-variable edits made elsewhere never appeared. It resyncs now, with equality checks so a resync cannot stomp in-flight typing. Disabled providers also get a muted status dot instead of an amber one that read as a warning.Adapting it to Pylon
Both files had diverged, so this is a cherry-pick with real resolution rather than a clean apply.
connectionPhaseDotClassNameandconnectionPhasePingClassName; Pylon has neither, having replacedConnectionStatusDotwith a DotMatrix-backed component that takes astate. Rewritten against Pylon's API.ProviderAuthEmailand leaves the email nowhere on the page — fine there, because upstream has one account per driver. Pylon has several per driver with an explicit drain order, so the redacted email is the thing that tells two Claude accounts apart, and it is what the sign-in dialog reads.showEditorStatusnow covers any account with an email or a sign-in to offer, not only warning and error states.ProviderUsageSummarybecame a blockspanso it is valid DOM inside the row's select button.Tests
Adds a focused test that the editor receives drain-order controls for a driver with several accounts, that list rows do not, that a read-only session gets none, and that a move writes the expected priority patch. Both halves were mutation-checked: deleting the
drainOrdergraft fails it, and so does droppingtimestampFormat.The environment-variable resync fix ships without a new test.
apps/webhas no DOM test environment — component tests here userenderToStaticMarkupor shallow prop inspection, neither of which runs the effect the fix lives in. Adding jsdom for one test is out of scope for an adoption; flagging it rather than claiming coverage.Checks
vp run -F @t3tools/web typecheck— cleanvp test run apps/web/src/components/settings/ apps/web/src/components/providerUsage/— 24 files, 151 tests passingvp lint --report-unused-disable-directivesandvp fmt --checkon the six changed files — cleanVerified in the app
Ran a dev server against a copy of a real Pylon database (Codex plus two Claude accounts) and captured Settings → Providers. Re-run on
82edffce2, so it covers the review fixes below, not just the original split. Images attached.Confirmed live:
Use Work earlier (currently 1 of 2)/Use Work later (currently 1 of 2).Update availablelabels in the DOM.Disabled · Cursor is disabled in Pylon settings.— both the un-gated line and the preserved server reason.The first pass earned its keep by catching a layout bug in my own graft: a Claude account reports three usage windows, each
whitespace-nowrap, so the summary line was wider than the 20rem column, could not shrink, and painted under the enable switch. Fixed in1f1cae8daby truncating the summary.Device tabs are not exercised: this environment has one primary device, so
deviceTabsrenders null by design. That path is still unverified visually.Review fixes
A review of this branch found four defects, all fixed in
a9d75ce1e:rows[0]while nothing has been clicked, and a move rewrites the prioritiesrowsis sorted by — so "use this account later" on the first account maderows[0]the account that took its place, remounting the editor onto it, resetting the tab, discarding environment-variable drafts, and pointing the next click at the wrong account. The selection is pinned before the patch now, and the new test applies the emitted patch and re-renders, so it fails without the pin.showEditorStatusrequiredenabled, hiding the account email exactly when you are choosing which of two disabled accounts to re-enable — the case the graft exists for. It also discarded the server's reason, so a disabled provider with a missing CLI said only "Disabled".instance.environment ?? [], so an instance with no variables allocates a new array every render and the effect runs every render; the guard was cleared unconditionally at the top, so a publish's echo routinely arrived unsuppressed and was treated as an external edit — resyncing mid-edit and remounting the inputs. It is only consumed now when the environment actually changed.Two findings are recorded but not fixed here, both in code adopted verbatim:
aria-pressedbuttons withhiddenpanels, so assistive tech gets no tab/panel relationship and no arrow-key navigation. Upstream's design; worth a follow-up across both strips.Upstream
e2d4d12a8/ pingdotgg/t3code#8380.Built with Opus 5 in the Claude Code harness.
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.