@agent-relay/dashboard-server 2.0.57 → 2.0.59
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/dist/server.js +28 -16
- package/dist/server.js.map +1 -1
- package/dist/start.js +1 -0
- package/dist/start.js.map +1 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -1
- package/out/404.html +1 -1
- package/out/about.html +1 -1
- package/out/about.txt +1 -1
- package/out/app/onboarding.html +1 -1
- package/out/app/onboarding.txt +1 -1
- package/out/app.html +1 -1
- package/out/app.txt +1 -1
- package/out/blog/go-to-bed-wake-up-to-a-finished-product.html +1 -1
- package/out/blog/go-to-bed-wake-up-to-a-finished-product.txt +1 -1
- package/out/blog.html +1 -1
- package/out/blog.txt +1 -1
- package/out/careers.html +1 -1
- package/out/careers.txt +1 -1
- package/out/changelog.html +1 -1
- package/out/changelog.txt +1 -1
- package/out/cloud/link.html +1 -1
- package/out/cloud/link.txt +1 -1
- package/out/complete-profile.html +1 -1
- package/out/complete-profile.txt +1 -1
- package/out/connect-repos.html +1 -1
- package/out/connect-repos.txt +1 -1
- package/out/contact.html +1 -1
- package/out/contact.txt +1 -1
- package/out/docs.html +1 -1
- package/out/docs.txt +1 -1
- package/out/history.html +1 -1
- package/out/history.txt +1 -1
- package/out/index.html +1 -1
- package/out/index.txt +1 -1
- package/out/login.html +1 -1
- package/out/login.txt +1 -1
- package/out/metrics.html +1 -1
- package/out/metrics.txt +1 -1
- package/out/pricing.html +1 -1
- package/out/pricing.txt +1 -1
- package/out/privacy.html +1 -1
- package/out/privacy.txt +1 -1
- package/out/providers/setup/claude.html +1 -1
- package/out/providers/setup/claude.txt +1 -1
- package/out/providers/setup/codex.html +1 -1
- package/out/providers/setup/codex.txt +1 -1
- package/out/providers/setup/cursor.html +1 -1
- package/out/providers/setup/cursor.txt +1 -1
- package/out/providers.html +1 -1
- package/out/providers.txt +1 -1
- package/out/security.html +1 -1
- package/out/security.txt +1 -1
- package/out/signup.html +1 -1
- package/out/signup.txt +1 -1
- package/out/terms.html +1 -1
- package/out/terms.txt +1 -1
- package/package.json +10 -10
- /package/out/_next/static/{QS-NFfJUw1w3081kmWJg9 → vqqAzuICuRIakU1wIp0AV}/_buildManifest.js +0 -0
- /package/out/_next/static/{QS-NFfJUw1w3081kmWJg9 → vqqAzuICuRIakU1wIp0AV}/_ssgManifest.js +0 -0
package/dist/server.js
CHANGED
|
@@ -318,8 +318,15 @@ export async function startDashboard(portOrOptions, dataDirArg, teamDirArg, dbPa
|
|
|
318
318
|
const options = typeof portOrOptions === 'number'
|
|
319
319
|
? { port: portOrOptions, dataDir: dataDirArg, teamDir: teamDirArg, dbPath: dbPathArg }
|
|
320
320
|
: portOrOptions;
|
|
321
|
-
const { port, dataDir, teamDir, dbPath, enableSpawner, projectRoot, tmuxSession, onMarkSpawning, onClearSpawning } = options;
|
|
322
|
-
|
|
321
|
+
const { port, dataDir, teamDir, dbPath, enableSpawner, projectRoot, tmuxSession, onMarkSpawning, onClearSpawning, verbose } = options;
|
|
322
|
+
// Debug logging helper - only logs when verbose is true or VERBOSE env var is set
|
|
323
|
+
const isVerbose = verbose || process.env.VERBOSE === 'true';
|
|
324
|
+
const debug = (message) => {
|
|
325
|
+
if (isVerbose) {
|
|
326
|
+
console.log(message);
|
|
327
|
+
}
|
|
328
|
+
};
|
|
329
|
+
console.log('[dashboard] Starting dashboard...');
|
|
323
330
|
const disableStorage = process.env.RELAY_DISABLE_STORAGE === 'true';
|
|
324
331
|
// Use createStorageAdapter to match daemon's storage type (JSONL by default)
|
|
325
332
|
// This ensures dashboard reads from the same storage as daemon writes to
|
|
@@ -576,7 +583,7 @@ export async function startDashboard(portOrOptions, dataDirArg, teamDirArg, dbPa
|
|
|
576
583
|
wss.clients.forEach((ws) => {
|
|
577
584
|
if (mainClientAlive.get(ws) === false) {
|
|
578
585
|
// Client didn't respond to last ping - close gracefully
|
|
579
|
-
|
|
586
|
+
debug('[dashboard] Main WebSocket client unresponsive, closing gracefully');
|
|
580
587
|
ws.close(1000, 'unresponsive');
|
|
581
588
|
return;
|
|
582
589
|
}
|
|
@@ -590,7 +597,7 @@ export async function startDashboard(portOrOptions, dataDirArg, teamDirArg, dbPa
|
|
|
590
597
|
const bridgePingInterval = setInterval(() => {
|
|
591
598
|
wssBridge.clients.forEach((ws) => {
|
|
592
599
|
if (bridgeClientAlive.get(ws) === false) {
|
|
593
|
-
|
|
600
|
+
debug('[dashboard] Bridge WebSocket client unresponsive, closing gracefully');
|
|
594
601
|
ws.close(1000, 'unresponsive');
|
|
595
602
|
return;
|
|
596
603
|
}
|
|
@@ -780,6 +787,11 @@ export async function startDashboard(portOrOptions, dataDirArg, teamDirArg, dbPa
|
|
|
780
787
|
app.get('/app', (req, res) => {
|
|
781
788
|
res.sendFile(path.join(dashboardDir, 'app.html'));
|
|
782
789
|
});
|
|
790
|
+
// Catch-all for /app/* routes - serve app.html and let client-side routing handle it
|
|
791
|
+
// Express 5 requires named parameter for wildcards
|
|
792
|
+
app.get('/app/{*path}', (req, res) => {
|
|
793
|
+
res.sendFile(path.join(dashboardDir, 'app.html'));
|
|
794
|
+
});
|
|
783
795
|
}
|
|
784
796
|
else {
|
|
785
797
|
// Serve a fallback page when dashboard UI files aren't available
|
|
@@ -1971,7 +1983,7 @@ export async function startDashboard(portOrOptions, dataDirArg, teamDirArg, dbPa
|
|
|
1971
1983
|
};
|
|
1972
1984
|
// Handle new WebSocket connections - send initial data immediately
|
|
1973
1985
|
wss.on('connection', async (ws, req) => {
|
|
1974
|
-
|
|
1986
|
+
debug(`[dashboard] WebSocket client connected from: ${req.socket.remoteAddress}`);
|
|
1975
1987
|
// Mark client as alive initially for ping/pong keepalive
|
|
1976
1988
|
mainClientAlive.set(ws, true);
|
|
1977
1989
|
// Handle pong responses (keep connection alive)
|
|
@@ -1989,9 +2001,9 @@ export async function startDashboard(portOrOptions, dataDirArg, teamDirArg, dbPa
|
|
|
1989
2001
|
return;
|
|
1990
2002
|
}
|
|
1991
2003
|
if (ws.readyState === WebSocket.OPEN) {
|
|
1992
|
-
|
|
2004
|
+
debug(`[dashboard] Sending initial data, size: ${payload.length}, first 200 chars: ${payload.substring(0, 200)}`);
|
|
1993
2005
|
ws.send(payload);
|
|
1994
|
-
|
|
2006
|
+
debug('[dashboard] Initial data sent successfully');
|
|
1995
2007
|
}
|
|
1996
2008
|
else {
|
|
1997
2009
|
console.warn('[dashboard] WebSocket not open, state:', ws.readyState);
|
|
@@ -2008,12 +2020,12 @@ export async function startDashboard(portOrOptions, dataDirArg, teamDirArg, dbPa
|
|
|
2008
2020
|
console.error('[dashboard] WebSocket client error:', err);
|
|
2009
2021
|
});
|
|
2010
2022
|
ws.on('close', (code, reason) => {
|
|
2011
|
-
|
|
2023
|
+
debug(`[dashboard] WebSocket client disconnected, code: ${code}, reason: ${reason?.toString() || 'none'}`);
|
|
2012
2024
|
});
|
|
2013
2025
|
});
|
|
2014
2026
|
// Handle bridge WebSocket connections
|
|
2015
2027
|
wssBridge.on('connection', async (ws) => {
|
|
2016
|
-
|
|
2028
|
+
debug('[dashboard] Bridge WebSocket client connected');
|
|
2017
2029
|
// Mark client as alive initially for ping/pong keepalive
|
|
2018
2030
|
bridgeClientAlive.set(ws, true);
|
|
2019
2031
|
// Handle pong responses (keep connection alive)
|
|
@@ -2034,7 +2046,7 @@ export async function startDashboard(portOrOptions, dataDirArg, teamDirArg, dbPa
|
|
|
2034
2046
|
console.error('[dashboard] Bridge WebSocket client error:', err);
|
|
2035
2047
|
});
|
|
2036
2048
|
ws.on('close', (code, reason) => {
|
|
2037
|
-
|
|
2049
|
+
debug(`[dashboard] Bridge WebSocket client disconnected, code: ${code}, reason: ${reason?.toString() || 'none'}`);
|
|
2038
2050
|
});
|
|
2039
2051
|
});
|
|
2040
2052
|
// Track alive status for ping/pong keepalive on log connections
|
|
@@ -2046,7 +2058,7 @@ export async function startDashboard(portOrOptions, dataDirArg, teamDirArg, dbPa
|
|
|
2046
2058
|
wssLogs.clients.forEach((ws) => {
|
|
2047
2059
|
if (logClientAlive.get(ws) === false) {
|
|
2048
2060
|
// Client didn't respond to last ping - close gracefully
|
|
2049
|
-
|
|
2061
|
+
debug('[dashboard] Logs WebSocket client unresponsive, closing gracefully');
|
|
2050
2062
|
ws.close(1000, 'unresponsive');
|
|
2051
2063
|
return;
|
|
2052
2064
|
}
|
|
@@ -2061,7 +2073,7 @@ export async function startDashboard(portOrOptions, dataDirArg, teamDirArg, dbPa
|
|
|
2061
2073
|
});
|
|
2062
2074
|
// Handle logs WebSocket connections for live log streaming
|
|
2063
2075
|
wssLogs.on('connection', (ws, req) => {
|
|
2064
|
-
|
|
2076
|
+
debug('[dashboard] Logs WebSocket client connected');
|
|
2065
2077
|
const clientSubscriptions = new Set();
|
|
2066
2078
|
// Mark client as alive initially
|
|
2067
2079
|
logClientAlive.set(ws, true);
|
|
@@ -2208,7 +2220,7 @@ export async function startDashboard(portOrOptions, dataDirArg, teamDirArg, dbPa
|
|
|
2208
2220
|
logSubscriptions.set(agentName, new Set());
|
|
2209
2221
|
}
|
|
2210
2222
|
logSubscriptions.get(agentName).add(ws);
|
|
2211
|
-
|
|
2223
|
+
debug(`[dashboard] Client subscribed to logs for: ${agentName} (spawned: ${isSpawned}, daemon: ${isDaemon})`);
|
|
2212
2224
|
if (isSpawned && spawner) {
|
|
2213
2225
|
// Send initial log history for spawned agents (5000 lines to match xterm scrollback capacity)
|
|
2214
2226
|
const lines = spawner.getWorkerOutput(agentName, 5000);
|
|
@@ -2289,7 +2301,7 @@ export async function startDashboard(portOrOptions, dataDirArg, teamDirArg, dbPa
|
|
|
2289
2301
|
fileLastSize.delete(agentName);
|
|
2290
2302
|
}
|
|
2291
2303
|
}
|
|
2292
|
-
|
|
2304
|
+
debug(`[dashboard] Client unsubscribed from logs for: ${agentName}`);
|
|
2293
2305
|
ws.send(JSON.stringify({
|
|
2294
2306
|
type: 'unsubscribed',
|
|
2295
2307
|
agent: agentName,
|
|
@@ -2436,7 +2448,7 @@ export async function startDashboard(portOrOptions, dataDirArg, teamDirArg, dbPa
|
|
|
2436
2448
|
const payload = JSON.stringify(message);
|
|
2437
2449
|
// Broadcast to main WebSocket clients (local mode)
|
|
2438
2450
|
const mainClients = Array.from(wss.clients).filter(c => c.readyState === WebSocket.OPEN);
|
|
2439
|
-
|
|
2451
|
+
debug(`[dashboard] Broadcasting direct_message to ${mainClients.length} main clients`);
|
|
2440
2452
|
wss.clients.forEach((client) => {
|
|
2441
2453
|
if (client.readyState === WebSocket.OPEN) {
|
|
2442
2454
|
client.send(payload);
|
|
@@ -2445,7 +2457,7 @@ export async function startDashboard(portOrOptions, dataDirArg, teamDirArg, dbPa
|
|
|
2445
2457
|
// Also broadcast to presence WebSocket clients (cloud mode)
|
|
2446
2458
|
const presenceClients = Array.from(wssPresence.clients).filter(c => c.readyState === WebSocket.OPEN);
|
|
2447
2459
|
if (presenceClients.length > 0) {
|
|
2448
|
-
|
|
2460
|
+
debug(`[dashboard] Broadcasting direct_message to ${presenceClients.length} presence clients`);
|
|
2449
2461
|
wssPresence.clients.forEach((client) => {
|
|
2450
2462
|
if (client.readyState === WebSocket.OPEN) {
|
|
2451
2463
|
client.send(payload);
|