@neta-art/cohub 5.10.0 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/README.md +47 -50
  2. package/dist/board/animation.d.ts +157 -67
  3. package/dist/board/animation.js +161 -306
  4. package/dist/board/core/connections.js +4 -4
  5. package/dist/board/core/export-plan.js +1 -1
  6. package/dist/board/core/shape-types.js +0 -1
  7. package/dist/board/geometry.js +4 -4
  8. package/dist/board/index.d.ts +8 -7
  9. package/dist/board/index.js +8 -9
  10. package/dist/board/mutation.d.ts +2 -17
  11. package/dist/board/mutation.js +2 -93
  12. package/dist/board/render/renderers/text-card-renderer.js +1 -1
  13. package/dist/board/semantic-document.d.ts +30 -0
  14. package/dist/board/semantic-document.js +271 -0
  15. package/dist/board/semantic-mutation.d.ts +10 -0
  16. package/dist/board/semantic-mutation.js +203 -0
  17. package/dist/chunks/http.d.ts +27 -95
  18. package/dist/chunks/http.js +628 -1610
  19. package/dist/chunks/transport.js +1 -1
  20. package/dist/chunks/websocket.d.ts +3462 -533
  21. package/dist/chunks/websocket.js +1 -1
  22. package/dist/http.d.ts +3 -3
  23. package/dist/index.d.ts +158 -299
  24. package/dist/index.js +1207 -499
  25. package/dist/protocol/dist/board-authoring.d.ts +1305 -0
  26. package/dist/protocol/dist/board-authoring.js +291 -0
  27. package/dist/protocol/dist/board-capability-registry.d.ts +2 -0
  28. package/dist/protocol/dist/board-capability-registry.js +74 -0
  29. package/dist/protocol/dist/board-codec.d.ts +2 -0
  30. package/dist/protocol/dist/board-codec.js +19 -0
  31. package/dist/protocol/dist/board-composition.d.ts +383 -0
  32. package/dist/protocol/dist/board-composition.js +310 -0
  33. package/dist/protocol/dist/board-connection.d.ts +16 -16
  34. package/dist/protocol/dist/board-connection.js +16 -16
  35. package/dist/protocol/dist/board-constants.js +0 -25
  36. package/dist/protocol/dist/board-document.d.ts +34 -3
  37. package/dist/protocol/dist/board-document.js +3 -1
  38. package/dist/protocol/dist/board-effect.d.ts +94 -0
  39. package/dist/protocol/dist/board-effect.js +53 -0
  40. package/dist/protocol/dist/board-json.js +16 -0
  41. package/dist/protocol/dist/board-node.d.ts +1 -12
  42. package/dist/protocol/dist/board-node.js +1 -81
  43. package/dist/protocol/dist/board.d.ts +42 -245
  44. package/dist/protocol/dist/board.js +56 -117
  45. package/dist/protocol/dist/index.d.ts +9 -4
  46. package/dist/types.d.ts +4 -1
  47. package/docs/work-runtime-guide.md +19 -3
  48. package/package.json +2 -2
  49. package/dist/board/codec.d.ts +0 -27
  50. package/dist/board/codec.js +0 -277
  51. package/dist/board/nodes.d.ts +0 -113
  52. package/dist/board/nodes.js +0 -154
  53. package/dist/protocol/dist/board-content.js +0 -26
  54. package/dist/protocol/dist/identifiers.js +0 -10
  55. package/dist/protocol/dist/index.js +0 -14
  56. package/dist/protocol/dist/provenance.js +0 -15
  57. package/dist/protocol/dist/public-identifiers.js +0 -38
  58. package/dist/protocol/dist/realtime/board-awareness.js +0 -119
  59. package/dist/protocol/dist/ui-command.js +0 -2
  60. package/dist/protocol/dist/work-promotion-stats.js +0 -11
  61. package/dist/protocol/dist/work-surface.js +0 -2
  62. package/dist/protocol/dist/work-view-stats.js +0 -3
