prompt-builder.js
3.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/**
* 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();
}
/**
* 动态生成环境快照
*/
getSystemStateXML() {
return `<env_status>\n <timestamp>${new Date().toISOString()}</timestamp>\n</env_status>\n`;
}
/**
* 加载文件内容(带缓存)
*/
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}`);
}
// 在最终拼接前,注入上帝视角的环境感知
parts.unshift(this.getSystemStateXML());
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 };