@timmy_hu/plugin-middleware 1.0.2 → 1.0.3

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.
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "插件中间件",
3
3
  "code": "plugin-middleware",
4
- "version": "1.0.2",
5
- "description": "自动发现 XpertAI 平台上所有已安装的中间件类型插件,展示加载状态,支持从 npm 安装新插件、搜索、统计。通过 /api/auth/login 登录获取 token。",
4
+ "version": "1.0.3",
5
+ "description": "自动发现 XpertAI 平台上所有已安装的中间件类型插件,展示加载状态,提供插件绑定指导和诊断工具。注意:插件需要在 XpertAI 平台 UI 中手动绑定到智能体。",
6
6
  "createdBy": "fpi",
7
7
  "platform": "http://10.161.48.53:3300",
8
8
  "category": "middleware",
package/index.js CHANGED
@@ -15,8 +15,8 @@ class PluginMiddleware {
15
15
  zh_Hans: "插件中间件管理器"
16
16
  },
17
17
  description: {
18
- en_US: "Discovers all middleware-type plugins installed on the XpertAI platform, shows their load status, and can install new middleware plugins from npm. Authenticates via /api/auth/login.",
19
- zh_Hans: "自动发现 XpertAI 平台上所有已安装的中间件类型插件,展示加载状态,并支持从 npm 安装新的中间件插件。通过 /api/auth/login 登录获取 token。"
18
+ en_US: "Discovers all middleware-type plugins installed on the XpertAI platform, shows their load status, and provides guidance on binding plugins to agents. Note: Plugins must be manually bound to agents in the XpertAI platform UI.",
19
+ zh_Hans: "自动发现 XpertAI 平台上所有已安装的中间件类型插件,展示加载状态,并提供插件绑定指导。注意:插件需要在 XpertAI 平台 UI 中手动绑定到智能体。"
20
20
  },
