@memberjunction/ai-prompts 2.111.1 → 2.112.0

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.
@@ -26,8 +26,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.LoadAIPromptRunner = exports.AIPromptRunner = void 0;
27
27
  const ai_1 = require("@memberjunction/ai");
28
28
  const ai_core_plus_1 = require("@memberjunction/ai-core-plus");
29
- const core_1 = require("@memberjunction/core");
30
29
  const global_1 = require("@memberjunction/global");
30
+ const global_2 = require("@memberjunction/global");
31
31
  const templates_1 = require("@memberjunction/templates");
32
32
  const ExecutionPlanner_1 = require("./ExecutionPlanner");
33
33
  const ParallelExecutionCoordinator_1 = require("./ParallelExecutionCoordinator");
@@ -36,11 +36,11 @@ const ai_core_plus_2 = require("@memberjunction/ai-core-plus");
36
36
  const JSON5 = __importStar(require("json5"));
37
37
  class AIPromptRunner {
38
38
  constructor() {
39
- this._metadata = new core_1.Metadata();
39
+ this._metadata = new global_1.Metadata();
40
40
  this._templateEngine = templates_1.TemplateEngineServer.Instance;
41
41
  this._executionPlanner = new ExecutionPlanner_1.ExecutionPlanner();
42
42
  this._parallelCoordinator = new ParallelExecutionCoordinator_1.ParallelExecutionCoordinator();
43
- this._jsonValidator = new global_1.JSONValidator();
43
+ this._jsonValidator = new global_2.JSONValidator();
44
44
  }
45
45
  isValidAPIKey(apiKey) {
46
46
  if (apiKey === undefined || apiKey === null) {
@@ -51,14 +51,14 @@ class AIPromptRunner {
51
51
  }
52
52
  logStatus(message, verboseOnly = false, params) {
53
53
  if (verboseOnly) {
54
- (0, core_1.LogStatusEx)({
54
+ (0, global_1.LogStatusEx)({
55
55
  message,
56
56
  verboseOnly: true,
57
- isVerboseEnabled: () => params?.verbose === true || (0, core_1.IsVerboseLoggingEnabled)()
57
+ isVerboseEnabled: () => params?.verbose === true || (0, global_1.IsVerboseLoggingEnabled)(),
58
58
  });
59
59
  }
60
60
  else {
61
- (0, core_1.LogStatus)(message);
61
+ (0, global_1.LogStatus)(message);
62
62
  }
63
63
  }
64
64
  logError(error, options) {
@@ -68,7 +68,7 @@ class AIPromptRunner {
68
68
  errorMessage = errorMessage.substring(0, options.maxErrorLength) + '... [truncated]';
69
69
  }
70
70
  const metadata = {
71
- ...options?.metadata
71
+ ...options?.metadata,
72
72
  };
73
73
  if (options?.prompt) {
74
74
  metadata.promptId = options.prompt.ID;
@@ -78,18 +78,18 @@ class AIPromptRunner {
78
78
  metadata.modelId = options.model.ID;
79
79
  metadata.modelName = options.model.Name;
80
80
  }
81
- (0, core_1.LogErrorEx)({
81
+ (0, global_1.LogErrorEx)({
82
82
  message: errorMessage,
83
83
  error: errorObj,
84
84
  category: options?.category || 'AIPromptRunner',
85
85
  severity: options?.severity || 'error',
86
- metadata: Object.keys(metadata).length > 0 ? metadata : undefined
86
+ metadata: Object.keys(metadata).length > 0 ? metadata : undefined,
87
87
  });
88
88
  }
89
89
  isInferenceProvider(modelVendor) {
90
- const inferenceProviderType = aiengine_1.AIEngine.Instance.VendorTypeDefinitions.find(vt => vt.Name === 'Inference Provider');
90
+ const inferenceProviderType = aiengine_1.AIEngine.Instance.VendorTypeDefinitions.find((vt) => vt.Name === 'Inference Provider');
91
91
  if (!inferenceProviderType) {
92
- const modelDeveloperType = aiengine_1.AIEngine.Instance.VendorTypeDefinitions.find(vt => vt.Name === 'Model Developer');
92
+ const modelDeveloperType = aiengine_1.AIEngine.Instance.VendorTypeDefinitions.find((vt) => vt.Name === 'Model Developer');
93
93
  return modelVendor.TypeID !== modelDeveloperType?.ID;
94
94
  }
95
95
  return modelVendor.TypeID === inferenceProviderType.ID;
@@ -107,7 +107,7 @@ class AIPromptRunner {
107
107
  executionTimeMS: 0,
108
108
  chatResult: { success: false, errorMessage: 'Prompt execution was cancelled before starting' },
109
109
  tokensUsed: 0,
110
- combinedTokensUsed: 0
110
+ combinedTokensUsed: 0,
111
111
  };
112
112
  return result;
113
113
  }
@@ -194,9 +194,9 @@ class AIPromptRunner {
194
194
  prompt: params.prompt,
195
195
  metadata: {
196
196
  executionPhase: 'main-execution',
197
- hasChildPrompts: !!params.childPrompts?.length
197
+ hasChildPrompts: !!params.childPrompts?.length,
198
198
  },
199
- maxErrorLength: params.maxErrorLength
199
+ maxErrorLength: params.maxErrorLength,
200
200
  });
201
201
  const endTime = new Date();
202
202
  const executionTimeMS = endTime.getTime() - startTime.getTime();
@@ -219,9 +219,9 @@ class AIPromptRunner {
219
219
  category: 'PromptRunSave',
220
220
  metadata: {
221
221
  promptRunId: promptRun.ID,
222
- errorMessage: promptRun.LatestResult?.Message
222
+ errorMessage: promptRun.LatestResult?.Message,
223
223
  },
224
- maxErrorLength: params.maxErrorLength
224
+ maxErrorLength: params.maxErrorLength,
225
225
  });
226
226
  }
227
227
  }
@@ -232,7 +232,7 @@ class AIPromptRunner {
232
232
  executionTimeMS,
233
233
  chatResult: { success: false, errorMessage: error.message },
234
234
  tokensUsed: 0,
235
- combinedTokensUsed: 0
235
+ combinedTokensUsed: 0,
236
236
  };
237
237
  return errorResult;
238
238
  }
@@ -250,8 +250,7 @@ class AIPromptRunner {
250
250
  if (modelSelectionInfo) {
251
251
  const vendorID = modelSelectionInfo.vendorSelected?.ID;
252
252
  const modelID = modelSelectionInfo.modelSelected.ID;
253
- const modelVendor = aiengine_1.AIEngine.Instance.ModelVendors.find(mv => mv.VendorID === vendorID &&
254
- mv.ModelID === modelID);
253
+ const modelVendor = aiengine_1.AIEngine.Instance.ModelVendors.find((mv) => mv.VendorID === vendorID && mv.ModelID === modelID);
255
254
  if (modelVendor) {
256
255
  vendorDriverClass = modelVendor.DriverClass;
257
256
  vendorApiName = modelVendor.APIName;
@@ -279,7 +278,8 @@ class AIPromptRunner {
279
278
  if (params.cancellationToken?.aborted) {
280
279
  throw new Error('Prompt execution was cancelled after model selection');
281
280
  }
282
- const promptRun = existingPromptRun || await this.createPromptRun(prompt, selectedModel, params, renderedPromptText, startTime, params.override?.vendorId, modelSelectionInfo);
281
+ const promptRun = existingPromptRun ||
282
+ (await this.createPromptRun(prompt, selectedModel, params, renderedPromptText, startTime, params.override?.vendorId, modelSelectionInfo));
283
283
  if (params.cancellationToken?.aborted) {
284
284
  throw new Error('Prompt execution was cancelled before model execution');
285
285
  }
@@ -298,13 +298,13 @@ class AIPromptRunner {
298
298
  executionTimeMS,
299
299
  promptTokens: cumulativeTokens.promptTokens || usage?.promptTokens,
300
300
  completionTokens: cumulativeTokens.completionTokens || usage?.completionTokens,
301
- tokensUsed: (cumulativeTokens.promptTokens + cumulativeTokens.completionTokens) || ((usage?.promptTokens || 0) + (usage?.completionTokens || 0)),
301
+ tokensUsed: cumulativeTokens.promptTokens + cumulativeTokens.completionTokens || (usage?.promptTokens || 0) + (usage?.completionTokens || 0),
302
302
  cost: cumulativeTokens.totalCost || usage?.cost,
303
303
  costCurrency: usage?.costCurrency,
304
304
  validationResult: parsedResult.validationResult,
305
305
  validationAttempts,
306
- combinedTokensUsed: (cumulativeTokens.promptTokens + cumulativeTokens.completionTokens) || ((usage?.promptTokens || 0) + (usage?.completionTokens || 0)),
307
- modelSelectionInfo
306
+ combinedTokensUsed: cumulativeTokens.promptTokens + cumulativeTokens.completionTokens || (usage?.promptTokens || 0) + (usage?.completionTokens || 0),
307
+ modelSelectionInfo,
308
308
  };
309
309
  }
310
310
  async executePromptInParallel(prompt, renderedPromptText, params, startTime, existingPromptRun, existingModel, existingModelSelectionInfo) {
@@ -314,7 +314,8 @@ class AIPromptRunner {
314
314
  await aiengine_1.AIEngine.Instance.Config(false, params.contextUser);
315
315
  let executionTasks;
316
316
  if (existingModel) {
317
- executionTasks = [{
317
+ executionTasks = [
318
+ {
318
319
  taskId: 'pre-selected',
319
320
  model: existingModel,
320
321
  vendorDriverClass: undefined,
@@ -322,8 +323,9 @@ class AIPromptRunner {
322
323
  messages: params.conversationMessages || [],
323
324
  promptText: renderedPromptText,
324
325
  templateMessageRole: params.templateMessageRole || 'system',
325
- contextUser: params.contextUser
326
- }];
326
+ contextUser: params.contextUser,
327
+ },
328
+ ];
327
329
  this.logStatus(` Using pre-selected model "${existingModel.Name}" for parallel execution`, true, params);
328
330
  }
329
331
  else {
@@ -377,7 +379,8 @@ class AIPromptRunner {
377
379
  }
378
380
  }
379
381
  }
380
- const consolidatedPromptRun = existingPromptRun || await this.createPromptRun(prompt, selectedResult.task.model, params, renderedPromptText, startTime, params.override?.vendorId, existingModelSelectionInfo);
382
+ const consolidatedPromptRun = existingPromptRun ||
383
+ (await this.createPromptRun(prompt, selectedResult.task.model, params, renderedPromptText, startTime, params.override?.vendorId, existingModelSelectionInfo));
381
384
  const endTime = new Date();
382
385
  consolidatedPromptRun.CompletedAt = endTime;
383
386
  consolidatedPromptRun.ExecutionTimeMS = parallelResult.totalExecutionTimeMS;
@@ -425,9 +428,9 @@ class AIPromptRunner {
425
428
  metadata: {
426
429
  promptRunId: consolidatedPromptRun.ID,
427
430
  executionTasks: executionTasks.length,
428
- successfulResults: successfulResults.length
431
+ successfulResults: successfulResults.length,
429
432
  },
430
- maxErrorLength: params.maxErrorLength
433
+ maxErrorLength: params.maxErrorLength,
431
434
  });
432
435
  }
433
436
  const additionalResults = [];
@@ -462,7 +465,7 @@ class AIPromptRunner {
462
465
  vendorId: undefined,
463
466
  vendorName: result.task.model.Vendor,
464
467
  },
465
- combinedTokensUsed: (resultUsage?.promptTokens || 0) + (resultUsage?.completionTokens || 0)
468
+ combinedTokensUsed: (resultUsage?.promptTokens || 0) + (resultUsage?.completionTokens || 0),
466
469
  });
467
470
  }
468
471
  }
@@ -509,8 +512,8 @@ class AIPromptRunner {
509
512
  category: 'TemplateLoading',
510
513
  metadata: {
511
514
  templateId,
512
- phase: 'lookup'
513
- }
515
+ phase: 'lookup',
516
+ },
514
517
  });
