@neta-art/cohub 1.9.0 → 1.10.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.
Files changed (53) 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/debugger.d.ts +198 -0
  8. package/dist/debugger.js +1120 -0
  9. package/dist/http.d.ts +3 -32
  10. package/dist/http.js +2 -48
  11. package/dist/index.d.ts +35 -14
  12. package/dist/index.js +105 -8
  13. package/dist/websocket.d.ts +2 -141
  14. package/dist/websocket.js +2 -628
  15. package/package.json +11 -7
  16. package/dist/apis/channels.d.ts +0 -13
  17. package/dist/apis/channels.js +0 -24
  18. package/dist/apis/cron-jobs.d.ts +0 -18
  19. package/dist/apis/cron-jobs.js +0 -25
  20. package/dist/apis/explore.d.ts +0 -9
  21. package/dist/apis/explore.js +0 -9
  22. package/dist/apis/generations.d.ts +0 -7
  23. package/dist/apis/generations.js +0 -13
  24. package/dist/apis/invitations.d.ts +0 -20
  25. package/dist/apis/invitations.js +0 -36
  26. package/dist/apis/models.d.ts +0 -10
  27. package/dist/apis/models.js +0 -13
  28. package/dist/apis/prompts.d.ts +0 -9
  29. package/dist/apis/prompts.js +0 -16
  30. package/dist/apis/search.d.ts +0 -10
  31. package/dist/apis/search.js +0 -14
  32. package/dist/apis/session-access.d.ts +0 -13
  33. package/dist/apis/session-access.js +0 -19
  34. package/dist/apis/spaces.d.ts +0 -371
  35. package/dist/apis/spaces.js +0 -766
  36. package/dist/apis/tasks.d.ts +0 -13
  37. package/dist/apis/tasks.js +0 -18
  38. package/dist/apis/user.d.ts +0 -27
  39. package/dist/apis/user.js +0 -71
  40. package/dist/client.d.ts +0 -33
  41. package/dist/client.js +0 -103
  42. package/dist/environment.d.ts +0 -22
  43. package/dist/environment.js +0 -37
  44. package/dist/realtime.d.ts +0 -2
  45. package/dist/realtime.js +0 -8
  46. package/dist/session-generation-stream.d.ts +0 -114
  47. package/dist/session-generation-stream.js +0 -514
  48. package/dist/session-patch-reducer.d.ts +0 -61
  49. package/dist/session-patch-reducer.js +0 -432
  50. package/dist/transport.d.ts +0 -40
  51. package/dist/transport.js +0 -78
  52. package/dist/types.d.ts +0 -535
  53. package/dist/types.js +0 -1
