@lark-apaas/nestjs-capability 0.0.1-alpha.3 → 0.0.1-alpha.4

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
@@ -130,8 +130,8 @@ var PluginNotFoundError = class extends Error {
130
130
  static {
131
131
  __name(this, "PluginNotFoundError");
132
132
  }
133
- constructor(pluginID) {
134
- super(`Plugin not found: ${pluginID}`);
133
+ constructor(pluginKey) {
134
+ super(`Plugin not found: ${pluginKey}`);
135
135
  this.name = "PluginNotFoundError";
136
136
  }
137
137
  };
@@ -139,8 +139,8 @@ var PluginLoadError = class extends Error {
139
139
  static {
140
140
  __name(this, "PluginLoadError");
141
141
  }
142
- constructor(pluginID, reason) {
143
- super(`Failed to load plugin ${pluginID}: ${reason}`);
142
+ constructor(pluginKey, reason) {
143
+ super(`Failed to load plugin ${pluginKey}: ${reason}`);
144
144
  this.name = "PluginLoadError";
145
145
  }
146
146
  };
@@ -150,41 +150,41 @@ var PluginLoaderService = class _PluginLoaderService {
150
150
  }
151
151
  logger = new import_common2.Logger(_PluginLoaderService.name);
152
152
  pluginInstances = /* @__PURE__ */ new Map();
153
- async loadPlugin(pluginID) {
154
- const cached = this.pluginInstances.get(pluginID);
153
+ async loadPlugin(pluginKey) {
154
+ const cached = this.pluginInstances.get(pluginKey);
155
155
  if (cached) {
156
- this.logger.debug(`Using cached plugin instance: ${pluginID}`);
156
+ this.logger.debug(`Using cached plugin instance: ${pluginKey}`);
157
157
  return cached;
158
158
  }
159
- this.logger.log(`Loading plugin: ${pluginID}`);
159
+ this.logger.log(`Loading plugin: ${pluginKey}`);
160
160
  try {
161
- const pluginPackage = (await import(pluginID)).default;
161
+ const pluginPackage = (await import(pluginKey)).default;
162
162
  if (typeof pluginPackage.create !== "function") {
163
- throw new PluginLoadError(pluginID, "Plugin does not export create() function");
163
+ throw new PluginLoadError(pluginKey, "Plugin does not export create() function");
164
164
  }
165
165
  const instance = pluginPackage.create();
166
- this.pluginInstances.set(pluginID, instance);
167
- this.logger.log(`Plugin loaded successfully: ${pluginID}`);
166
+ this.pluginInstances.set(pluginKey, instance);
167
+ this.logger.log(`Plugin loaded successfully: ${pluginKey}`);
168
168
  return instance;
169
169
  } catch (error) {
170
170
  if (error.code === "MODULE_NOT_FOUND") {
171
- throw new PluginNotFoundError(pluginID);
171
+ throw new PluginNotFoundError(pluginKey);
172
172
  }
173
- throw new PluginLoadError(pluginID, error instanceof Error ? error.message : String(error));
173
+ throw new PluginLoadError(pluginKey, error instanceof Error ? error.message : String(error));
174
174
  }
175
175
  }
176
- isPluginInstalled(pluginID) {
176
+ isPluginInstalled(pluginKey) {
177
177
  try {
178
- require.resolve(pluginID);
178
+ require.resolve(pluginKey);
179
179
  return true;
180
180
  } catch {
181
181
  return false;
182
182
  }
183
183
  }
184
- clearCache(pluginID) {
185
- if (pluginID) {
186
- this.pluginInstances.delete(pluginID);
187
- this.logger.log(`Cleared cache for plugin: ${pluginID}`);
184
+ clearCache(pluginKey) {
185
+ if (pluginKey) {
186
+ this.pluginInstances.delete(pluginKey);
187
+ this.logger.log(`Cleared cache for plugin: ${pluginKey}`);
188
188
  } else {
189
189
  this.pluginInstances.clear();
190
190
  this.logger.log("Cleared all plugin caches");
@@ -230,8 +230,8 @@ var ActionNotFoundError = class extends Error {
230
230
  static {
231
231
  __name(this, "ActionNotFoundError");
232
232
  }
233
- constructor(pluginID, actionName) {
234
- super(`Action '${actionName}' not found in plugin ${pluginID}`);
233
+ constructor(pluginKey, actionName) {
234
+ super(`Action '${actionName}' not found in plugin ${pluginKey}`);
235
235
  this.name = "ActionNotFoundError";
236
236
  }
237
237
  };
@@ -320,9 +320,9 @@ var CapabilityService = class _CapabilityService {
320
320
  * 检查 action 是否为流式
321
321
  */
322
322
  async checkIsStream(config, actionName) {
323
- const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginID);
323
+ const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginKey);
324
324
  if (!pluginInstance.hasAction(actionName)) {
325
- throw new ActionNotFoundError(config.pluginID, actionName);
325
+ throw new ActionNotFoundError(config.pluginKey, actionName);
326
326
  }
327
327
  return pluginInstance.isStreamAction?.(actionName) ?? false;
328
328
  }
@@ -334,9 +334,9 @@ var CapabilityService = class _CapabilityService {
334
334
  async executeCall(config, actionName, input, contextOverride) {
335
335
  const startTime = Date.now();
336
336
  try {
337
- const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginID);
337
+ const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginKey);
338
338
  if (!pluginInstance.hasAction(actionName)) {
339
- throw new ActionNotFoundError(config.pluginID, actionName);
339
+ throw new ActionNotFoundError(config.pluginKey, actionName);
340
340
  }
341
341
  const resolvedParams = this.templateEngineService.resolve(config.formValue, input);
342
342
  const context = this.buildActionContext(contextOverride);
@@ -345,7 +345,7 @@ var CapabilityService = class _CapabilityService {
345
345
  message: "Executing capability",
346
346
  capabilityId: config.id,
347
347
  action: actionName,
348
- pluginID: config.pluginID,
348
+ pluginKey: config.pluginKey,
349
349
  isStream
350
350
  });
351
351
  let result;
@@ -384,9 +384,9 @@ var CapabilityService = class _CapabilityService {
384
384
  async *executeCallStream(config, actionName, input, contextOverride) {
385
385
  const startTime = Date.now();
386
386
  try {
387
- const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginID);
387
+ const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginKey);
388
388
  if (!pluginInstance.hasAction(actionName)) {
389
- throw new ActionNotFoundError(config.pluginID, actionName);
389
+ throw new ActionNotFoundError(config.pluginKey, actionName);
390
390
  }
391
391
  const resolvedParams = this.templateEngineService.resolve(config.formValue, input);
392
392
  const context = this.buildActionContext(contextOverride);
@@ -395,7 +395,7 @@ var CapabilityService = class _CapabilityService {
395
395
  message: "Executing capability (stream)",
396
396
  capabilityId: config.id,
397
397
  action: actionName,
398
- pluginID: config.pluginID,
398
+ pluginKey: config.pluginKey,
399
399
  isStream
400
400
  });
401
401
  if (isStream && pluginInstance.runStream) {
@@ -487,7 +487,7 @@ var DebugController = class {
487
487
  data: capabilities.map((c) => ({
488
488
  id: c.id,
489
489
  name: c.name,
490
- pluginID: c.pluginID,
490
+ pluginKey: c.pluginKey,
491
491
  pluginVersion: c.pluginVersion
492
492
  }))
493
493
  };
@@ -514,16 +514,16 @@ var DebugController = class {
514
514
  * 获取 action 名称
515
515
  * 优先使用传入的 action,否则使用插件第一个 action
516
516
  */
517
- async getActionName(pluginID, bodyAction) {
517
+ async getActionName(pluginKey, bodyAction) {
518
518
  if (bodyAction) {
519
519
  return bodyAction;
520
520
  }
521
- const pluginInstance = await this.pluginLoaderService.loadPlugin(pluginID);
521
+ const pluginInstance = await this.pluginLoaderService.loadPlugin(pluginKey);
522
522
  const actions = pluginInstance.listActions();
523
523
  if (actions.length === 0) {
524
524
  throw new import_common4.HttpException({
525
525
  code: 1,
526
- message: `Plugin ${pluginID} has no actions`,
526
+ message: `Plugin ${pluginKey} has no actions`,
527
527
  error: "NO_ACTIONS"
528
528
  }, import_common4.HttpStatus.BAD_REQUEST);
529
529
  }
@@ -533,7 +533,7 @@ var DebugController = class {
533
533
  const startTime = Date.now();
534
534
  const params = body.params ?? {};
535
535
  const config = this.getCapabilityConfig(capabilityId, body.capability);
536
- const action = await this.getActionName(config.pluginID, body.action);
536
+ const action = await this.getActionName(config.pluginKey, body.action);
537
537
  const resolvedParams = this.templateEngineService.resolve(config.formValue, params);
538
538
  try {
539
539
  const result = await this.capabilityService.loadWithConfig(config).call(action, params);
@@ -545,7 +545,7 @@ var DebugController = class {
545
545
  capabilityConfig: config,
546
546
  resolvedParams,
547
547
  duration: Date.now() - startTime,
548
- pluginID: config.pluginID,
548
+ pluginKey: config.pluginKey,
549
549
  action
550
550
  }
551
551
  };
@@ -568,7 +568,7 @@ var DebugController = class {
568
568
  error: "PLUGIN_NOT_FOUND",
569
569
  debug: {
570
570
  duration,
571
- pluginID: config.pluginID,
571
+ pluginKey: config.pluginKey,
572
572
  action
573
573
  }
574
574
  }, import_common4.HttpStatus.INTERNAL_SERVER_ERROR);
@@ -580,7 +580,7 @@ var DebugController = class {
580
580
  error: "ACTION_NOT_FOUND",
581
581
  debug: {
582
582
  duration,
583
- pluginID: config.pluginID,
583
+ pluginKey: config.pluginKey,
584
584
  action
585
585
  }
586
586
  }, import_common4.HttpStatus.BAD_REQUEST);
@@ -591,7 +591,7 @@ var DebugController = class {
591
591
  error: "EXECUTION_ERROR",
592
592
  debug: {
593
593
  duration,
594
- pluginID: config.pluginID,
594
+ pluginKey: config.pluginKey,
595
595
  action,
596
596
  resolvedParams
597
597
  }
@@ -605,7 +605,7 @@ var DebugController = class {
605
605
  res.setHeader("Connection", "keep-alive");
606
606
  try {
607
607
  const config = this.getCapabilityConfig(capabilityId, body.capability);
608
- const action = await this.getActionName(config.pluginID, body.action);
608
+ const action = await this.getActionName(config.pluginKey, body.action);
609
609
  const capability = this.capabilityService.loadWithConfig(config);
610
610
  const stream = capability.callStream(action, params);
611
611
  for await (const chunk of stream) {
@@ -714,7 +714,7 @@ var WebhookController = class {
714
714
  id: c.id,
715
715
  name: c.name,
716
716
  description: c.description,
717
- pluginID: c.pluginID,
717
+ pluginKey: c.pluginKey,
718
718
  pluginVersion: c.pluginVersion
719
719
  }))
720
720
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/services/template-engine.service.ts","../src/services/plugin-loader.service.ts","../src/services/capability.service.ts","../src/controllers/debug.controller.ts","../src/controllers/webhook.controller.ts","../src/capability.module.ts"],"sourcesContent":["export * from './interfaces';\nexport * from './services';\nexport * from './controllers';\nexport * from './capability.module';\n","import { Injectable } from '@nestjs/common';\n\n/**\n * 模板引擎服务\n *\n * 支持语法:\n * - expr: '{{' + selector + '}}'\n * - selector: 'input.' + ident | selector.ident\n * - ident: [a-zA-Z_]([a-zA-Z_0-9])*\n *\n * 示例:\n * - {{input.a}}\n * - {{input.a.b}}\n * - \"this is {{input.a.b}}\"\n *\n * 求值规则:\n * - 如果整个字符串是单个表达式,保留原始类型\n * - 如果是字符串插值(多个表达式或混合内容),返回字符串\n * - 如果变量不存在,返回原始表达式\n */\n@Injectable()\nexport class TemplateEngineService {\n // 匹配 {{input.xxx}} 或 {{input.xxx.yyy}} 表达式\n private readonly EXPR_REGEX = /\\{\\{input\\.([a-zA-Z_][a-zA-Z_0-9]*(?:\\.[a-zA-Z_][a-zA-Z_0-9]*)*)\\}\\}/g;\n // 匹配整串单个表达式\n private readonly WHOLE_STRING_EXPR_REGEX = /^\\{\\{input\\.([a-zA-Z_][a-zA-Z_0-9]*(?:\\.[a-zA-Z_][a-zA-Z_0-9]*)*)\\}\\}$/;\n\n resolve(template: unknown, input: Record<string, unknown>): unknown {\n if (typeof template === 'string') {\n return this.resolveString(template, input);\n }\n\n if (Array.isArray(template)) {\n return template.map(item => this.resolve(item, input));\n }\n\n if (template !== null && typeof template === 'object') {\n return this.resolveObject(template as Record<string, unknown>, input);\n }\n\n return template;\n }\n\n private resolveString(template: string, input: Record<string, unknown>): unknown {\n // 情况1: 整串是单个表达式 → 保留原始类型\n const wholeMatch = template.match(this.WHOLE_STRING_EXPR_REGEX);\n if (wholeMatch) {\n const path = wholeMatch[1];\n const value = this.getValueByPath(input, path);\n // 变量不存在,返回原始表达式\n return value !== undefined ? value : template;\n }\n\n // 情况2: 字符串插值 → 返回字符串\n // 重置正则的 lastIndex(因为使用了 g 标志)\n this.EXPR_REGEX.lastIndex = 0;\n\n // 检查是否有任何表达式\n if (!this.EXPR_REGEX.test(template)) {\n return template;\n }\n\n // 重置并进行替换\n this.EXPR_REGEX.lastIndex = 0;\n const result = template.replace(this.EXPR_REGEX, (match, path) => {\n const value = this.getValueByPath(input, path);\n // 变量不存在,保留原始表达式\n if (value === undefined) {\n return match;\n }\n return String(value);\n });\n\n return result;\n }\n\n private resolveObject(\n template: Record<string, unknown>,\n input: Record<string, unknown>,\n ): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(template)) {\n result[key] = this.resolve(value, input);\n }\n\n return result;\n }\n\n private getValueByPath(obj: Record<string, unknown>, path: string): unknown {\n const keys = path.split('.');\n let current: unknown = obj;\n\n for (const key of keys) {\n if (current === null || current === undefined) {\n return undefined;\n }\n current = (current as Record<string, unknown>)[key];\n }\n\n return current;\n }\n}\n","import { Injectable, Logger } from '@nestjs/common';\nimport type { PluginInstance, PluginPackage } from '../interfaces';\n\nexport class PluginNotFoundError extends Error {\n constructor(pluginID: string) {\n super(`Plugin not found: ${pluginID}`);\n this.name = 'PluginNotFoundError';\n }\n}\n\nexport class PluginLoadError extends Error {\n constructor(pluginID: string, reason: string) {\n super(`Failed to load plugin ${pluginID}: ${reason}`);\n this.name = 'PluginLoadError';\n }\n}\n\n@Injectable()\nexport class PluginLoaderService {\n private readonly logger = new Logger(PluginLoaderService.name);\n private readonly pluginInstances = new Map<string, PluginInstance>();\n\n async loadPlugin(pluginID: string): Promise<PluginInstance> {\n const cached = this.pluginInstances.get(pluginID);\n if (cached) {\n this.logger.debug(`Using cached plugin instance: ${pluginID}`);\n return cached;\n }\n\n this.logger.log(`Loading plugin: ${pluginID}`);\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const pluginPackage = (await import(pluginID)).default as PluginPackage;\n\n if (typeof pluginPackage.create !== 'function') {\n throw new PluginLoadError(pluginID, 'Plugin does not export create() function');\n }\n\n const instance = pluginPackage.create();\n this.pluginInstances.set(pluginID, instance);\n\n this.logger.log(`Plugin loaded successfully: ${pluginID}`);\n return instance;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'MODULE_NOT_FOUND') {\n throw new PluginNotFoundError(pluginID);\n }\n throw new PluginLoadError(\n pluginID,\n error instanceof Error ? error.message : String(error),\n );\n }\n }\n\n isPluginInstalled(pluginID: string): boolean {\n try {\n require.resolve(pluginID);\n return true;\n } catch {\n return false;\n }\n }\n\n clearCache(pluginID?: string): void {\n if (pluginID) {\n this.pluginInstances.delete(pluginID);\n this.logger.log(`Cleared cache for plugin: ${pluginID}`);\n } else {\n this.pluginInstances.clear();\n this.logger.log('Cleared all plugin caches');\n }\n }\n}\n","import { Injectable, Logger, Inject, OnModuleInit } from '@nestjs/common';\nimport {\n RequestContextService,\n PLATFORM_HTTP_CLIENT,\n type PlatformHttpClient,\n} from '@lark-apaas/nestjs-common';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { CapabilityConfig, PluginActionContext, UserContext } from '../interfaces';\nimport { PluginLoaderService } from './plugin-loader.service';\nimport { TemplateEngineService } from './template-engine.service';\n\nexport class CapabilityNotFoundError extends Error {\n constructor(capabilityId: string) {\n super(`Capability not found: ${capabilityId}`);\n this.name = 'CapabilityNotFoundError';\n }\n}\n\nexport class ActionNotFoundError extends Error {\n constructor(pluginID: string, actionName: string) {\n super(`Action '${actionName}' not found in plugin ${pluginID}`);\n this.name = 'ActionNotFoundError';\n }\n}\n\nexport interface CapabilityExecutor {\n /**\n * 调用 capability(始终返回 Promise)\n * - unary action: 直接返回结果\n * - stream action: 内部聚合所有 chunk 后返回\n */\n call(actionName: string, input: unknown, context?: Partial<PluginActionContext>): Promise<unknown>;\n\n /**\n * 流式调用 capability\n * - 返回原始 AsyncIterable\n * - 如果 action 是 unary,包装为单次 yield\n */\n callStream(actionName: string, input: unknown, context?: Partial<PluginActionContext>): AsyncIterable<unknown>;\n\n /**\n * 检查 action 是否为流式\n */\n isStream(actionName: string): Promise<boolean>;\n}\n\nexport interface CapabilityModuleOptions {\n capabilitiesDir?: string;\n}\n\n@Injectable()\nexport class CapabilityService implements OnModuleInit {\n private readonly logger = new Logger(CapabilityService.name);\n private readonly capabilities = new Map<string, CapabilityConfig>();\n private capabilitiesDir: string;\n\n constructor(\n private readonly requestContextService: RequestContextService,\n @Inject(PLATFORM_HTTP_CLIENT) private readonly httpClient: PlatformHttpClient,\n private readonly pluginLoaderService: PluginLoaderService,\n private readonly templateEngineService: TemplateEngineService,\n ) {\n this.capabilitiesDir = path.join(process.cwd(), 'server/capabilities');\n }\n\n setCapabilitiesDir(dir: string): void {\n this.capabilitiesDir = dir;\n }\n\n async onModuleInit(): Promise<void> {\n await this.loadCapabilities();\n }\n\n private async loadCapabilities(): Promise<void> {\n this.logger.log(`Loading capabilities from ${this.capabilitiesDir}`);\n\n if (!fs.existsSync(this.capabilitiesDir)) {\n this.logger.warn(`Capabilities directory not found: ${this.capabilitiesDir}`);\n return;\n }\n\n const files = fs.readdirSync(this.capabilitiesDir).filter(f => f.endsWith('.json'));\n\n for (const file of files) {\n try {\n const filePath = path.join(this.capabilitiesDir, file);\n const content = fs.readFileSync(filePath, 'utf-8');\n const config = JSON.parse(content) as CapabilityConfig;\n\n if (!config.id) {\n this.logger.warn(`Skipping capability without id: ${file}`);\n continue;\n }\n\n this.capabilities.set(config.id, config);\n this.logger.log(`Loaded capability: ${config.id} (${config.name})`);\n } catch (error) {\n this.logger.error(`Failed to load capability from ${file}:`, error);\n }\n }\n\n this.logger.log(`Loaded ${this.capabilities.size} capabilities`);\n }\n\n listCapabilities(): CapabilityConfig[] {\n return Array.from(this.capabilities.values());\n }\n\n getCapability(capabilityId: string): CapabilityConfig | null {\n return this.capabilities.get(capabilityId) ?? null;\n }\n\n load(capabilityId: string): CapabilityExecutor {\n const config = this.capabilities.get(capabilityId);\n if (!config) {\n throw new CapabilityNotFoundError(capabilityId);\n }\n\n return this.createExecutor(config);\n }\n\n /**\n * 使用传入的配置加载能力执行器\n * 用于 debug 场景,支持用户传入自定义配置\n */\n loadWithConfig(config: CapabilityConfig): CapabilityExecutor {\n return this.createExecutor(config);\n }\n\n private createExecutor(config: CapabilityConfig): CapabilityExecutor {\n return {\n call: async (\n actionName: string,\n input: unknown,\n contextOverride?: Partial<PluginActionContext>,\n ) => {\n return this.executeCall(config, actionName, input, contextOverride);\n },\n\n callStream: (\n actionName: string,\n input: unknown,\n contextOverride?: Partial<PluginActionContext>,\n ) => {\n return this.executeCallStream(config, actionName, input, contextOverride);\n },\n\n isStream: async (actionName: string) => {\n return this.checkIsStream(config, actionName);\n },\n };\n }\n\n /**\n * 检查 action 是否为流式\n */\n private async checkIsStream(config: CapabilityConfig, actionName: string): Promise<boolean> {\n const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginID);\n\n if (!pluginInstance.hasAction(actionName)) {\n throw new ActionNotFoundError(config.pluginID, actionName);\n }\n\n return pluginInstance.isStreamAction?.(actionName) ?? false;\n }\n\n /**\n * 执行 capability(始终返回 Promise)\n * - unary action: 直接返回结果\n * - stream action: 内部聚合所有 chunk 后返回\n */\n private async executeCall(\n config: CapabilityConfig,\n actionName: string,\n input: unknown,\n contextOverride?: Partial<PluginActionContext>,\n ): Promise<unknown> {\n const startTime = Date.now();\n\n try {\n const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginID);\n\n if (!pluginInstance.hasAction(actionName)) {\n throw new ActionNotFoundError(config.pluginID, actionName);\n }\n\n const resolvedParams = this.templateEngineService.resolve(\n config.formValue,\n input as Record<string, unknown>,\n );\n\n const context = this.buildActionContext(contextOverride);\n const isStream = pluginInstance.isStreamAction?.(actionName) ?? false;\n\n this.logger.log({\n message: 'Executing capability',\n capabilityId: config.id,\n action: actionName,\n pluginID: config.pluginID,\n isStream,\n });\n\n let result: unknown;\n\n if (isStream && pluginInstance.runStream) {\n // 流式 action:聚合所有 chunk\n const chunks: unknown[] = [];\n for await (const chunk of pluginInstance.runStream(actionName, context, resolvedParams)) {\n chunks.push(chunk);\n }\n // 使用插件的聚合方法,或默认返回 chunks 数组\n result = pluginInstance.aggregate\n ? pluginInstance.aggregate(actionName, chunks)\n : chunks;\n } else {\n // 非流式 action:直接调用\n result = await pluginInstance.run(actionName, context, resolvedParams);\n }\n\n this.logger.log({\n message: 'Capability executed successfully',\n capabilityId: config.id,\n action: actionName,\n duration: Date.now() - startTime,\n });\n\n return result;\n } catch (error) {\n this.logger.error({\n message: 'Capability execution failed',\n capabilityId: config.id,\n action: actionName,\n error: error instanceof Error ? error.message : String(error),\n duration: Date.now() - startTime,\n });\n throw error;\n }\n }\n\n /**\n * 流式执行 capability\n * - stream action: 返回原始 AsyncIterable\n * - unary action: 包装为单次 yield\n */\n private async *executeCallStream(\n config: CapabilityConfig,\n actionName: string,\n input: unknown,\n contextOverride?: Partial<PluginActionContext>,\n ): AsyncIterable<unknown> {\n const startTime = Date.now();\n\n try {\n const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginID);\n\n if (!pluginInstance.hasAction(actionName)) {\n throw new ActionNotFoundError(config.pluginID, actionName);\n }\n\n const resolvedParams = this.templateEngineService.resolve(\n config.formValue,\n input as Record<string, unknown>,\n );\n\n const context = this.buildActionContext(contextOverride);\n const isStream = pluginInstance.isStreamAction?.(actionName) ?? false;\n\n this.logger.log({\n message: 'Executing capability (stream)',\n capabilityId: config.id,\n action: actionName,\n pluginID: config.pluginID,\n isStream,\n });\n\n if (isStream && pluginInstance.runStream) {\n // 流式 action:透传 AsyncIterable\n yield* pluginInstance.runStream(actionName, context, resolvedParams);\n } else {\n // 非流式 action:包装为单次 yield\n const result = await pluginInstance.run(actionName, context, resolvedParams);\n yield result;\n }\n\n this.logger.log({\n message: 'Capability stream completed',\n capabilityId: config.id,\n action: actionName,\n duration: Date.now() - startTime,\n });\n } catch (error) {\n this.logger.error({\n message: 'Capability stream execution failed',\n capabilityId: config.id,\n action: actionName,\n error: error instanceof Error ? error.message : String(error),\n duration: Date.now() - startTime,\n });\n throw error;\n }\n }\n\n private buildActionContext(override?: Partial<PluginActionContext>): PluginActionContext {\n return {\n logger: this.logger,\n httpClient: this.httpClient,\n userContext: override?.userContext ?? this.getUserContext(),\n };\n }\n\n private getUserContext(): UserContext {\n const ctx = this.requestContextService.getContext();\n return {\n userId: ctx?.userId ?? '',\n tenantId: ctx?.tenantId ?? '',\n };\n }\n}\n","import {\n Controller,\n Post,\n Get,\n Param,\n Body,\n Res,\n HttpException,\n HttpStatus,\n} from '@nestjs/common';\nimport type { Response } from 'express';\nimport {\n CapabilityService,\n CapabilityNotFoundError,\n ActionNotFoundError,\n} from '../services/capability.service';\nimport { PluginLoaderService, PluginNotFoundError } from '../services/plugin-loader.service';\nimport { TemplateEngineService } from '../services/template-engine.service';\nimport type { CapabilityConfig } from '../interfaces';\n\ninterface DebugRequestBody {\n action?: string;\n params?: Record<string, unknown>;\n capability?: CapabilityConfig;\n}\n\ninterface DebugResponse {\n code: number;\n message: string;\n data: unknown;\n debug?: {\n capabilityConfig: unknown;\n resolvedParams: unknown;\n duration: number;\n pluginID: string;\n action: string;\n };\n}\n\ninterface ListResponse {\n code: number;\n message: string;\n data: Array<{\n id: string;\n name: string;\n pluginID: string;\n pluginVersion: string;\n }>;\n}\n\n@Controller('__innerapi__/capability')\nexport class DebugController {\n constructor(\n private readonly capabilityService: CapabilityService,\n private readonly pluginLoaderService: PluginLoaderService,\n private readonly templateEngineService: TemplateEngineService,\n ) {}\n\n @Get('list')\n list(): ListResponse {\n const capabilities = this.capabilityService.listCapabilities();\n\n return {\n code: 0,\n message: 'success',\n data: capabilities.map(c => ({\n id: c.id,\n name: c.name,\n pluginID: c.pluginID,\n pluginVersion: c.pluginVersion,\n })),\n };\n }\n\n /**\n * 获取 capability 配置\n * 优先使用 body.capability,否则从服务获取\n */\n private getCapabilityConfig(\n capabilityId: string,\n bodyCapability?: CapabilityConfig,\n ): CapabilityConfig {\n if (bodyCapability) {\n return bodyCapability;\n }\n\n const config = this.capabilityService.getCapability(capabilityId);\n if (!config) {\n throw new HttpException(\n {\n code: 1,\n message: `Capability not found: ${capabilityId}`,\n error: 'CAPABILITY_NOT_FOUND',\n },\n HttpStatus.NOT_FOUND,\n );\n }\n\n return config;\n }\n\n /**\n * 获取 action 名称\n * 优先使用传入的 action,否则使用插件第一个 action\n */\n private async getActionName(pluginID: string, bodyAction?: string): Promise<string> {\n if (bodyAction) {\n return bodyAction;\n }\n\n const pluginInstance = await this.pluginLoaderService.loadPlugin(pluginID);\n const actions = pluginInstance.listActions();\n\n if (actions.length === 0) {\n throw new HttpException(\n {\n code: 1,\n message: `Plugin ${pluginID} has no actions`,\n error: 'NO_ACTIONS',\n },\n HttpStatus.BAD_REQUEST,\n );\n }\n\n return actions[0];\n }\n\n @Post('debug/:capability_id')\n async debug(\n @Param('capability_id') capabilityId: string,\n @Body() body: DebugRequestBody,\n ): Promise<DebugResponse> {\n const startTime = Date.now();\n const params = body.params ?? {};\n\n const config = this.getCapabilityConfig(capabilityId, body.capability);\n const action = await this.getActionName(config.pluginID, body.action);\n\n const resolvedParams = this.templateEngineService.resolve(\n config.formValue,\n params,\n );\n\n try {\n const result = await this.capabilityService\n .loadWithConfig(config)\n .call(action, params);\n\n return {\n code: 0,\n message: 'success',\n data: result,\n debug: {\n capabilityConfig: config,\n resolvedParams,\n duration: Date.now() - startTime,\n pluginID: config.pluginID,\n action,\n },\n };\n } catch (error) {\n const duration = Date.now() - startTime;\n\n if (error instanceof CapabilityNotFoundError) {\n throw new HttpException(\n {\n code: 1,\n message: error.message,\n error: 'CAPABILITY_NOT_FOUND',\n debug: { duration },\n },\n HttpStatus.NOT_FOUND,\n );\n }\n\n if (error instanceof PluginNotFoundError) {\n throw new HttpException(\n {\n code: 1,\n message: error.message,\n error: 'PLUGIN_NOT_FOUND',\n debug: { duration, pluginID: config.pluginID, action },\n },\n HttpStatus.INTERNAL_SERVER_ERROR,\n );\n }\n\n if (error instanceof ActionNotFoundError) {\n throw new HttpException(\n {\n code: 1,\n message: error.message,\n error: 'ACTION_NOT_FOUND',\n debug: { duration, pluginID: config.pluginID, action },\n },\n HttpStatus.BAD_REQUEST,\n );\n }\n\n throw new HttpException(\n {\n code: 1,\n message: error instanceof Error ? error.message : String(error),\n error: 'EXECUTION_ERROR',\n debug: {\n duration,\n pluginID: config.pluginID,\n action,\n resolvedParams,\n },\n },\n HttpStatus.INTERNAL_SERVER_ERROR,\n );\n }\n }\n\n @Post('debug/:capability_id/stream')\n async debugStream(\n @Param('capability_id') capabilityId: string,\n @Body() body: DebugRequestBody,\n @Res() res: Response,\n ): Promise<void> {\n const params = body.params ?? {};\n\n // 设置 SSE 响应头\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n\n try {\n const config = this.getCapabilityConfig(capabilityId, body.capability);\n const action = await this.getActionName(config.pluginID, body.action);\n\n const capability = this.capabilityService.loadWithConfig(config);\n const stream = capability.callStream(action, params);\n\n for await (const chunk of stream) {\n res.write(`data: ${JSON.stringify(chunk)}\\n\\n`);\n }\n\n // 发送结束标记\n res.write('data: [DONE]\\n\\n');\n } catch (error) {\n // 错误时发送错误信息\n const message = error instanceof Error ? error.message : String(error);\n let errorCode = 'EXECUTION_ERROR';\n\n if (error instanceof CapabilityNotFoundError) {\n errorCode = 'CAPABILITY_NOT_FOUND';\n } else if (error instanceof PluginNotFoundError) {\n errorCode = 'PLUGIN_NOT_FOUND';\n } else if (error instanceof ActionNotFoundError) {\n errorCode = 'ACTION_NOT_FOUND';\n } else if (error instanceof HttpException) {\n const response = error.getResponse() as { error?: string };\n errorCode = response.error ?? 'EXECUTION_ERROR';\n }\n\n res.write(`data: ${JSON.stringify({ error: message, code: errorCode })}\\n\\n`);\n } finally {\n res.end();\n }\n }\n}\n","import {\n Controller,\n Get,\n Post,\n Param,\n Body,\n Res,\n HttpException,\n HttpStatus,\n} from '@nestjs/common';\nimport type { Response } from 'express';\nimport {\n CapabilityService,\n CapabilityNotFoundError,\n ActionNotFoundError,\n} from '../services/capability.service';\nimport { PluginNotFoundError } from '../services/plugin-loader.service';\n\ninterface ExecuteRequestBody {\n action: string;\n params: Record<string, unknown>;\n}\n\ninterface ExecuteResponse {\n code: number;\n message: string;\n data: unknown;\n}\n\ninterface CapabilityInfo {\n id: string;\n name: string;\n description: string;\n pluginID: string;\n pluginVersion: string;\n}\n\ninterface ListResponse {\n code: number;\n message: string;\n data: CapabilityInfo[];\n}\n\n@Controller('api/capability')\nexport class WebhookController {\n constructor(private readonly capabilityService: CapabilityService) {}\n\n @Get('list')\n list(): ListResponse {\n const capabilities = this.capabilityService.listCapabilities();\n return {\n code: 0,\n message: 'success',\n data: capabilities.map(c => ({\n id: c.id,\n name: c.name,\n description: c.description,\n pluginID: c.pluginID,\n pluginVersion: c.pluginVersion,\n })),\n };\n }\n\n @Post(':capability_id')\n async execute(\n @Param('capability_id') capabilityId: string,\n @Body() body: ExecuteRequestBody,\n ): Promise<ExecuteResponse> {\n try {\n const result = await this.capabilityService\n .load(capabilityId)\n .call(body.action, body.params);\n\n return {\n code: 0,\n message: 'success',\n data: result,\n };\n } catch (error) {\n if (error instanceof CapabilityNotFoundError) {\n throw new HttpException(\n {\n code: 1,\n message: error.message,\n error: 'CAPABILITY_NOT_FOUND',\n },\n HttpStatus.NOT_FOUND,\n );\n }\n\n if (error instanceof PluginNotFoundError) {\n throw new HttpException(\n {\n code: 1,\n message: error.message,\n error: 'PLUGIN_NOT_FOUND',\n },\n HttpStatus.INTERNAL_SERVER_ERROR,\n );\n }\n\n if (error instanceof ActionNotFoundError) {\n throw new HttpException(\n {\n code: 1,\n message: error.message,\n error: 'ACTION_NOT_FOUND',\n },\n HttpStatus.BAD_REQUEST,\n );\n }\n\n throw new HttpException(\n {\n code: 1,\n message: error instanceof Error ? error.message : String(error),\n error: 'EXECUTION_ERROR',\n },\n HttpStatus.INTERNAL_SERVER_ERROR,\n );\n }\n }\n\n @Post(':capability_id/stream')\n async executeStream(\n @Param('capability_id') capabilityId: string,\n @Body() body: ExecuteRequestBody,\n @Res() res: Response,\n ): Promise<void> {\n // 设置 SSE 响应头\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n\n try {\n const capability = this.capabilityService.load(capabilityId);\n const stream = capability.callStream(body.action, body.params);\n\n for await (const chunk of stream) {\n res.write(`data: ${JSON.stringify(chunk)}\\n\\n`);\n }\n\n // 发送结束标记\n res.write('data: [DONE]\\n\\n');\n } catch (error) {\n // 错误时发送错误信息\n const message = error instanceof Error ? error.message : String(error);\n let errorCode = 'EXECUTION_ERROR';\n\n if (error instanceof CapabilityNotFoundError) {\n errorCode = 'CAPABILITY_NOT_FOUND';\n } else if (error instanceof PluginNotFoundError) {\n errorCode = 'PLUGIN_NOT_FOUND';\n } else if (error instanceof ActionNotFoundError) {\n errorCode = 'ACTION_NOT_FOUND';\n }\n\n res.write(`data: ${JSON.stringify({ error: message, code: errorCode })}\\n\\n`);\n } finally {\n res.end();\n }\n }\n}\n","import { Module, DynamicModule, Type } from '@nestjs/common';\nimport {\n RequestContextService,\n PLATFORM_HTTP_CLIENT,\n} from '@lark-apaas/nestjs-common';\nimport { DebugController, WebhookController } from './controllers';\nimport {\n CapabilityService,\n PluginLoaderService,\n TemplateEngineService,\n type CapabilityModuleOptions,\n} from './services';\n\nconst CAPABILITY_OPTIONS = Symbol('CAPABILITY_OPTIONS');\n\nconst isDevelopment = process.env.NODE_ENV === 'development';\n\nfunction getControllers(): Type[] {\n const controllers: Type[] = [WebhookController];\n if (isDevelopment) {\n controllers.push(DebugController);\n }\n return controllers;\n}\n\n@Module({\n controllers: getControllers(),\n providers: [CapabilityService, PluginLoaderService, TemplateEngineService],\n exports: [CapabilityService],\n})\nexport class CapabilityModule {\n static forRoot(options?: CapabilityModuleOptions): DynamicModule {\n return {\n module: CapabilityModule,\n controllers: getControllers(),\n providers: [\n {\n provide: CAPABILITY_OPTIONS,\n useValue: options ?? {},\n },\n {\n provide: CapabilityService,\n useFactory: (\n requestContextService: RequestContextService,\n httpClient: any,\n pluginLoader: PluginLoaderService,\n templateEngine: TemplateEngineService,\n moduleOptions: CapabilityModuleOptions,\n ) => {\n const service = new CapabilityService(\n requestContextService,\n httpClient,\n pluginLoader,\n templateEngine,\n );\n if (moduleOptions?.capabilitiesDir) {\n service.setCapabilitiesDir(moduleOptions.capabilitiesDir);\n }\n return service;\n },\n inject: [\n RequestContextService,\n PLATFORM_HTTP_CLIENT,\n PluginLoaderService,\n TemplateEngineService,\n CAPABILITY_OPTIONS,\n ],\n },\n PluginLoaderService,\n TemplateEngineService,\n ],\n exports: [CapabilityService],\n };\n }\n}\n"],"mappings":"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","names":["TemplateEngineService","EXPR_REGEX","WHOLE_STRING_EXPR_REGEX","resolve","template","input","resolveString","Array","isArray","map","item","resolveObject","wholeMatch","match","path","value","getValueByPath","undefined","lastIndex","test","result","replace","String","key","Object","entries","obj","keys","split","current","import_common","PluginNotFoundError","Error","pluginID","name","PluginLoadError","reason","PluginLoaderService","logger","Logger","pluginInstances","Map","loadPlugin","cached","get","debug","log","pluginPackage","default","create","instance","set","error","code","message","String","isPluginInstalled","require","resolve","clearCache","delete","clear","import_common","CapabilityNotFoundError","Error","capabilityId","name","ActionNotFoundError","pluginID","actionName","CapabilityService","logger","Logger","capabilities","Map","capabilitiesDir","requestContextService","httpClient","pluginLoaderService","templateEngineService","join","process","cwd","setCapabilitiesDir","dir","onModuleInit","loadCapabilities","log","existsSync","warn","files","readdirSync","filter","f","endsWith","file","filePath","content","readFileSync","config","JSON","parse","id","set","error","size","listCapabilities","Array","from","values","getCapability","get","load","createExecutor","loadWithConfig","call","input","contextOverride","executeCall","callStream","executeCallStream","isStream","checkIsStream","pluginInstance","loadPlugin","hasAction","isStreamAction","startTime","Date","now","resolvedParams","resolve","formValue","context","buildActionContext","message","action","result","runStream","chunks","chunk","push","aggregate","run","duration","String","override","userContext","getUserContext","ctx","getContext","userId","tenantId","import_common","DebugController","capabilityService","pluginLoaderService","templateEngineService","list","capabilities","listCapabilities","code","message","data","map","c","id","name","pluginID","pluginVersion","getCapabilityConfig","capabilityId","bodyCapability","config","getCapability","HttpException","error","HttpStatus","NOT_FOUND","getActionName","bodyAction","pluginInstance","loadPlugin","actions","listActions","length","BAD_REQUEST","debug","body","startTime","Date","now","params","capability","action","resolvedParams","resolve","formValue","result","loadWithConfig","call","capabilityConfig","duration","CapabilityNotFoundError","PluginNotFoundError","INTERNAL_SERVER_ERROR","ActionNotFoundError","Error","String","debugStream","res","setHeader","stream","callStream","chunk","write","JSON","stringify","errorCode","response","getResponse","end","import_common","WebhookController","capabilityService","list","capabilities","listCapabilities","code","message","data","map","c","id","name","description","pluginID","pluginVersion","execute","capabilityId","body","result","load","call","action","params","error","CapabilityNotFoundError","HttpException","HttpStatus","NOT_FOUND","PluginNotFoundError","INTERNAL_SERVER_ERROR","ActionNotFoundError","BAD_REQUEST","Error","String","executeStream","res","setHeader","capability","stream","callStream","chunk","write","JSON","stringify","errorCode","end","import_common","import_nestjs_common","CAPABILITY_OPTIONS","Symbol","isDevelopment","process","env","NODE_ENV","getControllers","controllers","WebhookController","push","DebugController","CapabilityModule","forRoot","options","module","providers","provide","useValue","CapabilityService","useFactory","requestContextService","httpClient","pluginLoader","templateEngine","moduleOptions","service","capabilitiesDir","setCapabilitiesDir","inject","RequestContextService","PLATFORM_HTTP_CLIENT","PluginLoaderService","TemplateEngineService","exports"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/services/template-engine.service.ts","../src/services/plugin-loader.service.ts","../src/services/capability.service.ts","../src/controllers/debug.controller.ts","../src/controllers/webhook.controller.ts","../src/capability.module.ts"],"sourcesContent":["export * from './interfaces';\nexport * from './services';\nexport * from './controllers';\nexport * from './capability.module';\n","import { Injectable } from '@nestjs/common';\n\n/**\n * 模板引擎服务\n *\n * 支持语法:\n * - expr: '{{' + selector + '}}'\n * - selector: 'input.' + ident | selector.ident\n * - ident: [a-zA-Z_]([a-zA-Z_0-9])*\n *\n * 示例:\n * - {{input.a}}\n * - {{input.a.b}}\n * - \"this is {{input.a.b}}\"\n *\n * 求值规则:\n * - 如果整个字符串是单个表达式,保留原始类型\n * - 如果是字符串插值(多个表达式或混合内容),返回字符串\n * - 如果变量不存在,返回原始表达式\n */\n@Injectable()\nexport class TemplateEngineService {\n // 匹配 {{input.xxx}} 或 {{input.xxx.yyy}} 表达式\n private readonly EXPR_REGEX = /\\{\\{input\\.([a-zA-Z_][a-zA-Z_0-9]*(?:\\.[a-zA-Z_][a-zA-Z_0-9]*)*)\\}\\}/g;\n // 匹配整串单个表达式\n private readonly WHOLE_STRING_EXPR_REGEX = /^\\{\\{input\\.([a-zA-Z_][a-zA-Z_0-9]*(?:\\.[a-zA-Z_][a-zA-Z_0-9]*)*)\\}\\}$/;\n\n resolve(template: unknown, input: Record<string, unknown>): unknown {\n if (typeof template === 'string') {\n return this.resolveString(template, input);\n }\n\n if (Array.isArray(template)) {\n return template.map(item => this.resolve(item, input));\n }\n\n if (template !== null && typeof template === 'object') {\n return this.resolveObject(template as Record<string, unknown>, input);\n }\n\n return template;\n }\n\n private resolveString(template: string, input: Record<string, unknown>): unknown {\n // 情况1: 整串是单个表达式 → 保留原始类型\n const wholeMatch = template.match(this.WHOLE_STRING_EXPR_REGEX);\n if (wholeMatch) {\n const path = wholeMatch[1];\n const value = this.getValueByPath(input, path);\n // 变量不存在,返回原始表达式\n return value !== undefined ? value : template;\n }\n\n // 情况2: 字符串插值 → 返回字符串\n // 重置正则的 lastIndex(因为使用了 g 标志)\n this.EXPR_REGEX.lastIndex = 0;\n\n // 检查是否有任何表达式\n if (!this.EXPR_REGEX.test(template)) {\n return template;\n }\n\n // 重置并进行替换\n this.EXPR_REGEX.lastIndex = 0;\n const result = template.replace(this.EXPR_REGEX, (match, path) => {\n const value = this.getValueByPath(input, path);\n // 变量不存在,保留原始表达式\n if (value === undefined) {\n return match;\n }\n return String(value);\n });\n\n return result;\n }\n\n private resolveObject(\n template: Record<string, unknown>,\n input: Record<string, unknown>,\n ): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(template)) {\n result[key] = this.resolve(value, input);\n }\n\n return result;\n }\n\n private getValueByPath(obj: Record<string, unknown>, path: string): unknown {\n const keys = path.split('.');\n let current: unknown = obj;\n\n for (const key of keys) {\n if (current === null || current === undefined) {\n return undefined;\n }\n current = (current as Record<string, unknown>)[key];\n }\n\n return current;\n }\n}\n","import { Injectable, Logger } from '@nestjs/common';\nimport type { PluginInstance, PluginPackage } from '../interfaces';\n\nexport class PluginNotFoundError extends Error {\n constructor(pluginKey: string) {\n super(`Plugin not found: ${pluginKey}`);\n this.name = 'PluginNotFoundError';\n }\n}\n\nexport class PluginLoadError extends Error {\n constructor(pluginKey: string, reason: string) {\n super(`Failed to load plugin ${pluginKey}: ${reason}`);\n this.name = 'PluginLoadError';\n }\n}\n\n@Injectable()\nexport class PluginLoaderService {\n private readonly logger = new Logger(PluginLoaderService.name);\n private readonly pluginInstances = new Map<string, PluginInstance>();\n\n async loadPlugin(pluginKey: string): Promise<PluginInstance> {\n const cached = this.pluginInstances.get(pluginKey);\n if (cached) {\n this.logger.debug(`Using cached plugin instance: ${pluginKey}`);\n return cached;\n }\n\n this.logger.log(`Loading plugin: ${pluginKey}`);\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const pluginPackage = (await import(pluginKey)).default as PluginPackage;\n\n if (typeof pluginPackage.create !== 'function') {\n throw new PluginLoadError(pluginKey, 'Plugin does not export create() function');\n }\n\n const instance = pluginPackage.create();\n this.pluginInstances.set(pluginKey, instance);\n\n this.logger.log(`Plugin loaded successfully: ${pluginKey}`);\n return instance;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'MODULE_NOT_FOUND') {\n throw new PluginNotFoundError(pluginKey);\n }\n throw new PluginLoadError(\n pluginKey,\n error instanceof Error ? error.message : String(error),\n );\n }\n }\n\n isPluginInstalled(pluginKey: string): boolean {\n try {\n require.resolve(pluginKey);\n return true;\n } catch {\n return false;\n }\n }\n\n clearCache(pluginKey?: string): void {\n if (pluginKey) {\n this.pluginInstances.delete(pluginKey);\n this.logger.log(`Cleared cache for plugin: ${pluginKey}`);\n } else {\n this.pluginInstances.clear();\n this.logger.log('Cleared all plugin caches');\n }\n }\n}\n","import { Injectable, Logger, Inject, OnModuleInit } from '@nestjs/common';\nimport {\n RequestContextService,\n PLATFORM_HTTP_CLIENT,\n type PlatformHttpClient,\n} from '@lark-apaas/nestjs-common';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { CapabilityConfig, PluginActionContext, UserContext } from '../interfaces';\nimport { PluginLoaderService } from './plugin-loader.service';\nimport { TemplateEngineService } from './template-engine.service';\n\nexport class CapabilityNotFoundError extends Error {\n constructor(capabilityId: string) {\n super(`Capability not found: ${capabilityId}`);\n this.name = 'CapabilityNotFoundError';\n }\n}\n\nexport class ActionNotFoundError extends Error {\n constructor(pluginKey: string, actionName: string) {\n super(`Action '${actionName}' not found in plugin ${pluginKey}`);\n this.name = 'ActionNotFoundError';\n }\n}\n\nexport interface CapabilityExecutor {\n /**\n * 调用 capability(始终返回 Promise)\n * - unary action: 直接返回结果\n * - stream action: 内部聚合所有 chunk 后返回\n */\n call(actionName: string, input: unknown, context?: Partial<PluginActionContext>): Promise<unknown>;\n\n /**\n * 流式调用 capability\n * - 返回原始 AsyncIterable\n * - 如果 action 是 unary,包装为单次 yield\n */\n callStream(actionName: string, input: unknown, context?: Partial<PluginActionContext>): AsyncIterable<unknown>;\n\n /**\n * 检查 action 是否为流式\n */\n isStream(actionName: string): Promise<boolean>;\n}\n\nexport interface CapabilityModuleOptions {\n capabilitiesDir?: string;\n}\n\n@Injectable()\nexport class CapabilityService implements OnModuleInit {\n private readonly logger = new Logger(CapabilityService.name);\n private readonly capabilities = new Map<string, CapabilityConfig>();\n private capabilitiesDir: string;\n\n constructor(\n private readonly requestContextService: RequestContextService,\n @Inject(PLATFORM_HTTP_CLIENT) private readonly httpClient: PlatformHttpClient,\n private readonly pluginLoaderService: PluginLoaderService,\n private readonly templateEngineService: TemplateEngineService,\n ) {\n this.capabilitiesDir = path.join(process.cwd(), 'server/capabilities');\n }\n\n setCapabilitiesDir(dir: string): void {\n this.capabilitiesDir = dir;\n }\n\n async onModuleInit(): Promise<void> {\n await this.loadCapabilities();\n }\n\n private async loadCapabilities(): Promise<void> {\n this.logger.log(`Loading capabilities from ${this.capabilitiesDir}`);\n\n if (!fs.existsSync(this.capabilitiesDir)) {\n this.logger.warn(`Capabilities directory not found: ${this.capabilitiesDir}`);\n return;\n }\n\n const files = fs.readdirSync(this.capabilitiesDir).filter(f => f.endsWith('.json'));\n\n for (const file of files) {\n try {\n const filePath = path.join(this.capabilitiesDir, file);\n const content = fs.readFileSync(filePath, 'utf-8');\n const config = JSON.parse(content) as CapabilityConfig;\n\n if (!config.id) {\n this.logger.warn(`Skipping capability without id: ${file}`);\n continue;\n }\n\n this.capabilities.set(config.id, config);\n this.logger.log(`Loaded capability: ${config.id} (${config.name})`);\n } catch (error) {\n this.logger.error(`Failed to load capability from ${file}:`, error);\n }\n }\n\n this.logger.log(`Loaded ${this.capabilities.size} capabilities`);\n }\n\n listCapabilities(): CapabilityConfig[] {\n return Array.from(this.capabilities.values());\n }\n\n getCapability(capabilityId: string): CapabilityConfig | null {\n return this.capabilities.get(capabilityId) ?? null;\n }\n\n load(capabilityId: string): CapabilityExecutor {\n const config = this.capabilities.get(capabilityId);\n if (!config) {\n throw new CapabilityNotFoundError(capabilityId);\n }\n\n return this.createExecutor(config);\n }\n\n /**\n * 使用传入的配置加载能力执行器\n * 用于 debug 场景,支持用户传入自定义配置\n */\n loadWithConfig(config: CapabilityConfig): CapabilityExecutor {\n return this.createExecutor(config);\n }\n\n private createExecutor(config: CapabilityConfig): CapabilityExecutor {\n return {\n call: async (\n actionName: string,\n input: unknown,\n contextOverride?: Partial<PluginActionContext>,\n ) => {\n return this.executeCall(config, actionName, input, contextOverride);\n },\n\n callStream: (\n actionName: string,\n input: unknown,\n contextOverride?: Partial<PluginActionContext>,\n ) => {\n return this.executeCallStream(config, actionName, input, contextOverride);\n },\n\n isStream: async (actionName: string) => {\n return this.checkIsStream(config, actionName);\n },\n };\n }\n\n /**\n * 检查 action 是否为流式\n */\n private async checkIsStream(config: CapabilityConfig, actionName: string): Promise<boolean> {\n const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginKey);\n\n if (!pluginInstance.hasAction(actionName)) {\n throw new ActionNotFoundError(config.pluginKey, actionName);\n }\n\n return pluginInstance.isStreamAction?.(actionName) ?? false;\n }\n\n /**\n * 执行 capability(始终返回 Promise)\n * - unary action: 直接返回结果\n * - stream action: 内部聚合所有 chunk 后返回\n */\n private async executeCall(\n config: CapabilityConfig,\n actionName: string,\n input: unknown,\n contextOverride?: Partial<PluginActionContext>,\n ): Promise<unknown> {\n const startTime = Date.now();\n\n try {\n const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginKey);\n\n if (!pluginInstance.hasAction(actionName)) {\n throw new ActionNotFoundError(config.pluginKey, actionName);\n }\n\n const resolvedParams = this.templateEngineService.resolve(\n config.formValue,\n input as Record<string, unknown>,\n );\n\n const context = this.buildActionContext(contextOverride);\n const isStream = pluginInstance.isStreamAction?.(actionName) ?? false;\n\n this.logger.log({\n message: 'Executing capability',\n capabilityId: config.id,\n action: actionName,\n pluginKey: config.pluginKey,\n isStream,\n });\n\n let result: unknown;\n\n if (isStream && pluginInstance.runStream) {\n // 流式 action:聚合所有 chunk\n const chunks: unknown[] = [];\n for await (const chunk of pluginInstance.runStream(actionName, context, resolvedParams)) {\n chunks.push(chunk);\n }\n // 使用插件的聚合方法,或默认返回 chunks 数组\n result = pluginInstance.aggregate\n ? pluginInstance.aggregate(actionName, chunks)\n : chunks;\n } else {\n // 非流式 action:直接调用\n result = await pluginInstance.run(actionName, context, resolvedParams);\n }\n\n this.logger.log({\n message: 'Capability executed successfully',\n capabilityId: config.id,\n action: actionName,\n duration: Date.now() - startTime,\n });\n\n return result;\n } catch (error) {\n this.logger.error({\n message: 'Capability execution failed',\n capabilityId: config.id,\n action: actionName,\n error: error instanceof Error ? error.message : String(error),\n duration: Date.now() - startTime,\n });\n throw error;\n }\n }\n\n /**\n * 流式执行 capability\n * - stream action: 返回原始 AsyncIterable\n * - unary action: 包装为单次 yield\n */\n private async *executeCallStream(\n config: CapabilityConfig,\n actionName: string,\n input: unknown,\n contextOverride?: Partial<PluginActionContext>,\n ): AsyncIterable<unknown> {\n const startTime = Date.now();\n\n try {\n const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginKey);\n\n if (!pluginInstance.hasAction(actionName)) {\n throw new ActionNotFoundError(config.pluginKey, actionName);\n }\n\n const resolvedParams = this.templateEngineService.resolve(\n config.formValue,\n input as Record<string, unknown>,\n );\n\n const context = this.buildActionContext(contextOverride);\n const isStream = pluginInstance.isStreamAction?.(actionName) ?? false;\n\n this.logger.log({\n message: 'Executing capability (stream)',\n capabilityId: config.id,\n action: actionName,\n pluginKey: config.pluginKey,\n isStream,\n });\n\n if (isStream && pluginInstance.runStream) {\n // 流式 action:透传 AsyncIterable\n yield* pluginInstance.runStream(actionName, context, resolvedParams);\n } else {\n // 非流式 action:包装为单次 yield\n const result = await pluginInstance.run(actionName, context, resolvedParams);\n yield result;\n }\n\n this.logger.log({\n message: 'Capability stream completed',\n capabilityId: config.id,\n action: actionName,\n duration: Date.now() - startTime,\n });\n } catch (error) {\n this.logger.error({\n message: 'Capability stream execution failed',\n capabilityId: config.id,\n action: actionName,\n error: error instanceof Error ? error.message : String(error),\n duration: Date.now() - startTime,\n });\n throw error;\n }\n }\n\n private buildActionContext(override?: Partial<PluginActionContext>): PluginActionContext {\n return {\n logger: this.logger,\n httpClient: this.httpClient,\n userContext: override?.userContext ?? this.getUserContext(),\n };\n }\n\n private getUserContext(): UserContext {\n const ctx = this.requestContextService.getContext();\n return {\n userId: ctx?.userId ?? '',\n tenantId: ctx?.tenantId ?? '',\n };\n }\n}\n","import {\n Controller,\n Post,\n Get,\n Param,\n Body,\n Res,\n HttpException,\n HttpStatus,\n} from '@nestjs/common';\nimport type { Response } from 'express';\nimport {\n CapabilityService,\n CapabilityNotFoundError,\n ActionNotFoundError,\n} from '../services/capability.service';\nimport { PluginLoaderService, PluginNotFoundError } from '../services/plugin-loader.service';\nimport { TemplateEngineService } from '../services/template-engine.service';\nimport type { CapabilityConfig } from '../interfaces';\n\ninterface DebugRequestBody {\n action?: string;\n params?: Record<string, unknown>;\n capability?: CapabilityConfig;\n}\n\ninterface DebugResponse {\n code: number;\n message: string;\n data: unknown;\n debug?: {\n capabilityConfig: unknown;\n resolvedParams: unknown;\n duration: number;\n pluginKey: string;\n action: string;\n };\n}\n\ninterface ListResponse {\n code: number;\n message: string;\n data: Array<{\n id: string;\n name: string;\n pluginKey: string;\n pluginVersion: string;\n }>;\n}\n\n@Controller('__innerapi__/capability')\nexport class DebugController {\n constructor(\n private readonly capabilityService: CapabilityService,\n private readonly pluginLoaderService: PluginLoaderService,\n private readonly templateEngineService: TemplateEngineService,\n ) {}\n\n @Get('list')\n list(): ListResponse {\n const capabilities = this.capabilityService.listCapabilities();\n\n return {\n code: 0,\n message: 'success',\n data: capabilities.map(c => ({\n id: c.id,\n name: c.name,\n pluginKey: c.pluginKey,\n pluginVersion: c.pluginVersion,\n })),\n };\n }\n\n /**\n * 获取 capability 配置\n * 优先使用 body.capability,否则从服务获取\n */\n private getCapabilityConfig(\n capabilityId: string,\n bodyCapability?: CapabilityConfig,\n ): CapabilityConfig {\n if (bodyCapability) {\n return bodyCapability;\n }\n\n const config = this.capabilityService.getCapability(capabilityId);\n if (!config) {\n throw new HttpException(\n {\n code: 1,\n message: `Capability not found: ${capabilityId}`,\n error: 'CAPABILITY_NOT_FOUND',\n },\n HttpStatus.NOT_FOUND,\n );\n }\n\n return config;\n }\n\n /**\n * 获取 action 名称\n * 优先使用传入的 action,否则使用插件第一个 action\n */\n private async getActionName(pluginKey: string, bodyAction?: string): Promise<string> {\n if (bodyAction) {\n return bodyAction;\n }\n\n const pluginInstance = await this.pluginLoaderService.loadPlugin(pluginKey);\n const actions = pluginInstance.listActions();\n\n if (actions.length === 0) {\n throw new HttpException(\n {\n code: 1,\n message: `Plugin ${pluginKey} has no actions`,\n error: 'NO_ACTIONS',\n },\n HttpStatus.BAD_REQUEST,\n );\n }\n\n return actions[0];\n }\n\n @Post('debug/:capability_id')\n async debug(\n @Param('capability_id') capabilityId: string,\n @Body() body: DebugRequestBody,\n ): Promise<DebugResponse> {\n const startTime = Date.now();\n const params = body.params ?? {};\n\n const config = this.getCapabilityConfig(capabilityId, body.capability);\n const action = await this.getActionName(config.pluginKey, body.action);\n\n const resolvedParams = this.templateEngineService.resolve(\n config.formValue,\n params,\n );\n\n try {\n const result = await this.capabilityService\n .loadWithConfig(config)\n .call(action, params);\n\n return {\n code: 0,\n message: 'success',\n data: result,\n debug: {\n capabilityConfig: config,\n resolvedParams,\n duration: Date.now() - startTime,\n pluginKey: config.pluginKey,\n action,\n },\n };\n } catch (error) {\n const duration = Date.now() - startTime;\n\n if (error instanceof CapabilityNotFoundError) {\n throw new HttpException(\n {\n code: 1,\n message: error.message,\n error: 'CAPABILITY_NOT_FOUND',\n debug: { duration },\n },\n HttpStatus.NOT_FOUND,\n );\n }\n\n if (error instanceof PluginNotFoundError) {\n throw new HttpException(\n {\n code: 1,\n message: error.message,\n error: 'PLUGIN_NOT_FOUND',\n debug: { duration, pluginKey: config.pluginKey, action },\n },\n HttpStatus.INTERNAL_SERVER_ERROR,\n );\n }\n\n if (error instanceof ActionNotFoundError) {\n throw new HttpException(\n {\n code: 1,\n message: error.message,\n error: 'ACTION_NOT_FOUND',\n debug: { duration, pluginKey: config.pluginKey, action },\n },\n HttpStatus.BAD_REQUEST,\n );\n }\n\n throw new HttpException(\n {\n code: 1,\n message: error instanceof Error ? error.message : String(error),\n error: 'EXECUTION_ERROR',\n debug: {\n duration,\n pluginKey: config.pluginKey,\n action,\n resolvedParams,\n },\n },\n HttpStatus.INTERNAL_SERVER_ERROR,\n );\n }\n }\n\n @Post('debug/:capability_id/stream')\n async debugStream(\n @Param('capability_id') capabilityId: string,\n @Body() body: DebugRequestBody,\n @Res() res: Response,\n ): Promise<void> {\n const params = body.params ?? {};\n\n // 设置 SSE 响应头\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n\n try {\n const config = this.getCapabilityConfig(capabilityId, body.capability);\n const action = await this.getActionName(config.pluginKey, body.action);\n\n const capability = this.capabilityService.loadWithConfig(config);\n const stream = capability.callStream(action, params);\n\n for await (const chunk of stream) {\n res.write(`data: ${JSON.stringify(chunk)}\\n\\n`);\n }\n\n // 发送结束标记\n res.write('data: [DONE]\\n\\n');\n } catch (error) {\n // 错误时发送错误信息\n const message = error instanceof Error ? error.message : String(error);\n let errorCode = 'EXECUTION_ERROR';\n\n if (error instanceof CapabilityNotFoundError) {\n errorCode = 'CAPABILITY_NOT_FOUND';\n } else if (error instanceof PluginNotFoundError) {\n errorCode = 'PLUGIN_NOT_FOUND';\n } else if (error instanceof ActionNotFoundError) {\n errorCode = 'ACTION_NOT_FOUND';\n } else if (error instanceof HttpException) {\n const response = error.getResponse() as { error?: string };\n errorCode = response.error ?? 'EXECUTION_ERROR';\n }\n\n res.write(`data: ${JSON.stringify({ error: message, code: errorCode })}\\n\\n`);\n } finally {\n res.end();\n }\n }\n}\n","import {\n Controller,\n Get,\n Post,\n Param,\n Body,\n Res,\n HttpException,\n HttpStatus,\n} from '@nestjs/common';\nimport type { Response } from 'express';\nimport {\n CapabilityService,\n CapabilityNotFoundError,\n ActionNotFoundError,\n} from '../services/capability.service';\nimport { PluginNotFoundError } from '../services/plugin-loader.service';\n\ninterface ExecuteRequestBody {\n action: string;\n params: Record<string, unknown>;\n}\n\ninterface ExecuteResponse {\n code: number;\n message: string;\n data: unknown;\n}\n\ninterface CapabilityInfo {\n id: string;\n name: string;\n description: string;\n pluginKey: string;\n pluginVersion: string;\n}\n\ninterface ListResponse {\n code: number;\n message: string;\n data: CapabilityInfo[];\n}\n\n@Controller('api/capability')\nexport class WebhookController {\n constructor(private readonly capabilityService: CapabilityService) {}\n\n @Get('list')\n list(): ListResponse {\n const capabilities = this.capabilityService.listCapabilities();\n return {\n code: 0,\n message: 'success',\n data: capabilities.map(c => ({\n id: c.id,\n name: c.name,\n description: c.description,\n pluginKey: c.pluginKey,\n pluginVersion: c.pluginVersion,\n })),\n };\n }\n\n @Post(':capability_id')\n async execute(\n @Param('capability_id') capabilityId: string,\n @Body() body: ExecuteRequestBody,\n ): Promise<ExecuteResponse> {\n try {\n const result = await this.capabilityService\n .load(capabilityId)\n .call(body.action, body.params);\n\n return {\n code: 0,\n message: 'success',\n data: result,\n };\n } catch (error) {\n if (error instanceof CapabilityNotFoundError) {\n throw new HttpException(\n {\n code: 1,\n message: error.message,\n error: 'CAPABILITY_NOT_FOUND',\n },\n HttpStatus.NOT_FOUND,\n );\n }\n\n if (error instanceof PluginNotFoundError) {\n throw new HttpException(\n {\n code: 1,\n message: error.message,\n error: 'PLUGIN_NOT_FOUND',\n },\n HttpStatus.INTERNAL_SERVER_ERROR,\n );\n }\n\n if (error instanceof ActionNotFoundError) {\n throw new HttpException(\n {\n code: 1,\n message: error.message,\n error: 'ACTION_NOT_FOUND',\n },\n HttpStatus.BAD_REQUEST,\n );\n }\n\n throw new HttpException(\n {\n code: 1,\n message: error instanceof Error ? error.message : String(error),\n error: 'EXECUTION_ERROR',\n },\n HttpStatus.INTERNAL_SERVER_ERROR,\n );\n }\n }\n\n @Post(':capability_id/stream')\n async executeStream(\n @Param('capability_id') capabilityId: string,\n @Body() body: ExecuteRequestBody,\n @Res() res: Response,\n ): Promise<void> {\n // 设置 SSE 响应头\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n\n try {\n const capability = this.capabilityService.load(capabilityId);\n const stream = capability.callStream(body.action, body.params);\n\n for await (const chunk of stream) {\n res.write(`data: ${JSON.stringify(chunk)}\\n\\n`);\n }\n\n // 发送结束标记\n res.write('data: [DONE]\\n\\n');\n } catch (error) {\n // 错误时发送错误信息\n const message = error instanceof Error ? error.message : String(error);\n let errorCode = 'EXECUTION_ERROR';\n\n if (error instanceof CapabilityNotFoundError) {\n errorCode = 'CAPABILITY_NOT_FOUND';\n } else if (error instanceof PluginNotFoundError) {\n errorCode = 'PLUGIN_NOT_FOUND';\n } else if (error instanceof ActionNotFoundError) {\n errorCode = 'ACTION_NOT_FOUND';\n }\n\n res.write(`data: ${JSON.stringify({ error: message, code: errorCode })}\\n\\n`);\n } finally {\n res.end();\n }\n }\n}\n","import { Module, DynamicModule, Type } from '@nestjs/common';\nimport {\n RequestContextService,\n PLATFORM_HTTP_CLIENT,\n} from '@lark-apaas/nestjs-common';\nimport { DebugController, WebhookController } from './controllers';\nimport {\n CapabilityService,\n PluginLoaderService,\n TemplateEngineService,\n type CapabilityModuleOptions,\n} from './services';\n\nconst CAPABILITY_OPTIONS = Symbol('CAPABILITY_OPTIONS');\n\nconst isDevelopment = process.env.NODE_ENV === 'development';\n\nfunction getControllers(): Type[] {\n const controllers: Type[] = [WebhookController];\n if (isDevelopment) {\n controllers.push(DebugController);\n }\n return controllers;\n}\n\n@Module({\n controllers: getControllers(),\n providers: [CapabilityService, PluginLoaderService, TemplateEngineService],\n exports: [CapabilityService],\n})\nexport class CapabilityModule {\n static forRoot(options?: CapabilityModuleOptions): DynamicModule {\n return {\n module: CapabilityModule,\n controllers: getControllers(),\n providers: [\n {\n provide: CAPABILITY_OPTIONS,\n useValue: options ?? {},\n },\n {\n provide: CapabilityService,\n useFactory: (\n requestContextService: RequestContextService,\n httpClient: any,\n pluginLoader: PluginLoaderService,\n templateEngine: TemplateEngineService,\n moduleOptions: CapabilityModuleOptions,\n ) => {\n const service = new CapabilityService(\n requestContextService,\n httpClient,\n pluginLoader,\n templateEngine,\n );\n if (moduleOptions?.capabilitiesDir) {\n service.setCapabilitiesDir(moduleOptions.capabilitiesDir);\n }\n return service;\n },\n inject: [\n RequestContextService,\n PLATFORM_HTTP_CLIENT,\n PluginLoaderService,\n TemplateEngineService,\n CAPABILITY_OPTIONS,\n ],\n },\n PluginLoaderService,\n TemplateEngineService,\n ],\n exports: [CapabilityService],\n };\n }\n}\n"],"mappings":"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","names":["TemplateEngineService","EXPR_REGEX","WHOLE_STRING_EXPR_REGEX","resolve","template","input","resolveString","Array","isArray","map","item","resolveObject","wholeMatch","match","path","value","getValueByPath","undefined","lastIndex","test","result","replace","String","key","Object","entries","obj","keys","split","current","import_common","PluginNotFoundError","Error","pluginKey","name","PluginLoadError","reason","PluginLoaderService","logger","Logger","pluginInstances","Map","loadPlugin","cached","get","debug","log","pluginPackage","default","create","instance","set","error","code","message","String","isPluginInstalled","require","resolve","clearCache","delete","clear","import_common","CapabilityNotFoundError","Error","capabilityId","name","ActionNotFoundError","pluginKey","actionName","CapabilityService","logger","Logger","capabilities","Map","capabilitiesDir","requestContextService","httpClient","pluginLoaderService","templateEngineService","join","process","cwd","setCapabilitiesDir","dir","onModuleInit","loadCapabilities","log","existsSync","warn","files","readdirSync","filter","f","endsWith","file","filePath","content","readFileSync","config","JSON","parse","id","set","error","size","listCapabilities","Array","from","values","getCapability","get","load","createExecutor","loadWithConfig","call","input","contextOverride","executeCall","callStream","executeCallStream","isStream","checkIsStream","pluginInstance","loadPlugin","hasAction","isStreamAction","startTime","Date","now","resolvedParams","resolve","formValue","context","buildActionContext","message","action","result","runStream","chunks","chunk","push","aggregate","run","duration","String","override","userContext","getUserContext","ctx","getContext","userId","tenantId","import_common","DebugController","capabilityService","pluginLoaderService","templateEngineService","list","capabilities","listCapabilities","code","message","data","map","c","id","name","pluginKey","pluginVersion","getCapabilityConfig","capabilityId","bodyCapability","config","getCapability","HttpException","error","HttpStatus","NOT_FOUND","getActionName","bodyAction","pluginInstance","loadPlugin","actions","listActions","length","BAD_REQUEST","debug","body","startTime","Date","now","params","capability","action","resolvedParams","resolve","formValue","result","loadWithConfig","call","capabilityConfig","duration","CapabilityNotFoundError","PluginNotFoundError","INTERNAL_SERVER_ERROR","ActionNotFoundError","Error","String","debugStream","res","setHeader","stream","callStream","chunk","write","JSON","stringify","errorCode","response","getResponse","end","import_common","WebhookController","capabilityService","list","capabilities","listCapabilities","code","message","data","map","c","id","name","description","pluginKey","pluginVersion","execute","capabilityId","body","result","load","call","action","params","error","CapabilityNotFoundError","HttpException","HttpStatus","NOT_FOUND","PluginNotFoundError","INTERNAL_SERVER_ERROR","ActionNotFoundError","BAD_REQUEST","Error","String","executeStream","res","setHeader","capability","stream","callStream","chunk","write","JSON","stringify","errorCode","end","import_common","import_nestjs_common","CAPABILITY_OPTIONS","Symbol","isDevelopment","process","env","NODE_ENV","getControllers","controllers","WebhookController","push","DebugController","CapabilityModule","forRoot","options","module","providers","provide","useValue","CapabilityService","useFactory","requestContextService","httpClient","pluginLoader","templateEngine","moduleOptions","service","capabilitiesDir","setCapabilitiesDir","inject","RequestContextService","PLATFORM_HTTP_CLIENT","PluginLoaderService","TemplateEngineService","exports"]}
package/dist/index.d.cts CHANGED
@@ -50,7 +50,7 @@ interface JSONSchema {
50
50
  }
51
51
  interface CapabilityConfig {
52
52
  id: string;
53
- pluginID: string;
53
+ pluginKey: string;
54
54
  pluginVersion: string;
55
55
  name: string;
56
56
  description: string;
@@ -88,24 +88,24 @@ declare class TemplateEngineService {
88
88
  }
89
89
 
90
90
  declare class PluginNotFoundError extends Error {
91
- constructor(pluginID: string);
91
+ constructor(pluginKey: string);
92
92
  }
93
93
  declare class PluginLoadError extends Error {
94
- constructor(pluginID: string, reason: string);
94
+ constructor(pluginKey: string, reason: string);
95
95
  }
96
96
  declare class PluginLoaderService {
97
97
  private readonly logger;
98
98
  private readonly pluginInstances;
99
- loadPlugin(pluginID: string): Promise<PluginInstance>;
100
- isPluginInstalled(pluginID: string): boolean;
101
- clearCache(pluginID?: string): void;
99
+ loadPlugin(pluginKey: string): Promise<PluginInstance>;
100
+ isPluginInstalled(pluginKey: string): boolean;
101
+ clearCache(pluginKey?: string): void;
102
102
  }
103
103
 
104
104
  declare class CapabilityNotFoundError extends Error {
105
105
  constructor(capabilityId: string);
106
106
  }
107
107
  declare class ActionNotFoundError extends Error {
108
- constructor(pluginID: string, actionName: string);
108
+ constructor(pluginKey: string, actionName: string);
109
109
  }
110
110
  interface CapabilityExecutor {
111
111
  /**
@@ -182,7 +182,7 @@ interface DebugResponse {
182
182
  capabilityConfig: unknown;
183
183
  resolvedParams: unknown;
184
184
  duration: number;
185
- pluginID: string;
185
+ pluginKey: string;
186
186
  action: string;
187
187
  };
188
188
  }
@@ -192,7 +192,7 @@ interface ListResponse$1 {
192
192
  data: Array<{
193
193
  id: string;
194
194
  name: string;
195
- pluginID: string;
195
+ pluginKey: string;
196
196
  pluginVersion: string;
197
197
  }>;
198
198
  }
@@ -229,7 +229,7 @@ interface CapabilityInfo {
229
229
  id: string;
230
230
  name: string;
231
231
  description: string;
232
- pluginID: string;
232
+ pluginKey: string;
233
233
  pluginVersion: string;
234
234
  }
235
235
  interface ListResponse {
package/dist/index.d.ts CHANGED
@@ -50,7 +50,7 @@ interface JSONSchema {
50
50
  }
51
51
  interface CapabilityConfig {
52
52
  id: string;
53
- pluginID: string;
53
+ pluginKey: string;
54
54
  pluginVersion: string;
55
55
  name: string;
56
56
  description: string;
@@ -88,24 +88,24 @@ declare class TemplateEngineService {
88
88
  }
89
89
 
90
90
  declare class PluginNotFoundError extends Error {
91
- constructor(pluginID: string);
91
+ constructor(pluginKey: string);
92
92
  }
93
93
  declare class PluginLoadError extends Error {
94
- constructor(pluginID: string, reason: string);
94
+ constructor(pluginKey: string, reason: string);
95
95
  }
96
96
  declare class PluginLoaderService {
97
97
  private readonly logger;
98
98
  private readonly pluginInstances;
99
- loadPlugin(pluginID: string): Promise<PluginInstance>;
100
- isPluginInstalled(pluginID: string): boolean;
101
- clearCache(pluginID?: string): void;
99
+ loadPlugin(pluginKey: string): Promise<PluginInstance>;
100
+ isPluginInstalled(pluginKey: string): boolean;
101
+ clearCache(pluginKey?: string): void;
102
102
  }
103
103
 
104
104
  declare class CapabilityNotFoundError extends Error {
105
105
  constructor(capabilityId: string);
106
106
  }
107
107
  declare class ActionNotFoundError extends Error {
108
- constructor(pluginID: string, actionName: string);
108
+ constructor(pluginKey: string, actionName: string);
109
109
  }
110
110
  interface CapabilityExecutor {
111
111
  /**
@@ -182,7 +182,7 @@ interface DebugResponse {
182
182
  capabilityConfig: unknown;
183
183
  resolvedParams: unknown;
184
184
  duration: number;
185
- pluginID: string;
185
+ pluginKey: string;
186
186
  action: string;
187
187
  };
188
188
  }
@@ -192,7 +192,7 @@ interface ListResponse$1 {
192
192
  data: Array<{
193
193
  id: string;
194
194
  name: string;
195
- pluginID: string;
195
+ pluginKey: string;
196
196
  pluginVersion: string;
197
197
  }>;
198
198
  }
@@ -229,7 +229,7 @@ interface CapabilityInfo {
229
229
  id: string;
230
230
  name: string;
231
231
  description: string;
232
- pluginID: string;
232
+ pluginKey: string;
233
233
  pluginVersion: string;
234
234
  }
235
235
  interface ListResponse {
package/dist/index.js CHANGED
@@ -93,8 +93,8 @@ var PluginNotFoundError = class extends Error {
93
93
  static {
94
94
  __name(this, "PluginNotFoundError");
95
95
  }
96
- constructor(pluginID) {
97
- super(`Plugin not found: ${pluginID}`);
96
+ constructor(pluginKey) {
97
+ super(`Plugin not found: ${pluginKey}`);
98
98
  this.name = "PluginNotFoundError";
99
99
  }
100
100
  };
@@ -102,8 +102,8 @@ var PluginLoadError = class extends Error {
102
102
  static {
103
103
  __name(this, "PluginLoadError");
104
104
  }
105
- constructor(pluginID, reason) {
106
- super(`Failed to load plugin ${pluginID}: ${reason}`);
105
+ constructor(pluginKey, reason) {
106
+ super(`Failed to load plugin ${pluginKey}: ${reason}`);
107
107
  this.name = "PluginLoadError";
108
108
  }
109
109
  };
@@ -113,41 +113,41 @@ var PluginLoaderService = class _PluginLoaderService {
113
113
  }
114
114
  logger = new Logger(_PluginLoaderService.name);
115
115
  pluginInstances = /* @__PURE__ */ new Map();
116
- async loadPlugin(pluginID) {
117
- const cached = this.pluginInstances.get(pluginID);
116
+ async loadPlugin(pluginKey) {
117
+ const cached = this.pluginInstances.get(pluginKey);
118
118
  if (cached) {
119
- this.logger.debug(`Using cached plugin instance: ${pluginID}`);
119
+ this.logger.debug(`Using cached plugin instance: ${pluginKey}`);
120
120
  return cached;
121
121
  }
122
- this.logger.log(`Loading plugin: ${pluginID}`);
122
+ this.logger.log(`Loading plugin: ${pluginKey}`);
123
123
  try {
124
- const pluginPackage = (await import(pluginID)).default;
124
+ const pluginPackage = (await import(pluginKey)).default;
125
125
  if (typeof pluginPackage.create !== "function") {
126
- throw new PluginLoadError(pluginID, "Plugin does not export create() function");
126
+ throw new PluginLoadError(pluginKey, "Plugin does not export create() function");
127
127
  }
128
128
  const instance = pluginPackage.create();
129
- this.pluginInstances.set(pluginID, instance);
130
- this.logger.log(`Plugin loaded successfully: ${pluginID}`);
129
+ this.pluginInstances.set(pluginKey, instance);
130
+ this.logger.log(`Plugin loaded successfully: ${pluginKey}`);
131
131
  return instance;
132
132
  } catch (error) {
133
133
  if (error.code === "MODULE_NOT_FOUND") {
134
- throw new PluginNotFoundError(pluginID);
134
+ throw new PluginNotFoundError(pluginKey);
135
135
  }
136
- throw new PluginLoadError(pluginID, error instanceof Error ? error.message : String(error));
136
+ throw new PluginLoadError(pluginKey, error instanceof Error ? error.message : String(error));
137
137
  }
138
138
  }
139
- isPluginInstalled(pluginID) {
139
+ isPluginInstalled(pluginKey) {
140
140
  try {
141
- __require.resolve(pluginID);
141
+ __require.resolve(pluginKey);
142
142
  return true;
143
143
  } catch {
144
144
  return false;
145
145
  }
146
146
  }
147
- clearCache(pluginID) {
148
- if (pluginID) {
149
- this.pluginInstances.delete(pluginID);
150
- this.logger.log(`Cleared cache for plugin: ${pluginID}`);
147
+ clearCache(pluginKey) {
148
+ if (pluginKey) {
149
+ this.pluginInstances.delete(pluginKey);
150
+ this.logger.log(`Cleared cache for plugin: ${pluginKey}`);
151
151
  } else {
152
152
  this.pluginInstances.clear();
153
153
  this.logger.log("Cleared all plugin caches");
@@ -193,8 +193,8 @@ var ActionNotFoundError = class extends Error {
193
193
  static {
194
194
  __name(this, "ActionNotFoundError");
195
195
  }
196
- constructor(pluginID, actionName) {
197
- super(`Action '${actionName}' not found in plugin ${pluginID}`);
196
+ constructor(pluginKey, actionName) {
197
+ super(`Action '${actionName}' not found in plugin ${pluginKey}`);
198
198
  this.name = "ActionNotFoundError";
199
199
  }
200
200
  };
@@ -283,9 +283,9 @@ var CapabilityService = class _CapabilityService {
283
283
  * 检查 action 是否为流式
284
284
  */
285
285
  async checkIsStream(config, actionName) {
286
- const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginID);
286
+ const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginKey);
287
287
  if (!pluginInstance.hasAction(actionName)) {
288
- throw new ActionNotFoundError(config.pluginID, actionName);
288
+ throw new ActionNotFoundError(config.pluginKey, actionName);
289
289
  }
290
290
  return pluginInstance.isStreamAction?.(actionName) ?? false;
291
291
  }
@@ -297,9 +297,9 @@ var CapabilityService = class _CapabilityService {
297
297
  async executeCall(config, actionName, input, contextOverride) {
298
298
  const startTime = Date.now();
299
299
  try {
300
- const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginID);
300
+ const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginKey);
301
301
  if (!pluginInstance.hasAction(actionName)) {
302
- throw new ActionNotFoundError(config.pluginID, actionName);
302
+ throw new ActionNotFoundError(config.pluginKey, actionName);
303
303
  }
304
304
  const resolvedParams = this.templateEngineService.resolve(config.formValue, input);
305
305
  const context = this.buildActionContext(contextOverride);
@@ -308,7 +308,7 @@ var CapabilityService = class _CapabilityService {
308
308
  message: "Executing capability",
309
309
  capabilityId: config.id,
310
310
  action: actionName,
311
- pluginID: config.pluginID,
311
+ pluginKey: config.pluginKey,
312
312
  isStream
313
313
  });
314
314
  let result;
@@ -347,9 +347,9 @@ var CapabilityService = class _CapabilityService {
347
347
  async *executeCallStream(config, actionName, input, contextOverride) {
348
348
  const startTime = Date.now();
349
349
  try {
350
- const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginID);
350
+ const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginKey);
351
351
  if (!pluginInstance.hasAction(actionName)) {
352
- throw new ActionNotFoundError(config.pluginID, actionName);
352
+ throw new ActionNotFoundError(config.pluginKey, actionName);
353
353
  }
354
354
  const resolvedParams = this.templateEngineService.resolve(config.formValue, input);
355
355
  const context = this.buildActionContext(contextOverride);
@@ -358,7 +358,7 @@ var CapabilityService = class _CapabilityService {
358
358
  message: "Executing capability (stream)",
359
359
  capabilityId: config.id,
360
360
  action: actionName,
361
- pluginID: config.pluginID,
361
+ pluginKey: config.pluginKey,
362
362
  isStream
363
363
  });
364
364
  if (isStream && pluginInstance.runStream) {
@@ -450,7 +450,7 @@ var DebugController = class {
450
450
  data: capabilities.map((c) => ({
451
451
  id: c.id,
452
452
  name: c.name,
453
- pluginID: c.pluginID,
453
+ pluginKey: c.pluginKey,
454
454
  pluginVersion: c.pluginVersion
455
455
  }))
456
456
  };
@@ -477,16 +477,16 @@ var DebugController = class {
477
477
  * 获取 action 名称
478
478
  * 优先使用传入的 action,否则使用插件第一个 action
479
479
  */
480
- async getActionName(pluginID, bodyAction) {
480
+ async getActionName(pluginKey, bodyAction) {
481
481
  if (bodyAction) {
482
482
  return bodyAction;
483
483
  }
484
- const pluginInstance = await this.pluginLoaderService.loadPlugin(pluginID);
484
+ const pluginInstance = await this.pluginLoaderService.loadPlugin(pluginKey);
485
485
  const actions = pluginInstance.listActions();
486
486
  if (actions.length === 0) {
487
487
  throw new HttpException({
488
488
  code: 1,
489
- message: `Plugin ${pluginID} has no actions`,
489
+ message: `Plugin ${pluginKey} has no actions`,
490
490
  error: "NO_ACTIONS"
491
491
  }, HttpStatus.BAD_REQUEST);
492
492
  }
@@ -496,7 +496,7 @@ var DebugController = class {
496
496
  const startTime = Date.now();
497
497
  const params = body.params ?? {};
498
498
  const config = this.getCapabilityConfig(capabilityId, body.capability);
499
- const action = await this.getActionName(config.pluginID, body.action);
499
+ const action = await this.getActionName(config.pluginKey, body.action);
500
500
  const resolvedParams = this.templateEngineService.resolve(config.formValue, params);
501
501
  try {
502
502
  const result = await this.capabilityService.loadWithConfig(config).call(action, params);
@@ -508,7 +508,7 @@ var DebugController = class {
508
508
  capabilityConfig: config,
509
509
  resolvedParams,
510
510
  duration: Date.now() - startTime,
511
- pluginID: config.pluginID,
511
+ pluginKey: config.pluginKey,
512
512
  action
513
513
  }
514
514
  };
@@ -531,7 +531,7 @@ var DebugController = class {
531
531
  error: "PLUGIN_NOT_FOUND",
532
532
  debug: {
533
533
  duration,
534
- pluginID: config.pluginID,
534
+ pluginKey: config.pluginKey,
535
535
  action
536
536
  }
537
537
  }, HttpStatus.INTERNAL_SERVER_ERROR);
@@ -543,7 +543,7 @@ var DebugController = class {
543
543
  error: "ACTION_NOT_FOUND",
544
544
  debug: {
545
545
  duration,
546
- pluginID: config.pluginID,
546
+ pluginKey: config.pluginKey,
547
547
  action
548
548
  }
549
549
  }, HttpStatus.BAD_REQUEST);
@@ -554,7 +554,7 @@ var DebugController = class {
554
554
  error: "EXECUTION_ERROR",
555
555
  debug: {
556
556
  duration,
557
- pluginID: config.pluginID,
557
+ pluginKey: config.pluginKey,
558
558
  action,
559
559
  resolvedParams
560
560
  }
@@ -568,7 +568,7 @@ var DebugController = class {
568
568
  res.setHeader("Connection", "keep-alive");
569
569
  try {
570
570
  const config = this.getCapabilityConfig(capabilityId, body.capability);
571
- const action = await this.getActionName(config.pluginID, body.action);
571
+ const action = await this.getActionName(config.pluginKey, body.action);
572
572
  const capability = this.capabilityService.loadWithConfig(config);
573
573
  const stream = capability.callStream(action, params);
574
574
  for await (const chunk of stream) {
@@ -677,7 +677,7 @@ var WebhookController = class {
677
677
  id: c.id,
678
678
  name: c.name,
679
679
  description: c.description,
680
- pluginID: c.pluginID,
680
+ pluginKey: c.pluginKey,
681
681
  pluginVersion: c.pluginVersion
682
682
  }))
683
683
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/services/template-engine.service.ts","../src/services/plugin-loader.service.ts","../src/services/capability.service.ts","../src/controllers/debug.controller.ts","../src/controllers/webhook.controller.ts","../src/capability.module.ts"],"sourcesContent":["import { Injectable } from '@nestjs/common';\n\n/**\n * 模板引擎服务\n *\n * 支持语法:\n * - expr: '{{' + selector + '}}'\n * - selector: 'input.' + ident | selector.ident\n * - ident: [a-zA-Z_]([a-zA-Z_0-9])*\n *\n * 示例:\n * - {{input.a}}\n * - {{input.a.b}}\n * - \"this is {{input.a.b}}\"\n *\n * 求值规则:\n * - 如果整个字符串是单个表达式,保留原始类型\n * - 如果是字符串插值(多个表达式或混合内容),返回字符串\n * - 如果变量不存在,返回原始表达式\n */\n@Injectable()\nexport class TemplateEngineService {\n // 匹配 {{input.xxx}} 或 {{input.xxx.yyy}} 表达式\n private readonly EXPR_REGEX = /\\{\\{input\\.([a-zA-Z_][a-zA-Z_0-9]*(?:\\.[a-zA-Z_][a-zA-Z_0-9]*)*)\\}\\}/g;\n // 匹配整串单个表达式\n private readonly WHOLE_STRING_EXPR_REGEX = /^\\{\\{input\\.([a-zA-Z_][a-zA-Z_0-9]*(?:\\.[a-zA-Z_][a-zA-Z_0-9]*)*)\\}\\}$/;\n\n resolve(template: unknown, input: Record<string, unknown>): unknown {\n if (typeof template === 'string') {\n return this.resolveString(template, input);\n }\n\n if (Array.isArray(template)) {\n return template.map(item => this.resolve(item, input));\n }\n\n if (template !== null && typeof template === 'object') {\n return this.resolveObject(template as Record<string, unknown>, input);\n }\n\n return template;\n }\n\n private resolveString(template: string, input: Record<string, unknown>): unknown {\n // 情况1: 整串是单个表达式 → 保留原始类型\n const wholeMatch = template.match(this.WHOLE_STRING_EXPR_REGEX);\n if (wholeMatch) {\n const path = wholeMatch[1];\n const value = this.getValueByPath(input, path);\n // 变量不存在,返回原始表达式\n return value !== undefined ? value : template;\n }\n\n // 情况2: 字符串插值 → 返回字符串\n // 重置正则的 lastIndex(因为使用了 g 标志)\n this.EXPR_REGEX.lastIndex = 0;\n\n // 检查是否有任何表达式\n if (!this.EXPR_REGEX.test(template)) {\n return template;\n }\n\n // 重置并进行替换\n this.EXPR_REGEX.lastIndex = 0;\n const result = template.replace(this.EXPR_REGEX, (match, path) => {\n const value = this.getValueByPath(input, path);\n // 变量不存在,保留原始表达式\n if (value === undefined) {\n return match;\n }\n return String(value);\n });\n\n return result;\n }\n\n private resolveObject(\n template: Record<string, unknown>,\n input: Record<string, unknown>,\n ): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(template)) {\n result[key] = this.resolve(value, input);\n }\n\n return result;\n }\n\n private getValueByPath(obj: Record<string, unknown>, path: string): unknown {\n const keys = path.split('.');\n let current: unknown = obj;\n\n for (const key of keys) {\n if (current === null || current === undefined) {\n return undefined;\n }\n current = (current as Record<string, unknown>)[key];\n }\n\n return current;\n }\n}\n","import { Injectable, Logger } from '@nestjs/common';\nimport type { PluginInstance, PluginPackage } from '../interfaces';\n\nexport class PluginNotFoundError extends Error {\n constructor(pluginID: string) {\n super(`Plugin not found: ${pluginID}`);\n this.name = 'PluginNotFoundError';\n }\n}\n\nexport class PluginLoadError extends Error {\n constructor(pluginID: string, reason: string) {\n super(`Failed to load plugin ${pluginID}: ${reason}`);\n this.name = 'PluginLoadError';\n }\n}\n\n@Injectable()\nexport class PluginLoaderService {\n private readonly logger = new Logger(PluginLoaderService.name);\n private readonly pluginInstances = new Map<string, PluginInstance>();\n\n async loadPlugin(pluginID: string): Promise<PluginInstance> {\n const cached = this.pluginInstances.get(pluginID);\n if (cached) {\n this.logger.debug(`Using cached plugin instance: ${pluginID}`);\n return cached;\n }\n\n this.logger.log(`Loading plugin: ${pluginID}`);\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const pluginPackage = (await import(pluginID)).default as PluginPackage;\n\n if (typeof pluginPackage.create !== 'function') {\n throw new PluginLoadError(pluginID, 'Plugin does not export create() function');\n }\n\n const instance = pluginPackage.create();\n this.pluginInstances.set(pluginID, instance);\n\n this.logger.log(`Plugin loaded successfully: ${pluginID}`);\n return instance;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'MODULE_NOT_FOUND') {\n throw new PluginNotFoundError(pluginID);\n }\n throw new PluginLoadError(\n pluginID,\n error instanceof Error ? error.message : String(error),\n );\n }\n }\n\n isPluginInstalled(pluginID: string): boolean {\n try {\n require.resolve(pluginID);\n return true;\n } catch {\n return false;\n }\n }\n\n clearCache(pluginID?: string): void {\n if (pluginID) {\n this.pluginInstances.delete(pluginID);\n this.logger.log(`Cleared cache for plugin: ${pluginID}`);\n } else {\n this.pluginInstances.clear();\n this.logger.log('Cleared all plugin caches');\n }\n }\n}\n","import { Injectable, Logger, Inject, OnModuleInit } from '@nestjs/common';\nimport {\n RequestContextService,\n PLATFORM_HTTP_CLIENT,\n type PlatformHttpClient,\n} from '@lark-apaas/nestjs-common';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { CapabilityConfig, PluginActionContext, UserContext } from '../interfaces';\nimport { PluginLoaderService } from './plugin-loader.service';\nimport { TemplateEngineService } from './template-engine.service';\n\nexport class CapabilityNotFoundError extends Error {\n constructor(capabilityId: string) {\n super(`Capability not found: ${capabilityId}`);\n this.name = 'CapabilityNotFoundError';\n }\n}\n\nexport class ActionNotFoundError extends Error {\n constructor(pluginID: string, actionName: string) {\n super(`Action '${actionName}' not found in plugin ${pluginID}`);\n this.name = 'ActionNotFoundError';\n }\n}\n\nexport interface CapabilityExecutor {\n /**\n * 调用 capability(始终返回 Promise)\n * - unary action: 直接返回结果\n * - stream action: 内部聚合所有 chunk 后返回\n */\n call(actionName: string, input: unknown, context?: Partial<PluginActionContext>): Promise<unknown>;\n\n /**\n * 流式调用 capability\n * - 返回原始 AsyncIterable\n * - 如果 action 是 unary,包装为单次 yield\n */\n callStream(actionName: string, input: unknown, context?: Partial<PluginActionContext>): AsyncIterable<unknown>;\n\n /**\n * 检查 action 是否为流式\n */\n isStream(actionName: string): Promise<boolean>;\n}\n\nexport interface CapabilityModuleOptions {\n capabilitiesDir?: string;\n}\n\n@Injectable()\nexport class CapabilityService implements OnModuleInit {\n private readonly logger = new Logger(CapabilityService.name);\n private readonly capabilities = new Map<string, CapabilityConfig>();\n private capabilitiesDir: string;\n\n constructor(\n private readonly requestContextService: RequestContextService,\n @Inject(PLATFORM_HTTP_CLIENT) private readonly httpClient: PlatformHttpClient,\n private readonly pluginLoaderService: PluginLoaderService,\n private readonly templateEngineService: TemplateEngineService,\n ) {\n this.capabilitiesDir = path.join(process.cwd(), 'server/capabilities');\n }\n\n setCapabilitiesDir(dir: string): void {\n this.capabilitiesDir = dir;\n }\n\n async onModuleInit(): Promise<void> {\n await this.loadCapabilities();\n }\n\n private async loadCapabilities(): Promise<void> {\n this.logger.log(`Loading capabilities from ${this.capabilitiesDir}`);\n\n if (!fs.existsSync(this.capabilitiesDir)) {\n this.logger.warn(`Capabilities directory not found: ${this.capabilitiesDir}`);\n return;\n }\n\n const files = fs.readdirSync(this.capabilitiesDir).filter(f => f.endsWith('.json'));\n\n for (const file of files) {\n try {\n const filePath = path.join(this.capabilitiesDir, file);\n const content = fs.readFileSync(filePath, 'utf-8');\n const config = JSON.parse(content) as CapabilityConfig;\n\n if (!config.id) {\n this.logger.warn(`Skipping capability without id: ${file}`);\n continue;\n }\n\n this.capabilities.set(config.id, config);\n this.logger.log(`Loaded capability: ${config.id} (${config.name})`);\n } catch (error) {\n this.logger.error(`Failed to load capability from ${file}:`, error);\n }\n }\n\n this.logger.log(`Loaded ${this.capabilities.size} capabilities`);\n }\n\n listCapabilities(): CapabilityConfig[] {\n return Array.from(this.capabilities.values());\n }\n\n getCapability(capabilityId: string): CapabilityConfig | null {\n return this.capabilities.get(capabilityId) ?? null;\n }\n\n load(capabilityId: string): CapabilityExecutor {\n const config = this.capabilities.get(capabilityId);\n if (!config) {\n throw new CapabilityNotFoundError(capabilityId);\n }\n\n return this.createExecutor(config);\n }\n\n /**\n * 使用传入的配置加载能力执行器\n * 用于 debug 场景,支持用户传入自定义配置\n */\n loadWithConfig(config: CapabilityConfig): CapabilityExecutor {\n return this.createExecutor(config);\n }\n\n private createExecutor(config: CapabilityConfig): CapabilityExecutor {\n return {\n call: async (\n actionName: string,\n input: unknown,\n contextOverride?: Partial<PluginActionContext>,\n ) => {\n return this.executeCall(config, actionName, input, contextOverride);\n },\n\n callStream: (\n actionName: string,\n input: unknown,\n contextOverride?: Partial<PluginActionContext>,\n ) => {\n return this.executeCallStream(config, actionName, input, contextOverride);\n },\n\n isStream: async (actionName: string) => {\n return this.checkIsStream(config, actionName);\n },\n };\n }\n\n /**\n * 检查 action 是否为流式\n */\n private async checkIsStream(config: CapabilityConfig, actionName: string): Promise<boolean> {\n const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginID);\n\n if (!pluginInstance.hasAction(actionName)) {\n throw new ActionNotFoundError(config.pluginID, actionName);\n }\n\n return pluginInstance.isStreamAction?.(actionName) ?? false;\n }\n\n /**\n * 执行 capability(始终返回 Promise)\n * - unary action: 直接返回结果\n * - stream action: 内部聚合所有 chunk 后返回\n */\n private async executeCall(\n config: CapabilityConfig,\n actionName: string,\n input: unknown,\n contextOverride?: Partial<PluginActionContext>,\n ): Promise<unknown> {\n const startTime = Date.now();\n\n try {\n const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginID);\n\n if (!pluginInstance.hasAction(actionName)) {\n throw new ActionNotFoundError(config.pluginID, actionName);\n }\n\n const resolvedParams = this.templateEngineService.resolve(\n config.formValue,\n input as Record<string, unknown>,\n );\n\n const context = this.buildActionContext(contextOverride);\n const isStream = pluginInstance.isStreamAction?.(actionName) ?? false;\n\n this.logger.log({\n message: 'Executing capability',\n capabilityId: config.id,\n action: actionName,\n pluginID: config.pluginID,\n isStream,\n });\n\n let result: unknown;\n\n if (isStream && pluginInstance.runStream) {\n // 流式 action:聚合所有 chunk\n const chunks: unknown[] = [];\n for await (const chunk of pluginInstance.runStream(actionName, context, resolvedParams)) {\n chunks.push(chunk);\n }\n // 使用插件的聚合方法,或默认返回 chunks 数组\n result = pluginInstance.aggregate\n ? pluginInstance.aggregate(actionName, chunks)\n : chunks;\n } else {\n // 非流式 action:直接调用\n result = await pluginInstance.run(actionName, context, resolvedParams);\n }\n\n this.logger.log({\n message: 'Capability executed successfully',\n capabilityId: config.id,\n action: actionName,\n duration: Date.now() - startTime,\n });\n\n return result;\n } catch (error) {\n this.logger.error({\n message: 'Capability execution failed',\n capabilityId: config.id,\n action: actionName,\n error: error instanceof Error ? error.message : String(error),\n duration: Date.now() - startTime,\n });\n throw error;\n }\n }\n\n /**\n * 流式执行 capability\n * - stream action: 返回原始 AsyncIterable\n * - unary action: 包装为单次 yield\n */\n private async *executeCallStream(\n config: CapabilityConfig,\n actionName: string,\n input: unknown,\n contextOverride?: Partial<PluginActionContext>,\n ): AsyncIterable<unknown> {\n const startTime = Date.now();\n\n try {\n const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginID);\n\n if (!pluginInstance.hasAction(actionName)) {\n throw new ActionNotFoundError(config.pluginID, actionName);\n }\n\n const resolvedParams = this.templateEngineService.resolve(\n config.formValue,\n input as Record<string, unknown>,\n );\n\n const context = this.buildActionContext(contextOverride);\n const isStream = pluginInstance.isStreamAction?.(actionName) ?? false;\n\n this.logger.log({\n message: 'Executing capability (stream)',\n capabilityId: config.id,\n action: actionName,\n pluginID: config.pluginID,\n isStream,\n });\n\n if (isStream && pluginInstance.runStream) {\n // 流式 action:透传 AsyncIterable\n yield* pluginInstance.runStream(actionName, context, resolvedParams);\n } else {\n // 非流式 action:包装为单次 yield\n const result = await pluginInstance.run(actionName, context, resolvedParams);\n yield result;\n }\n\n this.logger.log({\n message: 'Capability stream completed',\n capabilityId: config.id,\n action: actionName,\n duration: Date.now() - startTime,\n });\n } catch (error) {\n this.logger.error({\n message: 'Capability stream execution failed',\n capabilityId: config.id,\n action: actionName,\n error: error instanceof Error ? error.message : String(error),\n duration: Date.now() - startTime,\n });\n throw error;\n }\n }\n\n private buildActionContext(override?: Partial<PluginActionContext>): PluginActionContext {\n return {\n logger: this.logger,\n httpClient: this.httpClient,\n userContext: override?.userContext ?? this.getUserContext(),\n };\n }\n\n private getUserContext(): UserContext {\n const ctx = this.requestContextService.getContext();\n return {\n userId: ctx?.userId ?? '',\n tenantId: ctx?.tenantId ?? '',\n };\n }\n}\n","import {\n Controller,\n Post,\n Get,\n Param,\n Body,\n Res,\n HttpException,\n HttpStatus,\n} from '@nestjs/common';\nimport type { Response } from 'express';\nimport {\n CapabilityService,\n CapabilityNotFoundError,\n ActionNotFoundError,\n} from '../services/capability.service';\nimport { PluginLoaderService, PluginNotFoundError } from '../services/plugin-loader.service';\nimport { TemplateEngineService } from '../services/template-engine.service';\nimport type { CapabilityConfig } from '../interfaces';\n\ninterface DebugRequestBody {\n action?: string;\n params?: Record<string, unknown>;\n capability?: CapabilityConfig;\n}\n\ninterface DebugResponse {\n code: number;\n message: string;\n data: unknown;\n debug?: {\n capabilityConfig: unknown;\n resolvedParams: unknown;\n duration: number;\n pluginID: string;\n action: string;\n };\n}\n\ninterface ListResponse {\n code: number;\n message: string;\n data: Array<{\n id: string;\n name: string;\n pluginID: string;\n pluginVersion: string;\n }>;\n}\n\n@Controller('__innerapi__/capability')\nexport class DebugController {\n constructor(\n private readonly capabilityService: CapabilityService,\n private readonly pluginLoaderService: PluginLoaderService,\n private readonly templateEngineService: TemplateEngineService,\n ) {}\n\n @Get('list')\n list(): ListResponse {\n const capabilities = this.capabilityService.listCapabilities();\n\n return {\n code: 0,\n message: 'success',\n data: capabilities.map(c => ({\n id: c.id,\n name: c.name,\n pluginID: c.pluginID,\n pluginVersion: c.pluginVersion,\n })),\n };\n }\n\n /**\n * 获取 capability 配置\n * 优先使用 body.capability,否则从服务获取\n */\n private getCapabilityConfig(\n capabilityId: string,\n bodyCapability?: CapabilityConfig,\n ): CapabilityConfig {\n if (bodyCapability) {\n return bodyCapability;\n }\n\n const config = this.capabilityService.getCapability(capabilityId);\n if (!config) {\n throw new HttpException(\n {\n code: 1,\n message: `Capability not found: ${capabilityId}`,\n error: 'CAPABILITY_NOT_FOUND',\n },\n HttpStatus.NOT_FOUND,\n );\n }\n\n return config;\n }\n\n /**\n * 获取 action 名称\n * 优先使用传入的 action,否则使用插件第一个 action\n */\n private async getActionName(pluginID: string, bodyAction?: string): Promise<string> {\n if (bodyAction) {\n return bodyAction;\n }\n\n const pluginInstance = await this.pluginLoaderService.loadPlugin(pluginID);\n const actions = pluginInstance.listActions();\n\n if (actions.length === 0) {\n throw new HttpException(\n {\n code: 1,\n message: `Plugin ${pluginID} has no actions`,\n error: 'NO_ACTIONS',\n },\n HttpStatus.BAD_REQUEST,\n );\n }\n\n return actions[0];\n }\n\n @Post('debug/:capability_id')\n async debug(\n @Param('capability_id') capabilityId: string,\n @Body() body: DebugRequestBody,\n ): Promise<DebugResponse> {\n const startTime = Date.now();\n const params = body.params ?? {};\n\n const config = this.getCapabilityConfig(capabilityId, body.capability);\n const action = await this.getActionName(config.pluginID, body.action);\n\n const resolvedParams = this.templateEngineService.resolve(\n config.formValue,\n params,\n );\n\n try {\n const result = await this.capabilityService\n .loadWithConfig(config)\n .call(action, params);\n\n return {\n code: 0,\n message: 'success',\n data: result,\n debug: {\n capabilityConfig: config,\n resolvedParams,\n duration: Date.now() - startTime,\n pluginID: config.pluginID,\n action,\n },\n };\n } catch (error) {\n const duration = Date.now() - startTime;\n\n if (error instanceof CapabilityNotFoundError) {\n throw new HttpException(\n {\n code: 1,\n message: error.message,\n error: 'CAPABILITY_NOT_FOUND',\n debug: { duration },\n },\n HttpStatus.NOT_FOUND,\n );\n }\n\n if (error instanceof PluginNotFoundError) {\n throw new HttpException(\n {\n code: 1,\n message: error.message,\n error: 'PLUGIN_NOT_FOUND',\n debug: { duration, pluginID: config.pluginID, action },\n },\n HttpStatus.INTERNAL_SERVER_ERROR,\n );\n }\n\n if (error instanceof ActionNotFoundError) {\n throw new HttpException(\n {\n code: 1,\n message: error.message,\n error: 'ACTION_NOT_FOUND',\n debug: { duration, pluginID: config.pluginID, action },\n },\n HttpStatus.BAD_REQUEST,\n );\n }\n\n throw new HttpException(\n {\n code: 1,\n message: error instanceof Error ? error.message : String(error),\n error: 'EXECUTION_ERROR',\n debug: {\n duration,\n pluginID: config.pluginID,\n action,\n resolvedParams,\n },\n },\n HttpStatus.INTERNAL_SERVER_ERROR,\n );\n }\n }\n\n @Post('debug/:capability_id/stream')\n async debugStream(\n @Param('capability_id') capabilityId: string,\n @Body() body: DebugRequestBody,\n @Res() res: Response,\n ): Promise<void> {\n const params = body.params ?? {};\n\n // 设置 SSE 响应头\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n\n try {\n const config = this.getCapabilityConfig(capabilityId, body.capability);\n const action = await this.getActionName(config.pluginID, body.action);\n\n const capability = this.capabilityService.loadWithConfig(config);\n const stream = capability.callStream(action, params);\n\n for await (const chunk of stream) {\n res.write(`data: ${JSON.stringify(chunk)}\\n\\n`);\n }\n\n // 发送结束标记\n res.write('data: [DONE]\\n\\n');\n } catch (error) {\n // 错误时发送错误信息\n const message = error instanceof Error ? error.message : String(error);\n let errorCode = 'EXECUTION_ERROR';\n\n if (error instanceof CapabilityNotFoundError) {\n errorCode = 'CAPABILITY_NOT_FOUND';\n } else if (error instanceof PluginNotFoundError) {\n errorCode = 'PLUGIN_NOT_FOUND';\n } else if (error instanceof ActionNotFoundError) {\n errorCode = 'ACTION_NOT_FOUND';\n } else if (error instanceof HttpException) {\n const response = error.getResponse() as { error?: string };\n errorCode = response.error ?? 'EXECUTION_ERROR';\n }\n\n res.write(`data: ${JSON.stringify({ error: message, code: errorCode })}\\n\\n`);\n } finally {\n res.end();\n }\n }\n}\n","import {\n Controller,\n Get,\n Post,\n Param,\n Body,\n Res,\n HttpException,\n HttpStatus,\n} from '@nestjs/common';\nimport type { Response } from 'express';\nimport {\n CapabilityService,\n CapabilityNotFoundError,\n ActionNotFoundError,\n} from '../services/capability.service';\nimport { PluginNotFoundError } from '../services/plugin-loader.service';\n\ninterface ExecuteRequestBody {\n action: string;\n params: Record<string, unknown>;\n}\n\ninterface ExecuteResponse {\n code: number;\n message: string;\n data: unknown;\n}\n\ninterface CapabilityInfo {\n id: string;\n name: string;\n description: string;\n pluginID: string;\n pluginVersion: string;\n}\n\ninterface ListResponse {\n code: number;\n message: string;\n data: CapabilityInfo[];\n}\n\n@Controller('api/capability')\nexport class WebhookController {\n constructor(private readonly capabilityService: CapabilityService) {}\n\n @Get('list')\n list(): ListResponse {\n const capabilities = this.capabilityService.listCapabilities();\n return {\n code: 0,\n message: 'success',\n data: capabilities.map(c => ({\n id: c.id,\n name: c.name,\n description: c.description,\n pluginID: c.pluginID,\n pluginVersion: c.pluginVersion,\n })),\n };\n }\n\n @Post(':capability_id')\n async execute(\n @Param('capability_id') capabilityId: string,\n @Body() body: ExecuteRequestBody,\n ): Promise<ExecuteResponse> {\n try {\n const result = await this.capabilityService\n .load(capabilityId)\n .call(body.action, body.params);\n\n return {\n code: 0,\n message: 'success',\n data: result,\n };\n } catch (error) {\n if (error instanceof CapabilityNotFoundError) {\n throw new HttpException(\n {\n code: 1,\n message: error.message,\n error: 'CAPABILITY_NOT_FOUND',\n },\n HttpStatus.NOT_FOUND,\n );\n }\n\n if (error instanceof PluginNotFoundError) {\n throw new HttpException(\n {\n code: 1,\n message: error.message,\n error: 'PLUGIN_NOT_FOUND',\n },\n HttpStatus.INTERNAL_SERVER_ERROR,\n );\n }\n\n if (error instanceof ActionNotFoundError) {\n throw new HttpException(\n {\n code: 1,\n message: error.message,\n error: 'ACTION_NOT_FOUND',\n },\n HttpStatus.BAD_REQUEST,\n );\n }\n\n throw new HttpException(\n {\n code: 1,\n message: error instanceof Error ? error.message : String(error),\n error: 'EXECUTION_ERROR',\n },\n HttpStatus.INTERNAL_SERVER_ERROR,\n );\n }\n }\n\n @Post(':capability_id/stream')\n async executeStream(\n @Param('capability_id') capabilityId: string,\n @Body() body: ExecuteRequestBody,\n @Res() res: Response,\n ): Promise<void> {\n // 设置 SSE 响应头\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n\n try {\n const capability = this.capabilityService.load(capabilityId);\n const stream = capability.callStream(body.action, body.params);\n\n for await (const chunk of stream) {\n res.write(`data: ${JSON.stringify(chunk)}\\n\\n`);\n }\n\n // 发送结束标记\n res.write('data: [DONE]\\n\\n');\n } catch (error) {\n // 错误时发送错误信息\n const message = error instanceof Error ? error.message : String(error);\n let errorCode = 'EXECUTION_ERROR';\n\n if (error instanceof CapabilityNotFoundError) {\n errorCode = 'CAPABILITY_NOT_FOUND';\n } else if (error instanceof PluginNotFoundError) {\n errorCode = 'PLUGIN_NOT_FOUND';\n } else if (error instanceof ActionNotFoundError) {\n errorCode = 'ACTION_NOT_FOUND';\n }\n\n res.write(`data: ${JSON.stringify({ error: message, code: errorCode })}\\n\\n`);\n } finally {\n res.end();\n }\n }\n}\n","import { Module, DynamicModule, Type } from '@nestjs/common';\nimport {\n RequestContextService,\n PLATFORM_HTTP_CLIENT,\n} from '@lark-apaas/nestjs-common';\nimport { DebugController, WebhookController } from './controllers';\nimport {\n CapabilityService,\n PluginLoaderService,\n TemplateEngineService,\n type CapabilityModuleOptions,\n} from './services';\n\nconst CAPABILITY_OPTIONS = Symbol('CAPABILITY_OPTIONS');\n\nconst isDevelopment = process.env.NODE_ENV === 'development';\n\nfunction getControllers(): Type[] {\n const controllers: Type[] = [WebhookController];\n if (isDevelopment) {\n controllers.push(DebugController);\n }\n return controllers;\n}\n\n@Module({\n controllers: getControllers(),\n providers: [CapabilityService, PluginLoaderService, TemplateEngineService],\n exports: [CapabilityService],\n})\nexport class CapabilityModule {\n static forRoot(options?: CapabilityModuleOptions): DynamicModule {\n return {\n module: CapabilityModule,\n controllers: getControllers(),\n providers: [\n {\n provide: CAPABILITY_OPTIONS,\n useValue: options ?? {},\n },\n {\n provide: CapabilityService,\n useFactory: (\n requestContextService: RequestContextService,\n httpClient: any,\n pluginLoader: PluginLoaderService,\n templateEngine: TemplateEngineService,\n moduleOptions: CapabilityModuleOptions,\n ) => {\n const service = new CapabilityService(\n requestContextService,\n httpClient,\n pluginLoader,\n templateEngine,\n );\n if (moduleOptions?.capabilitiesDir) {\n service.setCapabilitiesDir(moduleOptions.capabilitiesDir);\n }\n return service;\n },\n inject: [\n RequestContextService,\n PLATFORM_HTTP_CLIENT,\n PluginLoaderService,\n TemplateEngineService,\n CAPABILITY_OPTIONS,\n ],\n },\n PluginLoaderService,\n TemplateEngineService,\n ],\n exports: [CapabilityService],\n };\n }\n}\n"],"mappings":"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","names":["Injectable","TemplateEngineService","EXPR_REGEX","WHOLE_STRING_EXPR_REGEX","resolve","template","input","resolveString","Array","isArray","map","item","resolveObject","wholeMatch","match","path","value","getValueByPath","undefined","lastIndex","test","result","replace","String","key","Object","entries","obj","keys","split","current","Injectable","Logger","PluginNotFoundError","Error","pluginID","name","PluginLoadError","reason","PluginLoaderService","logger","Logger","pluginInstances","Map","loadPlugin","cached","get","debug","log","pluginPackage","default","create","instance","set","error","code","message","String","isPluginInstalled","require","resolve","clearCache","delete","clear","Injectable","Logger","Inject","RequestContextService","PLATFORM_HTTP_CLIENT","fs","path","CapabilityNotFoundError","Error","capabilityId","name","ActionNotFoundError","pluginID","actionName","CapabilityService","logger","Logger","capabilities","Map","capabilitiesDir","requestContextService","httpClient","pluginLoaderService","templateEngineService","join","process","cwd","setCapabilitiesDir","dir","onModuleInit","loadCapabilities","log","existsSync","warn","files","readdirSync","filter","f","endsWith","file","filePath","content","readFileSync","config","JSON","parse","id","set","error","size","listCapabilities","Array","from","values","getCapability","get","load","createExecutor","loadWithConfig","call","input","contextOverride","executeCall","callStream","executeCallStream","isStream","checkIsStream","pluginInstance","loadPlugin","hasAction","isStreamAction","startTime","Date","now","resolvedParams","resolve","formValue","context","buildActionContext","message","action","result","runStream","chunks","chunk","push","aggregate","run","duration","String","override","userContext","getUserContext","ctx","getContext","userId","tenantId","Controller","Post","Get","Param","Body","Res","HttpException","HttpStatus","DebugController","capabilityService","pluginLoaderService","templateEngineService","list","capabilities","listCapabilities","code","message","data","map","c","id","name","pluginID","pluginVersion","getCapabilityConfig","capabilityId","bodyCapability","config","getCapability","HttpException","error","HttpStatus","NOT_FOUND","getActionName","bodyAction","pluginInstance","loadPlugin","actions","listActions","length","BAD_REQUEST","debug","body","startTime","Date","now","params","capability","action","resolvedParams","resolve","formValue","result","loadWithConfig","call","capabilityConfig","duration","CapabilityNotFoundError","PluginNotFoundError","INTERNAL_SERVER_ERROR","ActionNotFoundError","Error","String","debugStream","res","setHeader","stream","callStream","chunk","write","JSON","stringify","errorCode","response","getResponse","end","Controller","Get","Post","Param","Body","Res","HttpException","HttpStatus","WebhookController","capabilityService","list","capabilities","listCapabilities","code","message","data","map","c","id","name","description","pluginID","pluginVersion","execute","capabilityId","body","result","load","call","action","params","error","CapabilityNotFoundError","HttpException","HttpStatus","NOT_FOUND","PluginNotFoundError","INTERNAL_SERVER_ERROR","ActionNotFoundError","BAD_REQUEST","Error","String","executeStream","res","setHeader","capability","stream","callStream","chunk","write","JSON","stringify","errorCode","end","Module","RequestContextService","PLATFORM_HTTP_CLIENT","CAPABILITY_OPTIONS","Symbol","isDevelopment","process","env","NODE_ENV","getControllers","controllers","WebhookController","push","DebugController","CapabilityModule","forRoot","options","module","providers","provide","useValue","CapabilityService","useFactory","requestContextService","httpClient","pluginLoader","templateEngine","moduleOptions","service","capabilitiesDir","setCapabilitiesDir","inject","RequestContextService","PLATFORM_HTTP_CLIENT","PluginLoaderService","TemplateEngineService","exports"]}
1
+ {"version":3,"sources":["../src/services/template-engine.service.ts","../src/services/plugin-loader.service.ts","../src/services/capability.service.ts","../src/controllers/debug.controller.ts","../src/controllers/webhook.controller.ts","../src/capability.module.ts"],"sourcesContent":["import { Injectable } from '@nestjs/common';\n\n/**\n * 模板引擎服务\n *\n * 支持语法:\n * - expr: '{{' + selector + '}}'\n * - selector: 'input.' + ident | selector.ident\n * - ident: [a-zA-Z_]([a-zA-Z_0-9])*\n *\n * 示例:\n * - {{input.a}}\n * - {{input.a.b}}\n * - \"this is {{input.a.b}}\"\n *\n * 求值规则:\n * - 如果整个字符串是单个表达式,保留原始类型\n * - 如果是字符串插值(多个表达式或混合内容),返回字符串\n * - 如果变量不存在,返回原始表达式\n */\n@Injectable()\nexport class TemplateEngineService {\n // 匹配 {{input.xxx}} 或 {{input.xxx.yyy}} 表达式\n private readonly EXPR_REGEX = /\\{\\{input\\.([a-zA-Z_][a-zA-Z_0-9]*(?:\\.[a-zA-Z_][a-zA-Z_0-9]*)*)\\}\\}/g;\n // 匹配整串单个表达式\n private readonly WHOLE_STRING_EXPR_REGEX = /^\\{\\{input\\.([a-zA-Z_][a-zA-Z_0-9]*(?:\\.[a-zA-Z_][a-zA-Z_0-9]*)*)\\}\\}$/;\n\n resolve(template: unknown, input: Record<string, unknown>): unknown {\n if (typeof template === 'string') {\n return this.resolveString(template, input);\n }\n\n if (Array.isArray(template)) {\n return template.map(item => this.resolve(item, input));\n }\n\n if (template !== null && typeof template === 'object') {\n return this.resolveObject(template as Record<string, unknown>, input);\n }\n\n return template;\n }\n\n private resolveString(template: string, input: Record<string, unknown>): unknown {\n // 情况1: 整串是单个表达式 → 保留原始类型\n const wholeMatch = template.match(this.WHOLE_STRING_EXPR_REGEX);\n if (wholeMatch) {\n const path = wholeMatch[1];\n const value = this.getValueByPath(input, path);\n // 变量不存在,返回原始表达式\n return value !== undefined ? value : template;\n }\n\n // 情况2: 字符串插值 → 返回字符串\n // 重置正则的 lastIndex(因为使用了 g 标志)\n this.EXPR_REGEX.lastIndex = 0;\n\n // 检查是否有任何表达式\n if (!this.EXPR_REGEX.test(template)) {\n return template;\n }\n\n // 重置并进行替换\n this.EXPR_REGEX.lastIndex = 0;\n const result = template.replace(this.EXPR_REGEX, (match, path) => {\n const value = this.getValueByPath(input, path);\n // 变量不存在,保留原始表达式\n if (value === undefined) {\n return match;\n }\n return String(value);\n });\n\n return result;\n }\n\n private resolveObject(\n template: Record<string, unknown>,\n input: Record<string, unknown>,\n ): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(template)) {\n result[key] = this.resolve(value, input);\n }\n\n return result;\n }\n\n private getValueByPath(obj: Record<string, unknown>, path: string): unknown {\n const keys = path.split('.');\n let current: unknown = obj;\n\n for (const key of keys) {\n if (current === null || current === undefined) {\n return undefined;\n }\n current = (current as Record<string, unknown>)[key];\n }\n\n return current;\n }\n}\n","import { Injectable, Logger } from '@nestjs/common';\nimport type { PluginInstance, PluginPackage } from '../interfaces';\n\nexport class PluginNotFoundError extends Error {\n constructor(pluginKey: string) {\n super(`Plugin not found: ${pluginKey}`);\n this.name = 'PluginNotFoundError';\n }\n}\n\nexport class PluginLoadError extends Error {\n constructor(pluginKey: string, reason: string) {\n super(`Failed to load plugin ${pluginKey}: ${reason}`);\n this.name = 'PluginLoadError';\n }\n}\n\n@Injectable()\nexport class PluginLoaderService {\n private readonly logger = new Logger(PluginLoaderService.name);\n private readonly pluginInstances = new Map<string, PluginInstance>();\n\n async loadPlugin(pluginKey: string): Promise<PluginInstance> {\n const cached = this.pluginInstances.get(pluginKey);\n if (cached) {\n this.logger.debug(`Using cached plugin instance: ${pluginKey}`);\n return cached;\n }\n\n this.logger.log(`Loading plugin: ${pluginKey}`);\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const pluginPackage = (await import(pluginKey)).default as PluginPackage;\n\n if (typeof pluginPackage.create !== 'function') {\n throw new PluginLoadError(pluginKey, 'Plugin does not export create() function');\n }\n\n const instance = pluginPackage.create();\n this.pluginInstances.set(pluginKey, instance);\n\n this.logger.log(`Plugin loaded successfully: ${pluginKey}`);\n return instance;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'MODULE_NOT_FOUND') {\n throw new PluginNotFoundError(pluginKey);\n }\n throw new PluginLoadError(\n pluginKey,\n error instanceof Error ? error.message : String(error),\n );\n }\n }\n\n isPluginInstalled(pluginKey: string): boolean {\n try {\n require.resolve(pluginKey);\n return true;\n } catch {\n return false;\n }\n }\n\n clearCache(pluginKey?: string): void {\n if (pluginKey) {\n this.pluginInstances.delete(pluginKey);\n this.logger.log(`Cleared cache for plugin: ${pluginKey}`);\n } else {\n this.pluginInstances.clear();\n this.logger.log('Cleared all plugin caches');\n }\n }\n}\n","import { Injectable, Logger, Inject, OnModuleInit } from '@nestjs/common';\nimport {\n RequestContextService,\n PLATFORM_HTTP_CLIENT,\n type PlatformHttpClient,\n} from '@lark-apaas/nestjs-common';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { CapabilityConfig, PluginActionContext, UserContext } from '../interfaces';\nimport { PluginLoaderService } from './plugin-loader.service';\nimport { TemplateEngineService } from './template-engine.service';\n\nexport class CapabilityNotFoundError extends Error {\n constructor(capabilityId: string) {\n super(`Capability not found: ${capabilityId}`);\n this.name = 'CapabilityNotFoundError';\n }\n}\n\nexport class ActionNotFoundError extends Error {\n constructor(pluginKey: string, actionName: string) {\n super(`Action '${actionName}' not found in plugin ${pluginKey}`);\n this.name = 'ActionNotFoundError';\n }\n}\n\nexport interface CapabilityExecutor {\n /**\n * 调用 capability(始终返回 Promise)\n * - unary action: 直接返回结果\n * - stream action: 内部聚合所有 chunk 后返回\n */\n call(actionName: string, input: unknown, context?: Partial<PluginActionContext>): Promise<unknown>;\n\n /**\n * 流式调用 capability\n * - 返回原始 AsyncIterable\n * - 如果 action 是 unary,包装为单次 yield\n */\n callStream(actionName: string, input: unknown, context?: Partial<PluginActionContext>): AsyncIterable<unknown>;\n\n /**\n * 检查 action 是否为流式\n */\n isStream(actionName: string): Promise<boolean>;\n}\n\nexport interface CapabilityModuleOptions {\n capabilitiesDir?: string;\n}\n\n@Injectable()\nexport class CapabilityService implements OnModuleInit {\n private readonly logger = new Logger(CapabilityService.name);\n private readonly capabilities = new Map<string, CapabilityConfig>();\n private capabilitiesDir: string;\n\n constructor(\n private readonly requestContextService: RequestContextService,\n @Inject(PLATFORM_HTTP_CLIENT) private readonly httpClient: PlatformHttpClient,\n private readonly pluginLoaderService: PluginLoaderService,\n private readonly templateEngineService: TemplateEngineService,\n ) {\n this.capabilitiesDir = path.join(process.cwd(), 'server/capabilities');\n }\n\n setCapabilitiesDir(dir: string): void {\n this.capabilitiesDir = dir;\n }\n\n async onModuleInit(): Promise<void> {\n await this.loadCapabilities();\n }\n\n private async loadCapabilities(): Promise<void> {\n this.logger.log(`Loading capabilities from ${this.capabilitiesDir}`);\n\n if (!fs.existsSync(this.capabilitiesDir)) {\n this.logger.warn(`Capabilities directory not found: ${this.capabilitiesDir}`);\n return;\n }\n\n const files = fs.readdirSync(this.capabilitiesDir).filter(f => f.endsWith('.json'));\n\n for (const file of files) {\n try {\n const filePath = path.join(this.capabilitiesDir, file);\n const content = fs.readFileSync(filePath, 'utf-8');\n const config = JSON.parse(content) as CapabilityConfig;\n\n if (!config.id) {\n this.logger.warn(`Skipping capability without id: ${file}`);\n continue;\n }\n\n this.capabilities.set(config.id, config);\n this.logger.log(`Loaded capability: ${config.id} (${config.name})`);\n } catch (error) {\n this.logger.error(`Failed to load capability from ${file}:`, error);\n }\n }\n\n this.logger.log(`Loaded ${this.capabilities.size} capabilities`);\n }\n\n listCapabilities(): CapabilityConfig[] {\n return Array.from(this.capabilities.values());\n }\n\n getCapability(capabilityId: string): CapabilityConfig | null {\n return this.capabilities.get(capabilityId) ?? null;\n }\n\n load(capabilityId: string): CapabilityExecutor {\n const config = this.capabilities.get(capabilityId);\n if (!config) {\n throw new CapabilityNotFoundError(capabilityId);\n }\n\n return this.createExecutor(config);\n }\n\n /**\n * 使用传入的配置加载能力执行器\n * 用于 debug 场景,支持用户传入自定义配置\n */\n loadWithConfig(config: CapabilityConfig): CapabilityExecutor {\n return this.createExecutor(config);\n }\n\n private createExecutor(config: CapabilityConfig): CapabilityExecutor {\n return {\n call: async (\n actionName: string,\n input: unknown,\n contextOverride?: Partial<PluginActionContext>,\n ) => {\n return this.executeCall(config, actionName, input, contextOverride);\n },\n\n callStream: (\n actionName: string,\n input: unknown,\n contextOverride?: Partial<PluginActionContext>,\n ) => {\n return this.executeCallStream(config, actionName, input, contextOverride);\n },\n\n isStream: async (actionName: string) => {\n return this.checkIsStream(config, actionName);\n },\n };\n }\n\n /**\n * 检查 action 是否为流式\n */\n private async checkIsStream(config: CapabilityConfig, actionName: string): Promise<boolean> {\n const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginKey);\n\n if (!pluginInstance.hasAction(actionName)) {\n throw new ActionNotFoundError(config.pluginKey, actionName);\n }\n\n return pluginInstance.isStreamAction?.(actionName) ?? false;\n }\n\n /**\n * 执行 capability(始终返回 Promise)\n * - unary action: 直接返回结果\n * - stream action: 内部聚合所有 chunk 后返回\n */\n private async executeCall(\n config: CapabilityConfig,\n actionName: string,\n input: unknown,\n contextOverride?: Partial<PluginActionContext>,\n ): Promise<unknown> {\n const startTime = Date.now();\n\n try {\n const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginKey);\n\n if (!pluginInstance.hasAction(actionName)) {\n throw new ActionNotFoundError(config.pluginKey, actionName);\n }\n\n const resolvedParams = this.templateEngineService.resolve(\n config.formValue,\n input as Record<string, unknown>,\n );\n\n const context = this.buildActionContext(contextOverride);\n const isStream = pluginInstance.isStreamAction?.(actionName) ?? false;\n\n this.logger.log({\n message: 'Executing capability',\n capabilityId: config.id,\n action: actionName,\n pluginKey: config.pluginKey,\n isStream,\n });\n\n let result: unknown;\n\n if (isStream && pluginInstance.runStream) {\n // 流式 action:聚合所有 chunk\n const chunks: unknown[] = [];\n for await (const chunk of pluginInstance.runStream(actionName, context, resolvedParams)) {\n chunks.push(chunk);\n }\n // 使用插件的聚合方法,或默认返回 chunks 数组\n result = pluginInstance.aggregate\n ? pluginInstance.aggregate(actionName, chunks)\n : chunks;\n } else {\n // 非流式 action:直接调用\n result = await pluginInstance.run(actionName, context, resolvedParams);\n }\n\n this.logger.log({\n message: 'Capability executed successfully',\n capabilityId: config.id,\n action: actionName,\n duration: Date.now() - startTime,\n });\n\n return result;\n } catch (error) {\n this.logger.error({\n message: 'Capability execution failed',\n capabilityId: config.id,\n action: actionName,\n error: error instanceof Error ? error.message : String(error),\n duration: Date.now() - startTime,\n });\n throw error;\n }\n }\n\n /**\n * 流式执行 capability\n * - stream action: 返回原始 AsyncIterable\n * - unary action: 包装为单次 yield\n */\n private async *executeCallStream(\n config: CapabilityConfig,\n actionName: string,\n input: unknown,\n contextOverride?: Partial<PluginActionContext>,\n ): AsyncIterable<unknown> {\n const startTime = Date.now();\n\n try {\n const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginKey);\n\n if (!pluginInstance.hasAction(actionName)) {\n throw new ActionNotFoundError(config.pluginKey, actionName);\n }\n\n const resolvedParams = this.templateEngineService.resolve(\n config.formValue,\n input as Record<string, unknown>,\n );\n\n const context = this.buildActionContext(contextOverride);\n const isStream = pluginInstance.isStreamAction?.(actionName) ?? false;\n\n this.logger.log({\n message: 'Executing capability (stream)',\n capabilityId: config.id,\n action: actionName,\n pluginKey: config.pluginKey,\n isStream,\n });\n\n if (isStream && pluginInstance.runStream) {\n // 流式 action:透传 AsyncIterable\n yield* pluginInstance.runStream(actionName, context, resolvedParams);\n } else {\n // 非流式 action:包装为单次 yield\n const result = await pluginInstance.run(actionName, context, resolvedParams);\n yield result;\n }\n\n this.logger.log({\n message: 'Capability stream completed',\n capabilityId: config.id,\n action: actionName,\n duration: Date.now() - startTime,\n });\n } catch (error) {\n this.logger.error({\n message: 'Capability stream execution failed',\n capabilityId: config.id,\n action: actionName,\n error: error instanceof Error ? error.message : String(error),\n duration: Date.now() - startTime,\n });\n throw error;\n }\n }\n\n private buildActionContext(override?: Partial<PluginActionContext>): PluginActionContext {\n return {\n logger: this.logger,\n httpClient: this.httpClient,\n userContext: override?.userContext ?? this.getUserContext(),\n };\n }\n\n private getUserContext(): UserContext {\n const ctx = this.requestContextService.getContext();\n return {\n userId: ctx?.userId ?? '',\n tenantId: ctx?.tenantId ?? '',\n };\n }\n}\n","import {\n Controller,\n Post,\n Get,\n Param,\n Body,\n Res,\n HttpException,\n HttpStatus,\n} from '@nestjs/common';\nimport type { Response } from 'express';\nimport {\n CapabilityService,\n CapabilityNotFoundError,\n ActionNotFoundError,\n} from '../services/capability.service';\nimport { PluginLoaderService, PluginNotFoundError } from '../services/plugin-loader.service';\nimport { TemplateEngineService } from '../services/template-engine.service';\nimport type { CapabilityConfig } from '../interfaces';\n\ninterface DebugRequestBody {\n action?: string;\n params?: Record<string, unknown>;\n capability?: CapabilityConfig;\n}\n\ninterface DebugResponse {\n code: number;\n message: string;\n data: unknown;\n debug?: {\n capabilityConfig: unknown;\n resolvedParams: unknown;\n duration: number;\n pluginKey: string;\n action: string;\n };\n}\n\ninterface ListResponse {\n code: number;\n message: string;\n data: Array<{\n id: string;\n name: string;\n pluginKey: string;\n pluginVersion: string;\n }>;\n}\n\n@Controller('__innerapi__/capability')\nexport class DebugController {\n constructor(\n private readonly capabilityService: CapabilityService,\n private readonly pluginLoaderService: PluginLoaderService,\n private readonly templateEngineService: TemplateEngineService,\n ) {}\n\n @Get('list')\n list(): ListResponse {\n const capabilities = this.capabilityService.listCapabilities();\n\n return {\n code: 0,\n message: 'success',\n data: capabilities.map(c => ({\n id: c.id,\n name: c.name,\n pluginKey: c.pluginKey,\n pluginVersion: c.pluginVersion,\n })),\n };\n }\n\n /**\n * 获取 capability 配置\n * 优先使用 body.capability,否则从服务获取\n */\n private getCapabilityConfig(\n capabilityId: string,\n bodyCapability?: CapabilityConfig,\n ): CapabilityConfig {\n if (bodyCapability) {\n return bodyCapability;\n }\n\n const config = this.capabilityService.getCapability(capabilityId);\n if (!config) {\n throw new HttpException(\n {\n code: 1,\n message: `Capability not found: ${capabilityId}`,\n error: 'CAPABILITY_NOT_FOUND',\n },\n HttpStatus.NOT_FOUND,\n );\n }\n\n return config;\n }\n\n /**\n * 获取 action 名称\n * 优先使用传入的 action,否则使用插件第一个 action\n */\n private async getActionName(pluginKey: string, bodyAction?: string): Promise<string> {\n if (bodyAction) {\n return bodyAction;\n }\n\n const pluginInstance = await this.pluginLoaderService.loadPlugin(pluginKey);\n const actions = pluginInstance.listActions();\n\n if (actions.length === 0) {\n throw new HttpException(\n {\n code: 1,\n message: `Plugin ${pluginKey} has no actions`,\n error: 'NO_ACTIONS',\n },\n HttpStatus.BAD_REQUEST,\n );\n }\n\n return actions[0];\n }\n\n @Post('debug/:capability_id')\n async debug(\n @Param('capability_id') capabilityId: string,\n @Body() body: DebugRequestBody,\n ): Promise<DebugResponse> {\n const startTime = Date.now();\n const params = body.params ?? {};\n\n const config = this.getCapabilityConfig(capabilityId, body.capability);\n const action = await this.getActionName(config.pluginKey, body.action);\n\n const resolvedParams = this.templateEngineService.resolve(\n config.formValue,\n params,\n );\n\n try {\n const result = await this.capabilityService\n .loadWithConfig(config)\n .call(action, params);\n\n return {\n code: 0,\n message: 'success',\n data: result,\n debug: {\n capabilityConfig: config,\n resolvedParams,\n duration: Date.now() - startTime,\n pluginKey: config.pluginKey,\n action,\n },\n };\n } catch (error) {\n const duration = Date.now() - startTime;\n\n if (error instanceof CapabilityNotFoundError) {\n throw new HttpException(\n {\n code: 1,\n message: error.message,\n error: 'CAPABILITY_NOT_FOUND',\n debug: { duration },\n },\n HttpStatus.NOT_FOUND,\n );\n }\n\n if (error instanceof PluginNotFoundError) {\n throw new HttpException(\n {\n code: 1,\n message: error.message,\n error: 'PLUGIN_NOT_FOUND',\n debug: { duration, pluginKey: config.pluginKey, action },\n },\n HttpStatus.INTERNAL_SERVER_ERROR,\n );\n }\n\n if (error instanceof ActionNotFoundError) {\n throw new HttpException(\n {\n code: 1,\n message: error.message,\n error: 'ACTION_NOT_FOUND',\n debug: { duration, pluginKey: config.pluginKey, action },\n },\n HttpStatus.BAD_REQUEST,\n );\n }\n\n throw new HttpException(\n {\n code: 1,\n message: error instanceof Error ? error.message : String(error),\n error: 'EXECUTION_ERROR',\n debug: {\n duration,\n pluginKey: config.pluginKey,\n action,\n resolvedParams,\n },\n },\n HttpStatus.INTERNAL_SERVER_ERROR,\n );\n }\n }\n\n @Post('debug/:capability_id/stream')\n async debugStream(\n @Param('capability_id') capabilityId: string,\n @Body() body: DebugRequestBody,\n @Res() res: Response,\n ): Promise<void> {\n const params = body.params ?? {};\n\n // 设置 SSE 响应头\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n\n try {\n const config = this.getCapabilityConfig(capabilityId, body.capability);\n const action = await this.getActionName(config.pluginKey, body.action);\n\n const capability = this.capabilityService.loadWithConfig(config);\n const stream = capability.callStream(action, params);\n\n for await (const chunk of stream) {\n res.write(`data: ${JSON.stringify(chunk)}\\n\\n`);\n }\n\n // 发送结束标记\n res.write('data: [DONE]\\n\\n');\n } catch (error) {\n // 错误时发送错误信息\n const message = error instanceof Error ? error.message : String(error);\n let errorCode = 'EXECUTION_ERROR';\n\n if (error instanceof CapabilityNotFoundError) {\n errorCode = 'CAPABILITY_NOT_FOUND';\n } else if (error instanceof PluginNotFoundError) {\n errorCode = 'PLUGIN_NOT_FOUND';\n } else if (error instanceof ActionNotFoundError) {\n errorCode = 'ACTION_NOT_FOUND';\n } else if (error instanceof HttpException) {\n const response = error.getResponse() as { error?: string };\n errorCode = response.error ?? 'EXECUTION_ERROR';\n }\n\n res.write(`data: ${JSON.stringify({ error: message, code: errorCode })}\\n\\n`);\n } finally {\n res.end();\n }\n }\n}\n","import {\n Controller,\n Get,\n Post,\n Param,\n Body,\n Res,\n HttpException,\n HttpStatus,\n} from '@nestjs/common';\nimport type { Response } from 'express';\nimport {\n CapabilityService,\n CapabilityNotFoundError,\n ActionNotFoundError,\n} from '../services/capability.service';\nimport { PluginNotFoundError } from '../services/plugin-loader.service';\n\ninterface ExecuteRequestBody {\n action: string;\n params: Record<string, unknown>;\n}\n\ninterface ExecuteResponse {\n code: number;\n message: string;\n data: unknown;\n}\n\ninterface CapabilityInfo {\n id: string;\n name: string;\n description: string;\n pluginKey: string;\n pluginVersion: string;\n}\n\ninterface ListResponse {\n code: number;\n message: string;\n data: CapabilityInfo[];\n}\n\n@Controller('api/capability')\nexport class WebhookController {\n constructor(private readonly capabilityService: CapabilityService) {}\n\n @Get('list')\n list(): ListResponse {\n const capabilities = this.capabilityService.listCapabilities();\n return {\n code: 0,\n message: 'success',\n data: capabilities.map(c => ({\n id: c.id,\n name: c.name,\n description: c.description,\n pluginKey: c.pluginKey,\n pluginVersion: c.pluginVersion,\n })),\n };\n }\n\n @Post(':capability_id')\n async execute(\n @Param('capability_id') capabilityId: string,\n @Body() body: ExecuteRequestBody,\n ): Promise<ExecuteResponse> {\n try {\n const result = await this.capabilityService\n .load(capabilityId)\n .call(body.action, body.params);\n\n return {\n code: 0,\n message: 'success',\n data: result,\n };\n } catch (error) {\n if (error instanceof CapabilityNotFoundError) {\n throw new HttpException(\n {\n code: 1,\n message: error.message,\n error: 'CAPABILITY_NOT_FOUND',\n },\n HttpStatus.NOT_FOUND,\n );\n }\n\n if (error instanceof PluginNotFoundError) {\n throw new HttpException(\n {\n code: 1,\n message: error.message,\n error: 'PLUGIN_NOT_FOUND',\n },\n HttpStatus.INTERNAL_SERVER_ERROR,\n );\n }\n\n if (error instanceof ActionNotFoundError) {\n throw new HttpException(\n {\n code: 1,\n message: error.message,\n error: 'ACTION_NOT_FOUND',\n },\n HttpStatus.BAD_REQUEST,\n );\n }\n\n throw new HttpException(\n {\n code: 1,\n message: error instanceof Error ? error.message : String(error),\n error: 'EXECUTION_ERROR',\n },\n HttpStatus.INTERNAL_SERVER_ERROR,\n );\n }\n }\n\n @Post(':capability_id/stream')\n async executeStream(\n @Param('capability_id') capabilityId: string,\n @Body() body: ExecuteRequestBody,\n @Res() res: Response,\n ): Promise<void> {\n // 设置 SSE 响应头\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n\n try {\n const capability = this.capabilityService.load(capabilityId);\n const stream = capability.callStream(body.action, body.params);\n\n for await (const chunk of stream) {\n res.write(`data: ${JSON.stringify(chunk)}\\n\\n`);\n }\n\n // 发送结束标记\n res.write('data: [DONE]\\n\\n');\n } catch (error) {\n // 错误时发送错误信息\n const message = error instanceof Error ? error.message : String(error);\n let errorCode = 'EXECUTION_ERROR';\n\n if (error instanceof CapabilityNotFoundError) {\n errorCode = 'CAPABILITY_NOT_FOUND';\n } else if (error instanceof PluginNotFoundError) {\n errorCode = 'PLUGIN_NOT_FOUND';\n } else if (error instanceof ActionNotFoundError) {\n errorCode = 'ACTION_NOT_FOUND';\n }\n\n res.write(`data: ${JSON.stringify({ error: message, code: errorCode })}\\n\\n`);\n } finally {\n res.end();\n }\n }\n}\n","import { Module, DynamicModule, Type } from '@nestjs/common';\nimport {\n RequestContextService,\n PLATFORM_HTTP_CLIENT,\n} from '@lark-apaas/nestjs-common';\nimport { DebugController, WebhookController } from './controllers';\nimport {\n CapabilityService,\n PluginLoaderService,\n TemplateEngineService,\n type CapabilityModuleOptions,\n} from './services';\n\nconst CAPABILITY_OPTIONS = Symbol('CAPABILITY_OPTIONS');\n\nconst isDevelopment = process.env.NODE_ENV === 'development';\n\nfunction getControllers(): Type[] {\n const controllers: Type[] = [WebhookController];\n if (isDevelopment) {\n controllers.push(DebugController);\n }\n return controllers;\n}\n\n@Module({\n controllers: getControllers(),\n providers: [CapabilityService, PluginLoaderService, TemplateEngineService],\n exports: [CapabilityService],\n})\nexport class CapabilityModule {\n static forRoot(options?: CapabilityModuleOptions): DynamicModule {\n return {\n module: CapabilityModule,\n controllers: getControllers(),\n providers: [\n {\n provide: CAPABILITY_OPTIONS,\n useValue: options ?? {},\n },\n {\n provide: CapabilityService,\n useFactory: (\n requestContextService: RequestContextService,\n httpClient: any,\n pluginLoader: PluginLoaderService,\n templateEngine: TemplateEngineService,\n moduleOptions: CapabilityModuleOptions,\n ) => {\n const service = new CapabilityService(\n requestContextService,\n httpClient,\n pluginLoader,\n templateEngine,\n );\n if (moduleOptions?.capabilitiesDir) {\n service.setCapabilitiesDir(moduleOptions.capabilitiesDir);\n }\n return service;\n },\n inject: [\n RequestContextService,\n PLATFORM_HTTP_CLIENT,\n PluginLoaderService,\n TemplateEngineService,\n CAPABILITY_OPTIONS,\n ],\n },\n PluginLoaderService,\n TemplateEngineService,\n ],\n exports: [CapabilityService],\n };\n }\n}\n"],"mappings":"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","names":["Injectable","TemplateEngineService","EXPR_REGEX","WHOLE_STRING_EXPR_REGEX","resolve","template","input","resolveString","Array","isArray","map","item","resolveObject","wholeMatch","match","path","value","getValueByPath","undefined","lastIndex","test","result","replace","String","key","Object","entries","obj","keys","split","current","Injectable","Logger","PluginNotFoundError","Error","pluginKey","name","PluginLoadError","reason","PluginLoaderService","logger","Logger","pluginInstances","Map","loadPlugin","cached","get","debug","log","pluginPackage","default","create","instance","set","error","code","message","String","isPluginInstalled","require","resolve","clearCache","delete","clear","Injectable","Logger","Inject","RequestContextService","PLATFORM_HTTP_CLIENT","fs","path","CapabilityNotFoundError","Error","capabilityId","name","ActionNotFoundError","pluginKey","actionName","CapabilityService","logger","Logger","capabilities","Map","capabilitiesDir","requestContextService","httpClient","pluginLoaderService","templateEngineService","join","process","cwd","setCapabilitiesDir","dir","onModuleInit","loadCapabilities","log","existsSync","warn","files","readdirSync","filter","f","endsWith","file","filePath","content","readFileSync","config","JSON","parse","id","set","error","size","listCapabilities","Array","from","values","getCapability","get","load","createExecutor","loadWithConfig","call","input","contextOverride","executeCall","callStream","executeCallStream","isStream","checkIsStream","pluginInstance","loadPlugin","hasAction","isStreamAction","startTime","Date","now","resolvedParams","resolve","formValue","context","buildActionContext","message","action","result","runStream","chunks","chunk","push","aggregate","run","duration","String","override","userContext","getUserContext","ctx","getContext","userId","tenantId","Controller","Post","Get","Param","Body","Res","HttpException","HttpStatus","DebugController","capabilityService","pluginLoaderService","templateEngineService","list","capabilities","listCapabilities","code","message","data","map","c","id","name","pluginKey","pluginVersion","getCapabilityConfig","capabilityId","bodyCapability","config","getCapability","HttpException","error","HttpStatus","NOT_FOUND","getActionName","bodyAction","pluginInstance","loadPlugin","actions","listActions","length","BAD_REQUEST","debug","body","startTime","Date","now","params","capability","action","resolvedParams","resolve","formValue","result","loadWithConfig","call","capabilityConfig","duration","CapabilityNotFoundError","PluginNotFoundError","INTERNAL_SERVER_ERROR","ActionNotFoundError","Error","String","debugStream","res","setHeader","stream","callStream","chunk","write","JSON","stringify","errorCode","response","getResponse","end","Controller","Get","Post","Param","Body","Res","HttpException","HttpStatus","WebhookController","capabilityService","list","capabilities","listCapabilities","code","message","data","map","c","id","name","description","pluginKey","pluginVersion","execute","capabilityId","body","result","load","call","action","params","error","CapabilityNotFoundError","HttpException","HttpStatus","NOT_FOUND","PluginNotFoundError","INTERNAL_SERVER_ERROR","ActionNotFoundError","BAD_REQUEST","Error","String","executeStream","res","setHeader","capability","stream","callStream","chunk","write","JSON","stringify","errorCode","end","Module","RequestContextService","PLATFORM_HTTP_CLIENT","CAPABILITY_OPTIONS","Symbol","isDevelopment","process","env","NODE_ENV","getControllers","controllers","WebhookController","push","DebugController","CapabilityModule","forRoot","options","module","providers","provide","useValue","CapabilityService","useFactory","requestContextService","httpClient","pluginLoader","templateEngine","moduleOptions","service","capabilitiesDir","setCapabilitiesDir","inject","RequestContextService","PLATFORM_HTTP_CLIENT","PluginLoaderService","TemplateEngineService","exports"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lark-apaas/nestjs-capability",
3
- "version": "0.0.1-alpha.3",
3
+ "version": "0.0.1-alpha.4",
4
4
  "description": "NestJS capability module for FullStack",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",