@neta-art/cohub 5.6.0 → 5.8.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 (59) hide show
  1. package/README.md +18 -5
  2. package/dist/board/codec.js +15 -0
  3. package/dist/board/core/palette.d.ts +3 -2
  4. package/dist/board/core/shape-types.d.ts +8 -2
  5. package/dist/board/core/shape-types.js +3 -7
  6. package/dist/board/core/tool-styles.d.ts +2 -1
  7. package/dist/board/image-key.js +3 -5
  8. package/dist/board/index.d.ts +10 -5
  9. package/dist/board/index.js +7 -3
  10. package/dist/board/media-playback.d.ts +22 -0
  11. package/dist/board/media-playback.js +67 -0
  12. package/dist/board/media.d.ts +7 -0
  13. package/dist/board/media.js +70 -0
  14. package/dist/board/nodes.d.ts +113 -0
  15. package/dist/board/nodes.js +154 -0
  16. package/dist/board/render/audio-waveform.d.ts +12 -0
  17. package/dist/board/render/audio-waveform.js +36 -0
  18. package/dist/board/render/index.d.ts +4 -1
  19. package/dist/board/render/index.js +4 -1
  20. package/dist/board/render/media-interaction.d.ts +19 -0
  21. package/dist/board/render/media-interaction.js +26 -0
  22. package/dist/board/render/renderers/audio-card-renderer.d.ts +5 -0
  23. package/dist/board/render/renderers/audio-card-renderer.js +120 -0
  24. package/dist/board/render/renderers/board-renderer-registry.js +4 -2
  25. package/dist/board/render/renderers/draw-card-renderer.js +1 -1
  26. package/dist/board/render/renderers/file-card-renderer.js +1 -1
  27. package/dist/board/render/renderers/frame-card-renderer.js +1 -1
  28. package/dist/board/render/renderers/geo-card-renderer.js +1 -1
  29. package/dist/board/render/renderers/image-card-renderer.js +1 -1
  30. package/dist/board/render/renderers/task-card-renderer.d.ts +2 -1
  31. package/dist/board/render/renderers/task-card-renderer.js +21 -53
  32. package/dist/board/render/renderers/text-card-renderer.js +1 -1
  33. package/dist/board/render/renderers/unknown-card-renderer.js +1 -1
  34. package/dist/board/render/renderers/video-card-renderer.js +1 -1
  35. package/dist/board/render/video-thumbnail.d.ts +16 -0
  36. package/dist/board/render/video-thumbnail.js +86 -0
  37. package/dist/board/task.d.ts +10 -5
  38. package/dist/board/task.js +159 -103
  39. package/dist/chunks/environment.d.ts +6 -6
  40. package/dist/chunks/environment.js +6 -6
  41. package/dist/chunks/http.d.ts +71 -5
  42. package/dist/chunks/http.js +1535 -167
  43. package/dist/chunks/transport.js +8 -1
  44. package/dist/chunks/websocket.d.ts +139 -3
  45. package/dist/http.d.ts +3 -3
  46. package/dist/index.d.ts +245 -4
  47. package/dist/index.js +438 -788
  48. package/dist/protocol/dist/board-document.d.ts +271 -53
  49. package/dist/protocol/dist/board-document.js +54 -22
  50. package/dist/protocol/dist/board-node.d.ts +18 -0
  51. package/dist/protocol/dist/board-node.js +239 -0
  52. package/dist/protocol/dist/board-url.d.ts +12 -0
  53. package/dist/protocol/dist/board-url.js +83 -0
  54. package/dist/protocol/dist/board.d.ts +5 -0
  55. package/dist/protocol/dist/index.d.ts +2 -1
  56. package/dist/protocol/dist/index.js +2 -1
  57. package/dist/protocol/dist/provenance.js +1 -0
  58. package/docs/work-runtime-guide.md +7 -7
  59. package/package.json +1 -1
