foliko 1.1.13 → 1.1.14

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 (246) 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/poster-expert.md +135 -196
  36. package/.agent/agents/python-developer.md +60 -0
  37. package/.agent/agents/scheduler.md +59 -0
  38. package/.agent/agents/web-developer.md +45 -0
  39. package/.agent/data/default.json +404 -9
  40. package/.agent/data/plugins-state.json +172 -173
  41. package/.agent/data/puppeteer-sessions/undefined.json +6 -0
  42. package/.agent/data/weixin-media/2026-04-08/img_1775618677512.jpg +0 -0
  43. package/.agent/data/weixin-media/2026-04-08/img_1775619073340.jpg +0 -0
  44. package/.agent/data/weixin-media/2026-04-08/img_1775619097536.jpg +0 -0
  45. package/.agent/data/weixin-media/2026-04-08/img_1775619209388.jpg +0 -0
  46. package/.agent/mcp_config.json +21 -0
  47. package/.agent/memory/feedback/mnygjgox-ualjip.md +11 -0
  48. package/.agent/memory/project/mnqx54u5-loqtoe.md +9 -0
  49. package/.agent/memory/project/mnqx84cv-mx6dmd.md +9 -0
  50. package/.agent/memory/project/mnsacuyr-hgtk5n.md +20 -0
  51. package/.agent/memory/project/mnu5hy2x-bjsg7u.md +9 -0
  52. package/.agent/memory/project/mny28ot4-8qe9au.md +9 -0
  53. package/.agent/memory/reference/mnre3cww-penbo1.md +9 -0
  54. package/.agent/memory/reference/mns9wn48-luerua.md +14 -0
  55. package/.agent/memory/reference/mns9yz5c-thc2s0.md +16 -0
  56. package/.agent/memory/reference/mnsfy4um-910f1o.md +23 -0
  57. package/.agent/memory/reference/mnsg37dp-lmfj18.md +32 -0
  58. package/.agent/memory/reference/mnsll60q-0j911u.md +36 -0
  59. package/.agent/memory/reference/mnsmlb5y-nej31u.md +16 -0
  60. package/.agent/memory/reference/mnssle72-yrot96.md +9 -0
  61. package/.agent/memory/reference/mnygj8nb-bjthmc.md +20 -0
  62. package/.agent/memory/user/mnsfuon6-l416q1.md +21 -0
  63. package/.agent/memory/user/mnsg9kut-95m7rf.md +20 -0
  64. package/.agent/memory/user/mnu2eo1v-yy6fhe.md +9 -0
  65. package/.agent/memory/user/mnu2etuo-8u8jk8.md +9 -0
  66. package/.agent/memory/user/mnx0rk6g-gsznjj.md +9 -0
  67. package/.agent/memory/user/mnyf1riz-4yo5yz.md +9 -0
  68. package/.agent/plugins/puppeteer-plugin/README.md +147 -0
  69. package/.agent/plugins/puppeteer-plugin/index.js +1422 -0
  70. package/.agent/plugins/puppeteer-plugin/package.json +9 -0
  71. package/.agent/plugins.json +5 -11
  72. package/.agent/rules/GEMINI.md +273 -0
  73. package/.agent/rules/allow-rule.md +77 -0
  74. package/.agent/rules/log-rule.md +83 -0
  75. package/.agent/rules/security-rule.md +93 -0
  76. package/.agent/scripts/auto_preview.py +148 -0
  77. package/.agent/scripts/checklist.py +217 -0
  78. package/.agent/scripts/session_manager.py +120 -0
  79. package/.agent/scripts/verify_all.py +327 -0
  80. package/.agent/sessions/cli_default.json +11 -641
  81. package/.agent/skills/api-patterns/SKILL.md +81 -0
  82. package/.agent/skills/api-patterns/api-style.md +42 -0
  83. package/.agent/skills/api-patterns/auth.md +24 -0
  84. package/.agent/skills/api-patterns/documentation.md +26 -0
  85. package/.agent/skills/api-patterns/graphql.md +41 -0
  86. package/.agent/skills/api-patterns/rate-limiting.md +31 -0
  87. package/.agent/skills/api-patterns/response.md +37 -0
  88. package/.agent/skills/api-patterns/rest.md +40 -0
  89. package/.agent/skills/api-patterns/scripts/api_validator.py +211 -0
  90. package/.agent/skills/api-patterns/security-testing.md +122 -0
  91. package/.agent/skills/api-patterns/trpc.md +41 -0
  92. package/.agent/skills/api-patterns/versioning.md +22 -0
  93. package/.agent/skills/app-builder/SKILL.md +75 -0
  94. package/.agent/skills/app-builder/agent-coordination.md +71 -0
  95. package/.agent/skills/app-builder/feature-building.md +53 -0
  96. package/.agent/skills/app-builder/project-detection.md +34 -0
  97. package/.agent/skills/app-builder/scaffolding.md +118 -0
  98. package/.agent/skills/app-builder/tech-stack.md +40 -0
  99. package/.agent/skills/app-builder/templates/SKILL.md +39 -0
  100. package/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +76 -0
  101. package/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +92 -0
  102. package/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +88 -0
  103. package/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +88 -0
  104. package/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +83 -0
  105. package/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +90 -0
  106. package/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +90 -0
  107. package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +122 -0
  108. package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +122 -0
  109. package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +169 -0
  110. package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +134 -0
  111. package/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +83 -0
  112. package/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +119 -0
  113. package/.agent/skills/architecture/SKILL.md +55 -0
  114. package/.agent/skills/architecture/context-discovery.md +43 -0
  115. package/.agent/skills/architecture/examples.md +94 -0
  116. package/.agent/skills/architecture/pattern-selection.md +68 -0
  117. package/.agent/skills/architecture/patterns-reference.md +50 -0
  118. package/.agent/skills/architecture/trade-off-analysis.md +77 -0
  119. package/.agent/skills/clean-code/SKILL.md +201 -0
  120. package/.agent/skills/doc.md +177 -0
  121. package/.agent/skills/frontend-design/SKILL.md +418 -0
  122. package/.agent/skills/frontend-design/animation-guide.md +331 -0
  123. package/.agent/skills/frontend-design/color-system.md +311 -0
  124. package/.agent/skills/frontend-design/decision-trees.md +418 -0
  125. package/.agent/skills/frontend-design/motion-graphics.md +306 -0
  126. package/.agent/skills/frontend-design/scripts/accessibility_checker.py +183 -0
  127. package/.agent/skills/frontend-design/scripts/ux_audit.py +722 -0
  128. package/.agent/skills/frontend-design/typography-system.md +345 -0
  129. package/.agent/skills/frontend-design/ux-psychology.md +1116 -0
  130. package/.agent/skills/frontend-design/visual-effects.md +383 -0
  131. package/.agent/skills/i18n-localization/SKILL.md +154 -0
  132. package/.agent/skills/i18n-localization/scripts/i18n_checker.py +241 -0
  133. package/.agent/skills/mcp-builder/SKILL.md +176 -0
  134. package/.agent/skills/poster-design/SKILL.md +385 -0
  135. package/.agent/skills/web-design-guidelines/SKILL.md +57 -0
  136. package/.agent/workflows/brainstorm.md +113 -0
  137. package/.agent/workflows/create.md +59 -0
  138. package/.agent/workflows/debug.md +103 -0
  139. package/.agent/workflows/deploy.md +176 -0
  140. package/.agent/workflows/enhance.md +63 -0
  141. package/.agent/workflows/orchestrate.md +237 -0
  142. package/.agent/workflows/plan.md +89 -0
  143. package/.agent/workflows/preview.md +81 -0
  144. package/.agent/workflows/simple-test.md +42 -0
  145. package/.agent/workflows/status.md +86 -0
  146. package/.agent/workflows/structured-orchestrate.md +180 -0
  147. package/.agent/workflows/test.md +144 -0
  148. package/.agent/workflows/ui-ux-pro-max.md +296 -0
  149. package/.claude/settings.local.json +23 -1
  150. package/.env.example +56 -56
  151. package/README.md +441 -441
  152. package/cli/src/commands/chat.js +9 -15
  153. package/cli/src/ui/chat-ui.js +41 -71
  154. package/package.json +1 -1
  155. package/plugins/default-plugins.js +5 -5
  156. package/plugins/file-system-plugin.js +1 -1
  157. package/plugins/memory-plugin.js +12 -12
  158. package/plugins/plugin-manager-plugin.js +1 -0
  159. package/plugins/subagent-plugin.js +55 -1
  160. package/plugins/telegram-plugin.js +9 -6
  161. package/plugins/weixin-plugin.js +50 -34
  162. package/skills/find-skills/AGENTS.md +162 -162
  163. package/skills/find-skills/SKILL.md +133 -133
  164. package/src/core/agent-chat.js +460 -1612
  165. package/src/core/agent.js +53 -134
  166. package/src/core/chat-session.js +423 -0
  167. package/src/core/context-compressor.js +473 -0
  168. package/src/core/context-manager.js +0 -48
  169. package/src/core/framework.js +95 -68
  170. package/src/core/index.js +11 -0
  171. package/src/core/notification-manager.js +125 -0
  172. package/src/core/subagent.js +295 -0
  173. package/src/core/token-counter.js +190 -0
  174. package/src/core/tool-executor.js +270 -0
  175. package/src/executors/mcp-executor.js +14 -1
  176. package/system.md +312 -2373
  177. package/.agent/agents/code-assistant.json +0 -17
  178. package/.agent/agents/email-assistant.json +0 -14
  179. package/.agent/agents/file-assistant.json +0 -18
  180. package/.agent/agents/orchestrator-demo.md +0 -53
  181. package/.agent/agents/orchestrator.json +0 -7
  182. package/.agent/agents/system-assistant.json +0 -15
  183. package/.agent/agents/web-assistant.json +0 -12
  184. package/.agent/data/email/processed-emails.json +0 -1
  185. package/.agent/data/scheduler/tasks.json +0 -1
  186. package/.agent/data/web/web-config.json +0 -5
  187. package/.agent/memory/feedback/mnv3nu27-3o15pf.md +0 -9
  188. package/.agent/memory/feedback/mnv3o078-b959yj.md +0 -9
  189. package/.agent/memory/feedback/mnv3o6ej-u0fif5.md +0 -9
  190. package/.agent/memory/feedback/mnv3obgl-bkkjoj.md +0 -9
  191. package/.agent/memory/feedback/mnv4a3js-dv6onx.md +0 -9
  192. package/.agent/memory/feedback/mnv4aacm-sxxowp.md +0 -9
  193. package/.agent/memory/feedback/mnv4ahto-w40ffm.md +0 -9
  194. package/.agent/memory/feedback/mnv4anvp-3cs06y.md +0 -9
  195. package/.agent/memory/feedback/mnvzgvtd-0o2900.md +0 -9
  196. package/.agent/memory/feedback/mnvzhajn-swbx61.md +0 -15
  197. package/.agent/memory/feedback/mnvzhgsp-p5vog3.md +0 -9
  198. package/.agent/memory/feedback/mnvzho0c-fgql7q.md +0 -14
  199. package/.agent/memory/feedback/mnvzhtzq-ufr5at.md +0 -9
  200. package/.agent/memory/feedback/mnvzhyb3-9byq2z.md +0 -9
  201. package/.agent/memory/feedback/mnvzi7hp-hyeafp.md +0 -9
  202. package/.agent/memory/feedback/mnvzibph-z7rwp5.md +0 -9
  203. package/.agent/memory/feedback/mnvzilys-7h176w.md +0 -14
  204. package/.agent/memory/feedback/mnvziuh5-zjshci.md +0 -9
  205. package/.agent/memory/feedback/mnw07wde-6zqsc8.md +0 -9
  206. package/.agent/memory/feedback/mnw084bp-j0ba2a.md +0 -9
  207. package/.agent/memory/user/mnv3n62r-y0h79j.md +0 -21
  208. package/.agent/memory/user/mnv3n9yf-ead4g8.md +0 -13
  209. package/.agent/memory/user/mnv3ne3j-82tq1k.md +0 -19
  210. package/.agent/memory/user/mnv3nhgm-g2s2us.md +0 -11
  211. package/.agent/memory/user/mnv3nl9u-ejd998.md +0 -16
  212. package/.agent/memory/user/mnv3nofp-ya5szl.md +0 -10
  213. package/.agent/memory/user/mnv49qne-bhk0ki.md +0 -9
  214. package/.agent/memory/user/mnv49w3y-rzr8ju.md +0 -13
  215. package/.agent/package.json +0 -8
  216. package/.agent/plugins/__pycache__/file_writer.cpython-312.pyc +0 -0
  217. package/.agent/plugins/daytona/README.md +0 -89
  218. package/.agent/plugins/daytona/index.js +0 -377
  219. package/.agent/plugins/daytona/package.json +0 -12
  220. package/.agent/plugins/marknative/README.md +0 -134
  221. package/.agent/plugins/marknative/fonts/SegoeUI Emoji.ttf +0 -0
  222. package/.agent/plugins/marknative/fonts.zip +0 -0
  223. package/.agent/plugins/marknative/index.js +0 -256
  224. package/.agent/plugins/marknative/package.json +0 -12
  225. package/.agent/plugins/system-info/index.js +0 -387
  226. package/.agent/plugins/system-info/package.json +0 -4
  227. package/.agent/plugins/system-info/test.js +0 -40
  228. package/.agent/plugins/test-plugin.py +0 -123
  229. package/.agent/plugins/test_nested_plugin.py +0 -85
  230. package/.agent/python-scripts/test_sample.py +0 -24
  231. package/.agent/sessions/test.json +0 -16
  232. package/.agent/skills/agent-browser/SKILL.md +0 -311
  233. package/.agent/skills/agent-browser/TEST_PLAN.md +0 -200
  234. package/.agent/skills/sysinfo/SKILL.md +0 -38
  235. package/.agent/skills/sysinfo/system-info.sh +0 -130
  236. package/.agent/skills/workflow/SKILL.md +0 -324
  237. package/.agent/test-agent.js +0 -35
  238. package/.agent/weixin.json +0 -6
  239. package/.agent/workflows/email-digest.json +0 -50
  240. package/.agent/workflows/file-backup.json +0 -21
  241. package/.agent/workflows/get-ip-notify.json +0 -32
  242. package/.agent/workflows/news-aggregator.json +0 -93
  243. package/.agent/workflows/news-dashboard-v2.json +0 -94
  244. package/.agent/workflows/notification-batch.json +0 -32
  245. package/plugins/python-plugin-loader.js.bak +0 -856
  246. package/src/core/agent-context.js +0 -188
