@neta-art/cohub 3.0.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/README.md +33 -2
  2. package/dist/{board.d.ts → board/animation.d.ts} +4 -2
  3. package/dist/{chunks/board.js → board/animation.js} +5 -44
  4. package/dist/board/codec.d.ts +25 -0
  5. package/dist/board/codec.js +252 -0
  6. package/dist/board/core/bindings.d.ts +45 -0
  7. package/dist/board/core/bindings.js +162 -0
  8. package/dist/board/core/draw-geometry.d.ts +31 -0
  9. package/dist/board/core/draw-geometry.js +183 -0
  10. package/dist/board/core/export-assets.d.ts +14 -0
  11. package/dist/board/core/export-assets.js +22 -0
  12. package/dist/board/core/export-plan.d.ts +84 -0
  13. package/dist/board/core/export-plan.js +128 -0
  14. package/dist/board/core/file-preview.d.ts +176 -0
  15. package/dist/board/core/file-preview.js +271 -0
  16. package/dist/board/core/palette.d.ts +42 -0
  17. package/dist/board/core/palette.js +138 -0
  18. package/dist/board/core/shape-definition.d.ts +35 -0
  19. package/dist/board/core/shape-definition.js +64 -0
  20. package/dist/board/core/shape-types.d.ts +144 -0
  21. package/dist/board/core/shape-types.js +27 -0
  22. package/dist/board/core/text-metrics.d.ts +18 -0
  23. package/dist/board/core/text-metrics.js +43 -0
  24. package/dist/board/export/index.d.ts +56 -0
  25. package/dist/board/export/index.js +86 -0
  26. package/dist/board/export/scene.d.ts +35 -0
  27. package/dist/board/export/scene.js +69 -0
  28. package/dist/board/geometry.d.ts +131 -0
  29. package/dist/board/geometry.js +468 -0
  30. package/dist/board/headless/index.d.ts +69 -0
  31. package/dist/board/headless/index.js +150 -0
  32. package/dist/board/image-key.d.ts +19 -0
  33. package/dist/board/image-key.js +34 -0
  34. package/dist/board/index.d.ts +16 -0
  35. package/dist/board/index.js +16 -0
  36. package/dist/board/render/index.d.ts +6 -0
  37. package/dist/board/render/index.js +6 -0
  38. package/dist/board/render/palette.d.ts +5 -0
  39. package/dist/board/render/palette.js +30 -0
  40. package/dist/board/render/renderers/arrow-card-renderer.d.ts +5 -0
  41. package/dist/board/render/renderers/arrow-card-renderer.js +157 -0
  42. package/dist/board/render/renderers/base-card-renderer.d.ts +46 -0
  43. package/dist/board/render/renderers/base-card-renderer.js +153 -0
  44. package/dist/board/render/renderers/board-renderer-registry.d.ts +85 -0
  45. package/dist/board/render/renderers/board-renderer-registry.js +43 -0
  46. package/dist/board/render/renderers/draw-card-renderer.d.ts +5 -0
  47. package/dist/board/render/renderers/draw-card-renderer.js +82 -0
  48. package/dist/board/render/renderers/far-plate.d.ts +39 -0
  49. package/dist/board/render/renderers/far-plate.js +92 -0
  50. package/dist/board/render/renderers/file-card-renderer.d.ts +33 -0
  51. package/dist/board/render/renderers/file-card-renderer.js +371 -0
  52. package/dist/board/render/renderers/frame-card-renderer.d.ts +5 -0
  53. package/dist/board/render/renderers/frame-card-renderer.js +99 -0
  54. package/dist/board/render/renderers/geo-card-renderer.d.ts +5 -0
  55. package/dist/board/render/renderers/geo-card-renderer.js +128 -0
  56. package/dist/board/render/renderers/image-card-renderer.d.ts +8 -0
  57. package/dist/board/render/renderers/image-card-renderer.js +138 -0
  58. package/dist/board/render/renderers/note-card-renderer.d.ts +5 -0
  59. package/dist/board/render/renderers/note-card-renderer.js +112 -0
  60. package/dist/board/render/renderers/text-card-renderer.d.ts +7 -0
  61. package/dist/board/render/renderers/text-card-renderer.js +94 -0
  62. package/dist/board/render/renderers/unknown-card-renderer.d.ts +5 -0
  63. package/dist/board/render/renderers/unknown-card-renderer.js +102 -0
  64. package/dist/board/render/renderers/video-card-renderer.d.ts +7 -0
  65. package/dist/board/render/renderers/video-card-renderer.js +146 -0
  66. package/dist/board/render/text-measurement.d.ts +30 -0
  67. package/dist/board/render/text-measurement.js +57 -0
  68. package/dist/board/render/text-resolution.d.ts +16 -0
  69. package/dist/board/render/text-resolution.js +43 -0
  70. package/dist/board/render/themes/board-theme-registry.d.ts +20 -0
  71. package/dist/board/render/themes/board-theme-registry.js +13 -0
  72. package/dist/board/render/themes/clean-theme.d.ts +5 -0
  73. package/dist/board/render/themes/clean-theme.js +102 -0
  74. package/dist/chunks/http.d.ts +10 -40
  75. package/dist/chunks/http.js +26 -4
  76. package/dist/chunks/transport.js +4 -2
  77. package/dist/chunks/websocket.d.ts +832 -21
  78. package/dist/chunks/websocket.js +19 -2
  79. package/dist/http.d.ts +2 -3
  80. package/dist/index.d.ts +100 -5
  81. package/dist/index.js +391 -1
  82. package/dist/protocol/dist/board-constants.d.ts +23 -0
  83. package/dist/protocol/dist/board-constants.js +60 -0
  84. package/dist/protocol/dist/board-document.d.ts +1124 -0
  85. package/dist/protocol/dist/board-document.js +331 -0
  86. package/dist/protocol/dist/board.d.ts +186 -0
  87. package/dist/protocol/dist/board.js +207 -0
  88. package/dist/protocol/dist/index.d.ts +5 -0
  89. package/dist/protocol/dist/index.js +5 -0
  90. package/dist/protocol/dist/provenance.js +12 -0
  91. package/dist/protocol/dist/realtime/board-awareness.d.ts +1 -0
  92. package/dist/protocol/dist/realtime/board-awareness.js +117 -0
  93. package/dist/protocol/dist/realtime/types.d.ts +2 -0
  94. package/package.json +39 -4
  95. package/dist/board.js +0 -2
  96. package/dist/chunks/board.d.ts +0 -2589
