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:
@@ -0,0 +1,60 @@
|
||||
import { Message, getToolRequests, getTextContent, getToolResponses } from '../types/message';
|
||||
|
||||
export function identifyConsecutiveToolCalls(messages: Message[]): number[][] {
|
||||
const chains: number[][] = [];
|
||||
let currentChain: number[] = [];
|
||||
|
||||
for (let i = 0; i < messages.length; i++) {
|
||||
const message = messages[i];
|
||||
const toolRequests = getToolRequests(message);
|
||||
const toolResponses = getToolResponses(message);
|
||||
const textContent = getTextContent(message);
|
||||
const hasText = textContent.trim().length > 0;
|
||||
|
||||
if (toolResponses.length > 0 && toolRequests.length === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (toolRequests.length > 0) {
|
||||
if (hasText) {
|
||||
if (currentChain.length > 0) {
|
||||
if (currentChain.length > 1) {
|
||||
chains.push([...currentChain]);
|
||||
}
|
||||
}
|
||||
currentChain = [i];
|
||||
} else {
|
||||
currentChain.push(i);
|
||||
}
|
||||
} else if (hasText) {
|
||||
if (currentChain.length > 1) {
|
||||
chains.push([...currentChain]);
|
||||
}
|
||||
currentChain = [];
|
||||
} else {
|
||||
if (currentChain.length > 1) {
|
||||
chains.push([...currentChain]);
|
||||
}
|
||||
currentChain = [];
|
||||
}
|
||||
}
|
||||
|
||||
if (currentChain.length > 1) {
|
||||
chains.push(currentChain);
|
||||
}
|
||||
|
||||
return chains;
|
||||
}
|
||||
|
||||
export function shouldHideMessage(messageIndex: number, chains: number[][]): boolean {
|
||||
for (const chain of chains) {
|
||||
if (chain.includes(messageIndex)) {
|
||||
return chain[0] !== messageIndex;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function getChainForMessage(messageIndex: number, chains: number[][]): number[] | null {
|
||||
return chains.find(chain => chain.includes(messageIndex)) || null;
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
Archive,
|
||||
Brain,
|
||||
Camera,
|
||||
Code2,
|
||||
Eye,
|
||||
FileEdit,
|
||||
FilePlus,
|
||||
FileText,
|
||||
Globe,
|
||||
Monitor,
|
||||
Numbers,
|
||||
Save,
|
||||
Search,
|
||||
Settings,
|
||||
Terminal,
|
||||
Tool,
|
||||
} from '../components/icons/toolcalls';
|
||||
|
||||
export type ToolIconProps = {
|
||||
className?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Maps tool names to their corresponding icon components
|
||||
* @param toolName - The name of the tool (extracted from toolCall.name)
|
||||
* @returns React component for the tool icon
|
||||
*/
|
||||
export const getToolIcon = (toolName: string): React.ComponentType<ToolIconProps> => {
|
||||
switch (toolName) {
|
||||
// Developer Extension Tools
|
||||
case 'text_editor':
|
||||
return FileEdit;
|
||||
case 'shell':
|
||||
return Terminal;
|
||||
|
||||
// Memory Extension Tools
|
||||
case 'remember_memory':
|
||||
return Save;
|
||||
case 'retrieve_memories':
|
||||
return Brain;
|
||||
|
||||
// Computer Controller Extension Tools
|
||||
case 'automation_script':
|
||||
return Settings;
|
||||
case 'computer_control':
|
||||
return Monitor;
|
||||
case 'web_scrape':
|
||||
return Globe;
|
||||
case 'screen_capture':
|
||||
return Camera;
|
||||
case 'pdf_tool':
|
||||
return FileText;
|
||||
case 'docx_tool':
|
||||
return FileText;
|
||||
case 'xlsx_tool':
|
||||
return Numbers;
|
||||
case 'cache':
|
||||
return Archive;
|
||||
|
||||
// File Operations
|
||||
case 'search':
|
||||
return Search;
|
||||
case 'read':
|
||||
return Eye;
|
||||
case 'create_file':
|
||||
return FilePlus;
|
||||
case 'update_file':
|
||||
return FileEdit;
|
||||
|
||||
// Google Workspace Tools (if still supported)
|
||||
case 'sheets_tool':
|
||||
return Numbers;
|
||||
case 'docs_tool':
|
||||
return FileText;
|
||||
|
||||
// Special Tools
|
||||
case 'final_output':
|
||||
return Tool; // Could be a checkmark icon if we had one
|
||||
|
||||
// Default fallback for unknown tools
|
||||
default:
|
||||
return Tool;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Maps extension names to their corresponding icon components
|
||||
* @param extensionName - The name of the extension
|
||||
* @returns React component for the extension icon
|
||||
*/
|
||||
export const getExtensionIcon = (extensionName: string): React.ComponentType<ToolIconProps> => {
|
||||
switch (extensionName) {
|
||||
case 'developer':
|
||||
return Code2;
|
||||
case 'memory':
|
||||
return Brain;
|
||||
case 'computercontroller':
|
||||
return Monitor;
|
||||
default:
|
||||
return Tool;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper function to extract tool name from full tool call name
|
||||
* @param toolCallName - Full tool call name (e.g., "developer__text_editor")
|
||||
* @returns Extracted tool name (e.g., "text_editor")
|
||||
*/
|
||||
export const extractToolName = (toolCallName: string): string => {
|
||||
return toolCallName.substring(toolCallName.lastIndexOf('__') + 2);
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper function to extract extension name from full tool call name
|
||||
* @param toolCallName - Full tool call name (e.g., "developer__text_editor")
|
||||
* @returns Extracted extension name (e.g., "developer")
|
||||
*/
|
||||
export const extractExtensionName = (toolCallName: string): string => {
|
||||
const lastIndex = toolCallName.lastIndexOf('__');
|
||||
return lastIndex === -1 ? '' : toolCallName.substring(0, lastIndex);
|
||||
};
|
||||
|
||||
/**
|
||||
* Main function to get the appropriate icon for a tool call
|
||||
* @param toolCallName - Full tool call name (e.g., "developer__text_editor")
|
||||
* @param useExtensionIcon - Whether to use extension icon instead of tool icon
|
||||
* @returns React component for the icon
|
||||
*/
|
||||
export const getToolCallIcon = (
|
||||
toolCallName: string,
|
||||
useExtensionIcon: boolean = false
|
||||
): React.ComponentType<ToolIconProps> => {
|
||||
if (useExtensionIcon) {
|
||||
const extensionName = extractExtensionName(toolCallName);
|
||||
return getExtensionIcon(extensionName);
|
||||
}
|
||||
|
||||
const toolName = extractToolName(toolCallName);
|
||||
return getToolIcon(toolName);
|
||||
};
|
||||
Reference in New Issue
Block a user