feat(webui): global chat websocket client
This commit is contained in:
parent
47e497867f
commit
33dab85c1c
60
webui/src/lib/chat.svelte.js
Normal file
60
webui/src/lib/chat.svelte.js
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
import { clientId } from "./api.js";
|
||||||
|
|
||||||
|
class ChatClient {
|
||||||
|
connected = $state(false);
|
||||||
|
turn = $state(null); // 最新 turn 快照(任意 session),供活动脊
|
||||||
|
#socket = null;
|
||||||
|
#handlers = new Set();
|
||||||
|
#reconnectTimer = null;
|
||||||
|
#stopped = false;
|
||||||
|
|
||||||
|
connect() {
|
||||||
|
if (this.#socket) return;
|
||||||
|
this.#stopped = false;
|
||||||
|
const scheme = location.protocol === "https:" ? "wss" : "ws";
|
||||||
|
const ws = new WebSocket(`${scheme}://${location.host}/ws?client_id=${encodeURIComponent(clientId())}`);
|
||||||
|
this.#socket = ws;
|
||||||
|
ws.onopen = () => {
|
||||||
|
this.connected = true;
|
||||||
|
this.#dispatch({ type: "_open" });
|
||||||
|
};
|
||||||
|
ws.onerror = () => ws.close();
|
||||||
|
ws.onclose = () => {
|
||||||
|
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 (frame.type === "turn_updated" && frame.snapshot) this.turn = frame.snapshot;
|
||||||
|
this.#dispatch(frame);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
disconnect() {
|
||||||
|
this.#stopped = true;
|
||||||
|
clearTimeout(this.#reconnectTimer);
|
||||||
|
this.#socket?.close();
|
||||||
|
this.#socket = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
send(frame) {
|
||||||
|
if (this.#socket?.readyState === WebSocket.OPEN) {
|
||||||
|
this.#socket.send(JSON.stringify(frame));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
subscribe(handler) {
|
||||||
|
this.#handlers.add(handler);
|
||||||
|
return () => this.#handlers.delete(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
#dispatch(frame) {
|
||||||
|
for (const handler of this.#handlers) handler(frame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const chat = new ChatClient();
|
||||||
Loading…
x
Reference in New Issue
Block a user