fleetbo-cockpit-cli 1.0.71 → 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 +51 -134
  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,70 +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
- // NOUVEAU BLOC : INJECTION DE LA DOUBLE MÉMOIRE
270
- let memoryScript = "";
271
- if (cache.module.dataSchema) memoryScript += `\n[SCRIPT MÉMOIRE DONNÉES]\n${cache.module.dataSchema}\n`;
272
- if (cache.module.uiSchema) memoryScript += `\n[SCRIPT MÉMOIRE UI NATIF]\n${cache.module.uiSchema}\n`;
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`;
273
260
 
274
- if (!memoryScript) memoryScript = `\n[SCRIPT MÉMOIRE DU MODULE ${modName}]\nAucun schéma enregistré pour ce module.\n`;
275
-
276
- if (isReferenceOnly) {
277
- // 🚨 CAS A : INSPIRATION (Lecture seule)
278
- referenceContexts += `\n--- CONTEXTE : MODULE DE RÉFÉRENCE (${modName}) ---\nDOGME : Ne modifie pas ce module (Lecture seule). Tu dois l'utiliser comme modèle. Aligne-toi sur ses Scripts Mémoires (Données et/ou UI) et sur son Code Natif en fonction de ce que le Pilote te demande d'imiter.\n${memoryScript}\n[CODE NATIF DE RÉFÉRENCE]\n${cache.module.code}\n`;
279
- } else if (!targetModuleContext) {
280
- // 🚨 CAS B : CIBLE PRINCIPALE (Modification)
281
- // LE MOCK EST BANI ! Le Métal est la seule source de vérité.
282
- const intent = getContextIntent(prompt);
283
- if (intent === "MODIFICATION") {
284
- 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`;
285
- } else {
286
- targetModuleContext = `\n--- CONTEXTE : BASE DE TRAVAIL (${modName}) ---\n${memoryScript}\n`;
287
- }
288
- }
261
+ prompt = contextInjection + "\n\n[INSTRUCTION DU PILOTE]\n" + prompt;
262
+ break;
289
263
  } else {
290
264
  process.stdout.write(` \x1b[31mNOT FOUND\x1b[0m\n`);
291
265
  }
292
266
  }
267
+ // --- FIN MODIFICATION MÉMOIRE ---
293
268
 