@@ -0,0 +1,239 @@
1
+ import { BOARD_ARROW_STROKE_SIZE } from "./board-constants.js";
2
+ import { BoardTaskSnapshotSchema } from "./board-document.js";
3
+ import { z } from "zod";
4
+ //#region ../protocol/dist/board-node.js
5
+ const BOARD_COLOR_IDS = [
6
+ "brand",
7
+ "neutral",
8
+ "black",
9
+ "white",
10
+ "blue",
11
+ "green",
12
+ "amber",
13
+ "violet",
14
+ "rose"
15
+ ];
16
+ const BoardColorIdSchema = z.enum(BOARD_COLOR_IDS);
17
+ const BOARD_GEO_KINDS = [
18
+ "rectangle",
19
+ "rounded",
20
+ "ellipse",
21
+ "diamond",
22
+ "triangle"
23
+ ];
24
+ const BoardGeoKindSchema = z.enum(BOARD_GEO_KINDS);
25
+ const BOARD_NATIVE_NODE_TYPES = [
26
+ "image",
27
+ "video",
28
+ "audio",
29
+ "file",
30
+ "task",
31
+ "text",
32
+ "geo",
33
+ "draw",
34
+ "arrow",
35
+ "frame"
36
+ ];
37
+ const metadataSchema = z.record(z.string(), z.unknown());
38
+ const commonData = {
39
+ locked: z.boolean().optional(),
40
+ metadata: metadataSchema.optional()
41
+ };
42
+ const pointSchema = z.object({
43
+ x: z.number().finite(),
44
+ y: z.number().finite(),
45
+ p: z.number().finite().min(0).max(1).default(.5)
46
+ }).strict();
47
+ const worldPointSchema = z.object({
48
+ x: z.number().finite(),
49
+ y: z.number().finite()
50
+ }).strict();
51
+ const strokeSizeSchema = z.number().finite().min(1).max(64);
52
+ const mediaViewSchema = z.object({
53
+ title: z.string().optional(),
54
+ mimeType: z.string().optional(),
55
+ size: z.number().finite().nonnegative().optional(),
56
+ mtimeMs: z.number().finite().nonnegative().optional(),
57
+ naturalWidth: z.number().finite().positive().optional(),
58
+ naturalHeight: z.number().finite().positive().optional()
59
+ }).strict();
60
+ const audioViewSchema = mediaViewSchema.extend({ durationMs: z.number().finite().nonnegative().optional() });
61
+ const dataSchemas = {
62
+ text: z.object({
63
+ ...commonData,
64
+ text: z.string().default(""),
65
+ color: BoardColorIdSchema.default("neutral"),
66
+ fontSize: z.number().finite().min(2).max(512).default(24)
67
+ }).strict(),
68
+ geo: z.object({
69
+ ...commonData,
70
+ geo: BoardGeoKindSchema.default("rectangle"),
71
+ text: z.string().default(""),
72
+ color: BoardColorIdSchema.default("brand"),
73
+ fillOpacity: z.number().finite().min(0).max(1).default(0)
74
+ }).strict(),
75
+ draw: z.object({
76
+ ...commonData,
77
+ points: z.array(pointSchema).min(1),
78
+ color: BoardColorIdSchema.default("brand"),
79
+ size: strokeSizeSchema.default(4)
80
+ }).strict(),
81
+ arrow: z.object({
82
+ ...commonData,
83
+ start: worldPointSchema,
84
+ end: worldPointSchema,
85
+ bend: z.number().finite().min(-.85).max(.85).default(0),
86
+ color: BoardColorIdSchema.default("brand"),
87
+ size: strokeSizeSchema.default(BOARD_ARROW_STROKE_SIZE),
88
+ arrowStart: z.boolean().default(false),
89
+ arrowEnd: z.boolean().default(true),
90
+ label: z.string().default("")
91
+ }).strict(),
92
+ frame: z.object({
93
+ ...commonData,
94
+ label: z.string().default("Frame"),
95
+ color: BoardColorIdSchema.default("neutral")
96
+ }).strict(),
97
+ image: z.object({
98
+ ...commonData,
99
+ crop: z.object({
100
+ x: z.number().finite().min(0).max(1),
101
+ y: z.number().finite().min(0).max(1),
102
+ w: z.number().finite().min(0).max(1),
103
+ h: z.number().finite().min(0).max(1)
104
+ }).strict().optional()
105
+ }).strict(),
106
+ video: z.object(commonData).strict(),
107
+ audio: z.object(commonData).strict(),
108
+ file: z.object(commonData).strict(),
109
+ task: z.object({
110
+ ...commonData,
111
+ taskRunId: z.string().min(1)
112
+ }).strict()
113
+ };
114
+ const fileViewSchema = z.object({
115
+ title: z.string().optional(),
116
+ mimeType: z.string().optional(),
117
+ size: z.number().finite().nonnegative().optional(),
118
+ mtimeMs: z.number().finite().nonnegative().optional(),
119
+ excerpt: z.string().optional(),
120
+ coverPath: z.string().optional(),
121
+ coverUrl: z.string().url().optional()
122
+ }).strict();
123
+ const taskViewSchema = BoardTaskSnapshotSchema;
124
+ const emptyViewSchema = z.object({}).strict();
125
+ const viewSchemas = {
126
+ image: mediaViewSchema,
127
+ video: mediaViewSchema,
128
+ audio: audioViewSchema,
129
+ file: fileViewSchema,
130
+ task: taskViewSchema,
131
+ text: emptyViewSchema,
132
+ geo: emptyViewSchema,
133
+ draw: emptyViewSchema,
134
+ arrow: emptyViewSchema,
135
+ frame: emptyViewSchema
136
+ };
137
+ const nodeEnvelopeSchema = z.object({
138
+ nodeId: z.string().min(1).max(160),
139
+ type: z.string().min(1).max(40),
140
+ parentId: z.string().min(1).max(160).nullable(),
141
+ orderKey: z.string().max(4096).nullable(),
142
+ x: z.number().finite(),
143
+ y: z.number().finite(),
144
+ width: z.number().finite().positive(),
145
+ height: z.number().finite().positive(),
146
+ rotation: z.number().finite(),
147
+ refKind: z.string().max(40).nullable(),
148
+ refPath: z.string().max(4096).nullable(),
149
+ refUrl: z.string().max(4096).nullable(),
150
+ view: z.record(z.string(), z.unknown()),
151
+ style: z.record(z.string(), z.unknown()),
152
+ data: z.record(z.string(), z.unknown())
153
+ }).strict();
154
+ function jsonSchema(schema) {
155
+ return z.toJSONSchema(schema);
156
+ }
157
+ jsonSchema(nodeEnvelopeSchema), Object.fromEntries(BOARD_NATIVE_NODE_TYPES.map((type) => [type, jsonSchema(dataSchemas[type])])), Object.fromEntries(BOARD_NATIVE_NODE_TYPES.map((type) => [type, jsonSchema(viewSchemas[type])]));
158
+ function issueDiagnostic(issue, path) {
159
+ const fullPath = [path, ...issue.path].join(".");
160
+ const values = "values" in issue && Array.isArray(issue.values) ? issue.values.filter((value) => typeof value === "string") : void 0;
161
+ return {
162
+ severity: "error",
163
+ code: "INVALID_BOARD_NODE",
164
+ message: `${fullPath}: ${issue.message}`,
165
+ path: fullPath,
166
+ ...values?.length ? { allowedValues: values } : {}
167
+ };
168
+ }
169
+ function drawGeometryDiagnostic(node, data, path) {
170
+ let minX = Number.POSITIVE_INFINITY;
171
+ let minY = Number.POSITIVE_INFINITY;
172
+ let maxX = Number.NEGATIVE_INFINITY;
173
+ let maxY = Number.NEGATIVE_INFINITY;
174
+ for (const point of data.points) {
175
+ const radius = Math.max(.5, data.size / 2 * (.5 + point.p));
176
+ minX = Math.min(minX, point.x - radius);
177
+ minY = Math.min(minY, point.y - radius);
178
+ maxX = Math.max(maxX, point.x + radius);
179
+ maxY = Math.max(maxY, point.y + radius);
180
+ }
181
+ const width = Math.max(1, maxX - minX);
182
+ const height = Math.max(1, maxY - minY);
183
+ const tolerance = Math.max(.01, node.width * 1e-6, node.height * 1e-6);
184
+ if (Math.abs(minX) <= tolerance && Math.abs(minY) <= tolerance && Math.abs(width - node.width) <= tolerance && Math.abs(height - node.height) <= tolerance) return null;
185
+ return {
186
+ severity: "error",
187
+ code: "INVALID_BOARD_GEOMETRY",
188
+ message: `${path}.data.points must use frame-local coordinates and match the node frame`,
189
+ path: `${path}.data.points`,
190
+ expected: "frame-local points with bounds matching width and height",
191
+ coordinateSpace: "frame-local"
192
+ };
193
+ }
194
+ function validateBoardNodeInput(node, path = "node") {
195
+ const envelopeResult = nodeEnvelopeSchema.safeParse(node);
196
+ if (!envelopeResult.success) return envelopeResult.error.issues.map((issue) => issueDiagnostic(issue, path));
197
+ if (typeof node.type !== "string" || !BOARD_NATIVE_NODE_TYPES.includes(node.type)) return [{
198
+ severity: "error",
199
+ code: "INVALID_BOARD_NODE",
200
+ message: `${path}.type is not supported`,
201
+ path: `${path}.type`,
202
+ expected: "BoardNativeNodeType",
203
+ received: node.type,
204
+ allowedValues: BOARD_NATIVE_NODE_TYPES
205
+ }];
206
+ const type = node.type;
207
+ const dataResult = dataSchemas[type].safeParse(node.data ?? {});
208
+ if (!dataResult.success) return dataResult.error.issues.map((issue) => issueDiagnostic(issue, `${path}.data`));
209
+ const viewResult = viewSchemas[type].safeParse(node.view ?? {});
210
+ if (!viewResult.success) return viewResult.error.issues.map((issue) => issueDiagnostic(issue, `${path}.view`));
211
+ if (type === "image" || type === "video" || type === "audio" || type === "file") {
212
+ if (node.refKind !== "space_file" || typeof node.refPath !== "string" || !node.refPath) return [{
213
+ severity: "error",
214
+ code: "INVALID_BOARD_NODE",
215
+ message: `${path} requires a space file reference`,
216
+ path: `${path}.refPath`,
217
+ expected: "non-empty refPath with refKind space_file"
218
+ }];
219
+ }
220
+ if (type === "draw") {
221
+ const diagnostic = drawGeometryDiagnostic(node, dataResult.data, path);
222
+ return diagnostic ? [diagnostic] : [];
223
+ }
224
+ if (type === "arrow") {
225
+ const data = dataResult.data;
226
+ const inside = (point) => point.x >= node.x && point.x <= node.x + node.width && point.y >= node.y && point.y <= node.y + node.height;
227
+ if (!inside(data.start) || !inside(data.end)) return [{
228
+ severity: "error",
229
+ code: "INVALID_BOARD_GEOMETRY",
230
+ message: `${path}.data endpoints must be covered by the node frame`,
231
+ path: `${path}.data`,
232
+ expected: "world-space endpoints inside the node frame",
233
+ coordinateSpace: "world"
234
+ }];
235
+ }
236
+ return [];
237
+ }
238
+ //#endregion
239
+ export { BOARD_COLOR_IDS, BOARD_GEO_KINDS, BOARD_NATIVE_NODE_TYPES, BoardColorIdSchema, BoardGeoKindSchema, validateBoardNodeInput };
@@ -0,0 +1,12 @@
1
+ import { z } from "zod";
2
+ //#region ../protocol/dist/board-url.d.ts
3
+ declare const BOARD_REMOTE_URL_MAX_LENGTH = 4096;
4
+ /**
5
+ * Normalize a browser-loadable public HTTP(S) URL. This blocks explicit local
6
+ * addresses; any future server-side fetcher must additionally validate DNS
7
+ * resolution to defend against rebinding.
8
+ */
9
+ declare function normalizeBoardRemoteUrl(value: unknown): string | undefined;
10
+ declare const BoardRemoteUrlSchema: z.ZodString;
11
+ //#endregion
12
+ export { BOARD_REMOTE_URL_MAX_LENGTH, BoardRemoteUrlSchema, normalizeBoardRemoteUrl };
@@ -0,0 +1,83 @@
1
+ import { z } from "zod";
2
+ //#region ../protocol/dist/board-url.js
3
+ const BOARD_REMOTE_URL_MAX_LENGTH = 4096;
4
+ function parseIpv4(host) {
5
+ const parts = host.split(".").map(Number);
6
+ return parts.length === 4 && parts.every((part) => Number.isInteger(part) && part >= 0 && part <= 255) ? parts : null;
7
+ }
8
+ function isBlockedIpv4(host) {
9
+ const parts = parseIpv4(host);
10
+ if (!parts) return false;
11
+ const [first, second, third] = parts;
12
+ if (first === 0 || first === 10 || first === 127) return true;
13
+ if (first === 100 && second >= 64 && second <= 127) return true;
14
+ if (first === 169 && second === 254) return true;
15
+ if (first === 172 && second >= 16 && second <= 31) return true;
16
+ if (first === 192 && second === 168) return true;
17
+ if (first === 192 && second === 0 && (third === 0 || third === 2)) return true;
18
+ if (first === 192 && second === 88 && third === 99) return true;
19
+ if (first === 198 && (second === 18 || second === 19)) return true;
20
+ if (first === 198 && second === 51 && third === 100) return true;
21
+ if (first === 203 && second === 0 && third === 113) return true;
22
+ return first >= 224;
23
+ }
24
+ function expandIpv6(host) {
25
+ const [head, tail, extra] = host.toLowerCase().split("::");
26
+ if (extra !== void 0) return null;
27
+ const headParts = head ? head.split(":").filter(Boolean) : [];
28
+ const tailParts = tail ? tail.split(":").filter(Boolean) : [];
29
+ const missing = 8 - headParts.length - tailParts.length;
30
+ if (missing < 0 || tail === void 0 && missing !== 0) return null;
31
+ const parts = [
32
+ ...headParts,
33
+ ...Array.from({ length: missing }, () => "0"),
34
+ ...tailParts
35
+ ];
36
+ if (parts.length !== 8 || parts.some((part) => !/^[0-9a-f]{1,4}$/.test(part))) return null;
37
+ return parts.map((part) => part.padStart(4, "0"));
38
+ }
39
+ function isBlockedIpv6(host) {
40
+ const parts = expandIpv6(host);
41
+ if (!parts) return true;
42
+ if (parts.every((part) => part === "0000")) return true;
43
+ if (parts.slice(0, 7).every((part) => part === "0000") && parts[7] === "0001") return true;
44
+ if (parts.slice(0, 5).every((part) => part === "0000") && parts[5] === "ffff") {
45
+ const high = Number.parseInt(parts[6] ?? "0", 16);
46
+ const low = Number.parseInt(parts[7] ?? "0", 16);
47
+ return isBlockedIpv4(`${high >> 8}.${high & 255}.${low >> 8}.${low & 255}`);
48
+ }
49
+ if (parts.slice(0, 6).every((part) => part === "0000")) return true;
50
+ const first = Number.parseInt(parts[0] ?? "0", 16);
51
+ if ((first & 65024) === 64512) return true;
52
+ if ((first & 65472) === 65152 || (first & 65472) === 65216) return true;
53
+ if ((first & 65280) === 65280) return true;
54
+ return parts[0] === "2001" && parts[1] === "0db8";
55
+ }
56
+ function isBlockedHost(hostname) {
57
+ const host = hostname.toLowerCase().replace(/^\[|\]$/g, "").replace(/\.$/, "");
58
+ if (host === "localhost" || host.endsWith(".localhost") || host.endsWith(".local") || host.endsWith(".internal")) return true;
59
+ if (parseIpv4(host)) return isBlockedIpv4(host);
60
+ return host.includes(":") && isBlockedIpv6(host);
61
+ }
62
+ /**
63
+ * Normalize a browser-loadable public HTTP(S) URL. This blocks explicit local
64
+ * addresses; any future server-side fetcher must additionally validate DNS
65
+ * resolution to defend against rebinding.
66
+ */
67
+ function normalizeBoardRemoteUrl(value) {
68
+ if (typeof value !== "string") return void 0;
69
+ const input = value.trim();
70
+ if (!input || input.length > 4096) return void 0;
71
+ try {
72
+ const url = new URL(input);
73
+ if (url.protocol !== "https:" && url.protocol !== "http:") return void 0;
74
+ if (url.username || url.password || isBlockedHost(url.hostname)) return;
75
+ const normalized = url.toString();
76
+ return normalized.length <= 4096 ? normalized : void 0;
77
+ } catch {
78
+ return;
79
+ }
80
+ }
81
+ const BoardRemoteUrlSchema = z.string().max(BOARD_REMOTE_URL_MAX_LENGTH).refine((value) => normalizeBoardRemoteUrl(value) !== void 0, { message: "URL must be a public HTTP(S) URL without credentials" });
82
+ //#endregion
83
+ export { BOARD_REMOTE_URL_MAX_LENGTH, BoardRemoteUrlSchema, normalizeBoardRemoteUrl };
@@ -1,5 +1,6 @@
1
1
  import { BoardCapability, BoardRenderCost } from "./board-constants.js";
