@neta-art/cohub 8.11.0 → 8.12.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 (43) hide show
  1. package/dist/board/animation.js +14 -2
  2. package/dist/board/core/file-preview.d.ts +2 -2
  3. package/dist/board/core/file-preview.js +2 -2
  4. package/dist/board/index.d.ts +2 -1
  5. package/dist/board/index.js +2 -1
  6. package/dist/board/mutation.js +2 -1
  7. package/dist/board/render/board-background.d.ts +16 -0
  8. package/dist/board/render/{themes/clean-theme.js → board-background.js} +28 -35
  9. package/dist/board/render/index.d.ts +3 -3
  10. package/dist/board/render/index.js +2 -2
  11. package/dist/board/render/renderers/file-card-renderer.js +3 -32
  12. package/dist/board/replay.d.ts +52 -0
  13. package/dist/board/replay.js +261 -0
  14. package/dist/board/semantic-document.d.ts +9 -2
  15. package/dist/board/semantic-document.js +1 -3
  16. package/dist/chunks/environment.d.ts +272 -7
  17. package/dist/chunks/environment.js +1 -0
  18. package/dist/chunks/http.d.ts +76 -5
  19. package/dist/chunks/http.js +47 -10
  20. package/dist/chunks/websocket.d.ts +1 -1
  21. package/dist/http.d.ts +3 -3
  22. package/dist/index.d.ts +9 -4
  23. package/dist/index.js +167 -46
  24. package/dist/protocol/dist/board-animation.d.ts +1 -0
  25. package/dist/protocol/dist/board-animation.js +34 -0
  26. package/dist/protocol/dist/board-authoring.d.ts +2 -1
  27. package/dist/protocol/dist/board-capability-registry.js +53 -3
  28. package/dist/protocol/dist/board-codec.js +149 -2
  29. package/dist/protocol/dist/board-constants.js +29 -7
  30. package/dist/protocol/dist/board-document.d.ts +30 -16
  31. package/dist/protocol/dist/board-document.js +15 -12
  32. package/dist/protocol/dist/board-effect.d.ts +4 -2
  33. package/dist/protocol/dist/board-effect.js +3 -2
  34. package/dist/protocol/dist/board.d.ts +148 -3
  35. package/dist/protocol/dist/board.js +7 -0
  36. package/dist/protocol/dist/index.d.ts +4 -2
  37. package/dist/protocol/dist/provenance.d.ts +21 -0
  38. package/dist/types.d.ts +1 -1
  39. package/docs/app-runtime-guide.md +7 -4
  40. package/package.json +1 -1
  41. package/dist/board/render/themes/board-theme-registry.d.ts +0 -22
  42. package/dist/board/render/themes/board-theme-registry.js +0 -13
  43. package/dist/board/render/themes/clean-theme.d.ts +0 -5
@@ -21,7 +21,11 @@ const BOARD_BUILTIN_CLIP_KINDS = [
21
21
  "camera.focus",
22
22
  "camera.shake"
23
23
  ];
