fleetbo-cockpit-cli 1.0.45 → 1.0.46

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 +31 -44
  2. package/package.json +1 -1
package/cli.js CHANGED
@@ -239,11 +239,10 @@ if (command === 'alex') {
239
239
  console.log('\x1b[90mAlex prefers concise instructions. Please summarize.\x1b[0m');
240
240
  return;
241
241
  }
242
- //process.stdout.write('\x1b[33m🧠 Alex is thinking...\x1b[0m');
243
242
  console.log('\x1b[33m🧠 Alex is thinking...\x1b[0m');
244
243
 
245
244
  try {
246
- // --- DÉBUT MODIFICATION : SYSTÈME DE MÉMOIRE (SMART CACHE SCANNER) ---
245
+ // --- SYSTÈME DE MÉMOIRE (SMART CACHE SCANNER) ---
247
246
  let contextInjection = "";
248
247
  const potentialModules = extractPotentialModules(prompt);
249
248
  let referenceFound = false;
@@ -260,7 +259,6 @@ if (command === 'alex') {
260
259
  ? "MÉTAL EXISTANT (À MODIFIER)"
261
260
  : "MÉTAL DE RÉFÉRENCE (POUR PARITÉ DES DONNÉES)";
262
261
 
263
- // ⚠️ CHANGEMENT MAJEUR : ON N'ENVOIE QUE LE CODE NATIF
264
262
  contextInjection = `
265
263
 
266
264
  --- CONTEXTE SOUVERAIN : ${contextTitle} (${modName}) ---
@@ -280,7 +278,7 @@ if (command === 'alex') {
280
278
  process.stdout.write(` \x1b[31mNOT FOUND\x1b[0m\n`);
281
279
  }
282
280
  }
283
- // --- FIN MODIFICATION ---
281
+ // --- FIN MODIFICATION MÉMOIRE ---
284
282
 
285
283
  const result = await axios.post(ALEX_ENGINE_URL, { prompt, projectType: 'android' }, {
286
284
  headers: { 'x-project-id': projectId }
@@ -292,7 +290,6 @@ if (command === 'alex') {
292
290
  try { aiData = JSON.parse(aiData); } catch (_) {}
293
291
  }
294
292
 
295
- //process.stdout.write('\r' + ' '.repeat(50) + '\r');
296
293
  process.stdout.write('\x1b[A\r' + ' '.repeat(50) + '\r');
297
294
 
298
295
  if (aiData.status === 'quota_exceeded') {
@@ -304,11 +301,7 @@ if (command === 'alex') {
304
301
  console.log('');
305
302
  let rawMsg = aiData.message || "I'm ready.";
306
303
 
307
- // 🛡️ FIX DÉFINITIF: Gemini imbrique parfois le JSON complet dans "message"
308
- // Le JSON imbriqué peut être tronqué (4000 tokens), donc JSON.parse échoue.
309
- // On extrait le vrai message par découpe de string.
310
304
  if (typeof rawMsg === 'string' && rawMsg.trimStart().startsWith('{')) {
311
- // Tentative 1: Parse complet (JSON non tronqué)
312
305
  try {
313
306
  const nested = JSON.parse(rawMsg);
314
307
  if (nested && nested.message) {
@@ -318,7 +311,6 @@ if (command === 'alex') {
318
311
  }
319
312
  }
320
313
  } catch (_) {
321
- // Tentative 2: Extraction par regex (JSON tronqué)
322
314
  const msgMatch = rawMsg.match(/"message"\s*:\s*"((?:[^"\\]|\\.)*)"/);
323
315
  if (msgMatch && msgMatch[1]) {
324
316
  rawMsg = msgMatch[1].replace(/\\n/g, '\n').replace(/\\"/g, '"');
@@ -328,18 +320,15 @@ if (command === 'alex') {
328
320
  }
329
321
  }
330
322
 
331
- // 🛡️ SAFETY: Si le message est un JSON stringifié ou contient du code brut,
332
- // on extrait uniquement la partie lisible pour le terminal.
333
323
  if (typeof rawMsg === 'object') {
334
324
  rawMsg = rawMsg.message || rawMsg.text || "Module generated.";
335
325
  }
336
- // Détection d'un JSON brut accidentellement injecté dans le message
337
326
  try {
338
327
  const testParse = JSON.parse(rawMsg);
339
328
  if (testParse && typeof testParse === 'object' && testParse.status) {
340
329
  rawMsg = testParse.message || "Module generated.";
341
330
  }
342
- } catch (_) { /* Not JSON, continue normally */ }
331
+ } catch (_) { }
343
332
 
344
333
  const formattedMsg = wrapText(rawMsg, 85);
345
334
  console.log('\x1b[32mAlex ❯\x1b[0m ' + formattedMsg);
@@ -393,22 +382,29 @@ if (command === 'alex') {
393
382
  }
394
383
  }
395
384
 
396
- if (config_offload && (config_offload.dependencies?.length > 0 || config_offload.permissions?.length > 0)) {
397
- process.stdout.write(` \x1b[33m[Cloud Inject]\x1b[0m Syncing ${config_offload.dependencies?.length || 0} libs to OS...`);
398
- try {
399
- await axios.post(INJECT_DEPS_URL, {
400
- projectId: projectId,
401
- fileData: {
402
- path: fileName,
403
- config_offload: config_offload
404
- }
405
- });
406
- process.stdout.write(` \x1b[32mOK\x1b[0m\n`);
407
- } catch (err) {
408
- process.stdout.write(` \x1b[31mFAILED\x1b[0m\n`);
409
- console.error(` ⚠️ Config sync failed: ${err.message}`);
410
- }
385
+ // --- CORRECTION : SYNCHRONISATION DU KERNEL (Cache + Dépendances INCONDITIONNELLE) ---
386
+ const depsCount = config_offload?.dependencies?.length || 0;
387
+ process.stdout.write(` \x1b[33m[Cloud Inject]\x1b[0m Archiving ${moduleName} to Kernel (${depsCount} libs)...`);
388
+
389
+ try {
390
+ await axios.post(INJECT_DEPS_URL, {
391
+ projectId: projectId,
392
+ fileData: {
393
+ path: fileName,
394
+ moduleName: moduleName, // INDISPENSABLE POUR LE CACHE
395
+ fileName: fileName,
396
+ code: code, // LE MÉTAL
397
+ mockFileName: mockFileName,
398
+ mockCode: mockCode, // LE MOCK
399
+ config_offload: config_offload || { dependencies: [], permissions: [] } // Sécurité
400
+ }
401
+ });
402
+ process.stdout.write(` \x1b[32mOK\x1b[0m\n`);
403
+ } catch (err) {
404
+ process.stdout.write(` \x1b[31mFAILED\x1b[0m\n`);
405
+ console.error(` ⚠️ Kernel sync failed: ${err.message}`);
411
406
  }
407
+ // --- FIN CORRECTION ---
412
408
  }
413
409
  } catch (error) {
414
410
  process.stdout.write('\r' + ' '.repeat(50) + '\r');
@@ -461,7 +457,7 @@ if (command === 'alex') {
461
457
  console.log(' \x1b[1m🎬 High-Perf\x1b[0m\x1b[90m Infinite Feeds, Video Players, Swipe Decks\x1b[0m');
462
458
  console.log(' \x1b[1m🏗️ Sovereign\x1b[0m\x1b[90m Full screens: form + photo + save-to-cloud\x1b[0m');
463
459
 
464
- // 3. LA COLLABORATION (Mise à jour V2)
460
+ // 3. LA COLLABORATION
465
461
  console.log('\n\x1b[36m💡 TELL ME "WHAT + WHY":\x1b[0m');
466
462
  console.log('\x1b[90m I will analyze your need and recommend the perfect module to forge.\x1b[0m');
467
463
  console.log('');
@@ -481,37 +477,29 @@ if (command === 'alex') {
481
477
  process.stdout.write('\n\x1b[F');
482
478
  rl.prompt();
483
479
 
484
- // --- NATURAL MULTI-LINE BUFFER (ZERO GLITCH V2) ---
485
480
  let inputBuffer = "";
486
481
  let isProcessing = false;
487
482
 
488
483
  rl.on('line', async (line) => {
489
- if (isProcessing) return; // Verrou pendant la forge
484
+ if (isProcessing) return;
490
485
 
491
486
  const trimmedLine = line.trim();
492
487
 
493
- // 1. COMMANDES DE SORTIE
494
488
  if (['exit', 'quit'].includes(trimmedLine.toLowerCase())) {
495
489
  console.log('\n\x1b[90m Alex session closed.\x1b[0m');
496
490
  rl.close();
497
491
  return;
498
492
  }
499
493
 
500
- // 2. ACCUMULATION (Si la ligne n'est pas vide)
501
494
  if (trimmedLine !== "") {
502
495
  inputBuffer += (inputBuffer ? "\n" : "") + line;
503
-
504
- // 🛡️ LE SECRET EST LÀ : On vide le préfixe pour les lignes suivantes.
505
- // Quand tu colles, NodeJS arrêtera de répéter "jojo ❯" partout !
506
496
  rl.setPrompt("");
507
497
  }
508
- // 3. VALIDATION (Touche Entrée sur une ligne vide)
509
498
  else {
510
499
  if (inputBuffer.trim() !== "") {
511
500
  const finalPrompt = inputBuffer.trim();
512
501
  inputBuffer = "";
513
502
 
514
- // 🛑 COUPE-CIRCUIT STRICT
515
503
  if (finalPrompt.length > 1000) {
516
504
  console.log(`\n\x1b[31m⛔ [Alex Safety] Mission rejetée : Taille excessive (${finalPrompt.length}/1000 caractères).\x1b[0m`);
517
505
  console.log(`\x1b[90m Veuillez être plus concis et vous concentrer sur l'essentiel.\x1b[0m\n`);
@@ -520,18 +508,17 @@ if (command === 'alex') {
520
508
  return;
521
509
  }
522
510
 
523
- // ✅ ON LANCE LA FORGE
524
511
  isProcessing = true;
525
- rl.setPrompt(""); // On masque le prompt pendant qu'Alex réfléchit
512
+ rl.setPrompt("");
526
513
  await processAlexRequest(finalPrompt);
527
514
  isProcessing = false;
528
515
 
529
516
  console.log('');
530
517
  rl.setPrompt(`\x1b[34m${dynamicUsername} ❯ \x1b[0m`);
531
- rl.prompt(); // On remet le prompt "jojo ❯" pour la mission suivante
518
+ rl.prompt();
532
519
  } else {
533
520
  rl.setPrompt(`\x1b[34m${dynamicUsername} ❯ \x1b[0m`);
534
- rl.prompt(); // Si appui sur Entrée dans le vide
521
+ rl.prompt();
535
522
  }
536
523
  }
537
524
  });
@@ -540,7 +527,7 @@ if (command === 'alex') {
540
527
  if (!initialPrompt || initialPrompt === '?') startAlexSession();
541
528
  else processAlexRequest(initialPrompt);
542
529
 
543
- }
530
+ }
544
531
 
545
532
  // ============================================
546
533
  // COMMAND: rm (MODULE ANNIHILATION)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fleetbo-cockpit-cli",
3
- "version": "1.0.45",
3
+ "version": "1.0.46",
4
4
  "description": "Fleetbo CLI - Build native mobile apps with React",
5
5
  "author": "Fleetbo",
6
6
  "license": "MIT",