@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.esm.js CHANGED
@@ -1,14 +1,19 @@
1
- import { Module, Logger, SetMetadata, Injectable, HttpException, HttpStatus, NotFoundException, ForbiddenException } from '@nestjs/common';
1
+ import { Module, Logger, applyDecorators, SetMetadata, HttpException, HttpStatus, Injectable, Inject, NotFoundException, ForbiddenException } from '@nestjs/common';
2
2
  import { MODULE_METADATA } from '@nestjs/common/constants';
3
3
  import { pick } from 'lodash-es';
4
4
  import { DiscoveryService, Reflector } from '@nestjs/core';
5
+ import { Subject, filter } from 'rxjs';
6
+ import { LanguagesEnum, AiModelTypeEnum, ParameterType, PriceType, FetchFrom, ModelFeature, ModelPropertyKey } from '@metad/contracts';
7
+ export { IColumnDef, IDSSchema, IDSTable, TDocumentAsset } from '@metad/contracts';
8
+ import { AsyncLocalStorage } from 'node:async_hooks';
9
+ import { ExtractJwt } from 'passport-jwt';
10
+ import { verify, JsonWebTokenError } from 'jsonwebtoken';
11
+ import { randomUUID } from 'node:crypto';
5
12
  import { Command } from '@nestjs/cqrs';
6
13
  import * as fs from 'fs';
7
14
  import fs__default from 'fs';
8
15
  import http from 'http';
9
16
  import https from 'https';
10
- import { LanguagesEnum, AiModelTypeEnum, ParameterType, PriceType, FetchFrom, ModelPropertyKey } from '@metad/contracts';
11
- export { IColumnDef, IDSSchema, IDSTable, TDocumentAsset } from '@metad/contracts';
12
17
  import { BaseToolkit, StructuredTool } from '@langchain/core/tools';
13
18
  import { z } from 'zod';
14
19
  import fsPromises from 'fs/promises';
@@ -18,10 +23,8 @@ import { createInstance } from 'i18next';
18
23
  import FsBackend from 'i18next-fs-backend';
19
24
  import * as yaml from 'yaml';
20
25
  import yaml__default from 'yaml';
21
- import { AsyncLocalStorage } from 'node:async_hooks';
22
- import { ExtractJwt } from 'passport-jwt';
23
- import { verify, JsonWebTokenError } from 'jsonwebtoken';
24
- import { randomUUID } from 'node:crypto';
26
+ import Ajv from 'ajv';
27
+ import schemaDraft04 from 'ajv/dist/refs/json-schema-draft-06.json';
25
28
  import * as _axios from 'axios';
26
29
  import { ChatOpenAICompletions } from '@langchain/openai';
27
30
  import { Document } from '@langchain/core/documents';
@@ -64,6 +67,11 @@ import 'js-tiktoken';
64
67
  };
65
68
  }
66
69
 
