@neta-art/cohub 1.8.0 → 1.10.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.
Files changed (51) hide show
  1. package/README.md +6 -105
  2. package/dist/chunks/environment.js +33 -0
  3. package/dist/chunks/http.d.ts +1615 -0
  4. package/dist/chunks/http.js +1919 -0
  5. package/dist/chunks/websocket.d.ts +266 -0
  6. package/dist/chunks/websocket.js +655 -0
  7. package/dist/http.d.ts +3 -30
  8. package/dist/http.js +2 -45
  9. package/dist/index.d.ts +35 -14
  10. package/dist/index.js +105 -8
  11. package/dist/websocket.d.ts +2 -141
  12. package/dist/websocket.js +2 -628
  13. package/package.json +7 -7
  14. package/dist/apis/channels.d.ts +0 -13
  15. package/dist/apis/channels.js +0 -24
  16. package/dist/apis/cron-jobs.d.ts +0 -18
  17. package/dist/apis/cron-jobs.js +0 -25
  18. package/dist/apis/explore.d.ts +0 -9
  19. package/dist/apis/explore.js +0 -9
  20. package/dist/apis/generations.d.ts +0 -8
  21. package/dist/apis/generations.js +0 -16
  22. package/dist/apis/invitations.d.ts +0 -20
  23. package/dist/apis/invitations.js +0 -36
  24. package/dist/apis/models.d.ts +0 -7
  25. package/dist/apis/models.js +0 -9
  26. package/dist/apis/prompts.d.ts +0 -9
  27. package/dist/apis/prompts.js +0 -16
  28. package/dist/apis/search.d.ts +0 -10
  29. package/dist/apis/search.js +0 -14
  30. package/dist/apis/session-access.d.ts +0 -13
  31. package/dist/apis/session-access.js +0 -19
  32. package/dist/apis/spaces.d.ts +0 -371
  33. package/dist/apis/spaces.js +0 -766
  34. package/dist/apis/tasks.d.ts +0 -13
  35. package/dist/apis/tasks.js +0 -18
  36. package/dist/apis/user.d.ts +0 -27
  37. package/dist/apis/user.js +0 -71
  38. package/dist/client.d.ts +0 -33
  39. package/dist/client.js +0 -103
  40. package/dist/environment.d.ts +0 -22
  41. package/dist/environment.js +0 -37
  42. package/dist/realtime.d.ts +0 -2
  43. package/dist/realtime.js +0 -8
  44. package/dist/session-generation-stream.d.ts +0 -114
  45. package/dist/session-generation-stream.js +0 -514
  46. package/dist/session-patch-reducer.d.ts +0 -61
  47. package/dist/session-patch-reducer.js +0 -432
  48. package/dist/transport.d.ts +0 -40
  49. package/dist/transport.js +0 -78
  50. package/dist/types.d.ts +0 -535
  51. package/dist/types.js +0 -1
