@smythos/sre 1.7.9 → 1.7.15

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 (45) hide show
  1. package/CHANGELOG +7 -0
  2. package/dist/index.js +48 -48
  3. package/dist/index.js.map +1 -1
  4. package/dist/types/Components/APICall/OAuth.helper.d.ts +1 -1
  5. package/dist/types/Core/ConnectorsService.d.ts +3 -1
  6. package/dist/types/Core/HookService.d.ts +18 -0
  7. package/dist/types/helpers/Conversation.helper.d.ts +3 -0
  8. package/dist/types/index.d.ts +7 -3
  9. package/dist/types/subsystems/IO/VectorDB.service/embed/BaseEmbedding.d.ts +2 -1
  10. package/dist/types/subsystems/ObservabilityManager/Log.service/LogConnector.d.ts +19 -0
  11. package/dist/types/subsystems/ObservabilityManager/Log.service/connectors/ConsoleLog.class.d.ts +13 -0
  12. package/dist/types/subsystems/ObservabilityManager/Log.service/connectors/OTel/OTel.class.d.ts +59 -0
  13. package/dist/types/subsystems/ObservabilityManager/Log.service/connectors/OTel/OTelContextRegistry.d.ts +16 -0
  14. package/dist/types/subsystems/ObservabilityManager/Log.service/index.d.ts +4 -0
  15. package/dist/types/subsystems/ObservabilityManager/Telemetry.service/TelemetryConnector.d.ts +13 -0
  16. package/dist/types/subsystems/ObservabilityManager/Telemetry.service/connectors/OTel/OTel.class.d.ts +59 -0
  17. package/dist/types/subsystems/ObservabilityManager/Telemetry.service/connectors/OTel/OTelContextRegistry.d.ts +16 -0
  18. package/dist/types/subsystems/ObservabilityManager/Telemetry.service/index.d.ts +4 -0
  19. package/dist/types/types/LLM.types.d.ts +3 -1
  20. package/dist/types/types/SRE.types.d.ts +5 -2
  21. package/package.json +9 -1
  22. package/src/Components/APICall/OAuth.helper.ts +24 -25
  23. package/src/Components/APICall/mimeTypeCategories.ts +16 -1
  24. package/src/Components/Component.class.ts +3 -1
  25. package/src/Core/ConnectorsService.ts +5 -1
  26. package/src/Core/HookService.ts +104 -12
  27. package/src/Core/boot.ts +3 -1
  28. package/src/helpers/Conversation.helper.ts +42 -15
  29. package/src/index.ts +212 -208
  30. package/src/index.ts.bak +212 -208
  31. package/src/subsystems/AgentManager/Agent.class.ts +9 -8
  32. package/src/subsystems/AgentManager/AgentRuntime.class.ts +4 -4
  33. package/src/subsystems/AgentManager/OSResourceMonitor.ts +69 -8
  34. package/src/subsystems/IO/VectorDB.service/embed/BaseEmbedding.ts +7 -3
  35. package/src/subsystems/IO/VectorDB.service/embed/index.ts +1 -0
  36. package/src/subsystems/LLMManager/LLM.service/connectors/Echo.class.ts +1 -1
  37. package/src/subsystems/{IO → ObservabilityManager}/Log.service/LogConnector.ts +6 -1
  38. package/src/subsystems/{IO → ObservabilityManager}/Log.service/connectors/ConsoleLog.class.ts +6 -3
  39. package/src/subsystems/{IO → ObservabilityManager}/Log.service/index.ts +1 -2
  40. package/src/subsystems/ObservabilityManager/Telemetry.service/TelemetryConnector.ts +23 -0
  41. package/src/subsystems/ObservabilityManager/Telemetry.service/connectors/OTel/OTel.class.ts +759 -0
  42. package/src/subsystems/ObservabilityManager/Telemetry.service/connectors/OTel/OTelContextRegistry.ts +35 -0
  43. package/src/subsystems/ObservabilityManager/Telemetry.service/index.ts +12 -0
  44. package/src/types/LLM.types.ts +2 -0
  45. package/src/types/SRE.types.ts +4 -1
@@ -114,25 +114,119 @@ export function hook(hookName: string) {
114
114
  };
115
115
  }
116
116
 
