@neta-art/cohub 1.33.0 → 1.33.1

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.
@@ -1,3 +1,4 @@
1
+ import { r as getRealtimeSpaceRoom } from "./types.js";
1
2
  import { a as resolveApiBaseUrl } from "./environment.js";
2
3
  //#region src/apis/channels.ts
3
4
  var ChannelsApi = class {
@@ -928,6 +929,7 @@ var SessionGenerationStreamClient = class SessionGenerationStreamClient {
928
929
  let recoveryAborted = false;
929
930
  let bufferedEvents = [];
930
931
  let bufferedEventsReplayed = false;
932
+ const releaseRoom = this.websocketClient.retainRooms([getRealtimeSpaceRoom(this.spaceId)]);
931
933
  const unsubscribe = this.websocketClient.on("event", (event) => {
932
934
  if (event.spaceId !== this.spaceId || event.sessionId !== this.sessionId) return;
933
935
  if (recovering && isGenerationRealtimeEvent(event)) {
@@ -952,6 +954,7 @@ var SessionGenerationStreamClient = class SessionGenerationStreamClient {
952
954
  return () => {
953
955
  disposed = true;
954
956
  unsubscribe();
957
+ releaseRoom();
955
958
  };
956
959
  }
957
960
  async recoverFromSnapshot(handlers, options, shouldContinue) {
@@ -1529,6 +1532,7 @@ var SessionRealtimeClient = class {
1529
1532
  subscribe(handlers) {
1530
1533
  if (!this.websocketClient) throw new Error("realtime transport is not configured for this client");
1531
1534
  ensureRealtimeConnected(this.websocketClient);
1535
+ const releaseRoom = this.websocketClient.retainRooms([getRealtimeSpaceRoom(this.spaceId)]);
1532
1536
  const unsubscribe = this.websocketClient.on("event", (event) => {
1533
1537
  if (event.spaceId !== this.spaceId || event.sessionId !== this.sessionId) return;
1534
1538
  handlers.event?.(event);
@@ -1577,7 +1581,10 @@ var SessionRealtimeClient = class {
1577
1581
  turnId: getPersistedMessageTurnId(event)
1578
1582
  });
1579
1583
  });
1580
- return () => unsubscribe();
1584
+ return () => {
1585
+ unsubscribe();
1586
+ releaseRoom();
1587
+ };
1581
1588
  }
1582
1589
  on(type, handler) {
1583
1590
  return this.subscribe({ event: (event) => {
@@ -1691,10 +1698,15 @@ var SpaceEventsApi = class {
1691
1698
  subscribe(handler) {
1692
1699
  if (!this.websocketClient) throw new Error("realtime transport is not configured for this client");
1693
1700
  ensureRealtimeConnected(this.websocketClient);
1694
- return this.websocketClient.on("event", (event) => {
1701
+ const releaseRoom = this.websocketClient.retainRooms([getRealtimeSpaceRoom(this.spaceId)]);
1702
+ const offEvent = this.websocketClient.on("event", (event) => {
1695
1703
  if (event.spaceId !== this.spaceId) return;
1696
1704
  handler(event);
1697
1705
  });
1706
+ return () => {
1707
+ offEvent();
1708
+ releaseRoom();
1709
+ };
1698
1710
  }
1699
1711
  on(type, handler) {
1700
1712
  return this.subscribe((event) => {
@@ -0,0 +1,37 @@
1
+ //#region ../protocol/src/realtime/types.ts
2
+ const WS_COMPACT_STREAM_CAPABILITY = "session.compact_stream.v1";
3
+ const WS_ROOM_SUBSCRIPTION_CAPABILITY = "realtime.rooms.v1";
4
+ const getRealtimeSpaceRoom = (spaceId) => `space:${spaceId}`;
5
+ const parseRealtimeRoom = (room) => {
6
+ const trimmed = room.trim();
7
+ const separatorIndex = trimmed.indexOf(":");
8
+ if (separatorIndex <= 0) return null;
9
+ const kind = trimmed.slice(0, separatorIndex);
10
+ const id = trimmed.slice(separatorIndex + 1).trim();
11
+ if (!id) return null;
12
+ if (kind !== "space" && kind !== "user") return null;
13
+ return {
14
+ kind,
15
+ id
16
+ };
17
+ };
18
+ const normalizeRealtimeRooms = (rooms) => {
19
+ const normalized = /* @__PURE__ */ new Set();
20
+ for (const room of rooms) {
21
+ const parsed = typeof room === "string" ? parseRealtimeRoom(room) : null;
22
+ if (!parsed) continue;
23
+ normalized.add(`${parsed.kind}:${parsed.id}`);
24
+ }
25
+ return [...normalized];
26
+ };
27
+ const getNonEmptyString = (value) => typeof value === "string" && value.trim() ? value : null;
28
+ const getSessionTurnPatchStreamKey = (input, options = {}) => {
29
+ const turnId = getNonEmptyString(input.turnId);
30
+ const messageKey = getNonEmptyString(input.messageId) ?? getNonEmptyString(input.sourceMessageId) ?? getNonEmptyString(input.anchorUserMessageId) ?? (typeof input.messageOrdinal === "number" && Number.isFinite(input.messageOrdinal) ? `ordinal:${input.messageOrdinal}` : null);
31
+ if (turnId && messageKey) return `${turnId}:${messageKey}`;
32
+ const streamKey = messageKey ?? turnId;
33
+ if (streamKey) return streamKey;
34
+ return options.includeSessionFallback ? getNonEmptyString(input.sessionId) : null;
35
+ };
36
+ //#endregion
37
+ export { normalizeRealtimeRooms as a, getSessionTurnPatchStreamKey as i, WS_ROOM_SUBSCRIPTION_CAPABILITY as n, getRealtimeSpaceRoom as r, WS_COMPACT_STREAM_CAPABILITY as t };
@@ -275,6 +275,7 @@ type SpacePublicEndpoint = {
275
275
  type SpacePublicEndpoints = Record<string, SpacePublicEndpoint>;
276
276
  //#endregion
277
277
  //#region ../protocol/src/realtime/types.d.ts
278
+ type RealtimeRoom = `space:${string}` | `user:${string}`;
278
279
  type RealtimeEnvelope = {
279
280
  id: string;
280
281
  timestamp: number;
@@ -283,6 +284,7 @@ type RealtimeEnvelope = {
283
284
  requestId?: string | null;
284
285
  spaceId?: string | null;
285
286
  sessionId?: string | null;
287
+ rooms?: RealtimeRoom[];
286
288
  payload: Record<string, unknown>;
287
289
  };
288
290
  type ChannelEnvelope = RealtimeEnvelope;
@@ -346,6 +348,34 @@ type SystemAckOkEvent = {
346
348
  eventId?: string;
347
349
  };
348
350
  };
351
+ type SystemSubscribeOkEvent = {
352
+ id: string;
353
+ timestamp: number;
354
+ domain: "system";
355
+ type: "system.subscribe.ok";
356
+ requestId?: string | null;
357
+ spaceId?: string | null;
358
+ sessionId?: string | null;
359
+ payload: {
360
+ rooms: RealtimeRoom[];
361
+ };
362
+ };
363
+ type SystemSubscribeErrorEvent = {
364
+ id: string;
365
+ timestamp: number;
366
+ domain: "system";
367
+ type: "system.subscribe.error";
368
+ requestId?: string | null;
369
+ spaceId?: string | null;
370
+ sessionId?: string | null;
371
+ payload: {
372
+ rejected: Array<{
373
+ room: string;
374
+ code: "BAD_ROOM" | "FORBIDDEN";
375
+ message: string;
376
+ }>;
377
+ };
378
+ };
349
379
  type RealtimeSessionRecord = Pick<SessionRecord, "id" | "spaceId" | "userUuid" | "title" | "source" | "status" | "externalSessionId" | "latestMessageText" | "lastMessageAt" | "lastMessageId" | "createdAt" | "updatedAt">;
350
380
  type SessionCreatedEvent = {
351
381
  id: string;
@@ -651,7 +681,7 @@ type LabelAssignmentsUpdatedEvent = {
651
681
  affectedLabelIds: string[];
652
682
  };
653
683
  };
654
- type RealtimeServerEvent = SystemReadyEvent | SystemAuthOkEvent | SystemRequestErrorEvent | SystemPongEvent | SystemAckOkEvent | SessionCreatedEvent | SessionUpdatedEvent | SessionRequestAcceptedEvent | SessionRequestErrorEvent | SessionTurnCreatedEvent | SessionTurnPatchEvent | SessionTurnErrorEvent | SessionTurnLifecycleEvent | SessionTurnUpdatedEvent | SessionTurnFinalizedEvent | SessionMessagePersistedEvent | SpaceFsChangedEvent | SpacePortsChangedEvent | CanvasTransactionAppliedEvent | CanvasTransactionAckEvent | CanvasTransactionErrorEvent | TaskCreatedEvent | TaskUpdatedEvent | LabelAssignmentsUpdatedEvent;
684
+ type RealtimeServerEvent = SystemReadyEvent | SystemAuthOkEvent | SystemRequestErrorEvent | SystemPongEvent | SystemAckOkEvent | SystemSubscribeOkEvent | SystemSubscribeErrorEvent | SessionCreatedEvent | SessionUpdatedEvent | SessionRequestAcceptedEvent | SessionRequestErrorEvent | SessionTurnCreatedEvent | SessionTurnPatchEvent | SessionTurnErrorEvent | SessionTurnLifecycleEvent | SessionTurnUpdatedEvent | SessionTurnFinalizedEvent | SessionMessagePersistedEvent | SpaceFsChangedEvent | SpacePortsChangedEvent | CanvasTransactionAppliedEvent | CanvasTransactionAckEvent | CanvasTransactionErrorEvent | TaskCreatedEvent | TaskUpdatedEvent | LabelAssignmentsUpdatedEvent;
655
685
  //#endregion
656
686
  //#region src/websocket.d.ts
657
687
  type WebsocketEventPayload = ChannelEnvelope;
@@ -726,6 +756,18 @@ type WebsocketClientEvents = {
726
756
  spaceId?: string | null;
727
757
  clientMessageId?: string | null;
728
758
  };
759
+ subscribed: {
760
+ rooms: RealtimeRoom[];
761
+ requestId?: string | null;
762
+ };
763
+ subscribeError: {
764
+ rejected: Array<{
765
+ room: string;
766
+ code: string;
767
+ message: string;
768
+ }>;
769
+ requestId?: string | null;
770
+ };
729
771
  pong: {
730
772
  requestId?: string | null;
731
773
  };
@@ -754,6 +796,7 @@ declare class WebsocketClient {
754
796
  private pongDeadlineAt;
755
797
  private readonly compactStreamContexts;
756
798
  private readonly patchStreamBuffers;
799
+ private readonly roomSubscriptions;
757
800
  state: WebsocketClientState;
758
801
  connectionId: string | null;
759
802
  private readonly listeners;
@@ -783,11 +826,16 @@ declare class WebsocketClient {
783
826
  model?: string;
784
827
  provider?: string;
785
828
  }): Promise<void>;
829
+ retainRooms(rooms: readonly string[]): () => void;
830
+ subscribeRooms(rooms: readonly string[]): () => void;
831
+ subscribeSpace(spaceId: string): () => void;
786
832
  ack(eventId?: string, requestId?: string): void;
787
833
  ping(requestId?: string): void;
788
834
  private ensureOpen;
789
835
  private send;
790
836
  private authenticate;
837
+ private flushRoomSubscriptions;
838
+ private restoreRoomSubscriptions;
791
839
  private createAuthWaiter;
792
840
  private resolveAuthWaiter;
793
841
  private rejectAuthWaiter;
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { C as ChannelsApi, S as CronJobsApi, _ as SearchApi, a as TasksApi, b as ModelsApi, c as PublicInviteApi, d as parseAssistantMessageCommit, f as SessionPatchReducer, g as SessionAccessApi, h as HttpTransport, i as UserApi, l as SessionGenerationStreamClient, m as HttpError, n as createHttpClient, o as SpaceClient, p as createSessionPatchReducer, r as WorksApi, s as SpacesApi, t as CohubHttpClient, u as createSessionGenerationStreamClient, v as PublicAssetsApi, x as GenerationsApi, y as PromptsApi } from "./chunks/http.js";
2
2
  import { a as resolveApiBaseUrl, c as resolveWebsocketUrl, i as normalizeWebsocketUrl, n as normalizeBaseUrl, o as resolveCohubEnvironment, r as normalizeVoiceInputWebsocketUrl, s as resolveVoiceInputWebsocketUrl, t as COHUB_ENVIRONMENTS } from "./chunks/environment.js";
3
- import { n as createWebsocketClient, t as WebsocketClient } from "./chunks/websocket.js";
3
+ import { WebsocketClient, createWebsocketClient } from "./websocket.js";
4
4
  import { VoiceApi, VoiceInputClient, createVoiceInputClient } from "./voice-input.js";
5
5
  //#region src/apis/billing.ts
6
6
  var BillingApi = class {