fleetbo-cockpit-cli 1.0.63 → 1.0.65

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 +53 -35
  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,10 +293,10 @@ if (command === 'alex') {
276
293
  try { aiData = JSON.parse(aiData); } catch (_) {}
277
294
  }
278
295
 
279
- // 🟢 AFFICHAGE DU RAISONNEMENT DANS LE TERMINAL
296
+ // 🟢 DISPLAY REASONING IN TERMINAL
280
297
  if (aiData.thinking_process) {
281
- // Affiche le début du raisonnement en gris pour info
282
- console.log(` \x1b[90m🧠 Analyse Alex : ${aiData.thinking_process.substring(0, 150)}...\x1b[0m`);
298
+ // Show start of reasoning in gray for info
299
+ console.log(` \x1b[90m🧠 Alex Analysis: ${aiData.thinking_process.substring(0, 150)}...\x1b[0m`);
283
300
  }
284
301
 
285
302
  process.stdout.write('\x1b[A\r' + ' '.repeat(50) + '\r');
@@ -317,24 +334,16 @@ if (command === 'alex') {
317
334
 
318
335
  const formattedMsg = wrapText(rawMsg, 85);
319
336
  console.log('\x1b[32mAlex ❯\x1b[0m ' + formattedMsg);
320
-
321
- if (aiData.remainingConsultations !== undefined) {
322
- const remaining = aiData.remainingConsultations;
323
- const limit = aiData.consultationLimit || 7;
324
- const tierLabel = aiData.tier === 'senior' ? 'SENIOR' : aiData.tier === 'expert' ? 'EXPERT' : 'JUNIOR';
325
- const percent = Math.round((remaining / limit) * 100);
326
- const energyColor = percent > 20 ? '\x1b[32m' : '\x1b[31m';
327
- console.log(`\n\x1b[36m⚡ Architect Fuel:\x1b[0m ${energyColor}${percent}%\x1b[0m (${remaining}/${limit} instructions left) [${tierLabel}]\n`);
328
- }
337
+
329
338
  }
330
339
 
331
- // --- C'EST ICI QUE LES FICHIERS SONT CRÉÉS ---
340
+ // --- FILE CREATION LOGIC ---
332
341
  if (aiData.status === 'success' && aiData.moduleData) {
333
342
  let { fileName, code, mockFileName, mockCode, moduleName, instructions, config_offload } = aiData.moduleData;
334
343
 
335
- // 🛡️ BOUCLIER ANTI-DUMP (Empêche l'explosion du terminal)
344
+ // 🛡️ ANTI-DUMP SHIELD (Prevents terminal flooding)
336
345
  if (moduleName) {
337
- // Si l'IA met des sauts de ligne ou un texte trop long dans le nom, on coupe.
346
+ // Cleanup module name
338
347
  moduleName = moduleName.split('\n')[0].replace(/["'{}]/g, '').trim();
339
348
  if (moduleName.length > 40) moduleName = moduleName.substring(0, 40) + "...";
340
349
  }
@@ -374,7 +383,7 @@ if (command === 'alex') {
374
383
  }
375
384
  }
376
385
 
377
- // --- SYNCHRONISATION DU KERNEL ---
386
+ // --- KERNEL SYNCHRONIZATION ---
378
387
  const depsCount = config_offload?.dependencies?.length || 0;
379
388
  process.stdout.write(` \x1b[33m[Cloud Inject]\x1b[0m Archiving ${moduleName} to OS (${depsCount} libs)...`);
380
389
 
@@ -396,9 +405,18 @@ if (command === 'alex') {
396
405
  process.stdout.write(` \x1b[31mFAILED\x1b[0m\n`);
397
406
  console.error(` ⚠️ OS sync failed: ${err.message}`);
398
407
  }
408
+ // 🟢 LE FUEL EST DÉPLACÉ ICI (TOUTE FIN DU TRY)
409
+ if (aiData.remainingConsultations !== undefined) {
410
+ const remaining = aiData.remainingConsultations;
411
+ const limit = aiData.consultationLimit || 7;
412
+ const tierLabel = aiData.tier.toUpperCase();
413
+ const percent = Math.round((remaining / limit) * 100);
414
+ const energyColor = percent > 20 ? '\x1b[32m' : '\x1b[31m';
415
+ console.log(`\n\x1b[36m⚡ Architect Fuel:\x1b[0m ${energyColor}${percent}%\x1b[0m (${remaining}/${limit} instructions left) [${tierLabel}]\n`);
416
+ }
399
417
  } else if (aiData.status === 'success' && !aiData.moduleData) {
400
- // SÉCURITÉ : Si Alex s'emmêle les pinceaux et renvoie un mauvais format JSON
401
- 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`);
402
420
  }
403
421
  } catch (error) {
404
422
  process.stdout.write('\r' + ' '.repeat(50) + '\r');
@@ -440,25 +458,25 @@ if (command === 'alex') {
440
458
 
441
459
  process.stdout.write(' '.repeat(60) + '\r');
442
460
 
443
- // 1. IDENTITÉ
461
+ // 1. IDENTITY
444
462
  console.log('\n\x1b[32m🤖 Alex is online.\x1b[0m');
445
463
  console.log('\x1b[90m Your JS stays the brain. I forge the native muscle.\x1b[0m');
446
464
 
447
- // 2. CE QUE JE FORGE
465
+ // 2. FORGE CAPABILITIES
448
466
  console.log('\n\x1b[36m⚡ WHAT I CAN FORGE:\x1b[0m');
449
467
  console.log('');
450
468
  console.log(' \x1b[1m📷 Hardware\x1b[0m\x1b[90m Camera, Scanner, GPS, Biometrics, Sensors\x1b[0m');
451
469
  console.log(' \x1b[1m🎬 High-Perf\x1b[0m\x1b[90m Infinite Feeds, Video Players, Swipe Decks\x1b[0m');
452
470
  console.log(' \x1b[1m🏗️ Sovereign\x1b[0m\x1b[90m Full screens: form + photo + save-to-cloud\x1b[0m');
453
471
 
454
- // 3. LA COLLABORATION
472
+ // 3. COLLABORATION
455
473
  console.log('\n\x1b[36m💡 TELL ME "WHAT + WHY":\x1b[0m');
456
474
  console.log('\x1b[90m I will analyze your need and recommend the perfect module to forge.\x1b[0m');
457
475
  console.log('');
458
476
  console.log(' \x1b[33m"I need a camera [WHAT] to scan receipts for my expense tracker [WHY]"\x1b[0m');
459
477
  console.log(' \x1b[33m"I need a form [WHAT] to add products with photos to my catalog [WHY]"\x1b[0m');
460
478
 
461
- // 4. LA PRISE DE COMMANDE
479
+ // 4. READINESS
462
480
  console.log('\n\x1b[32mAlex ❯\x1b[0m I am ready. Describe your feature, and I will architect the solution.');
463
481
  console.log('');
464
482
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fleetbo-cockpit-cli",
3
- "version": "1.0.63",
3
+ "version": "1.0.65",
4
4
  "description": "Fleetbo CLI - Build native mobile apps with React",
5
5
  "author": "Fleetbo",
6
6
  "license": "MIT",