2
2
  import "./board-connection.js";
3
+ import "./board-node.js";
3
4
  import { z } from "zod";
4
5
  //#region ../protocol/dist/board.d.ts
5
6
  declare const BOARD_EXTENSION: ".board";
@@ -176,6 +177,10 @@ type BoardDiagnostic = {
176
177
  message: string;
177
178
  path?: string;
178
179
  adaptation?: Record<string, unknown>;
180
+ expected?: string;
181
+ received?: unknown;
182
+ allowedValues?: readonly string[];
183
+ coordinateSpace?: "frame-local" | "world";
179
184
  };
180
185
  type BoardValidationResult = {
181
186
  valid: boolean;
@@ -1,7 +1,8 @@
1
1
  import { BoardCapability, BoardRenderCost } from "./board-constants.js";
2
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";
3
4
  import { BOARD_DOCUMENT_KIND, BOARD_EXTENSION, BoardAssetRef, BoardAssetRefSchema, BoardClip, BoardClipSchema, BoardDiagnostic, BoardEffect, BoardEffectSchema, BoardManifest, BoardManifestSchema, BoardNodeInput, BoardNodeRecord, BoardRecord, BoardSequence, BoardSequenceSchema, BoardTarget, BoardTargetSchema, BoardValidationResult, InvalidBoardFileError, isBoardPath, parseBoardManifest, serializeBoardManifest } from "./board.js";
4
5
  import "./realtime/board-awareness.js";
5
6
  import "./work.js";
6
7
  import "./realtime/types.js";
7
- export { AUTO_BOARD_CONNECTION_ANCHOR, BOARD_CONNECTION_DIRECTIONS, BOARD_CONNECTION_LINES, BOARD_CONNECTION_ROUTINGS, BOARD_CONNECTION_SIDES, BOARD_DOCUMENT_KIND, BOARD_EXTENSION, BoardAssetRef, BoardAssetRefSchema, BoardClip, BoardClipSchema, BoardConnection, BoardConnectionAnchor, BoardConnectionAnchorSchema, BoardConnectionDirection, BoardConnectionEndpoint, BoardConnectionEndpointSchema, BoardConnectionInput, BoardConnectionLine, BoardConnectionPatch, BoardConnectionPatchSchema, BoardConnectionRecord, BoardConnectionRouting, BoardConnectionRoutingConfig, BoardConnectionRoutingSchema, BoardConnectionSchema, BoardConnectionSide, BoardConnectionStyle, BoardConnectionStyleSchema, BoardConnectionWaypointSchema, BoardDiagnostic, BoardEffect, BoardEffectSchema, BoardManifest, BoardManifestSchema, BoardNodeInput, BoardNodeRecord, 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 };
8
+ 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, BoardAssetRef, BoardAssetRefSchema, BoardClip, BoardClipSchema, BoardColorId, BoardConnection, BoardConnectionAnchor, BoardConnectionAnchorSchema, BoardConnectionDirection, BoardConnectionEndpoint, BoardConnectionEndpointSchema, BoardConnectionInput, BoardConnectionLine, BoardConnectionPatch, BoardConnectionPatchSchema, BoardConnectionRecord, BoardConnectionRouting, BoardConnectionRoutingConfig, BoardConnectionRoutingSchema, BoardConnectionSchema, BoardConnectionSide, BoardConnectionStyle, BoardConnectionStyleSchema, BoardConnectionWaypointSchema, BoardDiagnostic, BoardEffect, BoardEffectSchema, BoardGeoKind, BoardManifest, BoardManifestSchema, BoardNodeInput, BoardNodeRecord, BoardNodeValidationDiagnostic, 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 };
@@ -1,8 +1,9 @@
1
1
  import "./board-constants.js";
