@smythos/sre 1.7.40 → 1.7.41

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 +1 -0
  29. package/src/index.ts.bak +1 -0
  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 +229 -12
  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
@@ -5,7 +5,7 @@ import { IAccessCandidate } from '@sre/types/ACL.types';
5
5
  import { TelemetryConnector } from '../../TelemetryConnector';
6
6
  import { AgentCallLog } from '@sre/types/AgentLogger.types';
7
7
 
8
- import { trace, context, SpanStatusCode, Tracer } from '@opentelemetry/api';
8
+ import { trace, context, SpanStatusCode, Tracer, propagation } from '@opentelemetry/api';
9
9
  import { Logger as OTelLogger, logs, SeverityNumber } from '@opentelemetry/api-logs';
10
10
  import { OTelContextRegistry } from './OTelContextRegistry';
11
11
  import { HookService, THook } from '@sre/Core/HookService';
@@ -62,6 +62,10 @@ export class OTel extends TelemetryConnector {
62
62
 
63
63
  constructor(protected _settings: OTelLogConfig) {
64
64
  super();
65
+ if (!_settings.endpoint) {
66
+ outputLogger.warn('OTel initialization skipped, endpoint is not set');
67
+ return;
68
+ }
65
69
 
66
70
  outputLogger.log(`Initializing Tracer ...`);
67
71
 
@@ -279,6 +283,7 @@ export class OTel extends TelemetryConnector {
279
283
  attributes: {
280
284
  'agent.id': hookContext.agentId,
281
285
  'conv.id': hookContext.processId,
286
+ 'team.id': hookContext.teamId,
282
287
  'llm.model': modelId || 'unknown',
283
288
  },
284
289
  },
@@ -312,6 +317,7 @@ export class OTel extends TelemetryConnector {
312
317
  attributes: {
313
318
  'agent.id': hookContext.agentId,
314
319
  'conv.id': hookContext.processId,
320
+ 'team.id': hookContext.teamId,
315
321
  'request.id': reqInfo.requestId,
316
322
  'llm.model': modelId || 'unknown',
317
323
  'metric.type': 'ttfb',
@@ -331,11 +337,21 @@ export class OTel extends TelemetryConnector {
331
337
  HookService.register(
332
338
  'Conversation.streamPrompt',
333
339
  async function (additionalContext, args) {
334
- const conversation: Conversation = this.instance;
335
- const processId = conversation.id;
340
+ const conversation: Conversation = this.instance; //this.instance.agentData.teamId // this.instance.agentData.parenparentTeamId //this.instance.agentData.planInfo.properties this.instance.agentData.planInfo.flags
341
+ const processId = conversation.storeId || conversation.id;
336
342
  const agentId = conversation.agentId;
337
343
  const message = typeof args === 'object' ? args?.message : args || null;
338
344
  const hookContext: any = this.context;
345
+ const teamId = conversation.agentData.teamId;
346
+ const orgTier = 'standard';
347
+ const orgSlot = this.instance.agentData?.planInfo?.flags ? `standard/${teamId}` : undefined;
348
+ const agentData = conversation.agentData || {};
349
+ const isDebugSession = agentData.debugSessionEnabled || false;
350
+ const isTestDomain = agentData.usingTestDomain || false;
351
+ const sessionId = processId;
352
+ const workflowId = agentData?.workflowReqId || agentData?.workflowID || agentData?.workflowId || undefined;
353
+ const logTags = agentData?.sessionTag || (isDebugSession ? 'DEBUG' : undefined);
354
+
339
355
  if (message == null) {
340
356
  //this is a conversation step, will be handled by createRequestedHandler
341
357
 
@@ -354,14 +370,36 @@ export class OTel extends TelemetryConnector {
354
370
  'gen_ai.conversation.id': processId,
355
371
  'gen_ai.request.model': modelId || 'unknown',
356
372
  ////////////////////////////////
373
+ 'team.id': teamId,
374
+ 'org.tier': orgTier,
375
+ 'org.slot': orgSlot,
357
376
  'agent.id': agentId,
358
377
  'conv.id': processId,
359
378
  'llm.model': modelId || 'unknown',
379
+ 'agent.debug': isDebugSession,
380
+ 'agent.isTest': isTestDomain,
381
+ 'session.id': sessionId,
382
+ 'workflow.id': workflowId,
360
383
  },
361
384
  });
362
385
  hookContext.convSpan = convSpan;
363
386
  hookContext.agentId = agentId;
364
387
  hookContext.processId = processId;
388
+ hookContext.teamId = teamId;
389
+ hookContext.orgSlot = orgSlot;
390
+ hookContext.isDebugSession = isDebugSession;
391
+ hookContext.isTestDomain = isTestDomain;
392
+
393
+ // Inject trace context into conversation headers for distributed tracing
394
+ let headers = {};
395
+ const traceContext = trace.setSpan(context.active(), convSpan);
396
+ propagation.inject(traceContext, headers);
397
+ for (let [key, value] of Object.entries(headers)) {
398
+ conversation.headers[key] = value as string;
399
+ }
400
+ if (OTEL_DEBUG_LOGS) {
401
+ outputLogger.debug('Injected trace headers into conversation', { processId, headers });
402
+ }
365
403
 
366
404
  hookContext.dataHandler = createDataHandler(hookContext);
367
405
  conversation.on(TLLMEvent.Data, hookContext.dataHandler);
@@ -395,10 +433,19 @@ export class OTel extends TelemetryConnector {
395
433
  span_id: spanCtx.spanId,
396
434
  trace_flags: spanCtx.traceFlags,
397
435
 
436
+ /////
437
+ 'team.id': teamId,
438
+ 'org.slot': orgSlot,
439
+
398
440
  'agent.id': agentId,
399
441
  'conv.id': processId,
400
442
  'input.size': JSON.stringify(message || {}).length,
401
443
  'input.preview': message.substring(0, 2000),
444
+ 'agent.debug': isDebugSession,
445
+ 'agent.isTest': isTestDomain,
446
+ 'session.id': sessionId,
447
+ 'workflow.id': workflowId,
448
+ 'log.tags': logTags,
402
449
  },
403
450
  });
404
451
  });
@@ -410,10 +457,21 @@ export class OTel extends TelemetryConnector {
410
457
  'Conversation.streamPrompt',
411
458
  async function ({ result, args, error }) {
412
459
  const conversation: Conversation = this.instance;
413
- const processId = conversation.id;
460
+ const processId = conversation.storeId || conversation.id;
414
461
  const agentId = conversation.agentId;
415
462
  const message = typeof args?.[0] === 'object' ? args?.[0]?.message : args?.[0] || null;
416
463
  const hookContext: any = this.context;
464
+ const teamId = conversation.agentData.teamId;
465
+ const orgTier = 'standard';
466
+ const orgSlot = this.instance.agentData?.planInfo?.flags ? `standard/${teamId}` : undefined;
467
+
468
+ const isDebugSession = hookContext.isDebugSession || conversation.agentData?.debugSessionEnabled || false;
469
+ const isTestDomain = hookContext.isTestDomain || conversation.agentData?.usingTestDomain || false;
470
+ const agentData = conversation.agentData || {};
471
+ const sessionId = processId;
472
+ const workflowId = agentData?.workflowReqId || agentData?.workflowID || agentData?.workflowId || undefined;
473
+ const logTags = agentData?.sessionTag || (isDebugSession ? 'DEBUG' : undefined);
474
+
417
475
  if (message == null) {
418
476
  return;
419
477
  }
@@ -450,6 +508,14 @@ export class OTel extends TelemetryConnector {
450
508
  'conv.id': processId,
451
509
  'output.size': JSON.stringify(result || {}).length,
452
510
  'output.preview': result.substring(0, 2000),
511
+ 'team.id': teamId,
512
+ 'org.tier': orgTier,
513
+ 'org.slot': orgSlot,
514
+ 'agent.debug': isDebugSession,
515
+ 'agent.isTest': isTestDomain,
516
+ 'session.id': sessionId,
517
+ 'workflow.id': workflowId,
518
+ 'log.tags': logTags,
453
519
  },
454
520
  });
455
521
  });