@@ -0,0 +1,291 @@
1
+ import "./board-constants.js";
2
+ import { BoardConnectionPatchSchema, BoardConnectionSchema } from "./board-connection.js";
3
+ import { BoardCompositionInputSchema } from "./board-composition.js";
4
+ import { BoardEffectInputSchema } from "./board-effect.js";
5
+ import { z } from "zod";
6
+ //#region ../protocol/dist/board-authoring.js
7
+ const BOARD_AUTHORING_COLOR_IDS = [
8
+ "brand",
9
+ "neutral",
10
+ "black",
11
+ "white",
12
+ "blue",
13
+ "green",
14
+ "amber",
15
+ "violet",
16
+ "rose"
17
+ ];
18
+ const BOARD_AUTHORING_GEO_KINDS = [
19
+ "rectangle",
20
+ "rounded",
21
+ "ellipse",
22
+ "diamond",
23
+ "triangle"
24
+ ];
25
+ const idSchema = z.string().min(1).max(160);
26
+ const jsonObjectSchema = z.record(z.string(), z.unknown());
27
+ const finiteSchema = z.number().finite();
28
+ const extensionTypeSchema = z.string().regex(/^[a-z][a-z0-9]*(?:[.-][a-z0-9]+)+$/).max(160);
29
+ const BoardAuthoringFrameSchema = z.object({
30
+ x: finiteSchema,
31
+ y: finiteSchema,
32
+ width: finiteSchema.positive(),
33
+ height: finiteSchema.positive(),
34
+ rotation: finiteSchema.default(0)
35
+ }).strict();
36
+ const pointSchema = z.object({
37
+ x: finiteSchema,
38
+ y: finiteSchema,
39
+ p: finiteSchema.min(0).max(1).default(.5)
40
+ }).strict();
41
+ const worldPointSchema = z.object({
42
+ x: finiteSchema,
43
+ y: finiteSchema
44
+ }).strict();
45
+ const cropSchema = z.object({
46
+ x: finiteSchema.min(0).max(1),
47
+ y: finiteSchema.min(0).max(1),
48
+ w: finiteSchema.min(0).max(1),
49
+ h: finiteSchema.min(0).max(1)
50
+ }).strict();
51
+ const BoardItemStyleSchema = z.object({
52
+ color: z.enum(BOARD_AUTHORING_COLOR_IDS).optional(),
53
+ strokeWidth: finiteSchema.min(1).max(64).optional(),
54
+ fillOpacity: finiteSchema.min(0).max(1).optional()
55
+ }).strict();
56
+ const sourceSnapshotSchema = z.record(z.string(), z.unknown());
57
+ function isSafeBoardSourcePath(value) {
58
+ return value.length > 0 && value.length <= 4096 && !value.startsWith("/") && !value.startsWith("\\") && !value.includes("\\") && value.split("/").every((part) => part.length > 0 && part !== "." && part !== "..");
59
+ }
60
+ const BoardItemSourceSchema = z.object({
61
+ kind: z.literal("space-file"),
62
+ path: z.string().refine(isSafeBoardSourcePath, "source path must be a safe relative Board file path"),
63
+ snapshot: sourceSnapshotSchema.optional()
64
+ }).strict();
65
+ const baseFields = {
66
+ id: idSchema,
67
+ frame: BoardAuthoringFrameSchema,
68
+ parentId: idSchema.nullable().optional(),
69
+ locked: z.boolean().optional(),
70
+ metadata: jsonObjectSchema.optional()
71
+ };
72
+ const styledBaseFields = {
73
+ ...baseFields,
74
+ style: BoardItemStyleSchema.optional()
75
+ };
76
+ const BoardTextAuthoringItemSchema = z.object({
77
+ ...styledBaseFields,
78
+ type: z.literal("text"),
79
+ props: z.object({
80
+ text: z.string().default(""),
81
+ fontSize: finiteSchema.min(2).max(512).default(24)
82
+ }).strict()
83
+ }).strict();
84
+ const BoardGeoAuthoringItemSchema = z.object({
85
+ ...styledBaseFields,
86
+ type: z.literal("geo"),
87
+ props: z.object({
88
+ shape: z.enum(BOARD_AUTHORING_GEO_KINDS).default("rectangle"),
89
+ text: z.string().default("")
90
+ }).strict()
91
+ }).strict();
92
+ const BoardDrawAuthoringItemSchema = z.object({
93
+ ...styledBaseFields,
94
+ type: z.literal("draw"),
95
+ props: z.object({ points: z.array(pointSchema).min(1) }).strict()
96
+ }).strict();
97
+ const BoardArrowAuthoringItemSchema = z.object({
98
+ ...styledBaseFields,
99
+ type: z.literal("arrow"),
100
+ props: z.object({
101
+ start: worldPointSchema,
102
+ end: worldPointSchema,
103
+ bend: finiteSchema.min(-.85).max(.85).default(0),
104
+ arrowStart: z.boolean().default(false),
105
+ arrowEnd: z.boolean().default(true),
106
+ label: z.string().default("")
107
+ }).strict()
108
+ }).strict();
109
+ const BoardFrameAuthoringItemSchema = z.object({
110
+ ...styledBaseFields,
111
+ type: z.literal("frame"),
112
+ props: z.object({ label: z.string().default("Frame") }).strict()
113
+ }).strict();
114
+ const fileBackedFields = {
115
+ ...baseFields,
116
+ style: z.object({}).strict().optional(),
117
+ source: BoardItemSourceSchema
118
+ };
119
+ const BoardImageAuthoringItemSchema = z.object({
120
+ ...fileBackedFields,
121
+ type: z.literal("image"),
122
+ props: z.object({ crop: cropSchema.optional() }).strict()
123
+ }).strict();
124
+ const BoardVideoAuthoringItemSchema = z.object({
125
+ ...fileBackedFields,
126
+ type: z.literal("video"),
127
+ props: z.object({}).strict()
128
+ }).strict();
129
+ const BoardAudioAuthoringItemSchema = z.object({
130
+ ...fileBackedFields,
131
+ type: z.literal("audio"),
132
+ props: z.object({}).strict()
133
+ }).strict();
134
+ const BoardFileAuthoringItemSchema = z.object({
135
+ ...fileBackedFields,
136
+ type: z.literal("file"),
137
+ props: z.object({}).strict()
138
+ }).strict();
139
+ const BoardTaskAuthoringItemSchema = z.object({
140
+ ...baseFields,
141
+ type: z.literal("task"),
142
+ props: z.object({
143
+ taskRunId: z.string().min(1),
144
+ snapshot: z.record(z.string(), z.unknown())
145
+ }).strict(),
146
+ style: z.object({}).strict().optional()
147
+ }).strict();
148
+ const builtinItemSchemas = [
149
+ BoardTextAuthoringItemSchema,
150
+ BoardGeoAuthoringItemSchema,
151
+ BoardDrawAuthoringItemSchema,
152
+ BoardArrowAuthoringItemSchema,
153
+ BoardFrameAuthoringItemSchema,
154
+ BoardImageAuthoringItemSchema,
155
+ BoardVideoAuthoringItemSchema,
156
+ BoardAudioAuthoringItemSchema,
157
+ BoardFileAuthoringItemSchema,
158
+ BoardTaskAuthoringItemSchema
159
+ ];
160
+ const BoardBuiltinAuthoringItemSchema = z.discriminatedUnion("type", builtinItemSchemas);
161
+ const BoardExtensionAuthoringItemSchema = z.object({
162
+ ...baseFields,
163
+ type: extensionTypeSchema,
164
+ kindVersion: z.number().int().positive(),
165
+ props: jsonObjectSchema,
166
+ style: jsonObjectSchema.optional(),
167
+ source: z.object({
168
+ kind: z.string().min(1).max(80),
169
+ ref: z.string().min(1).max(4096),
170
+ snapshot: jsonObjectSchema.optional()
171
+ }).strict().optional()
172
+ }).strict();
173
+ const BoardAuthoringItemSchema = z.union([BoardBuiltinAuthoringItemSchema, BoardExtensionAuthoringItemSchema]);
174
+ const framePatchSchema = z.object({
175
+ x: finiteSchema.optional(),
176
+ y: finiteSchema.optional(),
177
+ width: finiteSchema.positive().optional(),
178
+ height: finiteSchema.positive().optional(),
179
+ rotation: finiteSchema.optional()
180
+ }).strict();
181
+ /** JSON Merge Patch semantics, constrained to the stable Item envelope. */
182
+ const BoardItemPatchSchema = z.object({
183
+ frame: framePatchSchema.optional(),
184
+ parentId: idSchema.nullable().optional(),
185
+ locked: z.boolean().nullable().optional(),
186
+ props: jsonObjectSchema.optional(),
187
+ style: jsonObjectSchema.nullable().optional(),
188
+ source: jsonObjectSchema.nullable().optional(),
189
+ metadata: jsonObjectSchema.nullable().optional()
190
+ }).strict().refine((patch) => Object.keys(patch).length > 0, "item patch is empty");
191
+ const BoardConnectionInputSchema = BoardConnectionSchema;
192
+ const stripServerFields = (value) => {
193
+ if (!value || typeof value !== "object" || Array.isArray(value)) return value;
194
+ const { boardId: _boardId, revision: _revision, ...input } = value;
195
+ return input;
196
+ };
197
+ const BoardEffectCommandInputSchema = z.preprocess(stripServerFields, BoardEffectInputSchema);
198
+ const BoardCompositionCommandInputSchema = z.preprocess(stripServerFields, BoardCompositionInputSchema);
199
+ const BoardSemanticCommandSchema = z.discriminatedUnion("type", [
200
+ z.object({
201
+ type: z.literal("board.patch"),
202
+ patch: z.object({
203
+ title: z.string().min(1).max(255).optional(),
204
+ metadata: jsonObjectSchema.nullable().optional(),
205
+ metadataPatch: jsonObjectSchema.optional()
206
+ }).strict().refine((patch) => Object.keys(patch).length > 0, "board patch is empty")
207
+ }).strict(),
208
+ z.object({
209
+ type: z.literal("item.create"),
210
+ item: BoardAuthoringItemSchema
211
+ }).strict(),
212
+ z.object({
213
+ type: z.literal("item.patch"),
214
+ itemId: idSchema,
215
+ patch: BoardItemPatchSchema
216
+ }).strict(),
217
+ z.object({
218
+ type: z.literal("item.replace"),
219
+ itemId: idSchema,
220
+ item: BoardAuthoringItemSchema
221
+ }).strict(),
222
+ z.object({
223
+ type: z.literal("item.delete"),
224
+ itemId: idSchema,
225
+ cascade: z.boolean().default(false)
226
+ }).strict(),
227
+ z.object({
228
+ type: z.literal("item.reorder"),
229
+ itemId: idSchema,
230
+ index: z.number().int().nonnegative()
231
+ }).strict(),
232
+ z.object({
233
+ type: z.literal("connection.create"),
234
+ connection: BoardConnectionInputSchema
235
+ }).strict(),
236
+ z.object({
237
+ type: z.literal("connection.patch"),
238
+ connectionId: idSchema,
239
+ patch: BoardConnectionPatchSchema
240
+ }).strict(),
241
+ z.object({
242
+ type: z.literal("connection.delete"),
243
+ connectionId: idSchema
244
+ }).strict(),
245
+ z.object({
246
+ type: z.literal("effect.apply"),
247
+ effect: BoardEffectCommandInputSchema
248
+ }).strict(),
249
+ z.object({
250
+ type: z.literal("effect.delete"),
251
+ effectId: idSchema
252
+ }).strict(),
253
+ z.object({
254
+ type: z.literal("composition.apply"),
255
+ composition: BoardCompositionCommandInputSchema
256
+ }).strict(),
257
+ z.object({
258
+ type: z.literal("composition.delete"),
259
+ compositionId: idSchema
260
+ }).strict()
261
+ ]);
262
+ const BoardSemanticMutationSchema = z.object({
263
+ mutationId: idSchema,
264
+ baseVersion: z.number().int().nonnegative(),
265
+ clientId: idSchema.optional(),
266
+ undoGroupId: idSchema.optional(),
267
+ /** Validate (including server-side reference checks) without writing. */
268
+ dryRun: z.boolean().default(false),
269
+ commands: z.array(BoardSemanticCommandSchema).min(1).max(5e4)
270
+ }).strict();
271
+ z.object({
272
+ include: z.array(z.enum([
273
+ "items",
274
+ "connections",
275
+ "effects",
276
+ "compositions",
277
+ "playback"
278
+ ])).optional(),
279
+ itemIds: z.array(idSchema).max(5e4).optional(),
280
+ connectionIds: z.array(idSchema).max(5e4).optional(),
281
+ effectIds: z.array(idSchema).max(5e4).optional(),
282
+ compositionIds: z.array(idSchema).max(5e4).optional(),
283
+ viewport: z.object({
284
+ x: finiteSchema,
285
+ y: finiteSchema,
286
+ width: finiteSchema.positive(),
287
+ height: finiteSchema.positive()
288
+ }).optional()
289
+ }).strict();
290
+ //#endregion
291
+ export { BOARD_AUTHORING_COLOR_IDS, BOARD_AUTHORING_GEO_KINDS, BoardArrowAuthoringItemSchema, BoardAudioAuthoringItemSchema, BoardAuthoringItemSchema, BoardBuiltinAuthoringItemSchema, BoardDrawAuthoringItemSchema, BoardExtensionAuthoringItemSchema, BoardFileAuthoringItemSchema, BoardFrameAuthoringItemSchema, BoardGeoAuthoringItemSchema, BoardImageAuthoringItemSchema, BoardItemPatchSchema, BoardItemSourceSchema, BoardItemStyleSchema, BoardSemanticCommandSchema, BoardSemanticMutationSchema, BoardTaskAuthoringItemSchema, BoardTextAuthoringItemSchema, BoardVideoAuthoringItemSchema, isSafeBoardSourcePath };
@@ -0,0 +1,2 @@
1
+ import "./board-composition.js";
2
+ import "./board.js";
@@ -0,0 +1,74 @@
1
+ import { BOARD_BUILTIN_CLIP_KINDS, BOARD_BUILTIN_EFFECT_KINDS, DEFAULT_BOARD_RENDER_LIMITS } from "./board-constants.js";
2
+ import { BoardCameraFocusParamsSchema } from "./board.js";
3
+ //#region ../protocol/dist/board-capability-registry.js
4
+ const CLIPS = new Set(BOARD_BUILTIN_CLIP_KINDS);
5
+ new Set(BOARD_BUILTIN_EFFECT_KINDS);
6
+ const record = (value) => Boolean(value && typeof value === "object" && !Array.isArray(value));
7
+ const finite = (value) => typeof value === "number" && Number.isFinite(value);
8
+ function validateBuiltinBoardClip(clip, path = "clip") {
9
+ if (!CLIPS.has(clip.kind)) return [];
10
+ const errors = [];
11
+ const error = (message, suffix, coordinateSpace, code = "INVALID_BOARD_CLIP") => {
12
+ errors.push({
13
+ severity: "error",
14
+ code,
15
+ message,
16
+ path: `${path}.${suffix}`,
17
+ ...coordinateSpace ? { coordinateSpace } : {}
18
+ });
19
+ };
20
+ if ((clip.kind.startsWith("motion.") || clip.kind.startsWith("draw.") || clip.kind === "text.reveal" || clip.kind === "effects.trail") && clip.target.type !== "item") error(`${clip.kind} must target an item`, "target");
21
+ if (clip.kind.startsWith("camera.") && clip.target.type !== "camera") error(`${clip.kind} must target the camera`, "target");
22
+ if (clip.kind === "motion.path") {
23
+ const points = clip.params.points;
24
+ if (!Array.isArray(points) || points.length < 2 || points.length > 1e4) error("motion path must contain 2 to 10000 world-offset points", "params.points", "world-offset");
25
+ else for (const [index, point] of points.entries()) if (!record(point) || !finite(point.x) || !finite(point.y)) error("motion path point must contain finite x and y", `params.points.${index}`, "world-offset");
26
+ }
27
+ if (clip.kind === "effects.particles") {
28
+ const count = clip.params.count;
29
+ if (!Number.isSafeInteger(count) || count < 1 || count > DEFAULT_BOARD_RENDER_LIMITS.particles) error(`particle count must be an integer from 1 to ${DEFAULT_BOARD_RENDER_LIMITS.particles}`, "params.count", void 0, "INVALID_PARTICLE_COUNT");
30
+ const bounds = clip.params.bounds;
31
+ if (!record(bounds) || !finite(bounds.x) || !finite(bounds.y) || !finite(bounds.width) || !finite(bounds.height) || bounds.width <= 0 || bounds.height <= 0) error("particles require positive finite world bounds", "params.bounds", "world", "PARTICLE_BOUNDS_REQUIRED");
32
+ }
33
+ if (clip.kind === "camera.focus") {
34
+ const parsed = BoardCameraFocusParamsSchema.safeParse(clip.params);
35
+ if (!parsed.success) error(parsed.error.issues[0]?.message ?? "invalid camera focus", "params", "world");
36
+ }
37
+ return errors;
38
+ }
39
+ function estimateBuiltinBoardClipCost(clip) {
40
+ switch (clip.kind) {
41
+ case "effects.particles": {
42
+ const count = Number.isSafeInteger(clip.params.count) ? Math.max(0, clip.params.count) : 0;
43
+ return {
44
+ particles: count,
45
+ vertices: count * 4,
46
+ dynamicVertices: count * 4,
47
+ drawCalls: 1,
48
+ bufferBytes: count * 48,
49
+ simulationSteps: count
50
+ };
51
+ }
52
+ case "effects.trail": return {
53
+ vertices: 32,
54
+ dynamicVertices: 32,
55
+ drawCalls: 1,
56
+ bufferBytes: 1024,
57
+ simulationSteps: 16
58
+ };
59
+ case "effects.impact":
60
+ case "effects.flash": return {
61
+ vertices: 64,
62
+ drawCalls: 1
63
+ };
64
+ case "draw.reveal":
65
+ case "draw.handwrite": return {
66
+ drawCalls: 1,
67
+ dynamicVertices: 1
68
+ };
69
+ case "motion.path": return { simulationSteps: Array.isArray(clip.params.points) ? clip.params.points.length : 0 };
70
+ default: return {};
71
+ }
72
+ }
73
+ //#endregion
74
+ export { estimateBuiltinBoardClipCost, validateBuiltinBoardClip };
@@ -0,0 +1,2 @@
1
+ import "./board-authoring.js";
2
+ import "./board.js";
@@ -0,0 +1,19 @@
1
+ import { BoardAuthoringItemSchema, BoardItemPatchSchema } from "./board-authoring.js";
2
+ //#region ../protocol/dist/board-codec.js
3
+ const isRecord = (value) => Boolean(value && typeof value === "object" && !Array.isArray(value));
4
+ function applyBoardItemPatch(current, value) {
5
+ const merged = mergePatch(current, BoardItemPatchSchema.parse(value));
6
+ merged.id = current.id;
7
+ merged.type = current.type;
8
+ if ("kindVersion" in current) merged.kindVersion = current.kindVersion;
9
+ return BoardAuthoringItemSchema.parse(merged);
10
+ }
11
+ function mergePatch(current, patch) {
12
+ if (!isRecord(patch)) return patch;
13
+ const result = isRecord(current) ? { ...current } : {};
14
+ for (const [key, value] of Object.entries(patch)) if (value === null) delete result[key];
15
+ else result[key] = isRecord(value) ? mergePatch(result[key], value) : value;
16
+ return result;
17
+ }
18
+ //#endregion
19
+ export { applyBoardItemPatch };