/** * @license * Copyright 2025 Qwen Team * SPDX-License-Identifier: Apache-2.0 * * WebFetch/WebSearch tool call component * Displays web fetch and search operations with URL/query and output */ import { useState, type FC } from 'react'; import { ToolCallContainer, safeTitle, groupContent, mapToolStatusToContainerStatus, } from './shared/index.js'; import type { BaseToolCallProps } from './shared/index.js'; import { getToolDisplayLabel } from './labelUtils.js'; import { MarkdownRenderer } from '../messages/MarkdownRenderer/MarkdownRenderer.js'; type WebVariant = 'fetch' | 'search'; /** Default collapsed height in pixels */ const COLLAPSED_HEIGHT = 120; /** Threshold for showing expand button (content longer than this will be collapsible) */ const EXPAND_THRESHOLD = 300; /** * Get the URL or query from tool call data * @param variant - 'fetch' or 'search' * @param title - Tool call title * @param rawInput - Raw input object * @returns URL or query string */ const getWebTarget = ( variant: WebVariant, title: unknown, rawInput?: unknown, ): string => { // Try to extract URL or query from rawInput if (rawInput && typeof rawInput === 'object') { const input = rawInput as Record; if (variant === 'fetch' && input['url']) { return String(input['url']); } if (variant === 'search' && input['query']) { return String(input['query']); } } return safeTitle(title); }; /** * Output card component with expand/collapse functionality * @param props - Component props * @returns JSX element */ const OutputCard: FC<{ content: string; isError?: boolean; }> = ({ content, isError = false }) => { const [isExpanded, setIsExpanded] = useState(false); const isLongContent = content.length > EXPAND_THRESHOLD; return (
OUT
{isError ? (
                {content}
              
) : (
)}
{/* Expand/Collapse button */} {isLongContent && (
)}
); }; /** * WebFetch/WebSearch tool call implementation * @param props - Component props including toolCall, variant, isFirst, isLast * @returns JSX element */ const WebFetchToolCallImpl: FC = ({ toolCall, variant, isFirst, isLast, }) => { const { title, content, rawInput, toolCallId } = toolCall; const webTarget = getWebTarget(variant, title, rawInput); const label = getToolDisplayLabel({ kind: toolCall.kind, title }); // Group content by type const { textOutputs, errors } = groupContent(content); // Map tool status to container status const containerStatus = errors.length > 0 ? 'error' : mapToolStatusToContainerStatus(toolCall.status); // Error case if (errors.length > 0) { return ( ); } // Success with output if (textOutputs.length > 0) { const output = textOutputs.join('\n'); return ( ); } // No output yet - show just the URL/query (loading state) return ( ); }; /** * WebFetchToolCall - displays web fetch/search tool calls * Shows URL/query and output with OUT card * @param props - Component props * @returns JSX element */ export const WebFetchToolCall: FC = (props) => ( );