foliko 1.0.73 → 1.0.75

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 (237) 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 +29 -0
  39. package/.agent/data/plugins-state.json +255 -0
  40. package/.agent/mcp_config.json +4 -0
  41. package/.agent/mcp_config_updated.json +12 -0
  42. package/.agent/plugins.json +5 -0
  43. package/.agent/rules/GEMINI.md +273 -0
  44. package/.agent/rules/allow-rule.md +77 -0
  45. package/.agent/rules/log-rule.md +83 -0
  46. package/.agent/rules/security-rule.md +93 -0
  47. package/.agent/scripts/auto_preview.py +148 -0
  48. package/.agent/scripts/checklist.py +217 -0
  49. package/.agent/scripts/session_manager.py +120 -0
  50. package/.agent/scripts/verify_all.py +327 -0
  51. package/.agent/skills/api-patterns/SKILL.md +81 -0
  52. package/.agent/skills/api-patterns/api-style.md +42 -0
  53. package/.agent/skills/api-patterns/auth.md +24 -0
  54. package/.agent/skills/api-patterns/documentation.md +26 -0
  55. package/.agent/skills/api-patterns/graphql.md +41 -0
  56. package/.agent/skills/api-patterns/rate-limiting.md +31 -0
  57. package/.agent/skills/api-patterns/response.md +37 -0
  58. package/.agent/skills/api-patterns/rest.md +40 -0
  59. package/.agent/skills/api-patterns/scripts/api_validator.py +211 -0
  60. package/.agent/skills/api-patterns/security-testing.md +122 -0
  61. package/.agent/skills/api-patterns/trpc.md +41 -0
  62. package/.agent/skills/api-patterns/versioning.md +22 -0
  63. package/.agent/skills/app-builder/SKILL.md +75 -0
  64. package/.agent/skills/app-builder/agent-coordination.md +71 -0
  65. package/.agent/skills/app-builder/feature-building.md +53 -0
  66. package/.agent/skills/app-builder/project-detection.md +34 -0
  67. package/.agent/skills/app-builder/scaffolding.md +118 -0
  68. package/.agent/skills/app-builder/tech-stack.md +40 -0
  69. package/.agent/skills/app-builder/templates/SKILL.md +39 -0
  70. package/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +76 -0
  71. package/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +92 -0
  72. package/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +88 -0
  73. package/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +88 -0
  74. package/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +83 -0
  75. package/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +90 -0
  76. package/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +90 -0
  77. package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +122 -0
  78. package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +122 -0
  79. package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +169 -0
  80. package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +134 -0
  81. package/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +83 -0
  82. package/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +119 -0
  83. package/.agent/skills/architecture/SKILL.md +55 -0
  84. package/.agent/skills/architecture/context-discovery.md +43 -0
  85. package/.agent/skills/architecture/examples.md +94 -0
  86. package/.agent/skills/architecture/pattern-selection.md +68 -0
  87. package/.agent/skills/architecture/patterns-reference.md +50 -0
  88. package/.agent/skills/architecture/trade-off-analysis.md +77 -0
  89. package/.agent/skills/clean-code/SKILL.md +201 -0
  90. package/.agent/skills/doc.md +177 -0
  91. package/.agent/skills/frontend-design/SKILL.md +418 -0
  92. package/.agent/skills/frontend-design/animation-guide.md +331 -0
  93. package/.agent/skills/frontend-design/color-system.md +311 -0
  94. package/.agent/skills/frontend-design/decision-trees.md +418 -0
  95. package/.agent/skills/frontend-design/motion-graphics.md +306 -0
  96. package/.agent/skills/frontend-design/scripts/accessibility_checker.py +183 -0
  97. package/.agent/skills/frontend-design/scripts/ux_audit.py +722 -0
  98. package/.agent/skills/frontend-design/typography-system.md +345 -0
  99. package/.agent/skills/frontend-design/ux-psychology.md +1116 -0
  100. package/.agent/skills/frontend-design/visual-effects.md +383 -0
  101. package/.agent/skills/i18n-localization/SKILL.md +154 -0
  102. package/.agent/skills/i18n-localization/scripts/i18n_checker.py +241 -0
  103. package/.agent/skills/mcp-builder/SKILL.md +176 -0
  104. package/.agent/skills/web-design-guidelines/SKILL.md +57 -0
  105. package/.agent/workflows/brainstorm.md +113 -0
  106. package/.agent/workflows/create.md +59 -0
  107. package/.agent/workflows/debug.md +103 -0
  108. package/.agent/workflows/deploy.md +176 -0
  109. package/.agent/workflows/enhance.md +63 -0
  110. package/.agent/workflows/orchestrate.md +237 -0
  111. package/.agent/workflows/plan.md +89 -0
  112. package/.agent/workflows/preview.md +81 -0
  113. package/.agent/workflows/simple-test.md +42 -0
  114. package/.agent/workflows/status.md +86 -0
  115. package/.agent/workflows/structured-orchestrate.md +180 -0
  116. package/.agent/workflows/test.md +144 -0
  117. package/.agent/workflows/ui-ux-pro-max.md +296 -0
  118. package/.claude/settings.local.json +157 -149
  119. package/.editorconfig +56 -0
  120. package/.husky/pre-commit +4 -0
  121. package/.lintstagedrc +7 -0
  122. package/.prettierignore +29 -0
  123. package/.prettierrc +11 -0
  124. package/CLAUDE.md +2 -0
  125. package/README.md +64 -55
  126. package/SPEC.md +102 -61
  127. package/cli/bin/foliko.js +4 -4
  128. package/cli/src/commands/chat.js +53 -51
  129. package/cli/src/commands/list.js +40 -37
  130. package/cli/src/index.js +18 -18
  131. package/cli/src/ui/chat-ui.js +78 -76
  132. package/cli/src/utils/ansi.js +15 -15
  133. package/cli/src/utils/markdown.js +112 -116
  134. package/docker-compose.yml +1 -1
  135. package/docs/ai-sdk-optimization.md +655 -636
  136. package/docs/features.md +80 -80
  137. package/docs/quick-reference.md +49 -46
  138. package/docs/user-manual.md +411 -380
  139. package/examples/ambient-example.js +95 -97
  140. package/examples/basic.js +115 -110
  141. package/examples/bootstrap.js +52 -43
  142. package/examples/mcp-example.js +56 -53
  143. package/examples/skill-example.js +49 -49
  144. package/examples/test-chat.js +60 -58
  145. package/examples/test-mcp.js +49 -43
  146. package/examples/test-reload.js +38 -40
  147. package/examples/test-telegram.js +3 -3
  148. package/examples/test-tg-bot.js +7 -4
  149. package/examples/test-tg-simple.js +4 -3
  150. package/examples/test-tg.js +3 -3
  151. package/examples/test-think.js +13 -7
  152. package/examples/test-web-plugin.js +61 -56
  153. package/examples/test-weixin-feishu.js +40 -37
  154. package/examples/workflow.js +49 -49
  155. package/foliko-1.0.75.tgz +0 -0
  156. package/package.json +37 -3
  157. package/plugins/ai-plugin.js +7 -5
  158. package/plugins/ambient-agent/EventWatcher.js +113 -0
  159. package/plugins/ambient-agent/ExplorerLoop.js +640 -0
  160. package/plugins/ambient-agent/GoalManager.js +197 -0
  161. package/plugins/ambient-agent/Reflector.js +95 -0
  162. package/plugins/ambient-agent/StateStore.js +90 -0
  163. package/plugins/ambient-agent/constants.js +101 -0
  164. package/plugins/ambient-agent/index.js +579 -0
  165. package/plugins/default-plugins.js +62 -49
  166. package/plugins/email/constants.js +64 -0
  167. package/plugins/email/handlers.js +461 -0
  168. package/plugins/email/index.js +278 -0
  169. package/plugins/email/monitor.js +269 -0
  170. package/plugins/email/parser.js +138 -0
  171. package/plugins/email/reply.js +151 -0
  172. package/plugins/email/utils.js +124 -0
  173. package/plugins/feishu-plugin.js +23 -19
  174. package/plugins/file-system-plugin.js +469 -120
  175. package/plugins/install-plugin.js +6 -4
  176. package/plugins/python-executor-plugin.js +3 -1
  177. package/plugins/python-plugin-loader.js +10 -8
  178. package/plugins/rules-plugin.js +5 -3
  179. package/plugins/scheduler-plugin.js +18 -16
  180. package/plugins/session-plugin.js +3 -1
  181. package/plugins/storage-plugin.js +5 -3
  182. package/plugins/subagent-plugin.js +152 -92
  183. package/plugins/telegram-plugin.js +26 -19
  184. package/plugins/think-plugin.js +4 -2
  185. package/plugins/tools-plugin.js +3 -1
  186. package/plugins/web-plugin.js +15 -13
  187. package/plugins/weixin-plugin.js +43 -36
  188. package/reports/system-health-report-20260401.md +79 -0
  189. package/skills/ambient-agent/SKILL.md +49 -39
  190. package/skills/foliko-dev/AGENTS.md +64 -61
  191. package/skills/foliko-dev/SKILL.md +125 -119
  192. package/skills/mcp-usage/SKILL.md +19 -17
  193. package/skills/python-plugin-dev/SKILL.md +16 -15
  194. package/skills/skill-guide/SKILL.md +12 -12
  195. package/skills/subagent-guide/SKILL.md +237 -0
  196. package/skills/workflow-guide/SKILL.md +90 -45
  197. package/skills/workflow-troubleshooting/DEBUGGING.md +36 -21
  198. package/skills/workflow-troubleshooting/SKILL.md +156 -79
  199. package/src/capabilities/index.js +4 -4
  200. package/src/capabilities/skill-manager.js +211 -197
  201. package/src/capabilities/workflow-engine.js +461 -547
  202. package/src/core/agent-chat.js +426 -279
  203. package/src/core/agent.js +453 -248
  204. package/src/core/framework.js +183 -149
  205. package/src/core/index.js +8 -8
  206. package/src/core/plugin-base.js +52 -52
  207. package/src/core/plugin-manager.js +377 -281
  208. package/src/core/provider.js +35 -32
  209. package/src/core/sub-agent-config.js +264 -0
  210. package/src/core/system-prompt-builder.js +120 -0
  211. package/src/core/tool-registry.js +416 -33
  212. package/src/core/tool-router.js +149 -68
  213. package/src/executors/executor-base.js +58 -58
  214. package/src/executors/mcp-executor.js +269 -257
  215. package/src/index.js +5 -17
  216. package/src/utils/circuit-breaker.js +301 -0
  217. package/src/utils/error-boundary.js +363 -0
  218. package/src/utils/error.js +374 -0
  219. package/src/utils/event-emitter.js +20 -20
  220. package/src/utils/id.js +133 -0
  221. package/src/utils/index.js +217 -3
  222. package/src/utils/logger.js +181 -0
  223. package/src/utils/plugin-helpers.js +90 -0
  224. package/src/utils/retry.js +122 -0
  225. package/src/utils/sandbox.js +292 -0
  226. package/test/tool-registry-validation.test.js +218 -0
  227. package/test_report.md +70 -0
  228. package/website/docs/api.html +169 -107
  229. package/website/docs/configuration.html +296 -144
  230. package/website/docs/plugin-development.html +154 -85
  231. package/website/docs/project-structure.html +110 -109
  232. package/website/docs/skill-development.html +117 -61
  233. package/website/index.html +209 -205
  234. package/website/script.js +20 -17
  235. package/website/styles.css +1 -1
  236. package/plugins/ambient-agent-plugin.js +0 -1565
  237. package/plugins/email.js +0 -1142
