@neta-art/cohub 12.1.1 → 12.3.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 (134) hide show
  1. package/README.md +85 -8
  2. package/dist/board/editor/clipboard.js +1 -1
  3. package/dist/board/editor/creation.js +1 -1
  4. package/dist/board/editor/document.d.ts +3 -1
  5. package/dist/board/editor/document.js +8 -6
  6. package/dist/board/editor/editor.d.ts +8 -3
  7. package/dist/board/editor/editor.js +8 -2
  8. package/dist/board/editor/index.d.ts +3 -3
  9. package/dist/board/editor/index.js +2 -2
  10. package/dist/board/editor/interaction.d.ts +23 -2
  11. package/dist/board/editor/interaction.js +93 -4
  12. package/dist/board/editor/query.d.ts +1 -1
  13. package/dist/board/editor/query.js +3 -7
  14. package/dist/board/editor/selection.js +1 -1
  15. package/dist/board/editor/snapshots.js +5 -57
  16. package/dist/board/editor/tool.d.ts +4 -1
  17. package/dist/board/editor/tool.js +6 -1
  18. package/dist/board/export/index.d.ts +2 -2
  19. package/dist/board/export/index.js +1 -1
  20. package/dist/board/export/node/fonts.js +4 -0
  21. package/dist/board/export/node/index.d.ts +2 -0
  22. package/dist/board/export/node/index.js +8 -1
  23. package/dist/board/export/node/scripts.js +1 -1
  24. package/dist/board/export/scene.d.ts +2 -2
  25. package/dist/board/export/scene.js +2 -2
  26. package/dist/board/model/asset-key.d.ts +24 -0
  27. package/dist/board/model/asset-key.js +104 -0
  28. package/dist/board/model/export-assets.d.ts +7 -3
  29. package/dist/board/model/export-assets.js +34 -13
  30. package/dist/board/model/index.d.ts +9 -7
  31. package/dist/board/model/index.js +22 -20
  32. package/dist/board/model/items/create.js +3 -3
  33. package/dist/board/model/items/definition.d.ts +9 -1
  34. package/dist/board/model/items/index.d.ts +2 -2
  35. package/dist/board/model/items/registry.d.ts +2 -1
  36. package/dist/board/model/items/registry.js +1 -0
  37. package/dist/board/model/media-sizes.d.ts +28 -0
  38. package/dist/board/model/media-sizes.js +64 -0
  39. package/dist/board/model/palette.d.ts +1 -0
  40. package/dist/board/model/palette.js +20 -130
  41. package/dist/board/model/sampling.js +1 -1
  42. package/dist/board/model/text-metrics.d.ts +28 -3
  43. package/dist/board/model/text-metrics.js +36 -2
  44. package/dist/board/model/themes.d.ts +495 -0
  45. package/dist/board/model/themes.js +500 -0
  46. package/dist/board/render/card-tag.js +2 -2
  47. package/dist/board/render/index.d.ts +11 -7
  48. package/dist/board/render/index.js +9 -5
  49. package/dist/board/render/labels.d.ts +15 -0
  50. package/dist/board/render/labels.js +14 -0
  51. package/dist/board/render/lod.d.ts +30 -0
  52. package/dist/board/render/lod.js +33 -0
  53. package/dist/board/render/media-interaction.d.ts +5 -2
  54. package/dist/board/render/media-interaction.js +15 -3
  55. package/dist/board/render/palette.js +2 -25
  56. package/dist/board/render/renderers/arrow-card-renderer.js +7 -5
  57. package/dist/board/render/renderers/audio-card-renderer.js +3 -2
  58. package/dist/board/render/renderers/board-renderer-registry.d.ts +22 -1
  59. package/dist/board/render/renderers/board-renderer-registry.js +9 -4
  60. package/dist/board/render/renderers/custom-card-renderer.js +5 -5
  61. package/dist/board/render/renderers/draw-card-renderer.js +1 -1
  62. package/dist/board/render/renderers/far-plate.d.ts +14 -1
  63. package/dist/board/render/renderers/far-plate.js +31 -8
  64. package/dist/board/render/renderers/file-card-renderer.js +49 -31
  65. package/dist/board/render/renderers/frame-card-renderer.js +9 -3
  66. package/dist/board/render/renderers/image-card-renderer.js +34 -8
  67. package/dist/board/render/renderers/model-card-renderer.js +6 -6
  68. package/dist/board/render/renderers/shape-card-renderer.js +25 -24
  69. package/dist/board/render/renderers/task-card-renderer.js +9 -10
  70. package/dist/board/render/renderers/text-card-renderer.js +86 -41
  71. package/dist/board/render/renderers/video-card-renderer.js +5 -4
  72. package/dist/board/render/script-export.js +1 -1
  73. package/dist/board/render/script-host.js +3 -3
  74. package/dist/board/render/style.d.ts +8 -2
  75. package/dist/board/render/style.js +8 -2
  76. package/dist/board/render/surface.d.ts +5 -0
  77. package/dist/board/render/surface.js +13 -3
  78. package/dist/board/render/text-edit.d.ts +32 -0
  79. package/dist/board/render/text-edit.js +134 -0
  80. package/dist/board/render/text-fit.d.ts +1 -3
  81. package/dist/board/render/text-fit.js +6 -49
  82. package/dist/board/render/text-measurement.d.ts +25 -1
  83. package/dist/board/render/text-measurement.js +157 -19
  84. package/dist/board/render/text-resolution.d.ts +1 -6
  85. package/dist/board/render/text-resolution.js +1 -10
  86. package/dist/board/render/theme.d.ts +15 -0
  87. package/dist/board/render/theme.js +15 -0
  88. package/dist/board/replica/index.d.ts +4 -2
  89. package/dist/board/replica/index.js +28 -17
  90. package/dist/board/replica/indexeddb.d.ts +16 -0
  91. package/dist/board/replica/indexeddb.js +155 -0
  92. package/dist/board/stage/assets.d.ts +28 -5
  93. package/dist/board/stage/assets.js +293 -102
  94. package/dist/board/stage/bench.d.ts +35 -0
  95. package/dist/board/stage/bench.js +153 -0
  96. package/dist/board/stage/device.d.ts +41 -0
  97. package/dist/board/stage/device.js +62 -0
  98. package/dist/board/stage/frame-budget.d.ts +19 -0
  99. package/dist/board/stage/frame-budget.js +69 -0
  100. package/dist/board/stage/idle.d.ts +4 -0
  101. package/dist/board/stage/idle.js +26 -0
  102. package/dist/board/stage/index.d.ts +11 -7
  103. package/dist/board/stage/index.js +7 -4
  104. package/dist/board/stage/lru.d.ts +13 -9
  105. package/dist/board/stage/lru.js +38 -20
  106. package/dist/board/stage/presses.d.ts +21 -0
  107. package/dist/board/stage/presses.js +66 -0
  108. package/dist/board/stage/scene.d.ts +15 -1
  109. package/dist/board/stage/scene.js +248 -141
  110. package/dist/board/stage/stage.d.ts +28 -2
  111. package/dist/board/stage/stage.js +404 -112
  112. package/dist/board/stage/texture-pool.d.ts +10 -1
  113. package/dist/board/stage/texture-pool.js +72 -2
  114. package/dist/chunks/environment.d.ts +6 -0
  115. package/dist/chunks/http.d.ts +9 -1
  116. package/dist/chunks/http.js +791 -4
  117. package/dist/index.d.ts +52 -1
  118. package/dist/index.js +202 -862
  119. package/dist/media.d.ts +3 -27
  120. package/dist/media.js +3 -82
  121. package/dist/protocol/dist/board-constants.js +3 -3
  122. package/dist/protocol/dist/board-layout.d.ts +17 -3
  123. package/dist/protocol/dist/board-layout.js +68 -11
  124. package/dist/protocol/dist/board-model.d.ts +15 -1
  125. package/dist/protocol/dist/board-model.js +12 -2
  126. package/dist/protocol/dist/board-patch.js +1 -1
  127. package/dist/protocol/dist/board-schema.d.ts +2 -1
  128. package/dist/protocol/dist/board-schema.js +4 -1
  129. package/dist/protocol/dist/core/media.d.ts +35 -1
  130. package/dist/protocol/dist/core/media.js +127 -1
  131. package/dist/protocol/dist/index.d.ts +3 -3
  132. package/package.json +4 -2
  133. package/dist/board/model/image-key.d.ts +0 -9
  134. package/dist/board/model/image-key.js +0 -33
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { c as AppRtcError, i as WorkRoom, n as AppRoom, o as AppRoomRtc, r as WorkRealtimeApi, s as AppRtcChannel, t as AppRealtimeApi } from "./chunks/app-realtime.js";
2
- import { $ as isTerminalDesktopCommandStatus, A as BoardClient, B as CronJobsApi, C as SessionPatchReducer, D as connectDisplay, E as DisplayConnection, F as PublicAssetsApi, G as DESKTOP_COMMAND_OPEN_TIMEOUT_MS, H as DESKTOP_COMMAND_ACCEPT_TIMEOUT_MS, I as SkillsApi, J as DESKTOP_COMMAND_SETTLEMENT_GRACE_SECONDS, K as DESKTOP_COMMAND_PAYLOAD_MAX_BYTES, L as PromptsApi, M as SessionAccessApi, N as ReferencesApi, P as SearchApi, Q as isDesktopCallMethod, R as ModelsApi, S as parseAssistantMessageCommit, T as SpaceDisplaysApi, U as DESKTOP_COMMAND_DEFAULT_TIMEOUT_MS, V as ChannelsApi, W as DESKTOP_COMMAND_MAX_TIMEOUT_MS, X as DESKTOP_COMMAND_VERSION, Y as DESKTOP_COMMAND_TERMINAL_TTL_SECONDS, Z as defaultDesktopCommandTimeoutMs, _ as PublicInviteApi, a as WorkCommerceApi, b as SessionGenerationStreamClient, c as AppsApi, ct as normalizeDisplayPoint, d as UserApi, et as parseDesktopCommand, f as TasksApi, g as SpacesApi, h as SpaceWebhooksApi, i as AppCommerceApi, it as DISPLAY_ELEMENT_REF_PATTERN, j as ensureRealtimeConnected, l as ReferralsApi, lt as splitDisplayText, m as SpacePublicFilesApi, n as createHttpClient, nt as resolveOpenSurface, o as DesktopCommandsApi, ot as DISPLAY_INPUT_MAX_TEXT, p as SpaceClient, q as DESKTOP_COMMAND_PENDING_TTL_SECONDS, r as RoomsApi, rt as NAVIGATION_ERROR_MESSAGE_MAX_LENGTH, s as UiCommandsApi, st as DISPLAY_SYSTEM_ACTIONS, t as CohubHttpClient, tt as parseDesktopCommandId, u as UsersApi, v as buildSpaceInvitePath, w as createSessionPatchReducer, x as createSessionGenerationStreamClient, y as buildSpacePath, z as GenerationsApi } from "./chunks/http.js";
2
+ import { $ as isTerminalDesktopCommandStatus, A as BoardClient, B as CronJobsApi, C as SessionPatchReducer, Ct as isBuiltinItemType, D as connectDisplay, Dt as boardDefaultSize, E as DisplayConnection, F as PublicAssetsApi, G as DESKTOP_COMMAND_OPEN_TIMEOUT_MS, H as DESKTOP_COMMAND_ACCEPT_TIMEOUT_MS, I as SkillsApi, J as DESKTOP_COMMAND_SETTLEMENT_GRACE_SECONDS, K as DESKTOP_COMMAND_PAYLOAD_MAX_BYTES, L as PromptsApi, M as SessionAccessApi, N as ReferencesApi, P as SearchApi, Q as isDesktopCallMethod, R as ModelsApi, S as parseAssistantMessageCommit, St as boardItemSchema, T as SpaceDisplaysApi, Tt as normalizeBoardRemoteUrl, U as DESKTOP_COMMAND_DEFAULT_TIMEOUT_MS, V as ChannelsApi, W as DESKTOP_COMMAND_MAX_TIMEOUT_MS, X as DESKTOP_COMMAND_VERSION, Y as DESKTOP_COMMAND_TERMINAL_TTL_SECONDS, Z as defaultDesktopCommandTimeoutMs, _ as PublicInviteApi, _t as BoardColorSchema, a as WorkCommerceApi, b as SessionGenerationStreamClient, bt as BoardTrackSchema, c as AppsApi, ct as normalizeDisplayPoint, d as UserApi, dt as BOARD_MIME_TYPE, et as parseDesktopCommand, f as TasksApi, ft as BOARD_CAMERA_TARGET, g as SpacesApi, gt as BoardAnimationSchema, h as SpaceWebhooksApi, ht as BoardAnimationHeaderSchema, i as AppCommerceApi, it as DISPLAY_ELEMENT_REF_PATTERN, j as ensureRealtimeConnected, l as ReferralsApi, lt as splitDisplayText, m as SpacePublicFilesApi, mt as BOARD_ITEM_TYPES, n as createHttpClient, nt as resolveOpenSurface, o as DesktopCommandsApi, ot as DISPLAY_INPUT_MAX_TEXT, p as SpaceClient, pt as BOARD_COLOR_TOKENS, q as DESKTOP_COMMAND_PENDING_TTL_SECONDS, r as RoomsApi, rt as NAVIGATION_ERROR_MESSAGE_MAX_LENGTH, s as UiCommandsApi, st as DISPLAY_SYSTEM_ACTIONS, t as CohubHttpClient, tt as parseDesktopCommandId, u as UsersApi, ut as BOARD_EXTENSION, v as buildSpaceInvitePath, vt as BoardPatchSchema, w as createSessionPatchReducer, wt as parseBoardItem, x as createSessionGenerationStreamClient, xt as BoardVec2Schema, y as buildSpacePath, yt as BoardSettingsSchema, z as GenerationsApi } from "./chunks/http.js";
3
3
  import { A as isRequestSourceClientId, B as isUuidLike, D as COHUB_SOURCE_HEADER_NAMES, E as COHUB_SOURCE_HEADER, F as parseRequestSourceFromHeaders, I as readRequestSourceFromEnv, L as requestSourceToHeaders, M as isRequestSourceUuid, N as mergeRequestSourceIntoMeta, O as REQUEST_SOURCE_VIA_MAX_LENGTH, P as normalizeRequestSource, R as resolveRequestSourceChannel, V as isUuidOrShortUuid, a as isBillingAccessBlockedError, c as HttpError, d as matchesUnauthorizedErrorToken, f as sanitizeAccessToken, i as isBillingAccessBlockedCode, j as isRequestSourceEmpty, k as hasRequestSourceIdentity, l as HttpTransport, n as FEATURE_NOT_ENTITLED_ERROR_CODE, o as isFeatureNotEntitledError, r as extractBillingPayload, s as isHttpErrorCode, t as BILLING_ACCESS_BLOCKED_ERROR_CODE, u as joinApiUrl, z as isUuid } from "./chunks/http-error.js";
