"use client"; import type { ToolCallMessagePartProps } from "@assistant-ui/react"; import { BrainIcon, CheckIcon, Loader2Icon, SearchIcon, XIcon } from "lucide-react"; import { z } from "zod"; // ============================================================================ // Zod Schemas for save_memory tool // ============================================================================ const SaveMemoryArgsSchema = z.object({ content: z.string(), category: z.string().default("fact"), }); const SaveMemoryResultSchema = z.object({ status: z.enum(["saved", "error"]), memory_id: z.number().nullish(), memory_text: z.string().nullish(), category: z.string().nullish(), message: z.string().nullish(), error: z.string().nullish(), }); type SaveMemoryArgs = z.infer; type SaveMemoryResult = z.infer; // ============================================================================ // Zod Schemas for recall_memory tool // ============================================================================ const RecallMemoryArgsSchema = z.object({ query: z.string().nullish(), category: z.string().nullish(), top_k: z.number().default(5), }); const MemoryItemSchema = z.object({ id: z.number(), memory_text: z.string(), category: z.string(), updated_at: z.string().nullish(), }); const RecallMemoryResultSchema = z.object({ status: z.enum(["success", "error"]), count: z.number().nullish(), memories: z.array(MemoryItemSchema).nullish(), formatted_context: z.string().nullish(), error: z.string().nullish(), }); type RecallMemoryArgs = z.infer; type RecallMemoryResult = z.infer; type MemoryItem = z.infer; // ============================================================================ // Category badge colors // ============================================================================ const categoryColors: Record = { preference: "bg-blue-500/10 text-blue-600 dark:text-blue-400", fact: "bg-green-500/10 text-green-600 dark:text-green-400", instruction: "bg-purple-500/10 text-purple-600 dark:text-purple-400", context: "bg-orange-500/10 text-orange-600 dark:text-orange-400", }; function CategoryBadge({ category }: { category: string }) { const colorClass = categoryColors[category] || "bg-gray-500/10 text-gray-600 dark:text-gray-400"; return ( {category} ); } // ============================================================================ // Save Memory Tool UI // ============================================================================ export const SaveMemoryToolUI = ({ args, result, status }: ToolCallMessagePartProps) => { const isRunning = status.type === "running" || status.type === "requires-action"; const isComplete = status.type === "complete"; const isError = result?.status === "error"; // Parse args safely const parsedArgs = SaveMemoryArgsSchema.safeParse(args); const content = parsedArgs.success ? parsedArgs.data.content : ""; const category = parsedArgs.success ? parsedArgs.data.category : "fact"; // Loading state if (isRunning) { return (
Saving to memory...
); } // Error state if (isError) { return (
Failed to save memory {result?.error &&

{result.error}

}
); } // Success state if (isComplete && result?.status === "saved") { return (
Memory saved

{content}

); } // Default/incomplete state - show what's being saved if (content) { return (
Saving memory

{content}

); } return null; }; // ============================================================================ // Recall Memory Tool UI // ============================================================================ export const RecallMemoryToolUI = ({ args, result, status }: ToolCallMessagePartProps) => { const isRunning = status.type === "running" || status.type === "requires-action"; const isComplete = status.type === "complete"; const isError = result?.status === "error"; // Parse args safely const parsedArgs = RecallMemoryArgsSchema.safeParse(args); const query = parsedArgs.success ? parsedArgs.data.query : null; // Loading state if (isRunning) { return (
{query ? `Searching memories for "${query}"...` : "Recalling memories..."}
); } // Error state if (isError) { return (
Failed to recall memories {result?.error &&

{result.error}

}
); } // Success state with memories if (isComplete && result?.status === "success") { const memories = result.memories || []; const count = result.count || 0; if (count === 0) { return (
No memories found
); } return (
Recalled {count} {count === 1 ? "memory" : "memories"}
{memories.slice(0, 5).map((memory: MemoryItem) => (
{memory.memory_text}
))} {memories.length > 5 && (

...and {memories.length - 5} more

)}
); } // Default/incomplete state if (query) { return (
Searching memories for "{query}"
); } return null; }; // ============================================================================ // Exports // ============================================================================ export { SaveMemoryArgsSchema, SaveMemoryResultSchema, RecallMemoryArgsSchema, RecallMemoryResultSchema, type SaveMemoryArgs, type SaveMemoryResult, type RecallMemoryArgs, type RecallMemoryResult, type MemoryItem, };