@@ -471,11 +537,21 @@ export class OTel extends TelemetryConnector {
471
537
  const conversationId = agent.conversationId || agent.agentRequest?.header('X-CONVERSATION-ID');
472
538
  const processId = agentProcessId.split(':').shift();
473
539
 
540
+ const orgTier = 'standard';
541
+ const orgSlot = agent.data.planInfo?.flags ? `standard/${agent.data.teamId}` : undefined;
474
542
  const agentId = agent.id;
475
543
  const agentRequest = agent.agentRequest;
476
544
  const teamId = agent.teamId;
477
545
  const _hookContext: any = this.context;
478
546
 
547
+ const sessionId = agent.callerSessionId || undefined;
548
+ const workflowId = agent.agentRuntime?.workflowReqId || undefined;
549
+
550
+ const isDebugSession = agent.debugSessionEnabled || agent.agentRuntime?.debug || false;
551
+ const logTags = agent.sessionTag || (isDebugSession ? 'DEBUG' : undefined);
552
+ const isTestDomain = agent.usingTestDomain || false;
553
+ const domain = agent.domain || undefined;
554
+
479
555
  const accessCandidate = AccessCandidate.agent(agentId);
480
556
  if (OTEL_DEBUG_LOGS) outputLogger.debug('SREAgent.process started', { processId, agentProcessId, endpointPath }, accessCandidate);
481
557
 
@@ -487,22 +563,50 @@ export class OTel extends TelemetryConnector {
487
563
  const input = { body, query, headers, processInput: agentInput };
488
564
 
489
565
  let convSpan;
490
- const ctx = OTelContextRegistry.get(agentId, processId) || OTelContextRegistry.get(agentId, conversationId);
566
+ let parentContext = context.active();
567
+
568
+ //try reading ctx from local registry (local execution)
569
+ let ctx = OTelContextRegistry.get(agentId, processId) || OTelContextRegistry.get(agentId, conversationId);
491
570
 
492
571
  if (ctx) {
493
572
  convSpan = ctx.rootSpan;
494
573
  _hookContext.otelSpan = convSpan;
574
+ parentContext = trace.setSpan(context.active(), convSpan);
575
+ } else {
576
+ // No local context found - try extracting from headers (remote execution)
577
+ const extractedContext = propagation.extract(context.active(), agentRequest.headers);
578
+ const extractedSpan = trace.getSpan(extractedContext);
579
+
580
+ if (extractedSpan) {
581
+ // Successfully extracted parent span from headers
582
+ parentContext = extractedContext;
583
+ if (OTEL_DEBUG_LOGS) {
584
+ outputLogger.debug('SREAgent.process extracted remote parent context from headers', {
585
+ processId,
586
+ traceId: extractedSpan.spanContext().traceId,
587
+ });
588
+ }
589
+ }
495
590
  }
591
+
496
592
  const agentSpan = tracer.startSpan(
497
593
  'Agent.Skill',
498
594
  {
499
595
  attributes: {
500
596
  'agent.id': agentId,
501
597
  'team.id': teamId,
598
+ 'conv.id': conversationId,
502
599
  'process.id': agentProcessId,
600
+ 'org.slot': orgSlot,
601
+ 'org.tier': orgTier,
602
+ 'session.id': sessionId,
603
+ 'workflow.id': workflowId,
604
+ 'agent.debug': isDebugSession,
605
+ 'agent.isTest': isTestDomain,
606
+ 'agent.domain': domain,
503
607
  },
504
608
  },
505
- convSpan ? trace.setSpan(context.active(), convSpan) : undefined
609
+ parentContext
506
610
  );
507
611
 
508
612
  // Add start event
@@ -528,12 +632,22 @@ export class OTel extends TelemetryConnector {
528
632
  trace_id: spanCtx.traceId,
529
633
  span_id: spanCtx.spanId,
530
634
  trace_flags: spanCtx.traceFlags,
531
- agentId,
532
- processId: agentProcessId,
635
+ 'agent.id': agentId,
636
+ 'process.id': agentProcessId,
533
637
  input: agentInput,
534
638
  body,
535
639
  query,
536
640
  headers,
641
+ 'team.id': teamId,
642
+ 'org.slot': orgSlot,
643
+ 'org.tier': orgTier,
644
+ 'conv.id': conversationId,
645
+ 'session.id': sessionId,
646
+ 'workflow.id': workflowId,
647
+ 'log.tags': logTags,
648
+ 'agent.debug': isDebugSession,
649
+ 'agent.isTest': isTestDomain,
650
+ 'agent.domain': domain,
537
651
  },
538
652
  } as any);
