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.
- package/.claude/settings.local.json +19 -10
- package/.dockerignore +45 -45
- package/.env.example +56 -56
- package/CLAUDE.md +2 -2
- package/README.md +13 -13
- package/SPEC.md +3 -3
- package/cli/src/commands/chat.js +2 -20
- package/cli/src/commands/list.js +7 -6
- package/cli/src/commands/plugin.js +3 -2
- package/cli/src/daemon.js +2 -2
- package/cli/src/ui/chat-ui-old.js +15 -4
- package/cli/src/ui/chat-ui.js +152 -38
- package/cli/src/ui/footer-bar.js +13 -14
- package/cli/src/utils/config.js +29 -0
- package/cli/src/utils/plugin-config.js +1 -1
- package/docker-compose.yml +33 -33
- package/docs/features.md +120 -120
- package/docs/quick-reference.md +160 -160
- package/docs/user-manual.md +1391 -1391
- package/examples/ambient-example.js +2 -2
- package/examples/bootstrap.js +3 -3
- package/examples/test-chat.js +1 -1
- package/examples/test-reload.js +1 -1
- package/examples/test-telegram.js +1 -1
- package/examples/test-tg-bot.js +1 -1
- package/examples/test-tg-simple.js +2 -2
- package/examples/test-tg.js +1 -1
- package/examples/test-think.js +1 -1
- package/examples/test-weixin-feishu.js +3 -3
- package/package.json +3 -1
- package/plugins/ambient-agent/index.js +1 -1
- package/plugins/audit-plugin.js +75 -24
- package/plugins/default-plugins.js +21 -11
- package/plugins/email/index.js +1 -1
- package/plugins/extension-executor-plugin.js +85 -7
- package/plugins/feishu-plugin.js +118 -16
- package/plugins/install-plugin.js +4 -4
- package/plugins/memory-plugin.js +1 -1
- package/plugins/plugin-manager-plugin.js +3 -3
- package/plugins/python-executor-plugin.js +1 -1
- package/plugins/python-plugin-loader.js +1 -1
- package/plugins/qq-plugin.js +143 -16
- package/plugins/rules-plugin.js +1 -1
- package/plugins/scheduler-plugin.js +2 -2
- package/plugins/session-plugin.js +309 -393
- package/plugins/storage-plugin.js +235 -176
- package/plugins/subagent-plugin.js +4 -4
- package/plugins/telegram-plugin.js +116 -17
- package/plugins/think-plugin.js +1 -1
- package/plugins/web-plugin.js +2 -2
- package/plugins/weixin-plugin.js +102 -19
- package/skills/find-skills/AGENTS.md +2 -2
- package/skills/find-skills/SKILL.md +133 -133
- package/skills/foliko-dev/AGENTS.md +236 -236
- package/skills/foliko-dev/SKILL.md +19 -19
- package/skills/mcp-usage/SKILL.md +200 -200
- package/skills/plugin-guide/SKILL.md +4 -4
- package/skills/python-plugin-dev/SKILL.md +5 -5
- package/skills/skill-guide/SKILL.md +104 -6
- package/skills/subagent-guide/SKILL.md +237 -237
- package/skills/workflow-guide/SKILL.md +646 -646
- package/src/capabilities/skill-manager.js +101 -2
- package/src/capabilities/workflow-engine.js +1 -1
- package/src/core/agent-chat.js +17 -14
- package/src/core/branch-summary-auto.js +206 -0
- package/src/core/chat-session.js +38 -8
- package/src/core/command-registry.js +200 -0
- package/src/core/constants.js +11 -11
- package/src/core/context-compressor.js +700 -149
- package/src/core/context-manager.js +0 -1
- package/src/core/enhanced-context-compressor.js +210 -0
- package/src/core/framework.js +140 -83
- package/src/core/jsonl-storage.js +253 -0
- package/src/core/plugin-manager.js +15 -10
- package/src/core/provider-registry.js +159 -0
- package/src/core/provider.js +2 -0
- package/src/core/session-entry.js +225 -0
- package/src/core/session-manager.js +701 -0
- package/src/core/storage-manager.js +494 -0
- package/src/core/sub-agent-config.js +1 -1
- package/src/core/token-counter.js +177 -58
- package/src/core/ui-extension-context.js +174 -0
- package/src/executors/mcp-executor.js +15 -6
- package/src/utils/logger.js +152 -180
- package/src/utils/plugin-helpers.js +2 -2
- package/website_v2/docs/api.html +1 -1
- package/website_v2/docs/configuration.html +2 -2
- package/website_v2/docs/plugin-development.html +4 -4
- package/website_v2/docs/project-structure.html +2 -2
- package/website_v2/docs/skill-development.html +2 -2
- package/website_v2/index.html +1 -1
- package/website_v2/styles/animations.css +7 -7
- package/.agent/agents/backend-dev.md +0 -102
- package/.agent/agents/data-analyst.md +0 -117
- package/.agent/agents/devops.md +0 -115
- package/.agent/agents/frontend-dev.md +0 -94
- package/.agent/agents/network-requester.md +0 -44
- package/.agent/agents/poster-designer.md +0 -52
- package/.agent/agents/product-manager.md +0 -85
- package/.agent/agents/qa-engineer.md +0 -100
- package/.agent/agents/security-engineer.md +0 -99
- package/.agent/agents/team-lead.md +0 -137
- package/.agent/agents/ui-designer.md +0 -116
- package/.agent/data/default.json +0 -58
- package/.agent/data/email/processed-emails.json +0 -1
- package/.agent/data/plugins-state.json +0 -207
- package/.agent/data/scheduler/tasks.json +0 -1
- package/.agent/data/web/web-config.json +0 -5
- package/.agent/data/weixin/images/file_1776188148383jpg +0 -0
- package/.agent/data/weixin/images/file_1776188458326.jpg +0 -0
- package/.agent/data/weixin/images/file_1776188689423.jpg +0 -0
- package/.agent/data/weixin/images/file_1776188813604.jpg +0 -0
- package/.agent/data/weixin/images/file_1776189097450.jpg +0 -0
- package/.agent/data/weixin/videos/file_1776188318431.mp4 +0 -0
- package/.agent/data/weixin.json +0 -6
- package/.agent/mcp_config.json +0 -14
- package/.agent/memory/user/mof6gk94-kneeuh.md +0 -9
- package/.agent/package.json +0 -8
- package/.agent/plugins/marknative/README.md +0 -134
- package/.agent/plugins/marknative/fonts/SegoeUI Emoji.ttf +0 -0
- package/.agent/plugins/marknative/fonts.zip +0 -0
- package/.agent/plugins/marknative/index.js +0 -256
- package/.agent/plugins/marknative/package.json +0 -12
- package/.agent/plugins/test-plugin.py +0 -99
- package/.agent/plugins.json +0 -14
- package/.agent/python-scripts/test_sample.py +0 -24
- package/.agent/sessions/cli_default.json +0 -4121
- package/.agent/skills/agent-browser/SKILL.md +0 -311
- package/.agent/skills/agent-browser/TEST_PLAN.md +0 -200
- package/.agent/skills/sysinfo/SKILL.md +0 -38
- package/.agent/skills/sysinfo/system-info.sh +0 -130
- package/.agent/skills/workflow/SKILL.md +0 -324
- package/.agent/test-agent.js +0 -35
- package/.agent/weixin.json +0 -6
- package/.agent/workflows/email-digest.json +0 -50
- package/.agent/workflows/file-backup.json +0 -21
- package/.agent/workflows/get-ip-notify.json +0 -32
- package/.agent/workflows/news-aggregator.json +0 -93
- package/.agent/workflows/news-dashboard-v2.json +0 -94
- package/.agent/workflows/notification-batch.json +0 -32
- package/src/core/session-context.js +0 -346
- 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.
|
|
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(), '.
|
|
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
|
-
// 清除
|
|
503
|
+
// 清除 SessionManager 的消息
|
|
474
504
|
if (this._framework) {
|
|
475
|
-
const
|
|
476
|
-
if (
|
|
477
|
-
|
|
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
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
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
|
|
package/plugins/think-plugin.js
CHANGED
|
@@ -151,7 +151,7 @@ class ThinkPlugin extends Plugin {
|
|
|
151
151
|
this._emitNotification('error', '🧠 思考失败', 'AI 未配置')
|
|
152
152
|
return {
|
|
153
153
|
success: false,
|
|
154
|
-
error: 'AI 未配置。请在 .
|
|
154
|
+
error: 'AI 未配置。请在 .foliko/ai.json 或环境变量中配置 AI API Key。'
|
|
155
155
|
}
|
|
156
156
|
}
|
|
157
157
|
|
package/plugins/web-plugin.js
CHANGED
|
@@ -14,7 +14,7 @@ const fs = require('fs')
|
|
|
14
14
|
const path = require('path')
|
|
15
15
|
|
|
16
16
|
// ============================================================================
|
|
17
|
-
// WebStore - 持久化 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 || '.
|
|
85
|
+
this._persistencePath = config.persistencePath || '.foliko/data/web'
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
// ==================== 生命周期 ====================
|
package/plugins/weixin-plugin.js
CHANGED
|
@@ -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
|
|
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=`.
|
|
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(), '.
|
|
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.
|
|
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
|
-
// 清除
|
|
660
|
+
// 清除 SessionManager 的消息
|
|
622
661
|
if (this._framework) {
|
|
623
|
-
const
|
|
624
|
-
if (
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
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
|
-
|
|
630
|
-
const
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
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 (~/.
|
|
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 `~/.
|
|
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
|
+
```
|