"use client" import * as React from "react" import { useChat } from "@ai-sdk/react" import type { UIMessage } from "ai" import { createChat, getMessageText } from "@/lib/ai" import { PartReasoning } from "@/registry/bases/radix/blocks/preview-03/components/part-reasoning" import { PartText } from "@/registry/bases/radix/blocks/preview-03/components/part-text" import { PartTool } from "@/registry/bases/radix/blocks/preview-03/components/part-tool" import { PromptInput } from "@/registry/bases/radix/blocks/preview-03/components/prompt-input" import { Example } from "@/registry/bases/radix/components/example" import { Button } from "@/registry/bases/radix/ui/button" import { Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, } from "@/registry/bases/radix/ui/card" import { Marker, MarkerContent, MarkerIcon, } from "@/registry/bases/radix/ui/marker" import { Message, MessageContent } from "@/registry/bases/radix/ui/message" import { MessageScroller, MessageScrollerButton, MessageScrollerContent, MessageScrollerItem, MessageScrollerProvider, MessageScrollerViewport, } from "@/registry/bases/radix/ui/message-scroller" import { Spinner } from "@/registry/bases/radix/ui/spinner" import { IconPlaceholder } from "@/app/(app)/create/components/icon-placeholder" type Tools = { getDeploymentHealth: { input: { project: string region: string } output: { status: "healthy" | "degraded" | "down" p95: number errors: number recommendation: string } } } type ChatMessage = UIMessage, Tools> const chat = createChat() .user("Check the deployment health for the checkout flow.") .sleep(1000) .assistant(({ writer }) => { writer.reasoning( "The user needs current operational state, so I should call a deployment-health tool before making a recommendation." ) const health = writer.tool("getDeploymentHealth", { title: "Checking deployment health", input: { project: "checkout", region: "iad1", }, }) health.sleep(1200).output({ status: "healthy", p95: 186, errors: 2, recommendation: "No rollback needed. Watch error rate for 15 minutes.", }) writer.text( "The checkout deployment looks healthy. P95 latency is **186ms** with **2 recent errors**, so I would keep the release live and watch it for another 15 minutes." ) }) const initialMessages = chat.get(0) const transport = chat.transport() function isToolPart(part: { type: string }): part is React.ComponentProps["part"] { return part.type === "dynamic-tool" || part.type.startsWith("tool-") } export function ToolChat() { const { status, messages, sendMessage, setMessages } = useChat({ messages: initialMessages, transport, }) const nextMessage = chat.next(messages) const isBusy = status === "submitted" || status === "streaming" const onSubmit = (input: string) => { if (!input.trim()) { return } if (nextMessage && input === getMessageText(nextMessage)) { void sendMessage(nextMessage) return } void sendMessage({ text: input }) } return ( Deployment check Reasoning followed by a tool call and result. {messages.map((message) => ( {message.parts.map((part, index) => ( {part.type === "text" ? ( ) : part.type === "reasoning" ? ( ) : isToolPart(part) ? ( ) : null} ))} ))} {status === "submitted" ? ( Thinking... ) : null} ) }