fluxy-bot 0.3.26 → 0.4.0

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.
package/bin/cli.js CHANGED
@@ -30,6 +30,8 @@ const c = {
30
30
  yellow: '\x1b[33m',
31
31
  red: '\x1b[31m',
32
32
  white: '\x1b[97m',
33
+ blue: '\x1b[38;2;50;165;247m',
34
+ pink: '\x1b[38;2;219;54;163m',
33
35
  };
34
36
 
35
37
  const SPINNER = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
@@ -100,10 +102,11 @@ class Stepper {
100
102
 
101
103
  function banner() {
102
104
  console.log(`
103
- ${c.cyan}${c.bold}╔═══════════════════════════════╗
104
- ║ FLUXY v${pkg.version.padEnd(13)}
105
- ╚═══════════════════════════════╝${c.reset}
106
- ${c.dim}Self-hosted AI bot${c.reset}`);
105
+ ${c.blue}${c.bold} ___ __ ${c.reset}
106
+ ${c.blue}${c.bold} / _/ / / __ __ __ __ __ ${c.reset}
107
+ ${c.pink}${c.bold} / _/ / / / / / / \\ \\/ / / / ${c.reset}
108
+ ${c.pink}${c.bold} /_/ /_/ \\_,_/ /_/\\_\\ /_/ ${c.reset}
109
+ ${c.dim}v${pkg.version} · Self-hosted AI bot${c.reset}`);
107
110
  }
108
111
 
109
112
  function finalMessage(tunnelUrl, relayUrl) {
@@ -112,13 +115,13 @@ function finalMessage(tunnelUrl, relayUrl) {
112
115
 
113
116
  ${c.bold}${c.white}Open your dashboard to finish setup:${c.reset}
114
117
 
115
- ${c.cyan}${c.bold}${tunnelUrl}${c.reset}`);
118
+ ${c.blue}${c.bold}${tunnelUrl}${c.reset}`);
116
119
 
117
120
  if (relayUrl) {
118
121
  console.log(`
119
122
  ${c.bold}${c.white}Your permanent URL:${c.reset}
120
123
 
121
- ${c.cyan}${c.bold}${relayUrl}${c.reset}`);
124
+ ${c.blue}${c.bold}${relayUrl}${c.reset}`);
122
125
  }
123
126
 
