@neta-art/cohub 8.10.2 → 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 (45) hide show
  1. package/dist/board/animation.js +14 -2
  2. package/dist/board/core/file-preview.d.ts +20 -141
  3. package/dist/board/core/file-preview.js +25 -202
  4. package/dist/board/core/file-snapshot.d.ts +106 -0
  5. package/dist/board/core/file-snapshot.js +503 -0
  6. package/dist/board/index.d.ts +4 -2
  7. package/dist/board/index.js +4 -2
  8. package/dist/board/mutation.js +2 -1
  9. package/dist/board/render/board-background.d.ts +16 -0
  10. package/dist/board/render/{themes/clean-theme.js → board-background.js} +28 -35
  11. package/dist/board/render/index.d.ts +3 -3
  12. package/dist/board/render/index.js +2 -2
  13. package/dist/board/render/renderers/file-card-renderer.js +62 -17
  14. package/dist/board/replay.d.ts +52 -0
  15. package/dist/board/replay.js +261 -0
  16. package/dist/board/semantic-document.d.ts +9 -2
  17. package/dist/board/semantic-document.js +1 -3
  18. package/dist/chunks/environment.d.ts +272 -7
  19. package/dist/chunks/environment.js +1 -0
  20. package/dist/chunks/http.d.ts +109 -7
  21. package/dist/chunks/http.js +47 -10
  22. package/dist/chunks/websocket.d.ts +1 -1
  23. package/dist/http.d.ts +3 -3
  24. package/dist/index.d.ts +65 -4
  25. package/dist/index.js +514 -64
  26. package/dist/protocol/dist/board-animation.d.ts +1 -0
  27. package/dist/protocol/dist/board-animation.js +34 -0
  28. package/dist/protocol/dist/board-authoring.d.ts +2 -1
  29. package/dist/protocol/dist/board-capability-registry.js +53 -3
  30. package/dist/protocol/dist/board-codec.js +149 -2
  31. package/dist/protocol/dist/board-constants.js +29 -7
  32. package/dist/protocol/dist/board-document.d.ts +30 -16
  33. package/dist/protocol/dist/board-document.js +15 -12
  34. package/dist/protocol/dist/board-effect.d.ts +4 -2
  35. package/dist/protocol/dist/board-effect.js +3 -2
  36. package/dist/protocol/dist/board.d.ts +148 -3
  37. package/dist/protocol/dist/board.js +7 -0
  38. package/dist/protocol/dist/index.d.ts +4 -2
  39. package/dist/protocol/dist/provenance.d.ts +21 -0
  40. package/dist/types.d.ts +1 -1
  41. package/docs/app-runtime-guide.md +28 -3
  42. package/package.json +1 -1
  43. package/dist/board/render/themes/board-theme-registry.d.ts +0 -22
  44. package/dist/board/render/themes/board-theme-registry.js +0 -13
  45. package/dist/board/render/themes/clean-theme.d.ts +0 -5