70
+ const ORGANIZATION_METADATA_KEY = 'xpert:organizationId';
71
+ const PLUGIN_METADATA_KEY = 'xpert:pluginName';
72
+ const GLOBAL_ORGANIZATION_SCOPE = 'global';
73
+ const STRATEGY_META_KEY = 'XPERT_STRATEGY_META_KEY';
74
+
67
75
  function _extends() {
68
76
  _extends = Object.assign || function assign(target) {
69
77
  for(var i = 1; i < arguments.length; i++){
@@ -95,7 +103,7 @@ function createPluginLogger(scope, baseMeta = {}) {
95
103
  }
96
104
 
97
105
  const INTEGRATION_STRATEGY = 'INTEGRATION_STRATEGY';
98
- const IntegrationStrategyKey = (provider)=>SetMetadata(INTEGRATION_STRATEGY, provider);
106
+ const IntegrationStrategyKey = (provider)=>applyDecorators(SetMetadata(INTEGRATION_STRATEGY, provider), SetMetadata(STRATEGY_META_KEY, INTEGRATION_STRATEGY));
99
107
 
100
108
  function __decorate(decorators, target, key, desc) {
101
109
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -111,35 +119,346 @@ typeof SuppressedError === "function" ? SuppressedError : function _SuppressedEr
111
119
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
112
120
  };
113
121
 
122
+ // request-context.ts
123
+ class RequestContext {
124
+ static currentRequestContext() {
125
+ const session = getRequestContext();
126
+ return session;
127
+ }
128
+ static currentRequest() {
129
+ const requestContext = RequestContext.currentRequestContext();
130
+ if (requestContext) {
131
+ return requestContext.request;
132
+ }
133
+ return null;
134
+ }
135
+ static currentTenantId() {
136
+ const user = RequestContext.currentUser();
137
+ if (user) {
138
+ return user.tenantId;
139
+ }
140
+ return null;
141
+ }
142
+ static currentUserId() {
143
+ const user = RequestContext.currentUser();
144
+ if (user) {
145
+ return user.id;
146
+ }
147
+ return null;
148
+ }
149
+ static currentRoleId() {
150
+ const user = RequestContext.currentUser();
151
+ if (user) {
152
+ return user.roleId;
153
+ }
154
+ return null;
155
+ }
156
+ static currentUser(throwError) {
157
+ const requestContext = RequestContext.currentRequestContext();
158
+ if (requestContext) {
159
+ // tslint:disable-next-line
160
+ const user = requestContext.request['user'];
161
+ if (user) {
162
+ return user;
163
+ }
164
+ }
165
+ if (throwError) {
166
+ throw new HttpException('Unauthorized', HttpStatus.UNAUTHORIZED);
167
+ }
168
+ return null;
169
+ }
170
+ static hasPermission(permission, throwError) {
171
+ return this.hasPermissions([
172
+ permission
173
+ ], throwError);
174
+ }
175
+ /**
176
+ * Retrieves the language code from the headers of the current request.
177
+ * @returns The language code (LanguagesEnum) extracted from the headers, or the default language (ENGLISH) if not found.
178
+ */ static getLanguageCode() {
179
+ // Retrieve the current request
180
+ const req = RequestContext.currentRequest();
181
+ // Variable to store the extracted language code
182
+ let lang;
183
+ // Check if a request exists
184
+ if (req) {
185
+ // Check if the 'language' header exists in the request
186
+ if (req.headers && req.headers['language']) {
187
+ // If found, set the lang variable
188
+ lang = req.headers['language'];
189
+ }
190
+ }
191
+ // Return the extracted language code or the default language (ENGLISH) if not found
192
+ return lang || LanguagesEnum.English;
193
+ }
194
+ static getOrganizationId() {
195
+ const req = this.currentRequest();
196
+ let organizationId;
197
+ const keys = [
198
+ 'organization-id'
199
+ ];
200
+ if (req) {
201
+ for (const key of keys){
202
+ if (req.headers && req.headers[key]) {
203
+ organizationId = req.headers[key];
204
+ break;
205
+ }
206
+ }
207
+ }
208
+ return organizationId;
209
+ }
210
+ static hasPermissions(findPermissions, throwError) {
211
+ const requestContext = RequestContext.currentRequestContext();
212
+ if (requestContext) {
213
+ // tslint:disable-next-line
214
+ const token = ExtractJwt.fromAuthHeaderAsBearerToken()(requestContext.request);
215
+ if (token) {
216
+ const { permissions } = verify(token, process.env['JWT_SECRET']);
217
+ if (permissions) {
218
+ const found = permissions.filter((value)=>findPermissions.indexOf(value) >= 0);
219
+ if (found.length === findPermissions.length) {
220
+ return true;
221
+ }
222
+ } else {
223
+ return false;
224
+ }
225
+ }
226
+ }
227
+ if (throwError) {
228
+ throw new HttpException('Unauthorized', HttpStatus.UNAUTHORIZED);
229
+ }
230
+ return false;
231
+ }
232
+ static hasAnyPermission(findPermissions, throwError) {
233
+ const requestContext = RequestContext.currentRequestContext();
234
+ if (requestContext) {
235
+ // tslint:disable-next-line
236
+ const token = ExtractJwt.fromAuthHeaderAsBearerToken()(requestContext.request);
237
+ if (token) {
238
+ const { permissions } = verify(token, process.env['JWT_SECRET']);
239
+ const found = permissions.filter((value)=>findPermissions.indexOf(value) >= 0);
240
+ if (found.length > 0) {
241
+ return true;
242
+ }
243
+ }
244
+ }
245
+ if (throwError) {
246
+ throw new HttpException('Unauthorized', HttpStatus.UNAUTHORIZED);
247
+ }
248
+ return false;
249
+ }
250
+ static currentToken(throwError) {
251
+ const requestContext = RequestContext.currentRequestContext();
252
+ if (requestContext) {
253
+ // tslint:disable-next-line
254
+ return ExtractJwt.fromAuthHeaderAsBearerToken()(requestContext.request);
255
+ }
256
+ if (throwError) {
257
+ throw new HttpException('Unauthorized', HttpStatus.UNAUTHORIZED);
258
+ }
259
+ return null;
260
+ }
261
+ /**
262
+ * Checks if the current user has a specific role.
263
+ * @param {RolesEnum} role - The role to check.
264
+ * @param {boolean} throwError - Flag indicating whether to throw an error if the role is not granted.
265
+ * @returns {boolean} - True if the user has the role, otherwise false.
266
+ */ static hasRole(role, throwError) {
267
+ return this.hasRoles([
268
+ role
269
+ ], throwError);
270
+ }
271
+ /**
272
+ * Checks if the current request context has any of the specified roles.
273
+ *
274
+ * @param roles - An array of roles to check.
275
+ * @param throwError - Whether to throw an error if no roles are found.
276
+ * @returns True if any of the required roles are found, otherwise false.
277
+ */ static hasRoles(roles, throwError) {
278
+ const context = RequestContext.currentRequestContext();
279
+ if (context) {
280
+ try {
281
+ // tslint:disable-next-line
282
+ const token = this.currentToken();
283
+ if (token) {
284
+ const { role } = verify(token, process.env['JWT_SECRET']);
285
+ return roles.includes(role != null ? role : null);
286
+ } else if (this.currentUser().role) {
287
+ return roles.includes(this.currentUser().role.name);
288
+ }
289
+ } catch (error) {
290
+ if (error instanceof JsonWebTokenError) {
291
+ return false;
292
+ } else {
293
+ throw error;
294
+ }
295
+ }
296
+ }
297
+ if (throwError) {
298
+ throw new HttpException('Unauthorized', HttpStatus.UNAUTHORIZED);
299
+ }
300
+ return false;
301
+ }
302
+ constructor(request, response, reqId, userId, extras = {}){
303
+ this.request = request;
304
+ this.response = response;
305
+ this.reqId = reqId;
306
+ this.userId = userId;
307
+ this.extras = extras;
308
+ }
309
+ }
310
+ const als = new AsyncLocalStorage();
311
+ function getRequestContext() {
312
+ return als.getStore();
313
+ }
314
+
315
+ // request-context.middleware.ts
316
+ let RequestContextMiddleware = class RequestContextMiddleware {
317
+ use(req, _res, next) {
318
+ var _req_user;
319
+ const reqId = req.headers['x-request-id'] || randomUUID();
320
+ // The userId can be placed in the authentication result here.
321
+ const userId = (_req_user = req['user']) == null ? void 0 : _req_user['id'];
322
+ const ctx = new RequestContext(req, _res, reqId, userId);
323
+ als.run(ctx, next);
324
+ }
325
+ };
326
+ RequestContextMiddleware = __decorate([
327
+ Injectable()
328
+ ], RequestContextMiddleware);
329
+ function runWithRequestContext(req, res, next) {
330
+ var _req_user;
331
+ const reqId = req.headers['x-request-id'] || randomUUID();
332
+ const userId = (_req_user = req['user']) == null ? void 0 : _req_user['id'];
333
+ const ctx = new RequestContext(req, res, reqId, userId);
334
+ // Enable ALS scope
335
+ als.run(ctx, next);
336
+ }
337
+
338
+ let StrategyBus = class StrategyBus {
339
+ upsert(strategyType, entry) {
340
+ this.subject.next({
341
+ type: 'UPSERT',
342
+ strategyType,
343
+ entry
344
+ });
345
+ }
346
+ remove(orgId, pluginName) {
347
+ this.subject.next({
348
+ type: 'REMOVE',
349
+ orgId,
350
+ pluginName
351
+ });
352
+ }
353
+ constructor(){
354
+ this.subject = new Subject();
355
+ this.events$ = this.subject.asObservable();
356
+ }
357
+ };
358
+ StrategyBus = __decorate([
359
+ Injectable()
360
+ ], StrategyBus);
361
+
114
362
  class BaseStrategyRegistry {
115
363
  onModuleInit() {
364
+ this.bus.events$.pipe(filter((event)=>!event.strategyType || event.strategyType === this.strategyKey)).subscribe((evt)=>{
365
+ if (evt.type === 'UPSERT') {
366
+ this.upsert(evt.entry.instance);
367
+ } else if (evt.type === 'REMOVE') {
368
+ this.remove(evt.orgId, evt.pluginName);
369
+ }
370
+ });
116
371
  const providers = this.discoveryService.getProviders();
117
372
  for (const wrapper of providers){
118
373
  const { instance } = wrapper;
119
374
  if (!instance) continue;
120
- const type = this.reflector.get(this.strategyKey, instance.constructor);
121
- if (type) {
122
- this.strategies.set(type, instance);
375
+ this.upsert(instance);
376
+ }
377
+ }
378
+ upsert(instance) {
379
+ const type = this.reflector.get(this.strategyKey, instance.constructor);
380
+ if (type) {
381
+ var _instance_metatype;
382
+ const target = (_instance_metatype = instance.metatype) != null ? _instance_metatype : instance.constructor;
383
+ var _this_reflector_get;
384
+ const organizationId = (_this_reflector_get = this.reflector.get(ORGANIZATION_METADATA_KEY, target)) != null ? _this_reflector_get : GLOBAL_ORGANIZATION_SCOPE;
385
+ var _this_strategies_get;
386
+ const orgMap = (_this_strategies_get = this.strategies.get(organizationId)) != null ? _this_strategies_get : new Map();
387
+ orgMap.set(type, instance);
388
+ this.strategies.set(organizationId, orgMap);
389
+ const pluginName = this.reflector.get(PLUGIN_METADATA_KEY, target);
390
+ this.logger.debug(`Registered strategy of type ${type} for organization ${organizationId} from plugin ${pluginName}`);
391
+ if (pluginName) {
392
+ var _this_pluginStrategies_get;
393
+ const pluginStrategies = (_this_pluginStrategies_get = this.pluginStrategies.get(pluginName)) != null ? _this_pluginStrategies_get : new Set();
394
+ pluginStrategies.add(type);
395
+ this.pluginStrategies.set(pluginName, pluginStrategies);
123
396
  }
124
397
  }
125
398
  }
126
- get(type) {
127
- const strategy = this.strategies.get(type);
399
+ /**
400
+ * Remove all strategies registered by the given plugin for the given organization.
401
+ */ remove(organizationId, pluginName) {
402
+ const strategies = this.pluginStrategies.get(pluginName);
403
+ const orgMap = this.strategies.get(organizationId);
404
+ for (const type of strategies != null ? strategies : []){
405
+ orgMap == null ? void 0 : orgMap.delete(type);
406
+ }
407
+ }
408
+ /**
409
+ * Resolve organization id, falling back to request context org or global scope.
410
+ */ resolveOrganization(organizationId) {
411
+ var _ref;
412
+ return (_ref = organizationId != null ? organizationId : RequestContext.getOrganizationId()) != null ? _ref : GLOBAL_ORGANIZATION_SCOPE;
413
+ }
414
+ /**
415
+ * Get strategy by type from the given organization including global strategies as fallback.
416
+ *
417
+ * @param type
418
+ * @param organizationId
419
+ * @returns
420
+ */ get(type, organizationId) {
421
+ var _this_strategies_get, _this_strategies_get1;
422
+ organizationId != null ? organizationId : organizationId = RequestContext.getOrganizationId();
423
+ const orgKey = this.resolveOrganization(organizationId);
424
+ var _this_strategies_get_get;
425
+ 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);
128
426
  if (!strategy) {
129
427
  throw new Error(`No strategy found for type ${type}`);
130
428
  }
131
429
  return strategy;
132
430
  }
133
- list() {
134
- return Array.from(this.strategies.values());
431
+ /**
432
+ * List all strategies for the given organization including global strategies, or only global strategies if global org is specified.
433
+ *
434
+ * @param organizationId
435
+ * @returns
436
+ */ list(organizationId) {
437
+ var _this_strategies_get, _this_strategies_get1;
438
+ organizationId != null ? organizationId : organizationId = RequestContext.getOrganizationId();
439
+ const orgKey = this.resolveOrganization(organizationId);
440
+ var _this_strategies_get_values;
441
+ 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 : [];
442
+ var _this_strategies_get_values1;
443
+ 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 : [];
444
+ return Array.from(new Set([
445
+ ...scoped,
446
+ ...global
447
+ ]));
135
448
  }
136
449
  constructor(strategyKey, discoveryService, reflector){
137
450
  this.strategyKey = strategyKey;
138
451
  this.discoveryService = discoveryService;
139
452
  this.reflector = reflector;
453
+ this.logger = new Logger(BaseStrategyRegistry.name);
140
454
  this.strategies = new Map();
455
+ this.pluginStrategies = new Map();
141
456
  }
142
457
  }
458
+ __decorate([
459
+ Inject(StrategyBus),
460
+ __metadata("design:type", typeof StrategyBus === "undefined" ? Object : StrategyBus)
461
+ ], BaseStrategyRegistry.prototype, "bus", void 0);
143
462
 
144
463
  let IntegrationStrategyRegistry = class IntegrationStrategyRegistry extends BaseStrategyRegistry {
145
464
  constructor(discoveryService, reflector){
@@ -156,7 +475,7 @@ IntegrationStrategyRegistry = __decorate([
156
475
  ], IntegrationStrategyRegistry);
157
476
 
158
477
  const WORKFLOW_TRIGGER_STRATEGY = 'WORKFLOW_TRIGGER_STRATEGY';
159
- const WorkflowTriggerStrategy = (provider)=>SetMetadata(WORKFLOW_TRIGGER_STRATEGY, provider);
478
+ const WorkflowTriggerStrategy = (provider)=>applyDecorators(SetMetadata(WORKFLOW_TRIGGER_STRATEGY, provider), SetMetadata(STRATEGY_META_KEY, WORKFLOW_TRIGGER_STRATEGY));
160
479
 
161
480
  let WorkflowTriggerRegistry = class WorkflowTriggerRegistry extends BaseStrategyRegistry {
162
481
  constructor(discoveryService, reflector){
@@ -175,7 +494,7 @@ WorkflowTriggerRegistry = __decorate([
175
494
  const WORKFLOW_NODE_STRATEGY = 'WORKFLOW_NODE_STRATEGY';
176
495
  /**
177
496
  * Decorator to mark a provider as a Workflow Node Strategy
178
- */ const WorkflowNodeStrategy = (provider)=>SetMetadata(WORKFLOW_NODE_STRATEGY, provider);
497
+ */ const WorkflowNodeStrategy = (provider)=>applyDecorators(SetMetadata(WORKFLOW_NODE_STRATEGY, provider), SetMetadata(STRATEGY_META_KEY, WORKFLOW_NODE_STRATEGY));
179
498
 
180
499
  let WorkflowNodeRegistry = class WorkflowNodeRegistry extends BaseStrategyRegistry {
181
500
  constructor(discoveryService, reflector){
@@ -203,7 +522,7 @@ WorkflowNodeRegistry = __decorate([
203
522
  WrapWorkflowNodeExecutionCommand.type = '[Workflow] Wrap Workflow Node Execution';
204
523
 
205
524
  const VECTOR_STORE_STRATEGY = 'VECTOR_STORE_STRATEGY';
206
- const VectorStoreStrategy = (provider)=>SetMetadata(VECTOR_STORE_STRATEGY, provider);
525
+ const VectorStoreStrategy = (provider)=>applyDecorators(SetMetadata(VECTOR_STORE_STRATEGY, provider), SetMetadata(STRATEGY_META_KEY, VECTOR_STORE_STRATEGY));
207
526
 
208
527
  let VectorStoreRegistry = class VectorStoreRegistry extends BaseStrategyRegistry {
209
528
  constructor(discoveryService, reflector){
@@ -220,7 +539,7 @@ VectorStoreRegistry = __decorate([
220
539
  ], VectorStoreRegistry);
221
540
 
222
541
  const TEXT_SPLITTER_STRATEGY = 'TEXT_SPLITTER_STRATEGY';
223
- const TextSplitterStrategy = (provider)=>SetMetadata(TEXT_SPLITTER_STRATEGY, provider);
542
+ const TextSplitterStrategy = (provider)=>applyDecorators(SetMetadata(TEXT_SPLITTER_STRATEGY, provider), SetMetadata(STRATEGY_META_KEY, TEXT_SPLITTER_STRATEGY));
224
543
 
225
544
  let TextSplitterRegistry = class TextSplitterRegistry extends BaseStrategyRegistry {
226
545
  constructor(discoveryService, reflector){
@@ -239,7 +558,7 @@ TextSplitterRegistry = __decorate([
239
558
  const DOCUMENT_SOURCE_STRATEGY = 'DOCUMENT_SOURCE_STRATEGY';
240
559
  /**
241
560
  * Decorator to mark a provider as a Document Source Strategy
242
- */ const DocumentSourceStrategy = (provider)=>SetMetadata(DOCUMENT_SOURCE_STRATEGY, provider);
561
+ */ const DocumentSourceStrategy = (provider)=>applyDecorators(SetMetadata(DOCUMENT_SOURCE_STRATEGY, provider), SetMetadata(STRATEGY_META_KEY, DOCUMENT_SOURCE_STRATEGY));
243
562
 
244
563
  let DocumentSourceRegistry = class DocumentSourceRegistry extends BaseStrategyRegistry {
245
564
  constructor(discoveryService, reflector){
@@ -258,7 +577,7 @@ DocumentSourceRegistry = __decorate([
258
577
  const DOCUMENT_TRANSFORMER_STRATEGY = 'DOCUMENT_TRANSFORMER_STRATEGY';
259
578
  /**
260
579
  * Decorator to mark a provider as a Document Transformer Strategy
261
- */ const DocumentTransformerStrategy = (provider)=>SetMetadata(DOCUMENT_TRANSFORMER_STRATEGY, provider);
580
+ */ const DocumentTransformerStrategy = (provider)=>applyDecorators(SetMetadata(DOCUMENT_TRANSFORMER_STRATEGY, provider), SetMetadata(STRATEGY_META_KEY, DOCUMENT_TRANSFORMER_STRATEGY));
262
581
 
263
582
  let DocumentTransformerRegistry = class DocumentTransformerRegistry extends BaseStrategyRegistry {
264
583
  constructor(discoveryService, reflector){
@@ -277,7 +596,7 @@ DocumentTransformerRegistry = __decorate([
277
596
  const RETRIEVER_STRATEGY = 'RETRIEVER_STRATEGY';
278
597
  /**
279
598
  * Decorator to mark a provider as a Retriever Strategy
280
- */ const RetrieverStrategy = (provider)=>SetMetadata(RETRIEVER_STRATEGY, provider);
599
+ */ const RetrieverStrategy = (provider)=>applyDecorators(SetMetadata(RETRIEVER_STRATEGY, provider), SetMetadata(STRATEGY_META_KEY, RETRIEVER_STRATEGY));
281
600
 
282
601
  let RetrieverRegistry = class RetrieverRegistry extends BaseStrategyRegistry {
283
602
  constructor(discoveryService, reflector){
@@ -352,7 +671,7 @@ async function downloadRemoteFile(url, dest) {
352
671
  const IMAGE_UNDERSTANDING_STRATEGY = 'IMAGE_UNDERSTANDING_STRATEGY';
353
672
  /**
354
673
  * Decorator to mark a provider as an Image Understanding Strategy
355
- */ const ImageUnderstandingStrategy = (provider)=>SetMetadata(IMAGE_UNDERSTANDING_STRATEGY, provider);
674
+ */ const ImageUnderstandingStrategy = (provider)=>applyDecorators(SetMetadata(IMAGE_UNDERSTANDING_STRATEGY, provider), SetMetadata(STRATEGY_META_KEY, IMAGE_UNDERSTANDING_STRATEGY));
356
675
 
357
676
  let ImageUnderstandingRegistry = class ImageUnderstandingRegistry extends BaseStrategyRegistry {
358
677
  constructor(discoveryService, reflector){
@@ -369,7 +688,7 @@ ImageUnderstandingRegistry = __decorate([
369
688
  ], ImageUnderstandingRegistry);
370
689
 
371
690
  const KNOWLEDGE_STRATEGY = 'KNOWLEDGE_STRATEGY';
372
- const KnowledgeStrategyKey = (provider)=>SetMetadata(KNOWLEDGE_STRATEGY, provider);
691
+ const KnowledgeStrategyKey = (provider)=>applyDecorators(SetMetadata(KNOWLEDGE_STRATEGY, provider), SetMetadata(STRATEGY_META_KEY, KNOWLEDGE_STRATEGY));
373
692
 
374
693
  let KnowledgeStrategyRegistry = class KnowledgeStrategyRegistry extends BaseStrategyRegistry {
375
694
  constructor(discoveryService, reflector){
@@ -388,7 +707,7 @@ KnowledgeStrategyRegistry = __decorate([
388
707
  const TOOLSET_STRATEGY = 'TOOLSET_STRATEGY';
389
708
  /**
390
709
  * Decorator to mark a provider as a Toolset Strategy
391
- */ const ToolsetStrategy = (provider)=>SetMetadata(TOOLSET_STRATEGY, provider);
710
+ */ const ToolsetStrategy = (provider)=>applyDecorators(SetMetadata(TOOLSET_STRATEGY, provider), SetMetadata(STRATEGY_META_KEY, TOOLSET_STRATEGY));
392
711
 
393
712
  let ToolsetRegistry = class ToolsetRegistry extends BaseStrategyRegistry {
394
713
  constructor(discoveryService, reflector){
@@ -580,336 +899,142 @@ BuiltinToolset.provider = '';
580
899
  const url = new URL(filePath, this.baseUrl);
581
900
  return url.href;
582
901
  }
583
- /**
584
- * Delete a file
585
- */ async deleteFile(filePath) {
586
- this.ensureAllowed('delete');
587
- this.ensureInScope(filePath);
588
- await fsPromises.unlink(filePath);
589
- }
590
- /**
591
- * List directory contents
592
- */ async listDir(dirPath) {
593
- this.ensureAllowed('list');
594
- this.ensureInScope(dirPath);
595
- return fsPromises.readdir(dirPath);
596
- }
597
- /**
598
- * Utility: check if a file or directory exists
599
- */ async exists(targetPath) {
600
- try {
601
- await fsPromises.access(targetPath);
602
- return true;
603
- } catch (e) {
604
- return false;
605
- }
606
- }
607
- constructor(permission, basePath, baseUrl){
608
- this.basePath = basePath;
609
- this.baseUrl = baseUrl;
610
- this.allowedOps = new Set(permission.operations);
611
- this.scope = permission.scope;
612
- }
613
- }
614
-
615
- async function createI18nInstance(pluginDir, language) {
616
- const instance = createInstance();
617
- const i18nDir = path__default.join(pluginDir, 'i18n');
618
- // detect available languages dynamically
619
- const lngs = fs__default.readdirSync(i18nDir).filter((f)=>f.endsWith('.json')).map((f)=>f.replace('.json', ''));
620
- await instance.use(FsBackend).init({
621
- lng: language,
622
- fallbackLng: 'en',
623
- preload: lngs,
624
- ns: [
625
- 'default'
626
- ],
627
- defaultNS: 'default',
628
- backend: {
629
- loadPath: path__default.join(i18nDir, '{{lng}}.json')
630
- },
631
- interpolation: {
632
- escapeValue: false
633
- }
634
- });
635
- return instance;
636
- }
637
-
638
- function loadYamlFile(filePath, logger, ignoreError = true, defaultValue = {}) {
639
- try {
640
- const fileContent = fs__default.readFileSync(filePath, 'utf-8');
641
- try {
642
- const yamlContent = yaml__default.parse(fileContent);
643
- return yamlContent || defaultValue;
644
- } catch (e) {
645
- throw new Error(`Failed to load YAML file ${filePath}: ${e}`);
646
- }
647
- } catch (e) {
648
- if (ignoreError) {
649
- logger == null ? void 0 : logger.debug(`Error loading YAML file: ${e}`);
650
- return defaultValue;
651
- } else {
652
- throw e;
653
- }
654
- }
655
- }
656
- /**
657
- * Get the mapping from name to index from a YAML file
658
- *
659
- * @param folderPath
660
- * @param fileName the YAML file name, default to '_position.yaml'
661
- * @return a dict with name as key and index as value
662
- */ function getPositionMap(folderPath, fileName = '_position.yaml', logger) {
663
- const positions = getPositionList(folderPath, fileName, logger);
664
- return positions.reduce((acc, name, index)=>{
665
- acc[name] = index;
666
- return acc;
667
- }, {});
668
- }
669
- function getPositionList(folderPath, fileName = '_position.yaml', logger) {
670
- const positionFilePath = path__default.join(folderPath, fileName);
671
- const yamlContent = loadYamlFile(positionFilePath, logger, true, []);
672
- const positions = yamlContent == null ? void 0 : yamlContent.filter((item)=>item && typeof item === 'string' && item.trim()).map((item)=>item.trim());
673
- return positions;
674
- }
675
- function getErrorMessage(err) {
676
- let error;
677
- if (typeof err === 'string') {
678
- error = err;
679
- } else if (err && (err.name === "AggregateError" || err.constructor.name === "AggregateError")) {
680
- return err.errors.map((_)=>getErrorMessage(_)).join('\n\n');
681
- } else if (err instanceof Error) {
682
- error = err == null ? void 0 : err.message;
683
- } else if ((err == null ? void 0 : err.error) instanceof Error) {
684
- var _err_error;
685
- error = err == null ? void 0 : (_err_error = err.error) == null ? void 0 : _err_error.message;
686
- } else if (err == null ? void 0 : err.message) {
687
- error = err == null ? void 0 : err.message;
688
- } else if (err) {
689
- // If there is no other way, convert it to JSON string
690
- error = JSON.stringify(err);
691
- }
692
- return error;
693
- }
694
-
695
- // request-context.ts
696
- class RequestContext {
697
- static currentRequestContext() {
698
- const session = getRequestContext();
699
- return session;
700
- }
701
- static currentRequest() {
702
- const requestContext = RequestContext.currentRequestContext();
703
- if (requestContext) {
704
- return requestContext.request;
705
- }
706
- return null;
707
- }
708
- static currentTenantId() {
709
- const user = RequestContext.currentUser();
710
- if (user) {
711
- return user.tenantId;
712
- }
713
- return null;
714
- }
715
- static currentUserId() {
716
- const user = RequestContext.currentUser();
717
- if (user) {
718
- return user.id;
719
- }
720
- return null;
721
- }
722
- static currentRoleId() {
723
- const user = RequestContext.currentUser();
724
- if (user) {
725
- return user.roleId;
726
- }
727
- return null;
728
- }
729
- static currentUser(throwError) {
730
- const requestContext = RequestContext.currentRequestContext();
731
- if (requestContext) {
732
- // tslint:disable-next-line
733
- const user = requestContext.request['user'];
734
- if (user) {
735
- return user;
736
- }
737
- }
738
- if (throwError) {
739
- throw new HttpException('Unauthorized', HttpStatus.UNAUTHORIZED);
740
- }
741
- return null;
742
- }
743
- static hasPermission(permission, throwError) {
744
- return this.hasPermissions([
745
- permission
746
- ], throwError);
747
- }
748
- /**
749
- * Retrieves the language code from the headers of the current request.
750
- * @returns The language code (LanguagesEnum) extracted from the headers, or the default language (ENGLISH) if not found.
751
- */ static getLanguageCode() {
752
- // Retrieve the current request
753
- const req = RequestContext.currentRequest();
754
- // Variable to store the extracted language code
755
- let lang;
756
- // Check if a request exists
757
- if (req) {
758
- // Check if the 'language' header exists in the request
759
- if (req.headers && req.headers['language']) {
760
- // If found, set the lang variable
761
- lang = req.headers['language'];
762
- }
763
- }
764
- // Return the extracted language code or the default language (ENGLISH) if not found
765
- return lang || LanguagesEnum.English;
766
- }
767
- static getOrganizationId() {
768
- const req = this.currentRequest();
769
- let organizationId;
770
- const keys = [
771
- 'organization-id'
772
- ];
773
- if (req) {
774
- for (const key of keys){
775
- if (req.headers && req.headers[key]) {
776
- organizationId = req.headers[key];
777
- break;
778
- }
779
- }
780
- }
781
- return organizationId;
782
- }
783
- static hasPermissions(findPermissions, throwError) {
784
- const requestContext = RequestContext.currentRequestContext();
785
- if (requestContext) {
786
- // tslint:disable-next-line
787
- const token = ExtractJwt.fromAuthHeaderAsBearerToken()(requestContext.request);
788
- if (token) {
789
- const { permissions } = verify(token, process.env['JWT_SECRET']);
790
- if (permissions) {
791
- const found = permissions.filter((value)=>findPermissions.indexOf(value) >= 0);
792
- if (found.length === findPermissions.length) {
793
- return true;
794
- }
795
- } else {
796
- return false;
797
- }
798
- }
799
- }
800
- if (throwError) {
801
- throw new HttpException('Unauthorized', HttpStatus.UNAUTHORIZED);
802
- }
803
- return false;
804
- }
805
- static hasAnyPermission(findPermissions, throwError) {
806
- const requestContext = RequestContext.currentRequestContext();
807
- if (requestContext) {
808
- // tslint:disable-next-line
809
- const token = ExtractJwt.fromAuthHeaderAsBearerToken()(requestContext.request);
810
- if (token) {
811
- const { permissions } = verify(token, process.env['JWT_SECRET']);
812
- const found = permissions.filter((value)=>findPermissions.indexOf(value) >= 0);
813
- if (found.length > 0) {
814
- return true;
815
- }
816
- }
817
- }
818
- if (throwError) {
819
- throw new HttpException('Unauthorized', HttpStatus.UNAUTHORIZED);
820
- }
821
- return false;
822
- }
823
- static currentToken(throwError) {
824
- const requestContext = RequestContext.currentRequestContext();
825
- if (requestContext) {
826
- // tslint:disable-next-line
827
- return ExtractJwt.fromAuthHeaderAsBearerToken()(requestContext.request);
828
- }
829
- if (throwError) {
830
- throw new HttpException('Unauthorized', HttpStatus.UNAUTHORIZED);
831
- }
832
- return null;
902
+ /**
903
+ * Delete a file
904
+ */ async deleteFile(filePath) {
905
+ this.ensureAllowed('delete');
906
+ this.ensureInScope(filePath);
907
+ await fsPromises.unlink(filePath);
833
908
  }
834
909
  /**
835
- * Checks if the current user has a specific role.
836
- * @param {RolesEnum} role - The role to check.
837
- * @param {boolean} throwError - Flag indicating whether to throw an error if the role is not granted.
838
- * @returns {boolean} - True if the user has the role, otherwise false.
839
- */ static hasRole(role, throwError) {
840
- return this.hasRoles([
841
- role
842
- ], throwError);
910
+ * List directory contents
911
+ */ async listDir(dirPath) {
912
+ this.ensureAllowed('list');
913
+ this.ensureInScope(dirPath);
914
+ return fsPromises.readdir(dirPath);
843
915
  }
844
916
  /**
845
- * Checks if the current request context has any of the specified roles.
846
- *
847
- * @param roles - An array of roles to check.
848
- * @param throwError - Whether to throw an error if no roles are found.
849
- * @returns True if any of the required roles are found, otherwise false.
850
- */ static hasRoles(roles, throwError) {
851
- const context = RequestContext.currentRequestContext();
852
- if (context) {
853
- try {
854
- // tslint:disable-next-line
855
- const token = this.currentToken();
856
- if (token) {
857
- const { role } = verify(token, process.env['JWT_SECRET']);
858
- return roles.includes(role != null ? role : null);
859
- } else if (this.currentUser().role) {
860
- return roles.includes(this.currentUser().role.name);
861
- }
862
- } catch (error) {
863
- if (error instanceof JsonWebTokenError) {
864
- return false;
865
- } else {
866
- throw error;
867
- }
868
- }
869
- }
870
- if (throwError) {
871
- throw new HttpException('Unauthorized', HttpStatus.UNAUTHORIZED);
917
+ * Utility: check if a file or directory exists
918
+ */ async exists(targetPath) {
919
+ try {
920
+ await fsPromises.access(targetPath);
921
+ return true;
922
+ } catch (e) {
923
+ return false;
872
924
  }
873
- return false;
874
925
  }
875
- constructor(request, response, reqId, userId, extras = {}){
876
- this.request = request;
877
- this.response = response;
878
- this.reqId = reqId;
879
- this.userId = userId;
880
- this.extras = extras;
926
+ constructor(permission, basePath, baseUrl){
927
+ this.basePath = basePath;
928
+ this.baseUrl = baseUrl;
929
+ this.allowedOps = new Set(permission.operations);
930
+ this.scope = permission.scope;
881
931
  }
882
932
  }
883
- const als = new AsyncLocalStorage();
884
- function getRequestContext() {
885
- return als.getStore();
933
+
934
+ async function createI18nInstance(pluginDir, language) {
935
+ const instance = createInstance();
936
+ const i18nDir = path__default.join(pluginDir, 'i18n');
937
+ // detect available languages dynamically
938
+ const lngs = fs__default.readdirSync(i18nDir).filter((f)=>f.endsWith('.json')).map((f)=>f.replace('.json', ''));
939
+ await instance.use(FsBackend).init({
940
+ lng: language,
941
+ fallbackLng: 'en',
942
+ preload: lngs,
943
+ ns: [
944
+ 'default'
945
+ ],
946
+ defaultNS: 'default',
947
+ backend: {
948
+ loadPath: path__default.join(i18nDir, '{{lng}}.json')
949
+ },
950
+ interpolation: {
951
+ escapeValue: false
952
+ }
953
+ });
954
+ return instance;
886
955
  }
887
956
 
888
- // request-context.middleware.ts
889
- let RequestContextMiddleware = class RequestContextMiddleware {
890
- use(req, _res, next) {
891
- var _req_user;
892
- const reqId = req.headers['x-request-id'] || randomUUID();
893
- // The userId can be placed in the authentication result here.
894
- const userId = (_req_user = req['user']) == null ? void 0 : _req_user['id'];
895
- const ctx = new RequestContext(req, _res, reqId, userId);
896
- als.run(ctx, next);
957
+ function loadYamlFile(filePath, logger, ignoreError = true, defaultValue = {}) {
958
+ try {
959
+ const fileContent = fs__default.readFileSync(filePath, 'utf-8');
960
+ try {
961
+ const yamlContent = yaml__default.parse(fileContent);
962
+ return yamlContent || defaultValue;
963
+ } catch (e) {
964
+ throw new Error(`Failed to load YAML file ${filePath}: ${e}`);
965
+ }
966
+ } catch (e) {
967
+ if (ignoreError) {
968
+ logger == null ? void 0 : logger.debug(`Error loading YAML file: ${e}`);
969
+ return defaultValue;
970
+ } else {
971
+ throw e;
972
+ }
973
+ }
974
+ }
975
+ /**
976
+ * Get the mapping from name to index from a YAML file
977
+ *
978
+ * @param folderPath
979
+ * @param fileName the YAML file name, default to '_position.yaml'
980
+ * @return a dict with name as key and index as value
981
+ */ function getPositionMap(folderPath, fileName = '_position.yaml', logger) {
982
+ const positions = getPositionList(folderPath, fileName, logger);
983
+ return positions.reduce((acc, name, index)=>{
984
+ acc[name] = index;
985
+ return acc;
986
+ }, {});
987
+ }
988
+ function getPositionList(folderPath, fileName = '_position.yaml', logger) {
989
+ const positionFilePath = path__default.join(folderPath, fileName);
990
+ const yamlContent = loadYamlFile(positionFilePath, logger, true, []);
991
+ const positions = yamlContent == null ? void 0 : yamlContent.filter((item)=>item && typeof item === 'string' && item.trim()).map((item)=>item.trim());
992
+ return positions;
993
+ }
994
+ function getErrorMessage(err) {
995
+ let error;
996
+ if (typeof err === 'string') {
997
+ error = err;
998
+ } else if (err && (err.name === "AggregateError" || err.constructor.name === "AggregateError")) {
999
+ return err.errors.map((_)=>getErrorMessage(_)).join('\n\n');
1000
+ } else if (err instanceof Error) {
1001
+ error = err == null ? void 0 : err.message;
1002
+ } else if ((err == null ? void 0 : err.error) instanceof Error) {
1003
+ var _err_error;
1004
+ error = err == null ? void 0 : (_err_error = err.error) == null ? void 0 : _err_error.message;
1005
+ } else if (err == null ? void 0 : err.message) {
1006
+ error = err == null ? void 0 : err.message;
1007
+ } else if (err) {
1008
+ // If there is no other way, convert it to JSON string
1009
+ error = JSON.stringify(err);
1010
+ }
1011
+ return error;
1012
+ }
1013
+ class JsonSchemaValidator {
1014
+ parseAndValidate(schemaStr) {
1015
+ if (!schemaStr) return undefined;
1016
+ let schema;
1017
+ try {
1018
+ schema = JSON.parse(schemaStr);
1019
+ } catch (e) {
1020
+ throw new Error('Schema is not valid JSON');
1021
+ }
1022
+ const validate = this.ajv.getSchema(schemaDraft04.$id);
1023
+ if (!validate(schema)) {
1024
+ throw new Error('Invalid JSON Schema: ' + this.ajv.errorsText(validate.errors));
1025
+ }
1026
+ return schema;
1027
+ }
1028
+ constructor(){
1029
+ this.ajv = new Ajv({
1030
+ strict: false
1031
+ });
1032
+ this.ajv.addMetaSchema(schemaDraft04);
897
1033
  }
898
- };
899
- RequestContextMiddleware = __decorate([
900
- Injectable()
901
- ], RequestContextMiddleware);
902
- function runWithRequestContext(req, res, next) {
903
- var _req_user;
904
- const reqId = req.headers['x-request-id'] || randomUUID();
905
- const userId = (_req_user = req['user']) == null ? void 0 : _req_user['id'];
906
- const ctx = new RequestContext(req, res, reqId, userId);
907
- // Enable ALS scope
908
- als.run(ctx, next);
909
1034
  }
910
1035
 
911
1036
  const DATASOURCE_STRATEGY = 'DATASOURCE_STRATEGY';
912
- const DataSourceStrategy = (provider)=>SetMetadata(DATASOURCE_STRATEGY, provider);
1037
+ const DataSourceStrategy = (provider)=>applyDecorators(SetMetadata(DATASOURCE_STRATEGY, provider), SetMetadata(STRATEGY_META_KEY, DATASOURCE_STRATEGY));
913
1038
 
914
1039
  let DataSourceStrategyRegistry = class DataSourceStrategyRegistry extends BaseStrategyRegistry {
915
1040
  constructor(discoveryService, reflector){
@@ -1222,6 +1347,7 @@ function AIModelProviderStrategy(provider) {
1222
1347
  }
1223
1348
  const dir = file ? path__default.dirname(file) : process.cwd();
1224
1349
  return function(target) {
1350
+ SetMetadata(STRATEGY_META_KEY, AI_MODEL_PROVIDER)(target);
1225
1351
  // Ensure NestJS is discoverable
1226
1352
  SetMetadata(AI_MODEL_PROVIDER, provider)(target);
1227
1353
  // Write custom path (does not affect Discovery)
@@ -1513,6 +1639,46 @@ const PARAMETER_RULE_TEMPLATE = {
1513
1639
  }
1514
1640
  };
1515
1641
 
1642
+ const CommonParameterRules = [
1643
+ {
1644
+ name: 'temperature',
1645
+ label: {
1646
+ zh_Hans: '温度',
1647
+ en_US: `Temperature`
1648
+ },
1649
+ type: ParameterType.FLOAT,
1650
+ help: {
1651
+ zh_Hans: '控制模型输出的随机性。较高的值(例如 1.0)使响应更具创意,而较低的值(例如 0.1)使响应更具确定性和重点性。',
1652
+ 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.`
1653
+ },
1654
+ required: false,
1655
+ default: 0.2,
1656
+ min: 0,
1657
+ max: 1,
1658
+ precision: 0.1
1659
+ },
1660
+ {
1661
+ label: {
1662
+ zh_Hans: '最大尝试次数',
1663
+ en_US: 'The maximum number of attempts'
1664
+ },
1665
+ type: ParameterType.INT,
1666
+ help: {
1667
+ zh_Hans: '如果请求由于网络超时或速率限制等问题而失败,系统将尝试重新发送请求的最大次数',
1668
+ 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'
1669
+ },
1670
+ required: false,
1671
+ default: 6,
1672
+ min: 0,
1673
+ max: 10,
1674
+ precision: 0,
1675
+ name: 'maxRetries'
1676
+ }
1677
+ ];
1678
+ function mergeCredentials(credentials, modelProperties) {
1679
+ return _extends({}, credentials != null ? credentials : {}, modelProperties != null ? modelProperties : {});
1680
+ }
1681
+
1516
1682
  let AIModel = class AIModel {
1517
1683
  getChatModel(copilotModel, options) {
1518
1684
  throw new Error(`Unsupport chat model!`);
@@ -1656,6 +1822,15 @@ let AIModel = class AIModel {
1656
1822
  ...parameterRules.filter((_)=>!CommonParameterRules.some((r)=>r.name === _.name))
1657
1823
  ];
1658
1824
  }
1825
+ getModelProfile(model, credentials) {
1826
+ var _modelSchema_model_properties, _modelSchema_features, _modelSchema_features1, _modelSchema_features2, _modelSchema_features3;
1827
+ const modelSchema = this.getModelSchema(model, credentials);
1828
+ return modelSchema && {
1829
+ maxInputTokens: (_modelSchema_model_properties = modelSchema.model_properties) == null ? void 0 : _modelSchema_model_properties.context_size,
1830
+ toolCalling: ((_modelSchema_features = modelSchema.features) == null ? void 0 : _modelSchema_features.includes(ModelFeature.TOOL_CALL)) || ((_modelSchema_features1 = modelSchema.features) == null ? void 0 : _modelSchema_features1.includes(ModelFeature.MULTI_TOOL_CALL)) || ((_modelSchema_features2 = modelSchema.features) == null ? void 0 : _modelSchema_features2.includes(ModelFeature.STREAM_TOOL_CALL)),
1831
+ structuredOutput: (_modelSchema_features3 = modelSchema.features) == null ? void 0 : _modelSchema_features3.includes(ModelFeature.STRUCTURED_OUTPUT)
1832
+ };
1833
+ }
1659
1834
  constructor(modelProvider, modelType){
1660
1835
  this.modelProvider = modelProvider;
1661
1836
  this.modelType = modelType;
@@ -1695,46 +1870,6 @@ class RerankModel extends AIModel {
1695
1870
  }
1696
1871
  }
1697
1872
 
1698
- const CommonParameterRules = [
1699
- {
1700
- name: 'temperature',
1701
- label: {
1702
- zh_Hans: '温度',
1703
- en_US: `Temperature`
1704
- },
1705
- type: ParameterType.FLOAT,
1706
- help: {
1707
- zh_Hans: '控制模型输出的随机性。较高的值(例如 1.0)使响应更具创意,而较低的值(例如 0.1)使响应更具确定性和重点性。',
1708
- 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.`
1709
- },
1710
- required: false,
1711
- default: 0.2,
1712
- min: 0,
1713
- max: 1,
1714
- precision: 0.1
1715
- },
1716
- {
1717
- label: {
1718
- zh_Hans: '最大尝试次数',
1719
- en_US: 'The maximum number of attempts'
1720
- },
1721
- type: ParameterType.INT,
1722
- help: {
1723
- zh_Hans: '如果请求由于网络超时或速率限制等问题而失败,系统将尝试重新发送请求的最大次数',
1724
- 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'
1725
- },
1726
- required: false,
1727
- default: 6,
1728
- min: 0,
1729
- max: 10,
1730
- precision: 0,
1731
- name: 'maxRetries'
1732
- }
1733
- ];
1734
- function mergeCredentials(credentials, modelProperties) {
1735
- return _extends({}, credentials != null ? credentials : {}, modelProperties != null ? modelProperties : {});
1736
- }
1737
-
1738
1873
  class SpeechToTextModel extends AIModel {
1739
1874
  }
1740
1875
 
@@ -2061,7 +2196,7 @@ class OpenAICompatibleReranker {
2061
2196
  if (!Array.isArray(output)) {
2062
2197
  throw new Error('Invalid response format: missing results array');
2063
2198
  }
2064
- // 收集原始分数并进行归一化处理
2199
+ // Collect raw scores and normalize them.
2065
2200
  const scores = output.map((r)=>r.relevance_score);
2066
2201
  const minScore = Math.min(...scores);
2067
2202
  const maxScore = Math.max(...scores);
@@ -2140,7 +2275,7 @@ class Speech2TextChatModel extends BaseChatModel {
2140
2275
  CreateModelClientCommand.type = '[AI Model] Create Model Client';
2141
2276
 
2142
2277
  const AGENT_MIDDLEWARE_STRATEGY = 'AGENT_MIDDLEWARE_STRATEGY';
2143
- const AgentMiddlewareStrategy = (provider)=>SetMetadata(AGENT_MIDDLEWARE_STRATEGY, provider);
2278
+ const AgentMiddlewareStrategy = (provider)=>applyDecorators(SetMetadata(AGENT_MIDDLEWARE_STRATEGY, provider), SetMetadata(STRATEGY_META_KEY, AGENT_MIDDLEWARE_STRATEGY));
2144
2279
 
2145
2280
  let AgentMiddlewareRegistry = class AgentMiddlewareRegistry extends BaseStrategyRegistry {
2146
2281
  constructor(discoveryService, reflector){
@@ -2164,4 +2299,4 @@ AgentMiddlewareRegistry = __decorate([
2164
2299
  "end"
2165
2300
  ];
2166
2301
 
2167
- export { AGENT_MIDDLEWARE_STRATEGY, AIModelProviderNotFoundException, AIModelProviderRegistry, AIModelProviderStrategy, AI_MODEL_PROVIDER, AdapterDataSourceStrategy, AgentMiddlewareRegistry, AgentMiddlewareStrategy, AiModelNotFoundException, BaseHTTPQueryRunner, BaseQueryRunner, BaseSQLQueryRunner, BaseTool, BaseToolset, BuiltinToolset, ChatOAICompatReasoningModel, CommonParameterRules, CreateModelClientCommand, CredentialsValidateFailedError, DATASOURCE_STRATEGY, DBCreateTableMode, DBProtocolEnum, DBSyntaxEnum, DBTableAction, DBTableDataAction, DOCUMENT_SOURCE_STRATEGY, DOCUMENT_TRANSFORMER_STRATEGY, DataSourceStrategy, DataSourceStrategyRegistry, DocumentSourceRegistry, DocumentSourceStrategy, DocumentTransformerRegistry, DocumentTransformerStrategy, IMAGE_UNDERSTANDING_STRATEGY, INTEGRATION_STRATEGY, ImageUnderstandingRegistry, ImageUnderstandingStrategy, IntegrationStrategyKey, IntegrationStrategyRegistry, JUMP_TO_TARGETS, KNOWLEDGE_STRATEGY, KnowledgeStrategyKey, KnowledgeStrategyRegistry, LLMUsage, LargeLanguageModel, ModelProvider, OpenAICompatibleReranker, PLUGIN_METADATA, PROVIDE_AI_MODEL_LLM, PROVIDE_AI_MODEL_MODERATION, PROVIDE_AI_MODEL_RERANK, PROVIDE_AI_MODEL_SPEECH2TEXT, PROVIDE_AI_MODEL_TEXT_EMBEDDING, PROVIDE_AI_MODEL_TTS, RETRIEVER_STRATEGY, RequestContext, RequestContextMiddleware, RerankModel, RetrieverRegistry, RetrieverStrategy, Speech2TextChatModel, SpeechToTextModel, TEXT_SPLITTER_STRATEGY, TOOLSET_STRATEGY, TextEmbeddingModelManager, TextSplitterRegistry, TextSplitterStrategy, TextToSpeechModel, ToolsetRegistry, ToolsetStrategy, VECTOR_STORE_STRATEGY, VectorStoreRegistry, VectorStoreStrategy, WORKFLOW_NODE_STRATEGY, WORKFLOW_TRIGGER_STRATEGY, WorkflowNodeRegistry, WorkflowNodeStrategy, WorkflowTriggerRegistry, WorkflowTriggerStrategy, WrapWorkflowNodeExecutionCommand, XpFileSystem, XpertServerPlugin, als, calcTokenUsage, countTokensSafe, createI18nInstance, createPluginLogger, downloadRemoteFile, getErrorMessage, getPositionList, getPositionMap, getRequestContext, isRemoteFile, loadYamlFile, mergeCredentials, mergeParentChildChunks, runWithRequestContext, sumTokenUsage };
2302
+ export { AGENT_MIDDLEWARE_STRATEGY, AIModelProviderNotFoundException, AIModelProviderRegistry, AIModelProviderStrategy, AI_MODEL_PROVIDER, AdapterDataSourceStrategy, AgentMiddlewareRegistry, AgentMiddlewareStrategy, AiModelNotFoundException, BaseHTTPQueryRunner, BaseQueryRunner, BaseSQLQueryRunner, BaseStrategyRegistry, BaseTool, BaseToolset, BuiltinToolset, ChatOAICompatReasoningModel, CommonParameterRules, CreateModelClientCommand, CredentialsValidateFailedError, DATASOURCE_STRATEGY, DBCreateTableMode, DBProtocolEnum, DBSyntaxEnum, DBTableAction, DBTableDataAction, DOCUMENT_SOURCE_STRATEGY, DOCUMENT_TRANSFORMER_STRATEGY, DataSourceStrategy, DataSourceStrategyRegistry, DocumentSourceRegistry, DocumentSourceStrategy, DocumentTransformerRegistry, DocumentTransformerStrategy, GLOBAL_ORGANIZATION_SCOPE, IMAGE_UNDERSTANDING_STRATEGY, INTEGRATION_STRATEGY, ImageUnderstandingRegistry, ImageUnderstandingStrategy, IntegrationStrategyKey, IntegrationStrategyRegistry, JUMP_TO_TARGETS, JsonSchemaValidator, KNOWLEDGE_STRATEGY, KnowledgeStrategyKey, KnowledgeStrategyRegistry, LLMUsage, LargeLanguageModel, ModelProvider, ORGANIZATION_METADATA_KEY, OpenAICompatibleReranker, PLUGIN_METADATA, PLUGIN_METADATA_KEY, PROVIDE_AI_MODEL_LLM, PROVIDE_AI_MODEL_MODERATION, PROVIDE_AI_MODEL_RERANK, PROVIDE_AI_MODEL_SPEECH2TEXT, PROVIDE_AI_MODEL_TEXT_EMBEDDING, PROVIDE_AI_MODEL_TTS, RETRIEVER_STRATEGY, RequestContext, RequestContextMiddleware, RerankModel, RetrieverRegistry, RetrieverStrategy, STRATEGY_META_KEY, Speech2TextChatModel, SpeechToTextModel, StrategyBus, TEXT_SPLITTER_STRATEGY, TOOLSET_STRATEGY, TextEmbeddingModelManager, TextSplitterRegistry, TextSplitterStrategy, TextToSpeechModel, ToolsetRegistry, ToolsetStrategy, VECTOR_STORE_STRATEGY, VectorStoreRegistry, VectorStoreStrategy, WORKFLOW_NODE_STRATEGY, WORKFLOW_TRIGGER_STRATEGY, WorkflowNodeRegistry, WorkflowNodeStrategy, WorkflowTriggerRegistry, WorkflowTriggerStrategy, WrapWorkflowNodeExecutionCommand, XpFileSystem, XpertServerPlugin, als, calcTokenUsage, countTokensSafe, createI18nInstance, createPluginLogger, downloadRemoteFile, getErrorMessage, getPositionList, getPositionMap, getRequestContext, isRemoteFile, loadYamlFile, mergeCredentials, mergeParentChildChunks, runWithRequestContext, sumTokenUsage };