foliko 1.0.26 → 1.0.28
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 +6 -1
- package/cli/src/commands/chat.js +0 -1
- package/package.json +1 -1
- package/plugins/ai-plugin.js +0 -1
- package/plugins/default-plugins.js +12 -2
- package/plugins/subagent-plugin.js +91 -10
- package/plugins/weixin-plugin.js +1 -1
- package/src/core/plugin-manager.js +11 -5
- package/src/core/provider.js +1 -1
|
@@ -63,7 +63,12 @@
|
|
|
63
63
|
"Bash(node -c plugins/default-plugins.js && node -c src/core/plugin-manager.js && node -c plugins/tools-plugin.js 2>&1)",
|
|
64
64
|
"Bash(node -c src/core/plugin-base.js && node -c src/core/plugin-manager.js 2>&1)",
|
|
65
65
|
"Bash(node -c plugins/telegram-plugin.js && node -c plugins/weixin-plugin.js 2>&1)",
|
|
66
|
-
"Bash(node -c src/core/plugin-manager.js 2>&1)"
|
|
66
|
+
"Bash(node -c src/core/plugin-manager.js 2>&1)",
|
|
67
|
+
"Bash(node -c src/core/plugin-manager.js && node -c src/core/plugin-base.js && node -c plugins/default-plugins.js && node -c plugins/telegram-plugin.js && node -c plugins/weixin-plugin.js 2>&1)",
|
|
68
|
+
"Bash(node -e \"require\\('dotenv'\\).config\\(\\); console.log\\('PROVIDER:', process.env.FOLIKO_PROVIDER\\); console.log\\('MODEL:', process.env.FOLIKO_MODEL\\); console.log\\('KEY:', process.env.DEEPSEEK_API_KEY ? 'set' : 'not set'\\)\" 2>&1)",
|
|
69
|
+
"Bash(node cli/src/index.js chat 2>&1 | head -30)",
|
|
70
|
+
"Bash(node -e 'const { DEFAULT_PROVIDERS } = require\\(\"./src/core/provider\"\\); console.log\\(DEFAULT_PROVIDERS\\);')",
|
|
71
|
+
"Bash(node -e \"const dotenv = require\\('dotenv'\\); const result = dotenv.config\\(\\); console.log\\('Result:', result\\); console.log\\('PROVIDER after dotenv:', process.env.FOLIKO_PROVIDER\\);\" 2>&1)"
|
|
67
72
|
]
|
|
68
73
|
}
|
|
69
74
|
}
|
package/cli/src/commands/chat.js
CHANGED
package/package.json
CHANGED
package/plugins/ai-plugin.js
CHANGED
|
@@ -214,7 +214,7 @@ async function bootstrapDefaults(framework, config = {}) {
|
|
|
214
214
|
'install', 'ai', 'storage', 'tools', 'workflow', 'skill-manager',
|
|
215
215
|
'mcp-executor', 'shell-executor', 'python-executor', 'session',
|
|
216
216
|
'audit', 'rules', 'scheduler', 'file-system', 'think',
|
|
217
|
-
'python-plugin-loader', 'telegram', 'weixin'
|
|
217
|
+
'python-plugin-loader', 'telegram', 'weixin', 'subagent-manager'
|
|
218
218
|
])
|
|
219
219
|
|
|
220
220
|
// 辅助函数:检查插件是否应该加载(核心插件不能禁用)
|
|
@@ -244,7 +244,6 @@ async function bootstrapDefaults(framework, config = {}) {
|
|
|
244
244
|
]
|
|
245
245
|
|
|
246
246
|
console.log('[Bootstrap] Loading default plugins...')
|
|
247
|
-
|
|
248
247
|
// AI 插件(如果已禁用则跳过)
|
|
249
248
|
if (!shouldLoad('ai') || !(aiConfig.provider || aiConfig.model || aiConfig.apiKey)) {
|
|
250
249
|
// 跳过或已禁用
|
|
@@ -421,6 +420,17 @@ async function bootstrapDefaults(framework, config = {}) {
|
|
|
421
420
|
}
|
|
422
421
|
}
|
|
423
422
|
|
|
423
|
+
// 12.8 SubAgent 管理器
|
|
424
|
+
if (shouldLoad('subagent-manager')) {
|
|
425
|
+
try {
|
|
426
|
+
const { SubAgentManagerPlugin } = require('./subagent-plugin')
|
|
427
|
+
await framework.loadPlugin(new SubAgentManagerPlugin({ agentsDir: agentConfig.agentsDir }))
|
|
428
|
+
console.log('[Bootstrap] SubAgent Manager loaded')
|
|
429
|
+
} catch (err) {
|
|
430
|
+
console.warn('[Bootstrap] SubAgent Manager failed:', err.message)
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
424
434
|
// 13. 加载自定义插件
|
|
425
435
|
await loadCustomPlugins(framework, agentConfig)
|
|
426
436
|
|
|
@@ -102,7 +102,7 @@ class SubAgentPlugin extends Plugin {
|
|
|
102
102
|
|
|
103
103
|
// 注册从父Agent继承的工具
|
|
104
104
|
for (const tool of parentTools) {
|
|
105
|
-
this.
|
|
105
|
+
this._framework.registerTool(tool)
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
// 注册自定义工具(只属于此子Agent,不污染全局)
|
|
@@ -111,10 +111,10 @@ class SubAgentPlugin extends Plugin {
|
|
|
111
111
|
for (const [toolName, toolDef] of Object.entries(this.config.tools)) {
|
|
112
112
|
const tool = typeof toolDef === 'function' ? toolDef() : toolDef
|
|
113
113
|
if (typeof tool === 'object' && tool.name) {
|
|
114
|
-
this.
|
|
114
|
+
this._framework.registerTool(tool)
|
|
115
115
|
} else {
|
|
116
116
|
// 假设是简化的工具定义,需要补充 name
|
|
117
|
-
this.
|
|
117
|
+
this._framework.registerTool({ name: toolName, ...tool })
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
120
|
}
|
|
@@ -209,7 +209,7 @@ class SubAgentPlugin extends Plugin {
|
|
|
209
209
|
}
|
|
210
210
|
|
|
211
211
|
/**
|
|
212
|
-
*
|
|
212
|
+
* 注册委托工具到框架和主Agent
|
|
213
213
|
*/
|
|
214
214
|
_registerDelegateTool() {
|
|
215
215
|
const framework = this._framework
|
|
@@ -218,8 +218,7 @@ class SubAgentPlugin extends Plugin {
|
|
|
218
218
|
const agentName = this.config.name
|
|
219
219
|
const role = this.config.role
|
|
220
220
|
|
|
221
|
-
|
|
222
|
-
framework.registerTool({
|
|
221
|
+
const toolDef = {
|
|
223
222
|
name: agentName,
|
|
224
223
|
description: `${role}:当需要${role}时,调用此工具执行任务。如:编译代码、运行测试、代码重构等。`,
|
|
225
224
|
inputSchema: z.object({
|
|
@@ -272,9 +271,17 @@ class SubAgentPlugin extends Plugin {
|
|
|
272
271
|
}
|
|
273
272
|
}
|
|
274
273
|
}
|
|
275
|
-
}
|
|
274
|
+
}
|
|
276
275
|
|
|
277
|
-
|
|
276
|
+
// 注册到框架(供后续创建的 Agent 同步)
|
|
277
|
+
framework.registerTool(toolDef)
|
|
278
|
+
|
|
279
|
+
// 如果主 Agent 已存在,直接注册到它
|
|
280
|
+
if (framework._mainAgent) {
|
|
281
|
+
framework._mainAgent.registerTool(toolDef)
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
console.log(`[SubAgent:${this.config.name}] Delegate tool registered`)
|
|
278
285
|
}
|
|
279
286
|
|
|
280
287
|
/**
|
|
@@ -351,16 +358,90 @@ class SubAgentManagerPlugin extends Plugin {
|
|
|
351
358
|
this._subAgents.set(agentConfig.name, plugin)
|
|
352
359
|
}
|
|
353
360
|
|
|
354
|
-
//
|
|
355
|
-
//
|
|
361
|
+
// 注册管理工具
|
|
362
|
+
// 如果主 Agent 已存在,直接注册到它(因为它不会自动同步框架工具)
|
|
363
|
+
if (framework._mainAgent) {
|
|
364
|
+
this._registerToolsToAgent(framework._mainAgent)
|
|
365
|
+
}
|
|
366
|
+
// 同时注册到框架(供后续创建的 Agent 同步)
|
|
356
367
|
this._registerTools(framework)
|
|
357
368
|
|
|
369
|
+
// 监听主 Agent 创建事件,为后续创建的主 Agent 注册工具
|
|
370
|
+
framework.on('agent:created', (agent) => {
|
|
371
|
+
if (framework._mainAgent && agent === framework._mainAgent) {
|
|
372
|
+
this._registerToolsToAgent(agent)
|
|
373
|
+
}
|
|
374
|
+
})
|
|
375
|
+
|
|
358
376
|
// 启动文件监控
|
|
359
377
|
this._startFileWatcher()
|
|
360
378
|
|
|
361
379
|
return this
|
|
362
380
|
}
|
|
363
381
|
|
|
382
|
+
/**
|
|
383
|
+
* 注册管理工具到指定 Agent
|
|
384
|
+
*/
|
|
385
|
+
_registerToolsToAgent(agent) {
|
|
386
|
+
agent.registerTool({
|
|
387
|
+
name: 'subagent_list',
|
|
388
|
+
description: '列出所有子Agent',
|
|
389
|
+
inputSchema: z.object({}),
|
|
390
|
+
execute: async () => {
|
|
391
|
+
const agents = Array.from(this._subAgents.values()).map(p => ({
|
|
392
|
+
name: p.config.name,
|
|
393
|
+
role: p.config.role,
|
|
394
|
+
description: p.config.description,
|
|
395
|
+
toolCount: p._agent ? p._agent.getTools().length : 0
|
|
396
|
+
}))
|
|
397
|
+
return { success: true, agents }
|
|
398
|
+
}
|
|
399
|
+
})
|
|
400
|
+
|
|
401
|
+
agent.registerTool({
|
|
402
|
+
name: 'subagent_call',
|
|
403
|
+
description: '调用指定的子Agent处理任务',
|
|
404
|
+
inputSchema: z.object({
|
|
405
|
+
agentName: z.string().describe('子Agent名称'),
|
|
406
|
+
task: z.string().describe('任务描述')
|
|
407
|
+
}),
|
|
408
|
+
execute: async (args) => {
|
|
409
|
+
const plugin = this._subAgents.get(args.agentName)
|
|
410
|
+
if (!plugin) {
|
|
411
|
+
return { success: false, error: `SubAgent ${args.agentName} not found` }
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
try {
|
|
415
|
+
const result = await plugin.chat(args.task)
|
|
416
|
+
return {
|
|
417
|
+
success: true,
|
|
418
|
+
agent: args.agentName,
|
|
419
|
+
result: result.message || result,
|
|
420
|
+
success: result.success !== false
|
|
421
|
+
}
|
|
422
|
+
} catch (err) {
|
|
423
|
+
return { success: false, error: err.message }
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
})
|
|
427
|
+
|
|
428
|
+
agent.registerTool({
|
|
429
|
+
name: 'subagent_reload',
|
|
430
|
+
description: '重新加载子Agent配置(当新增或删除.agent/agents下的文件后使用)',
|
|
431
|
+
inputSchema: z.object({}),
|
|
432
|
+
execute: async () => {
|
|
433
|
+
try {
|
|
434
|
+
this.reload(this._framework)
|
|
435
|
+
return { success: true, message: '子Agent配置已重新加载' }
|
|
436
|
+
} catch (err) {
|
|
437
|
+
return { success: false, error: err.message }
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
})
|
|
441
|
+
|
|
442
|
+
console.log('[SubAgentManager] Management tools registered to agent')
|
|
443
|
+
}
|
|
444
|
+
|
|
364
445
|
/**
|
|
365
446
|
* 注册管理工具到框架工具注册表
|
|
366
447
|
*/
|
package/plugins/weixin-plugin.js
CHANGED
|
@@ -24,7 +24,7 @@ module.exports = function(Plugin) {
|
|
|
24
24
|
this.config = {
|
|
25
25
|
forceLogin: config.forceLogin || process.env.WEIXIN_FORCE_LOGIN === 'true',
|
|
26
26
|
qrcodeTerminal: config.qrcodeTerminal !== false && process.env.WEIXIN_QRCODE_TERMINAL !== 'false',
|
|
27
|
-
systemPrompt: config.systemPrompt || '你是一个有帮助的AI
|
|
27
|
+
systemPrompt: config.systemPrompt || '你是一个有帮助的AI助手。回复内容不要使用markdown格式文本',
|
|
28
28
|
allowedUsers: config.allowedUsers || []
|
|
29
29
|
}
|
|
30
30
|
|
|
@@ -32,14 +32,20 @@ class PluginManager {
|
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
34
|
* 保存插件状态到文件
|
|
35
|
+
* 注意:AI 插件配置不保存(从环境变量和命令行获取)
|
|
35
36
|
*/
|
|
36
37
|
_saveState() {
|
|
37
38
|
try {
|
|
38
39
|
const state = {}
|
|
39
40
|
for (const [name, entry] of this._plugins) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
// AI 配置不保存,每次从环境变量和命令行获取
|
|
42
|
+
if (name === 'ai') {
|
|
43
|
+
state[name] = { enabled: entry.enabled }
|
|
44
|
+
} else {
|
|
45
|
+
state[name] = {
|
|
46
|
+
enabled: entry.enabled,
|
|
47
|
+
config: entry.instance?.config || {}
|
|
48
|
+
}
|
|
43
49
|
}
|
|
44
50
|
}
|
|
45
51
|
fs.writeFileSync(this._getStateFile(), JSON.stringify(state, null, 2))
|
|
@@ -85,8 +91,8 @@ class PluginManager {
|
|
|
85
91
|
const savedEnabled = savedState[pluginInstance.name]?.enabled
|
|
86
92
|
const savedConfig = savedState[pluginInstance.name]?.config
|
|
87
93
|
|
|
88
|
-
//
|
|
89
|
-
if (savedConfig && pluginInstance.config) {
|
|
94
|
+
// 恢复保存的配置到插件实例(AI 插件不恢复配置,从环境变量获取)
|
|
95
|
+
if (savedConfig && pluginInstance.config && pluginInstance.name !== 'ai') {
|
|
90
96
|
pluginInstance.config = { ...pluginInstance.config, ...savedConfig }
|
|
91
97
|
}
|
|
92
98
|
|
package/src/core/provider.js
CHANGED
|
@@ -44,7 +44,7 @@ const DEFAULT_PROVIDERS = {
|
|
|
44
44
|
function createAI(config) {
|
|
45
45
|
const { provider, model, apiKey, baseURL } = config
|
|
46
46
|
const providerName = (provider || 'deepseek').toLowerCase()
|
|
47
|
-
|
|
47
|
+
console.log(config)
|
|
48
48
|
// 检查是否是预定义提供商
|
|
49
49
|
if (DEFAULT_PROVIDERS[providerName]) {
|
|
50
50
|
const providerConfig = DEFAULT_PROVIDERS[providerName]
|