import { For, JSXElement, Match, Show, Switch, createEffect, createMemo, createSignal, onCleanup } from "solid-js" import { Markdown, Part } from "@opencode-ai/ui" import { useSync } from "@/context/sync" import type { AssistantMessage as AssistantMessageType, Part as PartType, ToolPart } from "@opencode-ai/sdk" import { Spinner } from "./spinner" export function MessageProgress(props: { assistantMessages: () => AssistantMessageType[]; done?: boolean }) { const sync = useSync() const parts = createMemo(() => props.assistantMessages().flatMap((m) => sync.data.part[m.id])) const done = createMemo(() => props.done ?? false) const currentTask = createMemo( () => parts().findLast( (p) => p && p.type === "tool" && p.tool === "task" && p.state && "metadata" in p.state && p.state.metadata && p.state.metadata.sessionId && p.state.status === "running", ) as ToolPart, ) const resolvedParts = createMemo(() => { let resolved = parts() const task = currentTask() if (task && task.state && "metadata" in task.state && task.state.metadata?.sessionId) { const messages = sync.data.message[task.state.metadata.sessionId as string]?.filter((m) => m.role === "assistant") resolved = messages?.flatMap((m) => sync.data.part[m.id]) ?? parts() } return resolved }) const currentText = createMemo( () => resolvedParts().findLast((p) => p?.type === "text")?.text || resolvedParts().findLast((p) => p?.type === "reasoning")?.text, ) const eligibleItems = createMemo(() => { return resolvedParts().filter((p) => p?.type === "tool" && p.state.status === "completed") }) const finishedItems = createMemo<(JSXElement | PartType)[]>(() => [
,
,
Thinking...
, ...eligibleItems(), ...(done() ? [
,
,
] : []), ]) const delay = createMemo(() => (done() ? 220 : 400)) const [visibleCount, setVisibleCount] = createSignal(eligibleItems().length) createEffect(() => { const total = finishedItems().length if (total > visibleCount()) { const timer = setTimeout(() => { setVisibleCount((prev) => prev + 1) }, delay()) onCleanup(() => clearTimeout(timer)) } else if (total < visibleCount()) { setVisibleCount(total) } }) const translateY = createMemo(() => { const total = visibleCount() if (total < 2) return "0px" return `-${(total - 2) * 40 - 8}px` }) return (
{(part) => { if (part && typeof part === "object" && "type" in part) { const message = createMemo(() => sync.data.message[part.sessionID].find((m) => m.id === part.messageID)) return (
{(p) => (
)} {(p) => } {(p) => }
) } return
{part}
}}
{(text) => (
)}
) }