()
| 388 | } |
| 389 | |
| 390 | private onServerHello(): void { |
| 391 | this.connected = true; |
| 392 | this.reconnectAttempts = 0; |
| 393 | this.handlers.onConnectionState(true); |
| 394 | |
| 395 | // Build the initial subscription list from current subscriptions + pending |
| 396 | const allSessionIds = Array.from(this.subscriptions.keys()); |
| 397 | // Drain pending: merge into subscriptions map (pending overrides if seq differs) |
| 398 | for (const p of this.pendingSubscriptions) { |
| 399 | this.subscriptions.set(p.sessionId, p.cursor); |
| 400 | if (!allSessionIds.includes(p.sessionId)) allSessionIds.push(p.sessionId); |
| 401 | } |
| 402 | this.pendingSubscriptions.length = 0; |
| 403 | |
| 404 | // Build cursors from subscriptions |
| 405 | const cursors: Record<string, SessionCursor> = {}; |
| 406 | for (const [sid, cursor] of this.subscriptions.entries()) { |
| 407 | cursors[sid] = cursor; |
| 408 | } |
| 409 | |
| 410 | this.send({ |
| 411 | type: 'client_hello', |
| 412 | id: this.nextId(), |
| 413 | payload: { |
| 414 | client_id: this.clientId, |
| 415 | subscriptions: allSessionIds, |
| 416 | cursors, |
| 417 | }, |
| 418 | }); |
| 419 | |
| 420 | for (const attachment of this.terminalAttachments.values()) { |
| 421 | this.sendTerminalAttach(attachment.sessionId, attachment.terminalId, attachment.lastSeq); |
| 422 | } |
| 423 | } |
| 424 | |
| 425 | private sendSubscribe(sessionIds: string[], cursors: Record<string, SessionCursor>): void { |
| 426 | this.send({ |
no test coverage detected