fluxy-bot 0.11.5 → 0.11.6
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/package.json +1 -1
- package/supervisor/index.ts +15 -40
- package/worker/index.ts +4 -9
package/package.json
CHANGED
package/supervisor/index.ts
CHANGED
|
@@ -9,7 +9,8 @@ import { paths } from '../shared/paths.js';
|
|
|
9
9
|
import { PKG_DIR, DATA_DIR, WORKSPACE_DIR } from '../shared/paths.js';
|
|
10
10
|
import { log } from '../shared/logger.js';
|
|
11
11
|
import { startTunnel, stopTunnel, isTunnelAlive, restartTunnel, startNamedTunnel, restartNamedTunnel } from './tunnel.js';
|
|
12
|
-
import {
|
|
12
|
+
import { createWorkerApp } from '../worker/index.js';
|
|
13
|
+
import { closeDb, getSession, getSetting } from '../worker/db.js';
|
|
13
14
|
import { spawnBackend, stopBackend, getBackendPort, isBackendAlive, resetBackendRestarts } from './backend.js';
|
|
14
15
|
import { updateTunnelUrl, startHeartbeat, stopHeartbeat, disconnect } from '../shared/relay.js';
|
|
15
16
|
import { startFluxyAgentQuery, stopFluxyAgentQuery, type RecentMessage } from './fluxy-agent.js';
|
|
@@ -195,7 +196,6 @@ const RECOVERING_HTML = `<!DOCTYPE html><html style="background:#222122"><head><
|
|
|
195
196
|
|
|
196
197
|
export async function startSupervisor() {
|
|
197
198
|
const config = loadConfig();
|
|
198
|
-
const workerPort = getWorkerPort(config.port);
|
|
199
199
|
const backendPort = getBackendPort(config.port);
|
|
200
200
|
|
|
201
201
|
// Create HTTP server first (Vite needs it for HMR WebSocket)
|
|
@@ -211,6 +211,9 @@ export async function startSupervisor() {
|
|
|
211
211
|
// Ensure file storage dirs exist
|
|
212
212
|
ensureFileDirs();
|
|
213
213
|
|
|
214
|
+
// Initialize worker routes in-process (no separate child process)
|
|
215
|
+
const workerApp = createWorkerApp();
|
|
216
|
+
|
|
214
217
|
// Fluxy's AI brain
|
|
215
218
|
let ai: AiProvider | null = null;
|
|
216
219
|
if (config.ai.provider && (config.ai.apiKey || config.ai.provider === 'ollama')) {
|
|
@@ -227,11 +230,11 @@ export async function startSupervisor() {
|
|
|
227
230
|
let currentStreamConvId: string | null = null;
|
|
228
231
|
let currentStreamBuffer = '';
|
|
229
232
|
|
|
230
|
-
/** Call worker API endpoints */
|
|
231
|
-
async function workerApi(
|
|
233
|
+
/** Call worker API endpoints (in-process via supervisor's own HTTP server) */
|
|
234
|
+
async function workerApi(apiPath: string, method = 'GET', body?: any) {
|
|
232
235
|
const opts: RequestInit = { method, headers: { 'Content-Type': 'application/json' } };
|
|
233
236
|
if (body) opts.body = JSON.stringify(body);
|
|
234
|
-
const res = await fetch(`http://127.0.0.1:${
|
|
237
|
+
const res = await fetch(`http://127.0.0.1:${config.port}${apiPath}`, opts);
|
|
235
238
|
return res.json();
|
|
236
239
|
}
|
|
237
240
|
|
|
@@ -252,13 +255,8 @@ export async function startSupervisor() {
|
|
|
252
255
|
if (cached && cached > Date.now()) return true;
|
|
253
256
|
|
|
254
257
|
try {
|
|
255
|
-
const
|
|
256
|
-
|
|
257
|
-
headers: { 'Content-Type': 'application/json' },
|
|
258
|
-
body: JSON.stringify({ token }),
|
|
259
|
-
});
|
|
260
|
-
const data = await res.json() as { valid: boolean };
|
|
261
|
-
if (data.valid) {
|
|
258
|
+
const session = getSession(token);
|
|
259
|
+
if (session) {
|
|
262
260
|
tokenCache.set(token, Date.now() + TOKEN_CACHE_TTL);
|
|
263
261
|
return true;
|
|
264
262
|
}
|
|
@@ -274,9 +272,7 @@ export async function startSupervisor() {
|
|
|
274
272
|
async function isAuthRequired(): Promise<boolean> {
|
|
275
273
|
if (authRequiredCache && authRequiredCache.expires > Date.now()) return authRequiredCache.value;
|
|
276
274
|
try {
|
|
277
|
-
const
|
|
278
|
-
const data = await res.json() as { portalConfigured: boolean };
|
|
279
|
-
const required = !!data.portalConfigured;
|
|
275
|
+
const required = !!getSetting('portal_pass');
|
|
280
276
|
authRequiredCache = { value: required, expires: Date.now() + 30_000 };
|
|
281
277
|
return required;
|
|
282
278
|
} catch {
|
|
@@ -368,16 +364,8 @@ export async function startSupervisor() {
|
|
|
368
364
|
return;
|
|
369
365
|
}
|
|
370
366
|
|
|
371
|
-
// API routes →
|
|
367
|
+
// API routes → handled in-process by worker Express app
|
|
372
368
|
if (req.url?.startsWith('/api')) {
|
|
373
|
-
console.log(`[supervisor] → worker :${workerPort} | ${req.method} ${req.url}`);
|
|
374
|
-
if (!isWorkerAlive()) {
|
|
375
|
-
console.log('[supervisor] Worker down — returning 503');
|
|
376
|
-
res.writeHead(503, { 'Content-Type': 'text/html' });
|
|
377
|
-
res.end(RECOVERING_HTML);
|
|
378
|
-
return;
|
|
379
|
-
}
|
|
380
|
-
|
|
381
369
|
// Auth check for mutation routes (POST/PUT/DELETE) — GET/HEAD are read-only, skip auth
|
|
382
370
|
const method = req.method || 'GET';
|
|
383
371
|
if (method !== 'GET' && method !== 'HEAD' && !isExemptRoute(method, req.url || '')) {
|
|
@@ -393,19 +381,7 @@ export async function startSupervisor() {
|
|
|
393
381
|
}
|
|
394
382
|
}
|
|
395
383
|
|
|
396
|
-
|
|
397
|
-
{ host: '127.0.0.1', port: workerPort, path: req.url, method: req.method, headers: req.headers },
|
|
398
|
-
(proxyRes) => {
|
|
399
|
-
res.writeHead(proxyRes.statusCode!, proxyRes.headers);
|
|
400
|
-
proxyRes.pipe(res);
|
|
401
|
-
},
|
|
402
|
-
);
|
|
403
|
-
proxy.on('error', (e) => {
|
|
404
|
-
console.error(`[supervisor] Worker proxy error: ${req.url}`, e.message);
|
|
405
|
-
res.writeHead(503, { 'Content-Type': 'text/html' });
|
|
406
|
-
res.end(RECOVERING_HTML);
|
|
407
|
-
});
|
|
408
|
-
req.pipe(proxy);
|
|
384
|
+
workerApp(req, res);
|
|
409
385
|
return;
|
|
410
386
|
}
|
|
411
387
|
|
|
@@ -1047,8 +1023,7 @@ export async function startSupervisor() {
|
|
|
1047
1023
|
}
|
|
1048
1024
|
}
|
|
1049
1025
|
|
|
1050
|
-
// Spawn worker
|
|
1051
|
-
spawnWorker(workerPort);
|
|
1026
|
+
// Spawn backend (worker runs in-process)
|
|
1052
1027
|
spawnBackend(backendPort);
|
|
1053
1028
|
|
|
1054
1029
|
// Start pulse/cron scheduler
|
|
@@ -1277,7 +1252,7 @@ export async function startSupervisor() {
|
|
|
1277
1252
|
// Clear persisted tunnel URL so stale values aren't reused
|
|
1278
1253
|
delete latestConfig.tunnelUrl;
|
|
1279
1254
|
saveConfig(latestConfig);
|
|
1280
|
-
|
|
1255
|
+
closeDb();
|
|
1281
1256
|
await stopBackend();
|
|
1282
1257
|
stopTunnel();
|
|
1283
1258
|
console.log('[supervisor] Stopping Vite dev servers...');
|
package/worker/index.ts
CHANGED
|
@@ -67,9 +67,7 @@ function parseCookie(cookieHeader: string | undefined, name: string): string | u
|
|
|
67
67
|
return match ? match.slice(name.length + 1) : undefined;
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
|
|
71
|
-
const config = loadConfig();
|
|
72
|
-
|
|
70
|
+
export function createWorkerApp() {
|
|
73
71
|
// Database
|
|
74
72
|
initDb();
|
|
75
73
|
|
|
@@ -882,10 +880,7 @@ app.post('/api/whisper/transcribe', express.json({ limit: '10mb' }), async (req,
|
|
|
882
880
|
// Serve stored files (audio, images, documents)
|
|
883
881
|
app.use('/api/files', express.static(paths.files));
|
|
884
882
|
|
|
885
|
-
|
|
886
|
-
console.log('[worker] API-only mode — dashboard served by Vite dev server');
|
|
887
|
-
|
|
888
|
-
// HTTP server (no WebSocket — chat lives in supervisor)
|
|
889
|
-
const server = app.listen(port, () => log.ok(`Worker on port ${port}`));
|
|
883
|
+
log.ok('Worker routes initialized (in-process)');
|
|
890
884
|
|
|
891
|
-
|
|
885
|
+
return app;
|
|
886
|
+
}
|