foliko 1.1.93 → 2.0.1

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.
Files changed (212) hide show
  1. package/.claude/settings.local.json +2 -1
  2. package/CLAUDE.md +56 -30
  3. package/REFACTORING_PLAN.md +645 -0
  4. package/docs/architecture.md +131 -0
  5. package/docs/migration.md +57 -0
  6. package/docs/public-api.md +138 -0
  7. package/docs/usage.md +385 -0
  8. package/examples/ambient-example.js +20 -137
  9. package/examples/basic.js +21 -48
  10. package/examples/bootstrap.js +16 -74
  11. package/examples/mcp-example.js +6 -29
  12. package/examples/skill-example.js +6 -19
  13. package/examples/workflow.js +8 -56
  14. package/package.json +8 -4
  15. package/plugins/README.md +49 -0
  16. package/plugins/{ambient-agent → ambient}/EventWatcher.js +1 -1
  17. package/plugins/{ambient-agent → ambient}/ExplorerLoop.js +3 -3
  18. package/plugins/{ambient-agent → ambient}/GoalManager.js +2 -2
  19. package/plugins/ambient/README.md +14 -0
  20. package/plugins/{ambient-agent → ambient}/Reflector.js +1 -1
  21. package/plugins/{ambient-agent → ambient}/StateStore.js +1 -1
  22. package/plugins/{ambient-agent → ambient}/index.js +2 -2
  23. package/plugins/{ai-plugin.js → core/ai/index.js} +14 -30
  24. package/plugins/{audit-plugin.js → core/audit/index.js} +3 -30
  25. package/plugins/{coordinator-plugin.js → core/coordinator/index.js} +3 -35
  26. package/plugins/core/default/bootstrap.js +224 -0
  27. package/plugins/core/default/config.js +222 -0
  28. package/plugins/core/default/index.js +58 -0
  29. package/plugins/core/mcp/index.js +1 -0
  30. package/plugins/{python-plugin-loader.js → core/python-loader/index.js} +7 -187
  31. package/plugins/{rules-plugin.js → core/rules/index.js} +121 -64
  32. package/plugins/{scheduler-plugin.js → core/scheduler/index.js} +12 -114
  33. package/plugins/{session-plugin.js → core/session/index.js} +9 -73
  34. package/{src/capabilities/skill-manager.js → plugins/core/skill-manager/index.js} +64 -18
  35. package/plugins/{storage-plugin.js → core/storage/index.js} +5 -29
  36. package/plugins/{subagent-plugin.js → core/sub-agent/index.js} +10 -171
  37. package/plugins/{think-plugin.js → core/think/index.js} +24 -91
  38. package/{src/capabilities/workflow-engine.js → plugins/core/workflow/index.js} +87 -85
  39. package/plugins/default-plugins.js +6 -720
  40. package/plugins/{data-splitter-plugin.js → executors/data-splitter/index.js} +9 -83
  41. package/plugins/{extension-executor-plugin.js → executors/extension/index.js} +13 -97
  42. package/plugins/{python-executor-plugin.js → executors/python/index.js} +6 -31
  43. package/plugins/{shell-executor-plugin.js → executors/shell/index.js} +2 -5
  44. package/plugins/install/README.md +9 -0
  45. package/plugins/{install-plugin.js → install/index.js} +3 -3
  46. package/plugins/{file-system-plugin.js → io/file-system/index.js} +34 -236
  47. package/plugins/{web-plugin.js → io/web/index.js} +11 -113
  48. package/plugins/memory/README.md +13 -0
  49. package/plugins/{memory-plugin.js → memory/index.js} +4 -18
  50. package/plugins/messaging/email/README.md +19 -0
  51. package/plugins/{email → messaging/email}/index.js +3 -3
  52. package/plugins/{feishu-plugin.js → messaging/feishu/index.js} +4 -4
  53. package/plugins/{qq-plugin.js → messaging/qq/index.js} +6 -17
  54. package/plugins/{telegram-plugin.js → messaging/telegram/index.js} +4 -4
  55. package/plugins/{weixin-plugin.js → messaging/weixin/index.js} +16 -16
  56. package/plugins/{plugin-manager-plugin.js → plugin-manager/index.js} +36 -180
  57. package/plugins/{tools-plugin.js → tools/index.js} +68 -116
  58. package/plugins/trading/README.md +15 -0
  59. package/plugins/{gate-trading.js → trading/index.js} +8 -8
  60. package/{examples → sandbox}/test-concurrent-chat.js +2 -2
  61. package/{examples → sandbox}/test-long-chat.js +2 -2
  62. package/{examples → sandbox}/test-session-chat.js +2 -2
  63. package/{examples → sandbox}/test-web-plugin.js +1 -1
  64. package/{examples → sandbox}/test-weixin-feishu.js +2 -2
  65. package/src/agent/base.js +56 -0
  66. package/src/{core/agent-chat.js → agent/chat.js} +11 -11
  67. package/src/{core/coordinator-manager.js → agent/coordinator.js} +3 -3
  68. package/src/agent/index.js +111 -0
  69. package/src/agent/main.js +337 -0
  70. package/src/agent/prompt.js +78 -0
  71. package/src/agent/sub.js +198 -0
  72. package/src/agent/worker.js +104 -0
  73. package/{cli/bin/foliko.js → src/cli/bin.js} +1 -1
  74. package/{cli/src → src/cli}/commands/chat.js +25 -21
  75. package/{cli/src → src/cli}/index.js +1 -0
  76. package/{cli/src → src/cli}/ui/chat-ui-old.js +40 -178
  77. package/{cli/src → src/cli}/ui/chat-ui.js +3 -3
  78. package/{cli/src → src/cli}/ui/components/footer-bar.js +1 -1
  79. package/src/common/errors.js +402 -0
  80. package/src/{utils → common}/logger.js +33 -0
  81. package/src/{utils/chat-queue.js → common/queue.js} +2 -2
  82. package/src/config/plugin-config.js +50 -0
  83. package/src/context/agent.js +32 -0
  84. package/src/context/compaction-prompts.js +170 -0
  85. package/src/context/compaction-utils.js +191 -0
  86. package/src/context/compressor.js +413 -0
  87. package/src/context/index.js +9 -0
  88. package/src/{core/context-manager.js → context/manager.js} +1 -1
  89. package/src/context/request.js +50 -0
  90. package/src/context/session.js +33 -0
  91. package/src/context/storage.js +30 -0
  92. package/src/executors/mcp-client.js +153 -0
  93. package/src/executors/mcp-desc.js +236 -0
  94. package/src/executors/mcp-executor.js +91 -956
  95. package/src/{core → framework}/command-registry.js +1 -1
  96. package/src/framework/framework.js +300 -0
  97. package/src/framework/index.js +18 -0
  98. package/src/framework/lifecycle.js +203 -0
  99. package/src/framework/loader.js +78 -0
  100. package/src/framework/registry.js +86 -0
  101. package/src/{core/ui-extension-context.js → framework/ui-extension.js} +1 -1
  102. package/src/index.js +130 -15
  103. package/src/llm/index.js +26 -0
  104. package/src/llm/provider.js +212 -0
  105. package/src/llm/registry.js +11 -0
  106. package/src/{core/token-counter.js → llm/tokens.js} +4 -37
  107. package/src/{core/plugin-base.js → plugin/base.js} +10 -136
  108. package/src/plugin/index.js +14 -0
  109. package/src/plugin/loader.js +101 -0
  110. package/src/plugin/manager.js +484 -0
  111. package/src/{core → session}/branch-summary-auto.js +2 -2
  112. package/src/{core/chat-session.js → session/chat.js} +2 -2
  113. package/src/session/index.js +7 -0
  114. package/src/{core/session-manager.js → session/session.js} +2 -2
  115. package/src/session/ttl.js +92 -0
  116. package/src/{core/jsonl-storage.js → storage/jsonl.js} +1 -1
  117. package/src/tool/executor.js +85 -0
  118. package/src/tool/index.js +15 -0
  119. package/src/tool/registry.js +143 -0
  120. package/src/{core/tool-router.js → tool/router.js} +17 -124
  121. package/src/tool/schema.js +108 -0
  122. package/src/utils/data-splitter.js +1 -1
  123. package/src/utils/download.js +1 -1
  124. package/src/utils/index.js +6 -6
  125. package/src/utils/message-validator.js +1 -1
  126. package/tests/core/context-storage.test.js +46 -0
  127. package/tests/core/llm.test.js +54 -0
  128. package/tests/core/plugin.test.js +42 -0
  129. package/tests/core/tool.test.js +60 -0
  130. package/tests/setup.js +10 -0
  131. package/tests/smoke.test.js +58 -0
  132. package/vitest.config.js +9 -0
  133. package/cli/src/daemon.js +0 -149
  134. package/docs/CONTEXT_DESIGN.md +0 -1596
  135. package/docs/ai-sdk-optimization.md +0 -655
  136. package/docs/features.md +0 -120
  137. package/docs/qq-bot.md +0 -976
  138. package/docs/quick-reference.md +0 -160
  139. package/docs/user-manual.md +0 -1391
  140. package/images/geometric_shapes.jpg +0 -0
  141. package/images/sunset_mountain_lake.jpg +0 -0
  142. package/skills/poster-guide/SKILL.md +0 -792
  143. package/src/capabilities/index.js +0 -11
  144. package/src/core/agent.js +0 -808
  145. package/src/core/context-compressor.js +0 -959
  146. package/src/core/enhanced-context-compressor.js +0 -210
  147. package/src/core/framework.js +0 -1422
  148. package/src/core/index.js +0 -30
  149. package/src/core/plugin-manager.js +0 -961
  150. package/src/core/provider-registry.js +0 -159
  151. package/src/core/provider.js +0 -156
  152. package/src/core/request-context.js +0 -98
  153. package/src/core/subagent.js +0 -442
  154. package/src/core/system-prompt-builder.js +0 -120
  155. package/src/core/tool-executor.js +0 -202
  156. package/src/core/tool-registry.js +0 -517
  157. package/src/core/worker-agent.js +0 -192
  158. package/src/executors/executor-base.js +0 -58
  159. package/src/utils/error-boundary.js +0 -363
  160. package/src/utils/error.js +0 -374
  161. package/system.md +0 -1645
  162. package/website_v2/README.md +0 -57
  163. package/website_v2/SPEC.md +0 -1
  164. package/website_v2/docs/api.html +0 -128
  165. package/website_v2/docs/configuration.html +0 -147
  166. package/website_v2/docs/plugin-development.html +0 -129
  167. package/website_v2/docs/project-structure.html +0 -89
  168. package/website_v2/docs/skill-development.html +0 -85
  169. package/website_v2/index.html +0 -489
  170. package/website_v2/scripts/main.js +0 -93
  171. package/website_v2/styles/animations.css +0 -8
  172. package/website_v2/styles/docs.css +0 -83
  173. package/website_v2/styles/main.css +0 -417
  174. package/xhs_auth.json +0 -268
  175. package//346/265/267/346/212/245/346/217/222/344/273/266.md +0 -621
  176. /package/plugins/{ambient-agent → ambient}/constants.js +0 -0
  177. /package/plugins/{email → messaging/email}/constants.js +0 -0
  178. /package/plugins/{email → messaging/email}/handlers.js +0 -0
  179. /package/plugins/{email → messaging/email}/monitor.js +0 -0
  180. /package/plugins/{email → messaging/email}/parser.js +0 -0
  181. /package/plugins/{email → messaging/email}/reply.js +0 -0
  182. /package/plugins/{email → messaging/email}/utils.js +0 -0
  183. /package/{examples → sandbox}/test-chat.js +0 -0
  184. /package/{examples → sandbox}/test-mcp.js +0 -0
  185. /package/{examples → sandbox}/test-reload.js +0 -0
  186. /package/{examples → sandbox}/test-telegram.js +0 -0
  187. /package/{examples → sandbox}/test-tg-bot.js +0 -0
  188. /package/{examples → sandbox}/test-tg-simple.js +0 -0
  189. /package/{examples → sandbox}/test-tg.js +0 -0
  190. /package/{examples → sandbox}/test-think.js +0 -0
  191. /package/src/{core/sub-agent-config.js → agent/sub-config.js} +0 -0
  192. /package/{cli/src → src/cli}/commands/daemon.js +0 -0
  193. /package/{cli/src → src/cli}/commands/list.js +0 -0
  194. /package/{cli/src → src/cli}/commands/plugin.js +0 -0
  195. /package/{cli/src → src/cli}/ui/components/agent-mention-provider.js +0 -0
  196. /package/{cli/src → src/cli}/ui/components/chained-autocomplete-provider.js +0 -0
  197. /package/{cli/src → src/cli}/ui/components/message-bubble.js +0 -0
  198. /package/{cli/src → src/cli}/ui/components/status-bar.js +0 -0
  199. /package/{cli/src → src/cli}/utils/ansi.js +0 -0
  200. /package/{cli/src → src/cli}/utils/config.js +0 -0
  201. /package/{cli/src → src/cli}/utils/markdown.js +0 -0
  202. /package/{cli/src → src/cli}/utils/plugin-config.js +0 -0
  203. /package/{cli/src → src/cli}/utils/render-diff.js +0 -0
  204. /package/src/{utils/circuit-breaker.js → common/circuit.js} +0 -0
  205. /package/src/{core → common}/constants.js +0 -0
  206. /package/src/{utils/edit-diff.js → common/diff.js} +0 -0
  207. /package/src/{utils/event-emitter.js → common/events.js} +0 -0
  208. /package/src/{utils → common}/id.js +0 -0
  209. /package/src/{utils → common}/retry.js +0 -0
  210. /package/src/{core/notification-manager.js → notification/manager.js} +0 -0
  211. /package/src/{core/session-entry.js → session/entry.js} +0 -0
  212. /package/src/{core/storage-manager.js → storage/manager.js} +0 -0
