diff --git a/webui/src/lib/chat.svelte.js b/webui/src/lib/chat.svelte.js index ab86d50..b01b927 100644 --- a/webui/src/lib/chat.svelte.js +++ b/webui/src/lib/chat.svelte.js @@ -11,22 +11,27 @@ class ChatClient { connect() { if (this.#socket) return; this.#stopped = false; + clearTimeout(this.#reconnectTimer); const scheme = location.protocol === "https:" ? "wss" : "ws"; const ws = new WebSocket(`${scheme}://${location.host}/ws?client_id=${encodeURIComponent(clientId())}`); this.#socket = ws; ws.onopen = () => { + if (this.#socket !== ws) return; this.connected = true; this.#dispatch({ type: "_open" }); }; ws.onerror = () => ws.close(); ws.onclose = () => { + if (this.#socket !== ws) return; this.connected = false; this.#socket = null; this.#dispatch({ type: "_close" }); if (!this.#stopped) this.#reconnectTimer = setTimeout(() => this.connect(), 1800); }; ws.onmessage = (event) => { - const frame = JSON.parse(event.data); + if (this.#socket !== ws) return; + let frame; + try { frame = JSON.parse(event.data); } catch { return; } if (frame.type === "turn_updated" && frame.snapshot) this.turn = frame.snapshot; this.#dispatch(frame); }; diff --git a/webui/src/lib/components/ActivitySpine.svelte b/webui/src/lib/components/ActivitySpine.svelte index 2d90273..191f10b 100644 --- a/webui/src/lib/components/ActivitySpine.svelte +++ b/webui/src/lib/components/ActivitySpine.svelte @@ -2,12 +2,12 @@ import { chat } from "../chat.svelte.js"; let { version = "" } = $props(); - let lastTokens = $state(null); // { at, completion } + let lastTokens = null; // { at, completion } — plain bookkeeping, NOT reactive let rate = $state(null); $effect(() => { const turn = chat.turn; - if (!turn || turn.status !== "running") { rate = null; return; } + if (!turn || turn.status !== "running") { rate = null; lastTokens = null; return; } const completion = turn.usage?.completion_tokens; const now = Date.now(); if (completion != null && lastTokens && now > lastTokens.at) {