From 2b2df22b9c7bac7b133d582f94aed67974bd3da6 Mon Sep 17 00:00:00 2001 From: Michael Neale Date: Thu, 8 May 2025 13:59:08 +1000 Subject: [PATCH] fix: will now correctly follow along with tool results (#2473) --- .../src/components/ToolCallArguments.tsx | 2 +- .../src/components/ToolCallWithResponse.tsx | 37 ++++++++++++++++++- ui/desktop/src/components/ui/scroll-area.tsx | 9 ++--- 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/ui/desktop/src/components/ToolCallArguments.tsx b/ui/desktop/src/components/ToolCallArguments.tsx index 8335ac82..581f1580 100644 --- a/ui/desktop/src/components/ToolCallArguments.tsx +++ b/ui/desktop/src/components/ToolCallArguments.tsx @@ -2,7 +2,7 @@ import React, { useState } from 'react'; import MarkdownContent from './MarkdownContent'; import Expand from './ui/Expand'; -type ToolCallArgumentValue = +export type ToolCallArgumentValue = | string | number | boolean diff --git a/ui/desktop/src/components/ToolCallWithResponse.tsx b/ui/desktop/src/components/ToolCallWithResponse.tsx index 9e6d2287..721a39de 100644 --- a/ui/desktop/src/components/ToolCallWithResponse.tsx +++ b/ui/desktop/src/components/ToolCallWithResponse.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { Card } from './ui/card'; -import { ToolCallArguments } from './ToolCallArguments'; +import { ToolCallArguments, ToolCallArgumentValue } from './ToolCallArguments'; import MarkdownContent from './MarkdownContent'; import { Content, ToolRequestMessageContent, ToolResponseMessageContent } from '../types/message'; import { snakeToTitleCase } from '../utils'; @@ -105,6 +105,35 @@ function ToolCallView({ isCancelledMessage, toolCall, toolResponse }: ToolCallVi const isShouldExpand = isExpandToolDetails || toolResults.some((v) => v.isExpandToolResults); + // Function to create a compact representation of arguments + const getCompactArguments = () => { + const args = toolCall.arguments as Record; + const entries = Object.entries(args); + + if (entries.length === 0) return null; + + // For a single parameter, show key and truncated value + if (entries.length === 1) { + const [key, value] = entries[0]; + const stringValue = typeof value === 'string' ? value : JSON.stringify(value); + const truncatedValue = + stringValue.length > 30 ? stringValue.substring(0, 30) + '...' : stringValue; + + return ( + + {key}: {truncatedValue} + + ); + } + + // For multiple parameters, just show the keys + return ( + + {entries.map(([key]) => key).join(', ')} + + ); + }; + return ( {snakeToTitleCase(toolCall.name.substring(toolCall.name.lastIndexOf('__') + 2))} + {/* Display compact arguments inline */} + {isToolDetails && getCompactArguments()} } > @@ -163,7 +194,9 @@ function ToolDetailsView({ toolCall, isStartExpanded }: ToolDetailsViewProps) { className="pl-[19px] py-1" isStartExpanded={isStartExpanded} > - {toolCall.arguments && } + {toolCall.arguments && ( + } /> + )} ); } diff --git a/ui/desktop/src/components/ui/scroll-area.tsx b/ui/desktop/src/components/ui/scroll-area.tsx index 79836a2e..f488d95b 100644 --- a/ui/desktop/src/components/ui/scroll-area.tsx +++ b/ui/desktop/src/components/ui/scroll-area.tsx @@ -32,6 +32,7 @@ const ScrollArea = React.forwardRef( block: 'end', inline: 'nearest', }); + // When explicitly scrolling to bottom, reset the following state setIsFollowing(true); } }, []); @@ -66,13 +67,11 @@ const ScrollArea = React.forwardRef( const { scrollHeight, scrollTop, clientHeight } = viewport; const scrollBottom = scrollTop + clientHeight; - const newIsFollowing = scrollHeight === scrollBottom; + // Allow a small tolerance (2px) for rounding errors + const isAtBottom = scrollHeight - scrollBottom <= 2; - // Check if scrolled from top + setIsFollowing(isAtBottom); setIsScrolled(scrollTop > 0); - - // react will internally optimize this to not re-store the same values - setIsFollowing(newIsFollowing); }, []); React.useEffect(() => {