Adam 3 месяцев назад
Родитель
Сommit
34f11c699e

+ 1 - 1
packages/desktop/src/components/message-progress.tsx

@@ -37,7 +37,7 @@ export function MessageProgress(props: { assistantMessages: () => AssistantMessa
   //     resolvedParts().findLast((p) => p?.type === "reasoning")?.text,
   // )
   const eligibleItems = createMemo(() => {
-    return resolvedParts().filter((p) => p?.type === "tool" && p.state.status === "completed") as ToolPart[]
+    return resolvedParts().filter((p) => p?.type === "tool" && p?.state.status === "completed") as ToolPart[]
   })
   const finishedItems = createMemo<(JSXElement | ToolPart)[]>(() => [
     <div class="h-8 w-full" />,

+ 28 - 10
packages/desktop/src/pages/index.tsx

@@ -13,6 +13,7 @@ import {
   ProgressCircle,
   Message,
   Typewriter,
+  Card,
 } from "@opencode-ai/ui"
 import { FileIcon } from "@/ui"
 import FileTree from "@/components/file-tree"
@@ -547,7 +548,13 @@ export default function Page() {
                               <For each={local.session.userMessages()}>
                                 {(message) => {
                                   const diffs = createMemo(() => message.summary?.diffs ?? [])
-                                  const working = createMemo(() => !message.summary?.body)
+                                  const assistantMessages = createMemo(() => {
+                                    return sync.data.message[activeSession().id]?.filter(
+                                      (m) => m.role === "assistant" && m.parentID == message.id,
+                                    ) as AssistantMessageType[]
+                                  })
+                                  const error = createMemo(() => assistantMessages().find((m) => m?.error)?.error)
+                                  const working = createMemo(() => !message.summary?.body && !error())
 
                                   return (
                                     <li class="group/li flex items-center self-stretch">
@@ -586,23 +593,24 @@ export default function Page() {
                               {(message) => {
                                 const isActive = createMemo(() => local.session.activeMessage()?.id === message.id)
                                 const [titled, setTitled] = createSignal(!!message.summary?.title)
-                                const [completed, setCompleted] = createSignal(!!message.summary?.body)
-                                const [expanded, setExpanded] = createSignal(false)
-                                const parts = createMemo(() => sync.data.part[message.id])
-                                const title = createMemo(() => message.summary?.title)
-                                const summary = createMemo(() => message.summary?.body)
-                                const diffs = createMemo(() => message.summary?.diffs ?? [])
                                 const assistantMessages = createMemo(() => {
                                   return sync.data.message[activeSession().id]?.filter(
                                     (m) => m.role === "assistant" && m.parentID == message.id,
                                   ) as AssistantMessageType[]
                                 })
+                                const error = createMemo(() => assistantMessages().find((m) => m?.error)?.error)
+                                const [completed, setCompleted] = createSignal(!!message.summary?.body || !!error())
+                                const [expanded, setExpanded] = createSignal(false)
+                                const parts = createMemo(() => sync.data.part[message.id])
+                                const title = createMemo(() => message.summary?.title)
+                                const summary = createMemo(() => message.summary?.body)
+                                const diffs = createMemo(() => message.summary?.diffs ?? [])
                                 const hasToolPart = createMemo(() =>
                                   assistantMessages()
                                     ?.flatMap((m) => sync.data.part[m.id])
                                     .some((p) => p?.type === "tool"),
                                 )
-                                const working = createMemo(() => !summary())
+                                const working = createMemo(() => !summary() && !error())
 
                                 // allowing time for the animations to finish
                                 createEffect(() => {
@@ -610,8 +618,8 @@ export default function Page() {
                                   setTimeout(() => setTitled(!!title()), 10_000)
                                 })
                                 createEffect(() => {
-                                  summary()
-                                  setTimeout(() => setCompleted(!!summary()), 1200)
+                                  const complete = !!summary() || !!error()
+                                  setTimeout(() => setCompleted(complete), 1200)
                                 })
 
                                 return (
@@ -707,6 +715,11 @@ export default function Page() {
                                           </Accordion>
                                         </div>
                                       </Show>
+                                      <Show when={error() && !expanded()}>
+                                        <Card variant="error" class="text-text-on-critical-base">
+                                          {error()?.data?.message as string}
+                                        </Card>
+                                      </Show>
                                       {/* Response */}
                                       <div class="w-full">
                                         <Switch>
@@ -736,6 +749,11 @@ export default function Page() {
                                                       return <Message message={assistantMessage} parts={parts()} />
                                                     }}
                                                   </For>
+                                                  <Show when={error()}>
+                                                    <Card variant="error" class="text-text-on-critical-base">
+                                                      {error()?.data?.message as string}
+                                                    </Card>
+                                                  </Show>
                                                 </div>
                                               </Collapsible.Content>
                                             </Collapsible>