124
127
  console.log(`
@@ -396,12 +399,128 @@ async function status() {
396
399
  }
397
400
  }
398
401
 
402
+ async function update() {
403
+ banner();
404
+
405
+ const currentVersion = pkg.version;
406
+ console.log(`\n ${c.dim}Current version: v${currentVersion}${c.reset}`);
407
+ console.log(` ${c.blue}⠋${c.reset} Checking for updates...\n`);
408
+
409
+ // Fetch latest package info from npm registry
410
+ let latest;
411
+ try {
412
+ const res = await fetch('https://registry.npmjs.org/fluxy-bot/latest');
413
+ if (!res.ok) throw new Error();
414
+ latest = await res.json();
415
+ } catch {
416
+ console.log(` ${c.red}✗${c.reset} Failed to check for updates\n`);
417
+ process.exit(1);
418
+ }
419
+
420
+ if (currentVersion === latest.version) {
421
+ console.log(` ${c.green}✔${c.reset} Already up to date (v${currentVersion})\n`);
422
+ return;
423
+ }
424
+
425
+ console.log(` ${c.dim}v${currentVersion} → v${latest.version}${c.reset}\n`);
426
+
427
+ const steps = [
428
+ 'Downloading update',
429
+ 'Updating files',
430
+ 'Installing dependencies',
431
+ 'Building interface',
432
+ ];
433
+
434
+ const stepper = new Stepper(steps);
435
+ stepper.start();
436
+
437
+ // Download tarball
438
+ const tarballUrl = latest.dist.tarball;
439
+ const tmpDir = path.join(os.tmpdir(), `fluxy-update-${Date.now()}`);
440
+ fs.mkdirSync(tmpDir, { recursive: true });
441
+ const tarball = path.join(tmpDir, 'fluxy.tgz');
442
+
443
+ try {
444
+ const res = await fetch(tarballUrl);
445
+ if (!res.ok) throw new Error();
446
+ const buf = Buffer.from(await res.arrayBuffer());
447
+ fs.writeFileSync(tarball, buf);
448
+ execSync(`tar xzf "${tarball}" -C "${tmpDir}"`, { stdio: 'ignore' });
449
+ } catch {
450
+ stepper.finish();
451
+ console.log(`\n ${c.red}✗${c.reset} Download failed\n`);
452
+ fs.rmSync(tmpDir, { recursive: true, force: true });
453
+ process.exit(1);
454
+ }
455
+ stepper.advance();
456
+
457
+ const extracted = path.join(tmpDir, 'package');
458
+
459
+ // Update code directories (preserve workspace/ user data)
460
+ for (const dir of ['bin', 'supervisor', 'worker', 'shared', 'scripts']) {
461
+ const src = path.join(extracted, dir);
462
+ if (fs.existsSync(src)) {
463
+ fs.cpSync(src, path.join(DATA_DIR, dir), { recursive: true, force: true });
464
+ }
465
+ }
466
+
467
+ // Copy workspace template only if it doesn't exist yet
468
+ if (!fs.existsSync(path.join(DATA_DIR, 'workspace'))) {
469
+ const wsSrc = path.join(extracted, 'workspace');
470
+ if (fs.existsSync(wsSrc)) {
471
+ fs.cpSync(wsSrc, path.join(DATA_DIR, 'workspace'), { recursive: true });
472
+ }
473
+ }
474
+
475
+ // Update code files (never touches config.json, memory.db, etc.)
476
+ for (const file of ['package.json', 'vite.config.ts', 'vite.fluxy.config.ts', 'tsconfig.json', 'postcss.config.js', 'components.json']) {
477
+ const src = path.join(extracted, file);
478
+ if (fs.existsSync(src)) {
479
+ fs.copyFileSync(src, path.join(DATA_DIR, file));
480
+ }
481
+ }
482
+
483
+ // Update pre-built UI from tarball
484
+ const distSrc = path.join(extracted, 'dist-fluxy');
485
+ const distDst = path.join(DATA_DIR, 'dist-fluxy');
486
+ if (fs.existsSync(distSrc)) {
487
+ if (fs.existsSync(distDst)) fs.rmSync(distDst, { recursive: true });
488
+ fs.cpSync(distSrc, distDst, { recursive: true });
489
+ }
490
+
491
+ stepper.advance();
492
+
493
+ // Install dependencies
494
+ try {
495
+ execSync('npm install --omit=dev', { cwd: DATA_DIR, stdio: 'ignore' });
496
+ } catch {}
497
+ stepper.advance();
498
+
499
+ // Rebuild UI if not in tarball
500
+ if (!fs.existsSync(path.join(distDst, 'onboard.html'))) {
501
+ try {
502
+ if (fs.existsSync(distDst)) fs.rmSync(distDst, { recursive: true });
503
+ execSync('npm run build:fluxy', { cwd: DATA_DIR, stdio: 'ignore' });
504
+ } catch {}
505
+ }
506
+ stepper.advance();
507
+
508
+ // Clean up
509
+ fs.rmSync(tmpDir, { recursive: true, force: true });
510
+
511
+ stepper.finish();
512
+
513
+ console.log(`\n ${c.green}${c.bold}✔ Updated to v${latest.version}${c.reset}\n`);
514
+ console.log(` ${c.dim}Run ${c.reset}${c.cyan}fluxy start${c.reset}${c.dim} to launch.${c.reset}\n`);
515
+ }
516
+
399
517
  // ── Route ──
400
518
 
401
519
  switch (command) {
402
520
  case 'init': init(); break;
403
521
  case 'start': start(); break;
404
522
  case 'status': status(); break;
523
+ case 'update': update(); break;
405
524
  default:
406
525
  fs.existsSync(CONFIG_PATH) ? start() : init();
407
526
  }