294
- contextInjection = referenceContexts + targetModuleContext;
295
- if (contextInjection) {
296
- prompt = contextInjection + "\n\n[INSTRUCTION DU PILOTE]\n" + prompt;
297
- }
298
- // --- END MEMORY MODIFICATION ---
299
-
300
- // 🟢 NEW: Real-time timestamp injection
301
- const now = new Date();
302
- // Clean format: YYYY-MM-DD at HH:MM:SS
303
- const exactTime = now.toISOString().split('T')[0] + ' at ' + now.toTimeString().split(' ')[0];
304
-
305
- 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.]`;
306
-
307
- const result = await axios.post(ALEX_ENGINE_URL, { prompt: promptWithTime, projectType: 'android' }, {
269
+ const result = await axios.post(ALEX_ENGINE_URL, { prompt, projectType: 'android' }, {
308
270
  headers: { 'x-project-id': projectId }
309
271
  });
310
272
 
@@ -314,12 +276,6 @@ if (command === 'alex') {
314
276
  try { aiData = JSON.parse(aiData); } catch (_) {}
315
277
  }
316
278
 
317
- // 🟢 DISPLAY REASONING IN TERMINAL
318
- if (aiData.thinking_process) {
319
- // Show start of reasoning in gray for info
320
- console.log(` \x1b[90m🧠 Alex Analysis: ${aiData.thinking_process.substring(0, 150)}...\x1b[0m`);
321
- }
322
-
323
279
  process.stdout.write('\x1b[A\r' + ' '.repeat(50) + '\r');
324
280
 
325
281
  if (aiData.status === 'quota_exceeded') {
@@ -356,21 +312,21 @@ if (command === 'alex') {
356
312
  const formattedMsg = wrapText(rawMsg, 85);
357
313
  console.log('\x1b[32mAlex ❯\x1b[0m ' + formattedMsg);
358
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
+ }
359
323
  }
360
324
 
361
- // --- FILE CREATION LOGIC ---
325
+ // --- C'EST ICI QUE LES FICHIERS SONT CRÉÉS ---
362
326
  if (aiData.status === 'success' && aiData.moduleData) {
363
- let { fileName, code, mockFileName, mockCode, moduleName, instructions, config_offload, dataSchema, uiSchema } = aiData.moduleData;
364
-
365
- // 🛡️ ANTI-DUMP SHIELD (Prevents terminal flooding)
366
- if (moduleName) {
367
- // Cleanup module name
368
- moduleName = moduleName.split('\n')[0].replace(/["'{}]/g, '').trim();
369
- if (moduleName.length > 40) moduleName = moduleName.substring(0, 40) + "...";
370
- }
371
-
327
+ const { fileName, code, mockFileName, mockCode, moduleName, instructions, config_offload } = aiData.moduleData;
372
328
  console.log(` \x1b[90m Architecting: ${moduleName}\x1b[0m`);
373
-
329
+
374
330
  const writeFile = (dir, name, content) => {
375
331
  const fullPath = path.join(process.cwd(), dir);
376
332
  const filePath = path.join(fullPath, name);
@@ -404,7 +360,7 @@ if (command === 'alex') {
404
360
  }
405
361
  }
406
362
 
407
- // --- KERNEL SYNCHRONIZATION ---
363
+ // --- SYNCHRONISATION DU KERNEL ---
408
364
  const depsCount = config_offload?.dependencies?.length || 0;
409
365
  process.stdout.write(` \x1b[33m[Cloud Inject]\x1b[0m Archiving ${moduleName} to OS (${depsCount} libs)...`);
410
366
 
@@ -418,9 +374,7 @@ if (command === 'alex') {
418
374
  code: code,
419
375
  mockFileName: mockFileName,
420
376
  mockCode: mockCode,
421
- config_offload: config_offload || { dependencies: [], permissions: [] },
422
- dataSchema: dataSchema || null, // 👈 LA LIGNE MAGIQUE
423
- uiSchema: uiSchema || null
377
+ config_offload: config_offload || { dependencies: [], permissions: [] }
424
378
  }
425
379
  });
426
380
  process.stdout.write(` \x1b[32mOK\x1b[0m\n`);
@@ -428,18 +382,9 @@ if (command === 'alex') {
428
382
  process.stdout.write(` \x1b[31mFAILED\x1b[0m\n`);
429
383
  console.error(` ⚠️ OS sync failed: ${err.message}`);
430
384
  }
431
- // 🟢 LE FUEL EST DÉPLACÉ ICI (TOUTE FIN DU TRY)
432
- if (aiData.remainingConsultations !== undefined) {
433
- const remaining = aiData.remainingConsultations;
434
- const limit = aiData.consultationLimit || 7;
435
- const tierLabel = aiData.tier.toUpperCase();
436
- const percent = Math.round((remaining / limit) * 100);
437
- const energyColor = percent > 20 ? '\x1b[32m' : '\x1b[31m';
438
- console.log(`\n\x1b[36m⚡ Architect Fuel:\x1b[0m ${energyColor}${percent}%\x1b[0m (${remaining}/${limit} instructions left) [${tierLabel}]\n`);
439
- }
440
385
  } else if (aiData.status === 'success' && !aiData.moduleData) {
441
- // SAFETY: If formatting is broken
442
- 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`);
443
388
  }
444
389
  } catch (error) {
445
390
  process.stdout.write('\r' + ' '.repeat(50) + '\r');
@@ -481,25 +426,25 @@ if (command === 'alex') {
481
426
 
482
427
  process.stdout.write(' '.repeat(60) + '\r');
483
428
 
484
- // 1. IDENTITY
429
+ // 1. IDENTITÉ
485
430
  console.log('\n\x1b[32m🤖 Alex is online.\x1b[0m');
486
431
  console.log('\x1b[90m Your JS stays the brain. I forge the native muscle.\x1b[0m');
487
432
 
488
- // 2. FORGE CAPABILITIES
433
+ // 2. CE QUE JE FORGE
489
434
  console.log('\n\x1b[36m⚡ WHAT I CAN FORGE:\x1b[0m');
490
435
  console.log('');
491
436
  console.log(' \x1b[1m📷 Hardware\x1b[0m\x1b[90m Camera, Scanner, GPS, Biometrics, Sensors\x1b[0m');
492
437
  console.log(' \x1b[1m🎬 High-Perf\x1b[0m\x1b[90m Infinite Feeds, Video Players, Swipe Decks\x1b[0m');
493
438
  console.log(' \x1b[1m🏗️ Sovereign\x1b[0m\x1b[90m Full screens: form + photo + save-to-cloud\x1b[0m');
494
439
 
495
- // 3. COLLABORATION
440
+ // 3. LA COLLABORATION
496
441
  console.log('\n\x1b[36m💡 TELL ME "WHAT + WHY":\x1b[0m');
497
442
  console.log('\x1b[90m I will analyze your need and recommend the perfect module to forge.\x1b[0m');
498
443
  console.log('');
499
444
  console.log(' \x1b[33m"I need a camera [WHAT] to scan receipts for my expense tracker [WHY]"\x1b[0m');
500
445
  console.log(' \x1b[33m"I need a form [WHAT] to add products with photos to my catalog [WHY]"\x1b[0m');
501
446
 
502
- // 4. READINESS
447
+ // 4. LA PRISE DE COMMANDE
503
448
  console.log('\n\x1b[32mAlex ❯\x1b[0m I am ready. Describe your feature, and I will architect the solution.');
504
449
  console.log('');
505
450
 
@@ -536,7 +481,7 @@ if (command === 'alex') {
536
481
  inputBuffer = "";
537
482
 
538
483
  if (finalPrompt.length > 1000) {
539
- 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`);
540
485
  rl.setPrompt(`\x1b[34m${dynamicUsername} ❯ \x1b[0m`);
541
486
  rl.prompt();
542
487
  return;
@@ -851,13 +796,13 @@ else {
851
796
  try {
852
797
  await axios.post(UPDATE_NETWORK_URL, { keyApp, networkUrl, tester: testerEmail });
853
798
  console.log('\n\x1b[32mEngine started successfully\x1b[0m');
854
- console.log(`\x1b[32mFleetbo OS ❯\x1b[0m -------------------------------------------------------------`);
855
- console.log('\x1b[32mFleetbo OS ❯\x1b[0m \x1b[1mGO GO GO ! OS IS READY\x1b[0m');
856
- console.log('\x1b[32mFleetbo OS ❯\x1b[0m You can now start coding and previewing. 🚀');
857
- console.log(`\x1b[32mFleetbo OS ❯\x1b[0m -------------------------------------------------------------`);
858
- 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`);
859
804
  } catch (err) {
860
- console.error(`\x1b[31mFleetbo OS ❯\x1b[0m Sync Error: ${err.message}`);
805
+ console.error(`[Fleetbo] Sync Error: ${err.message}`);
861
806
  }
862
807
  }
863
808
 
@@ -894,7 +839,7 @@ else {
894
839
  }
895
840
  });
896
841
 
897
- //devServer.stdout.pipe(process.stdout);
842
+ devServer.stdout.pipe(process.stdout);
898
843
  devServer.stderr.pipe(process.stderr);
899
844
 
900
845
  let connectionStarted = false;
@@ -902,39 +847,13 @@ else {
902
847
  devServer.stdout.on('data', (data) => {
903
848
  const output = data.toString();
904
849
 
905
- // 🛡️ FILTRE ANTI-PLOMBERIE FLEETBO
906
- const lines = output.split('\n');
907
- const forbiddenTerms = [
908
- 'Attempting to bind to HOST',
909
- 'If this was unintentional',
910
- 'Learn more here:',
911
- 'Starting the development server',
912
- 'You can now view',
913
- 'Local:',
914
- 'On Your Network:',
915
- 'Note that the development build',
916
- 'To create a production build',
917
- 'webpack compiled successfully'
918
- ];
919
-
920
- // On filtre les lignes pour ne garder que le vrai code/debug
921
- const filteredOutput = lines.filter(line => {
922
- return !forbiddenTerms.some(term => line.includes(term));
923
- }).join('\n');
924
-
925
- // S'il reste quelque chose d'utile (un console.log du dev, un warning, une vraie erreur), on l'affiche
926
- if (filteredOutput.trim() !== '') {
927
- process.stdout.write(filteredOutput + '\n');
928
- }
929
-
930
- // 🚀 DÉTECTION DU DÉMARRAGE ET LANCEMENT DE L'UPLINK
931
850
  if (!connectionStarted && (output.includes('Local:') || output.includes('Compiled successfully'))) {
932
851
  connectionStarted = true;
933
852
 
934
- console.log('\x1b[33mFleetbo OS ❯\x1b[0m ---------------------------------------------------');
935
- console.log(`\x1b[33mFleetbo OS ❯\x1b[0m 🔗 Establishing Secure Uplink...`);
936
- console.log(`\x1b[33mFleetbo OS ❯\x1b[0m ⏳ Please wait for the green message...`);
937
- 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] ---------------------------------------------------');
938
857
 
939
858
  // ============================================
940
859
  // UPLINK avec auto-retry (Fleetbo OS Resilience)
@@ -966,13 +885,11 @@ else {
966
885
  const match = text.match(/https:\/\/[a-zA-Z0-9-]+\.trycloudflare\.com/);
967
886
  if (match) {
968
887
  uplinkFound = true;
969
- // Stabilisation du noyau : on attend 1.5s
970
- setTimeout(() => {
971
- syncFirebase(process.env.REACT_KEY_APP, match[0], process.env.REACT_APP_TESTER_EMAIL);
972
- }, 1500);
888
+ syncFirebase(process.env.REACT_KEY_APP, match[0], process.env.REACT_APP_TESTER_EMAIL);
973
889
  }
974
890
  };
975
891
 
892
+ // Écoute sur les deux flux (stdout + stderr)
976
893
  uplinkProcess.stdout.on('data', handleUplinkOutput);
977
894
  uplinkProcess.stderr.on('data', handleUplinkOutput);
978
895
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fleetbo-cockpit-cli",
3
- "version": "1.0.71",
3
+ "version": "1.0.72",
4
4
  "description": "Fleetbo CLI - Build native mobile apps with React",
5
5
  "author": "Fleetbo",
6
6
  "license": "MIT",