2
2
  import { AUTO_BOARD_CONNECTION_ANCHOR, BOARD_CONNECTION_DIRECTIONS, BOARD_CONNECTION_LINES, BOARD_CONNECTION_ROUTINGS, BOARD_CONNECTION_SIDES, BoardConnectionAnchorSchema, BoardConnectionEndpointSchema, BoardConnectionPatchSchema, BoardConnectionRoutingSchema, BoardConnectionSchema, 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
3
  import { BOARD_DOCUMENT_KIND, BOARD_EXTENSION, BOARD_MANIFEST_KIND, BoardAssetRefSchema, BoardClipSchema, BoardEffectSchema, BoardKeyframeSchema, BoardManifestSchema, BoardNodeInputSchema, BoardSequenceSchema, BoardTargetSchema, InvalidBoardFileError, isBoardPath, parseBoardManifest, serializeBoardManifest } from "./board.js";
4
+ import { BOARD_COLOR_IDS, BOARD_GEO_KINDS, BOARD_NATIVE_NODE_TYPES, BoardColorIdSchema, BoardGeoKindSchema, validateBoardNodeInput } from "./board-node.js";
4
5
  import { BoardAwarenessDrawPointSchema, BoardAwarenessFrameSchema, BoardAwarenessGestureSchema, BoardAwarenessNodePreviewSchema, BoardAwarenessPointSchema, BoardAwarenessStateUpdateSchema, BoardAwarenessUpdateSchema } from "./realtime/board-awareness.js";
5
6
  import { COHUB_SOURCE_HEADER } from "./provenance.js";
6
7
  import { RESERVED_PLATFORM_PATH_SEGMENTS } from "./public-identifiers.js";
7
8
  import "./work-view-stats.js";
8
- export { AUTO_BOARD_CONNECTION_ANCHOR, BOARD_CONNECTION_DIRECTIONS, BOARD_CONNECTION_LINES, BOARD_CONNECTION_ROUTINGS, BOARD_CONNECTION_SIDES, BOARD_DOCUMENT_KIND, BOARD_EXTENSION, BOARD_MANIFEST_KIND, BoardAssetRefSchema, BoardAwarenessDrawPointSchema, BoardAwarenessFrameSchema, BoardAwarenessGestureSchema, BoardAwarenessNodePreviewSchema, BoardAwarenessPointSchema, BoardAwarenessStateUpdateSchema, BoardAwarenessUpdateSchema, BoardClipSchema, BoardConnectionAnchorSchema, BoardConnectionEndpointSchema, BoardConnectionPatchSchema, BoardConnectionRoutingSchema, BoardConnectionSchema, BoardConnectionStyleSchema, BoardConnectionWaypointSchema, BoardEffectSchema, BoardKeyframeSchema, BoardManifestSchema, BoardNodeInputSchema, BoardRelationSchema, BoardSequenceSchema, BoardTargetSchema, COHUB_SOURCE_HEADER, DEFAULT_BOARD_CONNECTION_ROUTING, DEFAULT_BOARD_CONNECTION_STYLE, DEFAULT_BOARD_RELATION, InvalidBoardFileError, RESERVED_PLATFORM_PATH_SEGMENTS, connectionNodeIds, connectionOtherNodeId, connectionTouchesNode, createBoardConnection, flipBoardConnection, isBoardPath, normalizeBoardConnectionStyle, parseBoardManifest, serializeBoardManifest };
9
+ 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_MANIFEST_KIND, BOARD_NATIVE_NODE_TYPES, BoardAssetRefSchema, BoardAwarenessDrawPointSchema, BoardAwarenessFrameSchema, BoardAwarenessGestureSchema, BoardAwarenessNodePreviewSchema, BoardAwarenessPointSchema, BoardAwarenessStateUpdateSchema, BoardAwarenessUpdateSchema, BoardClipSchema, BoardColorIdSchema, BoardConnectionAnchorSchema, BoardConnectionEndpointSchema, BoardConnectionPatchSchema, BoardConnectionRoutingSchema, BoardConnectionSchema, BoardConnectionStyleSchema, BoardConnectionWaypointSchema, BoardEffectSchema, BoardGeoKindSchema, BoardKeyframeSchema, BoardManifestSchema, BoardNodeInputSchema, BoardRelationSchema, BoardSequenceSchema, BoardTargetSchema, COHUB_SOURCE_HEADER, DEFAULT_BOARD_CONNECTION_ROUTING, DEFAULT_BOARD_CONNECTION_STYLE, DEFAULT_BOARD_RELATION, InvalidBoardFileError, RESERVED_PLATFORM_PATH_SEGMENTS, connectionNodeIds, connectionOtherNodeId, connectionTouchesNode, createBoardConnection, flipBoardConnection, isBoardPath, normalizeBoardConnectionStyle, parseBoardManifest, serializeBoardManifest, validateBoardNodeInput };
@@ -6,6 +6,7 @@ const COHUB_SOURCE_HEADER = {
6
6
  turn: "X-Cohub-Source-Turn",
7
7
  toolCall: "X-Cohub-Source-Tool-Call",
8
8
  client: "X-Cohub-Source-Client",
9
+ sandboxVersion: "X-Cohub-Source-Sandbox",
9
10
  via: "X-Cohub-Source-Via"
10
11
  };
