foliko 1.1.2 → 1.1.4

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 (205) hide show
  1. package/.agent/agents/code-assistant.json +14 -0
  2. package/.agent/agents/email-assistant.json +14 -0
  3. package/.agent/agents/file-assistant.json +15 -0
  4. package/.agent/agents/system-assistant.json +15 -0
  5. package/.agent/agents/web-assistant.json +12 -0
  6. package/.agent/data/ambient/goals.json +50 -0
  7. package/.agent/data/ambient/memories.json +7 -0
  8. package/.agent/data/default.json +3 -412
  9. package/.agent/data/plugins-state.json +174 -173
  10. package/.agent/data/scheduler/tasks.json +1 -0
  11. package/.agent/memory/core.md +1 -0
  12. package/.agent/memory/project/mnn93ogy-ypjn27.md +9 -0
  13. package/.agent/memory/project/mnn98fqy-5nhc1u.md +25 -0
  14. package/.agent/memory/reference/mnq3oenw-46haj6.md +63 -0
  15. package/.agent/memory/reference/mnq5qxm2-mjoooh.md +116 -0
  16. package/.agent/memory/user/mnm67t9m-x8rekk.md +9 -0
  17. package/.agent/memory/user/mnn5mmqh-w6aktx.md +11 -0
  18. package/.agent/memory/user/mnnbfhhn-dk1bd1.md +22 -0
  19. package/.agent/package.json +8 -0
  20. package/.agent/plugins/__pycache__/file_writer.cpython-312.pyc +0 -0
  21. package/.agent/plugins/daytona/README.md +89 -0
  22. package/.agent/plugins/daytona/index.js +377 -0
  23. package/.agent/plugins/daytona/package.json +12 -0
  24. package/.agent/plugins/marknative/README.md +134 -0
  25. package/.agent/plugins/marknative/fonts/SegoeUI Emoji.ttf +0 -0
  26. package/.agent/plugins/marknative/index.js +256 -0
  27. package/.agent/plugins/marknative/package.json +12 -0
  28. package/.agent/plugins/marknative/update-readme.js +134 -0
  29. package/.agent/plugins/poster-plugin/emojis/rocket.png +1 -0
  30. package/.agent/plugins/poster-plugin/fonts/SegoeUI Emoji.ttf +0 -0
  31. package/.agent/plugins/poster-plugin/src/elements/text.js +3 -1
  32. package/.agent/plugins/poster-plugin/src/fonts.js +10 -0
  33. package/.agent/plugins/poster-plugin/yarn.lock +1007 -0
  34. package/.agent/plugins/system-info/index.js +387 -0
  35. package/.agent/plugins/system-info/package.json +4 -0
  36. package/.agent/plugins/system-info/test.js +40 -0
  37. package/.agent/plugins.json +11 -5
  38. package/.agent/python-scripts/test_sample.py +24 -0
  39. package/.agent/sessions/cli_default.json +1869 -691
  40. package/.agent/skills/agent-browser/SKILL.md +311 -0
  41. package/.agent/skills/agent-browser/TEST_PLAN.md +200 -0
  42. package/.agent/skills/sysinfo/SKILL.md +38 -0
  43. package/.agent/skills/sysinfo/system-info.sh +130 -0
  44. package/.agent/skills/workflow/SKILL.md +324 -0
  45. package/.agent/weixin.json +6 -0
  46. package/.agent/workflows/email-digest.json +50 -0
  47. package/.agent/workflows/file-backup.json +21 -0
  48. package/.agent/workflows/get-ip-notify.json +32 -0
  49. package/.agent/workflows/news-aggregator.json +93 -0
  50. package/.agent/workflows/news-dashboard-v2.json +94 -0
  51. package/.agent/workflows/notification-batch.json +32 -0
  52. package/.claude/settings.local.json +1 -20
  53. package/.env.example +56 -56
  54. package/README.md +441 -441
  55. package/cli/src/commands/chat.js +22 -13
  56. package/cli/src/ui/chat-ui.js +50 -37
  57. package/output/emoji-segoe-test-v2.png +0 -0
  58. package/output/emoji-segoe-test.png +0 -0
  59. package/output/emoji-test.png +0 -0
  60. package/output/emoji-windows-test.png +0 -0
  61. package/output/foliko-emoji-poster.png +0 -0
  62. package/output/foliko-muji-poster-final.png +0 -0
  63. package/output/foliko-muji-poster-v2.png +0 -0
  64. package/output/foliko-muji-poster.png +0 -0
  65. package/output/foliko-share.png +0 -0
  66. package/output/progress-circle-test.png +0 -0
  67. package/output/vb-agent-poster.png +0 -0
  68. package/package.json +1 -2
  69. package/plugins/default-plugins.js +4 -3
  70. package/plugins/extension-executor-plugin.js +12 -91
  71. package/plugins/file-system-plugin.js +19 -4
  72. package/plugins/memory-plugin.js +33 -4
  73. package/plugins/subagent-plugin.js +14 -37
  74. package/plugins/weixin-plugin.js +40 -168
  75. package/skills/find-skills/AGENTS.md +162 -162
  76. package/skills/find-skills/SKILL.md +133 -133
  77. package/skills/poster-guide/SKILL.md +669 -1426
  78. package/src/core/agent-chat.js +439 -269
  79. package/src/core/agent.js +3 -6
  80. package/.agent/.shared/ui-ux-pro-max/data/charts.csv +0 -26
  81. package/.agent/.shared/ui-ux-pro-max/data/colors.csv +0 -97
  82. package/.agent/.shared/ui-ux-pro-max/data/icons.csv +0 -101
  83. package/.agent/.shared/ui-ux-pro-max/data/landing.csv +0 -31
  84. package/.agent/.shared/ui-ux-pro-max/data/products.csv +0 -97
  85. package/.agent/.shared/ui-ux-pro-max/data/prompts.csv +0 -24
  86. package/.agent/.shared/ui-ux-pro-max/data/react-performance.csv +0 -45
  87. package/.agent/.shared/ui-ux-pro-max/data/stacks/flutter.csv +0 -53
  88. package/.agent/.shared/ui-ux-pro-max/data/stacks/html-tailwind.csv +0 -56
  89. package/.agent/.shared/ui-ux-pro-max/data/stacks/jetpack-compose.csv +0 -53
  90. package/.agent/.shared/ui-ux-pro-max/data/stacks/nextjs.csv +0 -53
  91. package/.agent/.shared/ui-ux-pro-max/data/stacks/nuxt-ui.csv +0 -51
  92. package/.agent/.shared/ui-ux-pro-max/data/stacks/nuxtjs.csv +0 -59
  93. package/.agent/.shared/ui-ux-pro-max/data/stacks/react-native.csv +0 -52
  94. package/.agent/.shared/ui-ux-pro-max/data/stacks/react.csv +0 -54
  95. package/.agent/.shared/ui-ux-pro-max/data/stacks/shadcn.csv +0 -61
  96. package/.agent/.shared/ui-ux-pro-max/data/stacks/svelte.csv +0 -54
  97. package/.agent/.shared/ui-ux-pro-max/data/stacks/swiftui.csv +0 -51
  98. package/.agent/.shared/ui-ux-pro-max/data/stacks/vue.csv +0 -50
  99. package/.agent/.shared/ui-ux-pro-max/data/styles.csv +0 -59
  100. package/.agent/.shared/ui-ux-pro-max/data/typography.csv +0 -58
  101. package/.agent/.shared/ui-ux-pro-max/data/ui-reasoning.csv +0 -101
  102. package/.agent/.shared/ui-ux-pro-max/data/ux-guidelines.csv +0 -100
  103. package/.agent/.shared/ui-ux-pro-max/data/web-interface.csv +0 -31
  104. package/.agent/.shared/ui-ux-pro-max/scripts/__pycache__/core.cpython-313.pyc +0 -0
  105. package/.agent/.shared/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-313.pyc +0 -0
  106. package/.agent/.shared/ui-ux-pro-max/scripts/core.py +0 -258
  107. package/.agent/.shared/ui-ux-pro-max/scripts/design_system.py +0 -1067
  108. package/.agent/.shared/ui-ux-pro-max/scripts/search.py +0 -106
  109. package/.agent/ARCHITECTURE.md +0 -288
  110. package/.agent/agents/ambient-agent.md +0 -57
  111. package/.agent/agents/debugger.md +0 -55
  112. package/.agent/agents/email-assistant.md +0 -49
  113. package/.agent/agents/file-manager.md +0 -42
  114. package/.agent/agents/python-developer.md +0 -60
  115. package/.agent/agents/scheduler.md +0 -59
  116. package/.agent/agents/web-developer.md +0 -45
  117. package/.agent/data/puppeteer-sessions/undefined.json +0 -6
  118. package/.agent/data/weixin-media/2026-04-08/img_1775618677512.jpg +0 -0
  119. package/.agent/data/weixin-media/2026-04-08/img_1775619073340.jpg +0 -0
  120. package/.agent/data/weixin-media/2026-04-08/img_1775619097536.jpg +0 -0
  121. package/.agent/data/weixin-media/2026-04-08/img_1775619209388.jpg +0 -0
  122. package/.agent/mcp_config_updated.json +0 -12
  123. package/.agent/plugins/poster-plugin/fonts/NotoColorEmoji-Regular.ttf +0 -0
  124. package/.agent/plugins/puppeteer-plugin/README.md +0 -147
  125. package/.agent/plugins/puppeteer-plugin/index.js +0 -1418
  126. package/.agent/plugins/puppeteer-plugin/package.json +0 -9
  127. package/.agent/rules/GEMINI.md +0 -273
  128. package/.agent/rules/allow-rule.md +0 -77
  129. package/.agent/rules/log-rule.md +0 -83
  130. package/.agent/rules/security-rule.md +0 -93
  131. package/.agent/scripts/auto_preview.py +0 -148
  132. package/.agent/scripts/checklist.py +0 -217
  133. package/.agent/scripts/session_manager.py +0 -120
  134. package/.agent/scripts/verify_all.py +0 -327
  135. package/.agent/sessions/weixin_o9cq80zgZqKPA2-s59PN43GdDy1w@im.wechat.json +0 -11097
  136. package/.agent/skills/api-patterns/SKILL.md +0 -81
  137. package/.agent/skills/api-patterns/api-style.md +0 -42
  138. package/.agent/skills/api-patterns/auth.md +0 -24
  139. package/.agent/skills/api-patterns/documentation.md +0 -26
  140. package/.agent/skills/api-patterns/graphql.md +0 -41
  141. package/.agent/skills/api-patterns/rate-limiting.md +0 -31
  142. package/.agent/skills/api-patterns/response.md +0 -37
  143. package/.agent/skills/api-patterns/rest.md +0 -40
  144. package/.agent/skills/api-patterns/scripts/api_validator.py +0 -211
  145. package/.agent/skills/api-patterns/security-testing.md +0 -122
  146. package/.agent/skills/api-patterns/trpc.md +0 -41
  147. package/.agent/skills/api-patterns/versioning.md +0 -22
  148. package/.agent/skills/app-builder/SKILL.md +0 -75
  149. package/.agent/skills/app-builder/agent-coordination.md +0 -71
  150. package/.agent/skills/app-builder/feature-building.md +0 -53
  151. package/.agent/skills/app-builder/project-detection.md +0 -34
  152. package/.agent/skills/app-builder/scaffolding.md +0 -118
  153. package/.agent/skills/app-builder/tech-stack.md +0 -40
  154. package/.agent/skills/app-builder/templates/SKILL.md +0 -39
  155. package/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +0 -76
  156. package/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +0 -92
  157. package/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +0 -88
  158. package/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +0 -88
  159. package/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +0 -83
  160. package/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +0 -90
  161. package/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +0 -90
  162. package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +0 -122
  163. package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +0 -122
  164. package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +0 -169
  165. package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +0 -134
  166. package/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +0 -83
  167. package/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +0 -119
  168. package/.agent/skills/architecture/SKILL.md +0 -55
  169. package/.agent/skills/architecture/context-discovery.md +0 -43
  170. package/.agent/skills/architecture/examples.md +0 -94
  171. package/.agent/skills/architecture/pattern-selection.md +0 -68
  172. package/.agent/skills/architecture/patterns-reference.md +0 -50
  173. package/.agent/skills/architecture/trade-off-analysis.md +0 -77
  174. package/.agent/skills/clean-code/SKILL.md +0 -201
  175. package/.agent/skills/doc.md +0 -177
  176. package/.agent/skills/frontend-design/SKILL.md +0 -418
  177. package/.agent/skills/frontend-design/animation-guide.md +0 -331
  178. package/.agent/skills/frontend-design/color-system.md +0 -311
  179. package/.agent/skills/frontend-design/decision-trees.md +0 -418
  180. package/.agent/skills/frontend-design/motion-graphics.md +0 -306
  181. package/.agent/skills/frontend-design/scripts/accessibility_checker.py +0 -183
  182. package/.agent/skills/frontend-design/scripts/ux_audit.py +0 -722
  183. package/.agent/skills/frontend-design/typography-system.md +0 -345
  184. package/.agent/skills/frontend-design/ux-psychology.md +0 -1116
  185. package/.agent/skills/frontend-design/visual-effects.md +0 -383
  186. package/.agent/skills/i18n-localization/SKILL.md +0 -154
  187. package/.agent/skills/i18n-localization/scripts/i18n_checker.py +0 -241
  188. package/.agent/skills/mcp-builder/SKILL.md +0 -176
  189. package/.agent/skills/web-design-guidelines/SKILL.md +0 -57
  190. package/.agent/workflows/brainstorm.md +0 -113
  191. package/.agent/workflows/create.md +0 -59
  192. package/.agent/workflows/debug.md +0 -103
  193. package/.agent/workflows/deploy.md +0 -176
  194. package/.agent/workflows/enhance.md +0 -63
  195. package/.agent/workflows/orchestrate.md +0 -237
  196. package/.agent/workflows/plan.md +0 -89
  197. package/.agent/workflows/preview.md +0 -81
  198. package/.agent/workflows/simple-test.md +0 -42
  199. package/.agent/workflows/status.md +0 -86
  200. package/.agent/workflows/structured-orchestrate.md +0 -180
  201. package/.agent/workflows/test.md +0 -144
  202. package/.agent/workflows/ui-ux-pro-max.md +0 -296
  203. package/output/beef-love-poster.png +0 -0
  204. package/output/international-news-daily.png +0 -0
  205. package/poster-test-2.png +0 -0
