@memberjunction/ai-prompts 2.112.0 → 2.113.1

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