fleetbo-cockpit-cli 1.0.140 → 1.0.142

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 +70 -39
  2. package/package.json +1 -1
package/cli.js CHANGED
@@ -641,56 +641,87 @@ if (command === 'alex') {
641
641
 
642
642
  let inputBuffer = "";
643
643
  let isProcessing = false;
644
- let pasteTimeout = null;
644
+ let submitTimeout = null;
645
+ let isPasting = false;
646
+ let lastLineTime = Date.now(); // ⏱️ LE CHRONOMÈTRE MAGIQUE
647
+
648
+ const executePrompt = async (text) => {
649
+ if (['exit', 'quit'].includes(text.toLowerCase())) {
650
+ console.log('\n\x1b[90m Alex session closed.\x1b[0m');
651
+ rl.close();
652
+ return;
653
+ }
654
+ if (text !== "") {
655
+ if (text.length > 4000) {
656
+ console.log(`\n\x1b[31m⛔ [Alex Safety] Mission rejected: Excessive size (${text.length}/4000 characters).\x1b[0m`);
657
+ rl.setPrompt(`\x1b[34m${dynamicUsername} ❯ \x1b[0m`);
658
+ rl.prompt();
659
+ return;
660
+ }
661
+ isProcessing = true;
662
+ rl.setPrompt("");
663
+ await processAlexRequest(text);
664
+ isProcessing = false;
665
+ console.log('');
666
+ rl.setPrompt(`\x1b[34m${dynamicUsername} ❯ \x1b[0m`);
667
+ rl.prompt();
668
+ } else {
669
+ rl.setPrompt(`\x1b[34m${dynamicUsername} ❯ \x1b[0m`);
670
+ rl.prompt();
671
+ }
672
+ };
645
673
 
646
674
  rl.on('line', async (line) => {
647
675
  if (isProcessing) return;
648
676
 
649
- // 1. On accumule les lignes
650
- inputBuffer += (inputBuffer ? "\n" : "") + line;
651
-
652
- // 🪄 2. LE BOUCLIER VISUEL : On efface immédiatement le prompt.
653
- // Ça empêche le terminal de spammer "jojo ❯" à chaque ligne du copier-coller !
654
- rl.setPrompt("");
677
+ const now = Date.now();
678
+ const timeSinceLastLine = now - lastLineTime;
679
+ lastLineTime = now;
680
+
681
+ // 1. FIN DU MODE COLLAGE : On vérifie que c'est une ligne vide ET qu'elle vient d'un humain (> 150ms)
682
+ if (isPasting && line.trim() === "") {
683
+ if (timeSinceLastLine > 150) {
684
+ const finalPrompt = inputBuffer.trim();
685
+ inputBuffer = "";
686
+ isPasting = false;
687
+ await executePrompt(finalPrompt);
688
+ return;
689
+ }
690
+ // Si c'est < 150ms, c'est juste un paragraphe vide dans le texte copié ! On l'ignore et on accumule.
691
+ }
655
692
 
656
- // 3. On annule le timer précédent
657
- if (pasteTimeout) clearTimeout(pasteTimeout);
693
+ // 2. On accumule la donnée
694
+ inputBuffer += (inputBuffer ? "\n" : "") + line;
658
695
 
659
- // 4. Timer légèrement augmenté à 50ms
660
- pasteTimeout = setTimeout(async () => {
661
- const finalPrompt = inputBuffer.trim();
662
- inputBuffer = "";
696
+ // 3. Si on est DÉJÀ en mode paste, on s'arrête là (accumulation silencieuse)
697
+ if (isPasting) return;
663
698
 
664
- // Gestion de la sortie
665
- if (['exit', 'quit'].includes(finalPrompt.toLowerCase())) {
666
- console.log('\n\x1b[90m Alex session closed.\x1b[0m');
667
- rl.close();
668
- return;
699
+ // 4. DÉTECTEUR DE VITESSE : Si une ligne arrive à la vitesse de la lumière (< 50ms), c'est un copier-coller !
700
+ if (timeSinceLastLine < 50) {
701
+ if (submitTimeout) {
702
+ clearTimeout(submitTimeout);
703
+ submitTimeout = null;
669
704
  }
705
+ isPasting = true; // 🚨 Passage en mode manuel !
706
+ return;
707
+ }
670
708
 
671
- // Si le texte final n'est pas vide
672
- if (finalPrompt !== "") {
673
- if (finalPrompt.length > 4000) {
674
- console.log(`\n\x1b[31m⛔ [Alex Safety] Mission rejected: Excessive size (${finalPrompt.length}/4000 characters).\x1b[0m`);
675
- rl.setPrompt(`\x1b[34m${dynamicUsername} \x1b[0m`);
676
- rl.prompt();
677
- return;
678
- }
709
+ // 5. FRAPPE NORMALE : On lance le chrono
710
+ if (submitTimeout) clearTimeout(submitTimeout);
711
+
712
+ submitTimeout = setTimeout(async () => {
713
+ submitTimeout = null;
714
+
715
+ // Si on a basculé en mode paste entre temps (suite d'un collage), on annule l'envoi auto
716
+ if (isPasting) return;
679
717
 
680
- // On verrouille et on envoie
681
- isProcessing = true;
682
- await processAlexRequest(finalPrompt);
683
-
684
- // On libère et on RESTAURE le prompt
685
- isProcessing = false;
686
- console.log('');
687
- rl.setPrompt(`\x1b[34m${dynamicUsername} ❯ \x1b[0m`);
688
- rl.prompt();
718
+ const finalPrompt = inputBuffer.trim();
719
+ inputBuffer = "";
720
+
721
+ if (finalPrompt === "") {
722
+ rl.prompt(); // L'utilisateur a juste fait Entrée dans le vide
689
723
  } else {
690
- // Si l'utilisateur appuie juste sur Entrée dans le vide
691
- // On RESTAURE le prompt proprement
692
- rl.setPrompt(`\x1b[34m${dynamicUsername} ❯ \x1b[0m`);
693
- rl.prompt();
724
+ await executePrompt(finalPrompt); // Envoi direct
694
725
  }
695
726
  }, 50);
696
727
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fleetbo-cockpit-cli",
3
- "version": "1.0.140",
3
+ "version": "1.0.142",
4
4
  "description": "Fleetbo CLI - Build native mobile apps with React",
5
5
  "author": "Fleetbo",
6
6
  "license": "MIT",