From 20a0bfc9a60a98a63c8b7ba1dc565af1b596bbe9 Mon Sep 17 00:00:00 2001 From: Brooklyn Nicholson Date: Wed, 29 Jul 2026 00:24:50 -0500 Subject: [PATCH] feat(desktop): show the running version on the Update Hermes row The command palette named the action but not the install it acts on. Carry the version and its commit diff on the row, resolved from the shared resolver so it reads identically to the statusbar. --- .../desktop/src/app/command-palette/index.tsx | 48 +++++++++++++++++-- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/apps/desktop/src/app/command-palette/index.tsx b/apps/desktop/src/app/command-palette/index.tsx index 0014e4e71f1..59f8ba0cbae 100644 --- a/apps/desktop/src/app/command-palette/index.tsx +++ b/apps/desktop/src/app/command-palette/index.tsx @@ -49,6 +49,7 @@ import { } from '@/lib/icons' import { normalize } from '@/lib/text' import { cn } from '@/lib/utils' +import { resolveVersionStatus } from '@/lib/version-status' import { $repoWorktrees } from '@/store/coding-status' import { $commandPaletteOpen, @@ -59,8 +60,16 @@ import { import { $bindings } from '@/store/keybinds' import { openPetGenerate } from '@/store/pet-generate' import { requestStartWorkSession } from '@/store/projects' +import { $connection } from '@/store/session' import { runGatewayRestart } from '@/store/system-actions' -import { applyBackendUpdate } from '@/store/updates' +import { + $backendUpdateApply, + $backendUpdateStatus, + $desktopVersion, + $updateApply, + $updateStatus, + requestActiveUpdate +} from '@/store/updates' import { canOpenNewWindow, openNewWindow } from '@/store/windows' import { luminance } from '@/themes/color' import { type ThemeMode, useTheme } from '@/themes/context' @@ -93,6 +102,8 @@ interface PaletteItem { action?: string /** Renders a trailing check: this row IS the current setting (theme, mode). */ active?: boolean + /** Muted text beside the label — state the row acts on (a version, a count). */ + detail?: string icon: IconComponent id: string /** Keep the palette open after running (live-preview pickers like theme/mode). */ @@ -242,6 +253,7 @@ const PaletteRow = memo(function PaletteRow({ > {item.label} + {item.detail && {item.detail}} {combo && } {item.to && } {item.active && } @@ -345,6 +357,35 @@ export function CommandPalette() { const [search, setSearch] = useState('') const [page, setPage] = useState(null) + // The Update row names the same install the statusbar names — same target + // selection, same resolver. Reduced to the label string: an in-flight apply + // rewrites these stores on every progress line, and only a changed string + // should rebuild the palette's groups. + const connection = useStore($connection) + const desktopVersion = useStore($desktopVersion) + const clientStatus = useStore($updateStatus) + const clientApply = useStore($updateApply) + const backendStatus = useStore($backendUpdateStatus) + const backendApply = useStore($backendUpdateApply) + + const updateVersionLabel = useMemo(() => { + const backend = connection?.mode === 'remote' + const apply = backend ? backendApply : clientApply + const status = backend ? backendStatus : clientStatus + + return resolveVersionStatus({ + applying: apply.applying || apply.stage === 'restart', + behind: status?.behind ?? 0, + copy: t.shell.statusbar, + remote: backend, + restarting: apply.stage === 'restart', + sha: status?.currentSha?.slice(0, 7) ?? null, + target: backend ? 'backend' : 'client', + updateAvailable: status?.updateAvailable, + version: backend ? status?.currentVersion : desktopVersion?.appVersion + }).label + }, [backendApply, backendStatus, clientApply, clientStatus, connection?.mode, desktopVersion?.appVersion, t]) + // cmdk's onSelect doesn't forward the triggering event — keep the last // click/keydown modifiers so session rows can honour ⌘-Enter / ⌘-click. const lastSelectMods = useRef<{ ctrlKey: boolean; metaKey: boolean; shiftKey: boolean }>({ @@ -582,11 +623,12 @@ export function CommandPalette() { run: () => void runGatewayRestart() }, { + detail: updateVersionLabel, icon: Download, id: 'cc-update-hermes', keywords: ['update', 'upgrade', 'hermes', 'version', 'system', 'restart'], label: cc.updateHermes, - run: () => void applyBackendUpdate() + run: () => requestActiveUpdate() } ] }, @@ -663,7 +705,7 @@ export function CommandPalette() { ] : []) ] - }, [contributedItems, go, settingsSectionLabel, t, worktrees]) + }, [contributedItems, go, settingsSectionLabel, t, updateVersionLabel, worktrees]) // The long, granular lists (settings fields, API keys, MCP servers, archived // chats) only surface once the user types — otherwise they'd bury the