@@ -3,12 +3,12 @@
3
3
  * 使用 @ai-sdk/mcp 连接到 MCP 服务器
4
4
  */
5
5
 
6
- const { Plugin } = require('../core/plugin-base')
7
- const { spawn } = require('child_process')
8
- const fs = require('fs')
9
- const path = require('path')
10
- const { z } = require('zod')
11
- const {createMCPClient} = require('@ai-sdk/mcp')
6
+ const { Plugin } = require('../core/plugin-base');
7
+ const { spawn } = require('child_process');
8
+ const fs = require('fs');
9
+ const path = require('path');
10
+ const { z } = require('zod');
11
+ const { createMCPClient } = require('@ai-sdk/mcp');
12
12
  const { StdioClientTransport } = require('@modelcontextprotocol/sdk/client/stdio.js');
13
13
 
14
14
  /**
@@ -16,72 +16,72 @@ const { StdioClientTransport } = require('@modelcontextprotocol/sdk/client/stdio
16
16
  */
17
17
  class MCPClientWrapper {
18
18
  constructor(options = {}) {
19
- this.serverName = options.serverName || 'unknown'
20
- this.command = options.command
21
- this.args = options.args || []
22
- this.env = options.env || {}
23
- this.timeout = options.timeout || 30000
24
- this.priority = 11
25
- this.client = null
26
- this.connected = false
27
- this.tools = []
19
+ this.serverName = options.serverName || 'unknown';
20
+ this.command = options.command;
21
+ this.args = options.args || [];
22
+ this.env = options.env || {};
23
+ this.timeout = options.timeout || 30000;
24
+ this.priority = 11;
25
+ this.client = null;
26
+ this.connected = false;
27
+ this.tools = [];
28
28
  }
29
29
 
30
30
  /**
31
31
  * 连接 MCP 服务器
32
32
  */
33
33
  async connect() {
34
- if (this.connected) return
34
+ if (this.connected) return;
35
35
 
36
36
  try {
37
37
  // 动态导入 @ai-sdk/mcp
38
- let createMCPClient
38
+ let createMCPClient;
39
39
 
40
40
  try {
41
- const mcpModule = require('@ai-sdk/mcp')
42
- createMCPClient = mcpModule.createMCPClient || mcpModule.experimental_createMCPClient
41
+ const mcpModule = require('@ai-sdk/mcp');
42
+ createMCPClient = mcpModule.createMCPClient || mcpModule.experimental_createMCPClient;
43
43
  } catch (err) {
44
- throw new Error('@ai-sdk/mcp not installed. Please run: npm install @ai-sdk/mcp')
44
+ throw new Error('@ai-sdk/mcp not installed. Please run: npm install @ai-sdk/mcp');
45
45
  }
46
46
 
47
47
  if (!createMCPClient) {
48
- throw new Error('createMCPClient not available')
48
+ throw new Error('createMCPClient not available');
49
49
  }
50
50
 
51
51
  // 解析命令路径
52
- const { which, shellResolve } = this._resolveCommand(this.command)
52
+ const { which, shellResolve } = this._resolveCommand(this.command);
53
53
 
54
54
  // 使用正确的子路径导入
55
55
  try {
56
- const { Experimental_StdioMCPTransport } = require('@ai-sdk/mcp/mcp-stdio')
56
+ const { Experimental_StdioMCPTransport } = require('@ai-sdk/mcp/mcp-stdio');
57
57
  const transport = new Experimental_StdioMCPTransport({
58
58
  command: which || this.command,
59
59
  args: shellResolve ? [shellResolve, ...this.args] : this.args,
60
- env: { ...process.env, ...this.env }
61
- })
62
- this.client = await createMCPClient({ transport })
60
+ env: { ...process.env, ...this.env },
61
+ });
62
+ this.client = await createMCPClient({ transport });
63
63
  } catch (transportErr) {
64
- console.error(`[MCPExecutor] Transport error:`, transportErr.message)
65
- throw transportErr
64
+ log.error(` Transport error:`, transportErr.message);
65
+ throw transportErr;
66
66
  }
67
67
 
68
68
  // 获取工具列表
69
69
  // 新版 API: tools() 是函数
70
70
  if (typeof this.client.tools === 'function') {
71
- const toolsObject = await this.client.tools()
71
+ const toolsObject = await this.client.tools();
72
72
  this.tools = Object.entries(toolsObject)
73
73
  .filter(([, tool]) => tool != null)
74
- .map(([name, tool]) => ({ ...tool, name }))
74
+ .map(([name, tool]) => ({ ...tool, name }));
75
75
  } else if (this.client.tools && typeof this.client.tools.list === 'function') {
76
76
  // 旧版 API: tools.list()
77
- const listResult = await this.client.tools.list()
78
- this.tools = listResult.tools || []
77
+ const listResult = await this.client.tools.list();
78
+ this.tools = listResult.tools || [];
79
79
  }
80
80
 
81
- this.connected = true
82
- console.log(`[MCPExecutor] Connected to ${this.serverName} with ${this.tools.length} tools`)
81
+ this.connected = true;
82
+ log.info(` Connected to ${this.serverName} with ${this.tools.length} tools`);
83
83
  } catch (err) {
84
- console.error(`[MCPExecutor] Failed to connect to ${this.serverName}:`, err.message)
84
+ log.error(` Failed to connect to ${this.serverName}:`, err.message);
85
85
  // 不抛出错误,让框架继续运行
86
86
  }
