@memberjunction/react-test-harness 2.112.0 → 2.113.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.
@@ -24,7 +24,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.ComponentRunner = void 0;
27
- const global_1 = require("@memberjunction/global");
27
+ const core_1 = require("@memberjunction/core");
28
28
  const component_linter_1 = require("./component-linter");
29
29
  const core_entities_1 = require("@memberjunction/core-entities");
30
30
  const ai_vectors_memory_1 = require("@memberjunction/ai-vectors-memory");
@@ -63,10 +63,10 @@ class ComponentRunner {
63
63
  async lintComponent(componentCode, componentName, componentSpec, isRootComponent, contextUser, options) {
64
64
  const lintResult = await component_linter_1.ComponentLinter.lintComponent(componentCode, componentName, componentSpec, isRootComponent, contextUser, false, // debugMode
65
65
  options);
66
- const hasErrors = lintResult.violations.some((v) => v.severity === 'critical' || v.severity === 'high');
66
+ const hasErrors = lintResult.violations.some(v => v.severity === 'critical' || v.severity === 'high');
67
67
  return {
68
68
  violations: lintResult.violations,
69
- hasErrors,
69
+ hasErrors
70
70
  };
71
71
  }
72
72
  async executeComponent(options) {
@@ -89,7 +89,7 @@ class ComponentRunner {
89
89
  page.setDefaultTimeout(globalTimeout);
90
90
  // Load component metadata and libraries first (needed for library loading)
91
91
  await core_entities_1.ComponentMetadataEngine.Instance.Config(false, options.contextUser);
92
- const allLibraries = core_entities_1.ComponentMetadataEngine.Instance.ComponentLibraries.map((c) => c.GetAll());
92
+ const allLibraries = core_entities_1.ComponentMetadataEngine.Instance.ComponentLibraries.map(c => c.GetAll());
93
93
  try {
94
94
  // Navigate to a blank page FIRST, then load runtime
95
95
  await page.goto('about:blank');
@@ -101,12 +101,12 @@ class ComponentRunner {
101
101
  <meta charset="utf-8">
102
102
  <title>React Component Test (V2)</title>
103
103
  <style>
104
- body {
105
- margin: 0;
106
- padding: 20px;
104
+ body {
105
+ margin: 0;
106
+ padding: 20px;
107
107
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
108
108
  }
109
- #root {
109
+ #root {
110
110
  min-height: 100vh;
111
111
  background-color: white;
112
112
  padding: 20px;
@@ -130,7 +130,7 @@ class ComponentRunner {
130
130
  hasReact: typeof window.React !== 'undefined',
131
131
  hasReactDOM: typeof window.ReactDOM !== 'undefined',
132
132
  hasBabel: typeof window.Babel !== 'undefined',
133
- mjRuntimeKeys: window.MJReactRuntime ? Object.keys(window.MJReactRuntime) : [],
133
+ mjRuntimeKeys: window.MJReactRuntime ? Object.keys(window.MJReactRuntime) : []
134
134
  };
135
135
  });
136
136
  if (debug) {
@@ -152,10 +152,10 @@ class ComponentRunner {
152
152
  console.log(' - props:', JSON.stringify(options.props || {}, null, 2));
153
153
  // Show spec-specific libraries, not all available libraries
154
154
  if (options.componentSpec.libraries && options.componentSpec.libraries.length > 0) {
155
- console.log(' - spec requires libraries:', options.componentSpec.libraries.map((lib) => ({
155
+ console.log(' - spec requires libraries:', options.componentSpec.libraries.map(lib => ({
156
156
  name: lib.name,
157
157
  globalVariable: lib.globalVariable,
158
- version: lib.version,
158
+ version: lib.version
159
159
  })));
160
160
  }
161
161
  else {
@@ -213,7 +213,7 @@ class ComponentRunner {
213
213
  // Diagnostic: Check if React is available before creating context
214
214
  if (!window.React) {
215
215
  console.error('🔴 CRITICAL: React is NULL when creating runtimeContext!');
216
- console.error('Window keys:', Object.keys(window).filter((k) => k.toLowerCase().includes('react')));
216
+ console.error('Window keys:', Object.keys(window).filter(k => k.toLowerCase().includes('react')));
217
217
  throw new Error('React is not available in window context');
218
218
  }
219
219
  if (debug) {
@@ -222,13 +222,13 @@ class ComponentRunner {
222
222
  useState: typeof window.React?.useState,
223
223
  useEffect: typeof window.React?.useEffect,
224
224
  useRef: typeof window.React?.useRef,
225
- useMemo: typeof window.React?.useMemo,
225
+ useMemo: typeof window.React?.useMemo
226
226
  });
227
227
  }
228
228
  const runtimeContext = {
229
229
  React: window.React,
230
230
  ReactDOM: window.ReactDOM,
231
- libraries: {}, // Libraries are loaded internally by the compiler
231
+ libraries: {} // Libraries are loaded internally by the compiler
232
232
  };
233
233
  // Create instances with debug mode to see library loading
234
234
  const compiler = new ComponentCompiler({ debug: debug });
@@ -277,7 +277,7 @@ class ComponentRunner {
277
277
  continue;
278
278
  }
279
279
  if (!specLib.globalVariable) {
280
- const libDef = componentLibraries.find((l) => l && l.Name && l.Name.toLowerCase() === specLib.name.toLowerCase());
280
+ const libDef = componentLibraries.find(l => l && l.Name && l.Name.toLowerCase() === specLib.name.toLowerCase());
281
281
  if (libDef && libDef.GlobalVariable) {
282
282
  specLib.globalVariable = libDef.GlobalVariable;
283
283
  if (debug) {
@@ -289,7 +289,7 @@ class ComponentRunner {
289
289
  if (debug) {
290
290
  console.log('🔍 Spec libraries after enhancement:', spec.libraries.map((l) => ({
291
291
  name: l.name,
292
- globalVariable: l.globalVariable,
292
+ globalVariable: l.globalVariable
293
293
  })));
294
294
  }
295
295
  }
@@ -315,8 +315,8 @@ class ComponentRunner {
315
315
  dependencies: spec.dependencies?.map((d) => ({
316
316
  name: d.name,
317
317
  location: d.location,
318
- hasCode: !!d.code,
319
- })),
318
+ hasCode: !!d.code
319
+ }))
320
320
  });
321
321
  }
322
322
  // NEW: Use ComponentManager.loadHierarchy instead of registrar.registerHierarchy
@@ -328,23 +328,21 @@ class ComponentRunner {
328
328
  defaultVersion: 'v1',
329
329
  returnType: 'both',
330
330
  resolutionMode: 'embed', // Convert to embedded format for browser execution
331
- allLibraries: componentLibraries || [], // Pass libraries for compiler
331
+ allLibraries: componentLibraries || [] // Pass libraries for compiler
332
332
  });
333
333
  if (debug) {
334
334
  console.log('📋 [BROWSER] LoadHierarchy result:', {
335
335
  success: loadResult.success,
336
336
  rootComponent: !!loadResult.rootComponent,
337
- resolvedSpec: loadResult.resolvedSpec
338
- ? {
339
- name: loadResult.resolvedSpec.name,
340
- location: loadResult.resolvedSpec.location,
341
- registry: loadResult.resolvedSpec.registry,
342
- libraries: loadResult.resolvedSpec.libraries,
343
- hasCode: !!loadResult.resolvedSpec.code,
344
- }
345
- : null,
337
+ resolvedSpec: loadResult.resolvedSpec ? {
338
+ name: loadResult.resolvedSpec.name,
339
+ location: loadResult.resolvedSpec.location,
340
+ registry: loadResult.resolvedSpec.registry,
341
+ libraries: loadResult.resolvedSpec.libraries,
342
+ hasCode: !!loadResult.resolvedSpec.code
343
+ } : null,
346
344
  loadedComponents: loadResult.loadedComponents,
347
- errors: loadResult.errors,
345
+ errors: loadResult.errors
348
346
  });
349
347
  }
350
348
  // Convert to old format for compatibility
@@ -353,7 +351,7 @@ class ComponentRunner {
353
351
  registeredComponents: loadResult.loadedComponents,
354
352
  errors: loadResult.errors.map((e) => ({ componentName: e.componentName || '', error: e.message, phase: e.phase })),
355
353
  warnings: [],
356
- resolvedSpec: loadResult.resolvedSpec,
354
+ resolvedSpec: loadResult.resolvedSpec
357
355
  };
358
356
  }
359
357
  catch (registrationError) {
@@ -365,7 +363,7 @@ class ComponentRunner {
365
363
  stack: registrationError.stack,
366
364
  type: 'registration-error',
367
365
  phase: 'component-compilation',
368
- source: 'runtime-wrapper',
366
+ source: 'runtime-wrapper'
369
367
  });
370
368
  window.__testHarnessTestFailed = true;
371
369
  // Don't re-throw - let execution continue to collect this error properly
@@ -373,7 +371,7 @@ class ComponentRunner {
373
371
  return {
374
372
  success: false,
375
373
  error: `Component registration failed: ${registrationError.message || registrationError}`,
376
- componentCount: 0,
374
+ componentCount: 0
377
375
  };
378
376
  }
379
377
  if (debug && !registrationResult.success) {
@@ -415,7 +413,10 @@ class ComponentRunner {
415
413
  antd: typeof window.antd,
416
414
  React: typeof window.React,
417
415
  ReactDOM: typeof window.ReactDOM,
418
- windowKeys: Object.keys(window).filter((k) => k.toLowerCase().includes('apex') || k.toLowerCase().includes('antd') || k === 'ApexCharts' || k === 'antd'),
416
+ windowKeys: Object.keys(window).filter(k => k.toLowerCase().includes('apex') ||
417
+ k.toLowerCase().includes('antd') ||
418
+ k === 'ApexCharts' ||
419
+ k === 'antd')
419
420
  });
420
421
  // If libraries were supposed to be loaded, check their actual presence
421
422
  if (spec.libraries && spec.libraries.length > 0) {
@@ -478,7 +479,7 @@ class ComponentRunner {
478
479
  '',
479
480
  'Inspect all instances where you are using JSX elements that come from libraries or components to ensure they are properly referenced.',
480
481
  '',
481
- 'The exact fix depends on the specific library or component structure.',
482
+ 'The exact fix depends on the specific library or component structure.'
482
483
  ].join('\\n');
483
484
  // Log to both console and error tracking
484
485
  console.error('🔴 Invalid JSX Element Type Detected:', errorMsg);
@@ -488,7 +489,7 @@ class ComponentRunner {
488
489
  type: 'invalid-element-type',
489
490
  phase: 'createElement',
490
491
  source: 'enhanced-detection',
491
- elementInfo: objectInfo,
492
+ elementInfo: objectInfo
492
493
  });
493
494
  // Still try to call the original to get React's error too
494
495
  // This will provide the component stack trace
@@ -503,14 +504,14 @@ class ComponentRunner {
503
504
  '',
504
505
  'Inspect how this component is being accessed - it may not exist in the expected location or may have a different name.',
505
506
  '',
506
- 'Check that the component exists in your dependencies or libraries and is properly referenced.',
507
+ 'Check that the component exists in your dependencies or libraries and is properly referenced.'
507
508
  ].join('\\n');
508
509
  console.error('🔴 Undefined JSX Component:', errorMsg);
509
510
  window.__testHarnessRuntimeErrors.push({
510
511
  message: errorMsg,
511
512
  type: 'undefined-component',
512
513
  phase: 'createElement',
513
- source: 'enhanced-detection',
514
+ source: 'enhanced-detection'
514
515
  });
515
516
  }
516
517
  // Call original createElement
@@ -539,7 +540,7 @@ class ComponentRunner {
539
540
  window.__testHarnessRuntimeErrors.push({
540
541
  message: `Likely infinite render loop: ${currentRenderCount} createElement calls (max: ${MAX_RENDERS_ALLOWED})`,
541
542
  type: 'render-loop',
542
- source: 'test-harness',
543
+ source: 'test-harness'
543
544
  });
544
545
  // Try to unmount to stop the madness
545
546
  try {
@@ -573,8 +574,8 @@ class ComponentRunner {
573
574
  CreateSimpleNotification: (message, style, hideAfter) => {
574
575
  console.log('[Test Harness] CreateSimpleNotification called:', { message, style, hideAfter });
575
576
  // In test harness, we just log but don't display actual notifications
576
- },
577
- },
577
+ }
578
+ }
578
579
  };
579
580
  if (debug) {
580
581
  console.log('🎨 Rendering component with props:', Object.keys(componentProps));
@@ -603,7 +604,7 @@ class ComponentRunner {
603
604
  stack: error.stack,
604
605
  type: 'react-render-error',
605
606
  phase: 'component-render',
606
- source: 'user-component', // This is the actual error from user's component
607
+ source: 'user-component' // This is the actual error from user's component
607
608
  });
608
609
  window.__testHarnessTestFailed = true;
609
610
  return { hasError: true, error };
@@ -639,7 +640,7 @@ class ComponentRunner {
639
640
  }
640
641
  return {
641
642
  success: true,
642
- componentCount: registrationResult.registeredComponents.length,
643
+ componentCount: registrationResult.registeredComponents.length
643
644
  };
644
645
  }
645
646
  catch (error) {
@@ -656,19 +657,19 @@ class ComponentRunner {
656
657
  message: error.message || String(error),
657
658
  stack: error.stack,
658
659
  type: 'execution-error',
659
- source: 'runtime-wrapper',
660
+ source: 'runtime-wrapper'
660
661
  });
661
662
  window.__testHarnessTestFailed = true;
662
663
  return {
663
664
  success: false,
664
- error: error.message || String(error),
665
+ error: error.message || String(error)
665
666
  };
666
667
  }
667
668
  }, {
668
669
  spec: options.componentSpec,
669
670
  props: options.props,
670
671
  debug,
671
- componentLibraries: allLibraries || [],
672
+ componentLibraries: allLibraries || []
672
673
  });
673
674
  // Create timeout promise (Recommendation #1)
674
675
  const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error(`Component execution timeout after ${globalTimeout}ms`)), globalTimeout));
