Target server settings by environment - #4559
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
ApprovabilityVerdict: Needs human review This PR introduces a new "client-only" desktop mode that fundamentally changes how the app can operate - allowing it to run without managing a local backend. The changes span startup behavior, settings scoping, IPC contracts, and environment handling. Given this is a significant new feature affecting core app behavior, human review is warranted. You can customize Macroscope's approvability policy. Learn more. |
# Conflicts: # apps/desktop/src/ipc/methods/backendMode.test.ts # apps/desktop/src/ipc/methods/backendMode.ts # apps/web/src/components/CommandPalette.tsx # apps/web/src/components/Sidebar.tsx # apps/web/src/components/SidebarV2.tsx # apps/web/src/components/settings/DiagnosticsSettings.tsx # apps/web/src/hooks/useSettings.ts # apps/web/src/routes/_chat.tsx # apps/web/src/state/environments.ts
bf1d0ee to
d17eb8a
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit beb4f20. Configure here.
Let the desktop app run as a pure client for remote or independently managed backends, instead of always owning a local backend process. - Add a persisted `managed` / `client-only` backend mode with a launch-only `--backend-mode` override, exposed over IPC. - In client-only mode, bootstrap skips the backend pool entirely and serves the renderer from packaged static assets (or the dev proxy), opening the window on renderer readiness rather than backend readiness, and skipping backend shutdown on quit. - `ElectronProtocol` takes an explicit `source: "proxy" | "static"`. Static serving adds path-safe file resolution, SPA fallback, MIME types, CSP and HEAD support. - Web routing treats client-only like hosted static, and local environment bootstraps are empty, so a client-only desktop is never stranded on a dead primary-backend state. Co-Authored-By: Claude <noreply@anthropic.com>
The sidebar decided a thread or project was remote by comparing its environment against the primary environment id. A client-only desktop (and the hosted static web app) never registers a primary, so that id is always null and every row read as local: no cloud/server icon, and no environment name on the project header. Make the comparison explicit about the two different meanings of a null primary id. `isRemoteEnvironmentId` now takes an `ownsLocalEnvironment` flag: when the app can never serve an environment from its own backend, every environment is remote; when it can, a null primary id still means "the local backend has not registered yet" and nothing is flagged remote. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The diagnostics environment picker made three pieces of panel-local state lie about which machine they belong to: - `openLogsDirectoryError` / `isOpeningLogsDirectory` kept showing an environment A failure (or spinner) after switching to environment B. They are now stored together with the environment they belong to, so they only render for that environment and a late completion can only update its own request. - `signalingPid` was a single shared value, so completing a signal on environment A re-enabled the signal controls for an in-flight signal on environment B and allowed a duplicate SIGKILL. Pending signals are now identified by environment id plus pid. - Diagnostics queries only run while the selected environment's supervisor is connected, so a disconnected machine showed permanent "Loading..." placeholders with the refresh buttons disabled. The panel now derives a connection notice and renders it instead of the loading state. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Follow-up to the review feedback on the previous commit: - `DiagnosticsRefreshButton` used a single `isPending` prop for both the spinner and `disabled`, so suppressing the spinner while the selected environment is disconnected also made the button clickable even though the query cannot run. It now takes an explicit `isDisabled` prop. - The open-logs completion matched on environment id alone, so returning to an environment and starting a second open while the first was still in flight let the older completion clear the newer pending state. The completion now matches the request by identity. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
0f957cc to
13a79c6
Compare

What Changed
Why
Client-only desktop mode deliberately has no
PrimaryConnectionTarget, but several settings surfaces still read and wrote exclusively through primary-server atoms and hooks. Those controls therefore displayed defaults and silently failed to persist.Settings now resolve an explicit selection first, then the managed primary environment, the active saved environment, and finally the first available environment. This preserves existing managed-client behavior while making client-only and multi-environment operation explicit.
UI Changes
This PR is stacked on
desktop-client-only-discovery, the branch behind #4444. It also carries the environment-scoped provider and diagnostics work needed by the complete settings flow.Checklist
vp test run apps/web/src/components/settings/SettingsPanels.logic.test.ts apps/web/src/components/settings/DiagnosticsSettings.logic.test.ts apps/web/src/hooks/useSettings.test.ts— 31 tests passedvp lint --report-unused-disable-directivesfor all changed filesvp run --filter @t3tools/web buildvp run --filter @t3tools/web typecheckremains blocked by pre-existing unrelated errors inBranchToolbarBranchSelector,ModelPickerContent,PreviewAutomationHosts, and the atom command/query helpersNote
High Risk
Touches desktop startup/shutdown, custom protocol static serving, and relaunch; web surfaces now depend on per-environment connection state instead of always-available primary server atoms.
Overview
Introduces a managed vs client-only desktop backend mode (
--backend-mode, persistedbackendMode, IPC + Connections UI). In client-only, startup skips the backend pool, registers the custom protocol as static (packaged renderer) or dev proxy, opens the window viahandleRendererReady, and omits local bootstraps; shutdown skips pool teardown. Managed mode keeps proxying to the backend but drops the separatebackendOriginon protocol registration.Electron protocol gains
source: "proxy" | "static"with path-normalized static serving (SPA fallback, HEAD, traversal guards). Relaunch schedules the replacement process earlier, surfacesDesktopLifecycleRelaunchError, andsetBackendModerolls back settings if relaunch fails.On the web side, server-backed settings (General, Providers, Keybindings, Source Control, Diagnostics) use a shared environment selector and
useSettingsEnvironment/ per-environment settings hooks instead of primary-only reads. Diagnostics is scoped to the selected environment with connection notices, disabled refresh when offline, and per-environment pending process signals. Chat, sidebar, and command palette stop usingprimaryServer*atoms for keybindings, providers, and config—useDefaultServerConfigand thread/project environment config drive defaults; remote thread labeling usesEnvironmentPresenceScope/ownsLocalEnvironmentrather than comparing only to the primary id.Reviewed by Cursor Bugbot for commit 13a79c6. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Scope settings panels and server config reads to target environment with desktop client-only mode support
client-onlydesktop backend mode that skips local backend startup, serves the renderer from either a dev proxy or packaged static assets, and hides local backend management UI.useDefaultServerConfiganduseDefaultEnvironmentIdhooks replace direct reads fromprimaryServer*atoms across sidebar, command palette, and chat components.buildSidebarProjectSnapshotsand remote-thread indicators now useisRemoteEnvironmentIdwith anEnvironmentPresenceScopeinstead of direct primary environment ID comparisons.DesktopLifecycle.relaunchnow propagates typedDesktopLifecycleRelaunchErrorfailures to callers;setBackendModerolls back settings when a triggered relaunch fails.Macroscope summarized 13a79c6.