- Complete knowledge base list and detail pages - Complete document upload component - Fix CORS config (add PUT/DELETE method support) - Fix file upload issues (disabled state and beforeUpload return value) - Add detailed debug logs (cleaned up) - Create Day 21-22 completion summary document
216 lines
5.5 KiB
TypeScript
216 lines
5.5 KiB
TypeScript
import fs from 'fs';
|
||
import path from 'path';
|
||
import yaml from 'js-yaml';
|
||
import { fileURLToPath } from 'url';
|
||
|
||
const __filename = fileURLToPath(import.meta.url);
|
||
const __dirname = path.dirname(__filename);
|
||
|
||
// 智能体配置接口
|
||
export interface AgentConfig {
|
||
id: string;
|
||
name: string;
|
||
nameEn: string;
|
||
description: string;
|
||
category: string;
|
||
icon: string;
|
||
enabled: boolean;
|
||
systemPromptFile: string;
|
||
userPromptTemplateFile: string;
|
||
models: {
|
||
[modelName: string]: {
|
||
temperature: number;
|
||
maxTokens: number;
|
||
topP?: number;
|
||
};
|
||
};
|
||
ragEnabled: boolean;
|
||
requiresProject: boolean;
|
||
outputFormat: 'text' | 'structured' | 'document';
|
||
tags: string[];
|
||
}
|
||
|
||
// 配置文件根结构
|
||
interface AgentsConfigFile {
|
||
agents: AgentConfig[];
|
||
}
|
||
|
||
class AgentService {
|
||
private agents: Map<string, AgentConfig> = new Map();
|
||
private prompts: Map<string, string> = new Map();
|
||
private configPath: string;
|
||
private promptsPath: string;
|
||
|
||
constructor() {
|
||
// 配置文件路径
|
||
this.configPath = path.resolve(__dirname, '../../config/agents.yaml');
|
||
this.promptsPath = path.resolve(__dirname, '../../prompts');
|
||
|
||
// 初始化加载配置
|
||
this.loadAgents();
|
||
}
|
||
|
||
// 加载智能体配置
|
||
private loadAgents() {
|
||
try {
|
||
const fileContents = fs.readFileSync(this.configPath, 'utf8');
|
||
const config = yaml.load(fileContents) as AgentsConfigFile;
|
||
|
||
if (!config || !config.agents) {
|
||
throw new Error('Invalid agents configuration file');
|
||
}
|
||
|
||
// 存储到Map中
|
||
config.agents.forEach((agent) => {
|
||
this.agents.set(agent.id, agent);
|
||
});
|
||
|
||
console.log(`✅ Loaded ${this.agents.size} agent configurations`);
|
||
} catch (error) {
|
||
console.error('❌ Failed to load agent configurations:', error);
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
// 加载Prompt模板
|
||
private loadPrompt(filename: string): string {
|
||
const cacheKey = filename;
|
||
|
||
// 检查缓存
|
||
if (this.prompts.has(cacheKey)) {
|
||
return this.prompts.get(cacheKey)!;
|
||
}
|
||
|
||
try {
|
||
const promptPath = path.join(this.promptsPath, filename);
|
||
const content = fs.readFileSync(promptPath, 'utf8');
|
||
|
||
// 缓存到内存
|
||
this.prompts.set(cacheKey, content);
|
||
|
||
return content;
|
||
} catch (error) {
|
||
console.error(`❌ Failed to load prompt file: ${filename}`, error);
|
||
throw new Error(`Prompt file not found: ${filename}`);
|
||
}
|
||
}
|
||
|
||
// 获取所有智能体列表
|
||
getAllAgents(): AgentConfig[] {
|
||
return Array.from(this.agents.values());
|
||
}
|
||
|
||
// 获取启用的智能体列表
|
||
getEnabledAgents(): AgentConfig[] {
|
||
return Array.from(this.agents.values()).filter((agent) => agent.enabled);
|
||
}
|
||
|
||
// 根据ID获取智能体配置
|
||
getAgentById(agentId: string): AgentConfig | null {
|
||
return this.agents.get(agentId) || null;
|
||
}
|
||
|
||
// 根据分类获取智能体列表
|
||
getAgentsByCategory(category: string): AgentConfig[] {
|
||
return Array.from(this.agents.values()).filter(
|
||
(agent) => agent.category === category
|
||
);
|
||
}
|
||
|
||
// 获取智能体的系统Prompt
|
||
getSystemPrompt(agentId: string): string {
|
||
const agent = this.getAgentById(agentId);
|
||
if (!agent) {
|
||
throw new Error(`Agent not found: ${agentId}`);
|
||
}
|
||
|
||
return this.loadPrompt(agent.systemPromptFile);
|
||
}
|
||
|
||
// 获取智能体的用户Prompt模板
|
||
getUserPromptTemplate(agentId: string): string {
|
||
const agent = this.getAgentById(agentId);
|
||
if (!agent) {
|
||
throw new Error(`Agent not found: ${agentId}`);
|
||
}
|
||
|
||
return this.loadPrompt(agent.userPromptTemplateFile);
|
||
}
|
||
|
||
// 渲染用户Prompt(替换模板变量)
|
||
renderUserPrompt(
|
||
agentId: string,
|
||
variables: {
|
||
projectBackground?: string;
|
||
userInput: string;
|
||
knowledgeBaseContext?: string;
|
||
}
|
||
): string {
|
||
const template = this.getUserPromptTemplate(agentId);
|
||
|
||
let rendered = template;
|
||
|
||
// 替换变量
|
||
rendered = rendered.replace(/\{\{projectBackground\}\}/g, variables.projectBackground || '未提供项目背景');
|
||
rendered = rendered.replace(/\{\{userInput\}\}/g, variables.userInput);
|
||
|
||
// 处理条件块(知识库上下文)
|
||
if (variables.knowledgeBaseContext) {
|
||
rendered = rendered.replace(
|
||
/\{\{#if knowledgeBaseContext\}\}([\s\S]*?)\{\{\/if\}\}/g,
|
||
'$1'
|
||
);
|
||
rendered = rendered.replace(/\{\{knowledgeBaseContext\}\}/g, variables.knowledgeBaseContext);
|
||
} else {
|
||
// 移除条件块
|
||
rendered = rendered.replace(
|
||
/\{\{#if knowledgeBaseContext\}\}[\s\S]*?\{\{\/if\}\}/g,
|
||
''
|
||
);
|
||
}
|
||
|
||
return rendered.trim();
|
||
}
|
||
|
||
// 检查智能体是否存在
|
||
agentExists(agentId: string): boolean {
|
||
return this.agents.has(agentId);
|
||
}
|
||
|
||
// 检查智能体是否启用
|
||
isAgentEnabled(agentId: string): boolean {
|
||
const agent = this.getAgentById(agentId);
|
||
return agent ? agent.enabled : false;
|
||
}
|
||
|
||
// 获取智能体的模型配置
|
||
getModelConfig(agentId: string, modelName: string) {
|
||
const agent = this.getAgentById(agentId);
|
||
if (!agent) {
|
||
throw new Error(`Agent not found: ${agentId}`);
|
||
}
|
||
|
||
const modelConfig = agent.models[modelName];
|
||
if (!modelConfig) {
|
||
throw new Error(`Model ${modelName} not configured for agent ${agentId}`);
|
||
}
|
||
|
||
return modelConfig;
|
||
}
|
||
|
||
// 重新加载配置(热更新)
|
||
reloadConfig() {
|
||
this.agents.clear();
|
||
this.prompts.clear();
|
||
this.loadAgents();
|
||
console.log('✅ Agent configurations reloaded');
|
||
}
|
||
}
|
||
|
||
// 导出单例
|
||
export const agentService = new AgentService();
|
||
|
||
|
||
|
||
|