@@ -684,21 +685,21 @@ class ComponentRunner {
684
685
  errors.push(`Component execution timed out after ${globalTimeout}ms`);
685
686
  executionResult = {
686
687
  success: false,
687
- error: timeoutError instanceof Error ? timeoutError.message : 'Execution timeout',
688
+ error: timeoutError instanceof Error ? timeoutError.message : 'Execution timeout'
688
689
  };
689
690
  }
690
691
  // Ensure executionResult has proper shape
691
692
  if (!executionResult) {
692
693
  executionResult = {
693
694
  success: false,
694
- error: 'Component execution returned no result',
695
+ error: 'Component execution returned no result'
695
696
  };
696
697
  errors.push('Component execution failed to return a result');
697
698
  }
698
699
  else if (!executionResult.success && executionResult.error) {
699
700
  // Add the execution error if it hasn't been captured elsewhere
700
701
  const errorMsg = `Component execution failed: ${executionResult.error}`;
701
- if (!errors.some((e) => e.includes(executionResult.error))) {
702
+ if (!errors.some(e => e.includes(executionResult.error))) {
702
703
  errors.push(errorMsg);
703
704
  }
704
705
  }
@@ -714,12 +715,13 @@ class ComponentRunner {
714
715
  const runtimeErrorsWithSource = await this.collectRuntimeErrors(page);
715
716
  // Filter out JSX element type errors when adding to errors array
716
717
  errors.push(...runtimeErrorsWithSource
717
- .filter((e) => {
718
+ .filter(e => {
718
719
  // Skip JSX element type errors from error count
719
- const isJSXError = e.type === 'invalid-element-type' || e.type === 'undefined-component';
720
+ const isJSXError = e.type === 'invalid-element-type' ||
721
+ e.type === 'undefined-component';
720
722
  return !isJSXError;
721
723
  })
722
- .map((e) => e.message)); // Extract messages for backward compat
724
+ .map(e => e.message)); // Extract messages for backward compat
723
725
  // Collect warnings (separate from errors)
724
726
  const collectedWarnings = await this.collectWarnings(page);
725
727
  warnings.push(...collectedWarnings);
@@ -728,20 +730,21 @@ class ComponentRunner {
728
730
  await page.waitForTimeout(asyncWaitTime);
729
731
  const asyncErrors = await this.collectRuntimeErrors(page);
730
732
  // Only add new errors (excluding JSX element type errors)
731
- asyncErrors.forEach((err) => {
732
- const isJSXError = err.type === 'invalid-element-type' || err.type === 'undefined-component';
733
+ asyncErrors.forEach(err => {
734
+ const isJSXError = err.type === 'invalid-element-type' ||
735
+ err.type === 'undefined-component';
733
736
  if (!isJSXError && !errors.includes(err.message)) {
734
737
  errors.push(err.message);
735
738
  runtimeErrorsWithSource.push(err); // Keep the structured version too
736
739
  }
737
- else if (isJSXError && !runtimeErrorsWithSource.some((e) => e.message === err.message)) {
740
+ else if (isJSXError && !runtimeErrorsWithSource.some(e => e.message === err.message)) {
738
741
  // Still track JSX errors for logging but don't add to errors array
739
742
  runtimeErrorsWithSource.push(err);
740
743
  }
741
744
  });
742
745
  // Also check for new warnings
743
746
  const asyncWarnings = await this.collectWarnings(page);
744
- asyncWarnings.forEach((warn) => {
747
+ asyncWarnings.forEach(warn => {
745
748
  if (!warnings.includes(warn)) {
746
749
  warnings.push(warn);
747
750
  }
@@ -756,13 +759,16 @@ class ComponentRunner {
756
759
  errors.push(`Possible render loop: ${renderCount} createElement calls detected (likely infinite loop)`);
757
760
  }
758
761
  // Determine success
759
- const success = errors.length === 0 && !hasRenderLoop && !hasTimeout && executionResult.success;
762
+ const success = errors.length === 0 &&
763
+ !hasRenderLoop &&
764
+ !hasTimeout &&
765
+ executionResult.success;
760
766
  // Combine runtime errors with data errors
761
767
  const allErrors = [...errors, ...dataErrors];
762
768
  // Map runtime errors with source info and specific rules
763
769
  // Filter out JSX element type errors - they're too noisy and often false positives
764
770
  const errorViolations = runtimeErrorsWithSource
765
- .filter((e) => {
771
+ .filter(e => {
766
772
  // Skip JSX element type errors - still logged but not reported as violations
767
773
  const isJSXError = e.rule === 'invalid-jsx-element' ||
768
774
  e.rule === 'undefined-jsx-component' ||
@@ -773,13 +779,13 @@ class ComponentRunner {
773
779
  }
774
780
  return !isJSXError;
775
781
  })
776
- .map((e) => ({
782
+ .map(e => ({
777
783
  message: e.message,
778
784
  severity: 'critical',
779
785
  rule: e.rule || 'runtime-error', // Use specific rule from collectRuntimeErrors
780
786
  line: 0,
781
787
  column: 0,
782
- source: e.source,
788
+ source: e.source
783
789
  }));
784
790
  // Add timeout error if detected
785
791
  if (hasTimeout) {
@@ -789,7 +795,7 @@ class ComponentRunner {
789
795
  rule: 'timeout',
790
796
  line: 0,
791
797
  column: 0,
792
- source: 'test-harness', // This is a test harness timeout
798
+ source: 'test-harness' // This is a test harness timeout
793
799
  });
794
800
  }
795
801
  // Add render loop error if detected
@@ -800,25 +806,25 @@ class ComponentRunner {
800
806
  rule: 'render-loop',
801
807
  line: 0,
802
808
  column: 0,
803
- source: 'test-harness', // This is a test harness detection
809
+ source: 'test-harness' // This is a test harness detection
804
810
  });
805
811
  }
806
812
  // Add data errors without source
807
- dataErrors.forEach((e) => {
813
+ dataErrors.forEach(e => {
808
814
  errorViolations.push({
809
815
  message: e,
810
816
  severity: 'critical',
811
817
  rule: 'runtime-error',
812
818
  line: 0,
813
819
  column: 0,
814
- source: 'user-component', // Data errors are from user's data access code
820
+ source: 'user-component' // Data errors are from user's data access code
815
821
  });
816
822
  });
817
823
  // Check warnings for critical patterns and move them to errors
818
824
  const criticalWarningViolations = [];
819
825
  const regularWarnings = [];
820
- warnings.forEach((w) => {
821
- if (ComponentRunner.CRITICAL_WARNING_PATTERNS.some((pattern) => pattern.test(w))) {
826
+ warnings.forEach(w => {
827
+ if (ComponentRunner.CRITICAL_WARNING_PATTERNS.some(pattern => pattern.test(w))) {
822
828
  // This is a critical warning - add to errors
823
829
  criticalWarningViolations.push({
824
830
  message: w,
@@ -826,7 +832,7 @@ class ComponentRunner {
826
832
  rule: 'critical-react-warning',
827
833
  line: 0,
828
834
  column: 0,
829
- source: 'react-framework',
835
+ source: 'react-framework'
830
836
  });
831
837
  }
832
838
  else {
@@ -840,17 +846,17 @@ class ComponentRunner {
840
846
  success: success && dataErrors.length === 0 && criticalWarningViolations.length === 0, // Fail on critical warnings too
841
847
  html,
842
848
  errors: allErrorViolations,
843
- warnings: regularWarnings.map((w) => ({
849
+ warnings: regularWarnings.map(w => ({
844
850
  message: w,
845
851
  severity: 'low',
846
852
  rule: 'warning',
847
853
  line: 0,
848
- column: 0,
854
+ column: 0
849
855
  })),
850
856
  console: consoleLogs,
851
857
  screenshot,
852
858
  executionTime: Date.now() - startTime,
853
- renderCount,
859
+ renderCount
854
860
  };
855
861
  if (debug) {
856
862
  this.dumpDebugInfo(result);
@@ -861,44 +867,42 @@ class ComponentRunner {
861
867
  // For catch block errors, we need to handle them specially
862
868
  const catchError = {
863
869
  message: error instanceof Error ? error.message : String(error),
864
- source: 'test-harness', // Errors caught here are usually test harness issues
870
+ source: 'test-harness' // Errors caught here are usually test harness issues
865
871
  };
866
872
  // Create error violations including the catch error
867
- const errorViolations = [
868
- {
873
+ const errorViolations = [{
869
874
  message: catchError.message,
870
875
  severity: 'critical',
871
876
  rule: 'runtime-error',
872
877
  line: 0,
873
878
  column: 0,
874
- source: catchError.source,
875
- },
876
- ];
879
+ source: catchError.source
880
+ }];
877
881
  // Add any data errors
878
- dataErrors.forEach((e) => {
882
+ dataErrors.forEach(e => {
879
883
  errorViolations.push({
880
884
  message: e,
881
885
  severity: 'critical',
882
886
  rule: 'runtime-error',
883
887
  line: 0,
884
888
  column: 0,
885
- source: 'user-component',
889
+ source: 'user-component'
886
890
  });
887
891
  });
888
892
  const result = {
889
893
  success: false,
890
894
  html: '',
891
895
  errors: errorViolations,
892
- warnings: warnings.map((w) => ({
896
+ warnings: warnings.map(w => ({
893
897
  message: w,
894
898
  severity: 'low',
895
899
  rule: 'warning',
896
900
  line: 0,
897
- column: 0,
901
+ column: 0
898
902
  })),
899
903
  console: consoleLogs,
900
904
  executionTime: Date.now() - startTime,
901
- renderCount,
905
+ renderCount
902
906
  };
903
907
  if (debug) {
904
908
  console.log('\n❌ Component execution failed with error:', error);
@@ -936,7 +940,7 @@ class ComponentRunner {
936
940
  try {
937
941
  await Promise.race([
938
942
  page.addScriptTag({ url }),
939
- new Promise((_, reject) => setTimeout(() => reject(new Error(`Script load timeout: ${url}`)), timeout)),
943
+ new Promise((_, reject) => setTimeout(() => reject(new Error(`Script load timeout: ${url}`)), timeout))
940
944
  ]);
941
945
  }
942
946
  catch (error) {
@@ -974,7 +978,7 @@ class ComponentRunner {
974
978
  React: typeof window.React !== 'undefined',
975
979
  ReactDOM: typeof window.ReactDOM !== 'undefined',
976
980
  Babel: typeof window.Babel !== 'undefined',
977
- MJRuntime: typeof window.MJReactRuntime !== 'undefined',
981
+ MJRuntime: typeof window.MJReactRuntime !== 'undefined'
978
982
  };
979
983
  });
980
984
  // All core libraries loaded successfully
@@ -993,10 +997,10 @@ class ComponentRunner {
993
997
  async loadComponentLibraries(page, specLibraries, allLibraries, debug = false) {
994
998
  if (debug) {
995
999
  console.log('📚 Loading component libraries:');
996
- console.log(' 🔍 Component requires libraries:', specLibraries.map((l) => l.name));
1000
+ console.log(' 🔍 Component requires libraries:', specLibraries.map(l => l.name));
997
1001
  console.log(' 📦 Total available ComponentLibrary entries:', allLibraries.length);
998
1002
  console.log(' 📋 Sample of available libraries (first 10):');
999
- allLibraries.slice(0, 10).forEach((lib) => {
1003
+ allLibraries.slice(0, 10).forEach(lib => {
1000
1004
  console.log(` - ${lib.Name}@${lib.Version} (${lib.Status})`);
1001
1005
  });
1002
1006
  }
@@ -1016,12 +1020,12 @@ class ComponentRunner {
1016
1020
  console.log(`📦 Loading ${specLib.name}:`, {
1017
1021
  cdnUrl: libDef.CDNUrl,
1018
1022
  globalVariable: libDef.GlobalVariable,
1019
- dependencies: libDef.Dependencies ? JSON.parse(libDef.Dependencies) : null,
1023
+ dependencies: libDef.Dependencies ? JSON.parse(libDef.Dependencies) : null
1020
1024
  });
1021
1025
  }
1022
1026
  // Load CSS if available
1023
1027
  if (libDef.CDNCssUrl) {
1024
- const cssUrls = libDef.CDNCssUrl.split(',').map((url) => url.trim());
1028
+ const cssUrls = libDef.CDNCssUrl.split(',').map(url => url.trim());
1025
1029
  for (const cssUrl of cssUrls) {
1026
1030
  if (cssUrl) {
1027
1031
  await page.addStyleTag({ url: cssUrl });
@@ -1037,7 +1041,7 @@ class ComponentRunner {
1037
1041
  // Add timeout for library loading (Recommendation #3)
1038
1042
  await Promise.race([
1039
1043
  page.addScriptTag({ url: libDef.CDNUrl }),
1040
- new Promise((_, reject) => setTimeout(() => reject(new Error(`Library load timeout: ${libDef.CDNUrl}`)), 10000)),
1044
+ new Promise((_, reject) => setTimeout(() => reject(new Error(`Library load timeout: ${libDef.CDNUrl}`)), 10000))
1041
1045
  ]);
1042
1046
  // Verify the library loaded
1043
1047
  const isLoaded = await page.evaluate((globalVar) => {
@@ -1064,12 +1068,10 @@ class ComponentRunner {
1064
1068
  if (debug) {
1065
1069
  // Log all available global variables that look like libraries
1066
1070
  // Get all the global variables we expect from the spec
1067
- const expectedGlobals = specLibraries
1068
- .map((lib) => {
1071
+ const expectedGlobals = specLibraries.map(lib => {
1069
1072
  const libDef = libraryMap.get(lib.name.toLowerCase());
1070
1073
  return libDef?.GlobalVariable;
1071
- })
1072
- .filter(Boolean);
1074
+ }).filter(Boolean);
1073
1075
  const globals = await page.evaluate((expected) => {
1074
1076
  const relevantGlobals = {};
1075
1077
  // Check the expected globals from the spec
@@ -1143,7 +1145,7 @@ class ComponentRunner {
1143
1145
  '',
1144
1146
  'Inspect all instances where you are using JSX elements that come from libraries or components to ensure they are properly referenced.',
1145
1147
  '',
1146
- 'The exact fix depends on the specific library or component structure.',
1148
+ 'The exact fix depends on the specific library or component structure.'
1147
1149
  ].join('\\n');
1148
1150
  // Log to both console and error tracking
1149
1151
  console.error('🔴 Invalid JSX Element Type Detected:', errorMsg);
@@ -1154,7 +1156,7 @@ class ComponentRunner {
1154
1156
  type: 'invalid-element-type',
1155
1157
  phase: 'createElement',
1156
1158
  source: 'enhanced-detection',
1157
- elementInfo: objectInfo,
1159
+ elementInfo: objectInfo
1158
1160
  });
1159
1161
  // Still try to call the original to get React's error too
1160
1162
  // This will provide the component stack trace
@@ -1169,7 +1171,7 @@ class ComponentRunner {
1169
1171
  '',
1170
1172
  'Inspect how this component is being accessed - it may not exist in the expected location or may have a different name.',
1171
1173
  '',
1172
- 'Check that the component exists in your dependencies or libraries and is properly referenced.',
1174
+ 'Check that the component exists in your dependencies or libraries and is properly referenced.'
1173
1175
  ].join('\\n');
1174
1176
  console.error('🔴 Undefined JSX Component:', errorMsg);
1175
1177
  window.__testHarnessRuntimeErrors = window.__testHarnessRuntimeErrors || [];
@@ -1177,7 +1179,7 @@ class ComponentRunner {
1177
1179
  message: errorMsg,
1178
1180
  type: 'undefined-component',
1179
1181
  phase: 'createElement',
1180
- source: 'enhanced-detection',
1182
+ source: 'enhanced-detection'
1181
1183
  });
1182
1184
  }
1183
1185
  // Call original createElement
@@ -1187,7 +1189,7 @@ class ComponentRunner {
1187
1189
  // Override console.error
1188
1190
  const originalConsoleError = console.error;
1189
1191
  console.error = function (...args) {
1190
- const errorText = args.map((arg) => (typeof arg === 'object' ? JSON.stringify(arg) : String(arg))).join(' ');
1192
+ const errorText = args.map(arg => typeof arg === 'object' ? JSON.stringify(arg) : String(arg)).join(' ');
1191
1193
  // Check if this is a warning rather than an error
1192
1194
  // React warnings typically start with "Warning:" or contain warning-related text
1193
1195
  const isWarning = errorText.includes('Warning:') ||
@@ -1218,15 +1220,16 @@ class ComponentRunner {
1218
1220
  isAvailableLibrary: false,
1219
1221
  matchedLibrary: null,
1220
1222
  specLibraries: spec?.libraries || [],
1221
- specDependencies: spec?.dependencies || [],
1223
+ specDependencies: spec?.dependencies || []
1222
1224
  };
1223
1225
  // Check if it's in spec libraries
1224
1226
  result.isInSpecLibraries = result.specLibraries.some((lib) => lib.globalVariable === identifier);
1225
- // Check if it's in spec dependencies
1227
+ // Check if it's in spec dependencies
1226
1228
  result.isInSpecDependencies = result.specDependencies.some((dep) => dep.name === identifier);
1227
1229
  // Check against ALL available libraries (case-insensitive)
1228
1230
  if (availableLibraries) {
1229
- const availableLib = availableLibraries.find((lib) => lib.GlobalVariable && lib.GlobalVariable.toLowerCase() === identifier.toLowerCase());
1231
+ const availableLib = availableLibraries.find((lib) => lib.GlobalVariable &&
1232
+ lib.GlobalVariable.toLowerCase() === identifier.toLowerCase());
1230
1233
  if (availableLib) {
1231
1234
  result.isAvailableLibrary = true;
1232
1235
  result.matchedLibrary = availableLib;
@@ -1239,35 +1242,29 @@ class ComponentRunner {
1239
1242
  // Case 1: Trying to use a library not in their spec
1240
1243
  if (analysis.isAvailableLibrary && !analysis.isInSpecLibraries) {
1241
1244
  const libList = analysis.specLibraries.length > 0
1242
- ? analysis.specLibraries
1243
- .map((l) => l.globalVariable || l.name)
1244
- .filter(Boolean)
1245
- .join(', ')
1245
+ ? analysis.specLibraries.map((l) => l.globalVariable || l.name).filter(Boolean).join(', ')
1246
1246
  : 'no third-party libraries';
1247
- return (`${identifier} is not defined. It appears you're trying to use the ${analysis.matchedLibrary.Name} library. ` +
1247
+ return `${identifier} is not defined. It appears you're trying to use the ${analysis.matchedLibrary.Name} library. ` +
1248
1248
  `You do NOT have access to this library. ` +
1249
1249
  `Your architect gave you access to: ${libList}. ` +
1250
- `You must work within these constraints and cannot load additional libraries.`);
1250
+ `You must work within these constraints and cannot load additional libraries.`;
1251
1251
  }
1252
1252
  // Case 2: Should be a component but not properly accessed
1253
1253
  if (analysis.isInSpecDependencies) {
1254
- return (`${identifier} is not defined. This component exists in your dependencies. ` +
1254
+ return `${identifier} is not defined. This component exists in your dependencies. ` +
1255
1255
  `Ensure you've destructured it: const { ${identifier} } = components; ` +
1256
- `or accessed it as: components.${identifier}`);
1256
+ `or accessed it as: components.${identifier}`;
1257
1257
  }
1258
1258
  // Case 3: Not a valid library or component
1259
1259
  const libList = analysis.specLibraries.length > 0
1260
- ? `Available libraries: ${analysis.specLibraries
1261
- .map((l) => l.globalVariable || l.name)
1262
- .filter(Boolean)
1263
- .join(', ')}`
1260
+ ? `Available libraries: ${analysis.specLibraries.map((l) => l.globalVariable || l.name).filter(Boolean).join(', ')}`
1264
1261
  : 'No third-party libraries are available';
1265
1262
  const depList = analysis.specDependencies.length > 0
1266
1263
  ? `Available components: ${analysis.specDependencies.map((d) => d.name).join(', ')}`
1267
1264
  : 'No component dependencies are available';
1268
- return (`${identifier} is not defined. This is not a valid library or component in your specification. ` +
1265
+ return `${identifier} is not defined. This is not a valid library or component in your specification. ` +
1269
1266
  `${libList}. ${depList}. ` +
1270
- `You must only use the libraries and components specified in your component specification.`);
1267
+ `You must only use the libraries and components specified in your component specification.`;
1271
1268
  };
1272
1269
  // Global error handler
1273
1270
  window.addEventListener('error', (event) => {
@@ -1285,7 +1282,7 @@ class ComponentRunner {
1285
1282
  stack: event.error?.stack,
1286
1283
  type: 'undefined-identifier',
1287
1284
  source: 'user-component',
1288
- identifier: identifier,
1285
+ identifier: identifier
1289
1286
  });
1290
1287
  window.__testHarnessTestFailed = true;
1291
1288
  return;
@@ -1299,7 +1296,7 @@ class ComponentRunner {
1299
1296
  message: event.error?.message || event.message,
1300
1297
  stack: event.error?.stack,
1301
1298
  type: 'runtime',
1302
- source: source,
1299
+ source: source
1303
1300
  });
1304
1301
  window.__testHarnessTestFailed = true;
1305
1302
  });
@@ -1309,7 +1306,7 @@ class ComponentRunner {
1309
1306
  message: 'Unhandled Promise Rejection: ' + (event.reason?.message || event.reason),
1310
1307
  stack: event.reason?.stack,
1311
1308
  type: 'promise-rejection',
1312
- source: 'user-component', // Async errors are likely from user code
1309
+ source: 'user-component' // Async errors are likely from user code
1313
1310
  });
1314
1311
  window.__testHarnessTestFailed = true;
1315
1312
  event.preventDefault();
@@ -1324,17 +1321,20 @@ class ComponentRunner {
1324
1321
  return {
1325
1322
  runtimeErrors: window.__testHarnessRuntimeErrors || [],
1326
1323
  consoleErrors: window.__testHarnessConsoleErrors || [],
1327
- testFailed: window.__testHarnessTestFailed || false,
1324
+ testFailed: window.__testHarnessTestFailed || false
1328
1325
  };
1329
1326
  });
1330
1327
  // Track unique errors and their counts
1331
1328
  const errorMap = new Map();
1332
1329
  // Check if we have any specific React render errors
1333
- const hasSpecificReactError = errorData.runtimeErrors.some((error) => error.type === 'react-render-error' && !error.message.includes('Script error'));
1330
+ const hasSpecificReactError = errorData.runtimeErrors.some((error) => error.type === 'react-render-error' &&
1331
+ !error.message.includes('Script error'));
1334
1332
  // Process runtime errors with their source information
1335
1333
  errorData.runtimeErrors.forEach((error) => {
1336
1334
  // Skip generic "Script error" messages if we have more specific React errors
1337
- if (hasSpecificReactError && error.type === 'runtime' && error.message === 'Script error.') {
1335
+ if (hasSpecificReactError &&
1336
+ error.type === 'runtime' &&
1337
+ error.message === 'Script error.') {
1338
1338
  return; // Skip this generic error
1339
1339
  }
1340
1340
  // Map error types to specific rule names
@@ -1381,9 +1381,9 @@ class ComponentRunner {
1381
1381
  message: error.message,
1382
1382
  source: error.source,
1383
1383
  type: error.type,
1384
- rule: rule,
1384
+ rule: rule
1385
1385
  },
1386
- count: 1,
1386
+ count: 1
1387
1387
  });
1388
1388
  }
1389
1389
  });
@@ -1399,9 +1399,9 @@ class ComponentRunner {
1399
1399
  message: error,
1400
1400
  source: 'react-framework',
1401
1401
  type: 'console-error',
1402
- rule: 'console-error',
1402
+ rule: 'console-error'
1403
1403
  },
1404
- count: 1,
1404
+ count: 1
1405
1405
  });
1406
1406
  }
1407
1407
  });
@@ -1409,10 +1409,12 @@ class ComponentRunner {
1409
1409
  const errors = [];
1410
1410
  errorMap.forEach(({ error, count }) => {
1411
1411
  // Append count if > 1
1412
- const message = count > 1 ? `${error.message} (occurred ${count} times)` : error.message;
1412
+ const message = count > 1
1413
+ ? `${error.message} (occurred ${count} times)`
1414
+ : error.message;
1413
1415
  errors.push({
1414
1416
  ...error,
1415
- message,
1417
+ message
1416
1418
  });
1417
1419
  });
1418
1420
  return errors;
@@ -1423,7 +1425,7 @@ class ComponentRunner {
1423
1425
  async collectWarnings(page) {
1424
1426
  const warningData = await page.evaluate(() => {
1425
1427
  return {
1426
- consoleWarnings: window.__testHarnessConsoleWarnings || [],
1428
+ consoleWarnings: window.__testHarnessConsoleWarnings || []
1427
1429
  };
1428
1430
  });
1429
1431
  const warnings = [];
@@ -1455,23 +1457,23 @@ class ComponentRunner {
1455
1457
  });
1456
1458
  }
1457
1459
  async buildLocalMJUtilities(contextUser) {
1458
- console.log(' Building local MJ utilities');
1459
- const rv = new global_1.RunView();
1460
- const rq = new global_1.RunQuery();
1461
- const md = new global_1.Metadata();
1460
+ console.log(" Building local MJ utilities");
1461
+ const rv = new core_1.RunView();
1462
+ const rq = new core_1.RunQuery();
1463
+ const md = new core_1.Metadata();
1462
1464
  return {
1463
1465
  rv: {
1464
1466
  RunView: rv.RunView,
1465
- RunViews: rv.RunViews,
1467
+ RunViews: rv.RunViews
1466
1468
  },
1467
1469
  rq: {
1468
- RunQuery: rq.RunQuery,
1470
+ RunQuery: rq.RunQuery
1469
1471
  },
1470
1472
  md: {
1471
1473
  GetEntityObject: md.GetEntityObject, // return the function
1472
- Entities: md.Entities, // return the function
1474
+ Entities: md.Entities // return the function
1473
1475
  },
1474
- ai: await this.BuildLocalSimpleAITools(contextUser),
1476
+ ai: await this.BuildLocalSimpleAITools(contextUser)
1475
1477
  };
1476
1478
  }
1477
1479
  async BuildLocalSimpleAITools(contextUser) {
@@ -1488,7 +1490,8 @@ class ComponentRunner {
1488
1490
  await aiEngine.Config(false, params.contextUser);
1489
1491
  const models = aiEngine.Models;
1490
1492
  for (const preferredModel of params.preferredModels) {
1491
- model = models.find((m) => m.Name === preferredModel && m.IsActive === true);
1493
+ model = models.find((m) => m.Name === preferredModel &&
1494
+ m.IsActive === true);
1492
1495
  if (model)
1493
1496
  break;
1494
1497
  }
@@ -1498,7 +1501,8 @@ class ComponentRunner {
1498
1501
  if (params.modelPower === 'lowest') {
1499
1502
  // Get lowest power model by sorting in reverse
1500
1503
  await aiEngine.Config(false, params.contextUser);
1501
- const llmModels = aiEngine.Models.filter((m) => m.AIModelType === 'LLM' && m.IsActive === true);
1504
+ const llmModels = aiEngine.Models.filter((m) => m.AIModelType === 'LLM' &&
1505
+ m.IsActive === true);
1502
1506
  model = llmModels.sort((a, b) => (a.PowerRank || 0) - (b.PowerRank || 0))[0];
1503
1507
  }
1504
1508
  else if (params.modelPower === 'highest') {
@@ -1507,7 +1511,8 @@ class ComponentRunner {
1507
1511
  else {
1508
1512
  // Default to medium - get a model in the middle range
1509
1513
  await aiEngine.Config(false, params.contextUser);
1510
- const llmModels = aiEngine.Models.filter((m) => m.AIModelType === 'LLM' && m.IsActive === true);
1514
+ const llmModels = aiEngine.Models.filter((m) => m.AIModelType === 'LLM' &&
1515
+ m.IsActive === true);
1511
1516
  const sortedModels = llmModels.sort((a, b) => (b.PowerRank || 0) - (a.PowerRank || 0));
1512
1517
  const midIndex = Math.floor(sortedModels.length / 2);
1513
1518
  model = sortedModels[midIndex] || sortedModels[0];
@@ -1516,7 +1521,9 @@ class ComponentRunner {
1516
1521
  // Build full conversation from messages if provided
1517
1522
  let fullUserPrompt = '';
1518
1523
  if (params.messages && params.messages.length > 0) {
1519
- fullUserPrompt = params.messages.map((m) => `${m.role === 'user' ? 'User' : 'Assistant'}: ${m.message}`).join('\n');
1524
+ fullUserPrompt = params.messages
1525
+ .map(m => `${m.role === 'user' ? 'User' : 'Assistant'}: ${m.message}`)
1526
+ .join('\n');
1520
1527
  }
1521
1528
  // Execute the prompt using AIEngine
1522
1529
  const result = await aiEngine.SimpleLLMCompletion(fullUserPrompt || '', params.contextUser || {}, // Provide empty object if no context user
@@ -1537,33 +1544,35 @@ class ComponentRunner {
1537
1544
  success: true,
1538
1545
  result: result,
1539
1546
  resultObject,
1540
- modelName: model?.Name || 'Unknown',
1547
+ modelName: model?.Name || 'Unknown'
1541
1548
  };
1542
1549
  }
1543
1550
  catch (error) {
1544
- (0, global_1.LogError)(error);
1551
+ (0, core_1.LogError)(error);
1545
1552
  return {
1546
1553
  success: false,
1547
1554
  result: 'Failed to execute prompt: ' + (error instanceof Error ? error.message : String(error)),
1548
- modelName: '',
1555
+ modelName: ''
1549
1556
  };
1550
1557
  }
1551
1558
  },
1552
1559
  EmbedText: async (params) => {
1553
1560
  try {
1554
1561
  // Handle both single string and array of strings
1555
- const texts = Array.isArray(params.textToEmbed) ? params.textToEmbed : [params.textToEmbed];
1562
+ const texts = Array.isArray(params.textToEmbed)
1563
+ ? params.textToEmbed
1564
+ : [params.textToEmbed];
1556
1565
  // Use appropriate embedding model based on size
1557
1566
  await aiEngine.Config(false, params.contextUser);
1558
1567
  // Get embedding models and filter by size preference
1559
- const embeddingModels = aiEngine.Models.filter((m) => m.AIModelType === 'Embeddings' && m.IsActive === true);
1568
+ const embeddingModels = aiEngine.Models.filter((m) => m.AIModelType === 'Embeddings' &&
1569
+ m.IsActive === true);
1560
1570
  // Select model based on size preference
1561
1571
  let model;
1562
1572
  if (params.modelSize === 'small') {
1563
1573
  // Prefer local/smaller models for 'small'
1564
- model =
1565
- embeddingModels.find((m) => m.Vendor === 'LocalEmbeddings') ||
1566
- embeddingModels.sort((a, b) => (a.PowerRank || 0) - (b.PowerRank || 0))[0];
1574
+ model = embeddingModels.find((m) => m.Vendor === 'LocalEmbeddings') ||
1575
+ embeddingModels.sort((a, b) => (a.PowerRank || 0) - (b.PowerRank || 0))[0];
1567
1576
  }
1568
1577
  else {
1569
1578
  // Use more powerful models for 'medium'
@@ -1584,19 +1593,21 @@ class ComponentRunner {
1584
1593
  }
1585
1594
  }
1586
1595
  // Return single embedding or array based on input
1587
- const returnEmbeddings = Array.isArray(params.textToEmbed) ? embeddings : embeddings[0];
1596
+ const returnEmbeddings = Array.isArray(params.textToEmbed)
1597
+ ? embeddings
1598
+ : embeddings[0];
1588
1599
  return {
1589
1600
  result: returnEmbeddings,
1590
1601
  modelName: model.Name,
1591
- vectorDimensions: embeddings[0]?.length || 0,
1602
+ vectorDimensions: embeddings[0]?.length || 0
1592
1603
  };
1593
1604
  }
1594
1605
  catch (error) {
1595
- (0, global_1.LogError)(error);
1606
+ (0, core_1.LogError)(error);
1596
1607
  throw error; // Re-throw for embeddings as they're critical
1597
1608
  }
1598
1609
  },
1599
- VectorService: new ai_vectors_memory_1.SimpleVectorService(),
1610
+ VectorService: new ai_vectors_memory_1.SimpleVectorService()
1600
1611
  };
1601
1612
  }
1602
1613
  /**
@@ -1609,7 +1620,7 @@ class ComponentRunner {
1609
1620
  // UserInfo is a simple object that can be serialized
1610
1621
  const serializedContextUser = JSON.parse(JSON.stringify(options.contextUser));
1611
1622
  // utilities - favor the one passed in by the caller, or fall back to the local ones
1612
- const util = options.utilities || (await this.buildLocalMJUtilities(options.contextUser));
1623
+ const util = options.utilities || await this.buildLocalMJUtilities(options.contextUser);
1613
1624
  // Create a lightweight mock metadata object with serializable data
1614
1625
  // This avoids authentication/provider issues in the browser context
1615
1626
  let entitiesData = [];
@@ -1644,7 +1655,7 @@ class ComponentRunner {
1644
1655
  AuditLogTypes: [],
1645
1656
  Authorizations: [],
1646
1657
  VisibleExplorerNavigationItems: [],
1647
- AllExplorerNavigationItems: [],
1658
+ AllExplorerNavigationItems: []
1648
1659
  };
1649
1660
  // Inject both the contextUser and mock metadata into the page
1650
1661
  // Playwright only accepts a single argument, so wrap in an object
@@ -1660,7 +1671,7 @@ class ComponentRunner {
1660
1671
  // This must be available before any component code runs
1661
1672
  if (!window.Metadata) {
1662
1673
  window.Metadata = {
1663
- Provider: mockMd,
1674
+ Provider: mockMd
1664
1675
  };
1665
1676
  // Created global Metadata mock with Provider (early)
1666
1677
  }
@@ -1731,7 +1742,7 @@ class ComponentRunner {
1731
1742
  }
1732
1743
  catch (error) {
1733
1744
  const errorMessage = error instanceof Error ? error.message : String(error);
1734
- const entities = params.map((p) => p.EntityName || 'unknown').join(', ');
1745
+ const entities = params.map(p => p.EntityName || 'unknown').join(', ');
1735
1746
  // Debug logging for errors
1736
1747
  if (debug) {
1737
1748
  console.log(`❌ RunViews FAILED: Entities=[${entities}]`);
@@ -1800,7 +1811,7 @@ class ComponentRunner {
1800
1811
  return {
1801
1812
  success: false,
1802
1813
  result: errorMessage,
1803
- modelName: '',
1814
+ modelName: ''
1804
1815
  };
1805
1816
  }
1806
1817
  });
@@ -1813,7 +1824,9 @@ class ComponentRunner {
1813
1824
  const paramsWithUser = { ...params, contextUser: options.contextUser };
1814
1825
  const result = await util.ai.EmbedText(paramsWithUser);
1815
1826
  if (debug) {
1816
- const count = Array.isArray(result.result) ? (Array.isArray(result.result[0]) ? result.result.length : 1) : 1;
1827
+ const count = Array.isArray(result.result)
1828
+ ? (Array.isArray(result.result[0]) ? result.result.length : 1)
1829
+ : 1;
1817
1830
  console.log(`🤖 EmbedText SUCCESS: Model="${result.modelName}" Count=${count} Dims=${result.vectorDimensions}`);
1818
1831
  }
1819
1832
  return result;
@@ -1836,9 +1849,7 @@ class ComponentRunner {
1836
1849
  const VectorService = window.MJReactRuntime?.SimpleVectorService ||
1837
1850
  class {
1838
1851
  // Stub implementation if not available
1839
- cosineSimilarity(_a, _b) {
1840
- return 0;
1841
- }
1852
+ cosineSimilarity(_a, _b) { return 0; }
1842
1853
  };
1843
1854
  window.__mjUtilities = {
1844
1855
  md: {
@@ -1850,25 +1861,25 @@ class ComponentRunner {
1850
1861
  return mockMd.Entities.find((e) => e.Name === name) || null;
1851
1862
  },
1852
1863
  // Keep async function for GetEntityObject for compatibility
1853
- GetEntityObject: async (entityName) => await window.__mjGetEntityObject(entityName),
1864
+ GetEntityObject: async (entityName) => await window.__mjGetEntityObject(entityName)
1854
1865
  },
1855
1866
  rv: {
1856
1867
  RunView: async (params) => await window.__mjRunView(params),
1857
- RunViews: async (params) => await window.__mjRunViews(params),
1868
+ RunViews: async (params) => await window.__mjRunViews(params)
1858
1869
  },
1859
1870
  rq: {
1860
- RunQuery: async (params) => await window.__mjRunQuery(params),
1871
+ RunQuery: async (params) => await window.__mjRunQuery(params)
1861
1872
  },
1862
1873
  ai: {
1863
1874
  ExecutePrompt: async (params) => await window.__mjExecutePrompt(params),
1864
1875
  EmbedText: async (params) => await window.__mjEmbedText(params),
1865
- VectorService: new VectorService(),
1866
- },
1876
+ VectorService: new VectorService()
1877
+ }
1867
1878
  };
1868
1879
  // Update or create global Metadata mock (in case it wasn't created earlier)
1869
1880
  if (!window.Metadata) {
1870
1881
  window.Metadata = {
1871
- Provider: mockMd,
1882
+ Provider: mockMd
1872
1883
  };
1873
1884
  // Created global Metadata mock with Provider (late)
1874
1885
  }