fleetbo-cockpit-cli 1.0.70 → 1.0.72

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 +52 -131
  2. package/package.json +1 -1
package/cli.js CHANGED
@@ -146,10 +146,9 @@ const showEnergyTransfer = async () => {
146
146
 
147
147
  // Détecte TOUS les mots en PascalCase (ex: GuestCreator, CameraModule, Tab2)
148
148
  const extractPotentialModules = (text) => {
149
- // Regex stricte : Majuscule + minuscules + Majuscule (ex: ProfileCreator, UserConfig)
150
- const regex = /\b[A-Z][a-z]+[A-Z][a-zA-Z0-9_]*\b/g;
149
+ const regex = /\b[A-Z][a-zA-Z0-9_]{2,}\b/g;
151
150
  const matches = text.match(regex) || [];
152
- return [...new Set(matches)];
151
+ return [...new Set(matches)]; // Dédoublonne les résultats
153
152
  };
154
153
 
155
154
 
@@ -220,8 +219,8 @@ if (command === 'alex') {
220
219
  return;
221
220
  }
222
221
 
223
- // 📋 INTERCEPTION: LIST MODULES
224
- const isListingRequest = /^(liste|list|quels modules|montre les modules|show modules)/i.test(prompt);
222
+ // 📋 INTERCEPTION : LISTER LES MODULES
223
+ const isListingRequest = /^(liste|list|quels modules|montre les modules)/i.test(prompt);
225
224
  if (isListingRequest) {
226
225
  process.stdout.write(` \x1b[90m🔍 Scanning OS Cache...\x1b[0m\n`);
227
226
  const cacheRes = await getModuleCache({ projectId, moduleName: null });
@@ -233,7 +232,7 @@ if (command === 'alex') {
233
232
  console.log(` ${metalColor}■\x1b[0m \x1b[1m${m.moduleName}\x1b[0m \x1b[90m(${m.platform})\x1b[0m`);
234
233
  });
235
234
  } else {
236
- console.log(`\n \x1b[90mNo modules found in the infrastructure of this project.\x1b[0m`);
235
+ console.log(`\n \x1b[90mAucun module trouvé dans l'infrastructure de ce projet.\x1b[0m`);
237
236
  }
238
237
  return;
239
238
  }
