Skip to content

feat: Add provider health and per-provider controls#1289

Open
huxcrux wants to merge 8 commits intopingdotgg:mainfrom
huxcrux:feat/provider-settings-cleanup
Open

feat: Add provider health and per-provider controls#1289
huxcrux wants to merge 8 commits intopingdotgg:mainfrom
huxcrux:feat/provider-settings-cleanup

Conversation

@huxcrux
Copy link
Contributor

@huxcrux huxcrux commented Mar 21, 2026

What Changed

Added provider health visibility and per-provider enablement across Settings and provider selection.

  • Added provider health states for supported providers.
  • Added per-provider enable/disable controls in Settings.
  • Added provider login/logout actions in Settings.
  • Improved the Settings provider list so status and disabled state are easier to scan.
  • Prevented unavailable providers from being selected in provider pickers.
  • Updated tests and fixtures for the new provider health and enablement behavior.

Why

As more providers are added, provider availability needs to be explicit and predictable across the app.

This change makes provider health visible in one place, gives users a direct way to disable providers individually, and ensures the picker only allows selecting providers that are actually usable.

UI Changes

Added aa few extra pictures to show the different states when a provider is not found, unauthed or working fine.

Provider picker:

Before After
image image
image
image

Settings:

Before After
This UI is new image
image
image
image

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Note

Add provider health controls, per-provider enable/disable, and login/logout to settings

  • Extends ProviderHealth service with refreshStatuses, refreshStatus, login, and logout methods; adds four matching WebSocket methods (serverRefreshProviderStatuses, serverRefreshProviderStatus, serverProviderLogin, serverProviderLogout) wired through the server and native API client.
  • Adds plan and version fields to ServerProviderStatus, fetching the Codex plan via a short-lived app-server session when not available in auth output.
  • Adds a Providers section to the Settings page showing each provider's status dot, version, plan, and auth summary, with a toggle to enable/disable and a menu for Refresh, Log in, and Log out actions.
  • Adds enabledProviders to AppSettingsSchema (defaults both codex and claudeAgent to true) with isProviderEnabled, getEnabledProviderOptions, and patchProviderEnabled helpers.
  • Blocks sending messages, switching providers, and implementing plans in ChatView when the selected provider is disabled, not installed, or unauthenticated, showing an inline warning banner with an Open Settings link.
  • Updates ProviderModelPicker to reflect per-provider usability: disables unusable options, adds status labels, and changes styling for an unusable active provider.
  • Risk: getStatuses now reads from a cached Ref updated by explicit refresh calls rather than a startup-time fiber; callers that relied on the old snapshot behavior will see stale data until a refresh is triggered.

Macroscope summarized 44cb513.


Note

Medium Risk
Adds new WebSocket RPCs that execute provider CLIs (refresh/login/logout) and changes provider status resolution/caching, which can affect UX and correctness of provider readiness reporting across the app.

Overview
Adds end-to-end provider health visibility and controls: provider statuses now include optional plan and version, are cached in the ProviderHealth service, and can be refreshed (all or per-provider) as well as triggered to login/logout.

Introduces per-provider enablement in persisted settings (enabledProviders) and updates chat UI/pickers to block sending and prevent selecting disabled/unavailable/unauthenticated providers, surfacing actionable errors and a Settings shortcut.

Extends contracts + WebSocket server/native API with new RPC methods (server.refreshProviderStatuses, server.refreshProviderStatus, server.providerLogin, server.providerLogout) and updates health probing to parse auth JSON more robustly (shared authProbe) with a Codex plan fallback via an app-server account/read probe. Also removes per-client git.actionProgress publishing from gitRunStackedAction routing and adjusts tests accordingly.

Written by Cursor Bugbot for commit 44cb513. This will update automatically on new commits. Configure here.

@coderabbitai
Copy link

coderabbitai bot commented Mar 21, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: b20b3b16-101e-4f2e-a8d6-58389a81d51a

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

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

@github-actions github-actions bot added size:XXL 1,000+ changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Mar 21, 2026
@huxcrux huxcrux changed the title feat: Refine provider settings and picker availability states feat: Add provider health and per-provider controls Mar 24, 2026
@huxcrux
Copy link
Contributor Author

huxcrux commented Mar 24, 2026

Changed this PR from modifying settings (after the settings change where merged) to only focus on provider health/controls instead

@huxcrux huxcrux force-pushed the feat/provider-settings-cleanup branch from c0aedc6 to ed8c49b Compare March 24, 2026 19:28
@github-actions github-actions bot added size:XL 500-999 changed lines (additions + deletions). and removed size:XXL 1,000+ changed lines (additions + deletions). labels Mar 24, 2026
@github-actions github-actions bot added size:XXL 1,000+ changed lines (additions + deletions). and removed size:XL 500-999 changed lines (additions + deletions). labels Mar 24, 2026
activeProviderStatus !== undefined &&
activeProviderStatus.status === "ready" &&
activeProviderStatus.available &&
activeProviderStatus.authStatus === "authenticated";
Copy link
Contributor

Choose a reason for hiding this comment

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

Dropdown chevron hidden during initial status loading

Low Severity

showActiveProviderChevron requires activeProviderStatus !== undefined and status "ready" with "authenticated" auth. Before provider statuses load (empty array on initial render), activeProviderStatus is undefined, so the chevron is always hidden on first render. It's also hidden for "warning" status with "unknown" auth, even though isProviderUsable considers those providers usable. This creates a visual inconsistency where a usable provider's dropdown indicator disappears.

Fix in Cursor Fix in Web

</p>
) : null}
</div>
) : null}
Copy link
Contributor

Choose a reason for hiding this comment

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

Redundant nested null-check for error display

Low Severity

refreshProviderStatusesError is checked in the outer conditional (line 1061) and then redundantly checked again in an identical inner conditional (line 1063). Since React state doesn't change within a single render, the inner check is always true when the outer check passes, making the nested conditional dead code.

Fix in Cursor Fix in Web

Copy link
Contributor

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 3 total unresolved issues (including 2 from previous reviews).

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.


const child = spawn("codex", ["app-server"], {
stdio: ["pipe", "pipe", "ignore"],
shell: process.platform === "win32",
Copy link
Contributor

Choose a reason for hiding this comment

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

App-server probe bypasses ChildProcessSpawner service abstraction

Medium Severity

readCodexAccountPlanViaAppServer uses Node's raw spawn from node:child_process instead of the Effect ChildProcessSpawner service that every other CLI invocation in the provider layer uses. This breaks the service abstraction: when checkCodexProviderStatus falls back to this function (when parsed.plan is absent), it spawns an actual codex app-server process that cannot be intercepted by the test mock spawner. In CI or test environments this could spawn real processes and make network calls unexpectedly.

Additional Locations (1)
Fix in Cursor Fix in Web

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

Labels

size:XXL 1,000+ changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant