/** * PromptBuilder - 根据 Agent 类型拼接 protocol + prompt */ const fs = require('fs'); const path = require('path'); class PromptBuilder { constructor(config, baseDir) { this.config = config; this.baseDir = baseDir; this.protocolCache = new Map(); this.promptCache = new Map(); } /** * 加载文件内容(带缓存) */ loadFile(filePath) { const fullPath = path.isAbsolute(filePath) ? filePath : path.join(this.baseDir, filePath); if (!this.promptCache.has(fullPath)) { if (!fs.existsSync(fullPath)) { throw new Error(`File not found: ${fullPath}`); } this.promptCache.set(fullPath, fs.readFileSync(fullPath, 'utf-8')); } return this.promptCache.get(fullPath); } /** * 获取 role protocol 内容 */ getProtocol(type) { const protocolPath = this.config.rolePrompts?.[type] || this.config.protocols?.[type]; if (!protocolPath) { return ''; } return this.loadFile(protocolPath); } /** * 获取 agent prompt 内容 */ getAgentPrompt(agentName) { const agent = this.config.agents[agentName]; if (!agent) { throw new Error(`Agent not found: ${agentName}`); } const promptPath = agent.prompt || agent.systemPrompt; if (!promptPath) { return ''; } return this.loadFile(promptPath); } /** * 构建可用 Agent 列表(用于 master protocol) */ buildAvailableAgentsList() { const excluded = new Set(['master', 'gateway']); return Object.entries(this.config.agents) .filter(([name]) => !excluded.has(name)) .map(([name, cfg]) => `- **${name}** (${cfg.type}): ${cfg.description}`) .join('\n'); } /** * 构建完整的 system prompt * - SKILL.md 模式: 直接使用 SKILL.md(已包含 protocol),不再叠加 protocol * - 旧模式: protocol + agent prompt(向后兼容非 Innovator agent) */ build(agentName, userTask = '') { const agent = this.config.agents[agentName]; if (!agent) { throw new Error(`Agent not found: ${agentName}`); } const parts = []; const promptPath = agent.prompt || agent.systemPrompt || ''; const isSkillBased = promptPath.endsWith('SKILL.md'); if (isSkillBased) { // SKILL.md 已包含 protocol,直接使用 const skillPrompt = this.getAgentPrompt(agentName); if (skillPrompt) parts.push(skillPrompt); } else { // 旧模式:先加 protocol,再加 agent prompt const protocol = this.getProtocol(agent.type); if (protocol) { let processedProtocol = protocol; if (agent.type === 'master') { processedProtocol = processedProtocol.replace( '{{AVAILABLE_AGENTS}}', this.buildAvailableAgentsList() ); } parts.push(processedProtocol); } const agentPrompt = this.getAgentPrompt(agentName); if (agentPrompt) parts.push(agentPrompt); } // User Task if (userTask) { parts.push(`---\n\n## 当前任务\n\n${userTask}`); } let result = parts.join('\n\n---\n\n'); // 替换 {{AVAILABLE_AGENTS}} 占位符(可能在 SKILL.md 或 protocol 中) if (result.includes('{{AVAILABLE_AGENTS}}')) { result = result.replace(/\{\{AVAILABLE_AGENTS\}\}/g, this.buildAvailableAgentsList()); } return result; } } module.exports = { PromptBuilder };