fix(ui): eliminate N+1 reactive subscriptions in SessionTurn (#18924)
parent
3f1a4abe6d
commit
c9c93eac00
|
|
@ -923,7 +923,15 @@ export function MessageTimeline(props: {
|
||||||
{(messageID) => {
|
{(messageID) => {
|
||||||
const active = createMemo(() => activeMessageID() === messageID)
|
const active = createMemo(() => activeMessageID() === messageID)
|
||||||
const comments = createMemo(() => messageComments(sync.data.part[messageID] ?? []), [], {
|
const comments = createMemo(() => messageComments(sync.data.part[messageID] ?? []), [], {
|
||||||
equals: (a, b) => JSON.stringify(a) === JSON.stringify(b),
|
equals: (a, b) =>
|
||||||
|
a.length === b.length &&
|
||||||
|
a.every(
|
||||||
|
(c, i) =>
|
||||||
|
c.path === b[i].path &&
|
||||||
|
c.comment === b[i].comment &&
|
||||||
|
c.selection?.startLine === b[i].selection?.startLine &&
|
||||||
|
c.selection?.endLine === b[i].selection?.endLine,
|
||||||
|
),
|
||||||
})
|
})
|
||||||
const commentCount = createMemo(() => comments().length)
|
const commentCount = createMemo(() => comments().length)
|
||||||
return (
|
return (
|
||||||
|
|
@ -979,6 +987,7 @@ export function MessageTimeline(props: {
|
||||||
<SessionTurn
|
<SessionTurn
|
||||||
sessionID={sessionID() ?? ""}
|
sessionID={sessionID() ?? ""}
|
||||||
messageID={messageID}
|
messageID={messageID}
|
||||||
|
messages={sessionMessages()}
|
||||||
actions={props.actions}
|
actions={props.actions}
|
||||||
active={active()}
|
active={active()}
|
||||||
status={active() ? sessionStatus() : undefined}
|
status={active() ? sessionStatus() : undefined}
|
||||||
|
|
|
||||||
|
|
@ -142,6 +142,7 @@ export function SessionTurn(
|
||||||
props: ParentProps<{
|
props: ParentProps<{
|
||||||
sessionID: string
|
sessionID: string
|
||||||
messageID: string
|
messageID: string
|
||||||
|
messages?: MessageType[]
|
||||||
actions?: UserActions
|
actions?: UserActions
|
||||||
showReasoningSummaries?: boolean
|
showReasoningSummaries?: boolean
|
||||||
shellToolDefaultOpen?: boolean
|
shellToolDefaultOpen?: boolean
|
||||||
|
|
@ -166,7 +167,7 @@ export function SessionTurn(
|
||||||
const emptyDiffs: FileDiff[] = []
|
const emptyDiffs: FileDiff[] = []
|
||||||
const idle = { type: "idle" as const }
|
const idle = { type: "idle" as const }
|
||||||
|
|
||||||
const allMessages = createMemo(() => list(data.store.message?.[props.sessionID], emptyMessages))
|
const allMessages = createMemo(() => props.messages ?? list(data.store.message?.[props.sessionID], emptyMessages))
|
||||||
|
|
||||||
const messageIndex = createMemo(() => {
|
const messageIndex = createMemo(() => {
|
||||||
const messages = allMessages() ?? emptyMessages
|
const messages = allMessages() ?? emptyMessages
|
||||||
|
|
@ -340,30 +341,28 @@ export function SessionTurn(
|
||||||
if (end < start) return undefined
|
if (end < start) return undefined
|
||||||
return end - start
|
return end - start
|
||||||
})
|
})
|
||||||
const assistantVisible = createMemo(() =>
|
const assistantDerived = createMemo(() => {
|
||||||
assistantMessages().reduce((count, message) => {
|
let visible = 0
|
||||||
const parts = list(data.store.part?.[message.id], emptyParts)
|
let tail: "text" | "other" | undefined
|
||||||
return count + parts.filter((part) => partState(part, showReasoningSummaries()) === "visible").length
|
let reason: string | undefined
|
||||||
}, 0),
|
const show = showReasoningSummaries()
|
||||||
)
|
for (const message of assistantMessages()) {
|
||||||
const assistantTailVisible = createMemo(() =>
|
for (const part of list(data.store.part?.[message.id], emptyParts)) {
|
||||||
assistantMessages()
|
if (partState(part, show) === "visible") {
|
||||||
.flatMap((message) => list(data.store.part?.[message.id], emptyParts))
|
visible++
|
||||||
.flatMap((part) => {
|
tail = part.type === "text" ? "text" : "other"
|
||||||
if (partState(part, showReasoningSummaries()) !== "visible") return []
|
}
|
||||||
if (part.type === "text") return ["text" as const]
|
if (part.type === "reasoning" && part.text) {
|
||||||
return ["other" as const]
|
const h = heading(part.text)
|
||||||
})
|
if (h) reason = h
|
||||||
.at(-1),
|
}
|
||||||
)
|
}
|
||||||
const reasoningHeading = createMemo(() =>
|
}
|
||||||
assistantMessages()
|
return { visible, tail, reason }
|
||||||
.flatMap((message) => list(data.store.part?.[message.id], emptyParts))
|
})
|
||||||
.filter((part): part is PartType & { type: "reasoning"; text: string } => part.type === "reasoning")
|
const assistantVisible = createMemo(() => assistantDerived().visible)
|
||||||
.map((part) => heading(part.text))
|
const assistantTailVisible = createMemo(() => assistantDerived().tail)
|
||||||
.filter((text): text is string => !!text)
|
const reasoningHeading = createMemo(() => assistantDerived().reason)
|
||||||
.at(-1),
|
|
||||||
)
|
|
||||||
const showThinking = createMemo(() => {
|
const showThinking = createMemo(() => {
|
||||||
if (!working() || !!error()) return false
|
if (!working() || !!error()) return false
|
||||||
if (status().type === "retry") return false
|
if (status().type === "retry") return false
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue