fluxy-bot 0.2.24 → 0.2.26
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 +15 -20
- package/package.json +1 -1
- package/scripts/install.sh +6 -1
- package/scripts/postinstall.js +11 -0
- package/supervisor/index.ts +51 -24
- package/supervisor/vite-dev.ts +16 -33
- package/vite.config.ts +11 -0
- package/vite.fluxy.config.ts +14 -0
package/bin/cli.js
CHANGED
|
@@ -219,6 +219,10 @@ function bootServer() {
|
|
|
219
219
|
let resolved = false;
|
|
220
220
|
let stderrBuf = '';
|
|
221
221
|
|
|
222
|
+
// Vite warmup tracking
|
|
223
|
+
let viteWarmResolve;
|
|
224
|
+
const viteWarm = new Promise((r) => { viteWarmResolve = r; });
|
|
225
|
+
|
|
222
226
|
const doResolve = () => {
|
|
223
227
|
if (resolved) return;
|
|
224
228
|
resolved = true;
|
|
@@ -227,6 +231,7 @@ function bootServer() {
|
|
|
227
231
|
child,
|
|
228
232
|
tunnelUrl: tunnelUrl || `http://localhost:${config.port}`,
|
|
229
233
|
relayUrl: relayUrl || config.relay?.url || null,
|
|
234
|
+
viteWarm,
|
|
230
235
|
});
|
|
231
236
|
};
|
|
232
237
|
|
|
@@ -239,6 +244,10 @@ function bootServer() {
|
|
|
239
244
|
const relayMatch = text.match(/__RELAY_URL__=(\S+)/);
|
|
240
245
|
if (relayMatch) relayUrl = relayMatch[1];
|
|
241
246
|
|
|
247
|
+
if (text.includes('__VITE_WARM__')) {
|
|
248
|
+
viteWarmResolve();
|
|
249
|
+
}
|
|
250
|
+
|
|
242
251
|
if (tunnelUrl && relayUrl) {
|
|
243
252
|
doResolve();
|
|
244
253
|
return;
|
|
@@ -308,18 +317,11 @@ async function init() {
|
|
|
308
317
|
console.error(` ${c.dim}${err.message}${c.reset}\n`);
|
|
309
318
|
process.exit(1);
|
|
310
319
|
}
|
|
311
|
-
const { child, tunnelUrl, relayUrl } = result;
|
|
320
|
+
const { child, tunnelUrl, relayUrl, viteWarm } = result;
|
|
312
321
|
stepper.advance();
|
|
313
322
|
|
|
314
|
-
//
|
|
315
|
-
|
|
316
|
-
const localUrl = `http://localhost:${config.port}`;
|
|
317
|
-
try {
|
|
318
|
-
await Promise.all([
|
|
319
|
-
fetch(localUrl + '/').then(r => r.text()),
|
|
320
|
-
fetch(localUrl + '/fluxy/onboard.html').then(r => r.text()),
|
|
321
|
-
]);
|
|
322
|
-
} catch {}
|
|
323
|
+
// Wait for Vite to finish pre-transforming all modules (with timeout)
|
|
324
|
+
await Promise.race([viteWarm, new Promise(r => setTimeout(r, 30_000))]);
|
|
323
325
|
stepper.advance();
|
|
324
326
|
|
|
325
327
|
stepper.finish();
|
|
@@ -358,18 +360,11 @@ async function start() {
|
|
|
358
360
|
console.error(` ${c.dim}${err.message}${c.reset}\n`);
|
|
359
361
|
process.exit(1);
|
|
360
362
|
}
|
|
361
|
-
const { child, tunnelUrl, relayUrl } = result;
|
|
363
|
+
const { child, tunnelUrl, relayUrl, viteWarm } = result;
|
|
362
364
|
stepper.advance();
|
|
363
365
|
|
|
364
|
-
//
|
|
365
|
-
|
|
366
|
-
const local = `http://localhost:${cfg.port}`;
|
|
367
|
-
try {
|
|
368
|
-
await Promise.all([
|
|
369
|
-
fetch(local + '/').then(r => r.text()),
|
|
370
|
-
fetch(local + '/fluxy/onboard.html').then(r => r.text()),
|
|
371
|
-
]);
|
|
372
|
-
} catch {}
|
|
366
|
+
// Wait for Vite to finish pre-transforming all modules (with timeout)
|
|
367
|
+
await Promise.race([viteWarm, new Promise(r => setTimeout(r, 30_000))]);
|
|
373
368
|
stepper.advance();
|
|
374
369
|
|
|
375
370
|
stepper.finish();
|
package/package.json
CHANGED
package/scripts/install.sh
CHANGED
|
@@ -69,9 +69,14 @@ ok "Files copied"
|
|
|
69
69
|
# ── Install dependencies ──
|
|
70
70
|
info "Installing dependencies (this may take a moment)..."
|
|
71
71
|
cd "$FLUXY_HOME"
|
|
72
|
-
npm install --omit=dev
|
|
72
|
+
npm install --omit=dev 2>/dev/null
|
|
73
73
|
ok "Dependencies installed"
|
|
74
74
|
|
|
75
|
+
# ── Build fluxy chat + onboard (served as static files) ──
|
|
76
|
+
info "Building chat interface..."
|
|
77
|
+
npm run build:fluxy 2>/dev/null
|
|
78
|
+
ok "Chat interface built"
|
|
79
|
+
|
|
75
80
|
# ── Create symlink ──
|
|
76
81
|
info "Creating fluxy command..."
|
|
77
82
|
chmod +x "$FLUXY_HOME/bin/cli.js"
|
package/scripts/postinstall.js
CHANGED
|
@@ -61,6 +61,17 @@ try {
|
|
|
61
61
|
// Non-fatal: deps may already exist from a previous install
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
+
// ── Build fluxy chat + onboard (served as static files) ──
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
execSync('npm run build:fluxy', {
|
|
68
|
+
cwd: FLUXY_HOME,
|
|
69
|
+
stdio: 'ignore',
|
|
70
|
+
});
|
|
71
|
+
} catch {
|
|
72
|
+
// Non-fatal: will be built on first start if needed
|
|
73
|
+
}
|
|
74
|
+
|
|
64
75
|
// ── Create fluxy symlink ──
|
|
65
76
|
|
|
66
77
|
const cliPath = path.join(FLUXY_HOME, 'bin', 'cli.js');
|
package/supervisor/index.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import http from 'http';
|
|
2
2
|
import net from 'net';
|
|
3
3
|
import fs from 'fs';
|
|
4
|
+
import path from 'path';
|
|
4
5
|
import { WebSocketServer, WebSocket } from 'ws';
|
|
5
6
|
import { loadConfig, saveConfig } from '../shared/config.js';
|
|
6
7
|
import { createProvider, type AiProvider, type ChatMessage } from '../shared/ai.js';
|
|
7
8
|
import { paths } from '../shared/paths.js';
|
|
9
|
+
import { PKG_DIR } from '../shared/paths.js';
|
|
8
10
|
import { log } from '../shared/logger.js';
|
|
9
11
|
import { startTunnel, stopTunnel, isTunnelAlive, restartTunnel } from './tunnel.js';
|
|
10
12
|
import { spawnWorker, stopWorker, getWorkerPort, isWorkerAlive } from './worker.js';
|
|
@@ -12,6 +14,20 @@ import { updateTunnelUrl, startHeartbeat, stopHeartbeat, disconnect } from '../s
|
|
|
12
14
|
import { startFluxyAgentQuery, stopFluxyAgentQuery } from './fluxy-agent.js';
|
|
13
15
|
import { startViteDevServers, stopViteDevServers } from './vite-dev.js';
|
|
14
16
|
|
|
17
|
+
const DIST_FLUXY = path.join(PKG_DIR, 'dist-fluxy');
|
|
18
|
+
|
|
19
|
+
const MIME_TYPES: Record<string, string> = {
|
|
20
|
+
'.html': 'text/html',
|
|
21
|
+
'.js': 'application/javascript',
|
|
22
|
+
'.css': 'text/css',
|
|
23
|
+
'.png': 'image/png',
|
|
24
|
+
'.jpg': 'image/jpeg',
|
|
25
|
+
'.svg': 'image/svg+xml',
|
|
26
|
+
'.webm': 'video/webm',
|
|
27
|
+
'.woff2': 'font/woff2',
|
|
28
|
+
'.json': 'application/json',
|
|
29
|
+
};
|
|
30
|
+
|
|
15
31
|
const RECOVERING_HTML = `<!DOCTYPE html><html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Recovering</title>
|
|
16
32
|
<style>body{background:#0a0a0f;color:#94a3b8;font-family:system-ui;display:flex;align-items:center;justify-content:center;height:100vh;margin:0}
|
|
17
33
|
div{text-align:center}h1{font-size:18px;margin-bottom:8px;color:#e2e8f0}p{font-size:14px}a{color:#60a5fa}</style></head>
|
|
@@ -23,10 +39,10 @@ export async function startSupervisor() {
|
|
|
23
39
|
const config = loadConfig();
|
|
24
40
|
const workerPort = getWorkerPort(config.port);
|
|
25
41
|
|
|
26
|
-
// Start Vite dev
|
|
27
|
-
console.log('[supervisor] Starting Vite dev
|
|
42
|
+
// Start Vite dev server for dashboard HMR
|
|
43
|
+
console.log('[supervisor] Starting Vite dev server...');
|
|
28
44
|
const vitePorts = await startViteDevServers(config.port);
|
|
29
|
-
console.log(`[supervisor] Vite ready — dashboard :${vitePorts.dashboard}
|
|
45
|
+
console.log(`[supervisor] Vite ready — dashboard :${vitePorts.dashboard}`);
|
|
30
46
|
|
|
31
47
|
// Fluxy's AI brain
|
|
32
48
|
let ai: AiProvider | null = null;
|
|
@@ -73,25 +89,37 @@ export async function startSupervisor() {
|
|
|
73
89
|
return;
|
|
74
90
|
}
|
|
75
91
|
|
|
76
|
-
// Fluxy routes →
|
|
92
|
+
// Fluxy routes → serve pre-built static files from dist-fluxy/
|
|
77
93
|
// Note: must check '/fluxy/' (with slash) to avoid matching '/fluxy_tilts.webm' etc.
|
|
78
94
|
if (req.url === '/fluxy' || req.url?.startsWith('/fluxy/')) {
|
|
79
|
-
//
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
+
// Strip /fluxy prefix and resolve file path
|
|
96
|
+
let filePath = req.url!.replace(/^\/fluxy\/?/, '') || 'fluxy.html';
|
|
97
|
+
// Strip query strings (e.g. ?v=xxx)
|
|
98
|
+
filePath = filePath.split('?')[0];
|
|
99
|
+
const fullPath = path.join(DIST_FLUXY, filePath);
|
|
100
|
+
|
|
101
|
+
// Security: prevent directory traversal
|
|
102
|
+
if (!fullPath.startsWith(DIST_FLUXY)) {
|
|
103
|
+
res.writeHead(403);
|
|
104
|
+
res.end('Forbidden');
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
try {
|
|
109
|
+
const stat = fs.statSync(fullPath);
|
|
110
|
+
if (stat.isFile()) {
|
|
111
|
+
const ext = path.extname(fullPath);
|
|
112
|
+
const mime = MIME_TYPES[ext] || 'application/octet-stream';
|
|
113
|
+
res.writeHead(200, { 'Content-Type': mime, 'Cache-Control': 'public, max-age=31536000, immutable' });
|
|
114
|
+
fs.createReadStream(fullPath).pipe(res);
|
|
115
|
+
} else {
|
|
116
|
+
res.writeHead(404);
|
|
117
|
+
res.end('Not found');
|
|
118
|
+
}
|
|
119
|
+
} catch {
|
|
120
|
+
res.writeHead(404);
|
|
121
|
+
res.end('Not found');
|
|
122
|
+
}
|
|
95
123
|
return;
|
|
96
124
|
}
|
|
97
125
|
|
|
@@ -213,10 +241,9 @@ export async function startSupervisor() {
|
|
|
213
241
|
return;
|
|
214
242
|
}
|
|
215
243
|
|
|
216
|
-
// Route HMR WebSocket to
|
|
217
|
-
const
|
|
218
|
-
|
|
219
|
-
console.log(`[supervisor] → Vite HMR (${isFluxy ? 'fluxy' : 'dashboard'}) :${targetPort}`);
|
|
244
|
+
// Route HMR WebSocket to dashboard Vite dev server
|
|
245
|
+
const targetPort = vitePorts.dashboard;
|
|
246
|
+
console.log(`[supervisor] → Vite HMR (dashboard) :${targetPort}`);
|
|
220
247
|
|
|
221
248
|
const proxy = net.connect(targetPort, () => {
|
|
222
249
|
const headers = Object.entries(req.headers).map(([k, v]) => `${k}: ${v}`).join('\r\n');
|
package/supervisor/vite-dev.ts
CHANGED
|
@@ -4,21 +4,16 @@ import { PKG_DIR } from '../shared/paths.js';
|
|
|
4
4
|
import { log } from '../shared/logger.js';
|
|
5
5
|
|
|
6
6
|
let dashboardVite: ViteDevServer | null = null;
|
|
7
|
-
let fluxyVite: ViteDevServer | null = null;
|
|
8
7
|
|
|
9
|
-
export async function startViteDevServers(supervisorPort: number): Promise<{ dashboard: number
|
|
8
|
+
export async function startViteDevServers(supervisorPort: number): Promise<{ dashboard: number }> {
|
|
10
9
|
const ports = {
|
|
11
10
|
dashboard: supervisorPort + 2,
|
|
12
|
-
fluxy: supervisorPort + 3,
|
|
13
11
|
};
|
|
14
12
|
|
|
15
|
-
console.log(`[vite-dev] Starting Vite dev
|
|
16
|
-
console.log(`[vite-dev] Dashboard → :${ports.dashboard}, Fluxy → :${ports.fluxy}`);
|
|
13
|
+
console.log(`[vite-dev] Starting dashboard Vite dev server on :${ports.dashboard}`);
|
|
17
14
|
console.log(`[vite-dev] HMR clientPort → :${supervisorPort} (browser connects through supervisor proxy)`);
|
|
18
15
|
console.log(`[vite-dev] PKG_DIR = ${PKG_DIR}`);
|
|
19
16
|
|
|
20
|
-
// Dashboard Vite dev server
|
|
21
|
-
console.log('[vite-dev] Creating dashboard Vite server...');
|
|
22
17
|
try {
|
|
23
18
|
dashboardVite = await createViteServer({
|
|
24
19
|
configFile: path.join(PKG_DIR, 'vite.config.ts'),
|
|
@@ -38,28 +33,21 @@ export async function startViteDevServers(supervisorPort: number): Promise<{ das
|
|
|
38
33
|
throw err;
|
|
39
34
|
}
|
|
40
35
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
await fluxyVite.listen();
|
|
56
|
-
console.log(`[vite-dev] ✓ Fluxy Vite ready on :${ports.fluxy}`);
|
|
57
|
-
} catch (err) {
|
|
58
|
-
console.error('[vite-dev] ✗ Fluxy Vite failed:', err);
|
|
59
|
-
throw err;
|
|
60
|
-
}
|
|
36
|
+
log.ok(`Vite HMR active — dashboard :${ports.dashboard}`);
|
|
37
|
+
|
|
38
|
+
// Warm up: fetch the dashboard entry to pre-transform modules
|
|
39
|
+
fetch(`http://127.0.0.1:${ports.dashboard}/`).then(r => r.text()).then(async (html) => {
|
|
40
|
+
const scriptRe = /src="([^"]+\.tsx)"/g;
|
|
41
|
+
let m;
|
|
42
|
+
while ((m = scriptRe.exec(html)) !== null) {
|
|
43
|
+
const url = `http://127.0.0.1:${ports.dashboard}${m[1].startsWith('/') ? '' : '/'}${m[1]}`;
|
|
44
|
+
await fetch(url).then(r => r.text()).catch(() => {});
|
|
45
|
+
}
|
|
46
|
+
console.log('__VITE_WARM__');
|
|
47
|
+
}).catch(() => {
|
|
48
|
+
console.log('__VITE_WARM__');
|
|
49
|
+
});
|
|
61
50
|
|
|
62
|
-
log.ok(`Vite HMR active — dashboard :${ports.dashboard}, fluxy :${ports.fluxy}`);
|
|
63
51
|
return ports;
|
|
64
52
|
}
|
|
65
53
|
|
|
@@ -70,9 +58,4 @@ export async function stopViteDevServers(): Promise<void> {
|
|
|
70
58
|
dashboardVite = null;
|
|
71
59
|
console.log('[vite-dev] Dashboard Vite stopped');
|
|
72
60
|
}
|
|
73
|
-
if (fluxyVite) {
|
|
74
|
-
await fluxyVite.close();
|
|
75
|
-
fluxyVite = null;
|
|
76
|
-
console.log('[vite-dev] Fluxy Vite stopped');
|
|
77
|
-
}
|
|
78
61
|
}
|
package/vite.config.ts
CHANGED
|
@@ -17,9 +17,20 @@ export default defineConfig({
|
|
|
17
17
|
proxy: {
|
|
18
18
|
'/api': 'http://localhost:3000',
|
|
19
19
|
},
|
|
20
|
+
warmup: {
|
|
21
|
+
clientFiles: ['./src/main.tsx'],
|
|
22
|
+
},
|
|
20
23
|
},
|
|
21
24
|
optimizeDeps: {
|
|
22
25
|
include: [
|
|
26
|
+
'react',
|
|
27
|
+
'react-dom/client',
|
|
28
|
+
'react/jsx-runtime',
|
|
29
|
+
'lucide-react',
|
|
30
|
+
'framer-motion',
|
|
31
|
+
'recharts',
|
|
32
|
+
'zustand',
|
|
33
|
+
'sonner',
|
|
23
34
|
'use-sync-external-store',
|
|
24
35
|
'use-sync-external-store/shim',
|
|
25
36
|
],
|
package/vite.fluxy.config.ts
CHANGED
|
@@ -19,8 +19,22 @@ export default defineConfig({
|
|
|
19
19
|
},
|
|
20
20
|
},
|
|
21
21
|
},
|
|
22
|
+
server: {
|
|
23
|
+
warmup: {
|
|
24
|
+
clientFiles: ['./fluxy-main.tsx', './onboard-main.tsx'],
|
|
25
|
+
},
|
|
26
|
+
},
|
|
22
27
|
optimizeDeps: {
|
|
23
28
|
include: [
|
|
29
|
+
'react',
|
|
30
|
+
'react-dom/client',
|
|
31
|
+
'react/jsx-runtime',
|
|
32
|
+
'lucide-react',
|
|
33
|
+
'framer-motion',
|
|
34
|
+
'react-markdown',
|
|
35
|
+
'remark-gfm',
|
|
36
|
+
'react-syntax-highlighter',
|
|
37
|
+
'react-syntax-highlighter/dist/esm/styles/prism/one-dark',
|
|
24
38
|
'use-sync-external-store',
|
|
25
39
|
'use-sync-external-store/shim',
|
|
26
40
|
],
|