515
518
  return null;
516
519
  }
@@ -518,7 +521,7 @@ class AIPromptRunner {
518
521
  async renderChildPromptTemplates(childPrompts, params, cancellationToken) {
519
522
  if (!childPrompts || childPrompts.length === 0) {
520
523
  return {
521
- renderedTemplates: {}
524
+ renderedTemplates: {},
522
525
  };
523
526
  }
524
527
  if (cancellationToken?.aborted) {
@@ -545,13 +548,13 @@ class AIPromptRunner {
545
548
  const mergedChildData = {
546
549
  ...params.data,
547
550
  ...childData,
548
- ...childParam.childPrompt.templateData
551
+ ...childParam.childPrompt.templateData,
549
552
  };
550
553
  const childRenderResult = await this.renderPromptTemplate(template, {
551
554
  ...params,
552
555
  prompt: childPrompt,
553
556
  data: mergedChildData,
554
- templateData: childParam.childPrompt.templateData
557
+ templateData: childParam.childPrompt.templateData,
555
558
  });
556
559
  if (!childRenderResult.Success) {
557
560
  throw new Error(`Failed to render child template for prompt ${childPrompt.Name}: ${childRenderResult.Message}`);
@@ -564,26 +567,26 @@ class AIPromptRunner {
564
567
  return {
565
568
  placeholder: childParam.parentPlaceholder,
566
569
  renderedTemplate: renderedChildTemplate,
567
- success: true
570
+ success: true,
568
571
  };
569
572
  }
570
573
  catch (error) {
571
574
  this.logError(error, {
572
575
  category: 'ChildTemplateRendering',
573
576
  metadata: {
574
- placeholder: childParam.parentPlaceholder
577
+ placeholder: childParam.parentPlaceholder,
575
578
  },
576
- maxErrorLength: params.maxErrorLength
579
+ maxErrorLength: params.maxErrorLength,
577
580
  });
578
581
  return {
579
582
  placeholder: childParam.parentPlaceholder,
580
583
  renderedTemplate: `ERROR: ${error.message}`,
581
- success: false
584
+ success: false,
582
585
  };
583
586
  }
584
587
  });
585
588
  const childResults = await Promise.all(childRenderingPromises);
586
- const failedChildren = childResults.filter(r => !r.success);
589
+ const failedChildren = childResults.filter((r) => !r.success);
587
590
  if (failedChildren.length > 0) {
588
591
  this.logError(`${failedChildren.length} out of ${childResults.length} child prompt templates failed to render`, {
589
592
  category: 'ChildTemplateFailures',
@@ -591,18 +594,18 @@ class AIPromptRunner {
591
594
  metadata: {
592
595
  failedCount: failedChildren.length,
593
596
  totalCount: childResults.length,
594
- failedPlaceholders: failedChildren.map(fc => fc.placeholder)
597
+ failedPlaceholders: failedChildren.map((fc) => fc.placeholder),
595
598
  },
596
- maxErrorLength: params.maxErrorLength
599
+ maxErrorLength: params.maxErrorLength,
597
600
  });
598
- throw new Error(`Failed to render ${failedChildren.length} child prompt templates: ${failedChildren.map(fc => fc.placeholder).join(', ')}`);
601
+ throw new Error(`Failed to render ${failedChildren.length} child prompt templates: ${failedChildren.map((fc) => fc.placeholder).join(', ')}`);
599
602
  }
600
603
  const renderedTemplatesMap = {};
601
604
  for (const childResult of childResults) {
602
605
  renderedTemplatesMap[childResult.placeholder] = childResult.renderedTemplate;
603
606
  }
604
607
  return {
605
- renderedTemplates: renderedTemplatesMap
608
+ renderedTemplates: renderedTemplatesMap,
606
609
  };
607
610
  }
608
611
  async renderPromptWithChildTemplates(prompt, params, childTemplates) {
@@ -620,7 +623,7 @@ class AIPromptRunner {
620
623
  ...systemPlaceholders,
621
624
  ...params.data,
622
625
  ...childTemplates,
623
- ...params.templateData
626
+ ...params.templateData,
624
627
  };
625
628
  this.logStatus(` 🔧 ${prompt.Name} [Rendering Prompt Template]`, true, params);
626
629
  for (const [placeholder, template] of Object.entries(childTemplates)) {
@@ -638,9 +641,9 @@ class AIPromptRunner {
638
641
  prompt: prompt,
639
642
  metadata: {
640
643
  childPromptCount: params.childPrompts?.length || 0,
641
- templateId: prompt.TemplateID
644
+ templateId: prompt.TemplateID,
642
645
  },
643
- maxErrorLength: params.maxErrorLength
646
+ maxErrorLength: params.maxErrorLength,
644
647
  });
645
648
  throw error;
646
649
  }
@@ -661,7 +664,7 @@ class AIPromptRunner {
661
664
  selectionStrategy = 'ByPower';
662
665
  }
663
666
  if (configurationId) {
664
- configuration = aiengine_1.AIEngine.Instance.Configurations.find(c => c.ID === configurationId);
667
+ configuration = aiengine_1.AIEngine.Instance.Configurations.find((c) => c.ID === configurationId);
665
668
  configurationName = configuration?.Name;
666
669
  }
667
670
  const candidates = this.buildModelVendorCandidates(prompt, explicitModelId, configurationId, vendorId, params.verbose);
@@ -671,7 +674,7 @@ class AIPromptRunner {
671
674
  category: 'ModelSelection',
672
675
  prompt: prompt,
673
676
  severity: 'critical',
674
- maxErrorLength: params?.maxErrorLength
677
+ maxErrorLength: params?.maxErrorLength,
675
678
  });
676
679
  return {
677
680
  model: null,
@@ -685,8 +688,8 @@ class AIPromptRunner {
685
688
  modelSelected: undefined,
686
689
  selectionReason: 'No suitable model candidates found',
687
690
  fallbackUsed: false,
688
- selectionStrategy
689
- })
691
+ selectionStrategy,
692
+ }),
690
693
  };
691
694
  }
692
695
  const { selected, consideredModels } = await this.selectModelWithAPIKeyTracked(candidates, params);
@@ -704,8 +707,8 @@ class AIPromptRunner {
704
707
  modelSelected: undefined,
705
708
  selectionReason: 'No API keys found for any model-vendor combination',
706
709
  fallbackUsed: false,
707
- selectionStrategy
708
- })
710
+ selectionStrategy,
711
+ }),
709
712
  };
710
713
  }
711
714
  let selectionReason = `Selected ${selected.model.Name} via ${selected.vendorName || 'default vendor'}`;
@@ -727,7 +730,7 @@ class AIPromptRunner {
727
730
  const fallbackUsed = candidates.indexOf(selected) > 0;
728
731
  let selectedVendor;
729
732
  if (selected.vendorId) {
730
- selectedVendor = aiengine_1.AIEngine.Instance.Vendors.find(v => v.ID === selected.vendorId);
733
+ selectedVendor = aiengine_1.AIEngine.Instance.Vendors.find((v) => v.ID === selected.vendorId);
731
734
  }
732
735
  return {
733
736
  model: selected.model,
@@ -742,15 +745,15 @@ class AIPromptRunner {
742
745
  vendorSelected: selectedVendor,
743
746
  selectionReason,
744
747
  fallbackUsed,
745
- selectionStrategy
746
- })
748
+ selectionStrategy,
749
+ }),
747
750
  };
748
751
  }
749
752
  catch (error) {
750
753
  this.logError(error, {
751
754
  category: 'ModelSelection',
752
755
  prompt: prompt,
753
- maxErrorLength: params?.maxErrorLength
756
+ maxErrorLength: params?.maxErrorLength,
754
757
  });
755
758
  return {
756
759
  model: null,
@@ -764,21 +767,18 @@ class AIPromptRunner {
764
767
  modelSelected: undefined,
765
768
  selectionReason: `Error during model selection: ${error.message}`,
766
769
  fallbackUsed: false,
767
- selectionStrategy: 'Default'
768
- })
770
+ selectionStrategy: 'Default',
771
+ }),
769
772
  };
770
773
  }
771
774
  }
772
775
  buildModelVendorCandidates(prompt, explicitModelId, configurationId, preferredVendorId, verbose) {
773
- const preferredVendorName = preferredVendorId ?
774
- aiengine_1.AIEngine.Instance.Vendors.find(v => v.ID === preferredVendorId)?.Name : undefined;
776
+ const preferredVendorName = preferredVendorId ? aiengine_1.AIEngine.Instance.Vendors.find((v) => v.ID === preferredVendorId)?.Name : undefined;
775
777
  const createCandidatesForModel = (model, basePriority, source, promptModelPriority) => {
776
778
  const modelCandidates = [];
777
- const modelVendors = aiengine_1.AIEngine.Instance.ModelVendors
778
- .filter(mv => mv.ModelID === model.ID && mv.Status === 'Active' && this.isInferenceProvider(mv))
779
- .sort((a, b) => b.Priority - a.Priority);
779
+ const modelVendors = aiengine_1.AIEngine.Instance.ModelVendors.filter((mv) => mv.ModelID === model.ID && mv.Status === 'Active' && this.isInferenceProvider(mv)).sort((a, b) => b.Priority - a.Priority);
780
780
  if (preferredVendorId) {
781
- const preferredVendor = modelVendors.find(mv => mv.VendorID === preferredVendorId);
781
+ const preferredVendor = modelVendors.find((mv) => mv.VendorID === preferredVendorId);
782
782
  if (preferredVendor) {
783
783
  modelCandidates.push({
784
784
  model,
@@ -789,7 +789,7 @@ class AIPromptRunner {
789
789
  supportsEffortLevel: preferredVendor.SupportsEffortLevel ?? model.SupportsEffortLevel ?? false,
790
790
  isPreferredVendor: true,
791
791
  priority: basePriority + 1000,
792
- source
792
+ source,
793
793
  });
794
794
  }
795
795
  }
@@ -804,7 +804,7 @@ class AIPromptRunner {
804
804
  supportsEffortLevel: vendor.SupportsEffortLevel ?? model.SupportsEffortLevel ?? false,
805
805
  isPreferredVendor: false,
806
806
  priority: basePriority + (vendor.Priority || 0),
807
- source
807
+ source,
808
808
  });
809
809
  }
810
810
  }
@@ -816,22 +816,21 @@ class AIPromptRunner {
816
816
  supportsEffortLevel: model.SupportsEffortLevel ?? false,
817
817
  isPreferredVendor: false,
818
818
  priority: basePriority,
819
- source
819
+ source,
820
820
  });
821
821
  }
822
822
  if (promptModelPriority !== undefined) {
823
- modelCandidates.forEach(c => c.priority += promptModelPriority * 10);
823
+ modelCandidates.forEach((c) => (c.priority += promptModelPriority * 10));
824
824
  }
825
825
  return modelCandidates;
826
826
  };
