@neta-art/cohub 5.7.0 → 5.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -5
- package/dist/board/core/palette.d.ts +3 -2
- package/dist/board/core/shape-types.d.ts +3 -1
- package/dist/board/core/shape-types.js +3 -7
- package/dist/board/core/tool-styles.d.ts +2 -1
- package/dist/board/image-key.js +3 -5
- package/dist/board/index.d.ts +9 -4
- package/dist/board/index.js +7 -3
- package/dist/board/media-playback.d.ts +22 -0
- package/dist/board/media-playback.js +67 -0
- package/dist/board/media.d.ts +7 -0
- package/dist/board/media.js +70 -0
- package/dist/board/nodes.d.ts +113 -0
- package/dist/board/nodes.js +154 -0
- package/dist/board/render/index.d.ts +3 -1
- package/dist/board/render/index.js +4 -2
- package/dist/board/render/media-interaction.d.ts +19 -0
- package/dist/board/render/media-interaction.js +26 -0
- package/dist/board/render/renderers/audio-card-renderer.js +1 -1
- package/dist/board/render/renderers/board-renderer-registry.js +2 -2
- package/dist/board/render/renderers/draw-card-renderer.js +1 -1
- package/dist/board/render/renderers/file-card-renderer.js +1 -1
- package/dist/board/render/renderers/frame-card-renderer.js +1 -1
- package/dist/board/render/renderers/geo-card-renderer.js +1 -1
- package/dist/board/render/renderers/image-card-renderer.js +1 -1
- package/dist/board/render/renderers/task-card-renderer.js +16 -13
- package/dist/board/render/renderers/text-card-renderer.js +1 -1
- package/dist/board/render/renderers/unknown-card-renderer.js +1 -1
- package/dist/board/render/renderers/video-card-renderer.js +1 -1
- package/dist/board/render/video-thumbnail.d.ts +16 -0
- package/dist/board/render/video-thumbnail.js +86 -0
- package/dist/board/task.d.ts +10 -5
- package/dist/board/task.js +159 -103
- package/dist/chunks/environment.d.ts +6 -6
- package/dist/chunks/environment.js +6 -6
- package/dist/chunks/http.d.ts +152 -5
- package/dist/chunks/http.js +1707 -169
- package/dist/chunks/transport.js +24 -4
- package/dist/chunks/websocket.d.ts +144 -2
- package/dist/chunks/websocket.js +1 -1
- package/dist/http.d.ts +3 -3
- package/dist/index.d.ts +273 -4
- package/dist/index.js +275 -741
- package/dist/protocol/dist/board-connection.d.ts +7 -0
- package/dist/protocol/dist/board-connection.js +4 -0
- package/dist/protocol/dist/board-content.d.ts +1 -0
- package/dist/protocol/dist/board-content.js +26 -0
- package/dist/protocol/dist/board-document.d.ts +157 -48
- package/dist/protocol/dist/board-document.js +40 -19
- package/dist/protocol/dist/board-node.d.ts +18 -0
- package/dist/protocol/dist/board-node.js +239 -0
- package/dist/protocol/dist/board-url.d.ts +12 -0
- package/dist/protocol/dist/board-url.js +83 -0
- package/dist/protocol/dist/board.d.ts +5 -0
- package/dist/protocol/dist/identifiers.js +10 -0
- package/dist/protocol/dist/index.d.ts +3 -1
- package/dist/protocol/dist/index.js +7 -1
- package/dist/protocol/dist/provenance.js +2 -0
- package/dist/protocol/dist/ui-command.js +2 -0
- package/dist/protocol/dist/work-promotion-stats.js +11 -0
- package/dist/protocol/dist/work-surface.js +2 -0
- package/dist/protocol/dist/work-view-stats.js +1 -0
- package/docs/work-runtime-guide.md +7 -7
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,9 +1,249 @@
|
|
|
1
|
-
import { A as
|
|
2
|
-
import { _ as requestSourceToHeaders, a as sanitizeAccessToken, b as
|
|
1
|
+
import { $ as parseUsername, A as WORK_SURFACE_READY_TIMEOUT_MS, B as parseWorkSurfaceRequest, C as BoardInputError, D as WORK_COMPOSER_CHIP_CONTENT_MAX_BYTES, E as validateBoardNodes, F as buildWorkSurfaceRequest, G as UI_COMMAND_PENDING_TTL_SECONDS, H as UI_COMMAND_DEFAULT_TIMEOUT_MS, I as buildWorkSurfaceResponse, J as UI_COMMAND_VERSION, K as UI_COMMAND_SETTLEMENT_GRACE_SECONDS, L as parseWorkComposerChipClear, M as buildWorkComposerChipClear, N as buildWorkComposerChipSet, O as WORK_COMPOSER_CHIP_KEY_MAX_LENGTH, P as buildWorkSurfaceReady, Q as parseSpaceSlug, R as parseWorkComposerChipSet, S as createSessionPatchReducer, T as createBoardNode, U as UI_COMMAND_MAX_TIMEOUT_MS, V as parseWorkSurfaceResponse, W as UI_COMMAND_PAYLOAD_MAX_BYTES, X as isUiSurfaceMethod, Y as isTerminalUiCommandStatus, Z as parseUiCommand, _ as buildSpacePath, _t as ModelsApi, a as ReferralsApi, at as validateBoardNodeInput, b as parseAssistantMessageCommit, bt as ChannelsApi, c as UiCommandsApi, ct as ensureRealtimeConnected, d as BoardTransactionError, dt as SessionAccessApi, et as BoardAwarenessClientPayloadSchema, f as SpaceClient, ft as ReferencesApi, g as buildSpaceInvitePath, gt as PromptsApi, h as PublicInviteApi, ht as SkillsApi, i as WorksApi, it as BOARD_NODE_CONTRACT, j as WORK_SURFACE_REQUEST_TIMEOUT_MS, k as WORK_COMPOSER_CHIP_LABEL_MAX_LENGTH, l as TasksApi, lt as BOARD_BUILTIN_CAPABILITIES, m as SpacesApi, mt as PublicAssetsApi, n as createHttpClient, nt as BOARD_GEO_KINDS, o as UsersApi, ot as BoardPlaybackPolicySchema, p as SpacePublicFilesApi, pt as SearchApi, q as UI_COMMAND_TERMINAL_TTL_SECONDS, r as WorkCommerceApi, rt as BOARD_NATIVE_NODE_TYPES, s as UserApi, st as parseBoardPlaybackPolicy, t as CohubHttpClient, tt as BOARD_COLOR_IDS, u as BoardClient, ut as DEFAULT_BOARD_RENDER_LIMITS, v as SessionGenerationStreamClient, vt as GenerationsApi, w as assertBoardNodes, x as SessionPatchReducer, y as createSessionGenerationStreamClient, yt as CronJobsApi, z as parseWorkSurfaceReady } from "./chunks/http.js";
|
|
2
|
+
import { _ as requestSourceToHeaders, a as sanitizeAccessToken, b as REALTIME_DOMAINS, c as REQUEST_SOURCE_VIA_MAX_LENGTH, d as isRequestSourceEmpty, f as isRequestSourceUuid, g as readRequestSourceFromEnv, h as parseRequestSourceFromHeaders, i as matchesUnauthorizedErrorToken, l as hasRequestSourceIdentity, m as normalizeRequestSource, n as HttpTransport, o as COHUB_SOURCE_HEADER, p as mergeRequestSourceIntoMeta, r as joinApiUrl, s as COHUB_SOURCE_HEADER_NAMES, t as HttpError, u as isRequestSourceClientId, v as resolveRequestSourceChannel, x as REALTIME_ROOM_EVENT_NAME_PATTERN, y as isUuid } from "./chunks/transport.js";
|
|
3
3
|
import { a as resolveApiBaseUrl, c as resolveWebsocketUrl, i as normalizeWebsocketUrl, n as normalizeBaseUrl, o as resolveCohubEnvironment, r as normalizeVoiceInputWebsocketUrl, s as resolveVoiceInputWebsocketUrl, t as COHUB_ENVIRONMENTS } from "./chunks/environment.js";
|
|
4
4
|
import { a as extractBillingPayload, c as isFeatureNotEntitledError, i as FEATURE_NOT_ENTITLED_ERROR_CODE, l as isHttpErrorCode, n as createWebsocketClient, o as isBillingAccessBlockedCode, r as BILLING_ACCESS_BLOCKED_ERROR_CODE, s as isBillingAccessBlockedError, t as WebsocketClient } from "./chunks/websocket.js";
|
|
5
5
|
import { VoiceApi, VoiceInputClient, createVoiceInputClient } from "./voice-input.js";
|
|
6
6
|
import { z } from "zod";
|
|
7
|
+
//#region ../protocol/dist/generation/catalog.js
|
|
8
|
+
function isGenerationModelHidden(model) {
|
|
9
|
+
return model.hidden === true;
|
|
10
|
+
}
|
|
11
|
+
function filterDiscoverableGenerationModels(models, options = {}) {
|
|
12
|
+
const includeModelIds = new Set(options.includeModelIds);
|
|
13
|
+
return models.filter((model) => !isGenerationModelHidden(model) || includeModelIds.has(model.model));
|
|
14
|
+
}
|
|
15
|
+
//#endregion
|
|
16
|
+
//#region ../protocol/dist/generation/policy.js
|
|
17
|
+
const GENERATION_POLICY_ENV_KEY = "COHUB_GENERATION_POLICY_B64";
|
|
18
|
+
var GenerationPolicyError = class extends Error {
|
|
19
|
+
constructor(message) {
|
|
20
|
+
super(message);
|
|
21
|
+
this.name = "GenerationPolicyError";
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
function isRecord(value) {
|
|
25
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
26
|
+
}
|
|
27
|
+
function isPrimitiveEnumValue(value) {
|
|
28
|
+
return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
29
|
+
}
|
|
30
|
+
function normalizeConstraint(value) {
|
|
31
|
+
if (!isRecord(value) || typeof value.kind !== "string") return null;
|
|
32
|
+
if (value.kind === "enum") {
|
|
33
|
+
if (!Array.isArray(value.values) || value.values.length === 0 || !value.values.every(isPrimitiveEnumValue)) return null;
|
|
34
|
+
return {
|
|
35
|
+
kind: "enum",
|
|
36
|
+
values: value.values
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
if (value.kind === "number" || value.kind === "integer") {
|
|
40
|
+
const result = { kind: value.kind };
|
|
41
|
+
if (typeof value.min === "number" && Number.isFinite(value.min)) result.min = value.min;
|
|
42
|
+
if (typeof value.max === "number" && Number.isFinite(value.max)) result.max = value.max;
|
|
43
|
+
if (result.min !== void 0 && result.max !== void 0 && result.min > result.max) return null;
|
|
44
|
+
if (Array.isArray(value.values) && value.values.every((item) => typeof item === "number" && Number.isFinite(item))) {
|
|
45
|
+
if (value.kind === "integer" && !value.values.every(Number.isInteger)) return null;
|
|
46
|
+
const min = result.min;
|
|
47
|
+
const max = result.max;
|
|
48
|
+
if (min !== void 0 && value.values.some((item) => item < min)) return null;
|
|
49
|
+
if (max !== void 0 && value.values.some((item) => item > max)) return null;
|
|
50
|
+
result.values = value.values;
|
|
51
|
+
}
|
|
52
|
+
return result;
|
|
53
|
+
}
|
|
54
|
+
if (value.kind === "boolean") return typeof value.value === "boolean" ? {
|
|
55
|
+
kind: "boolean",
|
|
56
|
+
value: value.value
|
|
57
|
+
} : { kind: "boolean" };
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
function normalizeGenerationPolicy(value) {
|
|
61
|
+
if (!isRecord(value) || value.version !== 1) return null;
|
|
62
|
+
if (value.mode === "auto") return {
|
|
63
|
+
version: 1,
|
|
64
|
+
mode: "auto"
|
|
65
|
+
};
|
|
66
|
+
if (value.mode !== "limited" || !Array.isArray(value.models) || value.models.length === 0) return null;
|
|
67
|
+
const models = [];
|
|
68
|
+
for (const item of value.models) {
|
|
69
|
+
if (!isRecord(item) || typeof item.model !== "string" || !item.model.trim()) return null;
|
|
70
|
+
const modelPolicy = { model: item.model.trim() };
|
|
71
|
+
if (item.parameters !== void 0) {
|
|
72
|
+
if (!isRecord(item.parameters)) return null;
|
|
73
|
+
const parameters = {};
|
|
74
|
+
for (const [key, rawConstraint] of Object.entries(item.parameters)) {
|
|
75
|
+
if (!key.trim()) return null;
|
|
76
|
+
const constraint = normalizeConstraint(rawConstraint);
|
|
77
|
+
if (!constraint) return null;
|
|
78
|
+
parameters[key] = constraint;
|
|
79
|
+
}
|
|
80
|
+
if (Object.keys(parameters).length > 0) modelPolicy.parameters = parameters;
|
|
81
|
+
}
|
|
82
|
+
models.push(modelPolicy);
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
version: 1,
|
|
86
|
+
mode: "limited",
|
|
87
|
+
models
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function bytesToBase64(bytes) {
|
|
91
|
+
let binary = "";
|
|
92
|
+
for (const byte of bytes) binary += String.fromCharCode(byte);
|
|
93
|
+
return btoa(binary);
|
|
94
|
+
}
|
|
95
|
+
function base64ToBytes(value) {
|
|
96
|
+
const binary = atob(value);
|
|
97
|
+
const bytes = new Uint8Array(binary.length);
|
|
98
|
+
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
99
|
+
return bytes;
|
|
100
|
+
}
|
|
101
|
+
function toBase64Url(value) {
|
|
102
|
+
return bytesToBase64(new TextEncoder().encode(value)).replaceAll("+", "-").replaceAll("/", "_").replaceAll("=", "");
|
|
103
|
+
}
|
|
104
|
+
function fromBase64Url(value) {
|
|
105
|
+
const base64 = value.replaceAll("-", "+").replaceAll("_", "/");
|
|
106
|
+
const padded = base64.padEnd(base64.length + (4 - base64.length % 4) % 4, "=");
|
|
107
|
+
return new TextDecoder().decode(base64ToBytes(padded));
|
|
108
|
+
}
|
|
109
|
+
function encodeGenerationPolicy(policy) {
|
|
110
|
+
return toBase64Url(JSON.stringify(policy));
|
|
111
|
+
}
|
|
112
|
+
function decodeGenerationPolicy(value) {
|
|
113
|
+
try {
|
|
114
|
+
return normalizeGenerationPolicy(JSON.parse(fromBase64Url(value)));
|
|
115
|
+
} catch {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function parseGenerationPolicyFromEnv(env) {
|
|
120
|
+
const value = env[GENERATION_POLICY_ENV_KEY]?.trim();
|
|
121
|
+
return value ? decodeGenerationPolicy(value) : null;
|
|
122
|
+
}
|
|
123
|
+
function getAllowedGenerationModelIds(policy) {
|
|
124
|
+
if (!policy || policy.mode === "auto") return null;
|
|
125
|
+
return [...new Set((policy.models ?? []).map((item) => item.model))];
|
|
126
|
+
}
|
|
127
|
+
function findGenerationModelPolicy(policy, model) {
|
|
128
|
+
if (!policy || policy.mode === "auto") return null;
|
|
129
|
+
return policy.models?.find((item) => item.model === model) ?? null;
|
|
130
|
+
}
|
|
131
|
+
function formatList(values) {
|
|
132
|
+
return values.map((value) => `- ${String(value)}`).join("\n");
|
|
133
|
+
}
|
|
134
|
+
function modelNotSupportedMessage(allowedModels) {
|
|
135
|
+
return [
|
|
136
|
+
"This turn supports the following generation models:",
|
|
137
|
+
"",
|
|
138
|
+
formatList(allowedModels),
|
|
139
|
+
"",
|
|
140
|
+
"Choose one of these models or update Generation settings in the Models panel."
|
|
141
|
+
].join("\n");
|
|
142
|
+
}
|
|
143
|
+
function valuesNotSupportedMessage(model, name, values, received) {
|
|
144
|
+
return [
|
|
145
|
+
`This turn supports selected values for ${model}.${name}:`,
|
|
146
|
+
"",
|
|
147
|
+
formatList(values),
|
|
148
|
+
"",
|
|
149
|
+
"Received:",
|
|
150
|
+
`- ${String(received)}`
|
|
151
|
+
].join("\n");
|
|
152
|
+
}
|
|
153
|
+
function rangeNotSupportedMessage(model, name, min, max, received) {
|
|
154
|
+
return [
|
|
155
|
+
`This turn supports ${model}.${name} in the range ${min !== void 0 && max !== void 0 ? `${min}–${max}` : min !== void 0 ? `at least ${min}` : `at most ${max}`}.`,
|
|
156
|
+
"",
|
|
157
|
+
"Received:",
|
|
158
|
+
`- ${String(received)}`
|
|
159
|
+
].join("\n");
|
|
160
|
+
}
|
|
161
|
+
function booleanNotSupportedMessage(model, name, expected, received) {
|
|
162
|
+
return [
|
|
163
|
+
`This turn supports ${model}.${name}=${String(expected)}.`,
|
|
164
|
+
"",
|
|
165
|
+
"Received:",
|
|
166
|
+
`- ${String(received)}`
|
|
167
|
+
].join("\n");
|
|
168
|
+
}
|
|
169
|
+
function sameEnumValue(a, b) {
|
|
170
|
+
return typeof a === typeof b && a === b;
|
|
171
|
+
}
|
|
172
|
+
function validateConstraint(input) {
|
|
173
|
+
const { model, name, value, constraint } = input;
|
|
174
|
+
if (constraint.kind === "enum") {
|
|
175
|
+
if (!constraint.values.some((item) => sameEnumValue(item, value))) throw new GenerationPolicyError(valuesNotSupportedMessage(model, name, constraint.values, value));
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
if (constraint.kind === "number" || constraint.kind === "integer") {
|
|
179
|
+
if (typeof value !== "number" || !Number.isFinite(value)) throw new GenerationPolicyError(rangeNotSupportedMessage(model, name, constraint.min, constraint.max, value));
|
|
180
|
+
if (constraint.kind === "integer" && !Number.isInteger(value)) throw new GenerationPolicyError(rangeNotSupportedMessage(model, name, constraint.min, constraint.max, value));
|
|
181
|
+
if (constraint.values?.length && !constraint.values.includes(value)) throw new GenerationPolicyError(valuesNotSupportedMessage(model, name, constraint.values, value));
|
|
182
|
+
if (constraint.min !== void 0 && value < constraint.min) throw new GenerationPolicyError(rangeNotSupportedMessage(model, name, constraint.min, constraint.max, value));
|
|
183
|
+
if (constraint.max !== void 0 && value > constraint.max) throw new GenerationPolicyError(rangeNotSupportedMessage(model, name, constraint.min, constraint.max, value));
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
if (constraint.kind === "boolean" && constraint.value !== void 0 && value !== constraint.value) throw new GenerationPolicyError(booleanNotSupportedMessage(model, name, constraint.value, value));
|
|
187
|
+
}
|
|
188
|
+
function assertGenerationRequestAllowedByPolicy(input) {
|
|
189
|
+
const allowedModels = getAllowedGenerationModelIds(input.policy);
|
|
190
|
+
if (!allowedModels) return;
|
|
191
|
+
const modelPolicy = findGenerationModelPolicy(input.policy, input.model);
|
|
192
|
+
if (!modelPolicy) throw new GenerationPolicyError(modelNotSupportedMessage(allowedModels));
|
|
193
|
+
const parameters = input.parameters ?? {};
|
|
194
|
+
for (const [name, value] of Object.entries(parameters)) {
|
|
195
|
+
const constraint = modelPolicy.parameters?.[name];
|
|
196
|
+
if (!constraint) continue;
|
|
197
|
+
validateConstraint({
|
|
198
|
+
model: input.model,
|
|
199
|
+
name,
|
|
200
|
+
value,
|
|
201
|
+
constraint
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
function cloneDeclaration(declaration) {
|
|
206
|
+
return {
|
|
207
|
+
...declaration,
|
|
208
|
+
content: {
|
|
209
|
+
...declaration.content,
|
|
210
|
+
input: [...declaration.content.input]
|
|
211
|
+
},
|
|
212
|
+
parameters: declaration.parameters ? Object.fromEntries(Object.entries(declaration.parameters).map(([key, value]) => [key, { ...value }])) : declaration.parameters,
|
|
213
|
+
examples: declaration.examples ? [...declaration.examples] : declaration.examples
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
function narrowParameterSpec(spec, constraint) {
|
|
217
|
+
const next = { ...spec };
|
|
218
|
+
if (constraint.kind === "enum") {
|
|
219
|
+
if ("enum" in next && Array.isArray(next.enum)) next.enum = next.enum.filter((value) => constraint.values.some((allowed) => sameEnumValue(allowed, value)));
|
|
220
|
+
return next;
|
|
221
|
+
}
|
|
222
|
+
if (constraint.kind === "number" || constraint.kind === "integer") {
|
|
223
|
+
if ("min" in next && typeof next.min === "number" && constraint.min !== void 0) next.min = Math.max(next.min, constraint.min);
|
|
224
|
+
else if ("min" in next && constraint.min !== void 0) next.min = constraint.min;
|
|
225
|
+
if ("max" in next && typeof next.max === "number" && constraint.max !== void 0) next.max = Math.min(next.max, constraint.max);
|
|
226
|
+
else if ("max" in next && constraint.max !== void 0) next.max = constraint.max;
|
|
227
|
+
if (constraint.values?.length && "enum" in next && Array.isArray(next.enum)) next.enum = next.enum.filter((value) => constraint.values?.some((allowed) => sameEnumValue(allowed, value)));
|
|
228
|
+
}
|
|
229
|
+
return next;
|
|
230
|
+
}
|
|
231
|
+
function filterGenerationDeclarationsByPolicy(declarations, policy) {
|
|
232
|
+
const allowedModels = getAllowedGenerationModelIds(policy);
|
|
233
|
+
if (!allowedModels) return declarations;
|
|
234
|
+
const allowedSet = new Set(allowedModels);
|
|
235
|
+
return declarations.filter((declaration) => allowedSet.has(declaration.model)).map((declaration) => {
|
|
236
|
+
const cloned = cloneDeclaration(declaration);
|
|
237
|
+
const modelPolicy = findGenerationModelPolicy(policy, declaration.model);
|
|
238
|
+
if (!modelPolicy?.parameters || !cloned.parameters) return cloned;
|
|
239
|
+
for (const [name, constraint] of Object.entries(modelPolicy.parameters)) {
|
|
240
|
+
const spec = cloned.parameters[name];
|
|
241
|
+
if (spec) cloned.parameters[name] = narrowParameterSpec(spec, constraint);
|
|
242
|
+
}
|
|
243
|
+
return cloned;
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
//#endregion
|
|
7
247
|
//#region src/apis/billing.ts
|
|
8
248
|
var BillingApi = class {
|
|
9
249
|
transport;
|
|
@@ -35,6 +275,12 @@ var BillingApi = class {
|
|
|
35
275
|
const query = params.toString();
|
|
36
276
|
return this.transport.request(`/api/billing/subscriptions${query ? `?${query}` : ""}`);
|
|
37
277
|
}
|
|
278
|
+
async previewPromotionCode(input) {
|
|
279
|
+
return this.transport.request("/api/billing/promotion-code-preview", {
|
|
280
|
+
method: "POST",
|
|
281
|
+
body: JSON.stringify(input)
|
|
282
|
+
});
|
|
283
|
+
}
|
|
38
284
|
async createOrder(productKey, input) {
|
|
39
285
|
return this.transport.request("/api/billing/orders", {
|
|
40
286
|
method: "POST",
|
|
@@ -70,130 +316,14 @@ var BillingApi = class {
|
|
|
70
316
|
}
|
|
71
317
|
};
|
|
72
318
|
//#endregion
|
|
73
|
-
//#region ../protocol/dist/realtime/
|
|
74
|
-
const
|
|
75
|
-
const
|
|
76
|
-
const
|
|
77
|
-
x: finiteSchema$1,
|
|
78
|
-
y: finiteSchema$1
|
|
79
|
-
});
|
|
80
|
-
const BoardAwarenessDrawPointSchema = BoardAwarenessPointSchema.extend({ p: finiteSchema$1.min(0).max(1) });
|
|
81
|
-
const BoardAwarenessFrameSchema = z.object({
|
|
82
|
-
x: finiteSchema$1,
|
|
83
|
-
y: finiteSchema$1,
|
|
84
|
-
width: finiteSchema$1.positive(),
|
|
85
|
-
height: finiteSchema$1.positive(),
|
|
86
|
-
rotation: finiteSchema$1
|
|
87
|
-
});
|
|
88
|
-
const BoardAwarenessNodePreviewSchema = z.object({
|
|
89
|
-
nodeId: idSchema$1,
|
|
90
|
-
frame: BoardAwarenessFrameSchema,
|
|
91
|
-
/** Live endpoints of a free arrow being dragged. */
|
|
92
|
-
arrow: z.object({
|
|
93
|
-
start: BoardAwarenessPointSchema,
|
|
94
|
-
end: BoardAwarenessPointSchema,
|
|
95
|
-
bend: finiteSchema$1
|
|
96
|
-
}).optional()
|
|
97
|
-
});
|
|
98
|
-
const BoardAwarenessStateUpdateSchema = z.object({
|
|
99
|
-
type: z.literal("state"),
|
|
100
|
-
client: z.object({ formFactor: z.enum(["desktop", "mobile"]) }).optional(),
|
|
101
|
-
cursor: BoardAwarenessPointSchema.extend({ pointerType: z.enum([
|
|
102
|
-
"mouse",
|
|
103
|
-
"pen",
|
|
104
|
-
"touch"
|
|
105
|
-
]) }).nullable(),
|
|
106
|
-
tool: z.string().min(1).max(40),
|
|
107
|
-
selection: z.object({
|
|
108
|
-
ids: z.array(idSchema$1).max(64),
|
|
109
|
-
count: z.number().int().nonnegative().max(5e4),
|
|
110
|
-
bounds: BoardAwarenessFrameSchema.nullable()
|
|
111
|
-
}),
|
|
112
|
-
editingId: idSchema$1.nullable()
|
|
113
|
-
});
|
|
114
|
-
const BoardAwarenessGestureSchema = z.discriminatedUnion("kind", [
|
|
319
|
+
//#region ../protocol/dist/realtime/schema.js
|
|
320
|
+
const contentBlockMetaSchema = z.record(z.string(), z.unknown());
|
|
321
|
+
const realtimeRoomSchema = z.string().regex(/^(space|user|board|room):[^:]+$/);
|
|
322
|
+
const contentBlockSchema = z.discriminatedUnion("type", [
|
|
115
323
|
z.object({
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
color: z.string().min(1).max(64),
|
|
120
|
-
size: finiteSchema$1.positive().max(256),
|
|
121
|
-
from: z.number().int().nonnegative().max(1e5),
|
|
122
|
-
points: z.array(BoardAwarenessDrawPointSchema).min(1).max(64)
|
|
123
|
-
}),
|
|
124
|
-
z.object({
|
|
125
|
-
kind: z.literal("arrow"),
|
|
126
|
-
id: idSchema$1,
|
|
127
|
-
nodeId: idSchema$1,
|
|
128
|
-
start: BoardAwarenessPointSchema,
|
|
129
|
-
current: BoardAwarenessPointSchema,
|
|
130
|
-
color: z.string().min(1).max(64),
|
|
131
|
-
size: finiteSchema$1.positive().max(256).default(BOARD_ARROW_STROKE_SIZE)
|
|
132
|
-
}),
|
|
133
|
-
z.object({
|
|
134
|
-
kind: z.literal("box"),
|
|
135
|
-
id: idSchema$1,
|
|
136
|
-
nodeId: idSchema$1,
|
|
137
|
-
shape: z.enum(["geo", "frame"]),
|
|
138
|
-
start: BoardAwarenessPointSchema,
|
|
139
|
-
current: BoardAwarenessPointSchema,
|
|
140
|
-
color: z.string().min(1).max(64),
|
|
141
|
-
geo: z.string().min(1).max(40)
|
|
142
|
-
}),
|
|
143
|
-
z.object({
|
|
144
|
-
kind: z.literal("connection"),
|
|
145
|
-
id: idSchema$1,
|
|
146
|
-
sourceNodeId: idSchema$1,
|
|
147
|
-
targetNodeId: idSchema$1.nullable(),
|
|
148
|
-
current: BoardAwarenessPointSchema,
|
|
149
|
-
color: z.string().min(1).max(64),
|
|
150
|
-
size: finiteSchema$1.positive().max(256).default(BOARD_CONNECTION_STROKE_SIZE)
|
|
151
|
-
}),
|
|
152
|
-
z.object({
|
|
153
|
-
kind: z.literal("transform"),
|
|
154
|
-
id: idSchema$1,
|
|
155
|
-
mode: z.enum([
|
|
156
|
-
"translate",
|
|
157
|
-
"resize",
|
|
158
|
-
"rotate",
|
|
159
|
-
"arrow",
|
|
160
|
-
"connection"
|
|
161
|
-
]),
|
|
162
|
-
nodes: z.array(BoardAwarenessNodePreviewSchema).max(64),
|
|
163
|
-
bounds: BoardAwarenessFrameSchema.nullable()
|
|
164
|
-
})
|
|
165
|
-
]);
|
|
166
|
-
const BoardAwarenessUpdateSchema = z.discriminatedUnion("type", [
|
|
167
|
-
BoardAwarenessStateUpdateSchema,
|
|
168
|
-
z.object({
|
|
169
|
-
type: z.literal("gesture"),
|
|
170
|
-
gesture: BoardAwarenessGestureSchema
|
|
171
|
-
}),
|
|
172
|
-
z.object({
|
|
173
|
-
type: z.literal("gesture.end"),
|
|
174
|
-
gestureId: idSchema$1,
|
|
175
|
-
resultingNodeIds: z.array(idSchema$1).max(64)
|
|
176
|
-
}),
|
|
177
|
-
z.object({
|
|
178
|
-
type: z.literal("gesture.cancel"),
|
|
179
|
-
gestureId: idSchema$1
|
|
180
|
-
})
|
|
181
|
-
]);
|
|
182
|
-
const BoardAwarenessClientPayloadSchema = z.object({
|
|
183
|
-
spaceId: z.string().uuid(),
|
|
184
|
-
boardId: z.string().uuid(),
|
|
185
|
-
seq: z.number().int().nonnegative(),
|
|
186
|
-
update: BoardAwarenessUpdateSchema
|
|
187
|
-
});
|
|
188
|
-
//#endregion
|
|
189
|
-
//#region ../protocol/dist/realtime/schema.js
|
|
190
|
-
const contentBlockMetaSchema = z.record(z.string(), z.unknown());
|
|
191
|
-
const realtimeRoomSchema = z.string().regex(/^(space|user|board|room):[^:]+$/);
|
|
192
|
-
const contentBlockSchema = z.discriminatedUnion("type", [
|
|
193
|
-
z.object({
|
|
194
|
-
type: z.literal("text"),
|
|
195
|
-
text: z.string(),
|
|
196
|
-
_meta: contentBlockMetaSchema.optional()
|
|
324
|
+
type: z.literal("text"),
|
|
325
|
+
text: z.string(),
|
|
326
|
+
_meta: contentBlockMetaSchema.optional()
|
|
197
327
|
}),
|
|
198
328
|
z.object({
|
|
199
329
|
type: z.literal("thinking"),
|
|
@@ -796,130 +926,16 @@ var WorkRealtimeApi = class {
|
|
|
796
926
|
}
|
|
797
927
|
};
|
|
798
928
|
//#endregion
|
|
799
|
-
//#region ../protocol/dist/work-surface.js
|
|
800
|
-
const WORK_SURFACE_PROTOCOL = "cohub.surface";
|
|
801
|
-
const WORK_SURFACE_READY_TIMEOUT_MS = 1e4;
|
|
802
|
-
const WORK_SURFACE_REQUEST_TIMEOUT_MS = 15e3;
|
|
803
|
-
const WORK_COMPOSER_CHIP_KEY_MAX_LENGTH = 80;
|
|
804
|
-
const WORK_COMPOSER_CHIP_LABEL_MAX_LENGTH = 120;
|
|
805
|
-
const WORK_COMPOSER_CHIP_CONTENT_MAX_BYTES = 32 * 1024;
|
|
806
|
-
const isRecord$1 = (value) => Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
807
|
-
const isSurfaceEnvelope = (value) => isRecord$1(value) && value.protocol === "cohub.surface" && value.version === 1;
|
|
808
|
-
const parseWorkSurfaceReady = (value) => {
|
|
809
|
-
if (!isSurfaceEnvelope(value) || value.type !== "ready") return null;
|
|
810
|
-
const methods = Array.isArray(value.methods) ? value.methods.filter((method) => typeof method === "string" && Boolean(method)) : [];
|
|
811
|
-
return {
|
|
812
|
-
protocol: WORK_SURFACE_PROTOCOL,
|
|
813
|
-
version: 1,
|
|
814
|
-
type: "ready",
|
|
815
|
-
methods
|
|
816
|
-
};
|
|
817
|
-
};
|
|
818
|
-
const parseWorkSurfaceResponse = (value) => {
|
|
819
|
-
if (!isSurfaceEnvelope(value) || value.type !== "response") return null;
|
|
820
|
-
if (typeof value.requestId !== "string" || !value.requestId) return null;
|
|
821
|
-
const error = isRecord$1(value.error) ? {
|
|
822
|
-
code: typeof value.error.code === "string" && value.error.code ? value.error.code : "surface_error",
|
|
823
|
-
message: typeof value.error.message === "string" ? value.error.message : "Work surface call failed"
|
|
824
|
-
} : void 0;
|
|
825
|
-
return {
|
|
826
|
-
protocol: WORK_SURFACE_PROTOCOL,
|
|
827
|
-
version: 1,
|
|
828
|
-
type: "response",
|
|
829
|
-
requestId: value.requestId,
|
|
830
|
-
ok: value.ok === true,
|
|
831
|
-
...error ? { error } : {}
|
|
832
|
-
};
|
|
833
|
-
};
|
|
834
|
-
const parseComposerChipKey = (value) => {
|
|
835
|
-
if (typeof value !== "string") return null;
|
|
836
|
-
const key = value.trim();
|
|
837
|
-
if (!key || key.length > 80) return null;
|
|
838
|
-
return key;
|
|
839
|
-
};
|
|
840
|
-
const parseWorkComposerChipSet = (value) => {
|
|
841
|
-
if (!isSurfaceEnvelope(value) || value.type !== "composer.chip.set" || !isRecord$1(value.chip)) return null;
|
|
842
|
-
const key = parseComposerChipKey(value.chip.key);
|
|
843
|
-
if (!key || typeof value.chip.label !== "string" || typeof value.chip.content !== "string") return null;
|
|
844
|
-
const label = value.chip.label.trim();
|
|
845
|
-
if (!label || label.length > 120) return null;
|
|
846
|
-
if (!value.chip.content.trim()) return null;
|
|
847
|
-
if (new TextEncoder().encode(value.chip.content).length > 32768) return null;
|
|
848
|
-
return {
|
|
849
|
-
protocol: WORK_SURFACE_PROTOCOL,
|
|
850
|
-
version: 1,
|
|
851
|
-
type: "composer.chip.set",
|
|
852
|
-
chip: {
|
|
853
|
-
key,
|
|
854
|
-
label,
|
|
855
|
-
content: value.chip.content
|
|
856
|
-
}
|
|
857
|
-
};
|
|
858
|
-
};
|
|
859
|
-
const parseWorkComposerChipClear = (value) => {
|
|
860
|
-
if (!isSurfaceEnvelope(value) || value.type !== "composer.chip.clear") return null;
|
|
861
|
-
const key = parseComposerChipKey(value.key);
|
|
862
|
-
return key ? {
|
|
863
|
-
protocol: WORK_SURFACE_PROTOCOL,
|
|
864
|
-
version: 1,
|
|
865
|
-
type: "composer.chip.clear",
|
|
866
|
-
key
|
|
867
|
-
} : null;
|
|
868
|
-
};
|
|
869
|
-
const parseWorkSurfaceRequest = (value) => {
|
|
870
|
-
if (!isSurfaceEnvelope(value) || value.type !== "request") return null;
|
|
871
|
-
if (typeof value.requestId !== "string" || !value.requestId) return null;
|
|
872
|
-
if (typeof value.method !== "string" || !value.method) return null;
|
|
873
|
-
const commandId = parseUiCommandId(value.commandId);
|
|
874
|
-
if (!commandId) return null;
|
|
875
|
-
return {
|
|
876
|
-
protocol: WORK_SURFACE_PROTOCOL,
|
|
877
|
-
version: 1,
|
|
878
|
-
type: "request",
|
|
879
|
-
requestId: value.requestId,
|
|
880
|
-
method: value.method,
|
|
881
|
-
...value.input === void 0 ? {} : { input: value.input },
|
|
882
|
-
commandId
|
|
883
|
-
};
|
|
884
|
-
};
|
|
885
|
-
const buildWorkSurfaceReady = (methods) => ({
|
|
886
|
-
protocol: WORK_SURFACE_PROTOCOL,
|
|
887
|
-
version: 1,
|
|
888
|
-
type: "ready",
|
|
889
|
-
methods: [...methods]
|
|
890
|
-
});
|
|
891
|
-
const buildWorkSurfaceRequest = (input) => ({
|
|
892
|
-
protocol: WORK_SURFACE_PROTOCOL,
|
|
893
|
-
version: 1,
|
|
894
|
-
type: "request",
|
|
895
|
-
...input
|
|
896
|
-
});
|
|
897
|
-
const buildWorkSurfaceResponse = (input) => ({
|
|
898
|
-
protocol: WORK_SURFACE_PROTOCOL,
|
|
899
|
-
version: 1,
|
|
900
|
-
type: "response",
|
|
901
|
-
...input
|
|
902
|
-
});
|
|
903
|
-
const buildWorkComposerChipSet = (chip) => ({
|
|
904
|
-
protocol: WORK_SURFACE_PROTOCOL,
|
|
905
|
-
version: 1,
|
|
906
|
-
type: "composer.chip.set",
|
|
907
|
-
chip
|
|
908
|
-
});
|
|
909
|
-
const buildWorkComposerChipClear = (key) => ({
|
|
910
|
-
protocol: WORK_SURFACE_PROTOCOL,
|
|
911
|
-
version: 1,
|
|
912
|
-
type: "composer.chip.clear",
|
|
913
|
-
key
|
|
914
|
-
});
|
|
915
|
-
//#endregion
|
|
916
929
|
//#region src/work-surface.ts
|
|
917
930
|
/**
|
|
918
|
-
* Explicit app origins, not a
|
|
931
|
+
* Explicit app origins, not a Cohub suffix match: Works themselves are
|
|
919
932
|
* served from Cohub subdomains, so a suffix match would let one Work call into
|
|
920
933
|
* another and turn a subdomain takeover into surface access.
|
|
921
934
|
*/
|
|
922
935
|
const COHUB_APP_ORIGINS = [
|
|
936
|
+
"https://cohub.live",
|
|
937
|
+
"https://www.cohub.live",
|
|
938
|
+
"https://dev.cohub.live",
|
|
923
939
|
"https://cohub.run",
|
|
924
940
|
"https://www.cohub.run",
|
|
925
941
|
"https://dev.cohub.run"
|
|
@@ -1607,66 +1623,8 @@ var CohubClient = class {
|
|
|
1607
1623
|
};
|
|
1608
1624
|
const createCohubClient = (options) => new CohubClient(options);
|
|
1609
1625
|
//#endregion
|
|
1610
|
-
//#region ../protocol/dist/public-identifiers.js
|
|
1611
|
-
const USERNAME_PATTERN = /^(?!-)(?!.*--)[a-z0-9-]{1,39}(?<!-)$/;
|
|
1612
|
-
const SPACE_SLUG_PATTERN = /^[a-z0-9](?:[a-z0-9_-]{0,78}[a-z0-9])?$/;
|
|
1613
|
-
/**
|
|
1614
|
-
* Platform-owned path segments that must not be newly assigned to public
|
|
1615
|
-
* identities. Existing stored values remain readable through parse helpers.
|
|
1616
|
-
*/
|
|
1617
|
-
const RESERVED_PLATFORM_PATH_SEGMENTS = Object.freeze([
|
|
1618
|
-
"admin",
|
|
1619
|
-
"api",
|
|
1620
|
-
"assets",
|
|
1621
|
-
"auth",
|
|
1622
|
-
"callback",
|
|
1623
|
-
"changelog",
|
|
1624
|
-
"docs",
|
|
1625
|
-
"explore",
|
|
1626
|
-
"invite",
|
|
1627
|
-
"landing",
|
|
1628
|
-
"login",
|
|
1629
|
-
"logout",
|
|
1630
|
-
"new",
|
|
1631
|
-
"org",
|
|
1632
|
-
"pricing",
|
|
1633
|
-
"pwa",
|
|
1634
|
-
"referrals",
|
|
1635
|
-
"sessions",
|
|
1636
|
-
"settings",
|
|
1637
|
-
"spaces",
|
|
1638
|
-
"static",
|
|
1639
|
-
"teams",
|
|
1640
|
-
"trending",
|
|
1641
|
-
"u",
|
|
1642
|
-
"user",
|
|
1643
|
-
"users",
|
|
1644
|
-
"work-auth"
|
|
1645
|
-
]);
|
|
1646
|
-
new Set(RESERVED_PLATFORM_PATH_SEGMENTS);
|
|
1647
|
-
[...RESERVED_PLATFORM_PATH_SEGMENTS];
|
|
1648
|
-
function parseUsername(value) {
|
|
1649
|
-
if (value === null || value === void 0) return null;
|
|
1650
|
-
const normalized = value.trim().toLowerCase();
|
|
1651
|
-
return USERNAME_PATTERN.test(normalized) ? normalized : null;
|
|
1652
|
-
}
|
|
1653
|
-
function parseSpaceSlug(value) {
|
|
1654
|
-
if (value === null || value === void 0) return null;
|
|
1655
|
-
const normalized = value.trim();
|
|
1656
|
-
return SPACE_SLUG_PATTERN.test(normalized) ? normalized : null;
|
|
1657
|
-
}
|
|
1658
|
-
//#endregion
|
|
1659
1626
|
//#region src/work-ref.ts
|
|
1660
|
-
|
|
1661
|
-
* Accepts every way a Work is named across Cohub — id, management URL, public
|
|
1662
|
-
* URL, `cohub://works` URI, or `username/space/work` — and normalizes it.
|
|
1663
|
-
*
|
|
1664
|
-
* Public and mention forms may carry launch state (`?query#hash`); it is kept
|
|
1665
|
-
* separately so it can be forwarded to the Work while the stable identity stays
|
|
1666
|
-
* clean.
|
|
1667
|
-
*/
|
|
1668
|
-
const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
1669
|
-
const isWorkId = (value) => UUID_PATTERN.test(value.trim());
|
|
1627
|
+
const isWorkId = (value) => isUuid(value.trim());
|
|
1670
1628
|
function decodePart(value) {
|
|
1671
1629
|
try {
|
|
1672
1630
|
return decodeURIComponent(value).trim();
|
|
@@ -1708,7 +1666,7 @@ function parseUrlRef(value) {
|
|
|
1708
1666
|
} : null;
|
|
1709
1667
|
}
|
|
1710
1668
|
if (url.protocol !== "http:" && url.protocol !== "https:") return null;
|
|
1711
|
-
if (parts.length === 4 && parts[0] === "spaces" &&
|
|
1669
|
+
if (parts.length === 4 && parts[0] === "spaces" && isUuid(parts[1] ?? "") && parts[2] === "works" && isUuid(parts[3] ?? "")) return { id: parts[3] };
|
|
1712
1670
|
if (parts.length === 4 && parts[2] === "w") {
|
|
1713
1671
|
const ref = publicRef([
|
|
1714
1672
|
parts[0],
|
|
@@ -1730,7 +1688,7 @@ var WorkRefParseError = class extends Error {
|
|
|
1730
1688
|
};
|
|
1731
1689
|
function parseWorkRef(input) {
|
|
1732
1690
|
const value = input.trim();
|
|
1733
|
-
if (
|
|
1691
|
+
if (isUuid(value)) return { id: value };
|
|
1734
1692
|
const parsedUrl = parseUrlRef(value.includes("://") ? value : value.startsWith("/") ? `https://cohub.invalid${value}` : value);
|
|
1735
1693
|
if (parsedUrl) return parsedUrl;
|
|
1736
1694
|
const parts = value.split("/").filter(Boolean);
|
|
@@ -1954,6 +1912,7 @@ function createWorkBridgeCore(config) {
|
|
|
1954
1912
|
await config.requestSignIn(typeof location !== "undefined" ? location.pathname + location.search + location.hash : "/");
|
|
1955
1913
|
return null;
|
|
1956
1914
|
}
|
|
1915
|
+
const promotionAttribution = config.getPromotionAttribution?.() ?? null;
|
|
1957
1916
|
const response = await fetch(`${apiOrigin}/api/works/${work.id}/commerce/purchase`, {
|
|
1958
1917
|
method: "POST",
|
|
1959
1918
|
headers: {
|
|
@@ -1962,7 +1921,8 @@ function createWorkBridgeCore(config) {
|
|
|
1962
1921
|
},
|
|
1963
1922
|
body: JSON.stringify({
|
|
1964
1923
|
productKey,
|
|
1965
|
-
purchaseAttemptId
|
|
1924
|
+
purchaseAttemptId,
|
|
1925
|
+
...promotionAttribution ? { promotionAttribution } : {}
|
|
1966
1926
|
})
|
|
1967
1927
|
});
|
|
1968
1928
|
if (!response.ok) throw new Error((await response.json().catch(() => null))?.message ?? "Purchase failed.");
|
|
@@ -2034,6 +1994,7 @@ function createWorkBridgeCore(config) {
|
|
|
2034
1994
|
state.purchaseError = null;
|
|
2035
1995
|
state.purchaseOpen = true;
|
|
2036
1996
|
notify();
|
|
1997
|
+
config.onPurchaseRequested?.({ ...state.pendingPurchase });
|
|
2037
1998
|
}
|
|
2038
1999
|
if (data.type === "cohub.work.authorize") {
|
|
2039
2000
|
const allowedViewerScopes = clonePermissionScopes(work.allowedViewerScopes);
|
|
@@ -2124,7 +2085,14 @@ function createWorkBridgeCore(config) {
|
|
|
2124
2085
|
productKey: next.productKey
|
|
2125
2086
|
});
|
|
2126
2087
|
const url = next.checkoutUrl;
|
|
2127
|
-
if (next.checkoutUsable === true && typeof url === "string" && url)
|
|
2088
|
+
if (next.checkoutUsable === true && typeof url === "string" && url) {
|
|
2089
|
+
config.onCheckoutStarted?.({
|
|
2090
|
+
...state.pendingPurchase,
|
|
2091
|
+
...typeof next.value === "number" ? { value: next.value } : {},
|
|
2092
|
+
...typeof next.currency === "string" ? { currency: next.currency } : {}
|
|
2093
|
+
});
|
|
2094
|
+
window.location.href = url;
|
|
2095
|
+
}
|
|
2128
2096
|
}
|
|
2129
2097
|
state.purchaseOpen = false;
|
|
2130
2098
|
state.pendingPurchase = null;
|
|
@@ -2166,440 +2134,6 @@ function createWorkBridgeCore(config) {
|
|
|
2166
2134
|
};
|
|
2167
2135
|
}
|
|
2168
2136
|
//#endregion
|
|
2169
|
-
//#region ../protocol/dist/generation/catalog.js
|
|
2170
|
-
function isGenerationModelHidden(model) {
|
|
2171
|
-
return model.hidden === true;
|
|
2172
|
-
}
|
|
2173
|
-
function filterDiscoverableGenerationModels(models, options = {}) {
|
|
2174
|
-
const includeModelIds = new Set(options.includeModelIds);
|
|
2175
|
-
return models.filter((model) => !isGenerationModelHidden(model) || includeModelIds.has(model.model));
|
|
2176
|
-
}
|
|
2177
|
-
//#endregion
|
|
2178
|
-
//#region ../protocol/dist/generation/policy.js
|
|
2179
|
-
const GENERATION_POLICY_ENV_KEY = "COHUB_GENERATION_POLICY_B64";
|
|
2180
|
-
var GenerationPolicyError = class extends Error {
|
|
2181
|
-
constructor(message) {
|
|
2182
|
-
super(message);
|
|
2183
|
-
this.name = "GenerationPolicyError";
|
|
2184
|
-
}
|
|
2185
|
-
};
|
|
2186
|
-
function isRecord(value) {
|
|
2187
|
-
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
2188
|
-
}
|
|
2189
|
-
function isPrimitiveEnumValue(value) {
|
|
2190
|
-
return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
2191
|
-
}
|
|
2192
|
-
function normalizeConstraint(value) {
|
|
2193
|
-
if (!isRecord(value) || typeof value.kind !== "string") return null;
|
|
2194
|
-
if (value.kind === "enum") {
|
|
2195
|
-
if (!Array.isArray(value.values) || value.values.length === 0 || !value.values.every(isPrimitiveEnumValue)) return null;
|
|
2196
|
-
return {
|
|
2197
|
-
kind: "enum",
|
|
2198
|
-
values: value.values
|
|
2199
|
-
};
|
|
2200
|
-
}
|
|
2201
|
-
if (value.kind === "number" || value.kind === "integer") {
|
|
2202
|
-
const result = { kind: value.kind };
|
|
2203
|
-
if (typeof value.min === "number" && Number.isFinite(value.min)) result.min = value.min;
|
|
2204
|
-
if (typeof value.max === "number" && Number.isFinite(value.max)) result.max = value.max;
|
|
2205
|
-
if (result.min !== void 0 && result.max !== void 0 && result.min > result.max) return null;
|
|
2206
|
-
if (Array.isArray(value.values) && value.values.every((item) => typeof item === "number" && Number.isFinite(item))) {
|
|
2207
|
-
if (value.kind === "integer" && !value.values.every(Number.isInteger)) return null;
|
|
2208
|
-
const min = result.min;
|
|
2209
|
-
const max = result.max;
|
|
2210
|
-
if (min !== void 0 && value.values.some((item) => item < min)) return null;
|
|
2211
|
-
if (max !== void 0 && value.values.some((item) => item > max)) return null;
|
|
2212
|
-
result.values = value.values;
|
|
2213
|
-
}
|
|
2214
|
-
return result;
|
|
2215
|
-
}
|
|
2216
|
-
if (value.kind === "boolean") return typeof value.value === "boolean" ? {
|
|
2217
|
-
kind: "boolean",
|
|
2218
|
-
value: value.value
|
|
2219
|
-
} : { kind: "boolean" };
|
|
2220
|
-
return null;
|
|
2221
|
-
}
|
|
2222
|
-
function normalizeGenerationPolicy(value) {
|
|
2223
|
-
if (!isRecord(value) || value.version !== 1) return null;
|
|
2224
|
-
if (value.mode === "auto") return {
|
|
2225
|
-
version: 1,
|
|
2226
|
-
mode: "auto"
|
|
2227
|
-
};
|
|
2228
|
-
if (value.mode !== "limited" || !Array.isArray(value.models) || value.models.length === 0) return null;
|
|
2229
|
-
const models = [];
|
|
2230
|
-
for (const item of value.models) {
|
|
2231
|
-
if (!isRecord(item) || typeof item.model !== "string" || !item.model.trim()) return null;
|
|
2232
|
-
const modelPolicy = { model: item.model.trim() };
|
|
2233
|
-
if (item.parameters !== void 0) {
|
|
2234
|
-
if (!isRecord(item.parameters)) return null;
|
|
2235
|
-
const parameters = {};
|
|
2236
|
-
for (const [key, rawConstraint] of Object.entries(item.parameters)) {
|
|
2237
|
-
if (!key.trim()) return null;
|
|
2238
|
-
const constraint = normalizeConstraint(rawConstraint);
|
|
2239
|
-
if (!constraint) return null;
|
|
2240
|
-
parameters[key] = constraint;
|
|
2241
|
-
}
|
|
2242
|
-
if (Object.keys(parameters).length > 0) modelPolicy.parameters = parameters;
|
|
2243
|
-
}
|
|
2244
|
-
models.push(modelPolicy);
|
|
2245
|
-
}
|
|
2246
|
-
return {
|
|
2247
|
-
version: 1,
|
|
2248
|
-
mode: "limited",
|
|
2249
|
-
models
|
|
2250
|
-
};
|
|
2251
|
-
}
|
|
2252
|
-
function bytesToBase64(bytes) {
|
|
2253
|
-
let binary = "";
|
|
2254
|
-
for (const byte of bytes) binary += String.fromCharCode(byte);
|
|
2255
|
-
return btoa(binary);
|
|
2256
|
-
}
|
|
2257
|
-
function base64ToBytes(value) {
|
|
2258
|
-
const binary = atob(value);
|
|
2259
|
-
const bytes = new Uint8Array(binary.length);
|
|
2260
|
-
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
2261
|
-
return bytes;
|
|
2262
|
-
}
|
|
2263
|
-
function toBase64Url(value) {
|
|
2264
|
-
return bytesToBase64(new TextEncoder().encode(value)).replaceAll("+", "-").replaceAll("/", "_").replaceAll("=", "");
|
|
2265
|
-
}
|
|
2266
|
-
function fromBase64Url(value) {
|
|
2267
|
-
const base64 = value.replaceAll("-", "+").replaceAll("_", "/");
|
|
2268
|
-
const padded = base64.padEnd(base64.length + (4 - base64.length % 4) % 4, "=");
|
|
2269
|
-
return new TextDecoder().decode(base64ToBytes(padded));
|
|
2270
|
-
}
|
|
2271
|
-
function encodeGenerationPolicy(policy) {
|
|
2272
|
-
return toBase64Url(JSON.stringify(policy));
|
|
2273
|
-
}
|
|
2274
|
-
function decodeGenerationPolicy(value) {
|
|
2275
|
-
try {
|
|
2276
|
-
return normalizeGenerationPolicy(JSON.parse(fromBase64Url(value)));
|
|
2277
|
-
} catch {
|
|
2278
|
-
return null;
|
|
2279
|
-
}
|
|
2280
|
-
}
|
|
2281
|
-
function parseGenerationPolicyFromEnv(env) {
|
|
2282
|
-
const value = env[GENERATION_POLICY_ENV_KEY]?.trim();
|
|
2283
|
-
return value ? decodeGenerationPolicy(value) : null;
|
|
2284
|
-
}
|
|
2285
|
-
function getAllowedGenerationModelIds(policy) {
|
|
2286
|
-
if (!policy || policy.mode === "auto") return null;
|
|
2287
|
-
return [...new Set((policy.models ?? []).map((item) => item.model))];
|
|
2288
|
-
}
|
|
2289
|
-
function findGenerationModelPolicy(policy, model) {
|
|
2290
|
-
if (!policy || policy.mode === "auto") return null;
|
|
2291
|
-
return policy.models?.find((item) => item.model === model) ?? null;
|
|
2292
|
-
}
|
|
2293
|
-
function formatList(values) {
|
|
2294
|
-
return values.map((value) => `- ${String(value)}`).join("\n");
|
|
2295
|
-
}
|
|
2296
|
-
function modelNotSupportedMessage(allowedModels) {
|
|
2297
|
-
return [
|
|
2298
|
-
"This turn supports the following generation models:",
|
|
2299
|
-
"",
|
|
2300
|
-
formatList(allowedModels),
|
|
2301
|
-
"",
|
|
2302
|
-
"Choose one of these models or update Generation settings in the Models panel."
|
|
2303
|
-
].join("\n");
|
|
2304
|
-
}
|
|
2305
|
-
function valuesNotSupportedMessage(model, name, values, received) {
|
|
2306
|
-
return [
|
|
2307
|
-
`This turn supports selected values for ${model}.${name}:`,
|
|
2308
|
-
"",
|
|
2309
|
-
formatList(values),
|
|
2310
|
-
"",
|
|
2311
|
-
"Received:",
|
|
2312
|
-
`- ${String(received)}`
|
|
2313
|
-
].join("\n");
|
|
2314
|
-
}
|
|
2315
|
-
function rangeNotSupportedMessage(model, name, min, max, received) {
|
|
2316
|
-
return [
|
|
2317
|
-
`This turn supports ${model}.${name} in the range ${min !== void 0 && max !== void 0 ? `${min}–${max}` : min !== void 0 ? `at least ${min}` : `at most ${max}`}.`,
|
|
2318
|
-
"",
|
|
2319
|
-
"Received:",
|
|
2320
|
-
`- ${String(received)}`
|
|
2321
|
-
].join("\n");
|
|
2322
|
-
}
|
|
2323
|
-
function booleanNotSupportedMessage(model, name, expected, received) {
|
|
2324
|
-
return [
|
|
2325
|
-
`This turn supports ${model}.${name}=${String(expected)}.`,
|
|
2326
|
-
"",
|
|
2327
|
-
"Received:",
|
|
2328
|
-
`- ${String(received)}`
|
|
2329
|
-
].join("\n");
|
|
2330
|
-
}
|
|
2331
|
-
function sameEnumValue(a, b) {
|
|
2332
|
-
return typeof a === typeof b && a === b;
|
|
2333
|
-
}
|
|
2334
|
-
function validateConstraint(input) {
|
|
2335
|
-
const { model, name, value, constraint } = input;
|
|
2336
|
-
if (constraint.kind === "enum") {
|
|
2337
|
-
if (!constraint.values.some((item) => sameEnumValue(item, value))) throw new GenerationPolicyError(valuesNotSupportedMessage(model, name, constraint.values, value));
|
|
2338
|
-
return;
|
|
2339
|
-
}
|
|
2340
|
-
if (constraint.kind === "number" || constraint.kind === "integer") {
|
|
2341
|
-
if (typeof value !== "number" || !Number.isFinite(value)) throw new GenerationPolicyError(rangeNotSupportedMessage(model, name, constraint.min, constraint.max, value));
|
|
2342
|
-
if (constraint.kind === "integer" && !Number.isInteger(value)) throw new GenerationPolicyError(rangeNotSupportedMessage(model, name, constraint.min, constraint.max, value));
|
|
2343
|
-
if (constraint.values?.length && !constraint.values.includes(value)) throw new GenerationPolicyError(valuesNotSupportedMessage(model, name, constraint.values, value));
|
|
2344
|
-
if (constraint.min !== void 0 && value < constraint.min) throw new GenerationPolicyError(rangeNotSupportedMessage(model, name, constraint.min, constraint.max, value));
|
|
2345
|
-
if (constraint.max !== void 0 && value > constraint.max) throw new GenerationPolicyError(rangeNotSupportedMessage(model, name, constraint.min, constraint.max, value));
|
|
2346
|
-
return;
|
|
2347
|
-
}
|
|
2348
|
-
if (constraint.kind === "boolean" && constraint.value !== void 0 && value !== constraint.value) throw new GenerationPolicyError(booleanNotSupportedMessage(model, name, constraint.value, value));
|
|
2349
|
-
}
|
|
2350
|
-
function assertGenerationRequestAllowedByPolicy(input) {
|
|
2351
|
-
const allowedModels = getAllowedGenerationModelIds(input.policy);
|
|
2352
|
-
if (!allowedModels) return;
|
|
2353
|
-
const modelPolicy = findGenerationModelPolicy(input.policy, input.model);
|
|
2354
|
-
if (!modelPolicy) throw new GenerationPolicyError(modelNotSupportedMessage(allowedModels));
|
|
2355
|
-
const parameters = input.parameters ?? {};
|
|
2356
|
-
for (const [name, value] of Object.entries(parameters)) {
|
|
2357
|
-
const constraint = modelPolicy.parameters?.[name];
|
|
2358
|
-
if (!constraint) continue;
|
|
2359
|
-
validateConstraint({
|
|
2360
|
-
model: input.model,
|
|
2361
|
-
name,
|
|
2362
|
-
value,
|
|
2363
|
-
constraint
|
|
2364
|
-
});
|
|
2365
|
-
}
|
|
2366
|
-
}
|
|
2367
|
-
function cloneDeclaration(declaration) {
|
|
2368
|
-
return {
|
|
2369
|
-
...declaration,
|
|
2370
|
-
content: {
|
|
2371
|
-
...declaration.content,
|
|
2372
|
-
input: [...declaration.content.input]
|
|
2373
|
-
},
|
|
2374
|
-
parameters: declaration.parameters ? Object.fromEntries(Object.entries(declaration.parameters).map(([key, value]) => [key, { ...value }])) : declaration.parameters,
|
|
2375
|
-
examples: declaration.examples ? [...declaration.examples] : declaration.examples
|
|
2376
|
-
};
|
|
2377
|
-
}
|
|
2378
|
-
function narrowParameterSpec(spec, constraint) {
|
|
2379
|
-
const next = { ...spec };
|
|
2380
|
-
if (constraint.kind === "enum") {
|
|
2381
|
-
if ("enum" in next && Array.isArray(next.enum)) next.enum = next.enum.filter((value) => constraint.values.some((allowed) => sameEnumValue(allowed, value)));
|
|
2382
|
-
return next;
|
|
2383
|
-
}
|
|
2384
|
-
if (constraint.kind === "number" || constraint.kind === "integer") {
|
|
2385
|
-
if ("min" in next && typeof next.min === "number" && constraint.min !== void 0) next.min = Math.max(next.min, constraint.min);
|
|
2386
|
-
else if ("min" in next && constraint.min !== void 0) next.min = constraint.min;
|
|
2387
|
-
if ("max" in next && typeof next.max === "number" && constraint.max !== void 0) next.max = Math.min(next.max, constraint.max);
|
|
2388
|
-
else if ("max" in next && constraint.max !== void 0) next.max = constraint.max;
|
|
2389
|
-
if (constraint.values?.length && "enum" in next && Array.isArray(next.enum)) next.enum = next.enum.filter((value) => constraint.values?.some((allowed) => sameEnumValue(allowed, value)));
|
|
2390
|
-
}
|
|
2391
|
-
return next;
|
|
2392
|
-
}
|
|
2393
|
-
function filterGenerationDeclarationsByPolicy(declarations, policy) {
|
|
2394
|
-
const allowedModels = getAllowedGenerationModelIds(policy);
|
|
2395
|
-
if (!allowedModels) return declarations;
|
|
2396
|
-
const allowedSet = new Set(allowedModels);
|
|
2397
|
-
return declarations.filter((declaration) => allowedSet.has(declaration.model)).map((declaration) => {
|
|
2398
|
-
const cloned = cloneDeclaration(declaration);
|
|
2399
|
-
const modelPolicy = findGenerationModelPolicy(policy, declaration.model);
|
|
2400
|
-
if (!modelPolicy?.parameters || !cloned.parameters) return cloned;
|
|
2401
|
-
for (const [name, constraint] of Object.entries(modelPolicy.parameters)) {
|
|
2402
|
-
const spec = cloned.parameters[name];
|
|
2403
|
-
if (spec) cloned.parameters[name] = narrowParameterSpec(spec, constraint);
|
|
2404
|
-
}
|
|
2405
|
-
return cloned;
|
|
2406
|
-
});
|
|
2407
|
-
}
|
|
2408
|
-
//#endregion
|
|
2409
|
-
//#region ../protocol/dist/board.js
|
|
2410
|
-
const BOARD_MANIFEST_KIND = "cohub.board.manifest";
|
|
2411
|
-
const idSchema = z.string().min(1).max(160);
|
|
2412
|
-
const extensionIdSchema = z.string().regex(/^[a-z][a-z0-9]*(?:[.-][a-z0-9]+)+$/).max(160);
|
|
2413
|
-
const jsonObjectSchema = z.record(z.string(), z.unknown());
|
|
2414
|
-
const finiteSchema = z.number().finite();
|
|
2415
|
-
z.object({
|
|
2416
|
-
kind: z.literal(BOARD_MANIFEST_KIND),
|
|
2417
|
-
version: z.literal(1),
|
|
2418
|
-
boardId: z.string().uuid(),
|
|
2419
|
-
title: z.string().min(1).max(255)
|
|
2420
|
-
});
|
|
2421
|
-
const BoardTargetSchema = z.discriminatedUnion("type", [
|
|
2422
|
-
z.object({
|
|
2423
|
-
type: z.literal("node"),
|
|
2424
|
-
nodeId: idSchema
|
|
2425
|
-
}),
|
|
2426
|
-
z.object({
|
|
2427
|
-
type: z.literal("effect"),
|
|
2428
|
-
effectId: idSchema
|
|
2429
|
-
}),
|
|
2430
|
-
z.object({ type: z.literal("board") }),
|
|
2431
|
-
z.object({ type: z.literal("camera") })
|
|
2432
|
-
]);
|
|
2433
|
-
const BoardAssetRefSchema = z.object({
|
|
2434
|
-
type: z.enum(["space-file", "extension"]),
|
|
2435
|
-
ref: z.string().min(1).max(4096),
|
|
2436
|
-
digest: z.string().min(16).max(160).optional()
|
|
2437
|
-
});
|
|
2438
|
-
const BoardKeyframeSchema = z.object({
|
|
2439
|
-
at: finiteSchema.nonnegative(),
|
|
2440
|
-
value: z.unknown(),
|
|
2441
|
-
easing: z.string().min(1).max(80).optional()
|
|
2442
|
-
});
|
|
2443
|
-
const BoardClipSchema = z.object({
|
|
2444
|
-
id: idSchema,
|
|
2445
|
-
sequenceId: idSchema,
|
|
2446
|
-
kind: extensionIdSchema,
|
|
2447
|
-
kindVersion: z.number().int().positive(),
|
|
2448
|
-
target: BoardTargetSchema,
|
|
2449
|
-
start: finiteSchema.nonnegative(),
|
|
2450
|
-
duration: finiteSchema.positive(),
|
|
2451
|
-
layer: z.enum([
|
|
2452
|
-
"behind",
|
|
2453
|
-
"content",
|
|
2454
|
-
"front",
|
|
2455
|
-
"screen"
|
|
2456
|
-
]).default("content"),
|
|
2457
|
-
fill: z.enum([
|
|
2458
|
-
"none",
|
|
2459
|
-
"backwards",
|
|
2460
|
-
"forwards",
|
|
2461
|
-
"both"
|
|
2462
|
-
]).default("none"),
|
|
2463
|
-
easing: z.string().min(1).max(80).default("linear"),
|
|
2464
|
-
params: jsonObjectSchema.default({}),
|
|
2465
|
-
keyframes: z.array(BoardKeyframeSchema).default([]),
|
|
2466
|
-
assetRefs: z.array(BoardAssetRefSchema).default([]),
|
|
2467
|
-
seed: z.string().min(1).max(160),
|
|
2468
|
-
metadata: jsonObjectSchema.default({})
|
|
2469
|
-
});
|
|
2470
|
-
const BoardEffectSchema = z.object({
|
|
2471
|
-
id: idSchema,
|
|
2472
|
-
boardId: z.string().uuid(),
|
|
2473
|
-
target: z.discriminatedUnion("type", [z.object({
|
|
2474
|
-
type: z.literal("node"),
|
|
2475
|
-
nodeId: idSchema
|
|
2476
|
-
}), z.object({ type: z.literal("board") })]),
|
|
2477
|
-
kind: extensionIdSchema,
|
|
2478
|
-
kindVersion: z.number().int().positive(),
|
|
2479
|
-
enabled: z.boolean().default(true),
|
|
2480
|
-
lifecycle: z.enum([
|
|
2481
|
-
"persistent",
|
|
2482
|
-
"when-visible",
|
|
2483
|
-
"manual"
|
|
2484
|
-
]),
|
|
2485
|
-
timeOrigin: z.enum([
|
|
2486
|
-
"board",
|
|
2487
|
-
"visible",
|
|
2488
|
-
"activation"
|
|
2489
|
-
]),
|
|
2490
|
-
layer: z.enum([
|
|
2491
|
-
"behind",
|
|
2492
|
-
"front",
|
|
2493
|
-
"screen"
|
|
2494
|
-
]).default("front"),
|
|
2495
|
-
seed: z.string().min(1).max(160),
|
|
2496
|
-
params: jsonObjectSchema.default({}),
|
|
2497
|
-
assetRefs: z.array(BoardAssetRefSchema).default([]),
|
|
2498
|
-
metadata: jsonObjectSchema.default({}),
|
|
2499
|
-
revision: z.number().int().nonnegative()
|
|
2500
|
-
});
|
|
2501
|
-
const BoardSequenceSchema = z.object({
|
|
2502
|
-
id: idSchema,
|
|
2503
|
-
boardId: z.string().uuid(),
|
|
2504
|
-
name: z.string().min(1).max(255),
|
|
2505
|
-
duration: finiteSchema.nonnegative(),
|
|
2506
|
-
seed: z.string().min(1).max(160),
|
|
2507
|
-
restPose: jsonObjectSchema.default({}),
|
|
2508
|
-
metadata: jsonObjectSchema.default({}),
|
|
2509
|
-
revision: z.number().int().nonnegative()
|
|
2510
|
-
});
|
|
2511
|
-
const BoardNodeInputSchema = z.object({
|
|
2512
|
-
nodeId: idSchema,
|
|
2513
|
-
type: z.string().min(1).max(40),
|
|
2514
|
-
parentId: idSchema.nullable(),
|
|
2515
|
-
orderKey: z.string().max(4096).nullable(),
|
|
2516
|
-
x: finiteSchema,
|
|
2517
|
-
y: finiteSchema,
|
|
2518
|
-
width: finiteSchema.positive(),
|
|
2519
|
-
height: finiteSchema.positive(),
|
|
2520
|
-
rotation: finiteSchema,
|
|
2521
|
-
refKind: z.string().max(40).nullable(),
|
|
2522
|
-
refPath: z.string().max(4096).nullable(),
|
|
2523
|
-
refUrl: z.string().max(4096).nullable(),
|
|
2524
|
-
view: jsonObjectSchema,
|
|
2525
|
-
style: jsonObjectSchema,
|
|
2526
|
-
data: jsonObjectSchema
|
|
2527
|
-
});
|
|
2528
|
-
z.object({
|
|
2529
|
-
path: z.string().min(1),
|
|
2530
|
-
/** Reused by clients when board creation is interrupted and retried. */
|
|
2531
|
-
mutationId: z.string().max(128).optional(),
|
|
2532
|
-
title: z.string().min(1).max(255).optional(),
|
|
2533
|
-
metadata: jsonObjectSchema.optional(),
|
|
2534
|
-
nodes: z.array(BoardNodeInputSchema).max(5e4).optional(),
|
|
2535
|
-
connections: z.array(BoardConnectionSchema).max(5e4).optional(),
|
|
2536
|
-
effects: z.array(BoardEffectSchema.omit({
|
|
2537
|
-
boardId: true,
|
|
2538
|
-
revision: true
|
|
2539
|
-
})).optional(),
|
|
2540
|
-
sequences: z.array(z.object({
|
|
2541
|
-
sequence: BoardSequenceSchema.omit({
|
|
2542
|
-
boardId: true,
|
|
2543
|
-
revision: true
|
|
2544
|
-
}),
|
|
2545
|
-
clips: z.array(BoardClipSchema.omit({ sequenceId: true }))
|
|
2546
|
-
})).optional()
|
|
2547
|
-
});
|
|
2548
|
-
z.object({
|
|
2549
|
-
include: z.array(z.enum([
|
|
2550
|
-
"nodes",
|
|
2551
|
-
"connections",
|
|
2552
|
-
"effects",
|
|
2553
|
-
"sequences",
|
|
2554
|
-
"clips",
|
|
2555
|
-
"playback"
|
|
2556
|
-
])).optional(),
|
|
2557
|
-
viewport: z.object({
|
|
2558
|
-
x: finiteSchema,
|
|
2559
|
-
y: finiteSchema,
|
|
2560
|
-
width: finiteSchema.positive(),
|
|
2561
|
-
height: finiteSchema.positive()
|
|
2562
|
-
}).optional()
|
|
2563
|
-
});
|
|
2564
|
-
/** Persisted on `boards.metadata.playback`: how a Board plays when opened. */
|
|
2565
|
-
const BoardPlaybackPolicySchema = z.object({
|
|
2566
|
-
sequenceId: idSchema,
|
|
2567
|
-
/** Delay before the first local playback after opening the Board, in milliseconds. */
|
|
2568
|
-
delayMs: finiteSchema.nonnegative().default(0),
|
|
2569
|
-
loop: z.boolean().default(false)
|
|
2570
|
-
});
|
|
2571
|
-
function parseBoardPlaybackPolicy(metadata) {
|
|
2572
|
-
const parsed = BoardPlaybackPolicySchema.safeParse(metadata.playback);
|
|
2573
|
-
return parsed.success ? parsed.data : null;
|
|
2574
|
-
}
|
|
2575
|
-
z.discriminatedUnion("type", [
|
|
2576
|
-
z.object({
|
|
2577
|
-
commandId: idSchema,
|
|
2578
|
-
type: z.literal("play"),
|
|
2579
|
-
sequenceId: idSchema,
|
|
2580
|
-
position: finiteSchema.nonnegative().optional(),
|
|
2581
|
-
timeScale: finiteSchema.positive().max(4).optional(),
|
|
2582
|
-
shared: z.boolean().optional(),
|
|
2583
|
-
seed: idSchema.optional()
|
|
2584
|
-
}),
|
|
2585
|
-
z.object({
|
|
2586
|
-
commandId: idSchema,
|
|
2587
|
-
type: z.literal("pause"),
|
|
2588
|
-
playbackId: z.string().uuid()
|
|
2589
|
-
}),
|
|
2590
|
-
z.object({
|
|
2591
|
-
commandId: idSchema,
|
|
2592
|
-
type: z.literal("seek"),
|
|
2593
|
-
playbackId: z.string().uuid(),
|
|
2594
|
-
position: finiteSchema.nonnegative()
|
|
2595
|
-
}),
|
|
2596
|
-
z.object({
|
|
2597
|
-
commandId: idSchema,
|
|
2598
|
-
type: z.literal("stop"),
|
|
2599
|
-
playbackId: z.string().uuid()
|
|
2600
|
-
})
|
|
2601
|
-
]);
|
|
2602
|
-
//#endregion
|
|
2603
2137
|
//#region src/board/animation.ts
|
|
2604
2138
|
const ZERO_COST = {
|
|
2605
2139
|
particles: 0,
|
|
@@ -2951,4 +2485,4 @@ function createBoardExtensionRegistry(input = {}) {
|
|
|
2951
2485
|
return registry;
|
|
2952
2486
|
}
|
|
2953
2487
|
//#endregion
|
|
2954
|
-
export { BILLING_ACCESS_BLOCKED_ERROR_CODE, BillingApi, BoardClient, BoardExtensionRegistry, BoardPlaybackPolicySchema, BoardTransactionError, COHUB_ENVIRONMENTS, COHUB_SOURCE_HEADER, COHUB_SOURCE_HEADER_NAMES, CohubClient, CohubHttpClient, DEFAULT_BOARD_LIMITS, FEATURE_NOT_ENTITLED_ERROR_CODE, GenerationPolicyError, HttpError, ParentBridgeTransport, PopupBrokerTransport, REQUEST_SOURCE_VIA_MAX_LENGTH, ReferencesApi, ReferralsApi, SessionGenerationStreamClient, SessionPatchReducer, UI_COMMAND_DEFAULT_TIMEOUT_MS, UI_COMMAND_MAX_TIMEOUT_MS, UI_COMMAND_PAYLOAD_MAX_BYTES, UI_COMMAND_PENDING_TTL_SECONDS, UI_COMMAND_SETTLEMENT_GRACE_SECONDS, UI_COMMAND_TERMINAL_TTL_SECONDS, UI_COMMAND_VERSION, UiCommandsApi, UsersApi, VoiceApi, VoiceInputClient, WORK_COMPOSER_CHIP_CONTENT_MAX_BYTES, WORK_COMPOSER_CHIP_KEY_MAX_LENGTH, WORK_COMPOSER_CHIP_LABEL_MAX_LENGTH, WORK_SURFACE_READY_TIMEOUT_MS, WORK_SURFACE_REQUEST_TIMEOUT_MS, WebsocketClient, WorkCommerceApi, WorkRealtimeApi, WorkRefParseError, WorkRoom, WorkRuntimeApi, WorkSurfaceApi, WorksApi, assertGenerationRequestAllowedByPolicy, buildSpaceInvitePath, buildSpacePath, buildWorkSurfaceRequest, clearGrantedWorkScopes, clip, compileSequence, createBoardExtensionRegistry, createCohubClient, createHttpClient, createSessionGenerationStreamClient, createSessionPatchReducer, createSlugWorkIdResolver, createVoiceInputClient, createWebsocketClient, createWorkBridgeCore, createWorkRuntime, decodeGenerationPolicy, encodeGenerationPolicy, extractBillingPayload, filterDiscoverableGenerationModels, filterGenerationDeclarationsByPolicy, findGenerationModelPolicy, formatWorkRef, getAllowedGenerationModelIds, hasGrantedWorkScopes, hasRequestSourceIdentity, isBillingAccessBlockedCode, isBillingAccessBlockedError, isFeatureNotEntitledError, isGenerationModelHidden, isHttpErrorCode, isRequestSourceClientId, isRequestSourceEmpty, isRequestSourceUuid, isTerminalUiCommandStatus, isUiSurfaceMethod, isWorkId, joinApiUrl, matchesUnauthorizedErrorToken, mergeRequestSourceIntoMeta, normalizeBaseUrl, normalizeGenerationPolicy, normalizeRequestSource, normalizeVoiceInputWebsocketUrl, normalizeWebsocketUrl, parseAssistantMessageCommit, parseBoardPlaybackPolicy, parseGenerationPolicyFromEnv, parseRequestSourceFromHeaders, parseUiCommand, parseWorkRef, parseWorkSurfaceReady, parseWorkSurfaceResponse, readRequestSourceFromEnv, requestSourceToHeaders, resolveApiBaseUrl, resolveCohubEnvironment, resolveRequestSourceChannel, resolveVoiceInputWebsocketUrl, resolveWebsocketUrl, resolveWorkTransport, sanitizeAccessToken, setGrantedWorkScopes, timeline };
|
|
2488
|
+
export { BILLING_ACCESS_BLOCKED_ERROR_CODE, BOARD_COLOR_IDS, BOARD_GEO_KINDS, BOARD_NATIVE_NODE_TYPES, BOARD_NODE_CONTRACT, BillingApi, BoardClient, BoardExtensionRegistry, BoardInputError, BoardPlaybackPolicySchema, BoardTransactionError, COHUB_ENVIRONMENTS, COHUB_SOURCE_HEADER, COHUB_SOURCE_HEADER_NAMES, CohubClient, CohubHttpClient, DEFAULT_BOARD_LIMITS, FEATURE_NOT_ENTITLED_ERROR_CODE, GenerationPolicyError, HttpError, ParentBridgeTransport, PopupBrokerTransport, REQUEST_SOURCE_VIA_MAX_LENGTH, ReferencesApi, ReferralsApi, SessionGenerationStreamClient, SessionPatchReducer, SpacePublicFilesApi, UI_COMMAND_DEFAULT_TIMEOUT_MS, UI_COMMAND_MAX_TIMEOUT_MS, UI_COMMAND_PAYLOAD_MAX_BYTES, UI_COMMAND_PENDING_TTL_SECONDS, UI_COMMAND_SETTLEMENT_GRACE_SECONDS, UI_COMMAND_TERMINAL_TTL_SECONDS, UI_COMMAND_VERSION, UiCommandsApi, UsersApi, VoiceApi, VoiceInputClient, WORK_COMPOSER_CHIP_CONTENT_MAX_BYTES, WORK_COMPOSER_CHIP_KEY_MAX_LENGTH, WORK_COMPOSER_CHIP_LABEL_MAX_LENGTH, WORK_SURFACE_READY_TIMEOUT_MS, WORK_SURFACE_REQUEST_TIMEOUT_MS, WebsocketClient, WorkCommerceApi, WorkRealtimeApi, WorkRefParseError, WorkRoom, WorkRuntimeApi, WorkSurfaceApi, WorksApi, assertBoardNodes, assertGenerationRequestAllowedByPolicy, buildSpaceInvitePath, buildSpacePath, buildWorkSurfaceRequest, clearGrantedWorkScopes, clip, compileSequence, createBoardExtensionRegistry, createBoardNode, createCohubClient, createHttpClient, createSessionGenerationStreamClient, createSessionPatchReducer, createSlugWorkIdResolver, createVoiceInputClient, createWebsocketClient, createWorkBridgeCore, createWorkRuntime, decodeGenerationPolicy, encodeGenerationPolicy, extractBillingPayload, filterDiscoverableGenerationModels, filterGenerationDeclarationsByPolicy, findGenerationModelPolicy, formatWorkRef, getAllowedGenerationModelIds, hasGrantedWorkScopes, hasRequestSourceIdentity, isBillingAccessBlockedCode, isBillingAccessBlockedError, isFeatureNotEntitledError, isGenerationModelHidden, isHttpErrorCode, isRequestSourceClientId, isRequestSourceEmpty, isRequestSourceUuid, isTerminalUiCommandStatus, isUiSurfaceMethod, isUuid, isWorkId, joinApiUrl, matchesUnauthorizedErrorToken, mergeRequestSourceIntoMeta, normalizeBaseUrl, normalizeGenerationPolicy, normalizeRequestSource, normalizeVoiceInputWebsocketUrl, normalizeWebsocketUrl, parseAssistantMessageCommit, parseBoardPlaybackPolicy, parseGenerationPolicyFromEnv, parseRequestSourceFromHeaders, parseUiCommand, parseWorkRef, parseWorkSurfaceReady, parseWorkSurfaceResponse, readRequestSourceFromEnv, requestSourceToHeaders, resolveApiBaseUrl, resolveCohubEnvironment, resolveRequestSourceChannel, resolveVoiceInputWebsocketUrl, resolveWebsocketUrl, resolveWorkTransport, sanitizeAccessToken, setGrantedWorkScopes, timeline, validateBoardNodeInput, validateBoardNodes };
|