foliko 1.0.54 → 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/package.json +1 -1
- package/plugins/ambient-agent-plugin.js +49 -12
- package/plugins/email.js +196 -36
- package/plugins/feishu-plugin.js +2 -0
- package/plugins/telegram-plugin.js +3 -0
- package/plugins/weixin-plugin.js +2 -0
package/package.json
CHANGED
|
@@ -202,7 +202,8 @@ class GoalManager {
|
|
|
202
202
|
const goal = this._goals.get(goalId)
|
|
203
203
|
if (!goal) return
|
|
204
204
|
goal.eventsReceived.push({
|
|
205
|
-
event: event.
|
|
205
|
+
event: event.type, // "email:received"
|
|
206
|
+
data: event.data, // the actual event data (contains email object)
|
|
206
207
|
timestamp: new Date()
|
|
207
208
|
})
|
|
208
209
|
this._persist()
|
|
@@ -250,13 +251,22 @@ class EventWatcher {
|
|
|
250
251
|
}
|
|
251
252
|
|
|
252
253
|
_handleEvent(type, data) {
|
|
254
|
+
// Check active goals
|
|
253
255
|
const activeGoals = this._goalManager.getActiveGoals()
|
|
254
256
|
for (const goal of activeGoals) {
|
|
255
|
-
// Check if goal's conditions match this event
|
|
256
257
|
if (this._isRelevantToGoal(goal, type, data)) {
|
|
257
258
|
this._goalManager.addEventToGoal(goal.id, { type, data })
|
|
258
259
|
}
|
|
259
260
|
}
|
|
261
|
+
|
|
262
|
+
// Also check pending goals - activate if conditions match
|
|
263
|
+
const pendingGoals = this._goalManager.getPendingGoals()
|
|
264
|
+
for (const goal of pendingGoals) {
|
|
265
|
+
if (this._isRelevantToGoal(goal, type, data)) {
|
|
266
|
+
this._goalManager.activateGoal(goal.id)
|
|
267
|
+
this._goalManager.addEventToGoal(goal.id, { type, data })
|
|
268
|
+
}
|
|
269
|
+
}
|
|
260
270
|
}
|
|
261
271
|
|
|
262
272
|
_isRelevantToGoal(goal, eventType, data) {
|
|
@@ -425,7 +435,6 @@ class ExplorerLoop {
|
|
|
425
435
|
}
|
|
426
436
|
|
|
427
437
|
this._tickCount++
|
|
428
|
-
this._lastActionTime = Date.now()
|
|
429
438
|
|
|
430
439
|
try {
|
|
431
440
|
await this._processGoals()
|
|
@@ -450,10 +459,19 @@ class ExplorerLoop {
|
|
|
450
459
|
// Check if goal has unprocessed events
|
|
451
460
|
const hasNewEvents = goal.eventsReceived && goal.eventsReceived.length > 0
|
|
452
461
|
|
|
462
|
+
// Check if goal is event-driven
|
|
463
|
+
const isEventDriven = goal.conditions && goal.conditions.events && goal.conditions.events.length > 0
|
|
464
|
+
|
|
453
465
|
// Get next action
|
|
454
466
|
if (goal.actions && goal.actions.length > 0) {
|
|
455
467
|
const action = goal.actions[0] // Simple: take first action
|
|
456
468
|
|
|
469
|
+
// For event-driven goals, only execute if there are new events
|
|
470
|
+
if (isEventDriven && !hasNewEvents) {
|
|
471
|
+
// Skip execution but don't fail - just wait for events
|
|
472
|
+
continue
|
|
473
|
+
}
|
|
474
|
+
|
|
457
475
|
// Loop detection (only for non-event-driven actions)
|
|
458
476
|
if (!hasNewEvents && this._reflector.checkLoopDetection(goal, action.id)) {
|
|
459
477
|
this._addActivity('goal_failed', { goalId: goal.id, reason: 'Loop detected' })
|
|
@@ -467,19 +485,32 @@ class ExplorerLoop {
|
|
|
467
485
|
const outcome = this._reflector.evaluateOutcome(goal, result)
|
|
468
486
|
|
|
469
487
|
if (outcome.goalComplete) {
|
|
470
|
-
|
|
471
|
-
|
|
488
|
+
// For event-driven goals, don't complete - reset and wait for more events
|
|
489
|
+
if (isEventDriven) {
|
|
490
|
+
goal.eventsReceived = []
|
|
491
|
+
goal.attempts = 0
|
|
492
|
+
this._goalManager.updateGoal(goal.id, { eventsReceived: [], attempts: 0 })
|
|
493
|
+
this._addActivity('goal_reset', { goalId: goal.id, reason: 'Event-driven, waiting for more events' })
|
|
494
|
+
} else {
|
|
495
|
+
this._goalManager.completeGoal(goal.id)
|
|
496
|
+
this._addActivity('goal_completed', { goalId: goal.id, attempts: goal.attempts })
|
|
497
|
+
}
|
|
472
498
|
} else if (!outcome.shouldContinue) {
|
|
473
499
|
this._goalManager.failGoal(goal.id, 'Max attempts reached')
|
|
474
500
|
this._addActivity('goal_failed', { goalId: goal.id, reason: 'Max attempts' })
|
|
475
501
|
} else if (outcome.actionTaken) {
|
|
476
|
-
//
|
|
477
|
-
goal
|
|
502
|
+
// For event-driven goals, keep actions in queue for continuous processing
|
|
503
|
+
// Only shift if this is a one-time goal (no pending events)
|
|
504
|
+
if (!isEventDriven) {
|
|
505
|
+
goal.actions.shift()
|
|
506
|
+
}
|
|
478
507
|
this._addActivity('action_executed', { goalId: goal.id, action: action.id, hasEvents: hasNewEvents })
|
|
508
|
+
// Update last action time for cooldown
|
|
509
|
+
this._lastActionTime = Date.now()
|
|
479
510
|
}
|
|
480
511
|
|
|
481
512
|
// Clear processed events after action is taken
|
|
482
|
-
if (hasNewEvents
|
|
513
|
+
if (hasNewEvents) {
|
|
483
514
|
goal.eventsReceived = []
|
|
484
515
|
this._goalManager.updateGoal(goal.id, { eventsReceived: [] })
|
|
485
516
|
}
|
|
@@ -583,7 +614,16 @@ class AmbientAgentPlugin extends Plugin {
|
|
|
583
614
|
super()
|
|
584
615
|
this.name = 'ambient'
|
|
585
616
|
this.version = '1.0.0'
|
|
586
|
-
this.description =
|
|
617
|
+
this.description = `Ambient Agent - 持续运行的后台 Agent,用于主动监控和自动操作
|
|
618
|
+
支持监听的事件:
|
|
619
|
+
- email:received - 收到新邮件(需配合 email_watch 启动监控)
|
|
620
|
+
- webhook:received - 收到 webhook 请求
|
|
621
|
+
- scheduler:reminder - 定时提醒触发
|
|
622
|
+
- scheduler:task_completed - 定时任务完成
|
|
623
|
+
- scheduler:task_failed - 定时任务失败
|
|
624
|
+
- think:thought_completed - 思考完成
|
|
625
|
+
- tool:result - 工具执行结果
|
|
626
|
+
- agent:message - Agent 消息`
|
|
587
627
|
this.priority = 18
|
|
588
628
|
this.system = true
|
|
589
629
|
|
|
@@ -618,7 +658,6 @@ class AmbientAgentPlugin extends Plugin {
|
|
|
618
658
|
|
|
619
659
|
start(framework) {
|
|
620
660
|
if (!this.config.enabled) {
|
|
621
|
-
console.log('[Ambient] Plugin disabled, skipping start')
|
|
622
661
|
return this
|
|
623
662
|
}
|
|
624
663
|
|
|
@@ -643,7 +682,6 @@ class AmbientAgentPlugin extends Plugin {
|
|
|
643
682
|
// Register tools
|
|
644
683
|
this._registerTools(framework)
|
|
645
684
|
|
|
646
|
-
console.log('[Ambient] Plugin started')
|
|
647
685
|
return this
|
|
648
686
|
}
|
|
649
687
|
|
|
@@ -864,7 +902,6 @@ class AmbientAgentPlugin extends Plugin {
|
|
|
864
902
|
const waitInterval = 500
|
|
865
903
|
|
|
866
904
|
while (agent._status === 'busy' && attempts < maxWaitAttempts) {
|
|
867
|
-
console.log('[Ambient] Agent busy, waiting...')
|
|
868
905
|
await new Promise(resolve => setTimeout(resolve, waitInterval))
|
|
869
906
|
attempts++
|
|
870
907
|
}
|
package/plugins/email.js
CHANGED
|
@@ -11,11 +11,12 @@ class EmailPlugin extends Plugin {
|
|
|
11
11
|
super()
|
|
12
12
|
this.name = 'email'
|
|
13
13
|
this.version = '1.1.0'
|
|
14
|
-
this.description = `邮件收发插件 -
|
|
14
|
+
this.description = `邮件收发插件 - 支持读取和发送电子邮件、监控新邮件、自动回复,配置已经预设,不用获取配置
|
|
15
15
|
功能:
|
|
16
16
|
- 发送邮件支持附件(本地文件、远程URL、Base64)
|
|
17
17
|
- 读取邮件(IMAP协议)
|
|
18
18
|
- 监控新邮件(支持IMAP IDLE推送和定时轮询)
|
|
19
|
+
- 自动回复邮件(AI分析内容并发送回复,无需用户确认)
|
|
19
20
|
发送邮件支持附件:
|
|
20
21
|
- attachments.path: 本地文件路径
|
|
21
22
|
- attachments.url: 远程图片/文件URL(自动下载)
|
|
@@ -29,6 +30,7 @@ class EmailPlugin extends Plugin {
|
|
|
29
30
|
this._lastSeenUid = null
|
|
30
31
|
this._watchConfig = null
|
|
31
32
|
this._watchEnabled = false
|
|
33
|
+
this._checking = false // 防止并发检查
|
|
32
34
|
}
|
|
33
35
|
|
|
34
36
|
install(framework) {
|
|
@@ -39,10 +41,10 @@ class EmailPlugin extends Plugin {
|
|
|
39
41
|
|
|
40
42
|
start(framework) {
|
|
41
43
|
// 自动启动邮件监控(如果配置了 IMAP 且尚未运行)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
if (this._watchEnabled) {
|
|
45
|
+
console.log('[Email] Email watch already running, skipping auto-start')
|
|
46
|
+
return this
|
|
47
|
+
}
|
|
46
48
|
|
|
47
49
|
// if (process.env.IMAP_USER && process.env.IMAP_PASS) {
|
|
48
50
|
// console.log('[Email] Auto-starting email watch...')
|
|
@@ -149,27 +151,27 @@ class EmailPlugin extends Plugin {
|
|
|
149
151
|
})
|
|
150
152
|
|
|
151
153
|
// 配置邮箱连接
|
|
152
|
-
this._framework.registerTool({
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
})
|
|
154
|
+
// this._framework.registerTool({
|
|
155
|
+
// name: 'email_configure',
|
|
156
|
+
// description: '查看邮箱配置(实际配置通过环境变量设置)',
|
|
157
|
+
// inputSchema: z.object({}),
|
|
158
|
+
// execute: async () => {
|
|
159
|
+
// return {
|
|
160
|
+
// success: true,
|
|
161
|
+
// message: '邮箱配置通过环境变量设置',
|
|
162
|
+
// config: {
|
|
163
|
+
// smtp_host: process.env.SMTP_HOST || 'smtp.gmail.com',
|
|
164
|
+
// smtp_port: process.env.SMTP_PORT || 587,
|
|
165
|
+
// smtp_secure: process.env.SMTP_SECURE || 'false',
|
|
166
|
+
// imap_host: process.env.IMAP_HOST || 'imap.gmail.com',
|
|
167
|
+
// imap_port: process.env.IMAP_PORT || 993,
|
|
168
|
+
// from_email: process.env.FROM_EMAIL || '(未设置)',
|
|
169
|
+
// client_name: process.env.IMAP_CLIENT_NAME || 'FolikoAgent',
|
|
170
|
+
// client_version: process.env.IMAP_CLIENT_VERSION || '1.0.0'
|
|
171
|
+
// }
|
|
172
|
+
// }
|
|
173
|
+
// }
|
|
174
|
+
// })
|
|
173
175
|
|
|
174
176
|
// 监控新邮件
|
|
175
177
|
this._framework.registerTool({
|
|
@@ -178,16 +180,152 @@ class EmailPlugin extends Plugin {
|
|
|
178
180
|
inputSchema: z.object({
|
|
179
181
|
action: z.enum(['start', 'stop', 'status']).describe('操作:启动监控、停止监控、查看状态'),
|
|
180
182
|
interval: z.number().optional().describe('轮询间隔(秒),默认60秒,适用于不支持IDLE的服务器'),
|
|
181
|
-
host: z.string().optional().describe('IMAP服务器地址'),
|
|
182
|
-
port: z.number().optional().describe('IMAP端口'),
|
|
183
|
-
user: z.string().optional().describe('邮箱用户名'),
|
|
184
|
-
password: z.string().optional().describe('邮箱密码'),
|
|
183
|
+
// host: z.string().optional().describe('IMAP服务器地址'),
|
|
184
|
+
// port: z.number().optional().describe('IMAP端口'),
|
|
185
|
+
// user: z.string().optional().describe('邮箱用户名'),
|
|
186
|
+
// password: z.string().optional().describe('邮箱密码'),
|
|
185
187
|
box: z.string().optional().describe('邮箱文件夹,默认INBOX')
|
|
186
188
|
}),
|
|
187
189
|
execute: async (args) => {
|
|
188
|
-
|
|
190
|
+
|
|
191
|
+
return this._handleEmailWatch({
|
|
192
|
+
...args,
|
|
193
|
+
host: process.env.IMAP_HOST,
|
|
194
|
+
port: parseInt(process.env.IMAP_PORT) || 993,
|
|
195
|
+
user: process.env.IMAP_USER,
|
|
196
|
+
password: process.env.IMAP_PASS,
|
|
197
|
+
})
|
|
189
198
|
}
|
|
190
199
|
})
|
|
200
|
+
|
|
201
|
+
// 自动回复邮件
|
|
202
|
+
this._framework.registerTool({
|
|
203
|
+
name: 'email_auto_reply',
|
|
204
|
+
description: '自动分析邮件内容并发送回复(无需用户确认)',
|
|
205
|
+
inputSchema: z.object({
|
|
206
|
+
to: z.string().describe('收件人邮箱地址'),
|
|
207
|
+
subject: z.string().describe('原始邮件主题'),
|
|
208
|
+
body: z.string().describe('原始邮件内容'),
|
|
209
|
+
from: z.string().optional().describe('发件人邮箱地址(可选)')
|
|
210
|
+
}),
|
|
211
|
+
execute: async (args) => {
|
|
212
|
+
return this._handleAutoReply(args)
|
|
213
|
+
}
|
|
214
|
+
})
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* 处理自动回复
|
|
219
|
+
*/
|
|
220
|
+
async _handleAutoReply(args) {
|
|
221
|
+
// 支持两种模式:
|
|
222
|
+
// 1. 直接传参数: { to, subject, body, from }
|
|
223
|
+
// 2. 从 _event 提取: { _event } (来自 ambient agent 的事件触发)
|
|
224
|
+
let { to, subject, body, from, _event } = args
|
|
225
|
+
|
|
226
|
+
// 如果没有直接参数,尝试从 _event 提取
|
|
227
|
+
if (!to && !subject && !body && _event) {
|
|
228
|
+
const email = _event.data?.email || _event.email || {}
|
|
229
|
+
from = email.from?.text || email.from || ''
|
|
230
|
+
to = email.to?.text || email.to || ''
|
|
231
|
+
subject = email.subject || ''
|
|
232
|
+
body = email.text || email.body || ''
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// 检查必要参数
|
|
236
|
+
if (!from && !to) {
|
|
237
|
+
return { success: false, error: '缺少收件人地址' }
|
|
238
|
+
}
|
|
239
|
+
if (!body) {
|
|
240
|
+
return { success: false, error: '缺少邮件内容' }
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
try {
|
|
244
|
+
// 获取活跃的 Agent
|
|
245
|
+
const agent = this._getActiveAgent()
|
|
246
|
+
if (!agent) {
|
|
247
|
+
return { success: false, error: 'No active agent found' }
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// 构建提示让 LLM 生成回复
|
|
251
|
+
const prompt = `你是一封邮件自动回复助手。请根据以下邮件内容,生成一封专业的回复邮件。
|
|
252
|
+
|
|
253
|
+
【原始邮件】
|
|
254
|
+
发件人: ${from || to}
|
|
255
|
+
主题: ${subject}
|
|
256
|
+
内容:
|
|
257
|
+
${body}
|
|
258
|
+
|
|
259
|
+
【要求】
|
|
260
|
+
1. 回复内容要针对邮件中的问题或内容进行回复
|
|
261
|
+
2. 语言要专业、礼貌、简洁
|
|
262
|
+
3. 只输出邮件正文内容,不要额外解释
|
|
263
|
+
4. 回复语言应与原邮件一致(如果原邮件是中文,则用中文回复)`
|
|
264
|
+
|
|
265
|
+
// 等待 Agent 生成回复(带超时保护)
|
|
266
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
267
|
+
setTimeout(() => reject(new Error('AI回复生成超时(30秒)')), 30000)
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
const replyPromise = agent.pushMessage(prompt, { maxSteps: 3 })
|
|
271
|
+
const replyResult = await Promise.race([replyPromise, timeoutPromise])
|
|
272
|
+
|
|
273
|
+
// 提取回复内容
|
|
274
|
+
let replyContent = ''
|
|
275
|
+
if (typeof replyResult === 'string') {
|
|
276
|
+
replyContent = replyResult.trim()
|
|
277
|
+
} else if (replyResult && replyResult.content) {
|
|
278
|
+
replyContent = replyResult.content.trim()
|
|
279
|
+
} else if (replyResult && replyResult.message) {
|
|
280
|
+
replyContent = replyResult.message.trim()
|
|
281
|
+
} else {
|
|
282
|
+
replyContent = JSON.stringify(replyResult).trim()
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// 去掉 <</think> 思考过程标签
|
|
286
|
+
replyContent = replyContent.replace(/<think>[\s\S]*?<\/think>/g, '').trim()
|
|
287
|
+
|
|
288
|
+
// 如果去完后内容为空或太短,说明提取失败
|
|
289
|
+
if (replyContent.length < 5) {
|
|
290
|
+
return { success: false, error: 'AI回复内容太短或无效' }
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
if (!replyContent) {
|
|
294
|
+
return { success: false, error: 'AI未能生成有效的回复内容' }
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// 发送回复邮件
|
|
298
|
+
const sendResult = await this._sendEmail({
|
|
299
|
+
to: from || to,
|
|
300
|
+
subject: `Re: ${subject}`,
|
|
301
|
+
body: replyContent
|
|
302
|
+
})
|
|
303
|
+
|
|
304
|
+
if (sendResult.success) {
|
|
305
|
+
console.log(`[Email] Auto reply sent to ${from || to}`)
|
|
306
|
+
return {
|
|
307
|
+
success: true,
|
|
308
|
+
message: `自动回复已发送至 ${from || to}`,
|
|
309
|
+
replyContent
|
|
310
|
+
}
|
|
311
|
+
} else {
|
|
312
|
+
return { success: false, error: sendResult.error || '发送失败' }
|
|
313
|
+
}
|
|
314
|
+
} catch (err) {
|
|
315
|
+
console.error('[Email] Auto reply error:', err.message)
|
|
316
|
+
return { success: false, error: err.message }
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* 获取活跃的 Agent
|
|
322
|
+
*/
|
|
323
|
+
_getActiveAgent() {
|
|
324
|
+
if (this._framework._mainAgent) {
|
|
325
|
+
return this._framework._mainAgent
|
|
326
|
+
}
|
|
327
|
+
const agents = this._framework._agents || []
|
|
328
|
+
return agents.length > 0 ? agents[agents.length - 1] : null
|
|
191
329
|
}
|
|
192
330
|
|
|
193
331
|
/**
|
|
@@ -299,6 +437,8 @@ class EmailPlugin extends Plugin {
|
|
|
299
437
|
*/
|
|
300
438
|
async _checkNewEmails() {
|
|
301
439
|
if (!this._watchConfig) return
|
|
440
|
+
if (this._checking) return // 防止并发检查
|
|
441
|
+
this._checking = true
|
|
302
442
|
|
|
303
443
|
const Imap = require('imap-mkl')
|
|
304
444
|
const { simpleParser } = require('mailparser')
|
|
@@ -322,6 +462,7 @@ class EmailPlugin extends Plugin {
|
|
|
322
462
|
|
|
323
463
|
const cleanup = () => {
|
|
324
464
|
try { imap.end() } catch (e) {}
|
|
465
|
+
this._checking = false
|
|
325
466
|
}
|
|
326
467
|
|
|
327
468
|
imap.on('ready', () => {
|
|
@@ -600,6 +741,17 @@ class EmailPlugin extends Plugin {
|
|
|
600
741
|
try {
|
|
601
742
|
const Imap = require('imap-mkl')
|
|
602
743
|
|
|
744
|
+
// 支持从 _event 提取邮件 UID
|
|
745
|
+
let { messageId, _event } = args
|
|
746
|
+
if (!messageId && _event) {
|
|
747
|
+
const email = _event.data?.email || _event.email || {}
|
|
748
|
+
messageId = email.uid || email.messageId
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
if (!messageId) {
|
|
752
|
+
return { success: false, error: '缺少邮件标识(messageId 或 uid)' }
|
|
753
|
+
}
|
|
754
|
+
|
|
603
755
|
const imapConfig = {
|
|
604
756
|
user: args.user || process.env.IMAP_USER,
|
|
605
757
|
password: args.password || process.env.IMAP_PASS,
|
|
@@ -615,7 +767,7 @@ class EmailPlugin extends Plugin {
|
|
|
615
767
|
}
|
|
616
768
|
}
|
|
617
769
|
|
|
618
|
-
await this._markEmailAsRead(imapConfig,
|
|
770
|
+
await this._markEmailAsRead(imapConfig, messageId)
|
|
619
771
|
|
|
620
772
|
return {
|
|
621
773
|
success: true,
|
|
@@ -647,11 +799,19 @@ class EmailPlugin extends Plugin {
|
|
|
647
799
|
return reject(err)
|
|
648
800
|
}
|
|
649
801
|
|
|
650
|
-
let searchFilter
|
|
651
|
-
? searchCriteria.split(' ').filter(Boolean)
|
|
652
|
-
: ['ALL']
|
|
802
|
+
let searchFilter
|
|
653
803
|
if (unreadOnly) {
|
|
654
|
-
searchFilter = ['UNSEEN']
|
|
804
|
+
searchFilter = [['UNSEEN']]
|
|
805
|
+
} else if (searchCriteria) {
|
|
806
|
+
// 将 "FROM sender@example.com" 转换为 [['FROM', 'sender@example.com']]
|
|
807
|
+
const parts = searchCriteria.split(' ').filter(Boolean)
|
|
808
|
+
if (parts.length >= 2) {
|
|
809
|
+
searchFilter = [[parts[0], parts.slice(1).join(' ')]]
|
|
810
|
+
} else {
|
|
811
|
+
searchFilter = [parts]
|
|
812
|
+
}
|
|
813
|
+
} else {
|
|
814
|
+
searchFilter = [['ALL']]
|
|
655
815
|
}
|
|
656
816
|
|
|
657
817
|
imap.search(searchFilter, (err, results) => {
|
package/plugins/feishu-plugin.js
CHANGED
|
@@ -294,6 +294,8 @@ class FeishuPlugin extends Plugin {
|
|
|
294
294
|
}
|
|
295
295
|
|
|
296
296
|
if (fullResponse) {
|
|
297
|
+
// 去掉思考过程标签
|
|
298
|
+
fullResponse = fullResponse.replace(/<think>[\s\S]*?<\/think>/g, '').trim()
|
|
297
299
|
await this._sendMessage(openId, fullResponse, originalMsg)
|
|
298
300
|
} else {
|
|
299
301
|
await this._sendMessage(openId, '抱歉,我没有收到有效的回复。', originalMsg)
|
|
@@ -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 {
|