@@ -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 = {
@@ -61,13 +61,14 @@ requiring the viewer to paste an API key.
61
61
  └─────────────────────────────────────────┘
62
62
  ```
63
63
 
64
- Five runtime-only APIs form the foundation; everything else is standard SDK:
64
+ These runtime-only APIs form the foundation; everything else is standard SDK:
65
65
 
66
66
  | API | What it does | Returns |
67
67
  |---|---|---|
68
68
  | `client.context()` | Asks the host for the App's identity | `{ app, space, viewer?, invocation?, permissions }` or `null` |
69
69
  | `client.auth.request({ scopes, reason, spaceId?, alwaysAsk? })` | Ensures the app holds these scopes; silent when a grant already covers them, consent dialog otherwise | `true` / `false` |
70
70
  | `client.auth.requestSpace({ scopes, reason, alwaysAsk? })` | One consent: the viewer picks a Space and grants the scopes on it | `{ granted, space }` |
71
+ | `client.auth.requestCreateSpace({ scopes, space, reason })` | One consent: create a viewer-owned Space (`CreateSpaceInput`) and grant the scopes on it | `{ granted, space }` |
71
72
  | `client.context().permissions.viewerGrants` | Render the viewer's current per-space grants | `{ spaceId, scopes }[]` |
72
73
  | `client.app.commerce.*` / `client.app.realtime.*` | Commerce and realtime, bound to the app's runtime identity | (see below) |
73
74
 
@@ -206,7 +207,7 @@ command.execute — run sandbox shell commands
206
207
  ### Viewer grants (consent-required, any permission, per Space)
207
208
 
208
209
  A viewer grants these through a consent dialog triggered by
209
- `client.auth.request()` / `client.auth.requestSpace()`. A viewer may grant
210
+ `client.auth.request()` / `client.auth.requestSpace()` / `client.auth.requestCreateSpace()`. A viewer may grant
210
211
  **any** permission they currently hold on the target Space — including scopes
211
212
  outside the eight app scopes, such as `generation.create` or the account-level
212
213
  `user.*` scopes. Two hard rules are enforced by the server:
@@ -260,10 +261,30 @@ const { granted, space } = await client.auth.requestSpace({
260
261
  if (granted && space) {
261
262
  const picked = client.space(space.id);
262
263
  }
264
+
265
+ // Create a viewer-owned Space and grant on it — never silent. `space` is the
266
+ // same `CreateSpaceInput` as `client.spaces.create()` (blank, git, or checkpoint).
267
+ const created = await client.auth.requestCreateSpace({
268
+ scopes: ["file.view", "session.view", "session.prompt.fullaccess"],
269
+ space: {
270
+ name: "Whale Shrine",
271
+ bootstrapSource: { type: "checkpoint", checkpointId },
272
+ },
273
+ reason: "Create a workspace from this template.",
274
+ });
275
+ if (created.granted && created.space) {
276
+ const next = client.space(created.space.id);
277
+ }
278
+ // `granted: false` with a `space` means the Space was created but bootstrap
279
+ // did not finish — no grant was issued. A deny is `{ granted: false, space: null }`.
263
280
  ```
264
281
 
265
282
  Pass `alwaysAsk: true` to skip silent reuse and force a fresh dialog — for
266
283
  re-confirming a grant or letting the viewer switch to another Space.
284
+ `requestCreateSpace` always opens the dialog; each confirm mints a new Space.
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.
267
288
 
268
289
  ### Checking grant state at runtime
269
290
 
@@ -318,6 +339,8 @@ dialog can.
318
339
  | Read task run detail | `client.tasks.get(taskRunId)` | `taskrun.view` | app or viewer |
319
340
  | List tasks in a Space | `client.tasks.list({ spaceId })` | `taskrun.view` on that Space | app or viewer |
320
341
  | List all owned task runs | `client.tasks.list()` | `user.taskrun.list` | **viewer only** |
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** |
321
344
  | List viewer's spaces | `client.spaces.list()` | `user.space.list` | **viewer only** |
322
345
  | List viewer's sessions | `client.user.listSessions()` | `user.session.list` | **viewer only** |
323
346
  | Read viewer's activity | `client.user.getActivity()` | `user.usage.read` | **viewer only** |
@@ -1204,7 +1227,9 @@ Before publishing your App, verify each item:
1204
1227
  on page load. It is safe to call repeatedly — covered scopes renew silently.
1205
1228
  - [ ] **Cross-Space access targets the right Space** — viewer grants are per
1206
1229
  Space. Pass `spaceId` when requesting, or use `auth.requestSpace` to let the
1207
- viewer pick.
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.
1208
1233
  - [ ] **`subscribeGeneration` errors are not silently swallowed** — if the
1209
1234
  stream fails, surface it; a silent fallback to polling will also 403 if
1210
1235
  `session.view` is missing.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neta-art/cohub",
3
- "version": "8.10.2",
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 };