@@ -112,8 +112,6 @@ async function runContinuousTest(agent, options) {
112
112
  console.log(`命令数量: ${commands.length}`);
113
113
  console.log('');
114
114
 
115
- const runWithContext = agent.framework?.runWithContext.bind(agent.framework);
116
-
117
115
  for (let i = 0; i < commands.length; i++) {
118
116
  const cmd = commands[i];
119
117
  console.log(`\n[${i + 1}/${commands.length}] >>> ${cmd}`);
@@ -121,26 +119,22 @@ async function runContinuousTest(agent, options) {
121
119
 
122
120
  try {
123
121
  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
- }
122
+ for await (const chunk of agent.chatStream(cmd, { sessionId })) {
123
+ if (chunk.type === 'text') {
124
+ fullResponse += chunk.text;
125
+ process.stdout.write(chunk.text);
126
+ } else if (chunk.type === 'tool-call') {
127
+ console.log(`\n[工具调用] ${chunk.toolName} ${JSON.stringify(chunk.input)}`);
128
+ } else if (chunk.type === 'error') {
129
+ console.error(`\n[错误] ${chunk.error}`);
134
130
  }
135
- });
131
+ }
136
132
  console.log('\n' + '-'.repeat(50));
137
133
  console.log(`[完成] 回复长度: ${fullResponse.length}`);
138
134
  } catch (err) {
139
135
  console.error(`\n[执行错误] ${err.message}`);
140
- // 继续执行下一条命令
141
136
  }
