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.
Files changed (234) hide show
  1. package/.agent/.shared/ui-ux-pro-max/data/charts.csv +26 -0
  2. package/.agent/.shared/ui-ux-pro-max/data/colors.csv +97 -0
  3. package/.agent/.shared/ui-ux-pro-max/data/icons.csv +101 -0
  4. package/.agent/.shared/ui-ux-pro-max/data/landing.csv +31 -0
  5. package/.agent/.shared/ui-ux-pro-max/data/products.csv +97 -0
  6. package/.agent/.shared/ui-ux-pro-max/data/prompts.csv +24 -0
  7. package/.agent/.shared/ui-ux-pro-max/data/react-performance.csv +45 -0
  8. package/.agent/.shared/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  9. package/.agent/.shared/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
  10. package/.agent/.shared/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
  11. package/.agent/.shared/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  12. package/.agent/.shared/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
  13. package/.agent/.shared/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
  14. package/.agent/.shared/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  15. package/.agent/.shared/ui-ux-pro-max/data/stacks/react.csv +54 -0
  16. package/.agent/.shared/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
  17. package/.agent/.shared/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  18. package/.agent/.shared/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  19. package/.agent/.shared/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  20. package/.agent/.shared/ui-ux-pro-max/data/styles.csv +59 -0
  21. package/.agent/.shared/ui-ux-pro-max/data/typography.csv +58 -0
  22. package/.agent/.shared/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
  23. package/.agent/.shared/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  24. package/.agent/.shared/ui-ux-pro-max/data/web-interface.csv +31 -0
  25. package/.agent/.shared/ui-ux-pro-max/scripts/__pycache__/core.cpython-313.pyc +0 -0
  26. package/.agent/.shared/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-313.pyc +0 -0
  27. package/.agent/.shared/ui-ux-pro-max/scripts/core.py +258 -0
  28. package/.agent/.shared/ui-ux-pro-max/scripts/design_system.py +1067 -0
  29. package/.agent/.shared/ui-ux-pro-max/scripts/search.py +106 -0
  30. package/.agent/ARCHITECTURE.md +288 -0
  31. package/.agent/agents/ambient-agent.md +57 -0
  32. package/.agent/agents/debugger.md +55 -0
  33. package/.agent/agents/email-assistant.md +49 -0
  34. package/.agent/agents/file-manager.md +42 -0
  35. package/.agent/agents/python-developer.md +60 -0
  36. package/.agent/agents/scheduler.md +59 -0
  37. package/.agent/agents/web-developer.md +45 -0
  38. package/.agent/data/default.json +412 -3
  39. package/.agent/data/plugins-state.json +173 -174
  40. package/.agent/data/puppeteer-sessions/undefined.json +6 -0
  41. package/.agent/data/weixin-media/2026-04-08/img_1775618677512.jpg +0 -0
  42. package/.agent/data/weixin-media/2026-04-08/img_1775619073340.jpg +0 -0
  43. package/.agent/data/weixin-media/2026-04-08/img_1775619097536.jpg +0 -0
  44. package/.agent/data/weixin-media/2026-04-08/img_1775619209388.jpg +0 -0
  45. package/.agent/mcp_config_updated.json +12 -0
  46. package/.agent/memory/feedback/mnrdq5ps-ekch6c.md +9 -0
  47. package/.agent/memory/feedback/mnrdvj5i-ca3dkd.md +9 -0
  48. package/.agent/memory/feedback/mnre365e-7s4zax.md +9 -0
  49. package/.agent/memory/feedback/mnre36jn-nkfgmp.md +9 -0
  50. package/.agent/memory/feedback/mnre3805-kjiq6h.md +9 -0
  51. package/.agent/memory/feedback/test-1775733060827.md +6 -0
  52. package/.agent/memory/project/mnqx54u5-loqtoe.md +9 -0
  53. package/.agent/memory/project/mnqx84cv-mx6dmd.md +9 -0
  54. package/.agent/memory/reference/mnre3cww-penbo1.md +9 -0
  55. package/.agent/plugins/poster-plugin/fonts/NotoColorEmoji-Regular.ttf +0 -0
  56. package/.agent/plugins/poster-plugin/fonts/Symbola_hint.ttf +0 -0
  57. package/.agent/plugins/poster-plugin/src/index.js +30 -29
  58. package/.agent/plugins/puppeteer-plugin/README.md +147 -0
  59. package/.agent/plugins/puppeteer-plugin/index.js +1418 -0
  60. package/.agent/plugins/puppeteer-plugin/package.json +9 -0
  61. package/.agent/plugins.json +5 -11
  62. package/.agent/rules/GEMINI.md +273 -0
  63. package/.agent/rules/allow-rule.md +77 -0
  64. package/.agent/rules/log-rule.md +83 -0
  65. package/.agent/rules/security-rule.md +93 -0
  66. package/.agent/scripts/auto_preview.py +148 -0
  67. package/.agent/scripts/checklist.py +217 -0
  68. package/.agent/scripts/session_manager.py +120 -0
  69. package/.agent/scripts/verify_all.py +327 -0
  70. package/.agent/sessions/cli_default.json +636 -1833
  71. package/.agent/sessions/weixin_o9cq80zgZqKPA2-s59PN43GdDy1w@im.wechat.json +11097 -0
  72. package/.agent/skills/api-patterns/SKILL.md +81 -0
  73. package/.agent/skills/api-patterns/api-style.md +42 -0
  74. package/.agent/skills/api-patterns/auth.md +24 -0
  75. package/.agent/skills/api-patterns/documentation.md +26 -0
  76. package/.agent/skills/api-patterns/graphql.md +41 -0
  77. package/.agent/skills/api-patterns/rate-limiting.md +31 -0
  78. package/.agent/skills/api-patterns/response.md +37 -0
  79. package/.agent/skills/api-patterns/rest.md +40 -0
  80. package/.agent/skills/api-patterns/scripts/api_validator.py +211 -0
  81. package/.agent/skills/api-patterns/security-testing.md +122 -0
  82. package/.agent/skills/api-patterns/trpc.md +41 -0
  83. package/.agent/skills/api-patterns/versioning.md +22 -0
  84. package/.agent/skills/app-builder/SKILL.md +75 -0
  85. package/.agent/skills/app-builder/agent-coordination.md +71 -0
  86. package/.agent/skills/app-builder/feature-building.md +53 -0
  87. package/.agent/skills/app-builder/project-detection.md +34 -0
  88. package/.agent/skills/app-builder/scaffolding.md +118 -0
  89. package/.agent/skills/app-builder/tech-stack.md +40 -0
  90. package/.agent/skills/app-builder/templates/SKILL.md +39 -0
  91. package/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +76 -0
  92. package/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +92 -0
  93. package/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +88 -0
  94. package/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +88 -0
  95. package/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +83 -0
  96. package/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +90 -0
  97. package/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +90 -0
  98. package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +122 -0
  99. package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +122 -0
  100. package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +169 -0
  101. package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +134 -0
  102. package/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +83 -0
  103. package/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +119 -0
  104. package/.agent/skills/architecture/SKILL.md +55 -0
  105. package/.agent/skills/architecture/context-discovery.md +43 -0
  106. package/.agent/skills/architecture/examples.md +94 -0
  107. package/.agent/skills/architecture/pattern-selection.md +68 -0
  108. package/.agent/skills/architecture/patterns-reference.md +50 -0
  109. package/.agent/skills/architecture/trade-off-analysis.md +77 -0
  110. package/.agent/skills/clean-code/SKILL.md +201 -0
  111. package/.agent/skills/doc.md +177 -0
  112. package/.agent/skills/frontend-design/SKILL.md +418 -0
  113. package/.agent/skills/frontend-design/animation-guide.md +331 -0
  114. package/.agent/skills/frontend-design/color-system.md +311 -0
  115. package/.agent/skills/frontend-design/decision-trees.md +418 -0
  116. package/.agent/skills/frontend-design/motion-graphics.md +306 -0
  117. package/.agent/skills/frontend-design/scripts/accessibility_checker.py +183 -0
  118. package/.agent/skills/frontend-design/scripts/ux_audit.py +722 -0
  119. package/.agent/skills/frontend-design/typography-system.md +345 -0
  120. package/.agent/skills/frontend-design/ux-psychology.md +1116 -0
  121. package/.agent/skills/frontend-design/visual-effects.md +383 -0
  122. package/.agent/skills/i18n-localization/SKILL.md +154 -0
  123. package/.agent/skills/i18n-localization/scripts/i18n_checker.py +241 -0
  124. package/.agent/skills/mcp-builder/SKILL.md +176 -0
  125. package/.agent/skills/poster-design/SKILL.md +385 -0
  126. package/.agent/skills/web-design-guidelines/SKILL.md +57 -0
  127. package/.agent/workflows/brainstorm.md +113 -0
  128. package/.agent/workflows/create.md +59 -0
  129. package/.agent/workflows/debug.md +103 -0
  130. package/.agent/workflows/deploy.md +176 -0
  131. package/.agent/workflows/enhance.md +63 -0
  132. package/.agent/workflows/orchestrate.md +237 -0
  133. package/.agent/workflows/plan.md +89 -0
  134. package/.agent/workflows/preview.md +81 -0
  135. package/.agent/workflows/simple-test.md +42 -0
  136. package/.agent/workflows/status.md +86 -0
  137. package/.agent/workflows/structured-orchestrate.md +180 -0
  138. package/.agent/workflows/test.md +144 -0
  139. package/.agent/workflows/ui-ux-pro-max.md +296 -0
  140. package/.claude/settings.local.json +8 -1
  141. package/.env.example +56 -56
  142. package/37ua31lq.png +0 -0
  143. package/4ru0h1yo.png +0 -0
  144. package/55c90rsx.png +0 -0
  145. package/README.md +441 -441
  146. package/cli/src/commands/chat.js +69 -1
  147. package/cli/src/index.js +11 -2
  148. package/gud2mnws.png +0 -0
  149. package/output/poster_business.png.png +0 -0
  150. package/output/poster_business_product.png.png +0 -0
  151. package/output/poster_cyberpunk_neon.png.png +0 -0
  152. package/output/poster_festival.png.png +0 -0
  153. package/output/poster_foliko_personal.png.png +0 -0
  154. package/output/poster_french_romance.png.png +0 -0
  155. package/output/poster_guochao_landscape.png.png +0 -0
  156. package/output/poster_japanese_zen.png.png +0 -0
  157. package/output/poster_kawaii.png.png +0 -0
  158. package/output/poster_kawaii_hello.png.png +0 -0
  159. package/output/poster_luxury_gradient.png.png +0 -0
  160. package/output/poster_magazine_vogue.png.png +0 -0
  161. package/output/poster_minimal.png.png +0 -0
  162. package/output/poster_minimal_bw.png.png +0 -0
  163. package/output/poster_minimal_geometry.png.png +0 -0
  164. package/output/poster_pop_art.png.png +0 -0
  165. package/output/poster_sakura.png.png +0 -0
  166. package/output/poster_tech.png.png +0 -0
  167. package/output/poster_trendy.png.png +0 -0
  168. package/output/poster_vintage.png.png +0 -0
  169. package/output/poster_vintage_coffee.png.png +0 -0
  170. package/package.json +1 -1
  171. package/plugins/extension-executor-plugin.js +27 -1
  172. package/plugins/memory-plugin.js +197 -32
  173. package/skills/find-skills/AGENTS.md +162 -162
  174. package/skills/find-skills/SKILL.md +133 -133
  175. package/src/core/agent-chat.js +203 -112
  176. package/undefined.png +0 -0
  177. package/undefined.svg +1 -0
  178. package/xrrdyfr8.png +0 -0
  179. package/y9bfri9m.png +0 -0
  180. package/.agent/agents/code-assistant.json +0 -14
  181. package/.agent/agents/email-assistant.json +0 -14
  182. package/.agent/agents/file-assistant.json +0 -15
  183. package/.agent/agents/system-assistant.json +0 -15
  184. package/.agent/agents/web-assistant.json +0 -12
  185. package/.agent/data/ambient/goals.json +0 -50
  186. package/.agent/data/ambient/memories.json +0 -7
  187. package/.agent/data/scheduler/tasks.json +0 -1
  188. package/.agent/memory/core.md +0 -1
  189. package/.agent/memory/project/mnn93ogy-ypjn27.md +0 -9
  190. package/.agent/memory/project/mnn98fqy-5nhc1u.md +0 -25
  191. package/.agent/memory/reference/mnq3oenw-46haj6.md +0 -63
  192. package/.agent/memory/reference/mnq5qxm2-mjoooh.md +0 -116
  193. package/.agent/memory/user/mnm67t9m-x8rekk.md +0 -9
  194. package/.agent/memory/user/mnn5mmqh-w6aktx.md +0 -11
  195. package/.agent/memory/user/mnnbfhhn-dk1bd1.md +0 -22
  196. package/.agent/package.json +0 -8
  197. package/.agent/plugins/__pycache__/file_writer.cpython-312.pyc +0 -0
  198. package/.agent/plugins/daytona/README.md +0 -89
  199. package/.agent/plugins/daytona/index.js +0 -377
  200. package/.agent/plugins/daytona/package.json +0 -12
  201. package/.agent/plugins/marknative/README.md +0 -134
  202. package/.agent/plugins/marknative/fonts/SegoeUI Emoji.ttf +0 -0
  203. package/.agent/plugins/marknative/index.js +0 -256
  204. package/.agent/plugins/marknative/package.json +0 -12
  205. package/.agent/plugins/marknative/update-readme.js +0 -134
  206. package/.agent/plugins/poster-plugin/emojis/rocket.png +0 -1
  207. package/.agent/plugins/poster-plugin/yarn.lock +0 -1007
  208. package/.agent/plugins/system-info/index.js +0 -387
  209. package/.agent/plugins/system-info/package.json +0 -4
  210. package/.agent/plugins/system-info/test.js +0 -40
  211. package/.agent/python-scripts/test_sample.py +0 -24
  212. package/.agent/skills/agent-browser/SKILL.md +0 -311
  213. package/.agent/skills/agent-browser/TEST_PLAN.md +0 -200
  214. package/.agent/skills/sysinfo/SKILL.md +0 -38
  215. package/.agent/skills/sysinfo/system-info.sh +0 -130
  216. package/.agent/skills/workflow/SKILL.md +0 -324
  217. package/.agent/weixin.json +0 -6
  218. package/.agent/workflows/email-digest.json +0 -50
  219. package/.agent/workflows/file-backup.json +0 -21
  220. package/.agent/workflows/get-ip-notify.json +0 -32
  221. package/.agent/workflows/news-aggregator.json +0 -93
  222. package/.agent/workflows/news-dashboard-v2.json +0 -94
  223. package/.agent/workflows/notification-batch.json +0 -32
  224. package/output/emoji-segoe-test-v2.png +0 -0
  225. package/output/emoji-segoe-test.png +0 -0
  226. package/output/emoji-test.png +0 -0
  227. package/output/emoji-windows-test.png +0 -0
  228. package/output/foliko-emoji-poster.png +0 -0
  229. package/output/foliko-muji-poster-final.png +0 -0
  230. package/output/foliko-muji-poster-v2.png +0 -0
  231. package/output/foliko-muji-poster.png +0 -0
  232. package/output/foliko-share.png +0 -0
  233. package/output/progress-circle-test.png +0 -0
  234. package/output/vb-agent-poster.png +0 -0