87
87
  }
@@ -90,18 +90,18 @@ class MCPClientWrapper {
90
90
  * 解析命令路径
91
91
  */
92
92
  _resolveCommand(cmd) {
93
- const isWindows = process.platform === 'win32'
94
- const ext = isWindows ? '.cmd' : ''
95
- const withExt = cmd + ext
93
+ const isWindows = process.platform === 'win32';
94
+ const ext = isWindows ? '.cmd' : '';
95
+ const withExt = cmd + ext;
96
96
 
97
97
  // 检查命令是否直接存在
98
98
  try {
99
99
  const result = spawn.sync(withExt, ['--version'], {
100
100
  stdio: 'ignore',
101
- timeout: 2000
102
- })
101
+ timeout: 2000,
102
+ });
103
103
  if (result.error?.code !== 'ENOENT') {
104
- return { which: withExt, shellResolve: null }
104
+ return { which: withExt, shellResolve: null };
105
105
  }
106
106
  } catch (e) {
107
107
  // ignore
@@ -111,21 +111,21 @@ class MCPClientWrapper {
111
111
  const globalCommands = isWindows
112
112
  ? [
113
113
  path.join(process.env.APPDATA || '', 'npm', withExt),
114
- path.join(process.env.PROGRAMDATA || 'C:\\ProgramData', 'npm', withExt)
114
+ path.join(process.env.PROGRAMDATA || 'C:\\ProgramData', 'npm', withExt),
115
115
  ]
116
- : ['/usr/local/bin/' + cmd, '/usr/bin/' + cmd]
116
+ : ['/usr/local/bin/' + cmd, '/usr/bin/' + cmd];
117
117
 
118
118
  for (const cmdPath of globalCommands) {
119
119
  try {
120
120
  if (fs.existsSync(cmdPath)) {
121
- return { which: cmdPath, shellResolve: null }
121
+ return { which: cmdPath, shellResolve: null };
122
122
  }
123
123
  } catch (e) {
124
124
  // ignore
125
125
  }
126
126
  }
127
127
 
128
- return { which: cmd, shellResolve: null }
128
+ return { which: cmd, shellResolve: null };
129
129
  }
130
130
 
131
131
  /**
@@ -133,36 +133,36 @@ class MCPClientWrapper {
133
133
  */
134
134
  async callTool(toolName, args) {
135
135
  if (!this.connected) {
136
- await this.connect()
136
+ await this.connect();
137
137
  }
138
138
 
139
139
  if (!this.client) {
140
- throw new Error('MCP client not initialized')
140
+ throw new Error('MCP client not initialized');
141
141
  }
142
142
 
143
143
  try {
144
144
  // 新版 API: tools() 返回对象
145
- let toolsObject
145
+ let toolsObject;
146
146
  if (typeof this.client.tools === 'function') {
147
- toolsObject = await this.client.tools()
147
+ toolsObject = await this.client.tools();
148
148
  } else if (this.client.tools && typeof this.client.tools.list === 'function') {
149
149
  // 旧版 API
150
- const listResult = await this.client.tools.list()
151
- toolsObject = listResult.tools || {}
150
+ const listResult = await this.client.tools.list();
151
+ toolsObject = listResult.tools || {};
152
152
  } else {
153
- throw new Error('Cannot get tools from MCP client')
153
+ throw new Error('Cannot get tools from MCP client');
154
154
  }
155
155
 
156
- const tool = toolsObject[toolName]
156
+ const tool = toolsObject[toolName];
157
157
  if (!tool) {
158
- throw new Error(`Tool not found: ${toolName}`)
158
+ throw new Error(`Tool not found: ${toolName}`);
159
159
  }
160
160
 
161
- const result = await tool.execute(args)
162
- return result
161
+ const result = await tool.execute(args);
162
+ return result;
163
163
  } catch (err) {
164
- console.error(`[MCPExecutor] Tool call failed: ${toolName}:`, err.message)
165
- throw err
164
+ log.error(` Tool call failed: ${toolName}:`, err.message);
165
+ throw err;
166
166
  }
167
167
  }
168
168
 
@@ -172,13 +172,13 @@ class MCPClientWrapper {
172
172
  async disconnect() {
173
173
  if (this.client) {
174
174
  try {
175
- await this.client.destroy()
175
+ await this.client.destroy();
176
176
  } catch (e) {
177
177
  // ignore
178
178
  }
179
- this.client = null
180
- this.connected = false
181
- this.tools = []
179
+ this.client = null;
180
+ this.connected = false;
181
+ this.tools = [];
182
182
  }
183
183
  }
184
184
  }
@@ -188,29 +188,29 @@ class MCPClientWrapper {
188
188
  */
189
189
  class MCPExecutorPlugin extends Plugin {
190
190
  constructor(config = {}) {
191
- super()
192
- this.name = 'mcp-executor'
193
- this.version = '1.0.0'
194
- this.description = 'MCP (Model Context Protocol) 执行器'
195
- this.priority = 11
196
- this.system = true
197
-
198
- this._framework = null
191
+ super();
192
+ this.name = 'mcp-executor';
193
+ this.version = '1.0.0';
194
+ this.description = 'MCP (Model Context Protocol) 执行器';
195
+ this.priority = 11;
196
+ this.system = true;
197
+
198
+ this._framework = null;
199
199
  // serverName -> { client, tools: [{ name, description, inputSchema }], toolObjects: { toolName: actualTool } }
200
- this._clients = new Map()
201
- this._config = config
200
+ this._clients = new Map();
201
+ this._config = config;
202
202
  }
203
203
 
204
204
  install(framework) {
205
- this._framework = framework
206
- return this
205
+ this._framework = framework;
206
+ return this;
207
207
  }
208
208
 
209
209
  async start(framework) {
210
210
  // 先连接所有 MCP 服务器
211
211
  if (this._config.servers) {
212
212
  for (const serverConfig of this._config.servers) {
213
- await this.addServer(serverConfig)
213
+ await this.addServer(serverConfig);
214
214
  }
215
215
  }
216
216
 
@@ -220,60 +220,60 @@ class MCPExecutorPlugin extends Plugin {
220
220
  description: '查询工具的调用示例,直接复制 example 或 fullExample 字段使用',
221
221
  inputSchema: z.object({
222
222
  server: z.string().describe('MCP 服务器名称'),
223
- tool: z.string().describe('工具名称')
223
+ tool: z.string().describe('工具名称'),
224
224
  }),
225
225
  execute: async (args) => {
226
- const { server, tool } = args
227
- const clientInfo = this._clients.get(server)
226
+ const { server, tool } = args;
227
+ const clientInfo = this._clients.get(server);
228
228
  if (!clientInfo) {
229
- return { success: false, error: `MCP server '${server}' not found` }
229
+ return { success: false, error: `MCP server '${server}' not found` };
230
230
  }
231
231
 
232
- const toolInfo = clientInfo.tools.find(t => t.name === tool)
232
+ const toolInfo = clientInfo.tools.find((t) => t.name === tool);
233
233
  if (!toolInfo) {
234
- return { success: false, error: `Tool '${tool}' not found` }
234
+ return { success: false, error: `Tool '${tool}' not found` };
235
235
  }
236
236
 
237
- const schema = this._extractSchema(toolInfo.inputSchema)
238
- const props = schema.properties || {}
239
- const required = schema.required || []
237
+ const schema = this._extractSchema(toolInfo.inputSchema);
238
+ const props = schema.properties || {};
239
+ const required = schema.required || [];
240
240
 
241
241
  // 生成示例值的辅助函数
242
242
  const generateExample = (prop, depth = 0) => {
243
- if (!prop) return null
244
- const type = prop.type || (prop.properties ? 'object' : 'string')
243
+ if (!prop) return null;
244
+ const type = prop.type || (prop.properties ? 'object' : 'string');
245
245
 
246
246
  if (type === 'string') {
247
- return prop.description?.split('.')[0] || `${prop.title || '值'}`
247
+ return prop.description?.split('.')[0] || `${prop.title || '值'}`;
248
248
  } else if (type === 'number' || type === 'integer') {
249
- return prop.default || 0
249
+ return prop.default || 0;
250
250
  } else if (type === 'boolean') {
251
- return false
251
+ return false;
252
252
  } else if (type === 'array') {
253
253
  // 数组类型:提供单个示例元素
254
254
  if (prop.items) {
255
- const itemExample = generateExample(prop.items, depth + 1)
256
- return depth === 0 ? [itemExample] : itemExample
255
+ const itemExample = generateExample(prop.items, depth + 1);
256
+ return depth === 0 ? [itemExample] : itemExample;
257
257
  }
258
- return ['示例']
258
+ return ['示例'];
259
259
  } else if (type === 'object' || prop.properties) {
260
260
  // 对象类型:递归生成嵌套结构
261
- const obj = {}
262
- const objProps = prop.properties || {}
261
+ const obj = {};
262
+ const objProps = prop.properties || {};
263
263
  for (const [key, val] of Object.entries(objProps)) {
264
- obj[key] = generateExample(val, depth + 1)
264
+ obj[key] = generateExample(val, depth + 1);
265
265
  }
266
- return obj
266
+ return obj;
267
267
  }
268
- return null
269
- }
268
+ return null;
269
+ };
270
270
 
271
271
  // 生成可直接使用的调用示例
272
- const exampleArgs = {}
272
+ const exampleArgs = {};
273
273
  for (const key of required) {
274
- const prop = props[key]
274
+ const prop = props[key];
275
275
  if (prop) {
276
- exampleArgs[key] = generateExample(prop)
276
+ exampleArgs[key] = generateExample(prop);
277
277
  }
278
278
  }
279
279
 
@@ -285,76 +285,82 @@ class MCPExecutorPlugin extends Plugin {
285
285
  required,
286
286
  // 各参数的详细说明
287
287
  parameters: Object.fromEntries(
288
- required.map(key => [key, {
289
- type: props[key]?.type || 'string',
290
- description: props[key]?.description || '',
291
- example: generateExample(props[key])
292
- }])
288
+ required.map((key) => [
289
+ key,
290
+ {
291
+ type: props[key]?.type || 'string',
292
+ description: props[key]?.description || '',
293
+ example: generateExample(props[key]),
294
+ },
295
+ ])
293
296
  ),
294
297
  // 直接返回可以复制使用的调用示例
295
298
  example: JSON.stringify(exampleArgs, null, 2),
296
- fullExample: `mcp_call({ server: "${server}", tool: "${tool}", args_json: ${JSON.stringify(JSON.stringify(exampleArgs))} })`
297
- }
298
- }
299
- }
300
- })
299
+ fullExample: `mcp_call({ server: "${server}", tool: "${tool}", args_json: ${JSON.stringify(JSON.stringify(exampleArgs))} })`,
300
+ },
301
+ };
302
+ },
303
+ });
301
304
 