21
21
  configSchema: {
22
22
  type: "object",
@@ -61,17 +61,15 @@ class PluginMiddleware {
61
61
  const organizationId = options.organizationId || "";
62
62
  const cacheTtlSeconds = options.cacheTtlSeconds || 300;
63
63
 
64
- // In-memory state
65
64
  const state = {
66
- allPlugins: [], // 所有插件列表
67
- middlewarePlugins: [], // 中间件类型插件列表
65
+ allPlugins: [],
66
+ middlewarePlugins: [],
68
67
  lastRefresh: null,
69
68
  cacheTtl: cacheTtlSeconds * 1000,
70
69
  token: null,
71
70
  tokenExpiry: null
72
71
  };
73
72
 
74
- // ======== 登录:调用 /api/auth/login 获取 token ========
75
73
  async function loginAndGetToken() {
76
74
  const now = Date.now();
77
75
  if (state.token && state.tokenExpiry && now < state.tokenExpiry) {
@@ -107,7 +105,6 @@ class PluginMiddleware {
107
105
  return h;
108
106
  }
109
107
 
110
- // ======== 获取所有已安装插件(GET /api/plugin) ========
111
108
  async function fetchAllPlugins() {
112
109
  const now = Date.now();
113
110
  if (state.lastRefresh && (now - state.lastRefresh) < state.cacheTtl && state.allPlugins.length > 0) {
@@ -126,8 +123,7 @@ class PluginMiddleware {
126
123
  const newToken = await loginAndGetToken();
127
124
  const retry = await fetch(`${platformUrl}/api/plugin`, { method: "GET", headers: authHeaders(newToken), timeout: 15000 });
128
125
  if (!retry.ok) throw new Error(`Platform API returned ${retry.status}`);
129
- const retryData = await retry.json();
130
- return processPluginList(retryData);
126
+ return processPluginList(await retry.json());
131
127
  }
132
128
  throw new Error(`Platform API returned ${resp.status}: ${resp.statusText}`);
133
129
  }
@@ -146,7 +142,6 @@ class PluginMiddleware {
146
142
  return state.allPlugins;
147
143
  }
148
144
 
149
- // ======== 格式化中间件插件信息 ========
150
145
  function formatMiddlewarePlugin(p) {
151
146
  const meta = p.meta || {};
152
147
  return {
@@ -168,11 +163,12 @@ class PluginMiddleware {
168
163
  canUpdate: p.canUpdate || false,
169
164
  hasUpdate: p.hasUpdate || false,
170
165
  effectiveInCurrentScope: p.effectiveInCurrentScope !== false,
166
+ scopeRelation: p.scopeRelation || "unknown",
171
167
  componentSummary: p.componentSummary || { total: 0, skills: 0, mcpServers: 0, apps: 0, hooks: 0 }
172
168
  };
173
169
  }
174
170
 
175
- // ======== Tool 1: list_middleware_plugins ========
171
+ // Tool 1: list_middleware_plugins
176
172
  const listMiddlewarePlugins = tool(
177
173
  async (input) => {
178
174
  try {
@@ -194,7 +190,8 @@ class PluginMiddleware {
194
190
  totalAllPlugins: state.allPlugins.length,
195
191
  totalMiddleware: state.middlewarePlugins.length,
196
192
  filter,
197
- plugins: filtered.map(formatMiddlewarePlugin)
193
+ plugins: filtered.map(formatMiddlewarePlugin),
194
+ note: "⚠️ 插件已安装并加载,但需要在 XpertAI 平台 UI 中手动绑定到智能体才能使用其工具。请使用 get_binding_guidance 工具获取绑定指导。"
198
195
  };
199
196
  } catch (err) {
200
197
  return { success: false, error: err.message, plugins: [] };
@@ -202,7 +199,7 @@ class PluginMiddleware {
202
199
  },
203
200
  {
204
201
  name: "list_middleware_plugins",
205
- description: "列出平台上所有已安装的中间件类型插件,可按状态过滤。返回插件名称、版本、描述、加载状态等详细信息。",
202
+ description: "列出平台上所有已安装的中间件类型插件。注意:插件需要在 XpertAI 平台 UI 中手动绑定到智能体。",
206
203
  schema: z.object({
207
204
  filter: z.enum(["all", "loaded", "error", "updatable"]).optional().default("all")
208
205
  .describe("过滤条件:all=全部, loaded=已加载, error=加载出错, updatable=有可用更新")
@@ -210,7 +207,7 @@ class PluginMiddleware {
210
207
  }
211
208
  );
212
209
 
213
- // ======== Tool 2: get_middleware_plugin_detail ========
210
+ // Tool 2: get_middleware_plugin_detail
214
211
  const getMiddlewarePluginDetail = tool(
215
212
  async (input) => {
216
213
  try {
@@ -236,7 +233,6 @@ class PluginMiddleware {
236
233
 
237
234
  const detail = formatMiddlewarePlugin(found);
238
235
 
239
- // 尝试获取组件信息
240
236
  try {
241
237
  const token = await loginAndGetToken();
242
238
  const fetch = (await import("node-fetch")).default;
@@ -251,6 +247,13 @@ class PluginMiddleware {
251
247
  detail.components = [];
252
248
  }
253
249
 
250
+ // 添加绑定状态提示
251
+ if (detail.componentSummary.total === 0) {
252
+ detail.bindingWarning = "⚠️ 该插件没有暴露任何组件(工具/技能/MCP服务器)。请检查插件实现是否正确注册了中间件策略。";
253
+ } else if (!detail.effectiveInCurrentScope) {
254
+ detail.bindingWarning = "⚠️ 该插件在当前作用域中未生效。请在 XpertAI 平台 UI 中将此插件绑定到当前智能体。";
255
+ }
256
+
254
257
  return { success: true, plugin: detail };
255
258
  } catch (err) {
256
259
  return { success: false, error: err.message };
@@ -258,7 +261,7 @@ class PluginMiddleware {
258
261
  },
259
262
  {
260
263
  name: "get_middleware_plugin_detail",
261
- description: "查询指定中间件插件的详细信息,包括加载状态、配置状态、组件列表、版本信息等。",
264
+ description: "查询指定中间件插件的详细信息,包括加载状态、配置状态、组件列表、版本信息和绑定状态。",
262
265
  schema: z.object({
263
266
  pluginNameOrPackage: z.string().min(1)
264
267
  .describe("插件名称、packageName 或 displayName,例如 'echarts-generator' 或 '@timmy_hu/bulk-email-sender'")
@@ -266,7 +269,7 @@ class PluginMiddleware {
266
269
  }
267
270
  );
268
271
 
269
- // ======== Tool 3: install_middleware_plugin ========
272
+ // Tool 3: install_middleware_plugin
270
273
  const installMiddlewarePlugin = tool(
271
274
  async (input) => {
272
275
  const packageName = input.packageName;
@@ -288,8 +291,6 @@ class PluginMiddleware {
288
291
  }
289
292
 
290
293
  const result = await resp.json();
291
-
292
- // 刷新缓存
293
294
  state.lastRefresh = null;
294
295
 
295
296
  return {
@@ -300,7 +301,14 @@ class PluginMiddleware {
300
301
  packageName: result.packageName || packageName,
301
302
  version: result.currentVersion || version,
302
303
  organizationId: result.organizationId || organizationId
303
- }
304
+ },
305
+ nextSteps: [
306
+ "1. 插件已安装并加载到平台",
307
+ "2. 请在 XpertAI 平台 UI 中进入智能体编排页面",
308
+ "3. 点击\"添加中间件\"按钮",
309
+ "4. 在列表中找到刚安装的插件并添加",
310
+ "5. 保存智能体配置后,插件的工具即可使用"
311
+ ]
304
312
  };
305
313
  } catch (err) {
306
314
  return {
@@ -313,7 +321,7 @@ class PluginMiddleware {
313
321
  },
314
322
  {
315
323
  name: "install_middleware_plugin",
316
- description: "从 npm 安装一个新的中间件插件到 XpertAI 平台。安装后插件将自动加载并可供智能体使用。",
324
+ description: "从 npm 安装一个新的中间件插件到 XpertAI 平台。安装后需要在平台 UI 中手动绑定到智能体。",
317
325
  schema: z.object({
318
326
  packageName: z.string().min(1).describe("npm 包名,例如 '@timmy_hu/bulk-email-sender'"),
319
327
  version: z.string().optional().default("latest").describe("版本号,默认为 latest")
@@ -321,7 +329,7 @@ class PluginMiddleware {
321
329
  }
322
330
  );
323
331
 
324
- // ======== Tool 4: refresh_plugin_list ========
332
+ // Tool 4: refresh_plugin_list
325
333
  const refreshPluginList = tool(
326
334
  async (input) => {
327
335
  state.lastRefresh = null;
@@ -347,7 +355,7 @@ class PluginMiddleware {
347
355
  }
348
356
  );
349
357
 
350
- // ======== Tool 5: check_login_status ========
358
+ // Tool 5: check_login_status
351
359
  const checkLoginStatus = tool(
352
360
  async (input) => {
353
361
  try {
@@ -380,7 +388,7 @@ class PluginMiddleware {
380
388
  }
381
389
  );
382
390
 
383
- // ======== Tool 6: search_middleware_plugins ========
391
+ // Tool 6: search_middleware_plugins
384
392
  const searchMiddlewarePlugins = tool(
385
393
  async (input) => {
386
394
  try {
@@ -414,33 +422,26 @@ class PluginMiddleware {
414
422
  }
415
423
  );
416
424
 
417
- // ======== Tool 7: get_plugin_statistics ========
425
+ // Tool 7: get_plugin_statistics
418
426
  const getPluginStatistics = tool(
419
427
  async (input) => {
420
428
  try {
421
429
  await fetchAllPlugins();
422
430
 
423
- // 按 category 统计
424
431
  const categoryStats = {};
425
432
  for (const p of state.allPlugins) {
426
433
  const cat = (p.meta || {}).category || "unknown";
427
434
  categoryStats[cat] = (categoryStats[cat] || 0) + 1;
428
435
  }
429
436
 
430
- // 按 loadStatus 统计中间件
431
437
  const loadStatusStats = {};
432
438
  for (const p of state.middlewarePlugins) {
433
439
  const ls = p.loadStatus || "unknown";
434
440
  loadStatusStats[ls] = (loadStatusStats[ls] || 0) + 1;
435
441
  }
436
442
 
437
- // 有更新的插件
438
443
  const updatable = state.middlewarePlugins.filter(p => p.hasUpdate === true);
439
-
440
- // 有配置错误的插件
441
444
  const configErrors = state.middlewarePlugins.filter(p => p.configurationError);
442
-
443
- // 有加载错误的插件
444
445
  const loadErrors = state.middlewarePlugins.filter(p => p.loadError);
445
446
 
446
447
  return {
@@ -470,6 +471,248 @@ class PluginMiddleware {
470
471
  }
471
472
  );
472
473
 
474
+ // Tool 8: get_binding_guidance (NEW)
475
+ const getBindingGuidance = tool(
476
+ async (input) => {
477
+ const pluginName = input.pluginName;
478
+
479
+ try {
480
+ await fetchAllPlugins();
481
+
482
+ const plugin = state.middlewarePlugins.find(p => {
483
+ const meta = p.meta || {};
484
+ return p.name === pluginName
485
+ || meta.name === pluginName
486
+ || p.packageName === pluginName
487
+ || meta.displayName === pluginName;
488
+ });
489
+
490
+ if (!plugin) {
491
+ return {
492
+ success: false,
493
+ error: `未找到名为 "${pluginName}" 的中间件插件`,
494
+ guidance: "请先使用 list_middleware_plugins 查看所有可用的中间件插件"
495
+ };
496
+ }
497
+
498
+ const meta = plugin.meta || {};
499
+ const detail = formatMiddlewarePlugin(plugin);
500
+
501
+ const guidance = {
502
+ pluginName: detail.displayName,
503
+ packageName: detail.packageName,
504
+ version: detail.version,
505
+ loadStatus: detail.loadStatus,
506
+ componentSummary: detail.componentSummary,
507
+ steps: [
508
+ {
509
+ step: 1,
510
+ action: "打开 XpertAI 平台",
511
+ url: platformUrl,
512
+ description: "登录到 XpertAI 平台"
513
+ },
514
+ {
515
+ step: 2,
516
+ action: "进入智能体编排页面",
517
+ description: "找到并编辑需要使用该插件的智能体"
518
+ },
519
+ {
520
+ step: 3,
521
+ action: "添加中间件",
522
+ description: `点击"添加中间件"按钮,在列表中找到 "${detail.displayName}" (${detail.packageName})`
523
+ },
524
+ {
525
+ step: 4,
526
+ action: "配置插件(如需要)",
527
+ description: detail.canConfigure ? "根据插件要求填写配置参数" : "该插件无需额外配置"
528
+ },
529
+ {
530
+ step: 5,
531
+ action: "保存智能体",
532
+ description: "保存智能体配置,插件的工具将立即可用"
533
+ }
534
+ ],
535
+ troubleshooting: []
536
+ };
537
+
538
+ // 诊断问题
539
+ if (detail.loadStatus !== "loaded") {
540
+ guidance.troubleshooting.push({
541
+ issue: "插件未加载",
542
+ status: detail.loadStatus,
543
+ error: detail.loadError,
544
+ solution: "插件加载失败,请检查插件是否正确安装,或联系插件作者"
545
+ });
546
+ }
547
+
548
+ if (detail.componentSummary.total === 0) {
549
+ guidance.troubleshooting.push({
550
+ issue: "插件没有暴露任何组件",
551
+ componentSummary: detail.componentSummary,
552
+ solution: "插件实现可能有问题,没有正确注册中间件策略或工具。请联系插件作者检查插件代码。"
553
+ });
554
+ }
555
+
556
+ if (!detail.effectiveInCurrentScope) {
557
+ guidance.troubleshooting.push({
558
+ issue: "插件在当前作用域未生效",
559
+ scopeRelation: detail.scopeRelation,
560
+ solution: "请在智能体编排页面中手动添加此中间件到智能体"
561
+ });
562
+ }
563
+
564
+ if (detail.configurationError) {
565
+ guidance.troubleshooting.push({
566
+ issue: "插件配置错误",
567
+ error: detail.configurationError,
568
+ solution: "请检查并修正插件配置"
569
+ });
570
+ }
571
+
572
+ return {
573
+ success: true,
574
+ guidance
575
+ };
576
+ } catch (err) {
577
+ return {
578
+ success: false,
579
+ error: err.message
580
+ };
581
+ }
582
+ },
583
+ {
584
+ name: "get_binding_guidance",
585
+ description: "获取将指定中间件插件绑定到智能体的详细步骤指导,包括诊断插件状态和提供故障排除建议。",
586
+ schema: z.object({
587
+ pluginName: z.string().min(1)
588
+ .describe("插件名称、packageName 或 displayName,例如 '@timmy_hu/bulk-email-sender'")
589
+ })
590
+ }
591
+ );
592
+
593
+ // Tool 9: diagnose_plugin_availability (NEW)
594
+ const diagnosePluginAvailability = tool(
595
+ async (input) => {
596
+ const pluginName = input.pluginName;
597
+
598
+ try {
599
+ await fetchAllPlugins();
600
+
601
+ const plugin = state.middlewarePlugins.find(p => {
602
+ const meta = p.meta || {};
603
+ return p.name === pluginName
604
+ || meta.name === pluginName
605
+ || p.packageName === pluginName
606
+ || meta.displayName === pluginName;
607
+ });
608
+
609
+ if (!plugin) {
610
+ return {
611
+ success: false,
612
+ error: `未找到名为 "${pluginName}" 的中间件插件`,
613
+ diagnosis: "插件未安装",
614
+ solution: "使用 install_middleware_plugin 工具安装该插件"
615
+ };
616
+ }
617
+
618
+ const meta = plugin.meta || {};
619
+ const detail = formatMiddlewarePlugin(plugin);
620
+
621
+ const checks = [];
622
+ let allPassed = true;
623
+
624
+ // Check 1: 插件是否加载
625
+ const loadCheck = {
626
+ name: "插件加载状态",
627
+ passed: detail.loadStatus === "loaded",
628
+ status: detail.loadStatus,
629
+ error: detail.loadError
630
+ };
631
+ checks.push(loadCheck);
632
+ if (!loadCheck.passed) allPassed = false;
633
+
634
+ // Check 2: 是否有组件
635
+ const componentCheck = {
636
+ name: "组件暴露",
637
+ passed: detail.componentSummary.total > 0,
638
+ total: detail.componentSummary.total,
639
+ breakdown: detail.componentSummary
640
+ };
641
+ checks.push(componentCheck);
642
+ if (!componentCheck.passed) allPassed = false;
643
+
644
+ // Check 3: 配置状态
645
+ const configCheck = {
646
+ name: "配置状态",
647
+ passed: !detail.configurationError,
648
+ status: detail.configurationStatus,
649
+ error: detail.configurationError
650
+ };
651
+ checks.push(configCheck);
652
+ if (!configCheck.passed) allPassed = false;
653
+
654
+ // Check 4: 作用域生效
655
+ const scopeCheck = {
656
+ name: "作用域生效",
657
+ passed: detail.effectiveInCurrentScope,
658
+ scopeRelation: detail.scopeRelation
659
+ };
660
+ checks.push(scopeCheck);
661
+ if (!scopeCheck.passed) allPassed = false;
662
+
663
+ const diagnosis = {
664
+ pluginName: detail.displayName,
665
+ packageName: detail.packageName,
666
+ version: detail.version,
667
+ allChecksPassed: allPassed,
668
+ checks,
669
+ summary: allPassed
670
+ ? "✅ 插件状态正常,应该可以在智能体中使用。如果仍无法使用,请确保已在智能体编排页面中添加了该中间件。"
671
+ : "❌ 插件存在问题,需要修复后才能使用",
672
+ recommendations: []
673
+ };
674
+
675
+ if (!loadCheck.passed) {
676
+ diagnosis.recommendations.push("插件加载失败,请检查插件代码或联系插件作者");
677
+ }
678
+
679
+ if (!componentCheck.passed) {
680
+ diagnosis.recommendations.push("插件没有暴露任何工具或组件。这通常意味着插件代码没有正确实现中间件策略。请联系插件作者检查代码。");
681
+ }
682
+
683
+ if (!configCheck.passed) {
684
+ diagnosis.recommendations.push(`插件配置错误: ${detail.configurationError}`);
685
+ }
686
+
687
+ if (!scopeCheck.passed) {
688
+ diagnosis.recommendations.push("插件在当前作用域未生效。请在 XpertAI 平台 UI 的智能体编排页面中手动添加此中间件。");
689
+ }
690
+
691
+ if (allPassed) {
692
+ diagnosis.recommendations.push("插件状态正常。如果工具仍不可用,请确保:1) 已在智能体编排页面添加了该中间件;2) 已保存智能体配置;3) 刷新了智能体页面。");
693
+ }
694
+
695
+ return {
696
+ success: true,
697
+ diagnosis
698
+ };
699
+ } catch (err) {
700
+ return {
701
+ success: false,
702
+ error: err.message
703
+ };
704
+ }
705
+ },
706
+ {
707
+ name: "diagnose_plugin_availability",
708
+ description: "诊断指定中间件插件为什么其工具不可用。检查加载状态、组件暴露、配置状态和作用域生效情况,并提供修复建议。",
709
+ schema: z.object({
710
+ pluginName: z.string().min(1)
711
+ .describe("插件名称、packageName 或 displayName,例如 '@timmy_hu/bulk-email-sender'")
712
+ })
713
+ }
714
+ );
715
+
473
716
  return {
474
717
  name: MIDDLEWARE_PROVIDER,
475
718
  tools: [
@@ -479,7 +722,9 @@ class PluginMiddleware {
479
722
  refreshPluginList,
480
723
  checkLoginStatus,
481
724
  searchMiddlewarePlugins,
482
- getPluginStatistics
725
+ getPluginStatistics,
726
+ getBindingGuidance,
727
+ diagnosePluginAvailability
483
728
  ]
484
729
  };
485
730
  }
@@ -493,12 +738,12 @@ class PluginModule {}
493
738
  const plugin = {
494
739
  meta: {
495
740
  name: "@timmy_hu/plugin-middleware",
496
- version: "1.0.2",
741
+ version: "1.0.3",
497
742
  level: "organization",
498
743
  category: "middleware",
499
744
  displayName: "插件中间件",
500
- description: "自动发现 XpertAI 平台上所有已安装的中间件类型插件,展示加载状态,支持从 npm 安装新插件、搜索、统计。通过 /api/auth/login 登录获取 token。",
501
- keywords: ["middleware", "plugin", "discovery", "install", "agent", "orchestration"],
745
+ description: "自动发现 XpertAI 平台上所有已安装的中间件类型插件,展示加载状态,提供插件绑定指导和诊断工具。注意:插件需要在 XpertAI 平台 UI 中手动绑定到智能体。",
746
+ keywords: ["middleware", "plugin", "discovery", "install", "binding", "diagnosis", "agent"],
502
747
  author: "fpi"
503
748
  },
504
749
  register(ctx) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@timmy_hu/plugin-middleware",
3
- "version": "1.0.2",
4
- "description": "自动发现所有中间件类型插件,支持动态按需加载、卸载和状态查询",
3
+ "version": "1.0.3",
4
+ "description": "自动发现 XpertAI 平台上所有已安装的中间件类型插件,展示加载状态,提供插件绑定指导和诊断工具。注意:插件需要在 XpertAI 平台 UI 中手动绑定到智能体。",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
7
  "build": "echo 'No build step required for CJS plugin'",
@@ -15,8 +15,8 @@ export class PluginMiddleware {
15
15
  zh_Hans: "插件中间件管理器"
16
16
  },
17
17
  description: {
18
- en_US: "Discovers all middleware-type plugins installed on the XpertAI platform, shows their load status, and can install new middleware plugins from npm. Authenticates via /api/auth/login.",
19
- zh_Hans: "自动发现 XpertAI 平台上所有已安装的中间件类型插件,展示加载状态,并支持从 npm 安装新的中间件插件。通过 /api/auth/login 登录获取 token。"
18
+ en_US: "Discovers all middleware-type plugins installed on the XpertAI platform, shows their load status, and provides guidance on binding plugins to agents. Note: Plugins must be manually bound to agents in the XpertAI platform UI.",
19
+ zh_Hans: "自动发现 XpertAI 平台上所有已安装的中间件类型插件,展示加载状态,并提供插件绑定指导。注意:插件需要在 XpertAI 平台 UI 中手动绑定到智能体。"
20
20
  },
21
21
  configSchema: {
22
22
  type: "object",
@@ -156,6 +156,7 @@ export class PluginMiddleware {
156
156
  canUpdate: p.canUpdate || false,
157
157
  hasUpdate: p.hasUpdate || false,
158
158
  effectiveInCurrentScope: p.effectiveInCurrentScope !== false,
159
+ scopeRelation: p.scopeRelation || "unknown",
159
160
  componentSummary: p.componentSummary || { total: 0, skills: 0, mcpServers: 0, apps: 0, hooks: 0 }
160
161
  };
161
162
  }
@@ -175,7 +176,8 @@ export class PluginMiddleware {
175
176
  totalAllPlugins: state.allPlugins.length,
176
177
  totalMiddleware: state.middlewarePlugins.length,
177
178
  filter,
178
- plugins: filtered.map(formatMiddlewarePlugin)
179
+ plugins: filtered.map(formatMiddlewarePlugin),
180
+ note: "⚠️ 插件已安装并加载,但需要在 XpertAI 平台 UI 中手动绑定到智能体才能使用其工具。请使用 get_binding_guidance 工具获取绑定指导。"
179
181
  };
180
182
  } catch (err: any) {
181
183
  return { success: false, error: err.message, plugins: [] };
@@ -183,7 +185,7 @@ export class PluginMiddleware {
183
185
  },
184
186
  {
185
187
  name: "list_middleware_plugins",
186
- description: "列出平台上所有已安装的中间件类型插件,可按状态过滤。返回插件名称、版本、描述、加载状态等详细信息。",
188
+ description: "列出平台上所有已安装的中间件类型插件。注意:插件需要在 XpertAI 平台 UI 中手动绑定到智能体。",
187
189
  schema: z.object({
188
190
  filter: z.enum(["all", "loaded", "error", "updatable"]).optional().default("all")
189
191
  .describe("过滤条件:all=全部, loaded=已加载, error=加载出错, updatable=有可用更新")
@@ -223,6 +225,11 @@ export class PluginMiddleware {
223
225
  } catch (e) {
224
226
  detail.components = [];
225
227
  }
228
+ if (detail.componentSummary.total === 0) {
229
+ detail.bindingWarning = "⚠️ 该插件没有暴露任何组件(工具/技能/MCP服务器)。请检查插件实现是否正确注册了中间件策略。";
230
+ } else if (!detail.effectiveInCurrentScope) {
231
+ detail.bindingWarning = "⚠️ 该插件在当前作用域中未生效。请在 XpertAI 平台 UI 中将此插件绑定到当前智能体。";
232
+ }
226
233
  return { success: true, plugin: detail };
227
234
  } catch (err: any) {
228
235
  return { success: false, error: err.message };
@@ -230,7 +237,7 @@ export class PluginMiddleware {
230
237
  },
231
238
  {
232
239
  name: "get_middleware_plugin_detail",
233
- description: "查询指定中间件插件的详细信息,包括加载状态、配置状态、组件列表、版本信息等。",
240
+ description: "查询指定中间件插件的详细信息,包括加载状态、配置状态、组件列表、版本信息和绑定状态。",
234
241
  schema: z.object({
235
242
  pluginNameOrPackage: z.string().min(1)
236
243
  .describe("插件名称、packageName 或 displayName,例如 'echarts-generator' 或 '@timmy_hu/bulk-email-sender'")
@@ -265,7 +272,14 @@ export class PluginMiddleware {
265
272
  packageName: result.packageName || packageName,
266
273
  version: result.currentVersion || version,
267
274
  organizationId: result.organizationId || organizationId
268
- }
275
+ },
276
+ nextSteps: [
277
+ "1. 插件已安装并加载到平台",
278
+ "2. 请在 XpertAI 平台 UI 中进入智能体编排页面",
279
+ "3. 点击"添加中间件"按钮",
280
+ "4. 在列表中找到刚安装的插件并添加",
281
+ "5. 保存智能体配置后,插件的工具即可使用"
282
+ ]
269
283
  };
270
284
  } catch (err: any) {
271
285
  return { success: false, error: err.message, packageName, version };
@@ -273,7 +287,7 @@ export class PluginMiddleware {
273
287
  },
274
288
  {
275
289
  name: "install_middleware_plugin",
276
- description: "从 npm 安装一个新的中间件插件到 XpertAI 平台。安装后插件将自动加载并可供智能体使用。",
290
+ description: "从 npm 安装一个新的中间件插件到 XpertAI 平台。安装后需要在平台 UI 中手动绑定到智能体。",
277
291
  schema: z.object({
278
292
  packageName: z.string().min(1).describe("npm 包名,例如 '@timmy_hu/bulk-email-sender'"),
279
293
  version: z.string().optional().default("latest").describe("版本号,默认为 latest")
@@ -408,6 +422,176 @@ export class PluginMiddleware {
408
422
  }
409
423
  );
410
424
 
425
+ const getBindingGuidance = tool(
426
+ async (input) => {
427
+ const pluginName = input.pluginName;
428
+ try {
429
+ await fetchAllPlugins();
430
+ const plugin = state.middlewarePlugins.find((p: any) => {
431
+ const meta = p.meta || {};
432
+ return p.name === pluginName || meta.name === pluginName || p.packageName === pluginName || meta.displayName === pluginName;
433
+ });
434
+ if (!plugin) {
435
+ return {
436
+ success: false,
437
+ error: `未找到名为 "${pluginName}" 的中间件插件`,
438
+ guidance: "请先使用 list_middleware_plugins 查看所有可用的中间件插件"
439
+ };
440
+ }
441
+ const meta = plugin.meta || {};
442
+ const detail = formatMiddlewarePlugin(plugin);
443
+ const guidance = {
444
+ pluginName: detail.displayName,
445
+ packageName: detail.packageName,
446
+ version: detail.version,
447
+ loadStatus: detail.loadStatus,
448
+ componentSummary: detail.componentSummary,
449
+ steps: [
450
+ { step: 1, action: "打开 XpertAI 平台", url: platformUrl, description: "登录到 XpertAI 平台" },
451
+ { step: 2, action: "进入智能体编排页面", description: "找到并编辑需要使用该插件的智能体" },
452
+ { step: 3, action: "添加中间件", description: `点击"添加中间件"按钮,在列表中找到 "${detail.displayName}" (${detail.packageName})` },
453
+ { step: 4, action: "配置插件(如需要)", description: detail.canConfigure ? "根据插件要求填写配置参数" : "该插件无需额外配置" },
454
+ { step: 5, action: "保存智能体", description: "保存智能体配置,插件的工具将立即可用" }
455
+ ],
456
+ troubleshooting: [] as any[]
457
+ };
458
+ if (detail.loadStatus !== "loaded") {
459
+ guidance.troubleshooting.push({
460
+ issue: "插件未加载",
461
+ status: detail.loadStatus,
462
+ error: detail.loadError,
463
+ solution: "插件加载失败,请检查插件是否正确安装,或联系插件作者"
464
+ });
465
+ }
466
+ if (detail.componentSummary.total === 0) {
467
+ guidance.troubleshooting.push({
468
+ issue: "插件没有暴露任何组件",
469
+ componentSummary: detail.componentSummary,
470
+ solution: "插件实现可能有问题,没有正确注册中间件策略或工具。请联系插件作者检查插件代码。"
471
+ });
472
+ }
473
+ if (!detail.effectiveInCurrentScope) {
474
+ guidance.troubleshooting.push({
475
+ issue: "插件在当前作用域未生效",
476
+ scopeRelation: detail.scopeRelation,
477
+ solution: "请在智能体编排页面中手动添加此中间件到智能体"
478
+ });
479
+ }
480
+ if (detail.configurationError) {
481
+ guidance.troubleshooting.push({
482
+ issue: "插件配置错误",
483
+ error: detail.configurationError,
484
+ solution: "请检查并修正插件配置"
485
+ });
486
+ }
487
+ return { success: true, guidance };
488
+ } catch (err: any) {
489
+ return { success: false, error: err.message };
490
+ }
491
+ },
492
+ {
493
+ name: "get_binding_guidance",
494
+ description: "获取将指定中间件插件绑定到智能体的详细步骤指导,包括诊断插件状态和提供故障排除建议。",
495
+ schema: z.object({
496
+ pluginName: z.string().min(1)
497
+ .describe("插件名称、packageName 或 displayName,例如 '@timmy_hu/bulk-email-sender'")
498
+ })
499
+ }
500
+ );
501
+
502
+ const diagnosePluginAvailability = tool(
503
+ async (input) => {
504
+ const pluginName = input.pluginName;
505
+ try {
506
+ await fetchAllPlugins();
507
+ const plugin = state.middlewarePlugins.find((p: any) => {
508
+ const meta = p.meta || {};
509
+ return p.name === pluginName || meta.name === pluginName || p.packageName === pluginName || meta.displayName === pluginName;
510
+ });
511
+ if (!plugin) {
512
+ return {
513
+ success: false,
514
+ error: `未找到名为 "${pluginName}" 的中间件插件`,
515
+ diagnosis: "插件未安装",
516
+ solution: "使用 install_middleware_plugin 工具安装该插件"
517
+ };
518
+ }
519
+ const meta = plugin.meta || {};
520
+ const detail = formatMiddlewarePlugin(plugin);
521
+ const checks = [];
522
+ let allPassed = true;
523
+ const loadCheck = {
524
+ name: "插件加载状态",
525
+ passed: detail.loadStatus === "loaded",
526
+ status: detail.loadStatus,
527
+ error: detail.loadError
528
+ };
529
+ checks.push(loadCheck);
530
+ if (!loadCheck.passed) allPassed = false;
531
+ const componentCheck = {
532
+ name: "组件暴露",
533
+ passed: detail.componentSummary.total > 0,
534
+ total: detail.componentSummary.total,
535
+ breakdown: detail.componentSummary
536
+ };
537
+ checks.push(componentCheck);
538
+ if (!componentCheck.passed) allPassed = false;
539
+ const configCheck = {
540
+ name: "配置状态",
541
+ passed: !detail.configurationError,
542
+ status: detail.configurationStatus,
543
+ error: detail.configurationError
544
+ };
545
+ checks.push(configCheck);
546
+ if (!configCheck.passed) allPassed = false;
547
+ const scopeCheck = {
548
+ name: "作用域生效",
549
+ passed: detail.effectiveInCurrentScope,
550
+ scopeRelation: detail.scopeRelation
551
+ };
552
+ checks.push(scopeCheck);
553
+ if (!scopeCheck.passed) allPassed = false;
554
+ const diagnosis = {
555
+ pluginName: detail.displayName,
556
+ packageName: detail.packageName,
557
+ version: detail.version,
558
+ allChecksPassed: allPassed,
559
+ checks,
560
+ summary: allPassed
561
+ ? "✅ 插件状态正常,应该可以在智能体中使用。如果仍无法使用,请确保已在智能体编排页面中添加了该中间件。"
562
+ : "❌ 插件存在问题,需要修复后才能使用",
563
+ recommendations: [] as string[]
564
+ };
565
+ if (!loadCheck.passed) {
566
+ diagnosis.recommendations.push("插件加载失败,请检查插件代码或联系插件作者");
567
+ }
568
+ if (!componentCheck.passed) {
569
+ diagnosis.recommendations.push("插件没有暴露任何工具或组件。这通常意味着插件代码没有正确实现中间件策略。请联系插件作者检查代码。");
570
+ }
571
+ if (!configCheck.passed) {
572
+ diagnosis.recommendations.push(`插件配置错误: ${detail.configurationError}`);
573
+ }
574
+ if (!scopeCheck.passed) {
575
+ diagnosis.recommendations.push("插件在当前作用域未生效。请在 XpertAI 平台 UI 的智能体编排页面中手动添加此中间件。");
576
+ }
577
+ if (allPassed) {
578
+ diagnosis.recommendations.push("插件状态正常。如果工具仍不可用,请确保:1) 已在智能体编排页面添加了该中间件;2) 已保存智能体配置;3) 刷新了智能体页面。");
579
+ }
580
+ return { success: true, diagnosis };
581
+ } catch (err: any) {
582
+ return { success: false, error: err.message };
583
+ }
584
+ },
585
+ {
586
+ name: "diagnose_plugin_availability",
587
+ description: "诊断指定中间件插件为什么其工具不可用。检查加载状态、组件暴露、配置状态和作用域生效情况,并提供修复建议。",
588
+ schema: z.object({
589
+ pluginName: z.string().min(1)
590
+ .describe("插件名称、packageName 或 displayName,例如 '@timmy_hu/bulk-email-sender'")
591
+ })
592
+ }
593
+ );
594
+
411
595
  return {
412
596
  name: MIDDLEWARE_PROVIDER,
413
597
  tools: [
@@ -417,7 +601,9 @@ export class PluginMiddleware {
417
601
  refreshPluginList,
418
602
  checkLoginStatus,
419
603
  searchMiddlewarePlugins,
420
- getPluginStatistics
604
+ getPluginStatistics,
605
+ getBindingGuidance,
606
+ diagnosePluginAvailability
421
607
  ]
422
608
  };
423
609
  }