@@ -4,14 +4,13 @@
4
4
  * 任务触发时自动唤醒 Agent 发送消息
5
5
  */
6
6
 
7
- const { Plugin } = require('../src/core/plugin-base')
8
- const { logger } = require('../src/utils/logger')
7
+ const { Plugin } = require('../../../src/plugin/base')
8
+ const { logger } = require('../../../src/common/logger')
9
9
  const log = logger.child('Scheduler')
10
10
  const { z } = require('zod')
11
11
  const fs = require('fs')
12
12
  const path = require('path')
13
13
 
14
- // 尝试加载 node-schedule
15
14
  let schedule = null
16
15
  try {
17
16
  schedule = require('node-schedule')
@@ -19,9 +18,6 @@ try {
19
18
  log.warn(' node-schedule not installed, cron tasks will not work')
20
19
  }
21
20
 
22
- // ============================================================================
23
- // TaskStore - 持久化任务到 .foliko/data/scheduler/tasks.json
24
- // ============================================================================
25
21
  class TaskStore {
26
22
  constructor(persistencePath) {
27
23
  this._persistencePath = persistencePath
@@ -40,7 +36,6 @@ class TaskStore {
40
36
 
41
37
  saveTasks(tasks) {
42
38
  try {
43
- // 序列化时移除不可保存的字段(timer, cronTask)
44
39
  const serializable = tasks.map(t => ({
45
40
  id: t.id,
46
41
  name: t.name,
@@ -54,10 +49,10 @@ class TaskStore {
54
49
  cronExpression: t.cronExpression,
55
50
  sessionId: t.sessionId,
56
51
  llm: t.llm,
57
- persistDelay: t.persistDelay, // 相对时间的延迟毫秒数
58
- persistNextRun: t.persistNextRun, // 下次执行时间
59
- notify: t.notify, // 是否发送通知
60
- shell: t.shell // Shell 命令
52
+ persistDelay: t.persistDelay,
53
+ persistNextRun: t.persistNextRun,
54
+ notify: t.notify,
55
+ shell: t.shell
61
56
  }))
62
57
  fs.writeFileSync(this._getTasksPath(), JSON.stringify(serializable, null, 2))
63
58
  } catch (err) {
@@ -79,7 +74,6 @@ class TaskStore {
79
74
  }
80
75
  }
81
76
 
82
- // 时间解析辅助函数
83
77
  function parseDelay(delayStr) {
84
78
  const match = delayStr.match(/^(\d+)\s*(second|minute|hour|day|week)s?$/i)
85
79
  if (!match) return null
@@ -97,7 +91,6 @@ function parseDelay(delayStr) {
97
91
 
98
92
  function parseAtTime(timeStr) {
99
93
  const now = new Date()
100
- // 简单时间格式 "12:00"
101
94
  const timeMatch = timeStr.match(/^(\d{1,2}):(\d{2})(?::(\d{2}))?$/)
102
95
  if (timeMatch) {
103
96
  const date = new Date(now)
@@ -110,9 +103,6 @@ function parseAtTime(timeStr) {
110
103
  return new Date(timeStr)
111
104
  }
112
105
 
113
- /**
114
- * 生成唯一 ID
115
- */
116
106
  function generateId() {
117
107
  if (require('crypto').randomUUID) {
118
108
  return require('crypto').randomUUID()
@@ -129,7 +119,7 @@ class SchedulerPlugin extends Plugin {
129
119
  this.priority = 15
130
120
  this.system = true
131
121
  this.config = {
132
- checkInterval: config.checkInterval || 1000, // 每秒检查一次
122
+ checkInterval: config.checkInterval || 1000,
133
123
  persistencePath: config.persistencePath || '.foliko/data/scheduler'
134
124
  }
135
125
 
@@ -148,14 +138,10 @@ class SchedulerPlugin extends Plugin {
148
138
 
149
139
  install(framework) {
150
140
  this._framework = framework
151
- // 初始化任务存储
152
141
  this._taskStore = new TaskStore(this.config.persistencePath)
153
142
  return this
154
143
  }
155
144
 
156
- /**
157
- * 获取 Agent 实例
158
- */
159
145
  _getAgent() {
160
146
  if (this._agent) return this._agent
161
147
  if (this._framework._mainAgent) {
@@ -168,10 +154,8 @@ class SchedulerPlugin extends Plugin {
168
154
  }
169
155
 
170
156
  start(framework) {
171
- // 获取 Agent 实例
172
157
  this._agent = this._getAgent()
173
158
 
174
- // 注册调度工具
175
159
  framework.registerTool({
176
160
  name: 'schedule_task',
177
161
  description: '设置定时提醒任务。支持多种时间格式:相对时间(1 minute, 2 hours)、具体时间(12:00)、Cron表达式(* * * * *)。系统会自动判断任务是否需要 LLM 处理。',
@@ -194,7 +178,6 @@ class SchedulerPlugin extends Plugin {
194
178
  return { success: false, error: 'Agent not available' }
195
179
  }
196
180
 
197
- // 如果指定了 shell 命令,创建 Shell 任务
198
181
  if (shell) {
199
182
  const taskId = `task_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
200
183
  const isCron = /^[\d*,\/-\s]+$/.test(scheduleTime) && scheduleTime.split(' ').length >= 5
@@ -240,7 +223,6 @@ class SchedulerPlugin extends Plugin {
240
223
  }
241
224
  }
242
225
  } else {
243
- // 一次性 Shell 任务
244
226
  const delayMs = parseDelay(scheduleTime)
245
227
  if (!delayMs && !scheduleTime.includes(':')) {
246
228
  return { success: false, error: '无效的时间格式' }
@@ -293,7 +275,6 @@ class SchedulerPlugin extends Plugin {
293
275
  }
294
276
  }
295
277
 
296
- // 如果没有指定 sessionId,优先从执行上下文获取(来自 WeChat 等消息源)
297
278
  let targetSessionId = sessionId
298
279
  if (!targetSessionId) {
299
280
  const ctx = this._framework.getExecutionContext()
@@ -301,21 +282,17 @@ class SchedulerPlugin extends Plugin {
301
282
  targetSessionId = ctx.sessionId
302
283
  }
303
284
  }
304
- // 如果执行上下文也没有,从 sessionPlugin 获取最近活跃会话
305
285
  if (!targetSessionId) {
306
286
  const sessionPlugin = this._framework.pluginManager.get('session')
307
287
  if (sessionPlugin) {
308
288
  const sessions = sessionPlugin.listSessions()
309
- // 获取最近的活跃会话
310
289
  if (sessions.length > 0) {
311
- // 按 lastActive 排序,取最新的
312
290
  sessions.sort((a, b) => {
313
291
  const aTime = a.lastActive ? new Date(a.lastActive).getTime() : 0
314
292
  const bTime = b.lastActive ? new Date(b.lastActive).getTime() : 0
315
293
  return bTime - aTime
316
294
  })
317
295
  targetSessionId = sessions[0].id
318
- //log.info(` Auto-detected active session: ${targetSessionId}`)
319
296
  }
320
297
  }
321
298
  }
@@ -323,7 +300,6 @@ class SchedulerPlugin extends Plugin {
323
300
  const taskId = `task_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
324
301
  let task
325
302
 
326
- // 自动检测是否需要 LLM 处理
327
303
  const LLM_KEYWORDS = [
328
304
  '分析', '查询', '查看', '检查', '总结', '搜索', '获取',
329
305
  'list', 'get', 'check', 'search', 'find', 'fetch',
@@ -336,11 +312,9 @@ class SchedulerPlugin extends Plugin {
336
312
  )
337
313
  const llmMode = needsLLM
338
314
 
339
- // 检测是否像 Cron 表达式
340
315
  const isCron = /^[\d*,\/-\s]+$/.test(scheduleTime) && scheduleTime.split(' ').length >= 5
341
316
 
342
317
  if (isCron || repeat) {
343
- // Cron 任务
344
318
  if (!schedule) {
345
319
  return { success: false, error: 'node-schedule not installed' }
346
320
  }
@@ -358,15 +332,13 @@ class SchedulerPlugin extends Plugin {
358
332
  cronTask: null,
359
333
  sessionId: targetSessionId || null,
360
334
  llm: llmMode,
361
- notify: args.notify !== false // 默认发送通知
335
+ notify: args.notify !== false
362
336
  }
363
337
 
364
- // 使用 node-schedule 调度
365
338
  task.cronTask = schedule.scheduleJob(task.cronExpression, async () => {
366
339
  await this._executeTask(task)
367
340
  })
368
341
  } else if (scheduleTime.includes(':')) {
369
- // 具体时间
370
342
  const runAt = parseAtTime(scheduleTime)
371
343
  task = {
372
344
  id: taskId,
@@ -387,7 +359,6 @@ class SchedulerPlugin extends Plugin {
387
359
  await this._executeTask(task)
388
360
  }, runAt.getTime() - Date.now())
389
361
  } else {
390
- // 相对时间
391
362
  const delayMs = parseDelay(scheduleTime)
392
363
  if (!delayMs) {
393
364
  return { success: false, error: '无效的时间格式' }
@@ -406,7 +377,7 @@ class SchedulerPlugin extends Plugin {
406
377
  timer: null,
407
378
  sessionId: targetSessionId || null,
408
379
  llm: llmMode,
409
- persistDelay: delayMs, // 保存延迟毫秒数用于持久化
380
+ persistDelay: delayMs,
410
381
  notify: args.notify !== false
411
382
  }
412
383
  task.timer = setTimeout(async () => {
@@ -416,9 +387,8 @@ class SchedulerPlugin extends Plugin {
416
387
 
417
388
  this._tasks.set(task.id, task)
418
389
  this._taskStats.total++
419
- this._saveTasks() // 持久化
390
+ this._saveTasks()
420
391
 
421
- // 发送任务创建事件
422
392
  this._framework.emit('scheduler:task_created', {
423
393
  taskId: task.id,
424
394
  taskName: task.name,
@@ -489,9 +459,8 @@ class SchedulerPlugin extends Plugin {
489
459
 
490
460
  const taskName = task.name
491
461
  this._cancelTask(task)
492
- this._saveTasks() // 持久化
462
+ this._saveTasks()
493
463
 
494
- // 发送任务取消通知
495
464
  this._framework.emit('notification', {
496
465
  title: '任务已取消',
497
466
  message: `定时任务 "${taskName}" 已取消`,
@@ -528,18 +497,13 @@ class SchedulerPlugin extends Plugin {
528
497
  }
529
498
  })
530
499
 
531
- // 启动调度循环(用于检查一次性任务)
532
500
  this._startScheduler()
533
501
 
534
- // 加载持久化的任务
535
502
  this._loadPersistedTasks()
536
503
 
537
504
  return this
538
505
  }
539
506
 
540
- /**
541
- * 启动调度循环
542
- */
543
507
  _startScheduler() {
544
508
  if (this._timer) {
545
509
  clearInterval(this._timer)
@@ -550,46 +514,31 @@ class SchedulerPlugin extends Plugin {
550
514
  }, this.config.checkInterval)
551
515
  }
552
516
 
553
- /**
554
- * 检查任务状态(主要用于更新 stats)
555
- */
556
517
  _checkTasks() {
557
518
  for (const [id, task] of this._tasks) {
558
519
  if (!task.enabled) continue
559
- // 统计信息更新
560
520
  }
561
521
  }
562
522
 
563
- /**
564
- * 保存任务到持久化存储
565
- */
566
523
  _saveTasks() {
567
524
  if (this._taskStore) {
568
525
  this._taskStore.saveTasks(Array.from(this._tasks.values()))
569
526
  }
570
527
  }
571
528
 
572
- /**
573
- * 加载持久化的任务并重新调度
574
- */
575
529
  _loadPersistedTasks() {
576
530
  if (!this._taskStore) return
577
531
 
578
532
  const savedTasks = this._taskStore.loadTasks()
579
533
  if (!savedTasks || savedTasks.length === 0) return
580
534
 
581
- //log.info(` 加载 ${savedTasks.length} 个持久化任务...`)
582
-
583
535
  for (const saved of savedTasks) {
584
- // 跳过已过期的任务或已清理的任务
585
536
  if (saved.type === 'once' && saved.runCount > 0) {
586
- //log.info(` 跳过已完成的一次性任务: ${saved.name}`)
587
537
  continue
588
538
  }
589
539
 
590
540
  let task = { ...saved }
591
541
 
592
- // 重新调度 Cron 任务
593
542
  if (task.type === 'cron' && task.enabled && schedule) {
594
543
  try {
595
544
  task.cronTask = schedule.scheduleJob(task.cronExpression, async () => {
@@ -597,12 +546,10 @@ class SchedulerPlugin extends Plugin {
597
546
  })
598
547
  this._tasks.set(task.id, task)
599
548
  this._taskStats.total++
600
- //log.info(` 已恢复 Cron 任务: ${task.name}`)
601
549
  } catch (err) {
602
550
  log.error(` 恢复 Cron 任务失败: ${task.name}`, err.message)
603
551
  }
604
552
  }
605
- // 重新调度 Cron Shell 任务
606
553
  else if (task.type === 'shell' && task.enabled && task.cronExpression && schedule) {
607
554
  try {
608
555
  task.cronTask = schedule.scheduleJob(task.cronExpression, async () => {
@@ -610,12 +557,10 @@ class SchedulerPlugin extends Plugin {
610
557
  })
611
558
  this._tasks.set(task.id, task)
612
559
  this._taskStats.total++
613
- //log.info(` 已恢复 Shell Cron 任务: ${task.name}`)
614
560
  } catch (err) {
615
561
  log.error(` 恢复 Shell Cron 任务失败: ${task.name}`, err.message)
616
562
  }
617
563
  }
618
- // 重新调度相对时间任务(计算新的执行时间)
619
564
  else if (task.type === 'once' && task.enabled && task.persistDelay) {
620
565
  const newDelay = task.persistDelay
621
566
  if (newDelay > 0) {
@@ -625,10 +570,8 @@ class SchedulerPlugin extends Plugin {
625
570
  }, newDelay)
626
571
  this._tasks.set(task.id, task)
627
572
  this._taskStats.total++
628
- //log.info(` 已恢复一次性任务: ${task.name},将在 ${newDelay}ms 后执行`)
629
573
  }
630
574
  }
631
- // 重新调度绝对时间任务
632
575
  else if (task.type === 'once' && task.enabled && task.runAt) {
633
576
  const runAt = new Date(task.runAt)
634
577
  if (runAt > new Date()) {
@@ -638,17 +581,11 @@ class SchedulerPlugin extends Plugin {
638
581
  }, delay)
639
582
  this._tasks.set(task.id, task)
640
583
  this._taskStats.total++
641
- //log.info(` 已恢复一次性任务: ${task.name},将在 ${runAt} 执行`)
642
- } else {
643
- //log.info(` 跳过已过期的任务: ${task.name}`)
644
584
  }
645
585
  }
646
586
  }
647
587
  }
648
588
 
649
- /**
650
- * 取消任务
651
- */
652
589
  _cancelTask(task) {
653
590
  if (task.timer) {
654
591
  clearTimeout(task.timer)
@@ -661,23 +598,12 @@ class SchedulerPlugin extends Plugin {
661
598
  task.enabled = false
662
599
  }
663
600
 
664
- /**
665
- * 执行任务
666
- */
667
601
  async _executeTask(task) {
668
- // //log.info(` Executing task: ${task.name} (${task.id})`)
669
- // //log.info(` Message: ${task.message}`)
670
- // // if (task.sessionId) {
671
- // // //log.info(` Target session: ${task.sessionId}`)
672
- // // }
673
- // //log.info(` LLM mode: ${task.llm ? 'enabled' : 'disabled'}`)
674
-
675
602
  task.lastRun = new Date()
676
603
  task.runCount++
677
604
  this._taskStats.running++
678
605
 
679
606
  try {
680
- // Shell 命令执行模式
681
607
  if (task.type === 'shell') {
682
608
  const result = await this._framework.executeTool('shell', { command: task.shell })
683
609
  this._taskStats.completed++
@@ -705,7 +631,6 @@ class SchedulerPlugin extends Plugin {
705
631
 
706
632
  return { success: true }
707
633
  } else if (task.llm) {
708
- // LLM 模式:使用子Agent处理
709
634
  const schedulerAgent = this._framework.createSubAgent({
710
635
  name: 'scheduler_task',
711
636
  role: '定时任务执行助手,专注于处理定时提醒和任务执行'
@@ -715,17 +640,9 @@ class SchedulerPlugin extends Plugin {
715
640
 
716
641
  this._taskStats.completed++
717
642
 
718
- // 获取 LLM 返回的消息
719
643
  const responseText = result.message
720
644
 
721
- // if (responseText) {
722
- // console.log(`\n🔔 [定时提醒] ${responseText}\n`)
723
- // }
724
-
725
- // 根据 notify 参数决定是否发送通知
726
- // 只有当 LLM 返回了有效消息时才发送通知
727
645
  if (task.notify !== false && responseText && responseText.trim()) {
728
- // 发送统一的通知事件
729
646
  this._framework.emit('notification', {
730
647
  title: task.name,
731
648
  message: responseText,
@@ -734,7 +651,6 @@ class SchedulerPlugin extends Plugin {
734
651
  sessionId: task.sessionId,
735
652
  timestamp: new Date()
736
653
  })
737
- // 发送 scheduler:reminder 事件
738
654
  this._framework.emit('scheduler:reminder', {
739
655
  taskId: task.id,
740
656
  message: task.message,
@@ -742,16 +658,12 @@ class SchedulerPlugin extends Plugin {
742
658
  })
743
659
  }
744
660
 
745
- // 发送任务完成事件
746
661
  this._framework.emit('scheduler:task_completed', {
747
662
  taskId: task.id,
748
663
  result: responseText || task.message
749
664
  })
750
665
  } else {
751
- // 直接显示模式:只显示提醒,不发 LLM
752
- // 根据 notify 参数决定是否发送通知
753
666
  if (task.notify !== false) {
754
- // 发送统一的通知事件
755
667
  this._framework.emit('notification', {
756
668
  title: task.name,
757
669
  message: task.message,
@@ -760,7 +672,6 @@ class SchedulerPlugin extends Plugin {
760
672
  sessionId: task.sessionId,
761
673
  timestamp: new Date()
762
674
  })
763
- // 发送 scheduler:reminder 事件
764
675
  this._framework.emit('scheduler:reminder', {
765
676
  taskId: task.id,
766
677
  message: task.message,
@@ -768,7 +679,6 @@ class SchedulerPlugin extends Plugin {
768
679
  })
769
680
  }
770
681
 
771
- // 发送任务完成事件
772
682
  this._framework.emit('scheduler:task_completed', {
773
683
  taskId: task.id,
774
684
  result: task.message
@@ -776,7 +686,6 @@ class SchedulerPlugin extends Plugin {
776
686
  this._taskStats.completed++
777
687
  }
778
688
 
779
- // 一次性任务执行后清理
780
689
  if (task.type === 'once' && !task.cronTask) {
781
690
  this._cleanupTask(task.id)
782
691
  }
@@ -786,7 +695,6 @@ class SchedulerPlugin extends Plugin {
786
695
  this._taskStats.failed++
787
696
  log.error(` Task ${task.name} failed: ${err.message}`)
788
697
 
789
- // 发送统一的通知事件
790
698
  this._framework.emit('notification', {
791
699
  title: `任务失败: ${task.name}`,
792
700
  message: err.message,
@@ -796,13 +704,11 @@ class SchedulerPlugin extends Plugin {
796
704
  timestamp: new Date()
797
705
  })
798
706
 
799
- // 发送任务失败事件
800
707
  this._framework.emit('scheduler:task_failed', {
801
708
  taskId: task.id,
802
709
  error: err.message
803
710
  })
804
711
 
805
- // 一次性任务失败后也清理
806
712
  if (task.type === 'once' && !task.cronTask) {
807
713
  this._cleanupTask(task.id)
808
714
  }
@@ -813,9 +719,6 @@ class SchedulerPlugin extends Plugin {
813
719
  }
814
720
  }
815
721
 
816
- /**
817
- * 清理任务
818
- */
819
722
  _cleanupTask(taskId) {
820
723
  const task = this._tasks.get(taskId)
821
724
  if (task) {
@@ -828,13 +731,10 @@ class SchedulerPlugin extends Plugin {
828
731
  task.cronTask = null
829
732
  }
830
733
  this._tasks.delete(taskId)
831
- this._saveTasks() // 持久化
734
+ this._saveTasks()
832
735
  }
833
736
  }
834
737
 
835
- /**
836
- * 停止所有任务
837
- */
838
738
  stopAll() {
839
739
  for (const task of this._tasks.values()) {
840
740
  this._cancelTask(task)
@@ -845,7 +745,6 @@ class SchedulerPlugin extends Plugin {
845
745
  this._timer = null
846
746
  }
847
747
 
848
- // 保存状态
849
748
  this._saveTasks()
850
749
  }
851
750
 
@@ -853,7 +752,6 @@ class SchedulerPlugin extends Plugin {
853
752
  this._framework = framework
854
753
  this._agent = this._getAgent()
855
754
  this._startScheduler()
856
- // 重新加载持久化任务
857
755
  this._loadPersistedTasks()
858
756
  }
859
757