Precompute message display parts and pause scroll handling
This commit is contained in:
@@ -168,16 +168,20 @@ export default function MessageStream(props: MessageStreamProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handleScroll() {
|
function handleScroll() {
|
||||||
if (!containerRef) return
|
// Scroll handling temporarily disabled during testing
|
||||||
|
// if (!containerRef) return
|
||||||
const { scrollTop, scrollHeight, clientHeight } = containerRef
|
//
|
||||||
const isAtBottom = scrollHeight - scrollTop - clientHeight < 50
|
// const { scrollTop, scrollHeight, clientHeight } = containerRef
|
||||||
|
// const isAtBottom = scrollHeight - scrollTop - clientHeight < 50
|
||||||
setAutoScroll(isAtBottom)
|
//
|
||||||
setShowScrollButton(!isAtBottom)
|
// setAutoScroll(isAtBottom)
|
||||||
|
// setShowScrollButton(!isAtBottom)
|
||||||
}
|
}
|
||||||
|
|
||||||
const displayItems = createMemo(() => {
|
const displayItems = createMemo(() => {
|
||||||
|
// Ensure memo reacts to preference changes
|
||||||
|
preferences().showThinkingBlocks
|
||||||
|
|
||||||
const items: DisplayItem[] = []
|
const items: DisplayItem[] = []
|
||||||
|
|
||||||
let lastAssistantIndex = -1
|
let lastAssistantIndex = -1
|
||||||
@@ -197,9 +201,11 @@ export default function MessageStream(props: MessageStreamProps) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
const textParts = message.parts.filter((p) => p.type === "text" && !p.synthetic)
|
// Use precomputed displayParts, fallback to empty arrays if not available
|
||||||
const toolParts = message.parts.filter((p) => p.type === "tool")
|
const displayParts = message.displayParts || { text: [], tool: [], reasoning: [] }
|
||||||
const reasoningParts = preferences().showThinkingBlocks ? message.parts.filter((p) => p.type === "reasoning") : []
|
const textParts = displayParts.text
|
||||||
|
const toolParts = displayParts.tool
|
||||||
|
const reasoningParts = displayParts.reasoning
|
||||||
|
|
||||||
const isQueued = message.type === "user" && (lastAssistantIndex === -1 || index > lastAssistantIndex)
|
const isQueued = message.type === "user" && (lastAssistantIndex === -1 || index > lastAssistantIndex)
|
||||||
|
|
||||||
@@ -229,10 +235,11 @@ export default function MessageStream(props: MessageStreamProps) {
|
|||||||
|
|
||||||
const itemsLength = () => displayItems().length
|
const itemsLength = () => displayItems().length
|
||||||
createEffect(() => {
|
createEffect(() => {
|
||||||
|
// Scroll handling temporarily disabled during testing
|
||||||
itemsLength()
|
itemsLength()
|
||||||
if (autoScroll()) {
|
// if (autoScroll()) {
|
||||||
setTimeout(scrollToBottom, 0)
|
// setTimeout(scrollToBottom, 0)
|
||||||
}
|
// }
|
||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { createSignal } from "solid-js"
|
import { createSignal } from "solid-js"
|
||||||
import type { Session, Agent, Provider } from "../types/session"
|
import type { Session, Agent, Provider } from "../types/session"
|
||||||
import type { Message } from "../types/message"
|
import type { Message, MessageDisplayParts } from "../types/message"
|
||||||
import { instances } from "./instances"
|
import { instances } from "./instances"
|
||||||
import { sseManager } from "../lib/sse-manager"
|
import { sseManager } from "../lib/sse-manager"
|
||||||
|
import { preferences } from "./preferences"
|
||||||
|
|
||||||
interface SessionInfo {
|
interface SessionInfo {
|
||||||
tokens: number
|
tokens: number
|
||||||
@@ -81,6 +82,24 @@ function removeSessionIndexes(instanceId: string) {
|
|||||||
sessionIndexes.delete(instanceId)
|
sessionIndexes.delete(instanceId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function computeDisplayParts(message: Message, showThinking: boolean): MessageDisplayParts {
|
||||||
|
const text: any[] = []
|
||||||
|
const tool: any[] = []
|
||||||
|
const reasoning: any[] = []
|
||||||
|
|
||||||
|
for (const part of message.parts) {
|
||||||
|
if (part.type === "text" && !part.synthetic) {
|
||||||
|
text.push(part)
|
||||||
|
} else if (part.type === "tool") {
|
||||||
|
tool.push(part)
|
||||||
|
} else if (part.type === "reasoning" && showThinking) {
|
||||||
|
reasoning.push(part)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { text, tool, reasoning }
|
||||||
|
}
|
||||||
|
|
||||||
function withSession(instanceId: string, sessionId: string, updater: (session: Session) => void) {
|
function withSession(instanceId: string, sessionId: string, updater: (session: Session) => void) {
|
||||||
const instanceSessions = sessions().get(instanceId)
|
const instanceSessions = sessions().get(instanceId)
|
||||||
if (!instanceSessions) return
|
if (!instanceSessions) return
|
||||||
@@ -684,7 +703,7 @@ async function loadMessages(instanceId: string, sessionId: string, force = false
|
|||||||
|
|
||||||
messagesInfo.set(messageId, info)
|
messagesInfo.set(messageId, info)
|
||||||
|
|
||||||
return {
|
const message: Message = {
|
||||||
id: messageId,
|
id: messageId,
|
||||||
sessionId,
|
sessionId,
|
||||||
type: role === "user" ? "user" : "assistant",
|
type: role === "user" ? "user" : "assistant",
|
||||||
@@ -692,6 +711,10 @@ async function loadMessages(instanceId: string, sessionId: string, force = false
|
|||||||
timestamp: info.time?.created || Date.now(),
|
timestamp: info.time?.created || Date.now(),
|
||||||
status: "complete" as const,
|
status: "complete" as const,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message.displayParts = computeDisplayParts(message, preferences().showThinkingBlocks)
|
||||||
|
|
||||||
|
return message
|
||||||
})
|
})
|
||||||
|
|
||||||
let agentName = ""
|
let agentName = ""
|
||||||
@@ -794,7 +817,7 @@ function handleMessageUpdate(instanceId: string, event: any): void {
|
|||||||
|
|
||||||
if (messageIndex === undefined) {
|
if (messageIndex === undefined) {
|
||||||
// Create new message
|
// Create new message
|
||||||
const newMessage = {
|
const newMessage: Message = {
|
||||||
id: part.messageID,
|
id: part.messageID,
|
||||||
sessionId: part.sessionID,
|
sessionId: part.sessionID,
|
||||||
type: "assistant" as const,
|
type: "assistant" as const,
|
||||||
@@ -803,6 +826,8 @@ function handleMessageUpdate(instanceId: string, event: any): void {
|
|||||||
status: "streaming" as const,
|
status: "streaming" as const,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
newMessage.displayParts = computeDisplayParts(newMessage, preferences().showThinkingBlocks)
|
||||||
|
|
||||||
let insertIndex = session.messages.length
|
let insertIndex = session.messages.length
|
||||||
for (let i = session.messages.length - 1; i >= 0; i--) {
|
for (let i = session.messages.length - 1; i >= 0; i--) {
|
||||||
if (session.messages[i].id < newMessage.id) {
|
if (session.messages[i].id < newMessage.id) {
|
||||||
@@ -854,6 +879,8 @@ function handleMessageUpdate(instanceId: string, event: any): void {
|
|||||||
message.status = message.status === "sending" ? "streaming" : message.status
|
message.status = message.status === "sending" ? "streaming" : message.status
|
||||||
message.parts = baseParts
|
message.parts = baseParts
|
||||||
|
|
||||||
|
message.displayParts = computeDisplayParts(message, preferences().showThinkingBlocks)
|
||||||
|
|
||||||
// Update message index if ID changed
|
// Update message index if ID changed
|
||||||
if (oldId !== message.id) {
|
if (oldId !== message.id) {
|
||||||
index.messageIndex.delete(oldId)
|
index.messageIndex.delete(oldId)
|
||||||
@@ -937,7 +964,7 @@ function handleMessageUpdate(instanceId: string, event: any): void {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Append new message
|
// Append new message
|
||||||
const newMessage = {
|
const newMessage: Message = {
|
||||||
id: info.id,
|
id: info.id,
|
||||||
sessionId: info.sessionID,
|
sessionId: info.sessionID,
|
||||||
type: (info.role === "user" ? "user" : "assistant") as "user" | "assistant",
|
type: (info.role === "user" ? "user" : "assistant") as "user" | "assistant",
|
||||||
@@ -946,6 +973,8 @@ function handleMessageUpdate(instanceId: string, event: any): void {
|
|||||||
status: "complete" as const,
|
status: "complete" as const,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
newMessage.displayParts = computeDisplayParts(newMessage, preferences().showThinkingBlocks)
|
||||||
|
|
||||||
let insertIndex = session.messages.length
|
let insertIndex = session.messages.length
|
||||||
for (let i = session.messages.length - 1; i >= 0; i--) {
|
for (let i = session.messages.length - 1; i >= 0; i--) {
|
||||||
if (session.messages[i].id < newMessage.id) {
|
if (session.messages[i].id < newMessage.id) {
|
||||||
@@ -1083,6 +1112,8 @@ async function sendMessage(
|
|||||||
status: "sending",
|
status: "sending",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
optimisticMessage.displayParts = computeDisplayParts(optimisticMessage, preferences().showThinkingBlocks)
|
||||||
|
|
||||||
withSession(instanceId, sessionId, (session) => {
|
withSession(instanceId, sessionId, (session) => {
|
||||||
session.messages.push(optimisticMessage)
|
session.messages.push(optimisticMessage)
|
||||||
const index = getSessionIndex(instanceId, sessionId)
|
const index = getSessionIndex(instanceId, sessionId)
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
export interface MessageDisplayParts {
|
||||||
|
text: any[]
|
||||||
|
tool: any[]
|
||||||
|
reasoning: any[]
|
||||||
|
}
|
||||||
|
|
||||||
export interface Message {
|
export interface Message {
|
||||||
id: string
|
id: string
|
||||||
sessionId: string
|
sessionId: string
|
||||||
@@ -5,4 +11,5 @@ export interface Message {
|
|||||||
parts: any[]
|
parts: any[]
|
||||||
timestamp: number
|
timestamp: number
|
||||||
status: "sending" | "sent" | "streaming" | "complete" | "error"
|
status: "sending" | "sent" | "streaming" | "complete" | "error"
|
||||||
|
displayParts?: MessageDisplayParts
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user