fix(web): offer Update client when the app is behind the server - #5254
fix(web): offer Update client when the app is behind the server#5254matheustimbo wants to merge 7 commits into
Conversation
Detect which side of a client/server version mismatch is outdated so the banner offers Update client via the desktop updater instead of downgrading a newer server. Co-authored-by: Cursor <cursoragent@cursor.com>
|
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:
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 feature that offers client updates when the app is behind the server version. The new ClientUpdateAction component (300+ lines) includes non-trivial async update checking, polling logic, and desktop bridge integration. Changes to the version mismatch workflow warrant human review. You can customize Macroscope's approvability policy. Learn more. |
Address Bugbot findings on ClientUpdateAction: continue after check via subscribed update state instead of the async check return value, and show guidance when desktop auto-updates are disabled. Co-authored-by: Cursor <cursoragent@cursor.com>
Arm the Update client follow-up on checkedAt advancing so a pre-check idle/up-to-date snapshot cannot clear the pending download path. Co-authored-by: Cursor <cursoragent@cursor.com>
Babysit note
Once CI is approved/run, happy to chase any remaining failures. |
Move check-then-download into a module-scoped async flow that polls settled desktop update state, so dismissing the banner cannot drop the continuation. Co-authored-by: Cursor <cursoragent@cursor.com>
Avoid clearing local pending state when a second click hits the in-flight guard; wait for the module-scoped check to finish instead. Co-authored-by: Cursor <cursoragent@cursor.com>
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 db5f85b. Configure here.
Replace localCheckPending/useEffect with useSyncExternalStore over the module in-flight flag so remounts cannot leave the button stuck disabled. Co-authored-by: Cursor <cursoragent@cursor.com>
When checkForUpdate returns checked:false because a concurrent check is already running, wait for that check to settle (or act on the busy state) instead of showing a misleading failure toast.



What Changed
outdatedSidefromresolveVersionMismatchcheckForUpdate→downloadUpdate→installUpdate)docs/user/updating.mdfor the client-behind caseWhy
The version-drift UI treated the client as canonical and always offered a server update targeting the client version. When a newer server connected to an older macOS/desktop client, that CTA was inverted and could downgrade the server. Direction-aware skew fixes the CTA and routes client-behind cases through the existing Electron updater.
UI Changes
Before
Client behind server, but the banner still offers Update server:
After
Same mismatch offers Update client, which drives the desktop updater:
Checklist
Test plan
vp test run apps/web/src/versionSkew.test.tsNote
Medium Risk
Changes version-mismatch CTAs and desktop update orchestration; fixes a prior path that could push server updates toward the client version when the client was actually behind.
Overview
Version mismatch handling now compares client and server with semver and records which side is behind (
outdatedSide), instead of always treating the client version as the update target.When the client is older, the chat banner and Connections show Update client and
clientUpdateGuidance()text. On Electron, the newClientUpdateActionruns the desktop updater (check → download → install) with in-flight state kept outside React so dismiss/navigation does not cancel checks. Non-desktop clients get guidance only—no server update button.When the server is older, behavior stays on Update server / copy-command paths. Server update progress and failure UI are hidden when the client is the outdated side. Reconnect banners no longer fold into “server restarting” messaging when skew is client-behind.
User docs in
docs/user/updating.mddescribe client-behind vs server-behind actions.Reviewed by Cursor Bugbot for commit caff1ce. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Show client update controls in chat banner and settings when client is behind the server
ClientUpdateActioncomponent (ClientUpdateAction.tsx) that on Electron can check, download, and install updates with progress feedback via toasts; on non-Electron it renders static guidance text.versionSkew.tswithresolveVersionOutdatedSideand anoutdatedSidefield onVersionMismatch, so the UI can distinguish whether the client or server needs updating.ClientUpdateActionwhen the client is behind, suppressing server update controls and progress in that case.Macroscope summarized caff1ce.