foliko 1.0.85 → 1.0.87

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 (178) hide show
  1. package/.agent/agents/code-assistant.json +14 -0
  2. package/.agent/agents/email-assistant.json +14 -0
  3. package/.agent/agents/file-assistant.json +15 -0
  4. package/.agent/agents/system-assistant.json +15 -0
  5. package/.agent/agents/web-assistant.json +12 -0
  6. package/.agent/data/ambient/goals.json +50 -0
  7. package/.agent/data/ambient/memories.json +7 -0
  8. package/.agent/data/default.json +21 -311
  9. package/.agent/data/plugins-state.json +162 -174
  10. package/.agent/data/scheduler/tasks.json +1 -0
  11. package/.agent/data/weixin.json +6 -0
  12. package/.agent/mcp_config.json +1 -0
  13. package/.agent/package.json +8 -0
  14. package/.agent/plugins/__pycache__/test_plugin.cpython-312.pyc +0 -0
  15. package/.agent/plugins/daytona/README.md +89 -0
  16. package/.agent/plugins/daytona/index.js +377 -0
  17. package/.agent/plugins/daytona/package.json +12 -0
  18. package/.agent/plugins/marknative/README.md +134 -0
  19. package/.agent/plugins/marknative/index.js +228 -0
  20. package/.agent/plugins/marknative/package.json +12 -0
  21. package/.agent/plugins/marknative/update-readme.js +134 -0
  22. package/.agent/plugins/system-info/index.js +387 -0
  23. package/.agent/plugins/system-info/package.json +4 -0
  24. package/.agent/plugins/system-info/test.js +40 -0
  25. package/.agent/plugins/temp-repo/LICENSE +201 -0
  26. package/.agent/plugins/test_plugin.py +304 -0
  27. package/.agent/plugins.json +14 -5
  28. package/.agent/python-scripts/test_sample.py +24 -0
  29. package/.agent/skills/agent-browser/SKILL.md +311 -0
  30. package/.agent/skills/agent-browser/TEST_PLAN.md +200 -0
  31. package/.agent/skills/sysinfo/SKILL.md +38 -0
  32. package/.agent/skills/sysinfo/system-info.sh +130 -0
  33. package/.agent/skills/workflow/SKILL.md +324 -0
  34. package/.agent/workflows/email-digest.json +50 -0
  35. package/.agent/workflows/file-backup.json +21 -0
  36. package/.agent/workflows/get-ip-notify.json +32 -0
  37. package/.agent/workflows/news-aggregator.json +93 -0
  38. package/.agent/workflows/news-dashboard-v2.json +94 -0
  39. package/.agent/workflows/notification-batch.json +32 -0
  40. package/.claude/settings.local.json +8 -7
  41. package/.env.example +56 -56
  42. package/README.md +441 -441
  43. package/examples/test-chat-debug.js +102 -0
  44. package/examples/test-chat-result.js +76 -0
  45. package/examples/test-chat-stream-diff.js +63 -0
  46. package/examples/test-concurrent-chat.js +60 -0
  47. package/examples/test-long-chat.js +77 -0
  48. package/examples/test-session-chat.js +93 -0
  49. package/package.json +2 -2
  50. package/plugins/ambient-agent/EventWatcher.js +4 -4
  51. package/plugins/extension-executor-plugin.js +44 -1
  52. package/plugins/file-system-plugin.js +44 -5
  53. package/plugins/session-plugin.js +21 -0
  54. package/plugins/weixin-plugin.js +278 -29
  55. package/skills/find-skills/AGENTS.md +162 -162
  56. package/skills/find-skills/SKILL.md +133 -133
  57. package/skills/foliko-dev/SKILL.md +67 -0
  58. package/skills/python-plugin-dev/SKILL.md +238 -238
  59. package/src/core/agent-chat.js +106 -58
  60. package/src/core/agent.js +3 -61
  61. package/src/utils/index.js +1 -1
  62. package/.agent/.shared/ui-ux-pro-max/data/charts.csv +0 -26
  63. package/.agent/.shared/ui-ux-pro-max/data/colors.csv +0 -97
  64. package/.agent/.shared/ui-ux-pro-max/data/icons.csv +0 -101
  65. package/.agent/.shared/ui-ux-pro-max/data/landing.csv +0 -31
  66. package/.agent/.shared/ui-ux-pro-max/data/products.csv +0 -97
  67. package/.agent/.shared/ui-ux-pro-max/data/prompts.csv +0 -24
  68. package/.agent/.shared/ui-ux-pro-max/data/react-performance.csv +0 -45
  69. package/.agent/.shared/ui-ux-pro-max/data/stacks/flutter.csv +0 -53
  70. package/.agent/.shared/ui-ux-pro-max/data/stacks/html-tailwind.csv +0 -56
  71. package/.agent/.shared/ui-ux-pro-max/data/stacks/jetpack-compose.csv +0 -53
  72. package/.agent/.shared/ui-ux-pro-max/data/stacks/nextjs.csv +0 -53
  73. package/.agent/.shared/ui-ux-pro-max/data/stacks/nuxt-ui.csv +0 -51
  74. package/.agent/.shared/ui-ux-pro-max/data/stacks/nuxtjs.csv +0 -59
  75. package/.agent/.shared/ui-ux-pro-max/data/stacks/react-native.csv +0 -52
  76. package/.agent/.shared/ui-ux-pro-max/data/stacks/react.csv +0 -54
  77. package/.agent/.shared/ui-ux-pro-max/data/stacks/shadcn.csv +0 -61
  78. package/.agent/.shared/ui-ux-pro-max/data/stacks/svelte.csv +0 -54
  79. package/.agent/.shared/ui-ux-pro-max/data/stacks/swiftui.csv +0 -51
  80. package/.agent/.shared/ui-ux-pro-max/data/stacks/vue.csv +0 -50
  81. package/.agent/.shared/ui-ux-pro-max/data/styles.csv +0 -59
  82. package/.agent/.shared/ui-ux-pro-max/data/typography.csv +0 -58
  83. package/.agent/.shared/ui-ux-pro-max/data/ui-reasoning.csv +0 -101
  84. package/.agent/.shared/ui-ux-pro-max/data/ux-guidelines.csv +0 -100
  85. package/.agent/.shared/ui-ux-pro-max/data/web-interface.csv +0 -31
  86. package/.agent/.shared/ui-ux-pro-max/scripts/__pycache__/core.cpython-313.pyc +0 -0
  87. package/.agent/.shared/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-313.pyc +0 -0
  88. package/.agent/.shared/ui-ux-pro-max/scripts/core.py +0 -258
  89. package/.agent/.shared/ui-ux-pro-max/scripts/design_system.py +0 -1067
  90. package/.agent/.shared/ui-ux-pro-max/scripts/search.py +0 -106
  91. package/.agent/ARCHITECTURE.md +0 -288
  92. package/.agent/agents/ambient-agent.md +0 -57
  93. package/.agent/agents/debugger.md +0 -55
  94. package/.agent/agents/email-assistant.md +0 -49
  95. package/.agent/agents/file-manager.md +0 -42
  96. package/.agent/agents/python-developer.md +0 -60
  97. package/.agent/agents/scheduler.md +0 -59
  98. package/.agent/agents/web-developer.md +0 -45
  99. package/.agent/data/puppeteer-sessions/undefined.json +0 -6
  100. package/.agent/mcp_config_updated.json +0 -12
  101. package/.agent/rules/GEMINI.md +0 -273
  102. package/.agent/rules/allow-rule.md +0 -77
  103. package/.agent/rules/log-rule.md +0 -83
  104. package/.agent/rules/security-rule.md +0 -93
  105. package/.agent/scripts/auto_preview.py +0 -148
  106. package/.agent/scripts/checklist.py +0 -217
  107. package/.agent/scripts/session_manager.py +0 -120
  108. package/.agent/scripts/verify_all.py +0 -327
  109. package/.agent/skills/api-patterns/SKILL.md +0 -81
  110. package/.agent/skills/api-patterns/api-style.md +0 -42
  111. package/.agent/skills/api-patterns/auth.md +0 -24
  112. package/.agent/skills/api-patterns/documentation.md +0 -26
  113. package/.agent/skills/api-patterns/graphql.md +0 -41
  114. package/.agent/skills/api-patterns/rate-limiting.md +0 -31
  115. package/.agent/skills/api-patterns/response.md +0 -37
  116. package/.agent/skills/api-patterns/rest.md +0 -40
  117. package/.agent/skills/api-patterns/scripts/api_validator.py +0 -211
  118. package/.agent/skills/api-patterns/security-testing.md +0 -122
  119. package/.agent/skills/api-patterns/trpc.md +0 -41
  120. package/.agent/skills/api-patterns/versioning.md +0 -22
  121. package/.agent/skills/app-builder/SKILL.md +0 -75
  122. package/.agent/skills/app-builder/agent-coordination.md +0 -71
  123. package/.agent/skills/app-builder/feature-building.md +0 -53
  124. package/.agent/skills/app-builder/project-detection.md +0 -34
  125. package/.agent/skills/app-builder/scaffolding.md +0 -118
  126. package/.agent/skills/app-builder/tech-stack.md +0 -40
  127. package/.agent/skills/app-builder/templates/SKILL.md +0 -39
  128. package/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +0 -76
  129. package/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +0 -92
  130. package/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +0 -88
  131. package/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +0 -88
  132. package/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +0 -83
  133. package/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +0 -90
  134. package/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +0 -90
  135. package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +0 -122
  136. package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +0 -122
  137. package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +0 -169
  138. package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +0 -134
  139. package/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +0 -83
  140. package/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +0 -119
  141. package/.agent/skills/architecture/SKILL.md +0 -55
  142. package/.agent/skills/architecture/context-discovery.md +0 -43
  143. package/.agent/skills/architecture/examples.md +0 -94
  144. package/.agent/skills/architecture/pattern-selection.md +0 -68
  145. package/.agent/skills/architecture/patterns-reference.md +0 -50
  146. package/.agent/skills/architecture/trade-off-analysis.md +0 -77
  147. package/.agent/skills/clean-code/SKILL.md +0 -201
  148. package/.agent/skills/doc.md +0 -177
  149. package/.agent/skills/frontend-design/SKILL.md +0 -418
  150. package/.agent/skills/frontend-design/animation-guide.md +0 -331
  151. package/.agent/skills/frontend-design/color-system.md +0 -311
  152. package/.agent/skills/frontend-design/decision-trees.md +0 -418
  153. package/.agent/skills/frontend-design/motion-graphics.md +0 -306
  154. package/.agent/skills/frontend-design/scripts/accessibility_checker.py +0 -183
  155. package/.agent/skills/frontend-design/scripts/ux_audit.py +0 -722
  156. package/.agent/skills/frontend-design/typography-system.md +0 -345
  157. package/.agent/skills/frontend-design/ux-psychology.md +0 -1116
  158. package/.agent/skills/frontend-design/visual-effects.md +0 -383
  159. package/.agent/skills/i18n-localization/SKILL.md +0 -154
  160. package/.agent/skills/i18n-localization/scripts/i18n_checker.py +0 -241
  161. package/.agent/skills/mcp-builder/SKILL.md +0 -176
  162. package/.agent/skills/web-design-guidelines/SKILL.md +0 -57
  163. package/.agent/workflows/brainstorm.md +0 -113
  164. package/.agent/workflows/create.md +0 -59
  165. package/.agent/workflows/debug.md +0 -103
  166. package/.agent/workflows/deploy.md +0 -176
  167. package/.agent/workflows/enhance.md +0 -63
  168. package/.agent/workflows/orchestrate.md +0 -237
  169. package/.agent/workflows/plan.md +0 -89
  170. package/.agent/workflows/preview.md +0 -81
  171. package/.agent/workflows/simple-test.md +0 -42
  172. package/.agent/workflows/status.md +0 -86
  173. package/.agent/workflows/structured-orchestrate.md +0 -180
  174. package/.agent/workflows/test.md +0 -144
  175. package/.agent/workflows/ui-ux-pro-max.md +0 -296
  176. /package/.agent/plugins/{puppeteer-plugin → temp-repo/puppeteer-plugin}/README.md +0 -0
  177. /package/.agent/plugins/{puppeteer-plugin → temp-repo/puppeteer-plugin}/index.js +0 -0
  178. /package/.agent/plugins/{puppeteer-plugin → temp-repo/puppeteer-plugin}/package.json +0 -0
@@ -0,0 +1,102 @@
1
+ /**
2
+ * chat() 持续聊天调试测试
3
+ * 专门测试 chat 方法为什么不返回数据
4
+ */
5
+
6
+ const { Framework } = require('../src');
7
+ const AIPlugin = require('../plugins/ai-plugin');
8
+ require('dotenv').config();
9
+
10
+ async function main() {
11
+ console.log('=== chat() 持续聊天调试测试 ===\n');
12
+
13
+ // 创建框架
14
+ const framework = new Framework({ debug: true });
15
+
16
+ // 使用 MiniMax (Agent SDK)
17
+ await framework.loadPlugin(
18
+ new AIPlugin({
19
+ provider: 'minimax',
20
+ model: 'MiniMax-M2.7',
21
+ apiKey: process.env.MINIMAX_API_KEY || 'your-api-key',
22
+ })
23
+ );
24
+
25
+ // 注册一个简单的测试工具
26
+ const { z } = require('zod');
27
+ framework.registerTool({
28
+ name: 'test_tool',
29
+ description: '测试工具,返回传入的参数',
30
+ inputSchema: z.object({
31
+ msg: z.string().describe('要返回的消息'),
32
+ }),
33
+ execute: async (args) => {
34
+ console.log('[DEBUG] test_tool called with:', args);
35
+ return `工具收到: ${args.msg}`;
36
+ },
37
+ });
38
+
39
+ console.log('[Framework] Ready!');
40
+ console.log('[Tools]', framework.getTools().map((t) => t.name));
41
+
42
+ // 创建 Agent
43
+ const agent = framework.createAgent({
44
+ name: 'DebugAgent',
45
+ systemPrompt: '你是一个有帮助的助手。如果用户要求使用工具,请使用工具。',
46
+ });
47
+
48
+ // 监听所有事件
49
+ agent.on('tool-call', (tool) => {
50
+ console.log('[Event] tool-call:', tool.name, tool.args);
51
+ });
52
+
53
+ agent.on('tool-result', (result) => {
54
+ console.log('[Event] tool-result:', result.name, '->', JSON.stringify(result.result).substring(0, 200));
55
+ });
56
+
57
+ agent.on('error', (err) => {
58
+ console.error('[Event] error:', err.error);
59
+ });
60
+
61
+ // 测试函数
62
+ const testChat = async (question, round) => {
63
+ console.log(`\n========== Round ${round} ==========`);
64
+ console.log(`[User] ${question}`);
65
+
66
+ try {
67
+ // 打印 result 的完整结构
68
+ const result = await agent.chat(question);
69
+ console.log(`\n[DEBUG] result keys:`, Object.keys(result));
70
+ console.log(`[DEBUG] result:`, JSON.stringify(result, null, 2).substring(0, 500));
71
+
72
+ if (result.message) {
73
+ console.log(`\n[Agent] ${result.message}`);
74
+ } else {
75
+ console.log(`\n[WARNING] result.message is empty!`);
76
+ }
77
+
78
+ // 打印当前消息历史长度
79
+ const chatHandler = agent._chatHandler;
80
+ if (chatHandler) {
81
+ console.log(`[DEBUG] _messages.length:`, chatHandler._messages.length);
82
+ console.log(`[DEBUG] compression count:`, chatHandler._compressionCount);
83
+ }
84
+ } catch (err) {
85
+ console.error(`\n[Error]`, err.message);
86
+ console.error(err.stack);
87
+ }
88
+ };
89
+
90
+ // 执行多轮测试
91
+ await testChat('你好,介绍一下你自己', 1);
92
+ await testChat('请用 test_tool 工具返回 "hello world"', 2);
93
+ await testChat('今天天气不错,你觉得呢?', 3);
94
+ await testChat('帮我计算 123 + 456 等于多少', 4);
95
+ await testChat('再说一次你的名字', 5);
96
+
97
+ console.log('\n========== 测试完成 ==========');
98
+
99
+ await framework.destroy();
100
+ }
101
+
102
+ main().catch(console.error);
@@ -0,0 +1,76 @@
1
+ /**
2
+ * 测试 chat() 返回值的完整结构
3
+ */
4
+
5
+ const { Framework } = require('../src');
6
+ const AIPlugin = require('../plugins/ai-plugin');
7
+ require('dotenv').config();
8
+
9
+ async function main() {
10
+ console.log('=== 测试 chat() 返回值结构 ===\n');
11
+
12
+ const framework = new Framework({ debug: true });
13
+
14
+ await framework.loadPlugin(
15
+ new AIPlugin({
16
+ provider: 'minimax',
17
+ model: 'MiniMax-M2.7',
18
+ apiKey: process.env.MINIMAX_API_KEY || 'your-api-key',
19
+ })
20
+ );
21
+
22
+ const { z } = require('zod');
23
+ framework.registerTool({
24
+ name: 'echo',
25
+ description: '返回输入的内容',
26
+ inputSchema: z.object({
27
+ msg: z.string().describe('要返回的消息'),
28
+ }),
29
+ execute: async (args) => {
30
+ return `工具收到: ${args.msg}`;
31
+ },
32
+ });
33
+
34
+ console.log('[Framework] Ready!');
35
+
36
+ const agent = framework.createAgent({
37
+ name: 'TestAgent',
38
+ systemPrompt: '你是一个有帮助的助手。',
39
+ });
40
+
41
+ // 测试 1:简单对话
42
+ console.log('\n--- 测试 1:简单对话 ---');
43
+ try {
44
+ const result = await agent.chat('你好');
45
+ console.log('[DEBUG] result:', JSON.stringify(result, null, 2));
46
+ console.log('[DEBUG] result 顶层 keys:', Object.keys(result));
47
+ } catch (err) {
48
+ console.error('[Error]', err.message);
49
+ }
50
+
51
+ // 测试 2:触发工具调用
52
+ console.log('\n--- 测试 2:触发工具调用 ---');
53
+ try {
54
+ const result = await agent.chat('请用 echo 工具返回 "hello"');
55
+ console.log('[DEBUG] result:', JSON.stringify(result, null, 2));
56
+ console.log('[DEBUG] result 顶层 keys:', Object.keys(result));
57
+ } catch (err) {
58
+ console.error('[Error]', err.message);
59
+ }
60
+
61
+ // 测试 3:多次对话(累积上下文)
62
+ console.log('\n--- 测试 3:多次对话 ---');
63
+ try {
64
+ await agent.chat('你好');
65
+ await agent.chat('今天天气不错');
66
+ const result = await agent.chat('我刚才说什么了?');
67
+ console.log('[DEBUG] result:', JSON.stringify(result, null, 2));
68
+ } catch (err) {
69
+ console.error('[Error]', err.message);
70
+ }
71
+
72
+ await framework.destroy();
73
+ console.log('\n[Done]');
74
+ }
75
+
76
+ main().catch(console.error);
@@ -0,0 +1,63 @@
1
+ /**
2
+ * 测试 chat 和 chatStream 的差异
3
+ */
4
+
5
+ const { Framework } = require('../src');
6
+ const AIPlugin = require('../plugins/ai-plugin');
7
+ const SessionPlugin = require('../plugins/session-plugin');
8
+ require('dotenv').config();
9
+
10
+ async function main() {
11
+ console.log('=== 测试 chat vs chatStream 差异 ===\n');
12
+
13
+ const framework = new Framework({ debug: false });
14
+
15
+ await framework.loadPlugin(
16
+ new AIPlugin({
17
+ provider: 'minimax',
18
+ model: 'MiniMax-M2.7',
19
+ apiKey: process.env.MINIMAX_API_KEY || 'your-api-key',
20
+ })
21
+ );
22
+ await framework.loadPlugin(new SessionPlugin());
23
+
24
+ const systemPrompt = `你是一个有帮助的助手。`;
25
+
26
+ const agent = framework.createAgent({
27
+ name: 'TestAgent',
28
+ systemPrompt: systemPrompt,
29
+ });
30
+
31
+ const sessionId = 'test_session';
32
+ const sessionPlugin = framework.pluginManager.get('session');
33
+ sessionPlugin.getOrCreateSession(sessionId, { metadata: {} });
34
+
35
+ // 测试 chat
36
+ console.log('--- Test 1: chat() ---');
37
+ const result1 = await agent.chat('你好,介绍一下自己', { sessionId });
38
+ console.log('chat result.message length:', result1.message?.length);
39
+ console.log('chat result.message:', result1.message?.substring(0, 100));
40
+
41
+ // 测试 chatStream
42
+ console.log('\n--- Test 2: chatStream() ---');
43
+ let streamText = '';
44
+ for await (const chunk of agent.chatStream('今天天气怎么样?', { sessionId })) {
45
+ if (chunk.type === 'text') {
46
+ streamText += chunk.text;
47
+ }
48
+ }
49
+ console.log('chatStream full text length:', streamText.length);
50
+ console.log('chatStream full text:', streamText.substring(0, 100));
51
+
52
+ // 测试更多轮对话后的 chat
53
+ console.log('\n--- Test 3: 多轮后 chat() ---');
54
+ await agent.chat('再说一次你的名字', { sessionId });
55
+ const result3 = await agent.chat('我叫什么?', { sessionId });
56
+ console.log('chat result.message length:', result3.message?.length);
57
+ console.log('chat result.message:', result3.message?.substring(0, 100));
58
+
59
+ await framework.destroy();
60
+ console.log('\n[Done]');
61
+ }
62
+
63
+ main().catch(console.error);
@@ -0,0 +1,60 @@
1
+ /**
2
+ * 测试并发 chat 调用
3
+ */
4
+
5
+ const { Framework } = require('../src');
6
+ const AIPlugin = require('../plugins/ai-plugin');
7
+ const SessionPlugin = require('../plugins/session-plugin');
8
+ require('dotenv').config();
9
+
10
+ async function main() {
11
+ console.log('=== 测试并发 chat 调用 ===\n');
12
+
13
+ const framework = new Framework({ debug: false });
14
+
15
+ await framework.loadPlugin(
16
+ new AIPlugin({
17
+ provider: 'minimax',
18
+ model: 'MiniMax-M2.7',
19
+ apiKey: process.env.MINIMAX_API_KEY || 'your-api-key',
20
+ })
21
+ );
22
+ await framework.loadPlugin(new SessionPlugin());
23
+
24
+ const systemPrompt = `你是一个微信助手。`;
25
+
26
+ // 创建一个 agent(模拟单个用户)
27
+ const agent = framework.createAgent({
28
+ name: 'WeixinAgent',
29
+ systemPrompt: systemPrompt,
30
+ });
31
+
32
+ const sessionId = 'weixin_test_user';
33
+ const sessionPlugin = framework.pluginManager.get('session');
34
+ sessionPlugin.getOrCreateSession(sessionId, { metadata: { platform: 'weixin' } });
35
+
36
+ // 模拟 3 个并发 chat 调用
37
+ console.log('\n--- 并发发送 3 条消息 ---');
38
+
39
+ const results = await Promise.all([
40
+ agent.chat('你好', { sessionId }),
41
+ agent.chat('今天天气怎么样?', { sessionId }),
42
+ agent.chat('帮我查一下天气', { sessionId }),
43
+ ]);
44
+
45
+ console.log('\n--- 结果 ---');
46
+ for (let i = 0; i < results.length; i++) {
47
+ const r = results[i];
48
+ console.log(`[${i}] message length: ${r.message?.length || 'EMPTY'}`);
49
+ console.log(`[${i}] message: ${r.message?.substring(0, 50) || 'EMPTY'}...`);
50
+ }
51
+
52
+ // 检查 _messages 状态
53
+ const chatHandler = agent._chatHandler;
54
+ console.log(`\n[DEBUG] _messages count: ${chatHandler?._messages.length}`);
55
+
56
+ await framework.destroy();
57
+ console.log('\n[Done]');
58
+ }
59
+
60
+ main().catch(console.error);
@@ -0,0 +1,77 @@
1
+ /**
2
+ * 测试长对话压缩场景
3
+ */
4
+
5
+ const { Framework } = require('../src');
6
+ const AIPlugin = require('../plugins/ai-plugin');
7
+ const SessionPlugin = require('../plugins/session-plugin');
8
+ require('dotenv').config();
9
+
10
+ async function main() {
11
+ console.log('=== 测试长对话压缩场景 ===\n');
12
+
13
+ const framework = new Framework({ debug: false });
14
+
15
+ await framework.loadPlugin(
16
+ new AIPlugin({
17
+ provider: 'minimax',
18
+ model: 'MiniMax-M2.7',
19
+ apiKey: process.env.MINIMAX_API_KEY || 'your-api-key',
20
+ })
21
+ );
22
+ await framework.loadPlugin(new SessionPlugin());
23
+
24
+ const systemPrompt = `你是一个有帮助的助手。`;
25
+
26
+ const agent = framework.createAgent({
27
+ name: 'TestAgent',
28
+ systemPrompt: systemPrompt,
29
+ });
30
+
31
+ const sessionId = 'test_session';
32
+ const sessionPlugin = framework.pluginManager.get('session');
33
+ sessionPlugin.getOrCreateSession(sessionId, { metadata: {} });
34
+
35
+ // 发送多条长消息来触发压缩
36
+ const longContent = `请详细描述以下内容:人工智能的发展历史、现状和未来趋势。包括机器学习、深度学习、自然语言处理等核心技术的发展历程,以及在各个行业中的应用场景。同时分析当前面临的挑战,如数据隐私、算法偏见、能源消耗等问题。`;
37
+
38
+ console.log('--- 发送 15 条长消息 ---');
39
+ for (let i = 1; i <= 15; i++) {
40
+ try {
41
+ const result = await agent.chat(`${longContent}\n\n[消息 ${i}]`, { sessionId });
42
+ const msgLen = result.message?.length || 0;
43
+ console.log(`[${i}] message length: ${msgLen}, success: ${result.success}`);
44
+
45
+ if (!result.message) {
46
+ console.log(`[ERROR] message is empty!`);
47
+ console.log(`[DEBUG] result:`, JSON.stringify(result, null, 2));
48
+ break;
49
+ }
50
+ } catch (err) {
51
+ console.error(`[${i}] Error:`, err.message);
52
+ }
53
+ }
54
+
55
+ // 检查压缩统计
56
+ const chatHandler = agent._chatHandler;
57
+ console.log(`\n[DEBUG] compression count: ${chatHandler?._compressionCount}`);
58
+ console.log(`[DEBUG] _messages count: ${chatHandler?._messages.length}`);
59
+
60
+ // 压缩后再发一条
61
+ console.log('\n--- 压缩后发送测试 ---');
62
+ try {
63
+ const result = await agent.chat('你好,压缩后你还认识我吗?', { sessionId });
64
+ console.log(`message length: ${result.message?.length || 0}`);
65
+ console.log(`message: ${result.message?.substring(0, 100)}`);
66
+ if (!result.message) {
67
+ console.log(`[ERROR] message is empty after compression!`);
68
+ }
69
+ } catch (err) {
70
+ console.error(`Error:`, err.message);
71
+ }
72
+
73
+ await framework.destroy();
74
+ console.log('\n[Done]');
75
+ }
76
+
77
+ main().catch(console.error);
@@ -0,0 +1,93 @@
1
+ /**
2
+ * 模拟微信持续聊天场景
3
+ * 测试多轮对话后 result.message 是否为空
4
+ */
5
+
6
+ const { Framework } = require('../src');
7
+ const AIPlugin = require('../plugins/ai-plugin');
8
+ const SessionPlugin = require('../plugins/session-plugin');
9
+ require('dotenv').config();
10
+
11
+ async function main() {
12
+ console.log('=== 模拟微信持续聊天场景 ===\n');
13
+
14
+ const framework = new Framework({ debug: false });
15
+
16
+ await framework.loadPlugin(
17
+ new AIPlugin({
18
+ provider: 'minimax',
19
+ model: 'MiniMax-M2.7',
20
+ apiKey: process.env.MINIMAX_API_KEY || 'your-api-key',
21
+ })
22
+ );
23
+
24
+ // 加载 session 插件
25
+ await framework.loadPlugin(new SessionPlugin());
26
+
27
+ // 模拟微信的 system prompt
28
+ const systemPrompt = `你是一个微信助手。`;
29
+
30
+ // 创建 Agent(模拟 _getSessionAgent)
31
+ const agent = framework.createAgent({
32
+ name: 'WeixinAgent',
33
+ systemPrompt: systemPrompt,
34
+ });
35
+
36
+ // 模拟 session
37
+ const sessionPlugin = framework.pluginManager.get('session');
38
+ const sessionId = 'weixin_test_user';
39
+
40
+ // 初始化 session
41
+ sessionPlugin.getOrCreateSession(sessionId, {
42
+ metadata: { platform: 'weixin', userId: 'test_user' },
43
+ });
44
+
45
+ // 模拟微信的 _processChat
46
+ const processChat = async (userId, text) => {
47
+ console.log(`\n[User] ${text}`);
48
+
49
+ try {
50
+ const result = await agent.chat(text, { sessionId: `weixin_${userId}` });
51
+ const message = result.message || '';
52
+
53
+ if (message) {
54
+ console.log(`[Agent] ${message.substring(0, 100)}${message.length > 100 ? '...' : ''}`);
55
+ console.log(`[OK] message length: ${message.length}`);
56
+ } else {
57
+ console.log(`[WARNING] result.message is empty!`);
58
+ console.log(`[DEBUG] result:`, JSON.stringify(result, null, 2).substring(0, 500));
59
+ }
60
+
61
+ // 检查 _messages 状态
62
+ const chatHandler = agent._chatHandler;
63
+ if (chatHandler) {
64
+ console.log(`[DEBUG] _messages count: ${chatHandler._messages.length}`);
65
+ }
66
+
67
+ return message;
68
+ } catch (err) {
69
+ console.error(`[Error]`, err.message);
70
+ return '';
71
+ }
72
+ };
73
+
74
+ // 模拟多轮对话
75
+ await processChat('user1', '你好');
76
+ await processChat('user1', '今天天气怎么样?');
77
+ await processChat('user1', '帮我查一下北京的人口');
78
+ await processChat('user1', '再说一次北京的人口');
79
+
80
+ console.log('\n--- 测试压缩场景 ---');
81
+ // 发送更多消息触发压缩
82
+ for (let i = 0; i < 5; i++) {
83
+ await processChat('user1', `这是第 ${i + 1} 条测试消息`);
84
+ }
85
+
86
+ // 压缩后再发送一条
87
+ await processChat('user1', '你好,你还记得我吗?');
88
+
89
+ console.log('\n[Done]');
90
+ await framework.destroy();
91
+ }
92
+
93
+ main().catch(console.error);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "foliko",
3
- "version": "1.0.85",
3
+ "version": "1.0.87",
4
4
  "description": "简约的插件化 Agent 框架",
5
5
  "main": "src/index.js",
6
6
  "type": "commonjs",
@@ -53,7 +53,7 @@
53
53
  "@ai-sdk/openai": "^3.0.41",
54
54
  "@ai-sdk/openai-compatible": "^2.0.35",
55
55
  "@anthropic-ai/sdk": "^0.39.0",
56
- "@chnak/weixin-bot": "^1.2.1",
56
+ "@chnak/weixin-bot": "^1.2.7",
57
57
  "@chnak/zod-to-markdown": "^1.0.1",
58
58
  "@hono/node-server": "^1.19.11",
59
59
  "@larksuiteoapi/node-sdk": "^1.59.0",
@@ -53,17 +53,17 @@ class EventWatcher {
53
53
  */
54
54
  _handleEvent(type, data) {
55
55
  const activeGoals = this._goalManager.getActiveGoals()
56
- log.info(`_handleEvent: type=${type}, activeGoals=${activeGoals.length}`)
56
+ // log.info(`_handleEvent: type=${type}, activeGoals=${activeGoals.length}`)
57
57
 
58
58
  for (const goal of activeGoals) {
59
59
  // 检查目标条件是否匹配此事件
60
60
  const isRelevant = this._isRelevantToGoal(goal, type, data)
61
- log.info(`goal=${goal.id}, isRelevant=${isRelevant}, conditions=${JSON.stringify(goal.conditions)}`)
61
+ // log.info(`goal=${goal.id}, isRelevant=${isRelevant}, conditions=${JSON.stringify(goal.conditions)}`)
62
62
 
63
63
  if (isRelevant) {
64
64
  // 将 data 展平到事件对象中,方便通过 {{_event.xxx}} 访问
65
65
  this._goalManager.addEventToGoal(goal.id, { type, ...data })
66
- log.info(`Event added to goal ${goal.id}`)
66
+ // log.info(`Event added to goal ${goal.id}`)
67
67
  }
68
68
  }
69
69
 
@@ -75,7 +75,7 @@ class EventWatcher {
75
75
  this._goalManager.activateGoal(goal.id)
76
76
  // 添加事件
77
77
  this._goalManager.addEventToGoal(goal.id, { type, ...data })
78
- log.info(`事件触发激活目标: ${goal.id} (事件: ${type})`)
78
+ // log.info(`事件触发激活目标: ${goal.id} (事件: ${type})`)
79
79
  }
80
80
  }
81
81
  }
@@ -31,6 +31,11 @@ class ExtensionExecutorPlugin extends Plugin {
31
31
  this._scanPluginTools(plugin);
32
32
  });
33
33
 
34
+ // 监听插件重载事件,重新扫描工具
35
+ framework.on('plugin:reloaded', (plugin) => {
36
+ this._rescanPluginTools(plugin);
37
+ });
38
+
34
39
  return this;
35
40
  }
36
41
 
@@ -72,6 +77,34 @@ class ExtensionExecutorPlugin extends Plugin {
72
77
  }
73
78
  }
74
79
 
80
+ /**
81
+ * 重新扫描插件的工具(用于热重载)
82
+ */
83
+ _rescanPluginTools(plugin) {
84
+ if (!plugin || !plugin.tools || typeof plugin.tools !== 'object') {
85
+ return;
86
+ }
87
+
88
+ const pluginName = plugin.name;
89
+ if (!pluginName) return;
90
+
91
+ // 先移除旧工具
92
+ if (this._extensions.has(pluginName)) {
93
+ const ext = this._extensions.get(pluginName);
94
+ for (const tool of ext.tools || []) {
95
+ // 从 toolRouter 移除
96
+ if (this._framework?.toolRouter) {
97
+ this._framework.toolRouter.unregister(`ext_${tool.name}`);
98
+ }
99
+ }
100
+ this._extensions.delete(pluginName);
101
+ }
102
+
103
+ // 重新扫描工具
104
+ this._scanPluginTools(plugin);
105
+ log.info(` Rescanned tools from plugin '${pluginName}'`);
106
+ }
107
+
75
108
  async start(framework) {
76
109
  // 扫描所有已加载插件的 tools
77
110
  const plugins = framework.pluginManager.getAll();
@@ -217,7 +250,17 @@ class ExtensionExecutorPlugin extends Plugin {
217
250
  }
218
251
 
219
252
  const ext = this._extensions.get(pluginName);
220
- if (!ext.tools.find((t) => t.name === toolDef.name)) {
253
+ const existingIdx = ext.tools.findIndex((t) => t.name === toolDef.name);
254
+ if (existingIdx >= 0) {
255
+ // 更新已存在的工具
256
+ ext.tools[existingIdx] = {
257
+ name: toolDef.name,
258
+ description: toolDef.description || '',
259
+ inputSchema: toolDef.inputSchema,
260
+ execute: toolDef.execute,
261
+ };
262
+ } else {
263
+ // 添加新工具
221
264
  ext.tools.push({
222
265
  name: toolDef.name,
223
266
  description: toolDef.description || '',
@@ -154,11 +154,10 @@ class FileSystemPlugin extends Plugin {
154
154
  // 写入文件
155
155
  framework.registerTool({
156
156
  name: 'write_file',
157
- description: `创建或写入文件内容。
158
-
159
- 注意:
160
- - 对于大文件(>100MB),建议分多次调用 append_to_file
161
- - 支持覆盖写入和追加写入`,
157
+ description: `创建或写入文件内容(仅适用于小文件,建议小于10KB)。
158
+
159
+ 重要:大文件必须使用 append_to_file 分多次写入,每次追加一部分内容。
160
+ 禁止将大段内容作为 content 参数传入,这会导致工具调用失败。`,
162
161
  inputSchema: z.object({
163
162
  path: z.string().describe('文件路径'),
164
163
  content: z.string().describe('文件内容'),
@@ -225,6 +224,46 @@ class FileSystemPlugin extends Plugin {
225
224
  }
226
225
  })
227
226
 
227
+ // 追加文件内容(用于大文件分段写入)
228
+ framework.registerTool({
229
+ name: 'append_to_file',
230
+ description: `追加内容到文件末尾。适用于大文件写入,每次最多追加约64KB内容。
231
+
232
+ 使用方式:
233
+ 1. 先用 write_file 创建新文件(或清空现有文件)
234
+ 2. 多次调用 append_to_file 追加内容,每次 content 不超过 64KB
235
+ 3. 追加顺序很重要,content 应该按文件顺序排列`,
236
+ inputSchema: z.object({
237
+ path: z.string().describe('文件路径'),
238
+ content: z.string().describe('要追加的内容(建议不超过64KB)')
239
+ }),
240
+ execute: async (args, framework) => {
241
+ const { path: filePath, content } = args
242
+
243
+ const pathCheck = validatePath(filePath)
244
+ if (!pathCheck.valid) {
245
+ return { success: false, error: pathCheck.error }
246
+ }
247
+
248
+ try {
249
+ // 如果文件不存在,返回错误(应该先用 write_file 创建)
250
+ if (!fs.existsSync(pathCheck.resolved)) {
251
+ return { success: false, error: '文件不存在,请先用 write_file 创建文件' }
252
+ }
253
+
254
+ fs.appendFileSync(pathCheck.resolved, content, 'utf8')
255
+ return {
256
+ success: true,
257
+ message: `已追加内容到: ${pathCheck.resolved}`,
258
+ filePath: pathCheck.resolved,
259
+ appendedSize: content.length
260
+ }
261
+ } catch (error) {
262
+ return { success: false, error: error.message }
263
+ }
264
+ }
265
+ })
266
+
228
267
  // 删除文件
229
268
  framework.registerTool({
230
269
  name: 'delete_file',
@@ -335,6 +335,11 @@ class SessionPlugin extends Plugin {
335
335
  addMessage(sessionId, message) {
336
336
  const session = this.getSession(sessionId)
337
337
  if (session) {
338
+ // 基础消息验证
339
+ if (!message || !message.role || !message.content) {
340
+ log.warn('Invalid message format, skipping:', { sessionId, message });
341
+ return session;
342
+ }
338
343
  session.messages.push(message)
339
344
  session.lastActive = new Date()
340
345
 
@@ -349,6 +354,22 @@ class SessionPlugin extends Plugin {
349
354
  return session
350
355
  }
351
356
 
357
+ /**
358
+ * 整体替换会话消息(用于压缩后同步)
359
+ * @param {string} sessionId - 会话 ID
360
+ * @param {Array} messages - 新的消息数组
361
+ */
362
+ replaceMessages(sessionId, messages) {
363
+ const session = this.getSession(sessionId)
364
+ if (session) {
365
+ session.messages = messages || []
366
+ session.lastActive = new Date()
367
+ // 持久化到 storage
368
+ this._saveToStorage(session)
369
+ }
370
+ return session
371
+ }
372
+
352
373
  /**
353
374
  * 获取会话历史
354
375
  */