@neta-art/cohub 4.8.0 → 5.0.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 +42 -1
- package/dist/chunks/http.d.ts +2 -2
- package/dist/chunks/http.js +2 -2
- package/dist/chunks/transport.js +7 -2
- package/dist/chunks/websocket.d.ts +192 -49
- package/dist/chunks/websocket.js +56 -4
- package/dist/http.d.ts +2 -2
- package/dist/index.d.ts +131 -7
- package/dist/index.js +837 -230
- package/docs/work-runtime-guide.md +123 -12
- 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";
|
|
@@ -70,14 +70,776 @@ var BillingApi = class {
|
|
|
70
70
|
}
|
|
71
71
|
};
|
|
72
72
|
//#endregion
|
|
73
|
-
//#region
|
|
74
|
-
|
|
73
|
+
//#region ../protocol/dist/board-constants.js
|
|
74
|
+
const DEFAULT_BOARD_RENDER_LIMITS = {
|
|
75
|
+
particles: 2e4,
|
|
76
|
+
vertices: 5e5,
|
|
77
|
+
dynamicVertices: 15e4,
|
|
78
|
+
drawCalls: 400,
|
|
79
|
+
filterPasses: 24,
|
|
80
|
+
renderTexturePixels: 16777216,
|
|
81
|
+
textureBytes: 512 * 1024 * 1024,
|
|
82
|
+
bufferBytes: 256 * 1024 * 1024,
|
|
83
|
+
simulationSteps: 1e5
|
|
84
|
+
};
|
|
85
|
+
const BOARD_BUILTIN_CLIP_KINDS = [
|
|
86
|
+
"motion.keyframes",
|
|
87
|
+
"motion.path",
|
|
88
|
+
"draw.reveal",
|
|
89
|
+
"draw.handwrite",
|
|
90
|
+
"text.reveal",
|
|
91
|
+
"effects.particles",
|
|
92
|
+
"effects.trail",
|
|
93
|
+
"effects.impact",
|
|
94
|
+
"effects.flash",
|
|
95
|
+
"effects.color",
|
|
96
|
+
"camera.pan",
|
|
97
|
+
"camera.zoom",
|
|
98
|
+
"camera.shake"
|
|
99
|
+
];
|
|
100
|
+
const BOARD_BUILTIN_EFFECT_KINDS = ["effects.pulse", "effects.float"];
|
|
101
|
+
const BOARD_ARROW_STROKE_SIZE = 2.5;
|
|
102
|
+
const BOARD_BUILTIN_CAPABILITIES = [...BOARD_BUILTIN_CLIP_KINDS.map((id) => ({
|
|
103
|
+
kind: "clip",
|
|
104
|
+
id,
|
|
105
|
+
version: 1,
|
|
106
|
+
renderers: ["webgpu", "webgl"]
|
|
107
|
+
})), ...BOARD_BUILTIN_EFFECT_KINDS.map((id) => ({
|
|
108
|
+
kind: "effect",
|
|
109
|
+
id,
|
|
110
|
+
version: 1,
|
|
111
|
+
renderers: ["webgpu", "webgl"]
|
|
112
|
+
}))];
|
|
113
|
+
//#endregion
|
|
114
|
+
//#region ../protocol/dist/realtime/board-awareness.js
|
|
115
|
+
const idSchema$1 = z.string().min(1).max(160);
|
|
116
|
+
const finiteSchema$1 = z.number().finite();
|
|
117
|
+
const BoardAwarenessPointSchema = z.object({
|
|
118
|
+
x: finiteSchema$1,
|
|
119
|
+
y: finiteSchema$1
|
|
120
|
+
});
|
|
121
|
+
const BoardAwarenessDrawPointSchema = BoardAwarenessPointSchema.extend({ p: finiteSchema$1.min(0).max(1) });
|
|
122
|
+
const BoardAwarenessFrameSchema = z.object({
|
|
123
|
+
x: finiteSchema$1,
|
|
124
|
+
y: finiteSchema$1,
|
|
125
|
+
width: finiteSchema$1.positive(),
|
|
126
|
+
height: finiteSchema$1.positive(),
|
|
127
|
+
rotation: finiteSchema$1
|
|
128
|
+
});
|
|
129
|
+
const arrowEndpointSchema = z.union([z.object({
|
|
130
|
+
kind: z.literal("point"),
|
|
131
|
+
x: finiteSchema$1,
|
|
132
|
+
y: finiteSchema$1
|
|
133
|
+
}), z.object({
|
|
134
|
+
kind: z.literal("binding"),
|
|
135
|
+
target: idSchema$1,
|
|
136
|
+
nx: finiteSchema$1,
|
|
137
|
+
ny: finiteSchema$1,
|
|
138
|
+
precise: z.boolean()
|
|
139
|
+
})]);
|
|
140
|
+
const BoardAwarenessNodePreviewSchema = z.object({
|
|
141
|
+
nodeId: idSchema$1,
|
|
142
|
+
frame: BoardAwarenessFrameSchema,
|
|
143
|
+
arrow: z.object({
|
|
144
|
+
start: arrowEndpointSchema,
|
|
145
|
+
end: arrowEndpointSchema,
|
|
146
|
+
bend: finiteSchema$1
|
|
147
|
+
}).optional()
|
|
148
|
+
});
|
|
149
|
+
const BoardAwarenessStateUpdateSchema = z.object({
|
|
150
|
+
type: z.literal("state"),
|
|
151
|
+
client: z.object({ formFactor: z.enum(["desktop", "mobile"]) }).optional(),
|
|
152
|
+
cursor: BoardAwarenessPointSchema.extend({ pointerType: z.enum([
|
|
153
|
+
"mouse",
|
|
154
|
+
"pen",
|
|
155
|
+
"touch"
|
|
156
|
+
]) }).nullable(),
|
|
157
|
+
tool: z.string().min(1).max(40),
|
|
158
|
+
selection: z.object({
|
|
159
|
+
ids: z.array(idSchema$1).max(64),
|
|
160
|
+
count: z.number().int().nonnegative().max(5e4),
|
|
161
|
+
bounds: BoardAwarenessFrameSchema.nullable()
|
|
162
|
+
}),
|
|
163
|
+
editingId: idSchema$1.nullable()
|
|
164
|
+
});
|
|
165
|
+
const BoardAwarenessGestureSchema = z.discriminatedUnion("kind", [
|
|
166
|
+
z.object({
|
|
167
|
+
kind: z.literal("draw"),
|
|
168
|
+
id: idSchema$1,
|
|
169
|
+
nodeId: idSchema$1,
|
|
170
|
+
color: z.string().min(1).max(64),
|
|
171
|
+
size: finiteSchema$1.positive().max(256),
|
|
172
|
+
from: z.number().int().nonnegative().max(1e5),
|
|
173
|
+
points: z.array(BoardAwarenessDrawPointSchema).min(1).max(64)
|
|
174
|
+
}),
|
|
175
|
+
z.object({
|
|
176
|
+
kind: z.literal("arrow"),
|
|
177
|
+
id: idSchema$1,
|
|
178
|
+
nodeId: idSchema$1,
|
|
179
|
+
start: BoardAwarenessPointSchema,
|
|
180
|
+
current: BoardAwarenessPointSchema,
|
|
181
|
+
color: z.string().min(1).max(64),
|
|
182
|
+
size: finiteSchema$1.positive().max(256).default(BOARD_ARROW_STROKE_SIZE)
|
|
183
|
+
}),
|
|
184
|
+
z.object({
|
|
185
|
+
kind: z.literal("box"),
|
|
186
|
+
id: idSchema$1,
|
|
187
|
+
nodeId: idSchema$1,
|
|
188
|
+
shape: z.enum(["geo", "frame"]),
|
|
189
|
+
start: BoardAwarenessPointSchema,
|
|
190
|
+
current: BoardAwarenessPointSchema,
|
|
191
|
+
color: z.string().min(1).max(64),
|
|
192
|
+
geo: z.string().min(1).max(40)
|
|
193
|
+
}),
|
|
194
|
+
z.object({
|
|
195
|
+
kind: z.literal("transform"),
|
|
196
|
+
id: idSchema$1,
|
|
197
|
+
mode: z.enum([
|
|
198
|
+
"translate",
|
|
199
|
+
"resize",
|
|
200
|
+
"rotate",
|
|
201
|
+
"arrow"
|
|
202
|
+
]),
|
|
203
|
+
nodes: z.array(BoardAwarenessNodePreviewSchema).max(64),
|
|
204
|
+
bounds: BoardAwarenessFrameSchema.nullable()
|
|
205
|
+
})
|
|
206
|
+
]);
|
|
207
|
+
const BoardAwarenessUpdateSchema = z.discriminatedUnion("type", [
|
|
208
|
+
BoardAwarenessStateUpdateSchema,
|
|
209
|
+
z.object({
|
|
210
|
+
type: z.literal("gesture"),
|
|
211
|
+
gesture: BoardAwarenessGestureSchema
|
|
212
|
+
}),
|
|
213
|
+
z.object({
|
|
214
|
+
type: z.literal("gesture.end"),
|
|
215
|
+
gestureId: idSchema$1,
|
|
216
|
+
resultingNodeIds: z.array(idSchema$1).max(64)
|
|
217
|
+
}),
|
|
218
|
+
z.object({
|
|
219
|
+
type: z.literal("gesture.cancel"),
|
|
220
|
+
gestureId: idSchema$1
|
|
221
|
+
})
|
|
222
|
+
]);
|
|
223
|
+
const BoardAwarenessClientPayloadSchema = z.object({
|
|
224
|
+
spaceId: z.string().uuid(),
|
|
225
|
+
boardId: z.string().uuid(),
|
|
226
|
+
seq: z.number().int().nonnegative(),
|
|
227
|
+
update: BoardAwarenessUpdateSchema
|
|
228
|
+
});
|
|
229
|
+
//#endregion
|
|
230
|
+
//#region ../protocol/dist/realtime/schema.js
|
|
231
|
+
const contentBlockMetaSchema = z.record(z.string(), z.unknown());
|
|
232
|
+
const realtimeRoomSchema = z.string().regex(/^(space|user|board|room):[^:]+$/);
|
|
233
|
+
const contentBlockSchema = z.discriminatedUnion("type", [
|
|
234
|
+
z.object({
|
|
235
|
+
type: z.literal("text"),
|
|
236
|
+
text: z.string(),
|
|
237
|
+
_meta: contentBlockMetaSchema.optional()
|
|
238
|
+
}),
|
|
239
|
+
z.object({
|
|
240
|
+
type: z.literal("thinking"),
|
|
241
|
+
thinking: z.string(),
|
|
242
|
+
signature: z.string().optional(),
|
|
243
|
+
_meta: contentBlockMetaSchema.optional()
|
|
244
|
+
}),
|
|
245
|
+
z.object({
|
|
246
|
+
type: z.literal("image"),
|
|
247
|
+
source: z.union([z.object({
|
|
248
|
+
type: z.literal("url"),
|
|
249
|
+
url: z.string().url()
|
|
250
|
+
}), z.object({
|
|
251
|
+
type: z.literal("base64"),
|
|
252
|
+
media_type: z.string(),
|
|
253
|
+
data: z.string()
|
|
254
|
+
})]),
|
|
255
|
+
_meta: contentBlockMetaSchema.optional()
|
|
256
|
+
}),
|
|
257
|
+
z.object({
|
|
258
|
+
type: z.literal("shell_command"),
|
|
259
|
+
command: z.string(),
|
|
260
|
+
rawText: z.string(),
|
|
261
|
+
_meta: contentBlockMetaSchema.optional()
|
|
262
|
+
}),
|
|
263
|
+
z.object({
|
|
264
|
+
type: z.literal("tool_use"),
|
|
265
|
+
id: z.string(),
|
|
266
|
+
name: z.string(),
|
|
267
|
+
input: z.record(z.string(), z.unknown()),
|
|
268
|
+
_meta: contentBlockMetaSchema.optional()
|
|
269
|
+
}),
|
|
270
|
+
z.object({
|
|
271
|
+
type: z.literal("tool_result"),
|
|
272
|
+
tool_use_id: z.string(),
|
|
273
|
+
content: z.union([z.string(), z.array(z.unknown())]),
|
|
274
|
+
is_error: z.boolean().optional(),
|
|
275
|
+
_meta: contentBlockMetaSchema.optional()
|
|
276
|
+
}),
|
|
277
|
+
z.object({
|
|
278
|
+
type: z.literal("system_note"),
|
|
279
|
+
note_type: z.enum([
|
|
280
|
+
"session_created",
|
|
281
|
+
"forked",
|
|
282
|
+
"compacted",
|
|
283
|
+
"info"
|
|
284
|
+
]),
|
|
285
|
+
text: z.string(),
|
|
286
|
+
_meta: contentBlockMetaSchema.optional()
|
|
287
|
+
})
|
|
288
|
+
]);
|
|
289
|
+
z.discriminatedUnion("type", [
|
|
290
|
+
z.object({
|
|
291
|
+
type: z.literal("auth"),
|
|
292
|
+
requestId: z.string().optional(),
|
|
293
|
+
payload: z.object({
|
|
294
|
+
token: z.string().min(1),
|
|
295
|
+
capabilities: z.array(z.string().min(1)).optional()
|
|
296
|
+
})
|
|
297
|
+
}),
|
|
298
|
+
z.object({
|
|
299
|
+
type: z.literal("subscribe"),
|
|
300
|
+
requestId: z.string().optional(),
|
|
301
|
+
payload: z.object({ rooms: z.array(realtimeRoomSchema).min(1) })
|
|
302
|
+
}),
|
|
303
|
+
z.object({
|
|
304
|
+
type: z.literal("unsubscribe"),
|
|
305
|
+
requestId: z.string().optional(),
|
|
306
|
+
payload: z.object({ rooms: z.array(realtimeRoomSchema).min(1) })
|
|
307
|
+
}),
|
|
308
|
+
z.object({
|
|
309
|
+
type: z.literal("session.message.create"),
|
|
310
|
+
requestId: z.string().optional(),
|
|
311
|
+
payload: z.object({
|
|
312
|
+
spaceId: z.string().uuid(),
|
|
313
|
+
sessionId: z.string().uuid(),
|
|
314
|
+
clientMessageId: z.string().optional(),
|
|
315
|
+
content: z.array(contentBlockSchema).min(1),
|
|
316
|
+
model: z.string().optional(),
|
|
317
|
+
provider: z.string().optional(),
|
|
318
|
+
thinkingLevel: z.enum([
|
|
319
|
+
"off",
|
|
320
|
+
"minimal",
|
|
321
|
+
"low",
|
|
322
|
+
"medium",
|
|
323
|
+
"high",
|
|
324
|
+
"xhigh",
|
|
325
|
+
"max"
|
|
326
|
+
]).optional()
|
|
327
|
+
})
|
|
328
|
+
}),
|
|
329
|
+
z.object({
|
|
330
|
+
type: z.literal("presence.update"),
|
|
331
|
+
requestId: z.string().optional(),
|
|
332
|
+
payload: z.object({
|
|
333
|
+
spaceId: z.string().uuid(),
|
|
334
|
+
meta: z.record(z.string(), z.unknown()).nullable().optional()
|
|
335
|
+
})
|
|
336
|
+
}),
|
|
337
|
+
z.object({
|
|
338
|
+
type: z.literal("board.awareness.update"),
|
|
339
|
+
requestId: z.string().optional(),
|
|
340
|
+
payload: BoardAwarenessClientPayloadSchema
|
|
341
|
+
}),
|
|
342
|
+
z.object({
|
|
343
|
+
type: z.literal("realtime.room.join"),
|
|
344
|
+
requestId: z.string().optional(),
|
|
345
|
+
payload: z.object({
|
|
346
|
+
roomId: z.string().uuid(),
|
|
347
|
+
ticket: z.string().min(1)
|
|
348
|
+
})
|
|
349
|
+
}),
|
|
350
|
+
z.object({
|
|
351
|
+
type: z.literal("realtime.room.publish"),
|
|
352
|
+
requestId: z.string().optional(),
|
|
353
|
+
payload: z.object({
|
|
354
|
+
roomId: z.string().uuid(),
|
|
355
|
+
event: z.string().regex(REALTIME_ROOM_EVENT_NAME_PATTERN),
|
|
356
|
+
data: z.unknown(),
|
|
357
|
+
clientEventId: z.string().max(128).optional()
|
|
358
|
+
})
|
|
359
|
+
}),
|
|
360
|
+
z.object({
|
|
361
|
+
type: z.literal("realtime.room.leave"),
|
|
362
|
+
requestId: z.string().optional(),
|
|
363
|
+
payload: z.object({ roomId: z.string().uuid() })
|
|
364
|
+
}),
|
|
365
|
+
z.object({
|
|
366
|
+
type: z.literal("realtime.room.presence.update"),
|
|
367
|
+
requestId: z.string().optional(),
|
|
368
|
+
payload: z.object({
|
|
369
|
+
roomId: z.string().uuid(),
|
|
370
|
+
presence: z.record(z.string(), z.unknown()).nullable()
|
|
371
|
+
})
|
|
372
|
+
}),
|
|
373
|
+
z.object({
|
|
374
|
+
type: z.literal("ping"),
|
|
375
|
+
requestId: z.string().optional(),
|
|
376
|
+
payload: z.record(z.string(), z.unknown()).optional()
|
|
377
|
+
}),
|
|
378
|
+
z.object({
|
|
379
|
+
type: z.literal("ack"),
|
|
380
|
+
requestId: z.string().optional(),
|
|
381
|
+
payload: z.object({ eventId: z.string().optional() }).optional()
|
|
382
|
+
})
|
|
383
|
+
]);
|
|
384
|
+
z.object({
|
|
385
|
+
id: z.string(),
|
|
386
|
+
timestamp: z.number(),
|
|
387
|
+
domain: z.enum([
|
|
388
|
+
"system",
|
|
389
|
+
"session",
|
|
390
|
+
"space",
|
|
391
|
+
"label",
|
|
392
|
+
"room"
|
|
393
|
+
]),
|
|
394
|
+
type: z.string(),
|
|
395
|
+
requestId: z.string().nullable().optional(),
|
|
396
|
+
spaceId: z.string().nullable().optional(),
|
|
397
|
+
sessionId: z.string().nullable().optional(),
|
|
398
|
+
rooms: z.array(realtimeRoomSchema).optional(),
|
|
399
|
+
payload: z.record(z.string(), z.unknown())
|
|
400
|
+
});
|
|
401
|
+
z.discriminatedUnion("t", [z.object({
|
|
402
|
+
t: z.literal("d"),
|
|
403
|
+
sid: z.string().min(1),
|
|
404
|
+
s: z.number().int().nonnegative(),
|
|
405
|
+
b: z.number().int().nonnegative(),
|
|
406
|
+
v: z.unknown()
|
|
407
|
+
}), z.object({
|
|
408
|
+
t: z.literal("p"),
|
|
409
|
+
sid: z.string().min(1),
|
|
410
|
+
s: z.number().int().nonnegative(),
|
|
411
|
+
b: z.number().int().nonnegative(),
|
|
412
|
+
o: z.enum([
|
|
413
|
+
"append",
|
|
414
|
+
"replace",
|
|
415
|
+
"add",
|
|
416
|
+
"merge",
|
|
417
|
+
"remove"
|
|
418
|
+
]),
|
|
419
|
+
p: z.string().min(1),
|
|
420
|
+
v: z.unknown().optional()
|
|
421
|
+
})]);
|
|
422
|
+
//#endregion
|
|
423
|
+
//#region src/apis/work-realtime.ts
|
|
424
|
+
const randomId = () => globalThis.crypto?.randomUUID?.() ?? `${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
425
|
+
const textEncoder = new TextEncoder();
|
|
426
|
+
const byteLength = (text) => textEncoder.encode(text).byteLength;
|
|
427
|
+
/**
|
|
428
|
+
* Ceiling on deltas held during a join, so a stalled handshake cannot buffer without
|
|
429
|
+
* limit. Dropping the tail needs no extra signal: the gap detection below reports it.
|
|
430
|
+
*/
|
|
431
|
+
const WORK_ROOM_MAX_JOIN_BUFFER = 512;
|
|
432
|
+
/** Room events that mutate state, so they must not be applied before the join snapshot. */
|
|
433
|
+
const WORK_ROOM_DELTA_EVENTS = /* @__PURE__ */ new Set([
|
|
434
|
+
"realtime.room.event",
|
|
435
|
+
"realtime.room.member.joined",
|
|
436
|
+
"realtime.room.member.left",
|
|
437
|
+
"realtime.room.presence.updated"
|
|
438
|
+
]);
|
|
439
|
+
const requestError = (event) => {
|
|
440
|
+
const payload = event.payload;
|
|
441
|
+
return new Error(typeof payload.message === "string" ? payload.message : typeof payload.code === "string" ? payload.code : "room request failed");
|
|
442
|
+
};
|
|
443
|
+
const isRoomEvent = (event, roomId) => {
|
|
444
|
+
if (event.domain !== "room") return false;
|
|
445
|
+
return event.payload.roomId === roomId || event.rooms?.includes(`room:${roomId}`);
|
|
446
|
+
};
|
|
447
|
+
var WorkRoom = class {
|
|
448
|
+
websocket;
|
|
449
|
+
admission;
|
|
450
|
+
id;
|
|
451
|
+
code;
|
|
452
|
+
createdAt;
|
|
453
|
+
expiresAt;
|
|
454
|
+
maxParticipants;
|
|
455
|
+
seatPerUser;
|
|
456
|
+
/** Opaque, stable identity of this viewer inside the room. */
|
|
457
|
+
userKey;
|
|
458
|
+
_participantId;
|
|
459
|
+
_state = "connecting";
|
|
460
|
+
_members = [];
|
|
461
|
+
joinBuffer = null;
|
|
462
|
+
lastSequence = 0;
|
|
463
|
+
hasJoined = false;
|
|
464
|
+
explicitLeave = false;
|
|
465
|
+
expiryTimer = null;
|
|
466
|
+
pending = /* @__PURE__ */ new Map();
|
|
467
|
+
handlers = /* @__PURE__ */ new Map();
|
|
468
|
+
allHandlers = /* @__PURE__ */ new Set();
|
|
469
|
+
stateHandlers = /* @__PURE__ */ new Set();
|
|
470
|
+
membersHandlers = /* @__PURE__ */ new Set();
|
|
471
|
+
outOfSyncHandlers = /* @__PURE__ */ new Set();
|
|
472
|
+
sendErrorHandlers = /* @__PURE__ */ new Set();
|
|
473
|
+
offEvent;
|
|
474
|
+
offOpen;
|
|
475
|
+
offClose;
|
|
476
|
+
offReconnecting;
|
|
477
|
+
constructor(websocket, admission) {
|
|
478
|
+
this.websocket = websocket;
|
|
479
|
+
this.admission = admission;
|
|
480
|
+
this.id = admission.room.id;
|
|
481
|
+
this.code = admission.room.code;
|
|
482
|
+
this.createdAt = admission.room.createdAt;
|
|
483
|
+
this.expiresAt = admission.room.expiresAt;
|
|
484
|
+
this.maxParticipants = admission.room.maxParticipants;
|
|
485
|
+
this.seatPerUser = admission.room.seatPerUser === true;
|
|
486
|
+
this.userKey = admission.userKey;
|
|
487
|
+
this._participantId = admission.participantId;
|
|
488
|
+
this.offEvent = websocket.on("event", (event) => this.handleEvent(event));
|
|
489
|
+
this.offOpen = websocket.on("open", () => {
|
|
490
|
+
if (!this.hasJoined || this.explicitLeave || this._state === "expired" || this._state === "closed") return;
|
|
491
|
+
this.rejoin();
|
|
492
|
+
});
|
|
493
|
+
this.offReconnecting = websocket.on("reconnecting", () => {
|
|
494
|
+
if (this.hasJoined && !this.explicitLeave) this.setState("reconnecting");
|
|
495
|
+
});
|
|
496
|
+
this.offClose = websocket.on("close", ({ willReconnect }) => {
|
|
497
|
+
this.rejectPending(/* @__PURE__ */ new Error("room connection closed"));
|
|
498
|
+
if (this.explicitLeave || !willReconnect) {
|
|
499
|
+
if (this._state !== "expired") this.setState("closed");
|
|
500
|
+
this.hasJoined = false;
|
|
501
|
+
this.dispose();
|
|
502
|
+
} else if (this.hasJoined) this.setState("reconnecting");
|
|
503
|
+
});
|
|
504
|
+
const delay = Math.max(0, Date.parse(this.expiresAt) - Date.now());
|
|
505
|
+
this.expiryTimer = setTimeout(() => this.expire(), Math.min(delay, 2147e6));
|
|
506
|
+
}
|
|
507
|
+
get state() {
|
|
508
|
+
return this._state;
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* Identity of this connection inside the room. A `seatPerUser` join can take over a
|
|
512
|
+
* seat the viewer already holds, so this may differ from the id issued at admission.
|
|
513
|
+
*/
|
|
514
|
+
get participantId() {
|
|
515
|
+
return this._participantId;
|
|
516
|
+
}
|
|
517
|
+
get members() {
|
|
518
|
+
return this._members.slice();
|
|
519
|
+
}
|
|
520
|
+
async connect() {
|
|
521
|
+
await this.joinOverWebsocket(false);
|
|
522
|
+
return this;
|
|
523
|
+
}
|
|
524
|
+
subscribe(type, handler) {
|
|
525
|
+
const handlers = this.handlers.get(type) ?? /* @__PURE__ */ new Set();
|
|
526
|
+
handlers.add(handler);
|
|
527
|
+
this.handlers.set(type, handlers);
|
|
528
|
+
return () => handlers.delete(handler);
|
|
529
|
+
}
|
|
530
|
+
subscribeAll(handler) {
|
|
531
|
+
this.allHandlers.add(handler);
|
|
532
|
+
return () => this.allHandlers.delete(handler);
|
|
533
|
+
}
|
|
534
|
+
onStateChange(handler) {
|
|
535
|
+
this.stateHandlers.add(handler);
|
|
536
|
+
return () => this.stateHandlers.delete(handler);
|
|
537
|
+
}
|
|
538
|
+
onMembersChanged(handler) {
|
|
539
|
+
this.membersHandlers.add(handler);
|
|
540
|
+
return () => this.membersHandlers.delete(handler);
|
|
541
|
+
}
|
|
542
|
+
onOutOfSync(handler) {
|
|
543
|
+
this.outOfSyncHandlers.add(handler);
|
|
544
|
+
return () => this.outOfSyncHandlers.delete(handler);
|
|
545
|
+
}
|
|
546
|
+
/** Reports failures of {@link send}, which has no ack to reject. */
|
|
547
|
+
onSendError(handler) {
|
|
548
|
+
this.sendErrorHandlers.add(handler);
|
|
549
|
+
return () => this.sendErrorHandlers.delete(handler);
|
|
550
|
+
}
|
|
551
|
+
/**
|
|
552
|
+
* Publishes without waiting for the server ack, for high-frequency traffic such as
|
|
553
|
+
* input frames. Awaiting {@link publish} instead caps a loop at `1000 / rtt` events
|
|
554
|
+
* per second. Ordering still holds, but failures surface through
|
|
555
|
+
* {@link onSendError} rather than a rejected promise, and calls are ignored while
|
|
556
|
+
* the room is not joined; watch {@link onStateChange} to know when it resumes.
|
|
557
|
+
*/
|
|
558
|
+
send(type, data) {
|
|
559
|
+
if (this._state !== "joined" || !this.hasJoined) return;
|
|
560
|
+
const failure = this.validateSend(type, data);
|
|
561
|
+
if (failure) {
|
|
562
|
+
for (const handler of this.sendErrorHandlers) handler(failure);
|
|
563
|
+
return;
|
|
564
|
+
}
|
|
565
|
+
this.websocket.publishRealtimeRoom({
|
|
566
|
+
roomId: this.id,
|
|
567
|
+
event: type,
|
|
568
|
+
data
|
|
569
|
+
}).catch((error) => {
|
|
570
|
+
const reason = error instanceof Error ? error : new Error(String(error));
|
|
571
|
+
for (const handler of this.sendErrorHandlers) handler(reason);
|
|
572
|
+
});
|
|
573
|
+
}
|
|
574
|
+
validateSend(type, data) {
|
|
575
|
+
if (!REALTIME_ROOM_EVENT_NAME_PATTERN.test(type)) return /* @__PURE__ */ new Error(`invalid room event name: ${type}`);
|
|
576
|
+
let encoded;
|
|
577
|
+
try {
|
|
578
|
+
encoded = JSON.stringify(data);
|
|
579
|
+
} catch {
|
|
580
|
+
return /* @__PURE__ */ new Error("room event data is not serializable");
|
|
581
|
+
}
|
|
582
|
+
if (encoded === void 0) return /* @__PURE__ */ new Error("room event data is not serializable");
|
|
583
|
+
if (byteLength(encoded) > 16384) return /* @__PURE__ */ new Error("room event payload is too large");
|
|
584
|
+
return null;
|
|
585
|
+
}
|
|
586
|
+
async publish(type, data, options) {
|
|
587
|
+
this.assertJoined();
|
|
588
|
+
const failure = this.validateSend(type, data);
|
|
589
|
+
if (failure) throw failure;
|
|
590
|
+
const requestId = randomId();
|
|
591
|
+
const response = await this.request(requestId, /* @__PURE__ */ new Set(["realtime.room.request.ok"]), () => this.websocket.publishRealtimeRoom({
|
|
592
|
+
roomId: this.id,
|
|
593
|
+
event: type,
|
|
594
|
+
data,
|
|
595
|
+
clientEventId: options?.clientEventId,
|
|
596
|
+
requestId
|
|
597
|
+
}));
|
|
598
|
+
const payload = response.payload;
|
|
599
|
+
return {
|
|
600
|
+
eventId: typeof payload.eventId === "string" ? payload.eventId : response.id,
|
|
601
|
+
sequence: typeof payload.sequence === "number" ? payload.sequence : 0,
|
|
602
|
+
clientEventId: typeof payload.clientEventId === "string" ? payload.clientEventId : null
|
|
603
|
+
};
|
|
604
|
+
}
|
|
605
|
+
async setPresence(presence) {
|
|
606
|
+
this.assertJoined();
|
|
607
|
+
const requestId = randomId();
|
|
608
|
+
await this.request(requestId, /* @__PURE__ */ new Set(["realtime.room.request.ok"]), () => this.websocket.updateRealtimeRoomPresence({
|
|
609
|
+
roomId: this.id,
|
|
610
|
+
presence,
|
|
611
|
+
requestId
|
|
612
|
+
}));
|
|
613
|
+
}
|
|
614
|
+
async leave() {
|
|
615
|
+
if (this.explicitLeave || this._state === "closed" || this._state === "expired") return;
|
|
616
|
+
this.explicitLeave = true;
|
|
617
|
+
try {
|
|
618
|
+
if (this.hasJoined && this.websocket.state === "open") {
|
|
619
|
+
const requestId = randomId();
|
|
620
|
+
await this.request(requestId, /* @__PURE__ */ new Set(["realtime.room.request.ok"]), () => this.websocket.leaveRealtimeRoom({
|
|
621
|
+
roomId: this.id,
|
|
622
|
+
requestId
|
|
623
|
+
}));
|
|
624
|
+
}
|
|
625
|
+
} finally {
|
|
626
|
+
this.hasJoined = false;
|
|
627
|
+
this.setState("closed");
|
|
628
|
+
this.dispose();
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
async rejoin() {
|
|
632
|
+
if (this.explicitLeave || this._state === "expired" || this._state === "closed") return;
|
|
633
|
+
try {
|
|
634
|
+
await this.joinOverWebsocket(true);
|
|
635
|
+
} catch (error) {
|
|
636
|
+
if (this.state === "expired") return;
|
|
637
|
+
this.setState("closed");
|
|
638
|
+
this.dispose();
|
|
639
|
+
console.warn("[Cohub WorkRoom] failed to rejoin room", error);
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
async joinOverWebsocket(isReconnect) {
|
|
643
|
+
if (!this.websocket.supportsCapability("realtime.room.v1") && this.websocket.state === "open") throw new Error("Realtime rooms are not supported by the Gateway");
|
|
644
|
+
this.setState(isReconnect ? "reconnecting" : "connecting");
|
|
645
|
+
const requestId = randomId();
|
|
646
|
+
this.joinBuffer = [];
|
|
647
|
+
try {
|
|
648
|
+
const payload = (await this.request(requestId, /* @__PURE__ */ new Set(["realtime.room.joined"]), () => this.websocket.joinRealtimeRoom({
|
|
649
|
+
roomId: this.id,
|
|
650
|
+
ticket: this.admission.ticket,
|
|
651
|
+
requestId
|
|
652
|
+
}))).payload;
|
|
653
|
+
if (typeof payload.participantId !== "string" || !Array.isArray(payload.members)) throw new Error("invalid room join response");
|
|
654
|
+
this._participantId = payload.participantId;
|
|
655
|
+
this._members = payload.members;
|
|
656
|
+
this.lastSequence = typeof payload.sequence === "number" ? payload.sequence : 0;
|
|
657
|
+
} catch (error) {
|
|
658
|
+
this.joinBuffer = null;
|
|
659
|
+
throw error;
|
|
660
|
+
}
|
|
661
|
+
this.hasJoined = true;
|
|
662
|
+
this.setState("joined");
|
|
663
|
+
this.notifyMembers();
|
|
664
|
+
const buffered = this.joinBuffer ?? [];
|
|
665
|
+
this.joinBuffer = null;
|
|
666
|
+
for (const item of buffered) {
|
|
667
|
+
const sequence = item.payload.sequence;
|
|
668
|
+
if (typeof sequence === "number" && sequence <= this.lastSequence) continue;
|
|
669
|
+
this.handleEvent(item);
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
request(requestId, expected, send) {
|
|
673
|
+
return new Promise((resolve, reject) => {
|
|
674
|
+
const timer = setTimeout(() => {
|
|
675
|
+
this.pending.delete(requestId);
|
|
676
|
+
reject(/* @__PURE__ */ new Error("room request timed out"));
|
|
677
|
+
}, 2e4);
|
|
678
|
+
this.pending.set(requestId, {
|
|
679
|
+
expected,
|
|
680
|
+
resolve,
|
|
681
|
+
reject,
|
|
682
|
+
timer
|
|
683
|
+
});
|
|
684
|
+
send().catch((error) => {
|
|
685
|
+
this.pending.delete(requestId);
|
|
686
|
+
clearTimeout(timer);
|
|
687
|
+
reject(error instanceof Error ? error : new Error(String(error)));
|
|
688
|
+
});
|
|
689
|
+
});
|
|
690
|
+
}
|
|
691
|
+
/** Detaches the entry awaiting this requestId, so the caller can settle it. */
|
|
692
|
+
takePending(requestId) {
|
|
693
|
+
const pending = requestId ? this.pending.get(requestId) : void 0;
|
|
694
|
+
if (!pending || !requestId) return null;
|
|
695
|
+
this.pending.delete(requestId);
|
|
696
|
+
clearTimeout(pending.timer);
|
|
697
|
+
return pending;
|
|
698
|
+
}
|
|
699
|
+
handleEvent(event) {
|
|
700
|
+
if (!isRoomEvent(event, this.id)) {
|
|
701
|
+
if (event.type === "system.request.error") this.takePending(event.requestId)?.reject(requestError(event));
|
|
702
|
+
return;
|
|
703
|
+
}
|
|
704
|
+
if (event.type === "realtime.room.request.error") {
|
|
705
|
+
const failure = requestError(event);
|
|
706
|
+
if (event.requestId) {
|
|
707
|
+
this.takePending(event.requestId)?.reject(failure);
|
|
708
|
+
return;
|
|
709
|
+
}
|
|
710
|
+
for (const handler of this.sendErrorHandlers) handler(failure);
|
|
711
|
+
return;
|
|
712
|
+
}
|
|
713
|
+
const awaiting = event.requestId ? this.pending.get(event.requestId) : void 0;
|
|
714
|
+
if (awaiting?.expected.has(event.type)) {
|
|
715
|
+
this.takePending(event.requestId);
|
|
716
|
+
awaiting.resolve(event);
|
|
717
|
+
}
|
|
718
|
+
if (this.joinBuffer && WORK_ROOM_DELTA_EVENTS.has(event.type)) {
|
|
719
|
+
if (this.joinBuffer.length < WORK_ROOM_MAX_JOIN_BUFFER) this.joinBuffer.push(event);
|
|
720
|
+
return;
|
|
721
|
+
}
|
|
722
|
+
const payload = event.payload;
|
|
723
|
+
const sequence = typeof payload.sequence === "number" ? payload.sequence : null;
|
|
724
|
+
if (sequence !== null) this.observeSequence(sequence);
|
|
725
|
+
if (event.type === "realtime.room.member.joined" || event.type === "realtime.room.member.left" || event.type === "realtime.room.presence.updated") {
|
|
726
|
+
const member = payload.member;
|
|
727
|
+
if (member?.participantId) {
|
|
728
|
+
const members = new Map(this._members.map((item) => [item.participantId, item]));
|
|
729
|
+
if (event.type === "realtime.room.member.left") members.delete(member.participantId);
|
|
730
|
+
else members.set(member.participantId, member);
|
|
731
|
+
this._members = [...members.values()];
|
|
732
|
+
this.notifyMembers();
|
|
733
|
+
}
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
736
|
+
if (event.type === "realtime.room.closed") {
|
|
737
|
+
this.hasJoined = false;
|
|
738
|
+
if (payload.reason === "expired") this.setState("expired");
|
|
739
|
+
else this.setState("closed");
|
|
740
|
+
this.rejectPending(/* @__PURE__ */ new Error(`room closed: ${typeof payload.reason === "string" ? payload.reason : "unknown"}`));
|
|
741
|
+
this.dispose();
|
|
742
|
+
return;
|
|
743
|
+
}
|
|
744
|
+
if (event.type !== "realtime.room.event") return;
|
|
745
|
+
const roomEvent = event;
|
|
746
|
+
const roomPayload = roomEvent.payload;
|
|
747
|
+
const item = {
|
|
748
|
+
id: roomEvent.id,
|
|
749
|
+
timestamp: roomEvent.timestamp,
|
|
750
|
+
roomId: roomPayload.roomId,
|
|
751
|
+
sequence: roomPayload.sequence,
|
|
752
|
+
type: roomPayload.event,
|
|
753
|
+
data: roomPayload.data,
|
|
754
|
+
clientEventId: roomPayload.clientEventId,
|
|
755
|
+
sender: roomPayload.sender,
|
|
756
|
+
self: roomPayload.sender.participantId === this.participantId
|
|
757
|
+
};
|
|
758
|
+
this.handlers.get(item.type)?.forEach((handler) => {
|
|
759
|
+
handler(item);
|
|
760
|
+
});
|
|
761
|
+
this.allHandlers.forEach((handler) => {
|
|
762
|
+
handler(item);
|
|
763
|
+
});
|
|
764
|
+
}
|
|
765
|
+
observeSequence(sequence) {
|
|
766
|
+
if (this.lastSequence > 0 && sequence > this.lastSequence + 1) for (const handler of this.outOfSyncHandlers) handler(this.lastSequence + 1, sequence);
|
|
767
|
+
if (sequence > this.lastSequence) this.lastSequence = sequence;
|
|
768
|
+
}
|
|
769
|
+
assertJoined() {
|
|
770
|
+
if (this._state !== "joined" || !this.hasJoined) throw new Error("room is not joined");
|
|
771
|
+
}
|
|
772
|
+
setState(state) {
|
|
773
|
+
if (this._state === state) return;
|
|
774
|
+
this._state = state;
|
|
775
|
+
for (const handler of this.stateHandlers) handler(state);
|
|
776
|
+
}
|
|
777
|
+
notifyMembers() {
|
|
778
|
+
const members = this.members;
|
|
779
|
+
for (const handler of this.membersHandlers) handler(members);
|
|
780
|
+
}
|
|
781
|
+
rejectPending(error) {
|
|
782
|
+
for (const [requestId, pending] of this.pending) {
|
|
783
|
+
this.pending.delete(requestId);
|
|
784
|
+
clearTimeout(pending.timer);
|
|
785
|
+
pending.reject(error);
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
expire() {
|
|
789
|
+
if (this.explicitLeave || this._state === "closed" || this._state === "expired") return;
|
|
790
|
+
this.hasJoined = false;
|
|
791
|
+
this.setState("expired");
|
|
792
|
+
this.rejectPending(/* @__PURE__ */ new Error("room expired"));
|
|
793
|
+
this.dispose();
|
|
794
|
+
}
|
|
795
|
+
dispose() {
|
|
796
|
+
this.offEvent();
|
|
797
|
+
this.offOpen();
|
|
798
|
+
this.offClose();
|
|
799
|
+
this.offReconnecting();
|
|
800
|
+
if (this.expiryTimer) clearTimeout(this.expiryTimer);
|
|
801
|
+
this.expiryTimer = null;
|
|
802
|
+
}
|
|
803
|
+
};
|
|
804
|
+
var WorkRealtimeApi = class {
|
|
75
805
|
transport;
|
|
76
|
-
|
|
806
|
+
websocket;
|
|
807
|
+
getContext;
|
|
808
|
+
constructor(transport, websocket, getContext) {
|
|
77
809
|
this.transport = transport;
|
|
810
|
+
this.websocket = websocket;
|
|
811
|
+
this.getContext = getContext;
|
|
812
|
+
}
|
|
813
|
+
async createRoom(input = {}) {
|
|
814
|
+
const admission = await this.transport.request(`/api/works/${encodeURIComponent(await this.requireWorkId())}/realtime/rooms`, {
|
|
815
|
+
method: "POST",
|
|
816
|
+
headers: { "Content-Type": "application/json" },
|
|
817
|
+
body: JSON.stringify(input)
|
|
818
|
+
});
|
|
819
|
+
return this.openRoom(admission);
|
|
820
|
+
}
|
|
821
|
+
async joinRoom(input) {
|
|
822
|
+
const admission = await this.transport.request(`/api/works/${encodeURIComponent(await this.requireWorkId())}/realtime/rooms/join`, {
|
|
823
|
+
method: "POST",
|
|
824
|
+
headers: { "Content-Type": "application/json" },
|
|
825
|
+
body: JSON.stringify(input)
|
|
826
|
+
});
|
|
827
|
+
return this.openRoom(admission);
|
|
78
828
|
}
|
|
79
|
-
|
|
80
|
-
|
|
829
|
+
async requireWorkId() {
|
|
830
|
+
const context = await this.getContext();
|
|
831
|
+
if (!context?.work?.id) throw new Error("Work context is unavailable — not running inside a published Work runtime.");
|
|
832
|
+
return context.work.id;
|
|
833
|
+
}
|
|
834
|
+
async openRoom(admission) {
|
|
835
|
+
const room = new WorkRoom(this.websocket, admission);
|
|
836
|
+
try {
|
|
837
|
+
await room.connect();
|
|
838
|
+
return room;
|
|
839
|
+
} catch (error) {
|
|
840
|
+
await room.leave().catch(() => void 0);
|
|
841
|
+
throw error;
|
|
842
|
+
}
|
|
81
843
|
}
|
|
82
844
|
};
|
|
83
845
|
//#endregion
|
|
@@ -478,7 +1240,6 @@ var CohubClient = class {
|
|
|
478
1240
|
references;
|
|
479
1241
|
tasks;
|
|
480
1242
|
cronJobs;
|
|
481
|
-
explore;
|
|
482
1243
|
invite;
|
|
483
1244
|
referrals;
|
|
484
1245
|
voice;
|
|
@@ -535,46 +1296,49 @@ var CohubClient = class {
|
|
|
535
1296
|
this.references = new ReferencesApi(this.transport);
|
|
536
1297
|
this.tasks = new TasksApi(this.transport);
|
|
537
1298
|
this.cronJobs = new CronJobsApi(this.transport);
|
|
538
|
-
this.explore = new ExploreApi(this.transport);
|
|
539
1299
|
this.invite = new PublicInviteApi(this.transport);
|
|
540
1300
|
this.referrals = new ReferralsApi(this.transport);
|
|
541
1301
|
this.works = new WorksApi(this.transport);
|
|
542
1302
|
this.workCommerce = new WorkCommerceApi(this.transport);
|
|
1303
|
+
this.work.realtime = new WorkRealtimeApi(this.transport, this.websocketClient, () => this.workRuntime.context());
|
|
543
1304
|
}
|
|
544
1305
|
context() {
|
|
545
1306
|
return this.workRuntime.context();
|
|
546
1307
|
}
|
|
547
1308
|
auth = { request: (input) => this.workRuntime.requestAuthorization(input) };
|
|
548
|
-
work = {
|
|
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
|
-
|
|
574
|
-
|
|
575
|
-
|
|
1309
|
+
work = {
|
|
1310
|
+
realtime: null,
|
|
1311
|
+
commerce: {
|
|
1312
|
+
resolveProducts: async (input) => {
|
|
1313
|
+
const context = await this.workRuntime.context();
|
|
1314
|
+
if (!context?.work?.id) throw new Error("Work context is unavailable — not running inside a published Work runtime.");
|
|
1315
|
+
return this.workCommerce.resolveProducts(context.work.id, input);
|
|
1316
|
+
},
|
|
1317
|
+
getEntitlements: async () => {
|
|
1318
|
+
const context = await this.workRuntime.context();
|
|
1319
|
+
if (!context?.work?.id) throw new Error("Work context is unavailable — not running inside a published Work runtime.");
|
|
1320
|
+
return this.workCommerce.getEntitlements(context.work.id);
|
|
1321
|
+
},
|
|
1322
|
+
consumeCredits: async (input) => {
|
|
1323
|
+
const context = await this.workRuntime.context();
|
|
1324
|
+
if (!context?.work?.id) throw new Error("Work context is unavailable — not running inside a published Work runtime.");
|
|
1325
|
+
return this.workCommerce.consumeCredits(context.work.id, input);
|
|
1326
|
+
},
|
|
1327
|
+
purchase: async (input) => this.workRuntime.purchase(input),
|
|
1328
|
+
getCheckoutState: async () => {
|
|
1329
|
+
const result = await this.workRuntime.checkoutState();
|
|
1330
|
+
return {
|
|
1331
|
+
status: result?.status ?? null,
|
|
1332
|
+
orderId: result?.orderId ?? null
|
|
1333
|
+
};
|
|
1334
|
+
},
|
|
1335
|
+
getOrder: async (orderId) => {
|
|
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.getOrder(context.work.id, orderId);
|
|
1339
|
+
}
|
|
576
1340
|
}
|
|
577
|
-
}
|
|
1341
|
+
};
|
|
578
1342
|
space(spaceId) {
|
|
579
1343
|
return new SpaceClient(spaceId, this.transport, this.websocketClient);
|
|
580
1344
|
}
|
|
@@ -1290,53 +2054,12 @@ function filterGenerationDeclarationsByPolicy(declarations, policy) {
|
|
|
1290
2054
|
});
|
|
1291
2055
|
}
|
|
1292
2056
|
//#endregion
|
|
1293
|
-
//#region ../protocol/dist/board-constants.js
|
|
1294
|
-
const DEFAULT_BOARD_RENDER_LIMITS = {
|
|
1295
|
-
particles: 2e4,
|
|
1296
|
-
vertices: 5e5,
|
|
1297
|
-
dynamicVertices: 15e4,
|
|
1298
|
-
drawCalls: 400,
|
|
1299
|
-
filterPasses: 24,
|
|
1300
|
-
renderTexturePixels: 16777216,
|
|
1301
|
-
textureBytes: 512 * 1024 * 1024,
|
|
1302
|
-
bufferBytes: 256 * 1024 * 1024,
|
|
1303
|
-
simulationSteps: 1e5
|
|
1304
|
-
};
|
|
1305
|
-
const BOARD_BUILTIN_CLIP_KINDS = [
|
|
1306
|
-
"motion.keyframes",
|
|
1307
|
-
"motion.path",
|
|
1308
|
-
"draw.reveal",
|
|
1309
|
-
"draw.handwrite",
|
|
1310
|
-
"text.reveal",
|
|
1311
|
-
"effects.particles",
|
|
1312
|
-
"effects.trail",
|
|
1313
|
-
"effects.impact",
|
|
1314
|
-
"effects.flash",
|
|
1315
|
-
"effects.color",
|
|
1316
|
-
"camera.pan",
|
|
1317
|
-
"camera.zoom",
|
|
1318
|
-
"camera.shake"
|
|
1319
|
-
];
|
|
1320
|
-
const BOARD_BUILTIN_EFFECT_KINDS = ["effects.pulse", "effects.float"];
|
|
1321
|
-
const BOARD_ARROW_STROKE_SIZE = 2.5;
|
|
1322
|
-
const BOARD_BUILTIN_CAPABILITIES = [...BOARD_BUILTIN_CLIP_KINDS.map((id) => ({
|
|
1323
|
-
kind: "clip",
|
|
1324
|
-
id,
|
|
1325
|
-
version: 1,
|
|
1326
|
-
renderers: ["webgpu", "webgl"]
|
|
1327
|
-
})), ...BOARD_BUILTIN_EFFECT_KINDS.map((id) => ({
|
|
1328
|
-
kind: "effect",
|
|
1329
|
-
id,
|
|
1330
|
-
version: 1,
|
|
1331
|
-
renderers: ["webgpu", "webgl"]
|
|
1332
|
-
}))];
|
|
1333
|
-
//#endregion
|
|
1334
2057
|
//#region ../protocol/dist/board.js
|
|
1335
2058
|
const BOARD_MANIFEST_KIND = "cohub.board.manifest";
|
|
1336
|
-
const idSchema
|
|
2059
|
+
const idSchema = z.string().min(1).max(160);
|
|
1337
2060
|
const extensionIdSchema = z.string().regex(/^[a-z][a-z0-9]*(?:[.-][a-z0-9]+)+$/).max(160);
|
|
1338
2061
|
const jsonObjectSchema = z.record(z.string(), z.unknown());
|
|
1339
|
-
const finiteSchema
|
|
2062
|
+
const finiteSchema = z.number().finite();
|
|
1340
2063
|
z.object({
|
|
1341
2064
|
kind: z.literal(BOARD_MANIFEST_KIND),
|
|
1342
2065
|
version: z.literal(1),
|
|
@@ -1346,11 +2069,11 @@ z.object({
|
|
|
1346
2069
|
const BoardTargetSchema = z.discriminatedUnion("type", [
|
|
1347
2070
|
z.object({
|
|
1348
2071
|
type: z.literal("node"),
|
|
1349
|
-
nodeId: idSchema
|
|
2072
|
+
nodeId: idSchema
|
|
1350
2073
|
}),
|
|
1351
2074
|
z.object({
|
|
1352
2075
|
type: z.literal("effect"),
|
|
1353
|
-
effectId: idSchema
|
|
2076
|
+
effectId: idSchema
|
|
1354
2077
|
}),
|
|
1355
2078
|
z.object({ type: z.literal("board") }),
|
|
1356
2079
|
z.object({ type: z.literal("camera") })
|
|
@@ -1361,18 +2084,18 @@ const BoardAssetRefSchema = z.object({
|
|
|
1361
2084
|
digest: z.string().min(16).max(160).optional()
|
|
1362
2085
|
});
|
|
1363
2086
|
const BoardKeyframeSchema = z.object({
|
|
1364
|
-
at: finiteSchema
|
|
2087
|
+
at: finiteSchema.nonnegative(),
|
|
1365
2088
|
value: z.unknown(),
|
|
1366
2089
|
easing: z.string().min(1).max(80).optional()
|
|
1367
2090
|
});
|
|
1368
2091
|
const BoardClipSchema = z.object({
|
|
1369
|
-
id: idSchema
|
|
1370
|
-
sequenceId: idSchema
|
|
2092
|
+
id: idSchema,
|
|
2093
|
+
sequenceId: idSchema,
|
|
1371
2094
|
kind: extensionIdSchema,
|
|
1372
2095
|
kindVersion: z.number().int().positive(),
|
|
1373
2096
|
target: BoardTargetSchema,
|
|
1374
|
-
start: finiteSchema
|
|
1375
|
-
duration: finiteSchema
|
|
2097
|
+
start: finiteSchema.nonnegative(),
|
|
2098
|
+
duration: finiteSchema.positive(),
|
|
1376
2099
|
layer: z.enum([
|
|
1377
2100
|
"behind",
|
|
1378
2101
|
"content",
|
|
@@ -1393,11 +2116,11 @@ const BoardClipSchema = z.object({
|
|
|
1393
2116
|
metadata: jsonObjectSchema.default({})
|
|
1394
2117
|
});
|
|
1395
2118
|
const BoardEffectSchema = z.object({
|
|
1396
|
-
id: idSchema
|
|
2119
|
+
id: idSchema,
|
|
1397
2120
|
boardId: z.string().uuid(),
|
|
1398
2121
|
target: z.discriminatedUnion("type", [z.object({
|
|
1399
2122
|
type: z.literal("node"),
|
|
1400
|
-
nodeId: idSchema
|
|
2123
|
+
nodeId: idSchema
|
|
1401
2124
|
}), z.object({ type: z.literal("board") })]),
|
|
1402
2125
|
kind: extensionIdSchema,
|
|
1403
2126
|
kindVersion: z.number().int().positive(),
|
|
@@ -1424,25 +2147,25 @@ const BoardEffectSchema = z.object({
|
|
|
1424
2147
|
revision: z.number().int().nonnegative()
|
|
1425
2148
|
});
|
|
1426
2149
|
const BoardSequenceSchema = z.object({
|
|
1427
|
-
id: idSchema
|
|
2150
|
+
id: idSchema,
|
|
1428
2151
|
boardId: z.string().uuid(),
|
|
1429
2152
|
name: z.string().min(1).max(255),
|
|
1430
|
-
duration: finiteSchema
|
|
2153
|
+
duration: finiteSchema.nonnegative(),
|
|
1431
2154
|
seed: z.string().min(1).max(160),
|
|
1432
2155
|
restPose: jsonObjectSchema.default({}),
|
|
1433
2156
|
metadata: jsonObjectSchema.default({}),
|
|
1434
2157
|
revision: z.number().int().nonnegative()
|
|
1435
2158
|
});
|
|
1436
2159
|
const BoardNodeInputSchema = z.object({
|
|
1437
|
-
nodeId: idSchema
|
|
2160
|
+
nodeId: idSchema,
|
|
1438
2161
|
type: z.string().min(1).max(40),
|
|
1439
|
-
parentId: idSchema
|
|
2162
|
+
parentId: idSchema.nullable(),
|
|
1440
2163
|
orderKey: z.string().max(4096).nullable(),
|
|
1441
|
-
x: finiteSchema
|
|
1442
|
-
y: finiteSchema
|
|
1443
|
-
width: finiteSchema
|
|
1444
|
-
height: finiteSchema
|
|
1445
|
-
rotation: finiteSchema
|
|
2164
|
+
x: finiteSchema,
|
|
2165
|
+
y: finiteSchema,
|
|
2166
|
+
width: finiteSchema.positive(),
|
|
2167
|
+
height: finiteSchema.positive(),
|
|
2168
|
+
rotation: finiteSchema,
|
|
1446
2169
|
refKind: z.string().max(40).nullable(),
|
|
1447
2170
|
refPath: z.string().max(4096).nullable(),
|
|
1448
2171
|
refUrl: z.string().max(4096).nullable(),
|
|
@@ -1478,17 +2201,17 @@ z.object({
|
|
|
1478
2201
|
"playback"
|
|
1479
2202
|
])).optional(),
|
|
1480
2203
|
viewport: z.object({
|
|
1481
|
-
x: finiteSchema
|
|
1482
|
-
y: finiteSchema
|
|
1483
|
-
width: finiteSchema
|
|
1484
|
-
height: finiteSchema
|
|
2204
|
+
x: finiteSchema,
|
|
2205
|
+
y: finiteSchema,
|
|
2206
|
+
width: finiteSchema.positive(),
|
|
2207
|
+
height: finiteSchema.positive()
|
|
1485
2208
|
}).optional()
|
|
1486
2209
|
});
|
|
1487
2210
|
/** Persisted on `boards.metadata.playback`: how a Board plays when opened. */
|
|
1488
2211
|
const BoardPlaybackPolicySchema = z.object({
|
|
1489
|
-
sequenceId: idSchema
|
|
2212
|
+
sequenceId: idSchema,
|
|
1490
2213
|
/** Delay before the first local playback after opening the Board, in milliseconds. */
|
|
1491
|
-
delayMs: finiteSchema
|
|
2214
|
+
delayMs: finiteSchema.nonnegative().default(0),
|
|
1492
2215
|
loop: z.boolean().default(false)
|
|
1493
2216
|
});
|
|
1494
2217
|
function parseBoardPlaybackPolicy(metadata) {
|
|
@@ -1497,148 +2220,32 @@ function parseBoardPlaybackPolicy(metadata) {
|
|
|
1497
2220
|
}
|
|
1498
2221
|
z.discriminatedUnion("type", [
|
|
1499
2222
|
z.object({
|
|
1500
|
-
commandId: idSchema
|
|
2223
|
+
commandId: idSchema,
|
|
1501
2224
|
type: z.literal("play"),
|
|
1502
|
-
sequenceId: idSchema
|
|
1503
|
-
position: finiteSchema
|
|
1504
|
-
timeScale: finiteSchema
|
|
2225
|
+
sequenceId: idSchema,
|
|
2226
|
+
position: finiteSchema.nonnegative().optional(),
|
|
2227
|
+
timeScale: finiteSchema.positive().max(4).optional(),
|
|
1505
2228
|
shared: z.boolean().optional(),
|
|
1506
|
-
seed: idSchema
|
|
2229
|
+
seed: idSchema.optional()
|
|
1507
2230
|
}),
|
|
1508
2231
|
z.object({
|
|
1509
|
-
commandId: idSchema
|
|
2232
|
+
commandId: idSchema,
|
|
1510
2233
|
type: z.literal("pause"),
|
|
1511
2234
|
playbackId: z.string().uuid()
|
|
1512
2235
|
}),
|
|
1513
2236
|
z.object({
|
|
1514
|
-
commandId: idSchema
|
|
2237
|
+
commandId: idSchema,
|
|
1515
2238
|
type: z.literal("seek"),
|
|
1516
2239
|
playbackId: z.string().uuid(),
|
|
1517
|
-
position: finiteSchema
|
|
2240
|
+
position: finiteSchema.nonnegative()
|
|
1518
2241
|
}),
|
|
1519
2242
|
z.object({
|
|
1520
|
-
commandId: idSchema
|
|
2243
|
+
commandId: idSchema,
|
|
1521
2244
|
type: z.literal("stop"),
|
|
1522
2245
|
playbackId: z.string().uuid()
|
|
1523
2246
|
})
|
|
1524
2247
|
]);
|
|
1525
2248
|
//#endregion
|
|
1526
|
-
//#region ../protocol/dist/realtime/board-awareness.js
|
|
1527
|
-
const idSchema = z.string().min(1).max(160);
|
|
1528
|
-
const finiteSchema = z.number().finite();
|
|
1529
|
-
const BoardAwarenessPointSchema = z.object({
|
|
1530
|
-
x: finiteSchema,
|
|
1531
|
-
y: finiteSchema
|
|
1532
|
-
});
|
|
1533
|
-
const BoardAwarenessDrawPointSchema = BoardAwarenessPointSchema.extend({ p: finiteSchema.min(0).max(1) });
|
|
1534
|
-
const BoardAwarenessFrameSchema = z.object({
|
|
1535
|
-
x: finiteSchema,
|
|
1536
|
-
y: finiteSchema,
|
|
1537
|
-
width: finiteSchema.positive(),
|
|
1538
|
-
height: finiteSchema.positive(),
|
|
1539
|
-
rotation: finiteSchema
|
|
1540
|
-
});
|
|
1541
|
-
const arrowEndpointSchema = z.union([z.object({
|
|
1542
|
-
kind: z.literal("point"),
|
|
1543
|
-
x: finiteSchema,
|
|
1544
|
-
y: finiteSchema
|
|
1545
|
-
}), z.object({
|
|
1546
|
-
kind: z.literal("binding"),
|
|
1547
|
-
target: idSchema,
|
|
1548
|
-
nx: finiteSchema,
|
|
1549
|
-
ny: finiteSchema,
|
|
1550
|
-
precise: z.boolean()
|
|
1551
|
-
})]);
|
|
1552
|
-
const BoardAwarenessNodePreviewSchema = z.object({
|
|
1553
|
-
nodeId: idSchema,
|
|
1554
|
-
frame: BoardAwarenessFrameSchema,
|
|
1555
|
-
arrow: z.object({
|
|
1556
|
-
start: arrowEndpointSchema,
|
|
1557
|
-
end: arrowEndpointSchema,
|
|
1558
|
-
bend: finiteSchema
|
|
1559
|
-
}).optional()
|
|
1560
|
-
});
|
|
1561
|
-
const BoardAwarenessStateUpdateSchema = z.object({
|
|
1562
|
-
type: z.literal("state"),
|
|
1563
|
-
client: z.object({ formFactor: z.enum(["desktop", "mobile"]) }).optional(),
|
|
1564
|
-
cursor: BoardAwarenessPointSchema.extend({ pointerType: z.enum([
|
|
1565
|
-
"mouse",
|
|
1566
|
-
"pen",
|
|
1567
|
-
"touch"
|
|
1568
|
-
]) }).nullable(),
|
|
1569
|
-
tool: z.string().min(1).max(40),
|
|
1570
|
-
selection: z.object({
|
|
1571
|
-
ids: z.array(idSchema).max(64),
|
|
1572
|
-
count: z.number().int().nonnegative().max(5e4),
|
|
1573
|
-
bounds: BoardAwarenessFrameSchema.nullable()
|
|
1574
|
-
}),
|
|
1575
|
-
editingId: idSchema.nullable()
|
|
1576
|
-
});
|
|
1577
|
-
const BoardAwarenessGestureSchema = z.discriminatedUnion("kind", [
|
|
1578
|
-
z.object({
|
|
1579
|
-
kind: z.literal("draw"),
|
|
1580
|
-
id: idSchema,
|
|
1581
|
-
nodeId: idSchema,
|
|
1582
|
-
color: z.string().min(1).max(64),
|
|
1583
|
-
size: finiteSchema.positive().max(256),
|
|
1584
|
-
from: z.number().int().nonnegative().max(1e5),
|
|
1585
|
-
points: z.array(BoardAwarenessDrawPointSchema).min(1).max(64)
|
|
1586
|
-
}),
|
|
1587
|
-
z.object({
|
|
1588
|
-
kind: z.literal("arrow"),
|
|
1589
|
-
id: idSchema,
|
|
1590
|
-
nodeId: idSchema,
|
|
1591
|
-
start: BoardAwarenessPointSchema,
|
|
1592
|
-
current: BoardAwarenessPointSchema,
|
|
1593
|
-
color: z.string().min(1).max(64),
|
|
1594
|
-
size: finiteSchema.positive().max(256).default(BOARD_ARROW_STROKE_SIZE)
|
|
1595
|
-
}),
|
|
1596
|
-
z.object({
|
|
1597
|
-
kind: z.literal("box"),
|
|
1598
|
-
id: idSchema,
|
|
1599
|
-
nodeId: idSchema,
|
|
1600
|
-
shape: z.enum(["geo", "frame"]),
|
|
1601
|
-
start: BoardAwarenessPointSchema,
|
|
1602
|
-
current: BoardAwarenessPointSchema,
|
|
1603
|
-
color: z.string().min(1).max(64),
|
|
1604
|
-
geo: z.string().min(1).max(40)
|
|
1605
|
-
}),
|
|
1606
|
-
z.object({
|
|
1607
|
-
kind: z.literal("transform"),
|
|
1608
|
-
id: idSchema,
|
|
1609
|
-
mode: z.enum([
|
|
1610
|
-
"translate",
|
|
1611
|
-
"resize",
|
|
1612
|
-
"rotate",
|
|
1613
|
-
"arrow"
|
|
1614
|
-
]),
|
|
1615
|
-
nodes: z.array(BoardAwarenessNodePreviewSchema).max(64),
|
|
1616
|
-
bounds: BoardAwarenessFrameSchema.nullable()
|
|
1617
|
-
})
|
|
1618
|
-
]);
|
|
1619
|
-
const BoardAwarenessUpdateSchema = z.discriminatedUnion("type", [
|
|
1620
|
-
BoardAwarenessStateUpdateSchema,
|
|
1621
|
-
z.object({
|
|
1622
|
-
type: z.literal("gesture"),
|
|
1623
|
-
gesture: BoardAwarenessGestureSchema
|
|
1624
|
-
}),
|
|
1625
|
-
z.object({
|
|
1626
|
-
type: z.literal("gesture.end"),
|
|
1627
|
-
gestureId: idSchema,
|
|
1628
|
-
resultingNodeIds: z.array(idSchema).max(64)
|
|
1629
|
-
}),
|
|
1630
|
-
z.object({
|
|
1631
|
-
type: z.literal("gesture.cancel"),
|
|
1632
|
-
gestureId: idSchema
|
|
1633
|
-
})
|
|
1634
|
-
]);
|
|
1635
|
-
z.object({
|
|
1636
|
-
spaceId: z.string().uuid(),
|
|
1637
|
-
boardId: z.string().uuid(),
|
|
1638
|
-
seq: z.number().int().nonnegative(),
|
|
1639
|
-
update: BoardAwarenessUpdateSchema
|
|
1640
|
-
});
|
|
1641
|
-
//#endregion
|
|
1642
2249
|
//#region ../protocol/dist/public-identifiers.js
|
|
1643
2250
|
/**
|
|
1644
2251
|
* Platform-owned path segments that must not be newly assigned to public
|
|
@@ -2026,4 +2633,4 @@ function createBoardExtensionRegistry(input = {}) {
|
|
|
2026
2633
|
return registry;
|
|
2027
2634
|
}
|
|
2028
2635
|
//#endregion
|
|
2029
|
-
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 };
|
|
2636
|
+
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 };
|