fluxy-bot 0.5.36 → 0.5.38

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/bin/cli.js +78 -54
  2. package/package.json +1 -1
package/bin/cli.js CHANGED
@@ -1,7 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { spawn, execSync, spawnSync } from 'child_process';
4
- import readline from 'readline';
5
4
  import fs from 'fs';
6
5
  import path from 'path';
7
6
  import os from 'os';
@@ -81,16 +80,6 @@ WantedBy=multi-user.target
81
80
  `;
82
81
  }
83
82
 
84
- function askQuestion(query) {
85
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
86
- return new Promise((resolve) => {
87
- rl.question(query, (answer) => {
88
- rl.close();
89
- resolve(answer);
90
- });
91
- });
92
- }
93
-
94
83
  // ── UI helpers ──
95
84
 
96
85
  const c = {
@@ -215,16 +204,28 @@ function finalMessage(tunnelUrl, relayUrl) {
215
204
  ${c.pink}${c.bold}${link(relayUrl)}${c.reset}`);
216
205
  }
217
206
 
218
- console.log(`
207
+ if (os.platform() === 'linux') {
208
+ console.log(`
209
+ ${c.dim}─────────────────────────────────${c.reset}
210
+
211
+ ${c.bold}${c.white}Commands:${c.reset}
212
+ ${c.dim}Status${c.reset} ${c.pink}fluxy daemon status${c.reset}
213
+ ${c.dim}Logs${c.reset} ${c.pink}fluxy daemon logs${c.reset}
214
+ ${c.dim}Restart${c.reset} ${c.pink}fluxy daemon restart${c.reset}
215
+ ${c.dim}Stop${c.reset} ${c.pink}fluxy daemon stop${c.reset}
216
+ ${c.dim}Update${c.reset} ${c.pink}fluxy update${c.reset}
217
+ `);
218
+ } else {
219
+ console.log(`
219
220
  ${c.dim}─────────────────────────────────${c.reset}
220
221
 
221
222
  ${c.bold}${c.white}Commands:${c.reset}
222
223
  ${c.dim}Status${c.reset} ${c.pink}fluxy status${c.reset}
223
- ${c.dim}Update${c.reset} ${c.pink}fluxy update${c.reset}${os.platform() === 'linux' ? `
224
- ${c.dim}Daemon${c.reset} ${c.pink}fluxy daemon${c.reset}` : ''}
224
+ ${c.dim}Update${c.reset} ${c.pink}fluxy update${c.reset}
225
225
 
226
- ${c.dim}Press Ctrl+C to stop the bot${c.reset}
226
+ ${c.dim}Press Ctrl+C to stop${c.reset}
227
227
  `);
228
+ }
228
229
  }
229
230
 
230
231
  // ── Steps ──
@@ -387,6 +388,9 @@ async function init() {
387
388
 
388
389
  createConfig();
389
390
 
391
+ const isLinux = os.platform() === 'linux';
392
+ const hasSystemd = isLinux && (() => { try { execSync('systemctl --version', { stdio: 'ignore' }); return true; } catch { return false; } })();
393
+
390
394
  const steps = [
391
395
  'Creating config',
392
396
  'Installing cloudflared',
@@ -394,6 +398,7 @@ async function init() {
394
398
  'Connecting tunnel',
395
399
  'Verifying connection',
396
400
  'Preparing dashboard',
401
+ ...(hasSystemd ? ['Setting up auto-start daemon'] : []),
397
402
  ];
398
403
 
399
404
  const stepper = new Stepper(steps);
@@ -425,28 +430,32 @@ async function init() {
425
430
  await Promise.race([viteWarm, new Promise(r => setTimeout(r, 30_000))]);
426
431
  stepper.advance();
427
432
 
433
+ // Install systemd daemon on Linux
434
+ if (hasSystemd) {
435
+ child.removeAllListeners('exit');
436
+ child.kill('SIGTERM');
437
+ await new Promise((r) => setTimeout(r, 2000));
438
+ const nodePath = process.execPath;
439
+ const realHome = os.homedir();
440
+ const res = spawnSync(process.execPath, [process.argv[1], 'daemon', 'install'], {
441
+ stdio: 'pipe',
442
+ env: { ...process.env, FLUXY_NODE_PATH: nodePath, FLUXY_REAL_HOME: realHome },
443
+ });
444
+ stepper.advance();
445
+ stepper.finish();
446
+ finalMessage(tunnelUrl, relayUrl);
447
+ if (res.status === 0) {
448
+ console.log(` ${c.blue}✔${c.reset} Daemon installed — Fluxy will auto-start on boot.`);
449
+ } else {
450
+ console.log(` ${c.yellow}⚠${c.reset} Daemon install failed. Run ${c.pink}fluxy daemon install${c.reset} manually.`);
451
+ }
452
+ console.log('');
453
+ process.exit(res.status ?? 0);
454
+ }
455
+
428
456
  stepper.finish();
429
457
  finalMessage(tunnelUrl, relayUrl);
430
458
 
431
- // Offer daemon install on Linux
432
- if (os.platform() === 'linux' && process.stdin.isTTY) {
433
- try {
434
- const answer = await askQuestion(` ${c.bold}Install as a system daemon (auto-start on boot)?${c.reset} ${c.dim}[Y/n]${c.reset} `);
435
- if (!answer || answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes') {
436
- console.log(`\n ${c.dim}Stopping foreground server...${c.reset}`);
437
- child.kill('SIGTERM');
438
- await new Promise((r) => setTimeout(r, 2000));
439
- const nodePath = process.execPath;
440
- const realHome = os.homedir();
441
- const result = spawnSync(process.execPath, [process.argv[1], 'daemon', 'install'], {
442
- stdio: 'inherit',
443
- env: { ...process.env, FLUXY_NODE_PATH: nodePath, FLUXY_REAL_HOME: realHome },
444
- });
445
- process.exit(result.status ?? 0);
446
- }
447
- } catch {}
448
- }
449
-
450
459
  child.stdout.on('data', (d) => {
451
460
  process.stdout.write(` ${c.dim}${d.toString().trim()}${c.reset}\n`);
452
461
  });
@@ -462,9 +471,20 @@ async function start() {
462
471
  return init();
463
472
  }
464
473
 
474
+ const isLinux = os.platform() === 'linux';
475
+ const hasSystemd = isLinux && (() => { try { execSync('systemctl --version', { stdio: 'ignore' }); return true; } catch { return false; } })();
476
+ const needsDaemon = hasSystemd && !isServiceInstalled();
477
+
465
478
  banner();
466
479
 
467
- const steps = ['Loading config', 'Starting server', 'Connecting tunnel', 'Verifying connection', 'Preparing dashboard'];
480
+ const steps = [
481
+ 'Loading config',
482
+ 'Starting server',
483
+ 'Connecting tunnel',
484
+ 'Verifying connection',
485
+ 'Preparing dashboard',
486
+ ...(needsDaemon ? ['Setting up auto-start daemon'] : []),
487
+ ];
468
488
  const stepper = new Stepper(steps);
469
489
  stepper.start();
470
490
 
@@ -488,28 +508,32 @@ async function start() {
488
508
  await Promise.race([viteWarm, new Promise(r => setTimeout(r, 30_000))]);
489
509
  stepper.advance();
490
510
 
511
+ // Install systemd daemon on Linux if not already installed
512
+ if (needsDaemon) {
513
+ child.removeAllListeners('exit');
514
+ child.kill('SIGTERM');
515
+ await new Promise((r) => setTimeout(r, 2000));
516
+ const nodePath = process.execPath;
517
+ const realHome = os.homedir();
518
+ const res = spawnSync(process.execPath, [process.argv[1], 'daemon', 'install'], {
519
+ stdio: 'pipe',
520
+ env: { ...process.env, FLUXY_NODE_PATH: nodePath, FLUXY_REAL_HOME: realHome },
521
+ });
522
+ stepper.advance();
523
+ stepper.finish();
524
+ finalMessage(tunnelUrl, relayUrl);
525
+ if (res.status === 0) {
526
+ console.log(` ${c.blue}✔${c.reset} Daemon installed — Fluxy will auto-start on boot.`);
527
+ } else {
528
+ console.log(` ${c.yellow}⚠${c.reset} Daemon install failed. Run ${c.pink}fluxy daemon install${c.reset} manually.`);
529
+ }
530
+ console.log('');
531
+ process.exit(res.status ?? 0);
532
+ }
533
+
491
534
  stepper.finish();
492
535
  finalMessage(tunnelUrl, relayUrl);
493
536
 
494
- // Offer daemon install on Linux if not already installed
495
- if (os.platform() === 'linux' && !isServiceInstalled() && process.stdin.isTTY) {
496
- try {
497
- const answer = await askQuestion(` ${c.bold}Install as a system daemon (auto-start on boot)?${c.reset} ${c.dim}[Y/n]${c.reset} `);
498
- if (!answer || answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes') {
499
- console.log(`\n ${c.dim}Stopping foreground server...${c.reset}`);
500
- child.kill('SIGTERM');
501
- await new Promise((r) => setTimeout(r, 2000));
502
- const nodePath = process.execPath;
503
- const realHome = os.homedir();
504
- const result = spawnSync(process.execPath, [process.argv[1], 'daemon', 'install'], {
505
- stdio: 'inherit',
506
- env: { ...process.env, FLUXY_NODE_PATH: nodePath, FLUXY_REAL_HOME: realHome },
507
- });
508
- process.exit(result.status ?? 0);
509
- }
510
- } catch {}
511
- }
512
-
513
537
  child.stdout.on('data', (d) => {
514
538
  process.stdout.write(` ${c.dim}${d.toString().trim()}${c.reset}\n`);
515
539
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fluxy-bot",
3
- "version": "0.5.36",
3
+ "version": "0.5.38",
4
4
  "description": "Self-hosted, self-evolving AI agent with its own dashboard.",
5
5
  "type": "module",
6
6
  "license": "MIT",