foliko 1.1.67 → 1.1.69

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 (157) hide show
  1. package/.claude/settings.local.json +19 -10
  2. package/.dockerignore +45 -45
  3. package/.env.example +56 -56
  4. package/CLAUDE.md +2 -2
  5. package/README.md +13 -13
  6. package/SPEC.md +3 -3
  7. package/cli/src/commands/chat.js +2 -20
  8. package/cli/src/commands/list.js +7 -6
  9. package/cli/src/commands/plugin.js +3 -2
  10. package/cli/src/daemon.js +2 -2
  11. package/cli/src/ui/chat-ui-old.js +15 -4
  12. package/cli/src/ui/chat-ui.js +236 -203
  13. package/cli/src/ui/footer-bar.js +20 -46
  14. package/cli/src/ui/message-bubble.js +24 -2
  15. package/cli/src/ui/status-bar.js +177 -0
  16. package/cli/src/utils/config.js +29 -0
  17. package/cli/src/utils/plugin-config.js +1 -1
  18. package/docker-compose.yml +33 -33
  19. package/docs/features.md +120 -120
  20. package/docs/quick-reference.md +160 -160
  21. package/docs/user-manual.md +1391 -1391
  22. package/examples/ambient-example.js +2 -2
  23. package/examples/bootstrap.js +3 -3
  24. package/examples/test-chat.js +1 -1
  25. package/examples/test-reload.js +1 -1
  26. package/examples/test-telegram.js +1 -1
  27. package/examples/test-tg-bot.js +1 -1
  28. package/examples/test-tg-simple.js +2 -2
  29. package/examples/test-tg.js +1 -1
  30. package/examples/test-think.js +1 -1
  31. package/examples/test-weixin-feishu.js +3 -3
  32. package/package.json +3 -1
  33. package/plugins/ambient-agent/index.js +1 -1
  34. package/plugins/audit-plugin.js +84 -29
  35. package/plugins/coordinator-plugin.js +14 -12
  36. package/plugins/data-splitter-plugin.js +323 -0
  37. package/plugins/default-plugins.js +23 -12
  38. package/plugins/email/index.js +1 -1
  39. package/plugins/extension-executor-plugin.js +87 -9
  40. package/plugins/feishu-plugin.js +118 -16
  41. package/plugins/file-system-plugin.js +68 -50
  42. package/plugins/gate-trading.js +10 -10
  43. package/plugins/install-plugin.js +7 -7
  44. package/plugins/memory-plugin.js +9 -12
  45. package/plugins/plugin-manager-plugin.js +12 -14
  46. package/plugins/python-executor-plugin.js +1 -1
  47. package/plugins/python-plugin-loader.js +1 -1
  48. package/plugins/qq-plugin.js +151 -24
  49. package/plugins/rules-plugin.js +8 -8
  50. package/plugins/scheduler-plugin.js +24 -20
  51. package/plugins/session-plugin.js +313 -397
  52. package/plugins/storage-plugin.js +235 -175
  53. package/plugins/subagent-plugin.js +17 -13
  54. package/plugins/telegram-plugin.js +116 -17
  55. package/plugins/think-plugin.js +64 -60
  56. package/plugins/tools-plugin.js +8 -8
  57. package/plugins/web-plugin.js +2 -2
  58. package/plugins/weixin-plugin.js +107 -24
  59. package/skills/find-skills/AGENTS.md +2 -2
  60. package/skills/find-skills/SKILL.md +133 -133
  61. package/skills/foliko-dev/AGENTS.md +236 -236
  62. package/skills/foliko-dev/SKILL.md +19 -19
  63. package/skills/mcp-usage/SKILL.md +200 -200
  64. package/skills/plugin-guide/SKILL.md +4 -4
  65. package/skills/python-plugin-dev/SKILL.md +5 -5
  66. package/skills/skill-guide/SKILL.md +104 -6
  67. package/skills/subagent-guide/SKILL.md +237 -237
  68. package/skills/workflow-guide/SKILL.md +646 -646
  69. package/src/capabilities/skill-manager.js +124 -17
  70. package/src/capabilities/workflow-engine.js +3 -3
  71. package/src/core/agent-chat.js +72 -26
  72. package/src/core/agent.js +17 -27
  73. package/src/core/branch-summary-auto.js +206 -0
  74. package/src/core/chat-session.js +45 -169
  75. package/src/core/command-registry.js +200 -0
  76. package/src/core/constants.js +198 -0
  77. package/src/core/context-compressor.js +702 -326
  78. package/src/core/context-manager.js +0 -1
  79. package/src/core/enhanced-context-compressor.js +210 -0
  80. package/src/core/framework.js +260 -84
  81. package/src/core/jsonl-storage.js +253 -0
  82. package/src/core/plugin-base.js +7 -5
  83. package/src/core/plugin-manager.js +15 -10
  84. package/src/core/provider-registry.js +159 -0
  85. package/src/core/provider.js +2 -0
  86. package/src/core/session-entry.js +225 -0
  87. package/src/core/session-manager.js +701 -0
  88. package/src/core/storage-manager.js +494 -0
  89. package/src/core/sub-agent-config.js +1 -1
  90. package/src/core/subagent.js +16 -135
  91. package/src/core/token-counter.js +177 -58
  92. package/src/core/tool-executor.js +2 -70
  93. package/src/core/ui-extension-context.js +174 -0
  94. package/src/executors/mcp-executor.js +27 -16
  95. package/src/utils/chat-queue.js +11 -22
  96. package/src/utils/data-splitter.js +345 -0
  97. package/src/utils/logger.js +152 -180
  98. package/src/utils/message-validator.js +283 -0
  99. package/src/utils/plugin-helpers.js +2 -2
  100. package/src/utils/retry.js +168 -22
  101. package/website_v2/docs/api.html +1 -1
  102. package/website_v2/docs/configuration.html +2 -2
  103. package/website_v2/docs/plugin-development.html +4 -4
  104. package/website_v2/docs/project-structure.html +2 -2
  105. package/website_v2/docs/skill-development.html +2 -2
  106. package/website_v2/index.html +1 -1
  107. package/website_v2/styles/animations.css +7 -7
  108. package/.agent/agents/backend-dev.md +0 -102
  109. package/.agent/agents/data-analyst.md +0 -117
  110. package/.agent/agents/devops.md +0 -115
  111. package/.agent/agents/frontend-dev.md +0 -94
  112. package/.agent/agents/network-requester.md +0 -44
  113. package/.agent/agents/poster-designer.md +0 -52
  114. package/.agent/agents/product-manager.md +0 -85
  115. package/.agent/agents/qa-engineer.md +0 -100
  116. package/.agent/agents/security-engineer.md +0 -99
  117. package/.agent/agents/team-lead.md +0 -137
  118. package/.agent/agents/ui-designer.md +0 -116
  119. package/.agent/data/default.json +0 -58
  120. package/.agent/data/email/processed-emails.json +0 -1
  121. package/.agent/data/plugins-state.json +0 -199
  122. package/.agent/data/scheduler/tasks.json +0 -1
  123. package/.agent/data/web/web-config.json +0 -5
  124. package/.agent/data/weixin/images/file_1776188148383jpg +0 -0
  125. package/.agent/data/weixin/images/file_1776188458326.jpg +0 -0
  126. package/.agent/data/weixin/images/file_1776188689423.jpg +0 -0
  127. package/.agent/data/weixin/images/file_1776188813604.jpg +0 -0
  128. package/.agent/data/weixin/images/file_1776189097450.jpg +0 -0
  129. package/.agent/data/weixin/videos/file_1776188318431.mp4 +0 -0
  130. package/.agent/data/weixin.json +0 -6
  131. package/.agent/mcp_config.json +0 -14
  132. package/.agent/memory/user/mof6gk94-kneeuh.md +0 -9
  133. package/.agent/package.json +0 -8
  134. package/.agent/plugins/marknative/README.md +0 -134
  135. package/.agent/plugins/marknative/fonts/SegoeUI Emoji.ttf +0 -0
  136. package/.agent/plugins/marknative/fonts.zip +0 -0
  137. package/.agent/plugins/marknative/index.js +0 -256
  138. package/.agent/plugins/marknative/package.json +0 -12
  139. package/.agent/plugins/test-plugin.py +0 -99
  140. package/.agent/plugins.json +0 -14
  141. package/.agent/python-scripts/test_sample.py +0 -24
  142. package/.agent/sessions/cli_default.json +0 -247
  143. package/.agent/skills/agent-browser/SKILL.md +0 -311
  144. package/.agent/skills/agent-browser/TEST_PLAN.md +0 -200
  145. package/.agent/skills/sysinfo/SKILL.md +0 -38
  146. package/.agent/skills/sysinfo/system-info.sh +0 -130
  147. package/.agent/skills/workflow/SKILL.md +0 -324
  148. package/.agent/test-agent.js +0 -35
  149. package/.agent/weixin.json +0 -6
  150. package/.agent/workflows/email-digest.json +0 -50
  151. package/.agent/workflows/file-backup.json +0 -21
  152. package/.agent/workflows/get-ip-notify.json +0 -32
  153. package/.agent/workflows/news-aggregator.json +0 -93
  154. package/.agent/workflows/news-dashboard-v2.json +0 -94
  155. package/.agent/workflows/notification-batch.json +0 -32
  156. package/src/core/session-context.js +0 -346
  157. package/src/core/session-storage.js +0 -295
