@voyager-0x/agent-mcp
Version:
Voyager MCP Agent - A powerful Model Context Protocol agent
138 lines (117 loc) • 3.27 kB
text/typescript
import OpenAI from "openai";
import { log } from "./log.js";
import { Session } from "./session.js";
import { Prompt } from "./prompt.js";
import { aiConfigManager } from "./config.js";
type MessageItem = {
role: "system" | "user" | "assistant";
content: string;
};
export type LLMConfig = {
apiKey: string;
baseURL: string;
model: string;
};
export class AbortError extends Error {
constructor(message?: string) {
super(message);
this.name = "AbortError";
}
}
export class AIChat {
private session: Session;
private messages: MessageItem[] = [];
addMessage(messageItem: MessageItem) {
log.info("对话:", messageItem);
this.messages.push(messageItem);
}
getMessages() {
return this.messages;
}
constructor(systemPrompt: string, session: Session) {
this.session = session;
this.addMessage({
role: "system",
content: systemPrompt,
});
}
/**
* 流式对话,逐步推送内容
* @param usermessage 用户输入
* @returns 最终完整回复
*/
async chat(usermessage: string) {
// 创建新的 AbortController
const abortController = new AbortController();
const _cancel = () => {
abortController.abort();
};
const _chat = async (usermessage: string) => {
this.addMessage({
role: "user",
content: usermessage,
});
const config = aiConfigManager.getConfig();
const chatClient = new OpenAI({
apiKey: config.apiKey,
baseURL: config.baseURL,
// 在浏览器环境时允许调用
...((typeof globalThis !== 'undefined' && 'window' in globalThis)
? { dangerouslyAllowBrowser: true }
: {}),
});
let reply = "";
// 向大模型进行流式问答
const stream = await chatClient.chat.completions.create(
{
model: config.model,
messages: this.messages,
stream: true,
},
{
signal: abortController.signal,
}
);
for await (const chunk of stream) {
// 检查中止信号
if (abortController.signal.aborted) {
throw new AbortError();
}
const delta = chunk.choices?.[0]?.delta?.content || "";
if (delta) {
reply += delta;
this.session.emit("reply", delta);
}
}
this.addMessage({ role: "assistant", content: reply });
return reply;
};
try {
this.session.on("cancel", _cancel);
const reply = await _chat(usermessage);
return reply;
} finally {
this.session.off("cancel", _cancel);
}
}
}
export class ChatManager {
private session: Session;
private prompt: Prompt;
constructor({ session }: { session: Session }) {
this.session = session;
this.prompt = new Prompt();
}
private createChat(system_propmt: string): AIChat {
const chatClient = new AIChat(system_propmt, this.session);
return chatClient;
}
async createMcpChat() {
const system_propmt = await this.prompt.buildMcpPrompt();
return this.createChat(system_propmt);
}
async createFixJsonChat() {
const system_propmt = await this.prompt.buildFixJsonPrompt();
return this.createChat(system_propmt);
}
}