fleetbo-cockpit-cli 1.0.111 → 1.0.113

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/cli.js +87 -31
  2. package/package.json +1 -1
package/cli.js CHANGED
@@ -636,54 +636,110 @@ if (command === 'alex') {
636
636
  prompt: `\x1b[34m${dynamicUsername} ❯ \x1b[0m`
637
637
  });
638
638
 
639
- process.stdout.write('\n\x1b[F');
640
- rl.prompt();
639
+ // Active les events keypress sur stdin pour détecter le paste
640
+ readline.emitKeypressEvents(process.stdin, rl);
641
+ if (process.stdin.isTTY) process.stdin.setRawMode(true);
641
642
 
642
643
  let inputBuffer = "";
643
644
  let isProcessing = false;
645
+ let currentLine = "";
646
+ let isPasting = false;
647
+ let pasteTimer = null;
644
648
 
645
- rl.on('line', async (line) => {
649
+ const resetPrompt = () => {
650
+ rl.setPrompt(`\x1b[34m${dynamicUsername} ❯ \x1b[0m`);
651
+ rl.prompt(true);
652
+ };
653
+
654
+ const submit = async () => {
655
+ const finalPrompt = inputBuffer.trim();
656
+ inputBuffer = "";
657
+ currentLine = "";
658
+
659
+ if (!finalPrompt) { resetPrompt(); return; }
660
+
661
+ if (finalPrompt.length > 1000) {
662
+ console.log(`\n\x1b[31m⛔ [Alex Safety] Mission rejected: Excessive size (${finalPrompt.length}/1000 characters).\x1b[0m`);
663
+ resetPrompt();
664
+ return;
665
+ }
666
+
667
+ isProcessing = true;
668
+ rl.setPrompt("");
669
+ process.stdout.write('\n');
670
+ await processAlexRequest(finalPrompt);
671
+ isProcessing = false;
672
+ console.log('');
673
+ resetPrompt();
674
+ };
675
+
676
+ // Keypress : détecte si c'est un paste (chunk > 1 char) ou frappe normale
677
+ process.stdin.on('keypress', (char, key) => {
646
678
  if (isProcessing) return;
647
679
 
648
- const trimmedLine = line.trim();
680
+ // Ctrl+C
681
+ if (key && key.ctrl && key.name === 'c') {
682
+ console.log('\n\x1b[90mAlex session closed.\x1b[0m');
683
+ process.exit(0);
684
+ }
649
685
 
650
- if (['exit', 'quit'].includes(trimmedLine.toLowerCase())) {
651
- console.log('\n\x1b[90m Alex session closed.\x1b[0m');
652
- rl.close();
686
+ // Entrée : soumettre si buffer non vide
687
+ if (key && (key.name === 'return' || key.name === 'enter')) {
688
+ if (inputBuffer.trim() !== "") {
689
+ submit();
690
+ }
653
691
  return;
654
692
  }
655
693
 
656
- if (trimmedLine !== "") {
657
- // Accumule + invite à confirmer
694
+ // Paste : char arrive avec plusieurs caractères d'un coup
695
+ if (char && char.length > 1) {
696
+ isPasting = true;
697
+ if (pasteTimer) clearTimeout(pasteTimer);
698
+ // Accumule dans inputBuffer via readline line event
699
+ pasteTimer = setTimeout(() => {
700
+ isPasting = false;
701
+ // Affiche le hint après le paste
702
+ process.stdout.write(`\n\x1b[90m↵ to send · keep typing to add more\x1b[0m`);
703
+ rl.setPrompt(`\n\x1b[34m${dynamicUsername} ❯ \x1b[0m`);
704
+ rl.prompt(true);
705
+ }, 50);
706
+ }
707
+ });
708
+
709
+ // Line event : accumule les lignes dans le buffer
710
+ rl.on('line', (line) => {
711
+ if (isProcessing) return;
712
+
713
+ if (isPasting) {
714
+ // Pendant un paste : accumule sans soumettre
658
715
  inputBuffer += (inputBuffer ? "\n" : "") + line;
659
- rl.setPrompt(" \x1b[90m↵ to confirm · type more to add lines\x1b[0m\n ");
660
- rl.prompt();
661
- } else {
662
- if (inputBuffer.trim() !== "") {
663
- const finalPrompt = inputBuffer.trim();
664
- inputBuffer = "";
665
-
666
- if (finalPrompt.length > 1000) {
667
- console.log(`\n\x1b[31m⛔ [Alex Safety] Mission rejected: Excessive size (${finalPrompt.length}/1000 characters).\x1b[0m`);
668
- rl.setPrompt(`\x1b[34m${dynamicUsername} ❯ \x1b[0m`);
669
- rl.prompt();
670
- return;
671
- }
716
+ return;
717
+ }
672
718
 
673
- isProcessing = true;
674
- rl.setPrompt("");
675
- await processAlexRequest(finalPrompt);
676
- isProcessing = false;
719
+ const trimmed = line.trim();
720
+ if (['exit', 'quit'].includes(trimmed.toLowerCase())) {
721
+ console.log('\n\x1b[90mAlex session closed.\x1b[0m');
722
+ process.exit(0);
723
+ }
677
724
 
678
- console.log('');
679
- rl.setPrompt(`\x1b[34m${dynamicUsername} \x1b[0m`);
680
- rl.prompt();
725
+ if (trimmed !== "") {
726
+ inputBuffer += (inputBuffer ? "\n" : "") + line;
727
+ // Hint de confirmation après frappe normale
728
+ process.stdout.write(`\x1b[90m ↵ to send · keep typing to add more\x1b[0m\n`);
729
+ rl.setPrompt(`\x1b[34m${dynamicUsername} ❯ \x1b[0m`);
730
+ rl.prompt(true);
731
+ } else {
732
+ // Ligne vide = soumettre
733
+ if (inputBuffer.trim()) {
734
+ submit();
681
735
  } else {
682
- rl.setPrompt(`\x1b[34m${dynamicUsername} ❯ \x1b[0m`);
683
- rl.prompt();
736
+ resetPrompt();
684
737
  }
685
738
  }
686
739
  });
740
+
741
+ process.stdout.write('\n');
742
+ resetPrompt();
687
743
  };
688
744
 
689
745
  if (!initialPrompt || initialPrompt === '?') startAlexSession();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fleetbo-cockpit-cli",
3
- "version": "1.0.111",
3
+ "version": "1.0.113",
4
4
  "description": "Fleetbo CLI - Build native mobile apps with React",
5
5
  "author": "Fleetbo",
6
6
  "license": "MIT",