package/dist/index.js CHANGED
@@ -3,7 +3,6 @@ import { a as COHUB_SOURCE_HEADER, c as hasRequestSourceIdentity, d as mergeRequ
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";
6
- import { a as createBoardExtensionRegistry, i as compileSequence, n as DEFAULT_BOARD_LIMITS, o as timeline, r as clip, t as BoardExtensionRegistry } from "./chunks/board.js";
7
6
  //#region src/apis/billing.ts
8
7
  var BillingApi = class {
9
8
  transport;
@@ -1267,4 +1266,395 @@ function filterGenerationDeclarationsByPolicy(declarations, policy) {
1267
1266
  });
1268
1267
  }
1269
1268
  //#endregion
1269
+ //#region ../protocol/dist/board-constants.js
1270
+ const DEFAULT_BOARD_RENDER_LIMITS = {
1271
+ particles: 2e4,
1272
+ vertices: 5e5,
1273
+ dynamicVertices: 15e4,
1274
+ drawCalls: 400,
1275
+ filterPasses: 24,
1276
+ renderTexturePixels: 16777216,
1277
+ textureBytes: 512 * 1024 * 1024,
1278
+ bufferBytes: 256 * 1024 * 1024,
1279
+ simulationSteps: 1e5
1280
+ };
1281
+ const BOARD_BUILTIN_CLIP_KINDS = [
1282
+ "motion.keyframes",
1283
+ "motion.path",
1284
+ "draw.reveal",
1285
+ "draw.handwrite",
1286
+ "text.reveal",
1287
+ "effects.particles",
1288
+ "effects.trail",
1289
+ "effects.impact",
1290
+ "effects.flash",
1291
+ "effects.color",
1292
+ "camera.pan",
1293
+ "camera.zoom",
1294
+ "camera.shake"
1295
+ ];
1296
+ const BOARD_BUILTIN_EFFECT_KINDS = ["effects.pulse", "effects.float"];
1297
+ const BOARD_BUILTIN_CAPABILITIES = [...BOARD_BUILTIN_CLIP_KINDS.map((id) => ({
1298
+ kind: "clip",
1299
+ id,
1300
+ version: 1,
1301
+ renderers: ["webgpu", "webgl"]
1302
+ })), ...BOARD_BUILTIN_EFFECT_KINDS.map((id) => ({
1303
+ kind: "effect",
1304
+ id,
1305
+ version: 1,
1306
+ renderers: ["webgpu", "webgl"]
1307
+ }))];
1308
+ //#endregion
1309
+ //#region src/board/animation.ts
1310
+ const ZERO_COST = {
1311
+ particles: 0,
1312
+ vertices: 0,
1313
+ dynamicVertices: 0,
1314
+ drawCalls: 0,
1315
+ filterPasses: 0,
1316
+ renderTexturePixels: 0,
1317
+ textureBytes: 0,
1318
+ bufferBytes: 0,
1319
+ simulationSteps: 0
1320
+ };
1321
+ const DEFAULT_BOARD_LIMITS = DEFAULT_BOARD_RENDER_LIMITS;
1322
+ const BUILTIN_CAPABILITIES = BOARD_BUILTIN_CAPABILITIES;
1323
+ function numericParam(params, key, fallback) {
1324
+ const value = params[key];
1325
+ return typeof value === "number" && Number.isFinite(value) ? value : fallback;
1326
+ }
1327
+ function builtinDefinition(capability) {
1328
+ return {
1329
+ ...capability,
1330
+ validate(params) {
1331
+ const diagnostics = [];
1332
+ if (capability.id === "effects.particles") {
1333
+ const count = params.count;
1334
+ const bounds = params.bounds;
1335
+ if (!Number.isSafeInteger(count) || count < 1 || count > DEFAULT_BOARD_LIMITS.particles) diagnostics.push({
1336
+ severity: "error",
1337
+ code: "INVALID_PARTICLE_COUNT",
1338
+ message: `count must be an integer between 1 and ${DEFAULT_BOARD_LIMITS.particles}`,
1339
+ path: "params.count"
1340
+ });
1341
+ if (!bounds || typeof bounds !== "object" || Array.isArray(bounds)) diagnostics.push({
1342
+ severity: "error",
1343
+ code: "PARTICLE_BOUNDS_REQUIRED",
1344
+ message: "particles require finite bounds",
1345
+ path: "params.bounds"
1346
+ });
1347
+ else {
1348
+ const value = bounds;
1349
+ if (![
1350
+ value.x,
1351
+ value.y,
1352
+ value.width,
1353
+ value.height
1354
+ ].every((item) => typeof item === "number" && Number.isFinite(item)) || value.width <= 0 || value.height <= 0) diagnostics.push({
1355
+ severity: "error",
1356
+ code: "INVALID_PARTICLE_BOUNDS",
1357
+ message: "particle bounds must have a positive finite size",
1358
+ path: "params.bounds"
1359
+ });
1360
+ }
1361
+ }
1362
+ if (capability.id === "motion.path") {
1363
+ const points = params.points;
1364
+ if (!Array.isArray(points) || points.length < 2 || points.length > 1e4) diagnostics.push({
1365
+ severity: "error",
1366
+ code: "INVALID_MOTION_PATH",
1367
+ message: "motion path must contain 2 to 10000 points",
1368
+ path: "params.points"
1369
+ });
1370
+ }
1371
+ return diagnostics;
1372
+ },
1373
+ getBounds(params) {
1374
+ const bounds = params.bounds;
1375
+ if (!bounds || typeof bounds !== "object" || Array.isArray(bounds)) return null;
1376
+ const value = bounds;
1377
+ return [
1378
+ value.x,
1379
+ value.y,
1380
+ value.width,
1381
+ value.height
1382
+ ].every((item) => typeof item === "number" && Number.isFinite(item)) ? value : null;
1383
+ },
1384
+ estimateCost(params) {
1385
+ switch (capability.id) {
1386
+ case "effects.particles": {
1387
+ const particles = Math.max(0, Math.floor(numericParam(params, "count", 0)));
1388
+ return {
1389
+ particles,
1390
+ vertices: particles * 4,
1391
+ dynamicVertices: particles * 4,
1392
+ drawCalls: 1,
1393
+ bufferBytes: particles * 48,
1394
+ simulationSteps: particles
1395
+ };
1396
+ }
1397
+ case "effects.trail": return {
1398
+ vertices: 32,
1399
+ dynamicVertices: 32,
1400
+ drawCalls: 1,
1401
+ bufferBytes: 1024,
1402
+ simulationSteps: 16
1403
+ };
1404
+ case "effects.impact":
1405
+ case "effects.flash": return {
1406
+ vertices: 64,
1407
+ drawCalls: 1
1408
+ };
1409
+ case "effects.color": return {
1410
+ drawCalls: 1,
1411
+ filterPasses: 1
1412
+ };
1413
+ case "draw.reveal":
1414
+ case "draw.handwrite": return {
1415
+ drawCalls: 1,
1416
+ dynamicVertices: 1
1417
+ };
1418
+ default: return {};
1419
+ }
1420
+ }
1421
+ };
1422
+ }
1423
+ function stableHash(value) {
1424
+ let hash = 2166136261;
1425
+ for (let index = 0; index < value.length; index += 1) {
1426
+ hash ^= value.charCodeAt(index);
1427
+ hash = Math.imul(hash, 16777619);
1428
+ }
1429
+ return (hash >>> 0).toString(36).padStart(7, "0");
1430
+ }
1431
+ function stableId(prefix, seed, path) {
1432
+ return `${prefix}_${stableHash(`${seed}:${path}`)}`;
1433
+ }
1434
+ function assertDuration(value, field) {
1435
+ if (!Number.isFinite(value) || value < 0) throw new TypeError(`${field} must be a finite non-negative number`);
1436
+ }
1437
+ const timeline = {
1438
+ clip(clip) {
1439
+ return {
1440
+ type: "clip",
1441
+ clip
1442
+ };
1443
+ },
1444
+ parallel(...children) {
1445
+ return {
1446
+ type: "parallel",
1447
+ children
1448
+ };
1449
+ },
1450
+ sequence(...children) {
1451
+ return {
1452
+ type: "sequence",
1453
+ children
1454
+ };
1455
+ },
1456
+ stagger(each, ...children) {
1457
+ assertDuration(each, "stagger each");
1458
+ return {
1459
+ type: "stagger",
1460
+ each,
1461
+ children
1462
+ };
1463
+ },
1464
+ delay(duration, child) {
1465
+ assertDuration(duration, "delay duration");
1466
+ return {
1467
+ type: "delay",
1468
+ duration,
1469
+ child
1470
+ };
1471
+ },
1472
+ repeat(count, child) {
1473
+ if (!Number.isSafeInteger(count) || count < 1 || count > 1e3) throw new TypeError("repeat count must be an integer between 1 and 1000");
1474
+ return {
1475
+ type: "repeat",
1476
+ count,
1477
+ child
1478
+ };
1479
+ }
1480
+ };
1481
+ function clip(input) {
1482
+ assertDuration(input.duration, "clip duration");
1483
+ if (input.duration === 0) throw new TypeError("clip duration must be greater than zero");
1484
+ return timeline.clip({
1485
+ id: input.id,
1486
+ kind: input.kind,
1487
+ kindVersion: input.kindVersion ?? 1,
1488
+ target: input.target,
1489
+ duration: input.duration,
1490
+ layer: input.layer ?? "content",
1491
+ fill: input.fill ?? "none",
1492
+ easing: input.easing ?? "linear",
1493
+ params: input.params ?? {},
1494
+ keyframes: input.keyframes ?? [],
1495
+ assetRefs: input.assetRefs ?? [],
1496
+ seed: input.seed,
1497
+ metadata: input.metadata ?? {}
1498
+ });
1499
+ }
1500
+ function flatten(input, offset, sequenceSeed, path) {
1501
+ if (input.type === "clip") {
1502
+ const clipSeed = input.clip.seed ?? `${sequenceSeed}:${path}`;
1503
+ return {
1504
+ duration: input.clip.duration,
1505
+ clips: [{
1506
+ ...input.clip,
1507
+ id: input.clip.id ?? stableId("clip", sequenceSeed, path),
1508
+ start: offset,
1509
+ seed: clipSeed
1510
+ }]
1511
+ };
1512
+ }
1513
+ if (input.type === "delay") {
1514
+ const nested = flatten(input.child, offset + input.duration, sequenceSeed, `${path}.child`);
1515
+ return {
1516
+ duration: input.duration + nested.duration,
1517
+ clips: nested.clips
1518
+ };
1519
+ }
1520
+ if (input.type === "repeat") {
1521
+ const clips = [];
1522
+ let cursor = offset;
1523
+ let total = 0;
1524
+ for (let index = 0; index < input.count; index += 1) {
1525
+ const nested = flatten(input.child, cursor, sequenceSeed, `${path}.${index}`);
1526
+ clips.push(...nested.clips);
1527
+ cursor += nested.duration;
1528
+ total += nested.duration;
1529
+ }
1530
+ return {
1531
+ duration: total,
1532
+ clips
1533
+ };
1534
+ }
1535
+ const clips = [];
1536
+ let duration = 0;
1537
+ for (const [index, child] of input.children.entries()) {
1538
+ const childOffset = input.type === "sequence" ? duration : input.type === "stagger" ? input.each * index : 0;
1539
+ const nested = flatten(child, offset + childOffset, sequenceSeed, `${path}.${index}`);
1540
+ clips.push(...nested.clips);
1541
+ duration = input.type === "sequence" ? duration + nested.duration : Math.max(duration, childOffset + nested.duration);
1542
+ }
1543
+ return {
1544
+ duration,
1545
+ clips
1546
+ };
1547
+ }
1548
+ function compileSequence(input) {
1549
+ const flattened = flatten(input.timeline, 0, input.seed, "root");
1550
+ flattened.clips.sort((left, right) => left.start - right.start || left.id.localeCompare(right.id));
1551
+ const refs = /* @__PURE__ */ new Map();
1552
+ for (const item of flattened.clips) for (const ref of item.assetRefs) refs.set(`${ref.type}:${ref.ref}:${ref.digest ?? ""}`, ref);
1553
+ return {
1554
+ sequence: {
1555
+ id: input.id,
1556
+ name: input.name,
1557
+ duration: flattened.duration,
1558
+ seed: input.seed,
1559
+ restPose: input.restPose ?? {},
1560
+ metadata: input.metadata ?? {}
1561
+ },
1562
+ clips: flattened.clips,
1563
+ assetRefs: [...refs.values()]
1564
+ };
1565
+ }
1566
+ function addCost(target, source) {
1567
+ for (const key of Object.keys(target)) target[key] += source[key] ?? 0;
1568
+ }
1569
+ var BoardExtensionRegistry = class {
1570
+ #extensions = /* @__PURE__ */ new Map();
1571
+ #presets = /* @__PURE__ */ new Map();
1572
+ register(definition) {
1573
+ const key = `${definition.kind}:${definition.id}@${definition.version}`;
1574
+ const target = definition.kind === "preset" ? this.#presets : this.#extensions;
1575
+ if (target.has(key)) throw new Error(`Board extension is already registered: ${key}`);
1576
+ target.set(key, definition);
1577
+ return this;
1578
+ }
1579
+ capabilities() {
1580
+ const extensions = [...this.#extensions.values()].map(({ validate: _validate, getBounds: _bounds, getAssetRefs: _refs, estimateCost: _cost, ...definition }) => definition);
1581
+ const presets = [...this.#presets.values()].map(({ compile: _compile, ...definition }) => definition);
1582
+ return [...extensions, ...presets];
1583
+ }
1584
+ compilePreset(id, version, params) {
1585
+ const preset = this.#presets.get(`preset:${id}@${version}`);
1586
+ if (!preset) throw new Error(`Unknown Board preset: ${id}@${version}`);
1587
+ return preset.compile(params);
1588
+ }
1589
+ validate(input) {
1590
+ const diagnostics = [];
1591
+ const events = [];
1592
+ const profile = input.profile ?? "high";
1593
+ const persistentCost = { ...ZERO_COST };
1594
+ for (const [index, effect] of (input.effects ?? []).entries()) {
1595
+ const definition = this.#extensions.get(`effect:${effect.kind}@${effect.kindVersion}`);
1596
+ if (!definition) {
1597
+ diagnostics.push({
1598
+ severity: "warning",
1599
+ code: "UNKNOWN_EFFECT",
1600
+ message: `No renderer is registered for ${effect.kind}@${effect.kindVersion}`,
1601
+ path: `effects.${index}`
1602
+ });
1603
+ continue;
1604
+ }
1605
+ diagnostics.push(...definition.validate?.(effect.params) ?? []);
1606
+ addCost(persistentCost, definition.estimateCost(effect.params, profile));
1607
+ }
1608
+ for (const [index, clip] of input.clips.entries()) {
1609
+ const definition = this.#extensions.get(`clip:${clip.kind}@${clip.kindVersion}`);
1610
+ if (!definition) {
1611
+ diagnostics.push({
1612
+ severity: "warning",
1613
+ code: "UNKNOWN_CLIP",
1614
+ message: `No renderer is registered for ${clip.kind}@${clip.kindVersion}`,
1615
+ path: `clips.${index}`
1616
+ });
1617
+ continue;
1618
+ }
1619
+ diagnostics.push(...definition.validate?.(clip.params) ?? []);
1620
+ const cost = { ...ZERO_COST };
1621
+ addCost(cost, definition.estimateCost(clip.params, profile));
1622
+ events.push({
1623
+ at: clip.start,
1624
+ direction: 1,
1625
+ cost
1626
+ }, {
1627
+ at: clip.start + clip.duration,
1628
+ direction: -1,
1629
+ cost
1630
+ });
1631
+ }
1632
+ events.sort((left, right) => left.at - right.at || left.direction - right.direction);
1633
+ const current = { ...persistentCost };
1634
+ const peak = { ...persistentCost };
1635
+ for (const event of events) for (const key of Object.keys(current)) {
1636
+ current[key] += event.cost[key] * event.direction;
1637
+ peak[key] = Math.max(peak[key], current[key]);
1638
+ }
1639
+ const limits = input.limits ?? DEFAULT_BOARD_LIMITS;
1640
+ for (const key of Object.keys(limits)) if (peak[key] > limits[key]) diagnostics.push({
1641
+ severity: "warning",
1642
+ code: "RENDER_BUDGET_EXCEEDED",
1643
+ message: `${key} peaks at ${peak[key]}, above ${limits[key]}`,
1644
+ path: key,
1645
+ adaptation: { quality: "lower" }
1646
+ });
1647
+ return {
1648
+ valid: !diagnostics.some((item) => item.severity === "error"),
1649
+ diagnostics,
1650
+ peakCost: peak
1651
+ };
1652
+ }
1653
+ };
1654
+ function createBoardExtensionRegistry(input = {}) {
1655
+ const registry = new BoardExtensionRegistry();
1656
+ if (input.builtins !== false) for (const capability of BUILTIN_CAPABILITIES) registry.register(builtinDefinition(capability));
1657
+ return registry;
1658
+ }
1659
+ //#endregion
1270
1660
  export { BILLING_ACCESS_BLOCKED_ERROR_CODE, BillingApi, BoardClient, BoardExtensionRegistry, 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, clearGrantedWorkScopes, clip, compileSequence, createBoardExtensionRegistry, createCohubClient, createHttpClient, createSessionGenerationStreamClient, createSessionPatchReducer, createSlugWorkIdResolver, createVoiceInputClient, createWebsocketClient, createWorkBridgeCore, createWorkRuntime, decodeGenerationPolicy, encodeGenerationPolicy, extractBillingPayload, filterGenerationDeclarationsByPolicy, findGenerationModelPolicy, getAllowedGenerationModelIds, hasGrantedWorkScopes, hasRequestSourceIdentity, isBillingAccessBlockedCode, isBillingAccessBlockedError, isFeatureNotEntitledError, isHttpErrorCode, isRequestSourceEmpty, isRequestSourceUuid, joinApiUrl, mergeRequestSourceIntoMeta, normalizeBaseUrl, normalizeGenerationPolicy, normalizeRequestSource, normalizeVoiceInputWebsocketUrl, normalizeWebsocketUrl, parseAssistantMessageCommit, parseGenerationPolicyFromEnv, parseRequestSourceFromHeaders, readRequestSourceFromEnv, requestSourceToHeaders, resolveApiBaseUrl, resolveCohubEnvironment, resolveRequestSourceChannel, resolveVoiceInputWebsocketUrl, resolveWebsocketUrl, resolveWorkTransport, sanitizeAccessToken, setGrantedWorkScopes, timeline };
@@ -0,0 +1,23 @@
1
+ //#region ../protocol/dist/board-constants.d.ts
2
+ type BoardRenderCost = {
3
+ particles: number;
4
+ vertices: number;
5
+ dynamicVertices: number;
6
+ drawCalls: number;
7
+ filterPasses: number;
8
+ renderTexturePixels: number;
9
+ textureBytes: number;
10
+ bufferBytes: number;
11
+ simulationSteps: number;
12
+ };
13
+ type BoardCapability = {
14
+ kind: "preset" | "clip" | "effect" | "shader";
15
+ id: string;
16
+ version: number;
17
+ digest?: string;
18
+ renderers?: Array<"webgpu" | "webgl">;
19
+ fallbackId?: string;
20
+ schema?: Record<string, unknown>;
21
+ };
22
+ //#endregion
23
+ export { BoardCapability, BoardRenderCost };
@@ -0,0 +1,60 @@
1
+ //#region ../protocol/dist/board-constants.js
2
+ const DEFAULT_BOARD_RENDER_LIMITS = {
3
+ particles: 2e4,
4
+ vertices: 5e5,
5
+ dynamicVertices: 15e4,
6
+ drawCalls: 400,
7
+ filterPasses: 24,
8
+ renderTexturePixels: 16777216,
9
+ textureBytes: 512 * 1024 * 1024,
10
+ bufferBytes: 256 * 1024 * 1024,
11
+ simulationSteps: 1e5
12
+ };
13
+ const BOARD_BUILTIN_CLIP_KINDS = [
14
+ "motion.keyframes",
15
+ "motion.path",
16
+ "draw.reveal",
17
+ "draw.handwrite",
18
+ "text.reveal",
19
+ "effects.particles",
20
+ "effects.trail",
21
+ "effects.impact",
22
+ "effects.flash",
23
+ "effects.color",
24
+ "camera.pan",
25
+ "camera.zoom",
26
+ "camera.shake"
27
+ ];
28
+ const BOARD_BUILTIN_EFFECT_KINDS = ["effects.pulse", "effects.float"];
29
+ /**
30
+ * World-space typography for board text.
31
+ *
32
+ * These live here rather than beside the renderer because the document schema
33
+ * constrains persisted font sizes with them, and the schema must not depend on
34
+ * anything that draws.
35
+ */
36
+ const BOARD_TEXT_FONT_FAMILY = "Geist";
37
+ /**
38
+ * Font stacks used by every board renderer.
39
+ *
40
+ * A bare "Geist" would render CJK (and anything else outside the Latin subset)
41
+ * as missing-glyph boxes, because the shipped webfont is Latin-only. The stack
42
+ * mirrors the web `--font-sans` / `--font-mono` tokens and adds the common CJK
43
+ * families, so both the browser and a headless export fall back to a real face
44
+ * instead of tofu.
45
+ */
46
+ const BOARD_FONT_STACK = "\"Geist\", system-ui, -apple-system, \"Noto Sans CJK SC\", \"Noto Sans SC\", \"PingFang SC\", \"Microsoft YaHei\", sans-serif";
47
+ const BOARD_MONO_FONT_STACK = "\"Geist Mono\", \"Fira Code\", ui-monospace, \"Noto Sans Mono CJK SC\", monospace";
48
+ const BOARD_BUILTIN_CAPABILITIES = [...BOARD_BUILTIN_CLIP_KINDS.map((id) => ({
49
+ kind: "clip",
50
+ id,
51
+ version: 1,
52
+ renderers: ["webgpu", "webgl"]
53
+ })), ...BOARD_BUILTIN_EFFECT_KINDS.map((id) => ({
54
+ kind: "effect",
55
+ id,
56
+ version: 1,
57
+ renderers: ["webgpu", "webgl"]
58
+ }))];
59
+ //#endregion
60
+ export { BOARD_BUILTIN_CAPABILITIES, BOARD_BUILTIN_CLIP_KINDS, BOARD_BUILTIN_EFFECT_KINDS, BOARD_FONT_STACK, BOARD_MONO_FONT_STACK, BOARD_TEXT_FONT_FAMILY, DEFAULT_BOARD_RENDER_LIMITS };