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.
Files changed (69) hide show
  1. package/.agent/agents/code-assistant.json +4 -1
  2. package/.agent/agents/file-assistant.json +4 -1
  3. package/.agent/agents/orchestrator-demo.md +53 -0
  4. package/.agent/agents/orchestrator.json +7 -0
  5. package/.agent/data/plugins-state.json +4 -0
  6. package/.agent/mcp_config.json +6 -0
  7. package/.agent/memory/feedback/mnrsiuoc-e1ru74.md +9 -0
  8. package/.agent/memory/feedback/mnrt2mmz-98az6n.md +9 -0
  9. package/.agent/memory/feedback/mnrtqrhm-kxsicz.md +9 -0
  10. package/.agent/memory/feedback/mnrts8vg-i0ngzp.md +15 -0
  11. package/.agent/memory/feedback/mnrtt7jt-c0trb2.md +9 -0
  12. package/.agent/memory/feedback/mnruc2f0-5s52la.md +16 -0
  13. package/.agent/memory/feedback/mnrumbmx-63sa0v.md +9 -0
  14. package/.agent/memory/project/mnrp7p5n-8enm2a.md +31 -0
  15. package/.agent/memory/project/mnrp9ifb-yynks0.md +40 -0
  16. package/.agent/memory/project/mnrpb3b8-f617s4.md +25 -0
  17. package/.agent/memory/project/mnrrmqgg-focprv.md +9 -0
  18. package/.agent/memory/project/mnrtykbh-6atsor.md +9 -0
  19. package/.agent/memory/project/mnru9jiu-kgau16.md +35 -0
  20. package/.agent/memory/reference/mnrnvpwo-rcqv9m.md +52 -0
  21. package/.agent/memory/reference/mnrovxvz-zy9xqm.md +25 -0
  22. package/.agent/memory/reference/mnroxabj-1b3930.md +68 -0
  23. package/.agent/memory/reference/mnrpjtlp-mnb9od.md +35 -0
  24. package/.agent/memory/reference/mnrps1x3-6b8xfm.md +28 -0
  25. package/.agent/memory/reference/mnrpt9ov-15er5w.md +22 -0
  26. package/.agent/memory/reference/mnrq82dn-y9tv9e.md +50 -0
  27. package/.agent/memory/reference/mnrqnr5v-v75drf.md +34 -0
  28. package/.agent/memory/reference/mnrrfzys-urudaf.md +31 -0
  29. package/.agent/memory/reference/mnrrocha-t0027n.md +21 -0
  30. package/.agent/memory/reference/mnrukklc-bxndsb.md +35 -0
  31. package/.agent/memory/user/mnrt39t8-8eosy0.md +9 -0
  32. package/.agent/plugins/marknative/fonts.zip +0 -0
  33. package/.agent/sessions/cli_default.json +4493 -1183
  34. package/.agent/test-agent.js +35 -0
  35. package/cli/src/commands/chat.js +69 -1
  36. package/cli/src/index.js +11 -2
  37. package/foliko-cloud-rising.png +0 -0
  38. package/foliko-dawn-of-ai.png +0 -0
  39. package/foliko-mindful-observation.png +0 -0
  40. package/foliko-stellar-dreams.png +0 -0
  41. package/foliko-zen-jing.png +0 -0
  42. package/foliko-zen-kong.png +0 -0
  43. package/foliko-zen-wu.png +0 -0
  44. package/package.json +2 -2
  45. package/plugins/coordinator-plugin.js +282 -0
  46. package/plugins/default-plugins.js +1 -1
  47. package/plugins/extension-executor-plugin.js +27 -1
  48. package/plugins/memory-plugin.js +228 -57
  49. package/src/core/agent-chat.js +206 -115
  50. package/src/core/agent.js +258 -71
  51. package/src/core/coordinator-manager.js +341 -0
  52. package/src/core/framework.js +50 -0
  53. package/src/core/plugin-base.js +30 -17
  54. package/src/core/sub-agent-config.js +8 -1
  55. package/src/core/worker-agent.js +176 -0
  56. package/src/executors/mcp-executor.js +4 -4
  57. package/zen_karesansui.png +0 -0
  58. package/.agent/plugins/marknative/update-readme.js +0 -134
  59. package/output/emoji-segoe-test-v2.png +0 -0
  60. package/output/emoji-segoe-test.png +0 -0
  61. package/output/emoji-test.png +0 -0
  62. package/output/emoji-windows-test.png +0 -0
  63. package/output/foliko-emoji-poster.png +0 -0
  64. package/output/foliko-muji-poster-final.png +0 -0
  65. package/output/foliko-muji-poster-v2.png +0 -0
  66. package/output/foliko-muji-poster.png +0 -0
  67. package/output/foliko-share.png +0 -0
  68. package/output/progress-circle-test.png +0 -0
  69. 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 { zodSchemaToMarkdown } = require('@chnak/zod-to-markdown');
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
- this.providerOptions.maxOutputTokens = 8192;
36
- this.providerOptions.temperature = 0.3; // 降低 temperature 减少生成错误 JSON 的概率
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 (优先级 100)
73
- this._systemPromptBuilder.register('original-prompt', 100, () => this._originalPrompt);
132
+ // 1. 原始 system prompt
133
+ this._systemPromptBuilder.register(
134
+ 'original-prompt',
135
+ PROMPT_PRIORITY.ORIGINAL_PROMPT,
136
+ () => this._originalPrompt
137
+ );
74
138
 