539
653
  });
@@ -546,8 +660,20 @@ export class OTel extends TelemetryConnector {
546
660
  async function ({ result, error }) {
547
661
  const agent = this.instance;
548
662
  const agentProcessId = agent.agentRuntime.processID; // nested process has a subID that needs to be removed
663
+ const conversationId = agent.conversationId || agent.agentRequest?.header('X-CONVERSATION-ID');
549
664
  const agentId = agent.id;
550
665
  const _hookContext: any = this.context;
666
+ const teamId = agent.teamId;
667
+ const orgTier = 'standard';
668
+ const orgSlot = agent.data.planInfo?.flags ? `standard/${agent.data.teamId}` : undefined;
669
+
670
+ const sessionId = agent.callerSessionId || undefined;
671
+ const workflowId = agent.agentRuntime?.workflowReqId || undefined;
672
+
673
+ const isDebugSession = agent.debugSessionEnabled || agent.agentRuntime?.debug || false;
674
+ const logTags = agent.sessionTag || (isDebugSession ? 'DEBUG' : undefined);
675
+ const isTestDomain = agent.usingTestDomain || false;
676
+ const domain = agent.domain || undefined;
551
677
 
552
678
  const ctx = OTelContextRegistry.get(agentId, agentProcessId);
553
679
  if (!ctx) return;
@@ -582,11 +708,21 @@ export class OTel extends TelemetryConnector {
582
708
  trace_id: spanCtx.traceId,
583
709
  span_id: spanCtx.spanId,
584
710
  trace_flags: spanCtx.traceFlags,
585
- agentId,
586
- processId: agentProcessId,
711
+ 'agent.id': agentId,
712
+ 'process.id': agentProcessId,
587
713
  hasError: !!error,
588
714
  'error.message': error?.message,
589
715
  'error.stack': error?.stack,
716
+ 'team.id': teamId,
717
+ 'org.slot': orgSlot,
718
+ 'org.tier': orgTier,
719
+ 'conv.id': conversationId,
720
+ 'session.id': sessionId,
721
+ 'workflow.id': workflowId,
722
+ 'log.tags': logTags,
723
+ 'agent.debug': isDebugSession,
724
+ 'agent.isTest': isTestDomain,
725
+ 'agent.domain': domain,
590
726
  };
591
727
 
592
728
  // Only include output if formatOutputForLog returns a value
@@ -625,7 +761,27 @@ export class OTel extends TelemetryConnector {
625
761
  const componentName = settings.displayName || settings.name;
626
762
  const eventId = settings.eventId; // specific event id attached to this component execution
627
763
  const accessCandidate = AccessCandidate.agent(agentId);
628
- if (OTEL_DEBUG_LOGS) outputLogger.debug('Component.process started', { componentId }, accessCandidate);
764
+ const teamId = agent.teamId;
765
+ const orgTier = 'standard';
766
+ const orgSlot = agent.data.planInfo?.flags ? `standard/${agent.data.teamId}` : undefined;
767
+
768
+ const componentData = agent.agentRuntime?.getComponentData?.(componentId);
769
+ const sourceId = componentData?.sourceId || 'AGENT';
770
+ const sourceComponentData = sourceId !== 'AGENT' ? agent.components?.[sourceId] : null;
771
+ const sourceName = sourceComponentData?.displayName || sourceComponentData?.name || sourceId;
772
+
773
+ const sessionId = agent.callerSessionId || undefined;
774
+ const workflowId = agent.agentRuntime?.workflowReqId || undefined;
775
+ const workflowStep = agent.agentRuntime?.curStep || undefined;
776
+
777
+ const isDebugSession = agent.debugSessionEnabled || agent.agentRuntime?.debug || false;
778
+ const logTags = agent.sessionTag || (isDebugSession ? 'DEBUG' : undefined);
779
+ const isTestDomain = agent.usingTestDomain || false;
780
+
781
+ const inputAction = input?.__action || undefined;
782
+ const inputStatus = input?.__status || undefined;
783
+
784
+ if (OTEL_DEBUG_LOGS) outputLogger.debug('Component.process started', { componentId, sourceId }, accessCandidate);
629
785
 
630
786
  const ctx = OTelContextRegistry.get(agentId, processId);
631
787
  const parentSpan = ctx?.rootSpan;
@@ -642,13 +798,23 @@ export class OTel extends TelemetryConnector {
642
798
  'cmp.id': componentId,
643
799
  'cmp.type': componentType,
644
800
  'cmp.name': componentName,
801
+ 'team.id': teamId,
802
+ 'org.tier': orgTier,
803
+ 'org.slot': orgSlot,
804
+ 'source.id': sourceId,
805
+ 'source.name': sourceName,
806
+ 'session.id': sessionId,
807
+ 'workflow.id': workflowId,
808
+ 'workflow.step': workflowStep,
809
+ 'agent.debug': isDebugSession,
810
+ 'agent.isTest': isTestDomain,
645
811
  ...compSettingsData,
646
812
  },
647
813
  },
648
814
  parentSpan ? trace.setSpan(context.active(), parentSpan) : undefined
649
815
  );
650
816
 
651
- // Add event: Component started
817
+ // Add event: Component started - includes input.action and input.status for workflow tracking
652
818
  const inputStr = JSON.stringify(input || {});
653
819
 
654
820
  const compInputData = oTelInstance.prepareComponentData(input || {});
@@ -656,6 +822,8 @@ export class OTel extends TelemetryConnector {
656
822
  'event.id': eventId,
657
823
  'cmp.input.size': JSON.stringify(input || {}).length,
658
824
  'cmp.input': JSON.stringify(compInputData),
825
+ 'input.action': inputAction,
826
+ 'input.status': inputStatus,
659
827
  });
