fix: eliminate duplicate WebSocket messages during agent history priming

- Skip dispatching individual agent_stream events when replaying history
  (the snapshot is sent after priming anyway, so individual events were wasted)
- Add WebSocket message logging on client (type, size, id) for debugging
- Change default daemon URL from dev to localhost
- Clean up unused imports in session.ts

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Mohamed Boudra
2025-11-28 17:44:07 +00:00
parent 3dc517366d
commit ae4678bca8
4 changed files with 24 additions and 8 deletions

View File

@@ -7,7 +7,7 @@ const REGISTRY_STORAGE_KEY = "@paseo:daemon-registry";
const LEGACY_SETTINGS_KEY = "@paseo:settings";
const FALLBACK_DAEMON_URL = "ws://localhost:6767/ws";
const DEFAULT_DAEMONS: Array<{ label: string; wsUrl: string; restUrl?: string | null }> = [
{ label: "dev", wsUrl: "ws://dev:6767/ws" },
{ label: "localhost", wsUrl: "ws://localhost:6767/ws" },
{ label: "macbook", wsUrl: "ws://mohameds-macbook-pro:6767/ws" },
];
const DAEMON_REGISTRY_QUERY_KEY = ["daemon-registry"];

View File

@@ -123,12 +123,17 @@ export function useWebSocket(url: string, conversationId?: string | null): UseWe
ws.onmessage = (event) => {
try {
const wsMessage: WSOutboundMessage = JSON.parse(event.data);
const rawData = event.data;
const size = typeof rawData === "string" ? rawData.length : 0;
const wsMessage: WSOutboundMessage = JSON.parse(rawData);
// Only session messages trigger handlers
if (wsMessage.type === "session") {
const sessionMessage = wsMessage.message;
console.log(`[WS] Received session message type: ${sessionMessage.type}`);
const id = (sessionMessage as { requestId?: string }).requestId ??
(sessionMessage as { agentId?: string }).agentId ??
(sessionMessage as { payload?: { agentId?: string } }).payload?.agentId;
console.log(`[WS] ← ${sessionMessage.type}`, { size, id: id ?? "-" });
// Track conversation ID when loaded
if (sessionMessage.type === "conversation_loaded") {
@@ -147,8 +152,8 @@ export function useWebSocket(url: string, conversationId?: string | null): UseWe
});
}
} else {
// pong - just log
console.log(`[WS] Received ${wsMessage.type}`);
// pong
console.log(`[WS] ${wsMessage.type}`, { size });
}
} catch (err) {
console.error("[WS] Failed to parse message:", err);
@@ -200,7 +205,14 @@ export function useWebSocket(url: string, conversationId?: string | null): UseWe
const send = useCallback((message: WSInboundMessage) => {
if (wsRef.current?.readyState === WebSocket.OPEN) {
wsRef.current.send(JSON.stringify(message));
const payload = JSON.stringify(message);
const type = message.type === "session" ? message.message.type : message.type;
const id = message.type === "session"
? (message.message as { requestId?: string; agentId?: string }).requestId ??
(message.message as { agentId?: string }).agentId
: undefined;
console.log(`[WS] → ${type}`, { size: payload.length, id: id ?? "-" });
wsRef.current.send(payload);
} else {
console.warn("[WS] Cannot send message - not connected");
}

View File

@@ -707,7 +707,11 @@ export class AgentManager {
break;
}
this.dispatchStream(agent.id, event);
// Skip dispatching individual stream events during history replay.
// The caller will send a batched agent_stream_snapshot after priming.
if (!options?.fromHistory) {
this.dispatchStream(agent.id, event);
}
}
private recordTimeline(agent: ManagedAgent, item: AgentTimelineItem): void {

View File

@@ -1,6 +1,6 @@
import { v4 as uuidv4 } from "uuid";
import { readFile, mkdir, writeFile } from "fs/promises";
import { exec, spawn } from "child_process";
import { exec } from "child_process";
import { promisify, inspect } from "util";
import { join } from "path";
import invariant from "tiny-invariant";