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.
This commit is contained in:
Brooklyn Nicholson 2026-07-29 00:24:50 -05:00
parent a121b4972c
commit 20a0bfc9a6

View file

@ -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({
>
<Icon className="size-3.5 shrink-0 text-muted-foreground" />
<span className="truncate">{item.label}</span>
{item.detail && <span className="truncate text-muted-foreground/80">{item.detail}</span>}
{combo && <KbdCombo className="ml-auto opacity-55" combo={combo} size="sm" />}
{item.to && <ChevronRight className={cn('size-3.5 shrink-0 text-muted-foreground/70', !combo && 'ml-auto')} />}
{item.active && <Check className={cn('size-3.5 shrink-0 text-primary', !combo && !item.to && 'ml-auto')} />}
@ -345,6 +357,35 @@ export function CommandPalette() {
const [search, setSearch] = useState('')
const [page, setPage] = useState<string | null>(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