fleetbo-cockpit-cli 1.0.174 → 1.0.176
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 +43 -40
- package/package.json +1 -1
package/cli.js
CHANGED
|
@@ -48,6 +48,23 @@ const projectId = process.env.VITE_FLEETBO_ENTERPRISE_ID;
|
|
|
48
48
|
const keyApp = process.env.VITE_FLEETBO_KEY_APP;
|
|
49
49
|
const testerEmail = process.env.VITE_FLEETBO_TESTER_EMAIL;
|
|
50
50
|
|
|
51
|
+
// ═══════════════════════════════════════════════════════
|
|
52
|
+
// DÉTECTION AUTOMATIQUE DU FRAMEWORK JS (React ou Vue)
|
|
53
|
+
// Lit package.json — aucune configuration manuelle requise
|
|
54
|
+
// ═══════════════════════════════════════════════════════
|
|
55
|
+
const detectFramework = () => {
|
|
56
|
+
try {
|
|
57
|
+
const pkgPath = path.join(process.cwd(), 'package.json');
|
|
58
|
+
if (!fs.existsSync(pkgPath)) return 'react';
|
|
59
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
60
|
+
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
61
|
+
if (deps['vue'] || deps['@vue/core'] || deps['nuxt']) return 'vue';
|
|
62
|
+
return 'react';
|
|
63
|
+
} catch (e) {
|
|
64
|
+
return 'react';
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
const JS_FRAMEWORK = detectFramework();
|
|
51
68
|
|
|
52
69
|
if (!projectId) {
|
|
53
70
|
console.error('\n\x1b[31m❌ Error: Project ID missing in .env.\x1b[0m\n');
|
|
@@ -355,7 +372,7 @@ if (command === 'alex') {
|
|
|
355
372
|
|
|
356
373
|
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.]`;
|
|
357
374
|
|
|
358
|
-
const result = await axios.post(ALEX_ENGINE_URL, { prompt: promptWithTime, projectType: 'android' }, {
|
|
375
|
+
const result = await axios.post(ALEX_ENGINE_URL, { prompt: promptWithTime, projectType: 'android', jsFramework: JS_FRAMEWORK }, {
|
|
359
376
|
headers: { 'x-project-id': projectId }
|
|
360
377
|
});
|
|
361
378
|
|
|
@@ -594,6 +611,7 @@ if (command === 'alex') {
|
|
|
594
611
|
// AI ENGINE STATUS
|
|
595
612
|
console.log('');
|
|
596
613
|
console.log(`\x1b[32m✓\x1b[0m ${providerLabel} \x1b[90m· ${modelLabel}\x1b[0m`);
|
|
614
|
+
console.log(`\x1b[32m✓\x1b[0m ${JS_FRAMEWORK === 'vue' ? '\x1b[32mVue.js\x1b[0m' : '\x1b[36mReact\x1b[0m'} \x1b[90m· JS Framework detected\x1b[0m`);
|
|
597
615
|
|
|
598
616
|
// FORGE CAPABILITIES
|
|
599
617
|
console.log('');
|
|
@@ -1048,12 +1066,10 @@ else {
|
|
|
1048
1066
|
}
|
|
1049
1067
|
|
|
1050
1068
|
async function runDevEnvironment() {
|
|
1051
|
-
console.log(`[Fleetbo] 🛡️ Initializing Dev Environment...`);
|
|
1052
|
-
|
|
1053
|
-
|
|
1069
|
+
console.log(`[Fleetbo] 🛡️ Initializing Universal Dev Environment...`);
|
|
1054
1070
|
|
|
1055
1071
|
killNetworkService();
|
|
1056
|
-
killProcessOnPort(PORT);
|
|
1072
|
+
killProcessOnPort(PORT); // On tue le 3000 par précaution, au cas où
|
|
1057
1073
|
|
|
1058
1074
|
if (!testerEmail) {
|
|
1059
1075
|
console.error('\x1b[31mError: FLEETBO_APP_TESTER_EMAIL missing in .env\x1b[0m');
|
|
@@ -1062,20 +1078,21 @@ else {
|
|
|
1062
1078
|
|
|
1063
1079
|
const npmCmd = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
1064
1080
|
|
|
1065
|
-
//
|
|
1081
|
+
// Lancement agnostique du serveur de dev (React, Vue, etc.)
|
|
1066
1082
|
const devServer = spawn(`${npmCmd} run dev --silent`, {
|
|
1067
1083
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
1068
1084
|
shell: true,
|
|
1069
1085
|
env: {
|
|
1070
1086
|
...process.env,
|
|
1071
|
-
NODE_OPTIONS: '--no-deprecation'
|
|
1072
|
-
PORT
|
|
1087
|
+
NODE_OPTIONS: '--no-deprecation'
|
|
1088
|
+
// On a retiré le forçage du PORT ici pour laisser Vite choisir (souvent 5173 pour Vue)
|
|
1073
1089
|
}
|
|
1074
1090
|
});
|
|
1075
|
-
|
|
1091
|
+
|
|
1076
1092
|
devServer.stderr.pipe(process.stderr);
|
|
1077
1093
|
|
|
1078
1094
|
let connectionStarted = false;
|
|
1095
|
+
let detectedPort = PORT; // 3000 par défaut
|
|
1079
1096
|
|
|
1080
1097
|
devServer.stdout.on('data', (data) => {
|
|
1081
1098
|
const output = data.toString();
|
|
@@ -1083,45 +1100,36 @@ else {
|
|
|
1083
1100
|
// 🛡️ FILTRE ANTI-PLOMBERIE FLEETBO
|
|
1084
1101
|
const lines = output.split('\n');
|
|
1085
1102
|
const forbiddenTerms = [
|
|
1086
|
-
'Attempting to bind to HOST',
|
|
1087
|
-
'
|
|
1088
|
-
'
|
|
1089
|
-
'Starting the development server',
|
|
1090
|
-
'You can now view',
|
|
1091
|
-
'vite v',
|
|
1092
|
-
'VITE v',
|
|
1093
|
-
'ready in',
|
|
1094
|
-
'Local:', // 👈 Plus simple et infaillible
|
|
1095
|
-
'Network:', // 👈 Plus simple et infaillible
|
|
1096
|
-
'press h + enter',
|
|
1097
|
-
'> vite',
|
|
1098
|
-
'> fleetbo',
|
|
1099
|
-
'> npx fleetbo-cockpit-cli@latest'
|
|
1103
|
+
'Attempting to bind to HOST', 'If this was unintentional', 'Learn more here:',
|
|
1104
|
+
'Starting the development server', 'You can now view', 'vite v', 'VITE v',
|
|
1105
|
+
'ready in', 'Local:', 'Network:', 'press h + enter', '> vite', '> fleetbo', '> npx fleetbo-cockpit-cli@latest'
|
|
1100
1106
|
];
|
|
1101
1107
|
|
|
1102
1108
|
const filteredOutput = lines.filter(line => {
|
|
1103
|
-
// On nettoie les codes couleurs invisibles avant de lire
|
|
1104
1109
|
const cleanLine = line.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, '');
|
|
1105
1110
|
return !forbiddenTerms.some(term => cleanLine.includes(term));
|
|
1106
1111
|
}).join('\n');
|
|
1107
1112
|
|
|
1108
|
-
// S'il reste quelque chose d'utile (un console.log du dev, un warning, une vraie erreur), on l'affiche
|
|
1109
1113
|
if (filteredOutput.trim() !== '') {
|
|
1110
1114
|
process.stdout.write(filteredOutput + '\n');
|
|
1111
1115
|
}
|
|
1112
1116
|
|
|
1113
|
-
// 🚀 DÉTECTION DU
|
|
1114
|
-
|
|
1117
|
+
// 🚀 MAGIE 1 : DÉTECTION DU PORT RÉEL (Vite/Vue ou React)
|
|
1118
|
+
// Cherche un pattern comme http://localhost:5173 ou http://127.0.0.1:3000
|
|
1119
|
+
const portMatch = output.match(/http:\/\/(?:localhost|127\.0\.0\.1):(\d+)/);
|
|
1120
|
+
if (portMatch) {
|
|
1121
|
+
detectedPort = portMatch[1]; // On capture le vrai port !
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
// 🚀 MAGIE 2 : DÉTECTION DU DÉMARRAGE ET LANCEMENT DE L'UPLINK SUR LE BON PORT
|
|
1125
|
+
if (!connectionStarted && (output.includes('localhost') || output.includes('ready in') || output.includes('Local:'))){
|
|
1115
1126
|
connectionStarted = true;
|
|
1116
1127
|
|
|
1117
1128
|
console.log('\n\x1b[33mFleetbo OS ❯\x1b[0m ---------------------------------------------------');
|
|
1118
|
-
console.log(`\x1b[33mFleetbo OS ❯\x1b[0m Establishing Secure Uplink...`);
|
|
1129
|
+
console.log(`\x1b[33mFleetbo OS ❯\x1b[0m Establishing Secure Uplink on port ${detectedPort}...`);
|
|
1119
1130
|
console.log(`\x1b[33mFleetbo OS ❯\x1b[0m Please wait for the green message...`);
|
|
1120
1131
|
console.log('\x1b[33mFleetbo OS ❯\x1b[0m ---------------------------------------------------');
|
|
1121
1132
|
|
|
1122
|
-
// ============================================
|
|
1123
|
-
// UPLINK avec auto-retry (Fleetbo OS Resilience)
|
|
1124
|
-
// ============================================
|
|
1125
1133
|
const MAX_UPLINK_RETRIES = 5;
|
|
1126
1134
|
const RETRY_DELAYS = [0, 10, 20, 30, 45];
|
|
1127
1135
|
let uplinkFound = false;
|
|
@@ -1135,8 +1143,8 @@ else {
|
|
|
1135
1143
|
console.log(`\x1b[33m[Fleetbo] 🔄 Uplink reconnection ${attempt}/${MAX_UPLINK_RETRIES - 1}...\x1b[0m`);
|
|
1136
1144
|
}
|
|
1137
1145
|
|
|
1138
|
-
|
|
1139
|
-
const uplinkCommand = `${npxCmd} -y cloudflared tunnel --url http://127.0.0.1:${
|
|
1146
|
+
// ✅ LE TUNNEL CLOUDFLARE UTILISE LE PORT DÉTECTÉ DYNAMIQUEMENT !
|
|
1147
|
+
const uplinkCommand = `${npxCmd} -y cloudflared tunnel --url http://127.0.0.1:${detectedPort} --http-host-header 127.0.0.1:${detectedPort}`;
|
|
1140
1148
|
uplinkProcess = spawn(uplinkCommand, { shell: true });
|
|
1141
1149
|
|
|
1142
1150
|
const handleUplinkOutput = (chunk) => {
|
|
@@ -1145,7 +1153,6 @@ else {
|
|
|
1145
1153
|
const match = text.match(/https:\/\/[a-zA-Z0-9-]+\.trycloudflare\.com/);
|
|
1146
1154
|
if (match) {
|
|
1147
1155
|
uplinkFound = true;
|
|
1148
|
-
// ⚡ Stabilisation du noyau : on attend 1.5s
|
|
1149
1156
|
setTimeout(() => {
|
|
1150
1157
|
syncFirebase(process.env.VITE_FLEETBO_KEY_APP, match[0], process.env.VITE_FLEETBO_TESTER_EMAIL);
|
|
1151
1158
|
}, 1500);
|
|
@@ -1155,14 +1162,13 @@ else {
|
|
|
1155
1162
|
uplinkProcess.stdout.on('data', handleUplinkOutput);
|
|
1156
1163
|
uplinkProcess.stderr.on('data', handleUplinkOutput);
|
|
1157
1164
|
|
|
1158
|
-
uplinkProcess.on('error', (
|
|
1165
|
+
uplinkProcess.on('error', () => {
|
|
1159
1166
|
if (uplinkFound) return;
|
|
1160
1167
|
console.error(`\x1b[31m[Fleetbo] ⚠️ Uplink Connection failed to establish.\x1b[0m`);
|
|
1161
1168
|
});
|
|
1162
1169
|
|
|
1163
|
-
uplinkProcess.on('close', (
|
|
1170
|
+
uplinkProcess.on('close', () => {
|
|
1164
1171
|
if (uplinkFound) return;
|
|
1165
|
-
|
|
1166
1172
|
const nextAttempt = attempt + 1;
|
|
1167
1173
|
if (nextAttempt < MAX_UPLINK_RETRIES) {
|
|
1168
1174
|
const delay = RETRY_DELAYS[nextAttempt] || 30;
|
|
@@ -1170,9 +1176,6 @@ else {
|
|
|
1170
1176
|
setTimeout(() => startUplink(nextAttempt), delay * 1000);
|
|
1171
1177
|
} else {
|
|
1172
1178
|
console.error(`\x1b[31m[Fleetbo] ❌ Secure Uplink could not be established.\x1b[0m`);
|
|
1173
|
-
console.error(`\x1b[90m[Fleetbo] Fleetbo OS network is temporarily unavailable.\x1b[0m`);
|
|
1174
|
-
console.error(`\x1b[90m[Fleetbo] Your dev server is still running on http://localhost:${PORT}\x1b[0m`);
|
|
1175
|
-
console.error(`\x1b[90m[Fleetbo] Restart with "npm run fleetbo" when the network is back.\x1b[0m`);
|
|
1176
1179
|
}
|
|
1177
1180
|
});
|
|
1178
1181
|
};
|