@lark-apaas/nestjs-capability 0.0.1-alpha.4 → 0.0.1-alpha.7
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 +420 -157
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +183 -67
- package/dist/index.d.ts +183 -67
- package/dist/index.js +422 -160
- package/dist/index.js.map +1 -1
- package/package.json +1 -2
package/dist/index.js
CHANGED
|
@@ -7,6 +7,22 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
7
7
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
8
8
|
});
|
|
9
9
|
|
|
10
|
+
// src/interfaces/error-codes.ts
|
|
11
|
+
var ErrorCodes = {
|
|
12
|
+
/** 成功 */
|
|
13
|
+
SUCCESS: "0",
|
|
14
|
+
/** 能力不存在 */
|
|
15
|
+
CAPABILITY_NOT_FOUND: "k_ec_cap_001",
|
|
16
|
+
/** 插件不存在 */
|
|
17
|
+
PLUGIN_NOT_FOUND: "k_ec_cap_002",
|
|
18
|
+
/** Action 不存在 */
|
|
19
|
+
ACTION_NOT_FOUND: "k_ec_cap_003",
|
|
20
|
+
/** 参数验证失败 */
|
|
21
|
+
PARAMS_VALIDATION_ERROR: "k_ec_cap_004",
|
|
22
|
+
/** 执行失败 */
|
|
23
|
+
EXECUTION_ERROR: "k_ec_cap_005"
|
|
24
|
+
};
|
|
25
|
+
|
|
10
26
|
// src/services/template-engine.service.ts
|
|
11
27
|
import { Injectable } from "@nestjs/common";
|
|
12
28
|
function _ts_decorate(decorators, target, key, desc) {
|
|
@@ -163,6 +179,28 @@ import { Injectable as Injectable3, Logger as Logger2, Inject } from "@nestjs/co
|
|
|
163
179
|
import { RequestContextService, PLATFORM_HTTP_CLIENT } from "@lark-apaas/nestjs-common";
|
|
164
180
|
import * as fs from "fs";
|
|
165
181
|
import * as path from "path";
|
|
182
|
+
|
|
183
|
+
// src/utils/log-utils.ts
|
|
184
|
+
var DEFAULT_MAX_LENGTH = 1e3;
|
|
185
|
+
function truncateString(str, maxLength) {
|
|
186
|
+
if (str.length <= maxLength) {
|
|
187
|
+
return str;
|
|
188
|
+
}
|
|
189
|
+
return str.slice(0, maxLength) + `... [truncated, total ${str.length} chars]`;
|
|
190
|
+
}
|
|
191
|
+
__name(truncateString, "truncateString");
|
|
192
|
+
function stringifyForLog(value, maxLength = DEFAULT_MAX_LENGTH) {
|
|
193
|
+
try {
|
|
194
|
+
const str = JSON.stringify(value, null, 2);
|
|
195
|
+
return truncateString(str, maxLength);
|
|
196
|
+
} catch {
|
|
197
|
+
const str = String(value);
|
|
198
|
+
return truncateString(str, maxLength);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
__name(stringifyForLog, "stringifyForLog");
|
|
202
|
+
|
|
203
|
+
// src/services/capability.service.ts
|
|
166
204
|
function _ts_decorate3(decorators, target, key, desc) {
|
|
167
205
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
168
206
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -203,15 +241,15 @@ var CapabilityService = class _CapabilityService {
|
|
|
203
241
|
__name(this, "CapabilityService");
|
|
204
242
|
}
|
|
205
243
|
requestContextService;
|
|
206
|
-
|
|
244
|
+
platformHttpClient;
|
|
207
245
|
pluginLoaderService;
|
|
208
246
|
templateEngineService;
|
|
209
247
|
logger = new Logger2(_CapabilityService.name);
|
|
210
248
|
capabilities = /* @__PURE__ */ new Map();
|
|
211
249
|
capabilitiesDir;
|
|
212
|
-
constructor(requestContextService,
|
|
250
|
+
constructor(requestContextService, platformHttpClient, pluginLoaderService, templateEngineService) {
|
|
213
251
|
this.requestContextService = requestContextService;
|
|
214
|
-
this.
|
|
252
|
+
this.platformHttpClient = platformHttpClient;
|
|
215
253
|
this.pluginLoaderService = pluginLoaderService;
|
|
216
254
|
this.templateEngineService = templateEngineService;
|
|
217
255
|
this.capabilitiesDir = path.join(process.cwd(), "server/capabilities");
|
|
@@ -274,6 +312,9 @@ var CapabilityService = class _CapabilityService {
|
|
|
274
312
|
callStream: /* @__PURE__ */ __name((actionName, input, contextOverride) => {
|
|
275
313
|
return this.executeCallStream(config, actionName, input, contextOverride);
|
|
276
314
|
}, "callStream"),
|
|
315
|
+
callStreamWithEvents: /* @__PURE__ */ __name((actionName, input, contextOverride) => {
|
|
316
|
+
return this.executeCallStreamWithEvents(config, actionName, input, contextOverride);
|
|
317
|
+
}, "callStreamWithEvents"),
|
|
277
318
|
isStream: /* @__PURE__ */ __name(async (actionName) => {
|
|
278
319
|
return this.checkIsStream(config, actionName);
|
|
279
320
|
}, "isStream")
|
|
@@ -296,20 +337,23 @@ var CapabilityService = class _CapabilityService {
|
|
|
296
337
|
*/
|
|
297
338
|
async executeCall(config, actionName, input, contextOverride) {
|
|
298
339
|
const startTime = Date.now();
|
|
340
|
+
const loggerContext = {
|
|
341
|
+
capability_id: config.id,
|
|
342
|
+
plugin_key: config.pluginKey,
|
|
343
|
+
action: actionName
|
|
344
|
+
};
|
|
299
345
|
try {
|
|
300
346
|
const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginKey);
|
|
301
347
|
if (!pluginInstance.hasAction(actionName)) {
|
|
302
348
|
throw new ActionNotFoundError(config.pluginKey, actionName);
|
|
303
349
|
}
|
|
304
|
-
const resolvedParams = this.templateEngineService.resolve(config.formValue, input);
|
|
350
|
+
const resolvedParams = config.formValue ? this.templateEngineService.resolve(config.formValue, input) : input;
|
|
305
351
|
const context = this.buildActionContext(contextOverride);
|
|
306
352
|
const isStream = pluginInstance.isStreamAction?.(actionName) ?? false;
|
|
307
|
-
this.logger.log({
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
pluginKey: config.pluginKey,
|
|
312
|
-
isStream
|
|
353
|
+
this.logger.log("Executing capability (call)", {
|
|
354
|
+
...loggerContext,
|
|
355
|
+
is_stream: isStream,
|
|
356
|
+
input: stringifyForLog(input)
|
|
313
357
|
});
|
|
314
358
|
let result;
|
|
315
359
|
if (isStream && pluginInstance.runStream) {
|
|
@@ -321,20 +365,17 @@ var CapabilityService = class _CapabilityService {
|
|
|
321
365
|
} else {
|
|
322
366
|
result = await pluginInstance.run(actionName, context, resolvedParams);
|
|
323
367
|
}
|
|
324
|
-
this.logger.log({
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
duration: Date.now() - startTime
|
|
368
|
+
this.logger.log("Capability (call) executed successfully", {
|
|
369
|
+
...loggerContext,
|
|
370
|
+
duration_ms: Date.now() - startTime,
|
|
371
|
+
output: stringifyForLog(result)
|
|
329
372
|
});
|
|
330
373
|
return result;
|
|
331
374
|
} catch (error) {
|
|
332
|
-
this.logger.error({
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
error: error instanceof Error ? error.message : String(error),
|
|
337
|
-
duration: Date.now() - startTime
|
|
375
|
+
this.logger.error("Capability (call) execution failed", {
|
|
376
|
+
...loggerContext,
|
|
377
|
+
duration_ms: Date.now() - startTime,
|
|
378
|
+
error: error instanceof Error ? error.message : String(error)
|
|
338
379
|
});
|
|
339
380
|
throw error;
|
|
340
381
|
}
|
|
@@ -346,54 +387,140 @@ var CapabilityService = class _CapabilityService {
|
|
|
346
387
|
*/
|
|
347
388
|
async *executeCallStream(config, actionName, input, contextOverride) {
|
|
348
389
|
const startTime = Date.now();
|
|
390
|
+
const loggerContext = {
|
|
391
|
+
capability_id: config.id,
|
|
392
|
+
plugin_key: config.pluginKey,
|
|
393
|
+
action: actionName
|
|
394
|
+
};
|
|
395
|
+
const chunks = [];
|
|
349
396
|
try {
|
|
350
397
|
const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginKey);
|
|
351
398
|
if (!pluginInstance.hasAction(actionName)) {
|
|
352
399
|
throw new ActionNotFoundError(config.pluginKey, actionName);
|
|
353
400
|
}
|
|
354
|
-
const resolvedParams = this.templateEngineService.resolve(config.formValue, input);
|
|
401
|
+
const resolvedParams = config.formValue ? this.templateEngineService.resolve(config.formValue, input) : input;
|
|
355
402
|
const context = this.buildActionContext(contextOverride);
|
|
356
403
|
const isStream = pluginInstance.isStreamAction?.(actionName) ?? false;
|
|
357
|
-
this.logger.log({
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
pluginKey: config.pluginKey,
|
|
362
|
-
isStream
|
|
404
|
+
this.logger.log("Executing capability (stream)", {
|
|
405
|
+
...loggerContext,
|
|
406
|
+
is_stream: isStream,
|
|
407
|
+
input: stringifyForLog(input)
|
|
363
408
|
});
|
|
364
409
|
if (isStream && pluginInstance.runStream) {
|
|
365
|
-
|
|
410
|
+
for await (const chunk of pluginInstance.runStream(actionName, context, resolvedParams)) {
|
|
411
|
+
chunks.push(chunk);
|
|
412
|
+
yield chunk;
|
|
413
|
+
}
|
|
366
414
|
} else {
|
|
367
415
|
const result = await pluginInstance.run(actionName, context, resolvedParams);
|
|
416
|
+
chunks.push(result);
|
|
368
417
|
yield result;
|
|
369
418
|
}
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
419
|
+
const aggregatedResult = pluginInstance.aggregate ? pluginInstance.aggregate(actionName, chunks) : chunks;
|
|
420
|
+
this.logger.log("Capability (stream) executed successfully", {
|
|
421
|
+
...loggerContext,
|
|
422
|
+
duration_ms: Date.now() - startTime,
|
|
423
|
+
output: stringifyForLog(aggregatedResult)
|
|
375
424
|
});
|
|
376
425
|
} catch (error) {
|
|
377
|
-
this.logger.error({
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
error: error instanceof Error ? error.message : String(error),
|
|
382
|
-
duration: Date.now() - startTime
|
|
426
|
+
this.logger.error("Capability (stream) execution failed", {
|
|
427
|
+
...loggerContext,
|
|
428
|
+
duration_ms: Date.now() - startTime,
|
|
429
|
+
error: error instanceof Error ? error.message : String(error)
|
|
383
430
|
});
|
|
384
431
|
throw error;
|
|
385
432
|
}
|
|
386
433
|
}
|
|
434
|
+
/**
|
|
435
|
+
* 流式执行 capability,返回带事件协议的流
|
|
436
|
+
* - 优先使用 pluginInstance.runStreamWithEvents
|
|
437
|
+
* - 如果插件不支持,则包装 runStream/run 为 StreamEvent
|
|
438
|
+
*/
|
|
439
|
+
async *executeCallStreamWithEvents(config, actionName, input, contextOverride) {
|
|
440
|
+
const startTime = Date.now();
|
|
441
|
+
const loggerContext = {
|
|
442
|
+
capability_id: config.id,
|
|
443
|
+
plugin_key: config.pluginKey,
|
|
444
|
+
action: actionName
|
|
445
|
+
};
|
|
446
|
+
const chunks = [];
|
|
447
|
+
try {
|
|
448
|
+
const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginKey);
|
|
449
|
+
if (!pluginInstance.hasAction(actionName)) {
|
|
450
|
+
throw new ActionNotFoundError(config.pluginKey, actionName);
|
|
451
|
+
}
|
|
452
|
+
const resolvedParams = config.formValue ? this.templateEngineService.resolve(config.formValue, input) : input;
|
|
453
|
+
const context = this.buildActionContext(contextOverride);
|
|
454
|
+
const isStream = pluginInstance.isStreamAction?.(actionName) ?? false;
|
|
455
|
+
this.logger.log("Executing capability (streamWithEvents)", {
|
|
456
|
+
...loggerContext,
|
|
457
|
+
is_stream: isStream,
|
|
458
|
+
input: stringifyForLog(input)
|
|
459
|
+
});
|
|
460
|
+
if (pluginInstance.runStreamWithEvents) {
|
|
461
|
+
for await (const event of pluginInstance.runStreamWithEvents(actionName, context, resolvedParams)) {
|
|
462
|
+
if (event.type === "data") {
|
|
463
|
+
chunks.push(event.data);
|
|
464
|
+
}
|
|
465
|
+
yield event;
|
|
466
|
+
}
|
|
467
|
+
} else {
|
|
468
|
+
if (isStream && pluginInstance.runStream) {
|
|
469
|
+
for await (const chunk of pluginInstance.runStream(actionName, context, resolvedParams)) {
|
|
470
|
+
chunks.push(chunk);
|
|
471
|
+
yield {
|
|
472
|
+
type: "data",
|
|
473
|
+
data: chunk
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
} else {
|
|
477
|
+
const result = await pluginInstance.run(actionName, context, resolvedParams);
|
|
478
|
+
chunks.push(result);
|
|
479
|
+
yield {
|
|
480
|
+
type: "data",
|
|
481
|
+
data: result
|
|
482
|
+
};
|
|
483
|
+
}
|
|
484
|
+
yield {
|
|
485
|
+
type: "done",
|
|
486
|
+
metadata: {
|
|
487
|
+
chunks: chunks.length,
|
|
488
|
+
duration: Date.now() - startTime
|
|
489
|
+
}
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
const aggregatedResult = pluginInstance.aggregate ? pluginInstance.aggregate(actionName, chunks) : chunks;
|
|
493
|
+
this.logger.log("Capability (streamWithEvents) executed successfully", {
|
|
494
|
+
...loggerContext,
|
|
495
|
+
duration_ms: Date.now() - startTime,
|
|
496
|
+
output: stringifyForLog(aggregatedResult)
|
|
497
|
+
});
|
|
498
|
+
} catch (error) {
|
|
499
|
+
this.logger.error("Capability (streamWithEvents) execution failed", {
|
|
500
|
+
...loggerContext,
|
|
501
|
+
duration_ms: Date.now() - startTime,
|
|
502
|
+
error: error instanceof Error ? error.message : String(error)
|
|
503
|
+
});
|
|
504
|
+
yield {
|
|
505
|
+
type: "error",
|
|
506
|
+
error: {
|
|
507
|
+
code: "EXECUTION_ERROR",
|
|
508
|
+
message: error instanceof Error ? error.message : String(error)
|
|
509
|
+
}
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
}
|
|
387
513
|
buildActionContext(override) {
|
|
388
514
|
return {
|
|
389
515
|
logger: this.logger,
|
|
390
|
-
|
|
516
|
+
platformHttpClient: this.platformHttpClient,
|
|
391
517
|
userContext: override?.userContext ?? this.getUserContext()
|
|
392
518
|
};
|
|
393
519
|
}
|
|
394
520
|
getUserContext() {
|
|
395
521
|
const ctx = this.requestContextService.getContext();
|
|
396
522
|
return {
|
|
523
|
+
appId: ctx?.appId ?? "",
|
|
397
524
|
userId: ctx?.userId ?? "",
|
|
398
525
|
tenantId: ctx?.tenantId ?? ""
|
|
399
526
|
};
|
|
@@ -412,7 +539,7 @@ CapabilityService = _ts_decorate3([
|
|
|
412
539
|
], CapabilityService);
|
|
413
540
|
|
|
414
541
|
// src/controllers/debug.controller.ts
|
|
415
|
-
import { Controller, Post, Get, Param, Body, Res, HttpException, HttpStatus } from "@nestjs/common";
|
|
542
|
+
import { Controller, Post, Get, Param, Body, Res, HttpException, HttpStatus, Logger as Logger3 } from "@nestjs/common";
|
|
416
543
|
function _ts_decorate4(decorators, target, key, desc) {
|
|
417
544
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
418
545
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -430,13 +557,14 @@ function _ts_param2(paramIndex, decorator) {
|
|
|
430
557
|
};
|
|
431
558
|
}
|
|
432
559
|
__name(_ts_param2, "_ts_param");
|
|
433
|
-
var DebugController = class {
|
|
560
|
+
var DebugController = class _DebugController {
|
|
434
561
|
static {
|
|
435
562
|
__name(this, "DebugController");
|
|
436
563
|
}
|
|
437
564
|
capabilityService;
|
|
438
565
|
pluginLoaderService;
|
|
439
566
|
templateEngineService;
|
|
567
|
+
logger = new Logger3(_DebugController.name);
|
|
440
568
|
constructor(capabilityService, pluginLoaderService, templateEngineService) {
|
|
441
569
|
this.capabilityService = capabilityService;
|
|
442
570
|
this.pluginLoaderService = pluginLoaderService;
|
|
@@ -445,14 +573,15 @@ var DebugController = class {
|
|
|
445
573
|
list() {
|
|
446
574
|
const capabilities = this.capabilityService.listCapabilities();
|
|
447
575
|
return {
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
576
|
+
status_code: ErrorCodes.SUCCESS,
|
|
577
|
+
data: {
|
|
578
|
+
capabilities: capabilities.map((c) => ({
|
|
579
|
+
id: c.id,
|
|
580
|
+
name: c.name,
|
|
581
|
+
pluginID: c.pluginKey,
|
|
582
|
+
pluginVersion: c.pluginVersion
|
|
583
|
+
}))
|
|
584
|
+
}
|
|
456
585
|
};
|
|
457
586
|
}
|
|
458
587
|
/**
|
|
@@ -501,102 +630,153 @@ var DebugController = class {
|
|
|
501
630
|
try {
|
|
502
631
|
const result = await this.capabilityService.loadWithConfig(config).call(action, params);
|
|
503
632
|
return {
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
633
|
+
status_code: ErrorCodes.SUCCESS,
|
|
634
|
+
data: {
|
|
635
|
+
output: result,
|
|
636
|
+
debug: {
|
|
637
|
+
capabilityConfig: config,
|
|
638
|
+
resolvedParams,
|
|
639
|
+
duration: Date.now() - startTime,
|
|
640
|
+
pluginID: config.pluginKey,
|
|
641
|
+
action
|
|
642
|
+
}
|
|
513
643
|
}
|
|
514
644
|
};
|
|
515
645
|
} catch (error) {
|
|
516
|
-
const duration = Date.now() - startTime;
|
|
517
646
|
if (error instanceof CapabilityNotFoundError) {
|
|
518
647
|
throw new HttpException({
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
error: "CAPABILITY_NOT_FOUND",
|
|
522
|
-
debug: {
|
|
523
|
-
duration
|
|
524
|
-
}
|
|
648
|
+
status_code: ErrorCodes.CAPABILITY_NOT_FOUND,
|
|
649
|
+
error_msg: `Capability not found: ${capabilityId}`
|
|
525
650
|
}, HttpStatus.NOT_FOUND);
|
|
526
651
|
}
|
|
527
652
|
if (error instanceof PluginNotFoundError) {
|
|
528
653
|
throw new HttpException({
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
error: "PLUGIN_NOT_FOUND",
|
|
532
|
-
debug: {
|
|
533
|
-
duration,
|
|
534
|
-
pluginKey: config.pluginKey,
|
|
535
|
-
action
|
|
536
|
-
}
|
|
654
|
+
status_code: ErrorCodes.PLUGIN_NOT_FOUND,
|
|
655
|
+
error_msg: `Plugin not found: ${config.pluginKey}`
|
|
537
656
|
}, HttpStatus.INTERNAL_SERVER_ERROR);
|
|
538
657
|
}
|
|
539
658
|
if (error instanceof ActionNotFoundError) {
|
|
540
659
|
throw new HttpException({
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
error: "ACTION_NOT_FOUND",
|
|
544
|
-
debug: {
|
|
545
|
-
duration,
|
|
546
|
-
pluginKey: config.pluginKey,
|
|
547
|
-
action
|
|
548
|
-
}
|
|
660
|
+
status_code: ErrorCodes.ACTION_NOT_FOUND,
|
|
661
|
+
error_msg: `Action '${action}' not found in plugin ${config.pluginKey}`
|
|
549
662
|
}, HttpStatus.BAD_REQUEST);
|
|
550
663
|
}
|
|
551
664
|
throw new HttpException({
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
error: "EXECUTION_ERROR",
|
|
555
|
-
debug: {
|
|
556
|
-
duration,
|
|
557
|
-
pluginKey: config.pluginKey,
|
|
558
|
-
action,
|
|
559
|
-
resolvedParams
|
|
560
|
-
}
|
|
665
|
+
status_code: ErrorCodes.EXECUTION_ERROR,
|
|
666
|
+
error_msg: `Execution failed: ${error instanceof Error ? error.message : String(error)}`
|
|
561
667
|
}, HttpStatus.INTERNAL_SERVER_ERROR);
|
|
562
668
|
}
|
|
563
669
|
}
|
|
564
670
|
async debugStream(capabilityId, body, res) {
|
|
565
671
|
const params = body.params ?? {};
|
|
672
|
+
const startTime = Date.now();
|
|
566
673
|
res.setHeader("Content-Type", "text/event-stream");
|
|
567
674
|
res.setHeader("Cache-Control", "no-cache");
|
|
568
675
|
res.setHeader("Connection", "keep-alive");
|
|
569
676
|
try {
|
|
570
677
|
const config = this.getCapabilityConfig(capabilityId, body.capability);
|
|
571
678
|
const action = await this.getActionName(config.pluginKey, body.action);
|
|
679
|
+
const loggerContext = {
|
|
680
|
+
capability_id: config.id,
|
|
681
|
+
plugin_key: config.pluginKey,
|
|
682
|
+
action
|
|
683
|
+
};
|
|
684
|
+
this.logger.log(`Executing capability (stream), input: ${stringifyForLog(params)}`, loggerContext);
|
|
572
685
|
const capability = this.capabilityService.loadWithConfig(config);
|
|
573
|
-
const
|
|
574
|
-
|
|
575
|
-
|
|
686
|
+
const eventStream = capability.callStreamWithEvents(action, params);
|
|
687
|
+
let pendingChunk = null;
|
|
688
|
+
const allChunks = [];
|
|
689
|
+
for await (const event of eventStream) {
|
|
690
|
+
switch (event.type) {
|
|
691
|
+
case "data": {
|
|
692
|
+
allChunks.push(event.data);
|
|
693
|
+
if (pendingChunk !== null) {
|
|
694
|
+
const response = {
|
|
695
|
+
status_code: ErrorCodes.SUCCESS,
|
|
696
|
+
data: {
|
|
697
|
+
type: "content",
|
|
698
|
+
delta: {
|
|
699
|
+
content: pendingChunk
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
};
|
|
703
|
+
res.write(`data: ${JSON.stringify(response)}
|
|
704
|
+
|
|
705
|
+
`);
|
|
706
|
+
}
|
|
707
|
+
pendingChunk = event.data;
|
|
708
|
+
break;
|
|
709
|
+
}
|
|
710
|
+
case "done": {
|
|
711
|
+
if (pendingChunk !== null) {
|
|
712
|
+
const response = {
|
|
713
|
+
status_code: ErrorCodes.SUCCESS,
|
|
714
|
+
data: {
|
|
715
|
+
type: "content",
|
|
716
|
+
delta: {
|
|
717
|
+
content: pendingChunk
|
|
718
|
+
},
|
|
719
|
+
finished: true
|
|
720
|
+
}
|
|
721
|
+
};
|
|
722
|
+
res.write(`data: ${JSON.stringify(response)}
|
|
723
|
+
|
|
724
|
+
`);
|
|
725
|
+
}
|
|
726
|
+
this.logger.log(`Capability (stream) executed successfully, duration: ${Date.now() - startTime}ms, chunks: ${allChunks.length}, result: ${stringifyForLog(allChunks)}`, loggerContext);
|
|
727
|
+
res.end();
|
|
728
|
+
return;
|
|
729
|
+
}
|
|
730
|
+
case "error": {
|
|
731
|
+
const response = {
|
|
732
|
+
status_code: ErrorCodes.SUCCESS,
|
|
733
|
+
data: {
|
|
734
|
+
type: "error",
|
|
735
|
+
error: {
|
|
736
|
+
code: 0,
|
|
737
|
+
message: event.error.message
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
};
|
|
741
|
+
res.write(`data: ${JSON.stringify(response)}
|
|
742
|
+
|
|
743
|
+
`);
|
|
744
|
+
res.end();
|
|
745
|
+
return;
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
if (pendingChunk !== null) {
|
|
750
|
+
const response = {
|
|
751
|
+
status_code: ErrorCodes.SUCCESS,
|
|
752
|
+
data: {
|
|
753
|
+
type: "content",
|
|
754
|
+
delta: {
|
|
755
|
+
content: pendingChunk
|
|
756
|
+
},
|
|
757
|
+
finished: true
|
|
758
|
+
}
|
|
759
|
+
};
|
|
760
|
+
res.write(`data: ${JSON.stringify(response)}
|
|
576
761
|
|
|
577
762
|
`);
|
|
578
763
|
}
|
|
579
|
-
res.
|
|
764
|
+
res.end();
|
|
580
765
|
} catch (error) {
|
|
581
|
-
const
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
}
|
|
593
|
-
res.write(`data: ${JSON.stringify({
|
|
594
|
-
error: message,
|
|
595
|
-
code: errorCode
|
|
596
|
-
})}
|
|
766
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
767
|
+
const response = {
|
|
768
|
+
status_code: ErrorCodes.SUCCESS,
|
|
769
|
+
data: {
|
|
770
|
+
type: "error",
|
|
771
|
+
error: {
|
|
772
|
+
code: 0,
|
|
773
|
+
message: errorMsg
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
};
|
|
777
|
+
res.write(`data: ${JSON.stringify(response)}
|
|
597
778
|
|
|
598
779
|
`);
|
|
599
|
-
} finally {
|
|
600
780
|
res.end();
|
|
601
781
|
}
|
|
602
782
|
}
|
|
@@ -605,7 +785,7 @@ _ts_decorate4([
|
|
|
605
785
|
Get("list"),
|
|
606
786
|
_ts_metadata2("design:type", Function),
|
|
607
787
|
_ts_metadata2("design:paramtypes", []),
|
|
608
|
-
_ts_metadata2("design:returntype", typeof
|
|
788
|
+
_ts_metadata2("design:returntype", typeof SuccessResponse === "undefined" ? Object : SuccessResponse)
|
|
609
789
|
], DebugController.prototype, "list", null);
|
|
610
790
|
_ts_decorate4([
|
|
611
791
|
Post("debug/:capability_id"),
|
|
@@ -642,7 +822,7 @@ DebugController = _ts_decorate4([
|
|
|
642
822
|
], DebugController);
|
|
643
823
|
|
|
644
824
|
// src/controllers/webhook.controller.ts
|
|
645
|
-
import { Controller as Controller2, Get as Get2, Post as Post2, Param as Param2, Body as Body2, Res as Res2, HttpException as HttpException2, HttpStatus as HttpStatus2 } from "@nestjs/common";
|
|
825
|
+
import { Controller as Controller2, Get as Get2, Post as Post2, Param as Param2, Body as Body2, Res as Res2, HttpException as HttpException2, HttpStatus as HttpStatus2, Logger as Logger4 } from "@nestjs/common";
|
|
646
826
|
function _ts_decorate5(decorators, target, key, desc) {
|
|
647
827
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
648
828
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -660,95 +840,170 @@ function _ts_param3(paramIndex, decorator) {
|
|
|
660
840
|
};
|
|
661
841
|
}
|
|
662
842
|
__name(_ts_param3, "_ts_param");
|
|
663
|
-
var WebhookController = class {
|
|
843
|
+
var WebhookController = class _WebhookController {
|
|
664
844
|
static {
|
|
665
845
|
__name(this, "WebhookController");
|
|
666
846
|
}
|
|
667
847
|
capabilityService;
|
|
848
|
+
logger = new Logger4(_WebhookController.name);
|
|
668
849
|
constructor(capabilityService) {
|
|
669
850
|
this.capabilityService = capabilityService;
|
|
670
851
|
}
|
|
671
852
|
list() {
|
|
672
853
|
const capabilities = this.capabilityService.listCapabilities();
|
|
673
854
|
return {
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
}
|
|
855
|
+
status_code: ErrorCodes.SUCCESS,
|
|
856
|
+
data: {
|
|
857
|
+
capabilities: capabilities.map((c) => ({
|
|
858
|
+
id: c.id,
|
|
859
|
+
name: c.name,
|
|
860
|
+
pluginID: c.pluginKey,
|
|
861
|
+
pluginVersion: c.pluginVersion
|
|
862
|
+
}))
|
|
863
|
+
}
|
|
683
864
|
};
|
|
684
865
|
}
|
|
685
866
|
async execute(capabilityId, body) {
|
|
686
867
|
try {
|
|
687
868
|
const result = await this.capabilityService.load(capabilityId).call(body.action, body.params);
|
|
688
869
|
return {
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
870
|
+
status_code: ErrorCodes.SUCCESS,
|
|
871
|
+
data: {
|
|
872
|
+
output: result
|
|
873
|
+
}
|
|
692
874
|
};
|
|
693
875
|
} catch (error) {
|
|
694
876
|
if (error instanceof CapabilityNotFoundError) {
|
|
695
877
|
throw new HttpException2({
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
error: "CAPABILITY_NOT_FOUND"
|
|
878
|
+
status_code: ErrorCodes.CAPABILITY_NOT_FOUND,
|
|
879
|
+
error_msg: `Capability not found: ${capabilityId}`
|
|
699
880
|
}, HttpStatus2.NOT_FOUND);
|
|
700
881
|
}
|
|
701
882
|
if (error instanceof PluginNotFoundError) {
|
|
702
883
|
throw new HttpException2({
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
error: "PLUGIN_NOT_FOUND"
|
|
884
|
+
status_code: ErrorCodes.PLUGIN_NOT_FOUND,
|
|
885
|
+
error_msg: `Plugin not found`
|
|
706
886
|
}, HttpStatus2.INTERNAL_SERVER_ERROR);
|
|
707
887
|
}
|
|
708
888
|
if (error instanceof ActionNotFoundError) {
|
|
709
889
|
throw new HttpException2({
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
error: "ACTION_NOT_FOUND"
|
|
890
|
+
status_code: ErrorCodes.ACTION_NOT_FOUND,
|
|
891
|
+
error_msg: `Action '${body.action}' not found`
|
|
713
892
|
}, HttpStatus2.BAD_REQUEST);
|
|
714
893
|
}
|
|
715
894
|
throw new HttpException2({
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
error: "EXECUTION_ERROR"
|
|
895
|
+
status_code: ErrorCodes.EXECUTION_ERROR,
|
|
896
|
+
error_msg: `Execution failed: ${error instanceof Error ? error.message : String(error)}`
|
|
719
897
|
}, HttpStatus2.INTERNAL_SERVER_ERROR);
|
|
720
898
|
}
|
|
721
899
|
}
|
|
722
900
|
async executeStream(capabilityId, body, res) {
|
|
901
|
+
const startTime = Date.now();
|
|
902
|
+
const loggerContext = {
|
|
903
|
+
capability_id: capabilityId,
|
|
904
|
+
action: body.action
|
|
905
|
+
};
|
|
723
906
|
res.setHeader("Content-Type", "text/event-stream");
|
|
724
907
|
res.setHeader("Cache-Control", "no-cache");
|
|
725
908
|
res.setHeader("Connection", "keep-alive");
|
|
726
909
|
try {
|
|
910
|
+
this.logger.log(`Executing capability (stream), input: ${stringifyForLog(body.params)}`, loggerContext);
|
|
727
911
|
const capability = this.capabilityService.load(capabilityId);
|
|
728
|
-
const
|
|
729
|
-
|
|
730
|
-
|
|
912
|
+
const eventStream = capability.callStreamWithEvents(body.action, body.params);
|
|
913
|
+
let pendingChunk = null;
|
|
914
|
+
const allChunks = [];
|
|
915
|
+
for await (const event of eventStream) {
|
|
916
|
+
switch (event.type) {
|
|
917
|
+
case "data": {
|
|
918
|
+
allChunks.push(event.data);
|
|
919
|
+
if (pendingChunk !== null) {
|
|
920
|
+
const response = {
|
|
921
|
+
status_code: ErrorCodes.SUCCESS,
|
|
922
|
+
data: {
|
|
923
|
+
type: "content",
|
|
924
|
+
delta: {
|
|
925
|
+
content: pendingChunk
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
};
|
|
929
|
+
res.write(`data: ${JSON.stringify(response)}
|
|
930
|
+
|
|
931
|
+
`);
|
|
932
|
+
}
|
|
933
|
+
pendingChunk = event.data;
|
|
934
|
+
break;
|
|
935
|
+
}
|
|
936
|
+
case "done": {
|
|
937
|
+
if (pendingChunk !== null) {
|
|
938
|
+
const response = {
|
|
939
|
+
status_code: ErrorCodes.SUCCESS,
|
|
940
|
+
data: {
|
|
941
|
+
type: "content",
|
|
942
|
+
delta: {
|
|
943
|
+
content: pendingChunk
|
|
944
|
+
},
|
|
945
|
+
finished: true
|
|
946
|
+
}
|
|
947
|
+
};
|
|
948
|
+
res.write(`data: ${JSON.stringify(response)}
|
|
731
949
|
|
|
732
950
|
`);
|
|
951
|
+
}
|
|
952
|
+
this.logger.log(`Capability (stream) executed successfully, duration: ${Date.now() - startTime}ms, chunks: ${allChunks.length}, result: ${stringifyForLog(allChunks)}`, loggerContext);
|
|
953
|
+
res.end();
|
|
954
|
+
return;
|
|
955
|
+
}
|
|
956
|
+
case "error": {
|
|
957
|
+
const response = {
|
|
958
|
+
status_code: ErrorCodes.SUCCESS,
|
|
959
|
+
data: {
|
|
960
|
+
type: "error",
|
|
961
|
+
error: {
|
|
962
|
+
code: 0,
|
|
963
|
+
message: event.error.message
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
};
|
|
967
|
+
res.write(`data: ${JSON.stringify(response)}
|
|
968
|
+
|
|
969
|
+
`);
|
|
970
|
+
res.end();
|
|
971
|
+
return;
|
|
972
|
+
}
|
|
973
|
+
}
|
|
733
974
|
}
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
975
|
+
if (pendingChunk !== null) {
|
|
976
|
+
const response = {
|
|
977
|
+
status_code: ErrorCodes.SUCCESS,
|
|
978
|
+
data: {
|
|
979
|
+
type: "content",
|
|
980
|
+
delta: {
|
|
981
|
+
content: pendingChunk
|
|
982
|
+
},
|
|
983
|
+
finished: true
|
|
984
|
+
}
|
|
985
|
+
};
|
|
986
|
+
res.write(`data: ${JSON.stringify(response)}
|
|
987
|
+
|
|
988
|
+
`);
|
|
744
989
|
}
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
990
|
+
this.logger.log(`Capability (stream) executed successfully, duration: ${Date.now() - startTime}ms, chunks: ${allChunks.length}, result: ${stringifyForLog(allChunks)}`, loggerContext);
|
|
991
|
+
res.end();
|
|
992
|
+
} catch (error) {
|
|
993
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
994
|
+
const response = {
|
|
995
|
+
status_code: ErrorCodes.SUCCESS,
|
|
996
|
+
data: {
|
|
997
|
+
type: "error",
|
|
998
|
+
error: {
|
|
999
|
+
code: 0,
|
|
1000
|
+
message: errorMsg
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
};
|
|
1004
|
+
res.write(`data: ${JSON.stringify(response)}
|
|
749
1005
|
|
|
750
1006
|
`);
|
|
751
|
-
} finally {
|
|
752
1007
|
res.end();
|
|
753
1008
|
}
|
|
754
1009
|
}
|
|
@@ -757,7 +1012,7 @@ _ts_decorate5([
|
|
|
757
1012
|
Get2("list"),
|
|
758
1013
|
_ts_metadata3("design:type", Function),
|
|
759
1014
|
_ts_metadata3("design:paramtypes", []),
|
|
760
|
-
_ts_metadata3("design:returntype", typeof
|
|
1015
|
+
_ts_metadata3("design:returntype", typeof SuccessResponse === "undefined" ? Object : SuccessResponse)
|
|
761
1016
|
], WebhookController.prototype, "list", null);
|
|
762
1017
|
_ts_decorate5([
|
|
763
1018
|
Post2(":capability_id"),
|
|
@@ -793,7 +1048,7 @@ WebhookController = _ts_decorate5([
|
|
|
793
1048
|
|
|
794
1049
|
// src/capability.module.ts
|
|
795
1050
|
import { Module } from "@nestjs/common";
|
|
796
|
-
import { RequestContextService as RequestContextService2, PLATFORM_HTTP_CLIENT as PLATFORM_HTTP_CLIENT2 } from "@lark-apaas/nestjs-common";
|
|
1051
|
+
import { CommonModule, RequestContextService as RequestContextService2, PLATFORM_HTTP_CLIENT as PLATFORM_HTTP_CLIENT2 } from "@lark-apaas/nestjs-common";
|
|
797
1052
|
function _ts_decorate6(decorators, target, key, desc) {
|
|
798
1053
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
799
1054
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -820,6 +1075,9 @@ var CapabilityModule = class _CapabilityModule {
|
|
|
820
1075
|
static forRoot(options) {
|
|
821
1076
|
return {
|
|
822
1077
|
module: _CapabilityModule,
|
|
1078
|
+
imports: [
|
|
1079
|
+
CommonModule
|
|
1080
|
+
],
|
|
823
1081
|
controllers: getControllers(),
|
|
824
1082
|
providers: [
|
|
825
1083
|
{
|
|
@@ -854,6 +1112,9 @@ var CapabilityModule = class _CapabilityModule {
|
|
|
854
1112
|
};
|
|
855
1113
|
CapabilityModule = _ts_decorate6([
|
|
856
1114
|
Module({
|
|
1115
|
+
imports: [
|
|
1116
|
+
CommonModule
|
|
1117
|
+
],
|
|
857
1118
|
controllers: getControllers(),
|
|
858
1119
|
providers: [
|
|
859
1120
|
CapabilityService,
|
|
@@ -871,6 +1132,7 @@ export {
|
|
|
871
1132
|
CapabilityNotFoundError,
|
|
872
1133
|
CapabilityService,
|
|
873
1134
|
DebugController,
|
|
1135
|
+
ErrorCodes,
|
|
874
1136
|
PluginLoadError,
|
|
875
1137
|
PluginLoaderService,
|
|
876
1138
|
PluginNotFoundError,
|