117
+ // Store metadata about which methods should be auto-wrapped in child classes
118
+ // Maps constructor -> Map<methodName, {hookName, customContext}>
119
+ const hookableMethodsMetadata = new WeakMap<
120
+ any,
121
+ Map<string, { hookName: string; customContext?: Record<string, any> | ((instance: any) => Record<string, any>) }>
122
+ >();
123
+
124
+ /**
125
+ * Class decorator that automatically applies hookAsync to ALL child class methods
126
+ * that override parent methods decorated with hookAsync
127
+ *
128
+ * Usage:
129
+ * @hookableClass
130
+ * export class Component {
131
+ * @hookAsync('Component.process')
132
+ * async process(...) { ... }
133
+ *
134
+ * @hookAsync('Component.postProcess')
135
+ * async postProcess(...) { ... }
136
+ * }
137
+ */
138
+ export function hookableClass<T extends { new (...args: any[]): {} }>(constructor: T) {
139
+ return class extends constructor {
140
+ constructor(...args: any[]) {
141
+ super(...args);
142
+
143
+ // Get metadata for this class
144
+ const metadataMap = hookableMethodsMetadata.get(constructor);
145
+ if (!metadataMap) return; // No hooks to apply
146
+
147
+ const instance = this as any;
148
+ const childPrototype = Object.getPrototypeOf(instance);
149
+ const parentPrototype = constructor.prototype;
150
+
151
+ // Only process if this is a child class instance
152
+ if (childPrototype !== parentPrototype) {
153
+ // Apply hooks to all methods that have metadata
154
+ metadataMap.forEach((metadata, methodName) => {
155
+ // Get the method from the child prototype
156
+ const childMethod = childPrototype[methodName];
157
+ const parentMethod = parentPrototype[methodName];
158
+
159
+ // Check if child has overridden the method
160
+ if (childMethod && typeof childMethod === 'function' && childMethod !== parentMethod) {
161
+ // Get or create descriptor for the child method
162
+ let descriptor = Object.getOwnPropertyDescriptor(childPrototype, methodName);
163
+
164
+ // If not own property, create descriptor from the method
165
+ if (!descriptor) {
166
+ descriptor = {
167
+ value: childMethod,
168
+ writable: true,
169
+ enumerable: false,
170
+ configurable: true,
171
+ };
172
+ }
173
+
174
+ // Apply hookAsync decorator to child method
175
+ const modifiedDescriptor = hookAsync(metadata.hookName, metadata.customContext)(childPrototype, methodName, descriptor);
176
+
177
+ // Update the prototype with the modified descriptor
178
+ if (modifiedDescriptor && modifiedDescriptor.value) {
179
+ Object.defineProperty(childPrototype, methodName, {
180
+ value: modifiedDescriptor.value,
181
+ writable: true,
182
+ enumerable: false,
183
+ configurable: true,
184
+ });
185
+ }
186
+ }
187
+ });
188
+ }
189
+ }
190
+ } as T;
191
+ }
192
+
117
193
  /**
118
194
  * Decorator function that executes registered hooks asynchronously before and after the decorated method
195
+ * Automatically stores metadata for hookableClass decorator to enable automatic child class wrapping
119
196
  * @param hookName The name of the hook to trigger
120
197
  */