660
828
 
661
829
  // Emit structured log with full details
@@ -673,6 +841,17 @@ export class OTel extends TelemetryConnector {
673
841
  'cmp.type': componentType,
674
842
  'cmp.name': componentName,
675
843
  'cmp.input': input,
844
+ 'team.id': teamId,
845
+ 'org.slot': orgSlot,
846
+ 'org.tier': orgTier,
847
+ 'source.id': sourceId,
848
+ 'source.name': sourceName,
849
+ 'session.id': sessionId,
850
+ 'workflow.id': workflowId,
851
+ 'workflow.step': workflowStep,
852
+ 'log.tags': logTags,
853
+ 'agent.debug': isDebugSession,
854
+ 'agent.isTest': isTestDomain,
676
855
  },
677
856
  });
678
857
  });
@@ -699,6 +878,22 @@ export class OTel extends TelemetryConnector {
699
878
  const componentId = settings.id || 'unknown';
700
879
  const componentType = settings.name;
701
880
  const componentName = settings.displayName || settings.name;
881
+ const teamId = agent.teamId;
882
+ const orgTier = 'standard';
883
+ const orgSlot = agent.data.planInfo?.flags ? `standard/${agent.data.teamId}` : undefined;
884
+
885
+ const componentData = agent.agentRuntime?.getComponentData?.(componentId);
886
+ const sourceId = componentData?.sourceId || 'AGENT';
887
+ const sourceComponentData = sourceId !== 'AGENT' ? agent.components?.[sourceId] : null;
888
+ const sourceName = sourceComponentData?.displayName || sourceComponentData?.name || sourceId;
889
+
890
+ const sessionId = agent.callerSessionId || undefined;
891
+ const workflowId = agent.agentRuntime?.workflowReqId || undefined;
892
+ const workflowStep = agent.agentRuntime?.curStep || undefined;
893
+
894
+ const isDebugSession = agent.debugSessionEnabled || agent.agentRuntime?.debug || false;
895
+ const logTags = agent.sessionTag || (isDebugSession ? 'DEBUG' : undefined);
896
+ const isTestDomain = agent.usingTestDomain || false;
702
897
 
703
898
  const accessCandidate = AccessCandidate.agent(agentId);
704
899
  if (OTEL_DEBUG_LOGS) outputLogger.debug('Component.process completed', { componentId }, accessCandidate);
@@ -736,6 +931,17 @@ export class OTel extends TelemetryConnector {
736
931
  'error.type': error.name,
737
932
  'error.message': error.message,
738
933
  'error.stack': error.stack, // ← Full stack in logs
934
+ 'team.id': teamId,
935
+ 'org.slot': orgSlot,
936
+ 'org.tier': orgTier,
937
+ 'source.id': sourceId,
938
+ 'source.name': sourceName,
939
+ 'session.id': sessionId,
940
+ 'workflow.id': workflowId,
941
+ 'workflow.step': workflowStep,
942
+ 'log.tags': logTags,
943
+ 'agent.debug': isDebugSession,
944
+ 'agent.isTest': isTestDomain,
739
945
  },
740
946
  });
741
947
  });
@@ -765,6 +971,17 @@ export class OTel extends TelemetryConnector {
765
971
  'process.id': processId,
766
972
  'event.id': eventId,
767
973
  'cmp.output': result,
974
+ 'team.id': teamId,
975
+ 'org.slot': orgSlot,
976
+ 'org.tier': orgTier,
977
+ 'source.id': sourceId,
978
+ 'source.name': sourceName,
979
+ 'session.id': sessionId,
980
+ 'workflow.id': workflowId,
981
+ 'workflow.step': workflowStep,
982
+ 'log.tags': logTags,
983
+ 'agent.debug': isDebugSession,
984
+ 'agent.isTest': isTestDomain,
768
985
  };
769
986
 
770
987
  // Only include output if formatOutputForLog returns a value
@@ -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)}]`;