perf(ui): isolate sidebar session selection

This commit is contained in:
c_w_xiaohei
2026-08-26 00:42:36 +08:00
parent 77da97953f
commit ed37d8e249
8 changed files with 351 additions and 159 deletions
+91
View File
@@ -0,0 +1,91 @@
import type { PermissionRuleset, Session, SnapshotFileDiff } from "@opencode-ai/sdk/v2"
import { Binary } from "./binary"
function areMetadataEqual(left: Session["metadata"], right: Session["metadata"]): boolean {
return JSON.stringify(left ?? null) === JSON.stringify(right ?? null)
}
function optionalEqual<T>(
left: T | undefined,
right: T | undefined,
equal: (left: T, right: T) => boolean,
): boolean {
return left === right || (left !== undefined && right !== undefined && equal(left, right))
}
const diffsEqual = (left: SnapshotFileDiff[], right: SnapshotFileDiff[]) => (
left.length === right.length
&& left.every((item, index) => {
const candidate = right[index]
return item.file === candidate.file
&& item.patch === candidate.patch
&& item.additions === candidate.additions
&& item.deletions === candidate.deletions
&& item.status === candidate.status
})
)
const permissionsEqual = (left: PermissionRuleset, right: PermissionRuleset) => (
left.length === right.length
&& left.every((item, index) => {
const candidate = right[index]
return item.permission === candidate.permission
&& item.pattern === candidate.pattern
&& item.action === candidate.action
})
)
function areSessionsEqual(left: Session, right: Session): boolean {
return left.id === right.id
&& left.slug === right.slug
&& left.projectID === right.projectID
&& left.workspaceID === right.workspaceID
&& left.directory === right.directory
&& left.path === right.path
&& left.parentID === right.parentID
&& left.cost === right.cost
&& left.title === right.title
&& left.agent === right.agent
&& left.version === right.version
&& areMetadataEqual(left.metadata, right.metadata)
&& optionalEqual(left.summary, right.summary, (a, b) => (
a.additions === b.additions
&& a.deletions === b.deletions
&& a.files === b.files
&& optionalEqual(a.diffs, b.diffs, diffsEqual)
))
&& optionalEqual(left.tokens, right.tokens, (a, b) => (
a.input === b.input
&& a.output === b.output
&& a.reasoning === b.reasoning
&& a.cache.read === b.cache.read
&& a.cache.write === b.cache.write
))
&& optionalEqual(left.share, right.share, (a, b) => a.url === b.url)
&& optionalEqual(left.model, right.model, (a, b) => (
a.id === b.id
&& a.providerID === b.providerID
&& a.variant === b.variant
))
&& left.time.created === right.time.created
&& left.time.updated === right.time.updated
&& left.time.compacting === right.time.compacting
&& left.time.archived === right.time.archived
&& optionalEqual(left.permission, right.permission, permissionsEqual)
&& optionalEqual(left.revert, right.revert, (a, b) => (
a.messageID === b.messageID
&& a.partID === b.partID
&& a.snapshot === b.snapshot
&& a.diff === b.diff
))
}
export function upsertSessionRecord(current: Session[], incoming: Session): Session[] {
const result = Binary.search(current, incoming.id, (session) => session.id)
if (!result.found) return [...current.slice(0, result.index), incoming, ...current.slice(result.index)]
// Equivalent authoritative detail must retain sidebar session-list references.
if (areSessionsEqual(current[result.index], incoming)) return current
const next = [...current]
next[result.index] = incoming
return next
}