perf(desktop): stop the model-picker overlay re-rendering per streaming token

ModelPickerOverlay subscribed to $focusedSessionState whole — a
projection of $sessionStates, republished on every message delta — to
read two fields that essentially never change (model, provider). The
overlay is mounted app-wide and unconditionally renders the un-memoized
ModelPickerDialog (closed), so the focused session's stream re-ran the
dialog's full hook body ~30x/s.

Same defect class and same fix as the statusbar (#72163): select each
scalar through useStoreSelector so unchanged values bail out.
This commit is contained in:
Brooklyn Nicholson 2026-07-26 21:03:27 -05:00
parent c74f48b62e
commit 6107624727

View file

@ -3,6 +3,7 @@ import { useStore } from '@nanostores/react'
import type { ModelSelection } from '@/app/shell/model-menu-panel'
import { ModelPickerDialog } from '@/components/model-picker'
import type { HermesGateway } from '@/hermes'
import { useStoreSelector } from '@/lib/use-session-slice'
import {
$activeSessionId,
$currentModel,
@ -24,15 +25,22 @@ export function ModelPickerOverlay({ gateway, onSelect, profile }: ModelPickerOv
const primaryModel = useStore($currentModel)
const primaryProvider = useStore($currentProvider)
const focusedRuntimeId = useStore($focusedRuntimeId)
const focusedState = useStore($focusedSessionState)
// `$focusedSessionState` is a projection of `$sessionStates`, republished on
// EVERY message delta — and this overlay is mounted app-wide. Only two
// fields are read off it, so subscribing to the whole object re-rendered
// this component (and the un-memoized closed dialog below) per token while
// the focused session streamed. Select each scalar so an unchanged
// model/provider bails out instead — same fix as the statusbar (#72163).
const focusedModel = useStoreSelector($focusedSessionState, state => state?.model ?? null)
const focusedProvider = useStoreSelector($focusedSessionState, state => state?.provider ?? null)
const gatewayOpen = useStore($gatewayState) === 'open'
const open = useStore($modelPickerOpen)
// Prefer the focused tile's runtime when the overlay opens from a tile that
// lacked a live menu (gateway closed → fallback path).
const sessionId = focusedRuntimeId ?? primarySessionId
const currentModel = focusedRuntimeId && focusedState ? focusedState.model : primaryModel
const currentProvider = focusedRuntimeId && focusedState ? focusedState.provider : primaryProvider
const currentModel = focusedRuntimeId && focusedModel !== null ? focusedModel : primaryModel
const currentProvider = focusedRuntimeId && focusedProvider !== null ? focusedProvider : primaryProvider
if (!gatewayOpen) {
return null