24
- const BOARD_BUILTIN_EFFECT_KINDS = ["effects.pulse", "effects.float"];
24
+ const BOARD_BUILTIN_EFFECT_KINDS = [
25
+ "effects.pulse",
26
+ "effects.float",
27
+ "effects.deal"
28
+ ];
25
29
  /**
26
30
  * World-space typography for board text.
27
31
  *
@@ -85,6 +89,20 @@ function clipSchema(id) {
85
89
  default: return;
86
90
  }
87
91
  }
92
+ function effectSchema(id) {
93
+ switch (id) {
94
+ case "effects.deal": return { params: {
95
+ lift: { unit: "board" },
96
+ swing: { unit: "board" },
97
+ curve: { unit: "board" },
98
+ tilt: { unit: "degree" },
99
+ scale: { unit: "ratio" },
100
+ duration: { unit: "ms" },
101
+ landing: { unit: "ms" }
102
+ } };
103
+ default: return;
104
+ }
105
+ }
88
106
  const BOARD_BUILTIN_CAPABILITIES = [...BOARD_BUILTIN_CLIP_KINDS.map((id) => {
89
107
  const schema = clipSchema(id);
90
108
  return {
@@ -94,11 +112,15 @@ const BOARD_BUILTIN_CAPABILITIES = [...BOARD_BUILTIN_CLIP_KINDS.map((id) => {
94
112
  renderers: ["webgpu", "webgl"],
95
113
  ...schema ? { schema } : {}
96
114
  };
97
- }), ...BOARD_BUILTIN_EFFECT_KINDS.map((id) => ({
98
- kind: "effect",
99
- id,
100
- version: 1,
101
- renderers: ["webgpu", "webgl"]
102
- }))];
115
+ }), ...BOARD_BUILTIN_EFFECT_KINDS.map((id) => {
116
+ const schema = effectSchema(id);
117
+ return {
118
+ kind: "effect",
119
+ id,
120
+ version: 1,
121
+ renderers: ["webgpu", "webgl"],
122
+ ...schema ? { schema } : {}
123
+ };
124
+ })];
103
125
  //#endregion
104
126
  export { BOARD_ARROW_STROKE_SIZE, BOARD_BUILTIN_CAPABILITIES, BOARD_BUILTIN_CLIP_KINDS, BOARD_BUILTIN_EFFECT_KINDS, BOARD_CONNECTION_STROKE_SIZE, BOARD_FONT_STACK, BOARD_MONO_FONT_STACK, BOARD_STROKE_MAX_SIZE, BOARD_STROKE_MIN_SIZE, BOARD_TEXT_FONT_FAMILY, DEFAULT_BOARD_RENDER_LIMITS, clampBoardStrokeSize };
@@ -21,7 +21,21 @@ declare const BoardViewportSchema: z.ZodObject<{
21
21
  zoom: z.ZodNumber;
22
22
  }, z.core.$strip>;
23
23
  declare const BoardAppearanceSchema: z.ZodObject<{
24
- theme: z.ZodDefault<z.ZodString>;
24
+ theme: z.ZodOptional<z.ZodString>;
25
+ motion: z.ZodOptional<z.ZodObject<{
26
+ enter: z.ZodOptional<z.ZodObject<{
27
+ kind: z.ZodString;
28
+ kindVersion: z.ZodDefault<z.ZodNumber>;
29
+ params: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
30
+ }, z.core.$strict>>;
31
+ }, z.core.$strict>>;
32
+ mood: z.ZodOptional<z.ZodEnum<{
33
+ arcane: "arcane";
34
+ clean: "clean";
35
+ cyber: "cyber";
36
+ natural: "natural";
37
+ playful: "playful";
38
+ }>>;
25
39
  background: z.ZodDefault<z.ZodObject<{
26
40
  kind: z.ZodDefault<z.ZodEnum<{
27
41
  custom: "custom";
@@ -52,13 +66,6 @@ declare const BoardAppearanceSchema: z.ZodObject<{
52
66
  size: z.ZodDefault<z.ZodNumber>;
53
67
  opacity: z.ZodDefault<z.ZodNumber>;
54
68
  }, z.core.$strip>>;
55
- mood: z.ZodDefault<z.ZodEnum<{
56
- arcane: "arcane";
57
- clean: "clean";
58
- cyber: "cyber";
59
- natural: "natural";
60
- playful: "playful";
61
- }>>;
62
69
  }, z.core.$strip>;
63
70
  /** Optional visual chrome still carried by a few older shapes. */
