foliko 1.0.53 → 1.0.55
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/.claude/settings.local.json +141 -131
- package/CLAUDE.md +106 -0
- package/Dockerfile +2 -2
- package/cli/src/index.js +6 -3
- package/cli/src/ui/chat-ui.js +1 -1
- package/examples/ambient-example.js +196 -0
- package/package.json +1 -1
- package/plugins/ambient-agent-plugin.js +1134 -0
- package/plugins/default-plugins.js +38 -32
- package/plugins/email.js +484 -25
- package/plugins/feishu-plugin.js +2 -0
- package/plugins/file-system-plugin.js +57 -1
- package/plugins/python-executor-plugin.js +1 -1
- package/plugins/python-plugin-loader.js +2 -2
- package/plugins/subagent-plugin.js +25 -25
- package/plugins/telegram-plugin.js +3 -0
- package/plugins/weixin-plugin.js +2 -0
- package/src/capabilities/skill-manager.js +230 -2
- package/src/core/agent.js +19 -14
- package/src/core/plugin-manager.js +2 -2
- package/src/core/provider.js +0 -1
|
@@ -135,13 +135,13 @@ class SubAgentPlugin extends Plugin {
|
|
|
135
135
|
|
|
136
136
|
const parentToolNames = parentTools.map(t => t.name)
|
|
137
137
|
const customToolNames = Object.keys(this.config.tools || {})
|
|
138
|
-
console.log(`[SubAgent:${this.config.name}] Created with ${parentToolNames.length} parent tools + ${customToolNames.length} custom tools`)
|
|
139
|
-
if (parentToolNames.length > 0) {
|
|
140
|
-
|
|
141
|
-
}
|
|
142
|
-
if (customToolNames.length > 0) {
|
|
143
|
-
|
|
144
|
-
}
|
|
138
|
+
//console.log(`[SubAgent:${this.config.name}] Created with ${parentToolNames.length} parent tools + ${customToolNames.length} custom tools`)
|
|
139
|
+
// if (parentToolNames.length > 0) {
|
|
140
|
+
// console.log(` Parent tools: ${parentToolNames.join(', ')}`)
|
|
141
|
+
// }
|
|
142
|
+
// if (customToolNames.length > 0) {
|
|
143
|
+
// console.log(` Custom tools: ${customToolNames.join(', ')}`)
|
|
144
|
+
// }
|
|
145
145
|
}
|
|
146
146
|
|
|
147
147
|
/**
|
|
@@ -179,16 +179,16 @@ class SubAgentPlugin extends Plugin {
|
|
|
179
179
|
if (!this.config.parentTools || this.config.parentTools.length === 0) {
|
|
180
180
|
return allTools
|
|
181
181
|
}
|
|
182
|
-
|
|
183
182
|
// 过滤指定工具
|
|
184
183
|
const filtered = []
|
|
185
184
|
for (const toolName of this.config.parentTools) {
|
|
186
185
|
const tool = toolMap.get(toolName)
|
|
187
186
|
if (tool) {
|
|
188
187
|
filtered.push(tool)
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
}
|
|
188
|
+
}
|
|
189
|
+
// else {
|
|
190
|
+
// console.warn(`[SubAgent:${this.config.name}] Parent tool not found: ${toolName}`)
|
|
191
|
+
// }
|
|
192
192
|
}
|
|
193
193
|
|
|
194
194
|
return filtered
|
|
@@ -283,7 +283,7 @@ class SubAgentPlugin extends Plugin {
|
|
|
283
283
|
framework._mainAgent.registerTool(toolDef)
|
|
284
284
|
}
|
|
285
285
|
|
|
286
|
-
console.log(`[SubAgent:${this.config.name}] Delegate tool registered`)
|
|
286
|
+
//console.log(`[SubAgent:${this.config.name}] Delegate tool registered`)
|
|
287
287
|
}
|
|
288
288
|
|
|
289
289
|
/**
|
|
@@ -441,7 +441,7 @@ class SubAgentManagerPlugin extends Plugin {
|
|
|
441
441
|
}
|
|
442
442
|
})
|
|
443
443
|
|
|
444
|
-
console.log('[SubAgentManager] Management tools registered to agent')
|
|
444
|
+
//console.log('[SubAgentManager] Management tools registered to agent')
|
|
445
445
|
}
|
|
446
446
|
|
|
447
447
|
/**
|
|
@@ -504,7 +504,7 @@ class SubAgentManagerPlugin extends Plugin {
|
|
|
504
504
|
}
|
|
505
505
|
})
|
|
506
506
|
|
|
507
|
-
console.log('[SubAgentManager] Management tools registered to framework')
|
|
507
|
+
//console.log('[SubAgentManager] Management tools registered to framework')
|
|
508
508
|
}
|
|
509
509
|
|
|
510
510
|
/**
|
|
@@ -512,14 +512,14 @@ class SubAgentManagerPlugin extends Plugin {
|
|
|
512
512
|
*/
|
|
513
513
|
_loadAgentsFromDir() {
|
|
514
514
|
const agentsDir = this.config.agentsDir
|
|
515
|
-
console.log('[SubAgentManager] _loadAgentsFromDir called, agentsDir:', agentsDir)
|
|
515
|
+
//console.log('[SubAgentManager] _loadAgentsFromDir called, agentsDir:', agentsDir)
|
|
516
516
|
if (!agentsDir || !fs.existsSync(agentsDir)) {
|
|
517
517
|
console.log('[SubAgentManager] agentsDir not found or does not exist')
|
|
518
518
|
return
|
|
519
519
|
}
|
|
520
520
|
|
|
521
521
|
const entries = fs.readdirSync(agentsDir, { withFileTypes: true })
|
|
522
|
-
console.log('[SubAgentManager] Found entries:', entries.length)
|
|
522
|
+
//console.log('[SubAgentManager] Found entries:', entries.length)
|
|
523
523
|
|
|
524
524
|
for (const entry of entries) {
|
|
525
525
|
if (entry.isFile() && (entry.name.endsWith('.js') || entry.name.endsWith('.json') || entry.name.endsWith('.md'))) {
|
|
@@ -539,7 +539,7 @@ class SubAgentManagerPlugin extends Plugin {
|
|
|
539
539
|
} else if (entry.name.endsWith('.md')) {
|
|
540
540
|
// 解析 markdown 文件,提取 JSON 配置
|
|
541
541
|
agentConfig = this._parseMarkdownConfig(filePath, baseName)
|
|
542
|
-
console.log('[SubAgentManager] Parsed md:', baseName, agentConfig)
|
|
542
|
+
//console.log('[SubAgentManager] Parsed md:', baseName, agentConfig)
|
|
543
543
|
} else {
|
|
544
544
|
// 清除缓存并加载
|
|
545
545
|
delete require.cache[require.resolve(filePath)]
|
|
@@ -550,7 +550,7 @@ class SubAgentManagerPlugin extends Plugin {
|
|
|
550
550
|
if (agentConfig && agentConfig.name) {
|
|
551
551
|
agentConfig._fromDir = true
|
|
552
552
|
this.config.agents.push(agentConfig)
|
|
553
|
-
console.log('[SubAgentManager] Loaded agent:', agentConfig.name)
|
|
553
|
+
//console.log('[SubAgentManager] Loaded agent:', agentConfig.name)
|
|
554
554
|
} else {
|
|
555
555
|
console.warn('[SubAgentManager] Agent config has no name:', baseName, agentConfig)
|
|
556
556
|
}
|
|
@@ -571,14 +571,14 @@ class SubAgentManagerPlugin extends Plugin {
|
|
|
571
571
|
*/
|
|
572
572
|
_parseMarkdownConfig(filePath, defaultName) {
|
|
573
573
|
const content = fs.readFileSync(filePath, 'utf-8')
|
|
574
|
-
console.log('[SubAgentManager] _parseMarkdownConfig:', filePath)
|
|
574
|
+
//console.log('[SubAgentManager] _parseMarkdownConfig:', filePath)
|
|
575
575
|
|
|
576
576
|
// 尝试从 code block 中提取 JSON
|
|
577
577
|
const jsonMatch = content.match(/```(?:json)?\s*\n([\s\S]*?)\n\s*```/)
|
|
578
578
|
if (jsonMatch) {
|
|
579
579
|
try {
|
|
580
580
|
const config = JSON.parse(jsonMatch[1].trim())
|
|
581
|
-
console.log('[SubAgentManager] Found JSON in code block')
|
|
581
|
+
//console.log('[SubAgentManager] Found JSON in code block')
|
|
582
582
|
return config
|
|
583
583
|
} catch (err) {
|
|
584
584
|
// JSON 解析失败,继续
|
|
@@ -588,11 +588,11 @@ class SubAgentManagerPlugin extends Plugin {
|
|
|
588
588
|
// 尝试从 frontmatter 格式中提取
|
|
589
589
|
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/)
|
|
590
590
|
if (frontmatterMatch) {
|
|
591
|
-
console.log('[SubAgentManager] Found frontmatter')
|
|
591
|
+
//console.log('[SubAgentManager] Found frontmatter')
|
|
592
592
|
const frontmatterContent = frontmatterMatch[1]
|
|
593
593
|
const parsed = this._parseYamlLike(frontmatterContent)
|
|
594
594
|
if (parsed && parsed.name) {
|
|
595
|
-
console.log('[SubAgentManager] Parsed frontmatter:', parsed)
|
|
595
|
+
//console.log('[SubAgentManager] Parsed frontmatter:', parsed)
|
|
596
596
|
return { name: parsed.name || defaultName, ...parsed }
|
|
597
597
|
}
|
|
598
598
|
}
|
|
@@ -648,7 +648,7 @@ class SubAgentManagerPlugin extends Plugin {
|
|
|
648
648
|
// 使用 fs.watch 监控目录变化
|
|
649
649
|
this._fileWatcher = fs.watch(agentsDir, { recursive: false }, (eventType, filename) => {
|
|
650
650
|
if (filename && (filename.endsWith('.js') || filename.endsWith('.json') || filename.endsWith('.md'))) {
|
|
651
|
-
console.log(`[SubAgentManager] Detected change in agents dir: ${eventType} - ${filename}`)
|
|
651
|
+
//console.log(`[SubAgentManager] Detected change in agents dir: ${eventType} - ${filename}`)
|
|
652
652
|
|
|
653
653
|
// 防抖:延迟处理,等文件操作完成
|
|
654
654
|
setTimeout(() => {
|
|
@@ -657,7 +657,7 @@ class SubAgentManagerPlugin extends Plugin {
|
|
|
657
657
|
}
|
|
658
658
|
})
|
|
659
659
|
|
|
660
|
-
console.log(`[SubAgentManager] Watching agents dir for changes: ${agentsDir}`)
|
|
660
|
+
//console.log(`[SubAgentManager] Watching agents dir for changes: ${agentsDir}`)
|
|
661
661
|
}
|
|
662
662
|
|
|
663
663
|
/**
|
|
@@ -731,7 +731,7 @@ class SubAgentManagerPlugin extends Plugin {
|
|
|
731
731
|
}
|
|
732
732
|
|
|
733
733
|
if (hasChanges) {
|
|
734
|
-
console.log('[SubAgentManager] File changes detected, reloading...')
|
|
734
|
+
//console.log('[SubAgentManager] File changes detected, reloading...')
|
|
735
735
|
this._updateFileStates()
|
|
736
736
|
this.reload(this._framework)
|
|
737
737
|
}
|
|
@@ -295,6 +295,9 @@ class TelegramPlugin extends Plugin {
|
|
|
295
295
|
this._sessionPlugin.addMessage(sessionId, { role: 'assistant', content: fullResponse })
|
|
296
296
|
}
|
|
297
297
|
|
|
298
|
+
// 去掉思考过程标签
|
|
299
|
+
fullResponse = fullResponse.replace(/<think>[\s\S]*?<\/think>/g, '').trim()
|
|
300
|
+
|
|
298
301
|
const safeResponse = escapeMarkdown(fullResponse) || '抱歉,我没有收到有效的回复。'
|
|
299
302
|
await this._bot.editMessageText(safeResponse, {
|
|
300
303
|
chat_id: chatId,
|
package/plugins/weixin-plugin.js
CHANGED
|
@@ -260,6 +260,8 @@ class WeixinPlugin extends Plugin {
|
|
|
260
260
|
|
|
261
261
|
// 发送回复
|
|
262
262
|
if (fullResponse) {
|
|
263
|
+
// 去掉思考过程标签
|
|
264
|
+
fullResponse = fullResponse.replace(/<think>[\s\S]*?<\/think>/g, '').trim()
|
|
263
265
|
await this._bot.reply(originalMsg, fullResponse)
|
|
264
266
|
console.log(`[WeChat] 回复成功 (${fullResponse.length} 字符)`)
|
|
265
267
|
} else {
|
|
@@ -184,6 +184,84 @@ class SkillManagerPlugin extends Plugin {
|
|
|
184
184
|
}
|
|
185
185
|
})
|
|
186
186
|
|
|
187
|
+
// 注册 loadReference 工具(按需加载 skill 的附加文档)
|
|
188
|
+
framework.registerTool({
|
|
189
|
+
name: 'loadReference',
|
|
190
|
+
description: '加载指定技能的附加参考文档(references 目录下的文件)',
|
|
191
|
+
inputSchema: z.object({
|
|
192
|
+
skill: z.string().describe('技能名称'),
|
|
193
|
+
reference: z.string().describe('参考文档名称(不含 .md 后缀)'),
|
|
194
|
+
list: z.boolean().optional().describe('如果为 true,列出该技能的所有可用的 reference 文件')
|
|
195
|
+
}),
|
|
196
|
+
execute: async (args) => {
|
|
197
|
+
if (args.list) {
|
|
198
|
+
// 列出该技能的所有 reference
|
|
199
|
+
const refs = this.listReferences(args.skill)
|
|
200
|
+
return {
|
|
201
|
+
success: true,
|
|
202
|
+
skill: args.skill,
|
|
203
|
+
references: refs
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const content = this.loadReference(args.skill, args.reference)
|
|
208
|
+
if (content === null) {
|
|
209
|
+
return {
|
|
210
|
+
success: false,
|
|
211
|
+
error: `Reference '${args.reference}' not found in skill '${args.skill}'`
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return {
|
|
215
|
+
success: true,
|
|
216
|
+
skill: args.skill,
|
|
217
|
+
reference: args.reference,
|
|
218
|
+
content
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
})
|
|
222
|
+
|
|
223
|
+
// 注册 listScripts 工具(列出 skill 的脚本)
|
|
224
|
+
framework.registerTool({
|
|
225
|
+
name: 'listScripts',
|
|
226
|
+
description: '列出指定技能下的所有可执行脚本',
|
|
227
|
+
inputSchema: z.object({
|
|
228
|
+
skill: z.string().describe('技能名称')
|
|
229
|
+
}),
|
|
230
|
+
execute: async (args) => {
|
|
231
|
+
const scripts = this.listScripts(args.skill)
|
|
232
|
+
return {
|
|
233
|
+
success: true,
|
|
234
|
+
skill: args.skill,
|
|
235
|
+
scripts
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
})
|
|
239
|
+
|
|
240
|
+
// 注册 loadScript 工具(读取脚本内容)
|
|
241
|
+
framework.registerTool({
|
|
242
|
+
name: 'loadScript',
|
|
243
|
+
description: '读取指定技能下脚本文件的内容',
|
|
244
|
+
inputSchema: z.object({
|
|
245
|
+
skill: z.string().describe('技能名称'),
|
|
246
|
+
script: z.string().describe('脚本名称(包含扩展名)')
|
|
247
|
+
}),
|
|
248
|
+
execute: async (args) => {
|
|
249
|
+
const content = this.loadScript(args.skill, args.script)
|
|
250
|
+
if (content === null) {
|
|
251
|
+
return {
|
|
252
|
+
success: false,
|
|
253
|
+
error: `Script '${args.script}' not found in skill '${args.skill}'`
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
return {
|
|
257
|
+
success: true,
|
|
258
|
+
skill: args.skill,
|
|
259
|
+
script: args.script,
|
|
260
|
+
content
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
})
|
|
264
|
+
|
|
187
265
|
return this
|
|
188
266
|
}
|
|
189
267
|
|
|
@@ -303,15 +381,165 @@ class SkillManagerPlugin extends Plugin {
|
|
|
303
381
|
const skill = new Skill(metadata, stripFrontmatter(content))
|
|
304
382
|
skill.install(this._framework)
|
|
305
383
|
|
|
384
|
+
// 扫描 references 子目录(按需加载的附加文档)
|
|
385
|
+
const references = this._scanReferences(skillPath)
|
|
386
|
+
|
|
387
|
+
// 扫描 scripts 子目录(可执行脚本)
|
|
388
|
+
const scripts = this._scanScripts(skillPath)
|
|
389
|
+
|
|
306
390
|
this._skills.set(name, {
|
|
307
391
|
name,
|
|
308
392
|
metadata,
|
|
309
393
|
content: skill.content,
|
|
310
394
|
instance: skill,
|
|
311
|
-
path: skillPath
|
|
395
|
+
path: skillPath,
|
|
396
|
+
references,
|
|
397
|
+
scripts
|
|
312
398
|
})
|
|
313
399
|
|
|
314
|
-
|
|
400
|
+
const refsInfo = references.size > 0 ? `, ${references.size} refs` : ''
|
|
401
|
+
const scriptsInfo = scripts.size > 0 ? `, ${scripts.size} scripts` : ''
|
|
402
|
+
//console.log(`[SkillManager] Loaded skill: ${name}${refsInfo}${scriptsInfo}`)
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* 扫描 references 子目录,按需加载
|
|
407
|
+
* @param {string} skillPath - skill 目录路径
|
|
408
|
+
* @returns {Map} references 文件映射 { filename: { path, content } }
|
|
409
|
+
*/
|
|
410
|
+
_scanReferences(skillPath) {
|
|
411
|
+
const references = new Map()
|
|
412
|
+
const refsDir = path.join(skillPath, 'references')
|
|
413
|
+
|
|
414
|
+
if (!fs.existsSync(refsDir) || !fs.statSync(refsDir).isDirectory()) {
|
|
415
|
+
return references
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
try {
|
|
419
|
+
const entries = fs.readdirSync(refsDir, { withFileTypes: true })
|
|
420
|
+
for (const entry of entries) {
|
|
421
|
+
if (entry.isFile() && entry.name.endsWith('.md')) {
|
|
422
|
+
const refPath = path.join(refsDir, entry.name)
|
|
423
|
+
const refName = entry.name.replace('.md', '')
|
|
424
|
+
references.set(refName, {
|
|
425
|
+
path: refPath,
|
|
426
|
+
content: null // 延迟加载
|
|
427
|
+
})
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
} catch (err) {
|
|
431
|
+
console.warn(`[SkillManager] Failed to scan references for ${skillPath}:`, err.message)
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
return references
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* 扫描 scripts 子目录,获取脚本列表
|
|
439
|
+
* @param {string} skillPath - skill 目录路径
|
|
440
|
+
* @returns {Map} scripts 映射 { filename: { path, isExecutable } }
|
|
441
|
+
*/
|
|
442
|
+
_scanScripts(skillPath) {
|
|
443
|
+
const scripts = new Map()
|
|
444
|
+
const scriptsDir = path.join(skillPath, 'scripts')
|
|
445
|
+
|
|
446
|
+
if (!fs.existsSync(scriptsDir) || !fs.statSync(scriptsDir).isDirectory()) {
|
|
447
|
+
return scripts
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
try {
|
|
451
|
+
const entries = fs.readdirSync(scriptsDir, { withFileTypes: true })
|
|
452
|
+
for (const entry of entries) {
|
|
453
|
+
if (entry.isFile()) {
|
|
454
|
+
const scriptPath = path.join(scriptsDir, entry.name)
|
|
455
|
+
// 检查文件是否有执行权限(或检查扩展名)
|
|
456
|
+
const isExecutable = entry.name.endsWith('.sh') ||
|
|
457
|
+
entry.name.endsWith('.js') ||
|
|
458
|
+
entry.name.endsWith('.py') ||
|
|
459
|
+
entry.name.endsWith('.ts')
|
|
460
|
+
scripts.set(entry.name, {
|
|
461
|
+
path: scriptPath,
|
|
462
|
+
isExecutable
|
|
463
|
+
})
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
} catch (err) {
|
|
467
|
+
console.warn(`[SkillManager] Failed to scan scripts for ${skillPath}:`, err.message)
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
return scripts
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* 按需加载 reference 文件
|
|
475
|
+
* @param {string} skillName - skill 名称
|
|
476
|
+
* @param {string} refName - reference 文件名(不含 .md)
|
|
477
|
+
* @returns {string|null} 文件内容
|
|
478
|
+
*/
|
|
479
|
+
loadReference(skillName, refName) {
|
|
480
|
+
const skill = this._skills.get(skillName)
|
|
481
|
+
if (!skill || !skill.references.has(refName)) {
|
|
482
|
+
return null
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
const ref = skill.references.get(refName)
|
|
486
|
+
if (!ref.content) {
|
|
487
|
+
try {
|
|
488
|
+
ref.content = fs.readFileSync(ref.path, 'utf-8')
|
|
489
|
+
} catch (err) {
|
|
490
|
+
console.error(`[SkillManager] Failed to load reference ${skillName}/${refName}:`, err.message)
|
|
491
|
+
return null
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
return ref.content
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* 获取 skill 的 reference 列表
|
|
500
|
+
* @param {string} skillName
|
|
501
|
+
* @returns {string[]} reference 文件名列表
|
|
502
|
+
*/
|
|
503
|
+
listReferences(skillName) {
|
|
504
|
+
const skill = this._skills.get(skillName)
|
|
505
|
+
if (!skill) return []
|
|
506
|
+
return Array.from(skill.references.keys())
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
/**
|
|
510
|
+
* 获取 skill 的 scripts 列表
|
|
511
|
+
* @param {string} skillName
|
|
512
|
+
* @returns {Object[]} script 信息列表 [{ name, path, isExecutable }]
|
|
513
|
+
*/
|
|
514
|
+
listScripts(skillName) {
|
|
515
|
+
const skill = this._skills.get(skillName)
|
|
516
|
+
if (!skill) return []
|
|
517
|
+
return Array.from(skill.scripts.entries()).map(([name, info]) => ({
|
|
518
|
+
name,
|
|
519
|
+
path: info.path,
|
|
520
|
+
isExecutable: info.isExecutable
|
|
521
|
+
}))
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* 读取脚本内容
|
|
526
|
+
* @param {string} skillName
|
|
527
|
+
* @param {string} scriptName
|
|
528
|
+
* @returns {string|null}
|
|
529
|
+
*/
|
|
530
|
+
loadScript(skillName, scriptName) {
|
|
531
|
+
const skill = this._skills.get(skillName)
|
|
532
|
+
if (!skill || !skill.scripts.has(scriptName)) {
|
|
533
|
+
return null
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
const script = skill.scripts.get(scriptName)
|
|
537
|
+
try {
|
|
538
|
+
return fs.readFileSync(script.path, 'utf-8')
|
|
539
|
+
} catch (err) {
|
|
540
|
+
console.error(`[SkillManager] Failed to load script ${skillName}/${scriptName}:`, err.message)
|
|
541
|
+
return null
|
|
542
|
+
}
|
|
315
543
|
}
|
|
316
544
|
|
|
317
545
|
/**
|
package/src/core/agent.js
CHANGED
|
@@ -31,7 +31,7 @@ class Agent extends EventEmitter {
|
|
|
31
31
|
this.providerOptions = config.providerOptions || {}
|
|
32
32
|
|
|
33
33
|
// 原始 system prompt
|
|
34
|
-
this._originalPrompt = config.systemPrompt || '
|
|
34
|
+
this._originalPrompt = config.systemPrompt || '你是一个智能助手。当用户提出问题或任务时,你会主动分析需求,选择合适的工具来获取信息或执行操作。你善于将复杂任务拆解为多个步骤,通过工具协作完成。'
|
|
35
35
|
|
|
36
36
|
// 共享提示模板
|
|
37
37
|
this._sharedPrompt = config.sharedPrompt || ''
|
|
@@ -106,7 +106,9 @@ class Agent extends EventEmitter {
|
|
|
106
106
|
|
|
107
107
|
let desc = '【可用工具】\n'
|
|
108
108
|
for (const [name, tool] of this._tools) {
|
|
109
|
-
|
|
109
|
+
// 跳过没有描述的工具(对LLM无帮助)
|
|
110
|
+
if (!tool.description) continue
|
|
111
|
+
desc += `- ${name}: ${tool.description}\n`
|
|
110
112
|
}
|
|
111
113
|
return desc.trim()
|
|
112
114
|
}
|
|
@@ -184,7 +186,7 @@ class Agent extends EventEmitter {
|
|
|
184
186
|
for (const [name, { role, goal }] of this._subAgents) {
|
|
185
187
|
desc += ` - ${name}: ${role || goal || '子代理'}\n`
|
|
186
188
|
}
|
|
187
|
-
desc += '\n
|
|
189
|
+
desc += '\n使用 subagent_call 工具并指定 agentName 来委托任务给相应子Agent。'
|
|
188
190
|
|
|
189
191
|
return desc.trim()
|
|
190
192
|
}
|
|
@@ -256,19 +258,22 @@ class Agent extends EventEmitter {
|
|
|
256
258
|
*/
|
|
257
259
|
_getToolCoreRules() {
|
|
258
260
|
return `【工具调用核心规则】
|
|
259
|
-
1.
|
|
260
|
-
2.
|
|
261
|
-
3.
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
261
|
+
1. **必须先调用工具再回复**:当问题需要信息、操作或计算时,必须调用工具获取真实结果后才能回答。禁止在未调用工具的情况下直接给出答案。
|
|
262
|
+
2. **禁止编造数据**:不许捏造用户、订单、任务、文件、内容等任何数据。所有数据必须通过工具获取。
|
|
263
|
+
3. **工具优先**:可用工具列表会提供,格式为 toolName(toolArgs)。不确定用哪个工具时,优先调用可能相关的工具。
|
|
264
|
+
4. **结果导向**:调用工具后,基于返回结果回答,不要重复工具的内部实现细节。
|
|
265
|
+
5. **多步骤任务**:复杂任务拆解为多个工具调用,逐步完成,每步基于结果决定下一步。
|
|
266
|
+
6. **子Agent委托**:当任务匹配子Agent专业领域时,使用 subagent_call 工具委托给对应子Agent处理。
|
|
267
|
+
|
|
268
|
+
【响应规范】
|
|
269
|
+
- 直接给出结论或结果,不说"我需要..."、"我建议..."等铺垫话术
|
|
270
|
+
- 如果工具返回错误,说明错误原因并给出解决建议
|
|
271
|
+
- 如果信息不足,先调用工具获取必要信息,不要假设或猜测
|
|
267
272
|
|
|
268
273
|
【禁止事项】
|
|
269
|
-
-
|
|
270
|
-
-
|
|
271
|
-
-
|
|
274
|
+
- 不调用工具就直接回答
|
|
275
|
+
- 编造不存在的数据、文件、订单、用户等信息
|
|
276
|
+
- 回复含糊不清,让用户无法确定答案是否正确`
|
|
272
277
|
}
|
|
273
278
|
|
|
274
279
|
/**
|
|
@@ -76,7 +76,7 @@ class PluginManager {
|
|
|
76
76
|
const stateFile = this._getStateFile()
|
|
77
77
|
if (fs.existsSync(stateFile)) {
|
|
78
78
|
const state = JSON.parse(fs.readFileSync(stateFile, 'utf-8'))
|
|
79
|
-
console.log('[PluginManager] Loaded plugin state from file')
|
|
79
|
+
//console.log('[PluginManager] Loaded plugin state from file')
|
|
80
80
|
return state
|
|
81
81
|
}
|
|
82
82
|
} catch (err) {
|
|
@@ -189,7 +189,7 @@ class PluginManager {
|
|
|
189
189
|
|
|
190
190
|
// 注册后再次检查 enabled 状态
|
|
191
191
|
if (!entry.enabled) {
|
|
192
|
-
console.log(`[PluginManager] Plugin '${pluginInstance.name}' is disabled, skipping install`)
|
|
192
|
+
//console.log(`[PluginManager] Plugin '${pluginInstance.name}' is disabled, skipping install`)
|
|
193
193
|
return pluginInstance
|
|
194
194
|
}
|
|
195
195
|
|
package/src/core/provider.js
CHANGED
|
@@ -44,7 +44,6 @@ const DEFAULT_PROVIDERS = {
|
|
|
44
44
|
function createAI(config) {
|
|
45
45
|
const { provider, model, apiKey, baseURL } = config
|
|
46
46
|
const providerName = (provider || 'deepseek').toLowerCase()
|
|
47
|
-
console.log(config)
|
|
48
47
|
// 检查是否是预定义提供商
|
|
49
48
|
if (DEFAULT_PROVIDERS[providerName]) {
|
|
50
49
|
const providerConfig = DEFAULT_PROVIDERS[providerName]
|