foliko 1.0.7 → 1.0.9
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 +7 -1
- package/.env.example +23 -0
- package/README.md +29 -2
- package/SPEC.md +75 -2
- package/cli/src/ui/chat-ui.js +41 -2
- package/docs/quick-reference.md +30 -4
- package/docs/user-manual.md +158 -3
- package/{test-chat.js → examples/test-chat.js} +2 -2
- package/{test-mcp.js → examples/test-mcp.js} +2 -2
- package/{test-reload.js → examples/test-reload.js} +2 -2
- package/{test-telegram.js → examples/test-telegram.js} +1 -1
- package/{test-tg-bot.js → examples/test-tg-bot.js} +1 -1
- package/{test-tg.js → examples/test-tg.js} +1 -1
- package/{test-think.js → examples/test-think.js} +1 -1
- package/package.json +4 -1
- package/plugins/ai-plugin.js +8 -0
- package/plugins/default-plugins.js +139 -59
- package/plugins/email.js +382 -0
- package/plugins/install-plugin.js +115 -12
- package/plugins/telegram-plugin.js +9 -0
- package/plugins/tools-plugin.js +75 -0
- package/skills/vb-agent-dev/AGENTS.md +81 -10
- package/skills/vb-agent-dev/SKILL.md +149 -25
- package/src/core/framework.js +27 -0
- package/src/core/plugin-manager.js +272 -16
- /package/{test-tg-simple.js → examples/test-tg-simple.js} +0 -0
|
@@ -28,7 +28,13 @@
|
|
|
28
28
|
"Bash(cd D:/Code/vb-agent && pnpm install --shamefully-hoist 2>&1 | head -20)",
|
|
29
29
|
"Bash(cd D:/Code/vb-agent && rm -rf node_modules && pnpm install)",
|
|
30
30
|
"Bash(cd D:/Code/vb-agent && timeout 8 node test-tg.js 2>&1 || true)",
|
|
31
|
-
"Bash(cd D:/Code/vb-agent && timeout 10 node test-tg.js 2>&1 || true)"
|
|
31
|
+
"Bash(cd D:/Code/vb-agent && timeout 10 node test-tg.js 2>&1 || true)",
|
|
32
|
+
"Bash(find /d/Code/vb-agent -name \"*email*\" -type f 2>/dev/null | grep -v node_modules | grep -v .git)",
|
|
33
|
+
"Bash(find /d/Code/vb-agent -maxdepth 2 -name \"*.md\" -type f 2>/dev/null | grep -v node_modules)",
|
|
34
|
+
"Bash(node -c plugins/default-plugins.js && node -c src/core/plugin-manager.js && echo \"Syntax OK\")",
|
|
35
|
+
"Bash(node -c plugins/install-plugin.js && echo \"Syntax OK\")",
|
|
36
|
+
"Bash(node -c cli/src/ui/chat-ui.js && echo \"Syntax OK\")",
|
|
37
|
+
"Bash(node -c plugins/default-plugins.js && echo \"Syntax OK\")"
|
|
32
38
|
]
|
|
33
39
|
}
|
|
34
40
|
}
|
package/.env.example
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# ========== AI API Keys ==========
|
|
2
|
+
DEEPSEEK_API_KEY=sk-your-deepseek-api-key
|
|
3
|
+
MINIMAX_API_KEY=sk-your-minimax-api-key
|
|
4
|
+
|
|
5
|
+
# ========== Email Configuration ==========
|
|
6
|
+
# SMTP Settings (for sending emails)
|
|
7
|
+
SMTP_HOST=smtp.gmail.com
|
|
8
|
+
SMTP_PORT=587
|
|
9
|
+
SMTP_SECURE=false
|
|
10
|
+
SMTP_USER=your-email@gmail.com
|
|
11
|
+
SMTP_PASS=your-app-password
|
|
12
|
+
|
|
13
|
+
# IMAP Settings (for reading emails)
|
|
14
|
+
IMAP_HOST=imap.gmail.com
|
|
15
|
+
IMAP_PORT=993
|
|
16
|
+
IMAP_USER=your-email@gmail.com
|
|
17
|
+
IMAP_PASS=your-app-password
|
|
18
|
+
|
|
19
|
+
# Default sender email address
|
|
20
|
+
FROM_EMAIL=your-email@gmail.com
|
|
21
|
+
|
|
22
|
+
# ========== Telegram Bot (optional) ==========
|
|
23
|
+
TELEGRAM_BOT_TOKEN=your-telegram-bot-token
|
package/README.md
CHANGED
|
@@ -87,8 +87,27 @@ ai_provider: minimax
|
|
|
87
87
|
|
|
88
88
|
### 用户插件(.agent/plugins/)
|
|
89
89
|
|
|
90
|
+
插件支持两种结构:**文件夹结构**(推荐)和**单文件结构**。
|
|
91
|
+
|
|
92
|
+
#### 文件夹结构(推荐)
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
.agent/plugins/my-plugin/
|
|
96
|
+
├── package.json # 可选,main 字段指定入口
|
|
97
|
+
├── index.js # 默认入口
|
|
98
|
+
└── node_modules/ # 可选,插件私有依赖
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
```json
|
|
102
|
+
// package.json 示例
|
|
103
|
+
{
|
|
104
|
+
"name": "my-plugin",
|
|
105
|
+
"main": "index.js"
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
90
109
|
```javascript
|
|
91
|
-
// .agent/plugins/my-plugin.js
|
|
110
|
+
// .agent/plugins/my-plugin/index.js
|
|
92
111
|
module.exports = function(Plugin) {
|
|
93
112
|
return class MyPlugin extends Plugin {
|
|
94
113
|
constructor(config = {}) {
|
|
@@ -117,9 +136,17 @@ module.exports = function(Plugin) {
|
|
|
117
136
|
}
|
|
118
137
|
```
|
|
119
138
|
|
|
139
|
+
#### 单文件结构(兼容)
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
.agent/plugins/my-plugin.js
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
如果同时存在文件夹和同名 `.js` 文件,**文件夹优先**。
|
|
146
|
+
|
|
120
147
|
**注意**:如果插件需要第三方库(如 `zod`),需要先安装:
|
|
121
148
|
|
|
122
|
-
1.
|
|
149
|
+
1. 创建插件文件/文件夹
|
|
123
150
|
2. 调用 `install` 工具安装依赖
|
|
124
151
|
3. 热重载插件
|
|
125
152
|
|
package/SPEC.md
CHANGED
|
@@ -165,7 +165,9 @@ D:\code\vb-agent\
|
|
|
165
165
|
│ ├── rules-plugin.js # Rules规则引擎插件
|
|
166
166
|
│ ├── scheduler-plugin.js # Scheduler定时任务插件
|
|
167
167
|
│ ├── storage-plugin.js # Storage存储插件
|
|
168
|
-
│
|
|
168
|
+
│ ├── subagent-plugin.js # SubAgent子代理插件
|
|
169
|
+
│ ├── email.js # Email邮件插件
|
|
170
|
+
│ └── telegram-plugin.js # Telegram对话插件
|
|
169
171
|
├── examples/
|
|
170
172
|
│ ├── basic.js # 基础示例
|
|
171
173
|
│ ├── bootstrap.js # Bootstrap示例
|
|
@@ -182,6 +184,25 @@ D:\code\vb-agent\
|
|
|
182
184
|
|
|
183
185
|
## 四、核心模块
|
|
184
186
|
|
|
187
|
+
### 4.5 插件配置持久化
|
|
188
|
+
|
|
189
|
+
插件状态和配置自动保存到 `.agent/data/plugins-state.json`
|
|
190
|
+
|
|
191
|
+
```javascript
|
|
192
|
+
// 更新插件配置
|
|
193
|
+
framework.updatePluginConfig('telegram', { allowedChats: ['123'] })
|
|
194
|
+
|
|
195
|
+
// 启用/禁用插件
|
|
196
|
+
framework.enablePlugin('telegram')
|
|
197
|
+
framework.disablePlugin('telegram')
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
**保存的内容:**
|
|
201
|
+
- `enabled` - 插件启用状态
|
|
202
|
+
- `config` - 插件配置对象
|
|
203
|
+
|
|
204
|
+
**自动恢复:** 框架启动时自动加载保存的状态
|
|
205
|
+
|
|
185
206
|
### 4.1 Framework (src/core/framework.js)
|
|
186
207
|
|
|
187
208
|
**职责**:
|
|
@@ -278,6 +299,8 @@ const response = await agent.chat('你好')
|
|
|
278
299
|
'plugin:start' // 插件启动
|
|
279
300
|
'plugin:reload' // 插件重载
|
|
280
301
|
'plugin:uninstall' // 插件卸载
|
|
302
|
+
'plugin:enabled' // 插件启用
|
|
303
|
+
'plugin:disabled' // 插件禁用
|
|
281
304
|
'agent:message' // Agent消息
|
|
282
305
|
'agent:tool-call' // Agent调用工具
|
|
283
306
|
'agent:tool-result' // 工具执行结果
|
|
@@ -337,6 +360,40 @@ agent.chat('请重载 my-plugin 插件')
|
|
|
337
360
|
**内置工具**:
|
|
338
361
|
- `reload_plugins` - 热重载插件
|
|
339
362
|
- `list_plugins` - 列出已加载插件
|
|
363
|
+
- `enable_plugin` - 启用插件
|
|
364
|
+
- `disable_plugin` - 禁用插件
|
|
365
|
+
- `get_plugin_config` - 获取插件配置
|
|
366
|
+
- `update_plugin_config` - 更新插件配置
|
|
367
|
+
|
|
368
|
+
### 7.3 Email Plugin (plugins/email-plugin.js)
|
|
369
|
+
|
|
370
|
+
**功能**:
|
|
371
|
+
- SMTP 发送邮件
|
|
372
|
+
- IMAP 读取邮件
|
|
373
|
+
|
|
374
|
+
**工具**:
|
|
375
|
+
- `email_send` - 发送邮件
|
|
376
|
+
- `email_read` - 读取邮件
|
|
377
|
+
- `email_unread_count` - 未读数量
|
|
378
|
+
- `email_mark_read` - 标记已读
|
|
379
|
+
|
|
380
|
+
### 7.4 Telegram Plugin (plugins/telegram-plugin.js)
|
|
381
|
+
|
|
382
|
+
**功能**:
|
|
383
|
+
- Telegram Bot 对话
|
|
384
|
+
- 绑定主 Agent 持续对话
|
|
385
|
+
- 支持 MarkdownV2
|
|
386
|
+
- 图片/文档接收保存
|
|
387
|
+
|
|
388
|
+
**配置**:
|
|
389
|
+
```javascript
|
|
390
|
+
{
|
|
391
|
+
botToken: '...',
|
|
392
|
+
allowedChats: ['123'],
|
|
393
|
+
groupMode: false,
|
|
394
|
+
prefix: '/'
|
|
395
|
+
}
|
|
396
|
+
```
|
|
340
397
|
|
|
341
398
|
## 八、使用示例
|
|
342
399
|
|
|
@@ -437,16 +494,32 @@ class Framework {
|
|
|
437
494
|
- [x] Scheduler 定时任务 (`plugins/scheduler-plugin.js`) - Cron 调度
|
|
438
495
|
- [x] Storage 存储 (`plugins/storage-plugin.js`) - 键值对持久化存储
|
|
439
496
|
- [x] SubAgent 子Agent (`plugins/subagent-plugin.js`) - 子Agent隔离工具集
|
|
497
|
+
- [x] Email 插件 (`plugins/email.js`) - 邮件收发
|
|
498
|
+
- [x] Telegram 插件 (`plugins/telegram-plugin.js`) - Telegram Bot 对话
|
|
499
|
+
- [x] 插件配置持久化 - enabled/config 保存到 plugins-state.json
|
|
500
|
+
- [x] AI 热重载 - LLM 配置更新后自动刷新已有 Agent
|
|
440
501
|
|
|
441
502
|
## 十一、依赖
|
|
442
503
|
|
|
443
504
|
```json
|
|
444
505
|
{
|
|
445
506
|
"dependencies": {
|
|
507
|
+
"@ai-sdk/anthropic": "^3.0.58",
|
|
508
|
+
"@ai-sdk/mcp": "^1.0.25",
|
|
446
509
|
"@ai-sdk/openai": "^3.0.41",
|
|
447
510
|
"@ai-sdk/openai-compatible": "^2.0.35",
|
|
511
|
+
"@anthropic-ai/sdk": "^0.39.0",
|
|
512
|
+
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
448
513
|
"ai": "^6.0.116",
|
|
449
|
-
"
|
|
514
|
+
"dotenv": "^17.3.1",
|
|
515
|
+
"imap": "^0.8.19",
|
|
516
|
+
"mailparser": "^3.7.2",
|
|
517
|
+
"marked": "^11.2.0",
|
|
518
|
+
"marked-terminal": "6",
|
|
519
|
+
"node-cron": "^4.2.1",
|
|
520
|
+
"node-telegram-bot-api": "^0.67.0",
|
|
521
|
+
"nodemailer": "^6.10.0",
|
|
522
|
+
"zod": "^3.24.0"
|
|
450
523
|
}
|
|
451
524
|
}
|
|
452
525
|
```
|
package/cli/src/ui/chat-ui.js
CHANGED
|
@@ -22,6 +22,10 @@ class ChatUI extends EventEmitter {
|
|
|
22
22
|
this.lastKeyTime = 0
|
|
23
23
|
this.pasteBuffer = ''
|
|
24
24
|
this.isPasting = false
|
|
25
|
+
|
|
26
|
+
// 多行输入:记录上次 Enter 时间,检测连续两次空回车
|
|
27
|
+
this.lastEnterTime = 0
|
|
28
|
+
this.LINE_ENDING_INTERVAL = 800 // 毫秒内连续两次空回车结束输入
|
|
25
29
|
}
|
|
26
30
|
|
|
27
31
|
/**
|
|
@@ -73,14 +77,14 @@ class ChatUI extends EventEmitter {
|
|
|
73
77
|
*/
|
|
74
78
|
printWelcome() {
|
|
75
79
|
console.log(`${colored('Foliko', CYAN)} - 持续对话聊天`)
|
|
76
|
-
console.log(`${colored('Ctrl+C', DIM)} 退出 | ${colored('
|
|
80
|
+
console.log(`${colored('Ctrl+C', DIM)} 退出 | ${colored('Enter', DIM)} 换行 | ${colored('双Enter', DIM)} 发送\n`)
|
|
77
81
|
}
|
|
78
82
|
|
|
79
83
|
/**
|
|
80
84
|
* 显示提示符
|
|
81
85
|
*/
|
|
82
86
|
prompt() {
|
|
83
|
-
const prefix = this.isFirstLine ? colored('
|
|
87
|
+
const prefix = this.isFirstLine ? colored('> ', GREEN) : colored('- ', DIM)
|
|
84
88
|
process.stdout.write(`\r${CLEAR_LINE}${prefix}${this.currentLine}`)
|
|
85
89
|
}
|
|
86
90
|
|
|
@@ -157,12 +161,46 @@ class ChatUI extends EventEmitter {
|
|
|
157
161
|
* 处理发送
|
|
158
162
|
*/
|
|
159
163
|
async handleSubmit() {
|
|
164
|
+
const now = Date.now()
|
|
160
165
|
const content = this.lines.length > 0
|
|
161
166
|
? [...this.lines, this.currentLine].join('\n')
|
|
162
167
|
: this.currentLine
|
|
163
168
|
|
|
164
169
|
const trimmed = content.trim()
|
|
165
170
|
|
|
171
|
+
// 检测连续两次空回车(多行输入结束)
|
|
172
|
+
if (this.currentLine.trim() === '' && this.lines.length > 0) {
|
|
173
|
+
if (now - this.lastEnterTime < this.LINE_ENDING_INTERVAL) {
|
|
174
|
+
// 第二次空回车,结束输入
|
|
175
|
+
const finalContent = this.lines.join('\n').trim()
|
|
176
|
+
this.resetInput()
|
|
177
|
+
console.log()
|
|
178
|
+
|
|
179
|
+
if (!finalContent) {
|
|
180
|
+
this.prompt()
|
|
181
|
+
return
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
await this.sendMessage(finalContent)
|
|
185
|
+
return
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
this.lastEnterTime = now
|
|
189
|
+
|
|
190
|
+
// 输入 !! 立即结束多行输入
|
|
191
|
+
if (this.currentLine.trim() === '!!') {
|
|
192
|
+
const finalContent = this.lines.join('\n').trim()
|
|
193
|
+
this.resetInput()
|
|
194
|
+
console.log()
|
|
195
|
+
|
|
196
|
+
if (finalContent) {
|
|
197
|
+
await this.sendMessage(finalContent)
|
|
198
|
+
} else {
|
|
199
|
+
this.prompt()
|
|
200
|
+
}
|
|
201
|
+
return
|
|
202
|
+
}
|
|
203
|
+
|
|
166
204
|
// 显示空行
|
|
167
205
|
console.log()
|
|
168
206
|
|
|
@@ -199,6 +237,7 @@ class ChatUI extends EventEmitter {
|
|
|
199
237
|
this.pasteId = 0
|
|
200
238
|
this.isPasting = false
|
|
201
239
|
this.pasteBuffer = ''
|
|
240
|
+
this.lastEnterTime = 0
|
|
202
241
|
}
|
|
203
242
|
|
|
204
243
|
/**
|
package/docs/quick-reference.md
CHANGED
|
@@ -40,19 +40,34 @@ const result = await agent.chat('你好')
|
|
|
40
40
|
| `execute_command` | 执行命令 |
|
|
41
41
|
| `schedule_once` | 定时任务 |
|
|
42
42
|
| `think_now` | 主动思考 |
|
|
43
|
+
| `email_send` | 发送邮件 |
|
|
44
|
+
| `email_read` | 读取邮件 |
|
|
45
|
+
| `enable_plugin` | 启用插件 |
|
|
46
|
+
| `disable_plugin` | 禁用插件 |
|
|
47
|
+
| `update_plugin_config` | 更新插件配置 |
|
|
43
48
|
|
|
44
49
|
## 插件位置
|
|
45
50
|
|
|
46
51
|
- 内置插件:`plugins/`
|
|
47
52
|
- 用户插件:`.agent/plugins/`
|
|
48
53
|
|
|
49
|
-
##
|
|
54
|
+
## 插件管理
|
|
50
55
|
|
|
51
56
|
```javascript
|
|
52
|
-
//
|
|
57
|
+
// 重启插件
|
|
53
58
|
await framework.executeTool('reload_plugins', {})
|
|
54
|
-
|
|
55
|
-
|
|
59
|
+
await framework.executeTool('reload_plugins', { pluginName: 'telegram' })
|
|
60
|
+
|
|
61
|
+
// 启用/禁用插件
|
|
62
|
+
await framework.executeTool('enable_plugin', { name: 'telegram' })
|
|
63
|
+
await framework.executeTool('disable_plugin', { name: 'telegram' })
|
|
64
|
+
|
|
65
|
+
// 更新插件配置(持久化)
|
|
66
|
+
await framework.executeTool('update_plugin_config', {
|
|
67
|
+
name: 'telegram',
|
|
68
|
+
config: { allowedChats: ['123'], groupMode: true }
|
|
69
|
+
})
|
|
70
|
+
await framework.executeTool('get_plugin_config', { name: 'telegram' })
|
|
56
71
|
```
|
|
57
72
|
|
|
58
73
|
## 事件监听
|
|
@@ -129,3 +144,14 @@ agent.getStatus() // 'idle' | 'busy' | 'error'
|
|
|
129
144
|
agent.resetStatus() // 重置状态
|
|
130
145
|
agent.clearHistory() // 清空历史
|
|
131
146
|
```
|
|
147
|
+
|
|
148
|
+
## 配置持久化
|
|
149
|
+
|
|
150
|
+
插件配置自动保存到 `.agent/data/plugins-state.json`
|
|
151
|
+
|
|
152
|
+
| 文件 | 用途 |
|
|
153
|
+
|------|------|
|
|
154
|
+
| `.agent/data/plugins-state.json` | 插件启用状态和配置 |
|
|
155
|
+
| `.agent/data/storage.json` | 键值存储数据 |
|
|
156
|
+
| `.agent/data/telegram_images/` | Telegram 接收的图片 |
|
|
157
|
+
| `.agent/data/telegram_documents/` | Telegram 接收的文档 |
|
package/docs/user-manual.md
CHANGED
|
@@ -244,6 +244,22 @@ await framework.loadPlugin(new AIPlugin({
|
|
|
244
244
|
}))
|
|
245
245
|
```
|
|
246
246
|
|
|
247
|
+
**热重载支持:** 更新 AI 配置后执行 `reload_plugins('ai')`,所有已有 Agent 会自动使用新的 LLM 设置。
|
|
248
|
+
|
|
249
|
+
```javascript
|
|
250
|
+
// 1. 更新 LLM 配置
|
|
251
|
+
await framework.executeTool('update_plugin_config', {
|
|
252
|
+
name: 'ai',
|
|
253
|
+
config: {
|
|
254
|
+
model: 'gpt-4o',
|
|
255
|
+
apiKey: 'new-key'
|
|
256
|
+
}
|
|
257
|
+
})
|
|
258
|
+
|
|
259
|
+
// 2. 热重载 AI 插件
|
|
260
|
+
await framework.executeTool('reload_plugins', { pluginName: 'ai' })
|
|
261
|
+
```
|
|
262
|
+
|
|
247
263
|
### 4.2 存储插件 (storage-plugin)
|
|
248
264
|
|
|
249
265
|
键值对存储,支持 JSON 文件持久化。
|
|
@@ -263,9 +279,13 @@ storage_clear() // 清空存储
|
|
|
263
279
|
|
|
264
280
|
```javascript
|
|
265
281
|
// 注册的工具
|
|
266
|
-
reload_plugins(pluginName?) //
|
|
267
|
-
list_plugins()
|
|
268
|
-
list_tools()
|
|
282
|
+
reload_plugins(pluginName?) // 热重载插件(可选指定插件名)
|
|
283
|
+
list_plugins() // 列出已加载插件
|
|
284
|
+
list_tools() // 列出所有工具
|
|
285
|
+
enable_plugin(name) // 启用指定插件
|
|
286
|
+
disable_plugin(name) // 禁用指定插件
|
|
287
|
+
get_plugin_config(name) // 获取插件当前配置
|
|
288
|
+
update_plugin_config(name, config) // 更新插件配置(持久化)
|
|
269
289
|
```
|
|
270
290
|
|
|
271
291
|
### 4.4 文件系统插件 (file-system-plugin)
|
|
@@ -461,6 +481,132 @@ loadSkill(skill) // 加载指定技能
|
|
|
461
481
|
// 技能存放在 skills/ 或 .agent/skills/ 目录
|
|
462
482
|
```
|
|
463
483
|
|
|
484
|
+
### 4.14 Email 插件 (email-plugin)
|
|
485
|
+
|
|
486
|
+
邮件收发插件,支持 SMTP 发送和 IMAP 读取。
|
|
487
|
+
|
|
488
|
+
```javascript
|
|
489
|
+
// 配置
|
|
490
|
+
await framework.loadPlugin(new EmailPlugin({
|
|
491
|
+
smtp_host: 'smtp.gmail.com',
|
|
492
|
+
smtp_port: 587,
|
|
493
|
+
smtp_secure: false,
|
|
494
|
+
smtp_user: 'your-email@gmail.com',
|
|
495
|
+
smtp_pass: 'your-app-password',
|
|
496
|
+
imap_host: 'imap.gmail.com',
|
|
497
|
+
imap_port: 993,
|
|
498
|
+
imap_user: 'your-email@gmail.com',
|
|
499
|
+
imap_pass: 'your-app-password',
|
|
500
|
+
from_email: 'your-email@gmail.com'
|
|
501
|
+
}))
|
|
502
|
+
|
|
503
|
+
// 或通过工具配置
|
|
504
|
+
email_configure({
|
|
505
|
+
smtp_host: 'smtp.gmail.com',
|
|
506
|
+
smtp_user: 'your-email@gmail.com',
|
|
507
|
+
smtp_pass: 'your-app-password'
|
|
508
|
+
})
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
**注册的工具:**
|
|
512
|
+
|
|
513
|
+
| 工具 | 说明 |
|
|
514
|
+
|------|------|
|
|
515
|
+
| `email_send` | 发送电子邮件 |
|
|
516
|
+
| `email_read` | 读取电子邮件(IMAP) |
|
|
517
|
+
| `email_unread_count` | 获取未读邮件数量 |
|
|
518
|
+
| `email_mark_read` | 标记邮件为已读 |
|
|
519
|
+
| `email_configure` | 配置邮箱连接参数 |
|
|
520
|
+
|
|
521
|
+
```javascript
|
|
522
|
+
// 发送邮件
|
|
523
|
+
email_send({
|
|
524
|
+
to: 'recipient@example.com',
|
|
525
|
+
subject: '主题',
|
|
526
|
+
body: '正文内容',
|
|
527
|
+
cc: 'cc@example.com', // 可选
|
|
528
|
+
isHtml: false
|
|
529
|
+
})
|
|
530
|
+
|
|
531
|
+
// 读取邮件
|
|
532
|
+
email_read({
|
|
533
|
+
box: 'INBOX',
|
|
534
|
+
limit: 10,
|
|
535
|
+
unreadOnly: false
|
|
536
|
+
})
|
|
537
|
+
|
|
538
|
+
// 获取未读数量
|
|
539
|
+
email_unread_count({ box: 'INBOX' })
|
|
540
|
+
|
|
541
|
+
// 标记为已读
|
|
542
|
+
email_mark_read({ messageId: '12345' })
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
### 4.15 Telegram 插件 (telegram-plugin)
|
|
546
|
+
|
|
547
|
+
Telegram 对话插件,绑定主 Agent 进行持续对话。
|
|
548
|
+
|
|
549
|
+
```javascript
|
|
550
|
+
// 配置
|
|
551
|
+
await framework.loadPlugin(new TelegramPlugin({
|
|
552
|
+
botToken: 'YOUR_BOT_TOKEN', // 必需
|
|
553
|
+
allowedChats: ['123456789'], // 可选:允许的聊天ID
|
|
554
|
+
groupMode: false, // 可选:是否启用群组模式
|
|
555
|
+
prefix: '/', // 可选:命令前缀
|
|
556
|
+
systemPrompt: '你是一个有帮助的AI助手。'
|
|
557
|
+
}))
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
**功能特性:**
|
|
561
|
+
|
|
562
|
+
- 支持私聊和群组模式
|
|
563
|
+
- MarkdownV2 格式支持(自动转义特殊字符)
|
|
564
|
+
- 持续对话(基于 sessionId)
|
|
565
|
+
- 支持图片和文档接收
|
|
566
|
+
- 媒体文件自动保存到 `.agent/data/`
|
|
567
|
+
|
|
568
|
+
**命令:**
|
|
569
|
+
|
|
570
|
+
| 命令 | 说明 |
|
|
571
|
+
|------|------|
|
|
572
|
+
| `/start` | 显示帮助信息 |
|
|
573
|
+
| `/clear` | 清除对话历史 |
|
|
574
|
+
| `/history` | 查看对话状态 |
|
|
575
|
+
|
|
576
|
+
### 4.16 插件管理扩展
|
|
577
|
+
|
|
578
|
+
#### 插件启用/禁用
|
|
579
|
+
|
|
580
|
+
```javascript
|
|
581
|
+
// 启用插件
|
|
582
|
+
await framework.enablePlugin('telegram')
|
|
583
|
+
|
|
584
|
+
// 禁用插件
|
|
585
|
+
await framework.disablePlugin('telegram')
|
|
586
|
+
```
|
|
587
|
+
|
|
588
|
+
#### 插件配置更新
|
|
589
|
+
|
|
590
|
+
```javascript
|
|
591
|
+
// 更新插件配置(会自动保存到 .agent/data/plugins-state.json)
|
|
592
|
+
await framework.executeTool('update_plugin_config', {
|
|
593
|
+
name: 'telegram',
|
|
594
|
+
config: {
|
|
595
|
+
allowedChats: ['123456789', '987654321'],
|
|
596
|
+
groupMode: true
|
|
597
|
+
}
|
|
598
|
+
})
|
|
599
|
+
|
|
600
|
+
// 获取插件当前配置
|
|
601
|
+
await framework.executeTool('get_plugin_config', {
|
|
602
|
+
name: 'telegram'
|
|
603
|
+
})
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
**配置持久化:**
|
|
607
|
+
- 插件的 `enabled` 状态和 `config` 会自动保存到 `.agent/data/plugins-state.json`
|
|
608
|
+
- 重启后自动恢复配置
|
|
609
|
+
|
|
464
610
|
---
|
|
465
611
|
|
|
466
612
|
## 5. 插件开发
|
|
@@ -792,6 +938,8 @@ agent.emit('eventName', { key: 'value' })
|
|
|
792
938
|
| `plugin:loaded` | `plugin` | 插件加载完成 |
|
|
793
939
|
| `plugin:unloaded` | `plugin` | 插件卸载 |
|
|
794
940
|
| `plugin:reloaded` | `plugin` | 插件重载 |
|
|
941
|
+
| `plugin:enabled` | `plugin` | 插件启用 |
|
|
942
|
+
| `plugin:disabled` | `plugin` | 插件禁用 |
|
|
795
943
|
| `tool:registered` | `tool` | 工具注册 |
|
|
796
944
|
| `agent:created` | `agent` | Agent 创建 |
|
|
797
945
|
|
|
@@ -998,6 +1146,13 @@ await framework.loadPlugin(plugin)
|
|
|
998
1146
|
await framework.reloadPlugin(name)
|
|
999
1147
|
await framework.reloadAllPlugins()
|
|
1000
1148
|
|
|
1149
|
+
// 启用/禁用插件
|
|
1150
|
+
await framework.enablePlugin(name)
|
|
1151
|
+
await framework.disablePlugin(name)
|
|
1152
|
+
|
|
1153
|
+
// 更新插件配置
|
|
1154
|
+
framework.updatePluginConfig(name, config)
|
|
1155
|
+
|
|
1001
1156
|
// 执行工具
|
|
1002
1157
|
const result = await framework.executeTool(name, args)
|
|
1003
1158
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* 支持多行输入:连续按两次回车结束输入
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
const { Framework } = require('
|
|
7
|
+
const { Framework } = require('../src')
|
|
8
8
|
const readline = require('readline')
|
|
9
9
|
require('dotenv').config()
|
|
10
10
|
|
|
@@ -52,7 +52,7 @@ async function main() {
|
|
|
52
52
|
const lines = []
|
|
53
53
|
|
|
54
54
|
const question = () => {
|
|
55
|
-
rl.question(lines.length === 0 ? '
|
|
55
|
+
rl.question(lines.length === 0 ? '> ' : '- ', (input) => {
|
|
56
56
|
// 输入 !! 立即结束
|
|
57
57
|
if (input.trim() === '!!') {
|
|
58
58
|
const result = lines.join('\n').trim()
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* MCP 插件测试脚本
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
const { Framework } = require('
|
|
6
|
-
const { MCPExecutorPlugin } = require('
|
|
5
|
+
const { Framework } = require('../src')
|
|
6
|
+
const { MCPExecutorPlugin } = require('../src/executors/mcp-executor')
|
|
7
7
|
|
|
8
8
|
async function test() {
|
|
9
9
|
console.log('=== MCP Plugin Test ===\n')
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* MCP mcp_reload 功能测试
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
const { Framework } = require('
|
|
6
|
-
const { MCPExecutorPlugin } = require('
|
|
5
|
+
const { Framework } = require('../src')
|
|
6
|
+
const { MCPExecutorPlugin } = require('../src/executors/mcp-executor')
|
|
7
7
|
const fs = require('fs')
|
|
8
8
|
const path = require('path')
|
|
9
9
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "foliko",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.9",
|
|
4
4
|
"description": "简约的插件化 Agent 框架",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -28,10 +28,13 @@
|
|
|
28
28
|
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
29
29
|
"ai": "^6.0.116",
|
|
30
30
|
"dotenv": "^17.3.1",
|
|
31
|
+
"imap": "^0.8.19",
|
|
32
|
+
"mailparser": "^3.7.2",
|
|
31
33
|
"marked": "^11.2.0",
|
|
32
34
|
"marked-terminal": "6",
|
|
33
35
|
"node-cron": "^4.2.1",
|
|
34
36
|
"node-telegram-bot-api": "^0.67.0",
|
|
37
|
+
"nodemailer": "^6.10.0",
|
|
35
38
|
"zod": "^3.24.0"
|
|
36
39
|
}
|
|
37
40
|
}
|
package/plugins/ai-plugin.js
CHANGED
|
@@ -79,6 +79,14 @@ class AIPlugin extends Plugin {
|
|
|
79
79
|
console.log('[AIPlugin] Reloading...')
|
|
80
80
|
this._framework = framework
|
|
81
81
|
this._initAIClient()
|
|
82
|
+
|
|
83
|
+
// 刷新所有已有 Agent 的 AI client
|
|
84
|
+
for (const agent of framework._agents || []) {
|
|
85
|
+
if (agent._chatHandler) {
|
|
86
|
+
agent._chatHandler.setAIClient(this._aiClient)
|
|
87
|
+
console.log(`[AIPlugin] Refreshed AI client for agent: ${agent.name}`)
|
|
88
|
+
}
|
|
89
|
+
}
|
|
82
90
|
}
|
|
83
91
|
|
|
84
92
|
uninstall(framework) {
|