@@ -188,18 +188,28 @@ class FeishuPlugin extends Plugin {
188
188
  const command = parts[0].substring(1)
189
189
  const args = parts.slice(1).join(' ')
190
190
 
191
+ // 检查 skill 命令 (格式: skillname:cmdname)
192
+ if (command.includes(':')) {
193
+ const result = await this._executeSkillCommand(command, args)
194
+ if (result) {
195
+ await this._sendMessage(openId, `✅ ${result.data || result}`, originalMsg)
196
+ return
197
+ }
198
+ }
199
+
191
200
  switch (command.toLowerCase()) {
192
201
  case 'start':
193
202
  case 'help':
194
- await this._sendMessage(openId,
195
- '👋 欢迎使用 AI 助手!\n\n直接发送消息即可与我对话。\n\n可用命令:\n/start - 显示帮助\n/clean - 清除对话上下文\n/history - 查看历史消息数',
196
- originalMsg)
203
+ await this._sendMessageHelp(openId, originalMsg)
197
204
  break
198
205
  case 'clear':
199
206
  case 'clean':
200
207
  await this._clearSessionContext(openId)
201
208
  await this._sendMessage(openId, '✅ 对话上下文已清除', originalMsg)
202
209
  break
210
+ case 'compress':
211
+ await this._compressSessionContext(openId)
212
+ break
203
213
  case 'history':
204
214
  if (this._sessionPlugin) {
205
215
  const session = this._sessionPlugin.getSession(`feishu_${openId}`)
@@ -212,6 +222,26 @@ class FeishuPlugin extends Plugin {
212
222
  }
213
223
  break
214
224
  default:
225
+ // 检查是否是 skill 命令 (格式: skillname:cmdname)
226
+ if (text.startsWith('/')) {
227
+ const cmdParts = command.split(':')
228
+ if (cmdParts.length === 2) {
229
+ const skillCmd = `${cmdParts[0]}:${cmdParts[1]}`
230
+ try {
231
+ const result = await this._framework.executeTool('ext_call', {
232
+ plugin: 'skill',
233
+ tool: skillCmd,
234
+ args: { args }
235
+ })
236
+ if (result.success !== false) {
237
+ await this._sendMessage(openId, `✅ ${result.data || result}`, originalMsg)
238
+ return
239
+ }
240
+ } catch (err) {
241
+ log.warn('Skill command failed:', err.message)
242
+ }
243
+ }
244
+ }
215
245
  await this._processChat(openId, text, originalMsg)
216
246
  }
217
247
  }
@@ -444,7 +474,7 @@ class FeishuPlugin extends Plugin {
444
474
  }
445
475
 
446
476
  /**
447
- * 清除会话上下文(清除消息历史和压缩计数)
477
+ * 清除会话上下文(清除消息历史)
448
478
  */
449
479
  async _clearSessionContext(openId) {
450
480
  const sessionId = `feishu_${openId}`
@@ -457,21 +487,93 @@ class FeishuPlugin extends Plugin {
457
487
  agent._chatHandler.clearHistory(sessionId)
458
488
  }
459
489
 
460
- // 清除 SessionContext 的消息和压缩计数
490
+ // 清除 SessionManager 的消息
461
491
  if (this._framework) {
462
- const sessionCtx = this._framework.getSessionContext(sessionId)
463
- if (sessionCtx) {
464
- sessionCtx.clearMessages()
465
- sessionCtx.compressionState.count = 0
466
- sessionCtx.metadata.compressionCount = 0
492
+ const manager = this._framework.getSessionContext(sessionId)
493
+ if (manager) {
494
+ manager.clearMessages()
495
+ }
496
+ }
497
+ }
498
+
499
+ /**
500
+ * 检查并执行 skill 命令
501
+ */
502
+ async _executeSkillCommand(command, args) {
503
+ const extExecutor = this._framework?.pluginManager?.get('extension-executor')
504
+ if (!extExecutor || typeof extExecutor.executeSkillCommand !== 'function') return null
505
+ return await extExecutor.executeSkillCommand(command, args)
506
+ }
507
+
508
+ /**
509
+ * 发送帮助信息
510
+ */
511
+ async _sendMessageHelp(openId, originalMsg) {
512
+ const extExecutor = this._framework?.pluginManager?.get('extension-executor')
513
+ const skillHelp = extExecutor?.getSkillCommandsHelp?.() || ''
514
+
515
+ let helpText = '👋 欢迎使用 AI 助手!\n\n直接发送消息即可与我对话。\n\n可用命令:\n/start - 显示帮助\n/clean - 清除对话上下文\n/compress - 压缩上下文\n/history - 查看历史消息数'
516
+
517
+ if (skillHelp) {
518
+ helpText += '\n\n【技能命令】\n' + skillHelp.split('\n').map(line => line.replace(/^\//, '/')).join('\n')
519
+ }
520
+
521
+ await this._sendMessage(openId, helpText, originalMsg)
522
+ }
523
+
524
+ /**
525
+ * 压缩会话上下文
526
+ */
527
+ async _compressSessionContext(openId) {
528
+ const sessionId = `feishu_${openId}`
529
+
530
+ // 获取 sessionAgent
531
+ const { agent } = this._getSessionAgent(openId)
532
+
533
+ if (agent._chatHandler) {
534
+ const chatHandler = agent._chatHandler
535
+
536
+ // 先确保从 SessionContext 加载历史(强制重新加载)
537
+ const messageStore = chatHandler._chatSession.getSessionMessageStore(sessionId)
538
+ messageStore.historyLoaded = false
539
+ chatHandler._chatSession.loadHistory(sessionId)
540
+
541
+ let messages = messageStore.messages
542
+
543
+ // 如果 messageStore.messages 为空,尝试从 SessionContext 获取
544
+ if (!messages || messages.length === 0) {
545
+ if (this._framework) {
546
+ const sessionCtx = this._framework.getSessionContext(sessionId)
547
+ if (sessionCtx) {
548
+ messages = sessionCtx.getMessages()
549
+ messageStore.messages = messages
550
+ }
551
+ }
467
552
  }
468
- // 同步清除 framework 缓存的 sessionContexts
469
- const cachedCtx = this._framework._sessionContexts?.get(sessionId)
470
- if (cachedCtx) {
471
- cachedCtx.clearMessages()
472
- cachedCtx.compressionState.count = 0
473
- cachedCtx.metadata.compressionCount = 0
553
+
554
+ const beforeCount = messages ? messages.length : 0
555
+ await this._sendMessage(openId, `📦 开始压缩上下文,当前 ${beforeCount} 条消息...`, null)
556
+
557
+ if (messages && messages.length > 0) {
558
+ if (chatHandler._contextCompressor) {
559
+ await chatHandler._contextCompressor.compress(sessionId, messages, messageStore)
560
+ const afterCount = messages.length
561
+ // 同步回 SessionContext
562
+ if (this._framework) {
563
+ const sessionCtx = this._framework.getSessionContext(sessionId)
564
+ if (sessionCtx) {
565
+ sessionCtx.replaceMessages(messages)
566
+ }
567
+ }
568
+ await this._sendMessage(openId, `✅ 压缩完成:${beforeCount} → ${afterCount} 条(保留 ${chatHandler._contextCompressor._keepRecentMessages} 条)`, null)
569
+ } else {
570
+ await this._sendMessage(openId, '❌ 压缩器不可用', null)
571
+ }
572
+ } else {
573
+ await this._sendMessage(openId, '❌ 没有消息需要压缩', null)
474
574
  }
575
+ } else {
576
+ await this._sendMessage(openId, '❌ ChatHandler 不可用', null)
475
577
  }
476
578
  }
477
579
 
@@ -76,7 +76,7 @@ class FileSystemPlugin extends Plugin {
76
76
  }
77
77
  }
78
78
  readDir(dirPath)
79
- return { success: true, dirPath, items: items.slice(0, 100), total: items.length }
79
+ return { success: true, data: items.slice(0, 100), metadata: { dirPath, total: items.length } }
80
80
  } catch (error) {
81
81
  return { success: false, error: error.message }
82
82
  }
@@ -95,7 +95,7 @@ class FileSystemPlugin extends Plugin {
95
95
  const dirPath = args.path || args.dirPath
96
96
  try {
97
97
  fs.mkdirSync(dirPath, { recursive: true })
98
- return { success: true, message: `目录已创建: ${dirPath}` }
98
+ return { success: true, data: `目录已创建: ${dirPath}` }
99
99
  } catch (error) {
100
100
  return { success: false, error: error.message }
101
101
  }
@@ -140,10 +140,12 @@ class FileSystemPlugin extends Plugin {
140
140
  }
141
141
  return {
142
142
  success: true,
143
- filePath: pathCheck.resolved,
144
- content,
145
- size: stat.size,
146
- lines: lines ? null : content.split('\n').length
143
+ data: content,
144
+ metadata: {
145
+ filePath: pathCheck.resolved,
146
+ size: stat.size,
147
+ lines: lines ? null : content.split('\n').length
148
+ }
147
149
  }
148
150
  } catch (error) {
149
151
  return { success: false, error: error.message }
@@ -210,10 +212,12 @@ class FileSystemPlugin extends Plugin {
210
212
  if (err) reject(err)
211
213
  else resolve({
212
214
  success: true,
213
- message: `文件已${mode === 'append' ? '追加' : '写入'}: ${pathCheck.resolved}`,
214
- filePath: pathCheck.resolved,
215
- size: content.length,
216
- mode
215
+ data: `文件已${mode === 'append' ? '追加' : '写入'}: ${pathCheck.resolved}`,
216
+ metadata: {
217
+ filePath: pathCheck.resolved,
218
+ size: content.length,
219
+ mode
220
+ }
217
221
  })
218
222
  })
219
223
  })
@@ -254,9 +258,11 @@ class FileSystemPlugin extends Plugin {
254
258
  fs.appendFileSync(pathCheck.resolved, content, 'utf8')
255
259
  return {
256
260
  success: true,
257
- message: `已追加内容到: ${pathCheck.resolved}`,
258
- filePath: pathCheck.resolved,
259
- appendedSize: content.length
261
+ data: `已追加内容到: ${pathCheck.resolved}`,
262
+ metadata: {
263
+ filePath: pathCheck.resolved,
264
+ appendedSize: content.length
265
+ }
260
266
  }
261
267
  } catch (error) {
262
268
  return { success: false, error: error.message }
@@ -297,7 +303,7 @@ class FileSystemPlugin extends Plugin {
297
303
  } else {
298
304
  fs.unlinkSync(pathCheck.resolved)
299
305
  }
300
- return { success: true, message: `已删除: ${pathCheck.resolved}` }
306
+ return { success: true, data: `已删除: ${pathCheck.resolved}` }
301
307
  } catch (error) {
302
308
  return { success: false, error: error.message }
303
309
  }
@@ -660,13 +666,15 @@ edits 数组可以包含多个不重叠的替换操作,每个操作通过 oldT
660
666
 
661
667
  return {
662
668
  success: true,
663
- pattern,
664
- results: results.slice(0, maxResults),
665
- total: results.length,
666
- stats: {
667
- filesWithMatches,
668
- totalMatches,
669
- searchPath: targetFile || dirPath
669
+ data: results.slice(0, maxResults),
670
+ metadata: {
671
+ pattern,
672
+ total: results.length,
673
+ stats: {
674
+ filesWithMatches,
675
+ totalMatches,
676
+ searchPath: targetFile || dirPath
677
+ }
670
678
  }
671
679
  }
672
680
  } catch (error) {
@@ -817,19 +825,23 @@ edits 数组可以包含多个不重叠的替换操作,每个操作通过 oldT
817
825
  if (error) {
818
826
  resolve({
819
827
  success: false,
820
- command,
821
828
  error: error.message,
822
- stderr: stderr.substring(0, 2000),
823
- stdout: stdout.substring(0, 2000),
824
- duration
829
+ metadata: {
830
+ command,
831
+ stderr: stderr.substring(0, 2000),
832
+ stdout: stdout.substring(0, 2000),
833
+ duration
834
+ }
825
835
  })
826
836
  } else {
827
837
  resolve({
828
838
  success: true,
829
- command,
830
- stdout: stdout.substring(0, 10000),
831
- stderr: stderr.substring(0, 1000),
832
- duration
839
+ data: stdout.substring(0, 10000),
840
+ metadata: {
841
+ command,
842
+ stderr: stderr.substring(0, 1000),
843
+ duration
844
+ }
833
845
  })
834
846
  }
835
847
  }
@@ -848,16 +860,18 @@ edits 数组可以包含多个不重叠的替换操作,每个操作通过 oldT
848
860
  const beijingTime = new Date(now.getTime() + (8 * 60 * 60 * 1000))
849
861
  return {
850
862
  success: true,
851
- beijingTime: beijingTime.toISOString().replace('T', ' ').substring(0, 19),
852
- timestamp: now.getTime(),
853
- timezone: 'Asia/Shanghai (UTC+8)',
854
- formatted: {
855
- year: beijingTime.getUTCFullYear(),
856
- month: String(beijingTime.getUTCMonth() + 1).padStart(2, '0'),
857
- day: String(beijingTime.getUTCDate()).padStart(2, '0'),
858
- hour: String(beijingTime.getUTCHours()).padStart(2, '0'),
859
- minute: String(beijingTime.getUTCMinutes()).padStart(2, '0'),
860
- second: String(beijingTime.getUTCMinutes()).padStart(2, '0')
863
+ data: beijingTime.toISOString().replace('T', ' ').substring(0, 19),
864
+ metadata: {
865
+ timestamp: now.getTime(),
866
+ timezone: 'Asia/Shanghai (UTC+8)',
867
+ formatted: {
868
+ year: beijingTime.getUTCFullYear(),
869
+ month: String(beijingTime.getUTCMonth() + 1).padStart(2, '0'),
870
+ day: String(beijingTime.getUTCDate()).padStart(2, '0'),
871
+ hour: String(beijingTime.getUTCHours()).padStart(2, '0'),
872
+ minute: String(beijingTime.getUTCMinutes()).padStart(2, '0'),
873
+ second: String(beijingTime.getUTCMinutes()).padStart(2, '0')
874
+ }
861
875
  }
862
876
  }
863
877
  }
@@ -983,21 +997,25 @@ edits 数组可以包含多个不重叠的替换操作,每个操作通过 oldT
983
997
  : data
984
998
  return {
985
999
  success: true,
986
- status: response.status,
987
- statusText: response.statusText,
988
- headers: Object.fromEntries(response.headers.entries()),
989
- usedProxy: proxy,
990
- body: truncatedData,
991
- originalLength: typeof data === 'string' ? data.length : null,
992
- truncated: maxLength && typeof data === 'string' && data.length > maxLength
1000
+ data: truncatedData,
1001
+ metadata: {
1002
+ status: response.status,
1003
+ statusText: response.statusText,
1004
+ headers: Object.fromEntries(response.headers.entries()),
1005
+ usedProxy: proxy,
1006
+ originalLength: typeof data === 'string' ? data.length : null,
1007
+ truncated: maxLength && typeof data === 'string' && data.length > maxLength
1008
+ }
993
1009
  }
994
1010
  } catch (error) {
995
1011
  return {
996
1012
  success: false,
997
1013
  error: error.message,
998
- url,
999
- method,
1000
- hint: '如果访问失败,可尝试设置 proxy: true'
1014
+ metadata: {
1015
+ url,
1016
+ method,
1017
+ hint: '如果访问失败,可尝试设置 proxy: true'
1018
+ }
1001
1019
  }
1002
1020
  }
