fleetbo-cockpit-cli 1.0.62 → 1.0.64

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 +97 -37
  2. package/package.json +1 -1
package/cli.js CHANGED
@@ -146,9 +146,10 @@ const showEnergyTransfer = async () => {
146
146
 
147
147
  // Détecte TOUS les mots en PascalCase (ex: GuestCreator, CameraModule, Tab2)
148
148
  const extractPotentialModules = (text) => {
149
- const regex = /\b[A-Z][a-zA-Z0-9_]{2,}\b/g;
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;
150
151
  const matches = text.match(regex) || [];
151
- return [...new Set(matches)]; // Dédoublonne les résultats
152
+ return [...new Set(matches)];
152
153
  };
153
154
 
154
155
 
@@ -219,8 +220,8 @@ if (command === 'alex') {
219
220
  return;
220
221
  }
221
222
 
222
- // 📋 INTERCEPTION : LISTER LES MODULES
223
- const isListingRequest = /^(liste|list|quels modules|montre les modules)/i.test(prompt);
223
+ // 📋 INTERCEPTION: LIST MODULES
224
+ const isListingRequest = /^(liste|list|quels modules|montre les modules|show modules)/i.test(prompt);
224
225
  if (isListingRequest) {
225
226
  process.stdout.write(` \x1b[90m🔍 Scanning OS Cache...\x1b[0m\n`);
226
227
  const cacheRes = await getModuleCache({ projectId, moduleName: null });
@@ -232,7 +233,7 @@ if (command === 'alex') {
232
233
  console.log(` ${metalColor}■\x1b[0m \x1b[1m${m.moduleName}\x1b[0m \x1b[90m(${m.platform})\x1b[0m`);
233
234
  });
234
235
  } else {
235
- console.log(`\n \x1b[90mAucun module trouvé dans l'infrastructure de ce projet.\x1b[0m`);
236
+ console.log(`\n \x1b[90mNo modules found in the infrastructure of this project.\x1b[0m`);
236
237
  }
237
238
  return;
238
239
  }
@@ -240,12 +241,12 @@ if (command === 'alex') {
240
241
  console.log('\x1b[33m🧠 Alex is thinking...\x1b[0m');
241
242
 
242
243
  try {
243
- // --- SYSTÈME DE MÉMOIRE (SMART CACHE SCANNER) ---
244
+ // --- MEMORY SYSTEM (SMART CACHE SCANNER) ---
244
245
  let contextInjection = "";
245
246
  const potentialModules = extractPotentialModules(prompt);
246
247
 
247
248
  for (const modName of potentialModules) {
248
- process.stdout.write(` \x1b[90m🔍 Checking os cache for ${modName}...\x1b[0m`);
249
+ process.stdout.write(` \x1b[90m🔍 Checking OS cache for ${modName}...\x1b[0m`);
249
250
  const cache = await getModuleCache({ projectId, moduleName: modName });
250
251
 
251
252
  if (cache.found) {
@@ -253,20 +254,36 @@ if (command === 'alex') {
253
254
 
254
255
  const intent = getContextIntent(prompt);
255
256
  const contextTitle = intent === "MODIFICATION"
256
- ? "MÉTAL EXISTANT (À MODIFIER)"
257
- : "MÉTAL DE RÉFÉRENCE (POUR PARITÉ DES DONNÉES)";
257
+ ? "EXISTING METAL (TO MODIFY)"
258
+ : "REFERENCE METAL (FOR DATA PARITY)";
259
+
260
+ // 🟢 NEW: Data Schema extraction and formatting
261
+ let schemaInstruction = "";
262
+ if (cache.module.dataSchema && Array.isArray(cache.module.dataSchema)) {
263
+ schemaInstruction = "\n[STRICT DATA CONTRACT]\nThe reference module uses this configuration. You MUST strictly use these collections and keys:\n";
264
+ cache.module.dataSchema.forEach(schema => {
265
+ schemaInstruction += `- Collection '${schema.collection}': fields [${schema.fields.join(', ')}]\n`;
266
+ });
267
+ }
258
268
 
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`;
269
+ contextInjection = `\n--- SOVEREIGN CONTEXT: ${contextTitle} (${modName}) ---\nDOGMA: The Metal is the absolute source of truth.\n${schemaInstruction}\n\n[EXISTING NATIVE CODE]\n${cache.module.code}\n--- END OF CONTEXT ---\n`;
260
270
 
261
- prompt = contextInjection + "\n\n[INSTRUCTION DU PILOTE]\n" + prompt;
271
+ prompt = contextInjection + "\n\n[PILOT INSTRUCTION]\n" + prompt;
262
272
  break;
263
273
  } else {
264
274
  process.stdout.write(` \x1b[31mNOT FOUND\x1b[0m\n`);
265
275
  }
266
276
  }
267
- // --- FIN MODIFICATION MÉMOIRE ---
277
+ // --- END MEMORY MODIFICATION ---
278
+
279
+ // 🟢 NEW: Real-time timestamp injection
280
+ const now = new Date();
281
+ // Clean format: YYYY-MM-DD at HH:MM:SS
282
+ const exactTime = now.toISOString().split('T')[0] + ' at ' + now.toTimeString().split(' ')[0];
283
+
284
+ 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.]`;
268
285
 
269
- const result = await axios.post(ALEX_ENGINE_URL, { prompt, projectType: 'android' }, {
286
+ const result = await axios.post(ALEX_ENGINE_URL, { prompt: promptWithTime, projectType: 'android' }, {
270
287
  headers: { 'x-project-id': projectId }
271
288
  });
272
289
 
@@ -276,6 +293,12 @@ if (command === 'alex') {
276
293
  try { aiData = JSON.parse(aiData); } catch (_) {}
277
294
  }
278
295
 
296
+ // 🟢 DISPLAY REASONING IN TERMINAL
297
+ if (aiData.thinking_process) {
298
+ // Show start of reasoning in gray for info
299
+ console.log(` \x1b[90m🧠 Alex Analysis: ${aiData.thinking_process.substring(0, 150)}...\x1b[0m`);
300
+ }
301
+
279
302
  process.stdout.write('\x1b[A\r' + ' '.repeat(50) + '\r');
280
303
 
281
304
  if (aiData.status === 'quota_exceeded') {
@@ -322,16 +345,25 @@ if (command === 'alex') {
322
345
  }
323
346
  }
324
347
 
325
- // --- C'EST ICI QUE LES FICHIERS SONT CRÉÉS ---
348
+ // --- FILE CREATION LOGIC ---
326
349
  if (aiData.status === 'success' && aiData.moduleData) {
327
- const { fileName, code, mockFileName, mockCode, moduleName, instructions, config_offload } = aiData.moduleData;
350
+ let { fileName, code, mockFileName, mockCode, moduleName, instructions, config_offload } = aiData.moduleData;
351
+
352
+ // 🛡️ ANTI-DUMP SHIELD (Prevents terminal flooding)
353
+ if (moduleName) {
354
+ // Cleanup module name
355
+ moduleName = moduleName.split('\n')[0].replace(/["'{}]/g, '').trim();
356
+ if (moduleName.length > 40) moduleName = moduleName.substring(0, 40) + "...";
357
+ }
358
+
328
359
  console.log(` \x1b[90m Architecting: ${moduleName}\x1b[0m`);
329
-
360
+
330
361
  const writeFile = (dir, name, content) => {
331
362
  const fullPath = path.join(process.cwd(), dir);
332
363
  const filePath = path.join(fullPath, name);
333
364
  if (!fs.existsSync(fullPath)) fs.mkdirSync(fullPath, { recursive: true });
334
365
  fs.writeFileSync(filePath, content);
366
+ console.log('');
335
367
  console.log(` \x1b[32m[Written]\x1b[0m ${dir}${name}`);
336
368
  };
337
369
 
@@ -360,7 +392,7 @@ if (command === 'alex') {
360
392
  }
361
393
  }
362
394
 
363
- // --- SYNCHRONISATION DU KERNEL ---
395
+ // --- KERNEL SYNCHRONIZATION ---
364
396
  const depsCount = config_offload?.dependencies?.length || 0;
365
397
  process.stdout.write(` \x1b[33m[Cloud Inject]\x1b[0m Archiving ${moduleName} to OS (${depsCount} libs)...`);
366
398
 
@@ -383,8 +415,8 @@ if (command === 'alex') {
383
415
  console.error(` ⚠️ OS sync failed: ${err.message}`);
384
416
  }
385
417
  } else if (aiData.status === 'success' && !aiData.moduleData) {
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`);
418
+ // SAFETY: If formatting is broken
419
+ console.log(`\n\x1b[31m⚠️ Error: Alex replied, but source code could not be extracted. Try the command again.\x1b[0m\n`);
388
420
  }
389
421
  } catch (error) {
390
422
  process.stdout.write('\r' + ' '.repeat(50) + '\r');
@@ -426,25 +458,25 @@ if (command === 'alex') {
426
458
 
427
459
  process.stdout.write(' '.repeat(60) + '\r');
428
460
 
429
- // 1. IDENTITÉ
461
+ // 1. IDENTITY
430
462
  console.log('\n\x1b[32m🤖 Alex is online.\x1b[0m');
431
463
  console.log('\x1b[90m Your JS stays the brain. I forge the native muscle.\x1b[0m');
432
464
 
433
- // 2. CE QUE JE FORGE
465
+ // 2. FORGE CAPABILITIES
434
466
  console.log('\n\x1b[36m⚡ WHAT I CAN FORGE:\x1b[0m');
435
467
  console.log('');
436
468
  console.log(' \x1b[1m📷 Hardware\x1b[0m\x1b[90m Camera, Scanner, GPS, Biometrics, Sensors\x1b[0m');
437
469
  console.log(' \x1b[1m🎬 High-Perf\x1b[0m\x1b[90m Infinite Feeds, Video Players, Swipe Decks\x1b[0m');
438
470
  console.log(' \x1b[1m🏗️ Sovereign\x1b[0m\x1b[90m Full screens: form + photo + save-to-cloud\x1b[0m');
439
471
 
440
- // 3. LA COLLABORATION
472
+ // 3. COLLABORATION
441
473
  console.log('\n\x1b[36m💡 TELL ME "WHAT + WHY":\x1b[0m');
442
474
  console.log('\x1b[90m I will analyze your need and recommend the perfect module to forge.\x1b[0m');
443
475
  console.log('');
444
476
  console.log(' \x1b[33m"I need a camera [WHAT] to scan receipts for my expense tracker [WHY]"\x1b[0m');
445
477
  console.log(' \x1b[33m"I need a form [WHAT] to add products with photos to my catalog [WHY]"\x1b[0m');
446
478
 
447
- // 4. LA PRISE DE COMMANDE
479
+ // 4. READINESS
448
480
  console.log('\n\x1b[32mAlex ❯\x1b[0m I am ready. Describe your feature, and I will architect the solution.');
449
481
  console.log('');
450
482
 
@@ -481,7 +513,7 @@ if (command === 'alex') {
481
513
  inputBuffer = "";
482
514
 
483
515
  if (finalPrompt.length > 1000) {
484
- console.log(`\n\x1b[31m⛔ [Alex Safety] Mission rejetée : Taille excessive (${finalPrompt.length}/1000 caractères).\x1b[0m`);
516
+ console.log(`\n\x1b[31m⛔ [Alex Safety] Mission rejected: Excessive size (${finalPrompt.length}/1000 characters).\x1b[0m`);
485
517
  rl.setPrompt(`\x1b[34m${dynamicUsername} ❯ \x1b[0m`);
486
518
  rl.prompt();
487
519
  return;
@@ -796,13 +828,13 @@ else {
796
828
  try {
797
829
  await axios.post(UPDATE_NETWORK_URL, { keyApp, networkUrl, tester: testerEmail });
798
830
  console.log('\n\x1b[32mEngine started successfully\x1b[0m');
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`);
831
+ console.log(`\x1b[32mFleetbo OS ❯\x1b[0m -------------------------------------------------------------`);
832
+ console.log('\x1b[32mFleetbo OS ❯\x1b[0m \x1b[1mGO GO GO ! OS IS READY\x1b[0m');
833
+ console.log('\x1b[32mFleetbo OS ❯\x1b[0m You can now start coding and previewing. 🚀');
834
+ console.log(`\x1b[32mFleetbo OS ❯\x1b[0m -------------------------------------------------------------`);
835
+ console.log(`\x1b[34mPilot Instruction ❯\x1b[0m Return to the Workspace. The Engine is ready for your orders.\n`);
804
836
  } catch (err) {
805
- console.error(`[Fleetbo] Sync Error: ${err.message}`);
837
+ console.error(`\x1b[31mFleetbo OS ❯\x1b[0m Sync Error: ${err.message}`);
806
838
  }
807
839
  }
808
840
 
@@ -839,7 +871,7 @@ else {
839
871
  }
840
872
  });
841
873
 
842
- devServer.stdout.pipe(process.stdout);
874
+ //devServer.stdout.pipe(process.stdout);
843
875
  devServer.stderr.pipe(process.stderr);
844
876
 
845
877
  let connectionStarted = false;
@@ -847,13 +879,39 @@ else {
847
879
  devServer.stdout.on('data', (data) => {
848
880
  const output = data.toString();
849
881
 
882
+ // 🛡️ FILTRE ANTI-PLOMBERIE FLEETBO
883
+ const lines = output.split('\n');
884
+ const forbiddenTerms = [
885
+ 'Attempting to bind to HOST',
886
+ 'If this was unintentional',
887
+ 'Learn more here:',
888
+ 'Starting the development server',
889
+ 'You can now view',
890
+ 'Local:',
891
+ 'On Your Network:',
892
+ 'Note that the development build',
893
+ 'To create a production build',
894
+ 'webpack compiled successfully'
895
+ ];
896
+
897
+ // On filtre les lignes pour ne garder que le vrai code/debug
898
+ const filteredOutput = lines.filter(line => {
899
+ return !forbiddenTerms.some(term => line.includes(term));
900
+ }).join('\n');
901
+
902
+ // S'il reste quelque chose d'utile (un console.log du dev, un warning, une vraie erreur), on l'affiche
903
+ if (filteredOutput.trim() !== '') {
904
+ process.stdout.write(filteredOutput + '\n');
905
+ }
906
+
907
+ // 🚀 DÉTECTION DU DÉMARRAGE ET LANCEMENT DE L'UPLINK
850
908
  if (!connectionStarted && (output.includes('Local:') || output.includes('Compiled successfully'))) {
851
909
  connectionStarted = true;
852
910
 
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] ---------------------------------------------------');
911
+ console.log('\x1b[33mFleetbo OS ❯\x1b[0m ---------------------------------------------------');
912
+ console.log(`\x1b[33mFleetbo OS ❯\x1b[0m 🔗 Establishing Secure Uplink...`);
913
+ console.log(`\x1b[33mFleetbo OS ❯\x1b[0m ⏳ Please wait for the green message...`);
914
+ console.log('\x1b[33mFleetbo OS ❯\x1b[0m ---------------------------------------------------');
857
915
 
858
916
  // ============================================
859
917
  // UPLINK avec auto-retry (Fleetbo OS Resilience)
@@ -885,11 +943,13 @@ else {
885
943
  const match = text.match(/https:\/\/[a-zA-Z0-9-]+\.trycloudflare\.com/);
886
944
  if (match) {
887
945
  uplinkFound = true;
888
- syncFirebase(process.env.REACT_KEY_APP, match[0], process.env.REACT_APP_TESTER_EMAIL);
946
+ // Stabilisation du noyau : on attend 1.5s
947
+ setTimeout(() => {
948
+ syncFirebase(process.env.REACT_KEY_APP, match[0], process.env.REACT_APP_TESTER_EMAIL);
949
+ }, 1500);
889
950
  }
890
951
  };
891
952
 
892
- // Écoute sur les deux flux (stdout + stderr)
893
953
  uplinkProcess.stdout.on('data', handleUplinkOutput);
894
954
  uplinkProcess.stderr.on('data', handleUplinkOutput);
895
955
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fleetbo-cockpit-cli",
3
- "version": "1.0.62",
3
+ "version": "1.0.64",
4
4
  "description": "Fleetbo CLI - Build native mobile apps with React",
5
5
  "author": "Fleetbo",
6
6
  "license": "MIT",