diff --git a/utils/tools/CodeExecutionTool.js b/utils/tools/CodeExecutionTool.js index 327373f..45cfc7b 100644 --- a/utils/tools/CodeExecutionTool.js +++ b/utils/tools/CodeExecutionTool.js @@ -4,13 +4,15 @@ import { Config } from '../config.js'; import common from '../../../../lib/common/common.js'; /** - * 代码执行工具类 - 使用 Gemini API - * @class CodeExecutionTool + * CodeExecutionTool - Gemini API代码执行工具类 + * 支持多种编程语言的代码执行,并提供详细的执行结果和分析 * @extends {AbstractTool} */ export class CodeExecutionTool extends AbstractTool { + // 工具标识名称 name = 'CodeExecutionTool'; + // 工具参数定义 parameters = { properties: { code: { @@ -29,54 +31,54 @@ export class CodeExecutionTool extends AbstractTool { required: ['code', 'language'], }; + // 工具功能描述 description = '使用 Gemini API 执行代码,支持多种编程语言,并返回执行结果和相关解释。'; - // 配置常量 - static TIMEOUT = 30000; // 请求超时时间:30秒 + // API请求超时设置(30秒) + static TIMEOUT = 30000; /** - * 工具执行函数 - * @param {Object} opt - 工具参数 - * @param {string} opt.code - 代码内容 - * @param {string} opt.language - 编程语言 + * 工具主执行函数 + * @param {Object} opt - 执行参数对象 + * @param {string} opt.code - 需要执行的代码 + * @param {string} opt.language - 代码语言 * @param {string} [opt.description] - 代码功能描述 * @param {Object} e - 事件对象 - * @returns {Promise} - 包含执行结果的对象 + * @returns {Promise} 执行结果对象 */ func = async function (opt, e) { const { code, language, description } = opt; + // 代码内容验证 if (!code?.trim()) { throw new Error('代码内容不能为空'); } try { + // 执行代码并获取结果 const result = await this.executeCode(code, language, description); console.debug(`[CodeExecutionTool] 执行结果:`, result); - // 优化消息构建逻辑 - const messages = []; + // 解构结果对象 + const { output, executionOutput, explanation, error } = result; + const forwardMsg = []; - // 添加代码信息 - messages.push(`执行代码:\n\`\`\`${language}\n${code}\n\`\`\``); - - // 添加执行结果 - if (result.error) { - messages.push(`执行错误:\n\`\`\`\n${result.error}\n\`\`\``); + // 根据执行结果构建消息 + if (error) { + forwardMsg.push(`执行出错:\n${error}`); } else { - messages.push(`执行结果:\n\`\`\`\n${result.output}\n\`\`\``); + // 添加程序实际输出(如果有) + if (executionOutput) { + forwardMsg.push(`程序输出:\n${executionOutput}`); + } + forwardMsg.push(`执行结果:\n${output}`); + if (explanation) { + forwardMsg.push(`\n代码分析:\n${explanation}`); + } } - // 添加代码分析 - if (result.explanation) { - messages.push(`代码分析:\n${result.explanation}`); - } - - // 添加执行时间 - messages.push(`执行时间:${new Date(result.executionTime).toLocaleString()}`); - // 发送转发消息 - e.reply(await common.makeForwardMsg(e, messages, `${e.sender.card || e.sender.nickname || e.user_id}的代码执行结果`)); + e.reply(await common.makeForwardMsg(e, forwardMsg, `${e.sender.card || e.sender.nickname || e.user_id}的代码执行结果`)); return result; } catch (error) { @@ -86,22 +88,25 @@ export class CodeExecutionTool extends AbstractTool { }; /** - * 使用 Gemini API 执行代码 + * 通过Gemini API执行代码 * @param {string} code - 代码内容 * @param {string} language - 编程语言 - * @param {string} [description] - 代码功能描述 - * @returns {Promise} - 包含执行结果的对象 + * @param {string} [description] - 代码描述 + * @returns {Promise} API执行结果 * @private */ async executeCode(code, language, description) { + // 获取API配置信息 const apiKey = Config.geminiKey; const apiBaseUrl = Config.geminiBaseUrl; const apiUrl = `${apiBaseUrl}/v1beta/models/gemini-2.0-flash-exp:generateContent?key=${apiKey}`; + // API配置验证 if (!apiKey || !apiBaseUrl) { throw new Error('Gemini API 配置缺失'); } + // 构建API请求体 const requestBody = { "systemInstruction": { "parts": [{ @@ -126,9 +131,11 @@ export class CodeExecutionTool extends AbstractTool { }; try { + // 设置请求超时控制 const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), CodeExecutionTool.TIMEOUT); + // 发送API请求 const response = await fetch(apiUrl, { method: 'POST', headers: { @@ -142,6 +149,7 @@ export class CodeExecutionTool extends AbstractTool { const data = await response.json(); + // 响应状态检查 if (!response.ok) { throw new Error(`API 请求失败: ${data.error?.message || '未知错误'}`); } @@ -156,11 +164,11 @@ export class CodeExecutionTool extends AbstractTool { } /** - * 构建提示词 + * 构建API提示词 * @param {string} code - 代码内容 * @param {string} language - 编程语言 - * @param {string} [description] - 代码功能描述 - * @returns {string} - 格式化的提示词 + * @param {string} [description] - 代码描述 + * @returns {string} 格式化的提示词 * @private */ constructPrompt(code, language, description) { @@ -170,24 +178,27 @@ export class CodeExecutionTool extends AbstractTool { } prompt += `\n执行代码:\n\`\`\`${language}\n${code}\n\`\`\`\n`; prompt += '请按照以下格式返回结果:\n'; - prompt += '执行结果(OUTCOME_OK):\n```\n<执行输出>\n```\n'; + prompt += '执行输出:\n```\n<程序实际输出内容>\n```\n'; + prompt += '执行结果(OUTCOME_OK):\n```\n<执行状态和结果说明>\n```\n'; prompt += '如果执行出错,请使用:\n'; prompt += '执行结果(OUTCOME_ERROR):\n```\n<错误信息>\n```\n'; - prompt += '如果需要,可以在最后添加代码分析。'; + prompt += '代码分析:\n<分析和建议>'; return prompt; } /** - * 处理 Gemini API 响应 - * @param {Object} data - API 响应数据 - * @returns {Object} - 处理后的结果对象 + * 处理Gemini API响应数据 + * @param {Object} data - API响应数据 + * @returns {Object} 处理后的结果对象,包含输出、执行输出、解释和错误信息 * @private */ processGeminiResponse(data) { + // 响应数据结构验证 if (!data?.candidates?.[0]?.content?.parts) { throw new Error('无效的 API 响应'); } + // 合并响应文本 const response = data.candidates[0].content.parts .map(part => part.text) .filter(Boolean) @@ -196,23 +207,30 @@ export class CodeExecutionTool extends AbstractTool { let output = ''; let explanation = ''; let error = null; + let executionOutput = ''; try { - // 查找执行结果部分 + // 提取执行输出 + const outputMatch = response.match(/执行输出:\s*```(?:\w*\n)?([\s\S]*?)```/); + if (outputMatch) { + executionOutput = outputMatch[1].trim(); + } + + // 提取执行结果 const outcomeMatch = response.match(/执行结果\(OUTCOME_OK\):\s*```(?:\w*\n)?([\s\S]*?)```/); if (outcomeMatch) { output = outcomeMatch[1].trim(); } else { - // 检查是否有错误结果 + // 提取错误信息 const errorMatch = response.match(/执行结果\(OUTCOME_ERROR\):\s*```(?:\w*\n)?([\s\S]*?)```/); if (errorMatch) { error = errorMatch[1].trim(); } else { - output = response; // 如果没有匹配到预期格式,返回原始响应 + output = response; // 使用原始响应作为输出 } } - // 提取代码分析部分(如果有) + // 提取代码分析 const analysisMatch = response.match(/代码分析:([\s\S]*?)(?=\n\n|$)/); if (analysisMatch) { explanation = analysisMatch[1].trim(); @@ -222,11 +240,13 @@ export class CodeExecutionTool extends AbstractTool { output = response; // 解析失败时返回原始响应 } + // 返回完整的结果对象 return { - output, - explanation, - error, - executionTime: Date.now() + output, // 执行结果说明 + executionOutput, // 程序实际输出 + explanation, // 代码分析 + error, // 错误信息 + executionTime: Date.now() // 执行时间戳 }; } } \ No newline at end of file