"use client"; import { useAui, AuiProvider, Suggestions } from "@assistant-ui/react"; import { useA2ATask, useA2AArtifacts, useA2AAgentCard, type A2ATaskState, type A2APart, } from "@assistant-ui/react-a2a"; import { Thread } from "@/components/assistant-ui/thread"; const STATE_CONFIG: Record< string, { label: string; color: string; bg: string } > = { submitted: { label: "Submitted", color: "text-blue-600", bg: "bg-blue-100 dark:bg-blue-900/30", }, working: { label: "Working", color: "text-amber-600", bg: "bg-amber-100 dark:bg-amber-900/30", }, completed: { label: "Completed", color: "text-green-600", bg: "bg-green-100 dark:bg-green-900/30", }, failed: { label: "Failed", color: "text-red-600", bg: "bg-red-100 dark:bg-red-900/30", }, canceled: { label: "Canceled", color: "text-gray-600", bg: "bg-gray-100 dark:bg-gray-900/30", }, rejected: { label: "Rejected", color: "text-red-600", bg: "bg-red-100 dark:bg-red-900/30", }, input_required: { label: "Input Required", color: "text-purple-600", bg: "bg-purple-100 dark:bg-purple-900/30", }, auth_required: { label: "Auth Required", color: "text-orange-600", bg: "bg-orange-100 dark:bg-orange-900/30", }, }; function StateBadge({ state }: { state: A2ATaskState }) { const config = STATE_CONFIG[state] ?? { label: state, color: "text-gray-600", bg: "bg-gray-100", }; const isActive = state === "working" || state === "submitted"; return ( {isActive ? ( ) : ( )} {config.label} ); } function TaskStatusBar() { const task = useA2ATask(); if (!task) return null; const { state } = task.status; const isError = state === "failed" || state === "rejected"; const errorText = isError ? task.status.message?.parts?.[0]?.text : undefined; return (
Task {task.id.slice(0, 8)} {errorText && ( {errorText} )}
); } function ArtifactPartView({ part }: { part: A2APart }) { if (part.text !== undefined) { return (
        {part.text}
      
); } if (part.data !== undefined) { return (
Data
          {JSON.stringify(part.data, null, 2)}
        
); } if (part.url !== undefined) { const isImage = part.mediaType?.startsWith("image/"); if (isImage) { return ( {part.filename ); } return ( ๐Ÿ“„ {part.filename ?? "Download"} {part.mediaType && ( {part.mediaType} )} ); } if (part.raw !== undefined) { const isImage = part.mediaType?.startsWith("image/"); if (isImage) { return ( {part.filename ); } const dataUri = `data:${part.mediaType ?? "application/octet-stream"};base64,${part.raw}`; return ( ๐Ÿ“Ž {part.filename ?? "File"} {part.mediaType && ( {part.mediaType} )} ); } return null; } function ArtifactPanel() { const artifacts = useA2AArtifacts(); if (artifacts.length === 0) return null; return (

Artifacts ({artifacts.length})

{artifacts.map((artifact) => (
{artifact.name ?? artifact.artifactId} {artifact.description && ( {artifact.description} )}
{artifact.parts.map((part, i) => ( ))}
))}
); } function AgentCardBanner() { const card = useA2AAgentCard(); if (!card) return null; return (
{card.name}
{card.description}
{card.skills.map((skill) => ( {skill.name} ))}
v{card.version} {card.capabilities.streaming && " ยท Streaming"}
); } function ThreadWithSuggestions() { const aui = useAui({ suggestions: Suggestions([ { title: "Chat", label: "say hello", prompt: "Hello! What can you do?", }, { title: "Generate artifacts", label: "code + data + file", prompt: "/artifacts a fibonacci function in Python", }, { title: "Multi-step", label: "input-required flow", prompt: "/multistep", }, { title: "Failure demo", label: "test error handling", prompt: "/fail", }, { title: "Slow task", label: "test cancellation", prompt: "/slow", }, ]), }); return ( ); } export default function Home() { return (
); }