@neta-art/cohub 5.10.0 → 6.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.
- package/README.md +42 -46
- package/dist/board/animation.d.ts +156 -67
- package/dist/board/animation.js +161 -305
- package/dist/board/geometry.js +4 -4
- package/dist/board/index.d.ts +4 -4
- package/dist/board/index.js +3 -4
- package/dist/board/mutation.d.ts +5 -11
- package/dist/board/mutation.js +9 -46
- package/dist/chunks/http.d.ts +23 -12
- package/dist/chunks/http.js +674 -316
- package/dist/chunks/websocket.d.ts +2623 -201
- package/dist/http.d.ts +3 -3
- package/dist/index.d.ts +158 -299
- package/dist/index.js +164 -306
- package/dist/protocol/dist/board-authoring.d.ts +1 -0
- package/dist/protocol/dist/board-authoring.js +217 -0
- package/dist/protocol/dist/board-capability-registry.d.ts +2 -0
- package/dist/protocol/dist/board-capability-registry.js +74 -0
- package/dist/protocol/dist/board-codec.d.ts +2 -0
- package/dist/protocol/dist/board-codec.js +4 -0
- package/dist/protocol/dist/board-composition.d.ts +258 -0
- package/dist/protocol/dist/board-composition.js +318 -0
- package/dist/protocol/dist/board-constants.js +0 -25
- package/dist/protocol/dist/board-node.d.ts +1 -12
- package/dist/protocol/dist/board-node.js +1 -81
- package/dist/protocol/dist/board-upgrade.d.ts +1 -0
- package/dist/protocol/dist/board-upgrade.js +2 -0
- package/dist/protocol/dist/board.d.ts +19 -92
- package/dist/protocol/dist/board.js +18 -78
- package/dist/protocol/dist/index.d.ts +8 -3
- package/dist/protocol/dist/index.js +9 -4
- package/dist/types.d.ts +2 -1
- package/docs/work-runtime-guide.md +19 -3
- package/package.json +3 -2
- package/dist/board/nodes.d.ts +0 -113
- package/dist/board/nodes.js +0 -154
package/README.md
CHANGED
|
@@ -80,20 +80,16 @@ Use `space.boards` for collection operations and bind an ID with
|
|
|
80
80
|
`space.board(boardId)` for entity operations:
|
|
81
81
|
|
|
82
82
|
```ts
|
|
83
|
-
import { createBoardNode } from "@neta-art/cohub";
|
|
84
|
-
|
|
85
83
|
const created = await space.boards.create({
|
|
86
84
|
path: "boards/plan.board",
|
|
87
85
|
title: "Plan",
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}),
|
|
96
|
-
],
|
|
86
|
+
items: [{
|
|
87
|
+
id: "goal",
|
|
88
|
+
type: "geo",
|
|
89
|
+
frame: { x: 80, y: 80, width: 240, height: 120, rotation: 0 },
|
|
90
|
+
props: { shape: "rounded", text: "Ship" },
|
|
91
|
+
style: { color: "green" },
|
|
92
|
+
}],
|
|
97
93
|
});
|
|
98
94
|
|
|
99
95
|
const board = space.board(created.board.id);
|
|
@@ -102,22 +98,21 @@ const board = space.board(created.board.id);
|
|
|
102
98
|
// Machine-readable types, enums and coordinate spaces for dynamic clients.
|
|
103
99
|
const capabilities = await board.capabilities();
|
|
104
100
|
|
|
105
|
-
const snapshot = await board.
|
|
106
|
-
include: ["nodes", "effects", "sequences", "clips", "playback"],
|
|
107
|
-
});
|
|
101
|
+
const snapshot = await board.authoring();
|
|
108
102
|
|
|
109
|
-
await board.
|
|
110
|
-
txId: crypto.randomUUID(),
|
|
103
|
+
await board.mutateSemantic({
|
|
111
104
|
baseVersion: snapshot.board.version,
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
105
|
+
commands: [{
|
|
106
|
+
type: "item.patch",
|
|
107
|
+
itemId: "goal",
|
|
108
|
+
patch: { props: { text: "Updated plan" } },
|
|
109
|
+
}],
|
|
115
110
|
});
|
|
116
111
|
|
|
117
112
|
await board.play({
|
|
118
113
|
commandId: crypto.randomUUID(),
|
|
119
114
|
type: "play",
|
|
120
|
-
|
|
115
|
+
compositionId: "ambient",
|
|
121
116
|
});
|
|
122
117
|
```
|
|
123
118
|
|
|
@@ -156,40 +151,36 @@ graphics stack:
|
|
|
156
151
|
```ts
|
|
157
152
|
import {
|
|
158
153
|
BoardDocumentSchema,
|
|
159
|
-
|
|
160
|
-
compileSequence,
|
|
154
|
+
compileComposition,
|
|
161
155
|
createBoardExtensionRegistry,
|
|
162
156
|
itemBounds,
|
|
163
157
|
planBoardExport,
|
|
164
|
-
timeline,
|
|
165
158
|
} from "@neta-art/cohub/board";
|
|
166
159
|
|
|
167
|
-
const
|
|
160
|
+
const composition = compileComposition({
|
|
168
161
|
id: "ambient",
|
|
169
162
|
name: "Ambient",
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
target: { type: "
|
|
174
|
-
|
|
163
|
+
duration: 1_000,
|
|
164
|
+
tracks: [{
|
|
165
|
+
id: "image-translation",
|
|
166
|
+
target: { type: "item", itemId: "image" },
|
|
167
|
+
channel: "transform.translation",
|
|
168
|
+
fill: "both",
|
|
175
169
|
keyframes: [
|
|
176
|
-
{
|
|
177
|
-
{
|
|
178
|
-
{
|
|
170
|
+
{ time: 0, value: { x: 0, y: 0 } },
|
|
171
|
+
{ time: 500, value: { x: 0, y: -8 } },
|
|
172
|
+
{ time: 1_000, value: { x: 0, y: 0 } },
|
|
179
173
|
],
|
|
180
|
-
}
|
|
174
|
+
}],
|
|
175
|
+
playback: { loop: true, endBehavior: "hold", reducedMotion: { mode: "base" } },
|
|
181
176
|
});
|
|
182
177
|
|
|
183
178
|
await space.boards.create({
|
|
184
179
|
path: "boards/ambient.board",
|
|
185
180
|
metadata: {
|
|
186
|
-
playback: {
|
|
187
|
-
sequenceId: sequence.sequence.id,
|
|
188
|
-
delayMs: 500,
|
|
189
|
-
loop: true,
|
|
190
|
-
},
|
|
181
|
+
playback: { compositionId: composition.id, delayMs: 500 },
|
|
191
182
|
},
|
|
192
|
-
|
|
183
|
+
compositions: [composition],
|
|
193
184
|
});
|
|
194
185
|
```
|
|
195
186
|
|
|
@@ -241,8 +232,9 @@ access tokens — no API keys required.
|
|
|
241
232
|
|
|
242
233
|
Four runtime-only APIs are available **exclusively inside a published Work**:
|
|
243
234
|
|
|
244
|
-
- `client.context()` — returns Work identity, Space identity,
|
|
245
|
-
permission scopes
|
|
235
|
+
- `client.context()` — returns Work identity, Space identity, the current
|
|
236
|
+
viewer, permission scopes, and optional UI Preview invocation identifiers.
|
|
237
|
+
Returns `null` outside a Work runtime.
|
|
246
238
|
- `client.auth.request({ scopes, reason })` — shows the viewer a consent dialog
|
|
247
239
|
and caches a token with the approved scopes.
|
|
248
240
|
- `client.work.commerce.*` — entitlement checks, credit consumption,
|
|
@@ -259,6 +251,7 @@ const client = createCohubClient({ env: "prod" });
|
|
|
259
251
|
const ctx = await client.context();
|
|
260
252
|
if (!ctx?.space?.id) throw new Error("Not inside a published Work.");
|
|
261
253
|
|
|
254
|
+
const sourceSessionId = ctx.invocation?.sessionId ?? null;
|
|
262
255
|
const space = client.space(ctx.space.id);
|
|
263
256
|
|
|
264
257
|
// Request viewer scopes from a user gesture (button click)
|
|
@@ -274,11 +267,14 @@ Work permissions come in **two disjoint sets**:
|
|
|
274
267
|
|
|
275
268
|
- **Work scopes** (read, no consent): `space.view`, `session.view`,
|
|
276
269
|
`file.view`, `taskrun.view` — granted at publish time.
|
|
277
|
-
- **Viewer scopes** (
|
|
278
|
-
`
|
|
279
|
-
`user.usage.read` — approved per-viewer via
|
|
280
|
-
|
|
281
|
-
|
|
270
|
+
- **Viewer scopes** (consent-required): `taskrun.view`,
|
|
271
|
+
`session.prompt.fullaccess`, `generation.create`, `user.space.list`,
|
|
272
|
+
`user.session.list`, `user.usage.read` — approved per-viewer via
|
|
273
|
+
`auth.request()`.
|
|
274
|
+
|
|
275
|
+
Viewer-granted `taskrun.view` is checked against the viewer's own access to the
|
|
276
|
+
requested Space or Session. Other read operations need work scopes; action
|
|
277
|
+
operations need viewer scopes.
|
|
282
278
|
They never substitute for each other.** For example, `session.prompt.fullaccess`
|
|
283
279
|
lets you send a prompt but does NOT let you read the reply — that needs
|
|
284
280
|
`session.view` (a work scope). Similarly, `generation.create` lets you create
|
|
@@ -1,38 +1,46 @@
|
|
|
1
1
|
import { BoardCapability, BoardRenderCost } from "../protocol/dist/board-constants.js";
|
|
2
|
-
import {
|
|
2
|
+
import { BoardAnimationTarget, BoardComposition, BoardEasing, BoardProceduralClip, BoardTimelineMarker, BoardTrack, BoardTrackInterpolation } from "../protocol/dist/board-composition.js";
|
|
3
|
+
import { BoardAssetRef, BoardDiagnostic, BoardEffect, BoardValidationResult } from "../protocol/dist/board.js";
|
|
3
4
|
import "../protocol/dist/index.js";
|
|
4
5
|
//#region src/board/animation.d.ts
|
|
5
|
-
type
|
|
6
|
-
|
|
7
|
-
seed?: string;
|
|
6
|
+
type CompositionInput = Omit<BoardComposition, "revision"> & {
|
|
7
|
+
revision?: number;
|
|
8
8
|
};
|
|
9
|
-
type
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
} | {
|
|
13
|
-
type: "parallel";
|
|
14
|
-
children: TimelineInput[];
|
|
15
|
-
} | {
|
|
16
|
-
type: "sequence";
|
|
17
|
-
children: TimelineInput[];
|
|
18
|
-
} | {
|
|
19
|
-
type: "stagger";
|
|
20
|
-
each: number;
|
|
21
|
-
children: TimelineInput[];
|
|
22
|
-
} | {
|
|
23
|
-
type: "delay";
|
|
24
|
-
duration: number;
|
|
25
|
-
child: TimelineInput;
|
|
26
|
-
} | {
|
|
27
|
-
type: "repeat";
|
|
28
|
-
count: number;
|
|
29
|
-
child: TimelineInput;
|
|
9
|
+
type TrackInput = Omit<BoardTrack, "channelVersion" | "metadata"> & {
|
|
10
|
+
channelVersion?: number;
|
|
11
|
+
metadata?: Record<string, unknown>;
|
|
30
12
|
};
|
|
31
|
-
type
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
13
|
+
type ProceduralClipInput = Omit<BoardProceduralClip, "kindVersion" | "layer" | "fill" | "easing" | "params" | "assetRefs" | "metadata"> & {
|
|
14
|
+
kindVersion?: number;
|
|
15
|
+
layer?: BoardProceduralClip["layer"];
|
|
16
|
+
fill?: BoardProceduralClip["fill"];
|
|
17
|
+
easing?: BoardEasing;
|
|
18
|
+
params?: Record<string, unknown>;
|
|
19
|
+
assetRefs?: BoardAssetRef[];
|
|
20
|
+
metadata?: Record<string, unknown>;
|
|
21
|
+
};
|
|
22
|
+
declare function track(input: TrackInput): BoardTrack;
|
|
23
|
+
declare function proceduralClip(input: ProceduralClipInput): BoardProceduralClip;
|
|
24
|
+
declare function composition(input: CompositionInput): BoardComposition;
|
|
25
|
+
declare function compileComposition(input: {
|
|
26
|
+
id: string;
|
|
27
|
+
name: string;
|
|
28
|
+
duration: number;
|
|
29
|
+
tracks?: TrackInput[];
|
|
30
|
+
clips?: ProceduralClipInput[];
|
|
31
|
+
markers?: BoardTimelineMarker[];
|
|
32
|
+
playback?: BoardComposition["playback"];
|
|
33
|
+
metadata?: Record<string, unknown>;
|
|
34
|
+
}): BoardComposition;
|
|
35
|
+
type SampledTrack = {
|
|
36
|
+
target: BoardAnimationTarget;
|
|
37
|
+
channel: string;
|
|
38
|
+
value: unknown;
|
|
35
39
|
};
|
|
40
|
+
declare function sampleEasing(easing: BoardEasing, value: number): number;
|
|
41
|
+
/** Deterministically sample one validated Track without touching scene state. */
|
|
42
|
+
declare function sampleTrack(trackValue: BoardTrack, time: number): SampledTrack | null;
|
|
43
|
+
declare function sampleCompositionTracks(value: BoardComposition, time: number): SampledTrack[];
|
|
36
44
|
type RenderBounds = {
|
|
37
45
|
x: number;
|
|
38
46
|
y: number;
|
|
@@ -48,54 +56,135 @@ type BoardExtensionDefinition = BoardCapability & {
|
|
|
48
56
|
};
|
|
49
57
|
type BoardPresetDefinition = BoardCapability & {
|
|
50
58
|
kind: "preset";
|
|
51
|
-
compile: (params: Record<string, unknown>) =>
|
|
59
|
+
compile: (params: Record<string, unknown>) => BoardComposition;
|
|
52
60
|
};
|
|
53
61
|
declare const DEFAULT_BOARD_LIMITS: BoardRenderCost;
|
|
54
|
-
declare const timeline: {
|
|
55
|
-
clip(clip: TimelineClipInput): TimelineInput;
|
|
56
|
-
parallel(...children: TimelineInput[]): TimelineInput;
|
|
57
|
-
sequence(...children: TimelineInput[]): TimelineInput;
|
|
58
|
-
stagger(each: number, ...children: TimelineInput[]): TimelineInput;
|
|
59
|
-
delay(duration: number, child: TimelineInput): TimelineInput;
|
|
60
|
-
repeat(count: number, child: TimelineInput): TimelineInput;
|
|
61
|
-
};
|
|
62
|
-
declare function clip(input: {
|
|
63
|
-
kind: string;
|
|
64
|
-
target: BoardTarget;
|
|
65
|
-
duration: number;
|
|
66
|
-
params?: Record<string, unknown>;
|
|
67
|
-
keyframes?: BoardClip["keyframes"];
|
|
68
|
-
assetRefs?: BoardAssetRef[];
|
|
69
|
-
easing?: string;
|
|
70
|
-
fill?: BoardClip["fill"];
|
|
71
|
-
layer?: BoardClip["layer"];
|
|
72
|
-
kindVersion?: number;
|
|
73
|
-
id?: string;
|
|
74
|
-
seed?: string;
|
|
75
|
-
metadata?: Record<string, unknown>;
|
|
76
|
-
}): TimelineInput;
|
|
77
|
-
declare function compileSequence(input: {
|
|
78
|
-
id: string;
|
|
79
|
-
name: string;
|
|
80
|
-
seed: string;
|
|
81
|
-
timeline: TimelineInput;
|
|
82
|
-
restPose?: Record<string, unknown>;
|
|
83
|
-
metadata?: Record<string, unknown>;
|
|
84
|
-
}): CompiledSequence;
|
|
85
62
|
declare class BoardExtensionRegistry {
|
|
86
63
|
#private;
|
|
64
|
+
constructor();
|
|
87
65
|
register(definition: BoardExtensionDefinition | BoardPresetDefinition): this;
|
|
88
66
|
capabilities(): BoardCapability[];
|
|
89
|
-
compilePreset(id: string, version: number, params: Record<string, unknown>):
|
|
67
|
+
compilePreset(id: string, version: number, params: Record<string, unknown>): {
|
|
68
|
+
id: string;
|
|
69
|
+
name: string;
|
|
70
|
+
timeline: {
|
|
71
|
+
duration: number;
|
|
72
|
+
tracks: {
|
|
73
|
+
id: string;
|
|
74
|
+
target: {
|
|
75
|
+
type: "item";
|
|
76
|
+
itemId: string;
|
|
77
|
+
} | {
|
|
78
|
+
type: "effect";
|
|
79
|
+
effectId: string;
|
|
80
|
+
} | {
|
|
81
|
+
type: "camera";
|
|
82
|
+
} | {
|
|
83
|
+
type: "board";
|
|
84
|
+
};
|
|
85
|
+
channel: string;
|
|
86
|
+
channelVersion: number;
|
|
87
|
+
interpolation: "linear" | "step";
|
|
88
|
+
fill: "backwards" | "both" | "forwards" | "none";
|
|
89
|
+
keyframes: {
|
|
90
|
+
time: number;
|
|
91
|
+
value: unknown;
|
|
92
|
+
easing?: "ease-in-cubic" | "ease-in-out-cubic" | "ease-in-out-quad" | "ease-in-quad" | "ease-out-cubic" | "ease-out-expo" | "ease-out-quad" | "ease-out-quart" | "linear" | undefined;
|
|
93
|
+
}[];
|
|
94
|
+
metadata: Record<string, unknown>;
|
|
95
|
+
}[];
|
|
96
|
+
clips: {
|
|
97
|
+
id: string;
|
|
98
|
+
kind: string;
|
|
99
|
+
kindVersion: number;
|
|
100
|
+
target: {
|
|
101
|
+
type: "item";
|
|
102
|
+
itemId: string;
|
|
103
|
+
} | {
|
|
104
|
+
type: "effect";
|
|
105
|
+
effectId: string;
|
|
106
|
+
} | {
|
|
107
|
+
type: "camera";
|
|
108
|
+
} | {
|
|
109
|
+
type: "board";
|
|
110
|
+
};
|
|
111
|
+
start: number;
|
|
112
|
+
duration: number;
|
|
113
|
+
layer: "behind" | "content" | "front" | "screen";
|
|
114
|
+
fill: "backwards" | "both" | "forwards" | "none";
|
|
115
|
+
easing: "ease-in-cubic" | "ease-in-out-cubic" | "ease-in-out-quad" | "ease-in-quad" | "ease-out-cubic" | "ease-out-expo" | "ease-out-quad" | "ease-out-quart" | "linear";
|
|
116
|
+
params: Record<string, unknown>;
|
|
117
|
+
assetRefs: {
|
|
118
|
+
type: "extension" | "space-file";
|
|
119
|
+
ref: string;
|
|
120
|
+
digest?: string | undefined;
|
|
121
|
+
}[];
|
|
122
|
+
seed: string;
|
|
123
|
+
metadata: Record<string, unknown>;
|
|
124
|
+
}[];
|
|
125
|
+
markers: {
|
|
126
|
+
id: string;
|
|
127
|
+
time: number;
|
|
128
|
+
duration?: number | undefined;
|
|
129
|
+
metadata: Record<string, unknown>;
|
|
130
|
+
}[];
|
|
131
|
+
};
|
|
132
|
+
playback: {
|
|
133
|
+
loop: boolean;
|
|
134
|
+
endBehavior: "hold" | "reset";
|
|
135
|
+
reducedMotion: {
|
|
136
|
+
mode: "base";
|
|
137
|
+
} | {
|
|
138
|
+
mode: "time";
|
|
139
|
+
time: number;
|
|
140
|
+
} | {
|
|
141
|
+
mode: "marker";
|
|
142
|
+
markerId: string;
|
|
143
|
+
};
|
|
144
|
+
};
|
|
145
|
+
metadata: Record<string, unknown>;
|
|
146
|
+
revision: number;
|
|
147
|
+
};
|
|
90
148
|
validate(input: {
|
|
91
|
-
|
|
149
|
+
composition: BoardComposition;
|
|
92
150
|
effects?: Array<Omit<BoardEffect, "boardId" | "revision">>;
|
|
93
151
|
profile?: QualityProfile;
|
|
94
152
|
limits?: BoardRenderCost;
|
|
95
153
|
}): BoardValidationResult;
|
|
96
154
|
}
|
|
97
|
-
declare function createBoardExtensionRegistry(
|
|
98
|
-
|
|
99
|
-
|
|
155
|
+
declare function createBoardExtensionRegistry(): BoardExtensionRegistry;
|
|
156
|
+
declare const BOARD_CHANNELS: {
|
|
157
|
+
readonly "transform.translation": {
|
|
158
|
+
readonly targets: readonly ["item"];
|
|
159
|
+
readonly value: import("zod").ZodObject<{
|
|
160
|
+
x: import("zod").ZodNumber;
|
|
161
|
+
y: import("zod").ZodNumber;
|
|
162
|
+
}, import("zod/v4/core").$strict>;
|
|
163
|
+
readonly interpolations: readonly ["linear", "step"];
|
|
164
|
+
readonly coordinateSpace: "world-offset";
|
|
165
|
+
readonly unit: "board";
|
|
166
|
+
};
|
|
167
|
+
readonly "transform.rotation": {
|
|
168
|
+
readonly targets: readonly ["item"];
|
|
169
|
+
readonly value: import("zod").ZodNumber;
|
|
170
|
+
readonly interpolations: readonly ["linear", "step"];
|
|
171
|
+
readonly unit: "radian";
|
|
172
|
+
};
|
|
173
|
+
readonly "transform.scale": {
|
|
174
|
+
readonly targets: readonly ["item"];
|
|
175
|
+
readonly value: import("zod").ZodUnion<readonly [import("zod").ZodNumber, import("zod").ZodObject<{
|
|
176
|
+
x: import("zod").ZodNumber;
|
|
177
|
+
y: import("zod").ZodNumber;
|
|
178
|
+
}, import("zod/v4/core").$strict>]>;
|
|
179
|
+
readonly interpolations: readonly ["linear", "step"];
|
|
180
|
+
readonly unit: "ratio";
|
|
181
|
+
};
|
|
182
|
+
readonly "style.opacity": {
|
|
183
|
+
readonly targets: readonly ["item"];
|
|
184
|
+
readonly value: import("zod").ZodNumber;
|
|
185
|
+
readonly interpolations: readonly ["linear", "step"];
|
|
186
|
+
readonly unit: "ratio";
|
|
187
|
+
};
|
|
188
|
+
};
|
|
100
189
|
//#endregion
|
|
101
|
-
export { BoardExtensionDefinition, BoardExtensionRegistry, BoardPresetDefinition,
|
|
190
|
+
export { BOARD_CHANNELS, BoardExtensionDefinition, BoardExtensionRegistry, BoardPresetDefinition, type BoardTrackInterpolation, CompositionInput, DEFAULT_BOARD_LIMITS, ProceduralClipInput, QualityProfile, RenderBounds, SampledTrack, TrackInput, compileComposition, composition, createBoardExtensionRegistry, proceduralClip, sampleCompositionTracks, sampleEasing, sampleTrack, track };
|