302
305
  // 注册 mcp_call 工具
303
306
  framework.registerTool({
304
307
  name: 'mcp_call',
305
- description: '调用 MCP 服务器工具。args_json 是包含实际参数的 JSON 字符串,如 \'{"url": "https://news.baidu.com"}\'',
308
+ description:
309
+ '调用 MCP 服务器工具。args_json 是包含实际参数的 JSON 字符串,如 \'{"url": "https://news.baidu.com"}\'',
306
310
  inputSchema: z.object({
307
311
  server: z.string().describe('MCP 服务器名称'),
308
312
  tool: z.string().describe('工具名称'),
309
- args_json: z.string().describe('参数 JSON 字符串,如 {"url": "https://..."},fetch 工具必填 url')
313
+ args_json: z
314
+ .string()
315
+ .describe('参数 JSON 字符串,如 {"url": "https://..."},fetch 工具必填 url'),
310
316
  }),
311
317
  execute: async (args) => {
312
- const { server, tool, args_json } = args
313
- console.log(`[MCPExecutor] mcp_call: server=${server}, tool=${tool}, args_json=${args_json}`)
318
+ const { server, tool, args_json } = args;
319
+ log.info(` mcp_call: server=${server}, tool=${tool}, args_json=${args_json}`);
314
320
 
315
- const clientInfo = this._clients.get(server)
321
+ const clientInfo = this._clients.get(server);
316
322
  if (!clientInfo) {
317
- return { success: false, error: `MCP server '${server}' not found` }
323
+ return { success: false, error: `MCP server '${server}' not found` };
318
324
  }
319
325
 
320
326
  // 解析 args_json
321
- let finalArgs = {}
327
+ let finalArgs = {};
322
328
  if (args_json) {
323
329
  try {
324
- finalArgs = JSON.parse(args_json)
330
+ finalArgs = JSON.parse(args_json);
325
331
  } catch (e) {
326
- return { success: false, error: `args_json 格式错误,不是有效的 JSON: ${args_json}` }
332
+ return { success: false, error: `args_json 格式错误,不是有效的 JSON: ${args_json}` };
327
333
  }
328
334
  }
329
335
 
330
336
  // 检查参数是否为空
331
337
  if (!finalArgs || Object.keys(finalArgs).length === 0) {
332
- const toolInfo = clientInfo.tools.find(t => t.name === tool)
338
+ const toolInfo = clientInfo.tools.find((t) => t.name === tool);
333
339
  if (toolInfo) {
334
- const schema = this._extractSchema(toolInfo.inputSchema)
335
- const required = schema.required || []
340
+ const schema = this._extractSchema(toolInfo.inputSchema);
341
+ const required = schema.required || [];
336
342
  return {
337
343
  success: false,
338
344
  error: `参数为空!必须提供: ${required.join(', ')}`,
339
- hint: `正确格式: {"${required[0]}": "具体值"}`
340
- }
345
+ hint: `正确格式: {"${required[0]}": "具体值"}`,
346
+ };
341
347
  }
342
348
  }
343
349
 
344
350
  try {
345
351
  // 使用缓存的工具对象
346
- const mcpTool = clientInfo.toolObjects?.[tool]
352
+ const mcpTool = clientInfo.toolObjects?.[tool];
347
353
  if (!mcpTool) {
348
- return { success: false, error: `Tool '${tool}' not found on server '${server}'` }
354
+ return { success: false, error: `Tool '${tool}' not found on server '${server}'` };
349
355
  }
350
- const execResult = await mcpTool.execute(finalArgs)
351
- return { success: true, result: execResult }
356
+ const execResult = await mcpTool.execute(finalArgs);
357
+ return { success: true, result: execResult };
352
358
  } catch (err) {
353
- console.error(`[MCPExecutor] Tool '${tool}' failed:`, err.message)
354
- return { success: false, error: err.message }
359
+ log.error(` Tool '${tool}' failed:`, err.message);
360
+ return { success: false, error: err.message };
355
361
  }
356
- }
357
- })
362
+ },
363
+ });
358
364
 
