fluxy-bot 0.3.27 → 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
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "fluxy-bot",
3
- "version": "0.3.27",
4
- "description": "Self-hosted AI bot run your own AI assistant from anywhere",
3
+ "version": "0.4.0",
4
+ "description": "Self-hosted, self-evolving AI agent with its own dashboard.",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "bin": {
@@ -20,7 +20,6 @@
20
20
  "tsconfig.json",
21
21
  "postcss.config.js",
22
22
  "components.json",
23
- "install.sh",
24
23
  "install.ps1"
25
24
  ],
26
25
  "keywords": [
package/scripts/install CHANGED
@@ -15,7 +15,9 @@ NODE_DIR="$TOOLS_DIR/node"
15
15
  BIN_DIR="$FLUXY_HOME/bin"
16
16
  USE_SYSTEM_NODE=false
17
17
 
18
- CYAN='\033[36m'
18
+ # Brand colors: #32A5F7 (blue) and #DB36A3 (pink) via 256-color approximation
19
+ BLUE='\033[38;2;50;165;247m'
20
+ PINK='\033[38;2;219;54;163m'
19
21
  GREEN='\033[32m'
20
22
  YELLOW='\033[33m'
21
23
  RED='\033[31m'
@@ -23,10 +25,14 @@ DIM='\033[2m'
23
25
  BOLD='\033[1m'
24
26
  RESET='\033[0m'
25
27
 
26
- printf "\n${CYAN}${BOLD} ╔═══════════════════════════════╗${RESET}\n"
27
- printf "${CYAN}${BOLD} ║ FLUXY ║${RESET}\n"
28
- printf "${CYAN}${BOLD} ╚═══════════════════════════════╝${RESET}\n"
29
- printf "${DIM} Self-hosted AI bot${RESET}\n\n"
28
+ printf "\n"
29
+ printf "${BLUE}${BOLD} ___ __ ${RESET}\n"
30
+ printf "${BLUE}${BOLD} / _/ / / __ __ __ __ __ ${RESET}\n"
31
+ printf "${PINK}${BOLD} / _/ / / / / / / \\ \\/ / / / ${RESET}\n"
32
+ printf "${PINK}${BOLD} /_/ /_/ \\_,_/ /_/\\_\\ /_/ ${RESET}\n"
33
+ printf "\n"
34
+ printf "${DIM} Self-hosted AI bot installer${RESET}\n"
35
+ printf "${DIM} ─────────────────────────────${RESET}\n\n"
30
36
 
31
37
  # ─── Detect platform ────────────────────────────────────────────────────────
32
38
 
@@ -85,7 +91,7 @@ install_node() {
85
91
  fi
86
92
  fi
87
93
 
88
- printf " ${CYAN}↓${RESET} Downloading Node.js v${NODE_VERSION}...\n"
94
+ printf " ${BLUE}↓${RESET} Downloading Node.js v${NODE_VERSION}...\n"
89
95
 
90
96
  NODE_URL="https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-${PLATFORM}-${NODEARCH}.tar.xz"
91
97
  TMPFILE=$(mktemp /tmp/node-XXXXXX.tar.xz)
@@ -128,9 +134,14 @@ install_fluxy() {
128
134
  NODE="$NODE_DIR/bin/node"
129
135
  fi
130
136
 
131
- printf " ${CYAN}↓${RESET} Installing fluxy...\n"
137
+ # Fetch version + tarball URL from npm registry
138
+ NPM_VERSION=$("$NPM" view fluxy-bot version 2>/dev/null || echo "")
139
+ if [ -n "$NPM_VERSION" ]; then
140
+ printf " ${DIM}Latest npm version: fluxy-bot@${NPM_VERSION}${RESET}\n"
141
+ fi
142
+
143
+ printf " ${BLUE}↓${RESET} Installing fluxy...\n"
132
144
 
133
- # Get tarball URL from npm registry
134
145
  TARBALL_URL=$("$NPM" view fluxy-bot dist.tarball 2>/dev/null)
135
146
  if [ -z "$TARBALL_URL" ]; then
136
147
  printf " ${RED}✗${RESET} Failed to fetch package info from npm\n"
@@ -154,26 +165,42 @@ install_fluxy() {
154
165
  exit 1
155
166
  fi
156
167
 
157
- # Copy source files to ~/.fluxy/ (preserves existing config.json, memory.db, etc.)
158
- cp -r "$EXTRACTED"/* "$FLUXY_HOME"/
159
- cp -r "$EXTRACTED"/.[!.]* "$FLUXY_HOME"/ 2>/dev/null || true
160
- rm -rf "$TMPDIR"
168
+ # Copy code directories (always safe to overwrite)
169
+ for dir in bin supervisor worker shared scripts; do
170
+ [ -d "$EXTRACTED/$dir" ] && cp -r "$EXTRACTED/$dir" "$FLUXY_HOME/"
171
+ done
161
172
 
162
- # Install dependencies inside ~/.fluxy/
163
- (cd "$FLUXY_HOME" && "$NPM" install --omit=dev 2>/dev/null)
173
+ # Copy workspace template only on first install (preserves user files)
174
+ if [ ! -d "$FLUXY_HOME/workspace" ]; then
175
+ [ -d "$EXTRACTED/workspace" ] && cp -r "$EXTRACTED/workspace" "$FLUXY_HOME/"
176
+ fi
164
177
 
165
- # Build chat interface if not pre-built in the tarball
166
- if [ -d "$FLUXY_HOME/dist-fluxy" ] && [ -f "$FLUXY_HOME/dist-fluxy/onboard.html" ]; then
178
+ # Copy code files (never touches config.json, memory.db, etc.)
179
+ for f in package.json vite.config.ts vite.fluxy.config.ts tsconfig.json postcss.config.js components.json; do
180
+ [ -f "$EXTRACTED/$f" ] && cp "$EXTRACTED/$f" "$FLUXY_HOME/"
181
+ done
182
+
183
+ # Copy pre-built UI from tarball, or build from source
184
+ if [ -d "$EXTRACTED/dist-fluxy" ]; then
185
+ rm -rf "$FLUXY_HOME/dist-fluxy"
186
+ cp -r "$EXTRACTED/dist-fluxy" "$FLUXY_HOME/"
167
187
  printf " ${GREEN}✔${RESET} Chat interface ready\n"
168
- else
169
- printf " ${CYAN}↓${RESET} Building chat interface...\n"
188
+ elif [ ! -f "$FLUXY_HOME/dist-fluxy/onboard.html" ]; then
189
+ printf " ${BLUE}↓${RESET} Building chat interface...\n"
170
190
  if (cd "$FLUXY_HOME" && "$NPM" run build:fluxy 2>/dev/null); then
171
191
  printf " ${GREEN}✔${RESET} Chat interface built\n"
172
192
  else
173
193
  printf " ${YELLOW}!${RESET} Chat build skipped — will build on first start\n"
174
194
  fi
195
+ else
196
+ printf " ${GREEN}✔${RESET} Chat interface ready\n"
175
197
  fi
176
198
 
199
+ rm -rf "$TMPDIR"
200
+
201
+ # Install dependencies inside ~/.fluxy/
202
+ (cd "$FLUXY_HOME" && "$NPM" install --omit=dev 2>/dev/null)
203
+
177
204
  # Verify
178
205
  if [ ! -f "$FLUXY_HOME/bin/cli.js" ]; then
179
206
  printf " ${RED}✗${RESET} Installation failed\n"
@@ -270,10 +297,18 @@ install_fluxy
270
297
  create_wrapper
271
298
  setup_path
272
299
 
273
- printf "\n ${GREEN}${BOLD}✔ Fluxy is ready!${RESET}\n\n"
274
- printf " Get started:\n\n"
275
- printf " ${CYAN}fluxy init${RESET} Set up your bot\n"
276
- printf " ${CYAN}fluxy start${RESET} Start your bot\n"
277
- printf " ${CYAN}fluxy status${RESET} Check if it's running\n\n"
278
- printf " ${DIM}Run ${RESET}${CYAN}fluxy init${RESET}${DIM} to begin.${RESET}\n"
279
- printf " ${DIM}(Open a new terminal if 'fluxy' isn't found yet)${RESET}\n\n"
300
+ printf "\n"
301
+ printf " ${GREEN}${BOLD}✔ Fluxy is ready!${RESET}\n"
302
+ printf "\n"
303
+ printf " ${DIM}─────────────────────────────${RESET}\n"
304
+ printf " ${BOLD}Get started:${RESET}\n"
305
+ printf "\n"
306
+ printf " ${BLUE}fluxy init${RESET} Set up your bot\n"
307
+ printf " ${BLUE}fluxy start${RESET} Start your bot\n"
308
+ printf " ${BLUE}fluxy status${RESET} Check if it's running\n"
309
+ printf "\n"
310
+ printf " ${PINK}>${RESET} Run ${BLUE}fluxy init${RESET} to begin.\n"
311
+ printf " ${DIM}(Open a new terminal if 'fluxy' isn't found yet)${RESET}\n"
312
+ printf "\n"
313
+ printf " ${DIM}https://fluxy.bot${RESET}\n"
314
+ printf "\n"
@@ -14,11 +14,33 @@ $NODE_DIR = Join-Path $TOOLS_DIR "node"
14
14
  $BIN_DIR = Join-Path $FLUXY_HOME "bin"
15
15
  $USE_SYSTEM_NODE = $false
16
16
 
17
+ # Ensure UTF-8 output for proper rendering
18
+ [Console]::OutputEncoding = [System.Text.Encoding]::UTF8
19
+
20
+ # Brand colors via ANSI escape sequences: #32A5F7 (blue) and #DB36A3 (pink)
21
+ $BLUE = "`e[38;2;50;165;247m"
22
+ $PINK = "`e[38;2;219;54;163m"
23
+ $BOLD = "`e[1m"
24
+ $RSET = "`e[0m"
25
+
26
+ # Use ANSI sequences for consistent rendering; fallback to plain if no VT support
27
+ $vtSupported = $null -ne $env:WT_SESSION -or $PSVersionTable.PSVersion.Major -ge 7 -or $host.UI.SupportsVirtualTerminal
28
+
17
29
  Write-Host ""
18
- Write-Host " ╔═══════════════════════════════╗" -ForegroundColor Cyan
19
- Write-Host " ║ FLUXY ║" -ForegroundColor Cyan
20
- Write-Host " ╚═══════════════════════════════╝" -ForegroundColor Cyan
21
- Write-Host " Self-hosted AI bot" -ForegroundColor DarkGray
30
+ if ($vtSupported) {
31
+ Write-Host "${BLUE}${BOLD} ___ __ ${RSET}"
32
+ Write-Host "${BLUE}${BOLD} / _/ / / __ __ __ __ __ ${RSET}"
33
+ Write-Host "${PINK}${BOLD} / _/ / / / / / / \ \/ / / / ${RSET}"
34
+ Write-Host "${PINK}${BOLD} /_/ /_/ \_,_/ /_/\_\ /_/ ${RSET}"
35
+ } else {
36
+ Write-Host " ___ __ " -ForegroundColor Cyan
37
+ Write-Host " / _/ / / __ __ __ __ __ " -ForegroundColor Cyan
38
+ Write-Host " / _/ / / / / / / \ \/ / / / " -ForegroundColor Magenta
39
+ Write-Host " /_/ /_/ \_,_/ /_/\_\ /_/ " -ForegroundColor Magenta
40
+ }
41
+ Write-Host ""
42
+ Write-Host " Self-hosted AI bot installer" -ForegroundColor DarkGray
43
+ Write-Host " -----------------------------" -ForegroundColor DarkGray
22
44
  Write-Host ""
23
45
 
24
46
  # ─── Detect platform ────────────────────────────────────────────────────────
@@ -117,9 +139,15 @@ function Install-Fluxy {
117
139
  $NODE_BIN = Join-Path $NODE_DIR "node.exe"
118
140
  }
119
141
 
142
+ # Fetch version + tarball URL from npm registry
143
+ $npmVersion = ""
144
+ try { $npmVersion = (& $NPM view fluxy-bot version 2>$null).Trim() } catch {}
145
+ if ($npmVersion) {
146
+ Write-Host " Latest npm version: fluxy-bot@${npmVersion}" -ForegroundColor DarkGray
147
+ }
148
+
120
149
  Write-Host " ↓ Installing fluxy..." -ForegroundColor Cyan
121
150
 
122
- # Get tarball URL from npm registry
123
151
  $tarballUrl = (& $NPM view fluxy-bot dist.tarball 2>$null).Trim()
124
152
  if (-not $tarballUrl) {
125
153
  Write-Host " ✗ Failed to fetch package info from npm" -ForegroundColor Red
@@ -142,10 +170,52 @@ function Install-Fluxy {
142
170
  exit 1
143
171
  }
144
172
 
145
- # Copy source files to ~/.fluxy/ (preserves existing config.json, memory.db, etc.)
146
173
  New-Item -ItemType Directory -Path $FLUXY_HOME -Force | Out-Null
147
- Get-ChildItem -Path $extracted -Force | ForEach-Object {
148
- Copy-Item -Path $_.FullName -Destination $FLUXY_HOME -Recurse -Force
174
+
175
+ # Copy code directories (always safe to overwrite)
176
+ foreach ($dir in @("bin", "supervisor", "worker", "shared", "scripts")) {
177
+ $src = Join-Path $extracted $dir
178
+ if (Test-Path $src) {
179
+ Copy-Item -Path $src -Destination $FLUXY_HOME -Recurse -Force
180
+ }
181
+ }
182
+
183
+ # Copy workspace template only on first install (preserves user files)
184
+ $wsDst = Join-Path $FLUXY_HOME "workspace"
185
+ if (-not (Test-Path $wsDst)) {
186
+ $wsSrc = Join-Path $extracted "workspace"
187
+ if (Test-Path $wsSrc) {
188
+ Copy-Item -Path $wsSrc -Destination $FLUXY_HOME -Recurse
189
+ }
190
+ }
191
+
192
+ # Copy code files (never touches config.json, memory.db, etc.)
193
+ foreach ($file in @("package.json", "vite.config.ts", "vite.fluxy.config.ts", "tsconfig.json", "postcss.config.js", "components.json")) {
194
+ $src = Join-Path $extracted $file
195
+ if (Test-Path $src) {
196
+ Copy-Item -Path $src -Destination (Join-Path $FLUXY_HOME $file) -Force
197
+ }
198
+ }
199
+
200
+ # Copy pre-built UI from tarball, or build from source
201
+ $distSrc = Join-Path $extracted "dist-fluxy"
202
+ $distDst = Join-Path $FLUXY_HOME "dist-fluxy"
203
+ if (Test-Path $distSrc) {
204
+ if (Test-Path $distDst) { Remove-Item $distDst -Recurse -Force }
205
+ Copy-Item -Path $distSrc -Destination $distDst -Recurse
206
+ Write-Host " ✔ Chat interface ready" -ForegroundColor Green
207
+ } elseif (-not (Test-Path (Join-Path $distDst "onboard.html"))) {
208
+ Write-Host " ↓ Building chat interface..." -ForegroundColor Cyan
209
+ Push-Location $FLUXY_HOME
210
+ try {
211
+ & $NPM run build:fluxy 2>$null
212
+ Write-Host " ✔ Chat interface built" -ForegroundColor Green
213
+ } catch {
214
+ Write-Host " ! Chat build failed — will build on first start" -ForegroundColor Yellow
215
+ }
216
+ Pop-Location
217
+ } else {
218
+ Write-Host " ✔ Chat interface ready" -ForegroundColor Green
149
219
  }
150
220
  } finally {
151
221
  Remove-Item $tmpDir -Recurse -Force -ErrorAction SilentlyContinue
@@ -156,21 +226,6 @@ function Install-Fluxy {
156
226
  try {
157
227
  & $NPM install --omit=dev 2>$null
158
228
  } catch {}
159
-
160
- # Build fluxy chat + onboard (served as static files)
161
- $distFluxy = Join-Path $FLUXY_HOME "dist-fluxy"
162
- $onboardHtml = Join-Path $distFluxy "onboard.html"
163
- if ((Test-Path $distFluxy) -and (Test-Path $onboardHtml)) {
164
- Write-Host " ✔ Chat interface (pre-built)" -ForegroundColor Green
165
- } else {
166
- Write-Host " ↓ Building chat interface..." -ForegroundColor Cyan
167
- try {
168
- & $NPM run build:fluxy 2>$null
169
- Write-Host " ✔ Chat interface built" -ForegroundColor Green
170
- } catch {
171
- Write-Host " ! Chat interface build failed — it will be built on first start" -ForegroundColor Yellow
172
- }
173
- }
174
229
  Pop-Location
175
230
 
176
231
  # Verify
@@ -240,14 +295,18 @@ Setup-Path
240
295
  Write-Host ""
241
296
  Write-Host " ✔ Fluxy is ready!" -ForegroundColor Green
242
297
  Write-Host ""
243
- Write-Host " Get started:"
298
+ Write-Host " -----------------------------" -ForegroundColor DarkGray
299
+ Write-Host " Get started:" -NoNewline; Write-Host ""
244
300
  Write-Host ""
245
301
  Write-Host " fluxy init " -ForegroundColor Cyan -NoNewline; Write-Host "Set up your bot"
246
302
  Write-Host " fluxy start " -ForegroundColor Cyan -NoNewline; Write-Host "Start your bot"
247
303
  Write-Host " fluxy status " -ForegroundColor Cyan -NoNewline; Write-Host "Check if it's running"
248
304
  Write-Host ""
249
- Write-Host " Run " -ForegroundColor DarkGray -NoNewline
305
+ Write-Host " > " -ForegroundColor Magenta -NoNewline
306
+ Write-Host "Run " -NoNewline
250
307
  Write-Host "fluxy init" -ForegroundColor Cyan -NoNewline
251
- Write-Host " to begin." -ForegroundColor DarkGray
308
+ Write-Host " to begin."
252
309
  Write-Host " (Open a new terminal if 'fluxy' isn't found yet)" -ForegroundColor DarkGray
253
310
  Write-Host ""
311
+ Write-Host " https://fluxy.bot" -ForegroundColor DarkGray
312
+ Write-Host ""
@@ -15,7 +15,9 @@ NODE_DIR="$TOOLS_DIR/node"
15
15
  BIN_DIR="$FLUXY_HOME/bin"
16
16
  USE_SYSTEM_NODE=false
17
17
 
18
- CYAN='\033[36m'
18
+ # Brand colors: #32A5F7 (blue) and #DB36A3 (pink) via 256-color approximation
19
+ BLUE='\033[38;2;50;165;247m'
20
+ PINK='\033[38;2;219;54;163m'
19
21
  GREEN='\033[32m'
20
22
  YELLOW='\033[33m'
21
23
  RED='\033[31m'
@@ -23,10 +25,14 @@ DIM='\033[2m'
23
25
  BOLD='\033[1m'
24
26
  RESET='\033[0m'
25
27
 
26
- printf "\n${CYAN}${BOLD} ╔═══════════════════════════════╗${RESET}\n"
27
- printf "${CYAN}${BOLD} ║ FLUXY ║${RESET}\n"
28
- printf "${CYAN}${BOLD} ╚═══════════════════════════════╝${RESET}\n"
29
- printf "${DIM} Self-hosted AI bot${RESET}\n\n"
28
+ printf "\n"
29
+ printf "${BLUE}${BOLD} ___ __ ${RESET}\n"
30
+ printf "${BLUE}${BOLD} / _/ / / __ __ __ __ __ ${RESET}\n"
31
+ printf "${PINK}${BOLD} / _/ / / / / / / \\ \\/ / / / ${RESET}\n"
32
+ printf "${PINK}${BOLD} /_/ /_/ \\_,_/ /_/\\_\\ /_/ ${RESET}\n"
33
+ printf "\n"
34
+ printf "${DIM} Self-hosted AI bot installer${RESET}\n"
35
+ printf "${DIM} ─────────────────────────────${RESET}\n\n"
30
36
 
31
37
  # ─── Detect platform ────────────────────────────────────────────────────────
32
38
 
@@ -85,7 +91,7 @@ install_node() {
85
91
  fi
86
92
  fi
87
93
 
88
- printf " ${CYAN}↓${RESET} Downloading Node.js v${NODE_VERSION}...\n"
94
+ printf " ${BLUE}↓${RESET} Downloading Node.js v${NODE_VERSION}...\n"
89
95
 
90
96
  NODE_URL="https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-${PLATFORM}-${NODEARCH}.tar.xz"
91
97
  TMPFILE=$(mktemp /tmp/node-XXXXXX.tar.xz)
@@ -128,9 +134,14 @@ install_fluxy() {
128
134
  NODE="$NODE_DIR/bin/node"
129
135
  fi
130
136
 
131
- printf " ${CYAN}↓${RESET} Installing fluxy...\n"
137
+ # Fetch version + tarball URL from npm registry
138
+ NPM_VERSION=$("$NPM" view fluxy-bot version 2>/dev/null || echo "")
139
+ if [ -n "$NPM_VERSION" ]; then
140
+ printf " ${DIM}Latest npm version: fluxy-bot@${NPM_VERSION}${RESET}\n"
141
+ fi
142
+
143
+ printf " ${BLUE}↓${RESET} Installing fluxy...\n"
132
144
 
133
- # Get tarball URL from npm registry
134
145
  TARBALL_URL=$("$NPM" view fluxy-bot dist.tarball 2>/dev/null)
135
146
  if [ -z "$TARBALL_URL" ]; then
136
147
  printf " ${RED}✗${RESET} Failed to fetch package info from npm\n"
@@ -154,26 +165,42 @@ install_fluxy() {
154
165
  exit 1
155
166
  fi
156
167
 
157
- # Copy source files to ~/.fluxy/ (preserves existing config.json, memory.db, etc.)
158
- cp -r "$EXTRACTED"/* "$FLUXY_HOME"/
159
- cp -r "$EXTRACTED"/.[!.]* "$FLUXY_HOME"/ 2>/dev/null || true
160
- rm -rf "$TMPDIR"
168
+ # Copy code directories (always safe to overwrite)
169
+ for dir in bin supervisor worker shared scripts; do
170
+ [ -d "$EXTRACTED/$dir" ] && cp -r "$EXTRACTED/$dir" "$FLUXY_HOME/"
171
+ done
161
172
 
162
- # Install dependencies inside ~/.fluxy/
163
- (cd "$FLUXY_HOME" && "$NPM" install --omit=dev 2>/dev/null)
173
+ # Copy workspace template only on first install (preserves user files)
174
+ if [ ! -d "$FLUXY_HOME/workspace" ]; then
175
+ [ -d "$EXTRACTED/workspace" ] && cp -r "$EXTRACTED/workspace" "$FLUXY_HOME/"
176
+ fi
164
177
 
165
- # Build chat interface if not pre-built in the tarball
166
- if [ -d "$FLUXY_HOME/dist-fluxy" ] && [ -f "$FLUXY_HOME/dist-fluxy/onboard.html" ]; then
178
+ # Copy code files (never touches config.json, memory.db, etc.)
179
+ for f in package.json vite.config.ts vite.fluxy.config.ts tsconfig.json postcss.config.js components.json; do
180
+ [ -f "$EXTRACTED/$f" ] && cp "$EXTRACTED/$f" "$FLUXY_HOME/"
181
+ done
182
+
183
+ # Copy pre-built UI from tarball, or build from source
184
+ if [ -d "$EXTRACTED/dist-fluxy" ]; then
185
+ rm -rf "$FLUXY_HOME/dist-fluxy"
186
+ cp -r "$EXTRACTED/dist-fluxy" "$FLUXY_HOME/"
167
187
  printf " ${GREEN}✔${RESET} Chat interface ready\n"
168
- else
169
- printf " ${CYAN}↓${RESET} Building chat interface...\n"
188
+ elif [ ! -f "$FLUXY_HOME/dist-fluxy/onboard.html" ]; then
189
+ printf " ${BLUE}↓${RESET} Building chat interface...\n"
170
190
  if (cd "$FLUXY_HOME" && "$NPM" run build:fluxy 2>/dev/null); then
171
191
  printf " ${GREEN}✔${RESET} Chat interface built\n"
172
192
  else
173
193
  printf " ${YELLOW}!${RESET} Chat build skipped — will build on first start\n"
174
194
  fi
195
+ else
196
+ printf " ${GREEN}✔${RESET} Chat interface ready\n"
175
197
  fi
176
198
 
199
+ rm -rf "$TMPDIR"
200
+
201
+ # Install dependencies inside ~/.fluxy/
202
+ (cd "$FLUXY_HOME" && "$NPM" install --omit=dev 2>/dev/null)
203
+
177
204
  # Verify
178
205
  if [ ! -f "$FLUXY_HOME/bin/cli.js" ]; then
179
206
  printf " ${RED}✗${RESET} Installation failed\n"
@@ -270,10 +297,18 @@ install_fluxy
270
297
  create_wrapper
271
298
  setup_path
272
299
 
273
- printf "\n ${GREEN}${BOLD}✔ Fluxy is ready!${RESET}\n\n"
274
- printf " Get started:\n\n"
275
- printf " ${CYAN}fluxy init${RESET} Set up your bot\n"
276
- printf " ${CYAN}fluxy start${RESET} Start your bot\n"
277
- printf " ${CYAN}fluxy status${RESET} Check if it's running\n\n"
278
- printf " ${DIM}Run ${RESET}${CYAN}fluxy init${RESET}${DIM} to begin.${RESET}\n"
279
- printf " ${DIM}(Open a new terminal if 'fluxy' isn't found yet)${RESET}\n\n"
300
+ printf "\n"
301
+ printf " ${GREEN}${BOLD}✔ Fluxy is ready!${RESET}\n"
302
+ printf "\n"
303
+ printf " ${DIM}─────────────────────────────${RESET}\n"
304
+ printf " ${BOLD}Get started:${RESET}\n"
305
+ printf "\n"
306
+ printf " ${BLUE}fluxy init${RESET} Set up your bot\n"
307
+ printf " ${BLUE}fluxy start${RESET} Start your bot\n"
308
+ printf " ${BLUE}fluxy status${RESET} Check if it's running\n"
309
+ printf "\n"
310
+ printf " ${PINK}>${RESET} Run ${BLUE}fluxy init${RESET} to begin.\n"
311
+ printf " ${DIM}(Open a new terminal if 'fluxy' isn't found yet)${RESET}\n"
312
+ printf "\n"
313
+ printf " ${DIM}https://fluxy.bot${RESET}\n"
314
+ printf "\n"
@@ -28,23 +28,30 @@ if (fs.existsSync(path.join(PKG_ROOT, '.git'))) {
28
28
 
29
29
  fs.mkdirSync(FLUXY_HOME, { recursive: true });
30
30
 
31
- const DIRS_TO_COPY = [
32
- 'bin', 'supervisor', 'worker', 'shared', 'workspace', 'scripts',
33
- ];
31
+ // Code directories — always overwrite (these are application code)
32
+ const CODE_DIRS = ['bin', 'supervisor', 'worker', 'shared', 'scripts'];
34
33
 
35
- const FILES_TO_COPY = [
34
+ // Code files — always overwrite
35
+ const CODE_FILES = [
36
36
  'package.json', 'vite.config.ts', 'vite.fluxy.config.ts',
37
37
  'tsconfig.json', 'postcss.config.js', 'components.json',
38
38
  ];
39
39
 
40
- for (const dir of DIRS_TO_COPY) {
40
+ for (const dir of CODE_DIRS) {
41
41
  const src = path.join(PKG_ROOT, dir);
42
42
  if (!fs.existsSync(src)) continue;
43
43
  const dst = path.join(FLUXY_HOME, dir);
44
44
  fs.cpSync(src, dst, { recursive: true, force: true });
45
45
  }
46
46
 
47
- for (const file of FILES_TO_COPY) {
47
+ // Workspace template — only on first install (preserves user files, uploads, etc.)
48
+ const wsSrc = path.join(PKG_ROOT, 'workspace');
49
+ const wsDst = path.join(FLUXY_HOME, 'workspace');
50
+ if (fs.existsSync(wsSrc) && !fs.existsSync(wsDst)) {
51
+ fs.cpSync(wsSrc, wsDst, { recursive: true });
52
+ }
53
+
54
+ for (const file of CODE_FILES) {
48
55
  const src = path.join(PKG_ROOT, file);
49
56
  if (!fs.existsSync(src)) continue;
50
57
  fs.copyFileSync(src, path.join(FLUXY_HOME, file));
@@ -61,10 +68,15 @@ try {
61
68
  // Non-fatal: deps may already exist from a previous install
62
69
  }
63
70
 
64
- // ── Build fluxy chat + onboard (served as static files) ──
71
+ // ── Copy pre-built UI if available, otherwise build ──
65
72
 
66
- const distFluxy = path.join(FLUXY_HOME, 'dist-fluxy', 'onboard.html');
67
- if (!fs.existsSync(distFluxy)) {
73
+ const distSrc = path.join(PKG_ROOT, 'dist-fluxy');
74
+ const distDst = path.join(FLUXY_HOME, 'dist-fluxy');
75
+ if (fs.existsSync(distSrc)) {
76
+ // Always use the pre-built UI from the package (handles updates)
77
+ if (fs.existsSync(distDst)) fs.rmSync(distDst, { recursive: true });
78
+ fs.cpSync(distSrc, distDst, { recursive: true });
79
+ } else if (!fs.existsSync(path.join(distDst, 'onboard.html'))) {
68
80
  try {
69
81
  execSync('npm run build:fluxy', {
70
82
  cwd: FLUXY_HOME,