foliko 1.0.51 → 1.0.53
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 +131 -126
- package/Dockerfile +30 -2
- package/package.json +1 -1
- package/plugins/ai-plugin.js +1 -0
- package/plugins/audit-plugin.js +1 -0
- package/plugins/default-plugins.js +16 -12
- package/plugins/file-system-plugin.js +1 -0
- package/plugins/install-plugin.js +1 -0
- package/plugins/python-executor-plugin.js +2 -0
- package/plugins/python-plugin-loader.js +1 -0
- package/plugins/rules-plugin.js +2 -1
- package/plugins/scheduler-plugin.js +1 -1
- package/plugins/session-plugin.js +2 -0
- package/plugins/shell-executor-plugin.js +2 -0
- package/plugins/storage-plugin.js +2 -0
- package/plugins/subagent-plugin.js +2 -0
- package/plugins/tools-plugin.js +4 -1
- package/plugins/web-plugin.js +26 -5
- package/src/capabilities/skill-manager.js +1 -0
- package/src/capabilities/workflow-engine.js +1 -0
- package/src/core/agent.js +27 -0
- package/src/core/plugin-base.js +7 -0
- package/src/core/plugin-manager.js +58 -11
- package/src/executors/mcp-executor.js +1 -0
|
@@ -1,126 +1,131 @@
|
|
|
1
|
-
{
|
|
2
|
-
"permissions": {
|
|
3
|
-
"allow": [
|
|
4
|
-
"Bash(grep -r \"dotenv\" \"D:/Code/vb-agent/\" --include=\"*.json\" 2>/dev/null | head -20)",
|
|
5
|
-
"Bash(cd \"D:/Code/vb-agent\" && pnpm add dotenv)",
|
|
6
|
-
"Bash(cd \"D:/Code/vb-agent\" && node -e \"const ai = require\\('ai'\\); console.log\\(Object.keys\\(ai\\).filter\\(k => k.toLowerCase\\(\\).includes\\('reason'\\) || k.toLowerCase\\(\\).includes\\('split'\\) || k.toLowerCase\\(\\).includes\\('think'\\)\\)\\)\")",
|
|
7
|
-
"Bash(cd \"D:/Code/vb-agent\" && node -e \"const ai = require\\('ai'\\); console.log\\(typeof ai.extractReasoningMiddleware, ai.extractReasoningMiddleware.toString\\(\\).substring\\(0, 500\\)\\)\")",
|
|
8
|
-
"Bash(cd \"D:/Code/vb-agent\" && node -e \"\nconst ai = require\\('ai'\\);\nconsole.log\\('=== extractReasoningMiddleware ==='\\);\nconsole.log\\(ai.extractReasoningMiddleware.toString\\(\\)\\);\nconsole.log\\('\\\\n=== isReasoningUIPart ==='\\);\nconsole.log\\(typeof ai.isReasoningUIPart\\);\n\")",
|
|
9
|
-
"Bash(cd \"D:/Code/vb-agent\" && node -e \"const ai = require\\('ai'\\); console.log\\(Object.keys\\(ai\\).filter\\(k => k.toLowerCase\\(\\).includes\\('split'\\)\\)\\)\")",
|
|
10
|
-
"Bash(cd \"D:/Code/vb-agent\" && pnpm add ink react)",
|
|
11
|
-
"Bash(cd \"D:/Code/vb-agent\" && node cli/bin/foliko.js --help)",
|
|
12
|
-
"Bash(cd \"D:/Code/vb-agent\" && timeout 2 node cli/bin/foliko.js chat 2>&1 || true)",
|
|
13
|
-
"Bash(cd \"D:/Code/vb-agent\" && node -e \"const mt = require\\('marked-terminal'\\); console.log\\(typeof mt, Object.keys\\(mt\\)\\)\")",
|
|
14
|
-
"Bash(cd \"D:/Code/vb-agent\" && timeout 3 node cli/bin/foliko.js chat 2>&1 || true)",
|
|
15
|
-
"Bash(echo \"你好\" | node cli/bin/foliko.js chat 2>&1 | head -50)",
|
|
16
|
-
"Bash(printf '思考一下1+1等于几\\\\n' | node cli/bin/foliko.js chat 2>&1 | head -100)",
|
|
17
|
-
"Bash(printf '1+1等于几\\\\n' | node cli/bin/foliko.js chat 2>&1)",
|
|
18
|
-
"Bash(node -e \"\nconst { renderLine } = require\\('./cli/src/utils/markdown'\\)\nconsole.log\\(renderLine\\('🎉 这是一个 emoji'\\)\\)\nconsole.log\\(renderLine\\('**粗体** 和 🎉'\\)\\)\n\")",
|
|
19
|
-
"Bash(node -e \"\nconst { render } = require\\('./cli/src/utils/markdown'\\)\nconst text = '🎉 今天是个好日子\\\\n## 标题\\\\n- 列表项1\\\\n- 列表项2'\nconsole.log\\(render\\(text\\)\\)\n\")",
|
|
20
|
-
"Bash(node -e \"\nconst { renderLine } = require\\('./cli/src/utils/markdown'\\)\n\n// 模拟emoji被截断的情况\nconst emoji = '🎉'\nconsole.log\\('完整的 emoji:', renderLine\\(emoji\\)\\)\n\n// 模拟截断 - emoji的UTF-8字节是 \\\\xF0\\\\x9F\\\\x8E\\\\x89\nconst partial = '\\\\xF0\\\\x9F' // 不完整的emoji\nconsole.log\\('截断的 emoji:', renderLine\\(partial\\)\\)\n\")",
|
|
21
|
-
"Bash(node -e \"\nconst isIncompleteUTF8 = \\(str\\) => {\n if \\(!str || str.length === 0\\) return false\n const lastChar = str.charCodeAt\\(str.length - 1\\)\n if \\(lastChar >= 0x80 && lastChar < 0xC0\\) return true\n return false\n}\n\n// 测试各种emoji\nconst tests = ['🎉', '📁', '⚡', '🛠️', '🔑', '💾', '📝', '⏰', '🔌', '📋']\ntests.forEach\\(e => {\n console.log\\(e, '完整:', !isIncompleteUTF8\\(e\\)\\)\n}\\)\n\n// 测试被截断的emoji \\(只保留第一字节\\)\nconst broken = '🎉'.slice\\(0, 1\\)\nconsole.log\\('截断emoji:', broken, '检测:', isIncompleteUTF8\\(broken\\)\\)\n\")",
|
|
22
|
-
"Bash(node -e \"\nconst { renderLine } = require\\('./cli/src/utils/markdown'\\)\nconsole.log\\('测试:', renderLine\\('📁 文件操作:读取、创建'\\)\\)\n\")",
|
|
23
|
-
"Bash(node -e \"\nconst hasIncompleteSurrogate = \\(str\\) => {\n if \\(!str || str.length === 0\\) return false\n const lastChar = str.charCodeAt\\(str.length - 1\\)\n console.log\\('检查:', str, 'lastChar:', lastChar.toString\\(16\\), '范围:', \\(lastChar >= 0xD800 && lastChar <= 0xDBFF\\)\\)\n return lastChar >= 0xD800 && lastChar <= 0xDBFF\n}\n\nconst chunk1 = '\\\\xD83C'\nconsole.log\\('结果:', hasIncompleteSurrogate\\(chunk1\\)\\)\n\")",
|
|
24
|
-
"Bash(cd D:/Code/vb-agent && node test-stream-emoji.js 2>&1)",
|
|
25
|
-
"Read(//d/Date/20260321/app/**)",
|
|
26
|
-
"Bash(node -e \":*)",
|
|
27
|
-
"Bash(node -e \"\nconst { loadAgentConfig } = require\\('./plugins/default-plugins'\\);\nconst config = loadAgentConfig\\('D:/Date/20260321/app/.agent'\\);\nconsole.log\\('skillsDirs:', config.skillsDirs\\);\n\")",
|
|
28
|
-
"Bash(cd D:/Code/vb-agent && pnpm install --shamefully-hoist 2>&1 | head -20)",
|
|
29
|
-
"Bash(cd D:/Code/vb-agent && rm -rf node_modules && pnpm install)",
|
|
30
|
-
"Bash(cd D:/Code/vb-agent && timeout 8 node test-tg.js 2>&1 || true)",
|
|
31
|
-
"Bash(cd D:/Code/vb-agent && timeout 10 node test-tg.js 2>&1 || true)",
|
|
32
|
-
"Bash(find /d/Code/vb-agent -name \"*email*\" -type f 2>/dev/null | grep -v node_modules | grep -v .git)",
|
|
33
|
-
"Bash(find /d/Code/vb-agent -maxdepth 2 -name \"*.md\" -type f 2>/dev/null | grep -v node_modules)",
|
|
34
|
-
"Bash(node -c plugins/default-plugins.js && node -c src/core/plugin-manager.js && echo \"Syntax OK\")",
|
|
35
|
-
"Bash(node -c plugins/install-plugin.js && echo \"Syntax OK\")",
|
|
36
|
-
"Bash(node -c cli/src/ui/chat-ui.js && echo \"Syntax OK\")",
|
|
37
|
-
"Bash(node -c plugins/default-plugins.js && echo \"Syntax OK\")",
|
|
38
|
-
"Bash(node -c plugins/scheduler-plugin.js && echo \"Syntax OK\")",
|
|
39
|
-
"Bash(node -c plugins/telegram-plugin.js && node -c plugins/scheduler-plugin.js && echo \"Syntax OK\")",
|
|
40
|
-
"Bash(node -c plugins/telegram-plugin.js && echo \"Syntax OK\")",
|
|
41
|
-
"WebSearch",
|
|
42
|
-
"Bash(npm ls:*)",
|
|
43
|
-
"Bash(cd node_modules/@chnak/weixin-bot && npm run build 2>&1)",
|
|
44
|
-
"Bash(cd node_modules/@chnak/weixin-bot && npx tsc 2>&1)",
|
|
45
|
-
"Bash(npm install:*)",
|
|
46
|
-
"Bash(cd node_modules/@chnak/weixin-bot && npx typescript --version && npx tsc 2>&1)",
|
|
47
|
-
"Bash(npx tsc:*)",
|
|
48
|
-
"Bash(node --check /d/Code/vb-agent/plugins/weixin-plugin.js 2>&1)",
|
|
49
|
-
"Bash(node --check /d/Code/vb-agent/plugins/telegram-plugin.js && node --check /d/Code/vb-agent/plugins/weixin-plugin.js && echo \"OK\")",
|
|
50
|
-
"Bash(node --check /d/Code/vb-agent/cli/src/ui/chat-ui.js && echo \"OK\")",
|
|
51
|
-
"Bash(npm uninstall:*)",
|
|
52
|
-
"Bash(rm -rf /tmp/weixin-bot && git clone https://github.com/chnak/weixin-bot.git /tmp/weixin-bot 2>&1)",
|
|
53
|
-
"Bash(mkdir -p node_modules/@chnak/weixin-bot && cp -r /tmp/weixin-bot/nodejs/* node_modules/@chnak/weixin-bot/ && cd node_modules/@chnak/weixin-bot && npm install 2>&1)",
|
|
54
|
-
"Bash(node --check /d/Code/vb-agent/plugins/weixin-plugin.js && echo \"OK\")",
|
|
55
|
-
"Bash(node -e \"import\\('@chnak/weixin-bot'\\).then\\(m => console.log\\('OK:', Object.keys\\(m\\)\\)\\).catch\\(e => console.error\\('Error:', e.message\\)\\)\")",
|
|
56
|
-
"Bash(npm run:*)",
|
|
57
|
-
"Bash(node -e \"const { WeixinBot } = require\\('@chnak/weixin-bot'\\); console.log\\(typeof WeixinBot\\)\" 2>&1)",
|
|
58
|
-
"Bash(node -e \"import\\('@chnak/weixin-bot'\\).then\\(m => console.log\\('OK:', typeof m.WeixinBot\\)\\).catch\\(e => console.error\\('Error:', e.message\\)\\)\" 2>&1)",
|
|
59
|
-
"Bash(ls -la D:/code/vb-agent/cli/bin/ && cat D:/code/vb-agent/cli/bin/*.js 2>/dev/null | head -50)",
|
|
60
|
-
"Bash(npm config:*)",
|
|
61
|
-
"Bash(node -c plugins/subagent-plugin.js 2>&1)",
|
|
62
|
-
"Bash(node -c plugins/default-plugins.js 2>&1)",
|
|
63
|
-
"Bash(node -c plugins/default-plugins.js && node -c src/core/plugin-manager.js && node -c plugins/tools-plugin.js 2>&1)",
|
|
64
|
-
"Bash(node -c src/core/plugin-base.js && node -c src/core/plugin-manager.js 2>&1)",
|
|
65
|
-
"Bash(node -c plugins/telegram-plugin.js && node -c plugins/weixin-plugin.js 2>&1)",
|
|
66
|
-
"Bash(node -c src/core/plugin-manager.js 2>&1)",
|
|
67
|
-
"Bash(node -c src/core/plugin-manager.js && node -c src/core/plugin-base.js && node -c plugins/default-plugins.js && node -c plugins/telegram-plugin.js && node -c plugins/weixin-plugin.js 2>&1)",
|
|
68
|
-
"Bash(node -e \"require\\('dotenv'\\).config\\(\\); console.log\\('PROVIDER:', process.env.FOLIKO_PROVIDER\\); console.log\\('MODEL:', process.env.FOLIKO_MODEL\\); console.log\\('KEY:', process.env.DEEPSEEK_API_KEY ? 'set' : 'not set'\\)\" 2>&1)",
|
|
69
|
-
"Bash(node cli/src/index.js chat 2>&1 | head -30)",
|
|
70
|
-
"Bash(node -e 'const { DEFAULT_PROVIDERS } = require\\(\"./src/core/provider\"\\); console.log\\(DEFAULT_PROVIDERS\\);')",
|
|
71
|
-
"Bash(node -e \"const dotenv = require\\('dotenv'\\); const result = dotenv.config\\(\\); console.log\\('Result:', result\\); console.log\\('PROVIDER after dotenv:', process.env.FOLIKO_PROVIDER\\);\" 2>&1)",
|
|
72
|
-
"Bash(node -c plugins/email.js && node -c plugins/default-plugins.js 2>&1)",
|
|
73
|
-
"Bash(node -c plugins/email.js 2>&1)",
|
|
74
|
-
"Bash(npm list:*)",
|
|
75
|
-
"Bash(node -e \"const {EmailPlugin} = require\\('./plugins/email'\\); const p = new EmailPlugin\\(\\); console.log\\('email plugin loaded ok'\\); console.log\\('enabled:', p.enabled\\); console.log\\('version:', p.version\\);\" 2>&1)",
|
|
76
|
-
"Bash(cd D:/Code/vb-agent && node -e \"console.log\\('IMAP_HOST:', process.env.IMAP_HOST\\); console.log\\('IMAP_USER:', process.env.IMAP_USER\\); console.log\\('IMAP_PORT:', process.env.IMAP_PORT\\);\")",
|
|
77
|
-
"Bash(node -e \"const sdk = require\\('@larksuiteoapi/node-sdk'\\); console.log\\(Object.keys\\(sdk\\)\\);\")",
|
|
78
|
-
"Bash(node -e \"const { WSClient } = require\\('@larksuiteoapi/node-sdk'\\); const sdk = new WSClient\\({}\\); console.log\\(Object.getOwnPropertyNames\\(Object.getPrototypeOf\\(sdk\\)\\)\\);\")",
|
|
79
|
-
"Bash(node -c src/core/framework.js 2>&1)",
|
|
80
|
-
"Bash(node -c plugins/telegram-plugin.js 2>&1)",
|
|
81
|
-
"Bash(node -c src/capabilities/skill-manager.js 2>&1)",
|
|
82
|
-
"Bash(node -c plugins/feishu-plugin.js 2>&1)",
|
|
83
|
-
"Bash(node debug-skills.js)",
|
|
84
|
-
"Bash(node -c src/capabilities/workflow-engine.js 2>&1)",
|
|
85
|
-
"Bash(node -c skills/workflow-guide/SKILL.md 2>&1 || head -10 skills/workflow-guide/SKILL.md)",
|
|
86
|
-
"Bash(ls plugins/*.js 2>&1)",
|
|
87
|
-
"Bash(node -c plugins/web-plugin.js 2>&1)",
|
|
88
|
-
"Bash(cd D:/code/vb-agent && node -e \"require\\('./plugins/web-plugin.js'\\)\" 2>&1)",
|
|
89
|
-
"Bash(cd D:/code/vb-agent && node -e \"\nconst { WebPlugin } = require\\('./plugins/web-plugin.js'\\);\nconst p = new WebPlugin\\(\\);\nconsole.log\\('Plugin created:', p.name, p.version\\);\n\" 2>&1)",
|
|
90
|
-
"Bash(cd D:/code/vb-agent && mkdir -p test-static && echo '<html><body>Hello Static</body></html>' > test-static/index.html)",
|
|
91
|
-
"mcp__plugin_context7_context7__resolve-library-id",
|
|
92
|
-
"mcp__plugin_context7_context7__query-docs",
|
|
93
|
-
"Bash(cd D:/code/vb-agent && rm test-hono.js)",
|
|
94
|
-
"Bash(curl -s http://localhost:3000/test 2>&1 || echo \"连接失败\")",
|
|
95
|
-
"Bash(cd D:/code/vb-agent && timeout 15 node examples/test-web-plugin.js 2>&1)",
|
|
96
|
-
"Bash(cd D:/code/vb-agent && timeout 60 node examples/test-chat.js 2>&1 | head -100)",
|
|
97
|
-
"Bash(cd D:/code/vb-agent && timeout 120 node examples/test-chat.js 2>&1 | tail -80)",
|
|
98
|
-
"Bash(cd D:/code/vb-agent && timeout 120 node examples/bootstrap.js 2>&1 | tail -100)",
|
|
99
|
-
"Bash(cd D:/code/vb-agent && timeout 10 node examples/test-web-plugin.js 2>&1)",
|
|
100
|
-
"Bash(curl -s -X POST http://localhost:3000/test-webhook \\\\\n -H \"Content-Type: application/json\" \\\\\n -d '{\"message\":\"test from curl\",\"sessionId\":\"web_test\"}')",
|
|
101
|
-
"Bash(curl -s http://localhost:3000/test 2>&1 || echo \"Connection failed\")",
|
|
102
|
-
"Bash(curl -s -X POST http://localhost:3000/webhook/test-webhook \\\\\n -H \"Content-Type: application/json\" \\\\\n -d '{\"message\":\"test from curl\",\"sessionId\":\"web_test\"}')",
|
|
103
|
-
"Bash(curl -s http://localhost:3000/webui/status)",
|
|
104
|
-
"Bash(curl -s http://localhost:3000/test)",
|
|
105
|
-
"Bash(curl -s -v -X POST http://localhost:3000/test-webhook \\\\\n -H \"Content-Type: application/json\" \\\\\n -d '{\"message\":\"test\"}' 2>&1 | head -30)",
|
|
106
|
-
"Bash(curl -s -X POST \"http://localhost:3000/webhook/test-webhook\" \\\\\n -H \"Content-Type: application/json\" \\\\\n -d '{\"message\":\"test\"}' 2>&1)",
|
|
107
|
-
"Bash(curl -s http://localhost:3000/webui/ 2>&1)",
|
|
108
|
-
"Bash(curl -s -X POST http://localhost:3000/webui/list-routes \\\\\n -H \"Content-Type: application/json\" \\\\\n -d '{}' 2>&1 || echo \"Endpoint not found\")",
|
|
109
|
-
"Bash(curl -s http://localhost:3000/ 2>&1)",
|
|
110
|
-
"Bash(curl -s -X POST \"http://localhost:3000/webhook/test-webhook\" \\\\\n -H \"Content-Type: application/json\" \\\\\n -d '{\"message\":\"test with prefix\"}')",
|
|
111
|
-
"Bash(netstat -ano | grep :3000 | head -5)",
|
|
112
|
-
"Bash(netstat -ano | grep :3000 | grep LISTENING)",
|
|
113
|
-
"Bash(curl -s -X POST http://localhost:3000/test-webhook \\\\\n -H \"Content-Type: application/json\" \\\\\n -d '{\"message\":\"test\",\"sessionId\":\"web_test\"}')",
|
|
114
|
-
"Bash(taskkill /F /IM node.exe 2>/dev/null; sleep 1; echo \"Node processes killed\")",
|
|
115
|
-
"Bash(netstat -ano | grep :3000)",
|
|
116
|
-
"Bash(taskkill //F //PID 19848)",
|
|
117
|
-
"Bash(curl -s -X POST \"http://localhost:3000/webhook/075s5s2umn4smn4f\" \\\\\n -H \"Content-Type: application/json\" \\\\\n -d '{\"test\":\"data\"}' 2>&1)",
|
|
118
|
-
"Bash(curl -s http://localhost:3000/api/hello 2>&1)",
|
|
119
|
-
"Bash(curl -v -X POST \"http://localhost:3000/webhook/075s5s2umn4smn4f\" \\\\\n -H \"Content-Type: application/json\" \\\\\n -d '{\"test\":\"data\"}' 2>&1 | head -30)",
|
|
120
|
-
"Bash(cd D:/code/vb-agent && timeout 30 node test-compression.js 2>&1)",
|
|
121
|
-
"Bash(cd D:/code/vb-agent && node -c src/core/agent-chat.js 2>&1)",
|
|
122
|
-
"Bash(cd D:/code/vb-agent && node -e \"require\\('./src/core/agent-chat.js'\\); console.log\\('模块加载成功'\\)\" 2>&1)",
|
|
123
|
-
"Bash(cd D:/code/vb-agent && node -e \"require\\('./src/core/agent.js'\\); console.log\\('Agent 加载成功'\\)\" 2>&1)"
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(grep -r \"dotenv\" \"D:/Code/vb-agent/\" --include=\"*.json\" 2>/dev/null | head -20)",
|
|
5
|
+
"Bash(cd \"D:/Code/vb-agent\" && pnpm add dotenv)",
|
|
6
|
+
"Bash(cd \"D:/Code/vb-agent\" && node -e \"const ai = require\\('ai'\\); console.log\\(Object.keys\\(ai\\).filter\\(k => k.toLowerCase\\(\\).includes\\('reason'\\) || k.toLowerCase\\(\\).includes\\('split'\\) || k.toLowerCase\\(\\).includes\\('think'\\)\\)\\)\")",
|
|
7
|
+
"Bash(cd \"D:/Code/vb-agent\" && node -e \"const ai = require\\('ai'\\); console.log\\(typeof ai.extractReasoningMiddleware, ai.extractReasoningMiddleware.toString\\(\\).substring\\(0, 500\\)\\)\")",
|
|
8
|
+
"Bash(cd \"D:/Code/vb-agent\" && node -e \"\nconst ai = require\\('ai'\\);\nconsole.log\\('=== extractReasoningMiddleware ==='\\);\nconsole.log\\(ai.extractReasoningMiddleware.toString\\(\\)\\);\nconsole.log\\('\\\\n=== isReasoningUIPart ==='\\);\nconsole.log\\(typeof ai.isReasoningUIPart\\);\n\")",
|
|
9
|
+
"Bash(cd \"D:/Code/vb-agent\" && node -e \"const ai = require\\('ai'\\); console.log\\(Object.keys\\(ai\\).filter\\(k => k.toLowerCase\\(\\).includes\\('split'\\)\\)\\)\")",
|
|
10
|
+
"Bash(cd \"D:/Code/vb-agent\" && pnpm add ink react)",
|
|
11
|
+
"Bash(cd \"D:/Code/vb-agent\" && node cli/bin/foliko.js --help)",
|
|
12
|
+
"Bash(cd \"D:/Code/vb-agent\" && timeout 2 node cli/bin/foliko.js chat 2>&1 || true)",
|
|
13
|
+
"Bash(cd \"D:/Code/vb-agent\" && node -e \"const mt = require\\('marked-terminal'\\); console.log\\(typeof mt, Object.keys\\(mt\\)\\)\")",
|
|
14
|
+
"Bash(cd \"D:/Code/vb-agent\" && timeout 3 node cli/bin/foliko.js chat 2>&1 || true)",
|
|
15
|
+
"Bash(echo \"你好\" | node cli/bin/foliko.js chat 2>&1 | head -50)",
|
|
16
|
+
"Bash(printf '思考一下1+1等于几\\\\n' | node cli/bin/foliko.js chat 2>&1 | head -100)",
|
|
17
|
+
"Bash(printf '1+1等于几\\\\n' | node cli/bin/foliko.js chat 2>&1)",
|
|
18
|
+
"Bash(node -e \"\nconst { renderLine } = require\\('./cli/src/utils/markdown'\\)\nconsole.log\\(renderLine\\('🎉 这是一个 emoji'\\)\\)\nconsole.log\\(renderLine\\('**粗体** 和 🎉'\\)\\)\n\")",
|
|
19
|
+
"Bash(node -e \"\nconst { render } = require\\('./cli/src/utils/markdown'\\)\nconst text = '🎉 今天是个好日子\\\\n## 标题\\\\n- 列表项1\\\\n- 列表项2'\nconsole.log\\(render\\(text\\)\\)\n\")",
|
|
20
|
+
"Bash(node -e \"\nconst { renderLine } = require\\('./cli/src/utils/markdown'\\)\n\n// 模拟emoji被截断的情况\nconst emoji = '🎉'\nconsole.log\\('完整的 emoji:', renderLine\\(emoji\\)\\)\n\n// 模拟截断 - emoji的UTF-8字节是 \\\\xF0\\\\x9F\\\\x8E\\\\x89\nconst partial = '\\\\xF0\\\\x9F' // 不完整的emoji\nconsole.log\\('截断的 emoji:', renderLine\\(partial\\)\\)\n\")",
|
|
21
|
+
"Bash(node -e \"\nconst isIncompleteUTF8 = \\(str\\) => {\n if \\(!str || str.length === 0\\) return false\n const lastChar = str.charCodeAt\\(str.length - 1\\)\n if \\(lastChar >= 0x80 && lastChar < 0xC0\\) return true\n return false\n}\n\n// 测试各种emoji\nconst tests = ['🎉', '📁', '⚡', '🛠️', '🔑', '💾', '📝', '⏰', '🔌', '📋']\ntests.forEach\\(e => {\n console.log\\(e, '完整:', !isIncompleteUTF8\\(e\\)\\)\n}\\)\n\n// 测试被截断的emoji \\(只保留第一字节\\)\nconst broken = '🎉'.slice\\(0, 1\\)\nconsole.log\\('截断emoji:', broken, '检测:', isIncompleteUTF8\\(broken\\)\\)\n\")",
|
|
22
|
+
"Bash(node -e \"\nconst { renderLine } = require\\('./cli/src/utils/markdown'\\)\nconsole.log\\('测试:', renderLine\\('📁 文件操作:读取、创建'\\)\\)\n\")",
|
|
23
|
+
"Bash(node -e \"\nconst hasIncompleteSurrogate = \\(str\\) => {\n if \\(!str || str.length === 0\\) return false\n const lastChar = str.charCodeAt\\(str.length - 1\\)\n console.log\\('检查:', str, 'lastChar:', lastChar.toString\\(16\\), '范围:', \\(lastChar >= 0xD800 && lastChar <= 0xDBFF\\)\\)\n return lastChar >= 0xD800 && lastChar <= 0xDBFF\n}\n\nconst chunk1 = '\\\\xD83C'\nconsole.log\\('结果:', hasIncompleteSurrogate\\(chunk1\\)\\)\n\")",
|
|
24
|
+
"Bash(cd D:/Code/vb-agent && node test-stream-emoji.js 2>&1)",
|
|
25
|
+
"Read(//d/Date/20260321/app/**)",
|
|
26
|
+
"Bash(node -e \":*)",
|
|
27
|
+
"Bash(node -e \"\nconst { loadAgentConfig } = require\\('./plugins/default-plugins'\\);\nconst config = loadAgentConfig\\('D:/Date/20260321/app/.agent'\\);\nconsole.log\\('skillsDirs:', config.skillsDirs\\);\n\")",
|
|
28
|
+
"Bash(cd D:/Code/vb-agent && pnpm install --shamefully-hoist 2>&1 | head -20)",
|
|
29
|
+
"Bash(cd D:/Code/vb-agent && rm -rf node_modules && pnpm install)",
|
|
30
|
+
"Bash(cd D:/Code/vb-agent && timeout 8 node test-tg.js 2>&1 || true)",
|
|
31
|
+
"Bash(cd D:/Code/vb-agent && timeout 10 node test-tg.js 2>&1 || true)",
|
|
32
|
+
"Bash(find /d/Code/vb-agent -name \"*email*\" -type f 2>/dev/null | grep -v node_modules | grep -v .git)",
|
|
33
|
+
"Bash(find /d/Code/vb-agent -maxdepth 2 -name \"*.md\" -type f 2>/dev/null | grep -v node_modules)",
|
|
34
|
+
"Bash(node -c plugins/default-plugins.js && node -c src/core/plugin-manager.js && echo \"Syntax OK\")",
|
|
35
|
+
"Bash(node -c plugins/install-plugin.js && echo \"Syntax OK\")",
|
|
36
|
+
"Bash(node -c cli/src/ui/chat-ui.js && echo \"Syntax OK\")",
|
|
37
|
+
"Bash(node -c plugins/default-plugins.js && echo \"Syntax OK\")",
|
|
38
|
+
"Bash(node -c plugins/scheduler-plugin.js && echo \"Syntax OK\")",
|
|
39
|
+
"Bash(node -c plugins/telegram-plugin.js && node -c plugins/scheduler-plugin.js && echo \"Syntax OK\")",
|
|
40
|
+
"Bash(node -c plugins/telegram-plugin.js && echo \"Syntax OK\")",
|
|
41
|
+
"WebSearch",
|
|
42
|
+
"Bash(npm ls:*)",
|
|
43
|
+
"Bash(cd node_modules/@chnak/weixin-bot && npm run build 2>&1)",
|
|
44
|
+
"Bash(cd node_modules/@chnak/weixin-bot && npx tsc 2>&1)",
|
|
45
|
+
"Bash(npm install:*)",
|
|
46
|
+
"Bash(cd node_modules/@chnak/weixin-bot && npx typescript --version && npx tsc 2>&1)",
|
|
47
|
+
"Bash(npx tsc:*)",
|
|
48
|
+
"Bash(node --check /d/Code/vb-agent/plugins/weixin-plugin.js 2>&1)",
|
|
49
|
+
"Bash(node --check /d/Code/vb-agent/plugins/telegram-plugin.js && node --check /d/Code/vb-agent/plugins/weixin-plugin.js && echo \"OK\")",
|
|
50
|
+
"Bash(node --check /d/Code/vb-agent/cli/src/ui/chat-ui.js && echo \"OK\")",
|
|
51
|
+
"Bash(npm uninstall:*)",
|
|
52
|
+
"Bash(rm -rf /tmp/weixin-bot && git clone https://github.com/chnak/weixin-bot.git /tmp/weixin-bot 2>&1)",
|
|
53
|
+
"Bash(mkdir -p node_modules/@chnak/weixin-bot && cp -r /tmp/weixin-bot/nodejs/* node_modules/@chnak/weixin-bot/ && cd node_modules/@chnak/weixin-bot && npm install 2>&1)",
|
|
54
|
+
"Bash(node --check /d/Code/vb-agent/plugins/weixin-plugin.js && echo \"OK\")",
|
|
55
|
+
"Bash(node -e \"import\\('@chnak/weixin-bot'\\).then\\(m => console.log\\('OK:', Object.keys\\(m\\)\\)\\).catch\\(e => console.error\\('Error:', e.message\\)\\)\")",
|
|
56
|
+
"Bash(npm run:*)",
|
|
57
|
+
"Bash(node -e \"const { WeixinBot } = require\\('@chnak/weixin-bot'\\); console.log\\(typeof WeixinBot\\)\" 2>&1)",
|
|
58
|
+
"Bash(node -e \"import\\('@chnak/weixin-bot'\\).then\\(m => console.log\\('OK:', typeof m.WeixinBot\\)\\).catch\\(e => console.error\\('Error:', e.message\\)\\)\" 2>&1)",
|
|
59
|
+
"Bash(ls -la D:/code/vb-agent/cli/bin/ && cat D:/code/vb-agent/cli/bin/*.js 2>/dev/null | head -50)",
|
|
60
|
+
"Bash(npm config:*)",
|
|
61
|
+
"Bash(node -c plugins/subagent-plugin.js 2>&1)",
|
|
62
|
+
"Bash(node -c plugins/default-plugins.js 2>&1)",
|
|
63
|
+
"Bash(node -c plugins/default-plugins.js && node -c src/core/plugin-manager.js && node -c plugins/tools-plugin.js 2>&1)",
|
|
64
|
+
"Bash(node -c src/core/plugin-base.js && node -c src/core/plugin-manager.js 2>&1)",
|
|
65
|
+
"Bash(node -c plugins/telegram-plugin.js && node -c plugins/weixin-plugin.js 2>&1)",
|
|
66
|
+
"Bash(node -c src/core/plugin-manager.js 2>&1)",
|
|
67
|
+
"Bash(node -c src/core/plugin-manager.js && node -c src/core/plugin-base.js && node -c plugins/default-plugins.js && node -c plugins/telegram-plugin.js && node -c plugins/weixin-plugin.js 2>&1)",
|
|
68
|
+
"Bash(node -e \"require\\('dotenv'\\).config\\(\\); console.log\\('PROVIDER:', process.env.FOLIKO_PROVIDER\\); console.log\\('MODEL:', process.env.FOLIKO_MODEL\\); console.log\\('KEY:', process.env.DEEPSEEK_API_KEY ? 'set' : 'not set'\\)\" 2>&1)",
|
|
69
|
+
"Bash(node cli/src/index.js chat 2>&1 | head -30)",
|
|
70
|
+
"Bash(node -e 'const { DEFAULT_PROVIDERS } = require\\(\"./src/core/provider\"\\); console.log\\(DEFAULT_PROVIDERS\\);')",
|
|
71
|
+
"Bash(node -e \"const dotenv = require\\('dotenv'\\); const result = dotenv.config\\(\\); console.log\\('Result:', result\\); console.log\\('PROVIDER after dotenv:', process.env.FOLIKO_PROVIDER\\);\" 2>&1)",
|
|
72
|
+
"Bash(node -c plugins/email.js && node -c plugins/default-plugins.js 2>&1)",
|
|
73
|
+
"Bash(node -c plugins/email.js 2>&1)",
|
|
74
|
+
"Bash(npm list:*)",
|
|
75
|
+
"Bash(node -e \"const {EmailPlugin} = require\\('./plugins/email'\\); const p = new EmailPlugin\\(\\); console.log\\('email plugin loaded ok'\\); console.log\\('enabled:', p.enabled\\); console.log\\('version:', p.version\\);\" 2>&1)",
|
|
76
|
+
"Bash(cd D:/Code/vb-agent && node -e \"console.log\\('IMAP_HOST:', process.env.IMAP_HOST\\); console.log\\('IMAP_USER:', process.env.IMAP_USER\\); console.log\\('IMAP_PORT:', process.env.IMAP_PORT\\);\")",
|
|
77
|
+
"Bash(node -e \"const sdk = require\\('@larksuiteoapi/node-sdk'\\); console.log\\(Object.keys\\(sdk\\)\\);\")",
|
|
78
|
+
"Bash(node -e \"const { WSClient } = require\\('@larksuiteoapi/node-sdk'\\); const sdk = new WSClient\\({}\\); console.log\\(Object.getOwnPropertyNames\\(Object.getPrototypeOf\\(sdk\\)\\)\\);\")",
|
|
79
|
+
"Bash(node -c src/core/framework.js 2>&1)",
|
|
80
|
+
"Bash(node -c plugins/telegram-plugin.js 2>&1)",
|
|
81
|
+
"Bash(node -c src/capabilities/skill-manager.js 2>&1)",
|
|
82
|
+
"Bash(node -c plugins/feishu-plugin.js 2>&1)",
|
|
83
|
+
"Bash(node debug-skills.js)",
|
|
84
|
+
"Bash(node -c src/capabilities/workflow-engine.js 2>&1)",
|
|
85
|
+
"Bash(node -c skills/workflow-guide/SKILL.md 2>&1 || head -10 skills/workflow-guide/SKILL.md)",
|
|
86
|
+
"Bash(ls plugins/*.js 2>&1)",
|
|
87
|
+
"Bash(node -c plugins/web-plugin.js 2>&1)",
|
|
88
|
+
"Bash(cd D:/code/vb-agent && node -e \"require\\('./plugins/web-plugin.js'\\)\" 2>&1)",
|
|
89
|
+
"Bash(cd D:/code/vb-agent && node -e \"\nconst { WebPlugin } = require\\('./plugins/web-plugin.js'\\);\nconst p = new WebPlugin\\(\\);\nconsole.log\\('Plugin created:', p.name, p.version\\);\n\" 2>&1)",
|
|
90
|
+
"Bash(cd D:/code/vb-agent && mkdir -p test-static && echo '<html><body>Hello Static</body></html>' > test-static/index.html)",
|
|
91
|
+
"mcp__plugin_context7_context7__resolve-library-id",
|
|
92
|
+
"mcp__plugin_context7_context7__query-docs",
|
|
93
|
+
"Bash(cd D:/code/vb-agent && rm test-hono.js)",
|
|
94
|
+
"Bash(curl -s http://localhost:3000/test 2>&1 || echo \"连接失败\")",
|
|
95
|
+
"Bash(cd D:/code/vb-agent && timeout 15 node examples/test-web-plugin.js 2>&1)",
|
|
96
|
+
"Bash(cd D:/code/vb-agent && timeout 60 node examples/test-chat.js 2>&1 | head -100)",
|
|
97
|
+
"Bash(cd D:/code/vb-agent && timeout 120 node examples/test-chat.js 2>&1 | tail -80)",
|
|
98
|
+
"Bash(cd D:/code/vb-agent && timeout 120 node examples/bootstrap.js 2>&1 | tail -100)",
|
|
99
|
+
"Bash(cd D:/code/vb-agent && timeout 10 node examples/test-web-plugin.js 2>&1)",
|
|
100
|
+
"Bash(curl -s -X POST http://localhost:3000/test-webhook \\\\\n -H \"Content-Type: application/json\" \\\\\n -d '{\"message\":\"test from curl\",\"sessionId\":\"web_test\"}')",
|
|
101
|
+
"Bash(curl -s http://localhost:3000/test 2>&1 || echo \"Connection failed\")",
|
|
102
|
+
"Bash(curl -s -X POST http://localhost:3000/webhook/test-webhook \\\\\n -H \"Content-Type: application/json\" \\\\\n -d '{\"message\":\"test from curl\",\"sessionId\":\"web_test\"}')",
|
|
103
|
+
"Bash(curl -s http://localhost:3000/webui/status)",
|
|
104
|
+
"Bash(curl -s http://localhost:3000/test)",
|
|
105
|
+
"Bash(curl -s -v -X POST http://localhost:3000/test-webhook \\\\\n -H \"Content-Type: application/json\" \\\\\n -d '{\"message\":\"test\"}' 2>&1 | head -30)",
|
|
106
|
+
"Bash(curl -s -X POST \"http://localhost:3000/webhook/test-webhook\" \\\\\n -H \"Content-Type: application/json\" \\\\\n -d '{\"message\":\"test\"}' 2>&1)",
|
|
107
|
+
"Bash(curl -s http://localhost:3000/webui/ 2>&1)",
|
|
108
|
+
"Bash(curl -s -X POST http://localhost:3000/webui/list-routes \\\\\n -H \"Content-Type: application/json\" \\\\\n -d '{}' 2>&1 || echo \"Endpoint not found\")",
|
|
109
|
+
"Bash(curl -s http://localhost:3000/ 2>&1)",
|
|
110
|
+
"Bash(curl -s -X POST \"http://localhost:3000/webhook/test-webhook\" \\\\\n -H \"Content-Type: application/json\" \\\\\n -d '{\"message\":\"test with prefix\"}')",
|
|
111
|
+
"Bash(netstat -ano | grep :3000 | head -5)",
|
|
112
|
+
"Bash(netstat -ano | grep :3000 | grep LISTENING)",
|
|
113
|
+
"Bash(curl -s -X POST http://localhost:3000/test-webhook \\\\\n -H \"Content-Type: application/json\" \\\\\n -d '{\"message\":\"test\",\"sessionId\":\"web_test\"}')",
|
|
114
|
+
"Bash(taskkill /F /IM node.exe 2>/dev/null; sleep 1; echo \"Node processes killed\")",
|
|
115
|
+
"Bash(netstat -ano | grep :3000)",
|
|
116
|
+
"Bash(taskkill //F //PID 19848)",
|
|
117
|
+
"Bash(curl -s -X POST \"http://localhost:3000/webhook/075s5s2umn4smn4f\" \\\\\n -H \"Content-Type: application/json\" \\\\\n -d '{\"test\":\"data\"}' 2>&1)",
|
|
118
|
+
"Bash(curl -s http://localhost:3000/api/hello 2>&1)",
|
|
119
|
+
"Bash(curl -v -X POST \"http://localhost:3000/webhook/075s5s2umn4smn4f\" \\\\\n -H \"Content-Type: application/json\" \\\\\n -d '{\"test\":\"data\"}' 2>&1 | head -30)",
|
|
120
|
+
"Bash(cd D:/code/vb-agent && timeout 30 node test-compression.js 2>&1)",
|
|
121
|
+
"Bash(cd D:/code/vb-agent && node -c src/core/agent-chat.js 2>&1)",
|
|
122
|
+
"Bash(cd D:/code/vb-agent && node -e \"require\\('./src/core/agent-chat.js'\\); console.log\\('模块加载成功'\\)\" 2>&1)",
|
|
123
|
+
"Bash(cd D:/code/vb-agent && node -e \"require\\('./src/core/agent.js'\\); console.log\\('Agent 加载成功'\\)\" 2>&1)",
|
|
124
|
+
"Bash(node -c src/capabilities/skill-manager.js && node -c src/executors/mcp-executor.js && node -c src/capabilities/workflow-engine.js && node -c src/core/plugin-manager.js 2>&1)",
|
|
125
|
+
"Bash(node -c src/core/plugin-manager.js && node -c plugins/tools-plugin.js 2>&1)",
|
|
126
|
+
"Bash(node -c plugins/default-plugins.js && node -c cli/src/commands/chat.js 2>&1)",
|
|
127
|
+
"Bash(node -c plugins/telegram-plugin.js && node -c plugins/feishu-plugin.js && node -c plugins/weixin-plugin.js 2>&1)",
|
|
128
|
+
"Bash(node -c src/core/agent.js 2>&1)"
|
|
129
|
+
]
|
|
130
|
+
}
|
|
131
|
+
}
|
package/Dockerfile
CHANGED
|
@@ -3,15 +3,43 @@
|
|
|
3
3
|
|
|
4
4
|
FROM node:25-slim
|
|
5
5
|
|
|
6
|
-
#
|
|
6
|
+
# 安装无头浏览器(Chromium)和构建工具
|
|
7
7
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
8
8
|
build-essential \
|
|
9
9
|
python3 \
|
|
10
10
|
python3-pip \
|
|
11
11
|
curl \
|
|
12
12
|
git \
|
|
13
|
+
wget \
|
|
14
|
+
gnupg \
|
|
15
|
+
# Chromium 及依赖
|
|
16
|
+
chromium \
|
|
17
|
+
chromium-sandbox \
|
|
18
|
+
libnss3 \
|
|
19
|
+
libatk1.0-0 \
|
|
20
|
+
libatk-bridge2.0-0 \
|
|
21
|
+
libcups2 \
|
|
22
|
+
libdrm2 \
|
|
23
|
+
libxkbcommon0 \
|
|
24
|
+
libxcomposite1 \
|
|
25
|
+
libxdamage1 \
|
|
26
|
+
libxfixes3 \
|
|
27
|
+
libxrandr2 \
|
|
28
|
+
libgbm1 \
|
|
29
|
+
libasound2 \
|
|
30
|
+
libpango-1.0-0 \
|
|
31
|
+
libpangocairo-1.0-0 \
|
|
32
|
+
libgtk-3-0 \
|
|
33
|
+
fonts-liberation \
|
|
34
|
+
xdg-utils \
|
|
13
35
|
&& rm -rf /var/lib/apt/lists/* \
|
|
14
|
-
&& ln -sf /usr/bin/python3 /usr/bin/python
|
|
36
|
+
&& ln -sf /usr/bin/python3 /usr/bin/python \
|
|
37
|
+
&& ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
|
|
38
|
+
|
|
39
|
+
# 设置 Chromium 环境变量(无头模式运行)
|
|
40
|
+
ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium
|
|
41
|
+
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true
|
|
42
|
+
ENV CHROME_BIN=/usr/bin/chromium
|
|
15
43
|
|
|
16
44
|
# 安装 uv(快速的 Python 包管理器)
|
|
17
45
|
RUN curl -LsSf https://astral.sh/uv/install.sh | sh
|
package/package.json
CHANGED
package/plugins/ai-plugin.js
CHANGED
package/plugins/audit-plugin.js
CHANGED
|
@@ -170,6 +170,7 @@ class DefaultPlugins extends Plugin {
|
|
|
170
170
|
this.version = '1.0.0'
|
|
171
171
|
this.description = '默认插件配置加载器'
|
|
172
172
|
this.priority = 0 // 最先加载
|
|
173
|
+
this.system = true
|
|
173
174
|
|
|
174
175
|
this._framework = null
|
|
175
176
|
this._agentDir = config.agentDir || '.agent'
|
|
@@ -231,15 +232,23 @@ async function bootstrapDefaults(framework, config = {}) {
|
|
|
231
232
|
'python-plugin-loader', 'telegram', 'weixin', 'subagent-manager'
|
|
232
233
|
])
|
|
233
234
|
|
|
234
|
-
//
|
|
235
|
-
|
|
235
|
+
// 辅助函数:检查插件是否应该加载
|
|
236
|
+
// 传入插件名称(字符串)、已创建的实例,或插件类
|
|
237
|
+
const shouldLoad = (plugin) => {
|
|
238
|
+
const name = typeof plugin === 'string' ? plugin : (plugin.name || plugin.prototype?.name)
|
|
236
239
|
if (framework.pluginManager.has(name)) {
|
|
237
240
|
console.log(`[Bootstrap] ${name} Plugin already loaded, skipping`)
|
|
238
241
|
return false
|
|
239
242
|
}
|
|
240
|
-
//
|
|
241
|
-
|
|
242
|
-
|
|
243
|
+
// 系统插件(system: true)不能禁用
|
|
244
|
+
let isSystem = false
|
|
245
|
+
if (typeof plugin === 'function') {
|
|
246
|
+
isSystem = plugin.prototype?.system === true
|
|
247
|
+
} else if (typeof plugin === 'object') {
|
|
248
|
+
isSystem = plugin.system === true
|
|
249
|
+
}
|
|
250
|
+
if (isSystem && framework.pluginManager.isEnabled(name) === false) {
|
|
251
|
+
console.log(`[Bootstrap] ${name} is a system plugin, cannot be disabled`)
|
|
243
252
|
}
|
|
244
253
|
return true
|
|
245
254
|
}
|
|
@@ -615,14 +624,9 @@ async function loadCustomPlugins(framework, agentConfig) {
|
|
|
615
624
|
continue
|
|
616
625
|
}
|
|
617
626
|
|
|
618
|
-
// 如果插件被禁用(在 state 文件中 enabled: false),跳过
|
|
619
|
-
if (framework.pluginManager.isEnabled(resolvedPluginName) === false) {
|
|
620
|
-
console.log(`[Bootstrap] Custom plugin '${resolvedPluginName}' is disabled, skipping`)
|
|
621
|
-
continue
|
|
622
|
-
}
|
|
623
|
-
|
|
624
627
|
console.log(`[Bootstrap] Loading custom plugin: ${pluginName} (${type})`)
|
|
625
|
-
|
|
628
|
+
// .agent/plugins 目录下的插件强制启用,不受 state 文件 enabled: false 影响
|
|
629
|
+
await framework.pluginManager.load(plugin, { forceEnabled: true })
|
|
626
630
|
} catch (err) {
|
|
627
631
|
console.error(`[Bootstrap] Failed to load plugin ${pluginName}:`, err.message)
|
|
628
632
|
}
|
package/plugins/rules-plugin.js
CHANGED
|
@@ -36,7 +36,8 @@ class RulesPlugin extends Plugin {
|
|
|
36
36
|
this.version = '1.0.0'
|
|
37
37
|
this.description = '规则引擎插件,用于控制工具调用权限、内容过滤、触发动作'
|
|
38
38
|
this.priority = 25
|
|
39
|
-
|
|
39
|
+
this.system = true
|
|
40
|
+
|
|
40
41
|
this.config = {
|
|
41
42
|
rulesDir: config.rulesDir || '.agent/rules',
|
|
42
43
|
autoLoad: config.autoLoad !== false
|
|
@@ -17,6 +17,8 @@ class SubAgentPlugin extends Plugin {
|
|
|
17
17
|
this.description = config.description || `子Agent: ${config.name}`
|
|
18
18
|
this.priority = 10
|
|
19
19
|
|
|
20
|
+
this.system = true
|
|
21
|
+
|
|
20
22
|
// 子Agent配置
|
|
21
23
|
// tools: { toolName: toolFn } 自定义工具(只属于此子Agent)
|
|
22
24
|
// parentTools: ['read_file'] 从父Agent继承的工具名称列表
|
package/plugins/tools-plugin.js
CHANGED
|
@@ -13,6 +13,8 @@ class ToolsPlugin extends Plugin {
|
|
|
13
13
|
this.version = '1.0.0'
|
|
14
14
|
this.description = '内置工具插件,提供热重载和工具管理功能'
|
|
15
15
|
this.priority = 10
|
|
16
|
+
|
|
17
|
+
this.system = true
|
|
16
18
|
|
|
17
19
|
this._framework = null
|
|
18
20
|
}
|
|
@@ -74,7 +76,8 @@ class ToolsPlugin extends Plugin {
|
|
|
74
76
|
name: p.name,
|
|
75
77
|
status: p.status,
|
|
76
78
|
enabled: p.enabled,
|
|
77
|
-
version: p.version
|
|
79
|
+
version: p.version,
|
|
80
|
+
system: p.system
|
|
78
81
|
}))
|
|
79
82
|
}
|
|
80
83
|
}
|
package/plugins/web-plugin.js
CHANGED
|
@@ -18,6 +18,8 @@ class WebPlugin extends Plugin {
|
|
|
18
18
|
this.description = 'Web 服务插件,支持 HTTP 服务、路由注册、Webhook'
|
|
19
19
|
this.priority = 50
|
|
20
20
|
|
|
21
|
+
this.system = true
|
|
22
|
+
|
|
21
23
|
// 服务器配置
|
|
22
24
|
this._port = process.env.WEB_PORT || 3000
|
|
23
25
|
this._host = process.env.WEB_HOST || '127.0.0.1'
|
|
@@ -94,7 +96,12 @@ class WebPlugin extends Plugin {
|
|
|
94
96
|
inputSchema: z.object({
|
|
95
97
|
method: z.enum(['GET', 'POST', 'PUT', 'DELETE', 'PATCH']).describe('HTTP 方法'),
|
|
96
98
|
path: z.string().describe('路由路径,如 /api/user'),
|
|
97
|
-
handler: z.string().describe(
|
|
99
|
+
handler: z.string().describe(
|
|
100
|
+
'处理逻辑,JavaScript 代码字符串,必须用 return 返回内容。' +
|
|
101
|
+
'优先使用 tools.{toolName}(args) 调用工具获取真实数据。' +
|
|
102
|
+
'可用变量:context.params, context.query, context.body, tools。' +
|
|
103
|
+
'示例:return await tools.get_user({ id: context.params.id })'
|
|
104
|
+
),
|
|
98
105
|
description: z.string().optional().describe('路由描述')
|
|
99
106
|
}),
|
|
100
107
|
execute: async (args) => this._registerRoute(args.method, args.path, args.handler, args.description)
|
|
@@ -259,7 +266,21 @@ class WebPlugin extends Plugin {
|
|
|
259
266
|
const body = await this._parseBody(c)
|
|
260
267
|
|
|
261
268
|
const context = { params, query, body }
|
|
262
|
-
|
|
269
|
+
|
|
270
|
+
// 构建 tools 代理对象,允许 handler 以函数方式直接调用工具
|
|
271
|
+
// 例如: const user = await tools.get_user({ id: 1 })
|
|
272
|
+
const registry = this._framework.toolRegistry
|
|
273
|
+
const tools = new Proxy({}, {
|
|
274
|
+
get: (_, name) => {
|
|
275
|
+
if (name === 'call') {
|
|
276
|
+
// 保留 call 方式作为后备
|
|
277
|
+
return async (toolName, args) => registry.execute(toolName, args || {}, this._framework)
|
|
278
|
+
}
|
|
279
|
+
return async (args) => registry.execute(name, args || {}, this._framework)
|
|
280
|
+
}
|
|
281
|
+
})
|
|
282
|
+
|
|
283
|
+
const result = await this._executeHandler(route.handler, context, tools)
|
|
263
284
|
return c.json(result)
|
|
264
285
|
}
|
|
265
286
|
|
|
@@ -508,10 +529,10 @@ class WebPlugin extends Plugin {
|
|
|
508
529
|
return `http://${this._host}:${this._port}${path}`
|
|
509
530
|
}
|
|
510
531
|
|
|
511
|
-
async _executeHandler(handlerCode, context) {
|
|
532
|
+
async _executeHandler(handlerCode, context, tools) {
|
|
512
533
|
try {
|
|
513
|
-
const fn = new Function('context', `return (async () => { ${handlerCode} })()`)
|
|
514
|
-
return await fn(context)
|
|
534
|
+
const fn = new Function('context', 'tools', `return (async () => { ${handlerCode} })()`)
|
|
535
|
+
return await fn(context, tools)
|
|
515
536
|
} catch (err) {
|
|
516
537
|
return { success: false, error: `Handler error: ${err.message}` }
|
|
517
538
|
}
|
|
@@ -131,6 +131,7 @@ class SkillManagerPlugin extends Plugin {
|
|
|
131
131
|
this.version = '1.0.0'
|
|
132
132
|
this.description = '技能管理器,加载和管理 Skill'
|
|
133
133
|
this.priority = 5
|
|
134
|
+
this.system = true
|
|
134
135
|
|
|
135
136
|
this._framework = null
|
|
136
137
|
this._skillsDirs = Array.isArray(config.skillsDirs) ? config.skillsDirs : [config.skillsDir || '.agent/skills', 'skills']
|
package/src/core/agent.js
CHANGED
|
@@ -241,9 +241,36 @@ class Agent extends EventEmitter {
|
|
|
241
241
|
parts.push(capabilitiesDesc)
|
|
242
242
|
}
|
|
243
243
|
|
|
244
|
+
// 8. 工具调用核心规则(统一追加到所有 Agent)
|
|
245
|
+
const toolCoreRules = this._getToolCoreRules()
|
|
246
|
+
if (toolCoreRules) {
|
|
247
|
+
parts.push(toolCoreRules)
|
|
248
|
+
}
|
|
249
|
+
|
|
244
250
|
return parts.join('\n\n')
|
|
245
251
|
}
|
|
246
252
|
|
|
253
|
+
/**
|
|
254
|
+
* 获取工具调用核心规则
|
|
255
|
+
* @private
|
|
256
|
+
*/
|
|
257
|
+
_getToolCoreRules() {
|
|
258
|
+
return `【工具调用核心规则】
|
|
259
|
+
1. 当用户询问需要获取数据、信息或执行操作时,必须调用工具
|
|
260
|
+
2. 不要编造、推测数据,必须调用工具获取真实信息
|
|
261
|
+
3. 直接调用工具后,基于返回结果回答
|
|
262
|
+
|
|
263
|
+
【工具使用】
|
|
264
|
+
- 可用工具会提供,格式为 toolName(toolArgs)
|
|
265
|
+
- 如果不确定用哪个工具,先调用可能相关的工具
|
|
266
|
+
- 工具调用会返回结果,基于结果回答用户
|
|
267
|
+
|
|
268
|
+
【禁止事项】
|
|
269
|
+
- 不要回复"我需要..."、"我建议..."等模糊回答
|
|
270
|
+
- 不要在没有调用工具的情况下给出数据或答案
|
|
271
|
+
- 不要自己编造用户、订单、任务等任何数据`
|
|
272
|
+
}
|
|
273
|
+
|
|
247
274
|
/**
|
|
248
275
|
* 刷新上下文
|
|
249
276
|
*/
|
package/src/core/plugin-base.js
CHANGED
|
@@ -36,19 +36,33 @@ class PluginManager {
|
|
|
36
36
|
*/
|
|
37
37
|
_saveState() {
|
|
38
38
|
try {
|
|
39
|
-
const
|
|
39
|
+
const stateFile = this._getStateFile()
|
|
40
|
+
// 读取现有状态(如果存在),保留原有内容
|
|
41
|
+
let state = {}
|
|
42
|
+
if (fs.existsSync(stateFile)) {
|
|
43
|
+
try {
|
|
44
|
+
state = JSON.parse(fs.readFileSync(stateFile, 'utf-8'))
|
|
45
|
+
} catch (e) {
|
|
46
|
+
// 文件损坏,使用空对象
|
|
47
|
+
state = {}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// 合并新状态到现有状态
|
|
40
52
|
for (const [name, entry] of this._plugins) {
|
|
41
53
|
// AI 配置不保存,每次从环境变量和命令行获取
|
|
42
54
|
if (name === 'ai') {
|
|
43
55
|
state[name] = { enabled: entry.enabled }
|
|
44
56
|
} else {
|
|
45
57
|
state[name] = {
|
|
58
|
+
...(state[name] || {}), // 保留现有配置
|
|
46
59
|
enabled: entry.enabled,
|
|
47
60
|
config: entry.instance?.config || {}
|
|
48
61
|
}
|
|
49
62
|
}
|
|
50
63
|
}
|
|
51
|
-
|
|
64
|
+
|
|
65
|
+
fs.writeFileSync(stateFile, JSON.stringify(state, null, 2))
|
|
52
66
|
} catch (err) {
|
|
53
67
|
console.error('[PluginManager] Failed to save state:', err.message)
|
|
54
68
|
}
|
|
@@ -75,7 +89,7 @@ class PluginManager {
|
|
|
75
89
|
* 注册插件(不加载)
|
|
76
90
|
* @param {Plugin|Object} plugin - 插件实例或定义
|
|
77
91
|
*/
|
|
78
|
-
register(plugin) {
|
|
92
|
+
register(plugin, options = {}) {
|
|
79
93
|
if (!plugin.name) {
|
|
80
94
|
throw new Error('Plugin must have a name')
|
|
81
95
|
}
|
|
@@ -96,13 +110,21 @@ class PluginManager {
|
|
|
96
110
|
pluginInstance.config = { ...pluginInstance.config, ...savedConfig }
|
|
97
111
|
}
|
|
98
112
|
|
|
99
|
-
//
|
|
100
|
-
|
|
113
|
+
// 系统插件强制启用,不能禁用
|
|
114
|
+
// 普通插件:state 文件有记录则用 state,否则用插件默认配置
|
|
115
|
+
let enabled
|
|
116
|
+
if (pluginInstance.system) {
|
|
117
|
+
enabled = true
|
|
118
|
+
} else if (savedEnabled !== undefined) {
|
|
119
|
+
enabled = savedEnabled
|
|
120
|
+
} else {
|
|
121
|
+
enabled = pluginInstance.enabled !== undefined ? pluginInstance.enabled : true
|
|
122
|
+
}
|
|
101
123
|
|
|
102
124
|
this._plugins.set(pluginInstance.name, {
|
|
103
125
|
instance: pluginInstance,
|
|
104
126
|
status: 'registered',
|
|
105
|
-
enabled
|
|
127
|
+
enabled
|
|
106
128
|
})
|
|
107
129
|
|
|
108
130
|
this.framework.emit('plugin:registered', pluginInstance)
|
|
@@ -112,8 +134,10 @@ class PluginManager {
|
|
|
112
134
|
/**
|
|
113
135
|
* 加载插件
|
|
114
136
|
* @param {Plugin|Object} plugin - 插件实例或定义
|
|
137
|
+
* @param {Object} options - 加载选项
|
|
138
|
+
* @param {boolean} options.forceEnabled - 强制启用插件,忽略 state 文件的 disabled 状态(用于 .agent/plugins 目录的插件)
|
|
115
139
|
*/
|
|
116
|
-
async load(plugin) {
|
|
140
|
+
async load(plugin, options = {}) {
|
|
117
141
|
if (this._loading) {
|
|
118
142
|
throw new Error('Cannot load plugin during another load operation')
|
|
119
143
|
}
|
|
@@ -158,11 +182,17 @@ class PluginManager {
|
|
|
158
182
|
}
|
|
159
183
|
} else {
|
|
160
184
|
// 未注册,先注册
|
|
161
|
-
this.register(pluginInstance)
|
|
185
|
+
this.register(pluginInstance, options)
|
|
162
186
|
}
|
|
163
187
|
|
|
164
188
|
const entry = this._plugins.get(pluginInstance.name)
|
|
165
189
|
|
|
190
|
+
// 注册后再次检查 enabled 状态
|
|
191
|
+
if (!entry.enabled) {
|
|
192
|
+
console.log(`[PluginManager] Plugin '${pluginInstance.name}' is disabled, skipping install`)
|
|
193
|
+
return pluginInstance
|
|
194
|
+
}
|
|
195
|
+
|
|
166
196
|
// 调用 install
|
|
167
197
|
try {
|
|
168
198
|
await entry.instance.install(this.framework)
|
|
@@ -190,6 +220,10 @@ class PluginManager {
|
|
|
190
220
|
}
|
|
191
221
|
|
|
192
222
|
this.framework.emit('plugin:loaded', pluginInstance)
|
|
223
|
+
|
|
224
|
+
// 保存状态(创建或更新 state 文件)
|
|
225
|
+
this._saveState()
|
|
226
|
+
|
|
193
227
|
return pluginInstance
|
|
194
228
|
} finally {
|
|
195
229
|
this._loading = false
|
|
@@ -410,7 +444,8 @@ class PluginManager {
|
|
|
410
444
|
}
|
|
411
445
|
|
|
412
446
|
console.log(`[PluginManager] Loading new plugin: ${pluginName} (${type})`)
|
|
413
|
-
|
|
447
|
+
// .agent/plugins 目录下的插件默认强制启用,不受 state 文件影响
|
|
448
|
+
await this.load(plugin, { forceEnabled: true })
|
|
414
449
|
} catch (err) {
|
|
415
450
|
console.error(`[PluginManager] Failed to load plugin ${pluginName}:`, err.message)
|
|
416
451
|
}
|
|
@@ -464,7 +499,8 @@ class PluginManager {
|
|
|
464
499
|
name,
|
|
465
500
|
status: entry?.status || 'unknown',
|
|
466
501
|
enabled: entry?.enabled || false,
|
|
467
|
-
version: entry?.instance?.version
|
|
502
|
+
version: entry?.instance?.version,
|
|
503
|
+
system: entry?.instance?.system || false
|
|
468
504
|
})
|
|
469
505
|
}
|
|
470
506
|
// 也加入已加载但不在 knownPlugins 中的
|
|
@@ -474,7 +510,8 @@ class PluginManager {
|
|
|
474
510
|
name,
|
|
475
511
|
status: entry.status,
|
|
476
512
|
enabled: entry.enabled,
|
|
477
|
-
version: entry.instance?.version
|
|
513
|
+
version: entry.instance?.version,
|
|
514
|
+
system: entry.instance?.system || false
|
|
478
515
|
})
|
|
479
516
|
}
|
|
480
517
|
}
|
|
@@ -515,6 +552,11 @@ class PluginManager {
|
|
|
515
552
|
throw new Error(`Plugin '${name}' not found`)
|
|
516
553
|
}
|
|
517
554
|
|
|
555
|
+
// 系统插件不能被禁用,所以启用没有意义
|
|
556
|
+
if (entry.instance?.system) {
|
|
557
|
+
throw new Error(`Plugin '${name}' is a system plugin, cannot be disabled`)
|
|
558
|
+
}
|
|
559
|
+
|
|
518
560
|
if (entry.enabled) {
|
|
519
561
|
console.log(`[PluginManager] Plugin '${name}' already enabled`)
|
|
520
562
|
return
|
|
@@ -566,6 +608,11 @@ class PluginManager {
|
|
|
566
608
|
throw new Error(`Plugin '${name}' not found`)
|
|
567
609
|
}
|
|
568
610
|
|
|
611
|
+
// 系统插件不能被禁用
|
|
612
|
+
if (entry.instance?.system) {
|
|
613
|
+
throw new Error(`Plugin '${name}' is a system plugin, cannot be disabled`)
|
|
614
|
+
}
|
|
615
|
+
|
|
569
616
|
if (!entry.enabled) {
|
|
570
617
|
console.log(`[PluginManager] Plugin '${name}' already disabled`)
|
|
571
618
|
return
|
|
@@ -193,6 +193,7 @@ class MCPExecutorPlugin extends Plugin {
|
|
|
193
193
|
this.version = '1.0.0'
|
|
194
194
|
this.description = 'MCP (Model Context Protocol) 执行器'
|
|
195
195
|
this.priority = 11
|
|
196
|
+
this.system = true
|
|
196
197
|
|
|
197
198
|
this._framework = null
|
|
198
199
|
// serverName -> { client, tools: [{ name, description, inputSchema }], toolObjects: { toolName: actualTool } }
|