359
365
  // 注册 mcp_list_servers 工具
360
366
  framework.registerTool({
@@ -362,89 +368,94 @@ class MCPExecutorPlugin extends Plugin {
362
368
  description: '列出已连接的 MCP 服务器及其工具',
363
369
  inputSchema: z.object({}),
364
370
  execute: async () => {
365
- const servers = []
371
+ const servers = [];
366
372
  for (const [name, info] of this._clients) {
367
373
  servers.push({
368
374
  name,
369
- tools: info.tools.map(t => ({ name: t.name, description: t.description }))
370
- })
375
+ tools: info.tools.map((t) => ({ name: t.name, description: t.description })),
376
+ });
371
377
  }
372
- return { success: true, servers }
373
- }
374
- })
378
+ return { success: true, servers };
379
+ },
380
+ });
375
381
 
376
382
  // 注册 mcp_reload 工具
377
383
  framework.registerTool({
378
384
  name: 'mcp_reload',
379
- description: '重新加载 MCP 服务器配置。当配置文件 .agent/mcp_config.json 修改后使用此工具重载配置',
385
+ description:
386
+ '重新加载 MCP 服务器配置。当配置文件 .agent/mcp_config.json 修改后使用此工具重载配置',
380
387
  inputSchema: z.object({}),
381
388
  execute: async () => {
382
- console.log('[MCPExecutor] mcp_reload called')
389
+ log.info(' mcp_reload called');
383
390
  try {
384
- const fs = require('fs')
385
- const path = require('path')
386
- const configPath = path.resolve('.agent/mcp_config.json')
391
+ const fs = require('fs');
392
+ const path = require('path');
393
+ const configPath = path.resolve('.agent/mcp_config.json');
387
394
 
388
- console.log('[MCPExecutor] Reading config from:', configPath)
395
+ log.info(' Reading config from:', configPath);
389
396
  if (!fs.existsSync(configPath)) {
390
- return { success: false, error: `配置文件不存在: ${configPath}` }
397
+ return { success: false, error: `配置文件不存在: ${configPath}` };
391
398
  }
392
399
 
393
- const configContent = fs.readFileSync(configPath, 'utf8')
394
- const config = JSON.parse(configContent)
395
- console.log('[MCPExecutor] Config loaded, reloading...')
400
+ const configContent = fs.readFileSync(configPath, 'utf8');
401
+ const config = JSON.parse(configContent);
402
+ log.info(' Config loaded, reloading...');
396
403
 
397
- await this.reloadConfig(config)
398
- console.log('[MCPExecutor] Reload complete')
404
+ await this.reloadConfig(config);
405
+ log.info(' Reload complete');
399
406
 
400
- return { success: true, message: 'MCP 配置已重载', servers: Object.keys(config.mcpServers || {}) }
407
+ return {
408
+ success: true,
409
+ message: 'MCP 配置已重载',
410
+ servers: Object.keys(config.mcpServers || {}),
411
+ };
401
412
  } catch (err) {
402
- console.error('[MCPExecutor] Reload error:', err)
403
- return { success: false, error: `重载失败: ${err.message}` }
413
+ log.error(' Reload error:', err);
414
+ return { success: false, error: `重载失败: ${err.message}` };
404
415
  }
405
- }
406
- })
416
+ },
417
+ });
407
418
 
