@lark-apaas/nestjs-capability 0.0.1-alpha.0 → 0.0.1-alpha.2
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/README.md +107 -5
- package/dist/index.cjs +261 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +86 -9
- package/dist/index.d.ts +86 -9
- package/dist/index.js +263 -19
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -15,6 +15,7 @@ npm install @lark-apaas/nestjs-capability
|
|
|
15
15
|
- 从 `server/capabilities/` 目录加载能力配置
|
|
16
16
|
- 加载并实例化关联的插件
|
|
17
17
|
- 多种调用方式(Node 调用、Debug 调用、前端调用)
|
|
18
|
+
- 流式调用支持(SSE)
|
|
18
19
|
- 模板参数解析
|
|
19
20
|
|
|
20
21
|
## 快速开始
|
|
@@ -59,6 +60,36 @@ export class TaskService {
|
|
|
59
60
|
}
|
|
60
61
|
```
|
|
61
62
|
|
|
63
|
+
### 流式调用
|
|
64
|
+
|
|
65
|
+
用于 LLM 对话等流式输出场景:
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
@Injectable()
|
|
69
|
+
export class ChatService {
|
|
70
|
+
constructor(private readonly capabilityService: CapabilityService) {}
|
|
71
|
+
|
|
72
|
+
async *chat(message: string): AsyncIterable<{ content: string }> {
|
|
73
|
+
const stream = this.capabilityService
|
|
74
|
+
.load('ai_chat')
|
|
75
|
+
.callStream('chat', { message });
|
|
76
|
+
|
|
77
|
+
for await (const chunk of stream) {
|
|
78
|
+
yield chunk as { content: string };
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
普通调用会自动聚合流式结果:
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
// 即使是流式 action,call() 也会返回聚合后的完整结果
|
|
88
|
+
const result = await this.capabilityService
|
|
89
|
+
.load('ai_chat')
|
|
90
|
+
.call('chat', { message: 'hello' });
|
|
91
|
+
```
|
|
92
|
+
|
|
62
93
|
### 上下文覆盖
|
|
63
94
|
|
|
64
95
|
```typescript
|
|
@@ -128,16 +159,42 @@ POST /api/capability/:capability_id
|
|
|
128
159
|
}
|
|
129
160
|
```
|
|
130
161
|
|
|
131
|
-
###
|
|
162
|
+
### 前端流式调用
|
|
132
163
|
|
|
133
164
|
```
|
|
134
|
-
POST /
|
|
165
|
+
POST /api/capability/:capability_id/stream
|
|
135
166
|
|
|
136
167
|
请求体:
|
|
137
168
|
{
|
|
138
|
-
"action": "
|
|
169
|
+
"action": "chat",
|
|
139
170
|
"params": {
|
|
171
|
+
"message": "hello"
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
响应(SSE 格式):
|
|
176
|
+
data: {"content":"Hello"}
|
|
177
|
+
data: {"content":" World"}
|
|
178
|
+
data: [DONE]
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### Debug 调用(仅开发环境)
|
|
182
|
+
|
|
183
|
+
```
|
|
184
|
+
POST /__innerapi__/capability/debug/:capability_id
|
|
185
|
+
|
|
186
|
+
请求体(所有字段可选):
|
|
187
|
+
{
|
|
188
|
+
"action": "run", // 可选,默认使用插件第一个 action
|
|
189
|
+
"params": { // 可选,用户输入参数
|
|
140
190
|
"group_name": "测试群"
|
|
191
|
+
},
|
|
192
|
+
"capability": { // 可选,完整的 capability 配置(优先使用)
|
|
193
|
+
"id": "test",
|
|
194
|
+
"pluginID": "@test/plugin",
|
|
195
|
+
"pluginVersion": "1.0.0",
|
|
196
|
+
"name": "测试",
|
|
197
|
+
"formValue": {}
|
|
141
198
|
}
|
|
142
199
|
}
|
|
143
200
|
|
|
@@ -150,11 +207,30 @@ POST /__innerapi__/capability/debug/:capability_id
|
|
|
150
207
|
"capabilityConfig": { ... },
|
|
151
208
|
"resolvedParams": { ... },
|
|
152
209
|
"duration": 123,
|
|
153
|
-
"pluginID": "@xxx/plugin"
|
|
210
|
+
"pluginID": "@xxx/plugin",
|
|
211
|
+
"action": "run"
|
|
154
212
|
}
|
|
155
213
|
}
|
|
156
214
|
```
|
|
157
215
|
|
|
216
|
+
### Debug 流式调用(仅开发环境)
|
|
217
|
+
|
|
218
|
+
```
|
|
219
|
+
POST /__innerapi__/capability/debug/:capability_id/stream
|
|
220
|
+
|
|
221
|
+
请求体(所有字段可选):
|
|
222
|
+
{
|
|
223
|
+
"action": "chat",
|
|
224
|
+
"params": { "message": "hello" },
|
|
225
|
+
"capability": { ... }
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
响应(SSE 格式):
|
|
229
|
+
data: {"content":"Hello"}
|
|
230
|
+
data: {"content":" World"}
|
|
231
|
+
data: [DONE]
|
|
232
|
+
```
|
|
233
|
+
|
|
158
234
|
### 列出所有能力(仅开发环境)
|
|
159
235
|
|
|
160
236
|
```
|
|
@@ -192,16 +268,30 @@ interface CapabilityService {
|
|
|
192
268
|
// 加载能力并返回执行器
|
|
193
269
|
load(capabilityId: string): CapabilityExecutor;
|
|
194
270
|
|
|
271
|
+
// 使用传入的配置加载能力执行器(用于 debug 场景)
|
|
272
|
+
loadWithConfig(config: CapabilityConfig): CapabilityExecutor;
|
|
273
|
+
|
|
195
274
|
// 设置自定义能力目录
|
|
196
275
|
setCapabilitiesDir(dir: string): void;
|
|
197
276
|
}
|
|
198
277
|
|
|
199
278
|
interface CapabilityExecutor {
|
|
279
|
+
// 调用能力(流式 action 会自动聚合结果)
|
|
200
280
|
call(
|
|
201
281
|
actionName: string,
|
|
202
282
|
input: unknown,
|
|
203
283
|
context?: Partial<PluginActionContext>
|
|
204
284
|
): Promise<unknown>;
|
|
285
|
+
|
|
286
|
+
// 流式调用能力(返回 AsyncIterable)
|
|
287
|
+
callStream(
|
|
288
|
+
actionName: string,
|
|
289
|
+
input: unknown,
|
|
290
|
+
context?: Partial<PluginActionContext>
|
|
291
|
+
): AsyncIterable<unknown>;
|
|
292
|
+
|
|
293
|
+
// 检查 action 是否为流式
|
|
294
|
+
isStream(actionName: string): Promise<boolean>;
|
|
205
295
|
}
|
|
206
296
|
```
|
|
207
297
|
|
|
@@ -257,10 +347,22 @@ interface CapabilityConfig {
|
|
|
257
347
|
|
|
258
348
|
```typescript
|
|
259
349
|
interface PluginInstance {
|
|
350
|
+
// 执行 action(必需)
|
|
260
351
|
run(actionName: string, context: PluginActionContext, input: unknown): Promise<unknown>;
|
|
352
|
+
|
|
353
|
+
// 流式执行 action(可选)
|
|
354
|
+
runStream?(actionName: string, context: PluginActionContext, input: unknown): AsyncIterable<unknown>;
|
|
355
|
+
|
|
356
|
+
// 检查是否为流式 action(可选)
|
|
357
|
+
isStreamAction?(actionName: string): boolean;
|
|
358
|
+
|
|
359
|
+
// 聚合流式结果(可选,默认返回 chunks 数组)
|
|
360
|
+
aggregate?(actionName: string, chunks: unknown[]): unknown;
|
|
361
|
+
|
|
362
|
+
// Action 相关
|
|
261
363
|
hasAction(actionName: string): boolean;
|
|
262
|
-
getActionSchema(actionName: string): ActionSchema | null;
|
|
263
364
|
listActions(): string[];
|
|
365
|
+
getActionSchema(actionName: string): ActionSchema | null;
|
|
264
366
|
getInputSchema(actionName: string, config?: unknown): ZodSchema | undefined;
|
|
265
367
|
getOutputSchema(actionName: string, input: unknown, config?: unknown): ZodSchema | undefined;
|
|
266
368
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -134,7 +134,7 @@ var PluginLoaderService = class _PluginLoaderService {
|
|
|
134
134
|
}
|
|
135
135
|
logger = new import_common2.Logger(_PluginLoaderService.name);
|
|
136
136
|
pluginInstances = /* @__PURE__ */ new Map();
|
|
137
|
-
loadPlugin(pluginID) {
|
|
137
|
+
async loadPlugin(pluginID) {
|
|
138
138
|
const cached = this.pluginInstances.get(pluginID);
|
|
139
139
|
if (cached) {
|
|
140
140
|
this.logger.debug(`Using cached plugin instance: ${pluginID}`);
|
|
@@ -142,7 +142,7 @@ var PluginLoaderService = class _PluginLoaderService {
|
|
|
142
142
|
}
|
|
143
143
|
this.logger.log(`Loading plugin: ${pluginID}`);
|
|
144
144
|
try {
|
|
145
|
-
const pluginPackage =
|
|
145
|
+
const pluginPackage = (await import(pluginID)).default;
|
|
146
146
|
if (typeof pluginPackage.create !== "function") {
|
|
147
147
|
throw new PluginLoadError(pluginID, "Plugin does not export create() function");
|
|
148
148
|
}
|
|
@@ -278,28 +278,70 @@ var CapabilityService = class _CapabilityService {
|
|
|
278
278
|
if (!config) {
|
|
279
279
|
throw new CapabilityNotFoundError(capabilityId);
|
|
280
280
|
}
|
|
281
|
+
return this.createExecutor(config);
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* 使用传入的配置加载能力执行器
|
|
285
|
+
* 用于 debug 场景,支持用户传入自定义配置
|
|
286
|
+
*/
|
|
287
|
+
loadWithConfig(config) {
|
|
288
|
+
return this.createExecutor(config);
|
|
289
|
+
}
|
|
290
|
+
createExecutor(config) {
|
|
281
291
|
return {
|
|
282
292
|
call: /* @__PURE__ */ __name(async (actionName, input, contextOverride) => {
|
|
283
|
-
return this.
|
|
284
|
-
}, "call")
|
|
293
|
+
return this.executeCall(config, actionName, input, contextOverride);
|
|
294
|
+
}, "call"),
|
|
295
|
+
callStream: /* @__PURE__ */ __name((actionName, input, contextOverride) => {
|
|
296
|
+
return this.executeCallStream(config, actionName, input, contextOverride);
|
|
297
|
+
}, "callStream"),
|
|
298
|
+
isStream: /* @__PURE__ */ __name(async (actionName) => {
|
|
299
|
+
return this.checkIsStream(config, actionName);
|
|
300
|
+
}, "isStream")
|
|
285
301
|
};
|
|
286
302
|
}
|
|
287
|
-
|
|
303
|
+
/**
|
|
304
|
+
* 检查 action 是否为流式
|
|
305
|
+
*/
|
|
306
|
+
async checkIsStream(config, actionName) {
|
|
307
|
+
const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginID);
|
|
308
|
+
if (!pluginInstance.hasAction(actionName)) {
|
|
309
|
+
throw new ActionNotFoundError(config.pluginID, actionName);
|
|
310
|
+
}
|
|
311
|
+
return pluginInstance.isStreamAction?.(actionName) ?? false;
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* 执行 capability(始终返回 Promise)
|
|
315
|
+
* - unary action: 直接返回结果
|
|
316
|
+
* - stream action: 内部聚合所有 chunk 后返回
|
|
317
|
+
*/
|
|
318
|
+
async executeCall(config, actionName, input, contextOverride) {
|
|
288
319
|
const startTime = Date.now();
|
|
289
320
|
try {
|
|
290
|
-
const pluginInstance = this.pluginLoaderService.loadPlugin(config.pluginID);
|
|
321
|
+
const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginID);
|
|
291
322
|
if (!pluginInstance.hasAction(actionName)) {
|
|
292
323
|
throw new ActionNotFoundError(config.pluginID, actionName);
|
|
293
324
|
}
|
|
294
325
|
const resolvedParams = this.templateEngineService.resolve(config.formValue, input);
|
|
295
326
|
const context = this.buildActionContext(contextOverride);
|
|
327
|
+
const isStream = pluginInstance.isStreamAction?.(actionName) ?? false;
|
|
296
328
|
this.logger.log({
|
|
297
329
|
message: "Executing capability",
|
|
298
330
|
capabilityId: config.id,
|
|
299
331
|
action: actionName,
|
|
300
|
-
pluginID: config.pluginID
|
|
332
|
+
pluginID: config.pluginID,
|
|
333
|
+
isStream
|
|
301
334
|
});
|
|
302
|
-
|
|
335
|
+
let result;
|
|
336
|
+
if (isStream && pluginInstance.runStream) {
|
|
337
|
+
const chunks = [];
|
|
338
|
+
for await (const chunk of pluginInstance.runStream(actionName, context, resolvedParams)) {
|
|
339
|
+
chunks.push(chunk);
|
|
340
|
+
}
|
|
341
|
+
result = pluginInstance.aggregate ? pluginInstance.aggregate(actionName, chunks) : chunks;
|
|
342
|
+
} else {
|
|
343
|
+
result = await pluginInstance.run(actionName, context, resolvedParams);
|
|
344
|
+
}
|
|
303
345
|
this.logger.log({
|
|
304
346
|
message: "Capability executed successfully",
|
|
305
347
|
capabilityId: config.id,
|
|
@@ -318,6 +360,51 @@ var CapabilityService = class _CapabilityService {
|
|
|
318
360
|
throw error;
|
|
319
361
|
}
|
|
320
362
|
}
|
|
363
|
+
/**
|
|
364
|
+
* 流式执行 capability
|
|
365
|
+
* - stream action: 返回原始 AsyncIterable
|
|
366
|
+
* - unary action: 包装为单次 yield
|
|
367
|
+
*/
|
|
368
|
+
async *executeCallStream(config, actionName, input, contextOverride) {
|
|
369
|
+
const startTime = Date.now();
|
|
370
|
+
try {
|
|
371
|
+
const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginID);
|
|
372
|
+
if (!pluginInstance.hasAction(actionName)) {
|
|
373
|
+
throw new ActionNotFoundError(config.pluginID, actionName);
|
|
374
|
+
}
|
|
375
|
+
const resolvedParams = this.templateEngineService.resolve(config.formValue, input);
|
|
376
|
+
const context = this.buildActionContext(contextOverride);
|
|
377
|
+
const isStream = pluginInstance.isStreamAction?.(actionName) ?? false;
|
|
378
|
+
this.logger.log({
|
|
379
|
+
message: "Executing capability (stream)",
|
|
380
|
+
capabilityId: config.id,
|
|
381
|
+
action: actionName,
|
|
382
|
+
pluginID: config.pluginID,
|
|
383
|
+
isStream
|
|
384
|
+
});
|
|
385
|
+
if (isStream && pluginInstance.runStream) {
|
|
386
|
+
yield* pluginInstance.runStream(actionName, context, resolvedParams);
|
|
387
|
+
} else {
|
|
388
|
+
const result = await pluginInstance.run(actionName, context, resolvedParams);
|
|
389
|
+
yield result;
|
|
390
|
+
}
|
|
391
|
+
this.logger.log({
|
|
392
|
+
message: "Capability stream completed",
|
|
393
|
+
capabilityId: config.id,
|
|
394
|
+
action: actionName,
|
|
395
|
+
duration: Date.now() - startTime
|
|
396
|
+
});
|
|
397
|
+
} catch (error) {
|
|
398
|
+
this.logger.error({
|
|
399
|
+
message: "Capability stream execution failed",
|
|
400
|
+
capabilityId: config.id,
|
|
401
|
+
action: actionName,
|
|
402
|
+
error: error instanceof Error ? error.message : String(error),
|
|
403
|
+
duration: Date.now() - startTime
|
|
404
|
+
});
|
|
405
|
+
throw error;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
321
408
|
buildActionContext(override) {
|
|
322
409
|
return {
|
|
323
410
|
logger: this.logger,
|
|
@@ -369,9 +456,11 @@ var DebugController = class {
|
|
|
369
456
|
__name(this, "DebugController");
|
|
370
457
|
}
|
|
371
458
|
capabilityService;
|
|
459
|
+
pluginLoaderService;
|
|
372
460
|
templateEngineService;
|
|
373
|
-
constructor(capabilityService, templateEngineService) {
|
|
461
|
+
constructor(capabilityService, pluginLoaderService, templateEngineService) {
|
|
374
462
|
this.capabilityService = capabilityService;
|
|
463
|
+
this.pluginLoaderService = pluginLoaderService;
|
|
375
464
|
this.templateEngineService = templateEngineService;
|
|
376
465
|
}
|
|
377
466
|
list() {
|
|
@@ -387,8 +476,14 @@ var DebugController = class {
|
|
|
387
476
|
}))
|
|
388
477
|
};
|
|
389
478
|
}
|
|
390
|
-
|
|
391
|
-
|
|
479
|
+
/**
|
|
480
|
+
* 获取 capability 配置
|
|
481
|
+
* 优先使用 body.capability,否则从服务获取
|
|
482
|
+
*/
|
|
483
|
+
getCapabilityConfig(capabilityId, bodyCapability) {
|
|
484
|
+
if (bodyCapability) {
|
|
485
|
+
return bodyCapability;
|
|
486
|
+
}
|
|
392
487
|
const config = this.capabilityService.getCapability(capabilityId);
|
|
393
488
|
if (!config) {
|
|
394
489
|
throw new import_common4.HttpException({
|
|
@@ -397,9 +492,35 @@ var DebugController = class {
|
|
|
397
492
|
error: "CAPABILITY_NOT_FOUND"
|
|
398
493
|
}, import_common4.HttpStatus.NOT_FOUND);
|
|
399
494
|
}
|
|
400
|
-
|
|
495
|
+
return config;
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
* 获取 action 名称
|
|
499
|
+
* 优先使用传入的 action,否则使用插件第一个 action
|
|
500
|
+
*/
|
|
501
|
+
async getActionName(pluginID, bodyAction) {
|
|
502
|
+
if (bodyAction) {
|
|
503
|
+
return bodyAction;
|
|
504
|
+
}
|
|
505
|
+
const pluginInstance = await this.pluginLoaderService.loadPlugin(pluginID);
|
|
506
|
+
const actions = pluginInstance.listActions();
|
|
507
|
+
if (actions.length === 0) {
|
|
508
|
+
throw new import_common4.HttpException({
|
|
509
|
+
code: 1,
|
|
510
|
+
message: `Plugin ${pluginID} has no actions`,
|
|
511
|
+
error: "NO_ACTIONS"
|
|
512
|
+
}, import_common4.HttpStatus.BAD_REQUEST);
|
|
513
|
+
}
|
|
514
|
+
return actions[0];
|
|
515
|
+
}
|
|
516
|
+
async debug(capabilityId, body) {
|
|
517
|
+
const startTime = Date.now();
|
|
518
|
+
const params = body.params ?? {};
|
|
519
|
+
const config = this.getCapabilityConfig(capabilityId, body.capability);
|
|
520
|
+
const action = await this.getActionName(config.pluginID, body.action);
|
|
521
|
+
const resolvedParams = this.templateEngineService.resolve(config.formValue, params);
|
|
401
522
|
try {
|
|
402
|
-
const result = await this.capabilityService.
|
|
523
|
+
const result = await this.capabilityService.loadWithConfig(config).call(action, params);
|
|
403
524
|
return {
|
|
404
525
|
code: 0,
|
|
405
526
|
message: "success",
|
|
@@ -408,7 +529,8 @@ var DebugController = class {
|
|
|
408
529
|
capabilityConfig: config,
|
|
409
530
|
resolvedParams,
|
|
410
531
|
duration: Date.now() - startTime,
|
|
411
|
-
pluginID: config.pluginID
|
|
532
|
+
pluginID: config.pluginID,
|
|
533
|
+
action
|
|
412
534
|
}
|
|
413
535
|
};
|
|
414
536
|
} catch (error) {
|
|
@@ -430,7 +552,8 @@ var DebugController = class {
|
|
|
430
552
|
error: "PLUGIN_NOT_FOUND",
|
|
431
553
|
debug: {
|
|
432
554
|
duration,
|
|
433
|
-
pluginID: config.pluginID
|
|
555
|
+
pluginID: config.pluginID,
|
|
556
|
+
action
|
|
434
557
|
}
|
|
435
558
|
}, import_common4.HttpStatus.INTERNAL_SERVER_ERROR);
|
|
436
559
|
}
|
|
@@ -441,7 +564,8 @@ var DebugController = class {
|
|
|
441
564
|
error: "ACTION_NOT_FOUND",
|
|
442
565
|
debug: {
|
|
443
566
|
duration,
|
|
444
|
-
pluginID: config.pluginID
|
|
567
|
+
pluginID: config.pluginID,
|
|
568
|
+
action
|
|
445
569
|
}
|
|
446
570
|
}, import_common4.HttpStatus.BAD_REQUEST);
|
|
447
571
|
}
|
|
@@ -452,11 +576,51 @@ var DebugController = class {
|
|
|
452
576
|
debug: {
|
|
453
577
|
duration,
|
|
454
578
|
pluginID: config.pluginID,
|
|
579
|
+
action,
|
|
455
580
|
resolvedParams
|
|
456
581
|
}
|
|
457
582
|
}, import_common4.HttpStatus.INTERNAL_SERVER_ERROR);
|
|
458
583
|
}
|
|
459
584
|
}
|
|
585
|
+
async debugStream(capabilityId, body, res) {
|
|
586
|
+
const params = body.params ?? {};
|
|
587
|
+
res.setHeader("Content-Type", "text/event-stream");
|
|
588
|
+
res.setHeader("Cache-Control", "no-cache");
|
|
589
|
+
res.setHeader("Connection", "keep-alive");
|
|
590
|
+
try {
|
|
591
|
+
const config = this.getCapabilityConfig(capabilityId, body.capability);
|
|
592
|
+
const action = await this.getActionName(config.pluginID, body.action);
|
|
593
|
+
const capability = this.capabilityService.loadWithConfig(config);
|
|
594
|
+
const stream = capability.callStream(action, params);
|
|
595
|
+
for await (const chunk of stream) {
|
|
596
|
+
res.write(`data: ${JSON.stringify(chunk)}
|
|
597
|
+
|
|
598
|
+
`);
|
|
599
|
+
}
|
|
600
|
+
res.write("data: [DONE]\n\n");
|
|
601
|
+
} catch (error) {
|
|
602
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
603
|
+
let errorCode = "EXECUTION_ERROR";
|
|
604
|
+
if (error instanceof CapabilityNotFoundError) {
|
|
605
|
+
errorCode = "CAPABILITY_NOT_FOUND";
|
|
606
|
+
} else if (error instanceof PluginNotFoundError) {
|
|
607
|
+
errorCode = "PLUGIN_NOT_FOUND";
|
|
608
|
+
} else if (error instanceof ActionNotFoundError) {
|
|
609
|
+
errorCode = "ACTION_NOT_FOUND";
|
|
610
|
+
} else if (error instanceof import_common4.HttpException) {
|
|
611
|
+
const response = error.getResponse();
|
|
612
|
+
errorCode = response.error ?? "EXECUTION_ERROR";
|
|
613
|
+
}
|
|
614
|
+
res.write(`data: ${JSON.stringify({
|
|
615
|
+
error: message,
|
|
616
|
+
code: errorCode
|
|
617
|
+
})}
|
|
618
|
+
|
|
619
|
+
`);
|
|
620
|
+
} finally {
|
|
621
|
+
res.end();
|
|
622
|
+
}
|
|
623
|
+
}
|
|
460
624
|
};
|
|
461
625
|
_ts_decorate4([
|
|
462
626
|
(0, import_common4.Get)("list"),
|
|
@@ -471,15 +635,29 @@ _ts_decorate4([
|
|
|
471
635
|
_ts_metadata2("design:type", Function),
|
|
472
636
|
_ts_metadata2("design:paramtypes", [
|
|
473
637
|
String,
|
|
474
|
-
typeof
|
|
638
|
+
typeof DebugRequestBody === "undefined" ? Object : DebugRequestBody
|
|
475
639
|
]),
|
|
476
640
|
_ts_metadata2("design:returntype", Promise)
|
|
477
641
|
], DebugController.prototype, "debug", null);
|
|
642
|
+
_ts_decorate4([
|
|
643
|
+
(0, import_common4.Post)("debug/:capability_id/stream"),
|
|
644
|
+
_ts_param2(0, (0, import_common4.Param)("capability_id")),
|
|
645
|
+
_ts_param2(1, (0, import_common4.Body)()),
|
|
646
|
+
_ts_param2(2, (0, import_common4.Res)()),
|
|
647
|
+
_ts_metadata2("design:type", Function),
|
|
648
|
+
_ts_metadata2("design:paramtypes", [
|
|
649
|
+
String,
|
|
650
|
+
typeof DebugRequestBody === "undefined" ? Object : DebugRequestBody,
|
|
651
|
+
typeof Response === "undefined" ? Object : Response
|
|
652
|
+
]),
|
|
653
|
+
_ts_metadata2("design:returntype", Promise)
|
|
654
|
+
], DebugController.prototype, "debugStream", null);
|
|
478
655
|
DebugController = _ts_decorate4([
|
|
479
656
|
(0, import_common4.Controller)("__innerapi__/capability"),
|
|
480
657
|
_ts_metadata2("design:type", Function),
|
|
481
658
|
_ts_metadata2("design:paramtypes", [
|
|
482
659
|
typeof CapabilityService === "undefined" ? Object : CapabilityService,
|
|
660
|
+
typeof PluginLoaderService === "undefined" ? Object : PluginLoaderService,
|
|
483
661
|
typeof TemplateEngineService === "undefined" ? Object : TemplateEngineService
|
|
484
662
|
])
|
|
485
663
|
], DebugController);
|
|
@@ -511,6 +689,20 @@ var WebhookController = class {
|
|
|
511
689
|
constructor(capabilityService) {
|
|
512
690
|
this.capabilityService = capabilityService;
|
|
513
691
|
}
|
|
692
|
+
list() {
|
|
693
|
+
const capabilities = this.capabilityService.listCapabilities();
|
|
694
|
+
return {
|
|
695
|
+
code: 0,
|
|
696
|
+
message: "success",
|
|
697
|
+
data: capabilities.map((c) => ({
|
|
698
|
+
id: c.id,
|
|
699
|
+
name: c.name,
|
|
700
|
+
description: c.description,
|
|
701
|
+
pluginID: c.pluginID,
|
|
702
|
+
pluginVersion: c.pluginVersion
|
|
703
|
+
}))
|
|
704
|
+
};
|
|
705
|
+
}
|
|
514
706
|
async execute(capabilityId, body) {
|
|
515
707
|
try {
|
|
516
708
|
const result = await this.capabilityService.load(capabilityId).call(body.action, body.params);
|
|
@@ -548,7 +740,46 @@ var WebhookController = class {
|
|
|
548
740
|
}, import_common5.HttpStatus.INTERNAL_SERVER_ERROR);
|
|
549
741
|
}
|
|
550
742
|
}
|
|
743
|
+
async executeStream(capabilityId, body, res) {
|
|
744
|
+
res.setHeader("Content-Type", "text/event-stream");
|
|
745
|
+
res.setHeader("Cache-Control", "no-cache");
|
|
746
|
+
res.setHeader("Connection", "keep-alive");
|
|
747
|
+
try {
|
|
748
|
+
const capability = this.capabilityService.load(capabilityId);
|
|
749
|
+
const stream = capability.callStream(body.action, body.params);
|
|
750
|
+
for await (const chunk of stream) {
|
|
751
|
+
res.write(`data: ${JSON.stringify(chunk)}
|
|
752
|
+
|
|
753
|
+
`);
|
|
754
|
+
}
|
|
755
|
+
res.write("data: [DONE]\n\n");
|
|
756
|
+
} catch (error) {
|
|
757
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
758
|
+
let errorCode = "EXECUTION_ERROR";
|
|
759
|
+
if (error instanceof CapabilityNotFoundError) {
|
|
760
|
+
errorCode = "CAPABILITY_NOT_FOUND";
|
|
761
|
+
} else if (error instanceof PluginNotFoundError) {
|
|
762
|
+
errorCode = "PLUGIN_NOT_FOUND";
|
|
763
|
+
} else if (error instanceof ActionNotFoundError) {
|
|
764
|
+
errorCode = "ACTION_NOT_FOUND";
|
|
765
|
+
}
|
|
766
|
+
res.write(`data: ${JSON.stringify({
|
|
767
|
+
error: message,
|
|
768
|
+
code: errorCode
|
|
769
|
+
})}
|
|
770
|
+
|
|
771
|
+
`);
|
|
772
|
+
} finally {
|
|
773
|
+
res.end();
|
|
774
|
+
}
|
|
775
|
+
}
|
|
551
776
|
};
|
|
777
|
+
_ts_decorate5([
|
|
778
|
+
(0, import_common5.Get)("list"),
|
|
779
|
+
_ts_metadata3("design:type", Function),
|
|
780
|
+
_ts_metadata3("design:paramtypes", []),
|
|
781
|
+
_ts_metadata3("design:returntype", typeof ListResponse === "undefined" ? Object : ListResponse)
|
|
782
|
+
], WebhookController.prototype, "list", null);
|
|
552
783
|
_ts_decorate5([
|
|
553
784
|
(0, import_common5.Post)(":capability_id"),
|
|
554
785
|
_ts_param3(0, (0, import_common5.Param)("capability_id")),
|
|
@@ -560,6 +791,19 @@ _ts_decorate5([
|
|
|
560
791
|
]),
|
|
561
792
|
_ts_metadata3("design:returntype", Promise)
|
|
562
793
|
], WebhookController.prototype, "execute", null);
|
|
794
|
+
_ts_decorate5([
|
|
795
|
+
(0, import_common5.Post)(":capability_id/stream"),
|
|
796
|
+
_ts_param3(0, (0, import_common5.Param)("capability_id")),
|
|
797
|
+
_ts_param3(1, (0, import_common5.Body)()),
|
|
798
|
+
_ts_param3(2, (0, import_common5.Res)()),
|
|
799
|
+
_ts_metadata3("design:type", Function),
|
|
800
|
+
_ts_metadata3("design:paramtypes", [
|
|
801
|
+
String,
|
|
802
|
+
typeof ExecuteRequestBody === "undefined" ? Object : ExecuteRequestBody,
|
|
803
|
+
typeof Response === "undefined" ? Object : Response
|
|
804
|
+
]),
|
|
805
|
+
_ts_metadata3("design:returntype", Promise)
|
|
806
|
+
], WebhookController.prototype, "executeStream", null);
|
|
563
807
|
WebhookController = _ts_decorate5([
|
|
564
808
|
(0, import_common5.Controller)("api/capability"),
|
|
565
809
|
_ts_metadata3("design:type", Function),
|