喵喵喵

This commit is contained in:
gaoao-3 2025-01-03 15:19:08 +08:00
parent d1ca268f36
commit 267c24dda5

View file

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