11
12
  Object.values(COHUB_SOURCE_HEADER);
@@ -218,7 +218,7 @@ result needs `taskrun.view` (a work scope).
218
218
  | Read task run detail | `client.tasks.get(taskRunId)` | `taskrun.view` | work |
219
219
  | List viewer's spaces | `client.spaces.list()` | `user.space.list` | viewer |
220
220
  | List viewer's sessions | `client.user.listSessions()` | `user.session.list` | viewer |
221
- | Read viewer's usage | `client.user.getUsage()` | `user.usage.read` | viewer |
221
+ | Read viewer's activity | `client.user.getActivity()` | `user.usage.read` | viewer |
222
222
  | Commerce: entitlements | `client.work.commerce.getEntitlements()` | *(runtime only, no scope)* | — |
223
223
  | Commerce: consume credits | `client.work.commerce.consumeCredits()` | *(runtime only, no scope)* | — |
224
224
  | Commerce: purchase | `client.work.commerce.purchase()` | *(runtime only, no scope)* | — |
@@ -280,7 +280,7 @@ when a deployment needs reproducible dependency updates.
280
280
  ### Environment detection — critical
281
281
 
282
282
  The SDK defaults to **production**. A Work running on a dev/staging host
283
- (e.g. `dev.cohub.run`, a `/dev/` path prefix) **must** pass `env: "dev"`
283
+ (e.g. `dev.cohub.live`, a `/dev/` path prefix) **must** pass `env: "dev"`
284
284
  explicitly — browsers do not inject `ENV` like Node does. If you omit this,
