@lark-apaas/nestjs-capability 0.1.5-alpha.7 → 0.1.5
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 +7 -1
- package/dist/index.cjs +102 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +32 -4
- package/dist/index.d.ts +32 -4
- package/dist/index.js +104 -30
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Logger, OnModuleInit, OnModuleDestroy, DynamicModule } from '@nestjs/common';
|
|
2
|
-
import { PlatformHttpClient, RequestContextService } from '@lark-apaas/nestjs-common';
|
|
2
|
+
import { PlatformHttpClient, RequestContextService, HttpClientFactory } from '@lark-apaas/nestjs-common';
|
|
3
3
|
import { ZodSchema } from 'zod';
|
|
4
4
|
import { Response } from 'express';
|
|
5
5
|
|
|
@@ -9,6 +9,8 @@ interface UserContext {
|
|
|
9
9
|
appId: string;
|
|
10
10
|
}
|
|
11
11
|
interface PluginActionContext {
|
|
12
|
+
/** 插件标识(如 @official/ai-chat) */
|
|
13
|
+
pluginKey: string;
|
|
12
14
|
logger: Logger;
|
|
13
15
|
platformHttpClient: PlatformHttpClient;
|
|
14
16
|
userContext: UserContext;
|
|
@@ -48,6 +50,8 @@ interface SuccessResponse<T> {
|
|
|
48
50
|
interface ErrorResponse {
|
|
49
51
|
status_code: string;
|
|
50
52
|
error_msg: string;
|
|
53
|
+
/** 是否为计费受限错误(当 status_code 为业务错误码时为 true) */
|
|
54
|
+
is_rate_limit_error?: boolean;
|
|
51
55
|
}
|
|
52
56
|
/**
|
|
53
57
|
* Debug 信息
|
|
@@ -106,8 +110,11 @@ interface StreamErrorResponse {
|
|
|
106
110
|
data: {
|
|
107
111
|
type: 'error';
|
|
108
112
|
error: {
|
|
109
|
-
|
|
113
|
+
/** 错误码,计费受限时为业务错误码(如 k_st_ec_400002687),其他情况为框架错误码 */
|
|
114
|
+
code: string;
|
|
110
115
|
message: string;
|
|
116
|
+
/** 是否为计费受限错误 */
|
|
117
|
+
isRateLimitError?: boolean;
|
|
111
118
|
};
|
|
112
119
|
};
|
|
113
120
|
}
|
|
@@ -133,6 +140,10 @@ interface StreamError {
|
|
|
133
140
|
code: string;
|
|
134
141
|
message: string;
|
|
135
142
|
details?: unknown;
|
|
143
|
+
/** 计费受限时的业务错误码(仅 code 为 RATE_LIMIT_EXCEEDED 时存在) */
|
|
144
|
+
rateLimitCode?: string;
|
|
145
|
+
/** 计费受限时的业务错误消息(仅 code 为 RATE_LIMIT_EXCEEDED 时存在) */
|
|
146
|
+
rateLimitMessage?: string;
|
|
136
147
|
}
|
|
137
148
|
/**
|
|
138
149
|
* 流事件类型
|
|
@@ -197,6 +208,8 @@ declare const ErrorCodes: {
|
|
|
197
208
|
readonly PARAMS_VALIDATION_ERROR: "k_ec_cap_004";
|
|
198
209
|
/** 执行失败 */
|
|
199
210
|
readonly EXECUTION_ERROR: "k_ec_cap_005";
|
|
211
|
+
/** 计费受限 */
|
|
212
|
+
readonly RATE_LIMIT_EXCEEDED: "k_ec_cap_006";
|
|
200
213
|
};
|
|
201
214
|
type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes];
|
|
202
215
|
|
|
@@ -366,7 +379,7 @@ interface CapabilityModuleOptions {
|
|
|
366
379
|
}
|
|
367
380
|
declare class CapabilityService implements OnModuleInit, OnModuleDestroy {
|
|
368
381
|
private readonly requestContextService;
|
|
369
|
-
private readonly
|
|
382
|
+
private readonly httpClientFactory;
|
|
370
383
|
private readonly pluginLoaderService;
|
|
371
384
|
private readonly templateEngineService;
|
|
372
385
|
private readonly logger;
|
|
@@ -376,7 +389,7 @@ declare class CapabilityService implements OnModuleInit, OnModuleDestroy {
|
|
|
376
389
|
private capabilitiesDir;
|
|
377
390
|
private fileWatcher;
|
|
378
391
|
private options;
|
|
379
|
-
constructor(requestContextService: RequestContextService,
|
|
392
|
+
constructor(requestContextService: RequestContextService, httpClientFactory: HttpClientFactory, pluginLoaderService: PluginLoaderService, templateEngineService: TemplateEngineService);
|
|
380
393
|
/**
|
|
381
394
|
* 设置模块配置
|
|
382
395
|
*/
|
|
@@ -448,7 +461,22 @@ declare class CapabilityService implements OnModuleInit, OnModuleDestroy {
|
|
|
448
461
|
* - 如果插件不支持,则包装 runStream/run 为 StreamEvent
|
|
449
462
|
*/
|
|
450
463
|
private executeCallStreamWithEvents;
|
|
464
|
+
/**
|
|
465
|
+
* 从错误对象提取错误信息
|
|
466
|
+
* 支持 PluginError 和 RateLimitError
|
|
467
|
+
*/
|
|
468
|
+
private extractErrorInfo;
|
|
451
469
|
private buildActionContext;
|
|
470
|
+
/**
|
|
471
|
+
* 为指定插件创建独立的 HttpClient 实例
|
|
472
|
+
* 自动添加 x-plugin-key header
|
|
473
|
+
*/
|
|
474
|
+
private createPluginHttpClient;
|
|
475
|
+
/**
|
|
476
|
+
* 将 HttpClient 包装为受保护的 PlatformHttpClient
|
|
477
|
+
* 只暴露请求方法,不暴露 interceptors
|
|
478
|
+
*/
|
|
479
|
+
private wrapAsProtectedClient;
|
|
452
480
|
private getUserContext;
|
|
453
481
|
}
|
|
454
482
|
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,9 @@ var ErrorCodes = {
|
|
|
14
14
|
/** 参数验证失败 */
|
|
15
15
|
PARAMS_VALIDATION_ERROR: "k_ec_cap_004",
|
|
16
16
|
/** 执行失败 */
|
|
17
|
-
EXECUTION_ERROR: "k_ec_cap_005"
|
|
17
|
+
EXECUTION_ERROR: "k_ec_cap_005",
|
|
18
|
+
/** 计费受限 */
|
|
19
|
+
RATE_LIMIT_EXCEEDED: "k_ec_cap_006"
|
|
18
20
|
};
|
|
19
21
|
|
|
20
22
|
// src/services/template-engine.service.ts
|
|
@@ -380,7 +382,7 @@ PluginLoaderService = _ts_decorate2([
|
|
|
380
382
|
|
|
381
383
|
// src/services/capability.service.ts
|
|
382
384
|
import { Injectable as Injectable3, Logger as Logger2, Inject } from "@nestjs/common";
|
|
383
|
-
import { RequestContextService,
|
|
385
|
+
import { RequestContextService, HTTP_CLIENT_FACTORY } from "@lark-apaas/nestjs-common";
|
|
384
386
|
import * as fs2 from "fs";
|
|
385
387
|
import * as path2 from "path";
|
|
386
388
|
import * as chokidar from "chokidar";
|
|
@@ -489,7 +491,7 @@ var CapabilityService = class _CapabilityService {
|
|
|
489
491
|
__name(this, "CapabilityService");
|
|
490
492
|
}
|
|
491
493
|
requestContextService;
|
|
492
|
-
|
|
494
|
+
httpClientFactory;
|
|
493
495
|
pluginLoaderService;
|
|
494
496
|
templateEngineService;
|
|
495
497
|
logger = new Logger2(_CapabilityService.name);
|
|
@@ -499,9 +501,9 @@ var CapabilityService = class _CapabilityService {
|
|
|
499
501
|
capabilitiesDir;
|
|
500
502
|
fileWatcher = null;
|
|
501
503
|
options = {};
|
|
502
|
-
constructor(requestContextService,
|
|
504
|
+
constructor(requestContextService, httpClientFactory, pluginLoaderService, templateEngineService) {
|
|
503
505
|
this.requestContextService = requestContextService;
|
|
504
|
-
this.
|
|
506
|
+
this.httpClientFactory = httpClientFactory;
|
|
505
507
|
this.pluginLoaderService = pluginLoaderService;
|
|
506
508
|
this.templateEngineService = templateEngineService;
|
|
507
509
|
const isDev = process.env.NODE_ENV === "development";
|
|
@@ -741,7 +743,7 @@ var CapabilityService = class _CapabilityService {
|
|
|
741
743
|
if (!pluginInstance.hasAction(actionName)) {
|
|
742
744
|
throw new ActionNotFoundError(config.pluginKey, actionName);
|
|
743
745
|
}
|
|
744
|
-
const context = this.buildActionContext(contextOverride);
|
|
746
|
+
const context = this.buildActionContext(config.pluginKey, contextOverride);
|
|
745
747
|
const isStream = pluginInstance.isStreamAction?.(actionName) ?? false;
|
|
746
748
|
this.logger.log("Executing capability (call)", {
|
|
747
749
|
...loggerContext,
|
|
@@ -791,7 +793,7 @@ var CapabilityService = class _CapabilityService {
|
|
|
791
793
|
if (!pluginInstance.hasAction(actionName)) {
|
|
792
794
|
throw new ActionNotFoundError(config.pluginKey, actionName);
|
|
793
795
|
}
|
|
794
|
-
const context = this.buildActionContext(contextOverride);
|
|
796
|
+
const context = this.buildActionContext(config.pluginKey, contextOverride);
|
|
795
797
|
const isStream = pluginInstance.isStreamAction?.(actionName) ?? false;
|
|
796
798
|
this.logger.log("Executing capability (stream)", {
|
|
797
799
|
...loggerContext,
|
|
@@ -841,7 +843,7 @@ var CapabilityService = class _CapabilityService {
|
|
|
841
843
|
if (!pluginInstance.hasAction(actionName)) {
|
|
842
844
|
throw new ActionNotFoundError(config.pluginKey, actionName);
|
|
843
845
|
}
|
|
844
|
-
const context = this.buildActionContext(contextOverride);
|
|
846
|
+
const context = this.buildActionContext(config.pluginKey, contextOverride);
|
|
845
847
|
const isStream = pluginInstance.isStreamAction?.(actionName) ?? false;
|
|
846
848
|
this.logger.log("Executing capability (streamWithEvents)", {
|
|
847
849
|
...loggerContext,
|
|
@@ -907,21 +909,69 @@ var CapabilityService = class _CapabilityService {
|
|
|
907
909
|
});
|
|
908
910
|
yield {
|
|
909
911
|
type: "error",
|
|
910
|
-
error:
|
|
911
|
-
code: "EXECUTION_ERROR",
|
|
912
|
-
message: error instanceof Error ? error.message : String(error)
|
|
913
|
-
}
|
|
912
|
+
error: this.extractErrorInfo(error)
|
|
914
913
|
};
|
|
915
914
|
}
|
|
916
915
|
}
|
|
917
|
-
|
|
916
|
+
/**
|
|
917
|
+
* 从错误对象提取错误信息
|
|
918
|
+
* 支持 PluginError 和 RateLimitError
|
|
919
|
+
*/
|
|
920
|
+
extractErrorInfo(error) {
|
|
921
|
+
const err = error;
|
|
922
|
+
const code = err?.code ?? "EXECUTION_ERROR";
|
|
923
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
924
|
+
if (code === "RATE_LIMIT_EXCEEDED" && err?.rateLimitCode) {
|
|
925
|
+
return {
|
|
926
|
+
code,
|
|
927
|
+
message,
|
|
928
|
+
rateLimitCode: err.rateLimitCode,
|
|
929
|
+
rateLimitMessage: err.rateLimitMessage
|
|
930
|
+
};
|
|
931
|
+
}
|
|
918
932
|
return {
|
|
933
|
+
code,
|
|
934
|
+
message
|
|
935
|
+
};
|
|
936
|
+
}
|
|
937
|
+
buildActionContext(pluginKey, override) {
|
|
938
|
+
return {
|
|
939
|
+
pluginKey,
|
|
919
940
|
logger: this.logger,
|
|
920
|
-
platformHttpClient: this.
|
|
941
|
+
platformHttpClient: this.createPluginHttpClient(pluginKey),
|
|
921
942
|
userContext: override?.userContext ?? this.getUserContext(),
|
|
922
943
|
isDebug: override?.isDebug ?? false
|
|
923
944
|
};
|
|
924
945
|
}
|
|
946
|
+
/**
|
|
947
|
+
* 为指定插件创建独立的 HttpClient 实例
|
|
948
|
+
* 自动添加 x-plugin-key header
|
|
949
|
+
*/
|
|
950
|
+
createPluginHttpClient(pluginKey) {
|
|
951
|
+
const client = this.httpClientFactory.create();
|
|
952
|
+
client.interceptors.request.use((config) => {
|
|
953
|
+
config.headers = {
|
|
954
|
+
...config.headers,
|
|
955
|
+
"x-plugin-key": pluginKey
|
|
956
|
+
};
|
|
957
|
+
return config;
|
|
958
|
+
});
|
|
959
|
+
return this.wrapAsProtectedClient(client);
|
|
960
|
+
}
|
|
961
|
+
/**
|
|
962
|
+
* 将 HttpClient 包装为受保护的 PlatformHttpClient
|
|
963
|
+
* 只暴露请求方法,不暴露 interceptors
|
|
964
|
+
*/
|
|
965
|
+
wrapAsProtectedClient(client) {
|
|
966
|
+
return {
|
|
967
|
+
request: /* @__PURE__ */ __name((config) => client.request(config), "request"),
|
|
968
|
+
get: /* @__PURE__ */ __name((url, config) => client.get(url, config), "get"),
|
|
969
|
+
post: /* @__PURE__ */ __name((url, data, config) => client.post(url, data, config), "post"),
|
|
970
|
+
put: /* @__PURE__ */ __name((url, data, config) => client.put(url, data, config), "put"),
|
|
971
|
+
patch: /* @__PURE__ */ __name((url, data, config) => client.patch(url, data, config), "patch"),
|
|
972
|
+
delete: /* @__PURE__ */ __name((url, config) => client.delete(url, config), "delete")
|
|
973
|
+
};
|
|
974
|
+
}
|
|
925
975
|
getUserContext() {
|
|
926
976
|
const ctx = this.requestContextService.getContext();
|
|
927
977
|
return {
|
|
@@ -933,11 +983,11 @@ var CapabilityService = class _CapabilityService {
|
|
|
933
983
|
};
|
|
934
984
|
CapabilityService = _ts_decorate3([
|
|
935
985
|
Injectable3(),
|
|
936
|
-
_ts_param(1, Inject(
|
|
986
|
+
_ts_param(1, Inject(HTTP_CLIENT_FACTORY)),
|
|
937
987
|
_ts_metadata("design:type", Function),
|
|
938
988
|
_ts_metadata("design:paramtypes", [
|
|
939
989
|
typeof RequestContextService === "undefined" ? Object : RequestContextService,
|
|
940
|
-
typeof
|
|
990
|
+
typeof HttpClientFactory === "undefined" ? Object : HttpClientFactory,
|
|
941
991
|
typeof PluginLoaderService === "undefined" ? Object : PluginLoaderService,
|
|
942
992
|
typeof TemplateEngineService === "undefined" ? Object : TemplateEngineService
|
|
943
993
|
])
|
|
@@ -1078,6 +1128,14 @@ var DebugController = class _DebugController {
|
|
|
1078
1128
|
error_msg: `Action '${error.actionName}' not found in plugin ${error.pluginKey}`
|
|
1079
1129
|
};
|
|
1080
1130
|
}
|
|
1131
|
+
const err = error;
|
|
1132
|
+
if (err?.code === "RATE_LIMIT_EXCEEDED" && err?.rateLimitCode) {
|
|
1133
|
+
return {
|
|
1134
|
+
status_code: err.rateLimitCode,
|
|
1135
|
+
error_msg: err.rateLimitMessage || err.message,
|
|
1136
|
+
is_rate_limit_error: true
|
|
1137
|
+
};
|
|
1138
|
+
}
|
|
1081
1139
|
return {
|
|
1082
1140
|
status_code: ErrorCodes.EXECUTION_ERROR,
|
|
1083
1141
|
error_msg: `Execution failed: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -1146,13 +1204,15 @@ var DebugController = class _DebugController {
|
|
|
1146
1204
|
return;
|
|
1147
1205
|
}
|
|
1148
1206
|
case "error": {
|
|
1207
|
+
const isRateLimitError = event.error.code === "RATE_LIMIT_EXCEEDED" && !!event.error.rateLimitCode;
|
|
1149
1208
|
const response = {
|
|
1150
1209
|
status_code: ErrorCodes.SUCCESS,
|
|
1151
1210
|
data: {
|
|
1152
1211
|
type: "error",
|
|
1153
1212
|
error: {
|
|
1154
|
-
code:
|
|
1155
|
-
message: event.error.message
|
|
1213
|
+
code: isRateLimitError ? event.error.rateLimitCode : event.error.code,
|
|
1214
|
+
message: isRateLimitError ? event.error.rateLimitMessage : event.error.message,
|
|
1215
|
+
isRateLimitError: isRateLimitError || void 0
|
|
1156
1216
|
}
|
|
1157
1217
|
}
|
|
1158
1218
|
};
|
|
@@ -1179,14 +1239,16 @@ var DebugController = class _DebugController {
|
|
|
1179
1239
|
}
|
|
1180
1240
|
res.end();
|
|
1181
1241
|
} catch (error) {
|
|
1182
|
-
const
|
|
1242
|
+
const err = error;
|
|
1243
|
+
const isRateLimitError = err?.code === "RATE_LIMIT_EXCEEDED" && !!err?.rateLimitCode;
|
|
1183
1244
|
const response = {
|
|
1184
1245
|
status_code: ErrorCodes.SUCCESS,
|
|
1185
1246
|
data: {
|
|
1186
1247
|
type: "error",
|
|
1187
1248
|
error: {
|
|
1188
|
-
code:
|
|
1189
|
-
message:
|
|
1249
|
+
code: isRateLimitError ? err.rateLimitCode : err?.code ?? "EXECUTION_ERROR",
|
|
1250
|
+
message: isRateLimitError ? err.rateLimitMessage : error instanceof Error ? error.message : String(error),
|
|
1251
|
+
isRateLimitError: isRateLimitError || void 0
|
|
1190
1252
|
}
|
|
1191
1253
|
}
|
|
1192
1254
|
};
|
|
@@ -1330,6 +1392,14 @@ var WebhookController = class _WebhookController {
|
|
|
1330
1392
|
error_msg: `Action '${error.actionName}' not found in plugin ${error.pluginKey}`
|
|
1331
1393
|
};
|
|
1332
1394
|
}
|
|
1395
|
+
const err = error;
|
|
1396
|
+
if (err?.code === "RATE_LIMIT_EXCEEDED" && err?.rateLimitCode) {
|
|
1397
|
+
return {
|
|
1398
|
+
status_code: err.rateLimitCode,
|
|
1399
|
+
error_msg: err.rateLimitMessage || err.message,
|
|
1400
|
+
is_rate_limit_error: true
|
|
1401
|
+
};
|
|
1402
|
+
}
|
|
1333
1403
|
return {
|
|
1334
1404
|
status_code: ErrorCodes.EXECUTION_ERROR,
|
|
1335
1405
|
error_msg: `Execution failed: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -1392,13 +1462,15 @@ var WebhookController = class _WebhookController {
|
|
|
1392
1462
|
return;
|
|
1393
1463
|
}
|
|
1394
1464
|
case "error": {
|
|
1465
|
+
const isRateLimitError = event.error.code === "RATE_LIMIT_EXCEEDED" && !!event.error.rateLimitCode;
|
|
1395
1466
|
const response = {
|
|
1396
1467
|
status_code: ErrorCodes.SUCCESS,
|
|
1397
1468
|
data: {
|
|
1398
1469
|
type: "error",
|
|
1399
1470
|
error: {
|
|
1400
|
-
code:
|
|
1401
|
-
message: event.error.message
|
|
1471
|
+
code: isRateLimitError ? event.error.rateLimitCode : event.error.code,
|
|
1472
|
+
message: isRateLimitError ? event.error.rateLimitMessage : event.error.message,
|
|
1473
|
+
isRateLimitError: isRateLimitError || void 0
|
|
1402
1474
|
}
|
|
1403
1475
|
}
|
|
1404
1476
|
};
|
|
@@ -1425,14 +1497,16 @@ var WebhookController = class _WebhookController {
|
|
|
1425
1497
|
}
|
|
1426
1498
|
res.end();
|
|
1427
1499
|
} catch (error) {
|
|
1428
|
-
const
|
|
1500
|
+
const err = error;
|
|
1501
|
+
const isRateLimitError = err?.code === "RATE_LIMIT_EXCEEDED" && !!err?.rateLimitCode;
|
|
1429
1502
|
const response = {
|
|
1430
1503
|
status_code: ErrorCodes.SUCCESS,
|
|
1431
1504
|
data: {
|
|
1432
1505
|
type: "error",
|
|
1433
1506
|
error: {
|
|
1434
|
-
code:
|
|
1435
|
-
message:
|
|
1507
|
+
code: isRateLimitError ? err.rateLimitCode : err?.code ?? "EXECUTION_ERROR",
|
|
1508
|
+
message: isRateLimitError ? err.rateLimitMessage : error instanceof Error ? error.message : String(error),
|
|
1509
|
+
isRateLimitError: isRateLimitError || void 0
|
|
1436
1510
|
}
|
|
1437
1511
|
}
|
|
1438
1512
|
};
|
|
@@ -1489,7 +1563,7 @@ WebhookController = _ts_decorate5([
|
|
|
1489
1563
|
|
|
1490
1564
|
// src/capability.module.ts
|
|
1491
1565
|
import { Module } from "@nestjs/common";
|
|
1492
|
-
import { CommonModule, RequestContextService as RequestContextService2,
|
|
1566
|
+
import { CommonModule, RequestContextService as RequestContextService2, HTTP_CLIENT_FACTORY as HTTP_CLIENT_FACTORY2 } from "@lark-apaas/nestjs-common";
|
|
1493
1567
|
function _ts_decorate6(decorators, target, key, desc) {
|
|
1494
1568
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1495
1569
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -1527,8 +1601,8 @@ var CapabilityModule = class _CapabilityModule {
|
|
|
1527
1601
|
},
|
|
1528
1602
|
{
|
|
1529
1603
|
provide: CapabilityService,
|
|
1530
|
-
useFactory: /* @__PURE__ */ __name((requestContextService,
|
|
1531
|
-
const service = new CapabilityService(requestContextService,
|
|
1604
|
+
useFactory: /* @__PURE__ */ __name((requestContextService, httpClientFactory, pluginLoader, templateEngine, moduleOptions) => {
|
|
1605
|
+
const service = new CapabilityService(requestContextService, httpClientFactory, pluginLoader, templateEngine);
|
|
1532
1606
|
if (moduleOptions) {
|
|
1533
1607
|
service.setOptions(moduleOptions);
|
|
1534
1608
|
}
|
|
@@ -1536,7 +1610,7 @@ var CapabilityModule = class _CapabilityModule {
|
|
|
1536
1610
|
}, "useFactory"),
|
|
1537
1611
|
inject: [
|
|
1538
1612
|
RequestContextService2,
|
|
1539
|
-
|
|
1613
|
+
HTTP_CLIENT_FACTORY2,
|
|
1540
1614
|
PluginLoaderService,
|
|
1541
1615
|
TemplateEngineService,
|
|
1542
1616
|
CAPABILITY_OPTIONS
|