1003
1021
  }
@@ -1026,7 +1044,7 @@ edits 数组可以包含多个不重叠的替换操作,每个操作通过 oldT
1026
1044
  sessionId,
1027
1045
  timestamp: new Date().toISOString()
1028
1046
  })
1029
- return { success: true, message: '通知已发送' }
1047
+ return { success: true, data: '通知已发送' }
1030
1048
  } catch (error) {
1031
1049
  return { success: false, error: error.message }
1032
1050
  }
@@ -64,7 +64,7 @@ class GateTradingPlugin extends Plugin {
64
64
  this.secretKey = args.secret;
65
65
  const fs = require('fs');
66
66
  fs.writeFileSync(__dirname + '/.env', `GATE_API_KEY=${args.api_key}\nGATE_SECRET_KEY=${args.secret}\n`);
67
- return { success: true, message: 'Gate API 密钥已成功配置' };
67
+ return { success: true, data: 'Gate API 密钥已成功配置' };
68
68
  },
69
69
  });
70
70
 
@@ -86,7 +86,7 @@ class GateTradingPlugin extends Plugin {
86
86
  this.apiKey = '';
87
87
  this.secretKey = '';
88
88
  try { require('fs').unlinkSync(__dirname + '/.env'); } catch (e) {}
89
- return { success: true, message: 'API 配置已清除' };
89
+ return { success: true, data: 'API 配置已清除' };
90
90
  },
