diff --git a/src/components/thread/messages/ai.tsx b/src/components/thread/messages/ai.tsx index e269a63..91fa365 100644 --- a/src/components/thread/messages/ai.tsx +++ b/src/components/thread/messages/ai.tsx @@ -6,7 +6,7 @@ import { Avatar, AvatarFallback } from "@/components/ui/avatar"; import { MarkdownText } from "../markdown-text"; import { LoadExternalComponent } from "@langchain/langgraph-sdk/react-ui/client"; import { cn } from "@/lib/utils"; -import { ToolCalls } from "./tool-calls"; +import { ToolCalls, ToolResult } from "./tool-calls"; function CustomComponent({ message, @@ -61,40 +61,45 @@ export function AssistantMessage({ "tool_calls" in message && message.tool_calls && message.tool_calls.length > 0; + const isToolResult = message.type === "tool"; return (
A -
- {hasToolCalls && } - - {contentString.length > 0 && ( -
- {contentString} -
- )} -
+ ) : ( +
+ {hasToolCalls && } + + {contentString.length > 0 && ( +
+ {contentString} +
)} - > - thread.setBranch(branch)} - isLoading={isLoading} - /> - handleRegenerate(parentCheckpoint)} - /> +
+ thread.setBranch(branch)} + isLoading={isLoading} + /> + handleRegenerate(parentCheckpoint)} + /> +
-
+ )}
); } diff --git a/src/components/thread/messages/tool-calls.tsx b/src/components/thread/messages/tool-calls.tsx index 741b297..ebf39f6 100644 --- a/src/components/thread/messages/tool-calls.tsx +++ b/src/components/thread/messages/tool-calls.tsx @@ -1,4 +1,7 @@ -import { AIMessage } from "@langchain/langgraph-sdk"; +import { AIMessage, ToolMessage } from "@langchain/langgraph-sdk"; +import { useState } from "react"; +import { motion, AnimatePresence } from "framer-motion"; +import { ChevronDown, ChevronUp } from "lucide-react"; function isComplexValue(value: any): boolean { return Array.isArray(value) || (typeof value === "object" && value !== null); @@ -23,7 +26,14 @@ export function ToolCalls({ className="border border-gray-200 rounded-lg overflow-hidden" >
-

{tc.name}

+

+ {tc.name} + {tc.id && ( + + {tc.id} + + )} +

@@ -51,3 +61,61 @@ export function ToolCalls({ ); } + +export function ToolResult({ message }: { message: ToolMessage }) { + const [isExpanded, setIsExpanded] = useState(false); + const contentStr = JSON.stringify(message.content, null, 2); + const contentLines = contentStr.split('\n'); + const shouldTruncate = contentLines.length > 4 || contentStr.length > 500; + const displayedContent = shouldTruncate && !isExpanded + ? (contentStr.length > 500 + ? contentStr.slice(0, 500) + '...' + : contentLines.slice(0, 4).join('\n') + '\n...') + : contentStr; + + return ( +
+
+
+ {message.name ?

Tool Result: {message.name}

:

Tool Result

} + {message.tool_call_id && ( + + {message.tool_call_id} + + )} +
+
+ +
+ + + {displayedContent} + + +
+ {shouldTruncate && ( + setIsExpanded(!isExpanded)} + className="w-full py-2 flex items-center justify-center border-t-[1px] border-gray-200 text-gray-500 hover:text-gray-600 hover:bg-gray-50 transition-all ease-in-out duration-200 cursor-pointer" + initial={{ scale: 1 }} + whileHover={{ scale: 1.02 }} + whileTap={{ scale: 0.98 }} + > + {isExpanded ? : } + + )} +
+
+ ); +}