foliko 1.1.6 → 1.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agent/.shared/ui-ux-pro-max/data/charts.csv +26 -0
- package/.agent/.shared/ui-ux-pro-max/data/colors.csv +97 -0
- package/.agent/.shared/ui-ux-pro-max/data/icons.csv +101 -0
- package/.agent/.shared/ui-ux-pro-max/data/landing.csv +31 -0
- package/.agent/.shared/ui-ux-pro-max/data/products.csv +97 -0
- package/.agent/.shared/ui-ux-pro-max/data/prompts.csv +24 -0
- package/.agent/.shared/ui-ux-pro-max/data/react-performance.csv +45 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/react.csv +54 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/vue.csv +50 -0
- package/.agent/.shared/ui-ux-pro-max/data/styles.csv +59 -0
- package/.agent/.shared/ui-ux-pro-max/data/typography.csv +58 -0
- package/.agent/.shared/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
- package/.agent/.shared/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
- package/.agent/.shared/ui-ux-pro-max/data/web-interface.csv +31 -0
- package/.agent/.shared/ui-ux-pro-max/scripts/__pycache__/core.cpython-313.pyc +0 -0
- package/.agent/.shared/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-313.pyc +0 -0
- package/.agent/.shared/ui-ux-pro-max/scripts/core.py +258 -0
- package/.agent/.shared/ui-ux-pro-max/scripts/design_system.py +1067 -0
- package/.agent/.shared/ui-ux-pro-max/scripts/search.py +106 -0
- package/.agent/ARCHITECTURE.md +288 -0
- package/.agent/agents/ambient-agent.md +57 -0
- package/.agent/agents/debugger.md +55 -0
- package/.agent/agents/email-assistant.md +49 -0
- package/.agent/agents/file-manager.md +42 -0
- package/.agent/agents/python-developer.md +60 -0
- package/.agent/agents/scheduler.md +59 -0
- package/.agent/agents/web-developer.md +45 -0
- package/.agent/data/default.json +412 -3
- package/.agent/data/plugins-state.json +177 -174
- package/.agent/data/puppeteer-sessions/undefined.json +6 -0
- package/.agent/data/weixin-media/2026-04-08/img_1775618677512.jpg +0 -0
- package/.agent/data/weixin-media/2026-04-08/img_1775619073340.jpg +0 -0
- package/.agent/data/weixin-media/2026-04-08/img_1775619097536.jpg +0 -0
- package/.agent/data/weixin-media/2026-04-08/img_1775619209388.jpg +0 -0
- package/.agent/mcp_config.json +11 -3
- package/.agent/memory/feedback/mnrdvj5i-ca3dkd.md +9 -0
- package/.agent/memory/feedback/mnre365e-7s4zax.md +9 -0
- package/.agent/memory/feedback/mnre36jn-nkfgmp.md +9 -0
- package/.agent/memory/feedback/mnre3805-kjiq6h.md +9 -0
- package/.agent/memory/feedback/mnsf66kp-b10rcd.md +9 -0
- package/.agent/memory/feedback/mnsi3sz8-p5g2cw.md +9 -0
- package/.agent/memory/feedback/mnsibe47-sv2ni1.md +9 -0
- package/.agent/memory/feedback/mnsic89w-nn228o.md +9 -0
- package/.agent/memory/feedback/mnsj1xe9-x83ba0.md +9 -0
- package/.agent/memory/feedback/mnsj21iv-wnwelx.md +9 -0
- package/.agent/memory/feedback/mnsj2g4a-cog7a2.md +9 -0
- package/.agent/memory/feedback/mnsj4js7-lktjp6.md +9 -0
- package/.agent/memory/feedback/mnsj5d4y-uglwvp.md +9 -0
- package/.agent/memory/feedback/mnslkuo9-uous66.md +24 -0
- package/.agent/memory/feedback/mnsm3vq0-megoil.md +9 -0
- package/.agent/memory/feedback/mnsnn5x2-sxcihd.md +9 -0
- package/.agent/memory/feedback/mnsnq17s-nabrn9.md +9 -0
- package/.agent/memory/feedback/mnsnybet-wz7rn3.md +9 -0
- package/.agent/memory/feedback/mnsrw0s7-7s9e30.md +9 -0
- package/.agent/memory/feedback/mnu5hpnd-tlm16q.md +9 -0
- package/.agent/memory/feedback/mnu60uqe-xuoxp4.md +9 -0
- package/.agent/memory/project/mnqx54u5-loqtoe.md +9 -0
- package/.agent/memory/project/mnqx84cv-mx6dmd.md +9 -0
- package/.agent/memory/project/mnsacuyr-hgtk5n.md +20 -0
- package/.agent/memory/project/mnu5hy2x-bjsg7u.md +9 -0
- package/.agent/memory/reference/mnre3cww-penbo1.md +9 -0
- package/.agent/memory/reference/mns9wn48-luerua.md +14 -0
- package/.agent/memory/reference/mns9yz5c-thc2s0.md +16 -0
- package/.agent/memory/reference/mnsfy4um-910f1o.md +23 -0
- package/.agent/memory/reference/mnsg37dp-lmfj18.md +32 -0
- package/.agent/memory/reference/mnsll60q-0j911u.md +36 -0
- package/.agent/memory/reference/mnsmlb5y-nej31u.md +16 -0
- package/.agent/memory/reference/mnssle72-yrot96.md +9 -0
- package/.agent/memory/user/mnsfuon6-l416q1.md +21 -0
- package/.agent/memory/user/mnsg9kut-95m7rf.md +20 -0
- package/.agent/memory/user/mnu2eo1v-yy6fhe.md +9 -0
- package/.agent/memory/user/mnu2etuo-8u8jk8.md +9 -0
- package/.agent/plugins/poster-plugin/fonts/NotoColorEmoji-Regular.ttf +0 -0
- package/.agent/plugins/poster-plugin/fonts/Symbola_hint.ttf +0 -0
- package/.agent/plugins/poster-plugin/package.json +3 -3
- package/.agent/plugins/poster-plugin/src/canvas.js +8 -0
- package/.agent/plugins/poster-plugin/src/components/barcode.js +5 -2
- package/.agent/plugins/poster-plugin/src/components/bubble.js +3 -2
- package/.agent/plugins/poster-plugin/src/components/button.js +74 -30
- package/.agent/plugins/poster-plugin/src/components/columns.js +97 -83
- package/.agent/plugins/poster-plugin/src/components/grid.js +104 -92
- package/.agent/plugins/poster-plugin/src/components/highlightText.js +2 -1
- package/.agent/plugins/poster-plugin/src/components/imageFrame.js +143 -93
- package/.agent/plugins/poster-plugin/src/components/quote.js +85 -13
- package/.agent/plugins/poster-plugin/src/components/ribbon.js +13 -9
- package/.agent/plugins/poster-plugin/src/components/seal.js +5 -3
- package/.agent/plugins/poster-plugin/src/components/star.js +3 -3
- package/.agent/plugins/poster-plugin/src/components/table.js +1 -1
- package/.agent/plugins/poster-plugin/src/components/watermark.js +4 -2
- package/.agent/plugins/poster-plugin/src/composer.js +181 -13
- package/.agent/plugins/poster-plugin/src/elements/artText.js +16 -7
- package/.agent/plugins/poster-plugin/src/elements/background.js +20 -5
- package/.agent/plugins/poster-plugin/src/elements/richText.js +160 -107
- package/.agent/plugins/poster-plugin/src/elements/text.js +48 -45
- package/.agent/plugins/poster-plugin/src/fonts.js +556 -125
- package/.agent/plugins/poster-plugin/src/index.js +46 -1
- package/.agent/plugins/poster-plugin/yarn.lock +186 -356
- package/.agent/plugins/puppeteer-plugin/README.md +147 -0
- package/.agent/plugins/puppeteer-plugin/index.js +1422 -0
- package/.agent/plugins/puppeteer-plugin/package.json +9 -0
- package/.agent/plugins.json +5 -11
- package/.agent/rules/GEMINI.md +273 -0
- package/.agent/rules/allow-rule.md +77 -0
- package/.agent/rules/log-rule.md +83 -0
- package/.agent/rules/security-rule.md +93 -0
- package/.agent/scripts/auto_preview.py +148 -0
- package/.agent/scripts/checklist.py +217 -0
- package/.agent/scripts/session_manager.py +120 -0
- package/.agent/scripts/verify_all.py +327 -0
- package/.agent/sessions/cli_default.json +128 -5479
- package/.agent/skills/api-patterns/SKILL.md +81 -0
- package/.agent/skills/api-patterns/api-style.md +42 -0
- package/.agent/skills/api-patterns/auth.md +24 -0
- package/.agent/skills/api-patterns/documentation.md +26 -0
- package/.agent/skills/api-patterns/graphql.md +41 -0
- package/.agent/skills/api-patterns/rate-limiting.md +31 -0
- package/.agent/skills/api-patterns/response.md +37 -0
- package/.agent/skills/api-patterns/rest.md +40 -0
- package/.agent/skills/api-patterns/scripts/api_validator.py +211 -0
- package/.agent/skills/api-patterns/security-testing.md +122 -0
- package/.agent/skills/api-patterns/trpc.md +41 -0
- package/.agent/skills/api-patterns/versioning.md +22 -0
- package/.agent/skills/app-builder/SKILL.md +75 -0
- package/.agent/skills/app-builder/agent-coordination.md +71 -0
- package/.agent/skills/app-builder/feature-building.md +53 -0
- package/.agent/skills/app-builder/project-detection.md +34 -0
- package/.agent/skills/app-builder/scaffolding.md +118 -0
- package/.agent/skills/app-builder/tech-stack.md +40 -0
- package/.agent/skills/app-builder/templates/SKILL.md +39 -0
- package/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +76 -0
- package/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +92 -0
- package/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +88 -0
- package/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +88 -0
- package/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +83 -0
- package/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +90 -0
- package/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +90 -0
- package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +122 -0
- package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +122 -0
- package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +169 -0
- package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +134 -0
- package/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +83 -0
- package/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +119 -0
- package/.agent/skills/architecture/SKILL.md +55 -0
- package/.agent/skills/architecture/context-discovery.md +43 -0
- package/.agent/skills/architecture/examples.md +94 -0
- package/.agent/skills/architecture/pattern-selection.md +68 -0
- package/.agent/skills/architecture/patterns-reference.md +50 -0
- package/.agent/skills/architecture/trade-off-analysis.md +77 -0
- package/.agent/skills/clean-code/SKILL.md +201 -0
- package/.agent/skills/doc.md +177 -0
- package/.agent/skills/frontend-design/SKILL.md +418 -0
- package/.agent/skills/frontend-design/animation-guide.md +331 -0
- package/.agent/skills/frontend-design/color-system.md +311 -0
- package/.agent/skills/frontend-design/decision-trees.md +418 -0
- package/.agent/skills/frontend-design/motion-graphics.md +306 -0
- package/.agent/skills/frontend-design/scripts/accessibility_checker.py +183 -0
- package/.agent/skills/frontend-design/scripts/ux_audit.py +722 -0
- package/.agent/skills/frontend-design/typography-system.md +345 -0
- package/.agent/skills/frontend-design/ux-psychology.md +1116 -0
- package/.agent/skills/frontend-design/visual-effects.md +383 -0
- package/.agent/skills/i18n-localization/SKILL.md +154 -0
- package/.agent/skills/i18n-localization/scripts/i18n_checker.py +241 -0
- package/.agent/skills/mcp-builder/SKILL.md +176 -0
- package/.agent/skills/poster-design/SKILL.md +385 -0
- package/.agent/skills/web-design-guidelines/SKILL.md +57 -0
- package/.agent/workflows/brainstorm.md +113 -0
- package/.agent/workflows/create.md +59 -0
- package/.agent/workflows/debug.md +103 -0
- package/.agent/workflows/deploy.md +176 -0
- package/.agent/workflows/enhance.md +63 -0
- package/.agent/workflows/orchestrate.md +237 -0
- package/.agent/workflows/plan.md +89 -0
- package/.agent/workflows/preview.md +81 -0
- package/.agent/workflows/simple-test.md +42 -0
- package/.agent/workflows/status.md +86 -0
- package/.agent/workflows/structured-orchestrate.md +180 -0
- package/.agent/workflows/test.md +144 -0
- package/.agent/workflows/ui-ux-pro-max.md +296 -0
- package/.env.example +56 -56
- package/README.md +441 -441
- package/SPEC.md +735 -696
- package/output/foliko-poster.png +0 -0
- package/outputs/emoji-font-showcase.png +0 -0
- package/outputs/foliko-muji-style.png +0 -0
- package/package.json +3 -2
- package/plugins/ambient-agent/EventWatcher.js +33 -37
- package/plugins/ambient-agent/ExplorerLoop.js +338 -36
- package/plugins/ambient-agent/GoalManager.js +7 -3
- package/plugins/ambient-agent/StateStore.js +30 -1
- package/plugins/ambient-agent/constants.js +15 -1
- package/plugins/ambient-agent/index.js +26 -33
- package/plugins/coordinator-plugin.js +3 -3
- package/plugins/default-plugins.js +4 -3
- package/plugins/email/index.js +150 -36
- package/plugins/email/monitor.js +79 -5
- package/plugins/email/reply.js +15 -25
- package/plugins/extension-executor-plugin.js +184 -32
- package/plugins/feishu-plugin.js +2 -2
- package/plugins/file-system-plugin.js +57 -24
- package/plugins/memory-plugin.js +176 -64
- package/plugins/python-plugin-loader.js +79 -9
- package/plugins/scheduler-plugin.js +64 -24
- package/plugins/telegram-plugin.js +2 -2
- package/plugins/think-plugin.js +7 -2
- package/plugins/web-plugin.js +263 -4
- package/plugins/weixin-plugin.js +2 -2
- package/skills/ambient-agent/SKILL.md +342 -314
- package/skills/find-skills/AGENTS.md +162 -162
- package/skills/find-skills/SKILL.md +133 -133
- package/src/core/agent-chat.js +64 -9
- package/src/core/agent.js +216 -69
- package/src/core/tool-registry.js +5 -5
- package/src/executors/mcp-executor.js +453 -35
- package/src/utils/id.js +5 -0
- package/system.md +3629 -0
- package/.agent/agents/code-assistant.json +0 -17
- package/.agent/agents/email-assistant.json +0 -14
- package/.agent/agents/file-assistant.json +0 -18
- package/.agent/agents/orchestrator-demo.md +0 -53
- package/.agent/agents/orchestrator.json +0 -7
- package/.agent/agents/system-assistant.json +0 -15
- package/.agent/agents/web-assistant.json +0 -12
- package/.agent/data/ambient/goals.json +0 -50
- package/.agent/data/ambient/memories.json +0 -7
- package/.agent/data/scheduler/tasks.json +0 -1
- package/.agent/memory/core.md +0 -1
- package/.agent/memory/feedback/mnrsiuoc-e1ru74.md +0 -9
- package/.agent/memory/feedback/mnrt2mmz-98az6n.md +0 -9
- package/.agent/memory/feedback/mnrtqrhm-kxsicz.md +0 -9
- package/.agent/memory/feedback/mnrts8vg-i0ngzp.md +0 -15
- package/.agent/memory/feedback/mnrtt7jt-c0trb2.md +0 -9
- package/.agent/memory/feedback/mnruc2f0-5s52la.md +0 -16
- package/.agent/memory/feedback/mnrumbmx-63sa0v.md +0 -9
- package/.agent/memory/project/mnn93ogy-ypjn27.md +0 -9
- package/.agent/memory/project/mnn98fqy-5nhc1u.md +0 -25
- package/.agent/memory/project/mnrp7p5n-8enm2a.md +0 -31
- package/.agent/memory/project/mnrp9ifb-yynks0.md +0 -40
- package/.agent/memory/project/mnrpb3b8-f617s4.md +0 -25
- package/.agent/memory/project/mnrrmqgg-focprv.md +0 -9
- package/.agent/memory/project/mnrtykbh-6atsor.md +0 -9
- package/.agent/memory/project/mnru9jiu-kgau16.md +0 -35
- package/.agent/memory/reference/mnq3oenw-46haj6.md +0 -63
- package/.agent/memory/reference/mnq5qxm2-mjoooh.md +0 -116
- package/.agent/memory/reference/mnrnvpwo-rcqv9m.md +0 -52
- package/.agent/memory/reference/mnrovxvz-zy9xqm.md +0 -25
- package/.agent/memory/reference/mnroxabj-1b3930.md +0 -68
- package/.agent/memory/reference/mnrpjtlp-mnb9od.md +0 -35
- package/.agent/memory/reference/mnrps1x3-6b8xfm.md +0 -28
- package/.agent/memory/reference/mnrpt9ov-15er5w.md +0 -22
- package/.agent/memory/reference/mnrq82dn-y9tv9e.md +0 -50
- package/.agent/memory/reference/mnrqnr5v-v75drf.md +0 -34
- package/.agent/memory/reference/mnrrfzys-urudaf.md +0 -31
- package/.agent/memory/reference/mnrrocha-t0027n.md +0 -21
- package/.agent/memory/reference/mnrukklc-bxndsb.md +0 -35
- package/.agent/memory/user/mnm67t9m-x8rekk.md +0 -9
- package/.agent/memory/user/mnn5mmqh-w6aktx.md +0 -11
- package/.agent/memory/user/mnnbfhhn-dk1bd1.md +0 -22
- package/.agent/memory/user/mnrt39t8-8eosy0.md +0 -9
- package/.agent/package.json +0 -8
- package/.agent/plugins/__pycache__/file_writer.cpython-312.pyc +0 -0
- package/.agent/plugins/daytona/README.md +0 -89
- package/.agent/plugins/daytona/index.js +0 -377
- package/.agent/plugins/daytona/package.json +0 -12
- package/.agent/plugins/marknative/README.md +0 -134
- package/.agent/plugins/marknative/fonts/SegoeUI Emoji.ttf +0 -0
- package/.agent/plugins/marknative/fonts.zip +0 -0
- package/.agent/plugins/marknative/index.js +0 -256
- package/.agent/plugins/marknative/package.json +0 -12
- package/.agent/plugins/poster-plugin/emojis/rocket.png +0 -1
- package/.agent/plugins/poster-plugin/test-background.svg +0 -1
- package/.agent/plugins/poster-plugin/test-full-poster.svg +0 -2
- package/.agent/plugins/poster-plugin/test-image.png +0 -0
- package/.agent/plugins/system-info/index.js +0 -387
- package/.agent/plugins/system-info/package.json +0 -4
- package/.agent/plugins/system-info/test.js +0 -40
- package/.agent/python-scripts/test_sample.py +0 -24
- package/.agent/skills/agent-browser/SKILL.md +0 -311
- package/.agent/skills/agent-browser/TEST_PLAN.md +0 -200
- package/.agent/skills/sysinfo/SKILL.md +0 -38
- package/.agent/skills/sysinfo/system-info.sh +0 -130
- package/.agent/skills/workflow/SKILL.md +0 -324
- package/.agent/test-agent.js +0 -35
- package/.agent/weixin.json +0 -6
- package/.agent/workflows/email-digest.json +0 -50
- package/.agent/workflows/file-backup.json +0 -21
- package/.agent/workflows/get-ip-notify.json +0 -32
- package/.agent/workflows/news-aggregator.json +0 -93
- package/.agent/workflows/news-dashboard-v2.json +0 -94
- package/.agent/workflows/notification-batch.json +0 -32
- package/foliko-cloud-rising.png +0 -0
- package/foliko-dawn-of-ai.png +0 -0
- package/foliko-mindful-observation.png +0 -0
- package/foliko-stellar-dreams.png +0 -0
- package/foliko-zen-jing.png +0 -0
- package/foliko-zen-kong.png +0 -0
- package/foliko-zen-wu.png +0 -0
- package/zen_karesansui.png +0 -0
|
@@ -10,7 +10,7 @@ const path = require('path');
|
|
|
10
10
|
const { z } = require('zod');
|
|
11
11
|
const { createMCPClient } = require('@ai-sdk/mcp');
|
|
12
12
|
const { StdioClientTransport } = require('@modelcontextprotocol/sdk/client/stdio.js');
|
|
13
|
-
const {
|
|
13
|
+
const { zodSchemaToMarkdown } = require('@chnak/zod-to-markdown');
|
|
14
14
|
const { logger } = require('../utils/logger');
|
|
15
15
|
|
|
16
16
|
const log = logger.child('MCPExecutor');
|
|
@@ -193,7 +193,7 @@ class MCPClientWrapper {
|
|
|
193
193
|
class MCPExecutorPlugin extends Plugin {
|
|
194
194
|
constructor(config = {}) {
|
|
195
195
|
super();
|
|
196
|
-
this.name = 'mcp
|
|
196
|
+
this.name = 'mcp';
|
|
197
197
|
this.version = '1.0.0';
|
|
198
198
|
this.description = 'MCP (Model Context Protocol) 执行器';
|
|
199
199
|
this.priority = 11;
|
|
@@ -202,7 +202,12 @@ class MCPExecutorPlugin extends Plugin {
|
|
|
202
202
|
this._framework = null;
|
|
203
203
|
// serverName -> { client, tools: [{ name, description, inputSchema }], toolObjects: { toolName: actualTool } }
|
|
204
204
|
this._clients = new Map();
|
|
205
|
+
// 保存服务器配置,用于重新启用
|
|
206
|
+
this._serverConfigs = new Map();
|
|
205
207
|
this._config = config;
|
|
208
|
+
// 注册的工具对象(extension-executor 会扫描这个)
|
|
209
|
+
// 格式: { 'server_toolname': { name, description, inputSchema, execute } }
|
|
210
|
+
this.tools = {};
|
|
206
211
|
}
|
|
207
212
|
|
|
208
213
|
install(framework) {
|
|
@@ -214,6 +219,12 @@ class MCPExecutorPlugin extends Plugin {
|
|
|
214
219
|
// 先连接所有 MCP 服务器
|
|
215
220
|
if (this._config.servers) {
|
|
216
221
|
for (const serverConfig of this._config.servers) {
|
|
222
|
+
if (serverConfig.enabled === false) {
|
|
223
|
+
log.info(` Skipping disabled server: ${serverConfig.name}`);
|
|
224
|
+
// 保存完整配置,以便后续动态启用
|
|
225
|
+
this._serverConfigs.set(serverConfig.name, { ...serverConfig });
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
217
228
|
await this.addServer(serverConfig);
|
|
218
229
|
}
|
|
219
230
|
}
|
|
@@ -406,12 +417,26 @@ class MCPExecutorPlugin extends Plugin {
|
|
|
406
417
|
inputSchema: z.object({}),
|
|
407
418
|
execute: async () => {
|
|
408
419
|
const servers = [];
|
|
420
|
+
// 已连接的服务器
|
|
409
421
|
for (const [name, info] of this._clients) {
|
|
410
422
|
servers.push({
|
|
411
423
|
name,
|
|
424
|
+
enabled: true,
|
|
425
|
+
connected: true,
|
|
412
426
|
tools: info.tools.map((t) => ({ name: t.name, description: t.description })),
|
|
413
427
|
});
|
|
414
428
|
}
|
|
429
|
+
// 未连接的服务器(配置中存在但未启用)
|
|
430
|
+
for (const [name, config] of this._serverConfigs) {
|
|
431
|
+
if (!this._clients.has(name)) {
|
|
432
|
+
servers.push({
|
|
433
|
+
name,
|
|
434
|
+
enabled: false,
|
|
435
|
+
connected: false,
|
|
436
|
+
tools: [],
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
}
|
|
415
440
|
return { success: true, servers };
|
|
416
441
|
},
|
|
417
442
|
});
|
|
@@ -453,6 +478,77 @@ class MCPExecutorPlugin extends Plugin {
|
|
|
453
478
|
},
|
|
454
479
|
});
|
|
455
480
|
|
|
481
|
+
// 注册 mcp_set_enabled 工具 - 动态开启/关闭 MCP 服务器
|
|
482
|
+
framework.registerTool({
|
|
483
|
+
name: 'mcp_set_enabled',
|
|
484
|
+
description: '动态开启或关闭某个 MCP 服务器',
|
|
485
|
+
inputSchema: z.object({
|
|
486
|
+
server: z.string().describe('MCP 服务器名称'),
|
|
487
|
+
enabled: z.boolean().describe('true=开启,false=关闭'),
|
|
488
|
+
}),
|
|
489
|
+
execute: async (args) => {
|
|
490
|
+
const { server, enabled } = args;
|
|
491
|
+
const clientInfo = this._clients.get(server);
|
|
492
|
+
const serverConfig = this._serverConfigs.get(server);
|
|
493
|
+
|
|
494
|
+
if (enabled) {
|
|
495
|
+
// 启用服务器
|
|
496
|
+
if (clientInfo && clientInfo.enabled) {
|
|
497
|
+
return { success: true, message: `MCP 服务器 '${server}' 已经是开启状态` };
|
|
498
|
+
}
|
|
499
|
+
// 如果服务器从未连接过,也检查配置中的 enabled 状态
|
|
500
|
+
if (!clientInfo && serverConfig && serverConfig.enabled === false) {
|
|
501
|
+
// 服务器是被禁用的,可以尝试启用
|
|
502
|
+
}
|
|
503
|
+
log.info(
|
|
504
|
+
`[MCP] Enabling server: ${server}, clientInfo=${!!clientInfo}, serverConfig.enabled=${serverConfig?.enabled}`
|
|
505
|
+
);
|
|
506
|
+
try {
|
|
507
|
+
if (serverConfig) {
|
|
508
|
+
const result = await this.addServer({ ...serverConfig, enabled: true });
|
|
509
|
+
log.info(`[MCP] addServer result:`, JSON.stringify(result));
|
|
510
|
+
if (!result || result.success === false) {
|
|
511
|
+
this._refreshAllAgentsMCPPrompt(this._framework);
|
|
512
|
+
return result;
|
|
513
|
+
}
|
|
514
|
+
// 保存 enabled 状态到配置文件
|
|
515
|
+
await this._saveMCPServerEnabled(server, true);
|
|
516
|
+
this._refreshAllAgentsMCPPrompt(this._framework);
|
|
517
|
+
return { success: true, message: `MCP 服务器 '${server}' 已开启` };
|
|
518
|
+
} else {
|
|
519
|
+
return { success: false, error: '服务器配置不存在,需要重载配置' };
|
|
520
|
+
}
|
|
521
|
+
} catch (err) {
|
|
522
|
+
log.error(`[MCP] Enabling failed:`, err.message);
|
|
523
|
+
return { success: false, error: `开启失败: ${err.message}` };
|
|
524
|
+
}
|
|
525
|
+
} else {
|
|
526
|
+
// 禁用服务器
|
|
527
|
+
if (!clientInfo) {
|
|
528
|
+
return { success: false, error: `MCP server '${server}' not found` };
|
|
529
|
+
}
|
|
530
|
+
log.info(` Disabling MCP server: ${server}`);
|
|
531
|
+
try {
|
|
532
|
+
clientInfo.client.close?.();
|
|
533
|
+
} catch (e) {}
|
|
534
|
+
// 从 clients 中移除
|
|
535
|
+
this._clients.delete(server);
|
|
536
|
+
// 移除该服务器注册的工具
|
|
537
|
+
for (const key of Object.keys(this.tools)) {
|
|
538
|
+
if (key.startsWith(`${server}_`)) {
|
|
539
|
+
delete this.tools[key];
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
// 保存 enabled 状态到配置文件
|
|
543
|
+
await this._saveMCPServerEnabled(server, false);
|
|
544
|
+
this._refreshAllAgentsMCPPrompt(this._framework);
|
|
545
|
+
return { success: true, message: `MCP 服务器 '${server}' 已关闭` };
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
return { success: true, message: `MCP 服务器 '${server}' 状态未变化` };
|
|
549
|
+
},
|
|
550
|
+
});
|
|
551
|
+
|
|
456
552
|
// 监听 agent 创建事件,附加 MCP 信息到系统提示词
|
|
457
553
|
framework.on('agent:created', (agent) => {
|
|
458
554
|
if (!this._mainAgent) {
|
|
@@ -482,7 +578,7 @@ class MCPExecutorPlugin extends Plugin {
|
|
|
482
578
|
const traverse = (agent) => {
|
|
483
579
|
if (!agent || visited.has(agent)) return;
|
|
484
580
|
visited.add(agent);
|
|
485
|
-
this._refreshAgentMCPPrompt(agent);
|
|
581
|
+
//this._refreshAgentMCPPrompt(agent);
|
|
486
582
|
|
|
487
583
|
// 递归处理子 agent
|
|
488
584
|
const subAgents = agent.getSubAgents?.() || agent._subAgents || new Map();
|
|
@@ -506,11 +602,11 @@ class MCPExecutorPlugin extends Plugin {
|
|
|
506
602
|
return;
|
|
507
603
|
}
|
|
508
604
|
|
|
509
|
-
const mcpDesc = this._buildMCPServersDescription();
|
|
510
|
-
if (!mcpDesc) return;
|
|
605
|
+
// const mcpDesc = this._buildMCPServersDescription();
|
|
606
|
+
// if (!mcpDesc) return;
|
|
511
607
|
|
|
512
608
|
// 将 MCP 描述追加到系统提示词
|
|
513
|
-
agent.setSystemPrompt(existingPrompt + '\n\n' + mcpDesc);
|
|
609
|
+
//agent.setSystemPrompt(existingPrompt + '\n\n' + mcpDesc);
|
|
514
610
|
}
|
|
515
611
|
|
|
516
612
|
/**
|
|
@@ -520,6 +616,8 @@ class MCPExecutorPlugin extends Plugin {
|
|
|
520
616
|
if (!inputSchema) return {};
|
|
521
617
|
// 处理 {jsonSchema: {...}} 格式
|
|
522
618
|
if (inputSchema.jsonSchema) return inputSchema.jsonSchema;
|
|
619
|
+
// 处理 {inputSchema: {...}} 格式 (某些 MCP 服务器返回这种格式)
|
|
620
|
+
if (inputSchema.inputSchema) return inputSchema.inputSchema;
|
|
523
621
|
// 处理直接是 schema 的格式
|
|
524
622
|
return inputSchema;
|
|
525
623
|
}
|
|
@@ -532,53 +630,134 @@ class MCPExecutorPlugin extends Plugin {
|
|
|
532
630
|
return '';
|
|
533
631
|
}
|
|
534
632
|
|
|
535
|
-
let desc = '【MCP Servers】 工具合集\n\n';
|
|
536
|
-
desc += '
|
|
633
|
+
let desc = '## 【MCP Servers】 工具合集\n\n';
|
|
634
|
+
desc += 'MCP 服务器工具已注册为 `服务器_工具名` 格式(如 github_search)。\n';
|
|
635
|
+
desc += '通过 `ext_call` 调用:\n\n';
|
|
537
636
|
|
|
538
637
|
for (const [serverName, info] of this._clients) {
|
|
539
638
|
desc += `### ${serverName}\n\n`;
|
|
540
639
|
for (const tool of info.tools) {
|
|
541
|
-
|
|
542
|
-
desc +=
|
|
640
|
+
const fullName = `${serverName}_${tool.name}`;
|
|
641
|
+
desc += `- **${fullName}**: ${tool.description || '无描述'}\n`;
|
|
543
642
|
|
|
544
643
|
// 使用 zodSchemaToMarkdown 生成参数文档
|
|
545
|
-
const
|
|
644
|
+
const rawSchema = tool.inputSchema;
|
|
645
|
+
const schema = this._extractSchema(rawSchema);
|
|
546
646
|
if (schema) {
|
|
547
647
|
try {
|
|
548
|
-
|
|
648
|
+
let schemaResult = null;
|
|
649
|
+
let zodSchemaForFallback = null; // 保存 Zod schema 供 fallback 使用
|
|
650
|
+
// 检查是否是 Zod schema (有 shape 方法或 _def 属性)
|
|
651
|
+
const isZodSchema =
|
|
652
|
+
typeof schema.shape === 'function' || (schema._def && schema._def.typeName);
|
|
653
|
+
if (isZodSchema) {
|
|
549
654
|
// Zod schema 直接转换
|
|
550
|
-
|
|
551
|
-
|
|
655
|
+
schemaResult = zodSchemaToMarkdown(schema);
|
|
656
|
+
zodSchemaForFallback = schema;
|
|
552
657
|
} else if (schema.jsonSchema) {
|
|
553
658
|
// JSON Schema 格式,尝试转换为 Zod schema
|
|
554
659
|
const zodSchema = this._jsonSchemaToZod(schema.jsonSchema || schema);
|
|
555
660
|
if (zodSchema) {
|
|
556
|
-
|
|
557
|
-
|
|
661
|
+
schemaResult = zodSchemaToMarkdown(zodSchema);
|
|
662
|
+
zodSchemaForFallback = zodSchema;
|
|
558
663
|
}
|
|
559
664
|
} else if (schema.properties) {
|
|
560
665
|
// 已经是对象格式
|
|
561
666
|
const zodSchema = this._jsonSchemaToZod(schema);
|
|
562
667
|
if (zodSchema) {
|
|
668
|
+
schemaResult = zodSchemaToMarkdown(zodSchema);
|
|
669
|
+
zodSchemaForFallback = zodSchema;
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
// 检查是否包含未解析的原始 Zod 类型名或只有类型信息没有参数
|
|
674
|
+
if (schemaResult) {
|
|
675
|
+
const hasUnparsedTypes = /\|.*\bZod\w+\b.*\|/.test(schemaResult);
|
|
676
|
+
// 检查是否只有类型信息而没有实际参数(如 "Type: Object" 或 "Type: ZodAny")
|
|
677
|
+
const hasOnlyType =
|
|
678
|
+
/^-\s+\w+:\s+.+\n?$/.test(schemaResult.trim()) && !schemaResult.includes('`');
|
|
679
|
+
if (hasUnparsedTypes || hasOnlyType) {
|
|
680
|
+
// zodSchemaToMarkdown 未正确解析,使用 fallback
|
|
681
|
+
desc += this._fallbackParamsDesc(zodSchemaForFallback || schema);
|
|
682
|
+
} else {
|
|
563
683
|
desc += `**参数:**\n\n`;
|
|
564
|
-
desc +=
|
|
684
|
+
desc += schemaResult + '\n\n';
|
|
565
685
|
}
|
|
566
686
|
}
|
|
567
687
|
} catch (e) {
|
|
568
|
-
//
|
|
569
|
-
|
|
688
|
+
// 如果转换失败,使用 fallback
|
|
689
|
+
try {
|
|
690
|
+
desc += this._fallbackParamsDesc(zodSchemaForFallback || schema);
|
|
691
|
+
} catch (e2) {
|
|
692
|
+
// fallback 也失败,忽略参数描述
|
|
693
|
+
}
|
|
570
694
|
}
|
|
571
695
|
}
|
|
572
696
|
}
|
|
573
|
-
desc += '
|
|
697
|
+
desc += '\n';
|
|
574
698
|
}
|
|
575
699
|
|
|
576
700
|
desc += '**调用格式:**\n';
|
|
577
|
-
desc += '```\
|
|
701
|
+
desc += '```\next_call({ plugin: "mcp", tool: "服务器_工具名", args: {参数} })\n';
|
|
578
702
|
desc += '```\n';
|
|
579
703
|
return desc.trim();
|
|
580
704
|
}
|
|
581
705
|
|
|
706
|
+
_bindMcpParamsDesc(rawSchema) {
|
|
707
|
+
let desc = '';
|
|
708
|
+
const schema = this._extractSchema(rawSchema);
|
|
709
|
+
if (!schema) return desc;
|
|
710
|
+
try {
|
|
711
|
+
let schemaResult = null;
|
|
712
|
+
let zodSchemaForFallback = null; // 保存 Zod schema 供 fallback 使用
|
|
713
|
+
// 检查是否是 Zod schema (有 shape 方法或 _def 属性)
|
|
714
|
+
const isZodSchema =
|
|
715
|
+
typeof schema.shape === 'function' || (schema._def && schema._def.typeName);
|
|
716
|
+
if (isZodSchema) {
|
|
717
|
+
// Zod schema 直接转换
|
|
718
|
+
schemaResult = zodSchemaToMarkdown(schema);
|
|
719
|
+
zodSchemaForFallback = schema;
|
|
720
|
+
} else if (schema.jsonSchema) {
|
|
721
|
+
// JSON Schema 格式,尝试转换为 Zod schema
|
|
722
|
+
const zodSchema = this._jsonSchemaToZod(schema.jsonSchema || schema);
|
|
723
|
+
if (zodSchema) {
|
|
724
|
+
schemaResult = zodSchemaToMarkdown(zodSchema);
|
|
725
|
+
zodSchemaForFallback = zodSchema;
|
|
726
|
+
}
|
|
727
|
+
} else if (schema.properties) {
|
|
728
|
+
// 已经是对象格式
|
|
729
|
+
const zodSchema = this._jsonSchemaToZod(schema);
|
|
730
|
+
if (zodSchema) {
|
|
731
|
+
schemaResult = zodSchemaToMarkdown(zodSchema);
|
|
732
|
+
zodSchemaForFallback = zodSchema;
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
// 检查是否包含未解析的原始 Zod 类型名或只有类型信息没有参数
|
|
737
|
+
if (schemaResult) {
|
|
738
|
+
const hasUnparsedTypes = /\|.*\bZod\w+\b.*\|/.test(schemaResult);
|
|
739
|
+
// 检查是否只有类型信息而没有实际参数(如 "Type: Object" 或 "Type: ZodAny")
|
|
740
|
+
const hasOnlyType =
|
|
741
|
+
/^-\s+\w+:\s+.+\n?$/.test(schemaResult.trim()) && !schemaResult.includes('`');
|
|
742
|
+
if (hasUnparsedTypes || hasOnlyType) {
|
|
743
|
+
// zodSchemaToMarkdown 未正确解析,使用 fallback
|
|
744
|
+
desc += this._fallbackParamsDesc(zodSchemaForFallback || schema);
|
|
745
|
+
} else {
|
|
746
|
+
desc += `**参数:**\n\n`;
|
|
747
|
+
desc += schemaResult + '\n\n';
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
} catch (e) {
|
|
751
|
+
// 如果转换失败,使用 fallback
|
|
752
|
+
try {
|
|
753
|
+
desc += this._fallbackParamsDesc(zodSchemaForFallback || schema);
|
|
754
|
+
} catch (e2) {
|
|
755
|
+
// fallback 也失败,忽略参数描述
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
return desc;
|
|
759
|
+
}
|
|
760
|
+
|
|
582
761
|
/**
|
|
583
762
|
* 将 JSON Schema 转换为 Zod schema
|
|
584
763
|
*/
|
|
@@ -648,21 +827,152 @@ class MCPExecutorPlugin extends Plugin {
|
|
|
648
827
|
* 回退的参数描述(当 zodSchemaToMarkdown 失败时)
|
|
649
828
|
*/
|
|
650
829
|
_fallbackParamsDesc(schema) {
|
|
830
|
+
// 优先尝试 JSON Schema 格式
|
|
651
831
|
const props = schema.properties || {};
|
|
652
832
|
const required = schema.required || [];
|
|
653
833
|
|
|
654
|
-
if (Object.keys(props).length
|
|
655
|
-
|
|
834
|
+
if (Object.keys(props).length > 0) {
|
|
835
|
+
let desc = '**参数:**\n\n';
|
|
836
|
+
for (const [key, prop] of Object.entries(props)) {
|
|
837
|
+
const isRequired = required.includes(key);
|
|
838
|
+
const type = prop.type || 'any';
|
|
839
|
+
const desc_text = prop.description || '';
|
|
840
|
+
desc += `- \`${key}\`${isRequired ? ' (必填)' : ''}: ${type} ${desc_text}\n`;
|
|
841
|
+
}
|
|
842
|
+
return desc + '\n';
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
// 尝试 Zod schema 格式
|
|
846
|
+
if (typeof schema.shape === 'function' || (schema._def && schema._def.shape)) {
|
|
847
|
+
const shape = typeof schema.shape === 'function' ? schema.shape() : schema._def.shape();
|
|
848
|
+
if (shape && typeof shape === 'object') {
|
|
849
|
+
let desc = '**参数:**\n\n';
|
|
850
|
+
for (const [key, field] of Object.entries(shape)) {
|
|
851
|
+
const typeInfo = this._extractZodFieldType(field);
|
|
852
|
+
const isOptional = typeInfo.isOptional ? ' (可选)' : ' (必填)';
|
|
853
|
+
desc += `- \`${key}\`${isOptional}: ${typeInfo.type}\n`;
|
|
854
|
+
}
|
|
855
|
+
return desc + '\n';
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
return '';
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
/**
|
|
863
|
+
* 从 Zod schema 字段提取类型信息
|
|
864
|
+
*/
|
|
865
|
+
_extractZodFieldType(field) {
|
|
866
|
+
if (!field) {
|
|
867
|
+
return { type: 'unknown', isOptional: false, description: '' };
|
|
656
868
|
}
|
|
657
869
|
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
870
|
+
const typeName = field._def?.typeName || field.constructor?.name || '';
|
|
871
|
+
const description = field.description || field._def?.description || '';
|
|
872
|
+
|
|
873
|
+
switch (typeName) {
|
|
874
|
+
case 'ZodOptional': {
|
|
875
|
+
const inner = field._def?.innerType;
|
|
876
|
+
if (!inner) return { type: 'optional', isOptional: true, description };
|
|
877
|
+
return this._extractZodFieldType(inner);
|
|
878
|
+
}
|
|
879
|
+
case 'ZodArray': {
|
|
880
|
+
const inner = field._def?.type;
|
|
881
|
+
if (!inner) return { type: 'array', isOptional: false, description };
|
|
882
|
+
const innerInfo = this._extractZodFieldType(inner);
|
|
883
|
+
return { type: `${innerInfo.type}[]`, isOptional: false, description };
|
|
884
|
+
}
|
|
885
|
+
case 'ZodObject': {
|
|
886
|
+
const shapeFn = field._def?.shape;
|
|
887
|
+
if (typeof shapeFn !== 'function')
|
|
888
|
+
return { type: 'object', isOptional: false, description };
|
|
889
|
+
const shape = shapeFn();
|
|
890
|
+
if (!shape) return { type: 'object', isOptional: false, description };
|
|
891
|
+
const props = Object.keys(shape).join(', ');
|
|
892
|
+
return { type: `object{${props}}`, isOptional: false, description };
|
|
893
|
+
}
|
|
894
|
+
case 'ZodString':
|
|
895
|
+
return { type: 'string', isOptional: false, description };
|
|
896
|
+
case 'ZodNumber':
|
|
897
|
+
return { type: 'number', isOptional: false, description };
|
|
898
|
+
case 'ZodBoolean':
|
|
899
|
+
return { type: 'boolean', isOptional: false, description };
|
|
900
|
+
case 'ZodEnum': {
|
|
901
|
+
const values = field._def?.values;
|
|
902
|
+
if (!values) return { type: 'enum', isOptional: false, description };
|
|
903
|
+
return {
|
|
904
|
+
type: values.map((v) => `"${v}"`).join(' | '),
|
|
905
|
+
isOptional: false,
|
|
906
|
+
description,
|
|
907
|
+
};
|
|
908
|
+
}
|
|
909
|
+
case 'ZodUnion': {
|
|
910
|
+
const options = field._def?.options;
|
|
911
|
+
if (!options) return { type: 'union', isOptional: false, description };
|
|
912
|
+
const types = options.map((opt) => this._extractZodFieldType(opt).type);
|
|
913
|
+
return { type: `union(${types.join(' | ')})`, isOptional: false, description };
|
|
914
|
+
}
|
|
915
|
+
case 'ZodLiteral':
|
|
916
|
+
return { type: JSON.stringify(field._def?.value), isOptional: false, description };
|
|
917
|
+
case 'ZodRecord': {
|
|
918
|
+
const keyType = this._extractZodFieldType(field._def?.keyType);
|
|
919
|
+
const valueType = this._extractZodFieldType(field._def?.valueType);
|
|
920
|
+
return {
|
|
921
|
+
type: `record<${keyType?.type || 'any'}, ${valueType?.type || 'any'}>`,
|
|
922
|
+
isOptional: false,
|
|
923
|
+
description,
|
|
924
|
+
};
|
|
925
|
+
}
|
|
926
|
+
case 'ZodMap': {
|
|
927
|
+
const keyType = this._extractZodFieldType(field._def?.keyType);
|
|
928
|
+
const valueType = this._extractZodFieldType(field._def?.valueType);
|
|
929
|
+
return {
|
|
930
|
+
type: `map<${keyType?.type || 'any'}, ${valueType?.type || 'any'}>`,
|
|
931
|
+
isOptional: false,
|
|
932
|
+
description,
|
|
933
|
+
};
|
|
934
|
+
}
|
|
935
|
+
case 'ZodSet': {
|
|
936
|
+
const valueType = this._extractZodFieldType(field._def?.valueType);
|
|
937
|
+
return { type: `set<${valueType?.type || 'any'}>`, isOptional: false, description };
|
|
938
|
+
}
|
|
939
|
+
case 'ZodAny':
|
|
940
|
+
return { type: 'any', isOptional: false, description };
|
|
941
|
+
case 'ZodUnknown':
|
|
942
|
+
return { type: 'unknown', isOptional: false, description };
|
|
943
|
+
case 'ZodNever':
|
|
944
|
+
return { type: 'never', isOptional: false, description };
|
|
945
|
+
case 'ZodNull':
|
|
946
|
+
return { type: 'null', isOptional: false, description };
|
|
947
|
+
case 'ZodUndefined':
|
|
948
|
+
return { type: 'undefined', isOptional: false, description };
|
|
949
|
+
case 'ZodDate':
|
|
950
|
+
return { type: 'date', isOptional: false, description };
|
|
951
|
+
case 'ZodBigInt':
|
|
952
|
+
return { type: 'bigint', isOptional: false, description };
|
|
953
|
+
case 'ZodFunction':
|
|
954
|
+
return { type: 'function', isOptional: false, description };
|
|
955
|
+
case 'ZodLazy':
|
|
956
|
+
return { type: 'lazy', isOptional: false, description };
|
|
957
|
+
case 'ZodNativeEnum':
|
|
958
|
+
return { type: 'nativeEnum', isOptional: false, description };
|
|
959
|
+
case 'ZodDefault': {
|
|
960
|
+
const inner = field._def?.innerType;
|
|
961
|
+
if (!inner) return { type: 'default', isOptional: false, description };
|
|
962
|
+
const innerInfo = this._extractZodFieldType(inner);
|
|
963
|
+
return { type: innerInfo.type, isOptional: false, description };
|
|
964
|
+
}
|
|
965
|
+
case 'ZodEffects':
|
|
966
|
+
return { type: 'effects', isOptional: false, description };
|
|
967
|
+
case 'ZodPipeline':
|
|
968
|
+
return { type: 'pipeline', isOptional: false, description };
|
|
969
|
+
default:
|
|
970
|
+
return {
|
|
971
|
+
type: typeName.replace('Zod', '').toLowerCase() || 'any',
|
|
972
|
+
isOptional: false,
|
|
973
|
+
description,
|
|
974
|
+
};
|
|
664
975
|
}
|
|
665
|
-
return desc + '\n';
|
|
666
976
|
}
|
|
667
977
|
|
|
668
978
|
_getParentAgent() {
|
|
@@ -703,11 +1013,44 @@ class MCPExecutorPlugin extends Plugin {
|
|
|
703
1013
|
* 添加 MCP 服务器
|
|
704
1014
|
*/
|
|
705
1015
|
async addServer(config) {
|
|
706
|
-
const {
|
|
1016
|
+
const {
|
|
1017
|
+
name,
|
|
1018
|
+
command,
|
|
1019
|
+
args = [],
|
|
1020
|
+
env,
|
|
1021
|
+
url,
|
|
1022
|
+
type,
|
|
1023
|
+
headers = {},
|
|
1024
|
+
authProvider,
|
|
1025
|
+
enabled,
|
|
1026
|
+
} = config;
|
|
1027
|
+
log.info(
|
|
1028
|
+
`[MCP] addServer called: ${name}, enabled=${enabled}, hasClient=${this._clients.has(name)}`
|
|
1029
|
+
);
|
|
1030
|
+
|
|
707
1031
|
if (this._clients.has(name)) {
|
|
708
1032
|
log.warn(` Server '${name}' already exists, skipping`);
|
|
709
|
-
return;
|
|
1033
|
+
return { success: false, error: `Server '${name}' already connected` };
|
|
710
1034
|
}
|
|
1035
|
+
|
|
1036
|
+
// 如果 enabled === false,跳过连接(用于 mcp_set_enabled 禁用后再开启的场景)
|
|
1037
|
+
if (enabled === false) {
|
|
1038
|
+
log.info(` Server '${name}' is disabled, skipping connection`);
|
|
1039
|
+
return { success: false, error: `Server '${name}' is disabled` };
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
// 保存配置,用于重新启用
|
|
1043
|
+
this._serverConfigs.set(name, {
|
|
1044
|
+
name,
|
|
1045
|
+
command,
|
|
1046
|
+
args,
|
|
1047
|
+
env,
|
|
1048
|
+
url,
|
|
1049
|
+
type,
|
|
1050
|
+
headers,
|
|
1051
|
+
authProvider,
|
|
1052
|
+
enabled,
|
|
1053
|
+
});
|
|
711
1054
|
log.info(` Connecting to ${name}...`);
|
|
712
1055
|
let client;
|
|
713
1056
|
try {
|
|
@@ -741,7 +1084,7 @@ class MCPExecutorPlugin extends Plugin {
|
|
|
741
1084
|
}
|
|
742
1085
|
} catch (err) {
|
|
743
1086
|
log.error(` Failed to create client '${name}':`, err.message);
|
|
744
|
-
return;
|
|
1087
|
+
return { success: false, error: `创建客户端失败: ${err.message}` };
|
|
745
1088
|
}
|
|
746
1089
|
|
|
747
1090
|
// 获取 MCP 服务器的工具列表
|
|
@@ -750,7 +1093,8 @@ class MCPExecutorPlugin extends Plugin {
|
|
|
750
1093
|
mcpTools = await this._withTimeout(client.tools(), 10000, `client.tools ${name}`);
|
|
751
1094
|
} catch (err) {
|
|
752
1095
|
log.error(` Failed to get tools from '${name}':`, err.message);
|
|
753
|
-
|
|
1096
|
+
client.close?.();
|
|
1097
|
+
return { success: false, error: `获取工具列表失败: ${err.message}` };
|
|
754
1098
|
}
|
|
755
1099
|
|
|
756
1100
|
// 提取工具信息和实际工具对象
|
|
@@ -765,6 +1109,22 @@ class MCPExecutorPlugin extends Plugin {
|
|
|
765
1109
|
description: tool.description || '',
|
|
766
1110
|
inputSchema: tool.inputSchema || {},
|
|
767
1111
|
});
|
|
1112
|
+
|
|
1113
|
+
// 注册为 server_toolname 格式,供 ext_call 使用
|
|
1114
|
+
const registeredName = `${name}_${toolName}`;
|
|
1115
|
+
this.tools[registeredName] = {
|
|
1116
|
+
name: registeredName,
|
|
1117
|
+
description: `[${name}] ${tool.description || ''}`,
|
|
1118
|
+
inputSchema: tool.inputSchema || {},
|
|
1119
|
+
execute: async (args) => {
|
|
1120
|
+
// 路由到 mcp_call
|
|
1121
|
+
return await this._framework.executeTool('mcp_call', {
|
|
1122
|
+
server: name,
|
|
1123
|
+
tool: toolName,
|
|
1124
|
+
args_json: JSON.stringify(args || {}),
|
|
1125
|
+
});
|
|
1126
|
+
},
|
|
1127
|
+
};
|
|
768
1128
|
}
|
|
769
1129
|
}
|
|
770
1130
|
|
|
@@ -773,9 +1133,18 @@ class MCPExecutorPlugin extends Plugin {
|
|
|
773
1133
|
client,
|
|
774
1134
|
tools: toolsInfo,
|
|
775
1135
|
toolObjects, // 实际工具对象,供 mcp_call 直接调用
|
|
1136
|
+
enabled: config.enabled !== false,
|
|
776
1137
|
});
|
|
777
1138
|
|
|
778
|
-
log.info(
|
|
1139
|
+
log.info(
|
|
1140
|
+
` Added server '${name}' with ${toolsInfo.length} tools (ext_call names: ${Object.keys(
|
|
1141
|
+
this.tools
|
|
1142
|
+
)
|
|
1143
|
+
.filter((k) => k.startsWith(name + '_'))
|
|
1144
|
+
.join(', ')})`
|
|
1145
|
+
);
|
|
1146
|
+
|
|
1147
|
+
return { success: true, name, toolsCount: toolsInfo.length };
|
|
779
1148
|
}
|
|
780
1149
|
|
|
781
1150
|
/**
|
|
@@ -796,6 +1165,14 @@ class MCPExecutorPlugin extends Plugin {
|
|
|
796
1165
|
} catch (e) {
|
|
797
1166
|
// ignore
|
|
798
1167
|
}
|
|
1168
|
+
|
|
1169
|
+
// 清理已注册的工具
|
|
1170
|
+
for (const toolName of Object.keys(this.tools)) {
|
|
1171
|
+
if (toolName.startsWith(name + '_')) {
|
|
1172
|
+
delete this.tools[toolName];
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
|
|
799
1176
|
this._clients.delete(name);
|
|
800
1177
|
}
|
|
801
1178
|
}
|
|
@@ -832,10 +1209,18 @@ class MCPExecutorPlugin extends Plugin {
|
|
|
832
1209
|
} catch (e) {}
|
|
833
1210
|
}
|
|
834
1211
|
this._clients.clear();
|
|
1212
|
+
// 清理服务器配置
|
|
1213
|
+
this._serverConfigs.clear();
|
|
835
1214
|
|
|
836
1215
|
// 2. 并行添加新服务器
|
|
837
1216
|
log.info(' Adding new servers...');
|
|
838
1217
|
const addPromises = Object.entries(newServers).map(async ([name, serverConfig]) => {
|
|
1218
|
+
if (serverConfig.enabled === false) {
|
|
1219
|
+
log.info(` Skipping disabled server: ${name}`);
|
|
1220
|
+
// 仍保存配置,以便后续动态启用
|
|
1221
|
+
this._serverConfigs.set(name, { name, ...serverConfig });
|
|
1222
|
+
return;
|
|
1223
|
+
}
|
|
839
1224
|
const normalizedConfig = {
|
|
840
1225
|
name,
|
|
841
1226
|
type: serverConfig.type,
|
|
@@ -845,6 +1230,7 @@ class MCPExecutorPlugin extends Plugin {
|
|
|
845
1230
|
command: serverConfig.command,
|
|
846
1231
|
args: serverConfig.args,
|
|
847
1232
|
env: serverConfig.env,
|
|
1233
|
+
enabled: true,
|
|
848
1234
|
};
|
|
849
1235
|
await this.addServer(normalizedConfig);
|
|
850
1236
|
});
|
|
@@ -858,6 +1244,38 @@ class MCPExecutorPlugin extends Plugin {
|
|
|
858
1244
|
}
|
|
859
1245
|
}
|
|
860
1246
|
|
|
1247
|
+
/**
|
|
1248
|
+
* 保存 MCP 服务器的 enabled 状态到配置文件
|
|
1249
|
+
*/
|
|
1250
|
+
async _saveMCPServerEnabled(serverName, enabled) {
|
|
1251
|
+
const fs = require('fs');
|
|
1252
|
+
const path = require('path');
|
|
1253
|
+
const configPath = path.resolve('.agent/mcp_config.json');
|
|
1254
|
+
|
|
1255
|
+
try {
|
|
1256
|
+
if (!fs.existsSync(configPath)) {
|
|
1257
|
+
log.warn(` MCP config file not found: ${configPath}`);
|
|
1258
|
+
return false;
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1261
|
+
const configContent = fs.readFileSync(configPath, 'utf8');
|
|
1262
|
+
const config = JSON.parse(configContent);
|
|
1263
|
+
|
|
1264
|
+
if (!config.mcpServers || !config.mcpServers[serverName]) {
|
|
1265
|
+
log.warn(` Server '${serverName}' not found in MCP config`);
|
|
1266
|
+
return false;
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
config.mcpServers[serverName].enabled = enabled;
|
|
1270
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf8');
|
|
1271
|
+
log.info(` Saved enabled=${enabled} for server '${serverName}' to config`);
|
|
1272
|
+
return true;
|
|
1273
|
+
} catch (err) {
|
|
1274
|
+
log.error(` Failed to save MCP config:`, err.message);
|
|
1275
|
+
return false;
|
|
1276
|
+
}
|
|
1277
|
+
}
|
|
1278
|
+
|
|
861
1279
|
async uninstall(framework) {
|
|
862
1280
|
// 断开所有 MCP 连接
|
|
863
1281
|
for (const [name, clientInfo] of this._clients) {
|
package/src/utils/id.js
CHANGED