@memograph/cli 0.1.8 → 1.0.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.
@@ -53,6 +53,7 @@ exports.runInteractiveMode = runInteractiveMode;
53
53
  const readline = __importStar(require("readline"));
54
54
  const inspect_js_1 = require("../core/inspect.js");
55
55
  const load_js_1 = require("../core/load.js");
56
+ const progress_js_1 = require("../core/progress.js");
56
57
  const render_js_1 = require("../core/render.js");
57
58
  const providers_js_1 = require("../core/llm/providers.js");
58
59
  const wizard_js_1 = require("./wizard.js");
@@ -503,17 +504,45 @@ function showBanner() {
503
504
  renderBanner(true);
504
505
  }
505
506
  /**
506
- * Check configuration and prompt wizard if needed
507
+ * Resolve analyze mode from settings + env
508
+ */
509
+ function resolveAnalyzeMode(settings) {
510
+ if (process.env.MEMOGRAPH_ANALYZE_MODE === 'llm') {
511
+ return 'llm';
512
+ }
513
+ return settings.analyzeMode || 'hosted';
514
+ }
515
+ /**
516
+ * Check configuration and prompt for required setup if needed
507
517
  */
508
518
  async function checkAndPromptWizard(settings) {
509
- const status = (0, settings_js_1.getConfigStatus)(settings);
519
+ settings.analyzeMode = resolveAnalyzeMode(settings);
520
+ const status = (0, settings_js_1.getAnalyzeConfigStatus)(settings);
510
521
  if (status.configured) {
511
522
  return true;
512
523
  }
513
524
  console.log(`\n❌ ${status.message}`);
514
- console.log('\nAI model is not configured yet.');
525
+ const mode = resolveAnalyzeMode(settings);
526
+ console.log(`\n${mode === 'hosted' ? 'Analyze API' : 'AI model'} is not configured yet.`);
515
527
  // Ensure stdin is active and in the correct mode
516
528
  await ensureStdinReady();
529
+ if (mode === 'hosted') {
530
+ const rl = createRL();
531
+ const response = await ask(rl, 'Set Analyze API URL now? (Y/n): ');
532
+ rl.close();
533
+ if (response.toLowerCase() === 'y' || response === '') {
534
+ await ensureStdinReady();
535
+ const rl2 = createRL();
536
+ const apiUrl = await ask(rl2, `Enter Analyze API URL (default: ${settings.api.url || 'https://ap-south-1-test.memograph.click/v1/analyze'}): `);
537
+ rl2.close();
538
+ if (apiUrl.trim()) {
539
+ settings.api.url = apiUrl.trim();
540
+ }
541
+ (0, settings_js_1.saveSettings)(settings);
542
+ return (0, settings_js_1.isAnalyzeConfigured)(settings);
543
+ }
544
+ return false;
545
+ }
517
546
  const rl = createRL();
518
547
  const response = await ask(rl, 'Run Setup Wizard now? (Y/n): ');
519
548
  rl.close();
@@ -521,9 +550,9 @@ async function checkAndPromptWizard(settings) {
521
550
  console.clear();
522
551
  const newSettings = await (0, wizard_js_1.runSetupWizard)(settings);
523
552
  Object.assign(settings, newSettings);
553
+ settings.analyzeMode = 'llm';
524
554
  (0, settings_js_1.saveSettings)(settings);
525
- // Check again
526
- return (0, settings_js_1.isLLMConfigured)(settings);
555
+ return (0, settings_js_1.isAnalyzeConfigured)(settings);
527
556
  }
528
557
  return false;
529
558
  }
