foliko 1.0.43 → 1.0.44
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/.dockerignore +45 -0
- package/.env.example +10 -0
- package/Dockerfile +35 -0
- package/docker-compose.yml +33 -0
- package/package.json +1 -1
- package/plugins/feishu-plugin.js +26 -0
- package/plugins/telegram-plugin.js +26 -0
- package/plugins/web-plugin.js +19 -4
- package/plugins/weixin-plugin.js +33 -0
- package/test.txt +3 -0
package/.dockerignore
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# 依赖
|
|
2
|
+
node_modules
|
|
3
|
+
.agent/node_modules
|
|
4
|
+
|
|
5
|
+
# 日志
|
|
6
|
+
*.log
|
|
7
|
+
npm-debug.log*
|
|
8
|
+
|
|
9
|
+
# 环境变量(包含敏感信息)
|
|
10
|
+
.env
|
|
11
|
+
.env.local
|
|
12
|
+
|
|
13
|
+
# Git
|
|
14
|
+
.git
|
|
15
|
+
.gitignore
|
|
16
|
+
|
|
17
|
+
# IDE
|
|
18
|
+
.idea
|
|
19
|
+
.vscode
|
|
20
|
+
*.swp
|
|
21
|
+
*.swo
|
|
22
|
+
|
|
23
|
+
# 文档(可选保留)
|
|
24
|
+
*.md
|
|
25
|
+
!README.md
|
|
26
|
+
|
|
27
|
+
# 测试
|
|
28
|
+
test
|
|
29
|
+
tests
|
|
30
|
+
coverage
|
|
31
|
+
|
|
32
|
+
# 临时文件
|
|
33
|
+
tmp
|
|
34
|
+
temp
|
|
35
|
+
*.tmp
|
|
36
|
+
|
|
37
|
+
# Docker 相关(避免递归)
|
|
38
|
+
Dockerfile*
|
|
39
|
+
docker-compose*
|
|
40
|
+
.dockerignore
|
|
41
|
+
|
|
42
|
+
# CI/CD
|
|
43
|
+
.github
|
|
44
|
+
.gitlab-ci.yml
|
|
45
|
+
.travis.yml
|
package/.env.example
CHANGED
|
@@ -38,3 +38,13 @@ FROM_EMAIL=your-email@gmail.com
|
|
|
38
38
|
|
|
39
39
|
# ========== Telegram Bot (optional) ==========
|
|
40
40
|
TELEGRAM_BOT_TOKEN=your-telegram-bot-token
|
|
41
|
+
|
|
42
|
+
# ========== Web Server (optional) ==========
|
|
43
|
+
# Web 服务端口,默认 8088
|
|
44
|
+
WEB_PORT=8088
|
|
45
|
+
|
|
46
|
+
# Web 服务主机,默认 127.0.0.1
|
|
47
|
+
WEB_HOST=127.0.0.1
|
|
48
|
+
|
|
49
|
+
# 公网访问的 base URL(用于生成 webhook URL 等),不设置则使用 host:port
|
|
50
|
+
WEB_BASE_URL=https://your-domain.com
|
package/Dockerfile
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# ========== Foliko - 插件化 Agent 框架 ==========
|
|
2
|
+
# 基于 Node.js 20 LTS
|
|
3
|
+
|
|
4
|
+
FROM node:20-slim
|
|
5
|
+
|
|
6
|
+
# 安装 Python 和构建工具(部分 npm 包需要编译)
|
|
7
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
8
|
+
build-essential \
|
|
9
|
+
python3 \
|
|
10
|
+
python3-pip \
|
|
11
|
+
curl \
|
|
12
|
+
git \
|
|
13
|
+
&& rm -rf /var/lib/apt/lists/* \
|
|
14
|
+
&& ln -sf /usr/bin/python3 /usr/bin/python
|
|
15
|
+
|
|
16
|
+
# 安装 uv(快速的 Python 包管理器)
|
|
17
|
+
RUN pip3 install uv
|
|
18
|
+
|
|
19
|
+
# 设置工作目录
|
|
20
|
+
WORKDIR /app
|
|
21
|
+
|
|
22
|
+
# 全局安装 foliko CLI
|
|
23
|
+
RUN npm install -g foliko
|
|
24
|
+
|
|
25
|
+
# 暴露端口
|
|
26
|
+
# 8088: Web 服务端口
|
|
27
|
+
EXPOSE 8088
|
|
28
|
+
|
|
29
|
+
# 环境变量(可以在 docker-compose 或运行时覆盖)
|
|
30
|
+
ENV NODE_ENV=production
|
|
31
|
+
ENV WEB_PORT=8088
|
|
32
|
+
ENV WEB_HOST=127.0.0.1
|
|
33
|
+
|
|
34
|
+
# 默认命令:运行聊天界面
|
|
35
|
+
CMD ["foliko", "chat"]
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# ========== Foliko Docker Compose ==========
|
|
2
|
+
# 使用方式: docker-compose up -d
|
|
3
|
+
|
|
4
|
+
services:
|
|
5
|
+
foliko:
|
|
6
|
+
build: .
|
|
7
|
+
container_name: foliko-agent
|
|
8
|
+
restart: unless-stopped
|
|
9
|
+
ports:
|
|
10
|
+
- "8088:8088"
|
|
11
|
+
environment:
|
|
12
|
+
# AI 配置
|
|
13
|
+
- FOLIKO_PROVIDER=${FOLIKO_PROVIDER:-minimax}
|
|
14
|
+
- FOLIKO_MODEL=${FOLIKO_MODEL:-}
|
|
15
|
+
- FOLIKO_BASE_URL=${FOLIKO_BASE_URL:-}
|
|
16
|
+
- FOLIKO_API_KEY=${FOLIKO_API_KEY:-}
|
|
17
|
+
# Web 服务配置
|
|
18
|
+
- WEB_PORT=8088
|
|
19
|
+
- WEB_HOST=0.0.0.0
|
|
20
|
+
- WEB_BASE_URL=${WEB_BASE_URL:-}
|
|
21
|
+
# Telegram 配置(可选)
|
|
22
|
+
- TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN:-}
|
|
23
|
+
# 飞书配置(可选)
|
|
24
|
+
- FEISHU_APP_ID=${FEISHU_APP_ID:-}
|
|
25
|
+
- FEISHU_APP_SECRET=${FEISHU_APP_SECRET:-}
|
|
26
|
+
volumes:
|
|
27
|
+
# 持久化数据
|
|
28
|
+
- foliko-data:/app/.agent/data
|
|
29
|
+
tty: true
|
|
30
|
+
stdin_open: true
|
|
31
|
+
|
|
32
|
+
volumes:
|
|
33
|
+
foliko-data:
|
package/package.json
CHANGED
package/plugins/feishu-plugin.js
CHANGED
|
@@ -105,6 +105,11 @@ class FeishuPlugin extends Plugin {
|
|
|
105
105
|
this._framework.on('scheduler:reminder', async (data) => {
|
|
106
106
|
await this._handleScheduledReminder(data)
|
|
107
107
|
})
|
|
108
|
+
|
|
109
|
+
// 监听 webhook 事件
|
|
110
|
+
this._framework.on('webhook:received', async (data) => {
|
|
111
|
+
await this._handleWebhookNotification(data)
|
|
112
|
+
})
|
|
108
113
|
}
|
|
109
114
|
|
|
110
115
|
console.log('[Feishu] WebSocket client started')
|
|
@@ -245,6 +250,27 @@ class FeishuPlugin extends Plugin {
|
|
|
245
250
|
}
|
|
246
251
|
}
|
|
247
252
|
|
|
253
|
+
/**
|
|
254
|
+
* 处理 webhook 通知
|
|
255
|
+
*/
|
|
256
|
+
async _handleWebhookNotification(data) {
|
|
257
|
+
const { data: webhookData, response, sessionId } = data
|
|
258
|
+
|
|
259
|
+
if (!sessionId || !sessionId.startsWith('feishu_')) {
|
|
260
|
+
return
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const openId = sessionId.replace('feishu_', '')
|
|
264
|
+
const notificationText = `📥 [Webhook 接收]\n\n路径: ${webhookData.path}\n方法: ${webhookData.method}\n\n处理结果: ${response || '处理中...'}`
|
|
265
|
+
|
|
266
|
+
try {
|
|
267
|
+
await this._sendTextMessage(openId, notificationText)
|
|
268
|
+
console.log(`[Feishu] Webhook notification sent to ${openId}`)
|
|
269
|
+
} catch (err) {
|
|
270
|
+
console.error(`[Feishu] Failed to send webhook notification:`, err.message)
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
248
274
|
async _processChat(openId, text, originalMsg) {
|
|
249
275
|
const sessionInfo = this._getSessionAgent(openId)
|
|
250
276
|
if (!sessionInfo) return
|
|
@@ -102,6 +102,11 @@ class TelegramPlugin extends Plugin {
|
|
|
102
102
|
this._framework.on('scheduler:reminder', async (data) => {
|
|
103
103
|
await this._handleScheduledReminder(data)
|
|
104
104
|
})
|
|
105
|
+
|
|
106
|
+
// 监听 webhook 事件
|
|
107
|
+
this._framework.on('webhook:received', async (data) => {
|
|
108
|
+
await this._handleWebhookNotification(data)
|
|
109
|
+
})
|
|
105
110
|
}
|
|
106
111
|
} catch (err) {
|
|
107
112
|
console.error('[Telegram] Failed to initialize bot:', err.message)
|
|
@@ -140,6 +145,27 @@ class TelegramPlugin extends Plugin {
|
|
|
140
145
|
}
|
|
141
146
|
}
|
|
142
147
|
|
|
148
|
+
/**
|
|
149
|
+
* 处理 webhook 通知
|
|
150
|
+
*/
|
|
151
|
+
async _handleWebhookNotification(data) {
|
|
152
|
+
const { data: webhookData, response, sessionId } = data
|
|
153
|
+
|
|
154
|
+
if (!sessionId || !sessionId.startsWith('telegram_')) {
|
|
155
|
+
return
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const chatId = sessionId.replace('telegram_', '')
|
|
159
|
+
const notificationText = `📥 [Webhook 接收]\n\n路径: ${webhookData.path}\n方法: ${webhookData.method}\n\n处理结果: ${response || '处理中...'}`
|
|
160
|
+
|
|
161
|
+
try {
|
|
162
|
+
await this._bot.sendMessage(chatId, notificationText)
|
|
163
|
+
console.log(`[Telegram] Webhook notification sent to chat ${chatId}`)
|
|
164
|
+
} catch (err) {
|
|
165
|
+
console.error(`[Telegram] Failed to send webhook notification:`, err.message)
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
143
169
|
_getMainAgent() {
|
|
144
170
|
if (this._framework._mainAgent) return this._framework._mainAgent
|
|
145
171
|
const agents = this._framework._agents || []
|
package/plugins/web-plugin.js
CHANGED
|
@@ -202,7 +202,22 @@ class WebPlugin extends Plugin {
|
|
|
202
202
|
|
|
203
203
|
// 1. 静态文件
|
|
204
204
|
const staticResult = this._serveStatic(pathname)
|
|
205
|
-
if (staticResult)
|
|
205
|
+
if (staticResult) {
|
|
206
|
+
if (staticResult.type === 'file') {
|
|
207
|
+
return c.newResponse(staticResult.content, {
|
|
208
|
+
headers: { 'Content-Type': staticResult.contentType }
|
|
209
|
+
})
|
|
210
|
+
}
|
|
211
|
+
if (staticResult.type === 'notFound') {
|
|
212
|
+
return c.json({ error: 'Not Found' }, 404)
|
|
213
|
+
}
|
|
214
|
+
if (staticResult.type === 'forbidden') {
|
|
215
|
+
return c.json({ error: 'Forbidden' }, 403)
|
|
216
|
+
}
|
|
217
|
+
if (staticResult.type === 'error') {
|
|
218
|
+
return c.json({ error: staticResult.message }, 500)
|
|
219
|
+
}
|
|
220
|
+
}
|
|
206
221
|
|
|
207
222
|
// 2. Webhook(精确匹配)
|
|
208
223
|
const webhook = this._webhooks.get(pathname)
|
|
@@ -261,7 +276,7 @@ class WebPlugin extends Plugin {
|
|
|
261
276
|
const finalSessionId = sessionId || `web_${Date.now()}`
|
|
262
277
|
|
|
263
278
|
// 触发 webhook 接收事件
|
|
264
|
-
this._framework.emit('webhook:received', { webhook, data: webhookData })
|
|
279
|
+
this._framework.emit('webhook:received', { webhook, data: webhookData, sessionId: finalSessionId })
|
|
265
280
|
|
|
266
281
|
if (!webhook.awaitResponse) {
|
|
267
282
|
// 不等待,立即返回
|
|
@@ -281,7 +296,7 @@ class WebPlugin extends Plugin {
|
|
|
281
296
|
}
|
|
282
297
|
|
|
283
298
|
// 触发 webhook 处理完成事件
|
|
284
|
-
this._framework.emit('webhook:received', { webhook, data: webhookData, response: responseText })
|
|
299
|
+
this._framework.emit('webhook:received', { webhook, data: webhookData, response: responseText, sessionId: finalSessionId })
|
|
285
300
|
}).catch(err => {
|
|
286
301
|
console.error('[Web] Webhook error:', err.message)
|
|
287
302
|
})
|
|
@@ -307,7 +322,7 @@ class WebPlugin extends Plugin {
|
|
|
307
322
|
}
|
|
308
323
|
|
|
309
324
|
// 触发 webhook 处理完成事件
|
|
310
|
-
this._framework.emit('webhook:received', { webhook, data: webhookData, response: responseText })
|
|
325
|
+
this._framework.emit('webhook:received', { webhook, data: webhookData, response: responseText, sessionId: finalSessionId })
|
|
311
326
|
|
|
312
327
|
return { success: true, message: 'Webhook processed', response: responseText }
|
|
313
328
|
} catch (err) {
|
package/plugins/weixin-plugin.js
CHANGED
|
@@ -74,6 +74,12 @@ class WeixinPlugin extends Plugin {
|
|
|
74
74
|
console.log('[WeChat] Received scheduler reminder:', data)
|
|
75
75
|
await this._handleScheduledReminder(data)
|
|
76
76
|
})
|
|
77
|
+
|
|
78
|
+
// 监听 webhook 事件
|
|
79
|
+
this._framework.on('webhook:received', async (data) => {
|
|
80
|
+
console.log('[WeChat] Received webhook event:', data)
|
|
81
|
+
await this._handleWebhookNotification(data)
|
|
82
|
+
})
|
|
77
83
|
}
|
|
78
84
|
|
|
79
85
|
// 异步初始化 Bot
|
|
@@ -334,6 +340,33 @@ class WeixinPlugin extends Plugin {
|
|
|
334
340
|
}
|
|
335
341
|
}
|
|
336
342
|
|
|
343
|
+
/**
|
|
344
|
+
* 处理 webhook 通知
|
|
345
|
+
*/
|
|
346
|
+
async _handleWebhookNotification(data) {
|
|
347
|
+
const { data: webhookData, response, sessionId } = data
|
|
348
|
+
|
|
349
|
+
if (!this._bot) {
|
|
350
|
+
console.warn('[WeChat] Bot not ready, cannot send webhook notification')
|
|
351
|
+
return
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// 只处理 weixin 相关的 session
|
|
355
|
+
if (!sessionId || !sessionId.startsWith('weixin_')) {
|
|
356
|
+
return
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
const userId = sessionId.replace('weixin_', '')
|
|
360
|
+
const notificationText = `📥 [Webhook 接收]\n\n路径: ${webhookData.path}\n方法: ${webhookData.method}\n\n处理结果: ${response || '处理中...'}`
|
|
361
|
+
|
|
362
|
+
try {
|
|
363
|
+
await this._bot.sendText(userId, notificationText)
|
|
364
|
+
console.log(`[WeChat] Webhook notification sent to user ${userId}`)
|
|
365
|
+
} catch (err) {
|
|
366
|
+
console.error(`[WeChat] Failed to send webhook notification:`, err.message)
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
337
370
|
/**
|
|
338
371
|
* 获取插件状态
|
|
339
372
|
*/
|
package/test.txt
ADDED