91
91
  });
92
92
 
@@ -99,7 +99,7 @@ class GateTradingPlugin extends Plugin {
99
99
  this._checkAuth();
100
100
  const spotApi = this._createSpotApi();
101
101
  const currencies = await spotApi.listCurrencies();
102
- return { success: true, message: 'API 连接成功,密钥有效', currencyCount: currencies.body.length };
102
+ return { success: true, data: 'API 连接成功,密钥有效', metadata: { currencyCount: currencies.body.length } };
103
103
  } catch (error) { return { success: false, error: error.message }; }
104
104
  },
105
105
  });
@@ -118,18 +118,18 @@ class GateTradingPlugin extends Plugin {
118
118
  const { currency_pair, info_type } = args;
119
119
  if (info_type === 'book' || !info_type) {
120
120
  const book = await spotApi.listOrderBook(currency_pair, { limit: 10 });
121
- return { success: true, type: 'order_book', currency_pair, bids: book.body.bids, asks: book.body.asks };
121
+ return { success: true, data: { bids: book.body.bids, asks: book.body.asks }, metadata: { type: 'order_book', currency_pair } };
122
122
  } else if (info_type === 'tickers') {
123
123
  const tickers = await spotApi.listTickers(currency_pair);
124
124
  const t = tickers.body.find(x => x.currencyPair === currency_pair) || tickers.body[0];
125
125
  return {
126
- success: true, type: 'ticker', currency_pair: t.currencyPair,
126
+ success: true, data: { type: 'ticker', currency_pair: t.currencyPair,
127
127
  last: t.last, high_24h: t.high24h, low_24h: t.low24h,
128
- volume_24h: t.baseVolume, quote_volume_24h: t.quoteVolume, change_percentage_24h: t.changePercentage,
128
+ volume_24h: t.baseVolume, quote_volume_24h: t.quoteVolume, change_percentage_24h: t.changePercentage },
129
129
  };
130
130
  } else if (info_type === 'trades') {
131
131
  const trades = await spotApi.listTrades(currency_pair);
132
- return { success: true, type: 'trades', currency_pair, trades: trades.body.slice(0, 20) };
132
+ return { success: true, data: trades.body.slice(0, 20), metadata: { type: 'trades', currency_pair } };
133
133
  }
134
134
  return { success: false, error: '未知的信息类型' };
135
135
  } catch (error) { return { success: false, error: error.message }; }
