foliko 1.1.75 → 1.1.76
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 +5 -1
- package/.dockerignore +45 -45
- package/.env.example +56 -56
- package/cli/src/ui/chat-ui.js +56 -126
- package/cli/src/ui/components/agent-mention-provider.js +175 -0
- package/cli/src/ui/components/chained-autocomplete-provider.js +64 -0
- package/cli/src/ui/{footer-bar.js → components/footer-bar.js} +2 -2
- package/docker-compose.yml +33 -33
- package/docs/features.md +120 -120
- package/docs/quick-reference.md +160 -160
- package/package.json +1 -1
- package/plugins/ai-plugin.js +3 -3
- package/plugins/ambient-agent/ExplorerLoop.js +17 -17
- package/plugins/ambient-agent/index.js +2 -2
- package/plugins/data-splitter-plugin.js +9 -9
- package/plugins/default-plugins.js +7 -8
- package/plugins/extension-executor-plugin.js +2 -2
- package/plugins/feishu-plugin.js +5 -5
- package/plugins/install-plugin.js +4 -4
- package/plugins/memory-plugin.js +1 -1
- package/plugins/plugin-manager-plugin.js +9 -8
- package/plugins/python-plugin-loader.js +2 -2
- package/plugins/qq-plugin.js +4 -4
- package/plugins/rules-plugin.js +2 -2
- package/plugins/scheduler-plugin.js +13 -13
- package/plugins/session-plugin.js +2 -2
- package/plugins/subagent-plugin.js +1 -1
- package/plugins/telegram-plugin.js +6 -6
- package/plugins/think-plugin.js +4 -4
- package/plugins/tools-plugin.js +1 -1
- package/plugins/web-plugin.js +16 -16
- package/skills/find-skills/SKILL.md +133 -133
- package/skills/foliko-dev/AGENTS.md +236 -236
- package/skills/mcp-usage/SKILL.md +200 -200
- package/skills/subagent-guide/SKILL.md +237 -237
- package/skills/workflow-guide/SKILL.md +646 -646
- package/src/capabilities/skill-manager.js +5 -5
- package/src/capabilities/workflow-engine.js +5 -5
- package/src/core/agent-chat.js +8 -8
- package/src/core/agent.js +80 -5
- package/src/core/branch-summary-auto.js +4 -4
- package/src/core/chat-session.js +1 -0
- package/src/core/session-entry.js +14 -6
- package/src/core/session-manager.js +15 -3
- package/src/executors/mcp-executor.js +21 -25
- package/src/utils/data-splitter.js +3 -3
- package/src/utils/message-validator.js +1 -1
- package/website_v2/styles/animations.css +7 -7
- /package/cli/src/ui/{message-bubble.js → components/message-bubble.js} +0 -0
- /package/cli/src/ui/{status-bar.js → components/status-bar.js} +0 -0
package/docs/quick-reference.md
CHANGED
|
@@ -1,160 +1,160 @@
|
|
|
1
|
-
# Foliko 快速参考
|
|
2
|
-
|
|
3
|
-
## 启动框架
|
|
4
|
-
|
|
5
|
-
```javascript
|
|
6
|
-
const framework = new Framework({ debug: false });
|
|
7
|
-
await framework.bootstrap({
|
|
8
|
-
agentDir: './.foliko',
|
|
9
|
-
aiConfig: { provider: 'deepseek', model: 'deepseek-chat', apiKey: '...' },
|
|
10
|
-
});
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
## 创建 Agent
|
|
14
|
-
|
|
15
|
-
```javascript
|
|
16
|
-
const agent = framework.createAgent({
|
|
17
|
-
name: 'MyAgent',
|
|
18
|
-
systemPrompt: '你是一个有帮助的助手。',
|
|
19
|
-
});
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
## 发送消息
|
|
23
|
-
|
|
24
|
-
```javascript
|
|
25
|
-
// 流式
|
|
26
|
-
for await (const chunk of agent.chatStream('你好')) {
|
|
27
|
-
if (chunk.type === 'text') process.stdout.write(chunk.text);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// 非流式
|
|
31
|
-
const result = await agent.chat('你好');
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
## 常用工具
|
|
35
|
-
|
|
36
|
-
| 工具 | 用途 |
|
|
37
|
-
| ---------------------- | ------------ |
|
|
38
|
-
| `list_tools` | 列出所有工具 |
|
|
39
|
-
| `loadSkill` | 加载技能 |
|
|
40
|
-
| `reload_plugins` | 重载插件 |
|
|
41
|
-
| `read_file` | 读取文件 |
|
|
42
|
-
| `write_file` | 写入文件 |
|
|
43
|
-
| `execute_command` | 执行命令 |
|
|
44
|
-
| `schedule_once` | 定时任务 |
|
|
45
|
-
| `think_now` | 主动思考 |
|
|
46
|
-
| `email_send` | 发送邮件 |
|
|
47
|
-
| `email_read` | 读取邮件 |
|
|
48
|
-
| `enable_plugin` | 启用插件 |
|
|
49
|
-
| `disable_plugin` | 禁用插件 |
|
|
50
|
-
| `update_plugin_config` | 更新插件配置 |
|
|
51
|
-
|
|
52
|
-
## 插件位置
|
|
53
|
-
|
|
54
|
-
- 内置插件:`plugins/`
|
|
55
|
-
- 用户插件:`.foliko/plugins/`
|
|
56
|
-
|
|
57
|
-
## 插件管理
|
|
58
|
-
|
|
59
|
-
```javascript
|
|
60
|
-
// 重启插件
|
|
61
|
-
await framework.executeTool('reload_plugins', {});
|
|
62
|
-
await framework.executeTool('reload_plugins', { pluginName: 'telegram' });
|
|
63
|
-
|
|
64
|
-
// 启用/禁用插件
|
|
65
|
-
await framework.executeTool('enable_plugin', { name: 'telegram' });
|
|
66
|
-
await framework.executeTool('disable_plugin', { name: 'telegram' });
|
|
67
|
-
|
|
68
|
-
// 更新插件配置(持久化)
|
|
69
|
-
await framework.executeTool('update_plugin_config', {
|
|
70
|
-
name: 'telegram',
|
|
71
|
-
config: { allowedChats: ['123'], groupMode: true },
|
|
72
|
-
});
|
|
73
|
-
await framework.executeTool('get_plugin_config', { name: 'telegram' });
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
## 事件监听
|
|
77
|
-
|
|
78
|
-
```javascript
|
|
79
|
-
// Framework 事件
|
|
80
|
-
framework.on('framework:ready', (fw) => {});
|
|
81
|
-
framework.on('plugin:loaded', (plugin) => {});
|
|
82
|
-
framework.on('tool:registered', (tool) => {});
|
|
83
|
-
|
|
84
|
-
// Agent 事件
|
|
85
|
-
agent.on('status', ({ status }) => {}); // idle/busy/error
|
|
86
|
-
agent.on('chunk', (chunk) => {}); // 流式输出
|
|
87
|
-
agent.on('tool-call', ({ name, args }) => {});
|
|
88
|
-
agent.on('tool-result', ({ name, result }) => {});
|
|
89
|
-
|
|
90
|
-
// 子 Agent 事件
|
|
91
|
-
agent.on('subagent:chat:start', (data) => {});
|
|
92
|
-
agent.on('subagent:chat:end', (data) => {});
|
|
93
|
-
agent.on('subagent:error', (data) => {});
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
## 子 Agent 注册
|
|
97
|
-
|
|
98
|
-
```javascript
|
|
99
|
-
const { tool } = require('ai')
|
|
100
|
-
const { z } = require('zod')
|
|
101
|
-
|
|
102
|
-
// 方式1:配置 agents 数组自动注册
|
|
103
|
-
class MyPlugin extends Plugin {
|
|
104
|
-
agents = [
|
|
105
|
-
{
|
|
106
|
-
name: 'code-agent',
|
|
107
|
-
role: '代码专家',
|
|
108
|
-
tools: {
|
|
109
|
-
compile: tool({
|
|
110
|
-
description: '编译',
|
|
111
|
-
parameters: z.object({ language: z.string(), code: z.string() }),
|
|
112
|
-
execute: async (args) => ({ success: true })
|
|
113
|
-
})
|
|
114
|
-
},
|
|
115
|
-
parentTools: ['read_file', 'write_file']
|
|
116
|
-
}
|
|
117
|
-
]
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// 方式2:手动调用
|
|
121
|
-
this.registerSubAgent({ name: 'code-agent', role: '代码专家', tools: {...}, parentTools: [...] })
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
## 系统提示中的部分
|
|
125
|
-
|
|
126
|
-
```
|
|
127
|
-
【可用工具】
|
|
128
|
-
- tool1: 描述
|
|
129
|
-
- tool2: 描述
|
|
130
|
-
|
|
131
|
-
【可用技能】
|
|
132
|
-
- skill1: 描述
|
|
133
|
-
- skill2: 描述
|
|
134
|
-
|
|
135
|
-
【子 Agent 分配规则】
|
|
136
|
-
- code-agent: 代码专家
|
|
137
|
-
|
|
138
|
-
【系统能力】
|
|
139
|
-
- ai: AI 对话能力
|
|
140
|
-
- storage: 存储
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
## 状态管理
|
|
144
|
-
|
|
145
|
-
```javascript
|
|
146
|
-
agent.getStatus(); // 'idle' | 'busy' | 'error'
|
|
147
|
-
agent.resetStatus(); // 重置状态
|
|
148
|
-
agent.clearHistory(); // 清空历史
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
## 配置持久化
|
|
152
|
-
|
|
153
|
-
插件配置自动保存到 `.foliko/data/plugins-state.json`
|
|
154
|
-
|
|
155
|
-
| 文件 | 用途 |
|
|
156
|
-
| --------------------------------- | ------------------- |
|
|
157
|
-
| `.foliko/data/plugins-state.json` | 插件启用状态和配置 |
|
|
158
|
-
| `.foliko/data/storage.json` | 键值存储数据 |
|
|
159
|
-
| `.foliko/data/telegram_images/` | Telegram 接收的图片 |
|
|
160
|
-
| `.foliko/data/telegram_documents/` | Telegram 接收的文档 |
|
|
1
|
+
# Foliko 快速参考
|
|
2
|
+
|
|
3
|
+
## 启动框架
|
|
4
|
+
|
|
5
|
+
```javascript
|
|
6
|
+
const framework = new Framework({ debug: false });
|
|
7
|
+
await framework.bootstrap({
|
|
8
|
+
agentDir: './.foliko',
|
|
9
|
+
aiConfig: { provider: 'deepseek', model: 'deepseek-chat', apiKey: '...' },
|
|
10
|
+
});
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## 创建 Agent
|
|
14
|
+
|
|
15
|
+
```javascript
|
|
16
|
+
const agent = framework.createAgent({
|
|
17
|
+
name: 'MyAgent',
|
|
18
|
+
systemPrompt: '你是一个有帮助的助手。',
|
|
19
|
+
});
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## 发送消息
|
|
23
|
+
|
|
24
|
+
```javascript
|
|
25
|
+
// 流式
|
|
26
|
+
for await (const chunk of agent.chatStream('你好')) {
|
|
27
|
+
if (chunk.type === 'text') process.stdout.write(chunk.text);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// 非流式
|
|
31
|
+
const result = await agent.chat('你好');
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## 常用工具
|
|
35
|
+
|
|
36
|
+
| 工具 | 用途 |
|
|
37
|
+
| ---------------------- | ------------ |
|
|
38
|
+
| `list_tools` | 列出所有工具 |
|
|
39
|
+
| `loadSkill` | 加载技能 |
|
|
40
|
+
| `reload_plugins` | 重载插件 |
|
|
41
|
+
| `read_file` | 读取文件 |
|
|
42
|
+
| `write_file` | 写入文件 |
|
|
43
|
+
| `execute_command` | 执行命令 |
|
|
44
|
+
| `schedule_once` | 定时任务 |
|
|
45
|
+
| `think_now` | 主动思考 |
|
|
46
|
+
| `email_send` | 发送邮件 |
|
|
47
|
+
| `email_read` | 读取邮件 |
|
|
48
|
+
| `enable_plugin` | 启用插件 |
|
|
49
|
+
| `disable_plugin` | 禁用插件 |
|
|
50
|
+
| `update_plugin_config` | 更新插件配置 |
|
|
51
|
+
|
|
52
|
+
## 插件位置
|
|
53
|
+
|
|
54
|
+
- 内置插件:`plugins/`
|
|
55
|
+
- 用户插件:`.foliko/plugins/`
|
|
56
|
+
|
|
57
|
+
## 插件管理
|
|
58
|
+
|
|
59
|
+
```javascript
|
|
60
|
+
// 重启插件
|
|
61
|
+
await framework.executeTool('reload_plugins', {});
|
|
62
|
+
await framework.executeTool('reload_plugins', { pluginName: 'telegram' });
|
|
63
|
+
|
|
64
|
+
// 启用/禁用插件
|
|
65
|
+
await framework.executeTool('enable_plugin', { name: 'telegram' });
|
|
66
|
+
await framework.executeTool('disable_plugin', { name: 'telegram' });
|
|
67
|
+
|
|
68
|
+
// 更新插件配置(持久化)
|
|
69
|
+
await framework.executeTool('update_plugin_config', {
|
|
70
|
+
name: 'telegram',
|
|
71
|
+
config: { allowedChats: ['123'], groupMode: true },
|
|
72
|
+
});
|
|
73
|
+
await framework.executeTool('get_plugin_config', { name: 'telegram' });
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## 事件监听
|
|
77
|
+
|
|
78
|
+
```javascript
|
|
79
|
+
// Framework 事件
|
|
80
|
+
framework.on('framework:ready', (fw) => {});
|
|
81
|
+
framework.on('plugin:loaded', (plugin) => {});
|
|
82
|
+
framework.on('tool:registered', (tool) => {});
|
|
83
|
+
|
|
84
|
+
// Agent 事件
|
|
85
|
+
agent.on('status', ({ status }) => {}); // idle/busy/error
|
|
86
|
+
agent.on('chunk', (chunk) => {}); // 流式输出
|
|
87
|
+
agent.on('tool-call', ({ name, args }) => {});
|
|
88
|
+
agent.on('tool-result', ({ name, result }) => {});
|
|
89
|
+
|
|
90
|
+
// 子 Agent 事件
|
|
91
|
+
agent.on('subagent:chat:start', (data) => {});
|
|
92
|
+
agent.on('subagent:chat:end', (data) => {});
|
|
93
|
+
agent.on('subagent:error', (data) => {});
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## 子 Agent 注册
|
|
97
|
+
|
|
98
|
+
```javascript
|
|
99
|
+
const { tool } = require('ai')
|
|
100
|
+
const { z } = require('zod')
|
|
101
|
+
|
|
102
|
+
// 方式1:配置 agents 数组自动注册
|
|
103
|
+
class MyPlugin extends Plugin {
|
|
104
|
+
agents = [
|
|
105
|
+
{
|
|
106
|
+
name: 'code-agent',
|
|
107
|
+
role: '代码专家',
|
|
108
|
+
tools: {
|
|
109
|
+
compile: tool({
|
|
110
|
+
description: '编译',
|
|
111
|
+
parameters: z.object({ language: z.string(), code: z.string() }),
|
|
112
|
+
execute: async (args) => ({ success: true })
|
|
113
|
+
})
|
|
114
|
+
},
|
|
115
|
+
parentTools: ['read_file', 'write_file']
|
|
116
|
+
}
|
|
117
|
+
]
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// 方式2:手动调用
|
|
121
|
+
this.registerSubAgent({ name: 'code-agent', role: '代码专家', tools: {...}, parentTools: [...] })
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## 系统提示中的部分
|
|
125
|
+
|
|
126
|
+
```
|
|
127
|
+
【可用工具】
|
|
128
|
+
- tool1: 描述
|
|
129
|
+
- tool2: 描述
|
|
130
|
+
|
|
131
|
+
【可用技能】
|
|
132
|
+
- skill1: 描述
|
|
133
|
+
- skill2: 描述
|
|
134
|
+
|
|
135
|
+
【子 Agent 分配规则】
|
|
136
|
+
- code-agent: 代码专家
|
|
137
|
+
|
|
138
|
+
【系统能力】
|
|
139
|
+
- ai: AI 对话能力
|
|
140
|
+
- storage: 存储
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## 状态管理
|
|
144
|
+
|
|
145
|
+
```javascript
|
|
146
|
+
agent.getStatus(); // 'idle' | 'busy' | 'error'
|
|
147
|
+
agent.resetStatus(); // 重置状态
|
|
148
|
+
agent.clearHistory(); // 清空历史
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## 配置持久化
|
|
152
|
+
|
|
153
|
+
插件配置自动保存到 `.foliko/data/plugins-state.json`
|
|
154
|
+
|
|
155
|
+
| 文件 | 用途 |
|
|
156
|
+
| --------------------------------- | ------------------- |
|
|
157
|
+
| `.foliko/data/plugins-state.json` | 插件启用状态和配置 |
|
|
158
|
+
| `.foliko/data/storage.json` | 键值存储数据 |
|
|
159
|
+
| `.foliko/data/telegram_images/` | Telegram 接收的图片 |
|
|
160
|
+
| `.foliko/data/telegram_documents/` | Telegram 接收的文档 |
|
package/package.json
CHANGED
package/plugins/ai-plugin.js
CHANGED
|
@@ -57,7 +57,7 @@ class AIPlugin extends Plugin {
|
|
|
57
57
|
|
|
58
58
|
// 创建模型实例
|
|
59
59
|
this._aiClient = provider(this.config.model)
|
|
60
|
-
log.info(` Initialized ${this.config.provider}/${this.config.model}`)
|
|
60
|
+
//log.info(` Initialized ${this.config.provider}/${this.config.model}`)
|
|
61
61
|
} catch (err) {
|
|
62
62
|
log.error(' Failed to initialize AI client:', err.message)
|
|
63
63
|
}
|
|
@@ -80,7 +80,7 @@ class AIPlugin extends Plugin {
|
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
reload(framework) {
|
|
83
|
-
log.info(' Reloading...')
|
|
83
|
+
//log.info(' Reloading...')
|
|
84
84
|
this._framework = framework
|
|
85
85
|
this._initAIClient()
|
|
86
86
|
|
|
@@ -88,7 +88,7 @@ class AIPlugin extends Plugin {
|
|
|
88
88
|
for (const agent of framework._agents || []) {
|
|
89
89
|
if (agent._chatHandler) {
|
|
90
90
|
agent._chatHandler.setAIClient(this._aiClient)
|
|
91
|
-
log.info(` Refreshed AI client for agent: ${agent.name}`)
|
|
91
|
+
//log.info(` Refreshed AI client for agent: ${agent.name}`)
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
94
|
}
|
|
@@ -75,7 +75,7 @@ class ExplorerLoop {
|
|
|
75
75
|
'后台任务执行器',
|
|
76
76
|
'执行需要 AI 能力的后台任务'
|
|
77
77
|
)
|
|
78
|
-
log.info('ambient-worker subagent registered')
|
|
78
|
+
// log.info('ambient-worker subagent registered')
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
/**
|
|
@@ -181,14 +181,14 @@ class ExplorerLoop {
|
|
|
181
181
|
|
|
182
182
|
async _processGoals() {
|
|
183
183
|
const activeGoals = this._goalManager.getActiveGoals()
|
|
184
|
-
|
|
184
|
+
//// log.info(`[ExplorerLoop] _processGoals: ${activeGoals.length} 个活跃目标, _lastActionTime=${this._lastActionTime}, cooldown=${this._config.cooldownPeriod}`)
|
|
185
185
|
|
|
186
186
|
for (const goal of activeGoals) {
|
|
187
187
|
// 检查冷却时间
|
|
188
188
|
const timeSinceLastAction = Date.now() - this._lastActionTime
|
|
189
|
-
|
|
189
|
+
//// log.info(`[ExplorerLoop] 检查 goal=${goal.id}, timeSinceLastAction=${timeSinceLastAction}`)
|
|
190
190
|
if (timeSinceLastAction < this._config.cooldownPeriod) {
|
|
191
|
-
|
|
191
|
+
//// log.info(`[ExplorerLoop] 跳过 goal=${goal.id}, 还在冷却中`)
|
|
192
192
|
continue
|
|
193
193
|
}
|
|
194
194
|
|
|
@@ -200,18 +200,18 @@ class ExplorerLoop {
|
|
|
200
200
|
|
|
201
201
|
// 事件驱动目标:只有在新事件时才执行 actions
|
|
202
202
|
if (isEventDriven && !hasNewEvents) {
|
|
203
|
-
|
|
203
|
+
//// log.info(`[ExplorerLoop] 跳过 goal=${goal.id}, 事件驱动但无新事件`)
|
|
204
204
|
continue
|
|
205
205
|
}
|
|
206
206
|
|
|
207
|
-
log.info(`[ExplorerLoop] 开始执行 goal=${goal.id}, hasNewEvents=${hasNewEvents}, actions=${goal.actions?.length}`)
|
|
207
|
+
// log.info(`[ExplorerLoop] 开始执行 goal=${goal.id}, hasNewEvents=${hasNewEvents}, actions=${goal.actions?.length}`)
|
|
208
208
|
|
|
209
209
|
// 获取下一个操作(跳过已完成的 actions)
|
|
210
210
|
if (goal.actions && goal.actions.length > 0) {
|
|
211
211
|
// 过滤掉已完成的 actions
|
|
212
212
|
const pendingActions = goal.actions.filter(a => !a.completed)
|
|
213
213
|
if (pendingActions.length === 0) {
|
|
214
|
-
log.info(`[ExplorerLoop] goal=${goal.id} 所有 actions 已完成,等待下一事件`)
|
|
214
|
+
// log.info(`[ExplorerLoop] goal=${goal.id} 所有 actions 已完成,等待下一事件`)
|
|
215
215
|
this._resetGoalForNextEvent(goal)
|
|
216
216
|
continue
|
|
217
217
|
}
|
|
@@ -219,9 +219,9 @@ class ExplorerLoop {
|
|
|
219
219
|
// 如果有多个 action,按顺序执行所有 action
|
|
220
220
|
if (goal.actions.length > 1) {
|
|
221
221
|
const eventData = hasNewEvents ? goal.eventsReceived[0] : null
|
|
222
|
-
log.info(`[ExplorerLoop] 执行 ${goal.actions.length} 个 actions, eventData=${JSON.stringify(eventData?.data?.subject || 'none')}`)
|
|
222
|
+
// log.info(`[ExplorerLoop] 执行 ${goal.actions.length} 个 actions, eventData=${JSON.stringify(eventData?.data?.subject || 'none')}`)
|
|
223
223
|
const results = await this._executeAllActions(goal.actions, eventData)
|
|
224
|
-
log.info(`[ExplorerLoop] actions 执行完成, results.length=${results.length}`)
|
|
224
|
+
// log.info(`[ExplorerLoop] actions 执行完成, results.length=${results.length}`)
|
|
225
225
|
|
|
226
226
|
// 最后一个结果用于评估
|
|
227
227
|
const lastResult = results.length > 0 ? results[results.length - 1].result : null
|
|
@@ -262,7 +262,7 @@ class ExplorerLoop {
|
|
|
262
262
|
const action = goal.actions.find(a => !a.completed)
|
|
263
263
|
if (!action) {
|
|
264
264
|
// 所有 actions 已完成
|
|
265
|
-
log.info(`[ExplorerLoop] goal=${goal.id} 所有 actions 已完成`)
|
|
265
|
+
// log.info(`[ExplorerLoop] goal=${goal.id} 所有 actions 已完成`)
|
|
266
266
|
const allDone = goal.actions.every(a => a.completed)
|
|
267
267
|
if (allDone && !goal.persistent) {
|
|
268
268
|
// 一次性目标:所有 actions 完成后直接完成
|
|
@@ -418,7 +418,7 @@ class ExplorerLoop {
|
|
|
418
418
|
if (extResult && (extResult.success !== false || !extResult.error?.includes('not found'))) {
|
|
419
419
|
return extResult
|
|
420
420
|
}
|
|
421
|
-
log.info(`[ExplorerLoop] ext_call 回退到 StepExecutor: ${step.tool}`)
|
|
421
|
+
// log.info(`[ExplorerLoop] ext_call 回退到 StepExecutor: ${step.tool}`)
|
|
422
422
|
} else {
|
|
423
423
|
// 工具未指定,让 LLM 选择工具
|
|
424
424
|
return await this._executeWithAmbientAgent(step, context)
|
|
@@ -826,7 +826,7 @@ ${lastResultStr}
|
|
|
826
826
|
}
|
|
827
827
|
|
|
828
828
|
if (toolChoice && toolChoice.tool) {
|
|
829
|
-
log.info(`[ExplorerLoop] LLM 选择工具: plugin=${toolChoice.plugin}, tool=${toolChoice.tool}, args=${JSON.stringify(toolChoice.args)}`)
|
|
829
|
+
// log.info(`[ExplorerLoop] LLM 选择工具: plugin=${toolChoice.plugin}, tool=${toolChoice.tool}, args=${JSON.stringify(toolChoice.args)}`)
|
|
830
830
|
return await this._executeViaExtCall(toolChoice.tool, toolChoice.args || {}, toolChoice.plugin)
|
|
831
831
|
} else {
|
|
832
832
|
return { success: true, message: 'LLM 选择不执行任何工具', response: responseText }
|
|
@@ -896,7 +896,7 @@ ${lastResultStr}
|
|
|
896
896
|
|
|
897
897
|
// 如果指定了 plugin,直接使用
|
|
898
898
|
if (plugin) {
|
|
899
|
-
log.info(`[ExplorerLoop] 通过 ext_call 执行: plugin=${plugin}, tool=${toolName}`)
|
|
899
|
+
// log.info(`[ExplorerLoop] 通过 ext_call 执行: plugin=${plugin}, tool=${toolName}`)
|
|
900
900
|
try {
|
|
901
901
|
const result = await this._framework.executeTool('ext_call', {
|
|
902
902
|
plugin,
|
|
@@ -912,7 +912,7 @@ ${lastResultStr}
|
|
|
912
912
|
|
|
913
913
|
// 先尝试从工具名推断的插件
|
|
914
914
|
const inferredPlugin = this._inferPluginName(toolName)
|
|
915
|
-
log.info(`[ExplorerLoop] 通过 ext_call 执行: plugin=${inferredPlugin}, tool=${toolName}`)
|
|
915
|
+
// log.info(`[ExplorerLoop] 通过 ext_call 执行: plugin=${inferredPlugin}, tool=${toolName}`)
|
|
916
916
|
|
|
917
917
|
try {
|
|
918
918
|
const result = await this._framework.executeTool('ext_call', {
|
|
@@ -939,7 +939,7 @@ ${lastResultStr}
|
|
|
939
939
|
tool: toolName,
|
|
940
940
|
args
|
|
941
941
|
})
|
|
942
|
-
log.info(`[ExplorerLoop] ext_call 成功: plugin=${extPlugin}, tool=${toolName}`)
|
|
942
|
+
// log.info(`[ExplorerLoop] ext_call 成功: plugin=${extPlugin}, tool=${toolName}`)
|
|
943
943
|
return result
|
|
944
944
|
} catch (err) {
|
|
945
945
|
continue
|
|
@@ -956,7 +956,7 @@ ${lastResultStr}
|
|
|
956
956
|
tool: shortName,
|
|
957
957
|
args
|
|
958
958
|
})
|
|
959
|
-
log.info(`[ExplorerLoop] ext_call 成功(短名): plugin=${plugin}, tool=${shortName}`)
|
|
959
|
+
// log.info(`[ExplorerLoop] ext_call 成功(短名): plugin=${plugin}, tool=${shortName}`)
|
|
960
960
|
return result
|
|
961
961
|
} catch (err) {
|
|
962
962
|
continue
|
|
@@ -1043,7 +1043,7 @@ ${lastResultStr}
|
|
|
1043
1043
|
timestamp: new Date()
|
|
1044
1044
|
})
|
|
1045
1045
|
|
|
1046
|
-
log.info(`${title}: ${message}`)
|
|
1046
|
+
// log.info(`${title}: ${message}`)
|
|
1047
1047
|
}
|
|
1048
1048
|
}
|
|
1049
1049
|
|
|
@@ -89,7 +89,7 @@ class AmbientAgentPlugin extends Plugin {
|
|
|
89
89
|
|
|
90
90
|
start(framework) {
|
|
91
91
|
if (!this.config.enabled) {
|
|
92
|
-
log.info('插件已禁用,跳过启动')
|
|
92
|
+
// log.info('插件已禁用,跳过启动')
|
|
93
93
|
return this
|
|
94
94
|
}
|
|
95
95
|
|
|
@@ -117,7 +117,7 @@ class AmbientAgentPlugin extends Plugin {
|
|
|
117
117
|
// 注册工具
|
|
118
118
|
this._registerTools(framework)
|
|
119
119
|
|
|
120
|
-
log.info('插件已启动')
|
|
120
|
+
// log.info('插件已启动')
|
|
121
121
|
return this
|
|
122
122
|
}
|
|
123
123
|
|
|
@@ -57,7 +57,7 @@ class DataSplitterPlugin extends Plugin {
|
|
|
57
57
|
// 注册工具结果监听器(自动检测大结果)
|
|
58
58
|
this._registerAutoSplitHook();
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
// log.info('[DataSplitterPlugin] 已启动,阈值:', this.config.autoSplitThreshold);
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
/**
|
|
@@ -105,7 +105,7 @@ class DataSplitterPlugin extends Plugin {
|
|
|
105
105
|
const sessionCtx = ctx?.getCurrentSessionContext?.();
|
|
106
106
|
const signal = sessionCtx?.abortSignal;
|
|
107
107
|
|
|
108
|
-
|
|
108
|
+
log.debug(
|
|
109
109
|
`[split_and_process] 开始分拆: ${stats.chars} 字符, ` +
|
|
110
110
|
`${stats.chunks} 块, 任务="${taskDescription?.slice(0, 40)}..."`
|
|
111
111
|
);
|
|
@@ -213,10 +213,10 @@ class DataSplitterPlugin extends Plugin {
|
|
|
213
213
|
if (!checkContent || checkContent.length < this.config.autoSplitThreshold) return;
|
|
214
214
|
|
|
215
215
|
// 不阻塞执行,只在日志中记录建议
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
);
|
|
216
|
+
// log.info(
|
|
217
|
+
// `[DataSplitter] 检测到大数据工具结果: ${name}, ` +
|
|
218
|
+
// `${checkContent.length} 字符, 建议使用 split_and_process 分拆处理`
|
|
219
|
+
// );
|
|
220
220
|
};
|
|
221
221
|
|
|
222
222
|
framework.on('tool:result', this._toolResultHandler);
|
|
@@ -291,9 +291,9 @@ async function autoSplitToolResult(toolName, result, framework) {
|
|
|
291
291
|
const splitter = new DataSplitter(framework);
|
|
292
292
|
const taskDescription = `从以下内容中提取关键信息(代码、配置、数据等),以结构化方式输出。`;
|
|
293
293
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
);
|
|
294
|
+
// log.info(
|
|
295
|
+
// `[DataSplitter] 自动分拆工具 "${toolName}": ${checkContent.length} 字符`
|
|
296
|
+
// );
|
|
297
297
|
|
|
298
298
|
try {
|
|
299
299
|
const chunks = splitter.splitContent(checkContent);
|
|
@@ -28,17 +28,17 @@ function loadAgentConfig(agentDir = '.foliko') {
|
|
|
28
28
|
const resolvedDir = path.resolve(process.cwd(), agentDir)
|
|
29
29
|
|
|
30
30
|
if (!fs.existsSync(resolvedDir)) {
|
|
31
|
-
log.info(` .foliko directory not found: ${resolvedDir}`)
|
|
31
|
+
//log.info(` .foliko directory not found: ${resolvedDir}`)
|
|
32
32
|
return config
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
log.info(` Loading config from: ${resolvedDir}`)
|
|
35
|
+
//log.info(` Loading config from: ${resolvedDir}`)
|
|
36
36
|
|
|
37
37
|
// 添加 agents 目录(如果存在)
|
|
38
38
|
const agentsDir = path.join(resolvedDir, 'agents')
|
|
39
39
|
if (fs.existsSync(agentsDir)) {
|
|
40
40
|
config.agentsDir = agentsDir
|
|
41
|
-
log.info(` Found agents directory: ${agentsDir}`)
|
|
41
|
+
//log.info(` Found agents directory: ${agentsDir}`)
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
// 加载 config 文件(key=value 格式)
|
|
@@ -104,9 +104,7 @@ function loadAgentConfig(agentDir = '.foliko') {
|
|
|
104
104
|
// 外部插件链接配置 (pluginLinks: { "poster": "/path/to/poster-plugin" })
|
|
105
105
|
if (pluginsConfig.pluginLinks) {
|
|
106
106
|
config.pluginLinks = pluginsConfig.pluginLinks
|
|
107
|
-
|
|
108
|
-
log.info(` Found plugin link: ${name} -> ${targetPath}`)
|
|
109
|
-
}
|
|
107
|
+
//log.info(` Found plugin link: ${name} -> ${targetPath}`)
|
|
110
108
|
}
|
|
111
109
|
} catch (err) {
|
|
112
110
|
log.error(` Failed to load plugins.json:`, err.message)
|
|
@@ -140,7 +138,7 @@ function loadAgentConfig(agentDir = '.foliko') {
|
|
|
140
138
|
const skillsDir = path.join(resolvedDir, 'skills')
|
|
141
139
|
if (fs.existsSync(resolvedDir) && !fs.existsSync(skillsDir)) {
|
|
142
140
|
fs.mkdirSync(skillsDir, { recursive: true })
|
|
143
|
-
log.info(` Created skills directory: ${skillsDir}`)
|
|
141
|
+
//log.info(` Created skills directory: ${skillsDir}`)
|
|
144
142
|
}
|
|
145
143
|
if (fs.existsSync(skillsDir)) {
|
|
146
144
|
config.skillsDirs.push(skillsDir)
|
|
@@ -150,7 +148,7 @@ function loadAgentConfig(agentDir = '.foliko') {
|
|
|
150
148
|
const cmdskillsDir = path.join(cmdDir, 'skills')
|
|
151
149
|
if (fs.existsSync(resolvedDir) && !fs.existsSync(cmdskillsDir)) {
|
|
152
150
|
fs.mkdirSync(cmdskillsDir, { recursive: true })
|
|
153
|
-
log.info(` Created skills directory: ${cmdskillsDir}`)
|
|
151
|
+
//log.info(` Created skills directory: ${cmdskillsDir}`)
|
|
154
152
|
}
|
|
155
153
|
if (fs.existsSync(cmdskillsDir)) {
|
|
156
154
|
config.skillsDirs.push(cmdskillsDir)
|
|
@@ -160,6 +158,7 @@ function loadAgentConfig(agentDir = '.foliko') {
|
|
|
160
158
|
const parentDir = path.dirname(__dirname)
|
|
161
159
|
const rootSkillsDir = path.join(parentDir, 'skills')
|
|
162
160
|
if (fs.existsSync(rootSkillsDir)) {
|
|
161
|
+
//log.info(` Found root skills directory: ${rootSkillsDir}`)
|
|
163
162
|
config.skillsDirs.push(rootSkillsDir)
|
|
164
163
|
}
|
|
165
164
|
|
|
@@ -130,7 +130,7 @@ class ExtensionExecutorPlugin extends Plugin {
|
|
|
130
130
|
|
|
131
131
|
// 重新扫描工具,使用正确的扩展名
|
|
132
132
|
this._scanPluginTools(plugin, extName);
|
|
133
|
-
log.info(` Rescanned tools from plugin '${pluginName}' (as '${extName}')`);
|
|
133
|
+
//log.info(` Rescanned tools from plugin '${pluginName}' (as '${extName}')`);
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
async start(framework) {
|
|
@@ -153,7 +153,7 @@ class ExtensionExecutorPlugin extends Plugin {
|
|
|
153
153
|
}),
|
|
154
154
|
execute: async (args) => {
|
|
155
155
|
const { plugin, tool, args: toolArgs = {} } = args;
|
|
156
|
-
log.info(`[Extension] ext_call: plugin=${plugin}, tool=${tool}`);
|
|
156
|
+
//log.info(`[Extension] ext_call: plugin=${plugin}, tool=${tool}`);
|
|
157
157
|
|
|
158
158
|
// MCP 服务器工具(已注册为 server_toolname 格式,如 github_search)
|
|
159
159
|
if (plugin === 'mcp' && this._mcpExecutor) {
|
package/plugins/feishu-plugin.js
CHANGED
|
@@ -74,7 +74,7 @@ class FeishuPlugin extends Plugin {
|
|
|
74
74
|
if (this._sessionPlugin) {
|
|
75
75
|
this._sessionDeleteHandler = (sessionId) => {
|
|
76
76
|
if (sessionId.startsWith('feishu_')) {
|
|
77
|
-
log.info(` Session deleted: ${sessionId}`)
|
|
77
|
+
//log.info(` Session deleted: ${sessionId}`)
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
80
|
this._sessionPlugin.on('session:deleted', this._sessionDeleteHandler)
|
|
@@ -128,7 +128,7 @@ class FeishuPlugin extends Plugin {
|
|
|
128
128
|
})
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
-
log.info(' WebSocket client started')
|
|
131
|
+
//log.info(' WebSocket client started')
|
|
132
132
|
} catch (err) {
|
|
133
133
|
log.error(' Failed to initialize client:', err.message, err.stack)
|
|
134
134
|
}
|
|
@@ -340,7 +340,7 @@ class FeishuPlugin extends Plugin {
|
|
|
340
340
|
|
|
341
341
|
try {
|
|
342
342
|
await this._sendTextMessage(openId, notificationText)
|
|
343
|
-
log.info(` Webhook notification sent to ${openId}`)
|
|
343
|
+
//log.info(` Webhook notification sent to ${openId}`)
|
|
344
344
|
} catch (err) {
|
|
345
345
|
log.error(` Failed to send webhook notification:`, err.message)
|
|
346
346
|
}
|
|
@@ -393,7 +393,7 @@ class FeishuPlugin extends Plugin {
|
|
|
393
393
|
|
|
394
394
|
try {
|
|
395
395
|
await this._sendTextMessage(openId, notificationText)
|
|
396
|
-
log.info(` Notification sent to ${openId}`)
|
|
396
|
+
//log.info(` Notification sent to ${openId}`)
|
|
397
397
|
} catch (err) {
|
|
398
398
|
log.error(` Failed to send notification:`, err.message)
|
|
399
399
|
}
|
|
@@ -612,7 +612,7 @@ class FeishuPlugin extends Plugin {
|
|
|
612
612
|
try { this._wsClient.close() } catch (e) { /* ignore */ }
|
|
613
613
|
this._wsClient = null
|
|
614
614
|
this._client = null
|
|
615
|
-
log.info(' Client stopped')
|
|
615
|
+
//log.info(' Client stopped')
|
|
616
616
|
}
|
|
617
617
|
}
|
|
618
618
|
|