408
419
  // 监听 agent 创建事件,附加 MCP 信息到系统提示词
409
420
  framework.on('agent:created', (agent) => {
410
421
  if (!this._mainAgent) {
411
- this._mainAgent = agent
422
+ this._mainAgent = agent;
412
423
  }
413
- this._refreshAgentMCPPrompt(agent)
414
- })
424
+ this._refreshAgentMCPPrompt(agent);
425
+ });
415
426
 
416
427
  // 等待框架就绪后,刷新所有已有 agent 的 MCP 提示词
417
428
  if (framework._ready) {
418
- this._refreshAllAgentsMCPPrompt(framework)
429
+ this._refreshAllAgentsMCPPrompt(framework);
419
430
  } else {
420
431
  framework.once('framework:ready', () => {
421
- this._refreshAllAgentsMCPPrompt(framework)
422
- })
432
+ this._refreshAllAgentsMCPPrompt(framework);
433
+ });
423
434
  }
424
435
 
425
- return this
436
+ return this;
426
437
  }
427
438
 
428
439
  /**
429
440
  * 刷新所有 agent 的 MCP 提示词(包括子 agent)
430
441
  */
431
442
  _refreshAllAgentsMCPPrompt(framework) {
432
- const visited = new Set()
443
+ const visited = new Set();
433
444
 
434
445
  const traverse = (agent) => {
435
- if (!agent || visited.has(agent)) return
436
- visited.add(agent)
437
- this._refreshAgentMCPPrompt(agent)
446
+ if (!agent || visited.has(agent)) return;
447
+ visited.add(agent);
448
+ this._refreshAgentMCPPrompt(agent);
438
449
 
439
450
  // 递归处理子 agent
440
- const subAgents = agent.getSubAgents?.() || agent._subAgents || new Map()
451
+ const subAgents = agent.getSubAgents?.() || agent._subAgents || new Map();
441
452
  for (const [name, subAgentInfo] of subAgents) {
442
- traverse(subAgentInfo.agent)
453
+ traverse(subAgentInfo.agent);
443
454
  }
444
- }
455
+ };
445
456
 
446
457
  for (const agent of framework._agents || []) {
447
- traverse(agent)
458
+ traverse(agent);
448
459
  }
449
460
  }
450
461
 