@@ -71,9 +71,18 @@ function parseArgs(args) {
71
71
  options.baseURL = args[++i];
72
72
  } else if (arg === '--api-key' && args[i + 1]) {
73
73
  options.apiKey = args[++i];
74
+ } else if (arg === '--stream') {
75
+ options.stream = true;
76
+ } else if (arg === '--no-stream') {
77
+ options.stream = false;
74
78
  }
75
79
  }
76
80
 
81
+ // 默认开启流式
82
+ if (options.stream === undefined) {
83
+ options.stream = true;
84
+ }
85
+
77
86
  return options;
78
87
  }
79
88
 
@@ -94,16 +103,21 @@ async function chatCommand(args) {
94
103
  baseURL: options.baseURL,
95
104
  apiKey: options.apiKey,
96
105
  providerOptions: {
97
- maxOutputTokens: 16384,
98
- reasoning_split: true,
106
+ maxOutputTokens: 8192,
99
107
  },
100
108
  },
101
109
  });
102
110
 
103
- // 创建 Agent
104
- const agent = framework.createAgent({
105
- name: 'FolikoAgent',
106
- systemPrompt: `你是一个有帮助的助手,擅长回答问题和执行任务。
111
+ // 使用框架的 _mainAgent(已注册 memory-context 等)
112
+ const agent = framework._mainAgent;
113
+ if (!agent) {
114
+ console.error('错误:框架未正确初始化,请检查 AI 配置');
115
+ process.exit(1);
116
+ }
117
+
118
+ // 更新 _mainAgent 的配置
119
+ agent.setMetadata('WORK_DIR', process.cwd());
120
+ agent.setSystemPrompt(`你是一个有帮助的助手,擅长回答问题和执行任务。
107
121
  **重要:** 子Agent 匹配规则必须遵守:
108
122
  - 根据【子 Agent 匹配表】,将任务委托给最匹配的子Agent处理
109
123
  - 使用 subagent_call 工具并指定 agentName 来委托任务
@@ -111,15 +125,10 @@ async function chatCommand(args) {
111
125
  **命令执行规范:**
112
126
  - 执行 npx skills add / npx skills remove / npx skills list 命令时,必须自动添加参数:-a openclaw -y
113
127
  - 禁止添加 -g 参数
114
- - 例如:npx skills add xxx 应该执行为 npx skills add xxx -a openclaw -y`,
115
- sharedPrompt: `工作目录: {{WORK_DIR}}`,
116
- metadata: {
117
- WORK_DIR: process.cwd(), // 覆盖内置的 WORK_DIR
118
- },
119
- });
128
+ - 例如:npx skills add xxx 应该执行为 npx skills add xxx -a openclaw -y`);
120
129
 
121
130
  // 初始化 UI
122
- const ui = new ChatUI(agent);
131
+ const ui = new ChatUI(agent, { stream: options.stream });
123
132
 
124
133
  // 监听通知事件,在 CLI 中显示
125
134
  // 显示当前会话的通知,以及没有指定 sessionId 的广播通知
@@ -13,6 +13,9 @@ class ChatUI {
13
13
  this.rl = null;
14
14
  this.lines = []; // 多行输入的累积
15
15
 
16
+ // 流式模式(默认开启)
17
+ this.stream = options.stream !== false;
18
+
16
19
  // 会话管理
17
20
  this.sessionId = options.sessionId || 'cli_default';
18
21
  this.sessionPlugin = null;
@@ -121,13 +124,6 @@ class ChatUI {
121
124
  * 发送消息并显示响应
122
125
  */
123
126
  async sendMessage(message) {
124
- // console.log();
125
-
126
- // // 添加用户消息到会话历史
127
- // if (this.sessionPlugin) {
128
- // this.sessionPlugin.addMessage(this.sessionId, { role: 'user', content: message });
129
- // }
130
-
131
127
  // 用于打断的标志
132
128
  let interrupted = false;
133
129
 
@@ -145,43 +141,65 @@ class ChatUI {
145
141
  let fullResponse = '';
146
142
 
147
143
  try {
148
- let lineBuffer = '';
149
144
  const renderState = { inThink: false, inCodeBlock: false };
150
-
151
- console.log(colored('● ', GREEN));
152
- // console.log()
153
-
154
145
  const runWithContext = this.agent.framework?.runWithContext.bind(this.agent.framework);
155
146
  const { sessionId } = this;
156
147
 
157
- await runWithContext({ sessionId }, async () => {
158
- for await (const chunk of this.agent.chatStream(message, { sessionId })) {
159
- if (interrupted) break;
148
+ if (this.stream) {
149
+ // 流式模式
150
+ console.log(colored('● ', GREEN));
151
+
152
+ let lineBuffer = '';
153
+ await runWithContext({ sessionId }, async () => {
154
+ for await (const chunk of this.agent.chatStream(message, { sessionId })) {
155
+ if (interrupted) break;
160
156
 
161
- if (chunk.type === 'text') {
162
- fullResponse += chunk.text;
163
- lineBuffer += chunk.text;
157
+ if (chunk.type === 'text') {
158
+ fullResponse += chunk.text;
159
+ lineBuffer += chunk.text;
164
160
 
165
- while (lineBuffer.includes('\n')) {
166
- if (interrupted) break;
161
+ while (lineBuffer.includes('\n')) {
162
+ if (interrupted) break;
167
163
 
168
- const nlIndex = lineBuffer.indexOf('\n');
169
- const line = lineBuffer.substring(0, nlIndex);
170
- lineBuffer = lineBuffer.substring(nlIndex + 1);
171
- if (line.trim()) {
172
- console.log(renderLine(line, renderState));
164
+ const nlIndex = lineBuffer.indexOf('\n');
165
+ const line = lineBuffer.substring(0, nlIndex);
166
+ lineBuffer = lineBuffer.substring(nlIndex + 1);
167
+ if (line.trim()) {
168
+ console.log(renderLine(line, renderState));
169
+ }
173
170
  }
171
+ } else if (chunk.type === 'tool-call') {
172
+ console.log(`\n${colored('[工具调用]', YELLOW)} ${chunk.toolName}`);
173
+ } else if (chunk.type === 'error') {
174
+ console.error(`\n${colored('[错误]', RED)} ${chunk.error}`);
174
175
  }
175
- } else if (chunk.type === 'tool-call') {
176
- console.log(`\n${colored('[工具调用]', YELLOW)} ${chunk.toolName}`);
177
- } else if (chunk.type === 'error') {
178
- console.error(`\n${colored('[错误]', RED)} ${chunk.error}`);
179
176
  }
177
+ });
178
+
179
+ if (lineBuffer.trim() && !interrupted) {
180
+ console.log(renderLine(lineBuffer, renderState));
180
181
  }
181
- });
182
+ } else {
183
+ // 非流式模式
184
+ console.log(colored('○ ', CYAN) + '处理中...\n');
182
185
 
183
- if (lineBuffer.trim() && !interrupted) {
184
- console.log(renderLine(lineBuffer, renderState));
186
+ const result = await runWithContext({ sessionId }, async () => {
187
+ return await this.agent.chat(message, { sessionId });
188
+ });
189
+
190
+ if (interrupted) return;
191
+
192
+ fullResponse = result.message;
193
+
194
+ // 一次性渲染完整响应
195
+ const lines = fullResponse.split('\n');
196
+ for (const line of lines) {
197
+ if (line.trim()) {
198
+ console.log(renderLine(line, renderState));
199
+ } else {
200
+ console.log();
201
+ }
202
+ }
185
203
  }
186
204
  } catch (err) {
187
205
  if (!interrupted) {
@@ -189,11 +207,6 @@ class ChatUI {
189
207
  }
190
208
  } finally {
191
209
  process.removeListener('SIGINT', interruptHandler);
192
-
193
- // 添加助手回复到会话历史
194
- // if (this.sessionPlugin && fullResponse) {
195
- // this.sessionPlugin.addMessage(this.sessionId, { role: 'assistant', content: fullResponse });
196
- // }
197
210
  }
198
211
  }
199
212
  }
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.2",
3
+ "version": "1.1.4",
4
4
  "description": "简约的插件化 Agent 框架",
5
5
  "main": "src/index.js",
6
6
  "type": "commonjs",
@@ -59,7 +59,6 @@
59
59
  "@larksuiteoapi/node-sdk": "^1.59.0",
60
60
  "@modelcontextprotocol/sdk": "^1.27.1",
61
61
  "ai": "^6.0.146",
62
- "dayjs": "^1.11.20",
63
62
  "dotenv": "^17.3.1",
64
63
  "gate-api": "^7.2.57",
65
64
  "hono": "^4.12.9",
@@ -289,7 +289,8 @@ async function bootstrapDefaults(framework, config = {}) {
289
289
  }
290
290
 
291
291
  // 1.5 创建主 Agent(供 Telegram 等需要绑定 Agent 的插件使用)
292
- if (!framework._mainAgent && aiConfig.provider) {
292
+ // 注意:即使没有 AI 配置也创建主 agent,让 memory-plugin 等能注册 prompt parts
293
+ if (!framework._mainAgent) {
293
294
  const { Agent } = require('../src/core/agent')
294
295
  const aiPlugin = framework.pluginManager.get('ai')
295
296
  const aiClient = aiPlugin ? aiPlugin.getAIClient() : null
@@ -298,8 +299,8 @@ async function bootstrapDefaults(framework, config = {}) {
298
299
  framework._mainAgent = framework.createAgent({
299
300
  name: 'MainAgent',
300
301
  systemPrompt: '你是一个智能助手。当用户提出问题或任务时,你会主动分析需求,选择合适的工具来获取信息或执行操作。你善于将复杂任务拆解为多个步骤,通过工具协作完成。',
301
- model: aiConfig.model,
302
- provider: aiConfig.provider,
302
+ model: aiConfig.model || 'deepseek-chat',
303
+ provider: aiConfig.provider || 'deepseek',
303
304
  apiKey: aiConfig.apiKey,
304
305
  baseURL: aiConfig.baseURL
305
306
  })
@@ -23,52 +23,6 @@ class ExtensionExecutorPlugin extends Plugin {
23
23
  this._extensions = new Map();
24
24
  }
25
25
 
26
- /**
27
- * 从 JSON Schema 构建 Zod Schema
28
- * @param {Object} jsonSchema - JSON Schema 对象
29
- * @returns {z.ZodObject}
30
- */
31
- _buildZodSchema(jsonSchema) {
32
- const properties = jsonSchema.properties || {};
33
- const required = jsonSchema.required || [];
34
- const shape = {};
35
-
36
- for (const [name, prop] of Object.entries(properties)) {
37
- let field;
38
- const isRequired = required.includes(name);
39
-
40
- switch (prop.type) {
41
- case 'string':
42
- field = z.string();
43
- break;
44
- case 'number':
45
- field = z.number();
46
- break;
47
- case 'boolean':
48
- field = z.boolean();
49
- break;
50
- case 'array':
51
- field = z.array(z.any());
52
- break;
53
- case 'object':
54
- field = z.object({});
55
- break;
56
- default:
57
- field = z.any();
58
- }
59
-
60
- if (prop.description) {
61
- field = field.describe(prop.description);
62
- }
63
- if (!isRequired) {
64
- field = field.optional();
65
- }
66
- shape[name] = field;
67
- }
68
-
69
- return z.object(shape);
70
- }
71
-
72
26
  install(framework) {
73
27
  this._framework = framework;
74
28
 
@@ -178,49 +132,20 @@ class ExtensionExecutorPlugin extends Plugin {
178
132
  args: z.record(z.any()).optional().describe('工具参数'),
179
133
  }),
180
134
  execute: async (args) => {
181
- try {
182
- const { plugin, tool, args: toolArgs = {} } = args;
183
- log.info(` ext_call: plugin=${plugin}, tool=${tool}`);
184
-
185
- const ext = this._extensions.get(plugin);
186
- if (!ext) {
187
- return { success: false, error: `扩展插件 '${plugin}' 不存在` };
188
- }
135
+ const { plugin, tool, args: toolArgs = {} } = args;
136
+ log.info(` ext_call: plugin=${plugin}, tool=${tool}`);
189
137
 
190
- const toolDef = ext.tools.find((t) => t.name === tool);
191
- if (!toolDef) {
192
- const availableTools = ext.tools.map((t) => t.name).join(', ');
193
- return {
194
- success: false,
195
- error: `扩展工具 '${tool}' 不存在。可用工具: ${availableTools || '无'}`
196
- };
197
- }
138
+ const ext = this._extensions.get(plugin);
139
+ if (!ext) {
140
+ return { success: false, error: `扩展插件 '${plugin}' 不存在` };
141
+ }
198
142
 
199
- // 验证参数
200
- if (toolDef.inputSchema) {
201
- try {
202
- const schema = toolDef.inputSchema instanceof z.ZodType
203
- ? toolDef.inputSchema
204
- : this._buildZodSchema(toolDef.inputSchema);
205
- schema.parse(toolArgs);
206
- } catch (err) {
207
- if (err instanceof z.ZodError) {
208
- const fieldErrors = err.errors.map((e) => `${e.path.join('.')}: ${e.message}`).join('; ');
209
- return {
210
- success: false,
211
- error: `参数错误: ${fieldErrors}`,
212
- inputSchema: toolDef.inputSchema,
213
- };
214
- }
215
- return {
216
- success: false,
217
- error: `参数验证失败: ${err.message}`,
218
- inputSchema: toolDef.inputSchema,
219
- };
220
- }
221
- }
143
+ const toolDef = ext.tools.find((t) => t.name === tool);
144
+ if (!toolDef) {
145
+ return { success: false, error: `扩展工具 '${tool}' 不存在` };
146
+ }
222
147
 
223
-
148
+ try {
224
149
  // 触发扩展工具开始事件
225
150
  framework.emit('tool:call', {
226
151
  name: `${plugin}:${tool}`,
@@ -295,11 +220,7 @@ class ExtensionExecutorPlugin extends Plugin {
295
220
 
296
221
  const toolDef = ext.tools.find((t) => t.name === tool);
297
222
  if (!toolDef) {
298
- const availableTools = ext.tools.map((t) => t.name).join(', ');
299
- return {
300
- success: false,
301
- error: `扩展工具 '${tool}' 不存在。可用工具: ${availableTools || '无'}`
302
- };
223
+ return { success: false, error: `扩展工具 '${tool}' 不存在` };
303
224
  }
304
225
 
305
226
  return {
@@ -827,9 +827,10 @@ class FileSystemPlugin extends Plugin {
827
827
  timeout: z.number().optional().describe('超时时间(ms),默认 30000'),
828
828
  proxy: z.boolean().optional().describe('是否使用代理,默认 false。访问失败时可自动设为 true 重试'),
829
829
  toMarkdown: z.boolean().default(true).describe('是否将 HTML 响应转换为 Markdown 格式,默认 true'),
830
+ maxLength: z.number().optional().describe('最大返回长度(字符数),超过则截断')
830
831
  }),
831
832
  execute: async (args, framework) => {
832
- const { url, method = 'GET', headers = {}, body, timeout = 30000, proxy = false, toMarkdown = true } = args
833
+ const { url, method = 'GET', headers = {}, body, timeout = 30000, proxy = false, toMarkdown = true, maxLength } = args
833
834
  try {
834
835
  const controller = new AbortController()
835
836
  const timeoutId = setTimeout(() => controller.abort(), timeout)
@@ -858,18 +859,27 @@ class FileSystemPlugin extends Plugin {
858
859
  const isHtml = /<[a-z][\s\S]*>/i.test(data) || data.trim().startsWith('<')
859
860
  if (isHtml) {
860
861
  try {
862
+
861
863
  const markdown = NodeHtmlMarkdown.translate(data)
864
+ // 限制返回长度
865
+ const truncatedMarkdown = maxLength && markdown.length > maxLength
866
+ ? markdown.substring(0, maxLength) + '\n\n...(truncated)'
867
+ : markdown
862
868
  return {
863
869
  success: true,
864
870
  status: response.status,
865
871
  statusText: response.statusText,
866
872
  headers: Object.fromEntries(response.headers.entries()),
867
873
  usedProxy: proxy,
868
- markdown: markdown,
874
+ markdown: truncatedMarkdown,
869
875
  originalLength: markdown.length,
876
+ truncated: maxLength && markdown.length > maxLength
870
877
  }
871
878
  } catch (e) {
872
879
  // 转换失败时返回原始 body
880
+ const truncatedBody = maxLength && data.length > maxLength
881
+ ? data.substring(0, maxLength) + '\n\n...(truncated)'
882
+ : data
873
883
  return {
874
884
  success: true,
875
885
  status: response.status,
@@ -877,8 +887,9 @@ class FileSystemPlugin extends Plugin {
877
887
  headers: Object.fromEntries(response.headers.entries()),
878
888
  usedProxy: proxy,
879
889
  markdown: null,
880
- body: data,
890
+ body: truncatedBody,
881
891
  originalLength: data.length,
892
+ truncated: maxLength && data.length > maxLength,
882
893
  markdownError: e.message
883
894
  }
884
895
  }
@@ -886,14 +897,18 @@ class FileSystemPlugin extends Plugin {
886
897
  }
887
898
 
888
899
  // toMarkdown 为 false 或非 HTML 内容时,返回原始内容
900
+ const truncatedData = maxLength && typeof data === 'string' && data.length > maxLength
901
+ ? data.substring(0, maxLength) + '\n\n...(truncated)'
902
+ : data
889
903
  return {
890
904
  success: true,
891
905
  status: response.status,
892
906
  statusText: response.statusText,
893
907
  headers: Object.fromEntries(response.headers.entries()),
894
908
  usedProxy: proxy,
895
- body: data,
909
+ body: truncatedData,
896
910
  originalLength: typeof data === 'string' ? data.length : null,
911
+ truncated: maxLength && typeof data === 'string' && data.length > maxLength
897
912
  }
898
913
  } catch (error) {
899
914
  return {
@@ -9,6 +9,7 @@ const log = logger.child('Memory')
9
9
  const { z } = require('zod')
10
10
  const fs = require('fs')
11
11
  const path = require('path')
12
+ const { EventEmitter } = require('events')
12
13
 
13
14
  /**
14
15
  * 记忆类型常量
@@ -190,8 +191,9 @@ function _extractJSON(text) {
190
191
  /**
191
192
  * MemoryStore - 双层存储(内存 + 文件)
192
193
  */
193
- class MemoryStore {
194
+ class MemoryStore extends EventEmitter {
194
195
  constructor(baseDir) {
196
+ super()
195
197
  this._baseDir = path.resolve(process.cwd(), baseDir)
196
198
  this._memory = new Map() // memoryId -> memory object
197
199
  this._indexByType = new Map() // type -> Set of memoryIds
@@ -353,6 +355,10 @@ class MemoryStore {
353
355
  this._fileIndex.set(id, filePath)
354
356
 
355
357
  log.debug(`Added memory: ${id} (${newMemory.type})`)
358
+
359
+ // 触发变化事件
360
+ this.emit('change', { action: 'add', memory: newMemory })
361
+
356
362
  return newMemory
357
363
  }
358
364
 
@@ -393,6 +399,10 @@ class MemoryStore {
393
399
  this._fileIndex.set(id, filePath)
394
400
 
395
401
  log.debug(`Updated memory: ${id}`)
402
+
403
+ // 触发变化事件
404
+ this.emit('change', { action: 'update', memory })
405
+
396
406
  return memory
397
407
  }
398
408
 
@@ -415,6 +425,10 @@ class MemoryStore {
415
425
  this._fileIndex.delete(id)
416
426
 
417
427
  log.debug(`Deleted memory: ${id}`)
428
+
429
+ // 触发变化事件
430
+ this.emit('change', { action: 'delete', memory })
431
+
418
432
  return true
419
433
  }
420
434
 
@@ -549,6 +563,9 @@ class MemoryPlugin extends Plugin {
549
563
  // 注册 memory-context 到系统提示(优先级 350)
550
564
  this._registerMemoryContext(framework)
551
565
 
566
+ // 监听记忆变化,动态刷新系统提示词
567
+ this._setupDynamicRefresh(framework)
568
+
552
569
  log.info('Memory plugin started')
553
570
  return this
554
571
  }
@@ -899,21 +916,34 @@ ${typeof assistantResponse === 'string' ? assistantResponse : JSON.stringify(ass
899
916
  * 注册 memory-context 到系统提示
900
917
  */
901
918
  _registerMemoryContext(framework) {
902
- // 获取主 agent 并注册 memory-context 部分
903
919
  const mainAgent = framework._mainAgent
904
920
  if (mainAgent) {
905
921
  mainAgent.registerPromptPart('memory-context', 350, () => {
906
922
  return this._buildMemoryContext()
907
923
  })
924
+ mainAgent._refreshContext()
908
925
  }
909
926
 
910
- // 也监听 framework:ready 事件,以防主 agent 还没创建
911
927
  framework.on('framework:ready', () => {
912
928
  const agent = framework._mainAgent
913
929
  if (agent) {
914
930
  agent.registerPromptPart('memory-context', 350, () => {
915
931
  return this._buildMemoryContext()
916
932
  })
933
+ agent._refreshContext()
934
+ }
935
+ })
936
+ }
937
+
938
+ /**
939
+ * 设置动态刷新 - 记忆变化时自动刷新系统提示词
940
+ */
941
+ _setupDynamicRefresh(framework) {
942
+ this._store.on('change', ({ action, memory }) => {
943
+ const mainAgent = framework._mainAgent
944
+ if (mainAgent) {
945
+ mainAgent.invalidatePromptPart('memory-context')
946
+ mainAgent._refreshContext()
917
947
  }
918
948
  })
919
949
  }
@@ -923,7 +953,6 @@ ${typeof assistantResponse === 'string' ? assistantResponse : JSON.stringify(ass
923
953
  */
924
954
  _buildMemoryContext() {
925
955
  try {
926
- // 获取所有 user 类型记忆作为用户偏好
927
956
  const userMemories = this._store.listByType(MEMORY_TYPES.USER, 10)
928
957
  const projectMemories = this._store.listByType(MEMORY_TYPES.PROJECT, 5)
929
958
 
@@ -9,7 +9,6 @@ const { Plugin } = require('../src/core/plugin-base')
9
9
  const { logger } = require('../src/utils/logger')
10
10
  const log = logger.child('SubAgent')
11
11
  const { z } = require('zod')
12
- const { cleanResponse } = require('../src/utils')
13
12
  const { Agent } = require('../src/core/agent')
14
13
 
15
14
  class SubAgentPlugin extends Plugin {
@@ -461,28 +460,17 @@ class SubAgentManagerPlugin extends Plugin {
461
460
  if (!plugin) {
462
461
  return { success: false, error: `SubAgent ${args.agentName} not found` }
463
462
  }
463
+
464
464
  try {
465
465
  const result = await plugin.chat(args.task)
466
- // 提取返回内容
467
- let output = result.message || result
468
- // 处理 { type: "text", value: "..." } 格式
469
- if (output && output.type === 'text' && output.value) {
470
- output = output.value
471
- }
472
- // 清理 thinking 标签
473
- if (typeof output === 'string') {
474
- output = cleanResponse(output)
475
- }
476
- if (result.success !== false) {
477
- // 确保返回的是字符串
478
- if (typeof output === 'string') {
479
- return output
480
- }
481
- return JSON.stringify(output, null, 2)
466
+ return {
467
+ success: true,
468
+ agent: args.agentName,
469
+ result: result.message || result,
470
+ success: result.success !== false
482
471
  }
483
- return { error: typeof output === 'string' ? output : JSON.stringify(output) }
484
472
  } catch (err) {
485
- return { error: err.message }
473
+ return { success: false, error: err.message }
486
474
  }
487
475
  }
488
476
  })
@@ -535,28 +523,17 @@ class SubAgentManagerPlugin extends Plugin {
535
523
  if (!plugin) {
536
524
  return { success: false, error: `SubAgent ${args.agentName} not found` }
537
525
  }
526
+
538
527
  try {
539
528
  const result = await plugin.chat(args.task)
540
- // 提取返回内容
541
- let output = result.message || result
542
- // 处理 { type: "text", value: "..." } 格式
543
- if (output && output.type === 'text' && output.value) {
544
- output = output.value
545
- }
546
- // 清理 thinking 标签
547
- if (typeof output === 'string') {
548
- output = cleanResponse(output)
549
- }
550
- if (result.success !== false) {
551
- // 确保返回的是字符串
552
- if (typeof output === 'string') {
553
- return output
554
- }
555
- return JSON.stringify(output, null, 2)
529
+ return {
530
+ success: true,
531
+ agent: args.agentName,
532
+ result: result.message || result,
533
+ success: result.success !== false
556
534
  }
557
- return { error: typeof output === 'string' ? output : JSON.stringify(output) }
558
535
  } catch (err) {
559
- return { error: err.message }
536
+ return { success: false, error: err.message }
560
537
  }
561
538
  }
562
539
  })