package/dist/websocket.js CHANGED
@@ -1,628 +1,2 @@
1
- import { getSessionTurnPatchStreamKey, realtimeCompactFrameSchema, realtimeEnvelopeSchema, WS_COMPACT_STREAM_CAPABILITY, } from "@neta-art/cohub-protocol/realtime";
2
- import { resolveWebsocketUrl } from "./environment.js";
3
- const createEventMap = () => ({
4
- connecting: new Set(),
5
- reconnecting: new Set(),
6
- open: new Set(),
7
- close: new Set(),
8
- error: new Set(),
9
- event: new Set(),
10
- ready: new Set(),
11
- auth: new Set(),
12
- messageAccepted: new Set(),
13
- serverError: new Set(),
14
- pong: new Set(),
15
- });
16
- const toWebSocketUrl = (input, env) => resolveWebsocketUrl({ url: input, env });
17
- const normalizeOptions = (options = {}) => ({
18
- url: toWebSocketUrl(options.url, options.env),
19
- autoReconnect: options.autoReconnect !== false,
20
- reconnectBaseDelayMs: options.reconnectBaseDelayMs ?? 1000,
21
- reconnectMaxDelayMs: options.reconnectMaxDelayMs ?? 15000,
22
- pingIntervalMs: options.pingIntervalMs ?? 20000,
23
- pongTimeoutMs: options.pongTimeoutMs ?? 15000,
24
- debug: options.debug === true,
25
- });
26
- const formatCloseMessage = (code, reason) => `WebSocket closed: ${code ?? 0} ${reason || ""}`.trim();
27
- const isRetryableCloseCode = (code) => {
28
- if (code === 1000)
29
- return false;
30
- if (code === 4003)
31
- return false;
32
- return true;
33
- };
34
- const AUTH_CLOSE_REASON = "authentication failed";
35
- const PATCH_STREAM_BUFFER_MAX_PENDING = 128;
36
- const isRecord = (value) => Boolean(value && typeof value === "object" && !Array.isArray(value));
37
- const compactFrameToPatchOperation = (frame) => {
38
- if (frame.t === "d")
39
- return { v: frame.v };
40
- if (frame.o === "remove")
41
- return { o: "remove", p: frame.p };
42
- if (frame.o === "merge") {
43
- return isRecord(frame.v) ? { o: "merge", p: frame.p, v: frame.v } : null;
44
- }
45
- if (!("v" in frame))
46
- return null;
47
- switch (frame.o) {
48
- case "append":
49
- return { o: "append", p: frame.p, v: frame.v };
50
- case "replace":
51
- return { o: "replace", p: frame.p, v: frame.v };
52
- case "add":
53
- return { o: "add", p: frame.p, v: frame.v };
54
- default:
55
- return null;
56
- }
57
- };
58
- class WebsocketAuthError extends Error {
59
- constructor(message) {
60
- super(message);
61
- this.name = "WebsocketAuthError";
62
- }
63
- }
64
- export class WebsocketClient {
65
- url;
66
- autoReconnect;
67
- reconnectBaseDelayMs;
68
- reconnectMaxDelayMs;
69
- pingIntervalMs;
70
- pongTimeoutMs;
71
- debug;
72
- getAccessToken;
73
- WebSocketImpl;
74
- ws = null;
75
- pingTimer = null;
76
- reconnectTimer = null;
77
- reconnectTimerResolver = null;
78
- reconnectAttempt = 0;
79
- manuallyClosed = false;
80
- connectPromise = null;
81
- authWaiter = null;
82
- awaitingPong = false;
83
- lastPingRequestId = null;
84
- pongDeadlineAt = 0;
85
- compactStreamContexts = new Map();
86
- patchStreamBuffers = new Map();
87
- state = "idle";
88
- connectionId = null;
89
- listeners = createEventMap();
90
- constructor(options = {}) {
91
- const normalized = normalizeOptions(options);
92
- this.url = normalized.url;
93
- this.autoReconnect = normalized.autoReconnect;
94
- this.reconnectBaseDelayMs = normalized.reconnectBaseDelayMs;
95
- this.reconnectMaxDelayMs = normalized.reconnectMaxDelayMs;
96
- this.pingIntervalMs = normalized.pingIntervalMs;
97
- this.pongTimeoutMs = normalized.pongTimeoutMs;
98
- this.debug = normalized.debug;
99
- this.getAccessToken = options.getAccessToken;
100
- this.WebSocketImpl = options.WebSocketImpl ?? WebSocket;
101
- }
102
- on(type, handler) {
103
- this.listeners[type].add(handler);
104
- return () => this.off(type, handler);
105
- }
106
- off(type, handler) {
107
- this.listeners[type].delete(handler);
108
- }
109
- emit(type, payload) {
110
- for (const handler of this.listeners[type]) {
111
- handler(payload);
112
- }
113
- }
114
- log(...args) {
115
- if (this.debug)
116
- console.log("[WebsocketClient]", ...args);
117
- }
118
- async connect() {
119
- if (this.connectPromise)
120
- return this.connectPromise;
121
- if (this.state === "open" && this.ws?.readyState === WebSocket.OPEN)
122
- return;
123
- const isReconnect = this.reconnectAttempt > 0 || this.state === "reconnecting";
124
- this.manuallyClosed = false;
125
- this.clearReconnectTimer();
126
- this.state = isReconnect ? "reconnecting" : "connecting";
127
- this.emit("connecting", { isReconnect, attempt: this.reconnectAttempt });
128
- this.connectPromise = new Promise((resolve, reject) => {
129
- const ws = new this.WebSocketImpl(this.url);
130
- this.ws = ws;
131
- let settled = false;
132
- const rejectOnce = (error) => {
133
- if (settled)
134
- return;
135
- settled = true;
136
- this.connectPromise = null;
137
- reject(error);
138
- };
139
- const resolveOnce = () => {
140
- if (settled)
141
- return;
142
- settled = true;
143
- this.connectPromise = null;
144
- resolve();
145
- };
146
- ws.onopen = async () => {
147
- try {
148
- this.log("connected", { url: this.url, isReconnect, attempt: this.reconnectAttempt });
149
- this.startPingLoop();
150
- await this.authenticate();
151
- this.state = "open";
152
- this.reconnectAttempt = 0;
153
- this.emit("open", { connectionId: this.connectionId });
154
- resolveOnce();
155
- }
156
- catch (error) {
157
- const authError = error instanceof Error ? error : new Error("authentication failed");
158
- this.emit("error", { error: authError, recoverable: false });
159
- rejectOnce(authError);
160
- ws.close(4003, AUTH_CLOSE_REASON);
161
- }
162
- };
163
- ws.onmessage = (event) => {
164
- this.handleMessage(event.data);
165
- };
166
- ws.onerror = (error) => {
167
- this.emit("error", { error, recoverable: !this.manuallyClosed });
168
- };
169
- ws.onclose = (event) => {
170
- this.stopPingLoop();
171
- const wasConnecting = this.state === "connecting" || this.state === "reconnecting";
172
- this.state = "closed";
173
- this.ws = null;
174
- this.compactStreamContexts.clear();
175
- this.patchStreamBuffers.clear();
176
- const closeError = new Error(formatCloseMessage(event.code, event.reason));
177
- this.rejectAuthWaiter(closeError);
178
- const willReconnect = !this.manuallyClosed && this.autoReconnect && isRetryableCloseCode(event.code);
179
- this.log("closed", { code: event.code, reason: event.reason, willReconnect, wasConnecting });
180
- this.emit("close", {
181
- code: event.code,
182
- reason: event.reason,
183
- willReconnect,
184
- });
185
- if (wasConnecting) {
186
- rejectOnce(closeError);
187
- }
188
- if (willReconnect) {
189
- void this.scheduleReconnect(event.code, event.reason);
190
- }
191
- };
192
- });
193
- return this.connectPromise;
194
- }
195
- async disconnect(code = 1000, reason = "manual") {
196
- this.manuallyClosed = true;
197
- this.clearReconnectTimer();
198
- this.stopPingLoop();
199
- this.state = "closed";
200
- this.rejectAuthWaiter(new Error("disconnected"));
201
- this.ws?.close(code, reason);
202
- this.ws = null;
203
- this.connectPromise = null;
204
- this.compactStreamContexts.clear();
205
- this.patchStreamBuffers.clear();
206
- }
207
- async sendMessage(input) {
208
- await this.ensureOpen();
209
- this.send({
210
- type: "session.message.create",
211
- requestId: input.requestId,
212
- payload: {
213
- spaceId: input.spaceId,
214
- sessionId: input.sessionId,
215
- content: input.content,
216
- clientMessageId: input.clientMessageId,
217
- model: input.model,
218
- provider: input.provider,
219
- },
220
- });
221
- }
222
- ack(eventId, requestId) {
223
- this.send({
224
- type: "ack",
225
- requestId,
226
- payload: eventId ? { eventId } : undefined,
227
- });
228
- }
229
- ping(requestId) {
230
- const effectiveRequestId = requestId ?? `ping-${Date.now()}`;
231
- this.awaitingPong = true;
232
- this.lastPingRequestId = effectiveRequestId;
233
- this.pongDeadlineAt = Date.now() + this.pongTimeoutMs;
234
- this.send({ type: "ping", requestId: effectiveRequestId, payload: {} });
235
- }
236
- async ensureOpen() {
237
- if (this.state === "open" && this.ws?.readyState === WebSocket.OPEN)
238
- return;
239
- await this.connect();
240
- }
241
- send(event) {
242
- const ws = this.ws;
243
- if (!ws || ws.readyState !== WebSocket.OPEN) {
244
- throw new Error("websocket is not open");
245
- }
246
- ws.send(JSON.stringify(event));
247
- }
248
- async authenticate() {
249
- const token = this.getAccessToken ? await this.getAccessToken() : null;
250
- if (!token)
251
- throw new WebsocketAuthError("missing access token");
252
- const waiter = this.createAuthWaiter();
253
- this.send({
254
- type: "auth",
255
- payload: { token, capabilities: [WS_COMPACT_STREAM_CAPABILITY] },
256
- });
257
- await waiter.promise;
258
- }
259
- createAuthWaiter() {
260
- this.rejectAuthWaiter(new Error("superseded auth waiter"));
261
- let resolve;
262
- let reject;
263
- const promise = new Promise((res, rej) => {
264
- resolve = res;
265
- reject = rej;
266
- });
267
- this.authWaiter = { promise, resolve, reject };
268
- return this.authWaiter;
269
- }
270
- resolveAuthWaiter() {
271
- if (!this.authWaiter)
272
- return;
273
- this.authWaiter.resolve();
274
- this.authWaiter = null;
275
- }
276
- rejectAuthWaiter(error) {
277
- if (!this.authWaiter)
278
- return;
279
- this.authWaiter.reject(error);
280
- this.authWaiter = null;
281
- }
282
- handleMessage(raw) {
283
- let parsed;
284
- try {
285
- parsed = typeof raw === "string" ? JSON.parse(raw) : JSON.parse(String(raw));
286
- }
287
- catch {
288
- this.emit("error", { error: new Error("invalid websocket payload"), recoverable: true });
289
- return;
290
- }
291
- const compactResult = realtimeCompactFrameSchema.safeParse(parsed);
292
- if (compactResult.success) {
293
- this.handleCompactFrame(compactResult.data);
294
- return;
295
- }
296
- const result = realtimeEnvelopeSchema.safeParse(parsed);
297
- if (!result.success) {
298
- this.emit("error", { error: new Error("invalid realtime envelope"), recoverable: true });
299
- return;
300
- }
301
- const envelope = result.data;
302
- this.rememberCompactStreamContext(envelope);
303
- if (envelope.type === "session.turn.patch") {
304
- this.handlePatchEnvelope(envelope);
305
- return;
306
- }
307
- switch (envelope.type) {
308
- case "system.ready": {
309
- const connectionId = typeof envelope.payload.connectionId === "string"
310
- ? envelope.payload.connectionId
311
- : null;
312
- if (connectionId) {
313
- this.connectionId = connectionId;
314
- this.emit("ready", { connectionId });
315
- }
316
- this.emit("event", envelope);
317
- return;
318
- }
319
- case "system.auth.ok": {
320
- const connectionId = typeof envelope.payload.connectionId === "string"
321
- ? envelope.payload.connectionId
322
- : this.connectionId;
323
- const user = envelope.payload.user && typeof envelope.payload.user === "object"
324
- ? envelope.payload.user
325
- : {};
326
- if (connectionId) {
327
- this.connectionId = connectionId;
328
- this.emit("auth", { connectionId, user });
329
- }
330
- this.resolveAuthWaiter();
331
- this.emit("event", envelope);
332
- return;
333
- }
334
- case "system.request.error": {
335
- const message = typeof envelope.payload.message === "string"
336
- ? envelope.payload.message
337
- : "request failed";
338
- const code = typeof envelope.payload.code === "string"
339
- ? envelope.payload.code
340
- : undefined;
341
- const error = new WebsocketAuthError(message);
342
- this.rejectAuthWaiter(error);
343
- this.emit("serverError", {
344
- code,
345
- message,
346
- requestId: envelope.requestId ?? null,
347
- sessionId: envelope.sessionId ?? null,
348
- spaceId: envelope.spaceId ?? null,
349
- });
350
- this.emit("event", envelope);
351
- return;
352
- }
353
- case "session.request.accepted": {
354
- const payload = envelope.payload;
355
- this.emit("messageAccepted", {
356
- requestId: envelope.requestId ?? null,
357
- sessionId: envelope.sessionId ?? null,
358
- spaceId: envelope.spaceId ?? null,
359
- clientMessageId: typeof payload.clientMessageId === "string" ? payload.clientMessageId : null,
360
- });
361
- this.emit("event", envelope);
362
- return;
363
- }
364
- case "session.request.error": {
365
- const payload = envelope.payload;
366
- this.emit("serverError", {
367
- code: typeof payload.code === "string" ? payload.code : undefined,
368
- message: typeof payload.message === "string" ? payload.message : undefined,
369
- requestId: envelope.requestId ?? null,
370
- sessionId: envelope.sessionId ?? null,
371
- spaceId: envelope.spaceId ?? null,
372
- clientMessageId: typeof payload.clientMessageId === "string" ? payload.clientMessageId : null,
373
- });
374
- this.emit("event", envelope);
375
- return;
376
- }
377
- case "system.pong": {
378
- const requestId = envelope.requestId ?? null;
379
- if (!requestId || requestId === this.lastPingRequestId) {
380
- this.awaitingPong = false;
381
- this.lastPingRequestId = null;
382
- this.pongDeadlineAt = 0;
383
- }
384
- this.emit("pong", { requestId });
385
- return;
386
- }
387
- case "system.ack.ok": {
388
- return;
389
- }
390
- default: {
391
- this.emit("event", envelope);
392
- return;
393
- }
394
- }
395
- }
396
- rememberCompactStreamContext(envelope) {
397
- if (envelope.type === "session.turn.patch") {
398
- const payload = envelope.payload;
399
- const turnId = typeof payload.turnId === "string" ? payload.turnId : null;
400
- const messageId = typeof payload.messageId === "string" ? payload.messageId : null;
401
- const realtimeMeta = payload._rt && typeof payload._rt === "object"
402
- ? payload._rt
403
- : null;
404
- const sid = typeof realtimeMeta?.sid === "string" && realtimeMeta.sid.trim()
405
- ? realtimeMeta.sid
406
- : turnId ?? messageId;
407
- if (!sid)
408
- return;
409
- this.compactStreamContexts.set(sid, {
410
- spaceId: envelope.spaceId ?? null,
411
- sessionId: envelope.sessionId ?? null,
412
- turnId,
413
- messageId,
414
- messageOrdinal: typeof payload.messageOrdinal === "number"
415
- ? payload.messageOrdinal
416
- : null,
417
- anchorUserMessageId: typeof payload.anchorUserMessageId === "string"
418
- ? payload.anchorUserMessageId
419
- : null,
420
- });
421
- return;
422
- }
423
- if (envelope.type !== "session.message.persisted")
424
- return;
425
- const message = envelope.payload.message;
426
- if (!message || typeof message !== "object")
427
- return;
428
- const meta = message.meta;
429
- const turnId = typeof meta?.turnId === "string" ? meta.turnId : null;
430
- if (!turnId)
431
- return;
432
- for (const [sid, context] of this.compactStreamContexts.entries()) {
433
- if (context.turnId === turnId) {
434
- this.compactStreamContexts.delete(sid);
435
- this.patchStreamBuffers.delete(sid);
436
- }
437
- }
438
- }
439
- getPatchStreamBufferKey(envelope) {
440
- if (envelope.type !== "session.turn.patch")
441
- return null;
442
- const payload = envelope.payload;
443
- const realtimeMeta = payload._rt && typeof payload._rt === "object"
444
- ? payload._rt
445
- : null;
446
- if (typeof realtimeMeta?.sid === "string" && realtimeMeta.sid.trim()) {
447
- return realtimeMeta.sid;
448
- }
449
- return getSessionTurnPatchStreamKey(payload, { includeSessionFallback: true });
450
- }
451
- handlePatchEnvelope(envelope) {
452
- const payload = envelope.payload;
453
- if (typeof payload.seq !== "number" ||
454
- typeof payload.baseSeq !== "number" ||
455
- !Number.isInteger(payload.seq) ||
456
- !Number.isInteger(payload.baseSeq) ||
457
- payload.seq < 0 ||
458
- payload.baseSeq < 0) {
459
- this.emit("event", envelope);
460
- return;
461
- }
462
- const key = this.getPatchStreamBufferKey(envelope);
463
- if (!key) {
464
- this.emit("event", envelope);
465
- return;
466
- }
467
- if (payload.baseSeq === 0) {
468
- const buffer = { nextSeq: payload.seq + 1, pending: new Map() };
469
- this.patchStreamBuffers.set(key, buffer);
470
- this.emit("event", envelope);
471
- this.flushPatchStreamBuffer(buffer);
472
- return;
473
- }
474
- const buffer = this.patchStreamBuffers.get(key);
475
- if (!buffer) {
476
- const newBuffer = {
477
- nextSeq: payload.baseSeq + 1,
478
- pending: new Map([[payload.seq, envelope]]),
479
- };
480
- this.patchStreamBuffers.set(key, newBuffer);
481
- this.flushPatchStreamBuffer(newBuffer);
482
- return;
483
- }
484
- if (payload.seq < buffer.nextSeq)
485
- return;
486
- buffer.pending.set(payload.seq, envelope);
487
- if (!this.enforcePatchStreamBufferLimit(key, buffer))
488
- return;
489
- this.flushPatchStreamBuffer(buffer);
490
- }
491
- enforcePatchStreamBufferLimit(key, buffer) {
492
- if (buffer.pending.size <= PATCH_STREAM_BUFFER_MAX_PENDING)
493
- return true;
494
- this.patchStreamBuffers.delete(key);
495
- this.emit("error", {
496
- error: new Error(`patch stream buffer overflow: ${key}`),
497
- recoverable: true,
498
- });
499
- return false;
500
- }
501
- flushPatchStreamBuffer(buffer) {
502
- while (true) {
503
- const envelope = buffer.pending.get(buffer.nextSeq);
504
- if (!envelope)
505
- return;
506
- const seq = envelope.payload.seq;
507
- if (typeof seq !== "number" || !Number.isInteger(seq))
508
- return;
509
- buffer.pending.delete(buffer.nextSeq);
510
- buffer.nextSeq = seq + 1;
511
- this.emit("event", envelope);
512
- }
513
- }
514
- handleCompactFrame(frame) {
515
- const context = this.compactStreamContexts.get(frame.sid);
516
- if (!context?.sessionId) {
517
- this.emit("error", {
518
- error: new Error(`unknown compact stream: ${frame.sid}`),
519
- recoverable: true,
520
- });
521
- return;
522
- }
523
- const op = compactFrameToPatchOperation(frame);
524
- if (!op) {
525
- this.emit("error", {
526
- error: new Error(`invalid compact stream frame: ${frame.sid}`),
527
- recoverable: true,
528
- });
529
- return;
530
- }
531
- const envelope = {
532
- id: `compact:${frame.sid}:${frame.s}`,
533
- timestamp: Date.now(),
534
- domain: "session",
535
- type: "session.turn.patch",
536
- spaceId: context.spaceId,
537
- sessionId: context.sessionId,
538
- payload: {
539
- turnId: context.turnId,
540
- messageId: context.messageId,
541
- messageOrdinal: context.messageOrdinal,
542
- sourceMessageId: context.messageId,
543
- anchorUserMessageId: context.anchorUserMessageId,
544
- seq: frame.s,
545
- baseSeq: frame.b,
546
- ops: [op],
547
- _rt: { sid: frame.sid },
548
- },
549
- };
550
- this.handlePatchEnvelope(envelope);
551
- }
552
- startPingLoop() {
553
- this.stopPingLoop();
554
- this.pingTimer = setInterval(() => {
555
- if (this.ws?.readyState !== WebSocket.OPEN)
556
- return;
557
- if (this.awaitingPong &&
558
- this.pongDeadlineAt > 0 &&
559
- Date.now() > this.pongDeadlineAt) {
560
- this.emit("error", { error: new Error("websocket pong timeout"), recoverable: true });
561
- this.ws.close(4002, "pong timeout");
562
- return;
563
- }
564
- this.ping();
565
- }, this.pingIntervalMs);
566
- }
567
- stopPingLoop() {
568
- if (this.pingTimer) {
569
- clearInterval(this.pingTimer);
570
- this.pingTimer = null;
571
- }
572
- this.awaitingPong = false;
573
- this.lastPingRequestId = null;
574
- this.pongDeadlineAt = 0;
575
- }
576
- clearReconnectTimer() {
577
- if (this.reconnectTimer) {
578
- clearTimeout(this.reconnectTimer);
579
- this.reconnectTimer = null;
580
- }
581
- if (this.reconnectTimerResolver) {
582
- const resolve = this.reconnectTimerResolver;
583
- this.reconnectTimerResolver = null;
584
- resolve();
585
- }
586
- }
587
- async scheduleReconnect(code, reason) {
588
- this.clearReconnectTimer();
589
- const attempt = this.reconnectAttempt + 1;
590
- const delay = Math.min(this.reconnectBaseDelayMs * 2 ** this.reconnectAttempt, this.reconnectMaxDelayMs);
591
- this.reconnectAttempt = attempt;
592
- this.state = "reconnecting";
593
- this.log("schedule reconnect", { attempt, delay, code, reason });
594
- this.emit("reconnecting", {
595
- attempt,
596
- delayMs: delay,
597
- code,
598
- reason,
599
- });
600
- await new Promise((resolve) => {
601
- this.reconnectTimerResolver = resolve;
602
- this.reconnectTimer = setTimeout(() => {
603
- this.reconnectTimer = null;
604
- this.reconnectTimerResolver = null;
605
- resolve();
606
- }, delay);
607
- });
608
- if (this.manuallyClosed)
609
- return;
610
- if (typeof navigator !== "undefined" && navigator.onLine === false) {
611
- await new Promise((resolve) => {
612
- const fallbackTimer = setTimeout(resolve, this.reconnectMaxDelayMs);
613
- const handleOnline = () => {
614
- clearTimeout(fallbackTimer);
615
- globalThis.removeEventListener?.("online", handleOnline);
616
- resolve();
617
- };
618
- globalThis.addEventListener?.("online", handleOnline, { once: true });
619
- });
620
- if (this.manuallyClosed)
621
- return;
622
- }
623
- await this.connect().catch((error) => {
624
- this.emit("error", { error, recoverable: true });
625
- });
626
- }
627
- }
628
- export const createWebsocketClient = (options) => new WebsocketClient(options);
1
+ import { n as createWebsocketClient, t as WebsocketClient } from "./chunks/websocket.js";
2
+ export { WebsocketClient, createWebsocketClient };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neta-art/cohub",
3
- "version": "1.8.0",
3
+ "version": "1.10.0",
4
4
  "description": "Cohub SDK for spaces, sessions, checkpoints, and realtime agent collaboration.",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,