@@ -453,27 +464,27 @@ class MCPExecutorPlugin extends Plugin {
453
464
  */
454
465
  _refreshAgentMCPPrompt(agent) {
455
466
  // 检查是否已刷新过(通过检查系统提示词是否已包含 MCP 描述)
456
- const existingPrompt = agent._originalPrompt || ''
467
+ const existingPrompt = agent._originalPrompt || '';
457
468
  if (existingPrompt.includes('[MCP Servers]')) {
458
- return
469
+ return;
459
470
  }
460
471
 
461
- const mcpDesc = this._buildMCPServersDescription()
462
- if (!mcpDesc) return
472
+ const mcpDesc = this._buildMCPServersDescription();
473
+ if (!mcpDesc) return;
463
474
 
464
475
  // 将 MCP 描述追加到系统提示词
465
- agent.setSystemPrompt(existingPrompt + '\n\n' + mcpDesc)
476
+ agent.setSystemPrompt(existingPrompt + '\n\n' + mcpDesc);
466
477
  }
467
478
 
468
479
  /**
469
480
  * 从 inputSchema 中提取实际 schema
470
481
  */
471
482
  _extractSchema(inputSchema) {
472
- if (!inputSchema) return {}
483
+ if (!inputSchema) return {};
473
484
  // 处理 {jsonSchema: {...}} 格式
474
- if (inputSchema.jsonSchema) return inputSchema.jsonSchema
485
+ if (inputSchema.jsonSchema) return inputSchema.jsonSchema;
475
486
  // 处理直接是 schema 的格式
476
- return inputSchema
487
+ return inputSchema;
477
488
  }
478
489
 
479
490
  /**
@@ -481,61 +492,62 @@ class MCPExecutorPlugin extends Plugin {
481
492
  */
482
493
  _buildMCPServersDescription() {
483
494
  if (this._clients.size === 0) {
484
- return ''
495
+ return '';
485
496
  }
486
497
 
487
- let desc = '【MCP Servers - 可用工具服务】\n'
488
- desc += '你可以通过 mcp_call 工具调用以下 MCP 服务器的工具。\n\n'
498
+ let desc = '【MCP Servers - 可用工具服务】\n';
499
+ desc += '你可以通过 mcp_call 工具调用以下 MCP 服务器的工具。\n\n';
489
500
 
490
501
  for (const [serverName, info] of this._clients) {
491
- desc += `【${serverName}】\n`
502
+ desc += `【${serverName}】\n`;
492
503
  for (const tool of info.tools) {
493
- const schema = this._extractSchema(tool.inputSchema)
494
- const props = schema.properties || {}
495
- const required = schema.required || []
504
+ const schema = this._extractSchema(tool.inputSchema);
505
+ const props = schema.properties || {};
506
+ const required = schema.required || [];
496
507
 
497
508
  // 简化参数列表
498
- let paramStr = ''
509
+ let paramStr = '';
499
510
  if (Object.keys(props).length > 0) {
500
511
  const params = Object.entries(props).map(([key, prop]) => {
501
- const isRequired = required.includes(key)
502
- return `${key}${isRequired ? '(必填)' : ''}`
503
- })
504
- paramStr = ` 参数: ${params.join(', ')}`
512
+ const isRequired = required.includes(key);
513
+ return `${key}${isRequired ? '(必填)' : ''}`;
514
+ });
515
+ paramStr = ` 参数: ${params.join(', ')}`;
505
516
  }
506
517
 
507
518
  // 截取描述的第一句
508
- const shortDesc = tool.description?.split('.')[0] || '无描述'
509
- desc += `- ${tool.name}: ${shortDesc}${paramStr}\n`
519
+ const shortDesc = tool.description?.split('.')[0] || '无描述';
520
+ desc += `- ${tool.name}: ${shortDesc}${paramStr}\n`;
510
521
  }
511
- desc += '\n'
522
+ desc += '\n';
512
523
  }
513
524
 
514
- desc += '调用格式:mcp_call({ server: "服务器", tool: "工具", args_json: \'{"参数": "值"}\' })\n'
515
- desc += '复杂参数时先用 mcp_tool_schema 查询完整参数结构\n'
516
- return desc.trim()
525
+ desc +=
526
+ '调用格式:mcp_call({ server: "服务器", tool: "工具", args_json: \'{"参数": "值"}\' })\n';
527
+ desc += '复杂参数时先用 mcp_tool_schema 查询完整参数结构\n';
528
+ return desc.trim();
517
529
  }
518
530
 
519
531
  _getParentAgent() {
520
532
  // 优先返回已缓存的主 agent
521
533
  if (this._mainAgent) {
522
- return this._mainAgent
534
+ return this._mainAgent;
523
535
  }
524
536
 
525
537
  // 尝试从 framework 获取
526
538
  if (this._framework._mainAgent) {
527
- this._mainAgent = this._framework._mainAgent
528
- return this._mainAgent
539
+ this._mainAgent = this._framework._mainAgent;
540
+ return this._mainAgent;
529
541
  }
530
542
 
531
543
  // 查找最后一个创建的 agent 作为父 agent
532
- const agents = this._framework._agents || []
544
+ const agents = this._framework._agents || [];
533
545
  if (agents.length > 0) {
534
- this._mainAgent = agents[agents.length - 1]
535
- return this._mainAgent
546
+ this._mainAgent = agents[agents.length - 1];
547
+ return this._mainAgent;
536
548
  }
537
549
 
538
- return null
550
+ return null;
539
551
  }
540
552
 
541
553
  /**
@@ -546,21 +558,21 @@ class MCPExecutorPlugin extends Plugin {
546
558
  promise,
547
559
  new Promise((_, reject) =>
548
560
  setTimeout(() => reject(new Error(`${name} timeout (${ms}ms)`)), ms)
549
- )
550
- ])
561
+ ),
562
+ ]);
551
563
  }
552
564
 
553
565
  /**
554
566
  * 添加 MCP 服务器
555
567
  */
556
568
  async addServer(config) {
557
- const { name, command, args = [], env, url, type, headers = {}, authProvider } = config
569
+ const { name, command, args = [], env, url, type, headers = {}, authProvider } = config;
558
570
  if (this._clients.has(name)) {
559
- console.warn(`[MCPExecutor] Server '${name}' already exists, skipping`)
560
- return
571
+ log.warn(` Server '${name}' already exists, skipping`);
572
+ return;
561
573
  }
562
- console.log(`[MCPExecutor] Connecting to ${name}...`)
563
- let client
574
+ log.info(` Connecting to ${name}...`);
575
+ let client;
564
576
  try {
565
577
  if (['sse', 'http'].includes(type)) {
566
578
  client = await this._withTimeout(
@@ -571,51 +583,51 @@ class MCPExecutorPlugin extends Plugin {
571
583
  headers: headers,
572
584
  authProvider: authProvider,
573
585
  redirect: 'error',
574
- env: env
586
+ env: env,
575
587
  },
576
588
  }),
577
589
  10000,
578
590
  `createMCPClient ${name}`
579
- )
591
+ );
580
592
  } else {
581
593
  client = await this._withTimeout(
582
594
  createMCPClient({
583
595
  transport: new StdioClientTransport({
584
596
  command: command,
585
597
  args: args,
586
- env: env
598
+ env: env,
587
599
  }),
588
600
  }),
589
601
  10000,
590
602
  `createMCPClient ${name}`
591
- )
603
+ );
592
604
  }
593
605
  } catch (err) {
594
- console.error(`[MCPExecutor] Failed to create client '${name}':`, err.message)
595
- return
606
+ log.error(` Failed to create client '${name}':`, err.message);
607
+ return;
596
608
  }
597
609
 
598
610
  // 获取 MCP 服务器的工具列表
599
- let mcpTools
611
+ let mcpTools;
600
612
  try {
601
- mcpTools = await this._withTimeout(client.tools(), 10000, `client.tools ${name}`)
613
+ mcpTools = await this._withTimeout(client.tools(), 10000, `client.tools ${name}`);
602
614
  } catch (err) {
603
- console.error(`[MCPExecutor] Failed to get tools from '${name}':`, err.message)
604
- return
615
+ log.error(` Failed to get tools from '${name}':`, err.message);
616
+ return;
605
617
  }