@@ -241,67 +240,33 @@ if (command === 'alex') {
241
240
  console.log('\x1b[33m🧠 Alex is thinking...\x1b[0m');
242
241
 
243
242
  try {
244
- // --- MEMORY SYSTEM (SMART CACHE SCANNER V3 - SOUVERAINETÉ DU MÉTAL) ---
243
+ // --- SYSTÈME DE MÉMOIRE (SMART CACHE SCANNER) ---
245
244
  let contextInjection = "";
246
245
  const potentialModules = extractPotentialModules(prompt);
247
-
248
- let targetModuleContext = "";
249
- let referenceContexts = "";
250
246
 
251
- for (let modName of potentialModules) {
252
- let isReferenceOnly = false;
253
-
254
- // 🟢 LE DÉTECTEUR D'INSPIRATION
255
- if (modName.endsWith('Ref')) {
256
- isReferenceOnly = true;
257
- modName = modName.replace('Ref', '');
258
- } else if (modName.endsWith('Schema')) {
259
- isReferenceOnly = true;
260
- modName = modName.replace('Schema', '');
261
- }
262
-
263
- process.stdout.write(` \x1b[90m🔍 Checking OS cache for ${modName}...\x1b[0m`);
247
+ for (const modName of potentialModules) {
248
+ process.stdout.write(` \x1b[90m🔍 Checking os cache for ${modName}...\x1b[0m`);
264
249
  const cache = await getModuleCache({ projectId, moduleName: modName });
265
250
 
266
251
  if (cache.found) {
267
252
  process.stdout.write(` \x1b[32mFOUND METAL\x1b[0m\n`);
268
253
 
269
- let memoryScript = cache.module.dataSchema
270
- ? `\n[SCRIPT MÉMOIRE DU MODULE ${modName}]\n${cache.module.dataSchema}\n`
271
- : `\n[SCRIPT MÉMOIRE DU MODULE ${modName}]\nAucun schéma enregistré pour ce module.\n`;
272
-
273
- if (isReferenceOnly) {
274
- // 🚨 CAS A : INSPIRATION (Lecture seule)
275
- referenceContexts += `\n--- CONTEXTE : RÉFÉRENCE DE DONNÉES (${modName}) ---\nDOGME : Ne modifie pas ce module. Aligne-toi uniquement sur le code Natif ci-dessous pour extraire les clés de données.\n${memoryScript}\n[CODE NATIF DE RÉFÉRENCE]\n${cache.module.code}\n`;
276
- } else if (!targetModuleContext) {
277
- // 🚨 CAS B : CIBLE PRINCIPALE (Modification)
278
- // LE MOCK EST BANI ! Le Métal est la seule source de vérité.
279
- const intent = getContextIntent(prompt);
280
- if (intent === "MODIFICATION") {
281
- targetModuleContext = `\n--- CONTEXTE : MÉTAL EXISTANT À MODIFIER (${modName}) ---\nDOGME: Tu dois modifier ce code Natif. Ensuite, tu forgeras un Mock JSX entièrement neuf basé UNIQUEMENT sur ton nouveau code Natif.\n${memoryScript}\n[CODE NATIF EXISTANT]\n${cache.module.code}\n--- FIN DU CONTEXTE ---\n`;
282
- } else {
283
- targetModuleContext = `\n--- CONTEXTE : BASE DE TRAVAIL (${modName}) ---\n${memoryScript}\n`;
284
- }
285
- }
254
+ const intent = getContextIntent(prompt);
255
+ const contextTitle = intent === "MODIFICATION"
256
+ ? "MÉTAL EXISTANT MODIFIER)"
257
+ : "MÉTAL DE RÉFÉRENCE (POUR PARITÉ DES DONNÉES)";
258
+
259
+ contextInjection = `\n--- CONTEXTE SOUVERAIN : ${contextTitle} (${modName}) ---\nDOGME: Le Métal est la source de vérité absolue. Le Mock n'est qu'une illusion.\nTu DOIS analyser ce code Natif pour comprendre EXACTEMENT comment les données ont été structurées, nommées (clés JSON) et sauvegardées.\n\n[CODE NATIF EXISTANT]\n${cache.module.code}\n--- FIN DU CONTEXTE ---\n`;
260
+
261
+ prompt = contextInjection + "\n\n[INSTRUCTION DU PILOTE]\n" + prompt;
262
+ break;
286
263
  } else {
287
264
  process.stdout.write(` \x1b[31mNOT FOUND\x1b[0m\n`);
288
265
  }
289
266
  }
267
+ // --- FIN MODIFICATION MÉMOIRE ---
290
268
 
291
- contextInjection = referenceContexts + targetModuleContext;
292
- if (contextInjection) {
293
- prompt = contextInjection + "\n\n[INSTRUCTION DU PILOTE]\n" + prompt;
294
- }
295
- // --- END MEMORY MODIFICATION ---
296
-
297
- // 🟢 NEW: Real-time timestamp injection
298
- const now = new Date();
299
- // Clean format: YYYY-MM-DD at HH:MM:SS
300
- const exactTime = now.toISOString().split('T')[0] + ' at ' + now.toTimeString().split(' ')[0];
301
-
302
- 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.]`;
303
-
304
- const result = await axios.post(ALEX_ENGINE_URL, { prompt: promptWithTime, projectType: 'android' }, {
269
+ const result = await axios.post(ALEX_ENGINE_URL, { prompt, projectType: 'android' }, {
305
270
  headers: { 'x-project-id': projectId }
306
271
  });
307
272
 
@@ -311,12 +276,6 @@ if (command === 'alex') {
311
276
  try { aiData = JSON.parse(aiData); } catch (_) {}
312
277
  }
313
278
 
314
- // 🟢 DISPLAY REASONING IN TERMINAL
315
- if (aiData.thinking_process) {
316
- // Show start of reasoning in gray for info
317
- console.log(` \x1b[90m🧠 Alex Analysis: ${aiData.thinking_process.substring(0, 150)}...\x1b[0m`);
318
- }
319
-
320
279
  process.stdout.write('\x1b[A\r' + ' '.repeat(50) + '\r');
321
280
 
322
281
  if (aiData.status === 'quota_exceeded') {
@@ -353,21 +312,21 @@ if (command === 'alex') {
353
312
  const formattedMsg = wrapText(rawMsg, 85);
354
313
  console.log('\x1b[32mAlex ❯\x1b[0m ' + formattedMsg);
355
314
 
315
+ if (aiData.remainingConsultations !== undefined) {
316
+ const remaining = aiData.remainingConsultations;
317
+ const limit = aiData.consultationLimit || 7;
318
+ const tierLabel = aiData.tier === 'senior' ? 'SENIOR' : aiData.tier === 'expert' ? 'EXPERT' : 'JUNIOR';
319
+ const percent = Math.round((remaining / limit) * 100);
320
+ const energyColor = percent > 20 ? '\x1b[32m' : '\x1b[31m';
321
+ console.log(`\n\x1b[36m⚡ Architect Fuel:\x1b[0m ${energyColor}${percent}%\x1b[0m (${remaining}/${limit} instructions left) [${tierLabel}]\n`);
322
+ }
356
323
  }
357
324
 
358
- // --- FILE CREATION LOGIC ---
325
+ // --- C'EST ICI QUE LES FICHIERS SONT CRÉÉS ---
359
326
  if (aiData.status === 'success' && aiData.moduleData) {
360
- let { fileName, code, mockFileName, mockCode, moduleName, instructions, config_offload, dataSchema } = aiData.moduleData;
361
-
362
- // 🛡️ ANTI-DUMP SHIELD (Prevents terminal flooding)
363
- if (moduleName) {
364
- // Cleanup module name
365
- moduleName = moduleName.split('\n')[0].replace(/["'{}]/g, '').trim();
366
- if (moduleName.length > 40) moduleName = moduleName.substring(0, 40) + "...";
367
- }
368
-
327
+ const { fileName, code, mockFileName, mockCode, moduleName, instructions, config_offload } = aiData.moduleData;
369
328
  console.log(` \x1b[90m Architecting: ${moduleName}\x1b[0m`);
370
-
329
+
371
330
  const writeFile = (dir, name, content) => {
372
331
  const fullPath = path.join(process.cwd(), dir);
373
332
  const filePath = path.join(fullPath, name);
@@ -401,7 +360,7 @@ if (command === 'alex') {
401
360
  }
402
361
  }
403
362
 
404
- // --- KERNEL SYNCHRONIZATION ---
363
+ // --- SYNCHRONISATION DU KERNEL ---
405
364
  const depsCount = config_offload?.dependencies?.length || 0;
406
365
  process.stdout.write(` \x1b[33m[Cloud Inject]\x1b[0m Archiving ${moduleName} to OS (${depsCount} libs)...`);
407
366
 
@@ -415,8 +374,7 @@ if (command === 'alex') {
415
374
  code: code,
416
375
  mockFileName: mockFileName,
417
376
  mockCode: mockCode,
418
- config_offload: config_offload || { dependencies: [], permissions: [] },
419
- dataSchema: dataSchema || null // 👈 LA LIGNE MAGIQUE
377
+ config_offload: config_offload || { dependencies: [], permissions: [] }
420
378
  }
421
379
  });
422
380
  process.stdout.write(` \x1b[32mOK\x1b[0m\n`);
@@ -424,18 +382,9 @@ if (command === 'alex') {
424
382
  process.stdout.write(` \x1b[31mFAILED\x1b[0m\n`);
425
383
  console.error(` ⚠️ OS sync failed: ${err.message}`);
426
384
  }
427
- // 🟢 LE FUEL EST DÉPLACÉ ICI (TOUTE FIN DU TRY)
428
- if (aiData.remainingConsultations !== undefined) {
429
- const remaining = aiData.remainingConsultations;
430
- const limit = aiData.consultationLimit || 7;
431
- const tierLabel = aiData.tier.toUpperCase();
432
- const percent = Math.round((remaining / limit) * 100);
433
- const energyColor = percent > 20 ? '\x1b[32m' : '\x1b[31m';
434
- console.log(`\n\x1b[36m⚡ Architect Fuel:\x1b[0m ${energyColor}${percent}%\x1b[0m (${remaining}/${limit} instructions left) [${tierLabel}]\n`);
435
- }
436
385
  } else if (aiData.status === 'success' && !aiData.moduleData) {
437
- // SAFETY: If formatting is broken
438
- console.log(`\n\x1b[31m⚠️ Error: Alex replied, but source code could not be extracted. Try the command again.\x1b[0m\n`);
386
+ // SÉCURITÉ : Si Alex s'emmêle les pinceaux et renvoie un mauvais format JSON
387
+ console.log(`\n\x1b[31m⚠️ Erreur : Alex a répondu, mais le code source n'a pas pu être extrait. Réessayez la commande.\x1b[0m\n`);
439
388
  }
440
389
  } catch (error) {
441
390
  process.stdout.write('\r' + ' '.repeat(50) + '\r');
@@ -477,25 +426,25 @@ if (command === 'alex') {
477
426
 
478
427
  process.stdout.write(' '.repeat(60) + '\r');
479
428
 
480
- // 1. IDENTITY
429
+ // 1. IDENTITÉ
481
430
  console.log('\n\x1b[32m🤖 Alex is online.\x1b[0m');
482
431
  console.log('\x1b[90m Your JS stays the brain. I forge the native muscle.\x1b[0m');
483
432
 
484
- // 2. FORGE CAPABILITIES
433
+ // 2. CE QUE JE FORGE
485
434
  console.log('\n\x1b[36m⚡ WHAT I CAN FORGE:\x1b[0m');
486
435
  console.log('');
487
436
  console.log(' \x1b[1m📷 Hardware\x1b[0m\x1b[90m Camera, Scanner, GPS, Biometrics, Sensors\x1b[0m');
488
437
  console.log(' \x1b[1m🎬 High-Perf\x1b[0m\x1b[90m Infinite Feeds, Video Players, Swipe Decks\x1b[0m');
489
438
  console.log(' \x1b[1m🏗️ Sovereign\x1b[0m\x1b[90m Full screens: form + photo + save-to-cloud\x1b[0m');
490
439
 
491
- // 3. COLLABORATION
440
+ // 3. LA COLLABORATION
492
441
  console.log('\n\x1b[36m💡 TELL ME "WHAT + WHY":\x1b[0m');
493
442
  console.log('\x1b[90m I will analyze your need and recommend the perfect module to forge.\x1b[0m');
494
443
  console.log('');
495
444
  console.log(' \x1b[33m"I need a camera [WHAT] to scan receipts for my expense tracker [WHY]"\x1b[0m');
496
445
  console.log(' \x1b[33m"I need a form [WHAT] to add products with photos to my catalog [WHY]"\x1b[0m');
497
446
 
498
- // 4. READINESS
447
+ // 4. LA PRISE DE COMMANDE
499
448
  console.log('\n\x1b[32mAlex ❯\x1b[0m I am ready. Describe your feature, and I will architect the solution.');
500
449
  console.log('');
501
450
 
@@ -532,7 +481,7 @@ if (command === 'alex') {
532
481
  inputBuffer = "";
533
482
 
534
483
  if (finalPrompt.length > 1000) {
535
- console.log(`\n\x1b[31m⛔ [Alex Safety] Mission rejected: Excessive size (${finalPrompt.length}/1000 characters).\x1b[0m`);
484
+ console.log(`\n\x1b[31m⛔ [Alex Safety] Mission rejetée : Taille excessive (${finalPrompt.length}/1000 caractères).\x1b[0m`);
536
485
  rl.setPrompt(`\x1b[34m${dynamicUsername} ❯ \x1b[0m`);
537
486
  rl.prompt();
538
487
  return;
@@ -847,13 +796,13 @@ else {
847
796
  try {
848
797
  await axios.post(UPDATE_NETWORK_URL, { keyApp, networkUrl, tester: testerEmail });
849
798
  console.log('\n\x1b[32mEngine started successfully\x1b[0m');
850
- console.log(`\x1b[32mFleetbo OS ❯\x1b[0m -------------------------------------------------------------`);
851
- console.log('\x1b[32mFleetbo OS ❯\x1b[0m \x1b[1mGO GO GO ! OS IS READY\x1b[0m');
852
- console.log('\x1b[32mFleetbo OS ❯\x1b[0m You can now start coding and previewing. 🚀');
853
- console.log(`\x1b[32mFleetbo OS ❯\x1b[0m -------------------------------------------------------------`);
854
- console.log(`\x1b[34mPilot Instruction ❯\x1b[0m Return to the Workspace. The Engine is ready for your orders.\n`);
799
+ console.log(`\x1b[32m[Fleetbo]\x1b[0m -------------------------------------------------------------`);
800
+ console.log('\x1b[32m[Fleetbo] \x1b[1mGO GO GO ! FLEETBO COCKPIT IS READY\x1b[0m');
801
+ console.log('\x1b[32m[Fleetbo] You can now start coding and previewing in Studio. 🚀\x1b[0m');
802
+ console.log(`\x1b[32m[Fleetbo]\x1b[0m -------------------------------------------------------------`);
803
+ console.log(`\x1b[34mPilot Instruction ❯\x1b[0m Switch to your Fleetbo Cockpit tab to begin.\n`);
855
804
  } catch (err) {
856
- console.error(`\x1b[31mFleetbo OS ❯\x1b[0m Sync Error: ${err.message}`);
805
+ console.error(`[Fleetbo] Sync Error: ${err.message}`);
857
806
  }
858
807
  }
859
808
 
@@ -890,7 +839,7 @@ else {
890
839
  }
891
840
  });
892
841
 
893
- //devServer.stdout.pipe(process.stdout);
842
+ devServer.stdout.pipe(process.stdout);
894
843
  devServer.stderr.pipe(process.stderr);
895
844
 
896
845
  let connectionStarted = false;
@@ -898,39 +847,13 @@ else {
898
847
  devServer.stdout.on('data', (data) => {
899
848
  const output = data.toString();
900
849
 
901
- // 🛡️ FILTRE ANTI-PLOMBERIE FLEETBO
902
- const lines = output.split('\n');
903
- const forbiddenTerms = [
904
- 'Attempting to bind to HOST',
905
- 'If this was unintentional',
906
- 'Learn more here:',
907
- 'Starting the development server',
908
- 'You can now view',
909
- 'Local:',
910
- 'On Your Network:',
911
- 'Note that the development build',
912
- 'To create a production build',
913
- 'webpack compiled successfully'
914
- ];
915
-
916
- // On filtre les lignes pour ne garder que le vrai code/debug
917
- const filteredOutput = lines.filter(line => {
918
- return !forbiddenTerms.some(term => line.includes(term));
919
- }).join('\n');
920
-
921
- // S'il reste quelque chose d'utile (un console.log du dev, un warning, une vraie erreur), on l'affiche
922
- if (filteredOutput.trim() !== '') {
923
- process.stdout.write(filteredOutput + '\n');
924
- }
925
-
926
- // 🚀 DÉTECTION DU DÉMARRAGE ET LANCEMENT DE L'UPLINK
927
850
  if (!connectionStarted && (output.includes('Local:') || output.includes('Compiled successfully'))) {
928
851
  connectionStarted = true;
929
852
 
930
- console.log('\x1b[33mFleetbo OS ❯\x1b[0m ---------------------------------------------------');
931
- console.log(`\x1b[33mFleetbo OS ❯\x1b[0m 🔗 Establishing Secure Uplink...`);
932
- console.log(`\x1b[33mFleetbo OS ❯\x1b[0m ⏳ Please wait for the green message...`);
933
- console.log('\x1b[33mFleetbo OS ❯\x1b[0m ---------------------------------------------------');
853
+ console.log('\n[Fleetbo] ---------------------------------------------------');
854
+ console.log(`[Fleetbo] 🔗 Establishing Secure Uplink...`);
855
+ console.log(`[Fleetbo] ⏳ Please wait for the green message...`);
856
+ console.log('[Fleetbo] ---------------------------------------------------');
934
857
 
935
858
  // ============================================
936
859
  // UPLINK avec auto-retry (Fleetbo OS Resilience)
@@ -962,13 +885,11 @@ else {
962
885
  const match = text.match(/https:\/\/[a-zA-Z0-9-]+\.trycloudflare\.com/);
963
886
  if (match) {
964
887
  uplinkFound = true;
965
- // Stabilisation du noyau : on attend 1.5s
966
- setTimeout(() => {
967
- syncFirebase(process.env.REACT_KEY_APP, match[0], process.env.REACT_APP_TESTER_EMAIL);
968
- }, 1500);
888
+ syncFirebase(process.env.REACT_KEY_APP, match[0], process.env.REACT_APP_TESTER_EMAIL);
969
889
  }
970
890
  };
971
891
 
892
+ // Écoute sur les deux flux (stdout + stderr)
972
893
  uplinkProcess.stdout.on('data', handleUplinkOutput);
973
894
  uplinkProcess.stderr.on('data', handleUplinkOutput);
974
895
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fleetbo-cockpit-cli",
3
- "version": "1.0.70",
3
+ "version": "1.0.72",
4
4
  "description": "Fleetbo CLI - Build native mobile apps with React",
5
5
  "author": "Fleetbo",
6
6
  "license": "MIT",