@@ -43,14 +43,14 @@
43
43
  "dist",
44
44
  "README.md"
45
45
  ],
46
- "dependencies": {
47
- "@neta-art/cohub-protocol": "1.6.0"
48
- },
46
+ "dependencies": {},
49
47
  "devDependencies": {
50
- "typescript": "^6.0.3"
48
+ "tsdown": "^0.22.0",
49
+ "typescript": "^6.0.3",
50
+ "@cohub/protocol": "2.0.0"
51
51
  },
52
52
  "scripts": {
53
- "build": "tsc -p tsconfig.build.json",
54
- "typecheck": "tsc -p tsconfig.json --noEmit"
53
+ "build": "tsdown",
54
+ "typecheck": "tsgo -p tsconfig.json --noEmit"
55
55
  }
56
56
  }
@@ -1,13 +0,0 @@
1
- import type { HttpTransport, Fetch } from "../transport.js";
2
- import type { Channel } from "../types.js";
3
- export declare class ChannelsApi {
4
- private readonly transport;
5
- constructor(transport: HttpTransport);
6
- list(customFetch?: Fetch): Promise<Channel[]>;
7
- create(data: {
8
- provider: string;
9
- name: string;
10
- credentials: Record<string, unknown>;
11
- }): Promise<unknown>;
12
- delete(id: string): Promise<unknown>;
13
- }
@@ -1,24 +0,0 @@
1
- export class ChannelsApi {
2
- transport;
3
- constructor(transport) {
4
- this.transport = transport;
5
- }
6
- list(customFetch) {
7
- return this.transport.request("/api/channels", {
8
- method: "GET",
9
- fetch: customFetch,
10
- });
11
- }
12
- create(data) {
13
- return this.transport.request("/api/channels", {
14
- method: "POST",
15
- headers: {
16
- "Content-Type": "application/json",
17
- },
18
- body: JSON.stringify(data),
19
- });
20
- }
21
- delete(id) {
22
- return this.transport.request(`/api/channels/${id}`, { method: "DELETE" });
23
- }
24
- }