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.
- package/.agent/agents/code-assistant.json +14 -0
- package/.agent/agents/email-assistant.json +14 -0
- package/.agent/agents/file-assistant.json +15 -0
- package/.agent/agents/system-assistant.json +15 -0
- package/.agent/agents/web-assistant.json +12 -0
- package/.agent/data/ambient/goals.json +50 -0
- package/.agent/data/ambient/memories.json +7 -0
- package/.agent/data/default.json +21 -311
- package/.agent/data/plugins-state.json +162 -174
- package/.agent/data/scheduler/tasks.json +1 -0
- package/.agent/data/weixin.json +6 -0
- package/.agent/mcp_config.json +1 -0
- package/.agent/package.json +8 -0
- package/.agent/plugins/__pycache__/test_plugin.cpython-312.pyc +0 -0
- package/.agent/plugins/daytona/README.md +89 -0
- package/.agent/plugins/daytona/index.js +377 -0
- package/.agent/plugins/daytona/package.json +12 -0
- package/.agent/plugins/marknative/README.md +134 -0
- package/.agent/plugins/marknative/index.js +228 -0
- package/.agent/plugins/marknative/package.json +12 -0
- package/.agent/plugins/marknative/update-readme.js +134 -0
- package/.agent/plugins/system-info/index.js +387 -0
- package/.agent/plugins/system-info/package.json +4 -0
- package/.agent/plugins/system-info/test.js +40 -0
- package/.agent/plugins/temp-repo/LICENSE +201 -0
- package/.agent/plugins/test_plugin.py +304 -0
- package/.agent/plugins.json +14 -5
- package/.agent/python-scripts/test_sample.py +24 -0
- package/.agent/skills/agent-browser/SKILL.md +311 -0
- package/.agent/skills/agent-browser/TEST_PLAN.md +200 -0
- package/.agent/skills/sysinfo/SKILL.md +38 -0
- package/.agent/skills/sysinfo/system-info.sh +130 -0
- package/.agent/skills/workflow/SKILL.md +324 -0
- package/.agent/workflows/email-digest.json +50 -0
- package/.agent/workflows/file-backup.json +21 -0
- package/.agent/workflows/get-ip-notify.json +32 -0
- package/.agent/workflows/news-aggregator.json +93 -0
- package/.agent/workflows/news-dashboard-v2.json +94 -0
- package/.agent/workflows/notification-batch.json +32 -0
- package/.claude/settings.local.json +8 -7
- package/.env.example +56 -56
- package/README.md +441 -441
- package/examples/test-chat-debug.js +102 -0
- package/examples/test-chat-result.js +76 -0
- package/examples/test-chat-stream-diff.js +63 -0
- package/examples/test-concurrent-chat.js +60 -0
- package/examples/test-long-chat.js +77 -0
- package/examples/test-session-chat.js +93 -0
- package/package.json +2 -2
- package/plugins/ambient-agent/EventWatcher.js +4 -4
- package/plugins/extension-executor-plugin.js +44 -1
- package/plugins/file-system-plugin.js +44 -5
- package/plugins/session-plugin.js +21 -0
- package/plugins/weixin-plugin.js +278 -29
- package/skills/find-skills/AGENTS.md +162 -162
- package/skills/find-skills/SKILL.md +133 -133
- package/skills/foliko-dev/SKILL.md +67 -0
- package/skills/python-plugin-dev/SKILL.md +238 -238
- package/src/core/agent-chat.js +106 -58
- package/src/core/agent.js +3 -61
- package/src/utils/index.js +1 -1
- package/.agent/.shared/ui-ux-pro-max/data/charts.csv +0 -26
- package/.agent/.shared/ui-ux-pro-max/data/colors.csv +0 -97
- package/.agent/.shared/ui-ux-pro-max/data/icons.csv +0 -101
- package/.agent/.shared/ui-ux-pro-max/data/landing.csv +0 -31
- package/.agent/.shared/ui-ux-pro-max/data/products.csv +0 -97
- package/.agent/.shared/ui-ux-pro-max/data/prompts.csv +0 -24
- package/.agent/.shared/ui-ux-pro-max/data/react-performance.csv +0 -45
- package/.agent/.shared/ui-ux-pro-max/data/stacks/flutter.csv +0 -53
- package/.agent/.shared/ui-ux-pro-max/data/stacks/html-tailwind.csv +0 -56
- package/.agent/.shared/ui-ux-pro-max/data/stacks/jetpack-compose.csv +0 -53
- package/.agent/.shared/ui-ux-pro-max/data/stacks/nextjs.csv +0 -53
- package/.agent/.shared/ui-ux-pro-max/data/stacks/nuxt-ui.csv +0 -51
- package/.agent/.shared/ui-ux-pro-max/data/stacks/nuxtjs.csv +0 -59
- package/.agent/.shared/ui-ux-pro-max/data/stacks/react-native.csv +0 -52
- package/.agent/.shared/ui-ux-pro-max/data/stacks/react.csv +0 -54
- package/.agent/.shared/ui-ux-pro-max/data/stacks/shadcn.csv +0 -61
- package/.agent/.shared/ui-ux-pro-max/data/stacks/svelte.csv +0 -54
- package/.agent/.shared/ui-ux-pro-max/data/stacks/swiftui.csv +0 -51
- package/.agent/.shared/ui-ux-pro-max/data/stacks/vue.csv +0 -50
- package/.agent/.shared/ui-ux-pro-max/data/styles.csv +0 -59
- package/.agent/.shared/ui-ux-pro-max/data/typography.csv +0 -58
- package/.agent/.shared/ui-ux-pro-max/data/ui-reasoning.csv +0 -101
- package/.agent/.shared/ui-ux-pro-max/data/ux-guidelines.csv +0 -100
- package/.agent/.shared/ui-ux-pro-max/data/web-interface.csv +0 -31
- package/.agent/.shared/ui-ux-pro-max/scripts/__pycache__/core.cpython-313.pyc +0 -0
- package/.agent/.shared/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-313.pyc +0 -0
- package/.agent/.shared/ui-ux-pro-max/scripts/core.py +0 -258
- package/.agent/.shared/ui-ux-pro-max/scripts/design_system.py +0 -1067
- package/.agent/.shared/ui-ux-pro-max/scripts/search.py +0 -106
- package/.agent/ARCHITECTURE.md +0 -288
- package/.agent/agents/ambient-agent.md +0 -57
- package/.agent/agents/debugger.md +0 -55
- package/.agent/agents/email-assistant.md +0 -49
- package/.agent/agents/file-manager.md +0 -42
- package/.agent/agents/python-developer.md +0 -60
- package/.agent/agents/scheduler.md +0 -59
- package/.agent/agents/web-developer.md +0 -45
- package/.agent/data/puppeteer-sessions/undefined.json +0 -6
- package/.agent/mcp_config_updated.json +0 -12
- package/.agent/rules/GEMINI.md +0 -273
- package/.agent/rules/allow-rule.md +0 -77
- package/.agent/rules/log-rule.md +0 -83
- package/.agent/rules/security-rule.md +0 -93
- package/.agent/scripts/auto_preview.py +0 -148
- package/.agent/scripts/checklist.py +0 -217
- package/.agent/scripts/session_manager.py +0 -120
- package/.agent/scripts/verify_all.py +0 -327
- package/.agent/skills/api-patterns/SKILL.md +0 -81
- package/.agent/skills/api-patterns/api-style.md +0 -42
- package/.agent/skills/api-patterns/auth.md +0 -24
- package/.agent/skills/api-patterns/documentation.md +0 -26
- package/.agent/skills/api-patterns/graphql.md +0 -41
- package/.agent/skills/api-patterns/rate-limiting.md +0 -31
- package/.agent/skills/api-patterns/response.md +0 -37
- package/.agent/skills/api-patterns/rest.md +0 -40
- package/.agent/skills/api-patterns/scripts/api_validator.py +0 -211
- package/.agent/skills/api-patterns/security-testing.md +0 -122
- package/.agent/skills/api-patterns/trpc.md +0 -41
- package/.agent/skills/api-patterns/versioning.md +0 -22
- package/.agent/skills/app-builder/SKILL.md +0 -75
- package/.agent/skills/app-builder/agent-coordination.md +0 -71
- package/.agent/skills/app-builder/feature-building.md +0 -53
- package/.agent/skills/app-builder/project-detection.md +0 -34
- package/.agent/skills/app-builder/scaffolding.md +0 -118
- package/.agent/skills/app-builder/tech-stack.md +0 -40
- package/.agent/skills/app-builder/templates/SKILL.md +0 -39
- package/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +0 -76
- package/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +0 -92
- package/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +0 -88
- package/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +0 -88
- package/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +0 -83
- package/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +0 -90
- package/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +0 -90
- package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +0 -122
- package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +0 -122
- package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +0 -169
- package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +0 -134
- package/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +0 -83
- package/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +0 -119
- package/.agent/skills/architecture/SKILL.md +0 -55
- package/.agent/skills/architecture/context-discovery.md +0 -43
- package/.agent/skills/architecture/examples.md +0 -94
- package/.agent/skills/architecture/pattern-selection.md +0 -68
- package/.agent/skills/architecture/patterns-reference.md +0 -50
- package/.agent/skills/architecture/trade-off-analysis.md +0 -77
- package/.agent/skills/clean-code/SKILL.md +0 -201
- package/.agent/skills/doc.md +0 -177
- package/.agent/skills/frontend-design/SKILL.md +0 -418
- package/.agent/skills/frontend-design/animation-guide.md +0 -331
- package/.agent/skills/frontend-design/color-system.md +0 -311
- package/.agent/skills/frontend-design/decision-trees.md +0 -418
- package/.agent/skills/frontend-design/motion-graphics.md +0 -306
- package/.agent/skills/frontend-design/scripts/accessibility_checker.py +0 -183
- package/.agent/skills/frontend-design/scripts/ux_audit.py +0 -722
- package/.agent/skills/frontend-design/typography-system.md +0 -345
- package/.agent/skills/frontend-design/ux-psychology.md +0 -1116
- package/.agent/skills/frontend-design/visual-effects.md +0 -383
- package/.agent/skills/i18n-localization/SKILL.md +0 -154
- package/.agent/skills/i18n-localization/scripts/i18n_checker.py +0 -241
- package/.agent/skills/mcp-builder/SKILL.md +0 -176
- package/.agent/skills/web-design-guidelines/SKILL.md +0 -57
- package/.agent/workflows/brainstorm.md +0 -113
- package/.agent/workflows/create.md +0 -59
- package/.agent/workflows/debug.md +0 -103
- package/.agent/workflows/deploy.md +0 -176
- package/.agent/workflows/enhance.md +0 -63
- package/.agent/workflows/orchestrate.md +0 -237
- package/.agent/workflows/plan.md +0 -89
- package/.agent/workflows/preview.md +0 -81
- package/.agent/workflows/simple-test.md +0 -42
- package/.agent/workflows/status.md +0 -86
- package/.agent/workflows/structured-orchestrate.md +0 -180
- package/.agent/workflows/test.md +0 -144
- package/.agent/workflows/ui-ux-pro-max.md +0 -296
- /package/.agent/plugins/{puppeteer-plugin → temp-repo/puppeteer-plugin}/README.md +0 -0
- /package/.agent/plugins/{puppeteer-plugin → temp-repo/puppeteer-plugin}/index.js +0 -0
- /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.
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
*/
|