fleetbo-cockpit-cli 1.0.111 → 1.0.112
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.
- package/cli.js +90 -41
- package/package.json +1 -1
package/cli.js
CHANGED
|
@@ -630,59 +630,108 @@ if (command === 'alex') {
|
|
|
630
630
|
console.log('\x1b[32mAlex ❯\x1b[0m Describe your feature.');
|
|
631
631
|
console.log('');
|
|
632
632
|
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
});
|
|
633
|
+
// ── Lecture raw stdin pour détecter le paste ──
|
|
634
|
+
// Un paste arrive en un seul burst de données en <30ms.
|
|
635
|
+
// Une frappe manuelle arrive caractère par caractère avec >30ms entre chaque.
|
|
636
|
+
// On accumule tout le burst, puis on affiche et attend confirmation.
|
|
638
637
|
|
|
639
|
-
process.
|
|
640
|
-
|
|
638
|
+
process.stdin.setRawMode(true);
|
|
639
|
+
process.stdin.resume();
|
|
640
|
+
process.stdin.setEncoding('utf8');
|
|
641
641
|
|
|
642
|
-
let inputBuffer = "";
|
|
642
|
+
let inputBuffer = ""; // ce qui est affiché à l'écran
|
|
643
643
|
let isProcessing = false;
|
|
644
|
+
let pasteChunk = ""; // accumule le burst de données
|
|
645
|
+
let pasteTimer = null;
|
|
646
|
+
|
|
647
|
+
const showPrompt = () => {
|
|
648
|
+
process.stdout.write(`\x1b[34m${dynamicUsername} ❯ \x1b[0m`);
|
|
649
|
+
};
|
|
650
|
+
|
|
651
|
+
const showConfirmHint = () => {
|
|
652
|
+
process.stdout.write(`\n\x1b[90m↵ to send · keep typing to add more\x1b[0m\n`);
|
|
653
|
+
showPrompt();
|
|
654
|
+
process.stdout.write(inputBuffer);
|
|
655
|
+
};
|
|
656
|
+
|
|
657
|
+
const submitInput = async () => {
|
|
658
|
+
const finalPrompt = inputBuffer.trim();
|
|
659
|
+
inputBuffer = "";
|
|
660
|
+
if (!finalPrompt) { process.stdout.write('\n'); showPrompt(); return; }
|
|
661
|
+
|
|
662
|
+
if (finalPrompt.length > 1000) {
|
|
663
|
+
process.stdout.write(`\n\x1b[31m⛔ [Alex Safety] Mission rejected: Excessive size (${finalPrompt.length}/1000 characters).\x1b[0m\n`);
|
|
664
|
+
showPrompt();
|
|
665
|
+
return;
|
|
666
|
+
}
|
|
644
667
|
|
|
645
|
-
|
|
646
|
-
|
|
668
|
+
process.stdout.write('\n');
|
|
669
|
+
isProcessing = true;
|
|
670
|
+
await processAlexRequest(finalPrompt);
|
|
671
|
+
isProcessing = false;
|
|
672
|
+
console.log('');
|
|
673
|
+
showPrompt();
|
|
674
|
+
};
|
|
647
675
|
|
|
648
|
-
|
|
676
|
+
const flushPaste = () => {
|
|
677
|
+
// Le burst est terminé — on l'ajoute au buffer et on affiche
|
|
678
|
+
const pasted = pasteChunk;
|
|
679
|
+
pasteChunk = "";
|
|
680
|
+
pasteTimer = null;
|
|
649
681
|
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
return;
|
|
654
|
-
}
|
|
682
|
+
// Affiche le texte collé tel quel à l'écran
|
|
683
|
+
process.stdout.write(pasted);
|
|
684
|
+
inputBuffer += pasted;
|
|
655
685
|
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
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
|
-
}
|
|
686
|
+
// Affiche le hint de confirmation
|
|
687
|
+
showConfirmHint();
|
|
688
|
+
};
|
|
689
|
+
|
|
690
|
+
showPrompt();
|
|
691
|
+
|
|
692
|
+
process.stdin.on('data', (key) => {
|
|
693
|
+
if (isProcessing) return;
|
|
672
694
|
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
695
|
+
// Ctrl+C
|
|
696
|
+
if (key === '\u0003') {
|
|
697
|
+
console.log('\n\x1b[90mAlex session closed.\x1b[0m');
|
|
698
|
+
process.exit(0);
|
|
699
|
+
}
|
|
677
700
|
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
701
|
+
// Entrée
|
|
702
|
+
if (key === '\r' || key === '\n') {
|
|
703
|
+
if (inputBuffer.trim() !== "") {
|
|
704
|
+
// Déjà du contenu → soumettre
|
|
705
|
+
submitInput();
|
|
681
706
|
} else {
|
|
682
|
-
|
|
683
|
-
|
|
707
|
+
// Buffer vide → juste nouvelle ligne
|
|
708
|
+
process.stdout.write('\n');
|
|
709
|
+
showPrompt();
|
|
710
|
+
}
|
|
711
|
+
return;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
// Backspace
|
|
715
|
+
if (key === '\u007f') {
|
|
716
|
+
if (inputBuffer.length > 0) {
|
|
717
|
+
inputBuffer = inputBuffer.slice(0, -1);
|
|
718
|
+
process.stdout.write('\b \b');
|
|
684
719
|
}
|
|
720
|
+
return;
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
// Paste détecté : plusieurs caractères arrivent en un seul chunk
|
|
724
|
+
if (key.length > 1) {
|
|
725
|
+
pasteChunk += key;
|
|
726
|
+
if (pasteTimer) clearTimeout(pasteTimer);
|
|
727
|
+
pasteTimer = setTimeout(flushPaste, 30);
|
|
728
|
+
return;
|
|
685
729
|
}
|
|
730
|
+
|
|
731
|
+
// Frappe normale : un seul caractère
|
|
732
|
+
if (key === '\t') return; // ignore tab
|
|
733
|
+
inputBuffer += key;
|
|
734
|
+
process.stdout.write(key);
|
|
686
735
|
});
|
|
687
736
|
};
|
|
688
737
|
|