foliko 1.1.4 → 1.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agent/agents/code-assistant.json +4 -1
- package/.agent/agents/file-assistant.json +4 -1
- package/.agent/agents/orchestrator-demo.md +53 -0
- package/.agent/agents/orchestrator.json +7 -0
- package/.agent/data/plugins-state.json +4 -0
- package/.agent/mcp_config.json +6 -0
- package/.agent/memory/feedback/mnrsiuoc-e1ru74.md +9 -0
- package/.agent/memory/feedback/mnrt2mmz-98az6n.md +9 -0
- package/.agent/memory/feedback/mnrtqrhm-kxsicz.md +9 -0
- package/.agent/memory/feedback/mnrts8vg-i0ngzp.md +15 -0
- package/.agent/memory/feedback/mnrtt7jt-c0trb2.md +9 -0
- package/.agent/memory/feedback/mnruc2f0-5s52la.md +16 -0
- package/.agent/memory/feedback/mnrumbmx-63sa0v.md +9 -0
- package/.agent/memory/project/mnrp7p5n-8enm2a.md +31 -0
- package/.agent/memory/project/mnrp9ifb-yynks0.md +40 -0
- package/.agent/memory/project/mnrpb3b8-f617s4.md +25 -0
- package/.agent/memory/project/mnrrmqgg-focprv.md +9 -0
- package/.agent/memory/project/mnrtykbh-6atsor.md +9 -0
- package/.agent/memory/project/mnru9jiu-kgau16.md +35 -0
- package/.agent/memory/reference/mnrnvpwo-rcqv9m.md +52 -0
- package/.agent/memory/reference/mnrovxvz-zy9xqm.md +25 -0
- package/.agent/memory/reference/mnroxabj-1b3930.md +68 -0
- package/.agent/memory/reference/mnrpjtlp-mnb9od.md +35 -0
- package/.agent/memory/reference/mnrps1x3-6b8xfm.md +28 -0
- package/.agent/memory/reference/mnrpt9ov-15er5w.md +22 -0
- package/.agent/memory/reference/mnrq82dn-y9tv9e.md +50 -0
- package/.agent/memory/reference/mnrqnr5v-v75drf.md +34 -0
- package/.agent/memory/reference/mnrrfzys-urudaf.md +31 -0
- package/.agent/memory/reference/mnrrocha-t0027n.md +21 -0
- package/.agent/memory/reference/mnrukklc-bxndsb.md +35 -0
- package/.agent/memory/user/mnrt39t8-8eosy0.md +9 -0
- package/.agent/plugins/marknative/fonts.zip +0 -0
- package/.agent/sessions/cli_default.json +4493 -1183
- package/.agent/test-agent.js +35 -0
- package/cli/src/commands/chat.js +69 -1
- package/cli/src/index.js +11 -2
- package/foliko-cloud-rising.png +0 -0
- package/foliko-dawn-of-ai.png +0 -0
- package/foliko-mindful-observation.png +0 -0
- package/foliko-stellar-dreams.png +0 -0
- package/foliko-zen-jing.png +0 -0
- package/foliko-zen-kong.png +0 -0
- package/foliko-zen-wu.png +0 -0
- package/package.json +2 -2
- package/plugins/coordinator-plugin.js +282 -0
- package/plugins/default-plugins.js +1 -1
- package/plugins/extension-executor-plugin.js +27 -1
- package/plugins/memory-plugin.js +228 -57
- package/src/core/agent-chat.js +206 -115
- package/src/core/agent.js +258 -71
- package/src/core/coordinator-manager.js +341 -0
- package/src/core/framework.js +50 -0
- package/src/core/plugin-base.js +30 -17
- package/src/core/sub-agent-config.js +8 -1
- package/src/core/worker-agent.js +176 -0
- package/src/executors/mcp-executor.js +4 -4
- package/zen_karesansui.png +0 -0
- package/.agent/plugins/marknative/update-readme.js +0 -134
- package/output/emoji-segoe-test-v2.png +0 -0
- package/output/emoji-segoe-test.png +0 -0
- package/output/emoji-test.png +0 -0
- package/output/emoji-windows-test.png +0 -0
- package/output/foliko-emoji-poster.png +0 -0
- package/output/foliko-muji-poster-final.png +0 -0
- package/output/foliko-muji-poster-v2.png +0 -0
- package/output/foliko-muji-poster.png +0 -0
- package/output/foliko-share.png +0 -0
- package/output/progress-circle-test.png +0 -0
- package/output/vb-agent-poster.png +0 -0
package/src/core/agent.js
CHANGED
|
@@ -3,13 +3,70 @@
|
|
|
3
3
|
* 负责对话和推理
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
const { pl } = require('zod/v4/locales');
|
|
7
6
|
const { EventEmitter } = require('../utils/event-emitter');
|
|
8
7
|
const { AgentChatHandler } = require('./agent-chat');
|
|
9
8
|
const { SystemPromptBuilder } = require('./system-prompt-builder');
|
|
10
|
-
const {
|
|
9
|
+
const { zodSchemaToTable } = require('@chnak/zod-to-markdown');
|
|
11
10
|
const os = require('os');
|
|
12
11
|
|
|
12
|
+
/**
|
|
13
|
+
* System Prompt 优先级常量
|
|
14
|
+
* 统一管理所有 prompt 部分的优先级,避免魔法数字
|
|
15
|
+
*/
|
|
16
|
+
const PROMPT_PRIORITY = {
|
|
17
|
+
ORIGINAL_PROMPT: 100,
|
|
18
|
+
SHARED_PROMPT: 200,
|
|
19
|
+
METADATA: 300,
|
|
20
|
+
TOOLS: 400,
|
|
21
|
+
SKILLS: 500,
|
|
22
|
+
SUB_AGENTS: 600,
|
|
23
|
+
CAPABILITIES: 700,
|
|
24
|
+
MCP_TOOLS: 750,
|
|
25
|
+
EXTENSION_TOOLS: 800,
|
|
26
|
+
TOOL_CORE_RULES: 1000,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Agent 配置常量
|
|
31
|
+
* 统一管理配置参数,避免魔法数字
|
|
32
|
+
*/
|
|
33
|
+
const AGENT_CONFIG = {
|
|
34
|
+
// AI 模型配置
|
|
35
|
+
MAX_OUTPUT_TOKENS: 8192,
|
|
36
|
+
TEMPERATURE: 0.3,
|
|
37
|
+
// 通知数量限制
|
|
38
|
+
MAX_NOTIFICATIONS: 5,
|
|
39
|
+
// 元数据提取配置
|
|
40
|
+
CAPABILITY_MAX_LENGTH: 50,
|
|
41
|
+
CAPABILITY_MAX_PARTS: 3,
|
|
42
|
+
// 错误重试配置
|
|
43
|
+
MAX_RETRIES: 3,
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* 日志工具函数
|
|
48
|
+
* @param {string} level - 日志级别
|
|
49
|
+
* @param {string} context - 上下文信息
|
|
50
|
+
* @param {string} message - 日志消息
|
|
51
|
+
* @param {any} data - 附加数据
|
|
52
|
+
*/
|
|
53
|
+
function log(level, context, message, data = null) {
|
|
54
|
+
const timestamp = new Date().toISOString();
|
|
55
|
+
const prefix = `[${timestamp}] [${level}] [${context}]`;
|
|
56
|
+
if (data !== null) {
|
|
57
|
+
console.log(`${prefix} ${message}`, data);
|
|
58
|
+
} else {
|
|
59
|
+
console.log(`${prefix} ${message}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const logger = {
|
|
64
|
+
info: (context, message, data) => log('INFO', context, message, data),
|
|
65
|
+
warn: (context, message, data) => log('WARN', context, message, data),
|
|
66
|
+
error: (context, message, data) => log('ERROR', context, message, data),
|
|
67
|
+
debug: (context, message, data) => log('DEBUG', context, message, data),
|
|
68
|
+
};
|
|
69
|
+
|
|
13
70
|
class Agent extends EventEmitter {
|
|
14
71
|
/**
|
|
15
72
|
* @param {Framework} framework - 框架实例
|
|
@@ -32,8 +89,9 @@ class Agent extends EventEmitter {
|
|
|
32
89
|
this.baseURL = config.baseURL;
|
|
33
90
|
this.provider = config.provider || 'deepseek';
|
|
34
91
|
this.providerOptions = config.providerOptions || {};
|
|
35
|
-
|
|
36
|
-
this.providerOptions.
|
|
92
|
+
// 使用常量替代硬编码数字
|
|
93
|
+
this.providerOptions.maxOutputTokens = AGENT_CONFIG.MAX_OUTPUT_TOKENS;
|
|
94
|
+
this.providerOptions.temperature = AGENT_CONFIG.TEMPERATURE;
|
|
37
95
|
// 原始 system prompt
|
|
38
96
|
this._originalPrompt =
|
|
39
97
|
config.systemPrompt ||
|
|
@@ -62,6 +120,8 @@ class Agent extends EventEmitter {
|
|
|
62
120
|
|
|
63
121
|
// 初始化聊天处理器
|
|
64
122
|
this._initChatHandler();
|
|
123
|
+
|
|
124
|
+
// logger.info('Agent', `Agent "${this.name}" 初始化完成`);
|
|
65
125
|
}
|
|
66
126
|
|
|
67
127
|
/**
|
|
@@ -69,19 +129,23 @@ class Agent extends EventEmitter {
|
|
|
69
129
|
* @private
|
|
70
130
|
*/
|
|
71
131
|
_registerDefaultPromptParts() {
|
|
72
|
-
// 1. 原始 system prompt
|
|
73
|
-
this._systemPromptBuilder.register(
|
|
132
|
+
// 1. 原始 system prompt
|
|
133
|
+
this._systemPromptBuilder.register(
|
|
134
|
+
'original-prompt',
|
|
135
|
+
PROMPT_PRIORITY.ORIGINAL_PROMPT,
|
|
136
|
+
() => this._originalPrompt
|
|
137
|
+
);
|
|
74
138
|
|
|
75
|
-
// 2. 共享提示模板
|
|
76
|
-
this._systemPromptBuilder.register('shared-prompt',
|
|
139
|
+
// 2. 共享提示模板
|
|
140
|
+
this._systemPromptBuilder.register('shared-prompt', PROMPT_PRIORITY.SHARED_PROMPT, () => {
|
|
77
141
|
if (this._sharedPrompt) {
|
|
78
142
|
return this._replacePlaceholders(this._sharedPrompt);
|
|
79
143
|
}
|
|
80
144
|
return null;
|
|
81
145
|
});
|
|
82
146
|
|
|
83
|
-
// 3. 元数据
|
|
84
|
-
this._systemPromptBuilder.register('metadata',
|
|
147
|
+
// 3. 元数据
|
|
148
|
+
this._systemPromptBuilder.register('metadata', PROMPT_PRIORITY.METADATA, () => {
|
|
85
149
|
if (this._metadata.size === 0) {
|
|
86
150
|
return null;
|
|
87
151
|
}
|
|
@@ -97,26 +161,34 @@ class Agent extends EventEmitter {
|
|
|
97
161
|
});
|
|
98
162
|
|
|
99
163
|
// 4. 工具列表 (优先级 400)
|
|
100
|
-
//this._systemPromptBuilder.register('tools',
|
|
164
|
+
//this._systemPromptBuilder.register('tools', PROMPT_PRIORITY.TOOLS, () => this._buildToolsDescription());
|
|
101
165
|
|
|
102
|
-
// 5. 技能列表
|
|
103
|
-
this._systemPromptBuilder.register('skills',
|
|
166
|
+
// 5. 技能列表
|
|
167
|
+
this._systemPromptBuilder.register('skills', PROMPT_PRIORITY.SKILLS, () =>
|
|
168
|
+
this._buildSkillsDescription()
|
|
169
|
+
);
|
|
104
170
|
|
|
105
|
-
// 6. 子Agent列表
|
|
106
|
-
this._systemPromptBuilder.register('subagents',
|
|
171
|
+
// 6. 子Agent列表
|
|
172
|
+
this._systemPromptBuilder.register('subagents', PROMPT_PRIORITY.SUB_AGENTS, () =>
|
|
173
|
+
this._buildSubAgentsDescription()
|
|
174
|
+
);
|
|
107
175
|
|
|
108
|
-
// 7. 系统能力
|
|
109
|
-
this._systemPromptBuilder.register('capabilities',
|
|
176
|
+
// 7. 系统能力
|
|
177
|
+
this._systemPromptBuilder.register('capabilities', PROMPT_PRIORITY.CAPABILITIES, () =>
|
|
110
178
|
this._buildCapabilitiesDescription()
|
|
111
179
|
);
|
|
112
|
-
// 8. MCP 工具列表
|
|
113
|
-
this._systemPromptBuilder.register('mcp-tools',
|
|
114
|
-
|
|
115
|
-
|
|
180
|
+
// 8. MCP 工具列表
|
|
181
|
+
this._systemPromptBuilder.register('mcp-tools', PROMPT_PRIORITY.MCP_TOOLS, () =>
|
|
182
|
+
this._buildMcpToolsDescription()
|
|
183
|
+
);
|
|
184
|
+
// 9. 扩展工具列表
|
|
185
|
+
this._systemPromptBuilder.register('extension-tools', PROMPT_PRIORITY.EXTENSION_TOOLS, () =>
|
|
116
186
|
this._buildExtensionToolsDescription()
|
|
117
187
|
);
|
|
118
|
-
// 10. 工具调用核心规则
|
|
119
|
-
this._systemPromptBuilder.register('tool-core-rules',
|
|
188
|
+
// 10. 工具调用核心规则
|
|
189
|
+
this._systemPromptBuilder.register('tool-core-rules', PROMPT_PRIORITY.TOOL_CORE_RULES, () =>
|
|
190
|
+
this._getToolCoreRules()
|
|
191
|
+
);
|
|
120
192
|
}
|
|
121
193
|
|
|
122
194
|
/**
|
|
@@ -182,12 +254,13 @@ class Agent extends EventEmitter {
|
|
|
182
254
|
return '';
|
|
183
255
|
}
|
|
184
256
|
|
|
185
|
-
|
|
257
|
+
// 使用数组收集 + join 优化字符串拼接
|
|
258
|
+
const lines = ['## 可用工具', ''];
|
|
186
259
|
for (const { name, tool } of directTools) {
|
|
187
|
-
|
|
260
|
+
lines.push(`- **${name}**: ${tool.description || '无描述'}`);
|
|
188
261
|
}
|
|
189
262
|
|
|
190
|
-
return
|
|
263
|
+
return lines.join('\n');
|
|
191
264
|
}
|
|
192
265
|
|
|
193
266
|
/**
|
|
@@ -204,15 +277,19 @@ class Agent extends EventEmitter {
|
|
|
204
277
|
return '';
|
|
205
278
|
}
|
|
206
279
|
|
|
207
|
-
|
|
280
|
+
// 使用数组收集 + join 优化字符串拼接
|
|
281
|
+
const lines = ['【可用技能】'];
|
|
208
282
|
for (const skill of skills) {
|
|
209
283
|
const name = skill.metadata?.name || skill.name || 'unknown';
|
|
210
284
|
const descText = skill.metadata?.description || '';
|
|
211
|
-
|
|
285
|
+
lines.push(`- ${name}: ${descText}`);
|
|
212
286
|
}
|
|
213
|
-
|
|
214
|
-
'
|
|
215
|
-
|
|
287
|
+
lines.push(
|
|
288
|
+
'',
|
|
289
|
+
'重要:当需要开发插件、执行专业任务时,必须先使用 loadSkill 工具加载对应技能,获取专业指导。'
|
|
290
|
+
);
|
|
291
|
+
|
|
292
|
+
return lines.join('\n');
|
|
216
293
|
}
|
|
217
294
|
|
|
218
295
|
/**
|
|
@@ -235,16 +312,21 @@ class Agent extends EventEmitter {
|
|
|
235
312
|
return '';
|
|
236
313
|
}
|
|
237
314
|
|
|
238
|
-
|
|
239
|
-
|
|
315
|
+
// 使用数组收集 + join 优化字符串拼接
|
|
316
|
+
const lines = ['【系统能力】'];
|
|
317
|
+
keyPlugins.forEach((plugin, index) => {
|
|
240
318
|
const name = plugin.instance?.name || plugin.name || 'unknown';
|
|
241
319
|
const description = plugin.instance?.description || '无描述';
|
|
242
|
-
|
|
320
|
+
lines.push(`${index + 1}. ${name}: ${description}`);
|
|
243
321
|
});
|
|
244
322
|
|
|
245
|
-
return
|
|
323
|
+
return lines.join('\n');
|
|
246
324
|
}
|
|
247
325
|
|
|
326
|
+
/**
|
|
327
|
+
* 构建扩展工具描述
|
|
328
|
+
* 使用 zodSchemaToMarkdown 解析参数,让 LLM 更易理解工具用法
|
|
329
|
+
*/
|
|
248
330
|
_buildExtensionToolsDescription() {
|
|
249
331
|
const extensionExecutor = this.framework.pluginManager.get('extension-executor');
|
|
250
332
|
if (!extensionExecutor) {
|
|
@@ -256,31 +338,113 @@ class Agent extends EventEmitter {
|
|
|
256
338
|
return '';
|
|
257
339
|
}
|
|
258
340
|
|
|
259
|
-
|
|
260
|
-
|
|
341
|
+
const sections = [
|
|
342
|
+
'## 【Extensions 扩展工具】',
|
|
343
|
+
'',
|
|
344
|
+
'你可以通过 `ext_call` 工具调用以下扩展插件的功能。',
|
|
345
|
+
'',
|
|
346
|
+
'**重要调用规则:**',
|
|
347
|
+
'1. 调用前必须指定 `plugin`(插件名)和 `tool`(工具名)',
|
|
348
|
+
'2. 参数通过 `args` 对象传入,参数名和类型见各工具说明',
|
|
349
|
+
'3. 必填参数(Required)必须提供,可选参数(Optional)可省略',
|
|
350
|
+
'',
|
|
351
|
+
'---',
|
|
352
|
+
'',
|
|
353
|
+
];
|
|
261
354
|
|
|
262
355
|
for (const ext of extensions) {
|
|
263
|
-
|
|
264
|
-
|
|
356
|
+
sections.push(`### ${ext.name}`, '');
|
|
357
|
+
sections.push(ext.description || '无描述', '');
|
|
358
|
+
|
|
265
359
|
for (const tool of ext.tools) {
|
|
266
|
-
|
|
267
|
-
|
|
360
|
+
sections.push(`#### ${tool.name}`, '');
|
|
361
|
+
sections.push(tool.description || '无描述', '');
|
|
362
|
+
|
|
363
|
+
// 使用 zodSchemaToMarkdown 解析参数
|
|
268
364
|
if (tool.inputSchema) {
|
|
269
365
|
try {
|
|
270
|
-
|
|
271
|
-
|
|
366
|
+
const schemaMarkdown = zodSchemaToTable(tool.inputSchema);
|
|
367
|
+
sections.push('**参数:**', ' ');
|
|
368
|
+
sections.push(schemaMarkdown || '无', ' ');
|
|
272
369
|
} catch (e) {
|
|
273
|
-
|
|
370
|
+
logger.warn('Agent', `转换工具 ${tool.name} 的参数描述失败`, e.message);
|
|
371
|
+
// 降级处理:手动解析常见 Zod 类型
|
|
372
|
+
sections.push('**参数:**', ' ');
|
|
373
|
+
sections.push(this._fallbackSchemaToText(tool.inputSchema), ' ');
|
|
274
374
|
}
|
|
275
375
|
}
|
|
376
|
+
|
|
377
|
+
sections.push('');
|
|
276
378
|
}
|
|
277
|
-
desc += '\n';
|
|
278
379
|
}
|
|
279
380
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
381
|
+
sections.push(
|
|
382
|
+
'---',
|
|
383
|
+
'',
|
|
384
|
+
'## 调用示例',
|
|
385
|
+
'',
|
|
386
|
+
'**格式:**',
|
|
387
|
+
'```',
|
|
388
|
+
'ext_call({ plugin: "插件名", tool: "工具名", args: {参数} })',
|
|
389
|
+
'```',
|
|
390
|
+
'',
|
|
391
|
+
'**示例 - 获取余额:**',
|
|
392
|
+
'```',
|
|
393
|
+
'ext_call({ plugin: "gate-trading", tool: "gate_get_account_balance", args: {} })',
|
|
394
|
+
'```',
|
|
395
|
+
'',
|
|
396
|
+
'**示例 - HTTP 请求:**',
|
|
397
|
+
'```',
|
|
398
|
+
'ext_call({ plugin: "web", tool: "web_request", args: { method: "GET", path: "/api/data" } })',
|
|
399
|
+
'```'
|
|
400
|
+
);
|
|
401
|
+
|
|
402
|
+
return sections.join('\n').trim();
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* 降级处理:当 zodSchemaToMarkdown 解析失败时的备用方案
|
|
407
|
+
* @param {Object} schema - Zod schema 对象
|
|
408
|
+
* @returns {string} 参数描述文本
|
|
409
|
+
*/
|
|
410
|
+
_fallbackSchemaToText(schema) {
|
|
411
|
+
if (!schema || !schema.shape) {
|
|
412
|
+
return '- (参数描述不可用)';
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
const lines = [];
|
|
416
|
+
for (const [name, field] of Object.entries(schema.shape)) {
|
|
417
|
+
const type = this._inferZodType(field);
|
|
418
|
+
const desc = field.description || field._def?.description || '';
|
|
419
|
+
const isOptional = type.includes('optional') ? '(可选)' : '(必填)';
|
|
420
|
+
lines.push(`- ${name} (${type}) ${isOptional}${desc ? `: ${desc}` : ''}`);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
return lines.join('\n') || '- (参数描述不可用)';
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* 从 Zod schema 推断类型名称
|
|
428
|
+
* @param {Object} field - Zod schema 字段
|
|
429
|
+
* @returns {string} 类型名称
|
|
430
|
+
*/
|
|
431
|
+
_inferZodType(field) {
|
|
432
|
+
const typeName = field._def?.typeName || field.constructor?.name || '';
|
|
433
|
+
|
|
434
|
+
const typeMap = {
|
|
435
|
+
ZodString: 'string',
|
|
436
|
+
ZodNumber: 'number',
|
|
437
|
+
ZodBoolean: 'boolean',
|
|
438
|
+
ZodArray: 'array',
|
|
439
|
+
ZodObject: 'object',
|
|
440
|
+
ZodOptional: 'optional',
|
|
441
|
+
ZodDefault: 'any',
|
|
442
|
+
ZodEnum: 'enum',
|
|
443
|
+
ZodUnion: 'union',
|
|
444
|
+
ZodRecord: 'record',
|
|
445
|
+
};
|
|
446
|
+
|
|
447
|
+
return typeMap[typeName] || typeName.replace('Zod', '').toLowerCase() || 'any';
|
|
284
448
|
}
|
|
285
449
|
|
|
286
450
|
_buildMcpToolsDescription() {
|
|
@@ -293,6 +457,7 @@ class Agent extends EventEmitter {
|
|
|
293
457
|
|
|
294
458
|
/**
|
|
295
459
|
* 构建子Agent描述
|
|
460
|
+
* 使用数组收集 + join 模式优化字符串拼接
|
|
296
461
|
* 动态从配置文件读取每个子Agent的专业领域
|
|
297
462
|
*/
|
|
298
463
|
_buildSubAgentsDescription() {
|
|
@@ -305,7 +470,8 @@ class Agent extends EventEmitter {
|
|
|
305
470
|
return '';
|
|
306
471
|
}
|
|
307
472
|
|
|
308
|
-
|
|
473
|
+
// 使用数组收集 + join 模式优化字符串拼接
|
|
474
|
+
const lines = ['【子 Agent 匹配表 - 优先使用】'];
|
|
309
475
|
|
|
310
476
|
// 动态从配置文件读取每个子Agent的核心能力
|
|
311
477
|
for (const plugin of allSubAgents) {
|
|
@@ -322,30 +488,32 @@ class Agent extends EventEmitter {
|
|
|
322
488
|
if (skills && skills.length > 0) {
|
|
323
489
|
info += ` (技能: ${skills.join(', ')})`;
|
|
324
490
|
}
|
|
325
|
-
|
|
491
|
+
lines.push(` - ${name}: ${info}`);
|
|
326
492
|
} else {
|
|
327
493
|
// 回退到旧逻辑
|
|
328
|
-
|
|
494
|
+
lines.push(` - ${name}: ${role || goal || '子代理'}`);
|
|
329
495
|
}
|
|
330
496
|
}
|
|
331
497
|
|
|
332
498
|
// 通用规则
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
499
|
+
lines.push('');
|
|
500
|
+
lines.push('【子Agent匹配规则 - 必须遵守】');
|
|
501
|
+
lines.push(' - 根据上述【子 Agent 匹配表】,将任务委托给最匹配的子Agent处理');
|
|
502
|
+
lines.push(' - 使用 subagent_call 工具并指定 agentName 来委托任务');
|
|
503
|
+
lines.push(' - 只有当没有匹配的子Agent时,才直接调用工具');
|
|
337
504
|
|
|
338
|
-
return
|
|
505
|
+
return lines.join('\n').trim();
|
|
339
506
|
}
|
|
340
507
|
|
|
341
508
|
/**
|
|
342
509
|
* 从配置文件动态读取子Agent的核心能力
|
|
343
510
|
* 支持 .json 和 .md 格式
|
|
344
511
|
* @private
|
|
512
|
+
* @returns {Promise<string|null>}
|
|
345
513
|
*/
|
|
346
|
-
_getSubAgentCapabilities(name) {
|
|
514
|
+
async _getSubAgentCapabilities(name) {
|
|
347
515
|
try {
|
|
348
|
-
const fs = require('fs');
|
|
516
|
+
const fs = require('fs').promises;
|
|
349
517
|
const path = require('path');
|
|
350
518
|
const agentsDir = path.join(process.cwd(), '.agent', 'agents');
|
|
351
519
|
|
|
@@ -357,7 +525,12 @@ class Agent extends EventEmitter {
|
|
|
357
525
|
|
|
358
526
|
let filePath = null;
|
|
359
527
|
for (const p of possiblePaths) {
|
|
360
|
-
if (
|
|
528
|
+
if (
|
|
529
|
+
await fs
|
|
530
|
+
.access(p)
|
|
531
|
+
.then(() => true)
|
|
532
|
+
.catch(() => false)
|
|
533
|
+
) {
|
|
361
534
|
filePath = p;
|
|
362
535
|
break;
|
|
363
536
|
}
|
|
@@ -367,7 +540,7 @@ class Agent extends EventEmitter {
|
|
|
367
540
|
return null;
|
|
368
541
|
}
|
|
369
542
|
|
|
370
|
-
const content = fs.
|
|
543
|
+
const content = await fs.readFile(filePath, 'utf-8');
|
|
371
544
|
|
|
372
545
|
// .json 格式
|
|
373
546
|
if (filePath.endsWith('.json')) {
|
|
@@ -382,6 +555,7 @@ class Agent extends EventEmitter {
|
|
|
382
555
|
|
|
383
556
|
return null;
|
|
384
557
|
} catch (e) {
|
|
558
|
+
logger.warn('Agent', `读取子Agent配置 ${name} 失败`, e.message);
|
|
385
559
|
return null;
|
|
386
560
|
}
|
|
387
561
|
}
|
|
@@ -397,7 +571,7 @@ class Agent extends EventEmitter {
|
|
|
397
571
|
.split('\n')
|
|
398
572
|
.map((line) => line.replace(/^[·\-*]\s*/, '').trim())
|
|
399
573
|
.filter((line) => line && !line.startsWith('你是一个'))
|
|
400
|
-
.slice(0,
|
|
574
|
+
.slice(0, AGENT_CONFIG.CAPABILITY_MAX_PARTS)
|
|
401
575
|
.join('、');
|
|
402
576
|
return capabilities || config.description;
|
|
403
577
|
}
|
|
@@ -442,13 +616,13 @@ class Agent extends EventEmitter {
|
|
|
442
616
|
const parts = desc.split(/[,,、]/).map((s) => s.trim());
|
|
443
617
|
// 取第一部分(通常是最核心的能力描述)
|
|
444
618
|
const firstPart = parts[0];
|
|
445
|
-
//
|
|
446
|
-
if (firstPart.length >
|
|
447
|
-
return firstPart.substring(0,
|
|
619
|
+
// 如果第一部分太长(说明是句子),取前指定长度字符
|
|
620
|
+
if (firstPart.length > AGENT_CONFIG.CAPABILITY_MAX_LENGTH) {
|
|
621
|
+
return firstPart.substring(0, AGENT_CONFIG.CAPABILITY_MAX_LENGTH).trim() + '...';
|
|
448
622
|
}
|
|
449
|
-
//
|
|
623
|
+
// 如果有多个部分,取前指定数量
|
|
450
624
|
if (parts.length > 1) {
|
|
451
|
-
return parts.slice(0,
|
|
625
|
+
return parts.slice(0, AGENT_CONFIG.CAPABILITY_MAX_PARTS).join('、');
|
|
452
626
|
}
|
|
453
627
|
return firstPart;
|
|
454
628
|
}
|
|
@@ -673,7 +847,8 @@ class Agent extends EventEmitter {
|
|
|
673
847
|
if (scheduler && scheduler.instance && scheduler.instance.getPendingNotifications) {
|
|
674
848
|
const results = scheduler.instance.getPendingNotifications();
|
|
675
849
|
if (results.length > 0) {
|
|
676
|
-
|
|
850
|
+
// 使用常量替代硬编码数字
|
|
851
|
+
const notifications = results.slice(-AGENT_CONFIG.MAX_NOTIFICATIONS).reverse();
|
|
677
852
|
// 清除已发送的通知
|
|
678
853
|
if (scheduler.instance.clearDeliveredNotifications) {
|
|
679
854
|
scheduler.instance.clearDeliveredNotifications(notifications.length);
|
|
@@ -682,7 +857,7 @@ class Agent extends EventEmitter {
|
|
|
682
857
|
}
|
|
683
858
|
}
|
|
684
859
|
} catch (err) {
|
|
685
|
-
|
|
860
|
+
logger.warn('Agent', '获取调度通知失败', err.message);
|
|
686
861
|
}
|
|
687
862
|
return [];
|
|
688
863
|
}
|
|
@@ -696,11 +871,12 @@ class Agent extends EventEmitter {
|
|
|
696
871
|
if (think && think.instance && think.instance.getPendingThoughts) {
|
|
697
872
|
const thoughts = think.instance.getPendingThoughts();
|
|
698
873
|
if (thoughts.length > 0) {
|
|
699
|
-
|
|
874
|
+
// 使用常量替代硬编码数字
|
|
875
|
+
return thoughts.slice(-AGENT_CONFIG.MAX_NOTIFICATIONS).reverse();
|
|
700
876
|
}
|
|
701
877
|
}
|
|
702
878
|
} catch (err) {
|
|
703
|
-
|
|
879
|
+
logger.warn('Agent', '获取思考通知失败', err.message);
|
|
704
880
|
}
|
|
705
881
|
return [];
|
|
706
882
|
}
|
|
@@ -760,6 +936,7 @@ class Agent extends EventEmitter {
|
|
|
760
936
|
return result;
|
|
761
937
|
} catch (err) {
|
|
762
938
|
this._status = 'error';
|
|
939
|
+
logger.error('Agent', `chat 方法执行失败: ${err.message}`, { stack: err.stack });
|
|
763
940
|
this.emit('status', { status: 'error', error: err.message });
|
|
764
941
|
throw err;
|
|
765
942
|
}
|
|
@@ -815,6 +992,7 @@ class Agent extends EventEmitter {
|
|
|
815
992
|
this.emit('status', { status: 'idle' });
|
|
816
993
|
} catch (err) {
|
|
817
994
|
this._status = 'error';
|
|
995
|
+
logger.error('Agent', `chatStream 方法执行失败: ${err.message}`, { stack: err.stack });
|
|
818
996
|
this.emit('status', { status: 'error', error: err.message });
|
|
819
997
|
|
|
820
998
|
throw err;
|
|
@@ -879,6 +1057,14 @@ class Agent extends EventEmitter {
|
|
|
879
1057
|
return this._status;
|
|
880
1058
|
}
|
|
881
1059
|
|
|
1060
|
+
/**
|
|
1061
|
+
* 获取Agent ID
|
|
1062
|
+
* @returns {string} Agent名称
|
|
1063
|
+
*/
|
|
1064
|
+
getCurrentAgentId() {
|
|
1065
|
+
return this.name;
|
|
1066
|
+
}
|
|
1067
|
+
|
|
882
1068
|
/**
|
|
883
1069
|
* 重置状态(从卡住状态恢复)
|
|
884
1070
|
*/
|
|
@@ -898,6 +1084,7 @@ class Agent extends EventEmitter {
|
|
|
898
1084
|
this._tools.clear();
|
|
899
1085
|
this.removeAllListeners();
|
|
900
1086
|
this.emit('destroyed');
|
|
1087
|
+
logger.info('Agent', `Agent "${this.name}" 已销毁`);
|
|
901
1088
|
}
|
|
902
1089
|
}
|
|
903
1090
|
|