@@ -0,0 +1,1919 @@
1
+ import { i as resolveApiBaseUrl } from "./environment.js";
2
+ //#region src/apis/channels.ts
3
+ var ChannelsApi = class {
4
+ transport;
5
+ constructor(transport) {
6
+ this.transport = transport;
7
+ }
8
+ list(customFetch) {
9
+ return this.transport.request("/api/channels", {
10
+ method: "GET",
11
+ fetch: customFetch
12
+ });
13
+ }
14
+ create(data) {
15
+ return this.transport.request("/api/channels", {
16
+ method: "POST",
17
+ headers: { "Content-Type": "application/json" },
18
+ body: JSON.stringify(data)
19
+ });
20
+ }
21
+ delete(id) {
22
+ return this.transport.request(`/api/channels/${id}`, { method: "DELETE" });
23
+ }
24
+ };
25
+ //#endregion
26
+ //#region src/apis/cron-jobs.ts
27
+ var CronJobsApi = class {
28
+ transport;
29
+ constructor(transport) {
30
+ this.transport = transport;
31
+ }
32
+ list(spaceId) {
33
+ const query = spaceId ? `?spaceId=${encodeURIComponent(spaceId)}` : "";
34
+ return this.transport.request(`/api/cron-jobs${query}`);
35
+ }
36
+ delete(id) {
37
+ return this.transport.request(`/api/cron-jobs/${id}`, { method: "DELETE" });
38
+ }
39
+ toggle(id, enabled) {
40
+ return this.transport.request(`/api/cron-jobs/${id}`, {
41
+ method: "PATCH",
42
+ headers: { "Content-Type": "application/json" },
43
+ body: JSON.stringify({ enabled })
44
+ });
45
+ }
46
+ runs(cronJobId) {
47
+ return this.transport.request(`/api/cron-jobs/${cronJobId}/runs`);
48
+ }
49
+ };
50
+ //#endregion
51
+ //#region src/apis/generations.ts
52
+ var GenerationsApi = class {
53
+ transport;
54
+ constructor(transport) {
55
+ this.transport = transport;
56
+ }
57
+ async create(request) {
58
+ return this.transport.request("/api/generations", {
59
+ method: "POST",
60
+ headers: { "Content-Type": "application/json" },
61
+ body: JSON.stringify(request)
62
+ });
63
+ }
64
+ };
65
+ //#endregion
66
+ //#region src/apis/models.ts
67
+ const MULTIMODAL_MODEL_TYPE = "multimodal";
68
+ var ModelsApi = class {
69
+ transport;
70
+ constructor(transport) {
71
+ this.transport = transport;
72
+ }
73
+ async list() {
74
+ return this.transport.request("/api/models");
75
+ }
76
+ async listMultimodal() {
77
+ return this.transport.request(`/api/models?modelType=${MULTIMODAL_MODEL_TYPE}`);
78
+ }
79
+ };
80
+ //#endregion
81
+ //#region src/apis/prompts.ts
82
+ var PromptsApi = class {
83
+ transport;
84
+ constructor(transport) {
85
+ this.transport = transport;
86
+ }
87
+ async list(options, customFetch) {
88
+ const params = new URLSearchParams();
89
+ if (options?.spaceId) params.set("spaceId", options.spaceId);
90
+ const query = params.toString();
91
+ const path = query ? `/api/prompts?${query}` : "/api/prompts";
92
+ return this.transport.request(path, { fetch: customFetch });
93
+ }
94
+ };
95
+ //#endregion
96
+ //#region src/apis/search.ts
97
+ var SearchApi = class {
98
+ transport;
99
+ constructor(transport) {
100
+ this.transport = transport;
101
+ }
102
+ query(input, customFetch) {
103
+ const params = new URLSearchParams({ q: input.q });
104
+ if (input.limit !== void 0) params.set("limit", String(input.limit));
105
+ for (const type of input.types ?? []) params.append("type", type);
106
+ if (input.spaceId) params.set("spaceId", input.spaceId);
107
+ return this.transport.request(`/api/search?${params.toString()}`, { fetch: customFetch });
108
+ }
109
+ };
110
+ //#endregion
111
+ //#region src/apis/session-access.ts
112
+ var SessionAccessApi = class {
113
+ transport;
114
+ constructor(transport) {
115
+ this.transport = transport;
116
+ }
117
+ get(sessionId) {
118
+ return this.transport.request(`/api/sessions/${sessionId}/access`);
119
+ }
120
+ set(sessionId, body) {
121
+ return this.transport.request(`/api/sessions/${sessionId}/access`, {
122
+ method: "PATCH",
123
+ headers: { "Content-Type": "application/json" },
124
+ body: JSON.stringify(body)
125
+ });
126
+ }
127
+ remove(sessionId) {
128
+ return this.transport.request(`/api/sessions/${sessionId}/access`, { method: "DELETE" });
129
+ }
130
+ };
131
+ //#endregion
132
+ //#region src/realtime.ts
133
+ function ensureRealtimeConnected(websocketClient) {
134
+ if (websocketClient.state === "open" || websocketClient.state === "connecting" || websocketClient.state === "reconnecting") return;
135
+ websocketClient.connect().catch((error) => {
136
+ console.error("[CohubClient] Failed to connect realtime websocket:", error);
137
+ });
138
+ }
139
+ //#endregion
140
+ //#region src/transport.ts
141
+ const responseBodyForError = async (response) => {
142
+ return (response.headers.get("content-type") ?? "").includes("application/json") ? await response.json().catch(() => null) : await response.text().catch(() => response.statusText);
143
+ };
144
+ const messageFromErrorBody = (body, fallback) => typeof body === "string" ? body : JSON.stringify(body ?? null) || fallback;
145
+ var HttpError = class extends Error {
146
+ status;
147
+ body;
148
+ constructor(message, status, body) {
149
+ super(message);
150
+ this.name = "HttpError";
151
+ this.status = status;
152
+ this.body = body;
153
+ }
154
+ };
155
+ var HttpTransport = class {
156
+ baseUrl;
157
+ fetcher;
158
+ getAccessToken;
159
+ onUnauthorized;
160
+ constructor(options = {}) {
161
+ this.baseUrl = resolveApiBaseUrl(options);
162
+ this.fetcher = options.fetch ?? fetch;
163
+ this.getAccessToken = options.getAccessToken;
164
+ this.onUnauthorized = options.onUnauthorized;
165
+ }
166
+ async withAuthorization(init) {
167
+ const headers = new Headers(init?.headers);
168
+ const token = this.getAccessToken ? await this.getAccessToken() : null;
169
+ if (token) headers.set("Authorization", `Bearer ${token}`);
170
+ else headers.delete("Authorization");
171
+ return {
172
+ ...init,
173
+ headers
174
+ };
175
+ }
176
+ async send(path, init) {
177
+ const response = await (init?.fetch ?? this.fetcher)(this.baseUrl ? `${this.baseUrl}${path}` : path, await this.withAuthorization(init));
178
+ if (response.status === 401) {
179
+ await this.onUnauthorized?.();
180
+ throw new HttpError("unauthorized", 401, null);
181
+ }
182
+ if (!response.ok) {
183
+ const body = await responseBodyForError(response);
184
+ throw new HttpError(messageFromErrorBody(body, response.statusText), response.status, body);
185
+ }
186
+ return response;
187
+ }
188
+ async request(path, init) {
189
+ const response = await this.send(path, init);
190
+ if (response.status === 204) return null;
191
+ return response.json();
192
+ }
193
+ async raw(path, init) {
194
+ const response = await this.send(path, init);
195
+ return {
196
+ response,
197
+ blob: () => response.blob(),
198
+ arrayBuffer: () => response.arrayBuffer(),
199
+ text: () => response.text(),
200
+ json: () => response.json()
201
+ };
202
+ }
203
+ async blob(path, init) {
204
+ return (await this.raw(path, init)).blob();
205
+ }
206
+ };
207
+ //#endregion
208
+ //#region src/session-patch-reducer.ts
209
+ const blockSubPathPattern = /^\/message\/content\/blocks\/(\d+)\/(.+)$/;
210
+ const blockPathPattern = /^\/message\/content\/blocks\/(\d+)$/;
211
+ const blockMetaPathPattern = /^\/message\/content\/blocks\/(\d+)\/_meta$/;
212
+ const TERMINAL_PATCH_STATUSES = new Set([
213
+ "completed",
214
+ "failed",
215
+ "interrupted"
216
+ ]);
217
+ const isTerminalPatchStatus = (status) => TERMINAL_PATCH_STATUSES.has(status);
218
+ const createIdleState = (input) => ({
219
+ spaceId: input.spaceId ?? null,
220
+ sessionId: input.sessionId,
221
+ status: "idle",
222
+ contentBlocks: [],
223
+ anchorUserMessageId: null,
224
+ patchSeq: 0,
225
+ turnId: null,
226
+ appendPath: null
227
+ });
228
+ function cloneBlock(block) {
229
+ return structuredClone(block);
230
+ }
231
+ function getStreamIndex$1(block) {
232
+ const value = block._meta?.streamIndex;
233
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
234
+ }
235
+ function blockIdentityCompatible(prev, next) {
236
+ if (prev.type !== next.type) return false;
237
+ if (prev.type === "tool_use" && next.type === "tool_use") return prev.id === next.id && prev.name === next.name;
238
+ if (prev.type === "tool_result" && next.type === "tool_result") return prev.tool_use_id === next.tool_use_id;
239
+ return true;
240
+ }
241
+ function findBlockByStreamIndex(blocks, streamIndex) {
242
+ return blocks.findIndex((block) => getStreamIndex$1(block) === streamIndex);
243
+ }
244
+ function findBlockForReplacement(blocks, streamIndex, nextBlock) {
245
+ const compatibleIndex = blocks.findIndex((block) => getStreamIndex$1(block) === streamIndex && blockIdentityCompatible(block, nextBlock));
246
+ if (compatibleIndex >= 0) return compatibleIndex;
247
+ const sameStreamIndex = blocks.findIndex((block) => getStreamIndex$1(block) === streamIndex);
248
+ if (sameStreamIndex >= 0 && nextBlock.type !== "tool_use" && nextBlock.type !== "tool_result") return sameStreamIndex;
249
+ return -1;
250
+ }
251
+ function sortBlocksByStreamIndex(blocks) {
252
+ return [...blocks].sort((a, b) => {
253
+ const aIndex = getStreamIndex$1(a);
254
+ const bIndex = getStreamIndex$1(b);
255
+ if (aIndex == null && bIndex == null) return 0;
256
+ if (aIndex == null) return 1;
257
+ if (bIndex == null) return -1;
258
+ return aIndex - bIndex;
259
+ });
260
+ }
261
+ function isContentBlock(value) {
262
+ return Boolean(value && typeof value === "object" && "type" in value);
263
+ }
264
+ function isPlainObject(value) {
265
+ return Boolean(value && typeof value === "object" && !Array.isArray(value));
266
+ }
267
+ function decodePointerSegments(encoded) {
268
+ if (!encoded) return [];
269
+ return encoded.split("/").map((s) => s.replace(/~1/g, "/").replace(/~0/g, "~"));
270
+ }
271
+ function ensureTextLikeBlock(blocks, streamIndex, field) {
272
+ const existingIndex = findBlockByStreamIndex(blocks, streamIndex);
273
+ const existing = existingIndex >= 0 ? blocks[existingIndex] : void 0;
274
+ if (field === "text") {
275
+ if (existing?.type === "text") return existing;
276
+ const block = {
277
+ type: "text",
278
+ text: "",
279
+ _meta: { streamIndex }
280
+ };
281
+ blocks.push(block);
282
+ return block;
283
+ }
284
+ if (existing?.type === "thinking") return existing;
285
+ const block = {
286
+ type: "thinking",
287
+ thinking: "",
288
+ _meta: { streamIndex }
289
+ };
290
+ blocks.push(block);
291
+ return block;
292
+ }
293
+ function getOrCreateBlockForSubpath(blocks, streamIndex, firstSegment) {
294
+ const idx = findBlockByStreamIndex(blocks, streamIndex);
295
+ if (idx >= 0) return blocks[idx] ?? null;
296
+ if (firstSegment === "text") return ensureTextLikeBlock(blocks, streamIndex, "text");
297
+ if (firstSegment === "thinking") return ensureTextLikeBlock(blocks, streamIndex, "thinking");
298
+ return null;
299
+ }
300
+ function setDeepOnContentBlock(root, segments, value) {
301
+ if (segments.length === 0) return false;
302
+ let cur = root;
303
+ for (let i = 0; i < segments.length - 1; i++) {
304
+ const k = segments[i];
305
+ if (k === void 0) return false;
306
+ if (!isPlainObject(cur)) return false;
307
+ const next = cur[k];
308
+ if (next === void 0) return false;
309
+ cur = next;
310
+ }
311
+ const last = segments[segments.length - 1];
312
+ if (last === void 0) return false;
313
+ if (!isPlainObject(cur)) return false;
314
+ const toAssign = value !== null && typeof value === "object" ? structuredClone(value) : value;
315
+ cur[last] = toAssign;
316
+ return true;
317
+ }
318
+ function appendDeepOnContentBlock(root, segments, suffix) {
319
+ if (segments.length === 0) return false;
320
+ let cur = root;
321
+ for (let i = 0; i < segments.length - 1; i++) {
322
+ const k = segments[i];
323
+ if (k === void 0) return false;
324
+ if (!isPlainObject(cur)) return false;
325
+ const next = cur[k];
326
+ if (next === void 0) return false;
327
+ cur = next;
328
+ }
329
+ const last = segments[segments.length - 1];
330
+ if (last === void 0) return false;
331
+ if (!isPlainObject(cur)) return false;
332
+ const parent = cur;
333
+ const leaf = parent[last];
334
+ if (typeof leaf !== "string") return false;
335
+ parent[last] = leaf + suffix;
336
+ return true;
337
+ }
338
+ function resolveBlockForSubpath(blocks, streamIndex, firstSegment) {
339
+ const idx = findBlockByStreamIndex(blocks, streamIndex);
340
+ if (idx >= 0) return blocks[idx] ?? null;
341
+ return getOrCreateBlockForSubpath(blocks, streamIndex, firstSegment);
342
+ }
343
+ function applyReplaceAtBlockSubpath(blocks, streamIndex, encodedTail, value) {
344
+ const segs = decodePointerSegments(encodedTail);
345
+ if (segs.length === 0) return false;
346
+ const block = resolveBlockForSubpath(blocks, streamIndex, segs[0] ?? "");
347
+ if (!block) return false;
348
+ return setDeepOnContentBlock(block, segs, value);
349
+ }
350
+ function applyAppendAtBlockSubpath(blocks, streamIndex, encodedTail, suffix) {
351
+ if (typeof suffix !== "string") return false;
352
+ const segs = decodePointerSegments(encodedTail);
353
+ if (segs.length === 0) return false;
354
+ const block = resolveBlockForSubpath(blocks, streamIndex, segs[0] ?? "");
355
+ if (!block) return false;
356
+ return appendDeepOnContentBlock(block, segs, suffix);
357
+ }
358
+ function appendPatchStreamValue(blocks, path, value) {
359
+ const m = path.match(blockSubPathPattern);
360
+ if (!m) return false;
361
+ return applyAppendAtBlockSubpath(blocks, Number(m[1]), m[2] ?? "", value);
362
+ }
363
+ function applyPatchOpsToBlocks(current, ops, initialAppendPath) {
364
+ const next = current.map(cloneBlock);
365
+ let anchorUserMessageId;
366
+ let appendPath = initialAppendPath;
367
+ let failed = false;
368
+ for (const op of ops) {
369
+ if (!op.o && !op.p) {
370
+ if (!appendPath || !appendPatchStreamValue(next, appendPath, op.v)) {
371
+ failed = true;
372
+ break;
373
+ }
374
+ continue;
375
+ }
376
+ if (op.o === "merge" && op.p === "/message/metadata") {
377
+ const anchor = op.v.anchorUserMessageId;
378
+ if (typeof anchor === "string" && anchor.trim()) anchorUserMessageId = anchor;
379
+ continue;
380
+ }
381
+ if (op.o === "append") {
382
+ if (typeof op.p !== "string" || !appendPatchStreamValue(next, op.p, op.v)) {
383
+ failed = true;
384
+ break;
385
+ }
386
+ appendPath = op.p;
387
+ continue;
388
+ }
389
+ if (op.o === "merge") {
390
+ const match = op.p.match(blockMetaPathPattern);
391
+ if (!match) continue;
392
+ const blockIndex = findBlockByStreamIndex(next, Number(match[1]));
393
+ const block = blockIndex >= 0 ? next[blockIndex] : void 0;
394
+ if (!block) continue;
395
+ block._meta = {
396
+ ...block._meta ?? {},
397
+ ...op.v
398
+ };
399
+ continue;
400
+ }
401
+ if (op.o === "replace") {
402
+ const sub = op.p.match(blockSubPathPattern);
403
+ if (sub?.[2] && typeof op.p === "string") {
404
+ const streamIndex = Number(sub[1]);
405
+ const encodedTail = sub[2];
406
+ if (applyReplaceAtBlockSubpath(next, streamIndex, encodedTail, op.v)) continue;
407
+ failed = true;
408
+ break;
409
+ }
410
+ }
411
+ if (op.o === "replace" || op.o === "add") {
412
+ const match = op.p.match(blockPathPattern);
413
+ if (!match || !isContentBlock(op.v)) continue;
414
+ const streamIndex = Number(match[1]);
415
+ const block = cloneBlock(op.v);
416
+ block._meta = {
417
+ ...block._meta ?? {},
418
+ streamIndex
419
+ };
420
+ const blockIndex = findBlockForReplacement(next, streamIndex, block);
421
+ if (blockIndex >= 0) next[blockIndex] = block;
422
+ else next.push(block);
423
+ continue;
424
+ }
425
+ if (op.o === "remove") {
426
+ const match = op.p.match(blockPathPattern);
427
+ if (!match) continue;
428
+ const blockIndex = findBlockByStreamIndex(next, Number(match[1]));
429
+ if (blockIndex >= 0) next.splice(blockIndex, 1);
430
+ }
431
+ }
432
+ return {
433
+ failed,
434
+ contentBlocks: sortBlocksByStreamIndex(next),
435
+ anchorUserMessageId,
436
+ appendPath
437
+ };
438
+ }
439
+ var SessionPatchReducer = class {
440
+ states = /* @__PURE__ */ new Map();
441
+ key(input) {
442
+ return `${input.spaceId ?? ""}:${input.sessionId}`;
443
+ }
444
+ get(input) {
445
+ const key = this.key(input);
446
+ return this.states.get(key) ?? createIdleState(input);
447
+ }
448
+ start(input) {
449
+ const state = {
450
+ ...this.get(input),
451
+ status: "pending",
452
+ contentBlocks: [],
453
+ anchorUserMessageId: null,
454
+ patchSeq: 0,
455
+ turnId: input.turnId ?? null,
456
+ appendPath: null
457
+ };
458
+ this.states.set(this.key(input), state);
459
+ return state;
460
+ }
461
+ replaceTurnId(input) {
462
+ const state = {
463
+ ...this.get(input),
464
+ turnId: input.nextTurnId
465
+ };
466
+ this.states.set(this.key(input), state);
467
+ return state;
468
+ }
469
+ complete(input) {
470
+ const current = this.get(input);
471
+ const state = {
472
+ ...current,
473
+ turnId: input.turnId ?? current.turnId,
474
+ status: "completed",
475
+ contentBlocks: [],
476
+ anchorUserMessageId: null
477
+ };
478
+ this.states.set(this.key(input), state);
479
+ return state;
480
+ }
481
+ fail(input) {
482
+ const current = this.get(input);
483
+ const state = {
484
+ ...current,
485
+ turnId: input.turnId ?? current.turnId,
486
+ status: "failed",
487
+ contentBlocks: [],
488
+ anchorUserMessageId: null
489
+ };
490
+ this.states.set(this.key(input), state);
491
+ return state;
492
+ }
493
+ interrupt(input) {
494
+ const current = this.get(input);
495
+ const state = {
496
+ ...current,
497
+ turnId: input.turnId ?? current.turnId,
498
+ status: "interrupted",
499
+ contentBlocks: [],
500
+ anchorUserMessageId: null,
501
+ appendPath: null
502
+ };
503
+ this.states.set(this.key(input), state);
504
+ return state;
505
+ }
506
+ reset(input) {
507
+ this.states.delete(this.key(input));
508
+ }
509
+ applySnapshot(input) {
510
+ const current = this.get(input);
511
+ const inputTurnId = input.turnId ?? null;
512
+ const currentTurnId = current.turnId;
513
+ const isDifferentKnownTurn = Boolean(currentTurnId && inputTurnId && currentTurnId !== inputTurnId);
514
+ if (isTerminalPatchStatus(current.status) && Boolean(currentTurnId) && currentTurnId === inputTurnId || !isDifferentKnownTurn && input.seq < current.patchSeq) return {
515
+ applied: false,
516
+ reason: "duplicate",
517
+ state: current
518
+ };
519
+ const state = {
520
+ ...current,
521
+ spaceId: input.spaceId ?? current.spaceId ?? null,
522
+ sessionId: input.sessionId,
523
+ status: "streaming",
524
+ contentBlocks: sortBlocksByStreamIndex(input.contentBlocks.map(cloneBlock)),
525
+ anchorUserMessageId: input.anchorUserMessageId ?? current.anchorUserMessageId ?? null,
526
+ patchSeq: input.seq,
527
+ turnId: inputTurnId ?? current.turnId ?? null,
528
+ appendPath: input.appendPath ?? null
529
+ };
530
+ this.states.set(this.key(input), state);
531
+ return {
532
+ applied: true,
533
+ state
534
+ };
535
+ }
536
+ resetAll() {
537
+ this.states.clear();
538
+ }
539
+ applyEvent(event) {
540
+ return this.applyPatch({
541
+ spaceId: event.spaceId,
542
+ sessionId: event.sessionId,
543
+ turnId: event.payload.turnId,
544
+ seq: event.payload.seq,
545
+ baseSeq: event.payload.baseSeq,
546
+ ops: event.payload.ops,
547
+ anchorUserMessageId: event.payload.anchorUserMessageId
548
+ });
549
+ }
550
+ applyPatch(input) {
551
+ const current = this.get(input);
552
+ const currentTurnId = current.turnId;
553
+ const inputTurnId = input.turnId ?? null;
554
+ const isDifferentKnownTurn = Boolean(currentTurnId && inputTurnId && currentTurnId !== inputTurnId);
555
+ const isFreshKnownTurn = isDifferentKnownTurn && input.baseSeq === 0;
556
+ const currentSeq = isFreshKnownTurn ? 0 : current.patchSeq;
557
+ const isSameTurnKeyframe = Boolean(currentTurnId && inputTurnId && currentTurnId === inputTurnId && input.baseSeq === 0 && input.seq >= currentSeq);
558
+ if (isTerminalPatchStatus(current.status) && Boolean(currentTurnId) && currentTurnId === inputTurnId) return {
559
+ applied: false,
560
+ reason: "duplicate",
561
+ state: current
562
+ };
563
+ if (isDifferentKnownTurn && !isFreshKnownTurn) return {
564
+ applied: false,
565
+ reason: "version_mismatch",
566
+ state: current
567
+ };
568
+ if (!isSameTurnKeyframe && input.seq <= currentSeq) return {
569
+ applied: false,
570
+ reason: "duplicate",
571
+ state: current
572
+ };
573
+ if (!isSameTurnKeyframe && input.baseSeq !== currentSeq) return {
574
+ applied: false,
575
+ reason: "version_mismatch",
576
+ state: current
577
+ };
578
+ const startingFresh = input.baseSeq === 0 || isFreshKnownTurn || isSameTurnKeyframe;
579
+ const patched = applyPatchOpsToBlocks(startingFresh ? [] : current.contentBlocks, input.ops, startingFresh ? null : current.appendPath);
580
+ if (patched.failed) return {
581
+ applied: false,
582
+ reason: "version_mismatch",
583
+ state: current
584
+ };
585
+ const next = {
586
+ ...current,
587
+ spaceId: input.spaceId ?? current.spaceId ?? null,
588
+ sessionId: input.sessionId,
589
+ status: "streaming",
590
+ contentBlocks: patched.contentBlocks,
591
+ anchorUserMessageId: patched.anchorUserMessageId ?? input.anchorUserMessageId ?? current.anchorUserMessageId ?? null,
592
+ patchSeq: input.seq,
593
+ turnId: input.turnId ?? current.turnId ?? null,
594
+ appendPath: patched.appendPath
595
+ };
596
+ this.states.set(this.key(next), next);
597
+ return {
598
+ applied: true,
599
+ state: next
600
+ };
601
+ }
602
+ };
603
+ const createSessionPatchReducer = () => new SessionPatchReducer();
604
+ //#endregion
605
+ //#region src/session-generation-stream.ts
606
+ const isRecord = (value) => Boolean(value && typeof value === "object" && !Array.isArray(value));
607
+ const isContentBlockArray = (value) => Array.isArray(value) && value.every((item) => isRecord(item) && typeof item.type === "string");
608
+ const stringField = (record, key) => {
609
+ const value = record[key];
610
+ return typeof value === "string" ? value : null;
611
+ };
612
+ const numberField = (record, key) => {
613
+ const value = record[key];
614
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
615
+ };
616
+ const getMessageKind = (message) => {
617
+ const kind = message.meta?.messageKind;
618
+ return typeof kind === "string" ? kind : null;
619
+ };
620
+ function parseAssistantMessageCommit(message) {
621
+ if (message.role !== "assistant") return {
622
+ kind: "ignored",
623
+ message,
624
+ isFinal: false
625
+ };
626
+ const kind = getMessageKind(message);
627
+ if (kind === "assistant_intermediate") return {
628
+ kind: "intermediate",
629
+ message,
630
+ isFinal: false
631
+ };
632
+ if (kind === "assistant_final") return {
633
+ kind: "final",
634
+ message,
635
+ isFinal: true
636
+ };
637
+ if (kind === "assistant_error") return {
638
+ kind: "error",
639
+ message,
640
+ isFinal: true
641
+ };
642
+ return {
643
+ kind: "ignored",
644
+ message,
645
+ isFinal: false
646
+ };
647
+ }
648
+ function cloneContentBlock(block) {
649
+ return structuredClone(block);
650
+ }
651
+ function getStreamIndex(block) {
652
+ const value = block._meta?.streamIndex;
653
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
654
+ }
655
+ function findMergeTargetIndex(result, block) {
656
+ const streamIndex = getStreamIndex(block);
657
+ if (streamIndex != null) return result.findIndex((existing) => existing.type === block.type && getStreamIndex(existing) === streamIndex);
658
+ if (block.type === "tool_use") return result.findIndex((existing) => existing.type === "tool_use" && existing.id === block.id);
659
+ if (block.type === "tool_result") return result.findIndex((existing) => existing.type === "tool_result" && existing.tool_use_id === block.tool_use_id);
660
+ return -1;
661
+ }
662
+ function mergeStreamingDeltaBlocks(existing, delta) {
663
+ if (delta.length === 0) return existing;
664
+ const result = existing.map(cloneContentBlock);
665
+ for (const block of delta) {
666
+ const targetIndex = findMergeTargetIndex(result, block);
667
+ if (targetIndex === -1) {
668
+ result.push(cloneContentBlock(block));
669
+ continue;
670
+ }
671
+ const target = result[targetIndex];
672
+ if (block.type === "text" && target?.type === "text") {
673
+ target.text += block.text;
674
+ continue;
675
+ }
676
+ if (block.type === "thinking" && target?.type === "thinking") {
677
+ target.thinking += block.thinking;
678
+ if (block.signature) target.signature = block.signature;
679
+ if (block._meta) target._meta = {
680
+ ...target._meta ?? {},
681
+ ...block._meta
682
+ };
683
+ continue;
684
+ }
685
+ result[targetIndex] = Object.assign(target ?? {}, cloneContentBlock(block));
686
+ }
687
+ return result;
688
+ }
689
+ function parseSnapshotMessage(value) {
690
+ if (!isRecord(value) || !isContentBlockArray(value.content)) return null;
691
+ return {
692
+ messageId: stringField(value, "messageId"),
693
+ messageOrdinal: numberField(value, "messageOrdinal"),
694
+ content: value.content,
695
+ ...typeof value.id === "string" ? { id: value.id } : {},
696
+ ...typeof value.sessionId === "string" ? { sessionId: value.sessionId } : {},
697
+ ...value.role === "user" || value.role === "assistant" || value.role === "system" ? { role: value.role } : {},
698
+ ...typeof value.text === "string" ? { text: value.text } : {},
699
+ ...typeof value.provider === "string" ? { provider: value.provider } : {},
700
+ ...typeof value.model === "string" ? { model: value.model } : {},
701
+ ...typeof value.stopReason === "string" ? { stopReason: value.stopReason } : {},
702
+ ...typeof value.errorMessage === "string" ? { errorMessage: value.errorMessage } : {},
703
+ ...isRecord(value.usage) ? { usage: value.usage } : {},
704
+ ...typeof value.toolCallsObjectKey === "string" ? { toolCallsObjectKey: value.toolCallsObjectKey } : {},
705
+ ...isRecord(value.meta) ? { meta: value.meta } : {},
706
+ ...typeof value.createdAt === "string" ? { createdAt: value.createdAt } : {}
707
+ };
708
+ }
709
+ function messageRecordToIntermediate(message) {
710
+ if (!isContentBlockArray(message.content) || message.content.length === 0) return null;
711
+ const meta = isRecord(message.meta) ? message.meta : {};
712
+ return {
713
+ id: message.id,
714
+ sessionId: message.sessionId,
715
+ role: message.role,
716
+ messageId: typeof meta.streamMessageId === "string" ? meta.streamMessageId : message.id ?? null,
717
+ messageOrdinal: typeof meta.messageOrdinal === "number" ? meta.messageOrdinal : null,
718
+ content: message.content,
719
+ text: message.text,
720
+ provider: message.provider,
721
+ model: message.model,
722
+ stopReason: message.stopReason,
723
+ errorMessage: message.errorMessage,
724
+ usage: message.usage,
725
+ meta: message.meta,
726
+ createdAt: message.createdAt
727
+ };
728
+ }
729
+ function resolveStreamMessageId(input) {
730
+ if (input.messageId?.trim()) return input.messageId.trim();
731
+ if (input.messageOrdinal == null) return null;
732
+ if (input.turnId?.trim()) return `turn:${input.turnId.trim()}:assistant:${input.messageOrdinal}`;
733
+ return `session:${input.sessionId}:assistant:${input.messageOrdinal}:${input.anchorUserMessageId ?? "unknown"}`;
734
+ }
735
+ function getTurnIdFromMessage(message) {
736
+ const turnId = message.meta?.turnId;
737
+ return typeof turnId === "string" ? turnId : null;
738
+ }
739
+ var SessionGenerationStreamClient = class SessionGenerationStreamClient {
740
+ websocketClient;
741
+ spaceId;
742
+ sessionId;
743
+ reducer = new SessionPatchReducer();
744
+ messageId = null;
745
+ messageOrdinal = null;
746
+ intermediateMessages = [];
747
+ progressState = null;
748
+ constructor(websocketClient, spaceId, sessionId) {
749
+ this.websocketClient = websocketClient;
750
+ this.spaceId = spaceId;
751
+ this.sessionId = sessionId;
752
+ }
753
+ subscribe(handlers) {
754
+ if (!this.websocketClient) throw new Error("realtime transport is not configured for this client");
755
+ ensureRealtimeConnected(this.websocketClient);
756
+ const stream = new SessionGenerationStreamClient(this.websocketClient, this.spaceId, this.sessionId);
757
+ const unsubscribe = this.websocketClient.on("event", (event) => {
758
+ if (event.spaceId !== this.spaceId || event.sessionId !== this.sessionId) return;
759
+ stream.handleEvent(event, handlers);
760
+ });
761
+ return () => unsubscribe();
762
+ }
763
+ emit(handlers, event) {
764
+ handlers.event?.(event);
765
+ if (event.type === "state") handlers.state?.(event);
766
+ if (event.type === "commit") handlers.commit?.(event);
767
+ if (event.type === "finalized") handlers.finalized?.(event);
768
+ if (event.type === "turn_updated") handlers.turnUpdated?.(event);
769
+ if (event.type === "error") handlers.error?.(event);
770
+ if (event.type === "out_of_sync") handlers.outOfSync?.(event);
771
+ }
772
+ resetCurrentMessage() {
773
+ this.messageId = null;
774
+ this.messageOrdinal = null;
775
+ this.progressState = null;
776
+ }
777
+ appendCurrentMessage(state) {
778
+ if (state.contentBlocks.length === 0) return;
779
+ this.addIntermediateMessage({
780
+ messageId: this.messageId,
781
+ messageOrdinal: this.messageOrdinal,
782
+ content: state.contentBlocks
783
+ });
784
+ }
785
+ addIntermediateMessage(message) {
786
+ const index = this.intermediateMessages.findIndex((existing) => {
787
+ if (message.messageId && existing.messageId) return existing.messageId === message.messageId;
788
+ return message.messageOrdinal !== null && existing.messageOrdinal === message.messageOrdinal;
789
+ });
790
+ if (index < 0) {
791
+ this.intermediateMessages = [...this.intermediateMessages, message];
792
+ return;
793
+ }
794
+ this.intermediateMessages = this.intermediateMessages.map((existing, i) => i === index ? {
795
+ ...existing,
796
+ ...message
797
+ } : existing);
798
+ }
799
+ handleAppliedState(handlers, source, result, rawEvent, messageId, messageOrdinal) {
800
+ if (!result.applied) {
801
+ this.emit(handlers, {
802
+ type: "out_of_sync",
803
+ source: source === "progress" ? "patch" : source,
804
+ reason: result.reason,
805
+ state: result.state,
806
+ rawEvent
807
+ });
808
+ return;
809
+ }
810
+ this.progressState = result.state;
811
+ this.messageId = messageId;
812
+ this.messageOrdinal = messageOrdinal;
813
+ this.emit(handlers, {
814
+ type: "state",
815
+ source,
816
+ state: result.state,
817
+ messageId,
818
+ messageOrdinal,
819
+ intermediateMessages: [...this.intermediateMessages],
820
+ rawEvent
821
+ });
822
+ }
823
+ prepareMessageBoundary(input) {
824
+ const current = this.progressState ?? this.reducer.get({
825
+ spaceId: this.spaceId,
826
+ sessionId: this.sessionId
827
+ });
828
+ const nextMessageId = resolveStreamMessageId({
829
+ sessionId: this.sessionId,
830
+ turnId: input.turnId,
831
+ anchorUserMessageId: input.anchorUserMessageId,
832
+ messageId: input.messageId,
833
+ messageOrdinal: input.messageOrdinal
834
+ });
835
+ const differentTurn = Boolean(current.turnId && input.turnId && current.turnId !== input.turnId);
836
+ const messageChanged = Boolean(nextMessageId && current.contentBlocks.length > 0 && this.messageId && nextMessageId !== this.messageId);
837
+ if (differentTurn) {
838
+ this.intermediateMessages = [];
839
+ this.resetCurrentMessage();
840
+ this.reducer.start({
841
+ spaceId: this.spaceId,
842
+ sessionId: this.sessionId,
843
+ turnId: input.turnId
844
+ });
845
+ } else if (messageChanged) {
846
+ this.appendCurrentMessage(current);
847
+ this.resetCurrentMessage();
848
+ this.reducer.start({
849
+ spaceId: this.spaceId,
850
+ sessionId: this.sessionId,
851
+ turnId: input.turnId ?? current.turnId
852
+ });
853
+ }
854
+ return nextMessageId;
855
+ }
856
+ handleSnapshot(event, handlers) {
857
+ const payload = event.payload;
858
+ const current = isRecord(payload.current) ? payload.current : null;
859
+ const content = current ? current.content : null;
860
+ const seq = typeof payload.seq === "number" ? payload.seq : null;
861
+ if (!current || !isContentBlockArray(content) || seq === null) {
862
+ this.emit(handlers, {
863
+ type: "out_of_sync",
864
+ source: "snapshot",
865
+ reason: "invalid",
866
+ state: this.reducer.get({
867
+ spaceId: this.spaceId,
868
+ sessionId: this.sessionId
869
+ }),
870
+ rawEvent: event
871
+ });
872
+ return;
873
+ }
874
+ const turnId = typeof payload.turnId === "string" ? payload.turnId : null;
875
+ const anchorUserMessageId = typeof payload.anchorUserMessageId === "string" ? payload.anchorUserMessageId : null;
876
+ const messageOrdinal = numberField(current, "messageOrdinal");
877
+ const messageId = this.prepareMessageBoundary({
878
+ turnId,
879
+ messageId: stringField(current, "messageId"),
880
+ messageOrdinal,
881
+ anchorUserMessageId
882
+ });
883
+ this.intermediateMessages = Array.isArray(payload.intermediateMessages) ? payload.intermediateMessages.map(parseSnapshotMessage).filter((message) => message !== null) : [];
884
+ const result = this.reducer.applySnapshot({
885
+ spaceId: this.spaceId,
886
+ sessionId: this.sessionId,
887
+ turnId,
888
+ seq,
889
+ contentBlocks: content,
890
+ anchorUserMessageId,
891
+ appendPath: stringField(current, "appendPath")
892
+ });
893
+ this.handleAppliedState(handlers, "snapshot", result, event, messageId, messageOrdinal);
894
+ }
895
+ handlePatch(event, handlers) {
896
+ const payload = event.payload;
897
+ const seq = typeof payload.seq === "number" ? payload.seq : null;
898
+ const baseSeq = typeof payload.baseSeq === "number" ? payload.baseSeq : null;
899
+ if (seq === null || baseSeq === null || !Array.isArray(payload.ops)) {
900
+ this.emit(handlers, {
901
+ type: "out_of_sync",
902
+ source: "patch",
903
+ reason: "invalid",
904
+ state: this.reducer.get({
905
+ spaceId: this.spaceId,
906
+ sessionId: this.sessionId
907
+ }),
908
+ rawEvent: event
909
+ });
910
+ return;
911
+ }
912
+ const turnId = typeof payload.turnId === "string" ? payload.turnId : null;
913
+ const anchorUserMessageId = typeof payload.anchorUserMessageId === "string" ? payload.anchorUserMessageId : null;
914
+ const messageOrdinal = typeof payload.messageOrdinal === "number" ? payload.messageOrdinal : null;
915
+ const messageId = this.prepareMessageBoundary({
916
+ turnId,
917
+ messageId: typeof payload.messageId === "string" ? payload.messageId : null,
918
+ messageOrdinal,
919
+ anchorUserMessageId
920
+ });
921
+ const input = {
922
+ spaceId: this.spaceId,
923
+ sessionId: this.sessionId,
924
+ turnId,
925
+ seq,
926
+ baseSeq,
927
+ ops: payload.ops,
928
+ anchorUserMessageId
929
+ };
930
+ const result = this.reducer.applyPatch(input);
931
+ this.handleAppliedState(handlers, "patch", result, event, messageId, messageOrdinal);
932
+ }
933
+ handleProgress(event, handlers) {
934
+ const payload = event.payload;
935
+ if (!isContentBlockArray(payload.content)) return;
936
+ const current = this.progressState ?? this.reducer.get({
937
+ spaceId: this.spaceId,
938
+ sessionId: this.sessionId
939
+ });
940
+ const turnId = typeof payload.turnId === "string" ? payload.turnId : current.turnId;
941
+ const anchorUserMessageId = typeof payload.anchorUserMessageId === "string" ? payload.anchorUserMessageId : current.anchorUserMessageId;
942
+ const messageOrdinal = typeof payload.messageOrdinal === "number" ? payload.messageOrdinal : this.messageOrdinal;
943
+ const messageId = this.prepareMessageBoundary({
944
+ turnId,
945
+ messageId: typeof payload.messageId === "string" ? payload.messageId : this.messageId,
946
+ messageOrdinal,
947
+ anchorUserMessageId
948
+ });
949
+ const base = this.progressState?.turnId === turnId ? this.progressState : current;
950
+ const state = {
951
+ ...base,
952
+ spaceId: this.spaceId,
953
+ sessionId: this.sessionId,
954
+ status: "streaming",
955
+ contentBlocks: mergeStreamingDeltaBlocks(base.contentBlocks, payload.content),
956
+ anchorUserMessageId,
957
+ turnId
958
+ };
959
+ this.progressState = state;
960
+ this.messageId = messageId;
961
+ this.messageOrdinal = messageOrdinal;
962
+ this.emit(handlers, {
963
+ type: "state",
964
+ source: "progress",
965
+ state,
966
+ messageId,
967
+ messageOrdinal,
968
+ intermediateMessages: [...this.intermediateMessages],
969
+ rawEvent: event
970
+ });
971
+ }
972
+ handlePersisted(event, handlers) {
973
+ const message = event.payload.message;
974
+ if (!isRecord(message)) return;
975
+ const commit = parseAssistantMessageCommit(message);
976
+ if (commit.kind === "intermediate") {
977
+ const intermediate = messageRecordToIntermediate(commit.message);
978
+ if (intermediate) this.addIntermediateMessage(intermediate);
979
+ this.reducer.reset({
980
+ spaceId: this.spaceId,
981
+ sessionId: this.sessionId
982
+ });
983
+ this.resetCurrentMessage();
984
+ }
985
+ if (commit.kind === "final") {
986
+ this.reducer.complete({
987
+ spaceId: this.spaceId,
988
+ sessionId: this.sessionId,
989
+ turnId: getTurnIdFromMessage(commit.message)
990
+ });
991
+ this.resetCurrentMessage();
992
+ }
993
+ if (commit.kind === "error") {
994
+ this.reducer.fail({
995
+ spaceId: this.spaceId,
996
+ sessionId: this.sessionId,
997
+ turnId: getTurnIdFromMessage(commit.message)
998
+ });
999
+ this.resetCurrentMessage();
1000
+ }
1001
+ this.emit(handlers, {
1002
+ type: "commit",
1003
+ commit,
1004
+ rawEvent: event
1005
+ });
1006
+ }
1007
+ handleFinalized(event, handlers) {
1008
+ const turn = event.payload.turn;
1009
+ if (!isRecord(turn)) return;
1010
+ const typedTurn = turn;
1011
+ if (typedTurn.status === "interrupted") this.reducer.interrupt({
1012
+ spaceId: this.spaceId,
1013
+ sessionId: this.sessionId,
1014
+ turnId: typedTurn.id
1015
+ });
1016
+ else this.reducer.complete({
1017
+ spaceId: this.spaceId,
1018
+ sessionId: this.sessionId,
1019
+ turnId: typedTurn.id
1020
+ });
1021
+ this.resetCurrentMessage();
1022
+ this.emit(handlers, {
1023
+ type: "finalized",
1024
+ turn: typedTurn,
1025
+ rawEvent: event
1026
+ });
1027
+ }
1028
+ handleEvent(event, handlers) {
1029
+ switch (event.type) {
1030
+ case "session.turn.snapshot":
1031
+ this.handleSnapshot(event, handlers);
1032
+ return;
1033
+ case "session.turn.patch":
1034
+ this.handlePatch(event, handlers);
1035
+ return;
1036
+ case "session.turn.progress":
1037
+ this.handleProgress(event, handlers);
1038
+ return;
1039
+ case "session.message.persisted":
1040
+ this.handlePersisted(event, handlers);
1041
+ return;
1042
+ case "session.turn.finalized":
1043
+ this.handleFinalized(event, handlers);
1044
+ return;
1045
+ case "session.turn.updated": {
1046
+ const turn = event.payload.turn;
1047
+ if (!isRecord(turn)) return;
1048
+ this.emit(handlers, {
1049
+ type: "turn_updated",
1050
+ turn,
1051
+ rawEvent: event
1052
+ });
1053
+ return;
1054
+ }
1055
+ case "session.turn.error": {
1056
+ const message = typeof event.payload.error === "string" && event.payload.error.trim() ? event.payload.error.trim() : "Generation failed";
1057
+ this.reducer.fail({
1058
+ spaceId: this.spaceId,
1059
+ sessionId: this.sessionId
1060
+ });
1061
+ this.resetCurrentMessage();
1062
+ this.emit(handlers, {
1063
+ type: "error",
1064
+ message,
1065
+ rawEvent: event
1066
+ });
1067
+ return;
1068
+ }
1069
+ default: return;
1070
+ }
1071
+ }
1072
+ };
1073
+ function createSessionGenerationStreamClient(input) {
1074
+ return new SessionGenerationStreamClient(input.websocketClient, input.spaceId, input.sessionId);
1075
+ }
1076
+ //#endregion
1077
+ //#region src/apis/invitations.ts
1078
+ var SpaceInvitationsApi = class {
1079
+ transport;
1080
+ spaceId;
1081
+ constructor(transport, spaceId) {
1082
+ this.transport = transport;
1083
+ this.spaceId = spaceId;
1084
+ }
1085
+ list() {
1086
+ return this.transport.request(`/api/spaces/${this.spaceId}/invitations`);
1087
+ }
1088
+ create(input) {
1089
+ return this.transport.request(`/api/spaces/${this.spaceId}/invitations`, {
1090
+ method: "POST",
1091
+ headers: { "Content-Type": "application/json" },
1092
+ body: JSON.stringify(input ?? {})
1093
+ });
1094
+ }
1095
+ revoke(token) {
1096
+ return this.transport.request(`/api/spaces/${this.spaceId}/invitations/${token}`, { method: "DELETE" });
1097
+ }
1098
+ };
1099
+ var PublicInviteApi = class {
1100
+ transport;
1101
+ constructor(transport) {
1102
+ this.transport = transport;
1103
+ }
1104
+ get(token) {
1105
+ return this.transport.request(`/api/invite/${token}`);
1106
+ }
1107
+ accept(token) {
1108
+ return this.transport.request(`/api/invite/${token}/accept`, { method: "POST" });
1109
+ }
1110
+ };
1111
+ //#endregion
1112
+ //#region src/apis/spaces.ts
1113
+ const DEFAULT_DEDUP_WINDOW_MS = 2e3;
1114
+ const getFilenameFromContentDisposition = (value) => {
1115
+ if (!value) return null;
1116
+ const encodedMatch = value.match(/filename\*=UTF-8''([^;]+)/i);
1117
+ if (encodedMatch?.[1]) try {
1118
+ return decodeURIComponent(encodedMatch[1]);
1119
+ } catch {
1120
+ return encodedMatch[1];
1121
+ }
1122
+ return value.match(/filename="?([^";]+)"?/i)?.[1] ?? null;
1123
+ };
1124
+ const toSessionEventName = (type) => {
1125
+ switch (type) {
1126
+ case "session.turn.patch": return "turn.patch";
1127
+ case "session.turn.snapshot": return "turn.snapshot";
1128
+ case "session.turn.progress": return "turn.progress";
1129
+ case "session.turn.error": return "turn.error";
1130
+ case "session.turn.updated": return "turn.updated";
1131
+ case "session.turn.finalized": return "turn.final";
1132
+ case "session.message.persisted": return "message.persisted";
1133
+ default: return null;
1134
+ }
1135
+ };
1136
+ const isAssistantFinalPersistedEvent = (event) => {
1137
+ if (event.type !== "session.message.persisted") return false;
1138
+ const message = event.payload.message;
1139
+ if (!message || typeof message !== "object") return false;
1140
+ const record = message;
1141
+ return record.role === "assistant" && (record.meta?.messageKind === "assistant_final" || record.meta?.messageKind === "assistant_error");
1142
+ };
1143
+ const isAssistantIntermediatePersistedEvent = (event) => {
1144
+ if (event.type !== "session.message.persisted") return false;
1145
+ const message = event.payload.message;
1146
+ if (!message || typeof message !== "object") return false;
1147
+ const record = message;
1148
+ return record.role === "assistant" && record.meta?.messageKind === "assistant_intermediate";
1149
+ };
1150
+ const getPersistedMessageTurnId = (event) => {
1151
+ if (event.type !== "session.message.persisted") return null;
1152
+ const message = event.payload.message;
1153
+ if (!message || typeof message !== "object") return null;
1154
+ const meta = message.meta;
1155
+ return typeof meta?.turnId === "string" ? meta.turnId : null;
1156
+ };
1157
+ var SpacesApi = class {
1158
+ transport;
1159
+ constructor(transport) {
1160
+ this.transport = transport;
1161
+ }
1162
+ list(customFetch) {
1163
+ return this.transport.request("/api/spaces", {
1164
+ method: "GET",
1165
+ fetch: customFetch
1166
+ });
1167
+ }
1168
+ get(spaceId, customFetch) {
1169
+ return this.transport.request(`/api/spaces/${spaceId}`, { fetch: customFetch });
1170
+ }
1171
+ create(input, headers) {
1172
+ return this.transport.request("/api/spaces", {
1173
+ method: "POST",
1174
+ headers: {
1175
+ ...headers,
1176
+ "Content-Type": "application/json"
1177
+ },
1178
+ body: JSON.stringify(input ?? {})
1179
+ });
1180
+ }
1181
+ };
1182
+ var SpaceFilesApi = class {
1183
+ transport;
1184
+ spaceId;
1185
+ constructor(transport, spaceId) {
1186
+ this.transport = transport;
1187
+ this.spaceId = spaceId;
1188
+ }
1189
+ list(path = "", customFetch) {
1190
+ const params = new URLSearchParams();
1191
+ if (path) params.set("path", path);
1192
+ const query = params.toString();
1193
+ return this.transport.request(`/api/spaces/${this.spaceId}/fs/tree${query ? `?${query}` : ""}`, { fetch: customFetch });
1194
+ }
1195
+ read(path, customFetch) {
1196
+ const params = new URLSearchParams({ path });
1197
+ return this.transport.request(`/api/spaces/${this.spaceId}/fs/file?${params.toString()}`, { fetch: customFetch });
1198
+ }
1199
+ readMany(paths, customFetch) {
1200
+ return this.transport.request(`/api/spaces/${this.spaceId}/fs/files`, {
1201
+ method: "POST",
1202
+ headers: { "Content-Type": "application/json" },
1203
+ body: JSON.stringify({ paths }),
1204
+ fetch: customFetch
1205
+ });
1206
+ }
1207
+ /**
1208
+ * Build a direct download URL. For private files, prefer `download()` so the
1209
+ * SDK can attach authorization headers.
1210
+ */
1211
+ getDownloadUrl(path) {
1212
+ const params = new URLSearchParams({ path });
1213
+ return `/api/spaces/${this.spaceId}/fs/download?${params.toString()}`;
1214
+ }
1215
+ async download(path, customFetch) {
1216
+ const params = new URLSearchParams({ path });
1217
+ const raw = await this.transport.raw(`/api/spaces/${this.spaceId}/fs/download?${params.toString()}`, { fetch: customFetch });
1218
+ if (raw.response.status === 202) throw new HttpError("File is being prepared. Please retry shortly.", 202, await raw.json().catch(() => null));
1219
+ const blob = await raw.blob();
1220
+ return {
1221
+ blob,
1222
+ filename: getFilenameFromContentDisposition(raw.response.headers.get("content-disposition")) ?? path.split("/").pop() ?? "download",
1223
+ mimeType: raw.response.headers.get("content-type") ?? blob.type ?? "application/octet-stream"
1224
+ };
1225
+ }
1226
+ write(input) {
1227
+ return this.transport.request(`/api/spaces/${this.spaceId}/fs/file`, {
1228
+ method: "PUT",
1229
+ headers: { "Content-Type": "application/json" },
1230
+ body: JSON.stringify(input)
1231
+ });
1232
+ }
1233
+ createDir(path) {
1234
+ return this.transport.request(`/api/spaces/${this.spaceId}/fs/dir`, {
1235
+ method: "POST",
1236
+ headers: { "Content-Type": "application/json" },
1237
+ body: JSON.stringify({ path })
1238
+ });
1239
+ }
1240
+ delete(path, recursive = false) {
1241
+ const params = new URLSearchParams({ path });
1242
+ if (recursive) params.set("recursive", "true");
1243
+ return this.transport.request(`/api/spaces/${this.spaceId}/fs/node?${params.toString()}`, { method: "DELETE" });
1244
+ }
1245
+ move(input) {
1246
+ return this.transport.request(`/api/spaces/${this.spaceId}/fs/move`, {
1247
+ method: "POST",
1248
+ headers: { "Content-Type": "application/json" },
1249
+ body: JSON.stringify(input)
1250
+ });
1251
+ }
1252
+ upload(files, dir = "") {
1253
+ const params = new URLSearchParams();
1254
+ if (dir) params.set("dir", dir);
1255
+ const query = params.toString();
1256
+ const formData = new FormData();
1257
+ for (const file of files) formData.append("files", file);
1258
+ return this.transport.request(`/api/spaces/${this.spaceId}/fs/upload${query ? `?${query}` : ""}`, {
1259
+ method: "POST",
1260
+ body: formData
1261
+ });
1262
+ }
1263
+ createUpload(input) {
1264
+ return this.transport.request(`/api/spaces/${this.spaceId}/fs/uploads`, {
1265
+ method: "POST",
1266
+ headers: { "Content-Type": "application/json" },
1267
+ body: JSON.stringify(input)
1268
+ });
1269
+ }
1270
+ completeUpload(uploadId, input) {
1271
+ return this.transport.request(`/api/spaces/${this.spaceId}/fs/uploads/${uploadId}/complete`, {
1272
+ method: "POST",
1273
+ headers: { "Content-Type": "application/json" },
1274
+ body: JSON.stringify(input)
1275
+ });
1276
+ }
1277
+ };
1278
+ var SessionMessagesClient = class {
1279
+ transport;
1280
+ sessionId;
1281
+ lastSentSignature = "";
1282
+ lastSentSessionId = "";
1283
+ lastSentAt = 0;
1284
+ constructor(transport, sessionId) {
1285
+ this.transport = transport;
1286
+ this.sessionId = sessionId;
1287
+ }
1288
+ list(customFetch) {
1289
+ return this.transport.request(`/api/sessions/${this.sessionId}/messages`, { fetch: customFetch });
1290
+ }
1291
+ get(messageId, optionsOrFetch, customFetch) {
1292
+ const options = typeof optionsOrFetch === "function" ? void 0 : optionsOrFetch;
1293
+ const fetch = typeof optionsOrFetch === "function" ? optionsOrFetch : customFetch;
1294
+ const params = new URLSearchParams();
1295
+ if (options?.detail) params.set("detail", options.detail);
1296
+ const query = params.toString();
1297
+ return this.transport.request(`/api/sessions/${this.sessionId}/messages/${messageId}${query ? `?${query}` : ""}`, { fetch });
1298
+ }
1299
+ listPaginated(options, customFetch) {
1300
+ const params = new URLSearchParams();
1301
+ if (options?.cursor !== void 0) params.set("cursor", String(options.cursor));
1302
+ if (options?.limit !== void 0) params.set("limit", String(options.limit));
1303
+ if (options?.direction) params.set("direction", options.direction);
1304
+ const query = params.toString();
1305
+ return this.transport.request(`/api/sessions/${this.sessionId}/messages${query ? `?${query}` : ""}`, { fetch: customFetch });
1306
+ }
1307
+ async send(input) {
1308
+ const signature = JSON.stringify({
1309
+ sessionId: this.sessionId,
1310
+ input
1311
+ });
1312
+ const now = Date.now();
1313
+ if (this.sessionId === this.lastSentSessionId && signature === this.lastSentSignature && now - this.lastSentAt < DEFAULT_DEDUP_WINDOW_MS) throw new Error("Duplicate message ignored");
1314
+ this.lastSentSessionId = this.sessionId;
1315
+ this.lastSentSignature = signature;
1316
+ this.lastSentAt = now;
1317
+ return this.transport.request(`/api/sessions/${this.sessionId}/messages`, {
1318
+ method: "POST",
1319
+ headers: { "Content-Type": "application/json" },
1320
+ body: JSON.stringify({
1321
+ content: input.content,
1322
+ model: input.model,
1323
+ provider: input.provider,
1324
+ clientMessageId: input.clientMessageId
1325
+ })
1326
+ });
1327
+ }
1328
+ };
1329
+ var SessionTurnsClient = class {
1330
+ transport;
1331
+ sessionId;
1332
+ constructor(transport, sessionId) {
1333
+ this.transport = transport;
1334
+ this.sessionId = sessionId;
1335
+ }
1336
+ listPaginated(options, customFetch) {
1337
+ const params = new URLSearchParams();
1338
+ if (options?.cursor !== void 0) params.set("cursor", String(options.cursor));
1339
+ if (options?.limit !== void 0) params.set("limit", String(options.limit));
1340
+ if (options?.direction) params.set("direction", options.direction);
1341
+ const query = params.toString();
1342
+ return this.transport.request(`/api/sessions/${this.sessionId}/turns${query ? `?${query}` : ""}`, { fetch: customFetch });
1343
+ }
1344
+ index(options, customFetch) {
1345
+ const params = new URLSearchParams();
1346
+ if (options?.cursor !== void 0) params.set("cursor", String(options.cursor));
1347
+ if (options?.limit !== void 0) params.set("limit", String(options.limit));
1348
+ const query = params.toString();
1349
+ return this.transport.request(`/api/sessions/${this.sessionId}/turns/index${query ? `?${query}` : ""}`, { fetch: customFetch });
1350
+ }
1351
+ window(options, customFetch) {
1352
+ const params = new URLSearchParams();
1353
+ if (options.sequence !== void 0) params.set("sequence", String(options.sequence));
1354
+ if (options.turnId) params.set("turnId", options.turnId);
1355
+ if (options.before !== void 0) params.set("before", String(options.before));
1356
+ if (options.after !== void 0) params.set("after", String(options.after));
1357
+ const query = params.toString();
1358
+ return this.transport.request(`/api/sessions/${this.sessionId}/turns/window${query ? `?${query}` : ""}`, { fetch: customFetch });
1359
+ }
1360
+ streamSnapshot(customFetch) {
1361
+ return this.transport.request(`/api/sessions/${this.sessionId}/turns/stream-snapshot`, { fetch: customFetch });
1362
+ }
1363
+ get(turnId, customFetch) {
1364
+ return this.transport.request(`/api/sessions/${this.sessionId}/turns/${turnId}`, { fetch: customFetch });
1365
+ }
1366
+ signedUrls(turnId, objectKeys) {
1367
+ return this.transport.request(`/api/sessions/${this.sessionId}/turns/${turnId}/signed-urls`, {
1368
+ method: "POST",
1369
+ headers: { "Content-Type": "application/json" },
1370
+ body: JSON.stringify({ objectKeys })
1371
+ });
1372
+ }
1373
+ };
1374
+ var SessionRealtimeClient = class {
1375
+ websocketClient;
1376
+ spaceId;
1377
+ sessionId;
1378
+ patchReducer = new SessionPatchReducer();
1379
+ constructor(websocketClient, spaceId, sessionId) {
1380
+ this.websocketClient = websocketClient;
1381
+ this.spaceId = spaceId;
1382
+ this.sessionId = sessionId;
1383
+ }
1384
+ subscribe(handlers) {
1385
+ if (!this.websocketClient) throw new Error("realtime transport is not configured for this client");
1386
+ ensureRealtimeConnected(this.websocketClient);
1387
+ const unsubscribe = this.websocketClient.on("event", (event) => {
1388
+ if (event.spaceId !== this.spaceId || event.sessionId !== this.sessionId) return;
1389
+ handlers.event?.(event);
1390
+ const eventName = toSessionEventName(event.type);
1391
+ if (eventName === "turn.patch") {
1392
+ handlers.patch?.(event);
1393
+ if (event.type === "session.turn.patch") {
1394
+ const payload = event.payload;
1395
+ if (typeof payload.seq === "number" && typeof payload.baseSeq === "number" && Array.isArray(payload.ops)) handlers.patchState?.(this.patchReducer.applyPatch({
1396
+ spaceId: this.spaceId,
1397
+ sessionId: this.sessionId,
1398
+ turnId: typeof payload.turnId === "string" ? payload.turnId : null,
1399
+ seq: payload.seq,
1400
+ baseSeq: payload.baseSeq,
1401
+ ops: payload.ops,
1402
+ anchorUserMessageId: typeof payload.anchorUserMessageId === "string" ? payload.anchorUserMessageId : null
1403
+ }));
1404
+ }
1405
+ }
1406
+ if (eventName === "turn.snapshot") handlers.snapshot?.(event);
1407
+ if (eventName === "turn.progress") handlers.progress?.(event);
1408
+ if (eventName === "turn.error") {
1409
+ this.patchReducer.fail({
1410
+ spaceId: this.spaceId,
1411
+ sessionId: this.sessionId
1412
+ });
1413
+ handlers.error?.(event);
1414
+ }
1415
+ if (eventName === "message.persisted") {
1416
+ handlers.persisted?.(event);
1417
+ if (isAssistantIntermediatePersistedEvent(event)) this.patchReducer.reset({
1418
+ spaceId: this.spaceId,
1419
+ sessionId: this.sessionId
1420
+ });
1421
+ }
1422
+ if (eventName === "turn.updated") handlers.turnUpdated?.(event);
1423
+ if (eventName === "turn.final") {
1424
+ this.patchReducer.complete({
1425
+ spaceId: this.spaceId,
1426
+ sessionId: this.sessionId,
1427
+ turnId: typeof event.payload.turn === "object" && event.payload.turn && "id" in event.payload.turn ? String(event.payload.turn.id) : null
1428
+ });
1429
+ handlers.turnFinalized?.(event);
1430
+ handlers.final?.(event);
1431
+ }
1432
+ if (isAssistantFinalPersistedEvent(event)) {
1433
+ this.patchReducer.complete({
1434
+ spaceId: this.spaceId,
1435
+ sessionId: this.sessionId,
1436
+ turnId: getPersistedMessageTurnId(event)
1437
+ });
1438
+ handlers.final?.(event);
1439
+ }
1440
+ });
1441
+ return () => unsubscribe();
1442
+ }
1443
+ on(type, handler) {
1444
+ return this.subscribe({ event: (event) => {
1445
+ if (type === "turn.final" && isAssistantFinalPersistedEvent(event)) {
1446
+ handler(event);
1447
+ return;
1448
+ }
1449
+ if (toSessionEventName(event.type) === type) handler(event);
1450
+ } });
1451
+ }
1452
+ };
1453
+ var SessionClient = class {
1454
+ spaceId;
1455
+ id;
1456
+ transport;
1457
+ messages;
1458
+ turns;
1459
+ realtime;
1460
+ generation;
1461
+ constructor(spaceId, id, transport, websocketClient) {
1462
+ this.spaceId = spaceId;
1463
+ this.id = id;
1464
+ this.transport = transport;
1465
+ this.messages = new SessionMessagesClient(transport, id);
1466
+ this.turns = new SessionTurnsClient(transport, id);
1467
+ this.realtime = new SessionRealtimeClient(websocketClient, spaceId, id);
1468
+ this.generation = new SessionGenerationStreamClient(websocketClient, spaceId, id);
1469
+ }
1470
+ get(customFetch) {
1471
+ return this.transport.request(`/api/sessions/${this.id}`, { fetch: customFetch });
1472
+ }
1473
+ rename(title, customFetch) {
1474
+ return this.transport.request(`/api/sessions/${this.id}`, {
1475
+ method: "PATCH",
1476
+ body: JSON.stringify({ title }),
1477
+ fetch: customFetch
1478
+ });
1479
+ }
1480
+ abort(optionsOrFetch, customFetch) {
1481
+ const options = typeof optionsOrFetch === "function" ? void 0 : optionsOrFetch;
1482
+ const fetch = typeof optionsOrFetch === "function" ? optionsOrFetch : customFetch;
1483
+ return this.transport.request(`/api/sessions/${this.id}/abort`, {
1484
+ method: "POST",
1485
+ headers: { "Content-Type": "application/json" },
1486
+ body: JSON.stringify({ turnId: options?.turnId ?? null }),
1487
+ fetch
1488
+ });
1489
+ }
1490
+ turn(turnId) {
1491
+ return { fork: (input = {}) => this.transport.request(`/api/sessions/${this.id}/turns/${turnId}/fork`, {
1492
+ method: "POST",
1493
+ headers: { "Content-Type": "application/json" },
1494
+ body: JSON.stringify(input)
1495
+ }) };
1496
+ }
1497
+ subscribe(handlers) {
1498
+ return this.realtime.subscribe(handlers);
1499
+ }
1500
+ subscribeGeneration(handlers) {
1501
+ return this.generation.subscribe(handlers);
1502
+ }
1503
+ on(type, handler) {
1504
+ return this.realtime.on(type, handler);
1505
+ }
1506
+ };
1507
+ var SpaceSessionsApi = class {
1508
+ transport;
1509
+ spaceId;
1510
+ websocketClient;
1511
+ constructor(transport, spaceId, websocketClient) {
1512
+ this.transport = transport;
1513
+ this.spaceId = spaceId;
1514
+ this.websocketClient = websocketClient;
1515
+ }
1516
+ create(input) {
1517
+ return this.transport.request(`/api/spaces/${this.spaceId}/sessions`, {
1518
+ method: "POST",
1519
+ headers: { "Content-Type": "application/json" },
1520
+ body: JSON.stringify(input ?? {})
1521
+ });
1522
+ }
1523
+ list(optionsOrFetch, customFetch) {
1524
+ const options = typeof optionsOrFetch === "function" ? void 0 : optionsOrFetch;
1525
+ const fetch = typeof optionsOrFetch === "function" ? optionsOrFetch : customFetch;
1526
+ const params = new URLSearchParams();
1527
+ if (options?.limit !== void 0) params.set("limit", String(options.limit));
1528
+ if (options?.cursor) params.set("cursor", options.cursor);
1529
+ if (options?.includeForks) params.set("includeForks", "1");
1530
+ const query = params.toString();
1531
+ return this.transport.request(`/api/spaces/${this.spaceId}/sessions${query ? `?${query}` : ""}`, { fetch });
1532
+ }
1533
+ byId(sessionId) {
1534
+ return new SessionClient(this.spaceId, sessionId, this.transport, this.websocketClient);
1535
+ }
1536
+ };
1537
+ var SpaceEventsApi = class {
1538
+ websocketClient;
1539
+ spaceId;
1540
+ constructor(websocketClient, spaceId) {
1541
+ this.websocketClient = websocketClient;
1542
+ this.spaceId = spaceId;
1543
+ }
1544
+ subscribe(handler) {
1545
+ if (!this.websocketClient) throw new Error("realtime transport is not configured for this client");
1546
+ ensureRealtimeConnected(this.websocketClient);
1547
+ return this.websocketClient.on("event", (event) => {
1548
+ if (event.spaceId !== this.spaceId) return;
1549
+ handler(event);
1550
+ });
1551
+ }
1552
+ on(type, handler) {
1553
+ return this.subscribe((event) => {
1554
+ if (type === "event") {
1555
+ handler(event);
1556
+ return;
1557
+ }
1558
+ if (type === "ports.changed" && event.type === "space.ports.changed") {
1559
+ handler(event);
1560
+ return;
1561
+ }
1562
+ if (type === "turn.final" && isAssistantFinalPersistedEvent(event)) {
1563
+ handler(event);
1564
+ return;
1565
+ }
1566
+ if (toSessionEventName(event.type) === type) handler(event);
1567
+ });
1568
+ }
1569
+ };
1570
+ var SpaceMembersApi = class {
1571
+ transport;
1572
+ spaceId;
1573
+ constructor(transport, spaceId) {
1574
+ this.transport = transport;
1575
+ this.spaceId = spaceId;
1576
+ }
1577
+ list() {
1578
+ return this.transport.request(`/api/spaces/${this.spaceId}/members`);
1579
+ }
1580
+ update(userId, role) {
1581
+ return this.transport.request(`/api/spaces/${this.spaceId}/members`, {
1582
+ method: "PUT",
1583
+ headers: { "Content-Type": "application/json" },
1584
+ body: JSON.stringify({
1585
+ userId,
1586
+ role
1587
+ })
1588
+ });
1589
+ }
1590
+ remove(userId) {
1591
+ return this.transport.request(`/api/spaces/${this.spaceId}/members`, {
1592
+ method: "DELETE",
1593
+ headers: { "Content-Type": "application/json" },
1594
+ body: JSON.stringify({ userId })
1595
+ });
1596
+ }
1597
+ };
1598
+ var SpaceAccessApi = class {
1599
+ transport;
1600
+ spaceId;
1601
+ constructor(transport, spaceId) {
1602
+ this.transport = transport;
1603
+ this.spaceId = spaceId;
1604
+ }
1605
+ get() {
1606
+ return this.transport.request(`/api/spaces/${this.spaceId}/access`);
1607
+ }
1608
+ set(body) {
1609
+ return this.transport.request(`/api/spaces/${this.spaceId}/access`, {
1610
+ method: "PATCH",
1611
+ headers: { "Content-Type": "application/json" },
1612
+ body: JSON.stringify(body)
1613
+ });
1614
+ }
1615
+ };
1616
+ var SpaceUsageApi = class {
1617
+ transport;
1618
+ spaceId;
1619
+ constructor(transport, spaceId) {
1620
+ this.transport = transport;
1621
+ this.spaceId = spaceId;
1622
+ }
1623
+ get(days = 30, customFetch) {
1624
+ const params = new URLSearchParams({ days: String(days) });
1625
+ return this.transport.request(`/api/spaces/${this.spaceId}/usage?${params.toString()}`, { fetch: customFetch });
1626
+ }
1627
+ };
1628
+ var SpaceChannelsApi = class {
1629
+ transport;
1630
+ spaceId;
1631
+ constructor(transport, spaceId) {
1632
+ this.transport = transport;
1633
+ this.spaceId = spaceId;
1634
+ }
1635
+ list() {
1636
+ return this.transport.request(`/api/spaces/${this.spaceId}/channels`);
1637
+ }
1638
+ bind(channelId, config) {
1639
+ return this.transport.request(`/api/spaces/${this.spaceId}/channels/${channelId}`, {
1640
+ method: "POST",
1641
+ headers: { "Content-Type": "application/json" },
1642
+ body: JSON.stringify({ config: config ?? null })
1643
+ });
1644
+ }
1645
+ unbind(channelId) {
1646
+ return this.transport.request(`/api/spaces/${this.spaceId}/channels/${channelId}`, { method: "DELETE" });
1647
+ }
1648
+ };
1649
+ var SpaceEnvApi = class {
1650
+ transport;
1651
+ spaceId;
1652
+ constructor(transport, spaceId) {
1653
+ this.transport = transport;
1654
+ this.spaceId = spaceId;
1655
+ }
1656
+ list() {
1657
+ return this.transport.request(`/api/spaces/${this.spaceId}/env`);
1658
+ }
1659
+ create(input) {
1660
+ return this.transport.request(`/api/spaces/${this.spaceId}/env`, {
1661
+ method: "POST",
1662
+ headers: { "Content-Type": "application/json" },
1663
+ body: JSON.stringify(input)
1664
+ });
1665
+ }
1666
+ update(name, value) {
1667
+ return this.transport.request(`/api/spaces/${this.spaceId}/env/${encodeURIComponent(name)}`, {
1668
+ method: "PUT",
1669
+ headers: { "Content-Type": "application/json" },
1670
+ body: JSON.stringify({ value })
1671
+ });
1672
+ }
1673
+ remove(name) {
1674
+ return this.transport.request(`/api/spaces/${this.spaceId}/env/${encodeURIComponent(name)}`, { method: "DELETE" });
1675
+ }
1676
+ };
1677
+ var SpaceSandboxApi = class {
1678
+ transport;
1679
+ spaceId;
1680
+ constructor(transport, spaceId) {
1681
+ this.transport = transport;
1682
+ this.spaceId = spaceId;
1683
+ }
1684
+ get() {
1685
+ return this.transport.request(`/api/spaces/${this.spaceId}/sandbox`);
1686
+ }
1687
+ ports() {
1688
+ return this.transport.request(`/api/spaces/${this.spaceId}/sandbox/ports`);
1689
+ }
1690
+ recreate() {
1691
+ return this.transport.request(`/api/spaces/${this.spaceId}/sandbox/recreate`, { method: "POST" });
1692
+ }
1693
+ };
1694
+ var SpaceMarksApi = class {
1695
+ transport;
1696
+ spaceId;
1697
+ constructor(transport, spaceId) {
1698
+ this.transport = transport;
1699
+ this.spaceId = spaceId;
1700
+ }
1701
+ list(kind = "pin") {
1702
+ const params = new URLSearchParams({ kind });
1703
+ return this.transport.request(`/api/spaces/${this.spaceId}/marks?${params.toString()}`);
1704
+ }
1705
+ create(input) {
1706
+ return this.transport.request(`/api/spaces/${this.spaceId}/marks`, {
1707
+ method: "POST",
1708
+ headers: { "Content-Type": "application/json" },
1709
+ body: JSON.stringify({
1710
+ kind: "pin",
1711
+ ...input
1712
+ })
1713
+ });
1714
+ }
1715
+ delete(markId) {
1716
+ return this.transport.request(`/api/spaces/${this.spaceId}/marks/${markId}`, { method: "DELETE" });
1717
+ }
1718
+ };
1719
+ var SpaceCheckpointsApi = class {
1720
+ transport;
1721
+ spaceId;
1722
+ constructor(transport, spaceId) {
1723
+ this.transport = transport;
1724
+ this.spaceId = spaceId;
1725
+ }
1726
+ create(description) {
1727
+ return this.transport.request(`/api/spaces/${this.spaceId}/checkpoints`, {
1728
+ method: "POST",
1729
+ headers: { "Content-Type": "application/json" },
1730
+ body: JSON.stringify({ description: description ?? null })
1731
+ });
1732
+ }
1733
+ list() {
1734
+ return this.transport.request(`/api/spaces/${this.spaceId}/checkpoints`);
1735
+ }
1736
+ get(checkpointId, customFetch) {
1737
+ return this.transport.request(`/api/spaces/${this.spaceId}/checkpoints/${checkpointId}`, { fetch: customFetch });
1738
+ }
1739
+ };
1740
+ var SpaceClient = class {
1741
+ id;
1742
+ transport;
1743
+ websocketClient;
1744
+ files;
1745
+ sessions;
1746
+ members;
1747
+ access;
1748
+ checkpoints;
1749
+ usage;
1750
+ channels;
1751
+ env;
1752
+ sandbox;
1753
+ invitations;
1754
+ marks;
1755
+ constructor(id, transport, websocketClient) {
1756
+ this.id = id;
1757
+ this.transport = transport;
1758
+ this.websocketClient = websocketClient;
1759
+ this.files = new SpaceFilesApi(transport, id);
1760
+ this.sessions = new SpaceSessionsApi(transport, id, websocketClient);
1761
+ this.members = new SpaceMembersApi(transport, id);
1762
+ this.access = new SpaceAccessApi(transport, id);
1763
+ this.checkpoints = new SpaceCheckpointsApi(transport, id);
1764
+ this.usage = new SpaceUsageApi(transport, id);
1765
+ this.channels = new SpaceChannelsApi(transport, id);
1766
+ this.env = new SpaceEnvApi(transport, id);
1767
+ this.sandbox = new SpaceSandboxApi(transport, id);
1768
+ this.invitations = new SpaceInvitationsApi(transport, id);
1769
+ this.marks = new SpaceMarksApi(transport, id);
1770
+ }
1771
+ get(customFetch) {
1772
+ return this.transport.request(`/api/spaces/${this.id}`, { fetch: customFetch });
1773
+ }
1774
+ prompt(input) {
1775
+ return this.transport.request(`/api/spaces/${this.id}/prompt`, {
1776
+ method: "POST",
1777
+ headers: { "Content-Type": "application/json" },
1778
+ body: JSON.stringify(input)
1779
+ });
1780
+ }
1781
+ rename(name) {
1782
+ return this.transport.request(`/api/spaces/${this.id}`, {
1783
+ method: "PATCH",
1784
+ headers: { "Content-Type": "application/json" },
1785
+ body: JSON.stringify({ name })
1786
+ });
1787
+ }
1788
+ profile(body) {
1789
+ return this.transport.request(`/api/spaces/${this.id}/profile`, {
1790
+ method: "PATCH",
1791
+ headers: { "Content-Type": "application/json" },
1792
+ body: JSON.stringify(body)
1793
+ });
1794
+ }
1795
+ session(sessionId) {
1796
+ return new SessionClient(this.id, sessionId, this.transport, this.websocketClient);
1797
+ }
1798
+ subscribe(handler) {
1799
+ return new SpaceEventsApi(this.websocketClient, this.id).subscribe(handler);
1800
+ }
1801
+ on(type, handler) {
1802
+ return new SpaceEventsApi(this.websocketClient, this.id).on(type, handler);
1803
+ }
1804
+ };
1805
+ //#endregion
1806
+ //#region src/apis/tasks.ts
1807
+ var TasksApi = class {
1808
+ transport;
1809
+ constructor(transport) {
1810
+ this.transport = transport;
1811
+ }
1812
+ get(taskRunId) {
1813
+ return this.transport.request(`/api/tasks/${taskRunId}`);
1814
+ }
1815
+ list(filters) {
1816
+ const params = new URLSearchParams();
1817
+ if (filters?.cronJobId) params.set("cronJobId", filters.cronJobId);
1818
+ if (filters?.spaceId) params.set("spaceId", filters.spaceId);
1819
+ const query = params.toString();
1820
+ return this.transport.request(`/api/tasks${query ? `?${query}` : ""}`);
1821
+ }
1822
+ };
1823
+ //#endregion
1824
+ //#region src/apis/user.ts
1825
+ var UserApi = class {
1826
+ transport;
1827
+ transportBaseUrl;
1828
+ setStoredAuthToken;
1829
+ clearStoredAuthToken;
1830
+ constructor(transport, transportBaseUrl, setStoredAuthToken, clearStoredAuthToken) {
1831
+ this.transport = transport;
1832
+ this.transportBaseUrl = transportBaseUrl;
1833
+ this.setStoredAuthToken = setStoredAuthToken;
1834
+ this.clearStoredAuthToken = clearStoredAuthToken;
1835
+ }
1836
+ getMe(customFetch) {
1837
+ return this.transport.request("/api/me", { fetch: customFetch });
1838
+ }
1839
+ updateProfile(input) {
1840
+ return this.transport.request("/api/me/profile", {
1841
+ method: "PATCH",
1842
+ headers: { "Content-Type": "application/json" },
1843
+ body: JSON.stringify(input)
1844
+ });
1845
+ }
1846
+ getRules(customFetch) {
1847
+ return this.transport.request("/api/me/rules", {
1848
+ method: "GET",
1849
+ fetch: customFetch
1850
+ });
1851
+ }
1852
+ async setAuthToken(token) {
1853
+ const trimmedToken = token.trim();
1854
+ const response = await fetch(this.transportBaseUrl ? `${this.transportBaseUrl}/api/me` : "/api/me", { headers: { Authorization: `Bearer ${trimmedToken}` } });
1855
+ if (!response.ok) {
1856
+ const body = (response.headers.get("content-type") ?? "").includes("application/json") ? await response.json().catch(() => null) : await response.text().catch(() => response.statusText);
1857
+ throw new HttpError((typeof body === "string" ? body : JSON.stringify(body ?? null)) || response.statusText, response.status, body);
1858
+ }
1859
+ this.setStoredAuthToken?.(trimmedToken);
1860
+ return response.json();
1861
+ }
1862
+ async clearAuthToken() {
1863
+ this.clearStoredAuthToken?.();
1864
+ return null;
1865
+ }
1866
+ getSshKeys(customFetch) {
1867
+ return this.transport.request("/api/user/ssh-keys", {
1868
+ method: "GET",
1869
+ fetch: customFetch
1870
+ });
1871
+ }
1872
+ createSshKey(data) {
1873
+ return this.transport.request("/api/user/ssh-keys", {
1874
+ method: "POST",
1875
+ headers: { "Content-Type": "application/json" },
1876
+ body: JSON.stringify(data)
1877
+ });
1878
+ }
1879
+ deleteSshKey(id) {
1880
+ return this.transport.request(`/api/user/ssh-keys/${id}`, { method: "DELETE" });
1881
+ }
1882
+ };
1883
+ //#endregion
1884
+ //#region src/http.ts
1885
+ var CohubHttpClient = class {
1886
+ spaces;
1887
+ channels;
1888
+ user;
1889
+ generations;
1890
+ models;
1891
+ prompts;
1892
+ sessionAccess;
1893
+ search;
1894
+ tasks;
1895
+ cronJobs;
1896
+ invite;
1897
+ transport;
1898
+ constructor(options = {}) {
1899
+ const apiBaseUrl = resolveApiBaseUrl(options);
1900
+ this.transport = new HttpTransport(options);
1901
+ this.spaces = new SpacesApi(this.transport);
1902
+ this.channels = new ChannelsApi(this.transport);
1903
+ this.user = new UserApi(this.transport, apiBaseUrl, options.setStoredAuthToken, options.clearStoredAuthToken);
1904
+ this.generations = new GenerationsApi(this.transport);
1905
+ this.models = new ModelsApi(this.transport);
1906
+ this.prompts = new PromptsApi(this.transport);
1907
+ this.sessionAccess = new SessionAccessApi(this.transport);
1908
+ this.search = new SearchApi(this.transport);
1909
+ this.tasks = new TasksApi(this.transport);
1910
+ this.cronJobs = new CronJobsApi(this.transport);
1911
+ this.invite = new PublicInviteApi(this.transport);
1912
+ }
1913
+ space(spaceId) {
1914
+ return new SpaceClient(spaceId, this.transport, null);
1915
+ }
1916
+ };
1917
+ const createHttpClient = (options) => new CohubHttpClient(options);
1918
+ //#endregion
1919
+ export { PromptsApi as _, SpaceClient as a, CronJobsApi as b, SessionGenerationStreamClient as c, SessionPatchReducer as d, createSessionPatchReducer as f, SearchApi as g, SessionAccessApi as h, TasksApi as i, createSessionGenerationStreamClient as l, HttpTransport as m, createHttpClient as n, SpacesApi as o, HttpError as p, UserApi as r, PublicInviteApi as s, CohubHttpClient as t, parseAssistantMessageCommit as u, ModelsApi as v, ChannelsApi as x, GenerationsApi as y };