64
71
  declare const BoardItemStyleSchema: z.ZodObject<{
@@ -1046,7 +1053,21 @@ declare const BoardDocumentSchema: z.ZodObject<{
1046
1053
  kind: z.ZodLiteral<"cohub.board">;
1047
1054
  version: z.ZodLiteral<1>;
1048
1055
  appearance: z.ZodDefault<z.ZodObject<{
1049
- theme: z.ZodDefault<z.ZodString>;
1056
+ theme: z.ZodOptional<z.ZodString>;
1057
+ motion: z.ZodOptional<z.ZodObject<{
1058
+ enter: z.ZodOptional<z.ZodObject<{
1059
+ kind: z.ZodString;
1060
+ kindVersion: z.ZodDefault<z.ZodNumber>;
1061
+ params: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1062
+ }, z.core.$strict>>;
1063
+ }, z.core.$strict>>;
1064
+ mood: z.ZodOptional<z.ZodEnum<{
1065
+ arcane: "arcane";
1066
+ clean: "clean";
1067
+ cyber: "cyber";
1068
+ natural: "natural";
1069
+ playful: "playful";
1070
+ }>>;
1050
1071
  background: z.ZodDefault<z.ZodObject<{
1051
1072
  kind: z.ZodDefault<z.ZodEnum<{
1052
1073
  custom: "custom";
@@ -1077,13 +1098,6 @@ declare const BoardDocumentSchema: z.ZodObject<{
1077
1098
  size: z.ZodDefault<z.ZodNumber>;
1078
1099
  opacity: z.ZodDefault<z.ZodNumber>;
1079
1100
  }, z.core.$strip>>;
1080
- mood: z.ZodDefault<z.ZodEnum<{
1081
- arcane: "arcane";
1082
- clean: "clean";
1083
- cyber: "cyber";
1084
- natural: "natural";
1085
- playful: "playful";
1086
- }>>;
1087
1101
  }, z.core.$strip>>;
1088
1102
  viewport: z.ZodObject<{
1089
1103
  x: z.ZodNumber;
@@ -1,6 +1,7 @@
1
1
  import { BOARD_ARROW_STROKE_SIZE } from "./board-constants.js";
2
2
  import { BoardConnectionSchema } from "./board-connection.js";
3
3
  import { BOARD_DOCUMENT_KIND, BOARD_EXTENSION } from "./board.js";
4
+ import { BoardMotionSchema } from "./board-animation.js";
4
5
  import { BOARD_REMOTE_URL_MAX_LENGTH, BoardRemoteUrlSchema, isPublicBoardRemoteAddress, normalizeBoardRemoteUrl } from "./board-url.js";
5
6
  import { z } from "zod";
6
7
  //#region ../protocol/dist/board-document.js
@@ -23,7 +24,18 @@ const BoardViewportSchema = z.object({
23
24
  zoom: z.number().finite().min(.05).max(8)
24
25
  });
25
26
  const BoardAppearanceSchema = z.object({
26
- theme: z.string().min(1).default("clean"),
27
+ /** Legacy field retained when reading older Board documents; not used for rendering. */
28
+ theme: z.string().min(1).optional(),
29
+ /** Board-wide motion policies. Omitted policies mean no motion. */
30
+ motion: BoardMotionSchema.optional(),
31
+ /** Legacy field retained when reading older Board documents; not used for rendering. */
32
+ mood: z.enum([
33
+ "clean",
34
+ "playful",
35
+ "arcane",
36
+ "cyber",
37
+ "natural"
38
+ ]).optional(),
27
39
  background: z.object({
28
40
  kind: z.enum([
29
41
  "solid",
@@ -57,14 +69,7 @@ const BoardAppearanceSchema = z.object({
57
69
  visible: false,
58
70
  size: 24,
59
71
  opacity: .12
60
- }),
61
- mood: z.enum([
62
- "clean",
63
- "playful",
64
- "arcane",
65
- "cyber",
66
- "natural"
67
- ]).default("clean")
72
+ })
68
73
  });
69
74
  /** Optional visual chrome still carried by a few older shapes. */
70
75
  const BoardItemStyleSchema = z.object({
@@ -390,14 +395,12 @@ const BoardDocumentSchema = z.object({
390
395
  kind: z.literal(BOARD_DOCUMENT_KIND),
391
396
  version: z.literal(1),
392
397
  appearance: BoardAppearanceSchema.default({
393
- theme: "clean",
394
398
  background: { kind: "solid" },
395
399
  grid: {
396
400
  visible: false,
397
401
  size: 24,
398
402
  opacity: .12
399
- },
400
- mood: "clean"
403
+ }
401
404
  }),
402
405
  viewport: BoardViewportSchema,
403
406
  items: z.array(BoardItemSchema),
@@ -18,10 +18,11 @@ declare const BoardEffectSchema: z.ZodObject<{
18
18
  type: z.ZodLiteral<"board">;
19
19
  }, z.core.$strict>], "type">;
20
20
  kind: z.ZodString;
21
- kindVersion: z.ZodNumber;
21
+ kindVersion: z.ZodDefault<z.ZodNumber>;
22
22
  enabled: z.ZodDefault<z.ZodBoolean>;
23
23
  lifecycle: z.ZodEnum<{
24
24
  manual: "manual";
25
+ "on-enter": "on-enter";
25
26
  persistent: "persistent";
26
27
  "when-visible": "when-visible";
27
28
  }>;
@@ -60,10 +61,11 @@ declare const BoardEffectInputSchema: z.ZodObject<{
60
61
  type: z.ZodLiteral<"board">;
61
62
  }, z.core.$strict>], "type">;
62
63
  kind: z.ZodString;
63
- kindVersion: z.ZodNumber;
64
+ kindVersion: z.ZodDefault<z.ZodNumber>;
64
65
  enabled: z.ZodDefault<z.ZodBoolean>;
65
66
  lifecycle: z.ZodEnum<{
66
67
  manual: "manual";
68
+ "on-enter": "on-enter";
67
69
  persistent: "persistent";
68
70
  "when-visible": "when-visible";
69
71
  }>;
@@ -21,12 +21,13 @@ const BoardEffectSchema = z.object({
21
21
  itemId: idSchema
22
22
  }).strict(), z.object({ type: z.literal("board") }).strict()]),
23
23
  kind: extensionIdSchema,
24
- kindVersion: z.number().int().positive(),
24
+ kindVersion: z.number().int().positive().default(1),
25
25
  enabled: z.boolean().default(true),
26
26
  lifecycle: z.enum([
27
27
  "persistent",
28
28
  "when-visible",
29
- "manual"
29
+ "manual",
30
+ "on-enter"
30
31
  ]),
31
32
  timeOrigin: z.enum([
32
33
  "board",
@@ -1,8 +1,9 @@
1
1
  import { BoardCapability, BoardCoordinateSpace, BoardRenderCost } from "./board-constants.js";
2
- import "./board-connection.js";
3
- import "./board-composition.js";
2
+ import { BoardConnectionInput, BoardConnectionPatch, BoardConnectionRecord } from "./board-connection.js";
3
+ import { BoardComposition } from "./board-composition.js";
4
4
  import { BoardAssetRef, BoardAssetRefSchema, BoardEffect, BoardEffectInput, BoardEffectInputSchema, BoardEffectSchema } from "./board-effect.js";
5
5
  import "./board-authoring.js";
6
+ import { RequestSource } from "./provenance.js";
6
7
  import { z } from "zod";
7
8
  //#region ../protocol/dist/board.d.ts
8
9
  declare const BOARD_EXTENSION: ".board";
@@ -69,6 +70,108 @@ declare const BoardCameraFocusParamsSchema: z.ZodObject<{
69
70
  type BoardCameraState = z.infer<typeof BoardCameraStateSchema>;
70
71
  type BoardCameraFocus = z.infer<typeof BoardCameraFocusSchema>;
71
72
  type BoardCameraFocusParams = z.infer<typeof BoardCameraFocusParamsSchema>;
73
+ type BoardRecord = {
74
+ id: string;
75
+ spaceId: string;
76
+ title: string;
77
+ version: number;
78
+ metadata: Record<string, unknown>;
79
+ createdAt: string | null;
80
+ updatedAt: string | null;
81
+ };
82
+ type BoardNodeRecord = {
83
+ boardId: string;
84
+ nodeId: string;
85
+ type: string;
86
+ parentId: string | null;
87
+ orderKey: string | null;
88
+ x: number;
89
+ y: number;
90
+ width: number;
91
+ height: number;
92
+ rotation: number;
93
+ refKind: string | null;
94
+ refPath: string | null;
95
+ refUrl: string | null;
96
+ view: Record<string, unknown>;
97
+ style: Record<string, unknown>;
98
+ data: Record<string, unknown>;
99
+ version: number;
100
+ createdAt: string | null;
101
+ updatedAt: string | null;
102
+ };
103
+ type BoardNodeInput = Omit<BoardNodeRecord, "boardId" | "version" | "createdAt" | "updatedAt">;
104
+ declare const BOARD_DELETE_REASONS: readonly ["user-delete", "orphan-cleanup", "layout-replace", "placeholder-cascade", "node-cascade"];
105
+ type BoardDeleteReason = (typeof BOARD_DELETE_REASONS)[number] | (string & {});
106
+ type BoardOperationBase = {
107
+ opId?: string;
108
+ /** Optional local undo hint. Servers recompute authoritative inverse data. */
109
+ inverse?: Record<string, unknown>;
110
+ };
111
+ type BoardOperation = (BoardOperationBase & {
112
+ type: "board.patch";
113
+ payload: {
114
+ patch: {
115
+ title?: string;
116
+ metadata?: Record<string, unknown>;
117
+ metadataPatch?: Record<string, unknown>;
118
+ };
119
+ };
120
+ }) | (BoardOperationBase & {
121
+ type: "node.create";
122
+ payload: {
123
+ node: BoardNodeInput;
124
+ };
125
+ }) | (BoardOperationBase & {
126
+ type: "node.patch";
127
+ payload: {
128
+ nodeId: string;
129
+ patch: Partial<BoardNodeInput>;
130
+ };
131
+ }) | (BoardOperationBase & {
132
+ type: "node.delete";
133
+ payload: {
134
+ nodeId: string;
135
+ reason?: BoardDeleteReason;
136
+ };
137
+ }) | (BoardOperationBase & {
138
+ type: "connection.create";
139
+ payload: {
140
+ connection: BoardConnectionInput;
141
+ };
142
+ }) | (BoardOperationBase & {
143
+ type: "connection.patch";
144
+ payload: {
145
+ connectionId: string;
146
+ patch: BoardConnectionPatch;
147
+ };
148
+ }) | (BoardOperationBase & {
149
+ type: "connection.delete";
150
+ payload: {
151
+ connectionId: string;
152
+ reason?: BoardDeleteReason;
153
+ };
154
+ }) | (BoardOperationBase & {
155
+ type: "effect.upsert";
156
+ payload: {
157
+ effect: Omit<BoardEffect, "boardId" | "revision">;
158
+ };
159
+ }) | (BoardOperationBase & {
160
+ type: "effect.delete";
161
+ payload: {
162
+ effectId: string;
163
+ };
164
+ }) | (BoardOperationBase & {
165
+ type: "composition.apply";
166
+ payload: {
167
+ composition: Omit<BoardComposition, "revision">;
168
+ };
169
+ }) | (BoardOperationBase & {
170
+ type: "composition.delete";
171
+ payload: {
172
+ compositionId: string;
173
+ };
174
+ });
72
175
  type BoardMutationReceipt = {
73
176
  mutationId: string;
74
177
  status: "applied" | "validated";
@@ -103,6 +206,48 @@ type BoardValidationResult = {
103
206
  diagnostics: BoardDiagnostic[];
104
207
  peakCost: BoardRenderCost;
105
208
  };
209
+ /**
210
+ * One applied Board transaction as recorded in the log, with the server-computed
211
+ * inverse of every operation. Read-only: replay walks the log in either
212
+ * direction without touching Board rows.
213
+ */
214
+ type BoardTransactionRecord = {
215
+ id: string;
216
+ txId: string;
217
+ baseVersion: number;
218
+ /** Board version this transaction produced. */
219
+ version: number;
220
+ actorId: string;
221
+ clientId: string | null;
222
+ undoGroupId: string | null;
223
+ source: RequestSource | null;
224
+ createdAt: string;
225
+ operations: BoardTransactionOperation[];
226
+ };
227
+ type BoardTransactionOperation = {
228
+ type: BoardOperation["type"];
229
+ payload: Record<string, unknown>;
230
+ inverse: Record<string, unknown> | null;
231
+ };
232
+ /**
233
+ * A page of the transaction log, newest first. The newest page (no `before`)
234
+ * carries the current rows unless `snapshot=false`, so a replay can start from
235
+ * the live state and walk inverses backwards; older pages carry transactions only.
236
+ */
237
+ type BoardTransactionsPage = {
238
+ board: {
239
+ id: string;
240
+ version: number;
241
+ };
242
+ transactions: BoardTransactionRecord[];
243
+ /** Version to pass as `before` for the next older page, or null when exhausted. */
244
+ nextBefore: number | null;
245
+ snapshot?: {
246
+ board: BoardRecord;
247
+ nodes: BoardNodeRecord[];
248
+ connections: BoardConnectionRecord[];
249
+ };
250
+ };
106
251
  type BoardPlaybackStatus = "playing" | "paused" | "stopped";
107
252
  type BoardPlaybackSnapshot = {
108
253
  boardId: string;
@@ -118,4 +263,4 @@ type BoardPlaybackSnapshot = {
118
263
  };
119
264
  declare function isBoardPath(path: string): boolean;
120
265
  //#endregion
121
- export { BOARD_DOCUMENT_KIND, BOARD_EXTENSION, type BoardAssetRef, BoardCameraFocus, BoardCameraFocusParams, BoardCameraFocusParamsSchema, BoardCameraFocusSchema, BoardCameraState, BoardCameraStateSchema, type BoardCapability, BoardDiagnostic, type BoardEffect, BoardManifest, BoardManifestSchema, BoardMutationReceipt, BoardPlaybackSnapshot, BoardPlaybackStatus, type BoardRenderCost, BoardValidationResult, isBoardPath, parseBoardManifest, serializeBoardManifest };
266
+ export { BOARD_DELETE_REASONS, BOARD_DOCUMENT_KIND, BOARD_EXTENSION, type BoardAssetRef, BoardCameraFocus, BoardCameraFocusParams, BoardCameraFocusParamsSchema, BoardCameraFocusSchema, BoardCameraState, BoardCameraStateSchema, type BoardCapability, BoardDeleteReason, BoardDiagnostic, type BoardEffect, BoardManifest, BoardManifestSchema, BoardMutationReceipt, BoardNodeInput, BoardNodeRecord, BoardOperation, BoardPlaybackSnapshot, BoardPlaybackStatus, BoardRecord, type BoardRenderCost, BoardTransactionOperation, BoardTransactionRecord, BoardTransactionsPage, BoardValidationResult, isBoardPath, parseBoardManifest, serializeBoardManifest };
@@ -159,6 +159,13 @@ z.object({
159
159
  height: finiteSchema.positive()
160
160
  }).optional()
161
161
  });
162
+ z.object({
163
+ /** Return transactions with `version < before`. Omit for the newest page. */
164
+ before: z.number().int().positive().optional(),
165
+ limit: z.number().int().min(1).max(500).default(200),
166
+ /** Include the current rows on the newest page (default true). Tail refreshes turn this off. */
167
+ snapshot: z.boolean().default(true)
168
+ });
162
169
  z.object({
163
170
  compositionId: idSchema,
164
171
  /** Delay before the first local playback after opening the Board, in milliseconds. */
@@ -3,7 +3,9 @@ import { AUTO_BOARD_CONNECTION_ANCHOR, BOARD_CONNECTION_DIRECTIONS, BOARD_CONNEC
3
3
  import { BoardAnimationTarget, BoardAnimationTargetSchema, BoardComposition, BoardCompositionInput, BoardCompositionInputSchema, BoardCompositionSchema, BoardEasing, BoardEasingSchema, BoardProceduralClip, BoardProceduralClipSchema, BoardTimelineMarker, BoardTimelineMarkerSchema, BoardTrack, BoardTrackInterpolation, BoardTrackSchema } from "./board-composition.js";
4
4
  import { BoardAssetRef, BoardAssetRefSchema, BoardEffect, BoardEffectInput, BoardEffectInputSchema, BoardEffectSchema } from "./board-effect.js";
5
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";
6
+ import { RequestSource, RequestSourceVia } from "./provenance.js";
7
+ import { BOARD_DELETE_REASONS, BOARD_DOCUMENT_KIND, BOARD_EXTENSION, BoardCameraFocus, BoardCameraFocusParams, BoardCameraFocusParamsSchema, BoardCameraFocusSchema, BoardCameraState, BoardCameraStateSchema, BoardDeleteReason, BoardDiagnostic, BoardManifest, BoardManifestSchema, BoardMutationReceipt, BoardNodeInput, BoardNodeRecord, BoardOperation, BoardPlaybackSnapshot, BoardPlaybackStatus, BoardRecord, BoardTransactionOperation, BoardTransactionRecord, BoardTransactionsPage, BoardValidationResult, isBoardPath, parseBoardManifest, serializeBoardManifest } from "./board.js";
8
+ import "./board-animation.js";
7
9
  import "./board-capability-registry.js";
8
10
  import { BOARD_COLOR_IDS, BOARD_GEO_KINDS, BoardColorId, BoardGeoKind } from "./board-node.js";
9
11
  import "./board-codec.js";
@@ -13,4 +15,4 @@ import "./realtime/board-awareness.js";
13
15
  import "./app.js";
14
16
  import "./realtime/types.js";
15
17
  import "./app-catalog.js";
16
- 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, BOARD_STROKE_MAX_SIZE, BOARD_STROKE_MIN_SIZE, BoardAnimationTarget, BoardAnimationTargetSchema, BoardArrowGeometryInput, type BoardAssetRef, BoardAuthoringItem, BoardAuthoringItemSchema, BoardAuthoringSnapshot, BoardCameraFocus, BoardCameraFocusParams, BoardCameraFocusParamsSchema, BoardCameraFocusSchema, BoardCameraState, BoardCameraStateSchema, 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, BoardRenderCost, BoardSemanticCommand, BoardSemanticCommandSchema, BoardTimelineMarker, BoardTimelineMarkerSchema, BoardTrack, BoardTrackInterpolation, BoardTrackSchema, BoardValidationResult, DEFAULT_BOARD_CONNECTION_ROUTING, DEFAULT_BOARD_CONNECTION_STYLE, DEFAULT_BOARD_RELATION, boardArrowFrame, boardDrawBounds, boardDrawSampleRadius, clampBoardStrokeSize, connectionItemIds, connectionOtherItemId, connectionTouchesItem, createBoardConnection, flipBoardConnection, isBoardPath, normalizeBoardConnectionStyle, parseBoardManifest, serializeBoardManifest };
18
+ 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, BOARD_STROKE_MAX_SIZE, BOARD_STROKE_MIN_SIZE, BoardAnimationTarget, BoardAnimationTargetSchema, BoardArrowGeometryInput, type BoardAssetRef, BoardAuthoringItem, BoardAuthoringItemSchema, BoardAuthoringSnapshot, BoardCameraFocus, BoardCameraFocusParams, BoardCameraFocusParamsSchema, BoardCameraFocusSchema, BoardCameraState, BoardCameraStateSchema, 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, BoardDeleteReason, BoardDiagnostic, BoardEasing, BoardEasingSchema, type BoardEffect, BoardGeoKind, BoardManifest, BoardManifestSchema, BoardMutationReceipt, BoardNodeInput, BoardNodeRecord, BoardOperation, BoardPlaybackSnapshot, BoardPlaybackStatus, BoardProceduralClip, BoardProceduralClipSchema, BoardRecord, BoardRelationSchema, BoardRenderCost, BoardSemanticCommand, BoardSemanticCommandSchema, BoardTimelineMarker, BoardTimelineMarkerSchema, BoardTrack, BoardTrackInterpolation, BoardTrackSchema, BoardTransactionOperation, BoardTransactionRecord, BoardTransactionsPage, BoardValidationResult, DEFAULT_BOARD_CONNECTION_ROUTING, DEFAULT_BOARD_CONNECTION_STYLE, DEFAULT_BOARD_RELATION, RequestSource, RequestSourceVia, boardArrowFrame, boardDrawBounds, boardDrawSampleRadius, clampBoardStrokeSize, connectionItemIds, connectionOtherItemId, connectionTouchesItem, createBoardConnection, flipBoardConnection, isBoardPath, normalizeBoardConnectionStyle, parseBoardManifest, serializeBoardManifest };
@@ -0,0 +1,21 @@
1
+ //#region ../protocol/dist/provenance.d.ts
2
+ type RequestSourceVia = "cli" | "bash" | "tool" | "api" | "web" | (string & {});
3
+ /** Caller context: via (channel) and optional identity fields. */
4
+ type RequestSource = {
5
+ spaceId?: string;
6
+ sessionId?: string;
7
+ turnId?: string;
8
+ toolCallId?: string;
9
+ /**
10
+ * Logical id of the frontend instance that originated this chain of work.
11
+ * Survives reloads and WebSocket reconnects, and is distinct per browser tab.
12
+ * Used to route UI commands back to the originating client. Routing hint only
13
+ * — never an authorization input.
14
+ */
15
+ clientId?: string;
16
+ /** Untrusted provenance hint derived from the Sandbox runtime environment. */
17
+ sandboxVersion?: string;
18
+ via?: RequestSourceVia;
19
+ };
20
+ //#endregion
21
+ export { RequestSource, RequestSourceVia };
package/dist/types.d.ts CHANGED
@@ -2,7 +2,7 @@ import { BoardCapability, BoardCoordinateSpace, BoardRenderCost } from "./protoc
2
2
  import { BoardAnimationTarget, BoardComposition, BoardEasing, BoardProceduralClip, BoardTimelineMarker, BoardTrack } from "./protocol/dist/board-composition.js";
3
3
  import { BoardAssetRef, BoardEffect, BoardEffectInput } from "./protocol/dist/board-effect.js";
4
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";
5
+ import { BoardCameraFocus, BoardCameraFocusParams, BoardCameraState, BoardDiagnostic, BoardManifest, BoardMutationReceipt, BoardPlaybackSnapshot, BoardRecord, BoardTransactionOperation, BoardTransactionRecord, BoardTransactionsPage, BoardValidationResult } from "./protocol/dist/board.js";
6
6
  import "./protocol/dist/index.js";
7
7
  //#region src/types.d.ts
8
8
  type UserProfile = {
@@ -282,8 +282,9 @@ if (created.granted && created.space) {
282
282
  Pass `alwaysAsk: true` to skip silent reuse and force a fresh dialog — for
283
283
  re-confirming a grant or letting the viewer switch to another Space.
284
284
  `requestCreateSpace` always opens the dialog; each confirm mints a new Space.
285
- The host creates it with the viewer's account token the app never calls
286
- `POST /api/spaces` itself.
285
+ The host creates it with the viewer's account token. An App can also create a
286
+ viewer-owned Space directly with `client.spaces.create()` once it holds a
287
+ `space.create` viewer grant.
287
288
 
288
289
  ### Checking grant state at runtime
289
290
 
@@ -339,6 +340,7 @@ dialog can.
339
340
  | List tasks in a Space | `client.tasks.list({ spaceId })` | `taskrun.view` on that Space | app or viewer |
340
341
  | List all owned task runs | `client.tasks.list()` | `user.taskrun.list` | **viewer only** |
341
342
  | Create a Space for the viewer | `client.auth.requestCreateSpace({ space, scopes })` | requested scopes on the new Space | **viewer consent** |
343
+ | Create a viewer-owned Space directly | `client.spaces.create(input)` | `space.create` | **viewer only** |
342
344
  | List viewer's spaces | `client.spaces.list()` | `user.space.list` | **viewer only** |
343
345
  | List viewer's sessions | `client.user.listSessions()` | `user.session.list` | **viewer only** |
344
346
  | Read viewer's activity | `client.user.getActivity()` | `user.usage.read` | **viewer only** |
@@ -1225,8 +1227,9 @@ Before publishing your App, verify each item:
1225
1227
  on page load. It is safe to call repeatedly — covered scopes renew silently.
1226
1228
  - [ ] **Cross-Space access targets the right Space** — viewer grants are per
1227
1229
  Space. Pass `spaceId` when requesting, or use `auth.requestSpace` to let the
1228
- viewer pick. Use `auth.requestCreateSpace` when the app should mint a new
1229
- viewer-owned Space; do not call `spaces.create()` with the App token.
1230
+ viewer pick. Use `auth.requestCreateSpace` to mint a new viewer-owned Space
1231
+ in one consent, or `spaces.create()` directly once the app holds a
1232
+ `space.create` viewer grant.
1230
1233
  - [ ] **`subscribeGeneration` errors are not silently swallowed** — if the
1231
1234
  stream fails, surface it; a silent fallback to polling will also 403 if
1232
1235
  `session.view` is missing.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neta-art/cohub",
3
- "version": "8.11.0",
3
+ "version": "8.12.0",
4
4
  "description": "Cohub SDK for spaces, sessions, boards, and realtime agent collaboration.",
5
5
  "license": "Apache-2.0",
6
6
  "private": false,
@@ -1,22 +0,0 @@
1
- import { BoardDocument, BoardViewport } from "../../../protocol/dist/board-document.js";
2
- import { BoardRenderPalette } from "../renderers/board-renderer-registry.js";
3
- import { Application, Container } from "pixi.js";
4
- //#region src/board/render/themes/board-theme-registry.d.ts
5
- type BoardThemeContext = {
6
- app: Application;
7
- document: BoardDocument;
8
- viewport: BoardViewport;
9
- palette: BoardRenderPalette;
10
- /** The host renders an image backdrop below the transparent Pixi canvas. */
11
- hasImageBackground?: boolean;
12
- };
13
- type BoardThemeRenderer = {
14
- id: string;
15
- canRender: (document: BoardDocument) => boolean;
16
- createBackground: (context: BoardThemeContext) => Container;
17
- updateBackground?: (container: Container, context: BoardThemeContext) => void;
18
- };
19
- declare function getBoardThemeRenderer(document: BoardDocument): BoardThemeRenderer;
20
- declare function registerBoardThemeRenderer(renderer: BoardThemeRenderer): void;
21
- //#endregion
22
- export { BoardThemeContext, BoardThemeRenderer, getBoardThemeRenderer, registerBoardThemeRenderer };
@@ -1,13 +0,0 @@
1
- import { cleanBoardTheme } from "./clean-theme.js";
2
- //#region src/board/render/themes/board-theme-registry.ts
3
- const boardThemeRenderers = [cleanBoardTheme];
4
- function getBoardThemeRenderer(document) {
5
- return boardThemeRenderers.find((renderer) => renderer.canRender(document)) ?? cleanBoardTheme;
6
- }
7
- function registerBoardThemeRenderer(renderer) {
8
- const existingIndex = boardThemeRenderers.findIndex((candidate) => candidate.id === renderer.id);
9
- if (existingIndex >= 0) boardThemeRenderers.splice(existingIndex, 1, renderer);
10
- else boardThemeRenderers.unshift(renderer);
11
- }
12
- //#endregion
13
- export { getBoardThemeRenderer, registerBoardThemeRenderer };
@@ -1,5 +0,0 @@
1
- import { BoardThemeRenderer } from "./board-theme-registry.js";
2
- //#region src/board/render/themes/clean-theme.d.ts
3
- declare const cleanBoardTheme: BoardThemeRenderer;
4
- //#endregion
5
- export { cleanBoardTheme };