/** * 统一工具执行器 * 根据工具名称和输入参数执行对应的工具 */ import { webSearch, formatSearchResults, formatSearchResultsShort, type WebSearchInput, type WebSearchResponse, } from './webSearch'; import { executeCode, formatExecutionResult, formatExecutionResultShort, type CodeExecutionInput, type CodeExecutionResponse, } from './codeExecution'; import { webFetch, formatFetchResult, formatFetchResultShort, type WebFetchInput, type WebFetchResponse, } from './webFetch'; import { metasoSearch, formatMetasoSearchResults, formatMetasoSearchResultsShort, getValidImages, ImageValidationConfig, type MetasoSearchInput, type MetasoSearchResponse, type MetasoImageResult, type MetasoVideoResult, } from './metasoSearch'; import { metasoReader, formatMetasoReaderResult, formatMetasoReaderResultShort, type MetasoReaderInput, type MetasoReaderResponse, } from './metasoReader'; import { translate, formatTranslateResult, formatTranslateResultShort, type TranslateInput, type TranslateResponse, } from './translate'; import { shouldUsePyodide, analyzeCode, type LoadingCallback } from './codeAnalyzer'; // 导出代码分析函数供外部使用 export { shouldUsePyodide, analyzeCode, type LoadingCallback } from './codeAnalyzer'; export interface ToolExecutionResult { success: boolean; /** 完整结果 - 发送给 AI */ fullResult: string; /** 简短结果 - 显示给用户 */ displayResult: string; /** 原始数据 */ rawData?: unknown; /** Base64 编码的图片数组(代码执行时可能产生) */ images?: string[]; /** 搜索到的图片数组(图片搜索时产生) */ searchImages?: MetasoImageResult[]; /** 搜索到的视频数组(视频搜索时产生) */ searchVideos?: MetasoVideoResult[]; /** 是否需要浏览器端 Pyodide 执行 */ requiresPyodide?: boolean; /** 代码内容(当 requiresPyodide 为 true 时) */ code?: string; /** 语言(当 requiresPyodide 为 true 时) */ language?: string; } export interface ToolExecutionOptions { /** Pyodide 加载进度回调 */ onProgress?: LoadingCallback; /** 秘塔AI API Key */ metasoApiKey?: string; } /** * 执行工具 * @param toolName 工具名称 * @param input 工具输入参数 * @param options 执行选项 * @returns 执行结果(包含完整版和简短版) */ export async function executeTool( toolName: string, input: Record, options?: ToolExecutionOptions ): Promise { const { onProgress, metasoApiKey } = options || {}; try { switch (toolName) { case 'web_search': { const query = String(input.query || ''); const searchInput: WebSearchInput = { query }; const response: WebSearchResponse = await webSearch(searchInput); return { success: response.success, fullResult: formatSearchResults(response), displayResult: formatSearchResultsShort(response, query), rawData: response, }; } case 'code_execution': { const language = String(input.language || 'python'); const code = String(input.code || ''); // 检测是否需要浏览器端 Pyodide 执行(Python + 图形代码) if (shouldUsePyodide(code, language)) { return { success: true, fullResult: '需要在浏览器端执行 Python 图形代码', displayResult: '检测到图形绑制代码,正在准备浏览器端执行...', requiresPyodide: true, code, language, }; } // 使用 Piston API 执行(服务端) const codeInput: CodeExecutionInput = { code, language, stdin: input.stdin ? String(input.stdin) : undefined, onProgress, // 传递 Pyodide 加载进度回调 }; const response: CodeExecutionResponse = await executeCode(codeInput); return { success: response.success, fullResult: formatExecutionResult(response), displayResult: formatExecutionResultShort(response, language), rawData: response, images: response.images, // 传递图片数据 }; } case 'web_fetch': { const fetchInput: WebFetchInput = { url: String(input.url || ''), }; const response: WebFetchResponse = await webFetch(fetchInput); return { success: response.success, fullResult: formatFetchResult(response), displayResult: formatFetchResultShort(response), rawData: response, }; } case 'mita_search': { const query = String(input.query || ''); const scope = (input.scope as 'webpage' | 'image' | 'video') || 'webpage'; // 图片搜索时请求更多图片用于验证筛选,视频和网页搜索保持原有逻辑 const requestSize = scope === 'image' ? ImageValidationConfig.REQUEST_SIZE : (input.size ? Number(input.size) : (scope === 'video' ? 5 : 10)); const searchInput: MetasoSearchInput = { query, scope, size: requestSize, includeSummary: Boolean(input.includeSummary), }; const response: MetasoSearchResponse = await metasoSearch(searchInput, metasoApiKey || ''); // 如果是图片搜索且成功,验证图片有效性 let validatedImages: MetasoImageResult[] | undefined; if (scope === 'image' && response.success && response.images && response.images.length > 0) { // 验证图片,返回指定数量的有效图片 validatedImages = await getValidImages( response.images, ImageValidationConfig.TARGET_COUNT, ImageValidationConfig.CONCURRENCY ); // 更新 response 中的图片为验证后的有效图片 response.images = validatedImages; } return { success: response.success, fullResult: formatMetasoSearchResults(response), displayResult: formatMetasoSearchResultsShort(response, query), rawData: response, // 如果是图片搜索,返回验证后的图片数据 searchImages: scope === 'image' ? validatedImages : undefined, // 如果是视频搜索,返回视频数据 searchVideos: scope === 'video' ? response.videos : undefined, }; } case 'mita_reader': { const url = String(input.url || ''); const readerInput: MetasoReaderInput = { url, format: 'Markdown', }; const response: MetasoReaderResponse = await metasoReader(readerInput, metasoApiKey || ''); return { success: response.success, fullResult: formatMetasoReaderResult(response, url), displayResult: formatMetasoReaderResultShort(response, url), rawData: response, }; } case 'youdao_translate': { const text = String(input.text || ''); const from = input.from ? String(input.from) : 'auto'; const to = input.to ? String(input.to) : 'zh-CHS'; const translateInput: TranslateInput = { text, from, to }; const response: TranslateResponse = await translate(translateInput); return { success: response.success, fullResult: formatTranslateResult(response, text), displayResult: formatTranslateResultShort(response, text), rawData: response, }; } default: return { success: false, fullResult: `未知的工具: ${toolName}`, displayResult: `未知的工具: ${toolName}`, }; } } catch (error) { console.error(`Tool execution error (${toolName}):`, error); const errorMsg = error instanceof Error ? error.message : '未知错误'; return { success: false, fullResult: `工具执行错误: ${errorMsg}`, displayResult: `工具执行错误: ${errorMsg}`, }; } } /** * 获取所有可用工具的信息 */ export function getAvailableTools() { return [ { id: 'web_search', name: '网络搜索', description: '搜索互联网获取最新信息', icon: '🔍', }, { id: 'web_fetch', name: '网页获取', description: '获取指定 URL 的网页内容', icon: '🌐', }, { id: 'mita_search', name: 'Metaso Search', description: '秘塔AI智能搜索,需要配置API Key', icon: '🔎', }, { id: 'mita_reader', name: 'Metaso Reader', description: '秘塔AI网页读取,返回Markdown格式', icon: '📄', }, { id: 'youdao_translate', name: '翻译', description: '有道智云高质量多语言翻译,支持100+种语言', icon: '🌐', }, ]; }