fix(web): copy an update command that matches how the server is installed - #9489
fix(web): copy an update command that matches how the server is installed#9489ylcn91 wants to merge 3 commits into
Conversation
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want higher recall? High effort reviews run extra passes and find more bugs. A team admin can switch effort levels in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 33ca5dd. Configure here.
ApprovabilityVerdict: Approved at Macroscope's review found this PR approvable — This is a focused fix to an existing version-mismatch action: it reports the server’s install type and copies the matching package-manager command while preserving older-server fallbacks and self-update paths. The additive descriptor is forward-compatible and the detection, wiring, and command selection are covered by targeted tests. You can add or adjust custom eligibility rules. Learn more. |

What Changed
packages/contracts/src/environment.ts: a new optional capability,serverInstall, says how the server's CLI is installed: run out of a package runner's cache (npx,pnpm-dlx,bunx) or installed globally by a package manager (npm-global,pnpm-global,bun-global). It is declared withForwardCompatibleOptional, likeplatform.machine, so a kind an older client does not know decodes as absent instead of failing the descriptor.apps/server/src/cli/invocation.ts:detectServerInstallbuilds on the existingdetectCliRunnerentry-path check and recognises global installs by each package manager's own layout: npm's<prefix>/lib/node_modules/(system node, nvm, fnm, volta, Homebrew) or%APPDATA%/npm/node_modules/on Windows, pnpm's/pnpm/global/, bun's/.bun/install/global/. Repo checkouts, project-local installs, and the pinned service runtime returnnull, since no global command would update the executable that gets restarted.apps/server/src/environment/ServerEnvironment.ts: the descriptor carriesserverInstallonly whenserverSelfUpdateis absent, since that is the only server whose clients hand out a command. The entry path is resolved first because a global install's bin is a symlink into the package.apps/web/src/versionSkew.ts:manualServerUpdateCommandpicks the command from it:npm i -g/pnpm add -g/bun add -g t3@<version>for a global install,npx/pnpm dlx/bunx t3@<version>for a package runner, and the unchangednpx t3@<version>when the server does not say (older servers, dev checkouts).ServerUpdateActiontakes the install as a prop; its three call sites (chat banner, Connections row, Connections primary card) pass it.docs/user/updating.md: the Copy update command description now matches.Tests:
detectServerInstallper layout, the descriptor advertisingserverInstallonly for a server that cannot update itself (through a real bin symlink), and the command per install kind.Why
Fixes #9370.
Copy update command always produced
npx t3@<version>. For a server started withnpxthat relaunches it at the right version, but for a server installed withnpm i -git runs a throwaway copy out of the npx cache and never touches the installed CLI. The nextt3 start, systemd unit, or shell alias comes back on the old version and the banner reappears, even though the user did exactly what the toast asked.The server already knows how it was launched (
detectCliRunnerpowers thenpx t3 servesuggestions), so this reports that over the existing capabilities channel and lets the client format the command that will actually land. Nothing changes for servers that self-update, and older servers keep the current behaviour because the field is optional.Model and harness: Claude Fable 5.1 in Claude Code.
Note
Show update command matching server install type instead of npx fallback
ServerInstallKindand an optionalserverInstallcapability to environment.ts so the server can report whether it runs via npx, pnpm dlx, bunx, or npm/pnpm/bun global.serverInstallonly for manually-updateable installs.serverInstall, so the web client falls back to the npx command — this is intentional but may not match the actual install.Macroscope summarized 290522b.