93 lines
2.7 KiB
TypeScript
93 lines
2.7 KiB
TypeScript
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<string> {
|
|
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;
|
|
}
|
|
}
|