@smythos/sre 1.7.40 → 1.7.42

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.
Files changed (40) hide show
  1. package/dist/index.js +49 -42
  2. package/dist/index.js.map +1 -1
  3. package/dist/types/Components/AgentPlugin.class.d.ts +1 -1
  4. package/dist/types/Components/RAG/DataSourceCleaner.class.d.ts +4 -4
  5. package/dist/types/Components/RAG/DataSourceComponent.class.d.ts +5 -1
  6. package/dist/types/config.d.ts +1 -0
  7. package/dist/types/helpers/Conversation.helper.d.ts +10 -13
  8. package/dist/types/helpers/TemplateString.helper.d.ts +1 -1
  9. package/dist/types/index.d.ts +1 -0
  10. package/dist/types/subsystems/IO/VectorDB.service/VectorDBConnector.d.ts +1 -0
  11. package/dist/types/subsystems/LLMManager/LLM.helper.d.ts +19 -0
  12. package/dist/types/subsystems/LLMManager/LLM.service/connectors/GoogleAI.class.d.ts +15 -10
  13. package/dist/types/types/LLM.types.d.ts +23 -0
  14. package/package.json +1 -1
  15. package/src/Components/AgentPlugin.class.ts +20 -3
  16. package/src/Components/Classifier.class.ts +79 -16
  17. package/src/Components/ForEach.class.ts +34 -6
  18. package/src/Components/GenAILLM.class.ts +54 -23
  19. package/src/Components/LLMAssistant.class.ts +56 -21
  20. package/src/Components/RAG/DataSourceCleaner.class.ts +13 -11
  21. package/src/Components/RAG/DataSourceComponent.class.ts +39 -13
  22. package/src/Components/RAG/DataSourceIndexer.class.ts +18 -12
  23. package/src/Components/RAG/DataSourceLookup.class.ts +14 -10
  24. package/src/Components/ScrapflyWebScrape.class.ts +7 -0
  25. package/src/config.ts +1 -0
  26. package/src/helpers/Conversation.helper.ts +112 -26
  27. package/src/helpers/TemplateString.helper.ts +6 -5
  28. package/src/index.ts +213 -212
  29. package/src/index.ts.bak +213 -212
  30. package/src/subsystems/IO/VectorDB.service/VectorDBConnector.ts +1 -0
  31. package/src/subsystems/IO/VectorDB.service/connectors/PineconeVectorDB.class.ts +11 -0
  32. package/src/subsystems/IO/VectorDB.service/embed/index.ts +9 -11
  33. package/src/subsystems/LLMManager/LLM.helper.ts +25 -0
  34. package/src/subsystems/LLMManager/LLM.service/LLMConnector.ts +1 -1
  35. package/src/subsystems/LLMManager/LLM.service/connectors/GoogleAI.class.ts +190 -146
  36. package/src/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/utils.ts +1 -1
  37. package/src/subsystems/ObservabilityManager/Telemetry.service/connectors/OTel/OTel.class.ts +402 -66
  38. package/src/types/LLM.types.ts +24 -0
  39. package/src/utils/data.utils.ts +6 -4
  40. package/src/Components/DataSourceIndexer.class.ts +0 -295
