@lark-apaas/nestjs-capability 0.0.1-alpha.8 → 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,20 +392,153 @@ 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;
291
403
  this.pluginLoaderService = pluginLoaderService;
292
404
  this.templateEngineService = templateEngineService;
293
- this.capabilitiesDir = path.join(process.cwd(), "server/capabilities");
405
+ const isDev = process.env.NODE_ENV === "development";
406
+ this.capabilitiesDir = path.join(process.cwd(), isDev ? "server/capabilities" : "capabilities");
407
+ }
408
+ /**
409
+ * 设置模块配置
410
+ */
411
+ setOptions(options) {
412
+ this.options = options;
413
+ if (options.capabilitiesDir) {
414
+ this.capabilitiesDir = options.capabilitiesDir;
415
+ }
294
416
  }
295
417
  setCapabilitiesDir(dir) {
296
418
  this.capabilitiesDir = dir;
297
419
  }
298
420
  async onModuleInit() {
299
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
+ }
300
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
+ // ==================== 原有方法 ====================
301
542
  async loadCapabilities() {
302
543
  this.logger.log(`Loading capabilities from ${this.capabilitiesDir}`);
303
544
  if (!fs.existsSync(this.capabilitiesDir)) {
@@ -308,14 +549,7 @@ var CapabilityService = class _CapabilityService {
308
549
  for (const file of files) {
309
550
  try {
310
551
  const filePath = path.join(this.capabilitiesDir, file);
311
- const content = fs.readFileSync(filePath, "utf-8");
312
- const config = JSON.parse(content);
313
- if (!config.id) {
314
- this.logger.warn(`Skipping capability without id: ${file}`);
315
- continue;
316
- }
317
- this.capabilities.set(config.id, config);
318
- this.logger.log(`Loaded capability: ${config.id} (${config.name})`);
552
+ this.loadCapabilityFromFile(filePath);
319
553
  } catch (error) {
320
554
  this.logger.error(`Failed to load capability from ${file}:`, error);
321
555
  }
@@ -592,6 +826,7 @@ CapabilityService = _ts_decorate3([
592
826
 
593
827
  // src/controllers/debug.controller.ts
594
828
  var import_common4 = require("@nestjs/common");
829
+ var import_swagger = require("@nestjs/swagger");
595
830
  function _ts_decorate4(decorators, target, key, desc) {
596
831
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
597
832
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -622,19 +857,27 @@ var DebugController = class _DebugController {
622
857
  this.pluginLoaderService = pluginLoaderService;
623
858
  this.templateEngineService = templateEngineService;
624
859
  }
625
- list() {
626
- const capabilities = this.capabilityService.listCapabilities();
627
- return {
628
- status_code: ErrorCodes.SUCCESS,
629
- data: {
630
- capabilities: capabilities.map((c) => ({
631
- id: c.id,
632
- name: c.name,
633
- pluginID: c.pluginKey,
634
- pluginVersion: c.pluginVersion
635
- }))
636
- }
637
- };
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
+ }
638
881
  }
639
882
  /**
640
883
  * 获取 capability 配置
@@ -646,11 +889,7 @@ var DebugController = class _DebugController {
646
889
  }
647
890
  const config = this.capabilityService.getCapability(capabilityId);
648
891
  if (!config) {
649
- throw new import_common4.HttpException({
650
- code: 1,
651
- message: `Capability not found: ${capabilityId}`,
652
- error: "CAPABILITY_NOT_FOUND"
653
- }, import_common4.HttpStatus.NOT_FOUND);
892
+ throw new CapabilityNotFoundError(capabilityId);
654
893
  }
655
894
  return config;
656
895
  }
@@ -665,25 +904,21 @@ var DebugController = class _DebugController {
665
904
  const pluginInstance = await this.pluginLoaderService.loadPlugin(pluginKey);
666
905
  const actions = pluginInstance.listActions();
667
906
  if (actions.length === 0) {
668
- throw new import_common4.HttpException({
669
- code: 1,
670
- message: `Plugin ${pluginKey} has no actions`,
671
- error: "NO_ACTIONS"
672
- }, import_common4.HttpStatus.BAD_REQUEST);
907
+ throw new Error(`Plugin ${pluginKey} has no actions`);
673
908
  }
674
909
  return actions[0];
675
910
  }
676
- async debug(capabilityId, body) {
911
+ async debug(capabilityId, body, res) {
677
912
  const startTime = Date.now();
678
913
  const params = body.params ?? {};
679
- const config = this.getCapabilityConfig(capabilityId, body.capability);
680
- const action = await this.getActionName(config.pluginKey, body.action);
681
- const resolvedParams = this.templateEngineService.resolve(config.formValue, params);
682
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);
683
918
  const result = await this.capabilityService.loadWithConfig(config).call(action, params, {
684
919
  isDebug: true
685
920
  });
686
- return {
921
+ res.status(import_common4.HttpStatus.OK).json({
687
922
  status_code: ErrorCodes.SUCCESS,
688
923
  data: {
689
924
  output: result,
@@ -695,32 +930,39 @@ var DebugController = class _DebugController {
695
930
  action
696
931
  }
697
932
  }
698
- };
933
+ });
699
934
  } catch (error) {
700
- if (error instanceof CapabilityNotFoundError) {
701
- throw new import_common4.HttpException({
702
- status_code: ErrorCodes.CAPABILITY_NOT_FOUND,
703
- error_msg: `Capability not found: ${capabilityId}`
704
- }, import_common4.HttpStatus.NOT_FOUND);
705
- }
706
- if (error instanceof PluginNotFoundError) {
707
- throw new import_common4.HttpException({
708
- status_code: ErrorCodes.PLUGIN_NOT_FOUND,
709
- error_msg: `Plugin not found: ${config.pluginKey}`
710
- }, import_common4.HttpStatus.INTERNAL_SERVER_ERROR);
711
- }
712
- if (error instanceof ActionNotFoundError) {
713
- throw new import_common4.HttpException({
714
- status_code: ErrorCodes.ACTION_NOT_FOUND,
715
- error_msg: `Action '${action}' not found in plugin ${config.pluginKey}`
716
- }, import_common4.HttpStatus.BAD_REQUEST);
717
- }
718
- throw new import_common4.HttpException({
719
- status_code: ErrorCodes.EXECUTION_ERROR,
720
- error_msg: `Execution failed: ${error instanceof Error ? error.message : String(error)}`
721
- }, 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));
722
937
  }
723
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
+ }
724
966
  async debugStream(capabilityId, body, res) {
725
967
  const params = body.params ?? {};
726
968
  res.setHeader("Content-Type", "text/event-stream");
@@ -751,9 +993,7 @@ var DebugController = class _DebugController {
751
993
  status_code: ErrorCodes.SUCCESS,
752
994
  data: {
753
995
  type: "content",
754
- delta: {
755
- content: pendingChunk
756
- }
996
+ delta: pendingChunk
757
997
  }
758
998
  };
759
999
  res.write(`data: ${JSON.stringify(response)}
@@ -769,9 +1009,7 @@ var DebugController = class _DebugController {
769
1009
  status_code: ErrorCodes.SUCCESS,
770
1010
  data: {
771
1011
  type: "content",
772
- delta: {
773
- content: pendingChunk
774
- },
1012
+ delta: pendingChunk,
775
1013
  finished: true
776
1014
  }
777
1015
  };
@@ -811,9 +1049,7 @@ var DebugController = class _DebugController {
811
1049
  status_code: ErrorCodes.SUCCESS,
812
1050
  data: {
813
1051
  type: "content",
814
- delta: {
815
- content: pendingChunk
816
- },
1052
+ delta: pendingChunk,
817
1053
  finished: true
818
1054
  }
819
1055
  };
@@ -843,18 +1079,23 @@ var DebugController = class _DebugController {
843
1079
  };
844
1080
  _ts_decorate4([
845
1081
  (0, import_common4.Get)("list"),
1082
+ _ts_param2(0, (0, import_common4.Res)()),
846
1083
  _ts_metadata2("design:type", Function),
847
- _ts_metadata2("design:paramtypes", []),
848
- _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)
849
1088
  ], DebugController.prototype, "list", null);
850
1089
  _ts_decorate4([
851
1090
  (0, import_common4.Post)("debug/:capability_id"),
852
1091
  _ts_param2(0, (0, import_common4.Param)("capability_id")),
853
1092
  _ts_param2(1, (0, import_common4.Body)()),
1093
+ _ts_param2(2, (0, import_common4.Res)()),
854
1094
  _ts_metadata2("design:type", Function),
855
1095
  _ts_metadata2("design:paramtypes", [
856
1096
  String,
857
- typeof DebugRequestBody === "undefined" ? Object : DebugRequestBody
1097
+ typeof DebugRequestBody === "undefined" ? Object : DebugRequestBody,
1098
+ typeof Response === "undefined" ? Object : Response
858
1099
  ]),
859
1100
  _ts_metadata2("design:returntype", Promise)
860
1101
  ], DebugController.prototype, "debug", null);
@@ -872,6 +1113,7 @@ _ts_decorate4([
872
1113
  _ts_metadata2("design:returntype", Promise)
873
1114
  ], DebugController.prototype, "debugStream", null);
874
1115
  DebugController = _ts_decorate4([
1116
+ (0, import_swagger.ApiExcludeController)(),
875
1117
  (0, import_common4.Controller)("__innerapi__/capability"),
876
1118
  _ts_metadata2("design:type", Function),
877
1119
  _ts_metadata2("design:paramtypes", [
@@ -883,6 +1125,7 @@ DebugController = _ts_decorate4([
883
1125
 
884
1126
  // src/controllers/webhook.controller.ts
885
1127
  var import_common5 = require("@nestjs/common");
1128
+ var import_swagger2 = require("@nestjs/swagger");
886
1129
  function _ts_decorate5(decorators, target, key, desc) {
887
1130
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
888
1131
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -909,54 +1152,69 @@ var WebhookController = class _WebhookController {
909
1152
  constructor(capabilityService) {
910
1153
  this.capabilityService = capabilityService;
911
1154
  }
912
- list() {
913
- const capabilities = this.capabilityService.listCapabilities();
914
- return {
915
- status_code: ErrorCodes.SUCCESS,
916
- data: {
917
- capabilities: capabilities.map((c) => ({
918
- id: c.id,
919
- name: c.name,
920
- pluginID: c.pluginKey,
921
- pluginVersion: c.pluginVersion
922
- }))
923
- }
924
- };
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
+ }
925
1176
  }
926
- async execute(capabilityId, body) {
1177
+ async execute(capabilityId, body, res) {
927
1178
  try {
928
1179
  const result = await this.capabilityService.load(capabilityId).call(body.action, body.params);
929
- return {
1180
+ res.status(import_common5.HttpStatus.OK).json({
930
1181
  status_code: ErrorCodes.SUCCESS,
931
1182
  data: {
932
1183
  output: result
933
1184
  }
934
- };
1185
+ });
935
1186
  } catch (error) {
936
- if (error instanceof CapabilityNotFoundError) {
937
- throw new import_common5.HttpException({
938
- status_code: ErrorCodes.CAPABILITY_NOT_FOUND,
939
- error_msg: `Capability not found: ${capabilityId}`
940
- }, import_common5.HttpStatus.NOT_FOUND);
941
- }
942
- if (error instanceof PluginNotFoundError) {
943
- throw new import_common5.HttpException({
944
- status_code: ErrorCodes.PLUGIN_NOT_FOUND,
945
- error_msg: `Plugin not found`
946
- }, import_common5.HttpStatus.INTERNAL_SERVER_ERROR);
947
- }
948
- if (error instanceof ActionNotFoundError) {
949
- throw new import_common5.HttpException({
950
- status_code: ErrorCodes.ACTION_NOT_FOUND,
951
- error_msg: `Action '${body.action}' not found`
952
- }, import_common5.HttpStatus.BAD_REQUEST);
953
- }
954
- throw new import_common5.HttpException({
955
- status_code: ErrorCodes.EXECUTION_ERROR,
956
- error_msg: `Execution failed: ${error instanceof Error ? error.message : String(error)}`
957
- }, 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));
958
1189
  }
959
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
+ }
960
1218
  async executeStream(capabilityId, body, res) {
961
1219
  const loggerContext = {
962
1220
  capability_id: capabilityId,
@@ -981,9 +1239,7 @@ var WebhookController = class _WebhookController {
981
1239
  status_code: ErrorCodes.SUCCESS,
982
1240
  data: {
983
1241
  type: "content",
984
- delta: {
985
- content: pendingChunk
986
- }
1242
+ delta: pendingChunk
987
1243
  }
988
1244
  };
989
1245
  res.write(`data: ${JSON.stringify(response)}
@@ -999,9 +1255,7 @@ var WebhookController = class _WebhookController {
999
1255
  status_code: ErrorCodes.SUCCESS,
1000
1256
  data: {
1001
1257
  type: "content",
1002
- delta: {
1003
- content: pendingChunk
1004
- },
1258
+ delta: pendingChunk,
1005
1259
  finished: true
1006
1260
  }
1007
1261
  };
@@ -1041,9 +1295,7 @@ var WebhookController = class _WebhookController {
1041
1295
  status_code: ErrorCodes.SUCCESS,
1042
1296
  data: {
1043
1297
  type: "content",
1044
- delta: {
1045
- content: pendingChunk
1046
- },
1298
+ delta: pendingChunk,
1047
1299
  finished: true
1048
1300
  }
1049
1301
  };
@@ -1073,18 +1325,23 @@ var WebhookController = class _WebhookController {
1073
1325
  };
1074
1326
  _ts_decorate5([
1075
1327
  (0, import_common5.Get)("list"),
1328
+ _ts_param3(0, (0, import_common5.Res)()),
1076
1329
  _ts_metadata3("design:type", Function),
1077
- _ts_metadata3("design:paramtypes", []),
1078
- _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)
1079
1334
  ], WebhookController.prototype, "list", null);
1080
1335
  _ts_decorate5([
1081
1336
  (0, import_common5.Post)(":capability_id"),
1082
1337
  _ts_param3(0, (0, import_common5.Param)("capability_id")),
1083
1338
  _ts_param3(1, (0, import_common5.Body)()),
1339
+ _ts_param3(2, (0, import_common5.Res)()),
1084
1340
  _ts_metadata3("design:type", Function),
1085
1341
  _ts_metadata3("design:paramtypes", [
1086
1342
  String,
1087
- typeof ExecuteRequestBody === "undefined" ? Object : ExecuteRequestBody
1343
+ typeof ExecuteRequestBody === "undefined" ? Object : ExecuteRequestBody,
1344
+ typeof Response === "undefined" ? Object : Response
1088
1345
  ]),
1089
1346
  _ts_metadata3("design:returntype", Promise)
1090
1347
  ], WebhookController.prototype, "execute", null);
@@ -1102,6 +1359,7 @@ _ts_decorate5([
1102
1359
  _ts_metadata3("design:returntype", Promise)
1103
1360
  ], WebhookController.prototype, "executeStream", null);
1104
1361
  WebhookController = _ts_decorate5([
1362
+ (0, import_swagger2.ApiExcludeController)(),
1105
1363
  (0, import_common5.Controller)("api/capability"),
1106
1364
  _ts_metadata3("design:type", Function),
1107
1365
  _ts_metadata3("design:paramtypes", [
@@ -1151,8 +1409,8 @@ var CapabilityModule = class _CapabilityModule {
1151
1409
  provide: CapabilityService,
1152
1410
  useFactory: /* @__PURE__ */ __name((requestContextService, httpClient, pluginLoader, templateEngine, moduleOptions) => {
1153
1411
  const service = new CapabilityService(requestContextService, httpClient, pluginLoader, templateEngine);
1154
- if (moduleOptions?.capabilitiesDir) {
1155
- service.setCapabilitiesDir(moduleOptions.capabilitiesDir);
1412
+ if (moduleOptions) {
1413
+ service.setOptions(moduleOptions);
1156
1414
  }
1157
1415
  return service;
1158
1416
  }, "useFactory"),
@@ -1201,6 +1459,7 @@ CapabilityModule = _ts_decorate6([
1201
1459
  PluginLoaderService,
1202
1460
  PluginNotFoundError,
1203
1461
  TemplateEngineService,
1204
- WebhookController
1462
+ WebhookController,
1463
+ migrationAdaptor
1205
1464
  });
1206
1465
  //# sourceMappingURL=index.cjs.map