827
827
  const createSpecificCandidatesForModel = (model, promptModel, preferredVendorId) => {
828
828
  const modelCandidates = [];
829
829
  const basePriority = 10000 + (promptModel.Priority || 0) * 100;
830
- const modelVendors = aiengine_1.AIEngine.Instance.ModelVendors
831
- .filter(mv => mv.ModelID === model.ID && mv.Status === 'Active' && this.isInferenceProvider(mv));
830
+ const modelVendors = aiengine_1.AIEngine.Instance.ModelVendors.filter((mv) => mv.ModelID === model.ID && mv.Status === 'Active' && this.isInferenceProvider(mv));
832
831
  const pmPreferredVendorId = promptModel.VendorID || preferredVendorId;
833
832
  if (pmPreferredVendorId) {
834
- const preferredVendor = modelVendors.find(mv => mv.VendorID === pmPreferredVendorId);
833
+ const preferredVendor = modelVendors.find((mv) => mv.VendorID === pmPreferredVendorId);
835
834
  if (preferredVendor) {
836
835
  modelCandidates.push({
837
836
  model,
@@ -842,7 +841,7 @@ class AIPromptRunner {
842
841
  supportsEffortLevel: preferredVendor.SupportsEffortLevel ?? model.SupportsEffortLevel ?? false,
843
842
  isPreferredVendor: true,
844
843
  priority: basePriority + 1000,
845
- source: 'prompt-model'
844
+ source: 'prompt-model',
846
845
  });
847
846
  }
848
847
  }
@@ -857,7 +856,7 @@ class AIPromptRunner {
857
856
  supportsEffortLevel: vendor.SupportsEffortLevel ?? model.SupportsEffortLevel ?? false,
858
857
  isPreferredVendor: false,
859
858
  priority: basePriority + (vendor.Priority || 0) * 10,
860
- source: 'prompt-model'
859
+ source: 'prompt-model',
861
860
  });
862
861
  }
863
862
  }
@@ -869,13 +868,13 @@ class AIPromptRunner {
869
868
  supportsEffortLevel: model.SupportsEffortLevel ?? false,
870
869
  isPreferredVendor: false,
871
870
  priority: basePriority,
872
- source: 'prompt-model'
871
+ source: 'prompt-model',
873
872
  });
874
873
  }
875
874
  return modelCandidates;
876
875
  };