142
137
 
143
- // 命令间隔 1 秒
144
138
  await new Promise((r) => setTimeout(r, 1000));
145
139
  }
146
140
 
@@ -125,10 +125,8 @@ class ChatUI {
125
125
  * 发送消息并显示响应
126
126
  */
127
127
  async sendMessage(message) {
128
- // 用于打断的标志
129
128
  let interrupted = false;
130
129
 
131
- // 设置打断处理
132
130
  const interruptHandler = () => {
133
131
  if (!interrupted) {
134
132
  interrupted = true;
@@ -136,78 +134,59 @@ class ChatUI {
136
134
  }
137
135
  };
138
136
 
139
- // 监听 Ctrl+C
140
137
  process.on('SIGINT', interruptHandler);
141
138
 
142
- let fullResponse = '';
143
- let sessionScope = null;
144
-
145
139
  try {
146
140
  const renderState = { inThink: false, inCodeBlock: false };
147
- const runWithContext = this.agent.framework?.runWithContext.bind(this.agent.framework);
148
141
  const { sessionId } = this;
149
142
 
150
- // 创建当前 session 的事件作用域,自动过滤其他 session 的事件
151
- sessionScope = this.agent.createSessionScope(sessionId);
152
-
153
143
  if (this.stream) {
154
- // 流式模式
144
+ // 流式模式 - 使用事件方式
155
145
  console.log(colored('● ', GREEN));
156
146
 
157
147
  let lineBuffer = '';
158
- await runWithContext({ sessionId }, async () => {
159
- // 使用 sessionScope 监听事件,自动只接收当前 session 的事件
160
- if (sessionScope) {
161
- sessionScope.on('stream:chunk', (data) => {
162
- const { chunk } = data;
163
- if (interrupted) return;
164
-
165
- if (chunk.type === 'text') {
166
- lineBuffer += chunk.text;
167
-
168
- while (lineBuffer.includes('\n')) {
169
- if (interrupted) break;
170
-
171
- const nlIndex = lineBuffer.indexOf('\n');
172
- const line = lineBuffer.substring(0, nlIndex);
173
- lineBuffer = lineBuffer.substring(nlIndex + 1);
174
- if (line.trim()) {
175
- console.log(renderLine(line, renderState));
176
- }
177
- }
178
- } else if (chunk.type === 'tool-call') {
179
- console.log(
180
- `\n${colored('[工具调用]', YELLOW)} ${chunk.toolName}`,
181
- `args=`,
182
- JSON.stringify(chunk.input)
183
- );
184
- } else if (chunk.type === 'error') {
185
- console.error(`\n${colored('[错误]', RED)} ${chunk.error}`);
186
- }
187
- });
188
-
189
- sessionScope.on('message:complete', ({ sessionId, content }) => {
190
- const message = '继续下一步';
191
- if (!content) {
192
- console.log(colored(`● ${message}...`, DIM));
193
- this.agent.sendMessage(message, {
194
- sessionId: sessionId,
195
- priority: 1,
196
- });
148
+ let hasToolCall = false;
149
+
150
+ // 创建 session scope 过滤事件
151
+ const sessionScope = this.agent.createSessionScope(sessionId);
152
+
153
+ // 监听流式数据
154
+ sessionScope.on('stream:chunk', ({ chunk }) => {
155
+ if (interrupted) return;
156
+
157
+ if (chunk.type === 'text') {
158
+ lineBuffer += chunk.text;
159
+
160
+ while (lineBuffer.includes('\n')) {
161
+ if (interrupted) break;
162
+
163
+ const nlIndex = lineBuffer.indexOf('\n');
164
+ const line = lineBuffer.substring(0, nlIndex);
165
+ lineBuffer = lineBuffer.substring(nlIndex + 1);
166
+ if (line.trim()) {
167
+ console.log(renderLine(line, renderState));
197
168
  }
198
- });
169
+ }
170
+ } else if (chunk.type === 'tool-call') {
171
+ if (!hasToolCall) {
172
+ hasToolCall = true;
173
+ console.log();
174
+ }
175
+ console.log(
176
+ `${colored('[工具调用]', YELLOW)} ${chunk.toolName}`,
177
+ `args=`,
178
+ JSON.stringify(chunk.input)
179
+ );
180
+ } else if (chunk.type === 'error') {
181
+ console.error(`\n${colored('[错误]', RED)} ${chunk.error}`);
199
182
  }
200
-
201
- const result = await this.agent.sendMessage(message, {
202
- sessionId: sessionId,
203
- priority: 1,
204
- });
205
183
  });
206
184
 
207
- // 清除 session scope 的监听器
208
- if (sessionScope) {
209
- sessionScope.removeAllListeners();
210
- }
185
+ // 调用 sendMessage 触发事件
186
+ await this.agent.sendMessage(message, { sessionId });
187
+
188
+ // 清理
189
+ sessionScope.removeAllListeners();
211
190
 
212
191
  if (lineBuffer.trim() && !interrupted) {
213
192
  console.log(renderLine(lineBuffer, renderState));
@@ -216,16 +195,11 @@ class ChatUI {
216
195
  // 非流式模式
217
196
  console.log(colored('○ ', CYAN) + '处理中...\n');
218
197
 
219
- const result = await runWithContext({ sessionId }, async () => {
220
- return await this.agent.chat(message, { sessionId });
221
- });
198
+ const result = await this.agent.chat(message, { sessionId });
222
199
 
223
200
  if (interrupted) return;
224
201
 
225
- fullResponse = result.message;
226
-
227
- // 一次性渲染完整响应
228
- const lines = fullResponse.split('\n');
202
+ const lines = result.message.split('\n');
229
203
  for (const line of lines) {
230
204
  if (line.trim()) {
231
205
  console.log(renderLine(line, renderState));
@@ -240,10 +214,6 @@ class ChatUI {
240
214
  console.error(`\n${colored('[错误]', RED)} ${err.message}\n`);
241
215
  }
242
216
  } finally {
243
- // 确保清理 session scope 的监听器
244
- if (sessionScope) {
245
- sessionScope.removeAllListeners();
246
- }
247
217
  process.removeListener('SIGINT', interruptHandler);
248
218
  }
249
219
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "foliko",
3
- "version": "1.1.13",
3
+ "version": "1.1.14",
4
4
  "description": "简约的插件化 Agent 框架",
5
5
  "main": "src/index.js",
6
6
  "type": "commonjs",
@@ -279,13 +279,13 @@ async function bootstrapDefaults(framework, config = {}) {
279
279
 
280
280
  framework._debug&&bootstrapLog.debug(' Loading default plugins...')
281
281
  // AI 插件(如果已禁用则跳过)
282
- if (!shouldLoad('ai') || !(aiConfig.provider || aiConfig.model || aiConfig.apiKey)) {
282
+ // 根据 provider 获取对应的 API key
283
+ const upperProvider = (aiConfig.provider || 'deepseek').toUpperCase().replace(/-/g, '_')
284
+ const envApiKey = process.env[`${upperProvider}_API_KEY`] || process.env.FOLIKO_API_KEY
285
+ if (!shouldLoad('ai') || !(aiConfig.provider || aiConfig.model || aiConfig.apiKey || envApiKey)) {
283
286
  // 跳过或已禁用
284
287
  } else {
285
288
  const AIPlugin = require('./ai-plugin')
286
- // 根据 provider 获取对应的 API key
287
- const upperProvider = (aiConfig.provider || 'deepseek').toUpperCase().replace(/-/g, '_')
288
- const envApiKey = process.env[`${upperProvider}_API_KEY`] || process.env.FOLIKO_API_KEY
289
289
  const aiPlugin = new AIPlugin({
290
290
  provider: aiConfig.provider || 'deepseek',
291
291
  model: aiConfig.model || 'deepseek-chat',
@@ -309,7 +309,7 @@ async function bootstrapDefaults(framework, config = {}) {
309
309
  systemPrompt: '你是一个智能助手。当用户提出问题或任务时,你会主动分析需求,选择合适的工具来获取信息或执行操作。你善于将复杂任务拆解为多个步骤,通过工具协作完成。',
310
310
  model: aiConfig.model || 'deepseek-chat',
311
311
  provider: aiConfig.provider || 'deepseek',
312
- apiKey: aiConfig.apiKey,
312
+ apiKey: aiPlugin ? aiPlugin.config.apiKey : (aiConfig.apiKey || envApiKey),
313
313
  baseURL: aiConfig.baseURL
314
314
  })
315
315
  framework._agents.push(framework._mainAgent)
@@ -13,7 +13,7 @@ class FileSystemPlugin extends Plugin {
13
13
  this.name = 'file-system'
14
14
  this.version = '1.0.0'
15
15
  this.description = '文件系统工具插件'
16
- this.priority = 5
16
+ this.priority = 12
17
17
  this.system = true
18
18
  }
19
19
 
@@ -977,18 +977,18 @@ class MemoryPlugin extends Plugin {
977
977
  }
978
978
 
979
979
  // 批量处理错误
980
- if (this._pendingErrors.length > 0) {
981
- const errors = this._pendingErrors.splice(0, 10) // 每次最多处理 10 条
982
- log.debug(`Processing ${errors.length} pending errors`)
983
-
984
- for (const errorData of errors) {
985
- try {
986
- await this._extractErrorLesson(errorData)
987
- } catch (err) {
988
- log.warn('Failed to extract error lesson:', err.message)
989
- }
990
- }
991
- }
980
+ // if (this._pendingErrors.length > 0) {
981
+ // const errors = this._pendingErrors.splice(0, 10) // 每次最多处理 10 条
982
+ // log.debug(`Processing ${errors.length} pending errors`)
983
+
984
+ // for (const errorData of errors) {
985
+ // try {
986
+ // await this._extractErrorLesson(errorData)
987
+ // } catch (err) {
988
+ // log.warn('Failed to extract error lesson:', err.message)
989
+ // }
990
+ // }
991
+ // }
992
992
  } finally {
993
993
  this._isExtracting = false
994
994
  }
@@ -79,6 +79,7 @@ class PluginManagerPlugin extends Plugin {
79
79
  this.description = '管理远程插件:列表、发布、安装';
80
80
  this._repo = config.repo || process.env.FOLIKO_PLUGIN_REPO || DEFAULT_REPO;
81
81
  this.system = true;
82
+ this.tools = {}; // ext_call 需要通过 this.tools 访问工具
82
83
  }
83
84
 
84
85
  install(framework) {
@@ -110,7 +110,7 @@ class SubAgentPlugin extends Plugin {
110
110
  tools:{}, // 自定义工具
111
111
  parentTools: all_tools
112
112
  })
113
-
113
+
114
114
 
115
115
  // 注册从父Agent继承的工具
116
116
  // for (const tool of parentTools) {
@@ -662,6 +662,60 @@ class SubAgentManagerPlugin extends Plugin {
662
662
  return config
663
663
  }
664
664
 
665
+
666
+ /**
667
+ * 构建子Agent描述
668
+ * 使用数组收集 + join 模式优化字符串拼接
669
+ * 动态从配置文件读取每个子Agent的专业领域
670
+ */
671
+ _buildDescription() {
672
+ const allSubAgents = this.getAllSubAgents();
673
+ if (!allSubAgents || allSubAgents.length === 0) {
674
+ return '';
675
+ }
676
+
677
+ // 使用数组收集 + join 模式优化字符串拼接
678
+ const lines = ['## 子 Agent 匹配表', ''];
679
+ lines.push('');
680
+ lines.push('> **提示**:根据任务类型选择最匹配的子 Agent 处理');
681
+ lines.push('');
682
+
683
+ // 动态从配置文件读取每个子Agent的核心能力
684
+ for (const plugin of allSubAgents) {
685
+ const name = plugin.name;
686
+ const role = plugin.role;
687
+ const goal = plugin.description || '';
688
+
689
+ // 优先使用 SubAgentConfigManager 获取详细信息
690
+ const config = this._framework._subAgentConfigManager?.get(name);
691
+ if (config) {
692
+ const agentDesc = config.getDescription();
693
+ const skills = config.getSkills();
694
+ let info = agentDesc || role || goal || '子代理';
695
+ if (skills && skills.length > 0) {
696
+ info += ` (技能: ${skills.join(', ')})`;
697
+ }
698
+ lines.push(`- **${name}**:${info}`);
699
+ } else {
700
+ // 回退到旧逻辑
701
+ lines.push(`- **${name}**:${role || goal || '子代理'}`);
702
+ }
703
+ }
704
+
705
+ // 通用规则
706
+ lines.push('');
707
+ lines.push('### 子 Agent 调用规则');
708
+ lines.push('');
709
+ lines.push('> **重要**:必须严格遵守以下规则');
710
+ lines.push('');
711
+ lines.push('1. 根据上述「子 Agent 匹配表」,将任务委托给最匹配的子 Agent 处理');
712
+ lines.push('2. 使用 `subagent_call` 工具并指定 `agentName` 来委托任务');
713
+ lines.push('3. 只有当没有匹配的子 Agent 时,才直接调用工具');
714
+ lines.push('4. 子 Agent 是没有记忆的,有需要的时候,有需要的时候,需要传递给上下文给子 Agent');
715
+
716
+ return lines.join('\n');
717
+ }
718
+
665
719
  /**
666
720
  * 获取所有 subAgent 的基本信息列表
667
721
  */
@@ -311,24 +311,27 @@ class TelegramPlugin extends Plugin {
311
311
  }
312
312
 
313
313
  try {
314
+ // 使用事件方式实时处理流式响应
315
+ const sessionScope = agent.createSessionScope(sessionId)
314
316
  let fullResponse = ''
315
- for await (const chunk of agent.chatStream(text, { sessionId })) {
317
+
318
+ sessionScope.on('stream:chunk', ({ chunk }) => {
316
319
  if (chunk.type === 'text' && chunk.text) {
317
320
  fullResponse += chunk.text
318
321
  if (fullResponse.length % 100 === 0) {
319
322
  try {
320
- await this._bot.editMessageText(`📝 ${escapeMarkdown(fullResponse)}▌`, {
323
+ this._bot.editMessageText(`📝 ${escapeMarkdown(fullResponse)}▌`, {
321
324
  chat_id: chatId,
322
325
  message_id: thinkingMsg.message_id
323
326
  })
324
327
  } catch (e) { /* ignore */ }
325
328
  }
326
329
  }
327
- }
330
+ })
331
+
332
+ await agent.sendMessage(text, { sessionId })
328
333
 
329
- // if (this._sessionPlugin) {
330
- // this._sessionPlugin.addMessage(sessionId, { role: 'assistant', content: fullResponse })
331
- // }
334
+ sessionScope.removeAllListeners()
332
335
 
333
336
  const safeResponse = escapeMarkdown(fullResponse) || '抱歉,我没有收到有效的回复。'
334
337
  await this._bot.editMessageText(safeResponse, {
@@ -390,13 +390,6 @@ class WeixinPlugin extends Plugin {
390
390
  metadata: { platform: 'weixin', userId }
391
391
  })
392
392
  }
393
- const sessionScope = agent.createSessionScope(sessionId);
394
- // sessionScope.on('stream:chunk', ({chunk}) => {
395
- // if (chunk.type === 'text') {
396
- // process.stdout.write(chunk.text);
397
- // }
398
- // });
399
- // log.info(` Session ready for user: ${userId}`)
400
393
  return { agent, sessionId }
401
394
  }
402
395
 
@@ -473,21 +466,32 @@ class WeixinPlugin extends Plugin {
473
466
  await new Promise((resolve) => setTimeout(resolve, 1000))
474
467
 
475
468
  try {
476
- // 使用 continue 获取流式响应
477
- const result = await agent.sendMessage(text, {
478
- sessionId: sessionId,
479
- priority: 1,
480
- });
481
- const errors=result.chunks.filter(a=>a.type==='error').map(a=>a.error)
482
- if(errors.length){
483
- throw new Error(errors.join('\n'))
484
- }
485
- if(result.content){
486
- await this._sendMessageBatch(originalMsg, userId, result.content, true)
487
- }else{
488
- const msg=`继续进行下一步`
469
+ // 使用事件方式实时处理流式响应
470
+ const sessionScope = agent.createSessionScope(sessionId)
471
+ let fullResponse = ''
472
+ let hasError = false
473
+
474
+ sessionScope.on('stream:chunk', ({ chunk }) => {
475
+ if (chunk.type === 'text') {
476
+ fullResponse += chunk.text
477
+ } else if (chunk.type === 'error') {
478
+ hasError = true
479
+ log.error(' Stream error:', chunk.error)
480
+ }
481
+ })
482
+
483
+ await agent.sendMessage(text, { sessionId, priority: 1 })
484
+
485
+ sessionScope.removeAllListeners()
486
+
487
+ if (hasError) {
488
+ await this._sendMessageBatch(originalMsg, userId, `发生错误`, true)
489
+ } else if (fullResponse) {
490
+ await this._sendMessageBatch(originalMsg, userId, fullResponse, true)
491
+ } else {
492
+ const msg = `继续进行下一步`
489
493
  await this._sendMessageBatch(originalMsg, userId, msg, true)
490
- agent.sendMessage(msg,{sessionId,priority: 1})
494
+ agent.sendMessage(msg, { sessionId, priority: 1 })
491
495
  }
492
496
  } catch (err) {
493
497
  log.error(' Media chat error:', err)
@@ -515,20 +519,32 @@ class WeixinPlugin extends Plugin {
515
519
  await new Promise((resolve) => setTimeout(resolve, 1000))
516
520
 
517
521
  try {
518
- const result = await agent.sendMessage(text, {
519
- sessionId: sessionId,
520
- priority: 1,
521
- });
522
- const errors=result.chunks.filter(a=>a.type==='error').map(a=>a.error)
523
- if(errors.length){
524
- throw new Error(errors.join('\n'))
525
- }
526
- if(result.content){
527
- await this._sendMessageBatch(originalMsg, userId, result.content, true)
528
- }else{
529
- const msg=`继续进行下一步`
522
+ // 使用事件方式实时处理流式响应
523
+ const sessionScope = agent.createSessionScope(sessionId)
524
+ let fullResponse = ''
525
+ let hasError = false
526
+
527
+ sessionScope.on('stream:chunk', ({ chunk }) => {
528
+ if (chunk.type === 'text') {
529
+ fullResponse += chunk.text
530
+ } else if (chunk.type === 'error') {
531
+ hasError = true
532
+ log.error(' Stream error:', chunk.error)
533
+ }
534
+ })
535
+
536
+ await agent.sendMessage(text, { sessionId, priority: 1 })
537
+
538
+ sessionScope.removeAllListeners()
539
+
540
+ if (hasError) {
541
+ await this._sendMessageBatch(originalMsg, userId, `发生错误`, true)
542
+ } else if (fullResponse) {
543
+ await this._sendMessageBatch(originalMsg, userId, fullResponse, true)
544
+ } else {
545
+ const msg = `继续进行下一步`
530
546
  await this._sendMessageBatch(originalMsg, userId, msg, true)
531
- agent.sendMessage(msg,{sessionId,priority: 1})
547
+ agent.sendMessage(msg, { sessionId, priority: 1 })
532
548
  }
533
549
 
534
550
  } catch (err) {