@neta-art/cohub 4.7.1 → 4.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -0
- package/dist/chunks/http.d.ts +3 -1
- package/dist/chunks/http.js +1 -1
- package/dist/chunks/transport.js +7 -2
- package/dist/chunks/websocket.d.ts +171 -4
- package/dist/chunks/websocket.js +56 -4
- package/dist/http.d.ts +1 -1
- package/dist/index.d.ts +136 -2
- package/dist/index.js +863 -229
- package/docs/work-runtime-guide.md +96 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { A as CronJobsApi, C as ReferencesApi, D as PromptsApi, E as SkillsApi, O as ModelsApi, S as SessionAccessApi, T as PublicAssetsApi, _ as createSessionGenerationStreamClient, a as ReferralsApi, b as createSessionPatchReducer, c as TasksApi, d as SpaceClient, f as SpacesApi, g as SessionGenerationStreamClient, h as buildSpacePath, i as WorksApi, j as ChannelsApi, k as GenerationsApi, l as BoardClient, m as buildSpaceInvitePath, n as createHttpClient, o as UsersApi, p as PublicInviteApi, r as WorkCommerceApi, s as UserApi, t as CohubHttpClient, u as BoardTransactionError, v as parseAssistantMessageCommit, w as SearchApi, x as ensureRealtimeConnected, y as SessionPatchReducer } from "./chunks/http.js";
|
|
2
|
-
import { a as COHUB_SOURCE_HEADER, c as hasRequestSourceIdentity, d as mergeRequestSourceIntoMeta, f as normalizeRequestSource, g as resolveRequestSourceChannel, h as requestSourceToHeaders, i as sanitizeAccessToken, l as isRequestSourceEmpty, m as readRequestSourceFromEnv, n as HttpTransport, o as COHUB_SOURCE_HEADER_NAMES, p as parseRequestSourceFromHeaders, r as joinApiUrl, s as REQUEST_SOURCE_VIA_MAX_LENGTH, t as HttpError, u as isRequestSourceUuid } from "./chunks/transport.js";
|
|
2
|
+
import { _ as REALTIME_ROOM_EVENT_NAME_PATTERN, a as COHUB_SOURCE_HEADER, c as hasRequestSourceIdentity, d as mergeRequestSourceIntoMeta, f as normalizeRequestSource, g as resolveRequestSourceChannel, h as requestSourceToHeaders, i as sanitizeAccessToken, l as isRequestSourceEmpty, m as readRequestSourceFromEnv, n as HttpTransport, o as COHUB_SOURCE_HEADER_NAMES, p as parseRequestSourceFromHeaders, r as joinApiUrl, s as REQUEST_SOURCE_VIA_MAX_LENGTH, t as HttpError, u as isRequestSourceUuid } from "./chunks/transport.js";
|
|
3
3
|
import { a as resolveApiBaseUrl, c as resolveWebsocketUrl, i as normalizeWebsocketUrl, n as normalizeBaseUrl, o as resolveCohubEnvironment, r as normalizeVoiceInputWebsocketUrl, s as resolveVoiceInputWebsocketUrl, t as COHUB_ENVIRONMENTS } from "./chunks/environment.js";
|
|
4
4
|
import { a as extractBillingPayload, c as isFeatureNotEntitledError, i as FEATURE_NOT_ENTITLED_ERROR_CODE, l as isHttpErrorCode, n as createWebsocketClient, o as isBillingAccessBlockedCode, r as BILLING_ACCESS_BLOCKED_ERROR_CODE, s as isBillingAccessBlockedError, t as WebsocketClient } from "./chunks/websocket.js";
|
|
5
5
|
import { VoiceApi, VoiceInputClient, createVoiceInputClient } from "./voice-input.js";
|
|
@@ -81,6 +81,779 @@ var ExploreApi = class {
|
|
|
81
81
|
}
|
|
82
82
|
};
|
|
83
83
|
//#endregion
|
|
84
|
+
//#region ../protocol/dist/board-constants.js
|
|
85
|
+
const DEFAULT_BOARD_RENDER_LIMITS = {
|
|
86
|
+
particles: 2e4,
|
|
87
|
+
vertices: 5e5,
|
|
88
|
+
dynamicVertices: 15e4,
|
|
89
|
+
drawCalls: 400,
|
|
90
|
+
filterPasses: 24,
|
|
91
|
+
renderTexturePixels: 16777216,
|
|
92
|
+
textureBytes: 512 * 1024 * 1024,
|
|
93
|
+
bufferBytes: 256 * 1024 * 1024,
|
|
94
|
+
simulationSteps: 1e5
|
|
95
|
+
};
|
|
96
|
+
const BOARD_BUILTIN_CLIP_KINDS = [
|
|
97
|
+
"motion.keyframes",
|
|
98
|
+
"motion.path",
|
|
99
|
+
"draw.reveal",
|
|
100
|
+
"draw.handwrite",
|
|
101
|
+
"text.reveal",
|
|
102
|
+
"effects.particles",
|
|
103
|
+
"effects.trail",
|
|
104
|
+
"effects.impact",
|
|
105
|
+
"effects.flash",
|
|
106
|
+
"effects.color",
|
|
107
|
+
"camera.pan",
|
|
108
|
+
"camera.zoom",
|
|
109
|
+
"camera.shake"
|
|
110
|
+
];
|
|
111
|
+
const BOARD_BUILTIN_EFFECT_KINDS = ["effects.pulse", "effects.float"];
|
|
112
|
+
const BOARD_ARROW_STROKE_SIZE = 2.5;
|
|
113
|
+
const BOARD_BUILTIN_CAPABILITIES = [...BOARD_BUILTIN_CLIP_KINDS.map((id) => ({
|
|
114
|
+
kind: "clip",
|
|
115
|
+
id,
|
|
116
|
+
version: 1,
|
|
117
|
+
renderers: ["webgpu", "webgl"]
|
|
118
|
+
})), ...BOARD_BUILTIN_EFFECT_KINDS.map((id) => ({
|
|
119
|
+
kind: "effect",
|
|
120
|
+
id,
|
|
121
|
+
version: 1,
|
|
122
|
+
renderers: ["webgpu", "webgl"]
|
|
123
|
+
}))];
|
|
124
|
+
//#endregion
|
|
125
|
+
//#region ../protocol/dist/realtime/board-awareness.js
|
|
126
|
+
const idSchema$1 = z.string().min(1).max(160);
|
|
127
|
+
const finiteSchema$1 = z.number().finite();
|
|
128
|
+
const BoardAwarenessPointSchema = z.object({
|
|
129
|
+
x: finiteSchema$1,
|
|
130
|
+
y: finiteSchema$1
|
|
131
|
+
});
|
|
132
|
+
const BoardAwarenessDrawPointSchema = BoardAwarenessPointSchema.extend({ p: finiteSchema$1.min(0).max(1) });
|
|
133
|
+
const BoardAwarenessFrameSchema = z.object({
|
|
134
|
+
x: finiteSchema$1,
|
|
135
|
+
y: finiteSchema$1,
|
|
136
|
+
width: finiteSchema$1.positive(),
|
|
137
|
+
height: finiteSchema$1.positive(),
|
|
138
|
+
rotation: finiteSchema$1
|
|
139
|
+
});
|
|
140
|
+
const arrowEndpointSchema = z.union([z.object({
|
|
141
|
+
kind: z.literal("point"),
|
|
142
|
+
x: finiteSchema$1,
|
|
143
|
+
y: finiteSchema$1
|
|
144
|
+
}), z.object({
|
|
145
|
+
kind: z.literal("binding"),
|
|
146
|
+
target: idSchema$1,
|
|
147
|
+
nx: finiteSchema$1,
|
|
148
|
+
ny: finiteSchema$1,
|
|
149
|
+
precise: z.boolean()
|
|
150
|
+
})]);
|
|
151
|
+
const BoardAwarenessNodePreviewSchema = z.object({
|
|
152
|
+
nodeId: idSchema$1,
|
|
153
|
+
frame: BoardAwarenessFrameSchema,
|
|
154
|
+
arrow: z.object({
|
|
155
|
+
start: arrowEndpointSchema,
|
|
156
|
+
end: arrowEndpointSchema,
|
|
157
|
+
bend: finiteSchema$1
|
|
158
|
+
}).optional()
|
|
159
|
+
});
|
|
160
|
+
const BoardAwarenessStateUpdateSchema = z.object({
|
|
161
|
+
type: z.literal("state"),
|
|
162
|
+
client: z.object({ formFactor: z.enum(["desktop", "mobile"]) }).optional(),
|
|
163
|
+
cursor: BoardAwarenessPointSchema.extend({ pointerType: z.enum([
|
|
164
|
+
"mouse",
|
|
165
|
+
"pen",
|
|
166
|
+
"touch"
|
|
167
|
+
]) }).nullable(),
|
|
168
|
+
tool: z.string().min(1).max(40),
|
|
169
|
+
selection: z.object({
|
|
170
|
+
ids: z.array(idSchema$1).max(64),
|
|
171
|
+
count: z.number().int().nonnegative().max(5e4),
|
|
172
|
+
bounds: BoardAwarenessFrameSchema.nullable()
|
|
173
|
+
}),
|
|
174
|
+
editingId: idSchema$1.nullable()
|
|
175
|
+
});
|
|
176
|
+
const BoardAwarenessGestureSchema = z.discriminatedUnion("kind", [
|
|
177
|
+
z.object({
|
|
178
|
+
kind: z.literal("draw"),
|
|
179
|
+
id: idSchema$1,
|
|
180
|
+
nodeId: idSchema$1,
|
|
181
|
+
color: z.string().min(1).max(64),
|
|
182
|
+
size: finiteSchema$1.positive().max(256),
|
|
183
|
+
from: z.number().int().nonnegative().max(1e5),
|
|
184
|
+
points: z.array(BoardAwarenessDrawPointSchema).min(1).max(64)
|
|
185
|
+
}),
|
|
186
|
+
z.object({
|
|
187
|
+
kind: z.literal("arrow"),
|
|
188
|
+
id: idSchema$1,
|
|
189
|
+
nodeId: idSchema$1,
|
|
190
|
+
start: BoardAwarenessPointSchema,
|
|
191
|
+
current: BoardAwarenessPointSchema,
|
|
192
|
+
color: z.string().min(1).max(64),
|
|
193
|
+
size: finiteSchema$1.positive().max(256).default(BOARD_ARROW_STROKE_SIZE)
|
|
194
|
+
}),
|
|
195
|
+
z.object({
|
|
196
|
+
kind: z.literal("box"),
|
|
197
|
+
id: idSchema$1,
|
|
198
|
+
nodeId: idSchema$1,
|
|
199
|
+
shape: z.enum(["geo", "frame"]),
|
|
200
|
+
start: BoardAwarenessPointSchema,
|
|
201
|
+
current: BoardAwarenessPointSchema,
|
|
202
|
+
color: z.string().min(1).max(64),
|
|
203
|
+
geo: z.string().min(1).max(40)
|
|
204
|
+
}),
|
|
205
|
+
z.object({
|
|
206
|
+
kind: z.literal("transform"),
|
|
207
|
+
id: idSchema$1,
|
|
208
|
+
mode: z.enum([
|
|
209
|
+
"translate",
|
|
210
|
+
"resize",
|
|
211
|
+
"rotate",
|
|
212
|
+
"arrow"
|
|
213
|
+
]),
|
|
214
|
+
nodes: z.array(BoardAwarenessNodePreviewSchema).max(64),
|
|
215
|
+
bounds: BoardAwarenessFrameSchema.nullable()
|
|
216
|
+
})
|
|
217
|
+
]);
|
|
218
|
+
const BoardAwarenessUpdateSchema = z.discriminatedUnion("type", [
|
|
219
|
+
BoardAwarenessStateUpdateSchema,
|
|
220
|
+
z.object({
|
|
221
|
+
type: z.literal("gesture"),
|
|
222
|
+
gesture: BoardAwarenessGestureSchema
|
|
223
|
+
}),
|
|
224
|
+
z.object({
|
|
225
|
+
type: z.literal("gesture.end"),
|
|
226
|
+
gestureId: idSchema$1,
|
|
227
|
+
resultingNodeIds: z.array(idSchema$1).max(64)
|
|
228
|
+
}),
|
|
229
|
+
z.object({
|
|
230
|
+
type: z.literal("gesture.cancel"),
|
|
231
|
+
gestureId: idSchema$1
|
|
232
|
+
})
|
|
233
|
+
]);
|
|
234
|
+
const BoardAwarenessClientPayloadSchema = z.object({
|
|
235
|
+
spaceId: z.string().uuid(),
|
|
236
|
+
boardId: z.string().uuid(),
|
|
237
|
+
seq: z.number().int().nonnegative(),
|
|
238
|
+
update: BoardAwarenessUpdateSchema
|
|
239
|
+
});
|
|
240
|
+
//#endregion
|
|
241
|
+
//#region ../protocol/dist/realtime/schema.js
|
|
242
|
+
const contentBlockMetaSchema = z.record(z.string(), z.unknown());
|
|
243
|
+
const realtimeRoomSchema = z.string().regex(/^(space|user|board|room):[^:]+$/);
|
|
244
|
+
const contentBlockSchema = z.discriminatedUnion("type", [
|
|
245
|
+
z.object({
|
|
246
|
+
type: z.literal("text"),
|
|
247
|
+
text: z.string(),
|
|
248
|
+
_meta: contentBlockMetaSchema.optional()
|
|
249
|
+
}),
|
|
250
|
+
z.object({
|
|
251
|
+
type: z.literal("thinking"),
|
|
252
|
+
thinking: z.string(),
|
|
253
|
+
signature: z.string().optional(),
|
|
254
|
+
_meta: contentBlockMetaSchema.optional()
|
|
255
|
+
}),
|
|
256
|
+
z.object({
|
|
257
|
+
type: z.literal("image"),
|
|
258
|
+
source: z.union([z.object({
|
|
259
|
+
type: z.literal("url"),
|
|
260
|
+
url: z.string().url()
|
|
261
|
+
}), z.object({
|
|
262
|
+
type: z.literal("base64"),
|
|
263
|
+
media_type: z.string(),
|
|
264
|
+
data: z.string()
|
|
265
|
+
})]),
|
|
266
|
+
_meta: contentBlockMetaSchema.optional()
|
|
267
|
+
}),
|
|
268
|
+
z.object({
|
|
269
|
+
type: z.literal("shell_command"),
|
|
270
|
+
command: z.string(),
|
|
271
|
+
rawText: z.string(),
|
|
272
|
+
_meta: contentBlockMetaSchema.optional()
|
|
273
|
+
}),
|
|
274
|
+
z.object({
|
|
275
|
+
type: z.literal("tool_use"),
|
|
276
|
+
id: z.string(),
|
|
277
|
+
name: z.string(),
|
|
278
|
+
input: z.record(z.string(), z.unknown()),
|
|
279
|
+
_meta: contentBlockMetaSchema.optional()
|
|
280
|
+
}),
|
|
281
|
+
z.object({
|
|
282
|
+
type: z.literal("tool_result"),
|
|
283
|
+
tool_use_id: z.string(),
|
|
284
|
+
content: z.union([z.string(), z.array(z.unknown())]),
|
|
285
|
+
is_error: z.boolean().optional(),
|
|
286
|
+
_meta: contentBlockMetaSchema.optional()
|
|
287
|
+
}),
|
|
288
|
+
z.object({
|
|
289
|
+
type: z.literal("system_note"),
|
|
290
|
+
note_type: z.enum([
|
|
291
|
+
"session_created",
|
|
292
|
+
"forked",
|
|
293
|
+
"compacted",
|
|
294
|
+
"info"
|
|
295
|
+
]),
|
|
296
|
+
text: z.string(),
|
|
297
|
+
_meta: contentBlockMetaSchema.optional()
|
|
298
|
+
})
|
|
299
|
+
]);
|
|
300
|
+
z.discriminatedUnion("type", [
|
|
301
|
+
z.object({
|
|
302
|
+
type: z.literal("auth"),
|
|
303
|
+
requestId: z.string().optional(),
|
|
304
|
+
payload: z.object({
|
|
305
|
+
token: z.string().min(1),
|
|
306
|
+
capabilities: z.array(z.string().min(1)).optional()
|
|
307
|
+
})
|
|
308
|
+
}),
|
|
309
|
+
z.object({
|
|
310
|
+
type: z.literal("subscribe"),
|
|
311
|
+
requestId: z.string().optional(),
|
|
312
|
+
payload: z.object({ rooms: z.array(realtimeRoomSchema).min(1) })
|
|
313
|
+
}),
|
|
314
|
+
z.object({
|
|
315
|
+
type: z.literal("unsubscribe"),
|
|
316
|
+
requestId: z.string().optional(),
|
|
317
|
+
payload: z.object({ rooms: z.array(realtimeRoomSchema).min(1) })
|
|
318
|
+
}),
|
|
319
|
+
z.object({
|
|
320
|
+
type: z.literal("session.message.create"),
|
|
321
|
+
requestId: z.string().optional(),
|
|
322
|
+
payload: z.object({
|
|
323
|
+
spaceId: z.string().uuid(),
|
|
324
|
+
sessionId: z.string().uuid(),
|
|
325
|
+
clientMessageId: z.string().optional(),
|
|
326
|
+
content: z.array(contentBlockSchema).min(1),
|
|
327
|
+
model: z.string().optional(),
|
|
328
|
+
provider: z.string().optional(),
|
|
329
|
+
thinkingLevel: z.enum([
|
|
330
|
+
"off",
|
|
331
|
+
"minimal",
|
|
332
|
+
"low",
|
|
333
|
+
"medium",
|
|
334
|
+
"high",
|
|
335
|
+
"xhigh",
|
|
336
|
+
"max"
|
|
337
|
+
]).optional()
|
|
338
|
+
})
|
|
339
|
+
}),
|
|
340
|
+
z.object({
|
|
341
|
+
type: z.literal("presence.update"),
|
|
342
|
+
requestId: z.string().optional(),
|
|
343
|
+
payload: z.object({
|
|
344
|
+
spaceId: z.string().uuid(),
|
|
345
|
+
meta: z.record(z.string(), z.unknown()).nullable().optional()
|
|
346
|
+
})
|
|
347
|
+
}),
|
|
348
|
+
z.object({
|
|
349
|
+
type: z.literal("board.awareness.update"),
|
|
350
|
+
requestId: z.string().optional(),
|
|
351
|
+
payload: BoardAwarenessClientPayloadSchema
|
|
352
|
+
}),
|
|
353
|
+
z.object({
|
|
354
|
+
type: z.literal("realtime.room.join"),
|
|
355
|
+
requestId: z.string().optional(),
|
|
356
|
+
payload: z.object({
|
|
357
|
+
roomId: z.string().uuid(),
|
|
358
|
+
ticket: z.string().min(1)
|
|
359
|
+
})
|
|
360
|
+
}),
|
|
361
|
+
z.object({
|
|
362
|
+
type: z.literal("realtime.room.publish"),
|
|
363
|
+
requestId: z.string().optional(),
|
|
364
|
+
payload: z.object({
|
|
365
|
+
roomId: z.string().uuid(),
|
|
366
|
+
event: z.string().regex(REALTIME_ROOM_EVENT_NAME_PATTERN),
|
|
367
|
+
data: z.unknown(),
|
|
368
|
+
clientEventId: z.string().max(128).optional()
|
|
369
|
+
})
|
|
370
|
+
}),
|
|
371
|
+
z.object({
|
|
372
|
+
type: z.literal("realtime.room.leave"),
|
|
373
|
+
requestId: z.string().optional(),
|
|
374
|
+
payload: z.object({ roomId: z.string().uuid() })
|
|
375
|
+
}),
|
|
376
|
+
z.object({
|
|
377
|
+
type: z.literal("realtime.room.presence.update"),
|
|
378
|
+
requestId: z.string().optional(),
|
|
379
|
+
payload: z.object({
|
|
380
|
+
roomId: z.string().uuid(),
|
|
381
|
+
presence: z.record(z.string(), z.unknown()).nullable()
|
|
382
|
+
})
|
|
383
|
+
}),
|
|
384
|
+
z.object({
|
|
385
|
+
type: z.literal("ping"),
|
|
386
|
+
requestId: z.string().optional(),
|
|
387
|
+
payload: z.record(z.string(), z.unknown()).optional()
|
|
388
|
+
}),
|
|
389
|
+
z.object({
|
|
390
|
+
type: z.literal("ack"),
|
|
391
|
+
requestId: z.string().optional(),
|
|
392
|
+
payload: z.object({ eventId: z.string().optional() }).optional()
|
|
393
|
+
})
|
|
394
|
+
]);
|
|
395
|
+
z.object({
|
|
396
|
+
id: z.string(),
|
|
397
|
+
timestamp: z.number(),
|
|
398
|
+
domain: z.enum([
|
|
399
|
+
"system",
|
|
400
|
+
"session",
|
|
401
|
+
"space",
|
|
402
|
+
"label",
|
|
403
|
+
"room"
|
|
404
|
+
]),
|
|
405
|
+
type: z.string(),
|
|
406
|
+
requestId: z.string().nullable().optional(),
|
|
407
|
+
spaceId: z.string().nullable().optional(),
|
|
408
|
+
sessionId: z.string().nullable().optional(),
|
|
409
|
+
rooms: z.array(realtimeRoomSchema).optional(),
|
|
410
|
+
payload: z.record(z.string(), z.unknown())
|
|
411
|
+
});
|
|
412
|
+
z.discriminatedUnion("t", [z.object({
|
|
413
|
+
t: z.literal("d"),
|
|
414
|
+
sid: z.string().min(1),
|
|
415
|
+
s: z.number().int().nonnegative(),
|
|
416
|
+
b: z.number().int().nonnegative(),
|
|
417
|
+
v: z.unknown()
|
|
418
|
+
}), z.object({
|
|
419
|
+
t: z.literal("p"),
|
|
420
|
+
sid: z.string().min(1),
|
|
421
|
+
s: z.number().int().nonnegative(),
|
|
422
|
+
b: z.number().int().nonnegative(),
|
|
423
|
+
o: z.enum([
|
|
424
|
+
"append",
|
|
425
|
+
"replace",
|
|
426
|
+
"add",
|
|
427
|
+
"merge",
|
|
428
|
+
"remove"
|
|
429
|
+
]),
|
|
430
|
+
p: z.string().min(1),
|
|
431
|
+
v: z.unknown().optional()
|
|
432
|
+
})]);
|
|
433
|
+
//#endregion
|
|
434
|
+
//#region src/apis/work-realtime.ts
|
|
435
|
+
const randomId = () => globalThis.crypto?.randomUUID?.() ?? `${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
436
|
+
const textEncoder = new TextEncoder();
|
|
437
|
+
const byteLength = (text) => textEncoder.encode(text).byteLength;
|
|
438
|
+
/**
|
|
439
|
+
* Ceiling on deltas held during a join, so a stalled handshake cannot buffer without
|
|
440
|
+
* limit. Dropping the tail needs no extra signal: the gap detection below reports it.
|
|
441
|
+
*/
|
|
442
|
+
const WORK_ROOM_MAX_JOIN_BUFFER = 512;
|
|
443
|
+
/** Room events that mutate state, so they must not be applied before the join snapshot. */
|
|
444
|
+
const WORK_ROOM_DELTA_EVENTS = /* @__PURE__ */ new Set([
|
|
445
|
+
"realtime.room.event",
|
|
446
|
+
"realtime.room.member.joined",
|
|
447
|
+
"realtime.room.member.left",
|
|
448
|
+
"realtime.room.presence.updated"
|
|
449
|
+
]);
|
|
450
|
+
const requestError = (event) => {
|
|
451
|
+
const payload = event.payload;
|
|
452
|
+
return new Error(typeof payload.message === "string" ? payload.message : typeof payload.code === "string" ? payload.code : "room request failed");
|
|
453
|
+
};
|
|
454
|
+
const isRoomEvent = (event, roomId) => {
|
|
455
|
+
if (event.domain !== "room") return false;
|
|
456
|
+
return event.payload.roomId === roomId || event.rooms?.includes(`room:${roomId}`);
|
|
457
|
+
};
|
|
458
|
+
var WorkRoom = class {
|
|
459
|
+
websocket;
|
|
460
|
+
admission;
|
|
461
|
+
id;
|
|
462
|
+
code;
|
|
463
|
+
createdAt;
|
|
464
|
+
expiresAt;
|
|
465
|
+
maxParticipants;
|
|
466
|
+
seatPerUser;
|
|
467
|
+
/** Opaque, stable identity of this viewer inside the room. */
|
|
468
|
+
userKey;
|
|
469
|
+
_participantId;
|
|
470
|
+
_state = "connecting";
|
|
471
|
+
_members = [];
|
|
472
|
+
joinBuffer = null;
|
|
473
|
+
lastSequence = 0;
|
|
474
|
+
hasJoined = false;
|
|
475
|
+
explicitLeave = false;
|
|
476
|
+
expiryTimer = null;
|
|
477
|
+
pending = /* @__PURE__ */ new Map();
|
|
478
|
+
handlers = /* @__PURE__ */ new Map();
|
|
479
|
+
allHandlers = /* @__PURE__ */ new Set();
|
|
480
|
+
stateHandlers = /* @__PURE__ */ new Set();
|
|
481
|
+
membersHandlers = /* @__PURE__ */ new Set();
|
|
482
|
+
outOfSyncHandlers = /* @__PURE__ */ new Set();
|
|
483
|
+
sendErrorHandlers = /* @__PURE__ */ new Set();
|
|
484
|
+
offEvent;
|
|
485
|
+
offOpen;
|
|
486
|
+
offClose;
|
|
487
|
+
offReconnecting;
|
|
488
|
+
constructor(websocket, admission) {
|
|
489
|
+
this.websocket = websocket;
|
|
490
|
+
this.admission = admission;
|
|
491
|
+
this.id = admission.room.id;
|
|
492
|
+
this.code = admission.room.code;
|
|
493
|
+
this.createdAt = admission.room.createdAt;
|
|
494
|
+
this.expiresAt = admission.room.expiresAt;
|
|
495
|
+
this.maxParticipants = admission.room.maxParticipants;
|
|
496
|
+
this.seatPerUser = admission.room.seatPerUser === true;
|
|
497
|
+
this.userKey = admission.userKey;
|
|
498
|
+
this._participantId = admission.participantId;
|
|
499
|
+
this.offEvent = websocket.on("event", (event) => this.handleEvent(event));
|
|
500
|
+
this.offOpen = websocket.on("open", () => {
|
|
501
|
+
if (!this.hasJoined || this.explicitLeave || this._state === "expired" || this._state === "closed") return;
|
|
502
|
+
this.rejoin();
|
|
503
|
+
});
|
|
504
|
+
this.offReconnecting = websocket.on("reconnecting", () => {
|
|
505
|
+
if (this.hasJoined && !this.explicitLeave) this.setState("reconnecting");
|
|
506
|
+
});
|
|
507
|
+
this.offClose = websocket.on("close", ({ willReconnect }) => {
|
|
508
|
+
this.rejectPending(/* @__PURE__ */ new Error("room connection closed"));
|
|
509
|
+
if (this.explicitLeave || !willReconnect) {
|
|
510
|
+
if (this._state !== "expired") this.setState("closed");
|
|
511
|
+
this.hasJoined = false;
|
|
512
|
+
this.dispose();
|
|
513
|
+
} else if (this.hasJoined) this.setState("reconnecting");
|
|
514
|
+
});
|
|
515
|
+
const delay = Math.max(0, Date.parse(this.expiresAt) - Date.now());
|
|
516
|
+
this.expiryTimer = setTimeout(() => this.expire(), Math.min(delay, 2147e6));
|
|
517
|
+
}
|
|
518
|
+
get state() {
|
|
519
|
+
return this._state;
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
* Identity of this connection inside the room. A `seatPerUser` join can take over a
|
|
523
|
+
* seat the viewer already holds, so this may differ from the id issued at admission.
|
|
524
|
+
*/
|
|
525
|
+
get participantId() {
|
|
526
|
+
return this._participantId;
|
|
527
|
+
}
|
|
528
|
+
get members() {
|
|
529
|
+
return this._members.slice();
|
|
530
|
+
}
|
|
531
|
+
async connect() {
|
|
532
|
+
await this.joinOverWebsocket(false);
|
|
533
|
+
return this;
|
|
534
|
+
}
|
|
535
|
+
subscribe(type, handler) {
|
|
536
|
+
const handlers = this.handlers.get(type) ?? /* @__PURE__ */ new Set();
|
|
537
|
+
handlers.add(handler);
|
|
538
|
+
this.handlers.set(type, handlers);
|
|
539
|
+
return () => handlers.delete(handler);
|
|
540
|
+
}
|
|
541
|
+
subscribeAll(handler) {
|
|
542
|
+
this.allHandlers.add(handler);
|
|
543
|
+
return () => this.allHandlers.delete(handler);
|
|
544
|
+
}
|
|
545
|
+
onStateChange(handler) {
|
|
546
|
+
this.stateHandlers.add(handler);
|
|
547
|
+
return () => this.stateHandlers.delete(handler);
|
|
548
|
+
}
|
|
549
|
+
onMembersChanged(handler) {
|
|
550
|
+
this.membersHandlers.add(handler);
|
|
551
|
+
return () => this.membersHandlers.delete(handler);
|
|
552
|
+
}
|
|
553
|
+
onOutOfSync(handler) {
|
|
554
|
+
this.outOfSyncHandlers.add(handler);
|
|
555
|
+
return () => this.outOfSyncHandlers.delete(handler);
|
|
556
|
+
}
|
|
557
|
+
/** Reports failures of {@link send}, which has no ack to reject. */
|
|
558
|
+
onSendError(handler) {
|
|
559
|
+
this.sendErrorHandlers.add(handler);
|
|
560
|
+
return () => this.sendErrorHandlers.delete(handler);
|
|
561
|
+
}
|
|
562
|
+
/**
|
|
563
|
+
* Publishes without waiting for the server ack, for high-frequency traffic such as
|
|
564
|
+
* input frames. Awaiting {@link publish} instead caps a loop at `1000 / rtt` events
|
|
565
|
+
* per second. Ordering still holds, but failures surface through
|
|
566
|
+
* {@link onSendError} rather than a rejected promise, and calls are ignored while
|
|
567
|
+
* the room is not joined; watch {@link onStateChange} to know when it resumes.
|
|
568
|
+
*/
|
|
569
|
+
send(type, data) {
|
|
570
|
+
if (this._state !== "joined" || !this.hasJoined) return;
|
|
571
|
+
const failure = this.validateSend(type, data);
|
|
572
|
+
if (failure) {
|
|
573
|
+
for (const handler of this.sendErrorHandlers) handler(failure);
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
576
|
+
this.websocket.publishRealtimeRoom({
|
|
577
|
+
roomId: this.id,
|
|
578
|
+
event: type,
|
|
579
|
+
data
|
|
580
|
+
}).catch((error) => {
|
|
581
|
+
const reason = error instanceof Error ? error : new Error(String(error));
|
|
582
|
+
for (const handler of this.sendErrorHandlers) handler(reason);
|
|
583
|
+
});
|
|
584
|
+
}
|
|
585
|
+
validateSend(type, data) {
|
|
586
|
+
if (!REALTIME_ROOM_EVENT_NAME_PATTERN.test(type)) return /* @__PURE__ */ new Error(`invalid room event name: ${type}`);
|
|
587
|
+
let encoded;
|
|
588
|
+
try {
|
|
589
|
+
encoded = JSON.stringify(data);
|
|
590
|
+
} catch {
|
|
591
|
+
return /* @__PURE__ */ new Error("room event data is not serializable");
|
|
592
|
+
}
|
|
593
|
+
if (encoded === void 0) return /* @__PURE__ */ new Error("room event data is not serializable");
|
|
594
|
+
if (byteLength(encoded) > 16384) return /* @__PURE__ */ new Error("room event payload is too large");
|
|
595
|
+
return null;
|
|
596
|
+
}
|
|
597
|
+
async publish(type, data, options) {
|
|
598
|
+
this.assertJoined();
|
|
599
|
+
const failure = this.validateSend(type, data);
|
|
600
|
+
if (failure) throw failure;
|
|
601
|
+
const requestId = randomId();
|
|
602
|
+
const response = await this.request(requestId, /* @__PURE__ */ new Set(["realtime.room.request.ok"]), () => this.websocket.publishRealtimeRoom({
|
|
603
|
+
roomId: this.id,
|
|
604
|
+
event: type,
|
|
605
|
+
data,
|
|
606
|
+
clientEventId: options?.clientEventId,
|
|
607
|
+
requestId
|
|
608
|
+
}));
|
|
609
|
+
const payload = response.payload;
|
|
610
|
+
return {
|
|
611
|
+
eventId: typeof payload.eventId === "string" ? payload.eventId : response.id,
|
|
612
|
+
sequence: typeof payload.sequence === "number" ? payload.sequence : 0,
|
|
613
|
+
clientEventId: typeof payload.clientEventId === "string" ? payload.clientEventId : null
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
async setPresence(presence) {
|
|
617
|
+
this.assertJoined();
|
|
618
|
+
const requestId = randomId();
|
|
619
|
+
await this.request(requestId, /* @__PURE__ */ new Set(["realtime.room.request.ok"]), () => this.websocket.updateRealtimeRoomPresence({
|
|
620
|
+
roomId: this.id,
|
|
621
|
+
presence,
|
|
622
|
+
requestId
|
|
623
|
+
}));
|
|
624
|
+
}
|
|
625
|
+
async leave() {
|
|
626
|
+
if (this.explicitLeave || this._state === "closed" || this._state === "expired") return;
|
|
627
|
+
this.explicitLeave = true;
|
|
628
|
+
try {
|
|
629
|
+
if (this.hasJoined && this.websocket.state === "open") {
|
|
630
|
+
const requestId = randomId();
|
|
631
|
+
await this.request(requestId, /* @__PURE__ */ new Set(["realtime.room.request.ok"]), () => this.websocket.leaveRealtimeRoom({
|
|
632
|
+
roomId: this.id,
|
|
633
|
+
requestId
|
|
634
|
+
}));
|
|
635
|
+
}
|
|
636
|
+
} finally {
|
|
637
|
+
this.hasJoined = false;
|
|
638
|
+
this.setState("closed");
|
|
639
|
+
this.dispose();
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
async rejoin() {
|
|
643
|
+
if (this.explicitLeave || this._state === "expired" || this._state === "closed") return;
|
|
644
|
+
try {
|
|
645
|
+
await this.joinOverWebsocket(true);
|
|
646
|
+
} catch (error) {
|
|
647
|
+
if (this.state === "expired") return;
|
|
648
|
+
this.setState("closed");
|
|
649
|
+
this.dispose();
|
|
650
|
+
console.warn("[Cohub WorkRoom] failed to rejoin room", error);
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
async joinOverWebsocket(isReconnect) {
|
|
654
|
+
if (!this.websocket.supportsCapability("realtime.room.v1") && this.websocket.state === "open") throw new Error("Realtime rooms are not supported by the Gateway");
|
|
655
|
+
this.setState(isReconnect ? "reconnecting" : "connecting");
|
|
656
|
+
const requestId = randomId();
|
|
657
|
+
this.joinBuffer = [];
|
|
658
|
+
try {
|
|
659
|
+
const payload = (await this.request(requestId, /* @__PURE__ */ new Set(["realtime.room.joined"]), () => this.websocket.joinRealtimeRoom({
|
|
660
|
+
roomId: this.id,
|
|
661
|
+
ticket: this.admission.ticket,
|
|
662
|
+
requestId
|
|
663
|
+
}))).payload;
|
|
664
|
+
if (typeof payload.participantId !== "string" || !Array.isArray(payload.members)) throw new Error("invalid room join response");
|
|
665
|
+
this._participantId = payload.participantId;
|
|
666
|
+
this._members = payload.members;
|
|
667
|
+
this.lastSequence = typeof payload.sequence === "number" ? payload.sequence : 0;
|
|
668
|
+
} catch (error) {
|
|
669
|
+
this.joinBuffer = null;
|
|
670
|
+
throw error;
|
|
671
|
+
}
|
|
672
|
+
this.hasJoined = true;
|
|
673
|
+
this.setState("joined");
|
|
674
|
+
this.notifyMembers();
|
|
675
|
+
const buffered = this.joinBuffer ?? [];
|
|
676
|
+
this.joinBuffer = null;
|
|
677
|
+
for (const item of buffered) {
|
|
678
|
+
const sequence = item.payload.sequence;
|
|
679
|
+
if (typeof sequence === "number" && sequence <= this.lastSequence) continue;
|
|
680
|
+
this.handleEvent(item);
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
request(requestId, expected, send) {
|
|
684
|
+
return new Promise((resolve, reject) => {
|
|
685
|
+
const timer = setTimeout(() => {
|
|
686
|
+
this.pending.delete(requestId);
|
|
687
|
+
reject(/* @__PURE__ */ new Error("room request timed out"));
|
|
688
|
+
}, 2e4);
|
|
689
|
+
this.pending.set(requestId, {
|
|
690
|
+
expected,
|
|
691
|
+
resolve,
|
|
692
|
+
reject,
|
|
693
|
+
timer
|
|
694
|
+
});
|
|
695
|
+
send().catch((error) => {
|
|
696
|
+
this.pending.delete(requestId);
|
|
697
|
+
clearTimeout(timer);
|
|
698
|
+
reject(error instanceof Error ? error : new Error(String(error)));
|
|
699
|
+
});
|
|
700
|
+
});
|
|
701
|
+
}
|
|
702
|
+
/** Detaches the entry awaiting this requestId, so the caller can settle it. */
|
|
703
|
+
takePending(requestId) {
|
|
704
|
+
const pending = requestId ? this.pending.get(requestId) : void 0;
|
|
705
|
+
if (!pending || !requestId) return null;
|
|
706
|
+
this.pending.delete(requestId);
|
|
707
|
+
clearTimeout(pending.timer);
|
|
708
|
+
return pending;
|
|
709
|
+
}
|
|
710
|
+
handleEvent(event) {
|
|
711
|
+
if (!isRoomEvent(event, this.id)) {
|
|
712
|
+
if (event.type === "system.request.error") this.takePending(event.requestId)?.reject(requestError(event));
|
|
713
|
+
return;
|
|
714
|
+
}
|
|
715
|
+
if (event.type === "realtime.room.request.error") {
|
|
716
|
+
const failure = requestError(event);
|
|
717
|
+
if (event.requestId) {
|
|
718
|
+
this.takePending(event.requestId)?.reject(failure);
|
|
719
|
+
return;
|
|
720
|
+
}
|
|
721
|
+
for (const handler of this.sendErrorHandlers) handler(failure);
|
|
722
|
+
return;
|
|
723
|
+
}
|
|
724
|
+
const awaiting = event.requestId ? this.pending.get(event.requestId) : void 0;
|
|
725
|
+
if (awaiting?.expected.has(event.type)) {
|
|
726
|
+
this.takePending(event.requestId);
|
|
727
|
+
awaiting.resolve(event);
|
|
728
|
+
}
|
|
729
|
+
if (this.joinBuffer && WORK_ROOM_DELTA_EVENTS.has(event.type)) {
|
|
730
|
+
if (this.joinBuffer.length < WORK_ROOM_MAX_JOIN_BUFFER) this.joinBuffer.push(event);
|
|
731
|
+
return;
|
|
732
|
+
}
|
|
733
|
+
const payload = event.payload;
|
|
734
|
+
const sequence = typeof payload.sequence === "number" ? payload.sequence : null;
|
|
735
|
+
if (sequence !== null) this.observeSequence(sequence);
|
|
736
|
+
if (event.type === "realtime.room.member.joined" || event.type === "realtime.room.member.left" || event.type === "realtime.room.presence.updated") {
|
|
737
|
+
const member = payload.member;
|
|
738
|
+
if (member?.participantId) {
|
|
739
|
+
const members = new Map(this._members.map((item) => [item.participantId, item]));
|
|
740
|
+
if (event.type === "realtime.room.member.left") members.delete(member.participantId);
|
|
741
|
+
else members.set(member.participantId, member);
|
|
742
|
+
this._members = [...members.values()];
|
|
743
|
+
this.notifyMembers();
|
|
744
|
+
}
|
|
745
|
+
return;
|
|
746
|
+
}
|
|
747
|
+
if (event.type === "realtime.room.closed") {
|
|
748
|
+
this.hasJoined = false;
|
|
749
|
+
if (payload.reason === "expired") this.setState("expired");
|
|
750
|
+
else this.setState("closed");
|
|
751
|
+
this.rejectPending(/* @__PURE__ */ new Error(`room closed: ${typeof payload.reason === "string" ? payload.reason : "unknown"}`));
|
|
752
|
+
this.dispose();
|
|
753
|
+
return;
|
|
754
|
+
}
|
|
755
|
+
if (event.type !== "realtime.room.event") return;
|
|
756
|
+
const roomEvent = event;
|
|
757
|
+
const roomPayload = roomEvent.payload;
|
|
758
|
+
const item = {
|
|
759
|
+
id: roomEvent.id,
|
|
760
|
+
timestamp: roomEvent.timestamp,
|
|
761
|
+
roomId: roomPayload.roomId,
|
|
762
|
+
sequence: roomPayload.sequence,
|
|
763
|
+
type: roomPayload.event,
|
|
764
|
+
data: roomPayload.data,
|
|
765
|
+
clientEventId: roomPayload.clientEventId,
|
|
766
|
+
sender: roomPayload.sender,
|
|
767
|
+
self: roomPayload.sender.participantId === this.participantId
|
|
768
|
+
};
|
|
769
|
+
this.handlers.get(item.type)?.forEach((handler) => {
|
|
770
|
+
handler(item);
|
|
771
|
+
});
|
|
772
|
+
this.allHandlers.forEach((handler) => {
|
|
773
|
+
handler(item);
|
|
774
|
+
});
|
|
775
|
+
}
|
|
776
|
+
observeSequence(sequence) {
|
|
777
|
+
if (this.lastSequence > 0 && sequence > this.lastSequence + 1) for (const handler of this.outOfSyncHandlers) handler(this.lastSequence + 1, sequence);
|
|
778
|
+
if (sequence > this.lastSequence) this.lastSequence = sequence;
|
|
779
|
+
}
|
|
780
|
+
assertJoined() {
|
|
781
|
+
if (this._state !== "joined" || !this.hasJoined) throw new Error("room is not joined");
|
|
782
|
+
}
|
|
783
|
+
setState(state) {
|
|
784
|
+
if (this._state === state) return;
|
|
785
|
+
this._state = state;
|
|
786
|
+
for (const handler of this.stateHandlers) handler(state);
|
|
787
|
+
}
|
|
788
|
+
notifyMembers() {
|
|
789
|
+
const members = this.members;
|
|
790
|
+
for (const handler of this.membersHandlers) handler(members);
|
|
791
|
+
}
|
|
792
|
+
rejectPending(error) {
|
|
793
|
+
for (const [requestId, pending] of this.pending) {
|
|
794
|
+
this.pending.delete(requestId);
|
|
795
|
+
clearTimeout(pending.timer);
|
|
796
|
+
pending.reject(error);
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
expire() {
|
|
800
|
+
if (this.explicitLeave || this._state === "closed" || this._state === "expired") return;
|
|
801
|
+
this.hasJoined = false;
|
|
802
|
+
this.setState("expired");
|
|
803
|
+
this.rejectPending(/* @__PURE__ */ new Error("room expired"));
|
|
804
|
+
this.dispose();
|
|
805
|
+
}
|
|
806
|
+
dispose() {
|
|
807
|
+
this.offEvent();
|
|
808
|
+
this.offOpen();
|
|
809
|
+
this.offClose();
|
|
810
|
+
this.offReconnecting();
|
|
811
|
+
if (this.expiryTimer) clearTimeout(this.expiryTimer);
|
|
812
|
+
this.expiryTimer = null;
|
|
813
|
+
}
|
|
814
|
+
};
|
|
815
|
+
var WorkRealtimeApi = class {
|
|
816
|
+
transport;
|
|
817
|
+
websocket;
|
|
818
|
+
getContext;
|
|
819
|
+
constructor(transport, websocket, getContext) {
|
|
820
|
+
this.transport = transport;
|
|
821
|
+
this.websocket = websocket;
|
|
822
|
+
this.getContext = getContext;
|
|
823
|
+
}
|
|
824
|
+
async createRoom(input = {}) {
|
|
825
|
+
const admission = await this.transport.request(`/api/works/${encodeURIComponent(await this.requireWorkId())}/realtime/rooms`, {
|
|
826
|
+
method: "POST",
|
|
827
|
+
headers: { "Content-Type": "application/json" },
|
|
828
|
+
body: JSON.stringify(input)
|
|
829
|
+
});
|
|
830
|
+
return this.openRoom(admission);
|
|
831
|
+
}
|
|
832
|
+
async joinRoom(input) {
|
|
833
|
+
const admission = await this.transport.request(`/api/works/${encodeURIComponent(await this.requireWorkId())}/realtime/rooms/join`, {
|
|
834
|
+
method: "POST",
|
|
835
|
+
headers: { "Content-Type": "application/json" },
|
|
836
|
+
body: JSON.stringify(input)
|
|
837
|
+
});
|
|
838
|
+
return this.openRoom(admission);
|
|
839
|
+
}
|
|
840
|
+
async requireWorkId() {
|
|
841
|
+
const context = await this.getContext();
|
|
842
|
+
if (!context?.work?.id) throw new Error("Work context is unavailable — not running inside a published Work runtime.");
|
|
843
|
+
return context.work.id;
|
|
844
|
+
}
|
|
845
|
+
async openRoom(admission) {
|
|
846
|
+
const room = new WorkRoom(this.websocket, admission);
|
|
847
|
+
try {
|
|
848
|
+
await room.connect();
|
|
849
|
+
return room;
|
|
850
|
+
} catch (error) {
|
|
851
|
+
await room.leave().catch(() => void 0);
|
|
852
|
+
throw error;
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
};
|
|
856
|
+
//#endregion
|
|
84
857
|
//#region src/work-runtime.ts
|
|
85
858
|
const isBrowser$1 = () => typeof window !== "undefined" && typeof window.parent !== "undefined";
|
|
86
859
|
const hasParent = () => isBrowser$1() && window.parent !== window;
|
|
@@ -94,7 +867,7 @@ const getParentOrigin = () => {
|
|
|
94
867
|
return null;
|
|
95
868
|
}
|
|
96
869
|
};
|
|
97
|
-
const generateRequestId = () => globalThis.crypto?.randomUUID?.() ?? `${Date.now()}-${Math.random()}`;
|
|
870
|
+
const generateRequestId = () => globalThis.crypto?.randomUUID?.() ?? `${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
98
871
|
/**
|
|
99
872
|
* Bridge-mode transport: posts messages to `window.parent` (the Cohub host
|
|
100
873
|
* embedding the work in an iframe) and listens for the matching reply.
|
|
@@ -400,9 +1173,11 @@ var WorkRuntimeApi = class {
|
|
|
400
1173
|
return Boolean(this.token);
|
|
401
1174
|
}
|
|
402
1175
|
async purchase(input) {
|
|
1176
|
+
const purchaseAttemptId = input.purchaseAttemptId?.trim() || generateRequestId();
|
|
403
1177
|
return (await this.transport.request({
|
|
404
1178
|
type: "cohub.work.purchase",
|
|
405
|
-
productKey: input.productKey
|
|
1179
|
+
productKey: input.productKey,
|
|
1180
|
+
purchaseAttemptId
|
|
406
1181
|
}, { timeoutMs: 12e4 }))?.checkout ?? null;
|
|
407
1182
|
}
|
|
408
1183
|
async checkoutState() {
|
|
@@ -538,41 +1313,45 @@ var CohubClient = class {
|
|
|
538
1313
|
this.referrals = new ReferralsApi(this.transport);
|
|
539
1314
|
this.works = new WorksApi(this.transport);
|
|
540
1315
|
this.workCommerce = new WorkCommerceApi(this.transport);
|
|
1316
|
+
this.work.realtime = new WorkRealtimeApi(this.transport, this.websocketClient, () => this.workRuntime.context());
|
|
541
1317
|
}
|
|
542
1318
|
context() {
|
|
543
1319
|
return this.workRuntime.context();
|
|
544
1320
|
}
|
|
545
1321
|
auth = { request: (input) => this.workRuntime.requestAuthorization(input) };
|
|
546
|
-
work = {
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
1322
|
+
work = {
|
|
1323
|
+
realtime: null,
|
|
1324
|
+
commerce: {
|
|
1325
|
+
resolveProducts: async (input) => {
|
|
1326
|
+
const context = await this.workRuntime.context();
|
|
1327
|
+
if (!context?.work?.id) throw new Error("Work context is unavailable — not running inside a published Work runtime.");
|
|
1328
|
+
return this.workCommerce.resolveProducts(context.work.id, input);
|
|
1329
|
+
},
|
|
1330
|
+
getEntitlements: async () => {
|
|
1331
|
+
const context = await this.workRuntime.context();
|
|
1332
|
+
if (!context?.work?.id) throw new Error("Work context is unavailable — not running inside a published Work runtime.");
|
|
1333
|
+
return this.workCommerce.getEntitlements(context.work.id);
|
|
1334
|
+
},
|
|
1335
|
+
consumeCredits: async (input) => {
|
|
1336
|
+
const context = await this.workRuntime.context();
|
|
1337
|
+
if (!context?.work?.id) throw new Error("Work context is unavailable — not running inside a published Work runtime.");
|
|
1338
|
+
return this.workCommerce.consumeCredits(context.work.id, input);
|
|
1339
|
+
},
|
|
1340
|
+
purchase: async (input) => this.workRuntime.purchase(input),
|
|
1341
|
+
getCheckoutState: async () => {
|
|
1342
|
+
const result = await this.workRuntime.checkoutState();
|
|
1343
|
+
return {
|
|
1344
|
+
status: result?.status ?? null,
|
|
1345
|
+
orderId: result?.orderId ?? null
|
|
1346
|
+
};
|
|
1347
|
+
},
|
|
1348
|
+
getOrder: async (orderId) => {
|
|
1349
|
+
const context = await this.workRuntime.context();
|
|
1350
|
+
if (!context?.work?.id) throw new Error("Work context is unavailable — not running inside a published Work runtime.");
|
|
1351
|
+
return this.workCommerce.getOrder(context.work.id, orderId);
|
|
1352
|
+
}
|
|
574
1353
|
}
|
|
575
|
-
}
|
|
1354
|
+
};
|
|
576
1355
|
space(spaceId) {
|
|
577
1356
|
return new SpaceClient(spaceId, this.transport, this.websocketClient);
|
|
578
1357
|
}
|
|
@@ -830,7 +1609,7 @@ function createWorkBridgeCore(config) {
|
|
|
830
1609
|
sessionStorage.removeItem(pendingPurchaseStorageKey);
|
|
831
1610
|
} catch {}
|
|
832
1611
|
}
|
|
833
|
-
async function createPurchase(productKey) {
|
|
1612
|
+
async function createPurchase(productKey, purchaseAttemptId) {
|
|
834
1613
|
const userToken = await getAccessToken();
|
|
835
1614
|
if (!userToken) {
|
|
836
1615
|
await config.requestSignIn(typeof location !== "undefined" ? location.pathname + location.search + location.hash : "/");
|
|
@@ -842,7 +1621,10 @@ function createWorkBridgeCore(config) {
|
|
|
842
1621
|
Authorization: `Bearer ${userToken}`,
|
|
843
1622
|
"Content-Type": "application/json"
|
|
844
1623
|
},
|
|
845
|
-
body: JSON.stringify({
|
|
1624
|
+
body: JSON.stringify({
|
|
1625
|
+
productKey,
|
|
1626
|
+
purchaseAttemptId
|
|
1627
|
+
})
|
|
846
1628
|
});
|
|
847
1629
|
if (!response.ok) throw new Error((await response.json().catch(() => null))?.message ?? "Purchase failed.");
|
|
848
1630
|
return (await response.json()).checkout ?? null;
|
|
@@ -897,9 +1679,18 @@ function createWorkBridgeCore(config) {
|
|
|
897
1679
|
});
|
|
898
1680
|
return;
|
|
899
1681
|
}
|
|
1682
|
+
const purchaseAttemptId = (typeof data.purchaseAttemptId === "string" ? data.purchaseAttemptId.trim() : "") || data.requestId.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 128);
|
|
1683
|
+
if (!/^[a-zA-Z0-9_-]{1,128}$/.test(purchaseAttemptId)) {
|
|
1684
|
+
reply(data.requestId, {
|
|
1685
|
+
type: "cohub.work.error",
|
|
1686
|
+
message: "Purchase attempt id is invalid."
|
|
1687
|
+
});
|
|
1688
|
+
return;
|
|
1689
|
+
}
|
|
900
1690
|
state.pendingPurchase = {
|
|
901
1691
|
requestId: data.requestId,
|
|
902
|
-
productKey
|
|
1692
|
+
productKey,
|
|
1693
|
+
purchaseAttemptId
|
|
903
1694
|
};
|
|
904
1695
|
state.purchaseError = null;
|
|
905
1696
|
state.purchaseOpen = true;
|
|
@@ -982,7 +1773,7 @@ function createWorkBridgeCore(config) {
|
|
|
982
1773
|
state.purchaseError = null;
|
|
983
1774
|
notify();
|
|
984
1775
|
try {
|
|
985
|
-
const checkout = await createPurchase(state.pendingPurchase.productKey);
|
|
1776
|
+
const checkout = await createPurchase(state.pendingPurchase.productKey, state.pendingPurchase.purchaseAttemptId);
|
|
986
1777
|
reply(state.pendingPurchase.requestId, {
|
|
987
1778
|
type: "cohub.work.purchase.result",
|
|
988
1779
|
checkout
|
|
@@ -1276,53 +2067,12 @@ function filterGenerationDeclarationsByPolicy(declarations, policy) {
|
|
|
1276
2067
|
});
|
|
1277
2068
|
}
|
|
1278
2069
|
//#endregion
|
|
1279
|
-
//#region ../protocol/dist/board-constants.js
|
|
1280
|
-
const DEFAULT_BOARD_RENDER_LIMITS = {
|
|
1281
|
-
particles: 2e4,
|
|
1282
|
-
vertices: 5e5,
|
|
1283
|
-
dynamicVertices: 15e4,
|
|
1284
|
-
drawCalls: 400,
|
|
1285
|
-
filterPasses: 24,
|
|
1286
|
-
renderTexturePixels: 16777216,
|
|
1287
|
-
textureBytes: 512 * 1024 * 1024,
|
|
1288
|
-
bufferBytes: 256 * 1024 * 1024,
|
|
1289
|
-
simulationSteps: 1e5
|
|
1290
|
-
};
|
|
1291
|
-
const BOARD_BUILTIN_CLIP_KINDS = [
|
|
1292
|
-
"motion.keyframes",
|
|
1293
|
-
"motion.path",
|
|
1294
|
-
"draw.reveal",
|
|
1295
|
-
"draw.handwrite",
|
|
1296
|
-
"text.reveal",
|
|
1297
|
-
"effects.particles",
|
|
1298
|
-
"effects.trail",
|
|
1299
|
-
"effects.impact",
|
|
1300
|
-
"effects.flash",
|
|
1301
|
-
"effects.color",
|
|
1302
|
-
"camera.pan",
|
|
1303
|
-
"camera.zoom",
|
|
1304
|
-
"camera.shake"
|
|
1305
|
-
];
|
|
1306
|
-
const BOARD_BUILTIN_EFFECT_KINDS = ["effects.pulse", "effects.float"];
|
|
1307
|
-
const BOARD_ARROW_STROKE_SIZE = 2.5;
|
|
1308
|
-
const BOARD_BUILTIN_CAPABILITIES = [...BOARD_BUILTIN_CLIP_KINDS.map((id) => ({
|
|
1309
|
-
kind: "clip",
|
|
1310
|
-
id,
|
|
1311
|
-
version: 1,
|
|
1312
|
-
renderers: ["webgpu", "webgl"]
|
|
1313
|
-
})), ...BOARD_BUILTIN_EFFECT_KINDS.map((id) => ({
|
|
1314
|
-
kind: "effect",
|
|
1315
|
-
id,
|
|
1316
|
-
version: 1,
|
|
1317
|
-
renderers: ["webgpu", "webgl"]
|
|
1318
|
-
}))];
|
|
1319
|
-
//#endregion
|
|
1320
2070
|
//#region ../protocol/dist/board.js
|
|
1321
2071
|
const BOARD_MANIFEST_KIND = "cohub.board.manifest";
|
|
1322
|
-
const idSchema
|
|
2072
|
+
const idSchema = z.string().min(1).max(160);
|
|
1323
2073
|
const extensionIdSchema = z.string().regex(/^[a-z][a-z0-9]*(?:[.-][a-z0-9]+)+$/).max(160);
|
|
1324
2074
|
const jsonObjectSchema = z.record(z.string(), z.unknown());
|
|
1325
|
-
const finiteSchema
|
|
2075
|
+
const finiteSchema = z.number().finite();
|
|
1326
2076
|
z.object({
|
|
1327
2077
|
kind: z.literal(BOARD_MANIFEST_KIND),
|
|
1328
2078
|
version: z.literal(1),
|
|
@@ -1332,11 +2082,11 @@ z.object({
|
|
|
1332
2082
|
const BoardTargetSchema = z.discriminatedUnion("type", [
|
|
1333
2083
|
z.object({
|
|
1334
2084
|
type: z.literal("node"),
|
|
1335
|
-
nodeId: idSchema
|
|
2085
|
+
nodeId: idSchema
|
|
1336
2086
|
}),
|
|
1337
2087
|
z.object({
|
|
1338
2088
|
type: z.literal("effect"),
|
|
1339
|
-
effectId: idSchema
|
|
2089
|
+
effectId: idSchema
|
|
1340
2090
|
}),
|
|
1341
2091
|
z.object({ type: z.literal("board") }),
|
|
1342
2092
|
z.object({ type: z.literal("camera") })
|
|
@@ -1347,18 +2097,18 @@ const BoardAssetRefSchema = z.object({
|
|
|
1347
2097
|
digest: z.string().min(16).max(160).optional()
|
|
1348
2098
|
});
|
|
1349
2099
|
const BoardKeyframeSchema = z.object({
|
|
1350
|
-
at: finiteSchema
|
|
2100
|
+
at: finiteSchema.nonnegative(),
|
|
1351
2101
|
value: z.unknown(),
|
|
1352
2102
|
easing: z.string().min(1).max(80).optional()
|
|
1353
2103
|
});
|
|
1354
2104
|
const BoardClipSchema = z.object({
|
|
1355
|
-
id: idSchema
|
|
1356
|
-
sequenceId: idSchema
|
|
2105
|
+
id: idSchema,
|
|
2106
|
+
sequenceId: idSchema,
|
|
1357
2107
|
kind: extensionIdSchema,
|
|
1358
2108
|
kindVersion: z.number().int().positive(),
|
|
1359
2109
|
target: BoardTargetSchema,
|
|
1360
|
-
start: finiteSchema
|
|
1361
|
-
duration: finiteSchema
|
|
2110
|
+
start: finiteSchema.nonnegative(),
|
|
2111
|
+
duration: finiteSchema.positive(),
|
|
1362
2112
|
layer: z.enum([
|
|
1363
2113
|
"behind",
|
|
1364
2114
|
"content",
|
|
@@ -1379,11 +2129,11 @@ const BoardClipSchema = z.object({
|
|
|
1379
2129
|
metadata: jsonObjectSchema.default({})
|
|
1380
2130
|
});
|
|
1381
2131
|
const BoardEffectSchema = z.object({
|
|
1382
|
-
id: idSchema
|
|
2132
|
+
id: idSchema,
|
|
1383
2133
|
boardId: z.string().uuid(),
|
|
1384
2134
|
target: z.discriminatedUnion("type", [z.object({
|
|
1385
2135
|
type: z.literal("node"),
|
|
1386
|
-
nodeId: idSchema
|
|
2136
|
+
nodeId: idSchema
|
|
1387
2137
|
}), z.object({ type: z.literal("board") })]),
|
|
1388
2138
|
kind: extensionIdSchema,
|
|
1389
2139
|
kindVersion: z.number().int().positive(),
|
|
@@ -1410,25 +2160,25 @@ const BoardEffectSchema = z.object({
|
|
|
1410
2160
|
revision: z.number().int().nonnegative()
|
|
1411
2161
|
});
|
|
1412
2162
|
const BoardSequenceSchema = z.object({
|
|
1413
|
-
id: idSchema
|
|
2163
|
+
id: idSchema,
|
|
1414
2164
|
boardId: z.string().uuid(),
|
|
1415
2165
|
name: z.string().min(1).max(255),
|
|
1416
|
-
duration: finiteSchema
|
|
2166
|
+
duration: finiteSchema.nonnegative(),
|
|
1417
2167
|
seed: z.string().min(1).max(160),
|
|
1418
2168
|
restPose: jsonObjectSchema.default({}),
|
|
1419
2169
|
metadata: jsonObjectSchema.default({}),
|
|
1420
2170
|
revision: z.number().int().nonnegative()
|
|
1421
2171
|
});
|
|
1422
2172
|
const BoardNodeInputSchema = z.object({
|
|
1423
|
-
nodeId: idSchema
|
|
2173
|
+
nodeId: idSchema,
|
|
1424
2174
|
type: z.string().min(1).max(40),
|
|
1425
|
-
parentId: idSchema
|
|
2175
|
+
parentId: idSchema.nullable(),
|
|
1426
2176
|
orderKey: z.string().max(4096).nullable(),
|
|
1427
|
-
x: finiteSchema
|
|
1428
|
-
y: finiteSchema
|
|
1429
|
-
width: finiteSchema
|
|
1430
|
-
height: finiteSchema
|
|
1431
|
-
rotation: finiteSchema
|
|
2177
|
+
x: finiteSchema,
|
|
2178
|
+
y: finiteSchema,
|
|
2179
|
+
width: finiteSchema.positive(),
|
|
2180
|
+
height: finiteSchema.positive(),
|
|
2181
|
+
rotation: finiteSchema,
|
|
1432
2182
|
refKind: z.string().max(40).nullable(),
|
|
1433
2183
|
refPath: z.string().max(4096).nullable(),
|
|
1434
2184
|
refUrl: z.string().max(4096).nullable(),
|
|
@@ -1464,17 +2214,17 @@ z.object({
|
|
|
1464
2214
|
"playback"
|
|
1465
2215
|
])).optional(),
|
|
1466
2216
|
viewport: z.object({
|
|
1467
|
-
x: finiteSchema
|
|
1468
|
-
y: finiteSchema
|
|
1469
|
-
width: finiteSchema
|
|
1470
|
-
height: finiteSchema
|
|
2217
|
+
x: finiteSchema,
|
|
2218
|
+
y: finiteSchema,
|
|
2219
|
+
width: finiteSchema.positive(),
|
|
2220
|
+
height: finiteSchema.positive()
|
|
1471
2221
|
}).optional()
|
|
1472
2222
|
});
|
|
1473
2223
|
/** Persisted on `boards.metadata.playback`: how a Board plays when opened. */
|
|
1474
2224
|
const BoardPlaybackPolicySchema = z.object({
|
|
1475
|
-
sequenceId: idSchema
|
|
2225
|
+
sequenceId: idSchema,
|
|
1476
2226
|
/** Delay before the first local playback after opening the Board, in milliseconds. */
|
|
1477
|
-
delayMs: finiteSchema
|
|
2227
|
+
delayMs: finiteSchema.nonnegative().default(0),
|
|
1478
2228
|
loop: z.boolean().default(false)
|
|
1479
2229
|
});
|
|
1480
2230
|
function parseBoardPlaybackPolicy(metadata) {
|
|
@@ -1483,148 +2233,32 @@ function parseBoardPlaybackPolicy(metadata) {
|
|
|
1483
2233
|
}
|
|
1484
2234
|
z.discriminatedUnion("type", [
|
|
1485
2235
|
z.object({
|
|
1486
|
-
commandId: idSchema
|
|
2236
|
+
commandId: idSchema,
|
|
1487
2237
|
type: z.literal("play"),
|
|
1488
|
-
sequenceId: idSchema
|
|
1489
|
-
position: finiteSchema
|
|
1490
|
-
timeScale: finiteSchema
|
|
2238
|
+
sequenceId: idSchema,
|
|
2239
|
+
position: finiteSchema.nonnegative().optional(),
|
|
2240
|
+
timeScale: finiteSchema.positive().max(4).optional(),
|
|
1491
2241
|
shared: z.boolean().optional(),
|
|
1492
|
-
seed: idSchema
|
|
2242
|
+
seed: idSchema.optional()
|
|
1493
2243
|
}),
|
|
1494
2244
|
z.object({
|
|
1495
|
-
commandId: idSchema
|
|
2245
|
+
commandId: idSchema,
|
|
1496
2246
|
type: z.literal("pause"),
|
|
1497
2247
|
playbackId: z.string().uuid()
|
|
1498
2248
|
}),
|
|
1499
2249
|
z.object({
|
|
1500
|
-
commandId: idSchema
|
|
2250
|
+
commandId: idSchema,
|
|
1501
2251
|
type: z.literal("seek"),
|
|
1502
2252
|
playbackId: z.string().uuid(),
|
|
1503
|
-
position: finiteSchema
|
|
2253
|
+
position: finiteSchema.nonnegative()
|
|
1504
2254
|
}),
|
|
1505
2255
|
z.object({
|
|
1506
|
-
commandId: idSchema
|
|
2256
|
+
commandId: idSchema,
|
|
1507
2257
|
type: z.literal("stop"),
|
|
1508
2258
|
playbackId: z.string().uuid()
|
|
1509
2259
|
})
|
|
1510
2260
|
]);
|
|
1511
2261
|
//#endregion
|
|
1512
|
-
//#region ../protocol/dist/realtime/board-awareness.js
|
|
1513
|
-
const idSchema = z.string().min(1).max(160);
|
|
1514
|
-
const finiteSchema = z.number().finite();
|
|
1515
|
-
const BoardAwarenessPointSchema = z.object({
|
|
1516
|
-
x: finiteSchema,
|
|
1517
|
-
y: finiteSchema
|
|
1518
|
-
});
|
|
1519
|
-
const BoardAwarenessDrawPointSchema = BoardAwarenessPointSchema.extend({ p: finiteSchema.min(0).max(1) });
|
|
1520
|
-
const BoardAwarenessFrameSchema = z.object({
|
|
1521
|
-
x: finiteSchema,
|
|
1522
|
-
y: finiteSchema,
|
|
1523
|
-
width: finiteSchema.positive(),
|
|
1524
|
-
height: finiteSchema.positive(),
|
|
1525
|
-
rotation: finiteSchema
|
|
1526
|
-
});
|
|
1527
|
-
const arrowEndpointSchema = z.union([z.object({
|
|
1528
|
-
kind: z.literal("point"),
|
|
1529
|
-
x: finiteSchema,
|
|
1530
|
-
y: finiteSchema
|
|
1531
|
-
}), z.object({
|
|
1532
|
-
kind: z.literal("binding"),
|
|
1533
|
-
target: idSchema,
|
|
1534
|
-
nx: finiteSchema,
|
|
1535
|
-
ny: finiteSchema,
|
|
1536
|
-
precise: z.boolean()
|
|
1537
|
-
})]);
|
|
1538
|
-
const BoardAwarenessNodePreviewSchema = z.object({
|
|
1539
|
-
nodeId: idSchema,
|
|
1540
|
-
frame: BoardAwarenessFrameSchema,
|
|
1541
|
-
arrow: z.object({
|
|
1542
|
-
start: arrowEndpointSchema,
|
|
1543
|
-
end: arrowEndpointSchema,
|
|
1544
|
-
bend: finiteSchema
|
|
1545
|
-
}).optional()
|
|
1546
|
-
});
|
|
1547
|
-
const BoardAwarenessStateUpdateSchema = z.object({
|
|
1548
|
-
type: z.literal("state"),
|
|
1549
|
-
client: z.object({ formFactor: z.enum(["desktop", "mobile"]) }).optional(),
|
|
1550
|
-
cursor: BoardAwarenessPointSchema.extend({ pointerType: z.enum([
|
|
1551
|
-
"mouse",
|
|
1552
|
-
"pen",
|
|
1553
|
-
"touch"
|
|
1554
|
-
]) }).nullable(),
|
|
1555
|
-
tool: z.string().min(1).max(40),
|
|
1556
|
-
selection: z.object({
|
|
1557
|
-
ids: z.array(idSchema).max(64),
|
|
1558
|
-
count: z.number().int().nonnegative().max(5e4),
|
|
1559
|
-
bounds: BoardAwarenessFrameSchema.nullable()
|
|
1560
|
-
}),
|
|
1561
|
-
editingId: idSchema.nullable()
|
|
1562
|
-
});
|
|
1563
|
-
const BoardAwarenessGestureSchema = z.discriminatedUnion("kind", [
|
|
1564
|
-
z.object({
|
|
1565
|
-
kind: z.literal("draw"),
|
|
1566
|
-
id: idSchema,
|
|
1567
|
-
nodeId: idSchema,
|
|
1568
|
-
color: z.string().min(1).max(64),
|
|
1569
|
-
size: finiteSchema.positive().max(256),
|
|
1570
|
-
from: z.number().int().nonnegative().max(1e5),
|
|
1571
|
-
points: z.array(BoardAwarenessDrawPointSchema).min(1).max(64)
|
|
1572
|
-
}),
|
|
1573
|
-
z.object({
|
|
1574
|
-
kind: z.literal("arrow"),
|
|
1575
|
-
id: idSchema,
|
|
1576
|
-
nodeId: idSchema,
|
|
1577
|
-
start: BoardAwarenessPointSchema,
|
|
1578
|
-
current: BoardAwarenessPointSchema,
|
|
1579
|
-
color: z.string().min(1).max(64),
|
|
1580
|
-
size: finiteSchema.positive().max(256).default(BOARD_ARROW_STROKE_SIZE)
|
|
1581
|
-
}),
|
|
1582
|
-
z.object({
|
|
1583
|
-
kind: z.literal("box"),
|
|
1584
|
-
id: idSchema,
|
|
1585
|
-
nodeId: idSchema,
|
|
1586
|
-
shape: z.enum(["geo", "frame"]),
|
|
1587
|
-
start: BoardAwarenessPointSchema,
|
|
1588
|
-
current: BoardAwarenessPointSchema,
|
|
1589
|
-
color: z.string().min(1).max(64),
|
|
1590
|
-
geo: z.string().min(1).max(40)
|
|
1591
|
-
}),
|
|
1592
|
-
z.object({
|
|
1593
|
-
kind: z.literal("transform"),
|
|
1594
|
-
id: idSchema,
|
|
1595
|
-
mode: z.enum([
|
|
1596
|
-
"translate",
|
|
1597
|
-
"resize",
|
|
1598
|
-
"rotate",
|
|
1599
|
-
"arrow"
|
|
1600
|
-
]),
|
|
1601
|
-
nodes: z.array(BoardAwarenessNodePreviewSchema).max(64),
|
|
1602
|
-
bounds: BoardAwarenessFrameSchema.nullable()
|
|
1603
|
-
})
|
|
1604
|
-
]);
|
|
1605
|
-
const BoardAwarenessUpdateSchema = z.discriminatedUnion("type", [
|
|
1606
|
-
BoardAwarenessStateUpdateSchema,
|
|
1607
|
-
z.object({
|
|
1608
|
-
type: z.literal("gesture"),
|
|
1609
|
-
gesture: BoardAwarenessGestureSchema
|
|
1610
|
-
}),
|
|
1611
|
-
z.object({
|
|
1612
|
-
type: z.literal("gesture.end"),
|
|
1613
|
-
gestureId: idSchema,
|
|
1614
|
-
resultingNodeIds: z.array(idSchema).max(64)
|
|
1615
|
-
}),
|
|
1616
|
-
z.object({
|
|
1617
|
-
type: z.literal("gesture.cancel"),
|
|
1618
|
-
gestureId: idSchema
|
|
1619
|
-
})
|
|
1620
|
-
]);
|
|
1621
|
-
z.object({
|
|
1622
|
-
spaceId: z.string().uuid(),
|
|
1623
|
-
boardId: z.string().uuid(),
|
|
1624
|
-
seq: z.number().int().nonnegative(),
|
|
1625
|
-
update: BoardAwarenessUpdateSchema
|
|
1626
|
-
});
|
|
1627
|
-
//#endregion
|
|
1628
2262
|
//#region ../protocol/dist/public-identifiers.js
|
|
1629
2263
|
/**
|
|
1630
2264
|
* Platform-owned path segments that must not be newly assigned to public
|
|
@@ -2012,4 +2646,4 @@ function createBoardExtensionRegistry(input = {}) {
|
|
|
2012
2646
|
return registry;
|
|
2013
2647
|
}
|
|
2014
2648
|
//#endregion
|
|
2015
|
-
export { BILLING_ACCESS_BLOCKED_ERROR_CODE, BillingApi, BoardClient, BoardExtensionRegistry, BoardPlaybackPolicySchema, BoardTransactionError, COHUB_ENVIRONMENTS, COHUB_SOURCE_HEADER, COHUB_SOURCE_HEADER_NAMES, CohubClient, CohubHttpClient, DEFAULT_BOARD_LIMITS, FEATURE_NOT_ENTITLED_ERROR_CODE, GenerationPolicyError, HttpError, ParentBridgeTransport, PopupBrokerTransport, REQUEST_SOURCE_VIA_MAX_LENGTH, ReferencesApi, ReferralsApi, SessionGenerationStreamClient, SessionPatchReducer, UsersApi, VoiceApi, VoiceInputClient, WebsocketClient, WorkCommerceApi, WorkRuntimeApi, WorksApi, assertGenerationRequestAllowedByPolicy, buildSpaceInvitePath, buildSpacePath, clearGrantedWorkScopes, clip, compileSequence, createBoardExtensionRegistry, createCohubClient, createHttpClient, createSessionGenerationStreamClient, createSessionPatchReducer, createSlugWorkIdResolver, createVoiceInputClient, createWebsocketClient, createWorkBridgeCore, createWorkRuntime, decodeGenerationPolicy, encodeGenerationPolicy, extractBillingPayload, filterDiscoverableGenerationModels, filterGenerationDeclarationsByPolicy, findGenerationModelPolicy, getAllowedGenerationModelIds, hasGrantedWorkScopes, hasRequestSourceIdentity, isBillingAccessBlockedCode, isBillingAccessBlockedError, isFeatureNotEntitledError, isGenerationModelHidden, isHttpErrorCode, isRequestSourceEmpty, isRequestSourceUuid, joinApiUrl, mergeRequestSourceIntoMeta, normalizeBaseUrl, normalizeGenerationPolicy, normalizeRequestSource, normalizeVoiceInputWebsocketUrl, normalizeWebsocketUrl, parseAssistantMessageCommit, parseBoardPlaybackPolicy, parseGenerationPolicyFromEnv, parseRequestSourceFromHeaders, readRequestSourceFromEnv, requestSourceToHeaders, resolveApiBaseUrl, resolveCohubEnvironment, resolveRequestSourceChannel, resolveVoiceInputWebsocketUrl, resolveWebsocketUrl, resolveWorkTransport, sanitizeAccessToken, setGrantedWorkScopes, timeline };
|
|
2649
|
+
export { BILLING_ACCESS_BLOCKED_ERROR_CODE, BillingApi, BoardClient, BoardExtensionRegistry, BoardPlaybackPolicySchema, BoardTransactionError, COHUB_ENVIRONMENTS, COHUB_SOURCE_HEADER, COHUB_SOURCE_HEADER_NAMES, CohubClient, CohubHttpClient, DEFAULT_BOARD_LIMITS, FEATURE_NOT_ENTITLED_ERROR_CODE, GenerationPolicyError, HttpError, ParentBridgeTransport, PopupBrokerTransport, REQUEST_SOURCE_VIA_MAX_LENGTH, ReferencesApi, ReferralsApi, SessionGenerationStreamClient, SessionPatchReducer, UsersApi, VoiceApi, VoiceInputClient, WebsocketClient, WorkCommerceApi, WorkRealtimeApi, WorkRoom, WorkRuntimeApi, WorksApi, assertGenerationRequestAllowedByPolicy, buildSpaceInvitePath, buildSpacePath, clearGrantedWorkScopes, clip, compileSequence, createBoardExtensionRegistry, createCohubClient, createHttpClient, createSessionGenerationStreamClient, createSessionPatchReducer, createSlugWorkIdResolver, createVoiceInputClient, createWebsocketClient, createWorkBridgeCore, createWorkRuntime, decodeGenerationPolicy, encodeGenerationPolicy, extractBillingPayload, filterDiscoverableGenerationModels, filterGenerationDeclarationsByPolicy, findGenerationModelPolicy, getAllowedGenerationModelIds, hasGrantedWorkScopes, hasRequestSourceIdentity, isBillingAccessBlockedCode, isBillingAccessBlockedError, isFeatureNotEntitledError, isGenerationModelHidden, isHttpErrorCode, isRequestSourceEmpty, isRequestSourceUuid, joinApiUrl, mergeRequestSourceIntoMeta, normalizeBaseUrl, normalizeGenerationPolicy, normalizeRequestSource, normalizeVoiceInputWebsocketUrl, normalizeWebsocketUrl, parseAssistantMessageCommit, parseBoardPlaybackPolicy, parseGenerationPolicyFromEnv, parseRequestSourceFromHeaders, readRequestSourceFromEnv, requestSourceToHeaders, resolveApiBaseUrl, resolveCohubEnvironment, resolveRequestSourceChannel, resolveVoiceInputWebsocketUrl, resolveWebsocketUrl, resolveWorkTransport, sanitizeAccessToken, setGrantedWorkScopes, timeline };
|