@@ -152,7 +152,7 @@ class GateTradingPlugin extends Plugin {
152
152
  const nonZero = balances.filter(b => parseFloat(b.available) > 0 || parseFloat(b.locked) > 0);
153
153
  return {
154
154
  success: true,
155
- balances: nonZero.map(b => ({
155
+ data: nonZero.map(b => ({
156
156
  currency: b.currency, available: b.available, locked: b.locked,
157
157
  total: parseFloat(b.available) + parseFloat(b.locked),
158
158
  })),
@@ -180,9 +180,9 @@ class GateTradingPlugin extends Plugin {
180
180
  const result = await spotApi.createOrder(order);
181
181
  const r = result.body;
182
182
  return {
183
- success: true, order_id: r.id, currency_pair: r.currency_pair,
183
+ success: true, data: { order_id: r.id, currency_pair: r.currency_pair,
184
184
  type: r.type, side: r.side, amount: r.amount,
185
- price: r.price, status: r.status, create_time: r.create_time,
185
+ price: r.price, status: r.status, create_time: r.create_time },
186
186
  };
187
187
  } catch (error) { return { success: false, error: error.message }; }
188
188
  },
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * InstallPlugin - npm 包安装工具
3
- * 自动安装缺少的 node 模块到 .agent 目录或指定目录
3
+ * 自动安装缺少的 node 模块到 .foliko 目录或指定目录
4
4
  */
5
5
 
6
6
  const { execSync } = require('child_process')
@@ -18,7 +18,7 @@ class InstallPlugin extends Plugin {
18
18
  this.version = '1.0.0'
19
19
  this.description = '自动安装 npm 包到指定目录'
20
20
 
21
- this._agentDir = config.agentDir || '.agent'
21
+ this._agentDir = config.agentDir || '.foliko' // 默认安装到 .foliko 目录
22
22
  this._nodeModulesDir = null
23
23
  this.system = true
24
24
  }
@@ -41,7 +41,7 @@ class InstallPlugin extends Plugin {
41
41
  description: '安装 npm 包到指定目录',
42
42
  inputSchema: z.object({
43
43
  package: z.string().optional().describe('包名,如 lodash、lodash@4.17.21 或 @scope/package'),
44
- path: z.string().optional().describe('安装目标目录,如 .agent/plugins/my-plugin(默认为 .agent)'),
44
+ path: z.string().optional().describe('安装目标目录,如 .foliko/plugins/my-plugin(默认为 .foliko)'),
45
45
  file: z.string().optional().describe('本地 package.json 路径,从该文件安装所有依赖')
46
46
  }),
47
47
  execute: async (args) => {
@@ -79,7 +79,7 @@ class InstallPlugin extends Plugin {
79
79
  /**
80
80
  * 安装单个包到指定目录
81
81
  * @param {string} packageName - 包名
82
- * @param {string|null} targetPath - 目标目录,默认为 .agent
82
+ * @param {string|null} targetPath - 目标目录,默认为 .foliko
83
83
  */
84
84
  _installPackage(packageName, targetPath = null) {
85
85
  try {
@@ -104,7 +104,7 @@ class InstallPlugin extends Plugin {
104
104
 
105
105
  return {
106
106
  success: true,
107
- message: `Successfully installed ${packageName} to ${installPath}`
107
+ data: `Successfully installed ${packageName} to ${installPath}`
108
108
  }
109
109
  } catch (err) {
110
110
  return {
@@ -141,7 +141,7 @@ class InstallPlugin extends Plugin {
141
141
  }
142
142
 
143
143
  if (packages.length === 0) {
144
- return { success: true, message: 'No dependencies to install' }
144
+ return { success: true, data: 'No dependencies to install' }
145
145
  }
146
146
 
147
147
  // 确保目标目录存在
@@ -159,7 +159,7 @@ class InstallPlugin extends Plugin {
159
159
 
160
160
  return {
161
161
  success: true,
162
- message: `Successfully installed ${packages.length} dependencies to ${installPath}`
162
+ data: `Successfully installed ${packages.length} dependencies to ${installPath}`
163
163
  }
164
164
  } catch (err) {
165
165
  return {
@@ -24,7 +24,7 @@ const MEMORY_TYPES = {
24
24
  /**
25
25
  * 记忆存储路径
26
26
  */
27
- const MEMORY_BASE_DIR = '.agent/memory'
27
+ const MEMORY_BASE_DIR = '.foliko/memory'
28
28
 
29
29
  /**
30
30
  * 解析 YAML frontmatter(从 skill-manager 复用)
@@ -625,8 +625,7 @@ class MemoryPlugin extends Plugin {
625
625
 
626
626
  return {
627
627
  success: true,
628
- count: results.length,
629
- memories: results.map(m => ({
628
+ data: results.map(m => ({
630
629
  id: m.id,
631
630
  name: m.name,
632
631
  type: m.type,
@@ -665,8 +664,8 @@ class MemoryPlugin extends Plugin {
665
664
 
666
665
  return {
667
666
  success: true,
668
- id: memory.id,
669
- message: `Memory created: ${memory.id}`
667
+ data: `Memory created: ${memory.id}`,
668
+ metadata: { id: memory.id }
670
669
  }
671
670
  } catch (err) {
672
671
  return { success: false, error: err.message }
@@ -694,8 +693,7 @@ class MemoryPlugin extends Plugin {
694
693
 
695
694
  return {
696
695
  success: true,
697
- count: memories.length,
698
- memories: memories.map(m => ({
696
+ data: memories.map(m => ({
699
697
  id: m.id,
700
698
  name: m.name,
701
699
  type: m.type,
@@ -752,8 +750,8 @@ class MemoryPlugin extends Plugin {
752
750
  const memory = this._store.update(args.id, updates)
753
751
  return {
754
752
  success: true,
755
- id: memory.id,
756
- message: `Memory updated: ${memory.id}`
753
+ data: `Memory updated: ${memory.id}`,
754
+ metadata: { id: memory.id }
757
755
  }
758
756
  } catch (err) {
759
757
  return { success: false, error: err.message }
@@ -776,7 +774,7 @@ class MemoryPlugin extends Plugin {
776
774
  }
777
775
  return {
778
776
  success: true,
779
- memory: {
777
+ data: {
780
778
  id: memory.id,
781
779
  name: memory.name,
782
780
  type: memory.type,
@@ -803,8 +801,7 @@ class MemoryPlugin extends Plugin {
803
801
  const projects = this._store.getProjects()
804
802
  return {
805
803
  success: true,
806
- stats,
807
- projects
804
+ data: { stats, projects }
808
805
  }
809
806
  } catch (err) {
810
807
  return { success: false, error: err.message }
@@ -119,7 +119,7 @@ class PluginManagerPlugin extends Plugin {
119
119
  // 3. plugin_install - 从远程仓库安装插件到本地
120
120
  framework.registerTool({
121
121
  name: 'plugin_install',
122
- description: '从远程 Git 仓库安装插件到本地 .agent/plugins 目录',
122
+ description: '从远程 Git 仓库安装插件到本地 .foliko/plugins 目录',
123
123
  inputSchema: z.object({
124
124
  name: z.string().describe('插件名称,如 puppeteer-plugin'),
125
125
  repo: z.string().optional().describe('插件仓库 URL'),
@@ -160,7 +160,7 @@ class PluginManagerPlugin extends Plugin {
160
160
  const contents = await response.json();
161
161
 
162
162
  if (!Array.isArray(contents) || contents.length === 0) {
163
- return { success: true, plugins: [], message: 'No plugins found in repository' };
163
+ return { success: true, data: [], metadata: { message: 'No plugins found in repository' } };
164
164
  }
165
165
 
166
166
  const plugins = [];
@@ -198,9 +198,8 @@ class PluginManagerPlugin extends Plugin {
198
198
 
199
199
  return {
200
200
  success: true,
201
- plugins,
202
- repo,
203
- count: plugins.length,
201
+ data: plugins,
202
+ metadata: { repo, count: plugins.length },
204
203
  };
205
204
 
206
205
  } catch (err) {
@@ -213,7 +212,7 @@ class PluginManagerPlugin extends Plugin {
213
212
  * 发布插件到远程仓库
214
213
  */
215
214
  async _publishPlugin(pluginName, repo) {
216
- const pluginsDir = path.resolve(process.cwd(), '.agent', 'plugins');
215
+ const pluginsDir = path.resolve(process.cwd(), '.foliko', 'plugins');
217
216
  const localPluginsDir = path.resolve(process.cwd(), 'plugins');
218
217
 
219
218
  // 确定插件目录
@@ -303,8 +302,8 @@ class PluginManagerPlugin extends Plugin {
303
302
  if (!status.trim()) {
304
303
  return {
305
304
  success: true,
306
- message: `No changes to commit for plugin "${pluginName}"`,
307
- repo,
305
+ data: `No changes to commit for plugin "${pluginName}"`,
306
+ metadata: { repo },
308
307
  };
309
308
  }
310
309
 
@@ -315,9 +314,8 @@ class PluginManagerPlugin extends Plugin {
315
314
 
316
315
  return {
317
316
  success: true,
318
- message: `Plugin "${pluginName}" published successfully`,
319
- repo,
320
- path: `${pluginName}/${pluginName}.js`,
317
+ data: `Plugin "${pluginName}" published successfully`,
318
+ metadata: { repo, path: `${pluginName}/${pluginName}.js` },
321
319
  };
322
320
 
323
321
  } catch (err) {
@@ -332,7 +330,7 @@ class PluginManagerPlugin extends Plugin {
332
330
  * 从远程仓库安装插件
333
331
  */
334
332
  async _installPlugin(pluginName, repo) {
335
- const localPluginsDir = path.resolve(process.cwd(), '.agent', 'plugins');
333
+ const localPluginsDir = path.resolve(process.cwd(), '.foliko', 'plugins');
336
334
  const tmpDir = path.join(require('os').tmpdir(), `foliko-plugin-install-${Date.now()}`);
337
335
 
338
336
  try {
@@ -387,8 +385,8 @@ class PluginManagerPlugin extends Plugin {
387
385
 
388
386
  return {
389
387
  success: true,
390
- message: `Plugin "${pluginName}" installed successfully`,
391
- path: targetDir,
388
+ data: `Plugin "${pluginName}" installed successfully`,
389
+ metadata: { path: targetDir },
392
390
  };
393
391
 
394
392
  } catch (err) {
@@ -23,7 +23,7 @@ class PythonExecutorPlugin extends Plugin {
23
23
  this.config = {
24
24
  pythonPath: config.pythonPath || 'python', // python 或 python3
25
25
  timeout: config.timeout || 120000, // 2分钟超时
26
- baseDir: config.baseDir || '.agent/python-scripts',
26
+ baseDir: config.baseDir || '.foliko/python-scripts',
27
27
  pipPath: config.pipPath || null // 可选,自定义 pip 路径
28
28
  }
29
29