import { Box, Text } from 'ink' import React from 'react' import { z } from 'zod' import { Cost } from '../../components/Cost' import { FallbackToolUseRejectedMessage } from '../../components/FallbackToolUseRejectedMessage' import { Tool, ToolUseContext } from '../../Tool' import { DESCRIPTION, TOOL_NAME_FOR_PROMPT } from './prompt' import { SearchResult, searchProviders } from './searchProviders' const inputSchema = z.strictObject({ query: z.string().describe('The search query'), }) type Input = z.infer type Output = { durationMs: number results: SearchResult[] } export const WebSearchTool = { name: TOOL_NAME_FOR_PROMPT, async description() { return DESCRIPTION }, userFacingName: () => 'Web Search', inputSchema, isReadOnly: () => true, isConcurrencySafe: () => true, async isEnabled() { return true }, needsPermissions() { return false }, async prompt() { return DESCRIPTION }, renderToolUseMessage({ query }: Input) { return `Searching for: "${query}" using DuckDuckGo` }, renderToolUseRejectedMessage() { return }, renderToolResultMessage(output: Output) { return (   ⎿  Found {output.results.length} {output.results.length === 1 ? 'result' : 'results'} using DuckDuckGo ) }, renderResultForAssistant(output: Output) { if (output.results.length === 0) { return `No results found using DuckDuckGo.` } let result = `Found ${output.results.length} search results using DuckDuckGo:\n\n` output.results.forEach((item, index) => { result += `${index + 1}. **${item.title}**\n` result += ` ${item.snippet}\n` result += ` Link: ${item.link}\n\n` }) result += `You can reference these results to provide current, accurate information to the user.` return result }, async *call({ query }: Input, {}: ToolUseContext) { const start = Date.now() try { const searchResults = await searchProviders.duckduckgo.search(query) const output: Output = { results: searchResults, durationMs: Date.now() - start, } yield { type: 'result' as const, resultForAssistant: this.renderResultForAssistant(output), data: output, } } catch (error: any) { const output: Output = { results: [], durationMs: Date.now() - start, } yield { type: 'result' as const, resultForAssistant: `An error occurred during web search with DuckDuckGo: ${error.message}`, data: output, } } }, } satisfies Tool