feat: integrate tool call icons with status indicators and daisy chaining (#4279)
Co-authored-by: dianed-square <73617011+dianed-square@users.noreply.github.com> Co-authored-by: Zane <75694352+zanesq@users.noreply.github.com> Co-authored-by: Taylor Ho <taylorkmho@gmail.com>
This commit is contained in:
@@ -1,12 +1,14 @@
|
||||
import { ToolIconWithStatus, ToolCallStatus } from './ToolCallStatusIndicator';
|
||||
import { getToolCallIcon } from '../utils/toolIconMapping';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { Button } from './ui/button';
|
||||
import { ToolCallArguments, ToolCallArgumentValue } from './ToolCallArguments';
|
||||
import MarkdownContent from './MarkdownContent';
|
||||
import { Content, ToolRequestMessageContent, ToolResponseMessageContent } from '../types/message';
|
||||
import { cn, snakeToTitleCase } from '../utils';
|
||||
import Dot, { LoadingStatus } from './ui/Dot';
|
||||
import { LoadingStatus } from './ui/Dot';
|
||||
import { NotificationEvent } from '../hooks/useMessageStream';
|
||||
import { ChevronRight, FlaskConical, LoaderCircle } from 'lucide-react';
|
||||
import { ChevronRight, FlaskConical } from 'lucide-react';
|
||||
import { TooltipWrapper } from './settings/providers/subcomponents/buttons/TooltipWrapper';
|
||||
import MCPUIResourceRenderer from './MCPUIResourceRenderer';
|
||||
import { isUIResource } from '@mcp-ui/client';
|
||||
@@ -173,16 +175,13 @@ function ToolCallView({
|
||||
}: ToolCallViewProps) {
|
||||
const [responseStyle, setResponseStyle] = useState(() => localStorage.getItem('response_style'));
|
||||
|
||||
// Listen for localStorage changes to update the response style
|
||||
useEffect(() => {
|
||||
const handleStorageChange = () => {
|
||||
setResponseStyle(localStorage.getItem('response_style'));
|
||||
};
|
||||
|
||||
// Listen for storage events (changes from other tabs/windows)
|
||||
window.addEventListener('storage', handleStorageChange);
|
||||
|
||||
// Listen for custom events (changes from same tab)
|
||||
window.addEventListener('responseStyleChanged', handleStorageChange);
|
||||
|
||||
return () => {
|
||||
@@ -283,12 +282,10 @@ function ToolCallView({
|
||||
const args = toolCall.arguments as Record<string, ToolCallArgumentValue>;
|
||||
const toolName = toolCall.name.substring(toolCall.name.lastIndexOf('__') + 2);
|
||||
|
||||
// Helper function to get string value safely
|
||||
const getStringValue = (value: ToolCallArgumentValue): string => {
|
||||
return typeof value === 'string' ? value : JSON.stringify(value);
|
||||
};
|
||||
|
||||
// Helper function to truncate long values
|
||||
const truncate = (str: string, maxLength: number = 50): string => {
|
||||
return str.length > maxLength ? str.substring(0, maxLength) + '...' : str;
|
||||
};
|
||||
@@ -442,34 +439,45 @@ function ToolCallView({
|
||||
// Fallback tool name formatting
|
||||
return snakeToTitleCase(toolCall.name.substring(toolCall.name.lastIndexOf('__') + 2));
|
||||
};
|
||||
// Map LoadingStatus to ToolCallStatus
|
||||
const getToolCallStatus = (loadingStatus: LoadingStatus): ToolCallStatus => {
|
||||
switch (loadingStatus) {
|
||||
case 'success':
|
||||
return 'success';
|
||||
case 'error':
|
||||
return 'error';
|
||||
case 'loading':
|
||||
return 'loading';
|
||||
default:
|
||||
return 'pending';
|
||||
}
|
||||
};
|
||||
|
||||
const toolCallStatus = getToolCallStatus(loadingStatus);
|
||||
|
||||
const toolLabel = (
|
||||
<span className={cn('ml-2', extensionTooltip && 'cursor-pointer hover:opacity-80')}>
|
||||
{getToolLabelContent()}
|
||||
<span
|
||||
className={cn(
|
||||
'flex items-center gap-2',
|
||||
extensionTooltip && 'cursor-pointer hover:opacity-80'
|
||||
)}
|
||||
>
|
||||
<ToolIconWithStatus ToolIcon={getToolCallIcon(toolCall.name)} status={toolCallStatus} />
|
||||
<span>{getToolLabelContent()}</span>
|
||||
</span>
|
||||
);
|
||||
|
||||
return (
|
||||
<ToolCallExpandable
|
||||
isStartExpanded={isRenderingProgress}
|
||||
isForceExpand={isShouldExpand}
|
||||
label={
|
||||
<>
|
||||
<div className="w-2 flex items-center justify-center">
|
||||
{loadingStatus === 'loading' ? (
|
||||
<LoaderCircle className="animate-spin text-text-muted" size={3} />
|
||||
) : (
|
||||
<Dot size={2} loadingStatus={loadingStatus} />
|
||||
)}
|
||||
</div>
|
||||
{extensionTooltip ? (
|
||||
<TooltipWrapper tooltipContent={extensionTooltip} side="top" align="start">
|
||||
{toolLabel}
|
||||
</TooltipWrapper>
|
||||
) : (
|
||||
toolLabel
|
||||
)}
|
||||
</>
|
||||
extensionTooltip ? (
|
||||
<TooltipWrapper tooltipContent={extensionTooltip} side="top" align="start">
|
||||
{toolLabel}
|
||||
</TooltipWrapper>
|
||||
) : (
|
||||
toolLabel
|
||||
)
|
||||
}
|
||||
>
|
||||
{/* Tool Details */}
|
||||
|
||||
Reference in New Issue
Block a user