@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
@@ -1,12 +1,14 @@
1
- import "./board-constants.js";
1
+ import { BOARD_BUILTIN_CAPABILITIES, DEFAULT_BOARD_RENDER_LIMITS } from "./board-constants.js";
2
2
  import { BoardConnectionSchema } from "./board-connection.js";
3
+ import { BoardCompositionInputSchema } from "./board-composition.js";
4
+ import { BoardEffectInputSchema } from "./board-effect.js";
5
+ import { BoardAuthoringItemSchema, BoardItemPatchSchema, BoardSemanticMutationSchema } from "./board-authoring.js";
3
6
  import { z } from "zod";
4
7
  //#region ../protocol/dist/board.js
5
8
  const BOARD_EXTENSION = ".board";
6
9
  const BOARD_DOCUMENT_KIND = "cohub.board";
7
10
  const BOARD_MANIFEST_KIND = "cohub.board.manifest";
8
11
  const idSchema = z.string().min(1).max(160);
9
- const extensionIdSchema = z.string().regex(/^[a-z][a-z0-9]*(?:[.-][a-z0-9]+)+$/).max(160);
10
12
  const jsonObjectSchema = z.record(z.string(), z.unknown());
11
13
  const finiteSchema = z.number().finite();
12
14
  const BoardManifestSchema = z.object({
@@ -36,18 +38,6 @@ function parseBoardManifest(input) {
36
38
  function serializeBoardManifest(manifest) {
37
39
  return `${JSON.stringify(BoardManifestSchema.parse(manifest), null, 2)}\n`;
38
40
  }
39
- const BoardTargetSchema = z.discriminatedUnion("type", [
40
- z.object({
41
- type: z.literal("node"),
42
- nodeId: idSchema
43
- }),
44
- z.object({
45
- type: z.literal("effect"),
46
- effectId: idSchema
47
- }),
48
- z.object({ type: z.literal("board") }),
49
- z.object({ type: z.literal("camera") })
50
- ]);
51
41
  const BoardCameraStateSchema = z.object({
52
42
  centerX: finiteSchema,
53
43
  centerY: finiteSchema,
@@ -64,12 +54,12 @@ const BoardCameraFocusSchema = z.discriminatedUnion("type", [
64
54
  })
65
55
  }),
66
56
  z.object({
67
- type: z.literal("node"),
68
- nodeId: idSchema
57
+ type: z.literal("item"),
58
+ itemId: idSchema
69
59
  }),
70
60
  z.object({
71
- type: z.literal("nodes"),
72
- nodeIds: z.array(idSchema).min(1).max(1e3)
61
+ type: z.literal("items"),
62
+ itemIds: z.array(idSchema).min(1).max(1e3)
73
63
  }),
74
64
  z.object({
75
65
  type: z.literal("frame"),
@@ -89,85 +79,7 @@ const BoardCameraFocusParamsSchema = z.object({
89
79
  path: ["minZoom"]
90
80
  });
91
81
  });
92
- const BoardAssetRefSchema = z.object({
93
- type: z.enum(["space-file", "extension"]),
94
- ref: z.string().min(1).max(4096),
95
- digest: z.string().min(16).max(160).optional()
96
- });
97
- const BoardKeyframeSchema = z.object({
98
- at: finiteSchema.nonnegative(),
99
- value: z.unknown(),
100
- easing: z.string().min(1).max(80).optional()
101
- });
102
- const BoardClipSchema = z.object({
103
- id: idSchema,
104
- sequenceId: idSchema,
105
- kind: extensionIdSchema,
106
- kindVersion: z.number().int().positive(),
107
- target: BoardTargetSchema,
108
- start: finiteSchema.nonnegative(),
109
- duration: finiteSchema.positive(),
110
- layer: z.enum([
111
- "behind",
112
- "content",
113
- "front",
114
- "screen"
115
- ]).default("content"),
116
- fill: z.enum([
117
- "none",
118
- "backwards",
119
- "forwards",
120
- "both"
121
- ]).default("none"),
122
- easing: z.string().min(1).max(80).default("linear"),
123
- params: jsonObjectSchema.default({}),
124
- keyframes: z.array(BoardKeyframeSchema).default([]),
125
- assetRefs: z.array(BoardAssetRefSchema).default([]),
126
- seed: z.string().min(1).max(160),
127
- metadata: jsonObjectSchema.default({})
128
- });
129
- const BoardEffectSchema = z.object({
130
- id: idSchema,
131
- boardId: z.string().uuid(),
132
- target: z.discriminatedUnion("type", [z.object({
133
- type: z.literal("node"),
134
- nodeId: idSchema
135
- }), z.object({ type: z.literal("board") })]),
136
- kind: extensionIdSchema,
137
- kindVersion: z.number().int().positive(),
138
- enabled: z.boolean().default(true),
139
- lifecycle: z.enum([
140
- "persistent",
141
- "when-visible",
142
- "manual"
143
- ]),
144
- timeOrigin: z.enum([
145
- "board",
146
- "visible",
147
- "activation"
148
- ]),
149
- layer: z.enum([
150
- "behind",
151
- "front",
152
- "screen"
153
- ]).default("front"),
154
- seed: z.string().min(1).max(160),
155
- params: jsonObjectSchema.default({}),
156
- assetRefs: z.array(BoardAssetRefSchema).default([]),
157
- metadata: jsonObjectSchema.default({}),
158
- revision: z.number().int().nonnegative()
159
- });
160
- const BoardSequenceSchema = z.object({
161
- id: idSchema,
162
- boardId: z.string().uuid(),
163
- name: z.string().min(1).max(255),
164
- duration: finiteSchema.nonnegative(),
165
- seed: z.string().min(1).max(160),
166
- restPose: jsonObjectSchema.default({}),
167
- metadata: jsonObjectSchema.default({}),
168
- revision: z.number().int().nonnegative()
169
- });
170
- const BoardNodeInputSchema = z.object({
82
+ z.object({
171
83
  nodeId: idSchema,
172
84
  type: z.string().min(1).max(40),
173
85
  parentId: idSchema.nullable(),
@@ -184,35 +96,63 @@ const BoardNodeInputSchema = z.object({
184
96
  style: jsonObjectSchema,
185
97
  data: jsonObjectSchema
186
98
  });
187
- z.object({
99
+ const stripBoardServerFields = (value) => {
100
+ if (!value || typeof value !== "object" || Array.isArray(value)) return value;
101
+ const { boardId: _boardId, revision: _revision, ...input } = value;
102
+ return input;
103
+ };
104
+ const BoardCreateEffectInputSchema = z.preprocess(stripBoardServerFields, BoardEffectInputSchema);
105
+ const BoardCreateCompositionInputSchema = z.preprocess(stripBoardServerFields, BoardCompositionInputSchema);
106
+ const BoardCreateInputSchema = z.object({
188
107
  path: z.string().min(1),
189
108
  /** Reused by clients when board creation is interrupted and retried. */
190
109
  mutationId: z.string().max(128).optional(),
191
110
  title: z.string().min(1).max(255).optional(),
192
111
  metadata: jsonObjectSchema.optional(),
193
- nodes: z.array(BoardNodeInputSchema).max(5e4).optional(),
112
+ items: z.array(BoardAuthoringItemSchema).max(5e4).optional(),
194
113
  connections: z.array(BoardConnectionSchema).max(5e4).optional(),
195
- effects: z.array(BoardEffectSchema.omit({
196
- boardId: true,
197
- revision: true
198
- })).optional(),
199
- sequences: z.array(z.object({
200
- sequence: BoardSequenceSchema.omit({
201
- boardId: true,
202
- revision: true
203
- }),
204
- clips: z.array(BoardClipSchema.omit({ sequenceId: true }))
205
- })).optional()
114
+ effects: z.array(BoardCreateEffectInputSchema).max(5e4).optional(),
115
+ compositions: z.array(BoardCreateCompositionInputSchema).max(5e4).optional()
206
116
  });
117
+ const jsonSchema = (schema) => z.toJSONSchema(schema);
118
+ const authoringSchemaFactories = {
119
+ item: () => jsonSchema(BoardAuthoringItemSchema),
120
+ itemPatch: () => jsonSchema(BoardItemPatchSchema),
121
+ mutation: () => jsonSchema(BoardSemanticMutationSchema),
122
+ composition: () => jsonSchema(BoardCompositionInputSchema),
123
+ effect: () => jsonSchema(BoardEffectInputSchema),
124
+ create: () => jsonSchema(BoardCreateInputSchema)
125
+ };
126
+ /**
127
+ * JSON Schemas for the semantic authoring surface. Each property is enumerable
128
+ * for Object.keys/JSON.stringify, but generated only when that property is
129
+ * requested. This keeps protocol imports cheap while capabilities still returns
130
+ * the complete machine-readable schema object.
131
+ */
132
+ const BOARD_AUTHORING_SCHEMAS = {};
133
+ for (const key of Object.keys(authoringSchemaFactories)) {
134
+ let cached;
135
+ Object.defineProperty(BOARD_AUTHORING_SCHEMAS, key, {
136
+ enumerable: true,
137
+ configurable: false,
138
+ get() {
139
+ cached ??= authoringSchemaFactories[key]();
140
+ return cached;
141
+ }
142
+ });
143
+ }
207
144
  z.object({
208
145
  include: z.array(z.enum([
209
146
  "nodes",
210
147
  "connections",
211
148
  "effects",
212
- "sequences",
213
- "clips",
149
+ "compositions",
214
150
  "playback"
215
151
  ])).optional(),
152
+ nodeIds: z.array(idSchema).max(5e4).optional(),
153
+ connectionIds: z.array(idSchema).max(5e4).optional(),
154
+ effectIds: z.array(idSchema).max(5e4).optional(),
155
+ compositionIds: z.array(idSchema).max(5e4).optional(),
216
156
  viewport: z.object({
217
157
  x: finiteSchema,
218
158
  y: finiteSchema,
@@ -221,16 +161,15 @@ z.object({
221
161
  }).optional()
222
162
  });
223
163
  z.object({
224
- sequenceId: idSchema,
164
+ compositionId: idSchema,
225
165
  /** Delay before the first local playback after opening the Board, in milliseconds. */
226
- delayMs: finiteSchema.nonnegative().default(0),
227
- loop: z.boolean().default(false)
166
+ delayMs: finiteSchema.nonnegative().default(0)
228
167
  });
229
168
  z.discriminatedUnion("type", [
230
169
  z.object({
231
170
  commandId: idSchema,
232
171
  type: z.literal("play"),
233
- sequenceId: idSchema,
172
+ compositionId: idSchema,
234
173
  position: finiteSchema.nonnegative().optional(),
235
174
  timeScale: finiteSchema.positive().max(4).optional(),
236
175
  shared: z.boolean().optional(),
@@ -257,4 +196,4 @@ function isBoardPath(path) {
257
196
  return path.toLowerCase().endsWith(BOARD_EXTENSION);
258
197
  }
259
198
  //#endregion
260
- export { BOARD_DOCUMENT_KIND, BOARD_EXTENSION, BOARD_MANIFEST_KIND, BoardAssetRefSchema, BoardCameraFocusParamsSchema, BoardCameraFocusSchema, BoardCameraStateSchema, BoardClipSchema, BoardEffectSchema, BoardKeyframeSchema, BoardManifestSchema, BoardNodeInputSchema, BoardSequenceSchema, BoardTargetSchema, InvalidBoardFileError, isBoardPath, parseBoardManifest, serializeBoardManifest };
199
+ export { BOARD_AUTHORING_SCHEMAS, BOARD_BUILTIN_CAPABILITIES, BOARD_DOCUMENT_KIND, BOARD_EXTENSION, BOARD_MANIFEST_KIND, BoardCameraFocusParamsSchema, BoardCameraFocusSchema, BoardCameraStateSchema, BoardCreateInputSchema, BoardManifestSchema, DEFAULT_BOARD_RENDER_LIMITS, InvalidBoardFileError, isBoardPath, parseBoardManifest, serializeBoardManifest };
@@ -1,9 +1,14 @@
1
1
  import { BoardCapability, BoardCoordinateSpace, BoardRenderCost } from "./board-constants.js";
2
- import { AUTO_BOARD_CONNECTION_ANCHOR, BOARD_CONNECTION_DIRECTIONS, BOARD_CONNECTION_LINES, BOARD_CONNECTION_ROUTINGS, BOARD_CONNECTION_SIDES, BoardConnection, BoardConnectionAnchor, BoardConnectionAnchorSchema, BoardConnectionDirection, BoardConnectionEndpoint, BoardConnectionEndpointSchema, BoardConnectionInput, BoardConnectionLine, BoardConnectionPatch, BoardConnectionPatchSchema, BoardConnectionRecord, BoardConnectionRouting, BoardConnectionRoutingConfig, BoardConnectionRoutingSchema, BoardConnectionSchema, BoardConnectionSide, BoardConnectionStyle, BoardConnectionStyleSchema, BoardConnectionWaypointSchema, BoardRelationSchema, DEFAULT_BOARD_CONNECTION_ROUTING, DEFAULT_BOARD_CONNECTION_STYLE, DEFAULT_BOARD_RELATION, connectionNodeIds, connectionOtherNodeId, connectionTouchesNode, createBoardConnection, flipBoardConnection, normalizeBoardConnectionStyle } from "./board-connection.js";
3
- import { BOARD_COLOR_IDS, BOARD_GEO_KINDS, BoardColorId, BoardGeoKind, BoardNodeValidationDiagnostic } from "./board-node.js";
4
- import { BOARD_DELETE_REASONS, BOARD_DOCUMENT_KIND, BOARD_EXTENSION, BoardAssetRef, BoardAssetRefSchema, BoardCameraFocus, BoardCameraFocusParams, BoardCameraFocusParamsSchema, BoardCameraFocusSchema, BoardCameraState, BoardCameraStateSchema, BoardClip, BoardClipSchema, BoardDeleteReason, BoardDiagnostic, BoardEffect, BoardEffectSchema, BoardManifest, BoardManifestSchema, BoardNodeInput, BoardNodeRecord, BoardOperation, BoardPlaybackPolicy, BoardPlaybackPolicySchema, BoardRecord, BoardSequence, BoardSequenceSchema, BoardTarget, BoardTargetSchema, BoardValidationResult, InvalidBoardFileError, isBoardPath, parseBoardManifest, serializeBoardManifest } from "./board.js";
2
+ import { AUTO_BOARD_CONNECTION_ANCHOR, BOARD_CONNECTION_DIRECTIONS, BOARD_CONNECTION_LINES, BOARD_CONNECTION_ROUTINGS, BOARD_CONNECTION_SIDES, BoardConnection, BoardConnectionAnchor, BoardConnectionAnchorSchema, BoardConnectionDirection, BoardConnectionEndpoint, BoardConnectionEndpointSchema, BoardConnectionInput, BoardConnectionLine, BoardConnectionPatch, BoardConnectionPatchSchema, BoardConnectionRecord, BoardConnectionRouting, BoardConnectionRoutingConfig, BoardConnectionRoutingSchema, BoardConnectionSchema, BoardConnectionSide, BoardConnectionStyle, BoardConnectionStyleSchema, BoardConnectionWaypointSchema, BoardRelationSchema, DEFAULT_BOARD_CONNECTION_ROUTING, DEFAULT_BOARD_CONNECTION_STYLE, DEFAULT_BOARD_RELATION, connectionItemIds, connectionOtherItemId, connectionTouchesItem, createBoardConnection, flipBoardConnection, normalizeBoardConnectionStyle } from "./board-connection.js";
3
+ import { BoardAnimationTarget, BoardAnimationTargetSchema, BoardComposition, BoardCompositionInput, BoardCompositionInputSchema, BoardCompositionSchema, BoardEasing, BoardEasingSchema, BoardProceduralClip, BoardProceduralClipSchema, BoardTimelineMarker, BoardTimelineMarkerSchema, BoardTrack, BoardTrackInterpolation, BoardTrackSchema } from "./board-composition.js";
4
+ import { BoardAssetRef, BoardAssetRefSchema, BoardEffect, BoardEffectInput, BoardEffectInputSchema, BoardEffectSchema } from "./board-effect.js";
5
+ import { BoardAuthoringItem, BoardAuthoringItemSchema, BoardAuthoringSnapshot, BoardSemanticCommand, BoardSemanticCommandSchema } from "./board-authoring.js";
6
+ import { BOARD_DOCUMENT_KIND, BOARD_EXTENSION, BoardCameraFocus, BoardCameraFocusParams, BoardCameraFocusParamsSchema, BoardCameraFocusSchema, BoardCameraState, BoardCameraStateSchema, BoardDiagnostic, BoardManifest, BoardManifestSchema, BoardMutationReceipt, BoardPlaybackSnapshot, BoardPlaybackStatus, BoardValidationResult, isBoardPath, parseBoardManifest, serializeBoardManifest } from "./board.js";
7
+ import "./board-capability-registry.js";
8
+ import "./board-codec.js";
5
9
  import "./board-content.js";
10
+ import { BOARD_COLOR_IDS, BOARD_GEO_KINDS, BoardColorId, BoardGeoKind } from "./board-node.js";
6
11
  import "./realtime/board-awareness.js";
7
12
  import "./work.js";
8
13
  import "./realtime/types.js";
9
- export { AUTO_BOARD_CONNECTION_ANCHOR, BOARD_COLOR_IDS, BOARD_CONNECTION_DIRECTIONS, BOARD_CONNECTION_LINES, BOARD_CONNECTION_ROUTINGS, BOARD_CONNECTION_SIDES, BOARD_DELETE_REASONS, BOARD_DOCUMENT_KIND, BOARD_EXTENSION, BOARD_GEO_KINDS, BoardAssetRef, BoardAssetRefSchema, BoardCameraFocus, BoardCameraFocusParams, BoardCameraFocusParamsSchema, BoardCameraFocusSchema, BoardCameraState, BoardCameraStateSchema, BoardClip, BoardClipSchema, BoardColorId, BoardConnection, BoardConnectionAnchor, BoardConnectionAnchorSchema, BoardConnectionDirection, BoardConnectionEndpoint, BoardConnectionEndpointSchema, BoardConnectionInput, BoardConnectionLine, BoardConnectionPatch, BoardConnectionPatchSchema, BoardConnectionRecord, BoardConnectionRouting, BoardConnectionRoutingConfig, BoardConnectionRoutingSchema, BoardConnectionSchema, BoardConnectionSide, BoardConnectionStyle, BoardConnectionStyleSchema, BoardConnectionWaypointSchema, BoardDeleteReason, BoardDiagnostic, BoardEffect, BoardEffectSchema, BoardGeoKind, BoardManifest, BoardManifestSchema, BoardNodeInput, BoardNodeRecord, BoardNodeValidationDiagnostic, BoardOperation, BoardPlaybackPolicy, BoardPlaybackPolicySchema, BoardRecord, BoardRelationSchema, BoardSequence, BoardSequenceSchema, BoardTarget, BoardTargetSchema, BoardValidationResult, DEFAULT_BOARD_CONNECTION_ROUTING, DEFAULT_BOARD_CONNECTION_STYLE, DEFAULT_BOARD_RELATION, InvalidBoardFileError, connectionNodeIds, connectionOtherNodeId, connectionTouchesNode, createBoardConnection, flipBoardConnection, isBoardPath, normalizeBoardConnectionStyle, parseBoardManifest, serializeBoardManifest };
14
+ export { AUTO_BOARD_CONNECTION_ANCHOR, BOARD_COLOR_IDS, BOARD_CONNECTION_DIRECTIONS, BOARD_CONNECTION_LINES, BOARD_CONNECTION_ROUTINGS, BOARD_CONNECTION_SIDES, BOARD_DOCUMENT_KIND, BOARD_EXTENSION, BOARD_GEO_KINDS, BoardAnimationTarget, BoardAnimationTargetSchema, type BoardAssetRef, BoardAuthoringItem, BoardAuthoringItemSchema, BoardAuthoringSnapshot, BoardCameraFocus, BoardCameraFocusParams, BoardCameraFocusParamsSchema, BoardCameraFocusSchema, BoardCameraState, BoardCameraStateSchema, type BoardCapability, BoardColorId, BoardComposition, BoardCompositionInput, BoardCompositionInputSchema, BoardCompositionSchema, BoardConnection, BoardConnectionAnchor, BoardConnectionAnchorSchema, BoardConnectionDirection, BoardConnectionEndpoint, BoardConnectionEndpointSchema, BoardConnectionInput, BoardConnectionLine, BoardConnectionPatch, BoardConnectionPatchSchema, BoardConnectionRecord, BoardConnectionRouting, BoardConnectionRoutingConfig, BoardConnectionRoutingSchema, BoardConnectionSchema, BoardConnectionSide, BoardConnectionStyle, BoardConnectionStyleSchema, BoardConnectionWaypointSchema, BoardDiagnostic, BoardEasing, BoardEasingSchema, type BoardEffect, BoardGeoKind, BoardManifest, BoardManifestSchema, BoardMutationReceipt, BoardPlaybackSnapshot, BoardPlaybackStatus, BoardProceduralClip, BoardProceduralClipSchema, BoardRelationSchema, type BoardRenderCost, BoardSemanticCommand, BoardSemanticCommandSchema, BoardTimelineMarker, BoardTimelineMarkerSchema, BoardTrack, BoardTrackInterpolation, BoardTrackSchema, BoardValidationResult, DEFAULT_BOARD_CONNECTION_ROUTING, DEFAULT_BOARD_CONNECTION_STYLE, DEFAULT_BOARD_RELATION, connectionItemIds, connectionOtherItemId, connectionTouchesItem, createBoardConnection, flipBoardConnection, isBoardPath, normalizeBoardConnectionStyle, parseBoardManifest, serializeBoardManifest };
package/dist/types.d.ts CHANGED
@@ -1,5 +1,8 @@
1
1
  import { BoardCapability, BoardCoordinateSpace, BoardRenderCost } from "./protocol/dist/board-constants.js";
2
- import { BoardAssetRef, BoardCameraFocus, BoardCameraFocusParams, BoardCameraState, BoardClip, BoardDeleteReason, BoardDiagnostic, BoardEffect, BoardManifest, BoardNodeInput, BoardNodeRecord, BoardOperation, BoardPlaybackPolicy, BoardRecord, BoardSequence, BoardTarget, BoardValidationResult } from "./protocol/dist/board.js";
2
+ import { BoardAnimationTarget, BoardComposition, BoardEasing, BoardProceduralClip, BoardTimelineMarker, BoardTrack } from "./protocol/dist/board-composition.js";
3
+ import { BoardAssetRef, BoardEffect, BoardEffectInput } from "./protocol/dist/board-effect.js";
4
+ import { BoardAuthoringItem, BoardAuthoringSnapshot, BoardSemanticCommand } from "./protocol/dist/board-authoring.js";
5
+ import { BoardCameraFocus, BoardCameraFocusParams, BoardCameraState, BoardDiagnostic, BoardManifest, BoardMutationReceipt, BoardPlaybackSnapshot, BoardValidationResult } from "./protocol/dist/board.js";
3
6
  import "./protocol/dist/index.js";
4
7
  //#region src/types.d.ts
5
8
  type UserProfile = {
@@ -83,10 +83,24 @@ The Work runs inside a Cohub-hosted iframe (`window.parent !== window`). The
83
83
  SDK communicates with the parent window via `postMessage` to request tokens
84
84
  and context. This is the normal case when a viewer opens a Work through Cohub.
85
85
 
86
- - `client.context()` returns the **real** `space.id`, `work.id`, and current
87
- permission scopes from the host.
86
+ - `client.context()` returns the **real** `space.id`, `work.id`, current viewer,
87
+ and permission scopes from the host.
88
+ - A Work opened through `cohub ui preview` also receives an `invocation`
89
+ snapshot with the originating `spaceId`, `sessionId`, `turnId`, and
90
+ `toolCallId` when available. The invocation Space may differ from the Work's
91
+ own `space.id`.
88
92
  - `client.auth.request()` triggers an in-shell consent flow (no popup window).
89
93
 
94
+ ```js
95
+ const ctx = await client.context();
96
+ console.log(ctx.viewer?.userUuid ?? null);
97
+ console.log(ctx.invocation?.sessionId ?? null);
98
+ ```
99
+
100
+ Invocation fields describe where the preview came from. They are identifiers,
101
+ not authorization: API access remains controlled by the Work session token and
102
+ its scopes.
103
+
90
104
  ### Broker mode (standalone deployment)
91
105
 
92
106
  The Work is accessed as a standalone page (`window.parent === window`), e.g.
@@ -183,6 +197,7 @@ but **not active** until the viewer approves them through a consent dialog
183
197
  triggered by `client.auth.request()`. These are **action** permissions.
184
198
 
185
199
  ```
200
+ taskrun.view — read Task Runs the viewer can already access
186
201
  session.prompt.readonly — send read-only prompts (no side effects)
187
202
  session.prompt.fullaccess — send prompts with full access (write, create sessions)
188
203
  generation.create — create generation tasks (image/video/audio)
@@ -199,7 +214,8 @@ user.usage.read — read the viewer's aggregated usage
199
214
  `session.prompt.fullaccess` lets you **send** a prompt, but does **not** let
200
215
  you **read** the result — that needs `session.view` (a work scope).
201
216
  `generation.create` lets you **create** a generation task, but reading its
202
- result needs `taskrun.view` (a work scope).
217
+ result needs `taskrun.view`, either from the publishing Space's work scopes or
218
+ from viewer authorization checked against the requested Space or Session.
203
219
 
204
220
  ### Complete API → scope mapping
205
221
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neta-art/cohub",
3
- "version": "5.10.0",
3
+ "version": "7.0.0",
4
4
  "description": "Cohub SDK for spaces, sessions, boards, and realtime agent collaboration.",
5
5
  "license": "Apache-2.0",
6
6
  "private": false,
@@ -100,7 +100,7 @@
100
100
  "build": "tsdown",
101
101
  "lint": "biome lint .",
102
102
  "lint:fix": "biome lint --write .",
103
- "test": "node ../../scripts/test/run.mjs 'src/**/*.test.ts' 'tests/**/*.test.ts'",
103
+ "test": "node ../../scripts/test/run.mjs --test-concurrency=2 'src/**/*.test.ts' 'tests/**/*.test.ts'",
104
104
  "typecheck": "tsc -p tsconfig.json --noEmit"
105
105
  }
106
106
  }
@@ -1,27 +0,0 @@
1
- import { BoardConnectionRecord } from "../protocol/dist/board-connection.js";
2
- import { BoardManifest, BoardNodeInput, BoardNodeRecord, BoardRecord, InvalidBoardFileError, isBoardPath, parseBoardManifest, serializeBoardManifest } from "../protocol/dist/board.js";
3
- import "../protocol/dist/index.js";
4
- import { BoardAppearance, BoardDocument, BoardItem } from "../protocol/dist/board-document.js";
5
- //#region src/board/codec.d.ts
6
- declare const DEFAULT_BOARD_APPEARANCE: BoardAppearance;
7
- declare const ITEM_BASE_KEYS: readonly ["id", "type", "frame", "locked", "style", "metadata"];
8
- /**
9
- * Original wire data follows an item through immutable object spreads while
10
- * remaining invisible to JSON serialization. Codecs can then patch only the
11
- * fields this client understands instead of rebuilding and truncating a node.
12
- */
13
- declare const BOARD_NODE_SOURCE: unique symbol;
14
- type WireBackedBoardItem = BoardItem & {
15
- [BOARD_NODE_SOURCE]?: BoardNodeInput;
16
- };
17
- declare function nodeInputFromRecord(node: BoardNodeRecord): BoardNodeInput;
18
- declare function sourceForItem(item: BoardItem): BoardNodeInput | undefined;
19
- declare function isRecord(value: unknown): value is Record<string, unknown>;
20
- declare function boardNodeToItem(node: BoardNodeRecord): BoardItem;
21
- declare function boardBootstrapToDocument(input: {
22
- board: BoardRecord;
23
- nodes: BoardNodeRecord[];
24
- connections?: BoardConnectionRecord[];
25
- }): BoardDocument;
26
- //#endregion
27
- export { BOARD_NODE_SOURCE, type BoardManifest, type BoardNodeRecord, type BoardRecord, DEFAULT_BOARD_APPEARANCE, ITEM_BASE_KEYS, InvalidBoardFileError, WireBackedBoardItem, boardBootstrapToDocument, boardNodeToItem, isBoardPath, isRecord, nodeInputFromRecord, parseBoardManifest, serializeBoardManifest, sourceForItem };
@@ -1,277 +0,0 @@
1
- import { BOARD_DOCUMENT_KIND, InvalidBoardFileError, isBoardPath, parseBoardManifest, serializeBoardManifest } from "../protocol/dist/board.js";
2
- import { BoardAppearanceSchema, BoardFileSnapshotSchema, BoardTaskSnapshotSchema, UNKNOWN_BOARD_ITEM_TYPE, parseBoardDocument } from "../protocol/dist/board-document.js";
3
- import "../protocol/dist/index.js";
4
- import { TEXT_FONT_SIZE, clampBoardTextFontSize } from "./core/text-metrics.js";
5
- //#region src/board/codec.ts
6
- const DEFAULT_BOARD_APPEARANCE = BoardAppearanceSchema.parse({
7
- theme: "clean",
8
- background: { kind: "solid" },
9
- grid: {
10
- visible: false,
11
- size: 24,
12
- opacity: .12
13
- },
14
- mood: "clean"
15
- });
16
- const ITEM_BASE_KEYS = [
17
- "id",
18
- "type",
19
- "frame",
20
- "locked",
21
- "style",
22
- "metadata"
23
- ];
24
- /**
25
- * Original wire data follows an item through immutable object spreads while
26
- * remaining invisible to JSON serialization. Codecs can then patch only the
27
- * fields this client understands instead of rebuilding and truncating a node.
28
- */
29
- const BOARD_NODE_SOURCE = Symbol("board-node-source");
30
- function nodeInputFromRecord(node) {
31
- return {
32
- nodeId: node.nodeId,
33
- type: node.type,
34
- parentId: node.parentId ?? null,
35
- orderKey: node.orderKey ?? null,
36
- x: node.x,
37
- y: node.y,
38
- width: node.width,
39
- height: node.height,
40
- rotation: node.rotation,
41
- refKind: node.refKind ?? null,
42
- refPath: node.refPath ?? null,
43
- refUrl: node.refUrl ?? null,
44
- view: node.view ?? {},
45
- style: node.style ?? {},
46
- data: node.data ?? {}
47
- };
48
- }
49
- function sourceForItem(item) {
50
- return item[BOARD_NODE_SOURCE];
51
- }
52
- function isRecord(value) {
53
- return Boolean(value && typeof value === "object" && !Array.isArray(value));
54
- }
55
- function frameFromNode(node) {
56
- return {
57
- x: node.x,
58
- y: node.y,
59
- width: node.width,
60
- height: node.height,
61
- rotation: node.rotation
62
- };
63
- }
64
- function lockedFromData(data) {
65
- return data.locked === true ? true : void 0;
66
- }
67
- function styleFromNode(node) {
68
- return Object.keys(node.style ?? {}).length ? node.style : void 0;
69
- }
70
- function spaceFilePathFromNode(node) {
71
- if (node.refKind === "space_file" && node.refPath) return node.refPath;
72
- if (typeof node.refPath === "string" && node.refPath) return node.refPath;
73
- return null;
74
- }
75
- /** Read a stored world point, defaulting to the origin when absent. */
76
- function pointFromData(value) {
77
- if (isRecord(value) && typeof value.x === "number" && typeof value.y === "number") return {
78
- x: value.x,
79
- y: value.y
80
- };
81
- return {
82
- x: 0,
83
- y: 0
84
- };
85
- }
86
- function unknownItemFromNode(node, frame, style, locked, data) {
87
- const raw = {
88
- ...data,
89
- id: node.nodeId,
90
- type: node.type,
91
- frame
92
- };
93
- if (style) raw.style = style;
94
- if (locked) raw.locked = true;
95
- return {
96
- id: node.nodeId,
97
- type: UNKNOWN_BOARD_ITEM_TYPE,
98
- frame,
99
- ...locked ? { locked } : {},
100
- style,
101
- raw
102
- };
103
- }
104
- function boardNodeToItemValue(node) {
105
- const frame = frameFromNode(node);
106
- const style = styleFromNode(node);
107
- const data = node.data ?? {};
108
- const locked = lockedFromData(data);
109
- switch (node.type) {
110
- case "text": return {
111
- id: node.nodeId,
112
- type: "text",
113
- text: typeof data.text === "string" ? data.text : "",
114
- color: typeof data.color === "string" ? data.color : "neutral",
115
- fontSize: clampBoardTextFontSize(typeof data.fontSize === "number" ? data.fontSize : TEXT_FONT_SIZE),
116
- frame,
117
- ...locked ? { locked } : {},
118
- style
119
- };
120
- case "geo": return {
121
- id: node.nodeId,
122
- type: "geo",
123
- geo: typeof data.geo === "string" ? data.geo : "rectangle",
124
- text: typeof data.text === "string" ? data.text : "",
125
- color: typeof data.color === "string" ? data.color : "brand",
126
- fillOpacity: typeof data.fillOpacity === "number" ? data.fillOpacity : 0,
127
- frame,
128
- ...locked ? { locked } : {},
129
- style
130
- };
131
- case "draw": return {
132
- id: node.nodeId,
133
- type: "draw",
134
- points: Array.isArray(data.points) ? data.points : [],
135
- color: typeof data.color === "string" ? data.color : "brand",
136
- size: typeof data.size === "number" ? data.size : 4,
137
- frame,
138
- ...locked ? { locked } : {},
139
- style
140
- };
141
- case "arrow": return {
142
- id: node.nodeId,
143
- type: "arrow",
144
- start: pointFromData(data.start),
145
- end: pointFromData(data.end),
146
- bend: typeof data.bend === "number" ? data.bend : 0,
147
- color: typeof data.color === "string" ? data.color : "brand",
148
- size: typeof data.size === "number" ? data.size : 2.5,
149
- arrowStart: Boolean(data.arrowStart),
150
- arrowEnd: data.arrowEnd === void 0 ? true : Boolean(data.arrowEnd),
151
- label: typeof data.label === "string" ? data.label : "",
152
- frame,
153
- ...locked ? { locked } : {},
154
- style
155
- };
156
- case "frame": return {
157
- id: node.nodeId,
158
- type: "frame",
159
- label: typeof data.label === "string" ? data.label : "Frame",
160
- color: typeof data.color === "string" ? data.color : "neutral",
161
- frame,
162
- ...locked ? { locked } : {},
163
- style
164
- };
165
- case "image": {
166
- const path = spaceFilePathFromNode(node) ?? "missing";
167
- return {
168
- id: node.nodeId,
169
- type: "image",
170
- ref: {
171
- kind: "space-file",
172
- path
173
- },
174
- snapshot: node.view,
175
- ...data.crop && typeof data.crop === "object" ? { crop: data.crop } : {},
176
- frame,
177
- ...locked ? { locked } : {},
178
- style
179
- };
180
- }
181
- case "video": {
182
- const path = spaceFilePathFromNode(node) ?? "missing";
183
- return {
184
- id: node.nodeId,
185
- type: "video",
186
- ref: {
187
- kind: "space-file",
188
- path
189
- },
190
- snapshot: node.view,
191
- frame,
192
- ...locked ? { locked } : {},
193
- style
194
- };
195
- }
196
- case "audio": {
197
- const path = spaceFilePathFromNode(node) ?? "missing";
198
- return {
199
- id: node.nodeId,
200
- type: "audio",
201
- ref: {
202
- kind: "space-file",
203
- path
204
- },
205
- snapshot: node.view,
206
- frame,
207
- ...locked ? { locked } : {},
208
- style
209
- };
210
- }
211
- case "file": {
212
- const path = spaceFilePathFromNode(node) ?? "missing";
213
- const parsed = BoardFileSnapshotSchema.safeParse(node.view ?? {});
214
- return {
215
- id: node.nodeId,
216
- type: "file",
217
- ref: {
218
- kind: "space-file",
219
- path
220
- },
221
- ...parsed.success ? { snapshot: parsed.data } : {},
222
- frame,
223
- ...locked ? { locked } : {},
224
- style
225
- };
226
- }
227
- case "task": {
228
- const parsed = BoardTaskSnapshotSchema.safeParse(node.view ?? {});
229
- if (parsed.success && typeof data.taskRunId === "string") return {
230
- id: node.nodeId,
231
- type: "task",
232
- taskRunId: data.taskRunId,
233
- snapshot: parsed.data,
234
- frame,
235
- ...locked ? { locked } : {},
236
- style
237
- };
238
- return unknownItemFromNode(node, frame, style, locked, data);
239
- }
240
- default: return unknownItemFromNode(node, frame, style, locked, data);
241
- }
242
- }
243
- function boardNodeToItem(node) {
244
- const item = boardNodeToItemValue(node);
245
- const metadata = isRecord(node.data?.metadata) ? node.data.metadata : void 0;
246
- return {
247
- ...item,
248
- ...metadata ? { metadata } : {},
249
- [BOARD_NODE_SOURCE]: nodeInputFromRecord(node)
250
- };
251
- }
252
- function boardBootstrapToDocument(input) {
253
- const appearance = BoardAppearanceSchema.safeParse(input.board.metadata.appearance);
254
- const connections = (input.connections ?? []).map(({ boardId: _boardId, revision: _revision, createdAt: _createdAt, updatedAt: _updatedAt, ...connection }) => connection);
255
- const document = parseBoardDocument({
256
- kind: BOARD_DOCUMENT_KIND,
257
- version: 1,
258
- appearance: appearance.success ? appearance.data : DEFAULT_BOARD_APPEARANCE,
259
- viewport: {
260
- x: 0,
261
- y: 0,
262
- zoom: 1
263
- },
264
- items: input.nodes.map(boardNodeToItem),
265
- connections
266
- });
267
- const sources = new Map(input.nodes.map((node) => [node.nodeId, nodeInputFromRecord(node)]));
268
- return {
269
- ...document,
270
- items: document.items.map((item) => ({
271
- ...item,
272
- [BOARD_NODE_SOURCE]: sources.get(item.id)
273
- }))
274
- };
275
- }
276
- //#endregion
277
- export { BOARD_NODE_SOURCE, DEFAULT_BOARD_APPEARANCE, ITEM_BASE_KEYS, InvalidBoardFileError, boardBootstrapToDocument, boardNodeToItem, isBoardPath, isRecord, nodeInputFromRecord, parseBoardManifest, serializeBoardManifest, sourceForItem };