4
4
  import { a as normalizeWebsocketUrl, c as resolveExecutionAppId, d as resolveWebBaseUrl, f as resolveWebsocketUrl, g as scopeListHasPermission, h as isUserLevelPermission, i as normalizeVoiceInputWebsocketUrl, l as resolveExecutionToken, m as USER_LEVEL_PERMISSIONS, n as getCohubContext, o as resolveApiBaseUrl, p as PERMISSIONS, r as normalizeBaseUrl, s as resolveCohubEnvironment, t as COHUB_ENVIRONMENTS, u as resolveVoiceInputWebsocketUrl } from "./chunks/environment.js";
5
5
  import { WebsocketClient, createWebsocketClient } from "./websocket.js";
@@ -72,6 +72,69 @@ const appAuthorizationResultSchema = z.discriminatedUnion("status", [
72
72
  code: z.string()
73
73
  })
74
74
  ]);
75
+ //#endregion
76
+ //#region ../protocol/dist/attachments.js
77
+ const escapeAttachmentPath = (path) => path.replace(/[\r\n`]/g, "_");
78
+ const escapeAttachmentUrl = (url) => url.replace(/[\r\n`]/g, "_");
79
+ function formatVisibleLines(range) {
80
+ if (!range) return "";
81
+ const start = Math.max(1, Math.floor(range.start));
82
+ const end = Math.max(start, Math.floor(range.end));
83
+ return start === end ? `L${start}` : `L${start}-${end}`;
84
+ }
85
+ function formatVisibleRect(rect) {
86
+ if (!rect) return "";
87
+ return `view ${Math.round(rect.width)}×${Math.round(rect.height)} at (${Math.round(rect.x)}, ${Math.round(rect.y)})`;
88
+ }
89
+ function escapeViewportLabel(value) {
90
+ return value.replace(/[\r\n`]/g, "_").trim();
91
+ }
92
+ function formatSelectedNodes(nodes) {
93
+ if (!nodes || nodes.length === 0) return "";
94
+ return `selected: ${nodes.map((node) => {
95
+ return (node.title ? escapeViewportLabel(node.title) : "") || escapeViewportLabel(node.id);
96
+ }).join(", ")}`;
97
+ }
98
+ function formatViewportContextLine(context) {
99
+ if (context.kind === "file") {
100
+ const lines = formatVisibleLines(context.visibleLines);
101
+ const suffix = lines ? ` (${lines})` : "";
102
+ return `- file: \`${escapeAttachmentPath(context.path)}\`${suffix}`;
103
+ }
104
+ if (context.kind === "board") {
105
+ const details = [
106
+ ...context.boardId ? [`id: ${escapeViewportLabel(context.boardId)}`] : [],
107
+ formatSelectedNodes(context.selectedNodes),
108
+ formatVisibleRect(context.visibleRect)
109
+ ].filter(Boolean);
110
+ const suffix = details.length > 0 ? ` (${details.join("; ")})` : "";
111
+ return `- board: \`${escapeAttachmentPath(context.path)}\`${suffix}`;
112
+ }
113
+ if (context.kind === "app") {
114
+ const label = escapeViewportLabel(context.label);
115
+ const content = context.content.replace(/\r\n?/g, "\n").trim();
116
+ return `- app: \`${escapeAttachmentPath(context.appId)}\` (${label})\n${content}`;
117
+ }
118
+ const url = context.url?.trim();
119
+ const suffix = url ? ` (${escapeAttachmentUrl(url)})` : "";
120
+ return `- port: \`${escapeAttachmentPath(context.port)}\`${suffix}`;
121
+ }
122
+ function buildViewportReferencesText(contexts) {
123
+ if (contexts.length === 0) return "";
124
+ return ["Viewport:", ...contexts.map(formatViewportContextLine)].join("\n");
125
+ }
126
+ function buildViewportContentBlock(contexts) {
127
+ const text = buildViewportReferencesText(contexts);
128
+ if (!text) return null;
129
+ return {
130
+ type: "text",
131
+ text,
132
+ _meta: {
133
+ attachmentKind: "viewport",
134
+ viewports: contexts
135
+ }
136
+ };
137
+ }
75
138
  const GiB = 1073741824;
76
139
  /** Maximum size of a single uploaded file. */
77
140
  const UPLOAD_MAX_FILE_BYTES = 2 * GiB;
@@ -118,737 +181,6 @@ function batchUploadEntries(entries, sizeOf, options = {}) {
118
181
  if (batch.length > 0) batches.push(batch);
119
182
  return batches;
120
183
  }
121
- const BOARD_DEFAULT_ITEM_SIZE = {
122
- width: 240,
123
- height: 160
124
- };
125
- const BOARD_DEFAULT_SIZES = {
126
- frame: {
127
- width: 480,
128
- height: 320
129
- },
130
- shape: {
131
- width: 200,
132
- height: 140
133
- },
134
- image: {
135
- width: 480,
136
- height: 270
137
- },
138
- video: {
139
- width: 480,
140
- height: 270
141
- },
142
- audio: {
143
- width: 320,
144
- height: 112
145
- },
146
- file: {
147
- width: 260,
148
- height: 132
149
- },
150
- task: {
151
- width: 480,
152
- height: 270
153
- },
154
- effect: {
155
- width: 240,
156
- height: 240
157
- },
158
- custom: {
159
- width: 480,
160
- height: 320
161
- }
162
- };
163
- function boardDefaultSize(type) {
164
- return { ...Object.hasOwn(BOARD_DEFAULT_SIZES, type) ? BOARD_DEFAULT_SIZES[type] : BOARD_DEFAULT_ITEM_SIZE };
165
- }
166
- //#endregion
167
- //#region ../protocol/dist/board-url.js
168
- const BOARD_REMOTE_URL_MAX_LENGTH = 4096;
169
- function parseIpv4(host) {
170
- const parts = host.split(".").map(Number);
171
- return parts.length === 4 && parts.every((part) => Number.isInteger(part) && part >= 0 && part <= 255) ? parts : null;
172
- }
173
- function isBlockedIpv4(host) {
174
- const parts = parseIpv4(host);
175
- if (!parts) return false;
176
- const [first, second, third] = parts;
177
- if (first === 0 || first === 10 || first === 127) return true;
178
- if (first === 100 && second >= 64 && second <= 127) return true;
179
- if (first === 169 && second === 254) return true;
180
- if (first === 172 && second >= 16 && second <= 31) return true;
181
- if (first === 192 && second === 168) return true;
182
- if (first === 192 && second === 0 && (third === 0 || third === 2)) return true;
183
- if (first === 192 && second === 88 && third === 99) return true;
184
- if (first === 198 && (second === 18 || second === 19)) return true;
185
- if (first === 198 && second === 51 && third === 100) return true;
186
- if (first === 203 && second === 0 && third === 113) return true;
187
- return first >= 224;
188
- }
189
- function expandIpv6(host) {
190
- const [head, tail, extra] = host.toLowerCase().split("::");
191
- if (extra !== void 0) return null;
192
- const headParts = head ? head.split(":").filter(Boolean) : [];
193
- const tailParts = tail ? tail.split(":").filter(Boolean) : [];
194
- const missing = 8 - headParts.length - tailParts.length;
195
- if (missing < 0 || tail === void 0 && missing !== 0) return null;
196
- const parts = [
197
- ...headParts,
198
- ...Array.from({ length: missing }, () => "0"),
199
- ...tailParts
200
- ];
201
- if (parts.length !== 8 || parts.some((part) => !/^[0-9a-f]{1,4}$/.test(part))) return null;
202
- return parts.map((part) => part.padStart(4, "0"));
203
- }
204
- function isBlockedIpv6(host) {
205
- const parts = expandIpv6(host);
206
- if (!parts) return true;
207
- if (parts.every((part) => part === "0000")) return true;
208
- if (parts.slice(0, 7).every((part) => part === "0000") && parts[7] === "0001") return true;
209
- if (parts.slice(0, 5).every((part) => part === "0000") && parts[5] === "ffff") {
210
- const high = Number.parseInt(parts[6] ?? "0", 16);
211
- const low = Number.parseInt(parts[7] ?? "0", 16);
212
- return isBlockedIpv4(`${high >> 8}.${high & 255}.${low >> 8}.${low & 255}`);
213
- }
214
- if (parts.slice(0, 6).every((part) => part === "0000")) return true;
215
- const first = Number.parseInt(parts[0] ?? "0", 16);
216
- if ((first & 65024) === 64512) return true;
217
- if ((first & 65472) === 65152 || (first & 65472) === 65216) return true;
218
- if ((first & 65280) === 65280) return true;
219
- return parts[0] === "2001" && parts[1] === "0db8";
220
- }
221
- function isPublicBoardRemoteAddress(value) {
222
- const address = value.toLowerCase().replace(/^\[|\]$/g, "").replace(/\.$/, "");
223
- if (parseIpv4(address)) return !isBlockedIpv4(address);
224
- return address.includes(":") && !isBlockedIpv6(address);
225
- }
226
- function isBlockedHost(hostname) {
227
- const host = hostname.toLowerCase().replace(/^\[|\]$/g, "").replace(/\.$/, "");
228
- if (host === "localhost" || host.endsWith(".localhost") || host.endsWith(".local") || host.endsWith(".internal")) return true;
229
- if (parseIpv4(host) || host.includes(":")) return !isPublicBoardRemoteAddress(host);
230
- return false;
231
- }
232
- /**
233
- * Normalize a browser-loadable public HTTP(S) URL. This blocks explicit local
234
- * addresses; any future server-side fetcher must additionally validate DNS
235
- * resolution to defend against rebinding.
236
- */
237
- function normalizeBoardRemoteUrl(value) {
238
- if (typeof value !== "string") return void 0;
239
- const input = value.trim();
240
- if (!input || input.length > 4096) return void 0;
241
- try {
242
- const url = new URL(input);
243
- if (url.protocol !== "https:" && url.protocol !== "http:") return void 0;
244
- if (url.username || url.password || isBlockedHost(url.hostname)) return;
245
- const normalized = url.toString();
246
- return normalized.length <= 4096 ? normalized : void 0;
247
- } catch {
248
- return;
249
- }
250
- }
251
- z.string().max(BOARD_REMOTE_URL_MAX_LENGTH).refine((value) => normalizeBoardRemoteUrl(value) !== void 0, { message: "URL must be a public HTTP(S) URL without credentials" });
252
- const BOARD_CAMERA_TARGET = "camera";
253
- const BoardKeySchema = z.string().min(1).max(160).regex(/^[^\s/]+$/, "ids must not contain whitespace or '/'");
254
- const BoardIdSchema = BoardKeySchema.refine((value) => value !== BOARD_CAMERA_TARGET, "\"camera\" is reserved");
255
- const finite$1 = z.number().finite();
256
- const nonNegative = finite$1.nonnegative();
257
- const ratio = finite$1.min(0).max(1);
258
- const BoardVec2Schema = z.object({
259
- x: finite$1,
260
- y: finite$1
261
- }).strict();
262
- const BoardSizeSchema = z.object({
263
- width: finite$1.positive(),
264
- height: finite$1.positive()
265
- }).strict();
266
- const BOARD_COLOR_TOKENS = [
267
- "brand",
268
- "neutral",
269
- "black",
270
- "white",
271
- "blue",
272
- "green",
273
- "amber",
274
- "violet",
275
- "rose"
276
- ];
277
- const CSS_NAMED_COLORS = new Set("transparent aliceblue antiquewhite aqua aquamarine azure beige bisque blanchedalmond blueviolet brown burlywood cadetblue chartreuse chocolate coral cornflowerblue cornsilk crimson cyan darkblue darkcyan darkgoldenrod darkgray darkgreen darkgrey darkkhaki darkmagenta darkolivegreen darkorange darkorchid darkred darksalmon darkseagreen darkslateblue darkslategray darkslategrey darkturquoise darkviolet deeppink deepskyblue dimgray dimgrey dodgerblue firebrick floralwhite forestgreen fuchsia gainsboro ghostwhite gold goldenrod gray grey greenyellow honeydew hotpink indianred indigo ivory khaki lavender lavenderblush lawngreen lemonchiffon lightblue lightcoral lightcyan lightgoldenrodyellow lightgray lightgreen lightgrey lightpink lightsalmon lightseagreen lightskyblue lightslategray lightslategrey lightsteelblue lightyellow lime limegreen linen magenta maroon mediumaquamarine mediumblue mediumorchid mediumpurple mediumseagreen mediumslateblue mediumspringgreen mediumturquoise mediumvioletred midnightblue mintcream mistyrose moccasin navajowhite navy oldlace olive olivedrab orange orangered orchid palegoldenrod palegreen paleturquoise palevioletred papayawhip peachpuff peru pink plum powderblue purple rebeccapurple red rosybrown royalblue saddlebrown salmon sandybrown seagreen seashell sienna silver skyblue slateblue slategray slategrey snow springgreen steelblue tan teal thistle tomato turquoise violet wheat whitesmoke yellow yellowgreen".split(" "));
278
- function isBoardColorString(value) {
279
- const color = value.trim().toLowerCase();
280
- return BOARD_COLOR_TOKENS.includes(color) || CSS_NAMED_COLORS.has(color) || /^#(?:[0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/.test(color) || /^(?:rgba?|hsla?|hwb|lab|lch|oklab|oklch|color)\([^()]*\)$/.test(color);
281
- }
282
- const colorString = z.string().max(120).refine(isBoardColorString, "expected a palette token or a CSS color");
283
- const BoardColorSchema = z.union([colorString, z.object({
284
- light: colorString,
285
- dark: colorString
286
- }).strict()]).describe("Palette token (follows the theme), CSS color, or { light, dark }.");
287
- const BoardStyleSchema = z.object({
288
- fill: BoardColorSchema.optional(),
289
- fillOpacity: ratio.optional().describe("Fill opacity, independent of the item's opacity."),
290
- stroke: BoardColorSchema.optional(),
291
- strokeWidth: finite$1.min(0).max(64).optional(),
292
- dash: z.enum([
293
- "solid",
294
- "dashed",
295
- "dotted"
296
- ]).optional(),
297
- radius: nonNegative.optional().describe("Corner radius in board units."),
298
- trim: ratio.optional().describe("Fraction of the outline drawn; animate 0 → 1 to draw it in.")
299
- }).strict();
300
- function isSafeBoardSourcePath(value) {
301
- return value.length > 0 && value.length <= 4096 && !value.startsWith("/") && !/^[a-z][a-z\d+.-]*:/i.test(value.trimStart()) && !value.includes("\\") && value.split("/").every((part) => part.length > 0 && part !== "." && part !== "..");
302
- }
303
- const srcSchema = z.string().refine(isSafeBoardSourcePath, "src must be a relative Space file path");
304
- function parseBoardMediaSource(src) {
305
- if (isSafeBoardSourcePath(src)) return {
306
- kind: "file",
307
- value: src
308
- };
309
- return normalizeBoardRemoteUrl(src) ? {
310
- kind: "url",
311
- value: src
312
- } : null;
313
- }
314
- const BoardMediaSourceSchema = z.string().max(4096).refine((src) => parseBoardMediaSource(src) !== null, "src must be a public HTTP(S) URL or relative Space file path").describe("Prefer a public HTTP(S) URL; a Space path relative to the workspace root also works.");
315
- const BoardScriptSchema = z.object({
316
- src: srcSchema.refine((path) => /\.m?js$/.test(path), "script src must be a .js or .mjs module").describe("A .js or .mjs Space file."),
317
- params: z.record(z.string(), z.json()).default({}).describe("Values the module reads as params."),
318
- targets: z.record(z.string().min(1).max(80), BoardIdSchema).default({}).describe("Named items the module can reach, as ctx.targets."),
319
- seed: z.string().min(1).max(160).optional().describe("Seed for ctx.random(); defaults to the item id."),
320
- enabled: z.boolean().default(true)
321
- }).strict().describe("A JavaScript module attached to the item; `cohub boards schema script` lists its API.");
322
- const itemEnvelope = {
323
- script: BoardScriptSchema.optional(),
324
- parent: BoardIdSchema.optional().describe("A frame id; position becomes relative to the frame, and the item moves with it."),
325
- z: finite$1.optional().describe("Order among siblings; new items go on top."),
326
- position: BoardVec2Schema.default({
327
- x: 0,
328
- y: 0
329
- }),
330
- rotation: finite$1.default(0),
331
- scale: z.union([finite$1, BoardVec2Schema]).default(1),
332
- origin: BoardVec2Schema.default({
333
- x: .5,
334
- y: .5
335
- }).describe("Rotation and scale origin as fractions of the size."),
336
- opacity: ratio.default(1),
337
- style: BoardStyleSchema.default({}),
338
- locked: z.boolean().optional(),
339
- metadata: z.record(z.string(), z.unknown()).optional()
340
- };
341
- const boxed = (size) => ({
342
- ...itemEnvelope,
343
- size: BoardSizeSchema.default({ ...size })
344
- });
345
- const unsized = { ...itemEnvelope };
346
- const fontSize = finite$1.min(2).max(512);
347
- const BOARD_TEXT_ALIGNS = [
348
- "left",
349
- "center",
350
- "right"
351
- ];
352
- const BOARD_SHAPE_GEOMETRIES = [
353
- "rectangle",
354
- "rounded",
355
- "ellipse",
356
- "diamond",
357
- "triangle",
358
- "path"
359
- ];
360
- const BoardFrameItemSchema = z.object({
361
- ...boxed(BOARD_DEFAULT_SIZES.frame),
362
- type: z.literal("frame"),
363
- props: z.object({
364
- label: z.string().max(280).default(""),
365
- decoration: z.enum(["frame", "none"]).optional().describe("none hides the title, border and background: an invisible group whose tracks move every child."),
366
- clip: z.boolean().default(true).describe("Hide children outside the frame.")
367
- }).strict().prefault({})
368
- }).strict();
369
- const BoardTextItemSchema = z.object({
370
- ...unsized,
371
- type: z.literal("text"),
372
- props: z.object({
373
- text: z.string().default(""),
374
- fontSize: fontSize.default(24),
375
- fontWeight: finite$1.min(100).max(900).default(500),
376
- font: z.string().min(1).max(120).default("sans").describe("sans, serif, mono, or a font family name."),
377
- align: z.enum(BOARD_TEXT_ALIGNS).default("left"),
378
- lineHeight: finite$1.min(.5).max(4).default(4 / 3),
379
- width: finite$1.positive().optional().describe("Wrap width; the height follows the text."),
380
- reveal: ratio.default(1).describe("Fraction of the text shown; animate 0 → 1 to type it."),
381
- caret: z.boolean().default(false).describe("Blink a caret while the text is being revealed.")
382
- }).strict().prefault({})
383
- }).strict();
384
- const BoardShapeItemSchema = z.object({
385
- ...boxed(BOARD_DEFAULT_SIZES.shape),
386
- type: z.literal("shape"),
387
- props: z.object({
388
- geometry: z.enum(BOARD_SHAPE_GEOMETRIES).default("rectangle"),
389
- path: z.string().min(1).max(2e5).optional().describe("SVG path data for path geometry, fitted to the item size."),
390
- text: z.string().default(""),
391
- fontSize: fontSize.default(20),
392
- align: z.enum(BOARD_TEXT_ALIGNS).default("center")
393
- }).strict().refine((props) => props.geometry !== "path" || Boolean(props.path), {
394
- message: "path geometry requires props.path",
395
- path: ["path"]
396
- }).prefault({})
397
- }).strict();
398
- const BoardDrawPointSchema = z.object({
399
- x: finite$1,
400
- y: finite$1,
401
- p: ratio.default(.5).describe("Pen pressure.")
402
- }).strict();
403
- const BoardDrawItemSchema = z.object({
404
- ...unsized,
405
- type: z.literal("draw"),
406
- props: z.object({ points: z.array(BoardDrawPointSchema).min(1).max(1e5).describe("Stroke points relative to position; the size follows them.") }).strict()
407
- }).strict();
408
- const BoardArrowAnchorSchema = z.union([
409
- z.literal("auto"),
410
- z.object({
411
- side: z.enum([
412
- "top",
413
- "right",
414
- "bottom",
415
- "left"
416
- ]),
417
- offset: ratio.default(.5)
418
- }).strict(),
419
- z.object({
420
- x: ratio,
421
- y: ratio
422
- }).strict()
423
- ]);
424
- const BoardArrowBindingSchema = z.object({
425
- item: BoardIdSchema,
426
- anchor: BoardArrowAnchorSchema.default("auto").describe("auto uses the side facing the other end; or a side with an offset, or a point as fractions of the item."),
427
- port: z.string().min(1).max(120).optional()
428
- }).strict();
429
- const BoardArrowEndSchema = z.union([BoardVec2Schema, BoardArrowBindingSchema]).describe("A point relative to position, or { item } to follow that item.");
430
- const BOARD_ARROW_ROUTES = [
431
- "straight",
432
- "curve",
433
- "orthogonal"
434
- ];
435
- const BoardArrowItemSchema = z.object({
436
- ...unsized,
437
- type: z.literal("arrow"),
438
- props: z.object({
439
- start: BoardArrowEndSchema,
440
- end: BoardArrowEndSchema,
441
- route: z.enum(BOARD_ARROW_ROUTES).default("straight"),
442
- bend: finite$1.min(-.85).max(.85).default(0).describe("Sideways curve as a fraction of the length; the sign picks the side."),
443
- waypoints: z.array(BoardVec2Schema).max(64).default([]).describe("Points the route passes through."),
444
- arrowStart: z.boolean().default(false),
445
- arrowEnd: z.boolean().default(true),
446
- label: z.string().max(280).default(""),
447
- fontSize: fontSize.default(14),
448
- relation: z.string().max(64).regex(/^[a-z0-9]+(?:[.-][a-z0-9]+)*$/, "relation must be a lowercase slug").optional().describe("What the arrow means, as a slug such as triggers or depends-on.")
449
- }).strict()
450
- }).strict();
451
- const fileProps = {
452
- src: BoardMediaSourceSchema,
453
- snapshot: z.object({
454
- title: z.string().optional(),
455
- mimeType: z.string().optional(),
456
- size: nonNegative.optional(),
457
- mtimeMs: nonNegative.optional(),
458
- naturalWidth: finite$1.positive().optional(),
459
- naturalHeight: finite$1.positive().optional(),
460
- durationMs: nonNegative.optional(),
461
- excerpt: z.string().optional(),
462
- coverPath: z.string().optional(),
463
- coverUrl: z.string().optional()
464
- }).strict().describe("Cached facts for an instant preview; filled in when the media loads.").optional()
465
- };
466
- const BoardMediaOriginSchema = z.object({
467
- taskRunId: z.string().min(1).max(160),
468
- artifactId: z.string().min(1).max(240)
469
- }).strict().describe("The generation run and result this media came from.");
470
- const mediaProps = {
471
- ...fileProps,
472
- origin: BoardMediaOriginSchema.optional()
473
- };
474
- const timedFileProps = {
475
- ...mediaProps,
476
- time: nonNegative.optional().describe("Playback position in milliseconds; animate props.time to play it on a timeline.")
477
- };
478
- const BoardCropSchema = z.object({
479
- x: ratio,
480
- y: ratio,
481
- w: ratio,
482
- h: ratio
483
- }).strict().describe("Region shown, as fractions of the image. Without it the whole image fits inside size.");
484
- const BoardImageItemSchema = z.object({
485
- ...boxed(BOARD_DEFAULT_SIZES.image),
486
- type: z.literal("image"),
487
- props: z.object({
488
- ...mediaProps,
489
- crop: BoardCropSchema.optional()
490
- }).strict()
491
- }).strict();
492
- const BoardVideoItemSchema = z.object({
493
- ...boxed(BOARD_DEFAULT_SIZES.video),
494
- type: z.literal("video"),
495
- props: z.object(timedFileProps).strict()
496
- }).strict();
497
- const BoardAudioItemSchema = z.object({
498
- ...boxed(BOARD_DEFAULT_SIZES.audio),
499
- type: z.literal("audio"),
500
- props: z.object(timedFileProps).strict()
501
- }).strict();
502
- const BoardFileItemSchema = z.object({
503
- ...boxed(BOARD_DEFAULT_SIZES.file),
504
- type: z.literal("file"),
505
- props: z.object(fileProps).strict()
506
- }).strict();
507
- const httpsUrl = z.string().max(4096).url();
508
- const artifactBase = {
509
- id: z.string().min(1).max(240),
510
- title: z.string().max(240).optional(),
511
- url: httpsUrl,
512
- mimeType: z.string().max(160).optional()
513
- };
514
- const BoardTaskArtifactSchema = z.discriminatedUnion("type", [
515
- z.object({
516
- ...artifactBase,
517
- type: z.literal("image"),
518
- naturalWidth: finite$1.positive().optional(),
519
- naturalHeight: finite$1.positive().optional()
520
- }).strict(),
521
- z.object({
522
- ...artifactBase,
523
- type: z.literal("video"),
524
- previewUrl: httpsUrl.optional(),
525
- durationMs: z.number().int().positive().optional(),
526
- naturalWidth: finite$1.positive().optional(),
527
- naturalHeight: finite$1.positive().optional()
528
- }).strict(),
529
- z.object({
530
- ...artifactBase,
531
- type: z.literal("audio"),
532
- previewUrl: httpsUrl.optional(),
533
- durationMs: z.number().int().positive().optional()
534
- }).strict(),
535
- z.object({
536
- id: z.string().min(1).max(240),
537
- type: z.literal("text"),
538
- title: z.string().max(240).optional(),
539
- textExcerpt: z.string().min(1).max(480)
540
- }).strict()
541
- ]);
542
- const BoardTaskSnapshotSchema = z.object({
543
- taskType: z.string().min(1).max(120),
544
- status: z.enum([
545
- "pending",
546
- "running",
547
- "completed",
548
- "failed"
549
- ]),
550
- title: z.string().min(1).max(240),
551
- model: z.string().max(160).optional(),
552
- promptExcerpt: z.string().max(480).optional(),
553
- errorExcerpt: z.string().max(240).optional(),
554
- artifactCount: z.number().int().nonnegative(),
555
- artifacts: z.array(BoardTaskArtifactSchema).max(6).default([]),
556
- startedAt: z.string().max(64).optional(),
557
- updatedAt: z.string().optional()
558
- }).strict();
559
- const BoardTaskItemSchema = z.object({
560
- ...boxed(BOARD_DEFAULT_SIZES.task),
561
- type: z.literal("task"),
562
- props: z.object({
563
- taskRunId: z.string().min(1).max(160).describe("The generation run shown; the server keeps the card's status and results up to date."),
564
- snapshot: BoardTaskSnapshotSchema.describe("Maintained by the server; omit it.")
565
- }).strict()
566
- }).strict();
567
- const BOARD_EFFECT_KINDS = [
568
- "particles",
569
- "trail",
570
- "impact",
571
- "flash",
572
- "glow"
573
- ];
574
- const BoardEffectItemSchema = z.object({
575
- ...boxed(BOARD_DEFAULT_SIZES.effect),
576
- type: z.literal("effect"),
577
- props: z.object({
578
- kind: z.enum(BOARD_EFFECT_KINDS),
579
- rate: nonNegative.max(2e4).default(40),
580
- life: finite$1.positive().max(6e4).default(1200),
581
- particleSize: finite$1.positive().max(512).default(6),
582
- speed: nonNegative.max(1e4).default(120),
583
- direction: finite$1.default(-90),
584
- spread: finite$1.min(0).max(360).default(360),
585
- gravity: finite$1.default(0),
586
- intensity: nonNegative.max(10).default(1),
587
- follow: BoardIdSchema.optional().describe("trail: the item to follow."),
588
- seed: z.string().min(1).max(160).optional().describe("Makes procedural motion repeatable.")
589
- }).strict()
590
- }).strict();
591
- const BoardCustomItemSchema = z.object({
592
- ...boxed(BOARD_DEFAULT_SIZES.custom),
593
- type: z.literal("custom"),
594
- script: BoardScriptSchema,
595
- props: z.object({}).strict().default({})
596
- }).strict();
597
- const BOARD_EXTENSION_TYPE_PATTERN = /^[a-z][a-z0-9]*(?:\.[a-z0-9-]+)+$/;
598
- const BoardExtensionItemSchema = z.object({
599
- ...boxed(BOARD_DEFAULT_ITEM_SIZE),
600
- type: z.string().regex(BOARD_EXTENSION_TYPE_PATTERN),
601
- props: z.record(z.string(), z.unknown()).default({})
602
- }).strict();
603
- const BOARD_ITEM_SCHEMAS = {
604
- frame: BoardFrameItemSchema,
605
- text: BoardTextItemSchema,
606
- shape: BoardShapeItemSchema,
607
- draw: BoardDrawItemSchema,
608
- arrow: BoardArrowItemSchema,
609
- image: BoardImageItemSchema,
610
- video: BoardVideoItemSchema,
611
- audio: BoardAudioItemSchema,
612
- file: BoardFileItemSchema,
613
- task: BoardTaskItemSchema,
614
- effect: BoardEffectItemSchema,
615
- custom: BoardCustomItemSchema
616
- };
617
- const BOARD_ITEM_TYPES = Object.keys(BOARD_ITEM_SCHEMAS);
618
- function isBuiltinItemType(type) {
619
- return Object.hasOwn(BOARD_ITEM_SCHEMAS, type);
620
- }
621
- function boardItemSchema(type) {
622
- if (isBuiltinItemType(type)) return BOARD_ITEM_SCHEMAS[type];
623
- return BOARD_EXTENSION_TYPE_PATTERN.test(type) ? BoardExtensionItemSchema : null;
624
- }
625
- function issuesToDiagnostics(error, path) {
626
- return error.issues.map((issue) => {
627
- return {
628
- severity: "error",
629
- code: "INVALID_ITEM",
630
- path: [path, ...issue.path.map(String)].filter(Boolean).join("."),
631
- message: issue.code === "unrecognized_keys" ? `unknown ${issue.keys.length === 1 ? "property" : "properties"} ${issue.keys.join(", ")}` : issue.message
632
- };
633
- });
634
- }
635
- function parseBoardItem(value, path = "item") {
636
- const type = value && typeof value === "object" && !Array.isArray(value) ? value.type : void 0;
637
- if (typeof type !== "string") return {
638
- ok: false,
639
- diagnostics: [{
640
- severity: "error",
641
- code: "INVALID_ITEM",
642
- path: `${path}.type`,
643
- message: "type is required"
644
- }]
645
- };
646
- const schema = boardItemSchema(type);
647
- if (!schema) return {
648
- ok: false,
649
- diagnostics: [{
650
- severity: "error",
651
- code: "INVALID_ITEM",
652
- path: `${path}.type`,
653
- message: `unknown type ${type}; expected ${BOARD_ITEM_TYPES.join(", ")} or a namespaced extension type`
654
- }]
655
- };
656
- const parsed = schema.safeParse(value);
657
- return parsed.success ? {
658
- ok: true,
659
- item: parsed.data
660
- } : {
661
- ok: false,
662
- diagnostics: issuesToDiagnostics(parsed.error, path)
663
- };
664
- }
665
- const CSS_EASE_KEYWORDS = /* @__PURE__ */ new Set([
666
- "linear",
667
- "ease",
668
- "ease-in",
669
- "ease-out",
670
- "ease-in-out",
671
- "step-start",
672
- "step-end"
673
- ]);
674
- function isBoardEase(value) {
675
- const ease = value.trim();
676
- if (CSS_EASE_KEYWORDS.has(ease)) return true;
677
- const bezier = /^cubic-bezier\(\s*([^,()]+),\s*([^,()]+),\s*([^,()]+),\s*([^,()]+)\)$/.exec(ease);
678
- if (bezier) {
679
- const [x1, , x2] = bezier.slice(1).map(Number);
680
- return bezier.slice(1).every((part) => Number.isFinite(Number(part))) && x1 >= 0 && x1 <= 1 && x2 >= 0 && x2 <= 1;
681
- }
682
- return /^steps\(\s*[1-9]\d*\s*(?:,\s*(?:start|end|jump-start|jump-end|jump-none|jump-both)\s*)?\)$/.test(ease);
683
- }
684
- const BoardEaseSchema = z.string().max(120).refine(isBoardEase, "expected a CSS easing: linear, ease-in-out, cubic-bezier(…) or steps(…)");
685
- const BoardKeyframeSchema = z.object({
686
- at: nonNegative.describe("Time in milliseconds."),
687
- value: z.unknown(),
688
- ease: BoardEaseSchema.optional().describe("Easing into this keyframe: a CSS keyword, cubic-bezier() or steps(); defaults to linear.")
689
- }).strict();
690
- const BoardTrackSchema = z.object({
691
- target: z.string().min(1).max(160).describe("An item id, camera, or another animation id (its time property nests that timeline)."),
692
- property: z.string().min(1).max(200).describe("JSON path in the target, e.g. position, opacity, style.fill, props.text."),
693
- keyframes: z.array(BoardKeyframeSchema).min(1).max(1e5).describe("Ordered by at. The value holds before the first and after the last keyframe."),
694
- composite: z.enum(["replace", "add"]).default("replace").describe("replace: the latest-started track wins. add: positions and rotations add; scale and opacity multiply."),
695
- interpolation: z.enum([
696
- "auto",
697
- "step",
698
- "spline"
699
- ]).default("auto").describe("auto blends numbers, vectors and colors and steps other values; spline smooths position paths."),
700
- orient: z.boolean().optional().describe("Rotate the item along its path.")
701
- }).strict().superRefine((track, context) => {
702
- for (let index = 1; index < track.keyframes.length; index += 1) if ((track.keyframes[index]?.at ?? 0) < (track.keyframes[index - 1]?.at ?? 0)) context.addIssue({
703
- code: "custom",
704
- message: "keyframes must be ordered by at",
705
- path: [
706
- "keyframes",
707
- index,
708
- "at"
709
- ]
710
- });
711
- });
712
- const BoardMarkerSchema = z.object({
713
- at: nonNegative,
714
- label: z.string().max(280).optional(),
715
- pause: z.boolean().optional().describe("Hold shared playback here until next.")
716
- }).strict();
717
- const BoardAnimationHeaderSchema = z.object({
718
- name: z.string().max(280).optional(),
719
- duration: finite$1.positive().max(864e5).describe("Milliseconds; a new animation without it ends at its last keyframe."),
720
- play: z.enum([
721
- "manual",
722
- "auto",
723
- "always"
724
- ]).default("manual").describe("manual: only shared playback starts it. auto: plays when the Board opens. always: loops continuously."),
725
- delay: nonNegative.default(0),
726
- loop: z.boolean().default(false),
727
- end: z.enum(["hold", "reset"]).default("hold").describe("hold keeps the last frame; reset returns to the start."),
728
- markers: z.array(BoardMarkerSchema).max(1e4).default([]).describe("Labeled points on this timeline; a nested animation's markers do not carry over.")
729
- }).strict();
730
- const BoardAnimationSchema = BoardAnimationHeaderSchema.extend({ tracks: z.record(BoardKeySchema, BoardTrackSchema).default({}) }).strict();
731
- const BOARD_ENTER_PRESETS = [
732
- "fade-in",
733
- "rise",
734
- "drop",
735
- "pop",
736
- "deal"
737
- ];
738
- const BoardBackgroundSchema = z.object({
739
- kind: z.enum([
740
- "solid",
741
- "dots",
742
- "grid",
743
- "image"
744
- ]).default("dots"),
745
- color: BoardColorSchema.optional(),
746
- imageUrl: z.string().url().max(4096).optional().describe("Background image for kind image."),
747
- fit: z.enum([
748
- "cover",
749
- "contain",
750
- "repeat"
751
- ]).optional(),
752
- opacity: ratio.optional()
753
- }).strict();
754
- const BoardSettingsSchema = z.object({
755
- title: z.string().min(1).max(255).optional(),
756
- background: BoardBackgroundSchema.default({ kind: "dots" }),
757
- grid: z.object({
758
- visible: z.boolean().default(false).describe("Show the grid overlay."),
759
- size: finite$1.min(4).max(512).default(24)
760
- }).strict().optional(),
761
- enter: z.object({
762
- preset: z.enum(BOARD_ENTER_PRESETS),
763
- duration: finite$1.positive().max(1e4).optional()
764
- }).strict().optional().describe("Motion for items as they are added.")
765
- }).strict();
766
- const patchObject = z.record(z.string(), z.unknown());
767
- const BoardPatchSchema = z.object({
768
- board: patchObject.nullable().optional(),
769
- items: z.record(BoardIdSchema, patchObject.nullable()).optional(),
770
- animations: z.record(BoardIdSchema, patchObject.and(z.object({ tracks: z.record(BoardKeySchema, patchObject.nullable()).optional() })).nullable()).optional()
771
- }).strict();
772
- //#endregion
773
- //#region ../protocol/dist/board.js
774
- const BOARD_EXTENSION = ".board";
775
- const BOARD_MIME_TYPE = "application/json";
776
- z.object({
777
- kind: z.literal("cohub.board.manifest"),
778
- version: z.literal(1),
779
- boardId: z.string().uuid(),
780
- title: z.string().min(1).max(255)
781
- });
782
- const BOARD_READ_SECTIONS = ["items", "animations"];
783
- const rectSchema = z.object({
784
- x: z.number().finite(),
785
- y: z.number().finite(),
786
- width: z.number().finite().positive(),
787
- height: z.number().finite().positive()
788
- }).strict();
789
- z.object({
790
- only: z.array(z.enum(BOARD_READ_SECTIONS)).optional(),
791
- rect: rectSchema.optional(),
792
- within: BoardIdSchema.optional(),
793
- items: z.array(z.string().min(1)).max(5e4).optional(),
794
- animations: z.array(z.string().min(1)).max(1e4).optional(),
795
- limit: z.number().int().min(1).max(5e4).optional(),
796
- cursor: z.string().min(1).optional()
797
- }).strict().refine((read) => !(read.cursor && (read.rect || read.within)), {
798
- path: ["cursor"],
799
- message: "cursor pages by id, so it cannot be combined with rect or within"
800
- });
801
- z.object({
802
- patch: BoardPatchSchema,
803
- replace: z.boolean().default(false),
804
- cascade: z.boolean().default(false),
805
- dryRun: z.boolean().default(false),
806
- baseVersion: z.number().int().nonnegative().optional(),
807
- mutationId: z.string().min(1).max(160).optional(),
808
- clientId: z.string().min(1).max(160).optional()
809
- }).strict();
810
- z.object({
811
- path: z.string().min(1),
812
- title: z.string().min(1).max(255).optional(),
813
- document: BoardPatchSchema.optional(),
814
- mutationId: z.string().max(160).optional()
815
- }).strict();
816
- z.object({
817
- before: z.number().int().positive().optional(),
818
- limit: z.number().int().min(1).max(500).default(200)
819
- }).strict();
820
- const commandId = z.string().min(1).max(160);
821
- z.discriminatedUnion("type", [
822
- z.object({
823
- commandId,
824
- type: z.literal("play"),
825
- animationId: z.string().min(1),
826
- position: z.number().finite().nonnegative().optional(),
827
- timeScale: z.number().finite().positive().max(4).optional(),
828
- seed: z.string().min(1).max(160).optional()
829
- }).strict(),
830
- z.object({
831
- commandId,
832
- type: z.literal("pause")
833
- }).strict(),
834
- z.object({
835
- commandId,
836
- type: z.literal("resume")
837
- }).strict(),
838
- z.object({
839
- commandId,
840
- type: z.literal("seek"),
841
- position: z.number().finite().nonnegative()
842
- }).strict(),
843
- z.object({
844
- commandId,
845
- type: z.literal("next")
846
- }).strict(),
847
- z.object({
848
- commandId,
849
- type: z.literal("stop")
850
- }).strict()
851
- ]);
852
184
  //#endregion
853
185
  //#region ../protocol/dist/board-json.js
854
186
  /** Structural equality for JSON-shaped semantic values. */
@@ -865,6 +197,128 @@ function boardJsonEquals(a, b) {
865
197
  return keys.length === Object.keys(bRecord).length && keys.every((key) => Object.hasOwn(bRecord, key) && boardJsonEquals(aRecord[key], bRecord[key]));
866
198
  }
867
199
  //#endregion
200
+ //#region ../protocol/dist/generation/blocks.js
201
+ const EXCERPT_LIMIT = 240;
202
+ function asRecord(value) {
203
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
204
+ }
205
+ function cleanExcerpt(value, limit = EXCERPT_LIMIT) {
206
+ if (typeof value !== "string") return void 0;
207
+ const clean = value.replace(/\s+/g, " ").trim();
208
+ if (!clean) return void 0;
209
+ return clean.length > limit ? `${clean.slice(0, limit - 3).trimEnd()}...` : clean;
210
+ }
211
+ function blockText(block) {
212
+ return cleanExcerpt(block.text ?? block.content ?? block.value);
213
+ }
214
+ function blockUrl(block) {
215
+ const source = asRecord(block.source);
216
+ return normalizeBoardRemoteUrl(source?.url ?? source?.src ?? block.url ?? block.src);
217
+ }
218
+ function blockMimeType(block) {
219
+ const source = asRecord(block.source);
220
+ const value = source?.mediaType ?? source?.media_type ?? source?.mimeType ?? block.mediaType ?? block.media_type ?? block.mimeType;
221
+ return typeof value === "string" ? value : void 0;
222
+ }
223
+ function positiveNumber(value) {
224
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : void 0;
225
+ }
226
+ function blockNaturalSize(block) {
227
+ const source = asRecord(block.source);
228
+ const naturalWidth = positiveNumber(source?.width ?? source?.naturalWidth ?? block.width ?? block.naturalWidth);
229
+ const naturalHeight = positiveNumber(source?.height ?? source?.naturalHeight ?? block.height ?? block.naturalHeight);
230
+ return {
231
+ ...naturalWidth ? { naturalWidth } : {},
232
+ ...naturalHeight ? { naturalHeight } : {}
233
+ };
234
+ }
235
+ function contentBlocks(value) {
236
+ return Array.isArray(value) ? value.filter((item) => asRecord(item)) : [];
237
+ }
238
+ function taskData(run) {
239
+ const payload = asRecord(run.payload);
240
+ return asRecord(payload?.data) ?? payload;
241
+ }
242
+ function generationOutput(run) {
243
+ return contentBlocks(asRecord(run.result)?.output);
244
+ }
245
+ function generationPrompt(run) {
246
+ for (const block of contentBlocks(taskData(run)?.content)) {
247
+ const text = blockText(block);
248
+ if (text) return text;
249
+ }
250
+ }
251
+ function blockMeta(block) {
252
+ return asRecord(block.meta);
253
+ }
254
+ function blockIdentity(block) {
255
+ const meta = blockMeta(block);
256
+ const value = meta?.id ?? meta?.clip_id ?? meta?.clipId ?? block.id ?? block.clip_id ?? block.clipId;
257
+ if (typeof value !== "string" && typeof value !== "number") return void 0;
258
+ return cleanExcerpt(String(value), 220);
259
+ }
260
+ function blockTitle(block) {
261
+ return cleanExcerpt(blockMeta(block)?.title ?? block.title ?? block.name, 240);
262
+ }
263
+ function blockDurationMs(block) {
264
+ const source = asRecord(block.source);
265
+ const meta = blockMeta(block);
266
+ const milliseconds = positiveNumber(source?.durationMs ?? meta?.durationMs ?? block.durationMs);
267
+ if (milliseconds) return Math.round(milliseconds);
268
+ const seconds = positiveNumber(source?.duration ?? meta?.duration ?? block.duration);
269
+ return seconds ? Math.round(seconds * 1e3) : void 0;
270
+ }
271
+ function blockPreviewUrl(block) {
272
+ const source = asRecord(block.source);
273
+ return normalizeBoardRemoteUrl(source?.poster ?? source?.thumbnail ?? source?.previewUrl ?? block.poster ?? block.thumbnail ?? block.previewUrl);
274
+ }
275
+ /**
276
+ * Image roles that depict playable media, by the media types they may cover;
277
+ * `last_frame` stays a result of its own.
278
+ */
279
+ const COVER_ROLES = /* @__PURE__ */ new Map([
280
+ ["first_frame", /* @__PURE__ */ new Set(["video"])],
281
+ ["cover", /* @__PURE__ */ new Set(["video", "audio"])],
282
+ ["poster", /* @__PURE__ */ new Set(["video", "audio"])],
283
+ ["thumbnail", /* @__PURE__ */ new Set(["video", "audio"])]
284
+ ]);
285
+ function isPlayable(block) {
286
+ return block.type === "video" || block.type === "audio";
287
+ }
288
+ /**
289
+ * Pair playable media with its cover image, returning media index → cover
290
+ * index. An image sharing the provider id wins (music tracks and their art,
291
+ * shared by every media of that id); otherwise cover-role images pair in
292
+ * order with remaining media their role fits (a video and its `first_frame`).
293
+ * Covers need a remote URL, so an inline image is never folded away.
294
+ */
295
+ function generationCovers(blocks) {
296
+ const covers = /* @__PURE__ */ new Map();
297
+ const isCover = (block) => block.type === "image" && blockUrl(block) !== void 0 && blockMeta(block)?.role !== "last_frame";
298
+ blocks.forEach((block, index) => {
299
+ const id = blockIdentity(block);
300
+ if (!isPlayable(block) || id === void 0) return;
301
+ const cover = blocks.findIndex((candidate) => isCover(candidate) && blockIdentity(candidate) === id);
302
+ if (cover >= 0) covers.set(index, cover);
303
+ });
304
+ const paired = new Set(covers.values());
305
+ const roleCovers = blocks.flatMap((block, index) => {
306
+ const role = blockMeta(block)?.role;
307
+ const types = typeof role === "string" ? COVER_ROLES.get(role) : void 0;
308
+ return isCover(block) && !paired.has(index) && types ? [{
309
+ index,
310
+ types
311
+ }] : [];
312
+ });
313
+ blocks.forEach((block, index) => {
314
+ if (!isPlayable(block) || covers.has(index)) return;
315
+ const at = roleCovers.findIndex(({ types }) => types.has(String(block.type)));
316
+ const [cover] = at < 0 ? [] : roleCovers.splice(at, 1);
317
+ if (cover) covers.set(index, cover.index);
318
+ });
319
+ return covers;
320
+ }
321
+ //#endregion
868
322
  //#region ../protocol/dist/board-layout.js
869
323
  const IDENTITY_MATRIX = [
870
324
  1,
@@ -927,8 +381,14 @@ function estimateTextWidth(text, fontSize) {
927
381
  }
928
382
  return ems * fontSize;
929
383
  }
930
- function measureLine(text, fontSize, fontWeight, font) {
931
- return estimateTextWidth(text, fontSize);
384
+ function estimateLines(text, { fontSize }, maxWidth) {
385
+ const measure = (line) => estimateTextWidth(line, fontSize);
386
+ const paragraphs = text.split("\n");
387
+ const lines = maxWidth ? paragraphs.flatMap((paragraph) => wrapParagraph(paragraph, maxWidth, measure)) : paragraphs;
388
+ return {
389
+ lines,
390
+ width: lines.reduce((max, line) => Math.max(max, measure(line)), 0)
391
+ };
932
392
  }
933
393
  function wrapParagraph(paragraph, width, measure) {
934
394
  if (!paragraph) return [""];
@@ -957,13 +417,15 @@ function layoutBoardText(props) {
957
417
  const key = `${fontSize}|${props.fontWeight}|${props.font}|${props.lineHeight}|${props.width ?? ""}|${props.text}`;
958
418
  const cached = textSizeCache.get(key);
959
419
  if (cached) return cached;
960
- const measure = (text) => measureLine(text, fontSize, props.fontWeight ?? 500, props.font ?? "sans");
961
- const paragraphs = (props.text || "").split("\n");
962
- const lines = props.width ? paragraphs.flatMap((paragraph) => wrapParagraph(paragraph, props.width, measure)) : paragraphs;
420
+ const font = {
421
+ fontSize,
422
+ fontWeight: props.fontWeight ?? 500,
423
+ font: props.font ?? "sans"
424
+ };
425
+ const { lines, width } = estimateLines(props.text || "", font, props.width || void 0);
963
426
  const lineHeight = fontSize * (props.lineHeight ?? 4 / 3);
964
- const widest = lines.reduce((max, line) => Math.max(max, measure(line)), 0);
965
427
  const layout = {
966
- width: Math.max(props.width ?? 0, widest, fontSize * .5),
428
+ width: Math.max(props.width ?? 0, width, fontSize * .5),
967
429
  height: Math.max(1, lines.length) * lineHeight,
968
430
  lines,
969
431
  lineHeight
@@ -1918,128 +1380,6 @@ function parseBoardDocument(input) {
1918
1380
  } : result;
1919
1381
  }
1920
1382
  //#endregion
1921
- //#region ../protocol/dist/generation/blocks.js
1922
- const EXCERPT_LIMIT = 240;
1923
- function asRecord(value) {
1924
- return value && typeof value === "object" && !Array.isArray(value) ? value : null;
1925
- }
1926
- function cleanExcerpt(value, limit = EXCERPT_LIMIT) {
1927
- if (typeof value !== "string") return void 0;
1928
- const clean = value.replace(/\s+/g, " ").trim();
1929
- if (!clean) return void 0;
1930
- return clean.length > limit ? `${clean.slice(0, limit - 3).trimEnd()}...` : clean;
1931
- }
1932
- function blockText(block) {
1933
- return cleanExcerpt(block.text ?? block.content ?? block.value);
1934
- }
1935
- function blockUrl(block) {
1936
- const source = asRecord(block.source);
1937
- return normalizeBoardRemoteUrl(source?.url ?? source?.src ?? block.url ?? block.src);
1938
- }
1939
- function blockMimeType(block) {
1940
- const source = asRecord(block.source);
1941
- const value = source?.mediaType ?? source?.media_type ?? source?.mimeType ?? block.mediaType ?? block.media_type ?? block.mimeType;
1942
- return typeof value === "string" ? value : void 0;
1943
- }
1944
- function positiveNumber(value) {
1945
- return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : void 0;
1946
- }
1947
- function blockNaturalSize(block) {
1948
- const source = asRecord(block.source);
1949
- const naturalWidth = positiveNumber(source?.width ?? source?.naturalWidth ?? block.width ?? block.naturalWidth);
1950
- const naturalHeight = positiveNumber(source?.height ?? source?.naturalHeight ?? block.height ?? block.naturalHeight);
1951
- return {
1952
- ...naturalWidth ? { naturalWidth } : {},
1953
- ...naturalHeight ? { naturalHeight } : {}
1954
- };
1955
- }
1956
- function contentBlocks(value) {
1957
- return Array.isArray(value) ? value.filter((item) => asRecord(item)) : [];
1958
- }
1959
- function taskData(run) {
1960
- const payload = asRecord(run.payload);
1961
- return asRecord(payload?.data) ?? payload;
1962
- }
1963
- function generationOutput(run) {
1964
- return contentBlocks(asRecord(run.result)?.output);
1965
- }
1966
- function generationPrompt(run) {
1967
- for (const block of contentBlocks(taskData(run)?.content)) {
1968
- const text = blockText(block);
1969
- if (text) return text;
1970
- }
1971
- }
1972
- function blockMeta(block) {
1973
- return asRecord(block.meta);
1974
- }
1975
- function blockIdentity(block) {
1976
- const meta = blockMeta(block);
1977
- const value = meta?.id ?? meta?.clip_id ?? meta?.clipId ?? block.id ?? block.clip_id ?? block.clipId;
1978
- if (typeof value !== "string" && typeof value !== "number") return void 0;
1979
- return cleanExcerpt(String(value), 220);
1980
- }
1981
- function blockTitle(block) {
1982
- return cleanExcerpt(blockMeta(block)?.title ?? block.title ?? block.name, 240);
1983
- }
1984
- function blockDurationMs(block) {
1985
- const source = asRecord(block.source);
1986
- const meta = blockMeta(block);
1987
- const milliseconds = positiveNumber(source?.durationMs ?? meta?.durationMs ?? block.durationMs);
1988
- if (milliseconds) return Math.round(milliseconds);
1989
- const seconds = positiveNumber(source?.duration ?? meta?.duration ?? block.duration);
1990
- return seconds ? Math.round(seconds * 1e3) : void 0;
1991
- }
1992
- function blockPreviewUrl(block) {
1993
- const source = asRecord(block.source);
1994
- return normalizeBoardRemoteUrl(source?.poster ?? source?.thumbnail ?? source?.previewUrl ?? block.poster ?? block.thumbnail ?? block.previewUrl);
1995
- }
1996
- /**
1997
- * Image roles that depict playable media, by the media types they may cover;
1998
- * `last_frame` stays a result of its own.
1999
- */
2000
- const COVER_ROLES = /* @__PURE__ */ new Map([
2001
- ["first_frame", /* @__PURE__ */ new Set(["video"])],
2002
- ["cover", /* @__PURE__ */ new Set(["video", "audio"])],
2003
- ["poster", /* @__PURE__ */ new Set(["video", "audio"])],
2004
- ["thumbnail", /* @__PURE__ */ new Set(["video", "audio"])]
2005
- ]);
2006
- function isPlayable(block) {
2007
- return block.type === "video" || block.type === "audio";
2008
- }
2009
- /**
2010
- * Pair playable media with its cover image, returning media index → cover
2011
- * index. An image sharing the provider id wins (music tracks and their art,
2012
- * shared by every media of that id); otherwise cover-role images pair in
2013
- * order with remaining media their role fits (a video and its `first_frame`).
2014
- * Covers need a remote URL, so an inline image is never folded away.
2015
- */
2016
- function generationCovers(blocks) {
2017
- const covers = /* @__PURE__ */ new Map();
2018
- const isCover = (block) => block.type === "image" && blockUrl(block) !== void 0 && blockMeta(block)?.role !== "last_frame";
2019
- blocks.forEach((block, index) => {
2020
- const id = blockIdentity(block);
2021
- if (!isPlayable(block) || id === void 0) return;
2022
- const cover = blocks.findIndex((candidate) => isCover(candidate) && blockIdentity(candidate) === id);
2023
- if (cover >= 0) covers.set(index, cover);
2024
- });
2025
- const paired = new Set(covers.values());
2026
- const roleCovers = blocks.flatMap((block, index) => {
2027
- const role = blockMeta(block)?.role;
2028
- const types = typeof role === "string" ? COVER_ROLES.get(role) : void 0;
2029
- return isCover(block) && !paired.has(index) && types ? [{
2030
- index,
2031
- types
2032
- }] : [];
2033
- });
2034
- blocks.forEach((block, index) => {
2035
- if (!isPlayable(block) || covers.has(index)) return;
2036
- const at = roleCovers.findIndex(({ types }) => types.has(String(block.type)));
2037
- const [cover] = at < 0 ? [] : roleCovers.splice(at, 1);
2038
- if (cover) covers.set(index, cover.index);
2039
- });
2040
- return covers;
2041
- }
2042
- //#endregion
2043
1383
  //#region ../protocol/dist/turn-origin.js
2044
1384
  const record$1 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
2045
1385
  const normalizeSessionTurnOrigin = (value) => {
@@ -7795,4 +7135,4 @@ function generationOutputSource(result, outputIndex) {
7795
7135
  return `data:${declared && MEDIA_TYPE_PATTERN.test(declared) ? declared : DEFAULT_MEDIA_TYPES[String(block.type)] ?? "application/octet-stream"};base64,${data}`;
7796
7136
  }
7797
7137
  //#endregion
7798
- export { APP_APPEARANCE_TOKENS, APP_COMPOSER_CHIP_CONTENT_MAX_BYTES, APP_COMPOSER_CHIP_KEY_MAX_LENGTH, APP_COMPOSER_CHIP_LABEL_MAX_LENGTH, APP_DEVICES, APP_SURFACE_READY_TIMEOUT_MS, APP_SURFACE_REQUEST_TIMEOUT_MS, AppCommerceApi, AppRealtimeApi, AppRefParseError, AppRoom, AppRoomRtc, AppRtcChannel, AppRtcError, AppRuntimeApi, AppRuntimeApi as WorkRuntimeApi, AppRuntimeError, AppSurfaceApi, AppWindowApi, AppsApi, BILLING_ACCESS_BLOCKED_ERROR_CODE, BOARD_COLOR_TOKENS, BOARD_ITEM_TYPES, BillingApi, BoardAnimationSchema, BoardClient, BoardPatchSchema, BoardTrackSchema, COHUB_ENVIRONMENTS, COHUB_SOURCE_HEADER, COHUB_SOURCE_HEADER_NAMES, CohubClient, CohubHttpClient, DESKTOP_COMMAND_ACCEPT_TIMEOUT_MS, DESKTOP_COMMAND_DEFAULT_TIMEOUT_MS, DESKTOP_COMMAND_MAX_TIMEOUT_MS, DESKTOP_COMMAND_OPEN_TIMEOUT_MS, DESKTOP_COMMAND_PAYLOAD_MAX_BYTES, DESKTOP_COMMAND_PENDING_TTL_SECONDS, DESKTOP_COMMAND_SETTLEMENT_GRACE_SECONDS, DESKTOP_COMMAND_TERMINAL_TTL_SECONDS, DESKTOP_COMMAND_VERSION, DISPLAY_ACTION_TYPES, DISPLAY_ELEMENT_REF_PATTERN, DISPLAY_SYSTEM_ACTIONS, DesktopCommandsApi, DisplayActionError, DisplayConnection, FEATURE_NOT_ENTITLED_ERROR_CODE, GenerationPolicyError, HOME_SPACE_SLUG, HttpError, LOCAL_HARNESSES, LOCAL_HARNESS_SPECS, NATIVE_INGEST_MAX_TURNS, NATIVE_SYNC_SOURCE, OriginBrokerTransport, PERMISSIONS, ParentBridgeTransport, PopupBrokerTransport, REQUEST_SOURCE_VIA_MAX_LENGTH, RUNTIME_ARCHIVE_SEGMENT_BYTES, RUNTIME_MAX_FRAME_BYTES, RUNTIME_PROTOCOL_VERSION, RUNTIME_RECOVERY_BATCH_SIZE, ReferencesApi, ReferralsApi, RoomsApi, SETTLED_TURN_STATUSES, SessionGenerationStreamClient, SessionPatchReducer, SpaceDisplaysApi, SpacePublicFilesApi, SpaceWebhooksApi, UPLOAD_ERROR_BATCH_TOO_LARGE, UPLOAD_ERROR_FILE_TOO_LARGE, UPLOAD_ERROR_RATE_LIMITED, UPLOAD_ERROR_TOO_MANY_FILES, UPLOAD_MAX_BATCH_BYTES, UPLOAD_MAX_BATCH_FILES, UPLOAD_MAX_FILE_BYTES, USER_LEVEL_PERMISSIONS, UiCommandsApi, UsersApi, VoiceApi, VoiceInputClient, WebsocketClient, WorkCommerceApi, WorkRealtimeApi, WorkRefParseError, WorkRoom, WorkSurfaceApi, appAppearanceVar, applyAppAppearance, assertGenerationRequestAllowedByPolicy, assertHarnessAccess, attachAppEmbed, batchUploadEntries, buildAppSurfaceRequest, buildSpaceInvitePath, buildSpacePath, clearGrantedAppScopes, compileDisplayActions, connectDisplay, contextToPiMessages, createAppBridgeCore, createAppBridgeCore as createWorkBridgeCore, createAppRuntime, createAppRuntime as createWorkRuntime, createCohubClient, createHttpClient, createOriginAppResolver, createSessionGenerationStreamClient, createSessionPatchReducer, createSlugAppIdResolver, createSlugAppIdResolver as createSlugWorkIdResolver, createVoiceInputClient, createWebsocketClient, decodeGenerationPolicy, defaultDesktopCommandTimeoutMs, encodeGenerationPolicy, extractBillingPayload, filterDiscoverableGenerationModels, filterGenerationDeclarationsByPolicy, filterSpacePickerItems, findGenerationModelPolicy, fingerprintProjectionTurns, formatAppRef, formatWorkRef, generationOutputSource, getAllowedGenerationModelIds, getCohubContext, harnessArchiveIndexSchema, harnessLabel, harnessSchema, hasGrantedAppScopes, hasRequestSourceIdentity, isActiveGenerationTask, isAppId, isBillingAccessBlockedCode, isBillingAccessBlockedError, isDesktopCallMethod, isFeatureNotEntitledError, isGenerationModelHidden, isHttpErrorCode, isLocalHarness, isNativeClientTurn, isProjectionCompaction, isProjectionPendingGeneration, isRequestSourceClientId, isRequestSourceEmpty, isRequestSourceUuid, isTerminalDesktopCommandStatus, isTextMime, isUserLevelPermission, isUuid, isWorkId, joinApiUrl, localHarnessSchema, matchesUnauthorizedErrorToken, mergeRequestSourceIntoMeta, mimeTypeForPath, nativeIngestTurnSchema, nativeRuntimeEventSchema, nativeTurnCompleteSchema, nativeTurnProgressSchema, normalizeBaseUrl, normalizeDisplayPoint, normalizeGenerationPolicy, normalizeRequestSource, normalizeSessionTurnOrigin, normalizeSpacePickerQuery, normalizeVoiceInputWebsocketUrl, normalizeWebsocketUrl, orderSpacePickerItems, parseAppRef, parseAppSurfaceReady, parseAppSurfaceResponse, parseAssistantMessageCommit, parseBoardDocument, parseBoardItem, parseDesktopCommand, parseGenerationPolicyFromEnv, parseRequestSourceFromHeaders, parseSpaceRef, parseWorkRef, projectNativeMessageMeta, projectNativeSession, readRequestSourceFromEnv, readSentTurns, readSessionTurnOrigin, requestSourceToHeaders, resolveApiBaseUrl, resolveAppTransport, resolveAppTransport as resolveWorkTransport, resolveCohubEnvironment, resolveExecutionAppId, resolveExecutionToken, resolveHarness, resolveOpenSurface, resolveRequestSourceChannel, resolveVoiceInputWebsocketUrl, resolveWebBaseUrl, resolveWebsocketUrl, runtimeCommandSchema, runtimeEventSchema, runtimeNativeStopSchema, runtimeReadySchema, sanitizeAccessToken, scopeListHasPermission, selectRuntimeContextMessages, selectSpacePickerItems, serializeProjection, serializeProjectionRecords, setGrantedAppScopes, toGenerationTaskView, trimProjectionTurnsToCompaction, validateArchiveBoundary };
7138
+ export { APP_APPEARANCE_TOKENS, APP_COMPOSER_CHIP_CONTENT_MAX_BYTES, APP_COMPOSER_CHIP_KEY_MAX_LENGTH, APP_COMPOSER_CHIP_LABEL_MAX_LENGTH, APP_DEVICES, APP_SURFACE_READY_TIMEOUT_MS, APP_SURFACE_REQUEST_TIMEOUT_MS, AppCommerceApi, AppRealtimeApi, AppRefParseError, AppRoom, AppRoomRtc, AppRtcChannel, AppRtcError, AppRuntimeApi, AppRuntimeApi as WorkRuntimeApi, AppRuntimeError, AppSurfaceApi, AppWindowApi, AppsApi, BILLING_ACCESS_BLOCKED_ERROR_CODE, BOARD_COLOR_TOKENS, BOARD_ITEM_TYPES, BillingApi, BoardAnimationSchema, BoardClient, BoardPatchSchema, BoardTrackSchema, COHUB_ENVIRONMENTS, COHUB_SOURCE_HEADER, COHUB_SOURCE_HEADER_NAMES, CohubClient, CohubHttpClient, DESKTOP_COMMAND_ACCEPT_TIMEOUT_MS, DESKTOP_COMMAND_DEFAULT_TIMEOUT_MS, DESKTOP_COMMAND_MAX_TIMEOUT_MS, DESKTOP_COMMAND_OPEN_TIMEOUT_MS, DESKTOP_COMMAND_PAYLOAD_MAX_BYTES, DESKTOP_COMMAND_PENDING_TTL_SECONDS, DESKTOP_COMMAND_SETTLEMENT_GRACE_SECONDS, DESKTOP_COMMAND_TERMINAL_TTL_SECONDS, DESKTOP_COMMAND_VERSION, DISPLAY_ACTION_TYPES, DISPLAY_ELEMENT_REF_PATTERN, DISPLAY_SYSTEM_ACTIONS, DesktopCommandsApi, DisplayActionError, DisplayConnection, FEATURE_NOT_ENTITLED_ERROR_CODE, GenerationPolicyError, HOME_SPACE_SLUG, HttpError, LOCAL_HARNESSES, LOCAL_HARNESS_SPECS, NATIVE_INGEST_MAX_TURNS, NATIVE_SYNC_SOURCE, OriginBrokerTransport, PERMISSIONS, ParentBridgeTransport, PopupBrokerTransport, REQUEST_SOURCE_VIA_MAX_LENGTH, RUNTIME_ARCHIVE_SEGMENT_BYTES, RUNTIME_MAX_FRAME_BYTES, RUNTIME_PROTOCOL_VERSION, RUNTIME_RECOVERY_BATCH_SIZE, ReferencesApi, ReferralsApi, RoomsApi, SETTLED_TURN_STATUSES, SessionGenerationStreamClient, SessionPatchReducer, SpaceDisplaysApi, SpacePublicFilesApi, SpaceWebhooksApi, UPLOAD_ERROR_BATCH_TOO_LARGE, UPLOAD_ERROR_FILE_TOO_LARGE, UPLOAD_ERROR_RATE_LIMITED, UPLOAD_ERROR_TOO_MANY_FILES, UPLOAD_MAX_BATCH_BYTES, UPLOAD_MAX_BATCH_FILES, UPLOAD_MAX_FILE_BYTES, USER_LEVEL_PERMISSIONS, UiCommandsApi, UsersApi, VoiceApi, VoiceInputClient, WebsocketClient, WorkCommerceApi, WorkRealtimeApi, WorkRefParseError, WorkRoom, WorkSurfaceApi, appAppearanceVar, applyAppAppearance, assertGenerationRequestAllowedByPolicy, assertHarnessAccess, attachAppEmbed, batchUploadEntries, buildAppSurfaceRequest, buildSpaceInvitePath, buildSpacePath, buildViewportContentBlock, clearGrantedAppScopes, compileDisplayActions, connectDisplay, contextToPiMessages, createAppBridgeCore, createAppBridgeCore as createWorkBridgeCore, createAppRuntime, createAppRuntime as createWorkRuntime, createCohubClient, createHttpClient, createOriginAppResolver, createSessionGenerationStreamClient, createSessionPatchReducer, createSlugAppIdResolver, createSlugAppIdResolver as createSlugWorkIdResolver, createVoiceInputClient, createWebsocketClient, decodeGenerationPolicy, defaultDesktopCommandTimeoutMs, encodeGenerationPolicy, extractBillingPayload, filterDiscoverableGenerationModels, filterGenerationDeclarationsByPolicy, filterSpacePickerItems, findGenerationModelPolicy, fingerprintProjectionTurns, formatAppRef, formatWorkRef, generationOutputSource, getAllowedGenerationModelIds, getCohubContext, harnessArchiveIndexSchema, harnessLabel, harnessSchema, hasGrantedAppScopes, hasRequestSourceIdentity, isActiveGenerationTask, isAppId, isBillingAccessBlockedCode, isBillingAccessBlockedError, isDesktopCallMethod, isFeatureNotEntitledError, isGenerationModelHidden, isHttpErrorCode, isLocalHarness, isNativeClientTurn, isProjectionCompaction, isProjectionPendingGeneration, isRequestSourceClientId, isRequestSourceEmpty, isRequestSourceUuid, isTerminalDesktopCommandStatus, isTextMime, isUserLevelPermission, isUuid, isWorkId, joinApiUrl, localHarnessSchema, matchesUnauthorizedErrorToken, mergeRequestSourceIntoMeta, mimeTypeForPath, nativeIngestTurnSchema, nativeRuntimeEventSchema, nativeTurnCompleteSchema, nativeTurnProgressSchema, normalizeBaseUrl, normalizeDisplayPoint, normalizeGenerationPolicy, normalizeRequestSource, normalizeSessionTurnOrigin, normalizeSpacePickerQuery, normalizeVoiceInputWebsocketUrl, normalizeWebsocketUrl, orderSpacePickerItems, parseAppRef, parseAppSurfaceReady, parseAppSurfaceResponse, parseAssistantMessageCommit, parseBoardDocument, parseBoardItem, parseDesktopCommand, parseGenerationPolicyFromEnv, parseRequestSourceFromHeaders, parseSpaceRef, parseWorkRef, projectNativeMessageMeta, projectNativeSession, readRequestSourceFromEnv, readSentTurns, readSessionTurnOrigin, requestSourceToHeaders, resolveApiBaseUrl, resolveAppTransport, resolveAppTransport as resolveWorkTransport, resolveCohubEnvironment, resolveExecutionAppId, resolveExecutionToken, resolveHarness, resolveOpenSurface, resolveRequestSourceChannel, resolveVoiceInputWebsocketUrl, resolveWebBaseUrl, resolveWebsocketUrl, runtimeCommandSchema, runtimeEventSchema, runtimeNativeStopSchema, runtimeReadySchema, sanitizeAccessToken, scopeListHasPermission, selectRuntimeContextMessages, selectSpacePickerItems, serializeProjection, serializeProjectionRecords, setGrantedAppScopes, toGenerationTaskView, trimProjectionTurnsToCompaction, validateArchiveBoundary };