foliko 1.0.10 → 1.0.13
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 +4 -1
- package/SPEC.md +78 -1
- package/package.json +1 -1
- package/plugins/scheduler-plugin.js +117 -26
- package/plugins/telegram-plugin.js +49 -0
|
@@ -34,7 +34,10 @@
|
|
|
34
34
|
"Bash(node -c plugins/default-plugins.js && node -c src/core/plugin-manager.js && echo \"Syntax OK\")",
|
|
35
35
|
"Bash(node -c plugins/install-plugin.js && echo \"Syntax OK\")",
|
|
36
36
|
"Bash(node -c cli/src/ui/chat-ui.js && echo \"Syntax OK\")",
|
|
37
|
-
"Bash(node -c plugins/default-plugins.js && echo \"Syntax OK\")"
|
|
37
|
+
"Bash(node -c plugins/default-plugins.js && echo \"Syntax OK\")",
|
|
38
|
+
"Bash(node -c plugins/scheduler-plugin.js && echo \"Syntax OK\")",
|
|
39
|
+
"Bash(node -c plugins/telegram-plugin.js && node -c plugins/scheduler-plugin.js && echo \"Syntax OK\")",
|
|
40
|
+
"Bash(node -c plugins/telegram-plugin.js && echo \"Syntax OK\")"
|
|
38
41
|
]
|
|
39
42
|
}
|
|
40
43
|
}
|
package/SPEC.md
CHANGED
|
@@ -304,8 +304,34 @@ const response = await agent.chat('你好')
|
|
|
304
304
|
'agent:message' // Agent消息
|
|
305
305
|
'agent:tool-call' // Agent调用工具
|
|
306
306
|
'agent:tool-result' // 工具执行结果
|
|
307
|
+
'scheduler:task_created' // 定时任务创建
|
|
308
|
+
'scheduler:task_cancelled' // 定时任务取消
|
|
309
|
+
'scheduler:task_completed' // 定时任务完成
|
|
310
|
+
'scheduler:task_failed' // 定时任务失败
|
|
311
|
+
'scheduler:reminder' // 定时提醒触发
|
|
312
|
+
'think:thought_completed' // 思考完成
|
|
313
|
+
'think:reflection_needs_attention' // 反思需要关注
|
|
307
314
|
```
|
|
308
315
|
|
|
316
|
+
### 事件详情
|
|
317
|
+
|
|
318
|
+
#### Scheduler 事件
|
|
319
|
+
|
|
320
|
+
| 事件 | 数据 | 说明 |
|
|
321
|
+
|------|------|------|
|
|
322
|
+
| `scheduler:task_created` | `{ taskId, taskName, type, scheduleTime, cronExpression }` | 任务创建时触发 |
|
|
323
|
+
| `scheduler:task_cancelled` | `{ taskId, taskName }` | 任务取消时触发 |
|
|
324
|
+
| `scheduler:task_completed` | `{ taskId, taskName, type }` | 任务完成时触发 |
|
|
325
|
+
| `scheduler:task_failed` | `{ taskId, taskName, error }` | 任务失败时触发 |
|
|
326
|
+
| `scheduler:reminder` | `{ taskId, taskName, message, sessionId, llm }` | 提醒触发时触发 |
|
|
327
|
+
|
|
328
|
+
#### Think 事件
|
|
329
|
+
|
|
330
|
+
| 事件 | 数据 | 说明 |
|
|
331
|
+
|------|------|------|
|
|
332
|
+
| `think:thought_completed` | `thought` | 思考完成时触发 |
|
|
333
|
+
| `think:reflection_needs_attention` | `{ thought, reason }` | 反思需要关注时触发 |
|
|
334
|
+
|
|
309
335
|
## 六、热重载机制
|
|
310
336
|
|
|
311
337
|
### 设计原则
|
|
@@ -384,6 +410,10 @@ agent.chat('请重载 my-plugin 插件')
|
|
|
384
410
|
- 绑定主 Agent 持续对话
|
|
385
411
|
- 支持 MarkdownV2
|
|
386
412
|
- 图片/文档接收保存
|
|
413
|
+
- 监听 `scheduler:reminder` 事件发送定时提醒
|
|
414
|
+
|
|
415
|
+
**监听事件**:
|
|
416
|
+
- `scheduler:reminder` - 接收定时任务提醒并发送到 Telegram
|
|
387
417
|
|
|
388
418
|
**配置**:
|
|
389
419
|
```javascript
|
|
@@ -395,6 +425,53 @@ agent.chat('请重载 my-plugin 插件')
|
|
|
395
425
|
}
|
|
396
426
|
```
|
|
397
427
|
|
|
428
|
+
### 7.5 Scheduler Plugin (plugins/scheduler-plugin.js)
|
|
429
|
+
|
|
430
|
+
**功能**:
|
|
431
|
+
- 定时任务调度(Cron 表达式、相对时间、绝对时间)
|
|
432
|
+
- 支持 LLM 自动检测(简单提醒直接显示,需要处理的任务启用 LLM)
|
|
433
|
+
- 会话自动检测(自动发送到最近活跃的会话)
|
|
434
|
+
- 事件系统(供其他插件监听和响应)
|
|
435
|
+
|
|
436
|
+
**工具**:
|
|
437
|
+
- `schedule_task` - 创建定时任务
|
|
438
|
+
- `schedule_list` - 列出所有任务
|
|
439
|
+
- `schedule_cancel` - 取消任务
|
|
440
|
+
- `cron_examples` - Cron 表达式示例
|
|
441
|
+
|
|
442
|
+
**schedule_task 参数**:
|
|
443
|
+
```javascript
|
|
444
|
+
{
|
|
445
|
+
name: '任务名称', // 可选
|
|
446
|
+
scheduleTime: '10 minutes', // 必填,支持多种格式
|
|
447
|
+
message: '提醒内容', // 必填
|
|
448
|
+
repeat: false, // 可选,是否重复
|
|
449
|
+
cronExpression: '*/5 * * * *', // 可选,Cron 表达式
|
|
450
|
+
sessionId: 'telegram_123', // 可选,会话 ID
|
|
451
|
+
llm: true // 可选,是否需要 LLM 处理(自动检测)
|
|
452
|
+
}
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
**时间格式**:
|
|
456
|
+
| 格式 | 示例 | 说明 |
|
|
457
|
+
|------|------|------|
|
|
458
|
+
| 相对时间 | `10 seconds`, `5 minutes`, `1 hour`, `2 days` | 多久后执行 |
|
|
459
|
+
| 绝对时间 | `12:00`, `14:30:00` | 具体时间(次日开始) |
|
|
460
|
+
| Cron | `*/5 * * * *`, `0 9 * * *` | Cron 表达式 |
|
|
461
|
+
|
|
462
|
+
**自动 LLM 检测**:
|
|
463
|
+
- 简单提醒(喝水、吃饭)→ 直接显示
|
|
464
|
+
- 查询/分析任务(查看列表、分析数据)→ 启用 LLM
|
|
465
|
+
|
|
466
|
+
**事件**:
|
|
467
|
+
| 事件 | 时机 |
|
|
468
|
+
|------|------|
|
|
469
|
+
| `scheduler:task_created` | 任务创建时 |
|
|
470
|
+
| `scheduler:task_cancelled` | 任务取消时 |
|
|
471
|
+
| `scheduler:task_completed` | 任务完成时 |
|
|
472
|
+
| `scheduler:task_failed` | 任务失败时 |
|
|
473
|
+
| `scheduler:reminder` | 提醒触发时 |
|
|
474
|
+
|
|
398
475
|
## 八、使用示例
|
|
399
476
|
|
|
400
477
|
### 8.1 基础用法
|
|
@@ -491,7 +568,7 @@ class Framework {
|
|
|
491
568
|
- [x] Session 管理 (`plugins/session-plugin.js`) - 多会话支持、历史记录
|
|
492
569
|
- [x] Audit 审计日志 (`plugins/audit-plugin.js`) - 操作日志记录和查询
|
|
493
570
|
- [x] Rules 规则引擎 (`plugins/rules-plugin.js`) - 权限控制、内容过滤
|
|
494
|
-
- [x] Scheduler 定时任务 (`plugins/scheduler-plugin.js`) - Cron
|
|
571
|
+
- [x] Scheduler 定时任务 (`plugins/scheduler-plugin.js`) - Cron 调度、事件系统、自动 LLM 检测
|
|
495
572
|
- [x] Storage 存储 (`plugins/storage-plugin.js`) - 键值对持久化存储
|
|
496
573
|
- [x] SubAgent 子Agent (`plugins/subagent-plugin.js`) - 子Agent隔离工具集
|
|
497
574
|
- [x] Email 插件 (`plugins/email.js`) - 邮件收发
|
package/package.json
CHANGED
|
@@ -106,25 +106,60 @@ class SchedulerPlugin extends Plugin {
|
|
|
106
106
|
// 注册调度工具
|
|
107
107
|
framework.registerTool({
|
|
108
108
|
name: 'schedule_task',
|
|
109
|
-
description: '设置定时提醒任务。支持多种时间格式:相对时间(1 minute, 2 hours)、具体时间(12:00)、Cron表达式(* * * * *)',
|
|
109
|
+
description: '设置定时提醒任务。支持多种时间格式:相对时间(1 minute, 2 hours)、具体时间(12:00)、Cron表达式(* * * * *)。系统会自动判断任务是否需要 LLM 处理。',
|
|
110
110
|
inputSchema: z.object({
|
|
111
111
|
name: z.string().optional().describe('任务名称'),
|
|
112
112
|
scheduleTime: z.string().describe('执行时间。支持格式:\n- 相对时间: "1 minute", "2 hours", "1 day"\n- 具体时间: "12:00", "14:30"\n- Cron表达式: "*/5 * * * *" (每5分钟)'),
|
|
113
|
-
message: z.string().describe('
|
|
113
|
+
message: z.string().describe('提醒消息内容。系统会自动判断:\n- 简单提醒(喝水、吃饭)直接显示\n- 需要查询/分析的任务(查看列表、分析数据)自动启用 LLM'),
|
|
114
114
|
repeat: z.boolean().optional().describe('是否重复执行 (默认 false)'),
|
|
115
|
-
cronExpression: z.string().optional().describe('Cron 表达式 (当 repeat 为 true 时使用)')
|
|
115
|
+
cronExpression: z.string().optional().describe('Cron 表达式 (当 repeat 为 true 时使用)'),
|
|
116
|
+
sessionId: z.string().optional().describe('会话 ID(提醒将发送到该会话,不填则使用默认会话)'),
|
|
117
|
+
llm: z.boolean().optional().describe('是否需要 LLM 处理(自动检测,可手动覆盖)')
|
|
116
118
|
}),
|
|
117
119
|
execute: async (args) => {
|
|
118
120
|
try {
|
|
119
|
-
const { scheduleTime, message, repeat, cronExpression } = args
|
|
121
|
+
const { scheduleTime, message, repeat, cronExpression, sessionId } = args
|
|
120
122
|
const agent = this._getAgent()
|
|
121
123
|
if (!agent) {
|
|
122
124
|
return { success: false, error: 'Agent not available' }
|
|
123
125
|
}
|
|
124
126
|
|
|
127
|
+
// 如果没有指定 sessionId,自动获取当前活跃会话
|
|
128
|
+
let targetSessionId = sessionId
|
|
129
|
+
if (!targetSessionId) {
|
|
130
|
+
const sessionPlugin = this._framework.pluginManager.get('session')
|
|
131
|
+
if (sessionPlugin) {
|
|
132
|
+
const sessions = sessionPlugin.listSessions()
|
|
133
|
+
// 获取最近的活跃会话
|
|
134
|
+
if (sessions.length > 0) {
|
|
135
|
+
// 按 lastActive 排序,取最新的
|
|
136
|
+
sessions.sort((a, b) => {
|
|
137
|
+
const aTime = a.lastActive ? new Date(a.lastActive).getTime() : 0
|
|
138
|
+
const bTime = b.lastActive ? new Date(b.lastActive).getTime() : 0
|
|
139
|
+
return bTime - aTime
|
|
140
|
+
})
|
|
141
|
+
targetSessionId = sessions[0].id
|
|
142
|
+
console.log(`[Scheduler] Auto-detected active session: ${targetSessionId}`)
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
125
147
|
const taskId = `task_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
|
|
126
148
|
let task
|
|
127
149
|
|
|
150
|
+
// 自动检测是否需要 LLM 处理
|
|
151
|
+
const LLM_KEYWORDS = [
|
|
152
|
+
'分析', '查询', '查看', '检查', '总结', '搜索', '获取',
|
|
153
|
+
'list', 'get', 'check', 'search', 'find', 'fetch',
|
|
154
|
+
'什么', '如何', '为什么', '什么时候', '多少', '谁',
|
|
155
|
+
'今天', '明天', '昨天', '这周', '这月', '今年'
|
|
156
|
+
]
|
|
157
|
+
const messageLower = message.toLowerCase()
|
|
158
|
+
const needsLLM = args.llm === true || LLM_KEYWORDS.some(kw =>
|
|
159
|
+
message.includes(kw) || messageLower.includes(kw.toLowerCase())
|
|
160
|
+
)
|
|
161
|
+
const llmMode = needsLLM
|
|
162
|
+
|
|
128
163
|
// 检测是否像 Cron 表达式
|
|
129
164
|
const isCron = /^[\d*,\/-\s]+$/.test(scheduleTime) && scheduleTime.split(' ').length >= 5
|
|
130
165
|
|
|
@@ -144,7 +179,9 @@ class SchedulerPlugin extends Plugin {
|
|
|
144
179
|
lastRun: null,
|
|
145
180
|
runCount: 0,
|
|
146
181
|
timer: null,
|
|
147
|
-
cronTask: null
|
|
182
|
+
cronTask: null,
|
|
183
|
+
sessionId: targetSessionId || null,
|
|
184
|
+
llm: llmMode
|
|
148
185
|
}
|
|
149
186
|
|
|
150
187
|
// 使用 node-cron 调度
|
|
@@ -164,7 +201,9 @@ class SchedulerPlugin extends Plugin {
|
|
|
164
201
|
createdAt: new Date(),
|
|
165
202
|
lastRun: null,
|
|
166
203
|
runCount: 0,
|
|
167
|
-
timer: null
|
|
204
|
+
timer: null,
|
|
205
|
+
sessionId: targetSessionId || null,
|
|
206
|
+
llm: llmMode
|
|
168
207
|
}
|
|
169
208
|
task.timer = setTimeout(async () => {
|
|
170
209
|
await this._executeTask(task)
|
|
@@ -186,7 +225,9 @@ class SchedulerPlugin extends Plugin {
|
|
|
186
225
|
createdAt: new Date(),
|
|
187
226
|
lastRun: null,
|
|
188
227
|
runCount: 0,
|
|
189
|
-
timer: null
|
|
228
|
+
timer: null,
|
|
229
|
+
sessionId: targetSessionId || null,
|
|
230
|
+
llm: llmMode
|
|
190
231
|
}
|
|
191
232
|
task.timer = setTimeout(async () => {
|
|
192
233
|
await this._executeTask(task)
|
|
@@ -196,6 +237,15 @@ class SchedulerPlugin extends Plugin {
|
|
|
196
237
|
this._tasks.set(task.id, task)
|
|
197
238
|
this._taskStats.total++
|
|
198
239
|
|
|
240
|
+
// 发送任务创建事件
|
|
241
|
+
this._framework.emit('scheduler:task_created', {
|
|
242
|
+
taskId: task.id,
|
|
243
|
+
taskName: task.name,
|
|
244
|
+
type: task.type,
|
|
245
|
+
scheduleTime,
|
|
246
|
+
cronExpression: task.cronExpression
|
|
247
|
+
})
|
|
248
|
+
|
|
199
249
|
return {
|
|
200
250
|
success: true,
|
|
201
251
|
taskId: task.id,
|
|
@@ -203,7 +253,9 @@ class SchedulerPlugin extends Plugin {
|
|
|
203
253
|
scheduleTime,
|
|
204
254
|
executeAt: task.runAt ? task.runAt.toISOString() : null,
|
|
205
255
|
cronExpression: task.cronExpression,
|
|
206
|
-
message: repeat ? '定时任务已创建 (重复执行)' : '提醒已设置'
|
|
256
|
+
message: repeat ? '定时任务已创建 (重复执行)' : '提醒已设置',
|
|
257
|
+
sessionId: sessionId || 'default',
|
|
258
|
+
llm: llmMode
|
|
207
259
|
}
|
|
208
260
|
} catch (err) {
|
|
209
261
|
return { success: false, error: err.message }
|
|
@@ -249,7 +301,15 @@ class SchedulerPlugin extends Plugin {
|
|
|
249
301
|
return { success: false, error: 'Task not found' }
|
|
250
302
|
}
|
|
251
303
|
|
|
304
|
+
const taskName = task.name
|
|
252
305
|
this._cancelTask(task)
|
|
306
|
+
|
|
307
|
+
// 发送任务取消事件
|
|
308
|
+
this._framework.emit('scheduler:task_cancelled', {
|
|
309
|
+
taskId: args.taskId,
|
|
310
|
+
taskName
|
|
311
|
+
})
|
|
312
|
+
|
|
253
313
|
return { success: true, cancelled: args.taskId }
|
|
254
314
|
}
|
|
255
315
|
})
|
|
@@ -322,37 +382,61 @@ class SchedulerPlugin extends Plugin {
|
|
|
322
382
|
}
|
|
323
383
|
|
|
324
384
|
/**
|
|
325
|
-
* 执行任务
|
|
385
|
+
* 执行任务
|
|
326
386
|
*/
|
|
327
387
|
async _executeTask(task) {
|
|
328
|
-
const agent = this._getAgent()
|
|
329
|
-
if (!agent) {
|
|
330
|
-
console.error('[Scheduler] Agent not available')
|
|
331
|
-
return
|
|
332
|
-
}
|
|
333
|
-
|
|
334
388
|
console.log(`[Scheduler] Executing task: ${task.name} (${task.id})`)
|
|
335
389
|
console.log(`[Scheduler] Message: ${task.message}`)
|
|
390
|
+
if (task.sessionId) {
|
|
391
|
+
console.log(`[Scheduler] Target session: ${task.sessionId}`)
|
|
392
|
+
}
|
|
393
|
+
console.log(`[Scheduler] LLM mode: ${task.llm ? 'enabled' : 'disabled'}`)
|
|
336
394
|
|
|
337
395
|
task.lastRun = new Date()
|
|
338
396
|
task.runCount++
|
|
339
397
|
this._taskStats.running++
|
|
340
398
|
|
|
341
399
|
try {
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
400
|
+
if (task.llm) {
|
|
401
|
+
// LLM 模式:调用 Agent 处理
|
|
402
|
+
const agent = this._getAgent()
|
|
403
|
+
if (!agent) {
|
|
404
|
+
console.error('[Scheduler] Agent not available')
|
|
405
|
+
return
|
|
406
|
+
}
|
|
346
407
|
|
|
347
|
-
|
|
408
|
+
const result = await agent.chat(task.message, {
|
|
409
|
+
isScheduledTask: true,
|
|
410
|
+
sessionId: task.sessionId
|
|
411
|
+
})
|
|
348
412
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
413
|
+
this._taskStats.completed++
|
|
414
|
+
|
|
415
|
+
if (result && result.message) {
|
|
416
|
+
console.log(`\n🔔 [定时提醒] ${result.message}\n`)
|
|
417
|
+
} else if (result && result.text) {
|
|
418
|
+
console.log(`\n🔔 [定时提醒] ${result.text}\n`)
|
|
419
|
+
}
|
|
354
420
|
} else {
|
|
421
|
+
// 直接显示模式:只显示提醒,不发 LLM
|
|
355
422
|
console.log(`\n🔔 [定时提醒] ${task.message}\n`)
|
|
423
|
+
|
|
424
|
+
// 发送事件,让其他插件(如 telegram)处理通知
|
|
425
|
+
this._framework.emit('scheduler:reminder', {
|
|
426
|
+
taskId: task.id,
|
|
427
|
+
taskName: task.name,
|
|
428
|
+
message: task.message,
|
|
429
|
+
sessionId: task.sessionId,
|
|
430
|
+
llm: task.llm
|
|
431
|
+
})
|
|
432
|
+
|
|
433
|
+
this._framework.emit('scheduler:task_completed', {
|
|
434
|
+
taskId: task.id,
|
|
435
|
+
taskName: task.name,
|
|
436
|
+
type: task.type
|
|
437
|
+
})
|
|
438
|
+
|
|
439
|
+
this._taskStats.completed++
|
|
356
440
|
}
|
|
357
441
|
|
|
358
442
|
// 一次性任务执行后清理
|
|
@@ -360,11 +444,18 @@ class SchedulerPlugin extends Plugin {
|
|
|
360
444
|
this._cleanupTask(task.id)
|
|
361
445
|
}
|
|
362
446
|
|
|
363
|
-
return
|
|
447
|
+
return { success: true }
|
|
364
448
|
} catch (err) {
|
|
365
449
|
this._taskStats.failed++
|
|
366
450
|
console.error(`[Scheduler] Task ${task.name} failed: ${err.message}`)
|
|
367
451
|
|
|
452
|
+
// 发送任务失败事件
|
|
453
|
+
this._framework.emit('scheduler:task_failed', {
|
|
454
|
+
taskId: task.id,
|
|
455
|
+
taskName: task.name,
|
|
456
|
+
error: err.message
|
|
457
|
+
})
|
|
458
|
+
|
|
368
459
|
// 一次性任务失败后也清理
|
|
369
460
|
if (task.type === 'once' && !task.cronTask) {
|
|
370
461
|
this._cleanupTask(task.id)
|
|
@@ -105,6 +105,12 @@ module.exports = function(Plugin) {
|
|
|
105
105
|
this._framework.on('agent:created', (agent) => {
|
|
106
106
|
console.log('[Telegram] New agent created:', agent.name)
|
|
107
107
|
})
|
|
108
|
+
|
|
109
|
+
// 监听定时提醒事件
|
|
110
|
+
this._framework.on('scheduler:reminder', async (data) => {
|
|
111
|
+
console.log('[Telegram] Received scheduler reminder:', data)
|
|
112
|
+
await this._handleScheduledReminder(data)
|
|
113
|
+
})
|
|
108
114
|
}
|
|
109
115
|
|
|
110
116
|
} catch (err) {
|
|
@@ -112,6 +118,49 @@ module.exports = function(Plugin) {
|
|
|
112
118
|
}
|
|
113
119
|
}
|
|
114
120
|
|
|
121
|
+
/**
|
|
122
|
+
* 处理定时提醒
|
|
123
|
+
*/
|
|
124
|
+
async _handleScheduledReminder(data) {
|
|
125
|
+
const { taskName, message, sessionId } = data
|
|
126
|
+
|
|
127
|
+
// 构建提醒消息
|
|
128
|
+
const reminderText = `🔔 [${taskName}]\n\n${message}`
|
|
129
|
+
|
|
130
|
+
// 如果有 sessionId 是 telegram 类型的,发送到对应 chat
|
|
131
|
+
if (sessionId && sessionId.startsWith('telegram_')) {
|
|
132
|
+
const chatId = sessionId.replace('telegram_', '')
|
|
133
|
+
try {
|
|
134
|
+
await this._bot.sendMessage(chatId, reminderText)
|
|
135
|
+
console.log(`[Telegram] Reminder sent to chat ${chatId}`)
|
|
136
|
+
} catch (err) {
|
|
137
|
+
console.error(`[Telegram] Failed to send reminder:`, err.message)
|
|
138
|
+
}
|
|
139
|
+
return
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// 其他情况(包括 null 或其他 sessionId),发送到最近的 Telegram 会话
|
|
143
|
+
if (this._sessions.size > 0) {
|
|
144
|
+
// 按最后活跃时间排序
|
|
145
|
+
const sortedSessions = Array.from(this._sessions.entries())
|
|
146
|
+
.sort((a, b) => {
|
|
147
|
+
const aTime = a[1].lastActive ? new Date(a[1].lastActive).getTime() : 0
|
|
148
|
+
const bTime = b[1].lastActive ? new Date(b[1].lastActive).getTime() : 0
|
|
149
|
+
return bTime - aTime
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
const [chatId] = sortedSessions[0]
|
|
153
|
+
try {
|
|
154
|
+
await this._bot.sendMessage(chatId, reminderText)
|
|
155
|
+
console.log(`[Telegram] Reminder sent to chat ${chatId}`)
|
|
156
|
+
} catch (err) {
|
|
157
|
+
console.error(`[Telegram] Failed to send reminder to ${chatId}:`, err.message)
|
|
158
|
+
}
|
|
159
|
+
} else {
|
|
160
|
+
console.log('[Telegram] No active Telegram sessions to send reminder')
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
115
164
|
/**
|
|
116
165
|
* 获取主Agent
|
|
117
166
|
*/
|