@neta-art/cohub 12.5.0 → 12.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/websocket.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { C as getSessionTurnPatchStreamKey, S as getRealtimeSpaceRoom, T as normalizeRealtimeRooms, _ as WS_REALTIME_ROOM_CAPABILITY, b as WS_ROOM_SUBSCRIPTION_CAPABILITY, g as WS_COMPACT_STREAM_CAPABILITY, h as WS_BOARD_AWARENESS_CAPABILITY, r as extractBillingPayload, v as WS_REALTIME_ROOM_HISTORY_CAPABILITY, w as isRealtimeDomain } from "./chunks/http-error.js";
2
- import { f as resolveWebsocketUrl } from "./chunks/environment.js";
2
+ import { p as resolveWebsocketUrl } from "./chunks/environment.js";
3
3
  //#region src/websocket.ts
4
4
  const createEventMap = () => ({
5
5
  connecting: /* @__PURE__ */ new Set(),
@@ -109,12 +109,15 @@ var WebsocketClient = class {
109
109
  pongTimeoutMs;
110
110
  debug;
111
111
  getAccessToken;
112
+ anonymous;
112
113
  WebSocketImpl;
113
114
  ws = null;
114
115
  pingTimer = null;
115
116
  reconnectTimer = null;
116
117
  reconnectTimerResolver = null;
117
118
  reconnectAttempt = 0;
119
+ resubscribeTimer = null;
120
+ resubscribeAttempt = 0;
118
121
  authReconnectAttempted = false;
119
122
  forceRefreshOnNextAuth = false;
120
123
  retryAuthClose = false;
@@ -146,6 +149,7 @@ var WebsocketClient = class {
146
149
  this.pongTimeoutMs = normalized.pongTimeoutMs;
147
150
  this.debug = normalized.debug;
148
151
  this.getAccessToken = options.getAccessToken;
152
+ this.anonymous = options.anonymous === true;
149
153
  this.WebSocketImpl = options.WebSocketImpl ?? WebSocket;
150
154
  }
151
155
  on(type, handler) {
@@ -481,6 +485,9 @@ var WebsocketClient = class {
481
485
  });
482
486
  };
483
487
  }
488
+ isRoomLive(room) {
489
+ return this.state === "open" && this.roomSubscriptions.get(room)?.subscribed === true;
490
+ }
484
491
  subscribeRooms(rooms) {
485
492
  return this.retainRooms(rooms);
486
493
  }
@@ -518,11 +525,11 @@ var WebsocketClient = class {
518
525
  const forceRefresh = this.forceRefreshOnNextAuth;
519
526
  this.forceRefreshOnNextAuth = false;
520
527
  const token = this.getAccessToken ? await this.getAccessToken(forceRefresh ? { forceRefresh: true } : void 0) : null;
521
- if (!token) throw new WebsocketAuthError("missing access token");
528
+ if (!token && !this.anonymous) throw new WebsocketAuthError("missing access token");
522
529
  const waiter = this.createAuthWaiter();
523
530
  this.send({
524
531
  type: "auth",
525
- payload: {
532
+ payload: token ? {
526
533
  token,
527
534
  capabilities: [
528
535
  WS_COMPACT_STREAM_CAPABILITY,
@@ -531,6 +538,9 @@ var WebsocketClient = class {
531
538
  WS_REALTIME_ROOM_CAPABILITY,
532
539
  WS_REALTIME_ROOM_HISTORY_CAPABILITY
533
540
  ]
541
+ } : {
542
+ anonymous: true,
543
+ capabilities: [WS_ROOM_SUBSCRIPTION_CAPABILITY]
534
544
  }
535
545
  });
536
546
  await waiter.promise;
@@ -554,6 +564,8 @@ var WebsocketClient = class {
554
564
  this.flushRoomSubscriptions();
555
565
  }
556
566
  resetRoomSubscriptions() {
567
+ if (this.resubscribeTimer) clearTimeout(this.resubscribeTimer);
568
+ this.resubscribeTimer = null;
557
569
  for (const state of this.roomSubscriptions.values()) {
558
570
  state.subscribed = false;
559
571
  state.pending = false;
@@ -633,6 +645,7 @@ var WebsocketClient = class {
633
645
  this.emit("auth", {
634
646
  connectionId,
635
647
  user,
648
+ anonymous: envelope.payload.anonymous === true,
636
649
  capabilities
637
650
  });
638
651
  }
@@ -703,6 +716,7 @@ var WebsocketClient = class {
703
716
  state.pending = false;
704
717
  }
705
718
  }
719
+ if (rooms.length > 0) this.resubscribeAttempt = 0;
706
720
  this.emit("subscribed", {
707
721
  rooms,
708
722
  requestId: envelope.requestId ?? null
@@ -717,11 +731,18 @@ var WebsocketClient = class {
717
731
  code: typeof entry.code === "string" ? entry.code : "UNKNOWN",
718
732
  message: typeof entry.message === "string" ? entry.message : "Subscription failed"
719
733
  })).filter((entry) => entry.room) : [];
734
+ let retry = false;
720
735
  for (const item of rejected) {
721
736
  const room = normalizeRealtimeRooms([item.room])[0];
722
737
  if (!room) continue;
723
- this.roomSubscriptions.delete(room);
738
+ const state = this.roomSubscriptions.get(room);
739
+ if (state && item.code === "UNAVAILABLE") {
740
+ state.subscribed = false;
741
+ state.pending = false;
742
+ retry = true;
743
+ } else this.roomSubscriptions.delete(room);
724
744
  }
745
+ if (retry) this.scheduleResubscribe();
725
746
  this.emit("subscribeError", {
726
747
  rejected,
727
748
  requestId: envelope.requestId ?? null
@@ -900,10 +921,21 @@ var WebsocketClient = class {
900
921
  resolve();
901
922
  }
902
923
  }
924
+ backoff(attempt) {
925
+ return Math.min(this.reconnectBaseDelayMs * 2 ** attempt, this.reconnectMaxDelayMs);
926
+ }
927
+ scheduleResubscribe() {
928
+ if (this.resubscribeTimer) return;
929
+ this.resubscribeTimer = setTimeout(() => {
930
+ this.resubscribeTimer = null;
931
+ this.flushRoomSubscriptions();
932
+ }, this.backoff(this.resubscribeAttempt));
933
+ this.resubscribeAttempt += 1;
934
+ }
903
935
  async scheduleReconnect(code, reason) {
904
936
  this.clearReconnectTimer();
905
937
  const attempt = this.reconnectAttempt + 1;
906
- const delay = Math.min(this.reconnectBaseDelayMs * 2 ** this.reconnectAttempt, this.reconnectMaxDelayMs);
938
+ const delay = this.backoff(this.reconnectAttempt);
907
939
  this.reconnectAttempt = attempt;
908
940
  this.state = "reconnecting";
909
941
  this.log("schedule reconnect", {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neta-art/cohub",
3
- "version": "12.5.0",
3
+ "version": "12.6.0",
4
4
  "description": "Cohub SDK for spaces, sessions, boards, and realtime agent collaboration.",
5
5
  "license": "Apache-2.0",
6
6
  "private": false,