MCPcopy Create free account
hub / github.com/MoonshotAI/kimi-code / DaemonEventSocket

Class DaemonEventSocket

apps/kimi-web/src/api/daemon/ws.ts:69–478  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

67}
68
69export class DaemonEventSocket {
70 private ws: WebSocket | null = null;
71 private connected = false;
72 private closed = false;
73
74 /** subscriptions we manage: sessionId → last known cursor {seq, epoch} */
75 private readonly subscriptions = new Map<string, SessionCursor>();
76
77 /** subscriptions queued while not yet connected */
78 private readonly pendingSubscriptions: PendingSubscription[] = [];
79 private readonly terminalAttachments = new Map<string, TerminalAttachment>();
80
81 private msgSeq = 0;
82
83 /** Automatic reconnect (exponential backoff, reset on a successful hello). */
84 private reconnectAttempts = 0;
85 private reconnectTimer: ReturnType<typeof setTimeout> | null = null;
86
87 constructor(
88 private readonly wsUrl: string,
89 private readonly clientId: string,
90 private readonly handlers: DaemonEventSocketHandlers,
91 ) {}
92
93 /** Open the WebSocket connection. No-op while one is open or after close(). */
94 connect(): void {
95 if (this.ws !== null || this.closed) return;
96
97 traceWsLifecycle('connect', { url: this.wsUrl, attempt: this.reconnectAttempts });
98 const credential = getCredential();
99 const protocols =
100 credential !== undefined ? [`${WS_BEARER_PROTOCOL_PREFIX}${credential}`] : undefined;
101 const ws = new WebSocket(this.wsUrl, protocols);
102 this.ws = ws;
103
104 ws.onopen = () => {
105 // Don't mark as connected yet — wait for server_hello
106 traceWsLifecycle('open');
107 };
108
109 ws.onmessage = (ev: MessageEvent) => {
110 try {
111 const frame = JSON.parse(String(ev.data)) as WireServerFrame;
112 traceWsIn(frame);
113 this.handleFrame(frame);
114 } catch (error) {
115 traceWsLifecycle('parse-error', { error: String(error) });
116 this.handlers.onError(0, `Failed to parse WS frame: ${String(error)}`, false);
117 }
118 };
119
120 ws.onerror = () => {
121 // The error details are not exposed by the browser WS API; the close
122 // event with a reason code follows immediately.
123 traceWsLifecycle('error');
124 this.handlers.onError(0, 'WebSocket error', false);
125 };
126

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected