index.ts•4.44 kB
import { ToolDefinition, ToolResponse } from '../types.js';
interface StackFrame {
file: string;
line: number;
function?: string;
error?: string;
message?: string;
}
// 工具辅助函数
function parsePythonStackTrace(error: string): StackFrame[] {
const frames: StackFrame[] = [];
const lines = error.split('\n');
let currentError: string | undefined;
let errorMessage: string | undefined;
// 查找错误类型和消息
const errorMatch = error.match(/^([A-Za-z.]+Error): (.+)$/m);
if (errorMatch) {
currentError = errorMatch[1];
errorMessage = errorMatch[2];
}
// 匹配堆栈帧
// 例如: File "path/to/file.py", line 10, in function_name
const frameRegex = /File "([^"]+)", line (\d+)(?:, in (\w+))?/;
for (let i = 0; i < lines.length; i++) {
const match = lines[i].match(frameRegex);
if (match) {
frames.push({
file: match[1],
line: parseInt(match[2], 10),
function: match[3],
error: currentError,
message: errorMessage
});
}
}
return frames;
}
function parseJsStackTrace(error: string): StackFrame[] {
const frames: StackFrame[] = [];
const lines = error.split('\n');
let currentError: string | undefined;
let errorMessage: string | undefined;
// 查找错误类型和消息
const errorMatch = error.match(/^([A-Za-z]+Error): (.+)$/m);
if (errorMatch) {
currentError = errorMatch[1];
errorMessage = errorMatch[2];
}
// 匹配堆栈帧
// 例如: at functionName (/path/to/file.js:10:20)
// 或者: at /path/to/file.js:10:20
const frameRegex = /at (?:([^(]+) \(([^:]+):(\d+):(\d+)\)|([^:]+):(\d+):(\d+))/;
for (const line of lines) {
const match = line.match(frameRegex);
if (match) {
if (match[1]) {
// 带函数名的格式
frames.push({
file: match[2],
line: parseInt(match[3], 10),
function: match[1].trim(),
error: currentError,
message: errorMessage
});
} else {
// 不带函数名的格式
frames.push({
file: match[5],
line: parseInt(match[6], 10),
error: currentError,
message: errorMessage
});
}
}
}
return frames;
}
// 堆栈跟踪处理器
async function stackTraceHandler(args: { error: string; language?: string }): Promise<ToolResponse> {
try {
const { error, language = 'javascript' } = args;
let frames: StackFrame[] = [];
switch (language) {
case 'python':
frames = parsePythonStackTrace(error);
break;
case 'javascript':
case 'typescript':
frames = parseJsStackTrace(error);
break;
default:
throw new Error(`不支持的语言: ${language}`);
}
if (frames.length === 0) {
return {
content: [{
type: 'text',
text: '未找到堆栈帧信息'
}],
isError: true
};
}
// 格式化堆栈跟踪为文本
let resultText = '';
// 添加错误信息
if (frames[0]?.error) {
resultText += `错误类型: ${frames[0].error}\n`;
if (frames[0].message) {
resultText += `错误信息: ${frames[0].message}\n`;
}
resultText += '\n';
}
// 添加堆栈帧信息
resultText += `堆栈跟踪 (共 ${frames.length} 帧):\n\n`;
frames.forEach((frame, index) => {
resultText += `${index + 1}. `;
if (frame.function) {
resultText += `在函数 ${frame.function} 中\n`;
}
resultText += ` 文件: ${frame.file}:${frame.line}\n`;
});
return {
content: [{
type: 'text',
text: resultText.trim()
}]
};
} catch (error) {
return {
content: [{
type: 'text',
text: error instanceof Error ? error.message : String(error)
}],
isError: true
};
}
}
// 导出堆栈跟踪工具定义
export const stackTraceTools: ToolDefinition[] = [{
name: 'get_stack_trace',
description: '从错误输出中提取堆栈跟踪信息',
inputSchema: {
type: 'object',
properties: {
error: {
type: 'string',
description: '错误输出文本'
},
language: {
type: 'string',
enum: ['python', 'javascript', 'typescript'],
description: '编程语言'
}
},
required: ['error']
},
handler: stackTraceHandler
}];