@lark-apaas/nestjs-capability 0.0.1-alpha.9 → 0.1.0

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/dist/index.cjs CHANGED
@@ -41,10 +41,15 @@ __export(index_exports, {
41
41
  PluginLoaderService: () => PluginLoaderService,
42
42
  PluginNotFoundError: () => PluginNotFoundError,
43
43
  TemplateEngineService: () => TemplateEngineService,
44
- WebhookController: () => WebhookController
44
+ WebhookController: () => WebhookController,
45
+ migrationAdaptor: () => migrationAdaptor
45
46
  });
46
47
  module.exports = __toCommonJS(index_exports);
47
48
 
49
+ // ../../../node_modules/tsup/assets/cjs_shims.js
50
+ var getImportMetaUrl = /* @__PURE__ */ __name(() => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.tagName.toUpperCase() === "SCRIPT" ? document.currentScript.src : new URL("main.js", document.baseURI).href, "getImportMetaUrl");
51
+ var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
52
+
48
53
  // src/interfaces/error-codes.ts
49
54
  var ErrorCodes = {
50
55
  /** 成功 */
@@ -75,9 +80,9 @@ var TemplateEngineService = class {
75
80
  __name(this, "TemplateEngineService");
76
81
  }
77
82
  // 匹配 {{input.xxx}} 或 {{input.xxx.yyy}} 表达式
78
- EXPR_REGEX = /\{\{input\.([a-zA-Z_][a-zA-Z_0-9]*(?:\.[a-zA-Z_][a-zA-Z_0-9]*)*)\}\}/g;
83
+ EXPR_REGEX = /\{\{\s*input\.([a-zA-Z_][a-zA-Z_0-9]*(?:\.[a-zA-Z_][a-zA-Z_0-9]*)*\s*)\}\}/g;
79
84
  // 匹配整串单个表达式
80
- WHOLE_STRING_EXPR_REGEX = /^\{\{input\.([a-zA-Z_][a-zA-Z_0-9]*(?:\.[a-zA-Z_][a-zA-Z_0-9]*)*)\}\}$/;
85
+ WHOLE_STRING_EXPR_REGEX = /^\{\{\s*input\.([a-zA-Z_][a-zA-Z_0-9]*(?:\.[a-zA-Z_][a-zA-Z_0-9]*)*)\s*\}\}$/;
81
86
  resolve(template, input) {
82
87
  if (typeof template === "string") {
83
88
  return this.resolveString(template, input);
@@ -136,6 +141,8 @@ TemplateEngineService = _ts_decorate([
136
141
 
137
142
  // src/services/plugin-loader.service.ts
138
143
  var import_common2 = require("@nestjs/common");
144
+ var import_node_module = require("module");
145
+ var import_node_url = require("url");
139
146
  function _ts_decorate2(decorators, target, key, desc) {
140
147
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
141
148
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -143,13 +150,16 @@ function _ts_decorate2(decorators, target, key, desc) {
143
150
  return c > 3 && r && Object.defineProperty(target, key, r), r;
144
151
  }
145
152
  __name(_ts_decorate2, "_ts_decorate");
153
+ var require2 = (0, import_node_module.createRequire)(importMetaUrl);
146
154
  var PluginNotFoundError = class extends Error {
147
155
  static {
148
156
  __name(this, "PluginNotFoundError");
149
157
  }
158
+ pluginKey;
150
159
  constructor(pluginKey) {
151
160
  super(`Plugin not found: ${pluginKey}`);
152
161
  this.name = "PluginNotFoundError";
162
+ this.pluginKey = pluginKey;
153
163
  }
154
164
  };
155
165
  var PluginLoadError = class extends Error {
@@ -167,6 +177,8 @@ var PluginLoaderService = class _PluginLoaderService {
167
177
  }
168
178
  logger = new import_common2.Logger(_PluginLoaderService.name);
169
179
  pluginInstances = /* @__PURE__ */ new Map();
180
+ /** 记录每个插件的加载版本(时间戳),用于 ESM 缓存绕过 */
181
+ pluginVersions = /* @__PURE__ */ new Map();
170
182
  async loadPlugin(pluginKey) {
171
183
  const cached = this.pluginInstances.get(pluginKey);
172
184
  if (cached) {
@@ -175,7 +187,12 @@ var PluginLoaderService = class _PluginLoaderService {
175
187
  }
176
188
  this.logger.log(`Loading plugin: ${pluginKey}`);
177
189
  try {
178
- const pluginPackage = (await import(pluginKey)).default;
190
+ const resolvedPath = require2.resolve(pluginKey);
191
+ const version = this.pluginVersions.get(pluginKey) ?? 0;
192
+ const fileUrl = (0, import_node_url.pathToFileURL)(resolvedPath).href;
193
+ const importPath = version > 0 ? `${fileUrl}?v=${version}` : fileUrl;
194
+ const mod = await import(importPath);
195
+ const pluginPackage = mod.default ?? mod;
179
196
  if (typeof pluginPackage.create !== "function") {
180
197
  throw new PluginLoadError(pluginKey, "Plugin does not export create() function");
181
198
  }
@@ -192,21 +209,68 @@ var PluginLoaderService = class _PluginLoaderService {
192
209
  }
193
210
  isPluginInstalled(pluginKey) {
194
211
  try {
195
- require.resolve(pluginKey);
212
+ require2.resolve(pluginKey);
196
213
  return true;
197
214
  } catch {
198
215
  return false;
199
216
  }
200
217
  }
218
+ /**
219
+ * 清除插件缓存
220
+ * - 清除应用层 pluginInstances 缓存
221
+ * - 清除 Node.js CJS 模块缓存(require.cache)
222
+ * - 更新版本号,下次 import 时绕过 ESM 缓存
223
+ * @param pluginKey - 插件标识,不传则清除所有
224
+ */
201
225
  clearCache(pluginKey) {
202
226
  if (pluginKey) {
203
227
  this.pluginInstances.delete(pluginKey);
228
+ this.clearNodeModuleCache(pluginKey);
229
+ this.pluginVersions.set(pluginKey, Date.now());
204
230
  this.logger.log(`Cleared cache for plugin: ${pluginKey}`);
205
231
  } else {
232
+ for (const key of this.pluginInstances.keys()) {
233
+ this.clearNodeModuleCache(key);
234
+ this.pluginVersions.set(key, Date.now());
235
+ }
206
236
  this.pluginInstances.clear();
207
237
  this.logger.log("Cleared all plugin caches");
208
238
  }
209
239
  }
240
+ /**
241
+ * 清除 CJS 模块缓存
242
+ */
243
+ clearNodeModuleCache(pluginKey) {
244
+ try {
245
+ const resolvedPath = require2.resolve(pluginKey);
246
+ const mod = require2.cache[resolvedPath];
247
+ if (mod) {
248
+ this.clearModuleAndChildren(mod, pluginKey);
249
+ }
250
+ delete require2.cache[resolvedPath];
251
+ } catch {
252
+ }
253
+ }
254
+ /**
255
+ * 递归清除子模块缓存
256
+ */
257
+ clearModuleAndChildren(mod, pluginKey) {
258
+ const pluginScope = pluginKey.startsWith("@") ? pluginKey.split("/").slice(0, 2).join("/") : pluginKey;
259
+ mod.children.forEach((child) => {
260
+ if (child.filename.includes(`node_modules/${pluginScope}`)) {
261
+ this.clearModuleAndChildren(child, pluginKey);
262
+ delete require2.cache[child.filename];
263
+ }
264
+ });
265
+ }
266
+ /**
267
+ * 强制重新加载插件
268
+ * @param pluginKey - 插件标识
269
+ */
270
+ async reloadPlugin(pluginKey) {
271
+ this.clearCache(pluginKey);
272
+ return this.loadPlugin(pluginKey);
273
+ }
210
274
  };
211
275
  PluginLoaderService = _ts_decorate2([
212
276
  (0, import_common2.Injectable)()
@@ -217,6 +281,7 @@ var import_common3 = require("@nestjs/common");
217
281
  var import_nestjs_common = require("@lark-apaas/nestjs-common");
218
282
  var fs = __toESM(require("fs"), 1);
219
283
  var path = __toESM(require("path"), 1);
284
+ var chokidar = __toESM(require("chokidar"), 1);
220
285
 
221
286
  // src/utils/log-utils.ts
222
287
  var DEFAULT_MAX_LENGTH = 1e3;
@@ -238,6 +303,43 @@ function stringifyForLog(value, maxLength = DEFAULT_MAX_LENGTH) {
238
303
  }
239
304
  __name(stringifyForLog, "stringifyForLog");
240
305
 
306
+ // src/utils/migration-adaptor.ts
307
+ async function migrationAdaptor(promise) {
308
+ try {
309
+ const result = await promise;
310
+ return {
311
+ code: 0,
312
+ data: {
313
+ output: result,
314
+ outcome: "success"
315
+ }
316
+ };
317
+ } catch (error) {
318
+ const errorMessage = error instanceof Error ? error.message : String(error);
319
+ const appStatusCode = error instanceof Error && "code" in error ? String(error.code) : "EXECUTION_ERROR";
320
+ return {
321
+ code: -1,
322
+ data: {
323
+ outcome: "error",
324
+ failureOutput: {
325
+ response: {
326
+ status: {
327
+ protocolStatusCode: "500",
328
+ appStatusCode
329
+ },
330
+ body: JSON.stringify({
331
+ error: errorMessage,
332
+ stack: error instanceof Error ? error.stack : void 0
333
+ })
334
+ }
335
+ }
336
+ },
337
+ message: errorMessage
338
+ };
339
+ }
340
+ }
341
+ __name(migrationAdaptor, "migrationAdaptor");
342
+
241
343
  // src/services/capability.service.ts
242
344
  function _ts_decorate3(decorators, target, key, desc) {
243
345
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -260,18 +362,24 @@ var CapabilityNotFoundError = class extends Error {
260
362
  static {
261
363
  __name(this, "CapabilityNotFoundError");
262
364
  }
365
+ capabilityId;
263
366
  constructor(capabilityId) {
264
367
  super(`Capability not found: ${capabilityId}`);
265
368
  this.name = "CapabilityNotFoundError";
369
+ this.capabilityId = capabilityId;
266
370
  }
267
371
  };
268
372
  var ActionNotFoundError = class extends Error {
269
373
  static {
270
374
  __name(this, "ActionNotFoundError");
271
375
  }
376
+ pluginKey;
377
+ actionName;
272
378
  constructor(pluginKey, actionName) {
273
379
  super(`Action '${actionName}' not found in plugin ${pluginKey}`);
274
380
  this.name = "ActionNotFoundError";
381
+ this.pluginKey = pluginKey;
382
+ this.actionName = actionName;
275
383
  }
276
384
  };
277
385
  var CapabilityService = class _CapabilityService {
@@ -284,7 +392,11 @@ var CapabilityService = class _CapabilityService {
284
392
  templateEngineService;
285
393
  logger = new import_common3.Logger(_CapabilityService.name);
286
394
  capabilities = /* @__PURE__ */ new Map();
395
+ /** 文件路径到 capability id 的映射,用于文件删除时查找 */
396
+ filePathToId = /* @__PURE__ */ new Map();
287
397
  capabilitiesDir;
398
+ fileWatcher = null;
399
+ options = {};
288
400
  constructor(requestContextService, platformHttpClient, pluginLoaderService, templateEngineService) {
289
401
  this.requestContextService = requestContextService;
290
402
  this.platformHttpClient = platformHttpClient;
@@ -293,12 +405,140 @@ var CapabilityService = class _CapabilityService {
293
405
  const isDev = process.env.NODE_ENV === "development";
294
406
  this.capabilitiesDir = path.join(process.cwd(), isDev ? "server/capabilities" : "capabilities");
295
407
  }
408
+ /**
409
+ * 设置模块配置
410
+ */
411
+ setOptions(options) {
412
+ this.options = options;
413
+ if (options.capabilitiesDir) {
414
+ this.capabilitiesDir = options.capabilitiesDir;
415
+ }
416
+ }
296
417
  setCapabilitiesDir(dir) {
297
418
  this.capabilitiesDir = dir;
298
419
  }
299
420
  async onModuleInit() {
300
421
  await this.loadCapabilities();
422
+ if (this.options.enableWatching) {
423
+ this.startWatching();
424
+ }
425
+ }
426
+ async onModuleDestroy() {
427
+ this.stopWatching();
428
+ }
429
+ // ==================== 文件监听相关方法 ====================
430
+ /**
431
+ * 启动文件监听(沙箱环境自动调用)
432
+ */
433
+ startWatching() {
434
+ if (this.fileWatcher) {
435
+ return;
436
+ }
437
+ if (!fs.existsSync(this.capabilitiesDir)) {
438
+ this.logger.warn(`Cannot start watching: directory not found: ${this.capabilitiesDir}`);
439
+ return;
440
+ }
441
+ const pattern = path.join(this.capabilitiesDir, "*.json");
442
+ const debounce = this.options.watchDebounce ?? 300;
443
+ this.logger.log(`Starting file watcher: ${pattern}`);
444
+ this.fileWatcher = chokidar.watch(pattern, {
445
+ persistent: true,
446
+ ignoreInitial: true,
447
+ awaitWriteFinish: {
448
+ // 等待写入完成
449
+ stabilityThreshold: debounce,
450
+ pollInterval: 100
451
+ }
452
+ });
453
+ this.fileWatcher.on("add", (filePath) => this.handleFileAdd(filePath)).on("change", (filePath) => this.handleFileChange(filePath)).on("unlink", (filePath) => this.handleFileUnlink(filePath)).on("error", (error) => this.logger.error("File watcher error:", error));
454
+ this.logger.log("File watcher started");
455
+ }
456
+ /**
457
+ * 停止文件监听
458
+ */
459
+ stopWatching() {
460
+ if (this.fileWatcher) {
461
+ this.fileWatcher.close();
462
+ this.fileWatcher = null;
463
+ this.logger.log("File watcher stopped");
464
+ }
465
+ }
466
+ /**
467
+ * 重新加载所有能力配置
468
+ */
469
+ async reloadAllCapabilities() {
470
+ this.capabilities.clear();
471
+ this.filePathToId.clear();
472
+ await this.loadCapabilities();
473
+ }
474
+ handleFileAdd(filePath) {
475
+ this.logger.log(`Capability file added: ${filePath}`);
476
+ try {
477
+ this.loadCapabilityFromFile(filePath);
478
+ const capabilityId = this.filePathToId.get(filePath);
479
+ if (capabilityId) {
480
+ const config = this.capabilities.get(capabilityId);
481
+ if (config?.pluginKey) {
482
+ this.pluginLoaderService.clearCache(config.pluginKey);
483
+ this.logger.log(`Cleared plugin cache for new capability: ${config.pluginKey}`);
484
+ }
485
+ }
486
+ } catch (error) {
487
+ this.logger.error(`Failed to load new capability: ${filePath}`, error);
488
+ }
301
489
  }
490
+ handleFileChange(filePath) {
491
+ this.logger.log(`Capability file changed: ${filePath}`);
492
+ try {
493
+ this.reloadCapabilityFromFile(filePath);
494
+ } catch (error) {
495
+ this.logger.error(`Failed to reload capability: ${filePath}`, error);
496
+ }
497
+ }
498
+ handleFileUnlink(filePath) {
499
+ this.logger.log(`Capability file removed: ${filePath}`);
500
+ this.removeCapabilityByFile(filePath);
501
+ }
502
+ /**
503
+ * 从文件加载单个能力配置
504
+ */
505
+ loadCapabilityFromFile(filePath) {
506
+ const content = fs.readFileSync(filePath, "utf-8");
507
+ const config = JSON.parse(content);
508
+ if (!config.id) {
509
+ this.logger.warn(`Skipping capability without id: ${filePath}`);
510
+ return;
511
+ }
512
+ this.capabilities.set(config.id, config);
513
+ this.filePathToId.set(filePath, config.id);
514
+ this.logger.log(`Loaded capability: ${config.id} (${config.name})`);
515
+ }
516
+ /**
517
+ * 重新加载单个能力配置
518
+ */
519
+ reloadCapabilityFromFile(filePath) {
520
+ const oldId = this.filePathToId.get(filePath);
521
+ if (oldId) {
522
+ const oldConfig = this.capabilities.get(oldId);
523
+ if (oldConfig) {
524
+ this.pluginLoaderService.clearCache(oldConfig.pluginKey);
525
+ }
526
+ this.capabilities.delete(oldId);
527
+ }
528
+ this.loadCapabilityFromFile(filePath);
529
+ }
530
+ /**
531
+ * 根据文件路径移除能力配置
532
+ */
533
+ removeCapabilityByFile(filePath) {
534
+ const capabilityId = this.filePathToId.get(filePath);
535
+ if (capabilityId) {
536
+ this.capabilities.delete(capabilityId);
537
+ this.filePathToId.delete(filePath);
538
+ this.logger.log(`Removed capability: ${capabilityId}`);
539
+ }
540
+ }
541
+ // ==================== 原有方法 ====================
302
542
  async loadCapabilities() {
303
543
  this.logger.log(`Loading capabilities from ${this.capabilitiesDir}`);
304
544
  if (!fs.existsSync(this.capabilitiesDir)) {
@@ -309,14 +549,7 @@ var CapabilityService = class _CapabilityService {
309
549
  for (const file of files) {
310
550
  try {
311
551
  const filePath = path.join(this.capabilitiesDir, file);
312
- const content = fs.readFileSync(filePath, "utf-8");
313
- const config = JSON.parse(content);
314
- if (!config.id) {
315
- this.logger.warn(`Skipping capability without id: ${file}`);
316
- continue;
317
- }
318
- this.capabilities.set(config.id, config);
319
- this.logger.log(`Loaded capability: ${config.id} (${config.name})`);
552
+ this.loadCapabilityFromFile(filePath);
320
553
  } catch (error) {
321
554
  this.logger.error(`Failed to load capability from ${file}:`, error);
322
555
  }
@@ -593,6 +826,7 @@ CapabilityService = _ts_decorate3([
593
826
 
594
827
  // src/controllers/debug.controller.ts
595
828
  var import_common4 = require("@nestjs/common");
829
+ var import_swagger = require("@nestjs/swagger");
596
830
  function _ts_decorate4(decorators, target, key, desc) {
597
831
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
598
832
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -623,19 +857,27 @@ var DebugController = class _DebugController {
623
857
  this.pluginLoaderService = pluginLoaderService;
624
858
  this.templateEngineService = templateEngineService;
625
859
  }
626
- list() {
627
- const capabilities = this.capabilityService.listCapabilities();
628
- return {
629
- status_code: ErrorCodes.SUCCESS,
630
- data: {
631
- capabilities: capabilities.map((c) => ({
632
- id: c.id,
633
- name: c.name,
634
- pluginID: c.pluginKey,
635
- pluginVersion: c.pluginVersion
636
- }))
637
- }
638
- };
860
+ list(res) {
861
+ try {
862
+ const capabilities = this.capabilityService.listCapabilities();
863
+ res.status(import_common4.HttpStatus.OK).json({
864
+ status_code: ErrorCodes.SUCCESS,
865
+ data: {
866
+ capabilities: capabilities.map((c) => ({
867
+ id: c.id,
868
+ name: c.name,
869
+ pluginID: c.pluginKey,
870
+ pluginVersion: c.pluginVersion
871
+ }))
872
+ }
873
+ });
874
+ } catch (error) {
875
+ this.logger.error("Failed to list capabilities", error);
876
+ res.status(import_common4.HttpStatus.INTERNAL_SERVER_ERROR).json({
877
+ status_code: ErrorCodes.EXECUTION_ERROR,
878
+ error_msg: `Failed to list capabilities: ${error instanceof Error ? error.message : String(error)}`
879
+ });
880
+ }
639
881
  }
640
882
  /**
641
883
  * 获取 capability 配置
@@ -647,11 +889,7 @@ var DebugController = class _DebugController {
647
889
  }
648
890
  const config = this.capabilityService.getCapability(capabilityId);
649
891
  if (!config) {
650
- throw new import_common4.HttpException({
651
- code: 1,
652
- message: `Capability not found: ${capabilityId}`,
653
- error: "CAPABILITY_NOT_FOUND"
654
- }, import_common4.HttpStatus.NOT_FOUND);
892
+ throw new CapabilityNotFoundError(capabilityId);
655
893
  }
656
894
  return config;
657
895
  }
@@ -666,25 +904,21 @@ var DebugController = class _DebugController {
666
904
  const pluginInstance = await this.pluginLoaderService.loadPlugin(pluginKey);
667
905
  const actions = pluginInstance.listActions();
668
906
  if (actions.length === 0) {
669
- throw new import_common4.HttpException({
670
- code: 1,
671
- message: `Plugin ${pluginKey} has no actions`,
672
- error: "NO_ACTIONS"
673
- }, import_common4.HttpStatus.BAD_REQUEST);
907
+ throw new Error(`Plugin ${pluginKey} has no actions`);
674
908
  }
675
909
  return actions[0];
676
910
  }
677
- async debug(capabilityId, body) {
911
+ async debug(capabilityId, body, res) {
678
912
  const startTime = Date.now();
679
913
  const params = body.params ?? {};
680
- const config = this.getCapabilityConfig(capabilityId, body.capability);
681
- const action = await this.getActionName(config.pluginKey, body.action);
682
- const resolvedParams = this.templateEngineService.resolve(config.formValue, params);
683
914
  try {
915
+ const config = this.getCapabilityConfig(capabilityId, body.capability);
916
+ const action = await this.getActionName(config.pluginKey, body.action);
917
+ const resolvedParams = this.templateEngineService.resolve(config.formValue, params);
684
918
  const result = await this.capabilityService.loadWithConfig(config).call(action, params, {
685
919
  isDebug: true
686
920
  });
687
- return {
921
+ res.status(import_common4.HttpStatus.OK).json({
688
922
  status_code: ErrorCodes.SUCCESS,
689
923
  data: {
690
924
  output: result,
@@ -696,32 +930,39 @@ var DebugController = class _DebugController {
696
930
  action
697
931
  }
698
932
  }
699
- };
933
+ });
700
934
  } catch (error) {
701
- if (error instanceof CapabilityNotFoundError) {
702
- throw new import_common4.HttpException({
703
- status_code: ErrorCodes.CAPABILITY_NOT_FOUND,
704
- error_msg: `Capability not found: ${capabilityId}`
705
- }, import_common4.HttpStatus.NOT_FOUND);
706
- }
707
- if (error instanceof PluginNotFoundError) {
708
- throw new import_common4.HttpException({
709
- status_code: ErrorCodes.PLUGIN_NOT_FOUND,
710
- error_msg: `Plugin not found: ${config.pluginKey}`
711
- }, import_common4.HttpStatus.INTERNAL_SERVER_ERROR);
712
- }
713
- if (error instanceof ActionNotFoundError) {
714
- throw new import_common4.HttpException({
715
- status_code: ErrorCodes.ACTION_NOT_FOUND,
716
- error_msg: `Action '${action}' not found in plugin ${config.pluginKey}`
717
- }, import_common4.HttpStatus.BAD_REQUEST);
718
- }
719
- throw new import_common4.HttpException({
720
- status_code: ErrorCodes.EXECUTION_ERROR,
721
- error_msg: `Execution failed: ${error instanceof Error ? error.message : String(error)}`
722
- }, import_common4.HttpStatus.INTERNAL_SERVER_ERROR);
935
+ this.logger.error("Debug execution failed", error);
936
+ res.status(import_common4.HttpStatus.INTERNAL_SERVER_ERROR).json(this.buildErrorResponse(error));
723
937
  }
724
938
  }
939
+ /**
940
+ * 构建错误响应
941
+ */
942
+ buildErrorResponse(error) {
943
+ if (error instanceof CapabilityNotFoundError) {
944
+ return {
945
+ status_code: ErrorCodes.CAPABILITY_NOT_FOUND,
946
+ error_msg: `Capability not found: ${error.capabilityId}`
947
+ };
948
+ }
949
+ if (error instanceof PluginNotFoundError) {
950
+ return {
951
+ status_code: ErrorCodes.PLUGIN_NOT_FOUND,
952
+ error_msg: `Plugin not found, please install plugin: ${error.pluginKey}`
953
+ };
954
+ }
955
+ if (error instanceof ActionNotFoundError) {
956
+ return {
957
+ status_code: ErrorCodes.ACTION_NOT_FOUND,
958
+ error_msg: `Action '${error.actionName}' not found in plugin ${error.pluginKey}`
959
+ };
960
+ }
961
+ return {
962
+ status_code: ErrorCodes.EXECUTION_ERROR,
963
+ error_msg: `Execution failed: ${error instanceof Error ? error.message : String(error)}`
964
+ };
965
+ }
725
966
  async debugStream(capabilityId, body, res) {
726
967
  const params = body.params ?? {};
727
968
  res.setHeader("Content-Type", "text/event-stream");
@@ -752,9 +993,7 @@ var DebugController = class _DebugController {
752
993
  status_code: ErrorCodes.SUCCESS,
753
994
  data: {
754
995
  type: "content",
755
- delta: {
756
- content: pendingChunk
757
- }
996
+ delta: pendingChunk
758
997
  }
759
998
  };
760
999
  res.write(`data: ${JSON.stringify(response)}
@@ -770,9 +1009,7 @@ var DebugController = class _DebugController {
770
1009
  status_code: ErrorCodes.SUCCESS,
771
1010
  data: {
772
1011
  type: "content",
773
- delta: {
774
- content: pendingChunk
775
- },
1012
+ delta: pendingChunk,
776
1013
  finished: true
777
1014
  }
778
1015
  };
@@ -812,9 +1049,7 @@ var DebugController = class _DebugController {
812
1049
  status_code: ErrorCodes.SUCCESS,
813
1050
  data: {
814
1051
  type: "content",
815
- delta: {
816
- content: pendingChunk
817
- },
1052
+ delta: pendingChunk,
818
1053
  finished: true
819
1054
  }
820
1055
  };
@@ -844,18 +1079,23 @@ var DebugController = class _DebugController {
844
1079
  };
845
1080
  _ts_decorate4([
846
1081
  (0, import_common4.Get)("list"),
1082
+ _ts_param2(0, (0, import_common4.Res)()),
847
1083
  _ts_metadata2("design:type", Function),
848
- _ts_metadata2("design:paramtypes", []),
849
- _ts_metadata2("design:returntype", typeof SuccessResponse === "undefined" ? Object : SuccessResponse)
1084
+ _ts_metadata2("design:paramtypes", [
1085
+ typeof Response === "undefined" ? Object : Response
1086
+ ]),
1087
+ _ts_metadata2("design:returntype", void 0)
850
1088
  ], DebugController.prototype, "list", null);
851
1089
  _ts_decorate4([
852
1090
  (0, import_common4.Post)("debug/:capability_id"),
853
1091
  _ts_param2(0, (0, import_common4.Param)("capability_id")),
854
1092
  _ts_param2(1, (0, import_common4.Body)()),
1093
+ _ts_param2(2, (0, import_common4.Res)()),
855
1094
  _ts_metadata2("design:type", Function),
856
1095
  _ts_metadata2("design:paramtypes", [
857
1096
  String,
858
- typeof DebugRequestBody === "undefined" ? Object : DebugRequestBody
1097
+ typeof DebugRequestBody === "undefined" ? Object : DebugRequestBody,
1098
+ typeof Response === "undefined" ? Object : Response
859
1099
  ]),
860
1100
  _ts_metadata2("design:returntype", Promise)
861
1101
  ], DebugController.prototype, "debug", null);
@@ -873,6 +1113,7 @@ _ts_decorate4([
873
1113
  _ts_metadata2("design:returntype", Promise)
874
1114
  ], DebugController.prototype, "debugStream", null);
875
1115
  DebugController = _ts_decorate4([
1116
+ (0, import_swagger.ApiExcludeController)(),
876
1117
  (0, import_common4.Controller)("__innerapi__/capability"),
877
1118
  _ts_metadata2("design:type", Function),
878
1119
  _ts_metadata2("design:paramtypes", [
@@ -884,6 +1125,7 @@ DebugController = _ts_decorate4([
884
1125
 
885
1126
  // src/controllers/webhook.controller.ts
886
1127
  var import_common5 = require("@nestjs/common");
1128
+ var import_swagger2 = require("@nestjs/swagger");
887
1129
  function _ts_decorate5(decorators, target, key, desc) {
888
1130
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
889
1131
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -910,54 +1152,69 @@ var WebhookController = class _WebhookController {
910
1152
  constructor(capabilityService) {
911
1153
  this.capabilityService = capabilityService;
912
1154
  }
913
- list() {
914
- const capabilities = this.capabilityService.listCapabilities();
915
- return {
916
- status_code: ErrorCodes.SUCCESS,
917
- data: {
918
- capabilities: capabilities.map((c) => ({
919
- id: c.id,
920
- name: c.name,
921
- pluginID: c.pluginKey,
922
- pluginVersion: c.pluginVersion
923
- }))
924
- }
925
- };
1155
+ list(res) {
1156
+ try {
1157
+ const capabilities = this.capabilityService.listCapabilities();
1158
+ res.status(import_common5.HttpStatus.OK).json({
1159
+ status_code: ErrorCodes.SUCCESS,
1160
+ data: {
1161
+ capabilities: capabilities.map((c) => ({
1162
+ id: c.id,
1163
+ name: c.name,
1164
+ pluginID: c.pluginKey,
1165
+ pluginVersion: c.pluginVersion
1166
+ }))
1167
+ }
1168
+ });
1169
+ } catch (error) {
1170
+ this.logger.error("Failed to list capabilities", error);
1171
+ res.status(import_common5.HttpStatus.INTERNAL_SERVER_ERROR).json({
1172
+ status_code: ErrorCodes.EXECUTION_ERROR,
1173
+ error_msg: `Failed to list capabilities: ${error instanceof Error ? error.message : String(error)}`
1174
+ });
1175
+ }
926
1176
  }
927
- async execute(capabilityId, body) {
1177
+ async execute(capabilityId, body, res) {
928
1178
  try {
929
1179
  const result = await this.capabilityService.load(capabilityId).call(body.action, body.params);
930
- return {
1180
+ res.status(import_common5.HttpStatus.OK).json({
931
1181
  status_code: ErrorCodes.SUCCESS,
932
1182
  data: {
933
1183
  output: result
934
1184
  }
935
- };
1185
+ });
936
1186
  } catch (error) {
937
- if (error instanceof CapabilityNotFoundError) {
938
- throw new import_common5.HttpException({
939
- status_code: ErrorCodes.CAPABILITY_NOT_FOUND,
940
- error_msg: `Capability not found: ${capabilityId}`
941
- }, import_common5.HttpStatus.NOT_FOUND);
942
- }
943
- if (error instanceof PluginNotFoundError) {
944
- throw new import_common5.HttpException({
945
- status_code: ErrorCodes.PLUGIN_NOT_FOUND,
946
- error_msg: `Plugin not found`
947
- }, import_common5.HttpStatus.INTERNAL_SERVER_ERROR);
948
- }
949
- if (error instanceof ActionNotFoundError) {
950
- throw new import_common5.HttpException({
951
- status_code: ErrorCodes.ACTION_NOT_FOUND,
952
- error_msg: `Action '${body.action}' not found`
953
- }, import_common5.HttpStatus.BAD_REQUEST);
954
- }
955
- throw new import_common5.HttpException({
956
- status_code: ErrorCodes.EXECUTION_ERROR,
957
- error_msg: `Execution failed: ${error instanceof Error ? error.message : String(error)}`
958
- }, import_common5.HttpStatus.INTERNAL_SERVER_ERROR);
1187
+ this.logger.error("Capability execution failed", error);
1188
+ res.status(import_common5.HttpStatus.INTERNAL_SERVER_ERROR).json(this.buildErrorResponse(error));
959
1189
  }
960
1190
  }
1191
+ /**
1192
+ * 构建错误响应
1193
+ */
1194
+ buildErrorResponse(error) {
1195
+ if (error instanceof CapabilityNotFoundError) {
1196
+ return {
1197
+ status_code: ErrorCodes.CAPABILITY_NOT_FOUND,
1198
+ error_msg: `Capability not found: ${error.capabilityId}`
1199
+ };
1200
+ }
1201
+ if (error instanceof PluginNotFoundError) {
1202
+ return {
1203
+ status_code: ErrorCodes.PLUGIN_NOT_FOUND,
1204
+ error_msg: `Plugin not found, please install plugin: ${error.pluginKey}`
1205
+ };
1206
+ }
1207
+ if (error instanceof ActionNotFoundError) {
1208
+ return {
1209
+ status_code: ErrorCodes.ACTION_NOT_FOUND,
1210
+ error_msg: `Action '${error.actionName}' not found in plugin ${error.pluginKey}`
1211
+ };
1212
+ }
1213
+ return {
1214
+ status_code: ErrorCodes.EXECUTION_ERROR,
1215
+ error_msg: `Execution failed: ${error instanceof Error ? error.message : String(error)}`
1216
+ };
1217
+ }
961
1218
  async executeStream(capabilityId, body, res) {
962
1219
  const loggerContext = {
963
1220
  capability_id: capabilityId,
@@ -982,9 +1239,7 @@ var WebhookController = class _WebhookController {
982
1239
  status_code: ErrorCodes.SUCCESS,
983
1240
  data: {
984
1241
  type: "content",
985
- delta: {
986
- content: pendingChunk
987
- }
1242
+ delta: pendingChunk
988
1243
  }
989
1244
  };
990
1245
  res.write(`data: ${JSON.stringify(response)}
@@ -1000,9 +1255,7 @@ var WebhookController = class _WebhookController {
1000
1255
  status_code: ErrorCodes.SUCCESS,
1001
1256
  data: {
1002
1257
  type: "content",
1003
- delta: {
1004
- content: pendingChunk
1005
- },
1258
+ delta: pendingChunk,
1006
1259
  finished: true
1007
1260
  }
1008
1261
  };
@@ -1042,9 +1295,7 @@ var WebhookController = class _WebhookController {
1042
1295
  status_code: ErrorCodes.SUCCESS,
1043
1296
  data: {
1044
1297
  type: "content",
1045
- delta: {
1046
- content: pendingChunk
1047
- },
1298
+ delta: pendingChunk,
1048
1299
  finished: true
1049
1300
  }
1050
1301
  };
@@ -1074,18 +1325,23 @@ var WebhookController = class _WebhookController {
1074
1325
  };
1075
1326
  _ts_decorate5([
1076
1327
  (0, import_common5.Get)("list"),
1328
+ _ts_param3(0, (0, import_common5.Res)()),
1077
1329
  _ts_metadata3("design:type", Function),
1078
- _ts_metadata3("design:paramtypes", []),
1079
- _ts_metadata3("design:returntype", typeof SuccessResponse === "undefined" ? Object : SuccessResponse)
1330
+ _ts_metadata3("design:paramtypes", [
1331
+ typeof Response === "undefined" ? Object : Response
1332
+ ]),
1333
+ _ts_metadata3("design:returntype", void 0)
1080
1334
  ], WebhookController.prototype, "list", null);
1081
1335
  _ts_decorate5([
1082
1336
  (0, import_common5.Post)(":capability_id"),
1083
1337
  _ts_param3(0, (0, import_common5.Param)("capability_id")),
1084
1338
  _ts_param3(1, (0, import_common5.Body)()),
1339
+ _ts_param3(2, (0, import_common5.Res)()),
1085
1340
  _ts_metadata3("design:type", Function),
1086
1341
  _ts_metadata3("design:paramtypes", [
1087
1342
  String,
1088
- typeof ExecuteRequestBody === "undefined" ? Object : ExecuteRequestBody
1343
+ typeof ExecuteRequestBody === "undefined" ? Object : ExecuteRequestBody,
1344
+ typeof Response === "undefined" ? Object : Response
1089
1345
  ]),
1090
1346
  _ts_metadata3("design:returntype", Promise)
1091
1347
  ], WebhookController.prototype, "execute", null);
@@ -1103,6 +1359,7 @@ _ts_decorate5([
1103
1359
  _ts_metadata3("design:returntype", Promise)
1104
1360
  ], WebhookController.prototype, "executeStream", null);
1105
1361
  WebhookController = _ts_decorate5([
1362
+ (0, import_swagger2.ApiExcludeController)(),
1106
1363
  (0, import_common5.Controller)("api/capability"),
1107
1364
  _ts_metadata3("design:type", Function),
1108
1365
  _ts_metadata3("design:paramtypes", [
@@ -1152,8 +1409,8 @@ var CapabilityModule = class _CapabilityModule {
1152
1409
  provide: CapabilityService,
1153
1410
  useFactory: /* @__PURE__ */ __name((requestContextService, httpClient, pluginLoader, templateEngine, moduleOptions) => {
1154
1411
  const service = new CapabilityService(requestContextService, httpClient, pluginLoader, templateEngine);
1155
- if (moduleOptions?.capabilitiesDir) {
1156
- service.setCapabilitiesDir(moduleOptions.capabilitiesDir);
1412
+ if (moduleOptions) {
1413
+ service.setOptions(moduleOptions);
1157
1414
  }
1158
1415
  return service;
1159
1416
  }, "useFactory"),
@@ -1202,6 +1459,7 @@ CapabilityModule = _ts_decorate6([
1202
1459
  PluginLoaderService,
1203
1460
  PluginNotFoundError,
1204
1461
  TemplateEngineService,
1205
- WebhookController
1462
+ WebhookController,
1463
+ migrationAdaptor
1206
1464
  });
1207
1465
  //# sourceMappingURL=index.cjs.map