foliko 1.1.68 → 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 (142) 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 +152 -38
  13. package/cli/src/ui/footer-bar.js +13 -14
  14. package/cli/src/utils/config.js +29 -0
  15. package/cli/src/utils/plugin-config.js +1 -1
  16. package/docker-compose.yml +33 -33
  17. package/docs/features.md +120 -120
  18. package/docs/quick-reference.md +160 -160
  19. package/docs/user-manual.md +1391 -1391
  20. package/examples/ambient-example.js +2 -2
  21. package/examples/bootstrap.js +3 -3
  22. package/examples/test-chat.js +1 -1
  23. package/examples/test-reload.js +1 -1
  24. package/examples/test-telegram.js +1 -1
  25. package/examples/test-tg-bot.js +1 -1
  26. package/examples/test-tg-simple.js +2 -2
  27. package/examples/test-tg.js +1 -1
  28. package/examples/test-think.js +1 -1
  29. package/examples/test-weixin-feishu.js +3 -3
  30. package/package.json +3 -1
  31. package/plugins/ambient-agent/index.js +1 -1
  32. package/plugins/audit-plugin.js +75 -24
  33. package/plugins/default-plugins.js +21 -11
  34. package/plugins/email/index.js +1 -1
  35. package/plugins/extension-executor-plugin.js +85 -7
  36. package/plugins/feishu-plugin.js +118 -16
  37. package/plugins/install-plugin.js +4 -4
  38. package/plugins/memory-plugin.js +1 -1
  39. package/plugins/plugin-manager-plugin.js +3 -3
  40. package/plugins/python-executor-plugin.js +1 -1
  41. package/plugins/python-plugin-loader.js +1 -1
  42. package/plugins/qq-plugin.js +143 -16
  43. package/plugins/rules-plugin.js +1 -1
  44. package/plugins/scheduler-plugin.js +2 -2
  45. package/plugins/session-plugin.js +309 -393
  46. package/plugins/storage-plugin.js +235 -176
  47. package/plugins/subagent-plugin.js +4 -4
  48. package/plugins/telegram-plugin.js +116 -17
  49. package/plugins/think-plugin.js +1 -1
  50. package/plugins/web-plugin.js +2 -2
  51. package/plugins/weixin-plugin.js +102 -19
  52. package/skills/find-skills/AGENTS.md +2 -2
  53. package/skills/find-skills/SKILL.md +133 -133
  54. package/skills/foliko-dev/AGENTS.md +236 -236
  55. package/skills/foliko-dev/SKILL.md +19 -19
  56. package/skills/mcp-usage/SKILL.md +200 -200
  57. package/skills/plugin-guide/SKILL.md +4 -4
  58. package/skills/python-plugin-dev/SKILL.md +5 -5
  59. package/skills/skill-guide/SKILL.md +104 -6
  60. package/skills/subagent-guide/SKILL.md +237 -237
  61. package/skills/workflow-guide/SKILL.md +646 -646
  62. package/src/capabilities/skill-manager.js +101 -2
  63. package/src/capabilities/workflow-engine.js +1 -1
  64. package/src/core/agent-chat.js +17 -14
  65. package/src/core/branch-summary-auto.js +206 -0
  66. package/src/core/chat-session.js +38 -8
  67. package/src/core/command-registry.js +200 -0
  68. package/src/core/constants.js +11 -11
  69. package/src/core/context-compressor.js +700 -149
  70. package/src/core/context-manager.js +0 -1
  71. package/src/core/enhanced-context-compressor.js +210 -0
  72. package/src/core/framework.js +140 -83
  73. package/src/core/jsonl-storage.js +253 -0
  74. package/src/core/plugin-manager.js +15 -10
  75. package/src/core/provider-registry.js +159 -0
  76. package/src/core/provider.js +2 -0
  77. package/src/core/session-entry.js +225 -0
  78. package/src/core/session-manager.js +701 -0
  79. package/src/core/storage-manager.js +494 -0
  80. package/src/core/sub-agent-config.js +1 -1
  81. package/src/core/token-counter.js +177 -58
  82. package/src/core/ui-extension-context.js +174 -0
  83. package/src/executors/mcp-executor.js +15 -6
  84. package/src/utils/logger.js +152 -180
  85. package/src/utils/plugin-helpers.js +2 -2
  86. package/website_v2/docs/api.html +1 -1
  87. package/website_v2/docs/configuration.html +2 -2
  88. package/website_v2/docs/plugin-development.html +4 -4
  89. package/website_v2/docs/project-structure.html +2 -2
  90. package/website_v2/docs/skill-development.html +2 -2
  91. package/website_v2/index.html +1 -1
  92. package/website_v2/styles/animations.css +7 -7
  93. package/.agent/agents/backend-dev.md +0 -102
  94. package/.agent/agents/data-analyst.md +0 -117
  95. package/.agent/agents/devops.md +0 -115
  96. package/.agent/agents/frontend-dev.md +0 -94
  97. package/.agent/agents/network-requester.md +0 -44
  98. package/.agent/agents/poster-designer.md +0 -52
  99. package/.agent/agents/product-manager.md +0 -85
  100. package/.agent/agents/qa-engineer.md +0 -100
  101. package/.agent/agents/security-engineer.md +0 -99
  102. package/.agent/agents/team-lead.md +0 -137
  103. package/.agent/agents/ui-designer.md +0 -116
  104. package/.agent/data/default.json +0 -58
  105. package/.agent/data/email/processed-emails.json +0 -1
  106. package/.agent/data/plugins-state.json +0 -207
  107. package/.agent/data/scheduler/tasks.json +0 -1
  108. package/.agent/data/web/web-config.json +0 -5
  109. package/.agent/data/weixin/images/file_1776188148383jpg +0 -0
  110. package/.agent/data/weixin/images/file_1776188458326.jpg +0 -0
  111. package/.agent/data/weixin/images/file_1776188689423.jpg +0 -0
  112. package/.agent/data/weixin/images/file_1776188813604.jpg +0 -0
  113. package/.agent/data/weixin/images/file_1776189097450.jpg +0 -0
  114. package/.agent/data/weixin/videos/file_1776188318431.mp4 +0 -0
  115. package/.agent/data/weixin.json +0 -6
  116. package/.agent/mcp_config.json +0 -14
  117. package/.agent/memory/user/mof6gk94-kneeuh.md +0 -9
  118. package/.agent/package.json +0 -8
  119. package/.agent/plugins/marknative/README.md +0 -134
  120. package/.agent/plugins/marknative/fonts/SegoeUI Emoji.ttf +0 -0
  121. package/.agent/plugins/marknative/fonts.zip +0 -0
  122. package/.agent/plugins/marknative/index.js +0 -256
  123. package/.agent/plugins/marknative/package.json +0 -12
  124. package/.agent/plugins/test-plugin.py +0 -99
  125. package/.agent/plugins.json +0 -14
  126. package/.agent/python-scripts/test_sample.py +0 -24
  127. package/.agent/sessions/cli_default.json +0 -4121
  128. package/.agent/skills/agent-browser/SKILL.md +0 -311
  129. package/.agent/skills/agent-browser/TEST_PLAN.md +0 -200
  130. package/.agent/skills/sysinfo/SKILL.md +0 -38
  131. package/.agent/skills/sysinfo/system-info.sh +0 -130
  132. package/.agent/skills/workflow/SKILL.md +0 -324
  133. package/.agent/test-agent.js +0 -35
  134. package/.agent/weixin.json +0 -6
  135. package/.agent/workflows/email-digest.json +0 -50
  136. package/.agent/workflows/file-backup.json +0 -21
  137. package/.agent/workflows/get-ip-notify.json +0 -32
  138. package/.agent/workflows/news-aggregator.json +0 -93
  139. package/.agent/workflows/news-dashboard-v2.json +0 -94
  140. package/.agent/workflows/notification-batch.json +0 -32
  141. package/src/core/session-context.js +0 -346
  142. package/src/core/session-storage.js +0 -295
