blob: 76c7ef5985f50dc899f3326e95827332981ece45 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
import { config } from "./config.js";
import type { AgentEvent, ConnectionStatus } from "./types.js";
type EventCallback = (event: AgentEvent) => void;
function createWebSocketClient(url: string) {
let connectionStatus: ConnectionStatus = $state("disconnected");
let ws: WebSocket | null = null;
let reconnectDelay = 1000;
let reconnectTimer: ReturnType<typeof setTimeout> | null = null;
let manualDisconnect = false;
const callbacks: EventCallback[] = [];
function connect() {
if (ws && (ws.readyState === WebSocket.OPEN || ws.readyState === WebSocket.CONNECTING)) {
return;
}
manualDisconnect = false;
connectionStatus = "connecting";
ws = new WebSocket(url);
ws.onopen = () => {
connectionStatus = "connected";
reconnectDelay = 1000;
};
ws.onmessage = (event: MessageEvent) => {
try {
const data = JSON.parse(event.data as string) as AgentEvent;
for (const cb of callbacks) {
cb(data);
}
} catch {
// ignore malformed messages
}
};
ws.onclose = () => {
connectionStatus = "disconnected";
ws = null;
if (!manualDisconnect) {
scheduleReconnect();
}
};
ws.onerror = () => {
ws?.close();
};
}
function scheduleReconnect() {
if (reconnectTimer) clearTimeout(reconnectTimer);
reconnectTimer = setTimeout(() => {
reconnectTimer = null;
connect();
}, reconnectDelay);
reconnectDelay = Math.min(reconnectDelay * 2, 10000);
}
function disconnect() {
manualDisconnect = true;
if (reconnectTimer) {
clearTimeout(reconnectTimer);
reconnectTimer = null;
}
ws?.close();
ws = null;
connectionStatus = "disconnected";
}
function onEvent(callback: EventCallback) {
callbacks.push(callback);
return () => {
const idx = callbacks.indexOf(callback);
if (idx !== -1) callbacks.splice(idx, 1);
};
}
return {
get connectionStatus() {
return connectionStatus;
},
connect,
disconnect,
onEvent,
};
}
export const wsClient = createWebSocketClient(config.wsUrl);
|