From 1b2e85cdad4e3f060b6802f70f9e42377539bb27 Mon Sep 17 00:00:00 2001 From: jules Date: Fri, 1 May 2026 20:25:36 +1000 Subject: [PATCH] Wire @crema/agent-ui: ToolCallCard + AgentAvatar with activity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The /ai surface now renders agent-ui primitives instead of homegrown tool/typing widgets: - AgentAvatar with activity (thinking / working / waiting / speaking / idle) replaces TypingIndicator. Pulses while the model is generating, shows "waiting" while a write is held for confirmation, "working" while a confirmed write is executing, "speaking" once tokens are streaming. - ToolCallCard renders each native tool_call with typed status (pending / running / success / error). Built from the assistant message's toolCalls plus the matching tool result message. Tool messages no longer render standalone — absorbed into their parent assistant turn. - Empty assistant bubbles (no prose, only tool_calls) collapse so the ToolCallCards carry the visual weight. Wiring: add @crema/agent-ui path entry to tsconfig and @source line to app.css. Sibling lib-agent-ui must be cloned next to arcadia-admin. Co-Authored-By: Claude Opus 4.7 (1M context) --- app/app.css | 1 + app/routes/ai.tsx | 141 +++++++++++++++++++++++++++++++++++++++------- tsconfig.json | 2 + 3 files changed, 123 insertions(+), 21 deletions(-) diff --git a/app/app.css b/app/app.css index 5a718f4..83d11e1 100644 --- a/app/app.css +++ b/app/app.css @@ -17,6 +17,7 @@ @source "../../lib-search-ui/src"; @source "../../lib-feedback-ui/src"; @source "../../lib-auth-ui/src"; +@source "../../lib-agent-ui/src"; /* CREMA:SOURCES */ @custom-variant dark (&:is(.dark *)); diff --git a/app/routes/ai.tsx b/app/routes/ai.tsx index 91865a6..95b4b2d 100644 --- a/app/routes/ai.tsx +++ b/app/routes/ai.tsx @@ -62,7 +62,13 @@ import { addLibraryItem } from "~/lib/library" import { Avatar, AvatarFallback } from "~/components/ui/avatar" import { pageTitle } from "~/lib/page-meta" import { useArcadiaClient } from "@crema/arcadia-client" -import type { ToolCall } from "@crema/llm-ui" +import type { Message as LLMMessage, ToolCall } from "@crema/llm-ui" +import { + AgentAvatar, + ToolCallCard, + type ToolCall as AgentToolCall, + type ToolCallStatus, +} from "@crema/agent-ui" import { buildDenialMessages, classifyCalls, @@ -523,30 +529,60 @@ function ChatSurface({ ) : (
- {messages - .filter((m) => m.role !== "system") - .map((m, i) => ( + {messages.map((m, i) => { + if (m.role === "system" || m.role === "tool") return null + const calls = + m.role === "assistant" && m.toolCalls + ? m.toolCalls.map((tc) => + buildAgentToolCall(tc, messages, isStreaming, !!pendingConfirm), + ) + : [] + const isWritePending = + pendingConfirm?.afterIndex === i ? pendingConfirm.writes : null + return (
- {pendingConfirm?.afterIndex === i && ( + {calls.length > 0 && ( +
+ {calls.map((c) => ( + + ))} +
+ )} + {isWritePending && ( )}
- ))} - {isStreaming && messages.at(-1)?.role !== "assistant" && ( -
- -
- )} + ) + })} + {(() => { + const activity = deriveAgentActivity({ + isStreaming, + lastMessage: messages.at(-1), + pendingConfirm: !!pendingConfirm, + confirmBusy, + }) + if (activity === "idle") return null + return ( +
+ +
+ ) + })()}