fleetbo-cockpit-cli 1.0.106 → 1.0.108
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 +48 -95
- package/package.json +1 -1
package/cli.js
CHANGED
|
@@ -5,56 +5,6 @@
|
|
|
5
5
|
process.stdout.write("\x1b[1A\x1b[2K".repeat(4));
|
|
6
6
|
console.clear();
|
|
7
7
|
|
|
8
|
-
// ============================================
|
|
9
|
-
// 1. MOTEUR D'ANIMATION PRÉ-BOOT (Blindé)
|
|
10
|
-
// ============================================
|
|
11
|
-
class FleetboSpinner {
|
|
12
|
-
constructor() {
|
|
13
|
-
this.frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
14
|
-
this.idx = 0;
|
|
15
|
-
this.timer = null;
|
|
16
|
-
this.currentMessage = "";
|
|
17
|
-
}
|
|
18
|
-
start(message) {
|
|
19
|
-
this.currentMessage = message;
|
|
20
|
-
|
|
21
|
-
if (this.timer) {
|
|
22
|
-
process.stdout.write(`\r\x1b[2K \x1b[32m${this.frames[this.idx]}\x1b[0m ${this.currentMessage}`);
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
process.stdout.write('\x1b[?25l');
|
|
27
|
-
|
|
28
|
-
process.stdout.write(`\r\x1b[2K \x1b[32m${this.frames[this.idx]}\x1b[0m ${this.currentMessage}`);
|
|
29
|
-
this.idx = (this.idx + 1) % this.frames.length;
|
|
30
|
-
|
|
31
|
-
this.timer = setInterval(() => {
|
|
32
|
-
process.stdout.write(`\r\x1b[2K \x1b[32m${this.frames[this.idx]}\x1b[0m ${this.currentMessage}`);
|
|
33
|
-
this.idx = (this.idx + 1) % this.frames.length;
|
|
34
|
-
}, 80);
|
|
35
|
-
}
|
|
36
|
-
stop() {
|
|
37
|
-
if (this.timer) {
|
|
38
|
-
clearInterval(this.timer);
|
|
39
|
-
this.timer = null;
|
|
40
|
-
}
|
|
41
|
-
// 🛡️ HARD-CLEAR : On écrase physiquement avec des espaces pour éviter le Ghosting
|
|
42
|
-
process.stdout.write('\r' + ' '.repeat(60) + '\r\x1b[?25h');
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
const osSpinner = new FleetboSpinner();
|
|
46
|
-
|
|
47
|
-
// ============================================
|
|
48
|
-
// 2. INTERCEPTION PRÉ-BOOT (Masque le délai de chargement)
|
|
49
|
-
// ============================================
|
|
50
|
-
const args = process.argv.slice(2);
|
|
51
|
-
const command = args[0];
|
|
52
|
-
|
|
53
|
-
if (command === 'alex' || !command) {
|
|
54
|
-
// Se lance avant même que Node n'ait chargé le reste du fichier !
|
|
55
|
-
osSpinner.start("\x1b[32m⚡ Booting Fleetbo Engine...\x1b[0m");
|
|
56
|
-
}
|
|
57
|
-
|
|
58
8
|
const { spawn, execSync } = require('child_process');
|
|
59
9
|
const fs = require('fs');
|
|
60
10
|
const path = require('path');
|
|
@@ -64,7 +14,6 @@ const os = require('os');
|
|
|
64
14
|
const archiver = require('archiver');
|
|
65
15
|
const readline = require('readline');
|
|
66
16
|
|
|
67
|
-
|
|
68
17
|
// ============================================
|
|
69
18
|
// FLEETBO CLI - Centralized Package
|
|
70
19
|
// ============================================
|
|
@@ -78,6 +27,8 @@ const CACHE_URL = "https://getmodulecache-jqycakhlxa-uc.a.run.app";
|
|
|
78
27
|
const PORT = 3000;
|
|
79
28
|
|
|
80
29
|
let uplinkProcess = null;
|
|
30
|
+
const args = process.argv.slice(2);
|
|
31
|
+
const command = args[0];
|
|
81
32
|
|
|
82
33
|
// ============================================
|
|
83
34
|
// CONFIGURATION (.env du projet dev)
|
|
@@ -322,7 +273,7 @@ if (command === 'alex') {
|
|
|
322
273
|
return;
|
|
323
274
|
}
|
|
324
275
|
|
|
325
|
-
|
|
276
|
+
console.log('\x1b[33m🧠 Alex is thinking...\x1b[0m');
|
|
326
277
|
|
|
327
278
|
try {
|
|
328
279
|
// --- MEMORY SYSTEM (SMART CACHE SCANNER V3 - SOUVERAINETÉ DU MÉTAL) ---
|
|
@@ -404,16 +355,10 @@ if (command === 'alex') {
|
|
|
404
355
|
|
|
405
356
|
const promptWithTime = prompt + `\n\n[SYSTEM INFO: The exact current timestamp is ${exactTime}. Use it STRICTLY for your signature '// ⚡ Forged by Alex on...' at the bottom of your files.]`;
|
|
406
357
|
|
|
407
|
-
// On met à jour le texte du spinner existant
|
|
408
|
-
osSpinner.start("\x1b[32m Alex is forging...\x1b[0m");
|
|
409
|
-
|
|
410
358
|
const result = await axios.post(ALEX_ENGINE_URL, { prompt: promptWithTime, projectType: 'android' }, {
|
|
411
359
|
headers: { 'x-project-id': projectId }
|
|
412
360
|
});
|
|
413
361
|
|
|
414
|
-
// 🛑 ARRÊT DE L'ANIMATION
|
|
415
|
-
osSpinner.stop();
|
|
416
|
-
|
|
417
362
|
let aiData = result.data;
|
|
418
363
|
|
|
419
364
|
// 🛡️ ROBUST PARSER: Unwrap all nesting levels until we find a valid aiData object
|
|
@@ -559,9 +504,6 @@ if (command === 'alex') {
|
|
|
559
504
|
console.log(`\n\x1b[31m⚠️ Error: Alex replied, but source code could not be extracted. Try the command again.\x1b[0m\n`);
|
|
560
505
|
}
|
|
561
506
|
} catch (error) {
|
|
562
|
-
// 🛑 SÉCURITÉ : Arrête le moteur global s'il y a un crash
|
|
563
|
-
osSpinner.stop();
|
|
564
|
-
|
|
565
507
|
process.stdout.write('\r' + ' '.repeat(50) + '\r');
|
|
566
508
|
console.error('\n\x1b[31m Alex Error:\x1b[0m ' + (error.response?.data?.message || error.message));
|
|
567
509
|
}
|
|
@@ -577,7 +519,7 @@ if (command === 'alex') {
|
|
|
577
519
|
// ============================================================
|
|
578
520
|
|
|
579
521
|
const startAlexSession = async () => {
|
|
580
|
-
|
|
522
|
+
process.stdout.write('\x1b[33m🛡️ Alex is checking runtime state...\x1b[0m\r');
|
|
581
523
|
let attempts = 0;
|
|
582
524
|
const maxAttempts = 5;
|
|
583
525
|
let isReady = false;
|
|
@@ -607,9 +549,6 @@ if (command === 'alex') {
|
|
|
607
549
|
await new Promise(r => setTimeout(r, 2000));
|
|
608
550
|
}
|
|
609
551
|
}
|
|
610
|
-
|
|
611
|
-
// 🛑 ON ARRÊTE L'ANIMATION DE DÉMARRAGE ICI
|
|
612
|
-
osSpinner.stop();
|
|
613
552
|
|
|
614
553
|
if (!isReady) {
|
|
615
554
|
console.error('\n\x1b[31m⚠️ ENGINE OFFLINE:\x1b[0m Start Fleetbo runtime first: "npm run fleetbo" ');
|
|
@@ -697,50 +636,63 @@ if (command === 'alex') {
|
|
|
697
636
|
prompt: `\x1b[34m${dynamicUsername} ❯ \x1b[0m`
|
|
698
637
|
});
|
|
699
638
|
|
|
639
|
+
// Active le curseur clignotant (séquence ANSI standard)
|
|
640
|
+
process.stdout.write('\x1b[?12h');
|
|
700
641
|
process.stdout.write('\n\x1b[F');
|
|
701
642
|
rl.prompt();
|
|
702
643
|
|
|
703
|
-
let inputBuffer = "";
|
|
704
|
-
let isProcessing = false;
|
|
644
|
+
let inputBuffer = "";
|
|
645
|
+
let isProcessing = false;
|
|
646
|
+
let submitTimer = null;
|
|
647
|
+
|
|
648
|
+
const submitBuffer = async () => {
|
|
649
|
+
if (submitTimer) { clearTimeout(submitTimer); submitTimer = null; }
|
|
650
|
+
if (isProcessing || inputBuffer.trim() === "") return;
|
|
651
|
+
|
|
652
|
+
const finalPrompt = inputBuffer.trim();
|
|
653
|
+
inputBuffer = "";
|
|
654
|
+
|
|
655
|
+
if (finalPrompt.length > 1000) {
|
|
656
|
+
console.log(`\n\x1b[31m⛔ [Alex Safety] Mission rejected: Excessive size (${finalPrompt.length}/1000 characters).\x1b[0m`);
|
|
657
|
+
rl.setPrompt(`\x1b[34m${dynamicUsername} ❯ \x1b[0m`);
|
|
658
|
+
rl.prompt();
|
|
659
|
+
return;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
isProcessing = true;
|
|
663
|
+
rl.setPrompt("");
|
|
664
|
+
await processAlexRequest(finalPrompt);
|
|
665
|
+
isProcessing = false;
|
|
666
|
+
|
|
667
|
+
console.log('');
|
|
668
|
+
rl.setPrompt(`\x1b[34m${dynamicUsername} ❯ \x1b[0m`);
|
|
669
|
+
rl.prompt();
|
|
670
|
+
};
|
|
705
671
|
|
|
706
672
|
rl.on('line', async (line) => {
|
|
707
|
-
if (isProcessing) return;
|
|
673
|
+
if (isProcessing) return;
|
|
708
674
|
|
|
709
675
|
const trimmedLine = line.trim();
|
|
710
676
|
|
|
711
|
-
if (['exit', 'quit'].includes(trimmedLine.toLowerCase())) {
|
|
677
|
+
if (['exit', 'quit'].includes(trimmedLine.toLowerCase())) {
|
|
712
678
|
console.log('\n\x1b[90m Alex session closed.\x1b[0m');
|
|
713
|
-
rl.close();
|
|
714
|
-
return;
|
|
679
|
+
rl.close();
|
|
680
|
+
return;
|
|
715
681
|
}
|
|
716
682
|
|
|
717
683
|
if (trimmedLine !== "") {
|
|
684
|
+
// Ligne avec contenu → accumule et arme un timer de 600ms
|
|
685
|
+
if (submitTimer) { clearTimeout(submitTimer); submitTimer = null; }
|
|
718
686
|
inputBuffer += (inputBuffer ? "\n" : "") + line;
|
|
719
|
-
rl.setPrompt("");
|
|
720
|
-
|
|
721
|
-
else {
|
|
687
|
+
rl.setPrompt("");
|
|
688
|
+
submitTimer = setTimeout(() => submitBuffer(), 600);
|
|
689
|
+
} else {
|
|
690
|
+
// Ligne vide → soumet immédiatement si buffer non vide, sinon prompt
|
|
722
691
|
if (inputBuffer.trim() !== "") {
|
|
723
|
-
|
|
724
|
-
inputBuffer = "";
|
|
725
|
-
|
|
726
|
-
if (finalPrompt.length > 1000) {
|
|
727
|
-
console.log(`\n\x1b[31m⛔ [Alex Safety] Mission rejected: Excessive size (${finalPrompt.length}/1000 characters).\x1b[0m`);
|
|
728
|
-
rl.setPrompt(`\x1b[34m${dynamicUsername} ❯ \x1b[0m`);
|
|
729
|
-
rl.prompt();
|
|
730
|
-
return;
|
|
731
|
-
}
|
|
732
|
-
|
|
733
|
-
isProcessing = true;
|
|
734
|
-
rl.setPrompt("");
|
|
735
|
-
await processAlexRequest(finalPrompt);
|
|
736
|
-
isProcessing = false;
|
|
737
|
-
|
|
738
|
-
console.log('');
|
|
739
|
-
rl.setPrompt(`\x1b[34m${dynamicUsername} ❯ \x1b[0m`);
|
|
740
|
-
rl.prompt();
|
|
692
|
+
submitBuffer();
|
|
741
693
|
} else {
|
|
742
694
|
rl.setPrompt(`\x1b[34m${dynamicUsername} ❯ \x1b[0m`);
|
|
743
|
-
rl.prompt();
|
|
695
|
+
rl.prompt();
|
|
744
696
|
}
|
|
745
697
|
}
|
|
746
698
|
});
|
|
@@ -1050,9 +1002,10 @@ else {
|
|
|
1050
1002
|
}
|
|
1051
1003
|
|
|
1052
1004
|
async function runDevEnvironment() {
|
|
1053
|
-
osSpinner.stop(); // 🛑 Tue le spinner Pre-Boot avant le console.log
|
|
1054
1005
|
console.log(`[Fleetbo] 🛡️ Initializing Dev Environment...`);
|
|
1055
|
-
|
|
1006
|
+
|
|
1007
|
+
|
|
1008
|
+
|
|
1056
1009
|
killNetworkService();
|
|
1057
1010
|
killProcessOnPort(PORT);
|
|
1058
1011
|
|