@@ -531,17 +560,24 @@ async function checkAndPromptWizard(settings) {
531
560
  * Display current settings
532
561
  */
533
562
  function displaySettings(settings) {
563
+ const mode = resolveAnalyzeMode(settings);
534
564
  const maskedKey = settings.llm.apiKey
535
565
  ? settings.llm.apiKey.substring(0, 8) + '••••••••••••'
536
566
  : '(not set)';
537
567
  console.log('\n╭─ Current Settings ─────────────────────────────────────╮');
538
568
  console.log('│ │');
539
- console.log(`│ ◆ LLM Provider: ${settings.llm.provider.padEnd(20)}│`);
540
- console.log(`│ ◆ LLM Model: ${settings.llm.model.padEnd(20)}│`);
541
- console.log(`│ ◆ Temperature: ${String(settings.llm.temperature).padEnd(20)}│`);
542
- console.log(`│ ◆ Max Tokens: ${String(settings.llm.maxTokens).padEnd(20)}│`);
543
- console.log(`│ ◆ Base URL: ${(settings.llm.baseUrl || '(default)').padEnd(20)}│`);
544
- console.log(`│ ◆ API Key: ${maskedKey.padEnd(20)}│`);
569
+ console.log(`│ ◆ Analyze Mode: ${mode.padEnd(20)}│`);
570
+ console.log(`│ ◆ API URL: ${(settings.api.url || '(not set)').padEnd(20)}│`);
571
+ console.log(`│ ◆ API Timeout: ${String(settings.api.timeoutMs).padEnd(20)}│`);
572
+ console.log(`│ ◆ API Retries: ${String(settings.api.retries).padEnd(20)}│`);
573
+ if (mode === 'llm') {
574
+ console.log(`│ ◆ LLM Provider: ${settings.llm.provider.padEnd(20)}│`);
575
+ console.log(`│ ◆ LLM Model: ${settings.llm.model.padEnd(20)}│`);
576
+ console.log(`│ ◆ Temperature: ${String(settings.llm.temperature).padEnd(20)}│`);
577
+ console.log(`│ ◆ Max Tokens: ${String(settings.llm.maxTokens).padEnd(20)}│`);
578
+ console.log(`│ ◆ LLM Base URL: ${(settings.llm.baseUrl || '(default)').padEnd(20)}│`);
579
+ console.log(`│ ◆ LLM API Key: ${maskedKey.padEnd(20)}│`);
580
+ }
545
581
  console.log('│ │');
546
582
  console.log('╰──────────────────────────────────────────────────────╯\n');
547
583
  }
@@ -549,160 +585,286 @@ function displaySettings(settings) {
549
585
  * Settings menu
550
586
  */
551
587
  async function settingsMenu(settings) {
552
- const options = [
553
- 'Quick Setup (Wizard)',
554
- 'Change LLM Provider',
555
- 'Change LLM Model',
556
- 'Change Temperature',
557
- 'Change Max Tokens',
558
- 'Change Base URL',
559
- 'Set/Update API Key',
560
- 'Show raw config',
561
- 'Back to main menu',
562
- ];
563
588
  while (true) {
589
+ const mode = resolveAnalyzeMode(settings);
590
+ settings.analyzeMode = mode;
591
+ const options = mode === 'hosted'
592
+ ? [
593
+ 'Change Analyze Mode',
594
+ 'Change API URL',
595
+ 'Change API Timeout',
596
+ 'Change API Retries',
597
+ 'Advanced: LLM Setup (Legacy)',
598
+ 'Show raw config',
599
+ 'Back to main menu',
600
+ ]
601
+ : [
602
+ 'Change Analyze Mode',
603
+ 'Quick Setup (Wizard)',
604
+ 'Change LLM Provider',
605
+ 'Change LLM Model',
606
+ 'Change Temperature',
607
+ 'Change Max Tokens',
608
+ 'Change Base URL',
609
+ 'Set/Update API Key',
610
+ 'Show raw config',
611
+ 'Back to main menu',
612
+ ];
564
613
  const choice = await selectMenu('Settings', options);
565
- switch (choice) {
566
- case 0: // Quick setup wizard
567
- {
568
- console.clear();
569
- const newSettings = await (0, wizard_js_1.runSetupWizard)(settings);
570
- Object.assign(settings, newSettings);
571
- (0, settings_js_1.saveSettings)(settings);
572
- console.clear();
573
- displaySettings(settings);
574
- await ensureStdinReady();
575
- await ask(createRL(), '\nPress Enter to continue...');
576
- }
577
- break;
578
- case 1: // Change provider
579
- {
580
- const selectedProvider = await selectProvider();
581
- settings.llm.provider = selectedProvider;
582
- const providerInfo = (0, providers_js_1.getProviderInfo)(selectedProvider);
583
- if (providerInfo?.defaultBaseUrl) {
584
- settings.llm.baseUrl = providerInfo.defaultBaseUrl;
585
- }
586
- (0, settings_js_1.saveSettings)(settings);
587
- console.log('\n✓ Provider updated to', settings.llm.provider);
588
- await ensureStdinReady();
589
- await ask(createRL(), '\nPress Enter to continue...');
590
- }
591
- break;
592
- case 2: // Change model
593
- {
594
- const models = settings.llm.provider === 'openai'
595
- ? ['gpt-4o-mini (recommended)', 'gpt-4o', 'gpt-3.5-turbo', 'Custom...']
596
- : ['claude-3-5-sonnet-20241022 (recommended)', 'claude-3-5-haiku-20241022', 'Custom...'];
597
- const modelChoice = await selectMenu('Select LLM Model', models);
598
- const selected = models[modelChoice];
599
- if (selected === 'Custom...') {
614
+ if (mode === 'hosted') {
615
+ switch (choice) {
616
+ case 0: // Change mode
617
+ {
618
+ const modeChoice = await selectMenu('Select Analyze Mode', [
619
+ 'hosted (default)',
620
+ 'llm (legacy fallback)',
621
+ ]);
622
+ settings.analyzeMode = modeChoice === 0 ? 'hosted' : 'llm';
623
+ (0, settings_js_1.saveSettings)(settings);
624
+ console.log('\n✓ Analyze mode updated to', settings.analyzeMode);
600
625
  await ensureStdinReady();
601
- const customModel = await ask(createRL(), 'Enter custom model name: ');
602
- settings.llm.model = customModel;
626
+ await ask(createRL(), '\nPress Enter to continue...');
603
627
  }
604
- else {
605
- settings.llm.model = selected.split(' ')[0];
628
+ break;
629
+ case 1: // API URL
630
+ {
631
+ await ensureStdinReady();
632
+ const apiUrl = await ask(createRL(), `Enter Analyze API URL (current: ${settings.api.url}): `);
633
+ if (apiUrl.trim()) {
634
+ settings.api.url = apiUrl.trim();
635
+ (0, settings_js_1.saveSettings)(settings);
636
+ console.log('\n✓ API URL updated');
637
+ }
638
+ await ensureStdinReady();
639
+ await ask(createRL(), '\nPress Enter to continue...');
606
640
  }
607
- (0, settings_js_1.saveSettings)(settings);
608
- console.log('\n✓ Model updated to', settings.llm.model);
609
- await ensureStdinReady();
610
- await ask(createRL(), '\nPress Enter to continue...');
611
- }
612
- break;
613
- case 3: // Change temperature
614
- {
615
- await ensureStdinReady();
616
- const temp = await ask(createRL(), 'Enter temperature (0.0-1.0, default 0.3): ');
617
- if (temp) {
618
- const tempVal = parseFloat(temp);
619
- if (!isNaN(tempVal) && tempVal >= 0 && tempVal <= 1) {
620
- settings.llm.temperature = tempVal;
641
+ break;
642
+ case 2: // API timeout
643
+ {
644
+ await ensureStdinReady();
645
+ const timeout = await ask(createRL(), `Enter API timeout in ms (current: ${settings.api.timeoutMs}): `);
646
+ const timeoutVal = parseInt(timeout, 10);
647
+ if (!isNaN(timeoutVal) && timeoutVal > 0) {
648
+ settings.api.timeoutMs = timeoutVal;
621
649
  (0, settings_js_1.saveSettings)(settings);
622
- console.log('\n✓ Temperature updated to', tempVal);
650
+ console.log('\n✓ API timeout updated');
623
651
  }
624
- else {
625
- console.log('\n❌ Invalid temperature. Must be between 0.0 and 1.0');
652
+ else if (timeout.trim()) {
653
+ console.log('\n❌ Invalid timeout value');
626
654
  }
655
+ await ensureStdinReady();
656
+ await ask(createRL(), '\nPress Enter to continue...');
627
657
  }
628
- await ensureStdinReady();
629
- await ask(createRL(), '\nPress Enter to continue...');
630
- }
631
- break;
632
- case 4: // Change max tokens
633
- {
634
- await ensureStdinReady();
635
- const maxTokens = await ask(createRL(), 'Enter max tokens (default 4096): ');
636
- if (maxTokens) {
637
- const tokensVal = parseInt(maxTokens, 10);
638
- if (!isNaN(tokensVal) && tokensVal > 0) {
639
- settings.llm.maxTokens = tokensVal;
658
+ break;
659
+ case 3: // API retries
660
+ {
661
+ await ensureStdinReady();
662
+ const retries = await ask(createRL(), `Enter API retries (current: ${settings.api.retries}): `);
663
+ const retriesVal = parseInt(retries, 10);
664
+ if (!isNaN(retriesVal) && retriesVal >= 0) {
665
+ settings.api.retries = retriesVal;
640
666
  (0, settings_js_1.saveSettings)(settings);
641
- console.log('\n✓ Max tokens updated to', tokensVal);
667
+ console.log('\n✓ API retries updated');
642
668
  }
643
- else {
644
- console.log('\n❌ Invalid value. Must be a positive number');
669
+ else if (retries.trim()) {
670
+ console.log('\n❌ Invalid retries value');
645
671
  }
672
+ await ensureStdinReady();
673
+ await ask(createRL(), '\nPress Enter to continue...');
646
674
  }
647
- await ensureStdinReady();
648
- await ask(createRL(), '\nPress Enter to continue...');
649
- }
650
- break;
651
- case 5: // Change base URL
652
- {
653
- await ensureStdinReady();
654
- const baseUrl = await ask(createRL(), 'Enter base URL (or press Enter to clear): ');
655
- if (baseUrl) {
656
- settings.llm.baseUrl = baseUrl;
675
+ break;
676
+ case 4: // Legacy wizard
677
+ {
678
+ console.clear();
679
+ const newSettings = await (0, wizard_js_1.runSetupWizard)(settings);
680
+ Object.assign(settings, newSettings);
681
+ settings.analyzeMode = 'llm';
682
+ (0, settings_js_1.saveSettings)(settings);
683
+ console.clear();
684
+ displaySettings(settings);
685
+ await ensureStdinReady();
686
+ await ask(createRL(), '\nPress Enter to continue...');
657
687
  }
658
- else {
659
- settings.llm.baseUrl = undefined;
688
+ break;
689
+ case 5: // Show raw config
690
+ {
691
+ const displayConfig = {
692
+ ...settings,
693
+ llm: {
694
+ ...settings.llm,
695
+ apiKey: settings.llm.apiKey
696
+ ? settings.llm.apiKey.substring(0, 8) + '••••••••••'
697
+ : '',
698
+ },
699
+ };
700
+ console.log('\nRaw configuration:');
701
+ console.log(JSON.stringify(displayConfig, null, 2));
702
+ await ensureStdinReady();
703
+ await ask(createRL(), '\nPress Enter to continue...');
660
704
  }
661
- (0, settings_js_1.saveSettings)(settings);
662
- console.log('\n✓ Base URL updated');
663
- await ensureStdinReady();
664
- await ask(createRL(), '\nPress Enter to continue...');
665
- }
666
- break;
667
- case 6: // Set API key
668
- {
669
- const currentKey = settings.llm.apiKey;
670
- if (currentKey) {
671
- console.log('\nCurrent API key:', currentKey.substring(0, 8) + '••••••••••');
705
+ break;
706
+ case 6: // Back
707
+ console.clear();
708
+ return true;
709
+ }
710
+ }
711
+ else {
712
+ switch (choice) {
713
+ case 0: // Change mode
714
+ {
715
+ const modeChoice = await selectMenu('Select Analyze Mode', [
716
+ 'hosted (default)',
717
+ 'llm (legacy fallback)',
718
+ ]);
719
+ settings.analyzeMode = modeChoice === 0 ? 'hosted' : 'llm';
720
+ (0, settings_js_1.saveSettings)(settings);
721
+ console.log('\n✓ Analyze mode updated to', settings.analyzeMode);
722
+ await ensureStdinReady();
723
+ await ask(createRL(), '\nPress Enter to continue...');
724
+ }
725
+ break;
726
+ case 1: // Quick setup wizard
727
+ {
728
+ console.clear();
729
+ const newSettings = await (0, wizard_js_1.runSetupWizard)(settings);
730
+ Object.assign(settings, newSettings);
731
+ settings.analyzeMode = 'llm';
732
+ (0, settings_js_1.saveSettings)(settings);
733
+ console.clear();
734
+ displaySettings(settings);
672
735
  await ensureStdinReady();
673
- const confirm = await ask(createRL(), 'Update API key? (y/N): ');
674
- if (confirm.toLowerCase() !== 'y') {
675
- console.clear();
676
- displaySettings(settings);
677
- break;
736
+ await ask(createRL(), '\nPress Enter to continue...');
737
+ }
738
+ break;
739
+ case 2: // Change provider
740
+ {
741
+ const selectedProvider = await selectProvider();
742
+ settings.llm.provider = selectedProvider;
743
+ const providerInfo = (0, providers_js_1.getProviderInfo)(selectedProvider);
744
+ if (providerInfo?.defaultBaseUrl) {
745
+ settings.llm.baseUrl = providerInfo.defaultBaseUrl;
678
746
  }
747
+ (0, settings_js_1.saveSettings)(settings);
748
+ console.log('\n✓ Provider updated to', settings.llm.provider);
749
+ await ensureStdinReady();
750
+ await ask(createRL(), '\nPress Enter to continue...');
679
751
  }
680
- await ensureStdinReady();
681
- const apiKey = await askMasked(`Enter ${settings.llm.provider.toUpperCase()} API key: `);
682
- if (apiKey) {
683
- settings.llm.apiKey = apiKey;
752
+ break;
753
+ case 3: // Change model
754
+ {
755
+ const models = settings.llm.provider === 'openai'
756
+ ? ['gpt-4o-mini (recommended)', 'gpt-4o', 'gpt-3.5-turbo', 'Custom...']
757
+ : ['claude-3-5-sonnet-20241022 (recommended)', 'claude-3-5-haiku-20241022', 'Custom...'];
758
+ const modelChoice = await selectMenu('Select LLM Model', models);
759
+ const selected = models[modelChoice];
760
+ if (selected === 'Custom...') {
761
+ await ensureStdinReady();
762
+ const customModel = await ask(createRL(), 'Enter custom model name: ');
763
+ settings.llm.model = customModel;
764
+ }
765
+ else {
766
+ settings.llm.model = selected.split(' ')[0];
767
+ }
684
768
  (0, settings_js_1.saveSettings)(settings);
685
- console.log('\n✓ API key updated');
769
+ console.log('\n✓ Model updated to', settings.llm.model);
770
+ await ensureStdinReady();
771
+ await ask(createRL(), '\nPress Enter to continue...');
686
772
  }
687
- await ensureStdinReady();
688
- await ask(createRL(), '\nPress Enter to continue...');
689
- }
690
- break;
691
- case 7: // Show raw config
692
- {
693
- const displayConfig = { ...settings };
694
- if (displayConfig.llm.apiKey) {
695
- displayConfig.llm.apiKey = displayConfig.llm.apiKey.substring(0, 8) + '••••••••••';
773
+ break;
774
+ case 4: // Change temperature
775
+ {
776
+ await ensureStdinReady();
777
+ const temp = await ask(createRL(), 'Enter temperature (0.0-1.0, default 0.3): ');
778
+ if (temp) {
779
+ const tempVal = parseFloat(temp);
780
+ if (!isNaN(tempVal) && tempVal >= 0 && tempVal <= 1) {
781
+ settings.llm.temperature = tempVal;
782
+ (0, settings_js_1.saveSettings)(settings);
783
+ console.log('\n✓ Temperature updated to', tempVal);
784
+ }
785
+ else {
786
+ console.log('\n❌ Invalid temperature. Must be between 0.0 and 1.0');
787
+ }
788
+ }
789
+ await ensureStdinReady();
790
+ await ask(createRL(), '\nPress Enter to continue...');
696
791
  }
697
- console.log('\nRaw configuration:');
698
- console.log(JSON.stringify(displayConfig, null, 2));
699
- await ensureStdinReady();
700
- await ask(createRL(), '\nPress Enter to continue...');
701
- }
702
- break;
703
- case 8: // Back
704
- console.clear();
705
- return true;
792
+ break;
793
+ case 5: // Change max tokens
794
+ {
795
+ await ensureStdinReady();
796
+ const maxTokens = await ask(createRL(), 'Enter max tokens (default 4096): ');
797
+ if (maxTokens) {
798
+ const tokensVal = parseInt(maxTokens, 10);
799
+ if (!isNaN(tokensVal) && tokensVal > 0) {
800
+ settings.llm.maxTokens = tokensVal;
801
+ (0, settings_js_1.saveSettings)(settings);
802
+ console.log('\n✓ Max tokens updated to', tokensVal);
803
+ }
804
+ else {
805
+ console.log('\n❌ Invalid value. Must be a positive number');
806
+ }
807
+ }
808
+ await ensureStdinReady();
809
+ await ask(createRL(), '\nPress Enter to continue...');
810
+ }
811
+ break;
812
+ case 6: // Change base URL
813
+ {
814
+ await ensureStdinReady();
815
+ const baseUrl = await ask(createRL(), 'Enter base URL (or press Enter to clear): ');
816
+ if (baseUrl) {
817
+ settings.llm.baseUrl = baseUrl;
818
+ }
819
+ else {
820
+ settings.llm.baseUrl = undefined;
821
+ }
822
+ (0, settings_js_1.saveSettings)(settings);
823
+ console.log('\n✓ Base URL updated');
824
+ await ensureStdinReady();
825
+ await ask(createRL(), '\nPress Enter to continue...');
826
+ }
827
+ break;
828
+ case 7: // Set API key
829
+ {
830
+ const currentKey = settings.llm.apiKey;
831
+ if (currentKey) {
832
+ console.log('\nCurrent API key:', currentKey.substring(0, 8) + '••••••••••');
833
+ await ensureStdinReady();
834
+ const confirm = await ask(createRL(), 'Update API key? (y/N): ');
835
+ if (confirm.toLowerCase() !== 'y') {
836
+ console.clear();
837
+ displaySettings(settings);
838
+ break;
839
+ }
840
+ }
841
+ await ensureStdinReady();
842
+ const apiKey = await askMasked(`Enter ${settings.llm.provider.toUpperCase()} API key: `);
843
+ if (apiKey) {
844
+ settings.llm.apiKey = apiKey;
845
+ (0, settings_js_1.saveSettings)(settings);
846
+ console.log('\n✓ API key updated');
847
+ }
848
+ await ensureStdinReady();
849
+ await ask(createRL(), '\nPress Enter to continue...');
850
+ }
851
+ break;
852
+ case 8: // Show raw config
853
+ {
854
+ const displayConfig = { ...settings };
855
+ if (displayConfig.llm.apiKey) {
856
+ displayConfig.llm.apiKey = displayConfig.llm.apiKey.substring(0, 8) + '••••••••••';
857
+ }
858
+ console.log('\nRaw configuration:');
859
+ console.log(JSON.stringify(displayConfig, null, 2));
860
+ await ensureStdinReady();
861
+ await ask(createRL(), '\nPress Enter to continue...');
862
+ }
863
+ break;
864
+ case 9: // Back
865
+ console.clear();
866
+ return true;
867
+ }
706
868
  }
707
869
  console.clear();
708
870
  displaySettings(settings);
@@ -748,15 +910,39 @@ async function inspectTranscriptInteractive(settings) {
748
910
  // Get output format
749
911
  const formatChoice = await selectMenu('Output Format', ['Text (human-readable)', 'JSON (machine-readable)']);
750
912
  const asJson = formatChoice === 1;
751
- console.log('\n✓ Loading transcript...');
752
913
  console.log(`✓ Loaded transcript with ${transcript.messages.length} messages`);
753
- console.log('✓ Extracting facts using LLM...');
914
+ const mode = resolveAnalyzeMode(settings);
754
915
  const config = {
916
+ analyzeMode: mode,
755
917
  max_messages: 2000,
756
- llm: settings.llm,
918
+ apiUrl: settings.api.url,
919
+ apiTimeoutMs: settings.api.timeoutMs,
920
+ apiRetries: settings.api.retries,
921
+ ...(mode === 'llm' ? { llm: settings.llm } : {}),
757
922
  };
758
- const result = await (0, inspect_js_1.inspectTranscript)(transcript, config);
759
- console.log('✓ Analysis complete!\n');
923
+ const progress = (0, progress_js_1.createProgressIndicator)(mode === 'hosted' ? 'Sending transcript to hosted Analyze API' : 'Extracting facts using LLM', {
924
+ messages: mode === 'hosted'
925
+ ? [
926
+ 'Sending transcript to hosted Analyze API',
927
+ 'Waiting for hosted analysis',
928
+ 'Preparing drift report',
929
+ ]
930
+ : [
931
+ 'Extracting facts using LLM',
932
+ 'Detecting drift patterns',
933
+ 'Scoring conversation quality',
934
+ ],
935
+ });
936
+ let result;
937
+ try {
938
+ result = await (0, inspect_js_1.inspectTranscript)(transcript, config);
939
+ progress.succeed('Analysis complete');
940
+ }
941
+ catch (error) {
942
+ progress.fail('Analysis failed');
943
+ throw error;
944
+ }
945
+ console.log('');
760
946
  const output = asJson ? (0, render_js_1.renderJsonReport)(result) : (0, render_js_1.renderTextReport)(result);
761
947
  // Use direct write with proper async handling instead of console.log
762
948
  await new Promise((resolve) => {
@@ -779,6 +965,9 @@ async function inspectTranscriptInteractive(settings) {
779
965
  await ensureStdinReady();
780
966
  }
781
967
  catch (error) {
968
+ if (process.stdout.isTTY) {
969
+ process.stdout.write('\n');
970
+ }
782
971
  const errorMsg = '\n❌ Error: ' + (error instanceof Error ? error.message : 'Unknown error');
783
972
  // Use direct write with proper async handling
784
973
  await new Promise((resolve) => {