877
876
  if (explicitModelId) {
878
- const model = aiengine_1.AIEngine.Instance.Models.find(m => m.ID === explicitModelId);
877
+ const model = aiengine_1.AIEngine.Instance.Models.find((m) => m.ID === explicitModelId);
879
878
  if (model && model.IsActive) {
880
879
  if (!prompt.AIModelTypeID || model.AIModelTypeID === prompt.AIModelTypeID) {
881
880
  const candidates = createCandidatesForModel(model, 20000, 'explicit');
@@ -887,26 +886,20 @@ class AIPromptRunner {
887
886
  }
888
887
  let promptModels = [];
889
888
  if (configurationId) {
890
- promptModels = aiengine_1.AIEngine.Instance.PromptModels.filter(pm => pm.PromptID === prompt.ID &&
891
- (pm.Status === 'Active' || pm.Status === 'Preview') &&
892
- pm.ConfigurationID === configurationId);
889
+ promptModels = aiengine_1.AIEngine.Instance.PromptModels.filter((pm) => pm.PromptID === prompt.ID && (pm.Status === 'Active' || pm.Status === 'Preview') && pm.ConfigurationID === configurationId);
893
890
  if (promptModels.length === 0) {
894
- (0, core_1.LogStatus)(`No models found for configuration "${configurationId}", falling back to default models`);
895
- promptModels = aiengine_1.AIEngine.Instance.PromptModels.filter(pm => pm.PromptID === prompt.ID &&
896
- (pm.Status === 'Active' || pm.Status === 'Preview') &&
897
- !pm.ConfigurationID);
891
+ (0, global_1.LogStatus)(`No models found for configuration "${configurationId}", falling back to default models`);
892
+ promptModels = aiengine_1.AIEngine.Instance.PromptModels.filter((pm) => pm.PromptID === prompt.ID && (pm.Status === 'Active' || pm.Status === 'Preview') && !pm.ConfigurationID);
898
893
  }
899
894
  }
900
895
  else {
901
- promptModels = aiengine_1.AIEngine.Instance.PromptModels.filter(pm => pm.PromptID === prompt.ID &&
902
- (pm.Status === 'Active' || pm.Status === 'Preview') &&
903
- !pm.ConfigurationID);
896
+ promptModels = aiengine_1.AIEngine.Instance.PromptModels.filter((pm) => pm.PromptID === prompt.ID && (pm.Status === 'Active' || pm.Status === 'Preview') && !pm.ConfigurationID);
904
897
  }
905
898
  if (prompt.SelectionStrategy === 'Specific' && promptModels.length > 0) {
906
899
  const candidates = [];
907
900
  promptModels.sort((a, b) => (b.Priority || 0) - (a.Priority || 0));
908
901
  for (const pm of promptModels) {
909
- const model = aiengine_1.AIEngine.Instance.Models.find(m => m.ID === pm.ModelID);
902
+ const model = aiengine_1.AIEngine.Instance.Models.find((m) => m.ID === pm.ModelID);
910
903
  if (model && model.IsActive) {
911
904
  const modelCandidates = createSpecificCandidatesForModel(model, pm, preferredVendorId);
912
905
  candidates.push(...modelCandidates);
@@ -915,32 +908,30 @@ class AIPromptRunner {
915
908
  if (candidates.length > 0) {
916
909
  candidates.sort((a, b) => b.priority - a.priority);
917
910
  if (verbose) {
918
- (0, core_1.LogStatus)(`Using SelectionStrategy='Specific' with ${promptModels.length} AIPromptModel entries, generated ${candidates.length} candidates`);
911
+ (0, global_1.LogStatus)(`Using SelectionStrategy='Specific' with ${promptModels.length} AIPromptModel entries, generated ${candidates.length} candidates`);
919
912
  }
920
913
  return candidates;
921
914
  }
922
915
  if (verbose) {
923
- (0, core_1.LogStatus)(`SelectionStrategy='Specific' specified but no usable candidates from AIPromptModel entries, falling back to general selection`);
916
+ (0, global_1.LogStatus)(`SelectionStrategy='Specific' specified but no usable candidates from AIPromptModel entries, falling back to general selection`);
924
917
  }
925
918
  }
926
919
  const candidates = [];
927
920
  if (promptModels.length > 0 && prompt.SelectionStrategy !== 'Specific') {
928
921
  for (const pm of promptModels) {
929
- const model = aiengine_1.AIEngine.Instance.Models.find(m => m.ID === pm.ModelID);
922
+ const model = aiengine_1.AIEngine.Instance.Models.find((m) => m.ID === pm.ModelID);
930
923
  if (model && model.IsActive) {
931
924
  const modelCandidates = createCandidatesForModel(model, 5000, 'prompt-model', pm.Priority);
932
925
  candidates.push(...modelCandidates);
933
926
  }
934
927
  }
935
928
  if (configurationId) {
936
- const nullConfigModels = aiengine_1.AIEngine.Instance.PromptModels.filter(pm => pm.PromptID === prompt.ID &&
937
- (pm.Status === 'Active' || pm.Status === 'Preview') &&
938
- !pm.ConfigurationID);
929
+ const nullConfigModels = aiengine_1.AIEngine.Instance.PromptModels.filter((pm) => pm.PromptID === prompt.ID && (pm.Status === 'Active' || pm.Status === 'Preview') && !pm.ConfigurationID);
939
930
  if (nullConfigModels.length > 0 && verbose) {
940
- (0, core_1.LogStatus)(`Adding ${nullConfigModels.length} NULL configuration models as fallback candidates`);
931
+ (0, global_1.LogStatus)(`Adding ${nullConfigModels.length} NULL configuration models as fallback candidates`);
941
932
  }
942
933
  for (const pm of nullConfigModels) {
943
- const model = aiengine_1.AIEngine.Instance.Models.find(m => m.ID === pm.ModelID);
934
+ const model = aiengine_1.AIEngine.Instance.Models.find((m) => m.ID === pm.ModelID);
944
935
  if (model && model.IsActive) {
945
936
  const modelCandidates = createCandidatesForModel(model, 2000, 'prompt-model', pm.Priority);
946
937
  candidates.push(...modelCandidates);
@@ -949,13 +940,10 @@ class AIPromptRunner {
949
940
  }
950
941
  }
951
942
  else {
952
- let modelPool = aiengine_1.AIEngine.Instance.Models.filter(m => m.IsActive &&
943
+ let modelPool = aiengine_1.AIEngine.Instance.Models.filter((m) => m.IsActive &&
953
944
  (!prompt.AIModelTypeID || m.AIModelTypeID === prompt.AIModelTypeID) &&
954
945
  (!preferredVendorName ||
955
- aiengine_1.AIEngine.Instance.ModelVendors.some(mv => mv.ModelID === m.ID &&
956
- mv.Status === 'Active' &&
957
- mv.Vendor === preferredVendorName &&
958
- this.isInferenceProvider(mv))));
946
+ aiengine_1.AIEngine.Instance.ModelVendors.some((mv) => mv.ModelID === m.ID && mv.Status === 'Active' && mv.Vendor === preferredVendorName && this.isInferenceProvider(mv))));
959
947
  switch (prompt.SelectionStrategy) {
960
948
  case 'ByPower':
961
949
  switch (prompt.PowerPreference) {
@@ -975,7 +963,7 @@ class AIPromptRunner {
975
963
  case 'Default':
976
964
  default:
977
965
  const minPowerRank = prompt.MinPowerRank || 0;
978
- modelPool = modelPool.filter(m => m.PowerRank >= minPowerRank);
966
+ modelPool = modelPool.filter((m) => m.PowerRank >= minPowerRank);
979
967
  modelPool.sort((a, b) => b.PowerRank - a.PowerRank);
980
968
  break;
981
969
  }
@@ -994,10 +982,10 @@ class AIPromptRunner {
994
982
  }
995
983
  buildCandidatesFromSelectionInfo(selectionInfo) {
996
984
  const validModels = selectionInfo.extractValidCandidates();
997
- return validModels.map(considered => {
985
+ return validModels
986
+ .map((considered) => {
998
987
  const modelVendor = considered.vendor
999
- ? aiengine_1.AIEngine.Instance.ModelVendors.find(mv => mv.ModelID === considered.model.ID &&
1000
- mv.VendorID === considered.vendor.ID)
988
+ ? aiengine_1.AIEngine.Instance.ModelVendors.find((mv) => mv.ModelID === considered.model.ID && mv.VendorID === considered.vendor.ID)
1001
989
  : undefined;
1002
990
  return {
1003
991
  model: considered.model,
@@ -1008,9 +996,10 @@ class AIPromptRunner {
1008
996
  supportsEffortLevel: modelVendor?.SupportsEffortLevel ?? considered.model.SupportsEffortLevel ?? false,
1009
997
  isPreferredVendor: false,
1010
998
  priority: considered.priority,
1011
- source: (selectionInfo.selectionStrategy === 'ByPower' ? 'power-rank' : 'model-type')
999
+ source: (selectionInfo.selectionStrategy === 'ByPower' ? 'power-rank' : 'model-type'),
1012
1000
  };
1013
- }).sort((a, b) => b.priority - a.priority);
1001
+ })
1002
+ .sort((a, b) => b.priority - a.priority);
1014
1003
  }
1015
1004
  async selectModelWithAPIKeyTracked(candidates, params) {
1016
1005
  const checkedDrivers = new Map();
@@ -1027,21 +1016,22 @@ class AIPromptRunner {
1027
1016
  }
1028
1017
  let vendorEntity;
1029
1018
  if (candidate.vendorId) {
1030
- vendorEntity = aiengine_1.AIEngine.Instance.Vendors.find(v => v.ID === candidate.vendorId);
1019
+ vendorEntity = aiengine_1.AIEngine.Instance.Vendors.find((v) => v.ID === candidate.vendorId);
1031
1020
  }
1032
1021
  consideredModels.push({
1033
1022
  model: candidate.model,
1034
1023
  vendor: vendorEntity,
1035
1024
  priority: candidate.priority,
1036
1025
  available: hasKey,
1037
- unavailableReason: hasKey ? undefined : `No API key for driver ${candidate.driverClass}`
1026
+ unavailableReason: hasKey ? undefined : `No API key for driver ${candidate.driverClass}`,
1038
1027
  });
1039
1028
  }
1040
- const selected = consideredModels.find(m => m.available);
1041
- const selectedCandidate = selected ? candidates.find(c => c.model.ID === selected.model.ID &&
1042
- c.vendorId === selected.vendor?.ID) : null;
1029
+ const selected = consideredModels.find((m) => m.available);
1030
+ const selectedCandidate = selected
1031
+ ? candidates.find((c) => c.model.ID === selected.model.ID && c.vendorId === selected.vendor?.ID)
1032
+ : null;
1043
1033
  if (selectedCandidate) {
1044
- const validCount = consideredModels.filter(m => m.available).length;
1034
+ const validCount = consideredModels.filter((m) => m.available).length;
1045
1035
  this.logStatus(` Selected model ${selectedCandidate.model.Name} with ${selectedCandidate.vendorName || 'default'} vendor (driver: ${selectedCandidate.driverClass})`, true);
1046
1036
  if (selectedCandidate.isPreferredVendor) {
1047
1037
  this.logStatus(` Using preferred vendor${selectedCandidate.vendorId ? ` (${selectedCandidate.vendorName})` : ''}`, true, params);
@@ -1049,15 +1039,18 @@ class AIPromptRunner {
1049
1039
  this.logStatus(` Found ${validCount} valid candidate(s) out of ${candidates.length} total`, true, params);
1050
1040
  }
1051
1041
  else {
1052
- const triedSummary = candidates.slice(0, 5).map(c => `${c.model.Name}/${c.vendorName || 'default'}(${c.driverClass})`).join(', ');
1042
+ const triedSummary = candidates
1043
+ .slice(0, 5)
1044
+ .map((c) => `${c.model.Name}/${c.vendorName || 'default'}(${c.driverClass})`)
1045
+ .join(', ');
1053
1046
  this.logError(`No API keys found for any model-vendor combination. Tried: ${triedSummary}${candidates.length > 5 ? `... (${candidates.length} total)` : ''}`, {
1054
1047
  category: 'APIKeyValidation',
1055
1048
  severity: 'critical',
1056
1049
  metadata: {
1057
1050
  candidatesChecked: candidates.length,
1058
- modelsChecked: consideredModels.length
1051
+ modelsChecked: consideredModels.length,
1059
1052
  },
1060
- maxErrorLength: params?.maxErrorLength
1053
+ maxErrorLength: params?.maxErrorLength,
1061
1054
  });
1062
1055
  }
1063
1056
  return { selected: selectedCandidate, consideredModels };
@@ -1077,20 +1070,20 @@ class AIPromptRunner {
1077
1070
  const dbSelectionInfo = {
1078
1071
  configurationId: modelSelectionInfo.aiConfiguration?.ID,
1079
1072
  configurationName: modelSelectionInfo.aiConfiguration?.Name,
1080
- modelsConsidered: modelSelectionInfo.modelsConsidered.map(mc => ({
1073
+ modelsConsidered: modelSelectionInfo.modelsConsidered.map((mc) => ({
1081
1074
  modelId: mc.model.ID,
1082
1075
  modelName: mc.model.Name,
1083
1076
  vendorId: mc.vendor?.ID,
1084
1077
  vendorName: mc.vendor?.Name || 'default',
1085
1078
  priority: mc.priority,
1086
1079
  available: mc.available,
1087
- unavailableReason: mc.unavailableReason
1080
+ unavailableReason: mc.unavailableReason,
1088
1081
  })),
1089
1082
  modelSelected: modelSelectionInfo.modelSelected?.ID,
1090
1083
  vendorSelected: modelSelectionInfo.vendorSelected?.ID,
1091
1084
  selectionReason: modelSelectionInfo.selectionReason,
1092
1085
  fallbackUsed: modelSelectionInfo.fallbackUsed,
1093
- selectionStrategy: modelSelectionInfo.selectionStrategy
1086
+ selectionStrategy: modelSelectionInfo.selectionStrategy,
1094
1087
  };
1095
1088
  promptRun.ModelSelection = JSON.stringify(dbSelectionInfo);
1096
1089
  promptRun.SelectionStrategy = modelSelectionInfo.selectionStrategy || 'Default';
@@ -1115,9 +1108,7 @@ class AIPromptRunner {
1115
1108
  promptRun.VendorID = modelWithVendor._selectedVendorId;
1116
1109
  }
1117
1110
  else {
1118
- const modelVendors = aiengine_1.AIEngine.Instance.ModelVendors
1119
- .filter((mv) => mv.ModelID === model.ID && mv.Status === 'Active' && this.isInferenceProvider(mv))
1120
- .sort((a, b) => b.Priority - a.Priority);
1111
+ const modelVendors = aiengine_1.AIEngine.Instance.ModelVendors.filter((mv) => mv.ModelID === model.ID && mv.Status === 'Active' && this.isInferenceProvider(mv)).sort((a, b) => b.Priority - a.Priority);
1121
1112
  if (modelVendors.length > 0) {
1122
1113
  promptRun.VendorID = modelVendors[0].VendorID;
1123
1114
  }
@@ -1199,9 +1190,9 @@ class AIPromptRunner {
1199
1190
  if (systemPromptText) {
1200
1191
  messages.push({
1201
1192
  role: 'system',
1202
- content: systemPromptText
1193
+ content: systemPromptText,
1203
1194
  });
1204
- messages.push(...params.conversationMessages || []);
1195
+ messages.push(...(params.conversationMessages || []));
1205
1196
  }
1206
1197
  promptRun.Messages = JSON.stringify({
1207
1198
  data: params.data,
@@ -1224,9 +1215,9 @@ class AIPromptRunner {
1224
1215
  metadata: {
1225
1216
  promptId: prompt.ID,
1226
1217
  modelId: model.ID,
1227
- vendorId
1218
+ vendorId,
1228
1219
  },
1229
- maxErrorLength: params.maxErrorLength
1220
+ maxErrorLength: params.maxErrorLength,
1230
1221
  });
1231
1222
  throw new Error(error);
1232
1223
  }
@@ -1235,7 +1226,7 @@ class AIPromptRunner {
1235
1226
  await params.onPromptRunCreated(promptRun.ID);
1236
1227
  }
1237
1228
  catch (callbackError) {
1238
- (0, core_1.LogStatus)(`Error in onPromptRunCreated callback: ${callbackError.message}`);
1229
+ (0, global_1.LogStatus)(`Error in onPromptRunCreated callback: ${callbackError.message}`);
1239
1230
  }
1240
1231
  }
1241
1232
  return promptRun;
@@ -1246,9 +1237,9 @@ class AIPromptRunner {
1246
1237
  category: 'PromptRunSave',
1247
1238
  metadata: {
1248
1239
  promptRunId: promptRun.ID,
1249
- saveError: promptRun.LatestResult?.Message
1240
+ saveError: promptRun.LatestResult?.Message,
1250
1241
  },
1251
- maxErrorLength: params.maxErrorLength
1242
+ maxErrorLength: params.maxErrorLength,
1252
1243
  });
1253
1244
  throw new Error(msg);
1254
1245
  }
@@ -1263,7 +1254,7 @@ class AIPromptRunner {
1263
1254
  const mergedData = {
1264
1255
  ...systemPlaceholders,
1265
1256
  ...params.data,
1266
- ...params.templateData
1257
+ ...params.templateData,
1267
1258
  };
1268
1259
  return await this._templateEngine.RenderTemplate(template, templateContent, mergedData);
1269
1260
  }
@@ -1273,9 +1264,9 @@ class AIPromptRunner {
1273
1264
  metadata: {
1274
1265
  templateId: template.ID,
1275
1266
  templateName: template.Name,
1276
- hasChildPrompts: !!params.childPrompts?.length
1267
+ hasChildPrompts: !!params.childPrompts?.length,
1277
1268
  },
1278
- maxErrorLength: params.maxErrorLength
1269
+ maxErrorLength: params.maxErrorLength,
1279
1270
  });
1280
1271
  throw error;
1281
1272
  }
@@ -1299,17 +1290,19 @@ class AIPromptRunner {
1299
1290
  try {
1300
1291
  if (attemptNumber > 1) {
1301
1292
  const vendorName = currentVendorId
1302
- ? aiengine_1.AIEngine.Instance.Vendors.find(v => v.ID === currentVendorId)?.Name || 'Unknown'
1293
+ ? aiengine_1.AIEngine.Instance.Vendors.find((v) => v.ID === currentVendorId)?.Name || 'Unknown'
1303
1294
  : 'default';
1304
- (0, core_1.LogStatusEx)({
1295
+ (0, global_1.LogStatusEx)({
1305
1296
  message: `🔄 Failover attempt ${attemptNumber} with model ${currentModel.Name} (vendor: ${currentVendorId || 'default'})`,
1306
1297
  category: 'AI',
1307
- additionalArgs: [{
1298
+ additionalArgs: [
1299
+ {
1308
1300
  promptId: prompt.ID,
1309
1301
  modelId: currentModel.ID,
1310
1302
  vendorId: currentVendorId,
1311
- attemptNumber
1312
- }]
1303
+ attemptNumber,
1304
+ },
1305
+ ],
1313
1306
  });
1314
1307
  }
1315
1308
  const result = await this.executeModel(currentModel, renderedPrompt, prompt, params, currentVendorId, conversationMessages, templateMessageRole, cancellationToken, vendorDriverClass, vendorApiName, vendorSupportsEffortLevel);
@@ -1329,7 +1322,7 @@ class AIPromptRunner {
1329
1322
  error: lastError,
1330
1323
  errorType: errorAnalysis.errorType,
1331
1324
  duration: attemptDuration,
1332
- timestamp: new Date()
1325
+ timestamp: new Date(),
1333
1326
  };
1334
1327
  failoverAttempts.push(failoverAttempt);
1335
1328
  allCandidates = this.filterAuthenticationFailedVendor(errorAnalysis.errorType, currentVendorId, allCandidates);
@@ -1362,11 +1355,11 @@ class AIPromptRunner {
1362
1355
  const aiEngine = aiengine_1.AIEngine.Instance;
1363
1356
  let allModels;
1364
1357
  if (prompt.AIModelTypeID) {
1365
- const modelType = aiEngine.ModelTypes.find(mt => mt.ID === prompt.AIModelTypeID);
1358
+ const modelType = aiEngine.ModelTypes.find((mt) => mt.ID === prompt.AIModelTypeID);
1366
1359
  if (!modelType) {
1367
1360
  throw new Error(`Model type ${prompt.AIModelTypeID} not found`);
1368
1361
  }
1369
- allModels = aiEngine.Models.filter(m => m.AIModelType?.trim().toLowerCase() === modelType.Name.trim().toLowerCase());
1362
+ allModels = aiEngine.Models.filter((m) => m.AIModelType?.trim().toLowerCase() === modelType.Name.trim().toLowerCase());
1370
1363
  }
1371
1364
  else {
1372
1365
  allModels = aiEngine.Models;
@@ -1387,7 +1380,7 @@ class AIPromptRunner {
1387
1380
  supportsEffortLevel: model.SupportsEffortLevel ?? false,
1388
1381
  isPreferredVendor: false,
1389
1382
  priority: model.PowerRank || 0,
1390
- source: 'power-rank'
1383
+ source: 'power-rank',
1391
1384
  });
1392
1385
  }
1393
1386
  else {
@@ -1401,7 +1394,7 @@ class AIPromptRunner {
1401
1394
  supportsEffortLevel: vendor.SupportsEffortLevel ?? model.SupportsEffortLevel ?? false,
1402
1395
  isPreferredVendor: vendor.Priority > 0,
1403
1396
  priority: (model.PowerRank || 0) + (vendor.Priority || 0),
1404
- source: 'power-rank'
1397
+ source: 'power-rank',
1405
1398
  });
1406
1399
  }
1407
1400
  }
@@ -1410,13 +1403,13 @@ class AIPromptRunner {
1410
1403
  }
1411
1404
  updatePromptRunWithFailoverSuccess(promptRun, failoverAttempts, currentModel, currentVendorId) {
1412
1405
  promptRun.FailoverAttempts = failoverAttempts.length;
1413
- promptRun.FailoverErrors = JSON.stringify(failoverAttempts.map(a => ({
1406
+ promptRun.FailoverErrors = JSON.stringify(failoverAttempts.map((a) => ({
1414
1407
  model: a.modelId,
1415
1408
  vendor: a.vendorId,
1416
1409
  error: a.error.message,
1417
- errorType: a.errorType
1410
+ errorType: a.errorType,
1418
1411
  })));
1419
- promptRun.FailoverDurations = JSON.stringify(failoverAttempts.map(a => a.duration));
1412
+ promptRun.FailoverDurations = JSON.stringify(failoverAttempts.map((a) => a.duration));
1420
1413
  promptRun.TotalFailoverDuration = failoverAttempts.reduce((sum, a) => sum + a.duration, 0);
1421
1414
  if (currentModel.ID !== promptRun.OriginalModelID) {
1422
1415
  promptRun.ModelID = currentModel.ID;
@@ -1427,20 +1420,19 @@ class AIPromptRunner {
1427
1420
  }
1428
1421
  updatePromptRunWithFailoverFailure(promptRun, failoverAttempts) {
1429
1422
  promptRun.FailoverAttempts = failoverAttempts.length;
1430
- promptRun.FailoverErrors = JSON.stringify(failoverAttempts.map(a => ({
1423
+ promptRun.FailoverErrors = JSON.stringify(failoverAttempts.map((a) => ({
1431
1424
  model: a.modelId,
1432
1425
  vendor: a.vendorId,
1433
1426
  error: a.error.message,
1434
- errorType: a.errorType
1427
+ errorType: a.errorType,
1435
1428
  })));
1436
- promptRun.FailoverDurations = JSON.stringify(failoverAttempts.map(a => a.duration));
1429
+ promptRun.FailoverDurations = JSON.stringify(failoverAttempts.map((a) => a.duration));
1437
1430
  promptRun.TotalFailoverDuration = failoverAttempts.reduce((sum, a) => sum + a.duration, 0);
1438
1431
  }
1439
1432
  createFailoverErrorResult(lastError, failoverAttempts) {
1440
1433
  const startTime = new Date();
1441
1434
  const endTime = new Date();
1442
- const hasContextLengthError = failoverAttempts.some(a => a.errorType === 'ContextLengthExceeded' ||
1443
- ai_1.ErrorAnalyzer.analyzeError(a.error).errorType === 'ContextLengthExceeded');
1435
+ const hasContextLengthError = failoverAttempts.some((a) => a.errorType === 'ContextLengthExceeded' || ai_1.ErrorAnalyzer.analyzeError(a.error).errorType === 'ContextLengthExceeded');
1444
1436
  let errorInfo;
1445
1437
  if (lastError) {
1446
1438
  errorInfo = ai_1.ErrorAnalyzer.analyzeError(lastError);
@@ -1457,7 +1449,7 @@ class AIPromptRunner {
1457
1449
  errorInfo: errorInfo,
1458
1450
  statusText: `Failover failed after ${failoverAttempts.length} attempts`,
1459
1451
  timeElapsed: endTime.getTime() - startTime.getTime(),
1460
- data: null
1452
+ data: null,
1461
1453
  };
1462
1454
  }
1463
1455
  async executeModel(model, renderedPrompt, prompt, params, vendorId, conversationMessages, templateMessageRole = 'system', cancellationToken, vendorDriverClass, vendorApiName, vendorSupportsEffortLevel) {
@@ -1466,7 +1458,7 @@ class AIPromptRunner {
1466
1458
  let llm;
1467
1459
  let chatParams;
1468
1460
  try {
1469
- const verbose = params.verbose === true || (0, core_1.IsVerboseLoggingEnabled)();
1461
+ const verbose = params.verbose === true || (0, global_1.IsVerboseLoggingEnabled)();
1470
1462
  let supportsEffortLevel = false;
1471
1463
  if (vendorDriverClass && vendorApiName) {
1472
1464
  driverClass = vendorDriverClass;
@@ -1491,7 +1483,7 @@ class AIPromptRunner {
1491
1483
  }
1492
1484
  let apiKey;
1493
1485
  if (params.apiKeys && params.apiKeys.length > 0) {
1494
- const localKey = params.apiKeys.find(k => k.driverClass === driverClass);
1486
+ const localKey = params.apiKeys.find((k) => k.driverClass === driverClass);
1495
1487
  if (localKey) {
1496
1488
  apiKey = localKey.apiKey;
1497
1489
  if (verbose) {
@@ -1508,7 +1500,7 @@ class AIPromptRunner {
1508
1500
  else {
1509
1501
  apiKey = (0, ai_1.GetAIAPIKey)(driverClass);
1510
1502
  }
1511
- llm = global_1.MJGlobal.Instance.ClassFactory.CreateInstance(ai_1.BaseLLM, driverClass, apiKey);
1503
+ llm = global_2.MJGlobal.Instance.ClassFactory.CreateInstance(ai_1.BaseLLM, driverClass, apiKey);
1512
1504
  chatParams = new ai_1.ChatParams();
1513
1505
  if (!apiName) {
1514
1506
  throw new Error(`No API name found for model ${model.Name}. Please ensure the model or its vendor configuration includes an APIName.`);
@@ -1530,7 +1522,9 @@ class AIPromptRunner {
1530
1522
  if (prompt.Seed != null)
1531
1523
  chatParams.seed = prompt.Seed;
1532
1524
  if (prompt.StopSequences) {
1533
- chatParams.stopSequences = prompt.StopSequences.split(',').map((s) => s.trim()).filter((s) => s.length > 0);
1525
+ chatParams.stopSequences = prompt.StopSequences.split(',')
1526
+ .map((s) => s.trim())
1527
+ .filter((s) => s.length > 0);
1534
1528
  }
1535
1529
  if (prompt.IncludeLogProbs != null)
1536
1530
  chatParams.includeLogProbs = prompt.IncludeLogProbs;
@@ -1617,9 +1611,9 @@ class AIPromptRunner {
1617
1611
  model: model,
1618
1612
  metadata: {
1619
1613
  vendorId,
1620
- errorInfo
1614
+ errorInfo,
1621
1615
  },
1622
- maxErrorLength: params.maxErrorLength
1616
+ maxErrorLength: params.maxErrorLength,
1623
1617
  });
1624
1618
  throw error;
1625
1619
  }
@@ -1664,7 +1658,7 @@ class AIPromptRunner {
1664
1658
  throw new Error('Execution was cancelled during validation retries');
1665
1659
  }
1666
1660
  if (attempt > 0) {
1667
- (0, core_1.LogStatus)(` 🔄 Retrying execution due to validation failure, attempt ${attempt + 1}/${maxRetries + 1}`);
1661
+ (0, global_1.LogStatus)(` 🔄 Retrying execution due to validation failure, attempt ${attempt + 1}/${maxRetries + 1}`);
1668
1662
  await this.applyRetryDelay(prompt, attempt);
1669
1663
  }
1670
1664
  const modelResult = await this.executeModelWithFailover(selectedModel, renderedPromptText, prompt, params, promptRun.VendorID, params.conversationMessages, params.templateMessageRole || 'system', params.cancellationToken, allCandidates, promptRun, vendorDriverClass, vendorApiName, vendorSupportsEffortLevel);
@@ -1681,7 +1675,7 @@ class AIPromptRunner {
1681
1675
  modelResult,
1682
1676
  parsedResult: {
1683
1677
  result: null,
1684
- validationResult: undefined
1678
+ validationResult: undefined,
1685
1679
  },
1686
1680
  validationAttempts,
1687
1681
  cumulativeTokens: {
@@ -1700,7 +1694,7 @@ class AIPromptRunner {
1700
1694
  const validationAttempt = {
1701
1695
  attemptNumber: attempt + 1,
1702
1696
  success: validationResult?.Success || false,
1703
- errorMessage: validationErrors?.length ? validationErrors.map(e => e.Message).join('; ') : undefined,
1697
+ errorMessage: validationErrors?.length ? validationErrors.map((e) => e.Message).join('; ') : undefined,
1704
1698
  validationErrors,
1705
1699
  rawOutput: modelResult.data?.choices?.[0]?.message?.content || '',
1706
1700
  parsedOutput: result,
@@ -1720,15 +1714,15 @@ class AIPromptRunner {
1720
1714
  };
1721
1715
  }
1722
1716
  if (prompt.ValidationBehavior === 'Strict' && attempt < maxRetries) {
1723
- lastError = new Error(`Validation failed: ${validationErrors?.map(e => e.Message).join('; ')}`);
1724
- (0, core_1.LogStatus)(` ⚠️ Validation failed on attempt ${attempt + 1}, will retry (Strict mode)`);
1717
+ lastError = new Error(`Validation failed: ${validationErrors?.map((e) => e.Message).join('; ')}`);
1718
+ (0, global_1.LogStatus)(` ⚠️ Validation failed on attempt ${attempt + 1}, will retry (Strict mode)`);
1725
1719
  continue;
1726
1720
  }
1727
1721
  else {
1728
1722
  const reason = prompt.ValidationBehavior !== 'Strict'
1729
1723
  ? `${prompt.ValidationBehavior || 'None'} mode - continuing with invalid output (no retry)`
1730
1724
  : 'max retries exceeded';
1731
- (0, core_1.LogStatus)(` ⚠️ Validation failed on attempt ${attempt + 1}, stopping retries (${reason})`);
1725
+ (0, global_1.LogStatus)(` ⚠️ Validation failed on attempt ${attempt + 1}, stopping retries (${reason})`);
1732
1726
  return {
1733
1727
  modelResult,
1734
1728
  parsedResult: { result, validationResult },
@@ -1749,9 +1743,9 @@ class AIPromptRunner {
1749
1743
  metadata: {
1750
1744
  attempt: attempt + 1,
1751
1745
  maxRetries: maxRetries + 1,
1752
- modelName: selectedModel.Name
1746
+ modelName: selectedModel.Name,
1753
1747
  },
1754
- maxErrorLength: params.maxErrorLength
1748
+ maxErrorLength: params.maxErrorLength,
1755
1749
  });
1756
1750
  const validationAttempt = {
1757
1751
  attemptNumber: attempt + 1,
@@ -1792,8 +1786,8 @@ class AIPromptRunner {
1792
1786
  async applyRetryDelay(prompt, attemptNumber, suggestedDelaySeconds) {
1793
1787
  const delay = this.calculateRetryDelay(prompt, attemptNumber, suggestedDelaySeconds);
1794
1788
  const delaySeconds = (delay / 1000).toFixed(1);
1795
- (0, core_1.LogStatus)(` Waiting ${delaySeconds}s before retry (strategy: ${prompt.RetryStrategy || 'Fixed'})...`);
1796
- await new Promise(resolve => setTimeout(resolve, delay));
1789
+ (0, global_1.LogStatus)(` Waiting ${delaySeconds}s before retry (strategy: ${prompt.RetryStrategy || 'Fixed'})...`);
1790
+ await new Promise((resolve) => setTimeout(resolve, delay));
1797
1791
  }
1798
1792
  filterAuthenticationFailedVendor(errorType, currentVendorId, allCandidates) {
1799
1793
  if (errorType !== 'Authentication') {
@@ -1801,10 +1795,10 @@ class AIPromptRunner {
1801
1795
  }
1802
1796
  const failedVendorId = currentVendorId || 'default';
1803
1797
  const beforeCount = allCandidates.length;
1804
- const filteredCandidates = allCandidates.filter(c => (c.vendorId || 'default') !== failedVendorId);
1798
+ const filteredCandidates = allCandidates.filter((c) => (c.vendorId || 'default') !== failedVendorId);
1805
1799
  const removedCount = beforeCount - filteredCandidates.length;
1806
1800
  if (removedCount > 0) {
1807
- const vendorName = aiengine_1.AIEngine.Instance.Vendors.find(v => v.ID === failedVendorId)?.Name || failedVendorId;
1801
+ const vendorName = aiengine_1.AIEngine.Instance.Vendors.find((v) => v.ID === failedVendorId)?.Name || failedVendorId;
1808
1802
  const remainingCount = filteredCandidates.length;
1809
1803
  this.logStatus(` 🔒 Invalid API key for ${vendorName} - excluding ${removedCount} model${removedCount === 1 ? '' : 's'} from this vendor (${remainingCount} remaining)`, true);
1810
1804
  }
@@ -1815,16 +1809,12 @@ class AIPromptRunner {
1815
1809
  if (!isRateLimit) {
1816
1810
  return false;
1817
1811
  }
1818
- const rateLimitRetryCount = failoverAttempts.filter(a => a.modelId === currentModel.ID &&
1819
- a.vendorId === currentVendorId &&
1820
- a.errorType === 'RateLimit').length;
1812
+ const rateLimitRetryCount = failoverAttempts.filter((a) => a.modelId === currentModel.ID && a.vendorId === currentVendorId && a.errorType === 'RateLimit').length;
1821
1813
  const maxRetries = prompt.MaxRetries ?? 3;
1822
1814
  const shouldRetry = rateLimitRetryCount <= maxRetries;
1823
1815
  if (shouldRetry) {
1824
1816
  const modelName = currentModel.Name;
1825
- const vendorName = currentVendorId
1826
- ? aiengine_1.AIEngine.Instance.Vendors.find(v => v.ID === currentVendorId)?.Name || 'default'
1827
- : 'default';
1817
+ const vendorName = currentVendorId ? aiengine_1.AIEngine.Instance.Vendors.find((v) => v.ID === currentVendorId)?.Name || 'default' : 'default';
1828
1818
  this.logStatus(` ⏳ Rate limit hit - retrying ${modelName} (${vendorName}) with backoff (attempt ${rateLimitRetryCount}/${maxRetries})`, true);
1829
1819
  this.logFailoverAttempt(prompt.ID, failoverAttempt, true);
1830
1820
  if (attemptNumber < maxAttempts) {
@@ -1844,21 +1834,19 @@ class AIPromptRunner {
1844
1834
  this.logFailoverAttempt(promptId, failoverAttempt, true);
1845
1835
  if (attemptNumber < failoverConfig.maxAttempts) {
1846
1836
  const delay = this.calculateFailoverDelay(attemptNumber, failoverConfig.delaySeconds);
1847
- await new Promise(resolve => setTimeout(resolve, delay));
1837
+ await new Promise((resolve) => setTimeout(resolve, delay));
1848
1838
  }
1849
1839
  return {
1850
1840
  model: nextCandidate.model,
1851
1841
  vendorId: nextCandidate.vendorId,
1852
1842
  driverClass: nextCandidate.driverClass,
1853
1843
  apiName: nextCandidate.apiName,
1854
- supportsEffortLevel: nextCandidate.supportsEffortLevel || false
1844
+ supportsEffortLevel: nextCandidate.supportsEffortLevel || false,
1855
1845
  };
1856
1846
  }
1857
1847
  getValidationDecisionDescription(finalSuccess, totalAttempts, validationBehavior) {
1858
1848
  if (finalSuccess) {
1859
- return totalAttempts === 1
1860
- ? 'Validation passed on first attempt'
1861
- : `Validation passed after ${totalAttempts} attempts`;
1849
+ return totalAttempts === 1 ? 'Validation passed on first attempt' : `Validation passed after ${totalAttempts} attempts`;
1862
1850
  }
1863
1851
  else {
1864
1852
  switch (validationBehavior) {
@@ -1987,9 +1975,9 @@ class AIPromptRunner {
1987
1975
  }
1988
1976
  }
1989
1977
  catch (parseError) {
1990
- const validationResult = new global_1.ValidationResult();
1978
+ const validationResult = new global_2.ValidationResult();
1991
1979
  validationResult.Success = false;
1992
- const error = new global_1.ValidationErrorInfo('parseAndValidateResultEnhanced', `Invalid OutputExample JSON: ${parseError.message}`, rawOutput, global_1.ValidationErrorType.Failure);
1980
+ const error = new global_2.ValidationErrorInfo('parseAndValidateResultEnhanced', `Invalid OutputExample JSON: ${parseError.message}`, rawOutput, global_2.ValidationErrorType.Failure);
1993
1981
  validationErrors.push(error);
1994
1982
  validationResult.Errors = validationErrors;
1995
1983
  return { result: rawOutput, validationResult, validationErrors };
@@ -2000,11 +1988,11 @@ class AIPromptRunner {
2000
1988
  validationErrors.push(...schemaValidationErrors);
2001
1989
  }
2002
1990
  catch (schemaError) {
2003
- const error = new global_1.ValidationErrorInfo('schema', `Schema validation failed: ${schemaError.message}`, undefined, global_1.ValidationErrorType.Failure);
1991
+ const error = new global_2.ValidationErrorInfo('schema', `Schema validation failed: ${schemaError.message}`, undefined, global_2.ValidationErrorType.Failure);
2004
1992
  validationErrors.push(error);
2005
1993
  }
2006
1994
  }
2007
- const validationResult = new global_1.ValidationResult();
1995
+ const validationResult = new global_2.ValidationResult();
2008
1996
  validationResult.Success = validationErrors.length === 0;
2009
1997
  validationResult.Errors = validationErrors;
2010
1998
  return { result: parsedResult, validationResult, validationErrors };
@@ -2015,15 +2003,16 @@ class AIPromptRunner {
2015
2003
  metadata: {
2016
2004
  rawOutput: rawOutput?.substring(0, 200),
2017
2005
  outputType: prompt.OutputType,
2018
- parseAttempt: true
2006
+ parseAttempt: true,
2019
2007
  },
2020
- maxErrorLength: params?.maxErrorLength
2008
+ maxErrorLength: params?.maxErrorLength,
2021
2009
  });
2022
- const validationResult = new global_1.ValidationResult();
2010
+ const validationResult = new global_2.ValidationResult();
2023
2011
  validationResult.Success = false;
2024
- validationResult.Errors = validationErrors.length > 0 ? validationErrors : [
2025
- new global_1.ValidationErrorInfo('general', error.message, undefined, global_1.ValidationErrorType.Failure)
2026
- ];
2012
+ validationResult.Errors =
2013
+ validationErrors.length > 0
2014
+ ? validationErrors
2015
+ : [new global_2.ValidationErrorInfo('general', error.message, undefined, global_2.ValidationErrorType.Failure)];
2027
2016
  switch (prompt.ValidationBehavior) {
2028
2017
  case 'Strict':
2029
2018
  return { result: undefined, validationResult, validationErrors: validationResult.Errors };
@@ -2034,9 +2023,9 @@ class AIPromptRunner {
2034
2023
  prompt: prompt,
2035
2024
  metadata: {
2036
2025
  validationPath: error.dataPath,
2037
- validationMessage: error.message
2026
+ validationMessage: error.message,
2038
2027
  },
2039
- maxErrorLength: params?.maxErrorLength
2028
+ maxErrorLength: params?.maxErrorLength,
2040
2029
  });
2041
2030
  return { result: modelResult.data?.choices?.[0]?.message?.content, validationResult, validationErrors: validationResult.Errors };
2042
2031
  case 'None':
@@ -2053,7 +2042,7 @@ class AIPromptRunner {
2053
2042
  const numberResult = parseFloat(rawOutput);
2054
2043
  if (isNaN(numberResult)) {
2055
2044
  if (!skipValidation) {
2056
- const error = new global_1.ValidationErrorInfo('output', `Expected number output but got: ${rawOutput}`, rawOutput, global_1.ValidationErrorType.Failure);
2045
+ const error = new global_2.ValidationErrorInfo('output', `Expected number output but got: ${rawOutput}`, rawOutput, global_2.ValidationErrorType.Failure);
2057
2046
  validationErrors.push(error);
2058
2047
  throw new Error(error.Message);
2059
2048
  }
@@ -2070,7 +2059,7 @@ class AIPromptRunner {
2070
2059
  return false;
2071
2060
  }
2072
2061
  else if (!skipValidation) {
2073
- const error = new global_1.ValidationErrorInfo('output', `Expected boolean output but got: ${rawOutput}`, rawOutput, global_1.ValidationErrorType.Failure);
2062
+ const error = new global_2.ValidationErrorInfo('output', `Expected boolean output but got: ${rawOutput}`, rawOutput, global_2.ValidationErrorType.Failure);
2074
2063
  validationErrors.push(error);
2075
2064
  throw new Error(error.Message);
2076
2065
  }
@@ -2079,7 +2068,7 @@ class AIPromptRunner {
2079
2068
  parseDateOutput(rawOutput, skipValidation, validationErrors) {
2080
2069
  const dateResult = new Date(rawOutput);
2081
2070
  if (isNaN(dateResult.getTime()) && !skipValidation) {
2082
- const error = new global_1.ValidationErrorInfo('output', `Expected date output but got: ${rawOutput}`, rawOutput, global_1.ValidationErrorType.Failure);
2071
+ const error = new global_2.ValidationErrorInfo('output', `Expected date output but got: ${rawOutput}`, rawOutput, global_2.ValidationErrorType.Failure);
2083
2072
  validationErrors.push(error);
2084
2073
  throw new Error(error.Message);
2085
2074
  }
@@ -2088,7 +2077,7 @@ class AIPromptRunner {
2088
2077
  async parseObjectOutput(rawOutput, prompt, skipValidation, cleanValidationSyntax, validationErrors, currentPromptRun, params) {
2089
2078
  let parsedResult;
2090
2079
  try {
2091
- parsedResult = JSON.parse((0, global_1.CleanJSON)(rawOutput));
2080
+ parsedResult = JSON.parse((0, global_2.CleanJSON)(rawOutput));
2092
2081
  }
2093
2082
  catch (jsonError) {
2094
2083
  if (params?.attemptJSONRepair && prompt.OutputType === 'object') {
@@ -2096,7 +2085,7 @@ class AIPromptRunner {
2096
2085
  }
2097
2086
  else {
2098
2087
  if (!skipValidation) {
2099
- const error = new global_1.ValidationErrorInfo('output', `Expected JSON object but got invalid JSON: ${rawOutput}`, rawOutput, global_1.ValidationErrorType.Failure);
2088
+ const error = new global_2.ValidationErrorInfo('output', `Expected JSON object but got invalid JSON: ${rawOutput}`, rawOutput, global_2.ValidationErrorType.Failure);
2100
2089
  validationErrors.push(error);
2101
2090
  throw new Error(error.Message);
2102
2091
  }
@@ -2104,7 +2093,7 @@ class AIPromptRunner {
2104
2093
  }
2105
2094
  }
2106
2095
  if (parsedResult && (cleanValidationSyntax || (!skipValidation && prompt.OutputExample))) {
2107
- const validator = new global_1.JSONValidator();
2096
+ const validator = new global_2.JSONValidator();
2108
2097
  parsedResult = validator.cleanValidationSyntax(parsedResult);
2109
2098
  }
2110
2099
  return parsedResult;
@@ -2115,9 +2104,9 @@ class AIPromptRunner {
2115
2104
  category: 'JSONRepairSkipped',
2116
2105
  metadata: {
2117
2106
  originalError: originalError.message,
2118
- rawOutput: rawOutput.substring(0, 500)
2107
+ rawOutput: rawOutput.substring(0, 500),
2119
2108
  },
2120
- maxErrorLength: params.maxErrorLength
2109
+ maxErrorLength: params.maxErrorLength,
2121
2110
  });
2122
2111
  throw new Error(`JSON repair skipped: raw output does not contain JSON-like characters. Original error: ${originalError.message}`);
2123
2112
  }
@@ -2125,16 +2114,16 @@ class AIPromptRunner {
2125
2114
  this.logStatus(' 🔧 Attempting JSON repair with JSON5...', true, params);
2126
2115
  let jsonToParse = rawOutput;
2127
2116
  try {
2128
- jsonToParse = (0, global_1.CleanJSON)(rawOutput);
2117
+ jsonToParse = (0, global_2.CleanJSON)(rawOutput);
2129
2118
  }
2130
2119
  catch (cleanError) {
2131
2120
  this.logError(cleanError, {
2132
2121
  category: 'JSONCleaningFailed',
2133
2122
  metadata: {
2134
2123
  originalError: originalError.message,
2135
- rawOutput: rawOutput.substring(0, 500)
2124
+ rawOutput: rawOutput.substring(0, 500),
2136
2125
  },
2137
- maxErrorLength: params.maxErrorLength
2126
+ maxErrorLength: params.maxErrorLength,
2138
2127
  });
2139
2128
  }
2140
2129
  const json5Result = JSON5.parse(jsonToParse);
@@ -2144,7 +2133,7 @@ class AIPromptRunner {
2144
2133
  catch (json5Error) {
2145
2134
  this.logStatus(' 🤖 JSON5 failed, attempting AI-based JSON repair...', true, params);
2146
2135
  try {
2147
- const repairPrompt = aiengine_1.AIEngine.Instance.Prompts.find(p => p.Name.trim().toLowerCase() === 'repair json' && p.Category.trim().toLowerCase() === 'mj: system');
2136
+ const repairPrompt = aiengine_1.AIEngine.Instance.Prompts.find((p) => p.Name.trim().toLowerCase() === 'repair json' && p.Category.trim().toLowerCase() === 'mj: system');
2148
2137
  if (!repairPrompt) {
2149
2138
  throw new Error('Repair JSON prompt not found in MJ: System category');
2150
2139
  }
@@ -2155,15 +2144,18 @@ class AIPromptRunner {
2155
2144
  prompt: repairPrompt,
2156
2145
  data: {
2157
2146
  ERROR_MESSAGE: originalError.message,
2158
- MALFORMED_JSON: rawOutput
2147
+ MALFORMED_JSON: rawOutput,
2159
2148
  },
2160
- skipValidation: true
2149
+ skipValidation: true,
2161
2150
  });
2162
2151
  if (!repairResult.success || !repairResult.result) {
2163
2152
  throw new Error('AI-based JSON repair failed' + (repairResult.errorMessage ? `: ${repairResult.errorMessage}` : ''));
2164
2153
  }
2165
2154
  const repairedJSON = JSON.parse(repairResult.result);
2166
- if (repairedJSON && typeof repairedJSON === 'object' && Object.keys(repairedJSON).length === 1 && repairedJSON.error?.trim().toLowerCase() === 'not_json') {
2155
+ if (repairedJSON &&
2156
+ typeof repairedJSON === 'object' &&
2157
+ Object.keys(repairedJSON).length === 1 &&
2158
+ repairedJSON.error?.trim().toLowerCase() === 'not_json') {
2167
2159
  throw new Error('AI-based JSON repair returned a non-JSON response indicating it could not repair the JSON');
2168
2160
  }
2169
2161
  this.logStatus(' ✅ AI successfully repaired the JSON', true, params);
@@ -2176,9 +2168,9 @@ class AIPromptRunner {
2176
2168
  originalError: originalError.message,
2177
2169
  json5Error: json5Error.message,
2178
2170
  aiError: aiRepairError.message,
2179
- rawOutput: rawOutput.substring(0, 500)
2171
+ rawOutput: rawOutput.substring(0, 500),
2180
2172
  },
2181
- maxErrorLength: params.maxErrorLength
2173
+ maxErrorLength: params.maxErrorLength,
2182
2174
  });
2183
2175
  throw new Error(`JSON repair failed after both JSON5 and AI attempts: ${originalError.message}`);
2184
2176
  }
@@ -2192,26 +2184,26 @@ class AIPromptRunner {
2192
2184
  exampleObject = JSON.parse(outputExample);
2193
2185
  }
2194
2186
  catch (parseError) {
2195
- const error = new global_1.ValidationErrorInfo('outputExample', `Invalid OutputExample JSON: ${parseError.message}`, outputExample, global_1.ValidationErrorType.Failure);
2187
+ const error = new global_2.ValidationErrorInfo('outputExample', `Invalid OutputExample JSON: ${parseError.message}`, outputExample, global_2.ValidationErrorType.Failure);
2196
2188
  validationErrors.push(error);
2197
2189
  return validationErrors;
2198
2190
  }
2199
2191
  const validationResult = this._jsonValidator.validate(parsedResult, exampleObject);
2200
2192
  validationErrors.push(...validationResult.Errors);
2201
2193
  if (validationErrors.length !== 0) {
2202
- (0, core_1.LogStatus)(`⚠️ Validation found ${validationErrors.length} issues for prompt ${promptId}:`);
2194
+ (0, global_1.LogStatus)(`⚠️ Validation found ${validationErrors.length} issues for prompt ${promptId}:`);
2203
2195
  validationErrors.forEach((error, index) => {
2204
- (0, core_1.LogStatus)(` ${index + 1}. ${error.Source}: ${error.Message}`);
2196
+ (0, global_1.LogStatus)(` ${index + 1}. ${error.Source}: ${error.Message}`);
2205
2197
  });
2206
- (0, core_1.LogStatus)(` Note: Validation syntax in OutputExample:`);
2207
- (0, core_1.LogStatus)(` - '?' = optional field (e.g., "reasoning?": "...")`);
2208
- (0, core_1.LogStatus)(` - '*' = required but any content (e.g., "payload*": {})`);
2209
- (0, core_1.LogStatus)(` - ':type' = type validation (e.g., "age:number": 25)`);
2210
- (0, core_1.LogStatus)(` - ':[N+]' = array length (e.g., "items:[2+]": [])`);
2198
+ (0, global_1.LogStatus)(` Note: Validation syntax in OutputExample:`);
2199
+ (0, global_1.LogStatus)(` - '?' = optional field (e.g., "reasoning?": "...")`);
2200
+ (0, global_1.LogStatus)(` - '*' = required but any content (e.g., "payload*": {})`);
2201
+ (0, global_1.LogStatus)(` - ':type' = type validation (e.g., "age:number": 25)`);
2202
+ (0, global_1.LogStatus)(` - ':[N+]' = array length (e.g., "items:[2+]": [])`);
2211
2203
  }
2212
2204
  }
2213
2205
  catch (error) {
2214
- const validationError = new global_1.ValidationErrorInfo('validation', `Unexpected validation error: ${error.message}`, undefined, global_1.ValidationErrorType.Failure);
2206
+ const validationError = new global_2.ValidationErrorInfo('validation', `Unexpected validation error: ${error.message}`, undefined, global_2.ValidationErrorType.Failure);
2215
2207
  validationErrors.push(validationError);
2216
2208
  }
2217
2209
  return validationErrors;
@@ -2229,7 +2221,7 @@ class AIPromptRunner {
2229
2221
  if (!promptRun.ErrorMessage) {
2230
2222
  const validationErrors = parsedResult.validationResult?.Errors;
2231
2223
  if (validationErrors && validationErrors.length > 0) {
2232
- promptRun.ErrorMessage = `JSON parsing/validation failed: ${validationErrors.map(e => e.Message).join('; ')}`;
2224
+ promptRun.ErrorMessage = `JSON parsing/validation failed: ${validationErrors.map((e) => e.Message).join('; ')}`;
2233
2225
  }
2234
2226
  else {
2235
2227
  promptRun.ErrorMessage = 'Failed to parse result into expected format; raw output saved instead';
@@ -2277,7 +2269,7 @@ class AIPromptRunner {
2277
2269
  }
2278
2270
  if (validationAttempts && validationAttempts.length > 0) {
2279
2271
  promptRun.ValidationAttemptCount = validationAttempts.length;
2280
- promptRun.SuccessfulValidationCount = validationAttempts.filter(a => a.success).length;
2272
+ promptRun.SuccessfulValidationCount = validationAttempts.filter((a) => a.success).length;
2281
2273
  promptRun.FinalValidationPassed = parsedResult.validationResult?.Success === true;
2282
2274
  promptRun.LastAttemptAt = endTime;
2283
2275
  if (validationAttempts.length > 1) {
@@ -2293,9 +2285,9 @@ class AIPromptRunner {
2293
2285
  promptRun.FinalValidationError = finalAttempt.errorMessage.substring(0, 500);
2294
2286
  promptRun.ValidationErrorCount = finalAttempt.validationErrors?.length || 0;
2295
2287
  }
2296
- if (validationAttempts.some(a => !a.success)) {
2288
+ if (validationAttempts.some((a) => !a.success)) {
2297
2289
  const errorCounts = new Map();
2298
- validationAttempts.forEach(attempt => {
2290
+ validationAttempts.forEach((attempt) => {
2299
2291
  if (!attempt.success && attempt.errorMessage) {
2300
2292
  const count = errorCounts.get(attempt.errorMessage) || 0;
2301
2293
  errorCounts.set(attempt.errorMessage, count + 1);
@@ -2306,17 +2298,17 @@ class AIPromptRunner {
2306
2298
  promptRun.CommonValidationError = commonError.substring(0, 255);
2307
2299
  }
2308
2300
  }
2309
- promptRun.ValidationAttempts = JSON.stringify(validationAttempts.map(a => ({
2301
+ promptRun.ValidationAttempts = JSON.stringify(validationAttempts.map((a) => ({
2310
2302
  attemptNumber: a.attemptNumber,
2311
2303
  success: a.success,
2312
2304
  errorMessage: a.errorMessage,
2313
2305
  validationErrorCount: a.validationErrors?.length || 0,
2314
2306
  timestamp: a.timestamp.toISOString(),
2315
- outputLength: a.rawOutput?.length || 0
2307
+ outputLength: a.rawOutput?.length || 0,
2316
2308
  })));
2317
2309
  promptRun.ValidationSummary = JSON.stringify({
2318
2310
  totalAttempts: validationAttempts.length,
2319
- successfulAttempts: validationAttempts.filter(a => a.success).length,
2311
+ successfulAttempts: validationAttempts.filter((a) => a.success).length,
2320
2312
  finalSuccess: parsedResult.validationResult?.Success || false,
2321
2313
  validationBehavior: promptRun.ValidationBehavior,
2322
2314
  retryStrategy: promptRun.RetryStrategy,
@@ -2325,15 +2317,15 @@ class AIPromptRunner {
2325
2317
  totalDurationMS: executionTimeMS,
2326
2318
  retryDurationMS: promptRun.TotalRetryDurationMS || 0,
2327
2319
  outputType: prompt.OutputType || 'unknown',
2328
- hasOutputExample: !!(prompt.OutputExample),
2320
+ hasOutputExample: !!prompt.OutputExample,
2329
2321
  schemaValidationUsed: !!(prompt.OutputExample && prompt.OutputType === 'object'),
2330
- finalValidationErrors: parsedResult.validationResult?.Errors?.map(e => ({
2322
+ finalValidationErrors: parsedResult.validationResult?.Errors?.map((e) => ({
2331
2323
  source: e.Source,
2332
2324
  message: e.Message,
2333
2325
  type: e.Type,
2334
- value: e.Value
2326
+ value: e.Value,
2335
2327
  })) || [],
2336
- validationDecision: this.getValidationDecisionDescription(parsedResult.validationResult?.Success || false, validationAttempts.length, promptRun.ValidationBehavior || 'Warn')
2328
+ validationDecision: this.getValidationDecisionDescription(parsedResult.validationResult?.Success || false, validationAttempts.length, promptRun.ValidationBehavior || 'Warn'),
2337
2329
  });
2338
2330
  }
2339
2331
  else {
@@ -2343,14 +2335,14 @@ class AIPromptRunner {
2343
2335
  promptRun.LastAttemptAt = endTime;
2344
2336
  promptRun.TotalRetryDurationMS = 0;
2345
2337
  }
2346
- promptRun.Success = modelResult.success && (parsedResult.validationResult?.Success !== false);
2338
+ promptRun.Success = modelResult.success && parsedResult.validationResult?.Success !== false;
2347
2339
  promptRun.Status = promptRun.Success ? 'Completed' : 'Failed';
2348
2340
  if (!promptRun.Success) {
2349
2341
  if (!modelResult.success && modelResult.errorMessage) {
2350
2342
  promptRun.ErrorDetails = modelResult.errorMessage;
2351
2343
  }
2352
2344
  else if (parsedResult.validationResult?.Success === false) {
2353
- promptRun.ErrorDetails = `Validation failed: ${parsedResult.validationResult.Errors?.map(e => e.Message).join(', ')}`;
2345
+ promptRun.ErrorDetails = `Validation failed: ${parsedResult.validationResult.Errors?.map((e) => e.Message).join(', ')}`;
2354
2346
  }
2355
2347
  }
2356
2348
  promptRun.TokensPromptRollup = promptRun.TokensPrompt;
@@ -2364,9 +2356,8 @@ class AIPromptRunner {
2364
2356
  let errorMsg = 'Unknown error';
2365
2357
  try {
2366
2358
  if (promptRun.LatestResult?.Message) {
2367
- errorMsg = typeof promptRun.LatestResult.Message === 'string'
2368
- ? promptRun.LatestResult.Message
2369
- : String(promptRun.LatestResult.Message);
2359
+ errorMsg =
2360
+ typeof promptRun.LatestResult.Message === 'string' ? promptRun.LatestResult.Message : String(promptRun.LatestResult.Message);
2370
2361
  }
2371
2362
  }
2372
2363
  catch (msgError) {
@@ -2376,8 +2367,8 @@ class AIPromptRunner {
2376
2367
  category: 'PromptRunUpdate',
2377
2368
  metadata: {
2378
2369
  promptRunId: promptRun.ID,
2379
- updateError: errorMsg
2380
- }
2370
+ updateError: errorMsg,
2371
+ },
2381
2372
  });
2382
2373
  }
2383
2374
  }
@@ -2385,8 +2376,8 @@ class AIPromptRunner {
2385
2376
  this.logError(error, {
2386
2377
  category: 'PromptRunUpdate',
2387
2378
  metadata: {
2388
- promptRunId: promptRun.ID
2389
- }
2379
+ promptRunId: promptRun.ID,
2380
+ },
2390
2381
  });
2391
2382
  }
2392
2383
  }
@@ -2396,7 +2387,7 @@ class AIPromptRunner {
2396
2387
  maxAttempts: prompt.FailoverMaxAttempts || 3,
2397
2388
  delaySeconds: prompt.FailoverDelaySeconds || 1,
2398
2389
  modelStrategy: prompt.FailoverModelStrategy || 'PreferSameModel',
2399
- errorScope: prompt.FailoverErrorScope || 'All'
2390
+ errorScope: prompt.FailoverErrorScope || 'All',
2400
2391
  };
2401
2392
  }
2402
2393
  shouldAttemptFailover(error, config, attemptNumber) {
@@ -2413,8 +2404,7 @@ class AIPromptRunner {
2413
2404
  case 'RateLimitOnly':
2414
2405
  return errorAnalysis.errorType === 'RateLimit';
2415
2406
  case 'ServiceErrorOnly':
2416
- return errorAnalysis.errorType === 'ServiceUnavailable' ||
2417
- errorAnalysis.errorType === 'InternalServerError';
2407
+ return errorAnalysis.errorType === 'ServiceUnavailable' || errorAnalysis.errorType === 'InternalServerError';
2418
2408
  case 'All':
2419
2409
  default:
2420
2410
  return true;
@@ -2427,22 +2417,21 @@ class AIPromptRunner {
2427
2417
  return totalDelay * 1000;
2428
2418
  }
2429
2419
  selectFailoverCandidates(currentModel, currentVendorId, strategy, modelStrategy, allCandidates, attemptHistory) {
2430
- const failedPairs = new Set(attemptHistory.map(a => `${a.modelId}:${a.vendorId || 'default'}`));
2431
- const availableCandidates = allCandidates.filter(c => {
2420
+ const failedPairs = new Set(attemptHistory.map((a) => `${a.modelId}:${a.vendorId || 'default'}`));
2421
+ const availableCandidates = allCandidates.filter((c) => {
2432
2422
  const key = `${c.model.ID}:${c.vendorId || 'default'}`;
2433
2423
  return !failedPairs.has(key);
2434
2424
  });
2435
- const hasContextLengthError = attemptHistory.some(a => a.errorType === 'ContextLengthExceeded' ||
2436
- ai_1.ErrorAnalyzer.analyzeError(a.error).errorType === 'ContextLengthExceeded');
2425
+ const hasContextLengthError = attemptHistory.some((a) => a.errorType === 'ContextLengthExceeded' || ai_1.ErrorAnalyzer.analyzeError(a.error).errorType === 'ContextLengthExceeded');
2437
2426
  let candidates;
2438
2427
  switch (strategy) {
2439
2428
  case 'SameModelDifferentVendor':
2440
- candidates = availableCandidates.filter(c => c.model.ID === currentModel.ID && c.vendorId !== currentVendorId);
2429
+ candidates = availableCandidates.filter((c) => c.model.ID === currentModel.ID && c.vendorId !== currentVendorId);
2441
2430
  break;
2442
2431
  case 'NextBestModel':
2443
2432
  candidates = availableCandidates;
2444
2433
  if (modelStrategy === 'RequireSameModel') {
2445
- candidates = candidates.filter(c => c.model.ID === currentModel.ID);
2434
+ candidates = candidates.filter((c) => c.model.ID === currentModel.ID);
2446
2435
  }
2447
2436
  else if (modelStrategy === 'PreferSameModel') {
2448
2437
  candidates.sort((a, b) => {
@@ -2466,23 +2455,23 @@ class AIPromptRunner {
2466
2455
  candidates = [];
2467
2456
  }
2468
2457
  if (hasContextLengthError) {
2469
- const currentMaxTokens = currentModel.ModelVendors?.length > 0 ?
2470
- Math.max(...currentModel.ModelVendors.map(mv => mv.MaxInputTokens || 0)) : 0;
2471
- candidates = candidates.filter(c => {
2472
- const candidateMaxTokens = c.model.ModelVendors?.length > 0 ?
2473
- Math.max(...c.model.ModelVendors.map(mv => mv.MaxInputTokens || 0)) : 0;
2458
+ const currentMaxTokens = currentModel.ModelVendors?.length > 0 ? Math.max(...currentModel.ModelVendors.map((mv) => mv.MaxInputTokens || 0)) : 0;
2459
+ candidates = candidates.filter((c) => {
2460
+ const candidateMaxTokens = c.model.ModelVendors?.length > 0 ? Math.max(...c.model.ModelVendors.map((mv) => mv.MaxInputTokens || 0)) : 0;
2474
2461
  return candidateMaxTokens > currentMaxTokens;
2475
2462
  });
2476
2463
  if (candidates.length === 0) {
2477
- (0, core_1.LogStatusEx)({
2464
+ (0, global_1.LogStatusEx)({
2478
2465
  message: `❌ Context length exceeded and no models with larger context windows available. Current model: ${currentModel.Name} (${currentMaxTokens} max tokens). This is a fatal error.`,
2479
2466
  category: 'AI',
2480
- additionalArgs: [{
2467
+ additionalArgs: [
2468
+ {
2481
2469
  currentModel: currentModel.Name,
2482
2470
  currentMaxTokens,
2483
- availableModels: allCandidates.map(c => c.model.Name).join(', '),
2484
- reason: 'No models with larger context windows available for failover'
2485
- }]
2471
+ availableModels: allCandidates.map((c) => c.model.Name).join(', '),
2472
+ reason: 'No models with larger context windows available for failover',
2473
+ },
2474
+ ],
2486
2475
  });
2487
2476
  return [];
2488
2477
  }
@@ -2490,25 +2479,26 @@ class AIPromptRunner {
2490
2479
  if (a.priority !== b.priority) {
2491
2480
  return b.priority - a.priority;
2492
2481
  }
2493
- const aMaxTokens = a.model.ModelVendors?.length > 0 ?
2494
- Math.max(...a.model.ModelVendors.map((mv) => mv.MaxInputTokens || 0)) : 0;
2495
- const bMaxTokens = b.model.ModelVendors?.length > 0 ?
2496
- Math.max(...b.model.ModelVendors.map((mv) => mv.MaxInputTokens || 0)) : 0;
2482
+ const aMaxTokens = a.model.ModelVendors?.length > 0 ? Math.max(...a.model.ModelVendors.map((mv) => mv.MaxInputTokens || 0)) : 0;
2483
+ const bMaxTokens = b.model.ModelVendors?.length > 0 ? Math.max(...b.model.ModelVendors.map((mv) => mv.MaxInputTokens || 0)) : 0;
2497
2484
  return bMaxTokens - aMaxTokens;
2498
2485
  });
2499
2486
  const bestCandidate = candidates[0];
2500
- const bestCandidateMaxTokens = bestCandidate.model.ModelVendors?.length > 0 ?
2501
- Math.max(...bestCandidate.model.ModelVendors.map((mv) => mv.MaxInputTokens || 0)) : 0;
2502
- (0, core_1.LogStatusEx)({
2487
+ const bestCandidateMaxTokens = bestCandidate.model.ModelVendors?.length > 0
2488
+ ? Math.max(...bestCandidate.model.ModelVendors.map((mv) => mv.MaxInputTokens || 0))
2489
+ : 0;
2490
+ (0, global_1.LogStatusEx)({
2503
2491
  message: `🔄 Context-aware failover: Selected model ${bestCandidate.model.Name} with ${bestCandidateMaxTokens} max input tokens (vs ${currentMaxTokens} for failed model)`,
2504
2492
  category: 'AI',
2505
- additionalArgs: [{
2493
+ additionalArgs: [
2494
+ {
2506
2495
  currentModel: currentModel.Name,
2507
2496
  currentMaxTokens,
2508
2497
  selectedModel: bestCandidate.model.Name,
2509
2498
  selectedMaxTokens: bestCandidateMaxTokens,
2510
- candidateCount: candidates.length
2511
- }]
2499
+ candidateCount: candidates.length,
2500
+ },
2501
+ ],
2512
2502
  });
2513
2503
  }
2514
2504
  else {
@@ -2526,22 +2516,22 @@ class AIPromptRunner {
2526
2516
  errorType: attempt.errorType,
2527
2517
  duration: attempt.duration,
2528
2518
  willRetry,
2529
- error: attempt.error.message
2519
+ error: attempt.error.message,
2530
2520
  };
2531
2521
  if (willRetry) {
2532
- (0, core_1.LogStatusEx)({
2522
+ (0, global_1.LogStatusEx)({
2533
2523
  message: `⚡ ${message}`,
2534
2524
  category: 'AI',
2535
- additionalArgs: [metadata]
2525
+ additionalArgs: [metadata],
2536
2526
  });
2537
2527
  }
2538
2528
  else {
2539
- (0, core_1.LogErrorEx)({
2529
+ (0, global_1.LogErrorEx)({
2540
2530
  message: message,
2541
2531
  error: attempt.error,
2542
2532
  category: 'AI',
2543
2533
  severity: 'error',
2544
- metadata: metadata
2534
+ metadata: metadata,
2545
2535
  });
2546
2536
  }
2547
2537
  }