285
285
  your Work will call the production API while the runtime host expects dev,
286
286
  causing silent auth failures.
@@ -304,7 +304,7 @@ iframe), pass the `work` option so the SDK can fall back to broker mode:
304
304
  const client = createCohubClient({
305
305
  env: isDevWork ? "dev" : "prod",
306
306
  work: {
307
- brokerOrigin: isDevWork ? "https://dev.cohub.run" : "https://cohub.run",
307
+ brokerOrigin: isDevWork ? "https://dev.cohub.live" : "https://cohub.live",
308
308
  workId: "<your-published-work-id>",
309
309
  },
310
310
  });
@@ -332,7 +332,7 @@ All three values are known before publishing:
332
332
  const client = createCohubClient({
333
333
  env: isDevWork ? "dev" : "prod",
334
334
  work: {
335
- brokerOrigin: isDevWork ? "https://dev.cohub.run" : "https://cohub.run",
335
+ brokerOrigin: isDevWork ? "https://dev.cohub.live" : "https://cohub.live",
336
336
  ownerUsername,
337
337
  spaceSlug,
338
338
  workSlug,
@@ -618,12 +618,12 @@ await client.auth.request({
618
618
  });
619
619
  const { sessions } = await client.user.listSessions({ limit: 20 });
620
620
 
621
- // Read aggregated usage — needs user.usage.read
621
+ // Read activity — needs user.usage.read
622
622
  await client.auth.request({
623
623
  scopes: ["user.usage.read"],
624
- reason: "Show your usage summary.",
624
+ reason: "Show your activity.",
625
625
  });
626
- const usage = await client.user.getUsage(30); // last 30 days
626
+ const activity = await client.user.getActivity({ days: 30 }); // last 30 days
627
627
  ```
628
628
 
629
629
  ### Commerce (`work.commerce`)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neta-art/cohub",
3
- "version": "5.6.0",
3
+ "version": "5.8.0",
4
4
  "description": "Cohub SDK for spaces, sessions, boards, and realtime agent collaboration.",
5
5
  "license": "Apache-2.0",
6
6
  "private": false,