fleetbo-cockpit-cli 1.0.112 → 1.0.114
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 +66 -116
- package/package.json +1 -1
package/cli.js
CHANGED
|
@@ -587,151 +587,101 @@ if (command === 'alex') {
|
|
|
587
587
|
const modelLabel = aiModel && aiModel !== 'auto' ? aiModel : 'auto';
|
|
588
588
|
|
|
589
589
|
console.log('');
|
|
590
|
-
console.log('\x1b[90m┌─────────────────────────────────────────────────────────┐\x1b[0m');
|
|
591
|
-
console.log('\x1b[90m│\x1b[0m \x1b[90m│\x1b[0m');
|
|
592
|
-
console.log('\x1b[90m│\x1b[0m \x1b[1m\x1b[36m⚡ ALEX\x1b[0m \x1b[90m— System Architect · Fleetbo OS\x1b[0m \x1b[90m│\x1b[0m');
|
|
593
|
-
console.log('\x1b[90m│\x1b[0m \x1b[90m│\x1b[0m');
|
|
594
|
-
console.log('\x1b[90m│\x1b[0m \x1b[90mYour JS stays the brain. I forge the metal.\x1b[0m \x1b[90m│\x1b[0m');
|
|
595
|
-
console.log('\x1b[90m│\x1b[0m \x1b[90m│\x1b[0m');
|
|
596
|
-
console.log('\x1b[90m└─────────────────────────────────────────────────────────┘\x1b[0m');
|
|
590
|
+
console.log('\x1b[90m ┌─────────────────────────────────────────────────────────┐\x1b[0m');
|
|
591
|
+
console.log('\x1b[90m │\x1b[0m \x1b[90m│\x1b[0m');
|
|
592
|
+
console.log('\x1b[90m │\x1b[0m \x1b[1m\x1b[36m⚡ ALEX\x1b[0m \x1b[90m— System Architect · Fleetbo OS\x1b[0m \x1b[90m│\x1b[0m');
|
|
593
|
+
console.log('\x1b[90m │\x1b[0m \x1b[90m│\x1b[0m');
|
|
594
|
+
console.log('\x1b[90m │\x1b[0m \x1b[90mYour JS stays the brain. I forge the metal.\x1b[0m \x1b[90m│\x1b[0m');
|
|
595
|
+
console.log('\x1b[90m │\x1b[0m \x1b[90m│\x1b[0m');
|
|
596
|
+
console.log('\x1b[90m └─────────────────────────────────────────────────────────┘\x1b[0m');
|
|
597
597
|
|
|
598
598
|
// AI ENGINE STATUS
|
|
599
599
|
console.log('');
|
|
600
|
-
console.log(
|
|
600
|
+
console.log(` \x1b[32m ✓\x1b[0m ${providerLabel} \x1b[90m· ${modelLabel}\x1b[0m`);
|
|
601
601
|
|
|
602
602
|
// FORGE CAPABILITIES
|
|
603
603
|
console.log('');
|
|
604
|
-
console.log('\x1b[
|
|
605
|
-
console.log('\x1b[90m─────────────────────────────────────────────────────\x1b[0m');
|
|
606
|
-
console.log('\x1b[
|
|
607
|
-
console.log('\x1b[
|
|
608
|
-
console.log('\x1b[
|
|
609
|
-
console.log('\x1b[
|
|
610
|
-
console.log('\x1b[90m─────────────────────────────────────────────────────\x1b[0m');
|
|
604
|
+
console.log(' \x1b[36m CAPABILITIES\x1b[0m');
|
|
605
|
+
console.log(' \x1b[90m ─────────────────────────────────────────────────────\x1b[0m');
|
|
606
|
+
console.log(' \x1b[1m Hardware\x1b[0m\x1b[90m Camera · Scanner · GPS · Biometrics\x1b[0m');
|
|
607
|
+
console.log(' \x1b[1m High-Perf\x1b[0m\x1b[90m Video Feed · Swipe Deck · Audio\x1b[0m');
|
|
608
|
+
console.log(' \x1b[1m Sovereign\x1b[0m\x1b[90m Form + Photo + Save-to-Cloud\x1b[0m');
|
|
609
|
+
console.log(' \x1b[1m Fleetbo View\x1b[0m\x1b[90m Full native tab (120 FPS)\x1b[0m');
|
|
610
|
+
console.log(' \x1b[90m ─────────────────────────────────────────────────────\x1b[0m');
|
|
611
611
|
|
|
612
612
|
// TRIGGER WORDS
|
|
613
613
|
console.log('');
|
|
614
|
-
console.log('\x1b[
|
|
614
|
+
console.log(' \x1b[36m TRIGGER WORDS\x1b[0m \x1b[90m(required to activate code generation)\x1b[0m');
|
|
615
615
|
console.log('');
|
|
616
|
-
console.log('\x1b[
|
|
616
|
+
console.log(' \x1b[33m forge\x1b[0m \x1b[90m·\x1b[0m \x1b[33mcreate\x1b[0m \x1b[90m·\x1b[0m \x1b[33mupdate\x1b[0m \x1b[90m·\x1b[0m \x1b[33mmodify\x1b[0m \x1b[90m·\x1b[0m \x1b[33mfix\x1b[0m \x1b[90m·\x1b[0m \x1b[33medit\x1b[0m');
|
|
617
617
|
console.log('');
|
|
618
|
-
console.log('\x1b[
|
|
618
|
+
console.log(' \x1b[90m Without a trigger word, Alex answers but does not generate code.\x1b[0m');
|
|
619
619
|
|
|
620
620
|
// EXAMPLES
|
|
621
621
|
console.log('');
|
|
622
|
-
console.log('\x1b[
|
|
622
|
+
console.log(' \x1b[36m EXAMPLES\x1b[0m');
|
|
623
623
|
console.log('');
|
|
624
|
-
console.log('\x1b[33m›\x1b[0m \x1b[90m"\x1b[33mforge\x1b[90m a camera to scan receipts for my expense tracker"\x1b[0m');
|
|
625
|
-
console.log('\x1b[33m›\x1b[0m \x1b[90m"\x1b[33mcreate\x1b[90m a form to add products with photos to my catalog"\x1b[0m');
|
|
626
|
-
console.log('\x1b[33m›\x1b[0m \x1b[90m"\x1b[33mupdate\x1b[90m CloudCamera to save in the collection orders"\x1b[0m');
|
|
624
|
+
console.log(' \x1b[33m ›\x1b[0m \x1b[90m"\x1b[33mforge\x1b[90m a camera to scan receipts for my expense tracker"\x1b[0m');
|
|
625
|
+
console.log(' \x1b[33m ›\x1b[0m \x1b[90m"\x1b[33mcreate\x1b[90m a form to add products with photos to my catalog"\x1b[0m');
|
|
626
|
+
console.log(' \x1b[33m ›\x1b[0m \x1b[90m"\x1b[33mupdate\x1b[90m CloudCamera to save in the collection orders"\x1b[0m');
|
|
627
627
|
|
|
628
628
|
// READY
|
|
629
629
|
console.log('');
|
|
630
|
-
console.log('\x1b[
|
|
630
|
+
console.log(' \x1b[32m Alex ❯\x1b[0m Describe your feature.');
|
|
631
631
|
console.log('');
|
|
632
|
+
|
|
633
|
+
const rl = readline.createInterface({
|
|
634
|
+
input: process.stdin,
|
|
635
|
+
output: process.stdout,
|
|
636
|
+
prompt: `\x1b[34m${dynamicUsername} ❯ \x1b[0m`
|
|
637
|
+
});
|
|
638
|
+
|
|
639
|
+
process.stdout.write('\n\x1b[F');
|
|
640
|
+
rl.prompt();
|
|
632
641
|
|
|
633
|
-
|
|
634
|
-
|
|
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.
|
|
637
|
-
|
|
638
|
-
process.stdin.setRawMode(true);
|
|
639
|
-
process.stdin.resume();
|
|
640
|
-
process.stdin.setEncoding('utf8');
|
|
641
|
-
|
|
642
|
-
let inputBuffer = ""; // ce qui est affiché à l'écran
|
|
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
|
-
}
|
|
667
|
-
|
|
668
|
-
process.stdout.write('\n');
|
|
669
|
-
isProcessing = true;
|
|
670
|
-
await processAlexRequest(finalPrompt);
|
|
671
|
-
isProcessing = false;
|
|
672
|
-
console.log('');
|
|
673
|
-
showPrompt();
|
|
674
|
-
};
|
|
675
|
-
|
|
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;
|
|
681
|
-
|
|
682
|
-
// Affiche le texte collé tel quel à l'écran
|
|
683
|
-
process.stdout.write(pasted);
|
|
684
|
-
inputBuffer += pasted;
|
|
685
|
-
|
|
686
|
-
// Affiche le hint de confirmation
|
|
687
|
-
showConfirmHint();
|
|
688
|
-
};
|
|
642
|
+
let inputBuffer = "";
|
|
643
|
+
let isProcessing = false;
|
|
689
644
|
|
|
690
|
-
|
|
645
|
+
rl.on('line', async (line) => {
|
|
646
|
+
if (isProcessing) return;
|
|
691
647
|
|
|
692
|
-
|
|
693
|
-
if (isProcessing) return;
|
|
648
|
+
const trimmedLine = line.trim();
|
|
694
649
|
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
650
|
+
if (['exit', 'quit'].includes(trimmedLine.toLowerCase())) {
|
|
651
|
+
console.log('\n\x1b[90m Alex session closed.\x1b[0m');
|
|
652
|
+
rl.close();
|
|
653
|
+
return;
|
|
699
654
|
}
|
|
700
655
|
|
|
701
|
-
|
|
702
|
-
|
|
656
|
+
if (trimmedLine !== "") {
|
|
657
|
+
inputBuffer += (inputBuffer ? "\n" : "") + line;
|
|
658
|
+
rl.setPrompt("");
|
|
659
|
+
}
|
|
660
|
+
else {
|
|
703
661
|
if (inputBuffer.trim() !== "") {
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
662
|
+
const finalPrompt = inputBuffer.trim();
|
|
663
|
+
inputBuffer = "";
|
|
664
|
+
|
|
665
|
+
if (finalPrompt.length > 1000) {
|
|
666
|
+
console.log(`\n\x1b[31m⛔ [Alex Safety] Mission rejected: Excessive size (${finalPrompt.length}/1000 characters).\x1b[0m`);
|
|
667
|
+
rl.setPrompt(`\x1b[34m${dynamicUsername} ❯ \x1b[0m`);
|
|
668
|
+
rl.prompt();
|
|
669
|
+
return;
|
|
670
|
+
}
|
|
713
671
|
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
672
|
+
isProcessing = true;
|
|
673
|
+
rl.setPrompt("");
|
|
674
|
+
await processAlexRequest(finalPrompt);
|
|
675
|
+
isProcessing = false;
|
|
676
|
+
|
|
677
|
+
console.log('');
|
|
678
|
+
rl.setPrompt(`\x1b[34m${dynamicUsername} ❯ \x1b[0m`);
|
|
679
|
+
rl.prompt();
|
|
680
|
+
} else {
|
|
681
|
+
rl.setPrompt(`\x1b[34m${dynamicUsername} ❯ \x1b[0m`);
|
|
682
|
+
rl.prompt();
|
|
719
683
|
}
|
|
720
|
-
return;
|
|
721
684
|
}
|
|
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;
|
|
729
|
-
}
|
|
730
|
-
|
|
731
|
-
// Frappe normale : un seul caractère
|
|
732
|
-
if (key === '\t') return; // ignore tab
|
|
733
|
-
inputBuffer += key;
|
|
734
|
-
process.stdout.write(key);
|
|
735
685
|
});
|
|
736
686
|
};
|
|
737
687
|
|