perf(ui): reduce session list churn and message block invalidation

This commit is contained in:
Shantur Rathore
2026-01-12 16:37:09 +00:00
parent 72f420b6f6
commit 927e4e1281
5 changed files with 71 additions and 23 deletions

View File

@@ -875,7 +875,6 @@ const InstanceShell2: Component<InstanceShellProps> = (props) => {
<div class="session-sidebar flex flex-col flex-1 min-h-0">
<SessionList
instanceId={props.instance.id}
sessions={allInstanceSessions()}
threads={sessionThreads()}
activeSessionId={activeSessionIdForInstance()}
onSelect={handleSessionSelect}

View File

@@ -1,4 +1,4 @@
import { For, Match, Show, Switch, createEffect, createMemo, createSignal } from "solid-js"
import { For, Match, Show, Switch, createEffect, createMemo, createSignal, untrack } from "solid-js"
import { FoldVertical } from "lucide-solid"
import MessageItem from "./message-item"
import ToolCall from "./tool-call"
@@ -235,16 +235,11 @@ export default function MessageBlock(props: MessageBlockProps) {
const index = props.messageIndex
const lastAssistantIdx = props.lastAssistantIndex()
const isQueued = current.role === "user" && (lastAssistantIdx === -1 || index > lastAssistantIdx)
const info = messageInfo()
const infoTime = (info?.time ?? {}) as { created?: number; updated?: number; completed?: number }
const infoTimestamp =
typeof infoTime.completed === "number"
? infoTime.completed
: typeof infoTime.updated === "number"
? infoTime.updated
: infoTime.created ?? 0
const infoError = (info as { error?: { name?: string } } | undefined)?.error
const infoErrorName = typeof infoError?.name === "string" ? infoError.name : ""
// Intentionally untracked: messageInfoVersion updates should not trigger
// a full message block rebuild; record revision is the invalidation key.
const info = untrack(messageInfo)
const cacheSignature = [
current.id,
current.revision,
@@ -252,8 +247,6 @@ export default function MessageBlock(props: MessageBlockProps) {
props.showThinking() ? 1 : 0,
props.thinkingDefaultExpanded() ? 1 : 0,
props.showUsageMetrics() ? 1 : 0,
infoTimestamp,
infoErrorName,
].join("|")
const cachedBlock = sessionCache.messageBlocks.get(current.id)

View File

@@ -1,5 +1,5 @@
import { Component, For, Show, createSignal, createMemo, createEffect, JSX, onCleanup } from "solid-js"
import type { Session, SessionStatus } from "../types/session"
import type { SessionStatus } from "../types/session"
import type { SessionThread } from "../stores/session-state"
import { getSessionStatus } from "../stores/session-status"
import { Bot, User, Copy, Trash2, Pencil, ShieldAlert, ChevronDown } from "lucide-solid"
@@ -14,6 +14,7 @@ import {
isSessionParentExpanded,
loading,
renameSession,
sessions as sessionStateSessions,
setActiveSessionFromList,
toggleSessionParentExpanded,
} from "../stores/sessions"
@@ -25,7 +26,6 @@ const log = getLogger("session")
interface SessionListProps {
instanceId: string
sessions: Map<string, Session>
threads: SessionThread[]
activeSessionId: string | null
onSelect: (sessionId: string) => void
@@ -58,7 +58,7 @@ const SessionList: Component<SessionListProps> = (props) => {
const selectSession = (sessionId: string) => {
const session = props.sessions.get(sessionId)
const session = sessionStateSessions().get(props.instanceId)?.get(sessionId)
const parentId = session?.parentId ?? session?.id
if (parentId) {
ensureSessionParentExpanded(props.instanceId, parentId)
@@ -132,7 +132,7 @@ const SessionList: Component<SessionListProps> = (props) => {
}
const openRenameDialog = (sessionId: string) => {
const session = props.sessions.get(sessionId)
const session = sessionStateSessions().get(props.instanceId)?.get(sessionId)
if (!session) return
const label = session.title && session.title.trim() ? session.title : sessionId
setRenameTarget({ id: sessionId, title: session.title ?? "", label })
@@ -167,7 +167,7 @@ const SessionList: Component<SessionListProps> = (props) => {
expanded?: boolean
onToggleExpand?: () => void
}> = (rowProps) => {
const session = () => props.sessions.get(rowProps.sessionId)
const session = createMemo(() => sessionStateSessions().get(props.instanceId)?.get(rowProps.sessionId))
if (!session()) {
return <></>
}
@@ -293,7 +293,7 @@ const SessionList: Component<SessionListProps> = (props) => {
const activeId = props.activeSessionId
if (!activeId || activeId === "info") return null
const activeSession = props.sessions.get(activeId)
const activeSession = sessionStateSessions().get(props.instanceId)?.get(activeId)
if (!activeSession) return null
return activeSession.parentId ?? activeSession.id