75
- // 2. 共享提示模板 (优先级 200)
76
- this._systemPromptBuilder.register('shared-prompt', 200, () => {
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. 元数据 (优先级 300)
84
- this._systemPromptBuilder.register('metadata', 300, () => {
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', 400, () => this._buildToolsDescription());
164
+ //this._systemPromptBuilder.register('tools', PROMPT_PRIORITY.TOOLS, () => this._buildToolsDescription());
101
165
 
102
- // 5. 技能列表 (优先级 500)
103
- this._systemPromptBuilder.register('skills', 500, () => this._buildSkillsDescription());
166
+ // 5. 技能列表
167
+ this._systemPromptBuilder.register('skills', PROMPT_PRIORITY.SKILLS, () =>
168
+ this._buildSkillsDescription()
169
+ );
104
170
 
105
- // 6. 子Agent列表 (优先级 600)
106
- this._systemPromptBuilder.register('subagents', 600, () => this._buildSubAgentsDescription());
171
+ // 6. 子Agent列表
172
+ this._systemPromptBuilder.register('subagents', PROMPT_PRIORITY.SUB_AGENTS, () =>
173
+ this._buildSubAgentsDescription()
174
+ );
107
175
 
108
- // 7. 系统能力 (优先级 700)
109
- this._systemPromptBuilder.register('capabilities', 700, () =>
176
+ // 7. 系统能力
177
+ this._systemPromptBuilder.register('capabilities', PROMPT_PRIORITY.CAPABILITIES, () =>
110
178
  this._buildCapabilitiesDescription()
111
179
  );
112
- // 8. MCP 工具列表 (优先级 750)
113
- this._systemPromptBuilder.register('mcp-tools', 750, () => this._buildMcpToolsDescription());
114
- // 9. 扩展工具列表 (优先级 800)
115
- this._systemPromptBuilder.register('extension-tools', 800, () =>
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. 工具调用核心规则 (优先级 1000)
119
- this._systemPromptBuilder.register('tool-core-rules', 1000, () => this._getToolCoreRules());
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
- let desc = '## 可用工具\n\n';
257
+ // 使用数组收集 + join 优化字符串拼接
258
+ const lines = ['## 可用工具', ''];
186
259
  for (const { name, tool } of directTools) {
187
- desc += `- **${name}**: ${tool.description || '无描述'}\n`;
260
+ lines.push(`- **${name}**: ${tool.description || '无描述'}`);
188
261
  }
189
262
 
190
- return desc.trim();
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
- let desc = '【可用技能】\n';
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
- desc += `- ${name}: ${descText}\n`;
285
+ lines.push(`- ${name}: ${descText}`);
212
286
  }
213
- desc +=
214
- '\n重要:当需要开发插件、执行专业任务时,必须先使用 loadSkill 工具加载对应技能,获取专业指导。';
215
- return desc.trim();
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
- let desc = '【系统能力】\n';
239
- keyPlugins.map((plugin, index) => {
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
- desc += `${index + 1}. ${name}: ${description}\n`;
320
+ lines.push(`${index + 1}. ${name}: ${description}`);
243
321
  });
244
322
 
245
- return desc.trim();
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
- let desc = '【Extensions 扩展工具】\n\n';
260
- desc += '你可以通过 `ext_call` 工具调用以下扩展插件的功能。\n\n';
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
- desc += `### ${ext.name}\n\n`;
264
- desc += `${ext.description || ''}\n\n`;
356
+ sections.push(`### ${ext.name}`, '');
357
+ sections.push(ext.description || '无描述', '');
358
+
265
359
  for (const tool of ext.tools) {
266
- desc += `- **${tool.name}**: ${tool.description || '无描述'}\n`;
267
- // 添加参数描述
360
+ sections.push(`#### ${tool.name}`, '');
361
+ sections.push(tool.description || '无描述', '');
362
+
363
+ // 使用 zodSchemaToMarkdown 解析参数
268
364
  if (tool.inputSchema) {
269
365
  try {
270
- desc += `**参数:**\n\n`;
271
- desc += zodSchemaToMarkdown(tool.inputSchema) + '\n\n';
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
- desc += '**调用格式:**\n';
281
- desc += '```\next_call({ plugin: "插件名", tool: "工具名", args: {参数} })\n';
282
- desc += '```\n';
283
- return desc.trim();
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
- let desc = '【子 Agent 匹配表 - 优先使用】\n';
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
- desc += ` - ${name}: ${info}\n`;
491
+ lines.push(` - ${name}: ${info}`);
326
492
  } else {
327
493
  // 回退到旧逻辑
328
- desc += ` - ${name}: ${role || goal || '子代理'}\n`;
494
+ lines.push(` - ${name}: ${role || goal || '子代理'}`);
329
495
  }
330
496
  }
331
497
 
332
498
  // 通用规则
333
- desc += '\n【子Agent匹配规则 - 必须遵守】\n';
334
- desc += ' - 根据上述【子 Agent 匹配表】,将任务委托给最匹配的子Agent处理\n';
335
- desc += ' - 使用 subagent_call 工具并指定 agentName 来委托任务\n';
336
- desc += ' - 只有当没有匹配的子Agent时,才直接调用工具\n';
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 desc.trim();
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 (fs.existsSync(p)) {
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.readFileSync(filePath, 'utf-8');
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, 4)
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
- // 如果第一部分太长(说明是句子),取前50个字符
446
- if (firstPart.length > 50) {
447
- return firstPart.substring(0, 50).trim() + '...';
619
+ // 如果第一部分太长(说明是句子),取前指定长度字符
620
+ if (firstPart.length > AGENT_CONFIG.CAPABILITY_MAX_LENGTH) {
621
+ return firstPart.substring(0, AGENT_CONFIG.CAPABILITY_MAX_LENGTH).trim() + '...';
448
622
  }
449
- // 如果有多个部分,取前3个
623
+ // 如果有多个部分,取前指定数量
450
624
  if (parts.length > 1) {
451
- return parts.slice(0, 3).join('、');
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
- const notifications = results.slice(-5).reverse(); // 最多5条,最新的在前
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
- return thoughts.slice(-5).reverse(); // 最多5条,最新的在前
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