121
198
  export function hookAsync(hookName: string, customContext?: Record<string, any> | ((instance: any) => Record<string, any>)) {
122
199
  return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
123
200
  const originalMethod = descriptor.value;
124
201
 
202
+ // Store metadata for this hookable method (for hookableClass decorator)
203
+ if (!hookableMethodsMetadata.has(target.constructor)) {
204
+ hookableMethodsMetadata.set(target.constructor, new Map());
205
+ }
206
+ const metadataMap = hookableMethodsMetadata.get(target.constructor)!;
207
+ metadataMap.set(propertyKey, { hookName, customContext });
208
+
125
209
  descriptor.value = async function (...args: any[]) {
210
+ // Check if we're being called via super from a child class that has its own wrapper
211
+ // If this[propertyKey] is different from our wrapped method, a child has overridden it
212
+ const instanceMethod = (this as any)[propertyKey];
213
+ const isSuperCall = instanceMethod !== descriptor.value && instanceMethod !== originalMethod;
214
+
215
+ // If called via super from a wrapped child, skip hooks and call original method directly
216
+ // The child wrapper already handles hooks, so we just need parent logic
217
+ if (isSuperCall) {
218
+ return await originalMethod.apply(this, args);
219
+ }
220
+
126
221
  // Get additional context if contextFn is provided
127
222
  let _context;
128
223
  if (typeof customContext === 'function') {
129
- _context = await customContext(this);
224
+ _context = { instance: this, args: args, context: await customContext(this) };
130
225
  } else if (typeof customContext === 'object') {
131
- _context = customContext;
226
+ _context = { instance: this, args: args, context: customContext };
132
227
  } else {
133
- _context = this;
228
+ _context = { instance: this, args: args, context: {} };
134
229
  }
135
-
136
230
  // Execute non-blocking pre-hooks first (fire and forget)
137
231
  if (nonBlockingHooks[hookName]) {
138
232
  void Promise.allSettled(nonBlockingHooks[hookName].map((callback) => Promise.resolve(callback.apply(_context, args)))).catch((err) =>
@@ -186,7 +280,6 @@ export function hookAsync(hookName: string, customContext?: Record<string, any>
186
280
  return descriptor;
187
281
  };
188
282
  }
189
-
190
283
  /**
191
284
  * Decorator function that executes registered hooks asynchronously before the decorated method
192
285
  * @param hookName The name of the hook to trigger
@@ -200,11 +293,12 @@ export function hookAsyncWithContext(hookName: string, contextFn?: (instance: an
200
293
  // Get additional context if contextFn is provided
201
294
  const additionalContext = typeof contextFn === 'function' ? await contextFn(this) : {};
202
295
  const contextualArgs = [additionalContext, ...args];
296
+ const _context = { instance: this, args: args, context: additionalContext };
203
297
 
204
298
  // Execute non-blocking pre-hooks first (fire and forget)
205
299
  if (nonBlockingHooks[hookName]) {
206
300
  void Promise.allSettled(
207
- nonBlockingHooks[hookName].map((callback) => Promise.resolve().then(() => callback.apply(this, contextualArgs)))
301
+ nonBlockingHooks[hookName].map((callback) => Promise.resolve().then(() => callback.apply(_context, contextualArgs)))
208
302
  );
209
303
  }
210
304
 
@@ -214,7 +308,7 @@ export function hookAsyncWithContext(hookName: string, contextFn?: (instance: an
214
308
  try {
215
309
  // Execute blocking pre-hooks and wait for them
216
310
  if (blockingHooks[hookName]) {
217
- await Promise.all(blockingHooks[hookName].map((callback) => Promise.resolve(callback.apply(this, contextualArgs))));
311
+ await Promise.all(blockingHooks[hookName].map((callback) => Promise.resolve(callback.apply(_context, contextualArgs))));
218
312
  }
219
313
 
220
314
  // Call the original method
@@ -228,16 +322,14 @@ export function hookAsyncWithContext(hookName: string, contextFn?: (instance: an
228
322
  // Execute non-blocking after-hooks first (fire and forget)
229
323
  if (nonBlockingAfterHooks[hookName]) {
230
324
  void Promise.allSettled(
231
- nonBlockingAfterHooks[hookName].map((callback) =>
232
- Promise.resolve().then(() => callback({ result, args: contextualArgs, error }))
233
- )
234
- );
325
+ nonBlockingAfterHooks[hookName].map((callback) => Promise.resolve(callback.apply(_context, [{ result, args, error }])))
326
+ ).catch((err) => console.error(`Non-blocking after-hook ${hookName} error:`, err));
235
327
  }
236
328
 
237
329
  // Execute blocking after-hooks and wait for them
238
330
  if (blockingAfterHooks[hookName]) {
239
331
  await Promise.all(
240
- blockingAfterHooks[hookName].map((callback) => Promise.resolve(callback({ result, args: contextualArgs, error })))
332
+ blockingAfterHooks[hookName].map((callback) => Promise.resolve(callback.apply(_context, [{ result, args, error }])))
241
333
  );
242
334
  }
243
335
  } catch (afterHookError) {
package/src/Core/boot.ts CHANGED
@@ -12,11 +12,12 @@ import { CLIService } from '@sre/IO/CLI.service';
12
12
  import { NKVService } from '@sre/IO/NKV.service';
13
13
  import { RouterService } from '@sre/IO/Router.service';
14
14
  import { ManagedVaultService } from '@sre/Security/ManagedVault.service';
15
- import { LogService } from '@sre/IO/Log.service';
15
+ import { LogService } from '@sre/ObservabilityManager/Log.service';
16
16
  import { ComponentService } from '@sre/AgentManager/Component.service';
17
17
  import { ModelsProviderService } from '@sre/LLMManager/ModelsProvider.service';
18
18
  import { CodeService } from '@sre/ComputeManager/Code.service';
19
19
  import { SchedulerService } from '@sre/AgentManager/Scheduler.service';
20
+ import { TelemetryService } from '@sre/ObservabilityManager/Telemetry.service';
20
21
  const console = Logger('Boot');
21
22
  let _booted = false;
22
23
  export function boot() {
@@ -44,6 +45,7 @@ export function boot() {
44
45
  service.Component = new ComponentService();
45
46
  service.Code = new CodeService();
46
47
  service.Scheduler = new SchedulerService();
48
+ service.Telemetry = new TelemetryService();
47
49
 
48
50
  SystemEvents.on('SRE:Initialized', () => {
49
51
  console.debug('SRE Initialized');
@@ -38,6 +38,9 @@ type ToolParams = {
38
38
  //TODO: handle authentication
39
39
  export class Conversation extends EventEmitter {
40
40
  private _agentId: string = '';
41
+ public get agentId() {
42
+ return this._agentId;
43
+ }
41
44
  private _systemPrompt;
42
45
  private userDefinedSystemPrompt: string = '';
43
46
  public toolChoice: string = 'auto';
@@ -68,6 +71,11 @@ export class Conversation extends EventEmitter {
68
71
  private _agentVersion: string = undefined;
69
72
  public agentData: any;
70
73
 
74
+ private _id: string = '';
75
+ public get id() {
76
+ return this._id;
77
+ }
78
+
71
79
  public get context() {
72
80
  return this._context;
73
81
  }
@@ -128,6 +136,7 @@ export class Conversation extends EventEmitter {
128
136
  //TODO: handle loading previous session (messages)
129
137
  super();
130
138
 
139
+ this._id = 'conv_' + randomUUID();
131
140
  //this event listener avoids unhandled errors that can cause crashes
132
141
  this.on('error', (error) => {
133
142
  this._lastError = error;
@@ -310,6 +319,16 @@ export class Conversation extends EventEmitter {
310
319
  maxTokens = this.model.params.maxTokens;
311
320
  }
312
321
 
322
+ const llmReqUid = randomUUID();
323
+ this.emit(TLLMEvent.Requested, {
324
+ model: typeof this.model === 'string' ? this.model : this.model?.modelId,
325
+ contextWindow,
326
+ files,
327
+ maxTokens,
328
+ agentId: this._agentId,
329
+ requestId: llmReqUid,
330
+ });
331
+
313
332
  const eventEmitter: any = await llmInference
314
333
  .promptStream({
315
334
  contextWindow,
@@ -325,7 +344,7 @@ export class Conversation extends EventEmitter {
325
344
  })
326
345
  .catch((error) => {
327
346
  console.error('Error on promptStream: ', error);
328
- this.emit(TLLMEvent.Error, error);
347
+ this.emit(TLLMEvent.Error, error, { requestId: llmReqUid });
329
348
  });
330
349
 
331
350
  // remove listeners from llm event emitter to stop receiving stream data
@@ -338,20 +357,24 @@ export class Conversation extends EventEmitter {
338
357
  throw new Error('[LLM Request Error]');
339
358
  }
340
359
 
341
- if (message) this.emit('start');
342
- eventEmitter.on('data', (data) => {
343
- if (this.stop) return;
344
- this.emit('data', data);
345
- });
360
+ if (message) this.emit('start', { requestId: llmReqUid });
361
+ // eventEmitter.on(TLLMEvent.Data, (data) => {
362
+ // if (this.stop) return;
363
+ // this.emit('data', data);
364
+ // });
346
365
 
347
366
  eventEmitter.on(TLLMEvent.Thinking, (thinking) => {
348
367
  if (this.stop) return;
349
- this.emit(TLLMEvent.Thinking, thinking);
368
+ this.emit(TLLMEvent.Thinking, thinking, { requestId: llmReqUid });
350
369
  });
351
370
 
352
371
  eventEmitter.on(TLLMEvent.Data, (data) => {
353
372
  if (this.stop) return;
354
- this.emit(TLLMEvent.Data, data);
373
+ this.emit(TLLMEvent.Data, data, {
374
+ contextWindow,
375
+ requestId: llmReqUid,
376
+ model: typeof this.model === 'string' ? this.model : this.model?.modelId,
377
+ });
355
378
  });
356
379
 
357
380
  eventEmitter.on(TLLMEvent.Content, (content) => {
@@ -368,7 +391,7 @@ export class Conversation extends EventEmitter {
368
391
  // let s = true;
369
392
  // }
370
393
  _content += content;
371
- this.emit(TLLMEvent.Content, content);
394
+ this.emit(TLLMEvent.Content, content, { requestId: llmReqUid });
372
395
  });
373
396
 
374
397
  let finishReason = 'stop';
@@ -408,6 +431,9 @@ export class Conversation extends EventEmitter {
408
431
  toolsData.forEach((tool) => {
409
432
  tool.status = tool.name ? this._toolStatusMap?.[tool.name] : undefined;
410
433
  });
434
+ toolsData.content = _content;
435
+ toolsData.requestId = llmReqUid;
436
+ toolsData.contextWindow = contextWindow;
411
437
 
412
438
  llmMessage.tool_calls = toolsData.map((tool) => {
413
439
  return {
@@ -473,7 +499,7 @@ export class Conversation extends EventEmitter {
473
499
  this.emit('beforeToolCall', { tool, args }, llmMessage); //deprecated
474
500
 
475
501
  const status = tool.name ? this._toolStatusMap?.[tool.name] : undefined;
476
- this.emit(TLLMEvent.ToolCall, { tool, status, _llmRequest: llmMessage });
502
+ this.emit(TLLMEvent.ToolCall, { tool, status, _llmRequest: llmMessage, requestId: llmReqUid });
477
503
 
478
504
  const toolArgs = {
479
505
  type: tool?.type,
@@ -500,7 +526,7 @@ export class Conversation extends EventEmitter {
500
526
 
501
527
  //await afterFunctionCall(functionResponse, toolsData[tool.index]);
502
528
  this.emit('afterToolCall', { tool, args }, functionResponse); // Deprecated
503
- this.emit(TLLMEvent.ToolResult, { tool, result });
529
+ this.emit(TLLMEvent.ToolResult, { tool, result, requestId: llmReqUid });
504
530
 
505
531
  return { ...tool, result: functionResponse };
506
532
  }
@@ -542,7 +568,7 @@ export class Conversation extends EventEmitter {
542
568
  if (_finishReason) finishReason = _finishReason;
543
569
  if (usage_data) {
544
570
  //FIXME : normalize the usage data format
545
- this.emit(TLLMEvent.Usage, usage_data);
571
+ this.emit(TLLMEvent.Usage, usage_data, { requestId: llmReqUid });
546
572
  }
547
573
  if (hasError) return;
548
574
 
@@ -563,7 +589,7 @@ export class Conversation extends EventEmitter {
563
589
  const toolsContent = await toolsPromise.catch((error) => {
564
590
  console.error('Error in toolsPromise: ', error);
565
591
  //this.emit('error', error);
566
- this.emit(TLLMEvent.Error, error);
592
+ this.emit(TLLMEvent.Error, error, { requestId: llmReqUid });
567
593
  return '';
568
594
  });
569
595
  _content += toolsContent;
@@ -588,9 +614,9 @@ export class Conversation extends EventEmitter {
588
614
  //this._context.push({ role: 'assistant', content: content });
589
615
 
590
616
  if (finishReason !== 'stop') {
591
- this.emit(TLLMEvent.Interrupted, finishReason);
617
+ this.emit(TLLMEvent.Interrupted, finishReason, { requestId: llmReqUid });
592
618
  }
593
- this.emit(TLLMEvent.End);
619
+ this.emit(TLLMEvent.End, { requestId: llmReqUid });
594
620
  } else {
595
621
  //console.log('tool content', content);
596
622
  }
@@ -671,6 +697,7 @@ export class Conversation extends EventEmitter {
671
697
 
672
698
  reqConfig.headers['X-CACHE-ID'] = this._context?.llmCache?.id;
673
699
 
700
+ reqConfig.headers['X-REQUEST-TAG'] = this.id;
674
701
  /*
675
702
  * Objective for the following conditions:
676
703
  * - In case it is not a debug call and there is no monitor id, then we need to run the agent locally to reduce latency