@smythos/sre 1.7.18 → 1.7.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +120 -82
- package/dist/index.js.map +1 -1
- package/dist/types/Components/DataSourceIndexer.class.d.ts +4 -12
- package/dist/types/Components/GenAILLM.class.d.ts +5 -5
- package/dist/types/Components/RAG/DataSourceCleaner.class.d.ts +37 -0
- package/dist/types/Components/RAG/DataSourceComponent.class.d.ts +30 -0
- package/dist/types/Components/RAG/DataSourceIndexer.class.d.ts +14 -0
- package/dist/types/Components/RAG/DataSourceLookup.class.d.ts +36 -0
- package/dist/types/Components/index.d.ts +3 -3
- package/dist/types/helpers/Conversation.helper.d.ts +3 -0
- package/dist/types/index.d.ts +3 -3
- package/dist/types/subsystems/IO/VectorDB.service/connectors/MilvusVectorDB.class.d.ts +1 -0
- package/dist/types/subsystems/IO/VectorDB.service/connectors/PineconeVectorDB.class.d.ts +11 -4
- package/dist/types/subsystems/IO/VectorDB.service/embed/index.d.ts +5 -0
- package/dist/types/subsystems/LLMManager/LLM.inference.d.ts +10 -3
- package/dist/types/subsystems/LLMManager/LLM.service/connectors/GoogleAI.class.d.ts +4 -2
- package/dist/types/subsystems/LLMManager/ModelsProvider.service/connectors/JSONModelsProvider.class.d.ts +35 -0
- package/dist/types/subsystems/Security/Account.service/AccountConnector.d.ts +2 -2
- package/dist/types/subsystems/Security/ManagedVault.service/connectors/SecretManagerManagedVault.d.ts +10 -0
- package/dist/types/subsystems/Security/Vault.service/connectors/SecretsManager.class.d.ts +6 -2
- package/dist/types/types/LLM.types.d.ts +2 -0
- package/dist/types/types/VectorDB.types.d.ts +4 -0
- package/dist/types/utils/array.utils.d.ts +4 -0
- package/dist/types/utils/string.utils.d.ts +1 -0
- package/package.json +3 -3
- package/src/Components/APIEndpoint.class.ts +1 -6
- package/src/Components/Component.class.ts +14 -1
- package/src/Components/DataSourceIndexer.class.ts +148 -34
- package/src/Components/GenAILLM.class.ts +21 -11
- package/src/Components/RAG/DataSourceCleaner.class.ts +178 -0
- package/src/Components/RAG/DataSourceComponent.class.ts +111 -0
- package/src/Components/RAG/DataSourceIndexer.class.ts +254 -0
- package/src/Components/{DataSourceLookup.class.ts → RAG/DataSourceLookup.class.ts} +92 -3
- package/src/Components/ServerlessCode.class.ts +1 -4
- package/src/Components/index.ts +3 -3
- package/src/helpers/AWSLambdaCode.helper.ts +40 -45
- package/src/helpers/Conversation.helper.ts +14 -10
- package/src/helpers/S3Cache.helper.ts +2 -1
- package/src/index.ts +212 -212
- package/src/index.ts.bak +212 -212
- package/src/subsystems/IO/NKV.service/connectors/NKVRedis.class.ts +3 -1
- package/src/subsystems/IO/VectorDB.service/connectors/MilvusVectorDB.class.ts +145 -19
- package/src/subsystems/IO/VectorDB.service/connectors/PineconeVectorDB.class.ts +56 -22
- package/src/subsystems/IO/VectorDB.service/embed/GoogleEmbedding.ts +1 -0
- package/src/subsystems/IO/VectorDB.service/embed/OpenAIEmbedding.ts +2 -1
- package/src/subsystems/IO/VectorDB.service/embed/index.ts +18 -0
- package/src/subsystems/LLMManager/LLM.inference.ts +63 -47
- package/src/subsystems/LLMManager/LLM.service/connectors/Anthropic.class.ts +35 -10
- package/src/subsystems/LLMManager/LLM.service/connectors/Bedrock.class.ts +12 -4
- package/src/subsystems/LLMManager/LLM.service/connectors/Echo.class.ts +4 -4
- package/src/subsystems/LLMManager/LLM.service/connectors/GoogleAI.class.ts +105 -23
- package/src/subsystems/LLMManager/LLM.service/connectors/Groq.class.ts +17 -5
- package/src/subsystems/LLMManager/LLM.service/connectors/Ollama.class.ts +18 -3
- package/src/subsystems/LLMManager/LLM.service/connectors/Perplexity.class.ts +14 -5
- package/src/subsystems/LLMManager/LLM.service/connectors/VertexAI.class.ts +6 -4
- package/src/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/ChatCompletionsApiInterface.ts +5 -5
- package/src/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/ResponsesApiInterface.ts +8 -3
- package/src/subsystems/LLMManager/LLM.service/connectors/xAI.class.ts +9 -8
- package/src/subsystems/LLMManager/ModelsProvider.service/connectors/JSONModelsProvider.class.ts +126 -28
- package/src/subsystems/ObservabilityManager/Telemetry.service/connectors/OTel/OTel.class.ts +38 -6
- package/src/subsystems/Security/Account.service/AccountConnector.ts +3 -3
- package/src/subsystems/Security/ManagedVault.service/connectors/SecretManagerManagedVault.ts +111 -48
- package/src/subsystems/Security/Vault.service/connectors/SecretsManager.class.ts +41 -66
- package/src/types/LLM.types.ts +5 -0
- package/src/types/VectorDB.types.ts +4 -0
- package/src/utils/array.utils.ts +11 -0
- package/src/utils/base64.utils.ts +1 -1
- package/src/utils/string.utils.ts +3 -192
- package/src/Components/DataSourceCleaner.class.ts +0 -92
package/src/subsystems/LLMManager/ModelsProvider.service/connectors/JSONModelsProvider.class.ts
CHANGED
|
@@ -16,7 +16,7 @@ import fsSync from 'fs';
|
|
|
16
16
|
import path from 'path';
|
|
17
17
|
import { findSmythPath } from '@sre/helpers/Sysconfig.helper';
|
|
18
18
|
|
|
19
|
-
const
|
|
19
|
+
const logger = Logger('SmythModelsProvider');
|
|
20
20
|
|
|
21
21
|
type SmythModelsProviderConfig = {
|
|
22
22
|
/**
|
|
@@ -58,7 +58,7 @@ export class JSONModelsProvider extends ModelsProviderConnector {
|
|
|
58
58
|
this._settings.mode = 'merge'; //Force merge mode if using models from .smyth folder
|
|
59
59
|
this.initDirWatcher(modelsFolder); //this.started will be set to true when the watcher is ready
|
|
60
60
|
} else {
|
|
61
|
-
|
|
61
|
+
logger.warn('No models folder found ... falling back to built-in models only');
|
|
62
62
|
this.started = true;
|
|
63
63
|
}
|
|
64
64
|
}
|
|
@@ -71,7 +71,7 @@ export class JSONModelsProvider extends ModelsProviderConnector {
|
|
|
71
71
|
const _modelsFolder = findSmythPath('models');
|
|
72
72
|
|
|
73
73
|
if (fsSync.existsSync(_modelsFolder)) {
|
|
74
|
-
|
|
74
|
+
logger.warn('Using default models folder : ', _modelsFolder);
|
|
75
75
|
return _modelsFolder;
|
|
76
76
|
}
|
|
77
77
|
|
|
@@ -106,7 +106,7 @@ export class JSONModelsProvider extends ModelsProviderConnector {
|
|
|
106
106
|
|
|
107
107
|
private async reindexModels(dir: string) {
|
|
108
108
|
try {
|
|
109
|
-
|
|
109
|
+
logger.debug(`Reindexing models from directory: ${dir}`);
|
|
110
110
|
|
|
111
111
|
// Scan directory for models and get them as an object
|
|
112
112
|
const scannedModels = await this.scanDirectoryForModels(dir);
|
|
@@ -121,9 +121,9 @@ export class JSONModelsProvider extends ModelsProviderConnector {
|
|
|
121
121
|
|
|
122
122
|
JSONModelsProvider.localCache.clear();
|
|
123
123
|
|
|
124
|
-
|
|
124
|
+
logger.debug(`Successfully reindexed models. Total models: ${Object.keys(this.models).length}`);
|
|
125
125
|
} catch (error) {
|
|
126
|
-
|
|
126
|
+
logger.error(`Error reindexing models from directory "${dir}":`, error);
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
129
|
|
|
@@ -141,15 +141,21 @@ export class JSONModelsProvider extends ModelsProviderConnector {
|
|
|
141
141
|
const subDirModels = await this.scanDirectoryForModels(fullPath);
|
|
142
142
|
Object.assign(scannedModels, subDirModels);
|
|
143
143
|
} else if (entry.isFile() && entry.name.endsWith('.json')) {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
144
|
+
try {
|
|
145
|
+
// Process JSON files and merge results
|
|
146
|
+
|
|
147
|
+
const fileContent = await fs.readFile(fullPath, 'utf-8');
|
|
148
|
+
const modelData = JSON.parse(fileContent);
|
|
149
|
+
const validModels = await this.getValidModels(modelData);
|
|
150
|
+
Object.assign(scannedModels, validModels);
|
|
151
|
+
} catch (error) {
|
|
152
|
+
console.error(`Error parsing model data from file "${fullPath}"`);
|
|
153
|
+
logger.warn(`Error parsing model data from file "${fullPath}":`, error.message);
|
|
154
|
+
}
|
|
149
155
|
}
|
|
150
156
|
}
|
|
151
157
|
} catch (error) {
|
|
152
|
-
|
|
158
|
+
logger.warn(`Error scanning directory "${dir}":`, error);
|
|
153
159
|
}
|
|
154
160
|
|
|
155
161
|
return scannedModels;
|
|
@@ -164,9 +170,9 @@ export class JSONModelsProvider extends ModelsProviderConnector {
|
|
|
164
170
|
// Single model case
|
|
165
171
|
if (this.isValidSingleModel(modelData)) {
|
|
166
172
|
validModels[modelData.modelId] = modelData as TLLMModel;
|
|
167
|
-
|
|
173
|
+
logger.debug(`Loaded model: ${modelData.modelId}`);
|
|
168
174
|
} else {
|
|
169
|
-
|
|
175
|
+
logger.warn(`Invalid model format`, modelData);
|
|
170
176
|
}
|
|
171
177
|
} else if (typeof modelData === 'object' && !Array.isArray(modelData)) {
|
|
172
178
|
// Object of models case
|
|
@@ -178,19 +184,19 @@ export class JSONModelsProvider extends ModelsProviderConnector {
|
|
|
178
184
|
//console.debug(`Loaded model: ${modelId}`);
|
|
179
185
|
models += `${modelId} `;
|
|
180
186
|
} else {
|
|
181
|
-
|
|
187
|
+
logger.warn(`Invalid model format for model "${modelId}"`);
|
|
182
188
|
}
|
|
183
189
|
} catch (error) {
|
|
184
|
-
|
|
190
|
+
logger.warn(`Error processing model "${modelId}":`, error);
|
|
185
191
|
// Continue processing other models instead of failing the whole file
|
|
186
192
|
}
|
|
187
193
|
}
|
|
188
|
-
|
|
194
|
+
logger.debug(`Loaded models: ${models}`);
|
|
189
195
|
} else {
|
|
190
|
-
|
|
196
|
+
logger.warn(`Invalid format (not a model or object of models)`);
|
|
191
197
|
}
|
|
192
198
|
} catch (error) {
|
|
193
|
-
|
|
199
|
+
logger.warn(`Error loading model:`, error);
|
|
194
200
|
}
|
|
195
201
|
|
|
196
202
|
return validModels;
|
|
@@ -208,11 +214,98 @@ export class JSONModelsProvider extends ModelsProviderConnector {
|
|
|
208
214
|
return this.isValidSingleModel(data);
|
|
209
215
|
}
|
|
210
216
|
|
|
217
|
+
/**
|
|
218
|
+
* Determines whether a file path should be ignored by the directory watcher.
|
|
219
|
+
*
|
|
220
|
+
* This method implements a sophisticated filtering strategy for dot-segment paths
|
|
221
|
+
* (paths containing directories that start with a dot, like .git, .env, .cache).
|
|
222
|
+
*
|
|
223
|
+
* **Filtering Strategy:**
|
|
224
|
+
* 1. Paths WITHOUT dot segments: Never ignored
|
|
225
|
+
* 2. Paths WITH dot segments:
|
|
226
|
+
* - If SMYTH_PATH is not configured: All ignored
|
|
227
|
+
* - If SMYTH_PATH is configured:
|
|
228
|
+
* - Allow the watched directory even if SMYTH_PATH contains dot-segments
|
|
229
|
+
* (e.g., /home/user/.smyth/models/OpenAI/default.json is allowed)
|
|
230
|
+
* - Ignore dot-segments INSIDE the models directory
|
|
231
|
+
* (e.g., /home/user/.smyth/models/.hidden/model.json is ignored)
|
|
232
|
+
* - Paths outside watched directory: Ignored
|
|
233
|
+
*
|
|
234
|
+
* @param filePath - The file path to check
|
|
235
|
+
* @param watchedDir - The absolute path of the directory being watched (models folder)
|
|
236
|
+
* @param smythPath - The resolved SMYTH_PATH, or null if not configured
|
|
237
|
+
* @returns true if the path should be ignored, false if it should be watched
|
|
238
|
+
*
|
|
239
|
+
* @example
|
|
240
|
+
* ```typescript
|
|
241
|
+
* // Path without dot-segment (allowed)
|
|
242
|
+
* shouldIgnorePath('/models/OpenAI/default.json', '/models', '/home/.smyth') // => false
|
|
243
|
+
*
|
|
244
|
+
* // Dot-segment inside models directory (ignored)
|
|
245
|
+
* shouldIgnorePath('/models/.git/config', '/models', '/home/.smyth') // => true
|
|
246
|
+
*
|
|
247
|
+
* // Dot-segment in parent path only (allowed)
|
|
248
|
+
* shouldIgnorePath('/home/.smyth/models/OpenAI/default.json', '/home/.smyth/models', '/home/.smyth') // => false
|
|
249
|
+
* ```
|
|
250
|
+
*/
|
|
251
|
+
private shouldIgnorePath(filePath: string, watchedDir: string, smythPath: string | null): boolean {
|
|
252
|
+
// Check if the file path contains a dot-segment (e.g., /.git/, /.env/, /.cache/)
|
|
253
|
+
// Regex explanation: [\\/]\. matches a path separator (/ or \) followed by a dot
|
|
254
|
+
const hasDotSegment = /[\\/]\./.test(filePath);
|
|
255
|
+
|
|
256
|
+
// CASE 1: If there is NO dot-segment at all, we never ignore this path
|
|
257
|
+
// Examples: /models/OpenAI/default.json, /models/Anthropic/claude.json
|
|
258
|
+
if (!hasDotSegment) {
|
|
259
|
+
return false;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// CASE 2: If there IS a dot-segment and SMYTH_PATH is not configured,
|
|
263
|
+
// we ignore all such paths to prevent watching system/hidden files
|
|
264
|
+
// Examples: /.git/config, /node_modules/.cache/file.json
|
|
265
|
+
if (hasDotSegment && !smythPath) {
|
|
266
|
+
return true;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Resolve the file path to an absolute path for accurate comparison
|
|
270
|
+
// This ensures we can reliably compare against the watched directory path
|
|
271
|
+
const resolvedPath = path.resolve(filePath);
|
|
272
|
+
|
|
273
|
+
// Check if the resolved path is inside the watched directory (models folder)
|
|
274
|
+
// This handles two cases:
|
|
275
|
+
// 1. The path exactly matches the watched directory
|
|
276
|
+
// 2. The path is a child of the watched directory (starts with watchedDir + separator)
|
|
277
|
+
const isInsideWatchedDir = resolvedPath === watchedDir || resolvedPath.startsWith(watchedDir + path.sep);
|
|
278
|
+
|
|
279
|
+
// CASE 3: If the path is outside the watched directory, ignore it
|
|
280
|
+
// This prevents watching unrelated files that happen to have dot-segments
|
|
281
|
+
if (!isInsideWatchedDir) {
|
|
282
|
+
return true;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// CASE 4: Path is inside the watched directory
|
|
286
|
+
// Now we need to determine if the dot-segment is in the models directory itself
|
|
287
|
+
// or if it is part of the parent path (e.g., SMYTH_PATH containing .smyth)
|
|
288
|
+
|
|
289
|
+
// Get the relative path from the watched directory to determine where the dot-segment is
|
|
290
|
+
const relativePath = path.relative(watchedDir, resolvedPath);
|
|
291
|
+
|
|
292
|
+
// Check if the dot-segment appears in the relative portion (inside models directory)
|
|
293
|
+
// Regex explanation: (^|[\\/])\. matches a dot at the start OR after a path separator
|
|
294
|
+
// Examples that match: '.git/config', 'subdir/.hidden/file.json'
|
|
295
|
+
const hasDotSegmentInsideWatchedDir = /(^|[\\/])\./.test(relativePath);
|
|
296
|
+
|
|
297
|
+
// FINAL DECISION:
|
|
298
|
+
// - If dot-segment is INSIDE the models directory (e.g., models/.git/config), IGNORE it (return true)
|
|
299
|
+
// - If dot-segment is OUTSIDE the models directory (e.g., /home/user/.smyth/models/OpenAI/default.json), ALLOW it (return false)
|
|
300
|
+
// This allows SMYTH_PATH to contain dot-segments while preventing dot-segments within the models folder
|
|
301
|
+
return hasDotSegmentInsideWatchedDir;
|
|
302
|
+
}
|
|
303
|
+
|
|
211
304
|
private initDirWatcher(dir) {
|
|
212
305
|
const stats = fsSync.statSync(dir);
|
|
213
306
|
|
|
214
307
|
if (!stats.isDirectory() && !stats.isFile()) {
|
|
215
|
-
|
|
308
|
+
logger.warn(`Path "${dir}" is neither a file nor a directory ... skipping models watcher and falling back to built-in models only`);
|
|
216
309
|
this.started = true;
|
|
217
310
|
return;
|
|
218
311
|
}
|
|
@@ -230,17 +323,18 @@ export class JSONModelsProvider extends ModelsProviderConnector {
|
|
|
230
323
|
if (this._settings?.mode === 'merge') this.models = { ...this.models, ...modelData };
|
|
231
324
|
else this.models = modelData;
|
|
232
325
|
} catch (error) {
|
|
233
|
-
console.error(`Error parsing model data from file "${dir}"
|
|
326
|
+
console.error(`Error parsing model data from file "${dir}":`);
|
|
327
|
+
logger.warn(`Error parsing model data from file "${dir}":`, error.message);
|
|
234
328
|
}
|
|
235
329
|
this.started = true;
|
|
236
330
|
return;
|
|
237
331
|
}
|
|
238
332
|
|
|
239
|
-
|
|
333
|
+
logger.warn(`Path "${dir}" is neither a file nor a directory`);
|
|
240
334
|
return;
|
|
241
335
|
}
|
|
242
336
|
} catch (error) {
|
|
243
|
-
|
|
337
|
+
logger.warn(`Path "${dir}" does not exist or cannot be accessed:`, error.message);
|
|
244
338
|
return;
|
|
245
339
|
}
|
|
246
340
|
|
|
@@ -250,8 +344,12 @@ export class JSONModelsProvider extends ModelsProviderConnector {
|
|
|
250
344
|
maxWait: 5000,
|
|
251
345
|
});
|
|
252
346
|
|
|
347
|
+
const smythPath = process.env.SMYTH_PATH ? path.resolve(process.env.SMYTH_PATH) : null;
|
|
348
|
+
const watchedDir = path.resolve(dir);
|
|
349
|
+
|
|
253
350
|
const watcher = chokidar.watch(dir, {
|
|
254
|
-
|
|
351
|
+
// Use the extracted method for path filtering
|
|
352
|
+
ignored: (filePath: string) => this.shouldIgnorePath(filePath, watchedDir, smythPath),
|
|
255
353
|
persistent: true,
|
|
256
354
|
ignoreInitial: true, // Don't fire events for files that already exist
|
|
257
355
|
awaitWriteFinish: {
|
|
@@ -262,19 +360,19 @@ export class JSONModelsProvider extends ModelsProviderConnector {
|
|
|
262
360
|
|
|
263
361
|
watcher
|
|
264
362
|
.on('add', (path) => {
|
|
265
|
-
|
|
363
|
+
logger.debug(`File ${path} has been added`);
|
|
266
364
|
debouncedReindex();
|
|
267
365
|
})
|
|
268
366
|
.on('change', (path) => {
|
|
269
|
-
|
|
367
|
+
logger.debug(`File ${path} has been changed`);
|
|
270
368
|
debouncedReindex();
|
|
271
369
|
})
|
|
272
370
|
.on('unlink', (path) => {
|
|
273
|
-
|
|
371
|
+
logger.debug(`File ${path} has been removed`);
|
|
274
372
|
debouncedReindex();
|
|
275
373
|
})
|
|
276
374
|
.on('ready', async () => {
|
|
277
|
-
|
|
375
|
+
logger.debug(`Watcher ready. Performing initial scan of ${dir}`);
|
|
278
376
|
// Do initial scan once when watcher is ready
|
|
279
377
|
await this.reindexModels(dir);
|
|
280
378
|
this.started = true;
|
|
@@ -20,8 +20,9 @@ import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http';
|
|
|
20
20
|
import { IAgent } from '@sre/types/Agent.types';
|
|
21
21
|
import { Conversation } from '@sre/helpers/Conversation.helper';
|
|
22
22
|
import { TLLMEvent } from '@sre/types/LLM.types';
|
|
23
|
+
import { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';
|
|
23
24
|
|
|
24
|
-
const outputLogger = Logger('
|
|
25
|
+
const outputLogger = Logger('OTel');
|
|
25
26
|
|
|
26
27
|
export type OTelLogConfig = {
|
|
27
28
|
endpoint: string;
|
|
@@ -50,7 +51,7 @@ export type OTelLogConfig = {
|
|
|
50
51
|
*/
|
|
51
52
|
redactFields?: string[];
|
|
52
53
|
};
|
|
53
|
-
|
|
54
|
+
const OTEL_DEBUG_LOGS = true;
|
|
54
55
|
export class OTel extends TelemetryConnector {
|
|
55
56
|
public name: string = 'OTel';
|
|
56
57
|
public id: string;
|
|
@@ -208,6 +209,8 @@ export class OTel extends TelemetryConnector {
|
|
|
208
209
|
|
|
209
210
|
const createToolInfoHandler = function (hookContext) {
|
|
210
211
|
return function (toolInfo: any) {
|
|
212
|
+
const accessCandidate = AccessCandidate.agent(hookContext?.agentId);
|
|
213
|
+
if (OTEL_DEBUG_LOGS) outputLogger.debug('createToolInfoHandler started', accessCandidate);
|
|
211
214
|
if (!hookContext.curLLMGenSpan || !hookContext.convSpan) return;
|
|
212
215
|
|
|
213
216
|
const modelId = toolInfo.model;
|
|
@@ -238,6 +241,7 @@ export class OTel extends TelemetryConnector {
|
|
|
238
241
|
|
|
239
242
|
hookContext.curLLMGenSpan.end();
|
|
240
243
|
delete hookContext.curLLMGenSpan;
|
|
244
|
+
if (OTEL_DEBUG_LOGS) outputLogger.debug('createToolInfoHandler completed', accessCandidate);
|
|
241
245
|
};
|
|
242
246
|
};
|
|
243
247
|
|
|
@@ -245,6 +249,8 @@ export class OTel extends TelemetryConnector {
|
|
|
245
249
|
return function (data: any, reqInfo: any) {
|
|
246
250
|
if (!hookContext.convSpan) return;
|
|
247
251
|
if (hookContext.curLLMGenSpan) return;
|
|
252
|
+
const accessCandidate = AccessCandidate.agent(hookContext?.agentId);
|
|
253
|
+
if (OTEL_DEBUG_LOGS) outputLogger.debug('createDataHandler started', reqInfo?.requestId, accessCandidate);
|
|
248
254
|
|
|
249
255
|
const modelId = reqInfo.model;
|
|
250
256
|
const contextWindow = reqInfo.contextWindow;
|
|
@@ -285,13 +291,15 @@ export class OTel extends TelemetryConnector {
|
|
|
285
291
|
'context.preview': JSON.stringify(lastContext).substring(0, 200),
|
|
286
292
|
});
|
|
287
293
|
hookContext.curLLMGenSpan = llmGenSpan;
|
|
294
|
+
if (OTEL_DEBUG_LOGS) outputLogger.debug('createDataHandler completed', reqInfo?.requestId, accessCandidate);
|
|
288
295
|
};
|
|
289
296
|
};
|
|
290
297
|
|
|
291
298
|
const createRequestedHandler = function (hookContext) {
|
|
292
299
|
return function (reqInfo: any) {
|
|
293
300
|
if (!hookContext.convSpan) return;
|
|
294
|
-
|
|
301
|
+
const accessCandidate = AccessCandidate.agent(hookContext?.agentId);
|
|
302
|
+
if (OTEL_DEBUG_LOGS) outputLogger.debug('createRequestedHandler started', reqInfo?.requestId, accessCandidate);
|
|
295
303
|
if (!hookContext.latencySpans) hookContext.latencySpans = {};
|
|
296
304
|
const contextWindow = reqInfo.contextWindow;
|
|
297
305
|
|
|
@@ -317,6 +325,7 @@ export class OTel extends TelemetryConnector {
|
|
|
317
325
|
'context.preview': JSON.stringify(lastContext).substring(0, 200),
|
|
318
326
|
});
|
|
319
327
|
hookContext.latencySpans[reqInfo.requestId] = llmGenLatencySpan;
|
|
328
|
+
if (OTEL_DEBUG_LOGS) outputLogger.debug('createRequestedHandler completed', reqInfo?.requestId, accessCandidate);
|
|
320
329
|
};
|
|
321
330
|
};
|
|
322
331
|
HookService.register(
|
|
@@ -332,26 +341,35 @@ export class OTel extends TelemetryConnector {
|
|
|
332
341
|
|
|
333
342
|
return;
|
|
334
343
|
}
|
|
344
|
+
const accessCandidate = AccessCandidate.agent(agentId);
|
|
345
|
+
if (OTEL_DEBUG_LOGS) outputLogger.debug('Conversation.streamPrompt started', { processId, message }, accessCandidate);
|
|
335
346
|
|
|
336
347
|
const modelId = typeof conversation?.model === 'string' ? conversation?.model : conversation?.model?.modelId;
|
|
337
348
|
|
|
338
349
|
const convSpan = tracer.startSpan('Agent.Conv', {
|
|
339
350
|
attributes: {
|
|
351
|
+
// OTel standard attributes
|
|
352
|
+
'gen_ai.operation.name': 'chat',
|
|
353
|
+
'gen_ai.provider.name': conversation?.llmInference?.llmProviderName || 'unknown',
|
|
354
|
+
'gen_ai.conversation.id': processId,
|
|
355
|
+
'gen_ai.request.model': modelId || 'unknown',
|
|
356
|
+
////////////////////////////////
|
|
340
357
|
'agent.id': agentId,
|
|
341
358
|
'conv.id': processId,
|
|
342
359
|
'llm.model': modelId || 'unknown',
|
|
343
360
|
},
|
|
344
361
|
});
|
|
345
362
|
hookContext.convSpan = convSpan;
|
|
363
|
+
hookContext.agentId = agentId;
|
|
364
|
+
hookContext.processId = processId;
|
|
346
365
|
|
|
347
366
|
hookContext.dataHandler = createDataHandler(hookContext);
|
|
348
367
|
conversation.on(TLLMEvent.Data, hookContext.dataHandler);
|
|
368
|
+
|
|
349
369
|
hookContext.requestedHandler = createRequestedHandler(hookContext);
|
|
350
370
|
conversation.on(TLLMEvent.Requested, hookContext.requestedHandler);
|
|
351
|
-
hookContext.agentId = agentId;
|
|
352
|
-
hookContext.processId = processId;
|
|
353
|
-
hookContext.toolInfoHandler = createToolInfoHandler(hookContext);
|
|
354
371
|
|
|
372
|
+
hookContext.toolInfoHandler = createToolInfoHandler(hookContext);
|
|
355
373
|
conversation.on(TLLMEvent.ToolInfo, hookContext.toolInfoHandler);
|
|
356
374
|
|
|
357
375
|
// Add start event
|
|
@@ -403,6 +421,9 @@ export class OTel extends TelemetryConnector {
|
|
|
403
421
|
const ctx = OTelContextRegistry.get(agentId, processId);
|
|
404
422
|
if (!ctx) return;
|
|
405
423
|
|
|
424
|
+
const accessCandidate = AccessCandidate.agent(agentId);
|
|
425
|
+
if (OTEL_DEBUG_LOGS) outputLogger.debug('Conversation.streamPrompt completed', { processId }, accessCandidate);
|
|
426
|
+
|
|
406
427
|
if (hookContext.curLLMGenSpan) {
|
|
407
428
|
hookContext.curLLMGenSpan.addEvent('llm.gen.content', {
|
|
408
429
|
'content.size': JSON.stringify(result || {}).length,
|
|
@@ -455,6 +476,9 @@ export class OTel extends TelemetryConnector {
|
|
|
455
476
|
const teamId = agent.teamId;
|
|
456
477
|
const _hookContext: any = this.context;
|
|
457
478
|
|
|
479
|
+
const accessCandidate = AccessCandidate.agent(agentId);
|
|
480
|
+
if (OTEL_DEBUG_LOGS) outputLogger.debug('SREAgent.process started', { processId, agentProcessId, endpointPath }, accessCandidate);
|
|
481
|
+
|
|
458
482
|
const body = oTelInstance.prepareComponentData(agentRequest.body || {});
|
|
459
483
|
const query = oTelInstance.prepareComponentData(agentRequest.query || {});
|
|
460
484
|
const headers = oTelInstance.prepareComponentData(agentRequest.headers || {});
|
|
@@ -531,6 +555,9 @@ export class OTel extends TelemetryConnector {
|
|
|
531
555
|
|
|
532
556
|
if (!agentSpan) return;
|
|
533
557
|
|
|
558
|
+
const accessCandidate = AccessCandidate.agent(agentId);
|
|
559
|
+
if (OTEL_DEBUG_LOGS) outputLogger.debug('SREAgent.process completed', { agentProcessId }, accessCandidate);
|
|
560
|
+
|
|
534
561
|
if (error) {
|
|
535
562
|
agentSpan.recordException(error);
|
|
536
563
|
agentSpan.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
|
|
@@ -597,6 +624,8 @@ export class OTel extends TelemetryConnector {
|
|
|
597
624
|
const componentType = settings.name;
|
|
598
625
|
const componentName = settings.displayName || settings.name;
|
|
599
626
|
const eventId = settings.eventId; // specific event id attached to this component execution
|
|
627
|
+
const accessCandidate = AccessCandidate.agent(agentId);
|
|
628
|
+
if (OTEL_DEBUG_LOGS) outputLogger.debug('Component.process started', { componentId }, accessCandidate);
|
|
600
629
|
|
|
601
630
|
const ctx = OTelContextRegistry.get(agentId, processId);
|
|
602
631
|
const parentSpan = ctx?.rootSpan;
|
|
@@ -671,6 +700,9 @@ export class OTel extends TelemetryConnector {
|
|
|
671
700
|
const componentType = settings.name;
|
|
672
701
|
const componentName = settings.displayName || settings.name;
|
|
673
702
|
|
|
703
|
+
const accessCandidate = AccessCandidate.agent(agentId);
|
|
704
|
+
if (OTEL_DEBUG_LOGS) outputLogger.debug('Component.process completed', { componentId }, accessCandidate);
|
|
705
|
+
|
|
674
706
|
if (error) {
|
|
675
707
|
// Capture error details
|
|
676
708
|
span.recordException(error);
|
|
@@ -10,7 +10,7 @@ export interface ISmythAccountRequest {
|
|
|
10
10
|
getCandidateTeam(): Promise<string | undefined>;
|
|
11
11
|
getAllTeamSettings(): Promise<KeyValueObject>;
|
|
12
12
|
getAllUserSettings(): Promise<KeyValueObject>;
|
|
13
|
-
getTeamSetting(settingKey: string): Promise<string>;
|
|
13
|
+
getTeamSetting(settingKey: string, group?: string): Promise<string>;
|
|
14
14
|
getUserSetting(settingKey: string): Promise<string>;
|
|
15
15
|
getAgentSetting(settingKey: string): Promise<string>;
|
|
16
16
|
getTeam(): Promise<string>;
|
|
@@ -25,7 +25,7 @@ export abstract class AccountConnector extends Connector {
|
|
|
25
25
|
getAllUserSettings: async () => this.getAllUserSettings(candidate.readRequest, candidate.id),
|
|
26
26
|
getUserSetting: async (settingKey: string) => this.getUserSetting(candidate.readRequest, candidate.id, settingKey),
|
|
27
27
|
getAllTeamSettings: async () => this.getAllTeamSettings(candidate.readRequest, candidate.id),
|
|
28
|
-
getTeamSetting: async (settingKey: string) => this.getTeamSetting(candidate.readRequest, candidate.id, settingKey),
|
|
28
|
+
getTeamSetting: async (settingKey: string, group?: string) => this.getTeamSetting(candidate.readRequest, candidate.id, settingKey, group),
|
|
29
29
|
isTeamMember: async (teamId: string) => this.isTeamMember(teamId, candidate),
|
|
30
30
|
getCandidateTeam: async () => this.getCandidateTeam(candidate),
|
|
31
31
|
getTeam: async () => this.getCandidateTeam(candidate),
|
|
@@ -38,7 +38,7 @@ export abstract class AccountConnector extends Connector {
|
|
|
38
38
|
public abstract getCandidateTeam(candidate: IAccessCandidate): Promise<string | undefined>;
|
|
39
39
|
public abstract getAllTeamSettings(acRequest: AccessRequest, teamId: string): Promise<KeyValueObject>;
|
|
40
40
|
public abstract getAllUserSettings(acRequest: AccessRequest, accountId: string): Promise<KeyValueObject>;
|
|
41
|
-
public abstract getTeamSetting(acRequest: AccessRequest, teamId: string, settingKey: string): Promise<string>;
|
|
41
|
+
public abstract getTeamSetting(acRequest: AccessRequest, teamId: string, settingKey: string, group?: string): Promise<string>;
|
|
42
42
|
public abstract getUserSetting(acRequest: AccessRequest, accountId: string, settingKey: string): Promise<string>;
|
|
43
43
|
public abstract getAgentSetting(acRequest: AccessRequest, agentId: string, settingKey: string): Promise<string>;
|
|
44
44
|
}
|