/** * @license * Copyright 2025 Qwen Team * SPDX-License-Identifier: Apache-2.0 * * Search tool call component - specialized for search operations */ import type { FC } from 'react'; import { safeTitle, groupContent, mapToolStatusToContainerStatus, ToolCallContainer, } from './shared/index.js'; import type { BaseToolCallProps, ContainerStatus } from './shared/index.js'; import { FileLink } from '../layout/FileLink.js'; /** * Row component for search card layout */ const SearchRow: FC<{ label: string; children: React.ReactNode }> = ({ label, children, }) => (
{label}
{children}
); /** * Card content wrapper for search results */ const SearchCardContent: FC<{ children: React.ReactNode }> = ({ children }) => (
{children}
); /** * Local locations list component */ const LocationsListLocal: FC<{ locations: Array<{ path: string; line?: number | null }>; }> = ({ locations }) => (
{locations.map((loc, idx) => ( ))}
); /** * Map tool call kind to appropriate display name */ const getDisplayLabel = (kind: string): string => { const normalizedKind = kind.toLowerCase(); if (normalizedKind === 'grep' || normalizedKind === 'grep_search') { return 'Grep'; } else if (normalizedKind === 'glob') { return 'Glob'; } else if (normalizedKind === 'web_search') { return 'WebSearch'; } else { return 'Search'; } }; /** * Specialized component for Search tool calls * Optimized for displaying search operations and results */ export const SearchToolCall: FC = ({ toolCall, isFirst, isLast, }) => { const { kind, title, content, locations } = toolCall; const queryText = safeTitle(title); const displayLabel = getDisplayLabel(kind); const containerStatus: ContainerStatus = mapToolStatusToContainerStatus( toolCall.status, ); // Group content by type const { errors, textOutputs } = groupContent(content); // Error case: show search query + error in card layout if (errors.length > 0) { return (
{queryText}
{errors.join('\n')}
); } // Success case with results: show search query + file list if (locations && locations.length > 0) { // Multiple results use card layout if (locations.length > 1) { return (
{queryText}
); } // Single result - compact format return ( ); } // Show content text if available if (textOutputs.length > 0) { return (
{textOutputs.map((text: string, index: number) => (
{text}
))}
); } // No results - show query only if (queryText) { return ( ); } return null; };