diff --git a/web-app/src/containers/ThreadContent.tsx b/web-app/src/containers/ThreadContent.tsx index 4ca6e47e0..f7ae1bec4 100644 --- a/web-app/src/containers/ThreadContent.tsx +++ b/web-app/src/containers/ThreadContent.tsx @@ -9,9 +9,10 @@ import { IconPencil, } from '@tabler/icons-react' import { useAppState } from '@/hooks/useAppState' -import ThinkingBlock from './ThinkingBlock' import { cn } from '@/lib/utils' import { useMessages } from '@/hooks/useMessages' +import ThinkingBlock from '@/containers/ThinkingBlock' +import ToolCallBlock from '@/containers/ToolCallBlock' const CopyButton = ({ text }: { text: string }) => { const [copied, setCopied] = useState(false) @@ -81,6 +82,12 @@ export const ThreadContent = memo( const { deleteMessage } = useMessages() + const isToolCalls = + item.metadata && + 'tool_calls' in item.metadata && + Array.isArray(item.metadata.tool_calls) && + item.metadata.tool_calls.length + return ( {item.content?.[0]?.text && item.role === 'user' && ( @@ -124,41 +131,59 @@ export const ThreadContent = memo( text={reasoningSegment} /> )} + -
-
- - - + + + +
- + )} )} {item.type === 'image_url' && image && ( diff --git a/web-app/src/containers/ToolCallBlock.tsx b/web-app/src/containers/ToolCallBlock.tsx new file mode 100644 index 000000000..f9cb1f1db --- /dev/null +++ b/web-app/src/containers/ToolCallBlock.tsx @@ -0,0 +1,79 @@ +import { ChevronDown, ChevronUp, Loader } from 'lucide-react' +import { cn } from '@/lib/utils' +import { create } from 'zustand' +import { RenderMarkdown } from './RenderMarkdown' + +interface Props { + result: string + name: string + id: number + loading: boolean +} + +type ToolCallBlockState = { + collapseState: { [id: number]: boolean } + setCollapseState: (id: number, expanded: boolean) => void +} + +const useToolCallBlockStore = create((set) => ({ + collapseState: {}, + setCollapseState: (id, expanded) => + set((state) => ({ + collapseState: { + ...state.collapseState, + [id]: expanded, + }, + })), +})) + +const ToolCallBlock = ({ id, name, result, loading }: Props) => { + const { collapseState, setCollapseState } = useToolCallBlockStore() + const isExpanded = collapseState[id] ?? false + + const handleClick = () => { + const newExpandedState = !isExpanded + setCollapseState(id, newExpandedState) + } + + return ( +
+
+
+ {loading && ( + + )} + +
+ +
+
+ +
+
+
+
+ ) +} + +export default ToolCallBlock diff --git a/web-app/src/routes/threads/$threadId.tsx b/web-app/src/routes/threads/$threadId.tsx index b5708ec78..12fee157f 100644 --- a/web-app/src/routes/threads/$threadId.tsx +++ b/web-app/src/routes/threads/$threadId.tsx @@ -177,6 +177,7 @@ function ThreadDetail() { messages.map((item, index) => { // Only pass isLastMessage to the last message in the array const isLastMessage = index === messages.length - 1 + console.log(messages, 'messages') return (