Fix loading state bugs and server crash

Backend fixes:
- Fix server crash when logging large session_state messages (186 agents)
- Use safe logging that extracts only message/stack properties
- Prevents TypeError in util.inspect on circular refs or deep objects

Frontend loading state fixes:
- Add reactive WebSocket update to prevent stale session.ws references
- Add timeout/retry wrapper for session_state loading (3 retries × 15s)
- Add hasEverReceivedSessionState flag to track cached data across reconnects
- Implement data-aware loading (isInitialLoad vs isRevalidating)
- Show reconnecting badge instead of hiding agents on reconnect

Debug improvements:
- Add detailed connection state logging in useAggregatedAgents
- Add connection status logging in AgentInputArea
- Track connecting reasons for easier debugging

Fixes:
- Agent screen no longer shows false "Offline" toast on reconnect
- Home screen shows loading immediately (no empty state flash)
- Home screen keeps agents visible during reconnect with badge
- Stuck loading has timeout protection with graceful degradation
- Server no longer crashes when sending session_state with many agents

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Mohamed Boudra
2025-12-03 02:45:16 +00:00
co-authored by Claude
parent 5ddaea7352
commit 348cb9d637
7 changed files with 244 additions and 30 deletions
+18 -3
View File
@@ -135,7 +135,10 @@ export class VoiceAssistantWebSocketServer {
// Set up error handler
ws.on("error", async (error) => {
console.error(`[WS] Client error:`, error);
// Safe error logging
const errorMessage = error instanceof Error ? error.message : "Unknown error";
const errorStack = error instanceof Error ? error.stack : undefined;
console.error(`[WS] Client error:`, { message: errorMessage, stack: errorStack });
const session = this.sessions.get(ws);
if (!session) return;
@@ -162,7 +165,14 @@ export class VoiceAssistantWebSocketServer {
// Validate with Zod
const message = WSInboundMessageSchema.parse(parsed);
console.log(`[WS] Received message type: ${message.type}`, message);
// Safe logging that handles large objects without crashing
const messageSummary = {
type: message.type,
...(message.type === "session" && message.message ? {
sessionMessageType: message.message.type,
} : {}),
};
console.log(`[WS] Received message:`, messageSummary);
// Handle WebSocket-level messages
switch (message.type) {
@@ -198,8 +208,13 @@ export class VoiceAssistantWebSocketServer {
return;
}
} catch (error) {
console.error("[WS] Failed to parse/handle message:", error);
// Safe error logging - avoid crashing on large/circular objects
const errorMessage = error instanceof Error ? error.message : "Unknown error";
const errorStack = error instanceof Error ? error.stack : undefined;
console.error("[WS] Failed to parse/handle message:", {
message: errorMessage,
stack: errorStack,
});
// Send error to client
this.sendToClient(
ws,