@@ -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 === '--model' && args[i + 1]) {
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
- const command = args[0] || 'chat';
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
- await chatCommand(args.slice(1));
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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "foliko",
3
- "version": "1.1.4",
3
+ "version": "1.1.5",
4
4
  "description": "简约的插件化 Agent 框架",
5
5
  "main": "src/index.js",
6
6
  "type": "commonjs",
@@ -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}`,
@@ -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
- let braceCount = 0
154
- let inString = false
155
- let escaped = false
151
+ // 方法1:如果直接以 { 开头,尝试直接解析
152
+ if (text.startsWith('{')) {
153
+ // 查找配对的括号位置
154
+ let braceCount = 0
155
+ let inString = false
156
+ let escaped = false
156
157
 
157
- for (let i = 0; i < text.length; i++) {
158
- const char = text[i]
158
+ for (let i = 0; i < text.length; i++) {
159
+ const char = text[i]
159
160
 
160
- if (escaped) {
161
- escaped = false
162
- continue
163
- }
161
+ if (escaped) {
162
+ escaped = false
163
+ continue
164
+ }
164
165
 
165
- if (char === '\\' && inString) {
166
- escaped = true
167
- continue
168
- }
166
+ if (char === '\\' && inString) {
167
+ escaped = true
168
+ continue
169
+ }
169
170
 
170
- if (char === '"') {
171
- inString = !inString
172
- continue
173
- }
171
+ if (char === '"') {
172
+ inString = !inString
173
+ continue
174
+ }
174
175
 
175
- if (!inString) {
176
- if (char === '{') {
177
- braceCount++
178
- } else if (char === '}') {
179
- braceCount--
180
- if (braceCount === 0) {
181
- // 找到完整的 JSON 对象
182
- return text.substring(0, i + 1)
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: '你是一个记忆提取专家,直接返回 JSON,不要有其他内容。',
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) {