@@ -300,18 +300,28 @@ class TelegramPlugin extends Plugin {
300
300
  const command = parts[0].substring(1)
301
301
  const args = parts.slice(1).join(' ')
302
302
 
303
+ // 检查 skill 命令 (格式: skillname:cmdname)
304
+ if (command.includes(':')) {
305
+ const result = await this._executeSkillCommand(command, args)
306
+ if (result) {
307
+ await this._sendMessage(chatId, `✅ ${result.data || result}`, msg.message_id)
308
+ return
309
+ }
310
+ }
311
+
303
312
  switch (command.toLowerCase()) {
304
313
  case 'start':
305
314
  case 'help':
306
- await this._sendMessage(chatId,
307
- '👋 欢迎使用 AI 助手!\n\n直接发送消息即可与我对话。\n\n可用命令:\n/clean - 清除对话上下文\n/history - 查看历史消息数',
308
- msg.message_id)
315
+ await this._sendMessageHelp(chatId, msg.message_id)
309
316
  break
310
317
  case 'clean':
311
318
  case 'clear':
312
319
  await this._clearSessionContext(chatId)
313
320
  await this._sendMessage(chatId, '✅ 对话上下文已清除', msg.message_id)
314
321
  break
322
+ case 'compress':
323
+ await this._compressSessionContext(chatId, msg.message_id)
324
+ break
315
325
  case 'history':
316
326
  const sessionInfo = this._getSessionAgent(chatId)
317
327
  if (sessionInfo && this._framework) {
@@ -326,6 +336,26 @@ class TelegramPlugin extends Plugin {
326
336
  }
327
337
  break
328
338
  default:
339
+ // 检查是否是 skill 命令 (格式: skillname:cmdname)
340
+ if (text.startsWith('/')) {
341
+ const cmdParts = command.split(':')
342
+ if (cmdParts.length === 2) {
343
+ const skillCmd = `${cmdParts[0]}:${cmdParts[1]}`
344
+ try {
345
+ const result = await this._framework.executeTool('ext_call', {
346
+ plugin: 'skill',
347
+ tool: skillCmd,
348
+ args: { args }
349
+ })
350
+ if (result.success !== false) {
351
+ await this._sendMessage(chatId, `✅ ${result.data || result}`, msg.message_id)
352
+ return
353
+ }
354
+ } catch (err) {
355
+ log.warn('Skill command failed:', err.message)
356
+ }
357
+ }
358
+ }
329
359
  await this._processChat(chatId, text, msg.message_id)
330
360
  }
331
361
  }
@@ -439,7 +469,7 @@ class TelegramPlugin extends Plugin {
439
469
  async _downloadFile(fileId, ext, subDir) {
440
470
  const path = require('path')
441
471
  const fs = require('fs')
442
- const saveDir = path.join(process.cwd(), '.agent', 'data', subDir)
472
+ const saveDir = path.join(process.cwd(), '.foliko', 'data', subDir)
443
473
  if (!fs.existsSync(saveDir)) fs.mkdirSync(saveDir, { recursive: true })
444
474
 
445
475
  const fileName = `${Date.now()}_${Math.random().toString(36).substring(7)}.${ext}`
@@ -457,7 +487,7 @@ class TelegramPlugin extends Plugin {
457
487
  }
458
488
 
459
489
  /**
460
- * 清除会话上下文(清除消息历史和压缩计数)
490
+ * 清除会话上下文(清除消息历史)
461
491
  */
462
492
  async _clearSessionContext(chatId) {
463
493
  const sessionId = `telegram_${chatId}`
@@ -470,21 +500,90 @@ class TelegramPlugin extends Plugin {
470
500
  agent._chatHandler.clearHistory(sessionId)
471
501
  }
472
502
 
473
- // 清除 SessionContext 的消息和压缩计数
503
+ // 清除 SessionManager 的消息
474
504
  if (this._framework) {
475
- const sessionCtx = this._framework.getSessionContext(sessionId)
476
- if (sessionCtx) {
477
- sessionCtx.clearMessages()
478
- sessionCtx.compressionState.count = 0
479
- sessionCtx.metadata.compressionCount = 0
505
+ const manager = this._framework.getSessionContext(sessionId)
506
+ if (manager) {
507
+ manager.clearMessages()
480
508
  }
481
- // 同步清除 framework 缓存的 sessionContexts
482
- const cachedCtx = this._framework._sessionContexts?.get(sessionId)
483
- if (cachedCtx) {
484
- cachedCtx.clearMessages()
485
- cachedCtx.compressionState.count = 0
486
- cachedCtx.metadata.compressionCount = 0
509
+ }
510
+ }
511
+
512
+ /**
513
+ * 检查并执行 skill 命令
514
+ */
515
+ async _executeSkillCommand(command, args) {
516
+ const extExecutor = this._framework?.pluginManager?.get('extension-executor')
517
+ if (!extExecutor || typeof extExecutor.executeSkillCommand !== 'function') return null
518
+ return await extExecutor.executeSkillCommand(command, args)
519
+ }
520
+
521
+ /**
522
+ * 发送帮助信息
523
+ */
524
+ async _sendMessageHelp(chatId, replyToMessageId) {
525
+ const extExecutor = this._framework?.pluginManager?.get('extension-executor')
526
+ const skillHelp = extExecutor?.getSkillCommandsHelp?.() || ''
527
+
528
+ let helpText = '👋 欢迎使用 AI 助手!\n\n直接发送消息即可与我对话。\n\n可用命令:\n/clean - 清除对话上下文\n/compress - 压缩上下文\n/history - 查看历史消息数'
529
+
530
+ if (skillHelp) {
531
+ helpText += '\n\n【技能命令】\n' + skillHelp.split('\n').map(line => line.replace(/^\//, '/')).join('\n')
532
+ }
533
+
534
+ await this._sendMessage(chatId, helpText, replyToMessageId)
535
+ }
536
+
537
+ /**
538
+ * 压缩会话上下文
539
+ */
540
+ async _compressSessionContext(chatId, replyToMessageId) {
541
+ const sessionId = `telegram_${chatId}`
542
+
543
+ // 获取 sessionAgent
544
+ const { agent } = this._getSessionAgent(chatId)
545
+
546
+ if (agent._chatHandler) {
547
+ const chatHandler = agent._chatHandler
548
+
549
+ const messageStore = chatHandler._chatSession.getSessionMessageStore(sessionId)
550
+ messageStore.historyLoaded = false
551
+ chatHandler._chatSession.loadHistory(sessionId)
552
+
553
+ let messages = messageStore.messages
554
+
555
+ if (!messages || messages.length === 0) {
556
+ if (this._framework) {
557
+ const sessionCtx = this._framework.getSessionContext(sessionId)
558
+ if (sessionCtx) {
559
+ messages = sessionCtx.getMessages()
560
+ messageStore.messages = messages
561
+ }
562
+ }
563
+ }
564
+
565
+ const beforeCount = messages ? messages.length : 0
566
+ await this._sendMessage(chatId, `📦 开始压缩上下文,当前 ${beforeCount} 条消息...`, replyToMessageId)
567
+
568
+ if (messages && messages.length > 0) {
569
+ if (chatHandler._contextCompressor) {
570
+ await chatHandler._contextCompressor.compress(sessionId, messages, messageStore)
571
+ const afterCount = messages.length
572
+ if (this._framework) {
573
+ const sessionCtx = this._framework.getSessionContext(sessionId)
574
+ if (sessionCtx) {
575
+ sessionCtx.replaceMessages(messages)
576
+ }
577
+ }
578
+ await this._sendMessage(chatId, `✅ 压缩完成:${beforeCount} → ${afterCount} 条(保留 ${chatHandler._contextCompressor._keepRecentMessages} 条)`, replyToMessageId)
579
+ } else {
580
+ await this._sendMessage(chatId, '❌ 压缩器不可用', replyToMessageId)
581
+ }
582
+ } else {
583
+ await this._sendMessage(chatId, '❌ 没有消息需要压缩', replyToMessageId)
487
584
  }
585
+ } else {
586
+ await this._sendMessage(chatId, '❌ ChatHandler 不可用', replyToMessageId)
488
587
  }
489
588
  }
490
589
 
@@ -151,7 +151,7 @@ class ThinkPlugin extends Plugin {
151
151
  this._emitNotification('error', '🧠 思考失败', 'AI 未配置')
152
152
  return {
153
153
  success: false,
154
- error: 'AI 未配置。请在 .agent/ai.json 或环境变量中配置 AI API Key。'
154
+ error: 'AI 未配置。请在 .foliko/ai.json 或环境变量中配置 AI API Key。'
155
155
  }
156
156
  }
157
157
 
@@ -14,7 +14,7 @@ const fs = require('fs')
14
14
  const path = require('path')
15
15
 
16
16
  // ============================================================================
17
- // WebStore - 持久化 Web 配置到 .agent/data/web/
17
+ // WebStore - 持久化 Web 配置到 .foliko/data/web/
18
18
  // ============================================================================
19
19
  class WebStore {
20
20
  constructor(persistencePath) {
@@ -82,7 +82,7 @@ class WebPlugin extends Plugin {
82
82
 
83
83
  // 持久化存储
84
84
  this._webStore = null
85
- this._persistencePath = config.persistencePath || '.agent/data/web'
85
+ this._persistencePath = config.persistencePath || '.foliko/data/web'
86
86
  }
87
87
 
88
88
  // ==================== 生命周期 ====================
@@ -8,7 +8,11 @@
8
8
  */
9
9
  const { CLEAR_LINE, CYAN, DIM, GREEN, RED, YELLOW, colored } = require('../cli/src/utils/ansi');
10
10
  const { renderLine } = require('../cli/src/utils/markdown');
11
- const { debounce, throttle, interval } = require('../cli/src/utils/debounce');
11
+ const { debounce, throttle } = require('../src/utils');
12
+ const interval = (fn) => {
13
+ const handle = setInterval(fn, 3000);
14
+ return { start: () => handle, stop: () => clearInterval(handle) };
15
+ };
12
16
  const { Plugin } = require('../src/core/plugin-base')
13
17
  const { logger } = require('../src/utils/logger')
14
18
  const log = logger.child('WeChat')
@@ -29,7 +33,7 @@ class WeixinPlugin extends Plugin {
29
33
  this.priority = 80
30
34
  // 默认不启用,需要在 plugins.json 中设置 enabled: true
31
35
  this.enabled = false
32
- this.path=`.agent/data`
36
+ this.path=`.foliko/data`
33
37
  this.systemPrompt=`你是一个微信助手。
34
38
 
35
39
  **重要:** 子Agent 匹配规则必须遵守:
@@ -59,7 +63,7 @@ class WeixinPlugin extends Plugin {
59
63
  this._initialized = false
60
64
  // 预创建的 sessionScope 监听器(避免每次消息都创建/销毁)
61
65
  this._sessionScopes = new Map()
62
- const saveDir = path.join(process.cwd(), '.agent', 'data', this.name)
66
+ const saveDir = path.join(process.cwd(), '.foliko', 'data', this.name)
63
67
  this.downloader=new FileDownloader({
64
68
  retries: 3,
65
69
  baseDir:saveDir
@@ -575,18 +579,28 @@ class WeixinPlugin extends Plugin {
575
579
  const command = parts[0].substring(1)
576
580
  const args = parts.slice(1).join(' ')
577
581
 
582
+ // 检查 skill 命令 (格式: skillname:cmdname)
583
+ if (command.includes(':')) {
584
+ const result = await this._executeSkillCommand(command, args)
585
+ if (result) {
586
+ await this._sendMessageBatch(originalMsg, userId, `✅ ${result.data || result}`, true)
587
+ return
588
+ }
589
+ }
590
+
578
591
  switch (command.toLowerCase()) {
579
592
  case 'start':
580
593
  case 'help':
581
- await this._sendMessageBatch(originalMsg, userId,
582
- '👋 欢迎使用 AI 助手!\n\n直接发送消息即可与我对话。\n\n可用命令:\n/clean - 清除对话上下文\n/history - 查看历史消息数',
583
- true)
594
+ await this._sendMessageHelp(originalMsg, userId)
584
595
  break
585
596
  case 'clean':
586
597
  case 'clear':
587
598
  await this._clearSessionContext(userId)
588
599
  await this._sendMessageBatch(originalMsg, userId, '✅ 对话上下文已清除', true)
589
600
  break
601
+ case 'compress':
602
+ await this._compressSessionContext(userId)
603
+ break
590
604
  case 'history':
591
605
  const sessionInfo = this._getSessionAgent(userId)
592
606
  if (sessionInfo && this._framework) {
@@ -605,7 +619,32 @@ class WeixinPlugin extends Plugin {
605
619
  }
606
620
 
607
621
  /**
608
- * 清除会话上下文(清除消息历史和压缩计数)
622
+ * 检查并执行 skill 命令
623
+ */
624
+ async _executeSkillCommand(command, args) {
625
+ const extExecutor = this._framework?.pluginManager?.get('extension-executor')
626
+ if (!extExecutor || typeof extExecutor.executeSkillCommand !== 'function') return null
627
+ return await extExecutor.executeSkillCommand(command, args)
628
+ }
629
+
630
+ /**
631
+ * 发送帮助信息
632
+ */
633
+ async _sendMessageHelp(originalMsg, userId) {
634
+ const extExecutor = this._framework?.pluginManager?.get('extension-executor')
635
+ const skillHelp = extExecutor?.getSkillCommandsHelp?.() || ''
636
+
637
+ let helpText = '👋 欢迎使用 AI 助手!\n\n直接发送消息即可与我对话。\n\n可用命令:\n/clean - 清除对话上下文\n/compress - 压缩上下文\n/history - 查看历史消息数'
638
+
639
+ if (skillHelp) {
640
+ helpText += '\n\n【技能命令】\n' + skillHelp.split('\n').map(line => line.replace(/^\//, '/')).join('\n')
641
+ }
642
+
643
+ await this._sendMessageBatch(originalMsg, userId, helpText, true)
644
+ }
645
+
646
+ /**
647
+ * 清除会话上下文(清除消息历史)
609
648
  */
610
649
  async _clearSessionContext(userId) {
611
650
  const sessionId = `weixin_${userId}`
@@ -618,21 +657,65 @@ class WeixinPlugin extends Plugin {
618
657
  agent._chatHandler.clearHistory(sessionId)
619
658
  }
620
659
 
621
- // 清除 SessionContext 的消息和压缩计数
660
+ // 清除 SessionManager 的消息
622
661
  if (this._framework) {
623
- const sessionCtx = this._framework.getSessionContext(sessionId)
624
- if (sessionCtx) {
625
- sessionCtx.clearMessages()
626
- sessionCtx.compressionState.count = 0
627
- sessionCtx.metadata.compressionCount = 0
662
+ const manager = this._framework.getSessionContext(sessionId)
663
+ if (manager) {
664
+ manager.clearMessages()
665
+ }
666
+ }
667
+ }
668
+
669
+ /**
670
+ * 压缩会话上下文
671
+ */
672
+ async _compressSessionContext(userId) {
673
+ const sessionId = `weixin_${userId}`
674
+
675
+ // 获取 sessionAgent
676
+ const { agent } = this._getSessionAgent(userId)
677
+
678
+ if (agent._chatHandler) {
679
+ const chatHandler = agent._chatHandler
680
+
681
+ const messageStore = chatHandler._chatSession.getSessionMessageStore(sessionId)
682
+ messageStore.historyLoaded = false
683
+ chatHandler._chatSession.loadHistory(sessionId)
684
+
685
+ let messages = messageStore.messages
686
+
687
+ if (!messages || messages.length === 0) {
688
+ if (this._framework) {
689
+ const sessionCtx = this._framework.getSessionContext(sessionId)
690
+ if (sessionCtx) {
691
+ messages = sessionCtx.getMessages()
692
+ messageStore.messages = messages
693
+ }
694
+ }
628
695
  }
629
- // 同步清除 framework 缓存的 sessionContexts
630
- const cachedCtx = this._framework._sessionContexts?.get(sessionId)
631
- if (cachedCtx) {
632
- cachedCtx.clearMessages()
633
- cachedCtx.compressionState.count = 0
634
- cachedCtx.metadata.compressionCount = 0
696
+
697
+ const beforeCount = messages ? messages.length : 0
698
+ await this._sendMessageBatch(null, userId, `📦 开始压缩上下文,当前 ${beforeCount} 条消息...`, true)
699
+
700
+ if (messages && messages.length > 0) {
701
+ if (chatHandler._contextCompressor) {
702
+ await chatHandler._contextCompressor.compress(sessionId, messages, messageStore)
703
+ const afterCount = messages.length
704
+ if (this._framework) {
705
+ const sessionCtx = this._framework.getSessionContext(sessionId)
706
+ if (sessionCtx) {
707
+ sessionCtx.replaceMessages(messages)
708
+ }
709
+ }
710
+ await this._sendMessageBatch(null, userId, `✅ 压缩完成:${beforeCount} → ${afterCount} 条(保留 ${chatHandler._contextCompressor._keepRecentMessages} 条)`, true)
711
+ } else {
712
+ await this._sendMessageBatch(null, userId, '❌ 压缩器不可用', true)
713
+ }
714
+ } else {
715
+ await this._sendMessageBatch(null, userId, '❌ 没有消息需要压缩', true)
635
716
  }
717
+ } else {
718
+ await this._sendMessageBatch(null, userId, '❌ ChatHandler 不可用', true)
636
719
  }
637
720
  }
638
721
 
@@ -34,7 +34,7 @@ src/
34
34
  ├── agents.ts # Agent definitions and detection
35
35
  ├── installer.ts # Skill installation logic (symlink/copy) + listInstalledSkills
36
36
  ├── skills.ts # Skill discovery and parsing
37
- ├── skill-lock.ts # Global lock file management (~/.agents/.skill-lock.json)
37
+ ├── skill-lock.ts # Global lock file management (~/.folikos/.skill-lock.json)
38
38
  ├── local-lock.ts # Local lock file management (skills-lock.json, checked in)
39
39
  ├── sync.ts # Sync command - crawl node_modules for skills
40
40
  ├── source-parser.ts # Parse git URLs, GitHub shorthand, local paths
@@ -66,7 +66,7 @@ tests/
66
66
 
67
67
  ### How `skills check` and `skills update` Work
68
68
 
69
- 1. Read `~/.agents/.skill-lock.json` for installed skills
69
+ 1. Read `~/.folikos/.skill-lock.json` for installed skills
70
70
  2. For each skill, get `skillFolderHash` from lock file
71
71
  3. POST to `https://add-skill.vercel.sh/check-updates` with:
72
72
  ```json
@@ -1,133 +1,133 @@
1
- ---
2
- name: find-skills
3
- description: Helps users discover and install agent skills when they ask questions like "how do I do X", "find a skill for X", "is there a skill that can...", or express interest in extending capabilities. This skill should be used when the user is looking for functionality that might exist as an installable skill.
4
- ---
5
-
6
- # Find Skills
7
-
8
- This skill helps you discover and install skills from the open agent skills ecosystem.
9
-
10
- ## When to Use This Skill
11
-
12
- Use this skill when the user:
13
-
14
- - Asks "how do I do X" where X might be a common task with an existing skill
15
- - Says "find a skill for X" or "is there a skill for X"
16
- - Asks "can you do X" where X is a specialized capability
17
- - Expresses interest in extending agent capabilities
18
- - Wants to search for tools, templates, or workflows
19
- - Mentions they wish they had help with a specific domain (design, testing, deployment, etc.)
20
-
21
- ## What is the Skills CLI?
22
-
23
- The Skills CLI (`npx skills`) is the package manager for the open agent skills ecosystem. Skills are modular packages that extend agent capabilities with specialized knowledge, workflows, and tools.
24
-
25
- **Key commands:**
26
-
27
- - `npx skills find [query]` - Search for skills interactively or by keyword
28
- - `npx skills add <package>` - Install a skill from GitHub or other sources
29
- - `npx skills check` - Check for skill updates
30
- - `npx skills update` - Update all installed skills
31
-
32
- **Browse skills at:** https://skills.sh/
33
-
34
- ## How to Help Users Find Skills
35
-
36
- ### Step 1: Understand What They Need
37
-
38
- When a user asks for help with something, identify:
39
-
40
- 1. The domain (e.g., React, testing, design, deployment)
41
- 2. The specific task (e.g., writing tests, creating animations, reviewing PRs)
42
- 3. Whether this is a common enough task that a skill likely exists
43
-
44
- ### Step 2: Search for Skills
45
-
46
- Run the find command with a relevant query:
47
-
48
- ```bash
49
- npx skills find [query]
50
- ```
51
-
52
- For example:
53
-
54
- - User asks "how do I make my React app faster?" → `npx skills find react performance`
55
- - User asks "can you help me with PR reviews?" → `npx skills find pr review`
56
- - User asks "I need to create a changelog" → `npx skills find changelog`
57
-
58
- The command will return results like:
59
-
60
- ```
61
- Install with npx skills add <owner/repo@skill>
62
-
63
- vercel-labs/agent-skills@vercel-react-best-practices
64
- └ https://skills.sh/vercel-labs/agent-skills/vercel-react-best-practices
65
- ```
66
-
67
- ### Step 3: Present Options to the User
68
-
69
- When you find relevant skills, present them to the user with:
70
-
71
- 1. The skill name and what it does
72
- 2. The install command they can run
73
- 3. A link to learn more at skills.sh
74
-
75
- Example response:
76
-
77
- ```
78
- I found a skill that might help! The "vercel-react-best-practices" skill provides
79
- React and Next.js performance optimization guidelines from Vercel Engineering.
80
-
81
- To install it:
82
- npx skills add vercel-labs/agent-skills@vercel-react-best-practices
83
-
84
- Learn more: https://skills.sh/vercel-labs/agent-skills/vercel-react-best-practices
85
- ```
86
-
87
- ### Step 4: Offer to Install
88
-
89
- If the user wants to proceed, you can install the skill for them:
90
-
91
- ```bash
92
- npx skills add <owner/repo@skill> -g -y
93
- ```
94
-
95
- The `-g` flag installs globally (user-level) and `-y` skips confirmation prompts.
96
-
97
- ## Common Skill Categories
98
-
99
- When searching, consider these common categories:
100
-
101
- | Category | Example Queries |
102
- | --------------- | ---------------------------------------- |
103
- | Web Development | react, nextjs, typescript, css, tailwind |
104
- | Testing | testing, jest, playwright, e2e |
105
- | DevOps | deploy, docker, kubernetes, ci-cd |
106
- | Documentation | docs, readme, changelog, api-docs |
107
- | Code Quality | review, lint, refactor, best-practices |
108
- | Design | ui, ux, design-system, accessibility |
109
- | Productivity | workflow, automation, git |
110
-
111
- ## Tips for Effective Searches
112
-
113
- 1. **Use specific keywords**: "react testing" is better than just "testing"
114
- 2. **Try alternative terms**: If "deploy" doesn't work, try "deployment" or "ci-cd"
115
- 3. **Check popular sources**: Many skills come from `vercel-labs/agent-skills` or `ComposioHQ/awesome-claude-skills`
116
-
117
- ## When No Skills Are Found
118
-
119
- If no relevant skills exist:
120
-
121
- 1. Acknowledge that no existing skill was found
122
- 2. Offer to help with the task directly using your general capabilities
123
- 3. Suggest the user could create their own skill with `npx skills init`
124
-
125
- Example:
126
-
127
- ```
128
- I searched for skills related to "xyz" but didn't find any matches.
129
- I can still help you with this task directly! Would you like me to proceed?
130
-
131
- If this is something you do often, you could create your own skill:
132
- npx skills init my-xyz-skill
133
- ```
1
+ ---
2
+ name: find-skills
3
+ description: Helps users discover and install agent skills when they ask questions like "how do I do X", "find a skill for X", "is there a skill that can...", or express interest in extending capabilities. This skill should be used when the user is looking for functionality that might exist as an installable skill.
4
+ ---
5
+
6
+ # Find Skills
7
+
8
+ This skill helps you discover and install skills from the open agent skills ecosystem.
9
+
10
+ ## When to Use This Skill
11
+
12
+ Use this skill when the user:
13
+
14
+ - Asks "how do I do X" where X might be a common task with an existing skill
15
+ - Says "find a skill for X" or "is there a skill for X"
16
+ - Asks "can you do X" where X is a specialized capability
17
+ - Expresses interest in extending agent capabilities
18
+ - Wants to search for tools, templates, or workflows
19
+ - Mentions they wish they had help with a specific domain (design, testing, deployment, etc.)
20
+
21
+ ## What is the Skills CLI?
22
+
23
+ The Skills CLI (`npx skills`) is the package manager for the open agent skills ecosystem. Skills are modular packages that extend agent capabilities with specialized knowledge, workflows, and tools.
24
+
25
+ **Key commands:**
26
+
27
+ - `npx skills find [query]` - Search for skills interactively or by keyword
28
+ - `npx skills add <package>` - Install a skill from GitHub or other sources
29
+ - `npx skills check` - Check for skill updates
30
+ - `npx skills update` - Update all installed skills
31
+
32
+ **Browse skills at:** https://skills.sh/
33
+
34
+ ## How to Help Users Find Skills
35
+
36
+ ### Step 1: Understand What They Need
37
+
38
+ When a user asks for help with something, identify:
39
+
40
+ 1. The domain (e.g., React, testing, design, deployment)
41
+ 2. The specific task (e.g., writing tests, creating animations, reviewing PRs)
42
+ 3. Whether this is a common enough task that a skill likely exists
43
+
44
+ ### Step 2: Search for Skills
45
+
46
+ Run the find command with a relevant query:
47
+
48
+ ```bash
49
+ npx skills find [query]
50
+ ```
51
+
52
+ For example:
53
+
54
+ - User asks "how do I make my React app faster?" → `npx skills find react performance`
55
+ - User asks "can you help me with PR reviews?" → `npx skills find pr review`
56
+ - User asks "I need to create a changelog" → `npx skills find changelog`
57
+
58
+ The command will return results like:
59
+
60
+ ```
61
+ Install with npx skills add <owner/repo@skill>
62
+
63
+ vercel-labs/agent-skills@vercel-react-best-practices
64
+ └ https://skills.sh/vercel-labs/agent-skills/vercel-react-best-practices
65
+ ```
66
+
67
+ ### Step 3: Present Options to the User
68
+
69
+ When you find relevant skills, present them to the user with:
70
+
71
+ 1. The skill name and what it does
72
+ 2. The install command they can run
73
+ 3. A link to learn more at skills.sh
74
+
75
+ Example response:
76
+
77
+ ```
78
+ I found a skill that might help! The "vercel-react-best-practices" skill provides
79
+ React and Next.js performance optimization guidelines from Vercel Engineering.
80
+
81
+ To install it:
82
+ npx skills add vercel-labs/agent-skills@vercel-react-best-practices
83
+
84
+ Learn more: https://skills.sh/vercel-labs/agent-skills/vercel-react-best-practices
85
+ ```
86
+
87
+ ### Step 4: Offer to Install
88
+
89
+ If the user wants to proceed, you can install the skill for them:
90
+
91
+ ```bash
92
+ npx skills add <owner/repo@skill> -g -y
93
+ ```
94
+
95
+ The `-g` flag installs globally (user-level) and `-y` skips confirmation prompts.
96
+
97
+ ## Common Skill Categories
98
+
99
+ When searching, consider these common categories:
100
+
101
+ | Category | Example Queries |
102
+ | --------------- | ---------------------------------------- |
103
+ | Web Development | react, nextjs, typescript, css, tailwind |
104
+ | Testing | testing, jest, playwright, e2e |
105
+ | DevOps | deploy, docker, kubernetes, ci-cd |
106
+ | Documentation | docs, readme, changelog, api-docs |
107
+ | Code Quality | review, lint, refactor, best-practices |
108
+ | Design | ui, ux, design-system, accessibility |
109
+ | Productivity | workflow, automation, git |
110
+
111
+ ## Tips for Effective Searches
112
+
113
+ 1. **Use specific keywords**: "react testing" is better than just "testing"
114
+ 2. **Try alternative terms**: If "deploy" doesn't work, try "deployment" or "ci-cd"
115
+ 3. **Check popular sources**: Many skills come from `vercel-labs/agent-skills` or `ComposioHQ/awesome-claude-skills`
116
+
117
+ ## When No Skills Are Found
118
+
119
+ If no relevant skills exist:
120
+
121
+ 1. Acknowledge that no existing skill was found
122
+ 2. Offer to help with the task directly using your general capabilities
123
+ 3. Suggest the user could create their own skill with `npx skills init`
124
+
125
+ Example:
126
+
127
+ ```
128
+ I searched for skills related to "xyz" but didn't find any matches.
129
+ I can still help you with this task directly! Would you like me to proceed?
130
+
131
+ If this is something you do often, you could create your own skill:
132
+ npx skills init my-xyz-skill
133
+ ```