@@ -237,6 +237,7 @@ export type TLLMModel = {
237
237
  isCustomLLM?: boolean;
238
238
  isUserCustomLLM?: boolean;
239
239
  modelId?: string;
240
+ modelEntryName?: string;
240
241
  tokens?: number;
241
242
  completionTokens?: number;
242
243
  components?: string[];
@@ -446,11 +447,34 @@ export type TLLMInputMessage = {
446
447
  };
447
448
 
448
449
  export interface ILLMContextStore {
450
+ id: string;
449
451
  save(messages: any[]): Promise<void>;
450
452
  load(count?: number): Promise<any[]>;
451
453
  getMessage(message_id: string): Promise<any[]>;
452
454
  }
453
455
 
456
+ /**
457
+ * Configuration options for Conversation helper
458
+ */
459
+ export interface IConversationSettings {
460
+ maxContextSize?: number;
461
+ maxOutputTokens?: number;
462
+ systemPrompt?: string;
463
+ toolChoice?: string;
464
+ store?: ILLMContextStore;
465
+ experimentalCache?: boolean;
466
+ toolsStrategy?: (toolsConfig: any) => any;
467
+ agentId?: string;
468
+ agentVersion?: string;
469
+ baseUrl?: string;
470
+ /**
471
+ * Maximum number of tool calls allowed in a single conversation session.
472
+ * Prevents infinite loops in tool calling scenarios.
473
+ * @default 100
474
+ */
475
+ maxToolCalls?: number;
476
+ }
477
+
454
478
  export enum APIKeySource {
455
479
  Smyth = 'smyth-managed',
456
480
  User = 'user-managed',
@@ -161,12 +161,12 @@ function isValidPathFormat(path: string): boolean {
161
161
  const windowsAbsolute = /^[a-zA-Z]:[\\\/]/; // C:\ or C:/
162
162
  const windowsUNC = /^\\\\[^\\]+\\[^\\]+/; // \\server\share
163
163
  const windowsRelative = /^\.{1,2}[\\\/]/; // .\ or ..\ or ./ or ../
164
-
164
+
165
165
  // Unix path patterns
166
166
  const unixAbsolute = /^\//; // /path/to/file
167
167
  const unixHome = /^~[\/]/; // ~/path/to/file
168
168
  const unixRelative = /^\.{1,2}\//; // ./ or ../
169
-
169
+
170
170
  // Relative paths without leading ./ or .\
171
171
  const genericRelative = /^[^\\\/]/; // path/to/file or path\to\file
172
172
 
@@ -259,12 +259,14 @@ export async function formatDataForDebug(data: any, candidate: IAccessCandidate)
259
259
  }
260
260
 
261
261
  try {
262
- if (data.constructor?.name === 'BinaryInput') {
262
+ // We use .includes() instead of === because constructor.name can be 'BinaryInput$1', 'FormData$1', etc.
263
+ // This happens when the same class is loaded in different module contexts (bundling, HMR, circular deps)
264
+ if (data.constructor?.name.includes('BinaryInput')) {
263
265
  const jsonData = await data.getJsonData(candidate);
264
266
  dataForDebug = `[BinaryInput size=${jsonData?.size}]`;
265
267
  } else if (isBuffer(data)) {
266
268
  dataForDebug = `[Buffer size=${data.byteLength}]`;
267
- } else if (data.constructor?.name === 'FormData') {
269
+ } else if (data.constructor?.name.includes('FormData')) {
268
270
  dataForDebug = `[FormData]`;
269
271
  } else if (isBase64(data) || isBase64DataUrl(data)) {
270
272
  dataForDebug = `[Base64 size=${getBase64FileSize(data)}]`;
@@ -1,295 +0,0 @@
1
- import { IAgent as Agent } from '@sre/types/Agent.types';
2
- import { Component } from './Component.class';
3
- import Joi from 'joi';
4
- import { validateCharacterSet } from '@sre/utils/validation.utils';
5
- import { TemplateString } from '@sre/helpers/TemplateString.helper';
6
- import { isUrl, detectURLSourceType } from '../utils';
7
- import { SmythFS } from '@sre/IO/Storage.service/SmythFS.class';
8
- import { ConnectorService } from '@sre/Core/ConnectorsService';
9
-
10
- import { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';
11
- import { TEmbeddings } from '@sre/IO/VectorDB.service/embed/BaseEmbedding';
12
- import { EmbeddingsFactory, SupportedModels } from '@sre/IO/VectorDB.service/embed';
13
- import { getLLMCredentials } from '@sre/LLMManager/LLM.service/LLMCredentials.helper';
14
-
15
- export class DataSourceIndexer extends Component {
16
- private MAX_ALLOWED_URLS_PER_INPUT = 20;
17
- protected configSchema = Joi.object({
18
- namespace: Joi.string().max(50).allow(''),
19
- id: Joi.string().custom(validateCharacterSet, 'id custom validation').allow('').label('source identifier'),
20
- name: Joi.string().max(50).allow('').label('label'),
21
- metadata: Joi.string().allow(null).allow('').max(10000).label('metadata'),
22
- chunkSize: Joi.number().optional(),
23
- chunkOverlap: Joi.number().optional(),
24
- version: Joi.string().valid('v1', 'v2').default('v1'),
25
- });
26
- constructor() {
27
- super();
28
- }
29
- init() {}
30
- async process(input, config, agent: Agent) {
31
- await super.process(input, config, agent);
32
-
33
- let response: any = null;
34
- if (!config.data.version || config.data.version === 'v1') {
35
- response = await this.processV1(input, config, agent);
36
- } else if (config.data.version === 'v2') {
37
- response = await this.processV2(input, config, agent);
38
- }
39
-
40
- return response;
41
- }
42
-
43
- private async processV1(input, config, agent: Agent) {
44
- const teamId = agent.teamId;
45
- const agentId = agent.id;
46
- let debugOutput = agent.agentRuntime?.debug ? '== Source Indexer Log ==\n' : null;
47
-
48
- try {
49
- const _config = {
50
- ...config.data,
51
- name: TemplateString(config.data.name).parse(input).result,
52
- id: TemplateString(config.data.id).parse(input).result,
53
- metadata: TemplateString(config.data.metadata).parse(input).result,
54
- };
55
-
56
- const outputs = {};
57
- for (let con of config.outputs) {
58
- if (con.default) continue;
59
- outputs[con.name] = con?.description ? `<${con?.description}>` : '';
60
- }
61
-
62
- const namespaceId = _config.namespace.split('_').slice(1).join('_') || _config.namespace;
63
- debugOutput += `[Selected namespace id] \n${namespaceId}\n\n`;
64
-
65
- const vectorDbConnector =
66
- // (await vectorDBHelper.getTeamConnector(teamId)) ||
67
- ConnectorService.getVectorDBConnector();
68
- const nsExists = await vectorDbConnector.requester(AccessCandidate.team(teamId)).namespaceExists(namespaceId);
69
-
70
- if (!nsExists) {
71
- const newNs = await vectorDbConnector.requester(AccessCandidate.team(teamId)).createNamespace(namespaceId);
72
- debugOutput += `[Created namespace] \n${newNs}\n\n`;
73
- }
74
-
75
- const inputSchema = this.validateInput(input);
76
- if (inputSchema.error) {
77
- throw new Error(`Input validation error: ${inputSchema.error}\n EXITING...`);
78
- }
79
-
80
- const providedId = _config.id;
81
- // const isAutoId = _config.isAutoId;
82
- const idRegex = /^[a-zA-Z0-9\-\_\.]+$/;
83
-
84
- if (!providedId) {
85
- // Assign a new ID if it's set to auto-generate or not provided
86
- // _config.id = crypto.randomBytes(16).toString('hex');
87
- throw new Error(`Id is required`);
88
- } else if (!idRegex.test(providedId)) {
89
- // Validate the provided ID if it's not auto-generated
90
- throw new Error(`Invalid id. Accepted characters: 'a-z', 'A-Z', '0-9', '-', '_', '.'`);
91
- }
92
-
93
- let indexRes: any = null;
94
- let parsedUrlArray: string[] | null = null;
95
- const dsId = DataSourceIndexer.genDsId(providedId, teamId, namespaceId);
96
-
97
- if (isUrl(inputSchema.value.Source)) {
98
- debugOutput += `STEP: Parsing input as url\n\n`;
99
- throw new Error('URLs are not supported yet');
100
- } else {
101
- debugOutput += `STEP: Parsing input as text\n\n`;
102
- indexRes = await this.addDSFromText({
103
- teamId,
104
- namespaceId: namespaceId,
105
- text: inputSchema.value.Source,
106
- name: _config.name || 'Untitled',
107
- metadata: _config.metadata || null,
108
- sourceId: dsId,
109
- });
110
- }
111
-
112
- debugOutput += `Created datasource successfully\n\n`;
113
-
114
- return {
115
- _debug: debugOutput,
116
- Success: {
117
- result: indexRes?.data?.dataSource || true,
118
- id: _config.id,
119
- },
120
- // _error,
121
- };
122
- } catch (err: any) {
123
- debugOutput += `Error: ${err?.message || "Couldn't index data source"}\n\n`;
124
- return {
125
- _debug: debugOutput,
126
- _error: err?.message || "Couldn't index data source",
127
- };
128
- }
129
- }
130
-
131
- private async processV2(input, config, agent: Agent) {
132
- const teamId = agent.teamId;
133
- const agentId = agent.id;
134
- let debugOutput = agent.agentRuntime?.debug ? '== Source Indexer Log ==\n' : null;
135
-
136
- try {
137
- const _config = {
138
- ...config.data,
139
- name: TemplateString(config.data.name).parse(input).result,
140
- id: TemplateString(config.data.id).parse(input).result,
141
- metadata: TemplateString(config.data.metadata).parse(input).result,
142
- };
143
-
144
- const outputs = {};
145
- for (let con of config.outputs) {
146
- if (con.default) continue;
147
- outputs[con.name] = con?.description ? `<${con?.description}>` : '';
148
- }
149
-
150
- // we try to get the namespace without the prefix teamId, if not exist, we use the full namespace id
151
- const namespaceLabel = _config.namespace.split('_').slice(1).join('_') || _config.namespace;
152
- const namespaceId = _config.namespace;
153
- debugOutput += `[Selected namespace] \n${namespaceLabel}\n\n`;
154
-
155
- // resolve the ns record, if not exist, throw an error (new in v2)
156
- // then we also need to resolve the credentials
157
- const nkvConnector = ConnectorService.getNKVConnector();
158
- const nkvClient = nkvConnector.requester(AccessCandidate.team(teamId));
159
- const rawNsRecord = await nkvClient.get(`vectorDB:namespaces`, namespaceId);
160
-
161
- if (!rawNsRecord) {
162
- return {
163
- _debug: debugOutput,
164
- _error: `Namespace ${namespaceLabel} does not exist`,
165
- };
166
- }
167
-
168
- // const { credentialId, embeddings: embeddingsOptions } = JSON.parse(rawNsRecord.toString());
169
- const namespaceRecord = JSON.parse(rawNsRecord.toString());
170
- const accountConnector = ConnectorService.getAccountConnector();
171
- const accountClient = accountConnector.requester(AccessCandidate.team(teamId));
172
- const rawCredRecord = await accountClient.getTeamSetting(namespaceRecord.credentialId, 'vector_db_creds');
173
- if (!rawCredRecord) {
174
- throw new Error(`Credential ${namespaceRecord.credentialId} does not exist`);
175
- }
176
- const credRecord = JSON.parse(rawCredRecord);
177
- await Promise.all(
178
- Object.keys(credRecord.credentials).map(async (key) => {
179
- if (typeof credRecord.credentials[key] !== 'string') return;
180
- credRecord.credentials[key] = await TemplateString(credRecord.credentials[key]).parseTeamKeysAsync(teamId).asyncResult;
181
- })
182
- );
183
-
184
- const vecDbConnector = ConnectorService.getVectorDBConnector(credRecord.provider).instance({
185
- credentials: credRecord.credentials,
186
- embeddings: await this.transformEmbedding(namespaceRecord.embeddings, config.data, teamId),
187
- });
188
- const vecDbClient = vecDbConnector.requester(AccessCandidate.team(teamId));
189
-
190
- const inputSchema = this.validateInput(input);
191
- if (inputSchema.error) {
192
- throw new Error(`Input validation error: ${inputSchema.error}\n EXITING...`);
193
- }
194
-
195
- const providedId = _config.id;
196
- // const isAutoId = _config.isAutoId;
197
- const idRegex = /^[a-zA-Z0-9\-\_\.]+$/;
198
-
199
- if (!providedId) {
200
- // Assign a new ID if it's set to auto-generate or not provided
201
- // _config.id = crypto.randomBytes(16).toString('hex');
202
- throw new Error(`Id is required`);
203
- } else if (!idRegex.test(providedId)) {
204
- // Validate the provided ID if it's not auto-generated
205
- throw new Error(`Invalid id. Accepted characters: 'a-z', 'A-Z', '0-9', '-', '_', '.'`);
206
- }
207
-
208
- const dsId = DataSourceIndexer.genDsId(providedId, teamId, namespaceLabel);
209
-
210
- debugOutput += `STEP: Parsing input as text\n\n`;
211
-
212
- const response = await vecDbClient.createDatasource(namespaceLabel, {
213
- text: inputSchema.value.Source,
214
- metadata: _config.metadata || null,
215
- id: dsId,
216
- label: _config.name || 'Untitled',
217
- });
218
-
219
- debugOutput += `Created datasource successfully\n\n`;
220
-
221
- return {
222
- _debug: debugOutput,
223
- Success: {
224
- result: response || true,
225
- id: _config.id,
226
- },
227
- // _error,
228
- };
229
- } catch (err: any) {
230
- debugOutput += `Error: ${err?.message || "Couldn't index data source"}\n\n`;
231
- return {
232
- _debug: debugOutput,
233
- _error: err?.message || "Couldn't index data source",
234
- };
235
- }
236
- }
237
-
238
- private async transformEmbedding(embedding: { dimensions: string; modelId: string }, data: any, teamId: string): Promise<TEmbeddings> {
239
- // we need to take this and return a proper TEmbeddings object
240
-
241
- const provider = EmbeddingsFactory.getProviderByModel(embedding.modelId as any);
242
-
243
- // based on the provider, we should be able to retreive the correct credentials
244
- const modelsProvider = ConnectorService.getModelsProviderConnector();
245
- const modelProviderCandidate = modelsProvider.requester(AccessCandidate.team(teamId));
246
- const modelInfo = await modelProviderCandidate.getModelInfo(embedding.modelId);
247
-
248
- const llmCreds = await getLLMCredentials(AccessCandidate.team(teamId), modelInfo);
249
-
250
- return {
251
- provider,
252
- model: embedding.modelId,
253
- credentials: llmCreds,
254
- params: {
255
- dimensions: parseInt(embedding.dimensions),
256
- chunkSize: data.chunkSize,
257
- },
258
- };
259
- }
260
-
261
- validateInput(input: any) {
262
- return Joi.object({
263
- Source: Joi.any().required(),
264
- })
265
- .unknown(true)
266
- .validate(input);
267
- }
268
-
269
- private async addDSFromText({ teamId, sourceId, namespaceId, text, name, metadata }) {
270
- let vectorDbConnector = ConnectorService.getVectorDBConnector();
271
- // const isOnCustomStorage = await vectorDBHelper.isNamespaceOnCustomStorage(teamId, namespaceId);
272
- // if (isOnCustomStorage) {
273
- // const customTeamConnector = await vectorDBHelper.getTeamConnector(teamId);
274
- // if (customTeamConnector) {
275
- // vectorDbConnector = customTeamConnector;
276
- // }
277
- // }
278
- const id = await vectorDbConnector.requester(AccessCandidate.team(teamId)).createDatasource(namespaceId, {
279
- text,
280
- metadata,
281
- id: sourceId,
282
- label: name,
283
- });
284
-
285
- return id;
286
- }
287
-
288
- public static genDsId(providedId: string, teamId: string, namespaceId: string) {
289
- return `${teamId}::${namespaceId}::${providedId}`;
290
- }
291
-
292
- private async addDSFromUrl({ teamId, namespaceId, dsId, type, url, name, metadata }) {
293
- throw new Error('URLs are not supported yet');
294
- }
295
- }