@xpert-ai/plugin-sdk 3.7.0 → 3.7.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/index.cjs.js +522 -381
- package/index.esm.js +519 -384
- package/package.json +4 -1
- package/src/index.d.ts +1 -0
- package/src/lib/agent/middleware/index.d.ts +1 -0
- package/src/lib/agent/middleware/runtime.d.ts +57 -0
- package/src/lib/agent/middleware/strategy.decorator.d.ts +1 -1
- package/src/lib/agent/middleware/types.d.ts +73 -6
- package/src/lib/agent/skill/skill-source-provider.decorator.d.ts +1 -1
- package/src/lib/ai-model/ai-model.d.ts +3 -1
- package/src/lib/core/index.d.ts +2 -0
- package/src/lib/core/strategy-bus.d.ts +17 -0
- package/src/lib/core/types.d.ts +16 -0
- package/src/lib/core/utils.d.ts +6 -0
- package/src/lib/data/datasource/strategy.decorator.d.ts +1 -1
- package/src/lib/integration/strategy.decorator.d.ts +1 -1
- package/src/lib/rag/image/strategy.decorator.d.ts +1 -1
- package/src/lib/rag/knowledge/knowledge-strategy.decorator.d.ts +1 -1
- package/src/lib/rag/retriever/strategy.decorator.d.ts +1 -1
- package/src/lib/rag/source/strategy.decorator.d.ts +1 -1
- package/src/lib/rag/textsplitter/strategy.decorator.d.ts +1 -1
- package/src/lib/rag/transformer/strategy.decorator.d.ts +1 -1
- package/src/lib/strategy.d.ts +29 -3
- package/src/lib/toolset/strategy.decorator.d.ts +1 -1
- package/src/lib/types.d.ts +4 -0
- package/src/lib/vectorstore/strategy.decorator.d.ts +1 -1
- package/src/lib/workflow/node/strategy.decorator.d.ts +1 -1
- package/src/lib/workflow/trigger/strategy.decorator.d.ts +1 -1
package/index.cjs.js
CHANGED
|
@@ -4,11 +4,16 @@ var common = require('@nestjs/common');
|
|
|
4
4
|
var constants = require('@nestjs/common/constants');
|
|
5
5
|
var lodashEs = require('lodash-es');
|
|
6
6
|
var core = require('@nestjs/core');
|
|
7
|
+
var rxjs = require('rxjs');
|
|
8
|
+
var contracts = require('@metad/contracts');
|
|
9
|
+
var node_async_hooks = require('node:async_hooks');
|
|
10
|
+
var passportJwt = require('passport-jwt');
|
|
11
|
+
var jsonwebtoken = require('jsonwebtoken');
|
|
12
|
+
var node_crypto = require('node:crypto');
|
|
7
13
|
var cqrs = require('@nestjs/cqrs');
|
|
8
14
|
var fs = require('fs');
|
|
9
15
|
var http = require('http');
|
|
10
16
|
var https = require('https');
|
|
11
|
-
var contracts = require('@metad/contracts');
|
|
12
17
|
var tools = require('@langchain/core/tools');
|
|
13
18
|
var zod = require('zod');
|
|
14
19
|
var fsPromises = require('fs/promises');
|
|
@@ -16,10 +21,8 @@ var path = require('path');
|
|
|
16
21
|
var i18next = require('i18next');
|
|
17
22
|
var FsBackend = require('i18next-fs-backend');
|
|
18
23
|
var yaml = require('yaml');
|
|
19
|
-
var
|
|
20
|
-
var
|
|
21
|
-
var jsonwebtoken = require('jsonwebtoken');
|
|
22
|
-
var node_crypto = require('node:crypto');
|
|
24
|
+
var Ajv = require('ajv');
|
|
25
|
+
var schemaDraft04 = require('ajv/dist/refs/json-schema-draft-06.json');
|
|
23
26
|
var _axios = require('axios');
|
|
24
27
|
var openai = require('@langchain/openai');
|
|
25
28
|
var documents = require('@langchain/core/documents');
|
|
@@ -84,6 +87,11 @@ var _axios__namespace = /*#__PURE__*/_interopNamespaceDefault(_axios);
|
|
|
84
87
|
};
|
|
85
88
|
}
|
|
86
89
|
|
|
90
|
+
const ORGANIZATION_METADATA_KEY = 'xpert:organizationId';
|
|
91
|
+
const PLUGIN_METADATA_KEY = 'xpert:pluginName';
|
|
92
|
+
const GLOBAL_ORGANIZATION_SCOPE = 'global';
|
|
93
|
+
const STRATEGY_META_KEY = 'XPERT_STRATEGY_META_KEY';
|
|
94
|
+
|
|
87
95
|
function _extends() {
|
|
88
96
|
_extends = Object.assign || function assign(target) {
|
|
89
97
|
for(var i = 1; i < arguments.length; i++){
|
|
@@ -115,7 +123,7 @@ function createPluginLogger(scope, baseMeta = {}) {
|
|
|
115
123
|
}
|
|
116
124
|
|
|
117
125
|
const INTEGRATION_STRATEGY = 'INTEGRATION_STRATEGY';
|
|
118
|
-
const IntegrationStrategyKey = (provider)=>common.SetMetadata(INTEGRATION_STRATEGY, provider);
|
|
126
|
+
const IntegrationStrategyKey = (provider)=>common.applyDecorators(common.SetMetadata(INTEGRATION_STRATEGY, provider), common.SetMetadata(STRATEGY_META_KEY, INTEGRATION_STRATEGY));
|
|
119
127
|
|
|
120
128
|
function __decorate(decorators, target, key, desc) {
|
|
121
129
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -131,35 +139,346 @@ typeof SuppressedError === "function" ? SuppressedError : function _SuppressedEr
|
|
|
131
139
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
132
140
|
};
|
|
133
141
|
|
|
142
|
+
// request-context.ts
|
|
143
|
+
class RequestContext {
|
|
144
|
+
static currentRequestContext() {
|
|
145
|
+
const session = getRequestContext();
|
|
146
|
+
return session;
|
|
147
|
+
}
|
|
148
|
+
static currentRequest() {
|
|
149
|
+
const requestContext = RequestContext.currentRequestContext();
|
|
150
|
+
if (requestContext) {
|
|
151
|
+
return requestContext.request;
|
|
152
|
+
}
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
static currentTenantId() {
|
|
156
|
+
const user = RequestContext.currentUser();
|
|
157
|
+
if (user) {
|
|
158
|
+
return user.tenantId;
|
|
159
|
+
}
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
static currentUserId() {
|
|
163
|
+
const user = RequestContext.currentUser();
|
|
164
|
+
if (user) {
|
|
165
|
+
return user.id;
|
|
166
|
+
}
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
static currentRoleId() {
|
|
170
|
+
const user = RequestContext.currentUser();
|
|
171
|
+
if (user) {
|
|
172
|
+
return user.roleId;
|
|
173
|
+
}
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
static currentUser(throwError) {
|
|
177
|
+
const requestContext = RequestContext.currentRequestContext();
|
|
178
|
+
if (requestContext) {
|
|
179
|
+
// tslint:disable-next-line
|
|
180
|
+
const user = requestContext.request['user'];
|
|
181
|
+
if (user) {
|
|
182
|
+
return user;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
if (throwError) {
|
|
186
|
+
throw new common.HttpException('Unauthorized', common.HttpStatus.UNAUTHORIZED);
|
|
187
|
+
}
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
static hasPermission(permission, throwError) {
|
|
191
|
+
return this.hasPermissions([
|
|
192
|
+
permission
|
|
193
|
+
], throwError);
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Retrieves the language code from the headers of the current request.
|
|
197
|
+
* @returns The language code (LanguagesEnum) extracted from the headers, or the default language (ENGLISH) if not found.
|
|
198
|
+
*/ static getLanguageCode() {
|
|
199
|
+
// Retrieve the current request
|
|
200
|
+
const req = RequestContext.currentRequest();
|
|
201
|
+
// Variable to store the extracted language code
|
|
202
|
+
let lang;
|
|
203
|
+
// Check if a request exists
|
|
204
|
+
if (req) {
|
|
205
|
+
// Check if the 'language' header exists in the request
|
|
206
|
+
if (req.headers && req.headers['language']) {
|
|
207
|
+
// If found, set the lang variable
|
|
208
|
+
lang = req.headers['language'];
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
// Return the extracted language code or the default language (ENGLISH) if not found
|
|
212
|
+
return lang || contracts.LanguagesEnum.English;
|
|
213
|
+
}
|
|
214
|
+
static getOrganizationId() {
|
|
215
|
+
const req = this.currentRequest();
|
|
216
|
+
let organizationId;
|
|
217
|
+
const keys = [
|
|
218
|
+
'organization-id'
|
|
219
|
+
];
|
|
220
|
+
if (req) {
|
|
221
|
+
for (const key of keys){
|
|
222
|
+
if (req.headers && req.headers[key]) {
|
|
223
|
+
organizationId = req.headers[key];
|
|
224
|
+
break;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return organizationId;
|
|
229
|
+
}
|
|
230
|
+
static hasPermissions(findPermissions, throwError) {
|
|
231
|
+
const requestContext = RequestContext.currentRequestContext();
|
|
232
|
+
if (requestContext) {
|
|
233
|
+
// tslint:disable-next-line
|
|
234
|
+
const token = passportJwt.ExtractJwt.fromAuthHeaderAsBearerToken()(requestContext.request);
|
|
235
|
+
if (token) {
|
|
236
|
+
const { permissions } = jsonwebtoken.verify(token, process.env['JWT_SECRET']);
|
|
237
|
+
if (permissions) {
|
|
238
|
+
const found = permissions.filter((value)=>findPermissions.indexOf(value) >= 0);
|
|
239
|
+
if (found.length === findPermissions.length) {
|
|
240
|
+
return true;
|
|
241
|
+
}
|
|
242
|
+
} else {
|
|
243
|
+
return false;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
if (throwError) {
|
|
248
|
+
throw new common.HttpException('Unauthorized', common.HttpStatus.UNAUTHORIZED);
|
|
249
|
+
}
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
252
|
+
static hasAnyPermission(findPermissions, throwError) {
|
|
253
|
+
const requestContext = RequestContext.currentRequestContext();
|
|
254
|
+
if (requestContext) {
|
|
255
|
+
// tslint:disable-next-line
|
|
256
|
+
const token = passportJwt.ExtractJwt.fromAuthHeaderAsBearerToken()(requestContext.request);
|
|
257
|
+
if (token) {
|
|
258
|
+
const { permissions } = jsonwebtoken.verify(token, process.env['JWT_SECRET']);
|
|
259
|
+
const found = permissions.filter((value)=>findPermissions.indexOf(value) >= 0);
|
|
260
|
+
if (found.length > 0) {
|
|
261
|
+
return true;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
if (throwError) {
|
|
266
|
+
throw new common.HttpException('Unauthorized', common.HttpStatus.UNAUTHORIZED);
|
|
267
|
+
}
|
|
268
|
+
return false;
|
|
269
|
+
}
|
|
270
|
+
static currentToken(throwError) {
|
|
271
|
+
const requestContext = RequestContext.currentRequestContext();
|
|
272
|
+
if (requestContext) {
|
|
273
|
+
// tslint:disable-next-line
|
|
274
|
+
return passportJwt.ExtractJwt.fromAuthHeaderAsBearerToken()(requestContext.request);
|
|
275
|
+
}
|
|
276
|
+
if (throwError) {
|
|
277
|
+
throw new common.HttpException('Unauthorized', common.HttpStatus.UNAUTHORIZED);
|
|
278
|
+
}
|
|
279
|
+
return null;
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Checks if the current user has a specific role.
|
|
283
|
+
* @param {RolesEnum} role - The role to check.
|
|
284
|
+
* @param {boolean} throwError - Flag indicating whether to throw an error if the role is not granted.
|
|
285
|
+
* @returns {boolean} - True if the user has the role, otherwise false.
|
|
286
|
+
*/ static hasRole(role, throwError) {
|
|
287
|
+
return this.hasRoles([
|
|
288
|
+
role
|
|
289
|
+
], throwError);
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Checks if the current request context has any of the specified roles.
|
|
293
|
+
*
|
|
294
|
+
* @param roles - An array of roles to check.
|
|
295
|
+
* @param throwError - Whether to throw an error if no roles are found.
|
|
296
|
+
* @returns True if any of the required roles are found, otherwise false.
|
|
297
|
+
*/ static hasRoles(roles, throwError) {
|
|
298
|
+
const context = RequestContext.currentRequestContext();
|
|
299
|
+
if (context) {
|
|
300
|
+
try {
|
|
301
|
+
// tslint:disable-next-line
|
|
302
|
+
const token = this.currentToken();
|
|
303
|
+
if (token) {
|
|
304
|
+
const { role } = jsonwebtoken.verify(token, process.env['JWT_SECRET']);
|
|
305
|
+
return roles.includes(role != null ? role : null);
|
|
306
|
+
} else if (this.currentUser().role) {
|
|
307
|
+
return roles.includes(this.currentUser().role.name);
|
|
308
|
+
}
|
|
309
|
+
} catch (error) {
|
|
310
|
+
if (error instanceof jsonwebtoken.JsonWebTokenError) {
|
|
311
|
+
return false;
|
|
312
|
+
} else {
|
|
313
|
+
throw error;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
if (throwError) {
|
|
318
|
+
throw new common.HttpException('Unauthorized', common.HttpStatus.UNAUTHORIZED);
|
|
319
|
+
}
|
|
320
|
+
return false;
|
|
321
|
+
}
|
|
322
|
+
constructor(request, response, reqId, userId, extras = {}){
|
|
323
|
+
this.request = request;
|
|
324
|
+
this.response = response;
|
|
325
|
+
this.reqId = reqId;
|
|
326
|
+
this.userId = userId;
|
|
327
|
+
this.extras = extras;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
const als = new node_async_hooks.AsyncLocalStorage();
|
|
331
|
+
function getRequestContext() {
|
|
332
|
+
return als.getStore();
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// request-context.middleware.ts
|
|
336
|
+
exports.RequestContextMiddleware = class RequestContextMiddleware {
|
|
337
|
+
use(req, _res, next) {
|
|
338
|
+
var _req_user;
|
|
339
|
+
const reqId = req.headers['x-request-id'] || node_crypto.randomUUID();
|
|
340
|
+
// The userId can be placed in the authentication result here.
|
|
341
|
+
const userId = (_req_user = req['user']) == null ? void 0 : _req_user['id'];
|
|
342
|
+
const ctx = new RequestContext(req, _res, reqId, userId);
|
|
343
|
+
als.run(ctx, next);
|
|
344
|
+
}
|
|
345
|
+
};
|
|
346
|
+
exports.RequestContextMiddleware = __decorate([
|
|
347
|
+
common.Injectable()
|
|
348
|
+
], exports.RequestContextMiddleware);
|
|
349
|
+
function runWithRequestContext(req, res, next) {
|
|
350
|
+
var _req_user;
|
|
351
|
+
const reqId = req.headers['x-request-id'] || node_crypto.randomUUID();
|
|
352
|
+
const userId = (_req_user = req['user']) == null ? void 0 : _req_user['id'];
|
|
353
|
+
const ctx = new RequestContext(req, res, reqId, userId);
|
|
354
|
+
// Enable ALS scope
|
|
355
|
+
als.run(ctx, next);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
exports.StrategyBus = class StrategyBus {
|
|
359
|
+
upsert(strategyType, entry) {
|
|
360
|
+
this.subject.next({
|
|
361
|
+
type: 'UPSERT',
|
|
362
|
+
strategyType,
|
|
363
|
+
entry
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
remove(orgId, pluginName) {
|
|
367
|
+
this.subject.next({
|
|
368
|
+
type: 'REMOVE',
|
|
369
|
+
orgId,
|
|
370
|
+
pluginName
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
constructor(){
|
|
374
|
+
this.subject = new rxjs.Subject();
|
|
375
|
+
this.events$ = this.subject.asObservable();
|
|
376
|
+
}
|
|
377
|
+
};
|
|
378
|
+
exports.StrategyBus = __decorate([
|
|
379
|
+
common.Injectable()
|
|
380
|
+
], exports.StrategyBus);
|
|
381
|
+
|
|
134
382
|
class BaseStrategyRegistry {
|
|
135
383
|
onModuleInit() {
|
|
384
|
+
this.bus.events$.pipe(rxjs.filter((event)=>!event.strategyType || event.strategyType === this.strategyKey)).subscribe((evt)=>{
|
|
385
|
+
if (evt.type === 'UPSERT') {
|
|
386
|
+
this.upsert(evt.entry.instance);
|
|
387
|
+
} else if (evt.type === 'REMOVE') {
|
|
388
|
+
this.remove(evt.orgId, evt.pluginName);
|
|
389
|
+
}
|
|
390
|
+
});
|
|
136
391
|
const providers = this.discoveryService.getProviders();
|
|
137
392
|
for (const wrapper of providers){
|
|
138
393
|
const { instance } = wrapper;
|
|
139
394
|
if (!instance) continue;
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
395
|
+
this.upsert(instance);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
upsert(instance) {
|
|
399
|
+
const type = this.reflector.get(this.strategyKey, instance.constructor);
|
|
400
|
+
if (type) {
|
|
401
|
+
var _instance_metatype;
|
|
402
|
+
const target = (_instance_metatype = instance.metatype) != null ? _instance_metatype : instance.constructor;
|
|
403
|
+
var _this_reflector_get;
|
|
404
|
+
const organizationId = (_this_reflector_get = this.reflector.get(ORGANIZATION_METADATA_KEY, target)) != null ? _this_reflector_get : GLOBAL_ORGANIZATION_SCOPE;
|
|
405
|
+
var _this_strategies_get;
|
|
406
|
+
const orgMap = (_this_strategies_get = this.strategies.get(organizationId)) != null ? _this_strategies_get : new Map();
|
|
407
|
+
orgMap.set(type, instance);
|
|
408
|
+
this.strategies.set(organizationId, orgMap);
|
|
409
|
+
const pluginName = this.reflector.get(PLUGIN_METADATA_KEY, target);
|
|
410
|
+
this.logger.debug(`Registered strategy of type ${type} for organization ${organizationId} from plugin ${pluginName}`);
|
|
411
|
+
if (pluginName) {
|
|
412
|
+
var _this_pluginStrategies_get;
|
|
413
|
+
const pluginStrategies = (_this_pluginStrategies_get = this.pluginStrategies.get(pluginName)) != null ? _this_pluginStrategies_get : new Set();
|
|
414
|
+
pluginStrategies.add(type);
|
|
415
|
+
this.pluginStrategies.set(pluginName, pluginStrategies);
|
|
143
416
|
}
|
|
144
417
|
}
|
|
145
418
|
}
|
|
146
|
-
|
|
147
|
-
|
|
419
|
+
/**
|
|
420
|
+
* Remove all strategies registered by the given plugin for the given organization.
|
|
421
|
+
*/ remove(organizationId, pluginName) {
|
|
422
|
+
const strategies = this.pluginStrategies.get(pluginName);
|
|
423
|
+
const orgMap = this.strategies.get(organizationId);
|
|
424
|
+
for (const type of strategies != null ? strategies : []){
|
|
425
|
+
orgMap == null ? void 0 : orgMap.delete(type);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* Resolve organization id, falling back to request context org or global scope.
|
|
430
|
+
*/ resolveOrganization(organizationId) {
|
|
431
|
+
var _ref;
|
|
432
|
+
return (_ref = organizationId != null ? organizationId : RequestContext.getOrganizationId()) != null ? _ref : GLOBAL_ORGANIZATION_SCOPE;
|
|
433
|
+
}
|
|
434
|
+
/**
|
|
435
|
+
* Get strategy by type from the given organization including global strategies as fallback.
|
|
436
|
+
*
|
|
437
|
+
* @param type
|
|
438
|
+
* @param organizationId
|
|
439
|
+
* @returns
|
|
440
|
+
*/ get(type, organizationId) {
|
|
441
|
+
var _this_strategies_get, _this_strategies_get1;
|
|
442
|
+
organizationId != null ? organizationId : organizationId = RequestContext.getOrganizationId();
|
|
443
|
+
const orgKey = this.resolveOrganization(organizationId);
|
|
444
|
+
var _this_strategies_get_get;
|
|
445
|
+
const strategy = (_this_strategies_get_get = (_this_strategies_get = this.strategies.get(orgKey)) == null ? void 0 : _this_strategies_get.get(type)) != null ? _this_strategies_get_get : orgKey === GLOBAL_ORGANIZATION_SCOPE ? undefined : (_this_strategies_get1 = this.strategies.get(GLOBAL_ORGANIZATION_SCOPE)) == null ? void 0 : _this_strategies_get1.get(type);
|
|
148
446
|
if (!strategy) {
|
|
149
447
|
throw new Error(`No strategy found for type ${type}`);
|
|
150
448
|
}
|
|
151
449
|
return strategy;
|
|
152
450
|
}
|
|
153
|
-
|
|
154
|
-
|
|
451
|
+
/**
|
|
452
|
+
* List all strategies for the given organization including global strategies, or only global strategies if global org is specified.
|
|
453
|
+
*
|
|
454
|
+
* @param organizationId
|
|
455
|
+
* @returns
|
|
456
|
+
*/ list(organizationId) {
|
|
457
|
+
var _this_strategies_get, _this_strategies_get1;
|
|
458
|
+
organizationId != null ? organizationId : organizationId = RequestContext.getOrganizationId();
|
|
459
|
+
const orgKey = this.resolveOrganization(organizationId);
|
|
460
|
+
var _this_strategies_get_values;
|
|
461
|
+
const scoped = (_this_strategies_get_values = (_this_strategies_get = this.strategies.get(orgKey)) == null ? void 0 : _this_strategies_get.values()) != null ? _this_strategies_get_values : [];
|
|
462
|
+
var _this_strategies_get_values1;
|
|
463
|
+
const global = orgKey === GLOBAL_ORGANIZATION_SCOPE ? [] : (_this_strategies_get_values1 = (_this_strategies_get1 = this.strategies.get(GLOBAL_ORGANIZATION_SCOPE)) == null ? void 0 : _this_strategies_get1.values()) != null ? _this_strategies_get_values1 : [];
|
|
464
|
+
return Array.from(new Set([
|
|
465
|
+
...scoped,
|
|
466
|
+
...global
|
|
467
|
+
]));
|
|
155
468
|
}
|
|
156
469
|
constructor(strategyKey, discoveryService, reflector){
|
|
157
470
|
this.strategyKey = strategyKey;
|
|
158
471
|
this.discoveryService = discoveryService;
|
|
159
472
|
this.reflector = reflector;
|
|
473
|
+
this.logger = new common.Logger(BaseStrategyRegistry.name);
|
|
160
474
|
this.strategies = new Map();
|
|
475
|
+
this.pluginStrategies = new Map();
|
|
161
476
|
}
|
|
162
477
|
}
|
|
478
|
+
__decorate([
|
|
479
|
+
common.Inject(exports.StrategyBus),
|
|
480
|
+
__metadata("design:type", typeof exports.StrategyBus === "undefined" ? Object : exports.StrategyBus)
|
|
481
|
+
], BaseStrategyRegistry.prototype, "bus", void 0);
|
|
163
482
|
|
|
164
483
|
exports.IntegrationStrategyRegistry = class IntegrationStrategyRegistry extends BaseStrategyRegistry {
|
|
165
484
|
constructor(discoveryService, reflector){
|
|
@@ -176,7 +495,7 @@ exports.IntegrationStrategyRegistry = __decorate([
|
|
|
176
495
|
], exports.IntegrationStrategyRegistry);
|
|
177
496
|
|
|
178
497
|
const WORKFLOW_TRIGGER_STRATEGY = 'WORKFLOW_TRIGGER_STRATEGY';
|
|
179
|
-
const WorkflowTriggerStrategy = (provider)=>common.SetMetadata(WORKFLOW_TRIGGER_STRATEGY, provider);
|
|
498
|
+
const WorkflowTriggerStrategy = (provider)=>common.applyDecorators(common.SetMetadata(WORKFLOW_TRIGGER_STRATEGY, provider), common.SetMetadata(STRATEGY_META_KEY, WORKFLOW_TRIGGER_STRATEGY));
|
|
180
499
|
|
|
181
500
|
exports.WorkflowTriggerRegistry = class WorkflowTriggerRegistry extends BaseStrategyRegistry {
|
|
182
501
|
constructor(discoveryService, reflector){
|
|
@@ -195,7 +514,7 @@ exports.WorkflowTriggerRegistry = __decorate([
|
|
|
195
514
|
const WORKFLOW_NODE_STRATEGY = 'WORKFLOW_NODE_STRATEGY';
|
|
196
515
|
/**
|
|
197
516
|
* Decorator to mark a provider as a Workflow Node Strategy
|
|
198
|
-
*/ const WorkflowNodeStrategy = (provider)=>common.SetMetadata(WORKFLOW_NODE_STRATEGY, provider);
|
|
517
|
+
*/ const WorkflowNodeStrategy = (provider)=>common.applyDecorators(common.SetMetadata(WORKFLOW_NODE_STRATEGY, provider), common.SetMetadata(STRATEGY_META_KEY, WORKFLOW_NODE_STRATEGY));
|
|
199
518
|
|
|
200
519
|
exports.WorkflowNodeRegistry = class WorkflowNodeRegistry extends BaseStrategyRegistry {
|
|
201
520
|
constructor(discoveryService, reflector){
|
|
@@ -223,7 +542,7 @@ exports.WorkflowNodeRegistry = __decorate([
|
|
|
223
542
|
WrapWorkflowNodeExecutionCommand.type = '[Workflow] Wrap Workflow Node Execution';
|
|
224
543
|
|
|
225
544
|
const VECTOR_STORE_STRATEGY = 'VECTOR_STORE_STRATEGY';
|
|
226
|
-
const VectorStoreStrategy = (provider)=>common.SetMetadata(VECTOR_STORE_STRATEGY, provider);
|
|
545
|
+
const VectorStoreStrategy = (provider)=>common.applyDecorators(common.SetMetadata(VECTOR_STORE_STRATEGY, provider), common.SetMetadata(STRATEGY_META_KEY, VECTOR_STORE_STRATEGY));
|
|
227
546
|
|
|
228
547
|
exports.VectorStoreRegistry = class VectorStoreRegistry extends BaseStrategyRegistry {
|
|
229
548
|
constructor(discoveryService, reflector){
|
|
@@ -240,7 +559,7 @@ exports.VectorStoreRegistry = __decorate([
|
|
|
240
559
|
], exports.VectorStoreRegistry);
|
|
241
560
|
|
|
242
561
|
const TEXT_SPLITTER_STRATEGY = 'TEXT_SPLITTER_STRATEGY';
|
|
243
|
-
const TextSplitterStrategy = (provider)=>common.SetMetadata(TEXT_SPLITTER_STRATEGY, provider);
|
|
562
|
+
const TextSplitterStrategy = (provider)=>common.applyDecorators(common.SetMetadata(TEXT_SPLITTER_STRATEGY, provider), common.SetMetadata(STRATEGY_META_KEY, TEXT_SPLITTER_STRATEGY));
|
|
244
563
|
|
|
245
564
|
exports.TextSplitterRegistry = class TextSplitterRegistry extends BaseStrategyRegistry {
|
|
246
565
|
constructor(discoveryService, reflector){
|
|
@@ -259,7 +578,7 @@ exports.TextSplitterRegistry = __decorate([
|
|
|
259
578
|
const DOCUMENT_SOURCE_STRATEGY = 'DOCUMENT_SOURCE_STRATEGY';
|
|
260
579
|
/**
|
|
261
580
|
* Decorator to mark a provider as a Document Source Strategy
|
|
262
|
-
*/ const DocumentSourceStrategy = (provider)=>common.SetMetadata(DOCUMENT_SOURCE_STRATEGY, provider);
|
|
581
|
+
*/ const DocumentSourceStrategy = (provider)=>common.applyDecorators(common.SetMetadata(DOCUMENT_SOURCE_STRATEGY, provider), common.SetMetadata(STRATEGY_META_KEY, DOCUMENT_SOURCE_STRATEGY));
|
|
263
582
|
|
|
264
583
|
exports.DocumentSourceRegistry = class DocumentSourceRegistry extends BaseStrategyRegistry {
|
|
265
584
|
constructor(discoveryService, reflector){
|
|
@@ -278,7 +597,7 @@ exports.DocumentSourceRegistry = __decorate([
|
|
|
278
597
|
const DOCUMENT_TRANSFORMER_STRATEGY = 'DOCUMENT_TRANSFORMER_STRATEGY';
|
|
279
598
|
/**
|
|
280
599
|
* Decorator to mark a provider as a Document Transformer Strategy
|
|
281
|
-
*/ const DocumentTransformerStrategy = (provider)=>common.SetMetadata(DOCUMENT_TRANSFORMER_STRATEGY, provider);
|
|
600
|
+
*/ const DocumentTransformerStrategy = (provider)=>common.applyDecorators(common.SetMetadata(DOCUMENT_TRANSFORMER_STRATEGY, provider), common.SetMetadata(STRATEGY_META_KEY, DOCUMENT_TRANSFORMER_STRATEGY));
|
|
282
601
|
|
|
283
602
|
exports.DocumentTransformerRegistry = class DocumentTransformerRegistry extends BaseStrategyRegistry {
|
|
284
603
|
constructor(discoveryService, reflector){
|
|
@@ -297,7 +616,7 @@ exports.DocumentTransformerRegistry = __decorate([
|
|
|
297
616
|
const RETRIEVER_STRATEGY = 'RETRIEVER_STRATEGY';
|
|
298
617
|
/**
|
|
299
618
|
* Decorator to mark a provider as a Retriever Strategy
|
|
300
|
-
*/ const RetrieverStrategy = (provider)=>common.SetMetadata(RETRIEVER_STRATEGY, provider);
|
|
619
|
+
*/ const RetrieverStrategy = (provider)=>common.applyDecorators(common.SetMetadata(RETRIEVER_STRATEGY, provider), common.SetMetadata(STRATEGY_META_KEY, RETRIEVER_STRATEGY));
|
|
301
620
|
|
|
302
621
|
exports.RetrieverRegistry = class RetrieverRegistry extends BaseStrategyRegistry {
|
|
303
622
|
constructor(discoveryService, reflector){
|
|
@@ -372,7 +691,7 @@ async function downloadRemoteFile(url, dest) {
|
|
|
372
691
|
const IMAGE_UNDERSTANDING_STRATEGY = 'IMAGE_UNDERSTANDING_STRATEGY';
|
|
373
692
|
/**
|
|
374
693
|
* Decorator to mark a provider as an Image Understanding Strategy
|
|
375
|
-
*/ const ImageUnderstandingStrategy = (provider)=>common.SetMetadata(IMAGE_UNDERSTANDING_STRATEGY, provider);
|
|
694
|
+
*/ const ImageUnderstandingStrategy = (provider)=>common.applyDecorators(common.SetMetadata(IMAGE_UNDERSTANDING_STRATEGY, provider), common.SetMetadata(STRATEGY_META_KEY, IMAGE_UNDERSTANDING_STRATEGY));
|
|
376
695
|
|
|
377
696
|
exports.ImageUnderstandingRegistry = class ImageUnderstandingRegistry extends BaseStrategyRegistry {
|
|
378
697
|
constructor(discoveryService, reflector){
|
|
@@ -389,7 +708,7 @@ exports.ImageUnderstandingRegistry = __decorate([
|
|
|
389
708
|
], exports.ImageUnderstandingRegistry);
|
|
390
709
|
|
|
391
710
|
const KNOWLEDGE_STRATEGY = 'KNOWLEDGE_STRATEGY';
|
|
392
|
-
const KnowledgeStrategyKey = (provider)=>common.SetMetadata(KNOWLEDGE_STRATEGY, provider);
|
|
711
|
+
const KnowledgeStrategyKey = (provider)=>common.applyDecorators(common.SetMetadata(KNOWLEDGE_STRATEGY, provider), common.SetMetadata(STRATEGY_META_KEY, KNOWLEDGE_STRATEGY));
|
|
393
712
|
|
|
394
713
|
exports.KnowledgeStrategyRegistry = class KnowledgeStrategyRegistry extends BaseStrategyRegistry {
|
|
395
714
|
constructor(discoveryService, reflector){
|
|
@@ -408,7 +727,7 @@ exports.KnowledgeStrategyRegistry = __decorate([
|
|
|
408
727
|
const TOOLSET_STRATEGY = 'TOOLSET_STRATEGY';
|
|
409
728
|
/**
|
|
410
729
|
* Decorator to mark a provider as a Toolset Strategy
|
|
411
|
-
*/ const ToolsetStrategy = (provider)=>common.SetMetadata(TOOLSET_STRATEGY, provider);
|
|
730
|
+
*/ const ToolsetStrategy = (provider)=>common.applyDecorators(common.SetMetadata(TOOLSET_STRATEGY, provider), common.SetMetadata(STRATEGY_META_KEY, TOOLSET_STRATEGY));
|
|
412
731
|
|
|
413
732
|
exports.ToolsetRegistry = class ToolsetRegistry extends BaseStrategyRegistry {
|
|
414
733
|
constructor(discoveryService, reflector){
|
|
@@ -600,336 +919,142 @@ BuiltinToolset.provider = '';
|
|
|
600
919
|
const url = new URL(filePath, this.baseUrl);
|
|
601
920
|
return url.href;
|
|
602
921
|
}
|
|
603
|
-
/**
|
|
604
|
-
* Delete a file
|
|
605
|
-
*/ async deleteFile(filePath) {
|
|
606
|
-
this.ensureAllowed('delete');
|
|
607
|
-
this.ensureInScope(filePath);
|
|
608
|
-
await fsPromises.unlink(filePath);
|
|
609
|
-
}
|
|
610
|
-
/**
|
|
611
|
-
* List directory contents
|
|
612
|
-
*/ async listDir(dirPath) {
|
|
613
|
-
this.ensureAllowed('list');
|
|
614
|
-
this.ensureInScope(dirPath);
|
|
615
|
-
return fsPromises.readdir(dirPath);
|
|
616
|
-
}
|
|
617
|
-
/**
|
|
618
|
-
* Utility: check if a file or directory exists
|
|
619
|
-
*/ async exists(targetPath) {
|
|
620
|
-
try {
|
|
621
|
-
await fsPromises.access(targetPath);
|
|
622
|
-
return true;
|
|
623
|
-
} catch (e) {
|
|
624
|
-
return false;
|
|
625
|
-
}
|
|
626
|
-
}
|
|
627
|
-
constructor(permission, basePath, baseUrl){
|
|
628
|
-
this.basePath = basePath;
|
|
629
|
-
this.baseUrl = baseUrl;
|
|
630
|
-
this.allowedOps = new Set(permission.operations);
|
|
631
|
-
this.scope = permission.scope;
|
|
632
|
-
}
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
async function createI18nInstance(pluginDir, language) {
|
|
636
|
-
const instance = i18next.createInstance();
|
|
637
|
-
const i18nDir = path.join(pluginDir, 'i18n');
|
|
638
|
-
// detect available languages dynamically
|
|
639
|
-
const lngs = fs.readdirSync(i18nDir).filter((f)=>f.endsWith('.json')).map((f)=>f.replace('.json', ''));
|
|
640
|
-
await instance.use(FsBackend).init({
|
|
641
|
-
lng: language,
|
|
642
|
-
fallbackLng: 'en',
|
|
643
|
-
preload: lngs,
|
|
644
|
-
ns: [
|
|
645
|
-
'default'
|
|
646
|
-
],
|
|
647
|
-
defaultNS: 'default',
|
|
648
|
-
backend: {
|
|
649
|
-
loadPath: path.join(i18nDir, '{{lng}}.json')
|
|
650
|
-
},
|
|
651
|
-
interpolation: {
|
|
652
|
-
escapeValue: false
|
|
653
|
-
}
|
|
654
|
-
});
|
|
655
|
-
return instance;
|
|
656
|
-
}
|
|
657
|
-
|
|
658
|
-
function loadYamlFile(filePath, logger, ignoreError = true, defaultValue = {}) {
|
|
659
|
-
try {
|
|
660
|
-
const fileContent = fs.readFileSync(filePath, 'utf-8');
|
|
661
|
-
try {
|
|
662
|
-
const yamlContent = yaml.parse(fileContent);
|
|
663
|
-
return yamlContent || defaultValue;
|
|
664
|
-
} catch (e) {
|
|
665
|
-
throw new Error(`Failed to load YAML file ${filePath}: ${e}`);
|
|
666
|
-
}
|
|
667
|
-
} catch (e) {
|
|
668
|
-
if (ignoreError) {
|
|
669
|
-
logger == null ? void 0 : logger.debug(`Error loading YAML file: ${e}`);
|
|
670
|
-
return defaultValue;
|
|
671
|
-
} else {
|
|
672
|
-
throw e;
|
|
673
|
-
}
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
|
-
/**
|
|
677
|
-
* Get the mapping from name to index from a YAML file
|
|
678
|
-
*
|
|
679
|
-
* @param folderPath
|
|
680
|
-
* @param fileName the YAML file name, default to '_position.yaml'
|
|
681
|
-
* @return a dict with name as key and index as value
|
|
682
|
-
*/ function getPositionMap(folderPath, fileName = '_position.yaml', logger) {
|
|
683
|
-
const positions = getPositionList(folderPath, fileName, logger);
|
|
684
|
-
return positions.reduce((acc, name, index)=>{
|
|
685
|
-
acc[name] = index;
|
|
686
|
-
return acc;
|
|
687
|
-
}, {});
|
|
688
|
-
}
|
|
689
|
-
function getPositionList(folderPath, fileName = '_position.yaml', logger) {
|
|
690
|
-
const positionFilePath = path.join(folderPath, fileName);
|
|
691
|
-
const yamlContent = loadYamlFile(positionFilePath, logger, true, []);
|
|
692
|
-
const positions = yamlContent == null ? void 0 : yamlContent.filter((item)=>item && typeof item === 'string' && item.trim()).map((item)=>item.trim());
|
|
693
|
-
return positions;
|
|
694
|
-
}
|
|
695
|
-
function getErrorMessage(err) {
|
|
696
|
-
let error;
|
|
697
|
-
if (typeof err === 'string') {
|
|
698
|
-
error = err;
|
|
699
|
-
} else if (err && (err.name === "AggregateError" || err.constructor.name === "AggregateError")) {
|
|
700
|
-
return err.errors.map((_)=>getErrorMessage(_)).join('\n\n');
|
|
701
|
-
} else if (err instanceof Error) {
|
|
702
|
-
error = err == null ? void 0 : err.message;
|
|
703
|
-
} else if ((err == null ? void 0 : err.error) instanceof Error) {
|
|
704
|
-
var _err_error;
|
|
705
|
-
error = err == null ? void 0 : (_err_error = err.error) == null ? void 0 : _err_error.message;
|
|
706
|
-
} else if (err == null ? void 0 : err.message) {
|
|
707
|
-
error = err == null ? void 0 : err.message;
|
|
708
|
-
} else if (err) {
|
|
709
|
-
// If there is no other way, convert it to JSON string
|
|
710
|
-
error = JSON.stringify(err);
|
|
711
|
-
}
|
|
712
|
-
return error;
|
|
713
|
-
}
|
|
714
|
-
|
|
715
|
-
// request-context.ts
|
|
716
|
-
class RequestContext {
|
|
717
|
-
static currentRequestContext() {
|
|
718
|
-
const session = getRequestContext();
|
|
719
|
-
return session;
|
|
720
|
-
}
|
|
721
|
-
static currentRequest() {
|
|
722
|
-
const requestContext = RequestContext.currentRequestContext();
|
|
723
|
-
if (requestContext) {
|
|
724
|
-
return requestContext.request;
|
|
725
|
-
}
|
|
726
|
-
return null;
|
|
727
|
-
}
|
|
728
|
-
static currentTenantId() {
|
|
729
|
-
const user = RequestContext.currentUser();
|
|
730
|
-
if (user) {
|
|
731
|
-
return user.tenantId;
|
|
732
|
-
}
|
|
733
|
-
return null;
|
|
734
|
-
}
|
|
735
|
-
static currentUserId() {
|
|
736
|
-
const user = RequestContext.currentUser();
|
|
737
|
-
if (user) {
|
|
738
|
-
return user.id;
|
|
739
|
-
}
|
|
740
|
-
return null;
|
|
741
|
-
}
|
|
742
|
-
static currentRoleId() {
|
|
743
|
-
const user = RequestContext.currentUser();
|
|
744
|
-
if (user) {
|
|
745
|
-
return user.roleId;
|
|
746
|
-
}
|
|
747
|
-
return null;
|
|
748
|
-
}
|
|
749
|
-
static currentUser(throwError) {
|
|
750
|
-
const requestContext = RequestContext.currentRequestContext();
|
|
751
|
-
if (requestContext) {
|
|
752
|
-
// tslint:disable-next-line
|
|
753
|
-
const user = requestContext.request['user'];
|
|
754
|
-
if (user) {
|
|
755
|
-
return user;
|
|
756
|
-
}
|
|
757
|
-
}
|
|
758
|
-
if (throwError) {
|
|
759
|
-
throw new common.HttpException('Unauthorized', common.HttpStatus.UNAUTHORIZED);
|
|
760
|
-
}
|
|
761
|
-
return null;
|
|
762
|
-
}
|
|
763
|
-
static hasPermission(permission, throwError) {
|
|
764
|
-
return this.hasPermissions([
|
|
765
|
-
permission
|
|
766
|
-
], throwError);
|
|
767
|
-
}
|
|
768
|
-
/**
|
|
769
|
-
* Retrieves the language code from the headers of the current request.
|
|
770
|
-
* @returns The language code (LanguagesEnum) extracted from the headers, or the default language (ENGLISH) if not found.
|
|
771
|
-
*/ static getLanguageCode() {
|
|
772
|
-
// Retrieve the current request
|
|
773
|
-
const req = RequestContext.currentRequest();
|
|
774
|
-
// Variable to store the extracted language code
|
|
775
|
-
let lang;
|
|
776
|
-
// Check if a request exists
|
|
777
|
-
if (req) {
|
|
778
|
-
// Check if the 'language' header exists in the request
|
|
779
|
-
if (req.headers && req.headers['language']) {
|
|
780
|
-
// If found, set the lang variable
|
|
781
|
-
lang = req.headers['language'];
|
|
782
|
-
}
|
|
783
|
-
}
|
|
784
|
-
// Return the extracted language code or the default language (ENGLISH) if not found
|
|
785
|
-
return lang || contracts.LanguagesEnum.English;
|
|
786
|
-
}
|
|
787
|
-
static getOrganizationId() {
|
|
788
|
-
const req = this.currentRequest();
|
|
789
|
-
let organizationId;
|
|
790
|
-
const keys = [
|
|
791
|
-
'organization-id'
|
|
792
|
-
];
|
|
793
|
-
if (req) {
|
|
794
|
-
for (const key of keys){
|
|
795
|
-
if (req.headers && req.headers[key]) {
|
|
796
|
-
organizationId = req.headers[key];
|
|
797
|
-
break;
|
|
798
|
-
}
|
|
799
|
-
}
|
|
800
|
-
}
|
|
801
|
-
return organizationId;
|
|
802
|
-
}
|
|
803
|
-
static hasPermissions(findPermissions, throwError) {
|
|
804
|
-
const requestContext = RequestContext.currentRequestContext();
|
|
805
|
-
if (requestContext) {
|
|
806
|
-
// tslint:disable-next-line
|
|
807
|
-
const token = passportJwt.ExtractJwt.fromAuthHeaderAsBearerToken()(requestContext.request);
|
|
808
|
-
if (token) {
|
|
809
|
-
const { permissions } = jsonwebtoken.verify(token, process.env['JWT_SECRET']);
|
|
810
|
-
if (permissions) {
|
|
811
|
-
const found = permissions.filter((value)=>findPermissions.indexOf(value) >= 0);
|
|
812
|
-
if (found.length === findPermissions.length) {
|
|
813
|
-
return true;
|
|
814
|
-
}
|
|
815
|
-
} else {
|
|
816
|
-
return false;
|
|
817
|
-
}
|
|
818
|
-
}
|
|
819
|
-
}
|
|
820
|
-
if (throwError) {
|
|
821
|
-
throw new common.HttpException('Unauthorized', common.HttpStatus.UNAUTHORIZED);
|
|
822
|
-
}
|
|
823
|
-
return false;
|
|
824
|
-
}
|
|
825
|
-
static hasAnyPermission(findPermissions, throwError) {
|
|
826
|
-
const requestContext = RequestContext.currentRequestContext();
|
|
827
|
-
if (requestContext) {
|
|
828
|
-
// tslint:disable-next-line
|
|
829
|
-
const token = passportJwt.ExtractJwt.fromAuthHeaderAsBearerToken()(requestContext.request);
|
|
830
|
-
if (token) {
|
|
831
|
-
const { permissions } = jsonwebtoken.verify(token, process.env['JWT_SECRET']);
|
|
832
|
-
const found = permissions.filter((value)=>findPermissions.indexOf(value) >= 0);
|
|
833
|
-
if (found.length > 0) {
|
|
834
|
-
return true;
|
|
835
|
-
}
|
|
836
|
-
}
|
|
837
|
-
}
|
|
838
|
-
if (throwError) {
|
|
839
|
-
throw new common.HttpException('Unauthorized', common.HttpStatus.UNAUTHORIZED);
|
|
840
|
-
}
|
|
841
|
-
return false;
|
|
842
|
-
}
|
|
843
|
-
static currentToken(throwError) {
|
|
844
|
-
const requestContext = RequestContext.currentRequestContext();
|
|
845
|
-
if (requestContext) {
|
|
846
|
-
// tslint:disable-next-line
|
|
847
|
-
return passportJwt.ExtractJwt.fromAuthHeaderAsBearerToken()(requestContext.request);
|
|
848
|
-
}
|
|
849
|
-
if (throwError) {
|
|
850
|
-
throw new common.HttpException('Unauthorized', common.HttpStatus.UNAUTHORIZED);
|
|
851
|
-
}
|
|
852
|
-
return null;
|
|
922
|
+
/**
|
|
923
|
+
* Delete a file
|
|
924
|
+
*/ async deleteFile(filePath) {
|
|
925
|
+
this.ensureAllowed('delete');
|
|
926
|
+
this.ensureInScope(filePath);
|
|
927
|
+
await fsPromises.unlink(filePath);
|
|
853
928
|
}
|
|
854
929
|
/**
|
|
855
|
-
*
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
return this.hasRoles([
|
|
861
|
-
role
|
|
862
|
-
], throwError);
|
|
930
|
+
* List directory contents
|
|
931
|
+
*/ async listDir(dirPath) {
|
|
932
|
+
this.ensureAllowed('list');
|
|
933
|
+
this.ensureInScope(dirPath);
|
|
934
|
+
return fsPromises.readdir(dirPath);
|
|
863
935
|
}
|
|
864
936
|
/**
|
|
865
|
-
*
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
if (context) {
|
|
873
|
-
try {
|
|
874
|
-
// tslint:disable-next-line
|
|
875
|
-
const token = this.currentToken();
|
|
876
|
-
if (token) {
|
|
877
|
-
const { role } = jsonwebtoken.verify(token, process.env['JWT_SECRET']);
|
|
878
|
-
return roles.includes(role != null ? role : null);
|
|
879
|
-
} else if (this.currentUser().role) {
|
|
880
|
-
return roles.includes(this.currentUser().role.name);
|
|
881
|
-
}
|
|
882
|
-
} catch (error) {
|
|
883
|
-
if (error instanceof jsonwebtoken.JsonWebTokenError) {
|
|
884
|
-
return false;
|
|
885
|
-
} else {
|
|
886
|
-
throw error;
|
|
887
|
-
}
|
|
888
|
-
}
|
|
889
|
-
}
|
|
890
|
-
if (throwError) {
|
|
891
|
-
throw new common.HttpException('Unauthorized', common.HttpStatus.UNAUTHORIZED);
|
|
937
|
+
* Utility: check if a file or directory exists
|
|
938
|
+
*/ async exists(targetPath) {
|
|
939
|
+
try {
|
|
940
|
+
await fsPromises.access(targetPath);
|
|
941
|
+
return true;
|
|
942
|
+
} catch (e) {
|
|
943
|
+
return false;
|
|
892
944
|
}
|
|
893
|
-
return false;
|
|
894
945
|
}
|
|
895
|
-
constructor(
|
|
896
|
-
this.
|
|
897
|
-
this.
|
|
898
|
-
this.
|
|
899
|
-
this.
|
|
900
|
-
this.extras = extras;
|
|
946
|
+
constructor(permission, basePath, baseUrl){
|
|
947
|
+
this.basePath = basePath;
|
|
948
|
+
this.baseUrl = baseUrl;
|
|
949
|
+
this.allowedOps = new Set(permission.operations);
|
|
950
|
+
this.scope = permission.scope;
|
|
901
951
|
}
|
|
902
952
|
}
|
|
903
|
-
|
|
904
|
-
function
|
|
905
|
-
|
|
953
|
+
|
|
954
|
+
async function createI18nInstance(pluginDir, language) {
|
|
955
|
+
const instance = i18next.createInstance();
|
|
956
|
+
const i18nDir = path.join(pluginDir, 'i18n');
|
|
957
|
+
// detect available languages dynamically
|
|
958
|
+
const lngs = fs.readdirSync(i18nDir).filter((f)=>f.endsWith('.json')).map((f)=>f.replace('.json', ''));
|
|
959
|
+
await instance.use(FsBackend).init({
|
|
960
|
+
lng: language,
|
|
961
|
+
fallbackLng: 'en',
|
|
962
|
+
preload: lngs,
|
|
963
|
+
ns: [
|
|
964
|
+
'default'
|
|
965
|
+
],
|
|
966
|
+
defaultNS: 'default',
|
|
967
|
+
backend: {
|
|
968
|
+
loadPath: path.join(i18nDir, '{{lng}}.json')
|
|
969
|
+
},
|
|
970
|
+
interpolation: {
|
|
971
|
+
escapeValue: false
|
|
972
|
+
}
|
|
973
|
+
});
|
|
974
|
+
return instance;
|
|
906
975
|
}
|
|
907
976
|
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
977
|
+
function loadYamlFile(filePath, logger, ignoreError = true, defaultValue = {}) {
|
|
978
|
+
try {
|
|
979
|
+
const fileContent = fs.readFileSync(filePath, 'utf-8');
|
|
980
|
+
try {
|
|
981
|
+
const yamlContent = yaml.parse(fileContent);
|
|
982
|
+
return yamlContent || defaultValue;
|
|
983
|
+
} catch (e) {
|
|
984
|
+
throw new Error(`Failed to load YAML file ${filePath}: ${e}`);
|
|
985
|
+
}
|
|
986
|
+
} catch (e) {
|
|
987
|
+
if (ignoreError) {
|
|
988
|
+
logger == null ? void 0 : logger.debug(`Error loading YAML file: ${e}`);
|
|
989
|
+
return defaultValue;
|
|
990
|
+
} else {
|
|
991
|
+
throw e;
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
/**
|
|
996
|
+
* Get the mapping from name to index from a YAML file
|
|
997
|
+
*
|
|
998
|
+
* @param folderPath
|
|
999
|
+
* @param fileName the YAML file name, default to '_position.yaml'
|
|
1000
|
+
* @return a dict with name as key and index as value
|
|
1001
|
+
*/ function getPositionMap(folderPath, fileName = '_position.yaml', logger) {
|
|
1002
|
+
const positions = getPositionList(folderPath, fileName, logger);
|
|
1003
|
+
return positions.reduce((acc, name, index)=>{
|
|
1004
|
+
acc[name] = index;
|
|
1005
|
+
return acc;
|
|
1006
|
+
}, {});
|
|
1007
|
+
}
|
|
1008
|
+
function getPositionList(folderPath, fileName = '_position.yaml', logger) {
|
|
1009
|
+
const positionFilePath = path.join(folderPath, fileName);
|
|
1010
|
+
const yamlContent = loadYamlFile(positionFilePath, logger, true, []);
|
|
1011
|
+
const positions = yamlContent == null ? void 0 : yamlContent.filter((item)=>item && typeof item === 'string' && item.trim()).map((item)=>item.trim());
|
|
1012
|
+
return positions;
|
|
1013
|
+
}
|
|
1014
|
+
function getErrorMessage(err) {
|
|
1015
|
+
let error;
|
|
1016
|
+
if (typeof err === 'string') {
|
|
1017
|
+
error = err;
|
|
1018
|
+
} else if (err && (err.name === "AggregateError" || err.constructor.name === "AggregateError")) {
|
|
1019
|
+
return err.errors.map((_)=>getErrorMessage(_)).join('\n\n');
|
|
1020
|
+
} else if (err instanceof Error) {
|
|
1021
|
+
error = err == null ? void 0 : err.message;
|
|
1022
|
+
} else if ((err == null ? void 0 : err.error) instanceof Error) {
|
|
1023
|
+
var _err_error;
|
|
1024
|
+
error = err == null ? void 0 : (_err_error = err.error) == null ? void 0 : _err_error.message;
|
|
1025
|
+
} else if (err == null ? void 0 : err.message) {
|
|
1026
|
+
error = err == null ? void 0 : err.message;
|
|
1027
|
+
} else if (err) {
|
|
1028
|
+
// If there is no other way, convert it to JSON string
|
|
1029
|
+
error = JSON.stringify(err);
|
|
1030
|
+
}
|
|
1031
|
+
return error;
|
|
1032
|
+
}
|
|
1033
|
+
class JsonSchemaValidator {
|
|
1034
|
+
parseAndValidate(schemaStr) {
|
|
1035
|
+
if (!schemaStr) return undefined;
|
|
1036
|
+
let schema;
|
|
1037
|
+
try {
|
|
1038
|
+
schema = JSON.parse(schemaStr);
|
|
1039
|
+
} catch (e) {
|
|
1040
|
+
throw new Error('Schema is not valid JSON');
|
|
1041
|
+
}
|
|
1042
|
+
const validate = this.ajv.getSchema(schemaDraft04.$id);
|
|
1043
|
+
if (!validate(schema)) {
|
|
1044
|
+
throw new Error('Invalid JSON Schema: ' + this.ajv.errorsText(validate.errors));
|
|
1045
|
+
}
|
|
1046
|
+
return schema;
|
|
1047
|
+
}
|
|
1048
|
+
constructor(){
|
|
1049
|
+
this.ajv = new Ajv({
|
|
1050
|
+
strict: false
|
|
1051
|
+
});
|
|
1052
|
+
this.ajv.addMetaSchema(schemaDraft04);
|
|
917
1053
|
}
|
|
918
|
-
};
|
|
919
|
-
exports.RequestContextMiddleware = __decorate([
|
|
920
|
-
common.Injectable()
|
|
921
|
-
], exports.RequestContextMiddleware);
|
|
922
|
-
function runWithRequestContext(req, res, next) {
|
|
923
|
-
var _req_user;
|
|
924
|
-
const reqId = req.headers['x-request-id'] || node_crypto.randomUUID();
|
|
925
|
-
const userId = (_req_user = req['user']) == null ? void 0 : _req_user['id'];
|
|
926
|
-
const ctx = new RequestContext(req, res, reqId, userId);
|
|
927
|
-
// Enable ALS scope
|
|
928
|
-
als.run(ctx, next);
|
|
929
1054
|
}
|
|
930
1055
|
|
|
931
1056
|
const DATASOURCE_STRATEGY = 'DATASOURCE_STRATEGY';
|
|
932
|
-
const DataSourceStrategy = (provider)=>common.SetMetadata(DATASOURCE_STRATEGY, provider);
|
|
1057
|
+
const DataSourceStrategy = (provider)=>common.applyDecorators(common.SetMetadata(DATASOURCE_STRATEGY, provider), common.SetMetadata(STRATEGY_META_KEY, DATASOURCE_STRATEGY));
|
|
933
1058
|
|
|
934
1059
|
exports.DataSourceStrategyRegistry = class DataSourceStrategyRegistry extends BaseStrategyRegistry {
|
|
935
1060
|
constructor(discoveryService, reflector){
|
|
@@ -1242,6 +1367,7 @@ function AIModelProviderStrategy(provider) {
|
|
|
1242
1367
|
}
|
|
1243
1368
|
const dir = file ? path.dirname(file) : process.cwd();
|
|
1244
1369
|
return function(target) {
|
|
1370
|
+
common.SetMetadata(STRATEGY_META_KEY, AI_MODEL_PROVIDER)(target);
|
|
1245
1371
|
// Ensure NestJS is discoverable
|
|
1246
1372
|
common.SetMetadata(AI_MODEL_PROVIDER, provider)(target);
|
|
1247
1373
|
// Write custom path (does not affect Discovery)
|
|
@@ -1533,6 +1659,46 @@ const PARAMETER_RULE_TEMPLATE = {
|
|
|
1533
1659
|
}
|
|
1534
1660
|
};
|
|
1535
1661
|
|
|
1662
|
+
const CommonParameterRules = [
|
|
1663
|
+
{
|
|
1664
|
+
name: 'temperature',
|
|
1665
|
+
label: {
|
|
1666
|
+
zh_Hans: '温度',
|
|
1667
|
+
en_US: `Temperature`
|
|
1668
|
+
},
|
|
1669
|
+
type: contracts.ParameterType.FLOAT,
|
|
1670
|
+
help: {
|
|
1671
|
+
zh_Hans: '控制模型输出的随机性。较高的值(例如 1.0)使响应更具创意,而较低的值(例如 0.1)使响应更具确定性和重点性。',
|
|
1672
|
+
en_US: `Controls the randomness of the model's output. A higher value (e.g., 1.0) makes responses more creative, while a lower value (e.g., 0.1) makes them more deterministic and focused.`
|
|
1673
|
+
},
|
|
1674
|
+
required: false,
|
|
1675
|
+
default: 0.2,
|
|
1676
|
+
min: 0,
|
|
1677
|
+
max: 1,
|
|
1678
|
+
precision: 0.1
|
|
1679
|
+
},
|
|
1680
|
+
{
|
|
1681
|
+
label: {
|
|
1682
|
+
zh_Hans: '最大尝试次数',
|
|
1683
|
+
en_US: 'The maximum number of attempts'
|
|
1684
|
+
},
|
|
1685
|
+
type: contracts.ParameterType.INT,
|
|
1686
|
+
help: {
|
|
1687
|
+
zh_Hans: '如果请求由于网络超时或速率限制等问题而失败,系统将尝试重新发送请求的最大次数',
|
|
1688
|
+
en_US: 'The maximum number of attempts the system will make to resend a request if it fails due to issues like network timeouts or rate limits'
|
|
1689
|
+
},
|
|
1690
|
+
required: false,
|
|
1691
|
+
default: 6,
|
|
1692
|
+
min: 0,
|
|
1693
|
+
max: 10,
|
|
1694
|
+
precision: 0,
|
|
1695
|
+
name: 'maxRetries'
|
|
1696
|
+
}
|
|
1697
|
+
];
|
|
1698
|
+
function mergeCredentials(credentials, modelProperties) {
|
|
1699
|
+
return _extends({}, credentials != null ? credentials : {}, modelProperties != null ? modelProperties : {});
|
|
1700
|
+
}
|
|
1701
|
+
|
|
1536
1702
|
let AIModel = class AIModel {
|
|
1537
1703
|
getChatModel(copilotModel, options) {
|
|
1538
1704
|
throw new Error(`Unsupport chat model!`);
|
|
@@ -1676,6 +1842,15 @@ let AIModel = class AIModel {
|
|
|
1676
1842
|
...parameterRules.filter((_)=>!CommonParameterRules.some((r)=>r.name === _.name))
|
|
1677
1843
|
];
|
|
1678
1844
|
}
|
|
1845
|
+
getModelProfile(model, credentials) {
|
|
1846
|
+
var _modelSchema_model_properties, _modelSchema_features, _modelSchema_features1, _modelSchema_features2, _modelSchema_features3;
|
|
1847
|
+
const modelSchema = this.getModelSchema(model, credentials);
|
|
1848
|
+
return modelSchema && {
|
|
1849
|
+
maxInputTokens: (_modelSchema_model_properties = modelSchema.model_properties) == null ? void 0 : _modelSchema_model_properties.context_size,
|
|
1850
|
+
toolCalling: ((_modelSchema_features = modelSchema.features) == null ? void 0 : _modelSchema_features.includes(contracts.ModelFeature.TOOL_CALL)) || ((_modelSchema_features1 = modelSchema.features) == null ? void 0 : _modelSchema_features1.includes(contracts.ModelFeature.MULTI_TOOL_CALL)) || ((_modelSchema_features2 = modelSchema.features) == null ? void 0 : _modelSchema_features2.includes(contracts.ModelFeature.STREAM_TOOL_CALL)),
|
|
1851
|
+
structuredOutput: (_modelSchema_features3 = modelSchema.features) == null ? void 0 : _modelSchema_features3.includes(contracts.ModelFeature.STRUCTURED_OUTPUT)
|
|
1852
|
+
};
|
|
1853
|
+
}
|
|
1679
1854
|
constructor(modelProvider, modelType){
|
|
1680
1855
|
this.modelProvider = modelProvider;
|
|
1681
1856
|
this.modelType = modelType;
|
|
@@ -1715,46 +1890,6 @@ class RerankModel extends AIModel {
|
|
|
1715
1890
|
}
|
|
1716
1891
|
}
|
|
1717
1892
|
|
|
1718
|
-
const CommonParameterRules = [
|
|
1719
|
-
{
|
|
1720
|
-
name: 'temperature',
|
|
1721
|
-
label: {
|
|
1722
|
-
zh_Hans: '温度',
|
|
1723
|
-
en_US: `Temperature`
|
|
1724
|
-
},
|
|
1725
|
-
type: contracts.ParameterType.FLOAT,
|
|
1726
|
-
help: {
|
|
1727
|
-
zh_Hans: '控制模型输出的随机性。较高的值(例如 1.0)使响应更具创意,而较低的值(例如 0.1)使响应更具确定性和重点性。',
|
|
1728
|
-
en_US: `Controls the randomness of the model's output. A higher value (e.g., 1.0) makes responses more creative, while a lower value (e.g., 0.1) makes them more deterministic and focused.`
|
|
1729
|
-
},
|
|
1730
|
-
required: false,
|
|
1731
|
-
default: 0.2,
|
|
1732
|
-
min: 0,
|
|
1733
|
-
max: 1,
|
|
1734
|
-
precision: 0.1
|
|
1735
|
-
},
|
|
1736
|
-
{
|
|
1737
|
-
label: {
|
|
1738
|
-
zh_Hans: '最大尝试次数',
|
|
1739
|
-
en_US: 'The maximum number of attempts'
|
|
1740
|
-
},
|
|
1741
|
-
type: contracts.ParameterType.INT,
|
|
1742
|
-
help: {
|
|
1743
|
-
zh_Hans: '如果请求由于网络超时或速率限制等问题而失败,系统将尝试重新发送请求的最大次数',
|
|
1744
|
-
en_US: 'The maximum number of attempts the system will make to resend a request if it fails due to issues like network timeouts or rate limits'
|
|
1745
|
-
},
|
|
1746
|
-
required: false,
|
|
1747
|
-
default: 6,
|
|
1748
|
-
min: 0,
|
|
1749
|
-
max: 10,
|
|
1750
|
-
precision: 0,
|
|
1751
|
-
name: 'maxRetries'
|
|
1752
|
-
}
|
|
1753
|
-
];
|
|
1754
|
-
function mergeCredentials(credentials, modelProperties) {
|
|
1755
|
-
return _extends({}, credentials != null ? credentials : {}, modelProperties != null ? modelProperties : {});
|
|
1756
|
-
}
|
|
1757
|
-
|
|
1758
1893
|
class SpeechToTextModel extends AIModel {
|
|
1759
1894
|
}
|
|
1760
1895
|
|
|
@@ -2081,7 +2216,7 @@ class OpenAICompatibleReranker {
|
|
|
2081
2216
|
if (!Array.isArray(output)) {
|
|
2082
2217
|
throw new Error('Invalid response format: missing results array');
|
|
2083
2218
|
}
|
|
2084
|
-
//
|
|
2219
|
+
// Collect raw scores and normalize them.
|
|
2085
2220
|
const scores = output.map((r)=>r.relevance_score);
|
|
2086
2221
|
const minScore = Math.min(...scores);
|
|
2087
2222
|
const maxScore = Math.max(...scores);
|
|
@@ -2160,7 +2295,7 @@ class Speech2TextChatModel extends chat_models.BaseChatModel {
|
|
|
2160
2295
|
CreateModelClientCommand.type = '[AI Model] Create Model Client';
|
|
2161
2296
|
|
|
2162
2297
|
const AGENT_MIDDLEWARE_STRATEGY = 'AGENT_MIDDLEWARE_STRATEGY';
|
|
2163
|
-
const AgentMiddlewareStrategy = (provider)=>common.SetMetadata(AGENT_MIDDLEWARE_STRATEGY, provider);
|
|
2298
|
+
const AgentMiddlewareStrategy = (provider)=>common.applyDecorators(common.SetMetadata(AGENT_MIDDLEWARE_STRATEGY, provider), common.SetMetadata(STRATEGY_META_KEY, AGENT_MIDDLEWARE_STRATEGY));
|
|
2164
2299
|
|
|
2165
2300
|
exports.AgentMiddlewareRegistry = class AgentMiddlewareRegistry extends BaseStrategyRegistry {
|
|
2166
2301
|
constructor(discoveryService, reflector){
|
|
@@ -2210,6 +2345,7 @@ exports.AiModelNotFoundException = AiModelNotFoundException;
|
|
|
2210
2345
|
exports.BaseHTTPQueryRunner = BaseHTTPQueryRunner;
|
|
2211
2346
|
exports.BaseQueryRunner = BaseQueryRunner;
|
|
2212
2347
|
exports.BaseSQLQueryRunner = BaseSQLQueryRunner;
|
|
2348
|
+
exports.BaseStrategyRegistry = BaseStrategyRegistry;
|
|
2213
2349
|
exports.BaseTool = BaseTool;
|
|
2214
2350
|
exports.BaseToolset = BaseToolset;
|
|
2215
2351
|
exports.BuiltinToolset = BuiltinToolset;
|
|
@@ -2223,17 +2359,21 @@ exports.DOCUMENT_TRANSFORMER_STRATEGY = DOCUMENT_TRANSFORMER_STRATEGY;
|
|
|
2223
2359
|
exports.DataSourceStrategy = DataSourceStrategy;
|
|
2224
2360
|
exports.DocumentSourceStrategy = DocumentSourceStrategy;
|
|
2225
2361
|
exports.DocumentTransformerStrategy = DocumentTransformerStrategy;
|
|
2362
|
+
exports.GLOBAL_ORGANIZATION_SCOPE = GLOBAL_ORGANIZATION_SCOPE;
|
|
2226
2363
|
exports.IMAGE_UNDERSTANDING_STRATEGY = IMAGE_UNDERSTANDING_STRATEGY;
|
|
2227
2364
|
exports.INTEGRATION_STRATEGY = INTEGRATION_STRATEGY;
|
|
2228
2365
|
exports.ImageUnderstandingStrategy = ImageUnderstandingStrategy;
|
|
2229
2366
|
exports.IntegrationStrategyKey = IntegrationStrategyKey;
|
|
2230
2367
|
exports.JUMP_TO_TARGETS = JUMP_TO_TARGETS;
|
|
2368
|
+
exports.JsonSchemaValidator = JsonSchemaValidator;
|
|
2231
2369
|
exports.KNOWLEDGE_STRATEGY = KNOWLEDGE_STRATEGY;
|
|
2232
2370
|
exports.KnowledgeStrategyKey = KnowledgeStrategyKey;
|
|
2233
2371
|
exports.LLMUsage = LLMUsage;
|
|
2234
2372
|
exports.LargeLanguageModel = LargeLanguageModel;
|
|
2373
|
+
exports.ORGANIZATION_METADATA_KEY = ORGANIZATION_METADATA_KEY;
|
|
2235
2374
|
exports.OpenAICompatibleReranker = OpenAICompatibleReranker;
|
|
2236
2375
|
exports.PLUGIN_METADATA = PLUGIN_METADATA;
|
|
2376
|
+
exports.PLUGIN_METADATA_KEY = PLUGIN_METADATA_KEY;
|
|
2237
2377
|
exports.PROVIDE_AI_MODEL_LLM = PROVIDE_AI_MODEL_LLM;
|
|
2238
2378
|
exports.PROVIDE_AI_MODEL_MODERATION = PROVIDE_AI_MODEL_MODERATION;
|
|
2239
2379
|
exports.PROVIDE_AI_MODEL_RERANK = PROVIDE_AI_MODEL_RERANK;
|
|
@@ -2244,6 +2384,7 @@ exports.RETRIEVER_STRATEGY = RETRIEVER_STRATEGY;
|
|
|
2244
2384
|
exports.RequestContext = RequestContext;
|
|
2245
2385
|
exports.RerankModel = RerankModel;
|
|
2246
2386
|
exports.RetrieverStrategy = RetrieverStrategy;
|
|
2387
|
+
exports.STRATEGY_META_KEY = STRATEGY_META_KEY;
|
|
2247
2388
|
exports.Speech2TextChatModel = Speech2TextChatModel;
|
|
2248
2389
|
exports.SpeechToTextModel = SpeechToTextModel;
|
|
2249
2390
|
exports.TEXT_SPLITTER_STRATEGY = TEXT_SPLITTER_STRATEGY;
|