import { For, Show, createSignal, createEffect, createMemo } from "solid-js" import type { Message } from "../types/message" import MessageItem from "./message-item" import ToolCall from "./tool-call" import { sseManager } from "../lib/sse-manager" import Kbd from "./kbd" interface MessageStreamProps { instanceId: string sessionId: string messages: Message[] messagesInfo?: Map loading?: boolean } interface DisplayItem { type: "message" | "tool" data: any messageInfo?: any } export default function MessageStream(props: MessageStreamProps) { let containerRef: HTMLDivElement | undefined const [autoScroll, setAutoScroll] = createSignal(true) const [showScrollButton, setShowScrollButton] = createSignal(false) const connectionStatus = () => sseManager.getStatus(props.instanceId) function scrollToBottom() { if (containerRef) { containerRef.scrollTop = containerRef.scrollHeight setAutoScroll(true) setShowScrollButton(false) } } function handleScroll() { if (!containerRef) return const { scrollTop, scrollHeight, clientHeight } = containerRef const isAtBottom = scrollHeight - scrollTop - clientHeight < 50 setAutoScroll(isAtBottom) setShowScrollButton(!isAtBottom) } const displayItems = createMemo(() => { const items: DisplayItem[] = [] for (const message of props.messages) { const messageInfo = props.messagesInfo?.get(message.id) const textParts = message.parts.filter((p) => p.type === "text" && !p.synthetic) const toolParts = message.parts.filter((p) => p.type === "tool") const reasoningParts = message.parts.filter((p) => p.type === "reasoning") if (textParts.length > 0 || reasoningParts.length > 0 || messageInfo?.error) { items.push({ type: "message", data: { ...message, parts: [...textParts, ...reasoningParts], }, messageInfo, }) } for (const toolPart of toolParts) { items.push({ type: "tool", data: toolPart, messageInfo, }) } } return items }) const itemsLength = () => displayItems().length createEffect(() => { itemsLength() if (autoScroll()) { setTimeout(scrollToBottom, 0) } }) return (
Command Palette
Connected Connecting... Disconnected

Start a conversation

Type a message below or try:

  • /init-project
  • Ask about your codebase
  • Attach files with @

Loading messages...

{(item, index) => { const key = item.type === "message" ? `msg-${item.data.id}` : `tool-${item.data.id}` return (
🔧 Tool Call {item.data?.tool || "unknown"}
} >
) }}
) }