import { ContextManager } from '../context.js'; import { chat } from '../llm.js'; import { getTools } from '../tools/registry.js'; import { Tool } from '../types/index.js'; import { hooks } from '../hooks/index.js'; export interface AgentConfig { name: string; systemPrompt: string; /** 该 Agent 可用的工具列表,默认使用全局注册的所有工具 */ tools?: Tool[]; } export class Agent { public name: string; private context: ContextManager; private tools: Tool[]; constructor(config: AgentConfig) { this.name = config.name; this.tools = config.tools ?? getTools(); this.context = new ContextManager(); this.context.add({ role: 'system', content: config.systemPrompt }); } /** * 运行 Agent 循环:发送消息 → 处理 tool_calls → 返回最终回复 */ async run(userMessage: string): Promise { this.context.add({ role: 'user', content: userMessage }); const openaiTools = this.tools.length > 0 ? this.tools.map((t) => ({ type: 'function' as const, function: { name: t.name, description: t.description, parameters: t.parameters, }, })) : undefined; let reply = await chat(this.context.getMessages(), openaiTools); // 工具调用循环 while (reply.tool_calls && reply.tool_calls.length > 0) { this.context.add({ role: 'assistant', content: '', tool_calls: reply.tool_calls, } as any); for (const tc of reply.tool_calls) { const tool = this.tools.find((t) => t.name === tc.function.name); if (!tool) { this.context.add({ role: 'tool', tool_call_id: tc.id, content: `错误: 未知工具 ${tc.function.name}`, } as any); continue; } hooks.emit('tool:before', { toolCall: tc, agentName: this.name }); try { const args = JSON.parse(tc.function.arguments); const result = await tool.execute(args); this.context.add({ role: 'tool', tool_call_id: tc.id, content: result, } as any); hooks.emit('tool:after', { toolCall: tc, result, agentName: this.name }); } catch (e: any) { this.context.add({ role: 'tool', tool_call_id: tc.id, content: `工具执行错误: ${e.message}`, } as any); hooks.emit('tool:after', { toolCall: tc, result: `错误: ${e.message}`, agentName: this.name }); } } reply = await chat(this.context.getMessages(), openaiTools); } const content = reply.content!; this.context.add({ role: 'assistant', content }); return content; } }