foliko 1.1.4 → 1.1.5
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/.shared/ui-ux-pro-max/data/charts.csv +26 -0
- package/.agent/.shared/ui-ux-pro-max/data/colors.csv +97 -0
- package/.agent/.shared/ui-ux-pro-max/data/icons.csv +101 -0
- package/.agent/.shared/ui-ux-pro-max/data/landing.csv +31 -0
- package/.agent/.shared/ui-ux-pro-max/data/products.csv +97 -0
- package/.agent/.shared/ui-ux-pro-max/data/prompts.csv +24 -0
- package/.agent/.shared/ui-ux-pro-max/data/react-performance.csv +45 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/react.csv +54 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/vue.csv +50 -0
- package/.agent/.shared/ui-ux-pro-max/data/styles.csv +59 -0
- package/.agent/.shared/ui-ux-pro-max/data/typography.csv +58 -0
- package/.agent/.shared/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
- package/.agent/.shared/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
- package/.agent/.shared/ui-ux-pro-max/data/web-interface.csv +31 -0
- 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 +258 -0
- package/.agent/.shared/ui-ux-pro-max/scripts/design_system.py +1067 -0
- package/.agent/.shared/ui-ux-pro-max/scripts/search.py +106 -0
- package/.agent/ARCHITECTURE.md +288 -0
- package/.agent/agents/ambient-agent.md +57 -0
- package/.agent/agents/debugger.md +55 -0
- package/.agent/agents/email-assistant.md +49 -0
- package/.agent/agents/file-manager.md +42 -0
- package/.agent/agents/python-developer.md +60 -0
- package/.agent/agents/scheduler.md +59 -0
- package/.agent/agents/web-developer.md +45 -0
- package/.agent/data/default.json +412 -3
- package/.agent/data/plugins-state.json +173 -174
- package/.agent/data/puppeteer-sessions/undefined.json +6 -0
- package/.agent/data/weixin-media/2026-04-08/img_1775618677512.jpg +0 -0
- package/.agent/data/weixin-media/2026-04-08/img_1775619073340.jpg +0 -0
- package/.agent/data/weixin-media/2026-04-08/img_1775619097536.jpg +0 -0
- package/.agent/data/weixin-media/2026-04-08/img_1775619209388.jpg +0 -0
- package/.agent/mcp_config_updated.json +12 -0
- package/.agent/memory/feedback/mnrdq5ps-ekch6c.md +9 -0
- package/.agent/memory/feedback/mnrdvj5i-ca3dkd.md +9 -0
- package/.agent/memory/feedback/mnre365e-7s4zax.md +9 -0
- package/.agent/memory/feedback/mnre36jn-nkfgmp.md +9 -0
- package/.agent/memory/feedback/mnre3805-kjiq6h.md +9 -0
- package/.agent/memory/feedback/test-1775733060827.md +6 -0
- package/.agent/memory/project/mnqx54u5-loqtoe.md +9 -0
- package/.agent/memory/project/mnqx84cv-mx6dmd.md +9 -0
- package/.agent/memory/reference/mnre3cww-penbo1.md +9 -0
- package/.agent/plugins/poster-plugin/fonts/NotoColorEmoji-Regular.ttf +0 -0
- package/.agent/plugins/poster-plugin/fonts/Symbola_hint.ttf +0 -0
- package/.agent/plugins/poster-plugin/src/index.js +30 -29
- package/.agent/plugins/puppeteer-plugin/README.md +147 -0
- package/.agent/plugins/puppeteer-plugin/index.js +1418 -0
- package/.agent/plugins/puppeteer-plugin/package.json +9 -0
- package/.agent/plugins.json +5 -11
- package/.agent/rules/GEMINI.md +273 -0
- package/.agent/rules/allow-rule.md +77 -0
- package/.agent/rules/log-rule.md +83 -0
- package/.agent/rules/security-rule.md +93 -0
- package/.agent/scripts/auto_preview.py +148 -0
- package/.agent/scripts/checklist.py +217 -0
- package/.agent/scripts/session_manager.py +120 -0
- package/.agent/scripts/verify_all.py +327 -0
- package/.agent/sessions/cli_default.json +636 -1833
- package/.agent/sessions/weixin_o9cq80zgZqKPA2-s59PN43GdDy1w@im.wechat.json +11097 -0
- package/.agent/skills/api-patterns/SKILL.md +81 -0
- package/.agent/skills/api-patterns/api-style.md +42 -0
- package/.agent/skills/api-patterns/auth.md +24 -0
- package/.agent/skills/api-patterns/documentation.md +26 -0
- package/.agent/skills/api-patterns/graphql.md +41 -0
- package/.agent/skills/api-patterns/rate-limiting.md +31 -0
- package/.agent/skills/api-patterns/response.md +37 -0
- package/.agent/skills/api-patterns/rest.md +40 -0
- package/.agent/skills/api-patterns/scripts/api_validator.py +211 -0
- package/.agent/skills/api-patterns/security-testing.md +122 -0
- package/.agent/skills/api-patterns/trpc.md +41 -0
- package/.agent/skills/api-patterns/versioning.md +22 -0
- package/.agent/skills/app-builder/SKILL.md +75 -0
- package/.agent/skills/app-builder/agent-coordination.md +71 -0
- package/.agent/skills/app-builder/feature-building.md +53 -0
- package/.agent/skills/app-builder/project-detection.md +34 -0
- package/.agent/skills/app-builder/scaffolding.md +118 -0
- package/.agent/skills/app-builder/tech-stack.md +40 -0
- package/.agent/skills/app-builder/templates/SKILL.md +39 -0
- package/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +76 -0
- package/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +92 -0
- package/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +88 -0
- package/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +88 -0
- package/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +83 -0
- package/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +90 -0
- package/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +90 -0
- package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +122 -0
- package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +122 -0
- package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +169 -0
- package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +134 -0
- package/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +83 -0
- package/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +119 -0
- package/.agent/skills/architecture/SKILL.md +55 -0
- package/.agent/skills/architecture/context-discovery.md +43 -0
- package/.agent/skills/architecture/examples.md +94 -0
- package/.agent/skills/architecture/pattern-selection.md +68 -0
- package/.agent/skills/architecture/patterns-reference.md +50 -0
- package/.agent/skills/architecture/trade-off-analysis.md +77 -0
- package/.agent/skills/clean-code/SKILL.md +201 -0
- package/.agent/skills/doc.md +177 -0
- package/.agent/skills/frontend-design/SKILL.md +418 -0
- package/.agent/skills/frontend-design/animation-guide.md +331 -0
- package/.agent/skills/frontend-design/color-system.md +311 -0
- package/.agent/skills/frontend-design/decision-trees.md +418 -0
- package/.agent/skills/frontend-design/motion-graphics.md +306 -0
- package/.agent/skills/frontend-design/scripts/accessibility_checker.py +183 -0
- package/.agent/skills/frontend-design/scripts/ux_audit.py +722 -0
- package/.agent/skills/frontend-design/typography-system.md +345 -0
- package/.agent/skills/frontend-design/ux-psychology.md +1116 -0
- package/.agent/skills/frontend-design/visual-effects.md +383 -0
- package/.agent/skills/i18n-localization/SKILL.md +154 -0
- package/.agent/skills/i18n-localization/scripts/i18n_checker.py +241 -0
- package/.agent/skills/mcp-builder/SKILL.md +176 -0
- package/.agent/skills/poster-design/SKILL.md +385 -0
- package/.agent/skills/web-design-guidelines/SKILL.md +57 -0
- package/.agent/workflows/brainstorm.md +113 -0
- package/.agent/workflows/create.md +59 -0
- package/.agent/workflows/debug.md +103 -0
- package/.agent/workflows/deploy.md +176 -0
- package/.agent/workflows/enhance.md +63 -0
- package/.agent/workflows/orchestrate.md +237 -0
- package/.agent/workflows/plan.md +89 -0
- package/.agent/workflows/preview.md +81 -0
- package/.agent/workflows/simple-test.md +42 -0
- package/.agent/workflows/status.md +86 -0
- package/.agent/workflows/structured-orchestrate.md +180 -0
- package/.agent/workflows/test.md +144 -0
- package/.agent/workflows/ui-ux-pro-max.md +296 -0
- package/.claude/settings.local.json +8 -1
- package/.env.example +56 -56
- package/37ua31lq.png +0 -0
- package/4ru0h1yo.png +0 -0
- package/55c90rsx.png +0 -0
- package/README.md +441 -441
- package/cli/src/commands/chat.js +69 -1
- package/cli/src/index.js +11 -2
- package/gud2mnws.png +0 -0
- package/output/poster_business.png.png +0 -0
- package/output/poster_business_product.png.png +0 -0
- package/output/poster_cyberpunk_neon.png.png +0 -0
- package/output/poster_festival.png.png +0 -0
- package/output/poster_foliko_personal.png.png +0 -0
- package/output/poster_french_romance.png.png +0 -0
- package/output/poster_guochao_landscape.png.png +0 -0
- package/output/poster_japanese_zen.png.png +0 -0
- package/output/poster_kawaii.png.png +0 -0
- package/output/poster_kawaii_hello.png.png +0 -0
- package/output/poster_luxury_gradient.png.png +0 -0
- package/output/poster_magazine_vogue.png.png +0 -0
- package/output/poster_minimal.png.png +0 -0
- package/output/poster_minimal_bw.png.png +0 -0
- package/output/poster_minimal_geometry.png.png +0 -0
- package/output/poster_pop_art.png.png +0 -0
- package/output/poster_sakura.png.png +0 -0
- package/output/poster_tech.png.png +0 -0
- package/output/poster_trendy.png.png +0 -0
- package/output/poster_vintage.png.png +0 -0
- package/output/poster_vintage_coffee.png.png +0 -0
- package/package.json +1 -1
- package/plugins/extension-executor-plugin.js +27 -1
- package/plugins/memory-plugin.js +197 -32
- package/skills/find-skills/AGENTS.md +162 -162
- package/skills/find-skills/SKILL.md +133 -133
- package/src/core/agent-chat.js +203 -112
- package/undefined.png +0 -0
- package/undefined.svg +1 -0
- package/xrrdyfr8.png +0 -0
- package/y9bfri9m.png +0 -0
- package/.agent/agents/code-assistant.json +0 -14
- package/.agent/agents/email-assistant.json +0 -14
- package/.agent/agents/file-assistant.json +0 -15
- package/.agent/agents/system-assistant.json +0 -15
- package/.agent/agents/web-assistant.json +0 -12
- package/.agent/data/ambient/goals.json +0 -50
- package/.agent/data/ambient/memories.json +0 -7
- package/.agent/data/scheduler/tasks.json +0 -1
- package/.agent/memory/core.md +0 -1
- package/.agent/memory/project/mnn93ogy-ypjn27.md +0 -9
- package/.agent/memory/project/mnn98fqy-5nhc1u.md +0 -25
- package/.agent/memory/reference/mnq3oenw-46haj6.md +0 -63
- package/.agent/memory/reference/mnq5qxm2-mjoooh.md +0 -116
- package/.agent/memory/user/mnm67t9m-x8rekk.md +0 -9
- package/.agent/memory/user/mnn5mmqh-w6aktx.md +0 -11
- package/.agent/memory/user/mnnbfhhn-dk1bd1.md +0 -22
- package/.agent/package.json +0 -8
- package/.agent/plugins/__pycache__/file_writer.cpython-312.pyc +0 -0
- package/.agent/plugins/daytona/README.md +0 -89
- package/.agent/plugins/daytona/index.js +0 -377
- package/.agent/plugins/daytona/package.json +0 -12
- package/.agent/plugins/marknative/README.md +0 -134
- package/.agent/plugins/marknative/fonts/SegoeUI Emoji.ttf +0 -0
- package/.agent/plugins/marknative/index.js +0 -256
- package/.agent/plugins/marknative/package.json +0 -12
- package/.agent/plugins/marknative/update-readme.js +0 -134
- package/.agent/plugins/poster-plugin/emojis/rocket.png +0 -1
- package/.agent/plugins/poster-plugin/yarn.lock +0 -1007
- package/.agent/plugins/system-info/index.js +0 -387
- package/.agent/plugins/system-info/package.json +0 -4
- package/.agent/plugins/system-info/test.js +0 -40
- package/.agent/python-scripts/test_sample.py +0 -24
- package/.agent/skills/agent-browser/SKILL.md +0 -311
- package/.agent/skills/agent-browser/TEST_PLAN.md +0 -200
- package/.agent/skills/sysinfo/SKILL.md +0 -38
- package/.agent/skills/sysinfo/system-info.sh +0 -130
- package/.agent/skills/workflow/SKILL.md +0 -324
- package/.agent/weixin.json +0 -6
- package/.agent/workflows/email-digest.json +0 -50
- package/.agent/workflows/file-backup.json +0 -21
- package/.agent/workflows/get-ip-notify.json +0 -32
- package/.agent/workflows/news-aggregator.json +0 -93
- package/.agent/workflows/news-dashboard-v2.json +0 -94
- package/.agent/workflows/notification-batch.json +0 -32
- package/output/emoji-segoe-test-v2.png +0 -0
- package/output/emoji-segoe-test.png +0 -0
- package/output/emoji-test.png +0 -0
- package/output/emoji-windows-test.png +0 -0
- package/output/foliko-emoji-poster.png +0 -0
- package/output/foliko-muji-poster-final.png +0 -0
- package/output/foliko-muji-poster-v2.png +0 -0
- package/output/foliko-muji-poster.png +0 -0
- package/output/foliko-share.png +0 -0
- package/output/progress-circle-test.png +0 -0
- package/output/vb-agent-poster.png +0 -0
package/cli/src/commands/chat.js
CHANGED
|
@@ -63,7 +63,12 @@ function parseArgs(args) {
|
|
|
63
63
|
|
|
64
64
|
for (let i = 0; i < args.length; i++) {
|
|
65
65
|
const arg = args[i];
|
|
66
|
-
if (arg === '--
|
|
66
|
+
if (arg === '-c' || arg === '--continue' || arg === '--continuous') {
|
|
67
|
+
// 持续测试模式:传入 'sessionId:command1|command2|command3'
|
|
68
|
+
// 或 command1|command2|command3 (使用默认 sessionId)
|
|
69
|
+
options.continuous = true;
|
|
70
|
+
options.commandSequence = args[++i] || '';
|
|
71
|
+
} else if (arg === '--model' && args[i + 1]) {
|
|
67
72
|
options.model = args[++i];
|
|
68
73
|
} else if (arg === '--provider' && args[i + 1]) {
|
|
69
74
|
options.provider = args[++i];
|
|
@@ -75,6 +80,10 @@ function parseArgs(args) {
|
|
|
75
80
|
options.stream = true;
|
|
76
81
|
} else if (arg === '--no-stream') {
|
|
77
82
|
options.stream = false;
|
|
83
|
+
} else if (arg === '--clear') {
|
|
84
|
+
options.clearSession = true;
|
|
85
|
+
} else if (arg === '--session' && args[i + 1]) {
|
|
86
|
+
options.sessionId = args[++i];
|
|
78
87
|
}
|
|
79
88
|
}
|
|
80
89
|
|
|
@@ -86,6 +95,59 @@ function parseArgs(args) {
|
|
|
86
95
|
return options;
|
|
87
96
|
}
|
|
88
97
|
|
|
98
|
+
/**
|
|
99
|
+
* 持续测试模式:自动发送多条消息进行测试
|
|
100
|
+
*/
|
|
101
|
+
async function runContinuousTest(agent, options) {
|
|
102
|
+
const sessionId = options.sessionId || 'cli_default';
|
|
103
|
+
const commands = options.commandSequence.split('|').filter((c) => c.trim());
|
|
104
|
+
|
|
105
|
+
if (commands.length === 0) {
|
|
106
|
+
console.log('错误:-c 参数需要提供命令序列,格式:command1|command2|command3');
|
|
107
|
+
process.exit(1);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
console.log('=== 持续测试模式 ===');
|
|
111
|
+
console.log(`Session: ${sessionId}`);
|
|
112
|
+
console.log(`命令数量: ${commands.length}`);
|
|
113
|
+
console.log('');
|
|
114
|
+
|
|
115
|
+
const runWithContext = agent.framework?.runWithContext.bind(agent.framework);
|
|
116
|
+
|
|
117
|
+
for (let i = 0; i < commands.length; i++) {
|
|
118
|
+
const cmd = commands[i];
|
|
119
|
+
console.log(`\n[${i + 1}/${commands.length}] >>> ${cmd}`);
|
|
120
|
+
console.log('-'.repeat(50));
|
|
121
|
+
|
|
122
|
+
try {
|
|
123
|
+
let fullResponse = '';
|
|
124
|
+
await runWithContext({ sessionId }, async () => {
|
|
125
|
+
for await (const chunk of agent.chatStream(cmd, { sessionId })) {
|
|
126
|
+
if (chunk.type === 'text') {
|
|
127
|
+
fullResponse += chunk.text;
|
|
128
|
+
process.stdout.write(chunk.text);
|
|
129
|
+
} else if (chunk.type === 'tool-call') {
|
|
130
|
+
console.log(`\n[工具调用] ${chunk.toolName} ${JSON.stringify(chunk.input)}`);
|
|
131
|
+
} else if (chunk.type === 'error') {
|
|
132
|
+
console.error(`\n[错误] ${chunk.error}`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
console.log('\n' + '-'.repeat(50));
|
|
137
|
+
console.log(`[完成] 回复长度: ${fullResponse.length}`);
|
|
138
|
+
} catch (err) {
|
|
139
|
+
console.error(`\n[执行错误] ${err.message}`);
|
|
140
|
+
// 继续执行下一条命令
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// 命令间隔 1 秒
|
|
144
|
+
await new Promise((r) => setTimeout(r, 1000));
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
console.log('\n=== 测试完成 ===');
|
|
148
|
+
console.log(`共执行 ${commands.length} 条命令`);
|
|
149
|
+
}
|
|
150
|
+
|
|
89
151
|
/**
|
|
90
152
|
* Chat 命令入口
|
|
91
153
|
*/
|
|
@@ -127,6 +189,12 @@ async function chatCommand(args) {
|
|
|
127
189
|
- 禁止添加 -g 参数
|
|
128
190
|
- 例如:npx skills add xxx 应该执行为 npx skills add xxx -a openclaw -y`);
|
|
129
191
|
|
|
192
|
+
// 持续测试模式
|
|
193
|
+
if (options.continuous) {
|
|
194
|
+
await runContinuousTest(agent, options);
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
|
|
130
198
|
// 初始化 UI
|
|
131
199
|
const ui = new ChatUI(agent, { stream: options.stream });
|
|
132
200
|
|
package/cli/src/index.js
CHANGED
|
@@ -12,12 +12,21 @@ const path = require('path');
|
|
|
12
12
|
*/
|
|
13
13
|
async function cli() {
|
|
14
14
|
const args = process.argv.slice(2);
|
|
15
|
-
|
|
15
|
+
let command = args[0] || 'chat';
|
|
16
16
|
const packageJsonPath = path.join(__dirname, '../../package.json');
|
|
17
17
|
|
|
18
|
+
// 如果第一个参数看起来像选项而不是命令,说明用户直接运行 "npm run chat -c ..."
|
|
19
|
+
// 把命令设为 'chat',所有参数都传给 chat 命令
|
|
20
|
+
if (command && command.startsWith('-')) {
|
|
21
|
+
command = 'chat';
|
|
22
|
+
}
|
|
23
|
+
|
|
18
24
|
switch (command) {
|
|
19
25
|
case 'chat':
|
|
20
|
-
|
|
26
|
+
// 如果第一个参数是选项(如 -c),args 已经是传给 chat 的参数
|
|
27
|
+
// 如果第一个参数是 'chat',需要 slice(1) 去掉 'chat'
|
|
28
|
+
const chatArgs = args[0] === 'chat' ? args.slice(1) : args;
|
|
29
|
+
await chatCommand(chatArgs);
|
|
21
30
|
break;
|
|
22
31
|
|
|
23
32
|
case 'list':
|
package/gud2mnws.png
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -133,15 +133,29 @@ class ExtensionExecutorPlugin extends Plugin {
|
|
|
133
133
|
}),
|
|
134
134
|
execute: async (args) => {
|
|
135
135
|
const { plugin, tool, args: toolArgs = {} } = args;
|
|
136
|
-
log.info(` ext_call: plugin=${plugin}, tool=${tool}`);
|
|
136
|
+
log.info(` ext_call: plugin=${plugin}, tool=${tool}, args=${JSON.stringify(toolArgs)}`);
|
|
137
137
|
|
|
138
138
|
const ext = this._extensions.get(plugin);
|
|
139
139
|
if (!ext) {
|
|
140
|
+
// 触发错误事件
|
|
141
|
+
framework.emit('tool:error', {
|
|
142
|
+
name: `${plugin}:${tool}`,
|
|
143
|
+
args: toolArgs,
|
|
144
|
+
error: `扩展插件 '${plugin}' 不存在`,
|
|
145
|
+
source: 'extension'
|
|
146
|
+
});
|
|
140
147
|
return { success: false, error: `扩展插件 '${plugin}' 不存在` };
|
|
141
148
|
}
|
|
142
149
|
|
|
143
150
|
const toolDef = ext.tools.find((t) => t.name === tool);
|
|
144
151
|
if (!toolDef) {
|
|
152
|
+
// 触发错误事件
|
|
153
|
+
framework.emit('tool:error', {
|
|
154
|
+
name: `${plugin}:${tool}`,
|
|
155
|
+
args: toolArgs,
|
|
156
|
+
error: `扩展工具 '${tool}' 不存在`,
|
|
157
|
+
source: 'extension'
|
|
158
|
+
});
|
|
145
159
|
return { success: false, error: `扩展工具 '${tool}' 不存在` };
|
|
146
160
|
}
|
|
147
161
|
|
|
@@ -161,6 +175,18 @@ class ExtensionExecutorPlugin extends Plugin {
|
|
|
161
175
|
// 统一 execute 签名为 (args, framework)
|
|
162
176
|
const result = await toolDef.execute(toolArgs, framework);
|
|
163
177
|
|
|
178
|
+
// 检查结果是否为错误
|
|
179
|
+
if (result && result.success === false && result.error) {
|
|
180
|
+
// 触发扩展工具错误事件
|
|
181
|
+
framework.emit('tool:error', {
|
|
182
|
+
name: `${plugin}:${tool}`,
|
|
183
|
+
args: toolArgs,
|
|
184
|
+
error: result.error,
|
|
185
|
+
source: 'extension'
|
|
186
|
+
});
|
|
187
|
+
return result;
|
|
188
|
+
}
|
|
189
|
+
|
|
164
190
|
// 触发扩展工具完成事件
|
|
165
191
|
framework.emit('tool:result', {
|
|
166
192
|
name: `${plugin}:${tool}`,
|
package/plugins/memory-plugin.js
CHANGED
|
@@ -10,7 +10,7 @@ const { z } = require('zod')
|
|
|
10
10
|
const fs = require('fs')
|
|
11
11
|
const path = require('path')
|
|
12
12
|
const { EventEmitter } = require('events')
|
|
13
|
-
|
|
13
|
+
const {cleanResponse} =require('../src/utils')
|
|
14
14
|
/**
|
|
15
15
|
* 记忆类型常量
|
|
16
16
|
*/
|
|
@@ -147,44 +147,60 @@ function _extractJSON(text) {
|
|
|
147
147
|
|
|
148
148
|
// 去掉首尾空白
|
|
149
149
|
text = text.trim()
|
|
150
|
-
if (!text.startsWith('{')) return null
|
|
151
150
|
|
|
152
|
-
//
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
151
|
+
// 方法1:如果直接以 { 开头,尝试直接解析
|
|
152
|
+
if (text.startsWith('{')) {
|
|
153
|
+
// 查找配对的括号位置
|
|
154
|
+
let braceCount = 0
|
|
155
|
+
let inString = false
|
|
156
|
+
let escaped = false
|
|
156
157
|
|
|
157
|
-
|
|
158
|
-
|
|
158
|
+
for (let i = 0; i < text.length; i++) {
|
|
159
|
+
const char = text[i]
|
|
159
160
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
161
|
+
if (escaped) {
|
|
162
|
+
escaped = false
|
|
163
|
+
continue
|
|
164
|
+
}
|
|
164
165
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
166
|
+
if (char === '\\' && inString) {
|
|
167
|
+
escaped = true
|
|
168
|
+
continue
|
|
169
|
+
}
|
|
169
170
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
171
|
+
if (char === '"') {
|
|
172
|
+
inString = !inString
|
|
173
|
+
continue
|
|
174
|
+
}
|
|
174
175
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
176
|
+
if (!inString) {
|
|
177
|
+
if (char === '{') {
|
|
178
|
+
braceCount++
|
|
179
|
+
} else if (char === '}') {
|
|
180
|
+
braceCount--
|
|
181
|
+
if (braceCount === 0) {
|
|
182
|
+
return text.substring(0, i + 1)
|
|
183
|
+
}
|
|
183
184
|
}
|
|
184
185
|
}
|
|
185
186
|
}
|
|
186
187
|
}
|
|
187
188
|
|
|
189
|
+
// 方法2:从 thinking 文本中查找 JSON(处理 AI 输出 thinking 的情况)
|
|
190
|
+
// 查找最后一个 { 到最后一个 } 之间的内容
|
|
191
|
+
const firstBrace = text.indexOf('{')
|
|
192
|
+
const lastBrace = text.lastIndexOf('}')
|
|
193
|
+
|
|
194
|
+
if (firstBrace !== -1 && lastBrace !== -1 && lastBrace > firstBrace) {
|
|
195
|
+
const potential = text.substring(firstBrace, lastBrace + 1)
|
|
196
|
+
try {
|
|
197
|
+
JSON.parse(potential) // 验证是否是有效 JSON
|
|
198
|
+
return potential
|
|
199
|
+
} catch (e) {
|
|
200
|
+
// 不是有效 JSON,继续尝试其他方法
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
188
204
|
return null
|
|
189
205
|
}
|
|
190
206
|
|
|
@@ -793,6 +809,144 @@ class MemoryPlugin extends Plugin {
|
|
|
793
809
|
log.warn('Auto memory extraction failed:', err.message)
|
|
794
810
|
}
|
|
795
811
|
})
|
|
812
|
+
|
|
813
|
+
// 监听所有工具调用错误(包括 ext_call, MCP, 原生工具等)
|
|
814
|
+
framework.on('tool:error', async (data) => {
|
|
815
|
+
try {
|
|
816
|
+
await this._extractErrorLesson({
|
|
817
|
+
name: data.name || data.tool || 'unknown-tool',
|
|
818
|
+
args: data.args || {},
|
|
819
|
+
error: data.error || data.message || String(data),
|
|
820
|
+
source: data.source || 'tool'
|
|
821
|
+
})
|
|
822
|
+
} catch (err) {
|
|
823
|
+
log.warn('Auto tool error lesson extraction failed:', err.message)
|
|
824
|
+
}
|
|
825
|
+
})
|
|
826
|
+
|
|
827
|
+
// 监听 tool-call 别名(AI SDK 6.x 格式)
|
|
828
|
+
framework.on('tool-error', async (data) => {
|
|
829
|
+
try {
|
|
830
|
+
await this._extractErrorLesson({
|
|
831
|
+
name: data.name || data.tool || 'unknown-tool',
|
|
832
|
+
args: data.args || {},
|
|
833
|
+
error: data.error || data.message || String(data),
|
|
834
|
+
source: data.source || 'tool'
|
|
835
|
+
})
|
|
836
|
+
} catch (err) {
|
|
837
|
+
log.warn('Auto tool-error lesson extraction failed:', err.message)
|
|
838
|
+
}
|
|
839
|
+
})
|
|
840
|
+
|
|
841
|
+
// 监听工具重试事件(重试可能意味着配置或参数问题)
|
|
842
|
+
framework.on('tool:retry', async (data) => {
|
|
843
|
+
try {
|
|
844
|
+
const { name, args, error, attempt } = data
|
|
845
|
+
await this._extractErrorLesson({
|
|
846
|
+
name: name || 'unknown-tool',
|
|
847
|
+
args: args || {},
|
|
848
|
+
error: `Retry attempt ${attempt} failed: ${error || data.message || 'unknown'}`,
|
|
849
|
+
source: 'tool-retry'
|
|
850
|
+
})
|
|
851
|
+
} catch (err) {
|
|
852
|
+
log.warn('Auto tool retry lesson extraction failed:', err.message)
|
|
853
|
+
}
|
|
854
|
+
})
|
|
855
|
+
|
|
856
|
+
// 监听 agent 对话过程中的错误
|
|
857
|
+
framework.on('error', async (data) => {
|
|
858
|
+
try {
|
|
859
|
+
const errorObj = typeof data === 'object' ? data : { error: String(data) }
|
|
860
|
+
await this._extractErrorLesson({
|
|
861
|
+
name: errorObj.context || 'agent-error',
|
|
862
|
+
args: errorObj.data || {},
|
|
863
|
+
error: errorObj.error || errorObj.message || String(data),
|
|
864
|
+
source: 'agent'
|
|
865
|
+
})
|
|
866
|
+
} catch (err) {
|
|
867
|
+
log.warn('Auto agent error lesson extraction failed:', err.message)
|
|
868
|
+
}
|
|
869
|
+
})
|
|
870
|
+
|
|
871
|
+
// 监听 agent status 错误
|
|
872
|
+
framework.on('status', async (data) => {
|
|
873
|
+
if (data.status === 'error' && data.error) {
|
|
874
|
+
try {
|
|
875
|
+
await this._extractErrorLesson({
|
|
876
|
+
name: 'agent-status-error',
|
|
877
|
+
args: {},
|
|
878
|
+
error: data.error,
|
|
879
|
+
source: 'agent-status'
|
|
880
|
+
})
|
|
881
|
+
} catch (err) {
|
|
882
|
+
log.warn('Auto status error lesson extraction failed:', err.message)
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
})
|
|
886
|
+
|
|
887
|
+
// 监听会话上下文错误
|
|
888
|
+
framework.on('session:context-destroyed', async (data) => {
|
|
889
|
+
// 上下文销毁通常是正常的,但如果有错误信息则记录
|
|
890
|
+
if (data && data.error) {
|
|
891
|
+
try {
|
|
892
|
+
await this._extractErrorLesson({
|
|
893
|
+
name: 'session-context-error',
|
|
894
|
+
args: { sessionId: data.sessionId },
|
|
895
|
+
error: data.error,
|
|
896
|
+
source: 'session'
|
|
897
|
+
})
|
|
898
|
+
} catch (err) {
|
|
899
|
+
log.warn('Auto session error lesson extraction failed:', err.message)
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
})
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
/**
|
|
906
|
+
* 从错误中提取经验教训并保存
|
|
907
|
+
*/
|
|
908
|
+
async _extractErrorLesson(errorData) {
|
|
909
|
+
const { name, args, error, source } = errorData
|
|
910
|
+
|
|
911
|
+
// 构建提取提示 - 强调"如何下次避免"
|
|
912
|
+
const extractPrompt = `你是一个经验总结专家。请分析以下错误,总结如何在未来避免类似错误。
|
|
913
|
+
|
|
914
|
+
错误信息:
|
|
915
|
+
- 工具名称: ${name}
|
|
916
|
+
- 调用参数: ${JSON.stringify(args)}
|
|
917
|
+
- 错误原因: ${error}
|
|
918
|
+
- 来源: ${source || 'unknown'}
|
|
919
|
+
|
|
920
|
+
请按以下格式返回(仅返回 JSON,不要有其他内容):
|
|
921
|
+
{
|
|
922
|
+
"extract": true/false,
|
|
923
|
+
"name": "【避免指南】具体说明避免什么(如:避免不传 plugin 参数调用 ext_call)",
|
|
924
|
+
"tags": ["error", "avoid", "${name}"],
|
|
925
|
+
"content": "以【下次这样做】为开头,说明正确的做法。例如:\n【下次这样做】调用 ext_call 时必须传入 plugin、tool、args 三个参数。错误原因:缺少 plugin 参数导致扩展插件无法定位。"
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
如果错误是无关紧要的(如用户主动取消、超时重试等),返回:
|
|
929
|
+
{"extract": false}`
|
|
930
|
+
|
|
931
|
+
try {
|
|
932
|
+
const result = await this._runMemoryExtractionAgent(extractPrompt)
|
|
933
|
+
|
|
934
|
+
if (result && result.extract === true) {
|
|
935
|
+
try {
|
|
936
|
+
const saved = this._store.add({
|
|
937
|
+
name: result.name,
|
|
938
|
+
type: result.type || MEMORY_TYPES.FEEDBACK,
|
|
939
|
+
project: null,
|
|
940
|
+
tags: result.tags || ['error', 'avoid'],
|
|
941
|
+
body: result.content
|
|
942
|
+
})
|
|
943
|
+
} catch (saveErr) {
|
|
944
|
+
log.warn('[Memory] Failed to save error lesson:', saveErr.message)
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
} catch (err) {
|
|
948
|
+
log.warn('[Memory] Error lesson extraction failed:', err.message)
|
|
949
|
+
}
|
|
796
950
|
}
|
|
797
951
|
|
|
798
952
|
/**
|
|
@@ -870,16 +1024,18 @@ ${typeof assistantResponse === 'string' ? assistantResponse : JSON.stringify(ass
|
|
|
870
1024
|
|
|
871
1025
|
const { text } = await generateText({
|
|
872
1026
|
model: aiClient,
|
|
873
|
-
system: '
|
|
1027
|
+
system: '你是一个记忆提取专家。直接返回 JSON 格式的答案,不要输出任何思考过程、解释或其他内容。格式:{"extract":true/false,"name":"...","tags":[...],"content":"..."}',
|
|
874
1028
|
prompt,
|
|
875
1029
|
maxTokens: 500,
|
|
876
1030
|
temperature: 0.3,
|
|
877
1031
|
maxSteps: 1
|
|
878
|
-
})
|
|
1032
|
+
}).catch(err => {
|
|
1033
|
+
return { text: null };
|
|
1034
|
+
});
|
|
879
1035
|
|
|
880
1036
|
// 解析 JSON 响应
|
|
881
1037
|
if (text) {
|
|
882
|
-
const cleanedText = text.trim()
|
|
1038
|
+
const cleanedText = cleanResponse(text.trim())
|
|
883
1039
|
|
|
884
1040
|
// 移除 markdown 代码块包裹
|
|
885
1041
|
let jsonText = cleanedText
|
|
@@ -955,13 +1111,22 @@ ${typeof assistantResponse === 'string' ? assistantResponse : JSON.stringify(ass
|
|
|
955
1111
|
try {
|
|
956
1112
|
const userMemories = this._store.listByType(MEMORY_TYPES.USER, 10)
|
|
957
1113
|
const projectMemories = this._store.listByType(MEMORY_TYPES.PROJECT, 5)
|
|
1114
|
+
const feedbackMemories = this._store.search('', { type: MEMORY_TYPES.FEEDBACK, tags: ['avoid'], limit: 10 })
|
|
958
1115
|
|
|
959
|
-
if (userMemories.length === 0 && projectMemories.length === 0) {
|
|
1116
|
+
if (userMemories.length === 0 && projectMemories.length === 0 && feedbackMemories.length === 0) {
|
|
960
1117
|
return null
|
|
961
1118
|
}
|
|
962
1119
|
|
|
963
1120
|
const parts = ['【记忆上下文】']
|
|
964
1121
|
|
|
1122
|
+
// 错误避免指南(优先显示,放在最前面)
|
|
1123
|
+
if (feedbackMemories.length > 0) {
|
|
1124
|
+
parts.push('【错误避免指南 - 必须遵守】')
|
|
1125
|
+
for (const m of feedbackMemories) {
|
|
1126
|
+
parts.push(`- ${m.body}`)
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
|
|
965
1130
|
if (userMemories.length > 0) {
|
|
966
1131
|
parts.push('【用户偏好】')
|
|
967
1132
|
for (const m of userMemories) {
|