606
618
 
607
619
  // 提取工具信息和实际工具对象
608
- const toolsInfo = []
609
- const toolObjects = {} // 缓存实际工具对象
620
+ const toolsInfo = [];
621
+ const toolObjects = {}; // 缓存实际工具对象
610
622
  if (mcpTools && typeof mcpTools === 'object') {
611
623
  for (const [toolName, tool] of Object.entries(mcpTools)) {
612
- if (!tool) continue
613
- toolObjects[toolName] = tool // 保存实际工具对象
624
+ if (!tool) continue;
625
+ toolObjects[toolName] = tool; // 保存实际工具对象
614
626
  toolsInfo.push({
615
627
  name: toolName,
616
628
  description: tool.description || '',
617
- inputSchema: tool.inputSchema || {}
618
- })
629
+ inputSchema: tool.inputSchema || {},
630
+ });
619
631
  }
620
632
  }
621
633
 
@@ -623,31 +635,31 @@ class MCPExecutorPlugin extends Plugin {
623
635
  this._clients.set(name, {
624
636
  client,
625
637
  tools: toolsInfo,
626
- toolObjects // 实际工具对象,供 mcp_call 直接调用
627
- })
638
+ toolObjects, // 实际工具对象,供 mcp_call 直接调用
639
+ });
628
640
 
629
- console.log(`[MCPExecutor] Added server '${name}' with ${toolsInfo.length} tools`)
641
+ log.info(` Added server '${name}' with ${toolsInfo.length} tools`);
630
642
  }
631
643
 
632
644
  /**
633
645
  * 移除 MCP 服务器
634
646
  */
635
647
  async removeServer(name) {
636
- const clientInfo = this._clients.get(name)
648
+ const clientInfo = this._clients.get(name);
637
649
  if (clientInfo) {
638
650
  try {
639
651
  // 添加超时保护,避免 close/destroy 阻塞
640
- const closePromise = clientInfo.client.close?.() || clientInfo.client.destroy?.()
652
+ const closePromise = clientInfo.client.close?.() || clientInfo.client.destroy?.();
641
653
  if (closePromise && typeof closePromise.then === 'function') {
642
654
  await Promise.race([
643
655
  closePromise,
644
- new Promise(resolve => setTimeout(() => resolve(), 3000))
645
- ])
656
+ new Promise((resolve) => setTimeout(() => resolve(), 3000)),
657
+ ]);
646
658
  }
647
659
  } catch (e) {
648
660
  // ignore
649
661
  }
650
- this._clients.delete(name)
662
+ this._clients.delete(name);
651
663
  }
652
664
  }
653
665
 
@@ -657,13 +669,13 @@ class MCPExecutorPlugin extends Plugin {
657
669
  getServers() {
658
670
  return Array.from(this._clients.entries()).map(([name, info]) => ({
659
671
  name,
660
- tools: info.tools.map(t => t.name)
661
- }))
672
+ tools: info.tools.map((t) => t.name),
673
+ }));
662
674
  }
663
675
 
664
676
  reload(framework) {
665
- console.log('[MCPExecutor] Reloading...')
666
- this._framework = framework
677
+ log.info(' Reloading...');
678
+ this._framework = framework;
667
679
  }
668
680
 
669
681
  /**
@@ -671,21 +683,21 @@ class MCPExecutorPlugin extends Plugin {
671
683
  * @param {Object} config - 新的配置对象,包含 mcpServers
672
684
  */
673
685
  async reloadConfig(config) {
674
- console.log('[MCPExecutor] reloadConfig start')
675
- const newServers = config?.mcpServers || {}
686
+ log.info(' reloadConfig start');
687
+ const newServers = config?.mcpServers || {};
676
688
 
677
689
  // 1. 先快速清理所有旧服务器(不等待 close 完成)
678
- console.log('[MCPExecutor] Clearing old servers...')
690
+ log.info(' Clearing old servers...');
679
691
  for (const [name, clientInfo] of this._clients) {
680
692
  try {
681
693
  // 不等待 close,直接删除
682
- clientInfo.client.close?.()?.catch?.(() => {})
694
+ clientInfo.client.close?.()?.catch?.(() => {});
683
695
  } catch (e) {}
684
696
  }
685
- this._clients.clear()
697
+ this._clients.clear();
686
698
 
687
699
  // 2. 并行添加新服务器
688
- console.log('[MCPExecutor] Adding new servers...')
700
+ log.info(' Adding new servers...');
689
701
  const addPromises = Object.entries(newServers).map(async ([name, serverConfig]) => {
690
702
  const normalizedConfig = {
691
703
  name,
@@ -695,17 +707,17 @@ class MCPExecutorPlugin extends Plugin {
695
707
  authProvider: serverConfig.authProvider,
696
708
  command: serverConfig.command,
697
709
  args: serverConfig.args,
698
- env: serverConfig.env
699
- }
700
- await this.addServer(normalizedConfig)
701
- })
710
+ env: serverConfig.env,
711
+ };
712
+ await this.addServer(normalizedConfig);
713
+ });
702
714
 
703
- await Promise.all(addPromises)
704
- console.log('[MCPExecutor] reloadConfig complete')
715
+ await Promise.all(addPromises);
716
+ log.info(' reloadConfig complete');
705
717
 
706
718
  // 3. 刷新所有 agent 的 MCP 提示词
707
719
  if (this._framework) {
708
- this._refreshAllAgentsMCPPrompt(this._framework)
720
+ this._refreshAllAgentsMCPPrompt(this._framework);
709
721
  }
710
722
  }
711
723
 
@@ -713,17 +725,17 @@ class MCPExecutorPlugin extends Plugin {
713
725
  // 断开所有 MCP 连接
714
726
  for (const [name, clientInfo] of this._clients) {
715
727
  try {
716
- await clientInfo.client.close?.() || clientInfo.client.destroy?.()
728
+ (await clientInfo.client.close?.()) || clientInfo.client.destroy?.();
717
729
  } catch (e) {
718
730
  // ignore
719
731
  }
720
732
  }
721
- this._clients.clear()
722
- this._framework = null
733
+ this._clients.clear();
734
+ this._framework = null;
723
735
  }
724
736
  }
725
737
 
726
738
  module.exports = {
727
739
  MCPExecutorPlugin,
728
- MCPClientWrapper
729
- }
740
+ MCPClientWrapper,
741
+ };