@cyberart-io/engine 0.0.1 → 0.0.3
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 +193 -11
- package/dist/headless.d.ts +637 -0
- package/dist/headless.js +8 -0
- package/dist/index.d.ts +753 -8
- package/dist/index.js +1 -1
- package/docs/asset-resolver.md +155 -0
- package/docs/deterministic-mode.md +132 -0
- package/docs/events.md +272 -0
- package/docs/headless-harness.md +186 -0
- package/docs/presentation-adapter.md +150 -0
- package/docs/presentation-cue.md +82 -0
- package/package.json +15 -3
package/dist/index.d.ts
CHANGED
|
@@ -43,6 +43,23 @@ type TokenData = {
|
|
|
43
43
|
/** Same idea for Arweave-typed external assets. We don't currently use it. */
|
|
44
44
|
preferredArweaveGateway?: string;
|
|
45
45
|
};
|
|
46
|
+
/**
|
|
47
|
+
* Canonical token hash for `Random` / Art Blocks.
|
|
48
|
+
*
|
|
49
|
+
* A full 64-hex hash (optional `0x`) is returned unchanged aside from a
|
|
50
|
+
* lowercase `0x` prefix — this is the kaleidoscope / Art Blocks path.
|
|
51
|
+
* Any other seed (including the Adventure Kit example `42`) is mixed into
|
|
52
|
+
* a 64-hex hash so `Random` always sees the same shape.
|
|
53
|
+
*/
|
|
54
|
+
declare function canonicalizeSeed(seed: string | number): string;
|
|
55
|
+
/**
|
|
56
|
+
* Seed policy for `createRuntime`.
|
|
57
|
+
*
|
|
58
|
+
* Live kaleidoscope / Art Blocks must keep a caller-supplied 64-hex hash (and
|
|
59
|
+
* a short `?hash=` string as `0x…`, not remixed). Deterministic mode and
|
|
60
|
+
* numeric seeds such as `42` go through `canonicalizeSeed`.
|
|
61
|
+
*/
|
|
62
|
+
declare function resolveRuntimeSeed(seed: string | number, mode: 'live' | 'deterministic'): string;
|
|
46
63
|
|
|
47
64
|
/**
|
|
48
65
|
* Copyright (c) 2026 Aaron Boyarsky
|
|
@@ -50,11 +67,29 @@ type TokenData = {
|
|
|
50
67
|
* See packages/engine/LICENSE
|
|
51
68
|
*/
|
|
52
69
|
|
|
70
|
+
type Sfc32Regs = {
|
|
71
|
+
a: number;
|
|
72
|
+
b: number;
|
|
73
|
+
c: number;
|
|
74
|
+
d: number;
|
|
75
|
+
};
|
|
76
|
+
/** Snapshot of the dual sfc32 generators after warmup (or after `setState`). */
|
|
77
|
+
type RandomState = {
|
|
78
|
+
seed: string;
|
|
79
|
+
useA: boolean;
|
|
80
|
+
prngA: Sfc32Regs;
|
|
81
|
+
prngB: Sfc32Regs;
|
|
82
|
+
};
|
|
53
83
|
declare class Random {
|
|
84
|
+
readonly seed: string;
|
|
54
85
|
private useA;
|
|
55
86
|
private prngA;
|
|
56
87
|
private prngB;
|
|
88
|
+
private genA;
|
|
89
|
+
private genB;
|
|
57
90
|
constructor(tokenData: TokenData);
|
|
91
|
+
getState(): RandomState;
|
|
92
|
+
setState(state: RandomState): void;
|
|
58
93
|
r_zero_one(): number;
|
|
59
94
|
dec(min?: number, max?: number): number;
|
|
60
95
|
int(min: number, max?: number): number;
|
|
@@ -86,12 +121,18 @@ type KeypressHandler = () => void;
|
|
|
86
121
|
declare class KeyboardManager {
|
|
87
122
|
private actionMap;
|
|
88
123
|
private debugMode;
|
|
124
|
+
private listening;
|
|
89
125
|
constructor(debugMode?: boolean, captureKeyboard?: boolean);
|
|
90
126
|
/**
|
|
91
127
|
* When a key is pressed, check if there's a corresponding action, and execute it.
|
|
92
128
|
* @param e
|
|
93
129
|
*/
|
|
94
130
|
checkKeypress({ key }: KeyboardEvent): void;
|
|
131
|
+
/**
|
|
132
|
+
* Inject a key without a DOM event. Deterministic hosts call this at a
|
|
133
|
+
* chosen frame instead of listening on `window`.
|
|
134
|
+
*/
|
|
135
|
+
inject(key: string): void;
|
|
95
136
|
/**
|
|
96
137
|
* Register a certain action to be performed when a given key is pressed.
|
|
97
138
|
* @param key
|
|
@@ -116,22 +157,112 @@ type PointerClick = {
|
|
|
116
157
|
x: number;
|
|
117
158
|
y: number;
|
|
118
159
|
};
|
|
160
|
+
type PointerManagerOptions = {
|
|
161
|
+
/**
|
|
162
|
+
* When false, do not attach canvas pointer listeners. Deterministic mode
|
|
163
|
+
* injects coordinates instead of reading the live pointer.
|
|
164
|
+
*/
|
|
165
|
+
listen?: boolean;
|
|
166
|
+
};
|
|
119
167
|
declare class PointerManager {
|
|
120
168
|
x: number;
|
|
121
169
|
y: number;
|
|
122
170
|
isDown: boolean;
|
|
123
171
|
private clicks;
|
|
124
172
|
private canvas;
|
|
125
|
-
|
|
173
|
+
private listening;
|
|
174
|
+
constructor(canvas: HTMLCanvasElement, options?: PointerManagerOptions);
|
|
126
175
|
private toCanvasCoords;
|
|
127
176
|
private onPointerDown;
|
|
128
177
|
private onPointerMove;
|
|
129
178
|
private onPointerUp;
|
|
130
179
|
hasClick(): boolean;
|
|
131
180
|
consumeClick(): PointerClick | null;
|
|
181
|
+
/**
|
|
182
|
+
* Inject a pointer sample in canvas pixel space. Deterministic hosts call
|
|
183
|
+
* this at a chosen frame instead of waiting on DOM pointer events.
|
|
184
|
+
*/
|
|
185
|
+
inject(kind: 'down' | 'move' | 'up', x: number, y: number): void;
|
|
132
186
|
destroy(): void;
|
|
133
187
|
}
|
|
134
188
|
|
|
189
|
+
/**
|
|
190
|
+
* Copyright (c) 2026 Aaron Boyarsky
|
|
191
|
+
* SPDX-License-Identifier: LicenseRef-CyberArt-Engine
|
|
192
|
+
* See packages/engine/LICENSE
|
|
193
|
+
*
|
|
194
|
+
* Versioned envelope for routed host ↔ cart events. Unattached HostChannel
|
|
195
|
+
* mailboxes still accept thin `{ type, payload }` events; this module is the
|
|
196
|
+
* schema the EventRouter normalizes to.
|
|
197
|
+
*/
|
|
198
|
+
declare const EVENT_ENVELOPE_VERSION: 1;
|
|
199
|
+
type EventKind = 'intent' | 'state' | 'diagnostic';
|
|
200
|
+
type RejectionReason = 'malformed' | 'unauthorized' | 'host-rejected' | 'rate-limited' | 'loop-detected' | 'storm-detected' | 'unknown-target' | 'not-subscribed' | 'hop-limit';
|
|
201
|
+
declare const REJECTED_EVENT_TYPE = "cyberart.diagnostic.rejected";
|
|
202
|
+
/** Remaining hops on a new root event; each caused follow-up decrements by 1. */
|
|
203
|
+
declare const DEFAULT_MAX_HOPS = 8;
|
|
204
|
+
type EventEnvelope = {
|
|
205
|
+
schemaVersion: typeof EVENT_ENVELOPE_VERSION;
|
|
206
|
+
type: string;
|
|
207
|
+
kind: EventKind;
|
|
208
|
+
source: string;
|
|
209
|
+
target?: string;
|
|
210
|
+
id: string;
|
|
211
|
+
correlationId: string;
|
|
212
|
+
causationId?: string;
|
|
213
|
+
seq: number;
|
|
214
|
+
hops: number;
|
|
215
|
+
idempotencyKey?: string;
|
|
216
|
+
payload?: unknown;
|
|
217
|
+
};
|
|
218
|
+
type EventInput = {
|
|
219
|
+
type: string;
|
|
220
|
+
payload?: unknown;
|
|
221
|
+
schemaVersion?: number;
|
|
222
|
+
kind?: EventKind;
|
|
223
|
+
source?: string;
|
|
224
|
+
target?: string;
|
|
225
|
+
id?: string;
|
|
226
|
+
correlationId?: string;
|
|
227
|
+
causationId?: string;
|
|
228
|
+
seq?: number;
|
|
229
|
+
hops?: number;
|
|
230
|
+
idempotencyKey?: string;
|
|
231
|
+
};
|
|
232
|
+
type RejectionPayload = {
|
|
233
|
+
reason: RejectionReason;
|
|
234
|
+
detail?: string;
|
|
235
|
+
eventType: string;
|
|
236
|
+
source: string;
|
|
237
|
+
};
|
|
238
|
+
type NormalizeContext = {
|
|
239
|
+
source: string;
|
|
240
|
+
createId: () => string;
|
|
241
|
+
seq: number;
|
|
242
|
+
causationId?: string;
|
|
243
|
+
maxHops?: number;
|
|
244
|
+
parentHops?: number;
|
|
245
|
+
};
|
|
246
|
+
type NormalizeSuccess = {
|
|
247
|
+
ok: true;
|
|
248
|
+
envelope: EventEnvelope;
|
|
249
|
+
};
|
|
250
|
+
type NormalizeFailure = {
|
|
251
|
+
ok: false;
|
|
252
|
+
reason: 'malformed';
|
|
253
|
+
detail: string;
|
|
254
|
+
};
|
|
255
|
+
type NormalizeResult = NormalizeSuccess | NormalizeFailure;
|
|
256
|
+
/**
|
|
257
|
+
* `kind` on the input wins. Otherwise persistence types are intents, then
|
|
258
|
+
* the first dotted segment that is `intent` | `state` | `diagnostic`.
|
|
259
|
+
* `adventure.presentation.*` does not infer a kind (the presentation segment
|
|
260
|
+
* is not one); put the kind in the name, e.g. `adventure.presentation.intent.*`.
|
|
261
|
+
*/
|
|
262
|
+
declare function inferEventKind(input: EventInput): EventKind | undefined;
|
|
263
|
+
declare function matchEventPattern(pattern: string, type: string): boolean;
|
|
264
|
+
declare function normalizeEvent(input: EventInput, context: NormalizeContext): NormalizeResult;
|
|
265
|
+
|
|
135
266
|
/**
|
|
136
267
|
* Copyright (c) 2026 Aaron Boyarsky
|
|
137
268
|
* SPDX-License-Identifier: LicenseRef-CyberArt-Engine
|
|
@@ -142,22 +273,49 @@ declare class PointerManager {
|
|
|
142
273
|
* `emit`ted by the cart and forwarded to host `onEvent` listeners.
|
|
143
274
|
*
|
|
144
275
|
* Carts that never mention this object behave as they do today.
|
|
276
|
+
*
|
|
277
|
+
* Routed traffic is a full EventEnvelope; thin `{ type, payload }` remains
|
|
278
|
+
* valid on an unattached mailbox. Extra envelope fields are optional here.
|
|
145
279
|
*/
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
payload?: unknown;
|
|
149
|
-
};
|
|
280
|
+
|
|
281
|
+
type HostEvent = EventInput;
|
|
150
282
|
type HostEventListener = (event: HostEvent) => void;
|
|
151
283
|
declare class HostChannel {
|
|
152
284
|
private inbound;
|
|
153
285
|
private listeners;
|
|
286
|
+
private closed;
|
|
154
287
|
dispatch(event: HostEvent): void;
|
|
155
288
|
consume(): HostEvent[];
|
|
156
289
|
emit(event: HostEvent): void;
|
|
157
290
|
onEvent(listener: HostEventListener): () => void;
|
|
291
|
+
/** Drop queued inbound events. Does not remove `onEvent` listeners. */
|
|
292
|
+
clearInbound(): void;
|
|
293
|
+
/** Drop inbound events and listeners. Runtime teardown; not cart unload. */
|
|
158
294
|
clear(): void;
|
|
295
|
+
/** Permanent close. Further dispatch / emit / consume / onEvent throw. */
|
|
296
|
+
close(): void;
|
|
297
|
+
private requireOpen;
|
|
159
298
|
}
|
|
160
299
|
|
|
300
|
+
/**
|
|
301
|
+
* Copyright (c) 2026 Aaron Boyarsky
|
|
302
|
+
* SPDX-License-Identifier: LicenseRef-CyberArt-Engine
|
|
303
|
+
* See packages/engine/LICENSE
|
|
304
|
+
*
|
|
305
|
+
* Time source for animation. Production uses the wall clock (`performance.now`);
|
|
306
|
+
* deterministic mode uses a host-advanced virtual clock so replays do not
|
|
307
|
+
* depend on rAF, `setTimeout`, or wall time.
|
|
308
|
+
*/
|
|
309
|
+
type Clock = {
|
|
310
|
+
now(): number;
|
|
311
|
+
};
|
|
312
|
+
type VirtualClock = Clock & {
|
|
313
|
+
set(ms: number): void;
|
|
314
|
+
advance(ms: number): void;
|
|
315
|
+
};
|
|
316
|
+
declare function createWallClock(): Clock;
|
|
317
|
+
declare function createVirtualClock(origin?: number): VirtualClock;
|
|
318
|
+
|
|
161
319
|
/**
|
|
162
320
|
* Copyright (c) 2026 Aaron Boyarsky
|
|
163
321
|
* SPDX-License-Identifier: LicenseRef-CyberArt-Engine
|
|
@@ -248,6 +406,217 @@ declare class IncompatibleCartStateError extends Error {
|
|
|
248
406
|
constructor(message: string);
|
|
249
407
|
}
|
|
250
408
|
|
|
409
|
+
/**
|
|
410
|
+
* Copyright (c) 2026 Aaron Boyarsky
|
|
411
|
+
* SPDX-License-Identifier: LicenseRef-CyberArt-Engine
|
|
412
|
+
* See packages/engine/LICENSE
|
|
413
|
+
*
|
|
414
|
+
* Host-controlled time, input, and asset completion for deterministic replays.
|
|
415
|
+
* Production kaleidoscope / Art Blocks playback does not enable this mode.
|
|
416
|
+
* Logical asset URLs are resolved by the host preloader (`assetResolver.ts`);
|
|
417
|
+
* this module only times `ASSET_READY_EVENT` / `ASSET_FAILED_EVENT` delivery.
|
|
418
|
+
*/
|
|
419
|
+
|
|
420
|
+
declare const ASSET_READY_EVENT = "cyberart.asset.ready";
|
|
421
|
+
declare const ASSET_FAILED_EVENT = "cyberart.asset.failed";
|
|
422
|
+
type PointerKind = 'down' | 'move' | 'up';
|
|
423
|
+
type ScriptedAction = {
|
|
424
|
+
atFrame: number;
|
|
425
|
+
} & ({
|
|
426
|
+
type: 'pointer';
|
|
427
|
+
pointer: {
|
|
428
|
+
kind: PointerKind;
|
|
429
|
+
x: number;
|
|
430
|
+
y: number;
|
|
431
|
+
};
|
|
432
|
+
} | {
|
|
433
|
+
type: 'key';
|
|
434
|
+
key: string;
|
|
435
|
+
} | {
|
|
436
|
+
type: 'event';
|
|
437
|
+
event: HostEvent;
|
|
438
|
+
} | {
|
|
439
|
+
type: 'asset';
|
|
440
|
+
id: string;
|
|
441
|
+
status: 'ready' | 'failed';
|
|
442
|
+
/** Optional structured failure or resolved resource. Envelope is unchanged. */
|
|
443
|
+
detail?: unknown;
|
|
444
|
+
});
|
|
445
|
+
type DeterministicRuntimeOptions = {
|
|
446
|
+
/** Virtual clock origin in ms. Default 0. */
|
|
447
|
+
origin?: number;
|
|
448
|
+
/** Actions applied at the start of `atFrame`, before `update`. */
|
|
449
|
+
actions?: ScriptedAction[];
|
|
450
|
+
};
|
|
451
|
+
type ClockSnapshot = {
|
|
452
|
+
now: number;
|
|
453
|
+
framesElapsed: number;
|
|
454
|
+
frameRate: number;
|
|
455
|
+
};
|
|
456
|
+
type ReplayMetadata = {
|
|
457
|
+
seed: string;
|
|
458
|
+
clock: ClockSnapshot;
|
|
459
|
+
rng: RandomState;
|
|
460
|
+
actions: ScriptedAction[];
|
|
461
|
+
applied: AppliedAction[];
|
|
462
|
+
events: HostEvent[];
|
|
463
|
+
state: unknown;
|
|
464
|
+
};
|
|
465
|
+
type AppliedAction = {
|
|
466
|
+
frame: number;
|
|
467
|
+
action: ScriptedAction;
|
|
468
|
+
};
|
|
469
|
+
/**
|
|
470
|
+
* Compare two replay captures. Empty array means identical; otherwise each
|
|
471
|
+
* string names the first disagreement on that field.
|
|
472
|
+
*/
|
|
473
|
+
declare function describeReplayMismatch(a: ReplayMetadata, b: ReplayMetadata): string[];
|
|
474
|
+
|
|
475
|
+
declare const ASSET_KINDS: readonly ["image", "audio", "font", "spritesheet"];
|
|
476
|
+
type AssetKind = (typeof ASSET_KINDS)[number];
|
|
477
|
+
declare const ASSET_FAILURE_CODES: readonly ["timeout", "cors", "not-found", "invalid", "aborted", "resolver"];
|
|
478
|
+
type AssetFailureCode = (typeof ASSET_FAILURE_CODES)[number];
|
|
479
|
+
type AssetCorsMode = 'anonymous' | 'use-credentials' | 'omit';
|
|
480
|
+
/** Logical silent placeholder. Carts/hosts may treat it as “no media”. */
|
|
481
|
+
declare const SILENT_ASSET_FALLBACK_REF = "cyberart:fallback/silent";
|
|
482
|
+
type AssetProvenance = {
|
|
483
|
+
readonly [key: string]: string | number | boolean | null | undefined;
|
|
484
|
+
};
|
|
485
|
+
type AssetDeclaration = {
|
|
486
|
+
/** Cache key and `ASSET_*_EVENT` payload `id`. */
|
|
487
|
+
id: string;
|
|
488
|
+
/** Logical URI: `https://…`, `moltazine:post/<id>#fragment`, `world:asset/…`, `library:…`. */
|
|
489
|
+
ref: string;
|
|
490
|
+
type: AssetKind;
|
|
491
|
+
integrity?: string;
|
|
492
|
+
provenance?: AssetProvenance;
|
|
493
|
+
/** Per-asset timeout. Ignored when wall-clock timeouts are off (deterministic). */
|
|
494
|
+
timeoutMs?: number;
|
|
495
|
+
/**
|
|
496
|
+
* `'silent'` synthesizes `SILENT_ASSET_FALLBACK_REF`. A string is another
|
|
497
|
+
* logical ref of the same type. A declaration is resolved as-is.
|
|
498
|
+
*/
|
|
499
|
+
fallback?: 'silent' | string | AssetDeclaration;
|
|
500
|
+
};
|
|
501
|
+
type AssetResolveRequest = {
|
|
502
|
+
id: string;
|
|
503
|
+
ref: string;
|
|
504
|
+
type: AssetKind;
|
|
505
|
+
integrity?: string;
|
|
506
|
+
provenance?: AssetProvenance;
|
|
507
|
+
};
|
|
508
|
+
type ResolvedAsset = {
|
|
509
|
+
id: string;
|
|
510
|
+
ref: string;
|
|
511
|
+
type: AssetKind;
|
|
512
|
+
url: string;
|
|
513
|
+
integrity?: string;
|
|
514
|
+
provenance?: AssetProvenance;
|
|
515
|
+
cors?: AssetCorsMode;
|
|
516
|
+
usedFallback?: boolean;
|
|
517
|
+
/** When true, `dispose` / `forget` call `URL.revokeObjectURL`. */
|
|
518
|
+
managed?: boolean;
|
|
519
|
+
};
|
|
520
|
+
type AssetFailure = {
|
|
521
|
+
id: string;
|
|
522
|
+
ref: string;
|
|
523
|
+
code: AssetFailureCode;
|
|
524
|
+
message: string;
|
|
525
|
+
};
|
|
526
|
+
type AssetItemStatus = {
|
|
527
|
+
state: 'pending';
|
|
528
|
+
} | {
|
|
529
|
+
state: 'loading';
|
|
530
|
+
} | {
|
|
531
|
+
state: 'ready';
|
|
532
|
+
resource: ResolvedAsset;
|
|
533
|
+
failure?: AssetFailure;
|
|
534
|
+
} | {
|
|
535
|
+
state: 'failed';
|
|
536
|
+
failure: AssetFailure;
|
|
537
|
+
};
|
|
538
|
+
type AssetPreloadSnapshot = {
|
|
539
|
+
total: number;
|
|
540
|
+
pending: number;
|
|
541
|
+
ready: number;
|
|
542
|
+
failed: number;
|
|
543
|
+
fallbacks: number;
|
|
544
|
+
items: Record<string, AssetItemStatus>;
|
|
545
|
+
failures: AssetFailure[];
|
|
546
|
+
};
|
|
547
|
+
type AssetResolver = {
|
|
548
|
+
resolve(request: AssetResolveRequest, signal?: AbortSignal): Promise<ResolvedAsset>;
|
|
549
|
+
};
|
|
550
|
+
type CreateAssetPreloaderOptions = {
|
|
551
|
+
resolver: AssetResolver;
|
|
552
|
+
timeoutMs?: number;
|
|
553
|
+
/**
|
|
554
|
+
* Dispatch `ASSET_READY_EVENT` / `ASSET_FAILED_EVENT` as loads settle.
|
|
555
|
+
* Default true. Deterministic runtimes pass false so scripted `asset`
|
|
556
|
+
* actions own delivery timing.
|
|
557
|
+
*/
|
|
558
|
+
emitEvents?: boolean;
|
|
559
|
+
/**
|
|
560
|
+
* Apply `timeoutMs` with `setTimeout`. Default true. Deterministic
|
|
561
|
+
* runtimes pass false so tests do not wait on wall-clock fetch.
|
|
562
|
+
*/
|
|
563
|
+
wallClockTimeout?: boolean;
|
|
564
|
+
dispatch?: (event: HostEvent) => void;
|
|
565
|
+
};
|
|
566
|
+
type AssetRuntimeOptions = {
|
|
567
|
+
resolver: AssetResolver;
|
|
568
|
+
timeoutMs?: number;
|
|
569
|
+
emitEvents?: boolean;
|
|
570
|
+
};
|
|
571
|
+
type AssetPreloader = {
|
|
572
|
+
preload(declarations: readonly AssetDeclaration[]): Promise<AssetPreloadSnapshot>;
|
|
573
|
+
get(id: string): ResolvedAsset | undefined;
|
|
574
|
+
getProgress(): AssetPreloadSnapshot;
|
|
575
|
+
onProgress(listener: (snapshot: AssetPreloadSnapshot) => void): () => void;
|
|
576
|
+
abort(id?: string): void;
|
|
577
|
+
forget(id?: string): void;
|
|
578
|
+
dispose(): void;
|
|
579
|
+
};
|
|
580
|
+
type FixtureAssetRecord = {
|
|
581
|
+
url: string;
|
|
582
|
+
integrity?: string;
|
|
583
|
+
cors?: AssetCorsMode;
|
|
584
|
+
provenance?: AssetProvenance;
|
|
585
|
+
} | {
|
|
586
|
+
error: AssetFailureCode;
|
|
587
|
+
message?: string;
|
|
588
|
+
};
|
|
589
|
+
type FixtureAssetCatalog = Readonly<Record<string, FixtureAssetRecord>>;
|
|
590
|
+
type HostedAssetResolverOptions = {
|
|
591
|
+
/** Prefix for rewritten logical refs. `http(s)` / `data:` / `blob:` pass through. */
|
|
592
|
+
cdnBase: string;
|
|
593
|
+
/** Authored refs that fail with a structured code. No network. */
|
|
594
|
+
failures?: Readonly<Record<string, AssetFailureCode | {
|
|
595
|
+
code: AssetFailureCode;
|
|
596
|
+
message?: string;
|
|
597
|
+
}>>;
|
|
598
|
+
};
|
|
599
|
+
declare function isAssetKind(value: unknown): value is AssetKind;
|
|
600
|
+
declare function isAssetFailureCode(value: unknown): value is AssetFailureCode;
|
|
601
|
+
declare function isAssetFailure(value: unknown): value is AssetFailure;
|
|
602
|
+
declare function createAssetFailure(input: {
|
|
603
|
+
id: string;
|
|
604
|
+
ref: string;
|
|
605
|
+
code: AssetFailureCode;
|
|
606
|
+
message?: string;
|
|
607
|
+
}): AssetFailure;
|
|
608
|
+
declare function assetStatusEvent(status: 'ready' | 'failed', payload: {
|
|
609
|
+
id: string;
|
|
610
|
+
ref?: string;
|
|
611
|
+
resource?: ResolvedAsset;
|
|
612
|
+
failure?: AssetFailure;
|
|
613
|
+
}): HostEvent;
|
|
614
|
+
/** Map a logical ref through a hosted CDN prefix. Ordinary URLs are unchanged. */
|
|
615
|
+
declare function rewriteHostedAssetRef(ref: string, cdnBase: string): string;
|
|
616
|
+
declare function createFixtureAssetResolver(catalog: FixtureAssetCatalog): AssetResolver;
|
|
617
|
+
declare function createHostedAssetResolver(options: HostedAssetResolverOptions): AssetResolver;
|
|
618
|
+
declare function createAssetPreloader(options: CreateAssetPreloaderOptions): AssetPreloader;
|
|
619
|
+
|
|
251
620
|
/**
|
|
252
621
|
* Copyright (c) 2026 Aaron Boyarsky
|
|
253
622
|
* SPDX-License-Identifier: LicenseRef-CyberArt-Engine
|
|
@@ -262,11 +631,16 @@ type FrameErrorInfo = {
|
|
|
262
631
|
type CreateRuntimeOptions = {
|
|
263
632
|
/** Required mount point. The runtime creates or adopts a canvas inside this element. */
|
|
264
633
|
container: HTMLElement;
|
|
265
|
-
/**
|
|
266
|
-
|
|
634
|
+
/**
|
|
635
|
+
* Token hash (`0x` + 64 hex) or any seed mixed into one. Instance-local;
|
|
636
|
+
* does not clobber an existing global cache. Kaleidoscope / Art Blocks
|
|
637
|
+
* pass the platform hash unchanged.
|
|
638
|
+
*/
|
|
639
|
+
seed?: string | number;
|
|
267
640
|
/**
|
|
268
641
|
* When true, the cart listens for window keydown (full-page players).
|
|
269
642
|
* Defaults to false so an embed does not steal keys from the host.
|
|
643
|
+
* Ignored when `deterministic` is set — input is injected per frame.
|
|
270
644
|
*/
|
|
271
645
|
captureKeyboard?: boolean;
|
|
272
646
|
/**
|
|
@@ -274,6 +648,19 @@ type CreateRuntimeOptions = {
|
|
|
274
648
|
* (click can beat idle prebuild). After mount, `cart.metadata.audio` wins.
|
|
275
649
|
*/
|
|
276
650
|
audio?: AudioLibrarySpec;
|
|
651
|
+
/**
|
|
652
|
+
* Host-controlled time, input, and asset events. Production playback
|
|
653
|
+
* (kaleidoscope locally and `build:art`) leaves this unset so rAF and the
|
|
654
|
+
* token hash drive the piece as they do today.
|
|
655
|
+
*/
|
|
656
|
+
deterministic?: boolean | DeterministicRuntimeOptions;
|
|
657
|
+
/**
|
|
658
|
+
* Host-pluggable asset resolver/preloader. Carts request logical refs;
|
|
659
|
+
* the host maps them to loadable URLs or blobs. Leave unset when unused.
|
|
660
|
+
* In deterministic mode, preload does not dispatch `ASSET_*` events —
|
|
661
|
+
* scripted `{ type: 'asset' }` actions own delivery timing.
|
|
662
|
+
*/
|
|
663
|
+
assets?: AssetRuntimeOptions;
|
|
277
664
|
};
|
|
278
665
|
type MountOptions<T = unknown> = {
|
|
279
666
|
/** Boot overrides passed as `customState` into `getDefaultState`. Not a live-state replay. */
|
|
@@ -310,6 +697,18 @@ type CartHandle = {
|
|
|
310
697
|
peekExportedFramebuffer(): ImageData | null;
|
|
311
698
|
peekSeed(): string | undefined;
|
|
312
699
|
isGenerative(): boolean;
|
|
700
|
+
/**
|
|
701
|
+
* Run `frames` ticks on the virtual clock. Requires `deterministic`.
|
|
702
|
+
* Does not use rAF; live kaleidoscope playback never calls this.
|
|
703
|
+
*/
|
|
704
|
+
step(frames?: number): Promise<void>;
|
|
705
|
+
/** Run the frames that span `ms` at the cart frame rate. Requires `deterministic`. */
|
|
706
|
+
advance(ms: number): Promise<void>;
|
|
707
|
+
/** Queue a scripted input/asset/host event for a future frame. */
|
|
708
|
+
schedule(action: ScriptedAction): void;
|
|
709
|
+
getClock(): ClockSnapshot;
|
|
710
|
+
getRandomState(): RandomState;
|
|
711
|
+
getReplayMetadata(): Promise<ReplayMetadata>;
|
|
313
712
|
readonly canvas: HTMLCanvasElement | undefined;
|
|
314
713
|
paused: boolean;
|
|
315
714
|
readonly tokenData: TokenData;
|
|
@@ -323,6 +722,16 @@ type CyberArtRuntime = {
|
|
|
323
722
|
unlockAudio(): Promise<void>;
|
|
324
723
|
destroy(): void;
|
|
325
724
|
readonly tokenData: TokenData;
|
|
725
|
+
/**
|
|
726
|
+
* This runtime's mailbox. Attach it to `createEventRouter` from the host;
|
|
727
|
+
* carts never receive the router. Survives cart remount; `destroy()` clears it.
|
|
728
|
+
*/
|
|
729
|
+
readonly hostChannel: HostChannel;
|
|
730
|
+
/**
|
|
731
|
+
* Preloader for this runtime. Undefined when `assets` was omitted.
|
|
732
|
+
* Survives cart remount; `destroy()` disposes it.
|
|
733
|
+
*/
|
|
734
|
+
readonly assets: AssetPreloader | undefined;
|
|
326
735
|
onError?: (error: unknown, info: FrameErrorInfo) => void;
|
|
327
736
|
};
|
|
328
737
|
declare function createRuntime(options: CreateRuntimeOptions): CyberArtRuntime;
|
|
@@ -374,4 +783,340 @@ type CartStateHotkeyOptions = {
|
|
|
374
783
|
*/
|
|
375
784
|
declare function registerCartStateHotkeys(keyboardManager: KeyboardManager, hostChannel: HostChannel, options?: CartStateHotkeyOptions): void;
|
|
376
785
|
|
|
377
|
-
|
|
786
|
+
/**
|
|
787
|
+
* Copyright (c) 2026 Aaron Boyarsky
|
|
788
|
+
* SPDX-License-Identifier: LicenseRef-CyberArt-Engine
|
|
789
|
+
* See packages/engine/LICENSE
|
|
790
|
+
*
|
|
791
|
+
* Host-side event router. Carts keep a dumb HostChannel mailbox; the host
|
|
792
|
+
* attaches those channels here so events are permissioned, budgeted, and
|
|
793
|
+
* loop-checked before they reach another cart. Carts never receive this
|
|
794
|
+
* object.
|
|
795
|
+
*/
|
|
796
|
+
|
|
797
|
+
type ValidateResult = true | {
|
|
798
|
+
reason: 'host-rejected';
|
|
799
|
+
detail?: string;
|
|
800
|
+
};
|
|
801
|
+
type AttachOptions = {
|
|
802
|
+
emit?: string[];
|
|
803
|
+
subscribe?: string[];
|
|
804
|
+
authoritative?: boolean;
|
|
805
|
+
};
|
|
806
|
+
type EventRouterOptions = {
|
|
807
|
+
validate?: (event: EventEnvelope) => ValidateResult;
|
|
808
|
+
createId?: () => string;
|
|
809
|
+
now?: () => number;
|
|
810
|
+
hostSource?: string;
|
|
811
|
+
maxPerTurn?: number;
|
|
812
|
+
maxPerWindow?: number;
|
|
813
|
+
windowMs?: number;
|
|
814
|
+
maxCausationDepth?: number;
|
|
815
|
+
maxHops?: number;
|
|
816
|
+
maxCorrelationPerTurn?: number;
|
|
817
|
+
maxIndex?: number;
|
|
818
|
+
};
|
|
819
|
+
type PublishExtras = {
|
|
820
|
+
cause?: EventEnvelope;
|
|
821
|
+
};
|
|
822
|
+
type EventRouter = {
|
|
823
|
+
attach(id: string, channel: HostChannel, options?: AttachOptions): void;
|
|
824
|
+
detach(id: string): void;
|
|
825
|
+
publish(event: EventInput, extras?: PublishExtras): EventEnvelope | undefined;
|
|
826
|
+
subscribe(patterns: string[], listener: (event: EventEnvelope) => void): () => void;
|
|
827
|
+
turn(): void;
|
|
828
|
+
};
|
|
829
|
+
declare function createEventRouter(options?: EventRouterOptions): EventRouter;
|
|
830
|
+
|
|
831
|
+
/**
|
|
832
|
+
* Copyright (c) 2026 Aaron Boyarsky
|
|
833
|
+
* SPDX-License-Identifier: LicenseRef-CyberArt-Engine
|
|
834
|
+
* See packages/engine/LICENSE
|
|
835
|
+
*
|
|
836
|
+
* One contract definition drives TypeScript payload types, runtime
|
|
837
|
+
* validation, router permission checks, and machine-readable manifests.
|
|
838
|
+
* Kind must appear as a dotted segment of `type` so names like
|
|
839
|
+
* `adventure.presentation.cue.started` fail at definition time instead of
|
|
840
|
+
* silently inferring a bogus kind.
|
|
841
|
+
*/
|
|
842
|
+
|
|
843
|
+
type ContractFieldType = 'string' | 'number' | 'boolean' | 'object' | 'array';
|
|
844
|
+
type PayloadFieldSpec = {
|
|
845
|
+
type: ContractFieldType;
|
|
846
|
+
optional?: boolean;
|
|
847
|
+
};
|
|
848
|
+
type PayloadSchema = {
|
|
849
|
+
/** Payload schema version. Bump on any field change. */
|
|
850
|
+
version: number;
|
|
851
|
+
fields: Record<string, PayloadFieldSpec>;
|
|
852
|
+
};
|
|
853
|
+
type ContractDiagnostic = {
|
|
854
|
+
code: string;
|
|
855
|
+
detail: string;
|
|
856
|
+
path?: string;
|
|
857
|
+
};
|
|
858
|
+
type EventContractManifest = {
|
|
859
|
+
type: string;
|
|
860
|
+
kind: EventKind;
|
|
861
|
+
version: number;
|
|
862
|
+
fields: Record<string, {
|
|
863
|
+
type: ContractFieldType;
|
|
864
|
+
optional: boolean;
|
|
865
|
+
}>;
|
|
866
|
+
emitPattern: string;
|
|
867
|
+
subscribePattern: string;
|
|
868
|
+
};
|
|
869
|
+
type PayloadValidation = {
|
|
870
|
+
ok: true;
|
|
871
|
+
payload: unknown;
|
|
872
|
+
} | {
|
|
873
|
+
ok: false;
|
|
874
|
+
errors: ContractDiagnostic[];
|
|
875
|
+
};
|
|
876
|
+
type EventContract = {
|
|
877
|
+
type: string;
|
|
878
|
+
kind: EventKind;
|
|
879
|
+
payloadSchema: PayloadSchema;
|
|
880
|
+
emitPattern: string;
|
|
881
|
+
subscribePattern: string;
|
|
882
|
+
toManifest(): EventContractManifest;
|
|
883
|
+
validatePayload(payload: unknown): PayloadValidation;
|
|
884
|
+
};
|
|
885
|
+
type DefineContractResult = {
|
|
886
|
+
ok: true;
|
|
887
|
+
contract: EventContract;
|
|
888
|
+
} | {
|
|
889
|
+
ok: false;
|
|
890
|
+
errors: ContractDiagnostic[];
|
|
891
|
+
};
|
|
892
|
+
type SchemaCompatibility = 'identical' | 'backward-compatible' | 'breaking';
|
|
893
|
+
type FieldTs<T extends ContractFieldType> = T extends 'string' ? string : T extends 'number' ? number : T extends 'boolean' ? boolean : T extends 'array' ? unknown[] : Record<string, unknown>;
|
|
894
|
+
type OptionalFieldKeys<S extends PayloadSchema> = {
|
|
895
|
+
[K in keyof S['fields']]: S['fields'][K] extends {
|
|
896
|
+
optional: true;
|
|
897
|
+
} ? K : never;
|
|
898
|
+
}[keyof S['fields']];
|
|
899
|
+
type RequiredFieldKeys<S extends PayloadSchema> = Exclude<keyof S['fields'], OptionalFieldKeys<S>>;
|
|
900
|
+
type InferredPayload<S extends PayloadSchema> = {
|
|
901
|
+
[K in RequiredFieldKeys<S>]: FieldTs<S['fields'][K]['type']>;
|
|
902
|
+
} & {
|
|
903
|
+
[K in OptionalFieldKeys<S>]?: FieldTs<S['fields'][K]['type']>;
|
|
904
|
+
};
|
|
905
|
+
/** First dotted segment that is `intent` | `state` | `diagnostic`. */
|
|
906
|
+
declare function kindSegmentInType(type: string): EventKind | undefined;
|
|
907
|
+
declare function familyPatternForType(type: string): string;
|
|
908
|
+
declare function defineIntent(type: string, schema: PayloadSchema): DefineContractResult;
|
|
909
|
+
declare function defineStateEvent(type: string, schema: PayloadSchema): DefineContractResult;
|
|
910
|
+
declare function defineDiagnostic(type: string, schema: PayloadSchema): DefineContractResult;
|
|
911
|
+
declare function comparePayloadSchemas(from: PayloadSchema, to: PayloadSchema): SchemaCompatibility;
|
|
912
|
+
declare function deriveAttachOptions(contracts: EventContract[], role: 'cart' | 'authoritative'): AttachOptions;
|
|
913
|
+
declare function verifyAttachOptions(options: AttachOptions, contracts: EventContract[]): {
|
|
914
|
+
ok: true;
|
|
915
|
+
} | {
|
|
916
|
+
ok: false;
|
|
917
|
+
errors: ContractDiagnostic[];
|
|
918
|
+
};
|
|
919
|
+
type ContractRegistry = {
|
|
920
|
+
get(type: string): EventContract | undefined;
|
|
921
|
+
manifest(): EventContractManifest[];
|
|
922
|
+
validateEnvelope(event: EventEnvelope): PayloadValidation;
|
|
923
|
+
asRouterValidate(event: EventEnvelope): ValidateResult;
|
|
924
|
+
};
|
|
925
|
+
declare function createContractRegistry(contracts: EventContract[]): ContractRegistry;
|
|
926
|
+
|
|
927
|
+
/**
|
|
928
|
+
* Copyright (c) 2026 Aaron Boyarsky
|
|
929
|
+
* SPDX-License-Identifier: LicenseRef-CyberArt-Engine
|
|
930
|
+
* See packages/engine/LICENSE
|
|
931
|
+
*
|
|
932
|
+
* Versioned presentation-adapter contract. Hosts own canonical state and
|
|
933
|
+
* push a render model; Cyberart presents it and emits interaction intents.
|
|
934
|
+
* Adventure Kit concepts stay in the host.
|
|
935
|
+
*/
|
|
936
|
+
|
|
937
|
+
declare const PRESENTATION_ADAPTER_VERSION: 1;
|
|
938
|
+
/** Host → cart render model. Kind is `state`. */
|
|
939
|
+
declare const PRESENTATION_MODEL_EVENT = "presentation.state.model";
|
|
940
|
+
/**
|
|
941
|
+
* Cart → host when a model cannot be presented. Kind is `intent` so a
|
|
942
|
+
* non-authoritative cart can emit it through the router.
|
|
943
|
+
*/
|
|
944
|
+
declare const PRESENTATION_UNSUPPORTED_EVENT = "presentation.intent.unsupported";
|
|
945
|
+
declare const PRESENTATION_PHASES: readonly ["loading", "ready", "error", "unsupported"];
|
|
946
|
+
type PresentationPhase = (typeof PRESENTATION_PHASES)[number];
|
|
947
|
+
/**
|
|
948
|
+
* Recommended router `subscribe` for a presentation cart. Intent type names
|
|
949
|
+
* are host-owned (`adventure.intent.*`); do not put domain objects in `target`.
|
|
950
|
+
*/
|
|
951
|
+
declare const PRESENTATION_SUBSCRIBE_PATTERNS: readonly ["presentation.state.*", "cyberart.diagnostic.rejected"];
|
|
952
|
+
declare const INVALID_PRESENTATION_MODEL_MESSAGE = "Presentation adapter: model is invalid or not JSON-serializable";
|
|
953
|
+
type PresentationRegion = {
|
|
954
|
+
id: string;
|
|
955
|
+
/** Drawing-space pixels — same space as `PointerManager` / harness `click`. */
|
|
956
|
+
x: number;
|
|
957
|
+
y: number;
|
|
958
|
+
width: number;
|
|
959
|
+
height: number;
|
|
960
|
+
/** Emitted on click while `phase === 'ready'`. Prefer `*.intent.*` type names. */
|
|
961
|
+
intent: EventInput;
|
|
962
|
+
};
|
|
963
|
+
type PresentationView = {
|
|
964
|
+
background?: string;
|
|
965
|
+
title?: string;
|
|
966
|
+
regions?: readonly PresentationRegion[];
|
|
967
|
+
};
|
|
968
|
+
type PresentationModel<TView = PresentationView> = {
|
|
969
|
+
contractVersion: typeof PRESENTATION_ADAPTER_VERSION;
|
|
970
|
+
phase: PresentationPhase;
|
|
971
|
+
/** Host-owned render model. The engine does not interpret domain fields. */
|
|
972
|
+
view?: TView;
|
|
973
|
+
/** Machine-readable when `phase` is `loading` | `error` | `unsupported`. */
|
|
974
|
+
reason?: string;
|
|
975
|
+
};
|
|
976
|
+
type PresentationCartState<TView = PresentationView> = {
|
|
977
|
+
model: PresentationModel<TView>;
|
|
978
|
+
};
|
|
979
|
+
type PresentationAdapterTarget = {
|
|
980
|
+
dispatch(event: HostEvent): void;
|
|
981
|
+
start(): Promise<void>;
|
|
982
|
+
pause(): void;
|
|
983
|
+
resume(): void;
|
|
984
|
+
destroy(): void;
|
|
985
|
+
readonly paused?: boolean;
|
|
986
|
+
};
|
|
987
|
+
type PresentationAdapter<TView = PresentationView, TTarget extends PresentationAdapterTarget = PresentationAdapterTarget> = {
|
|
988
|
+
readonly version: typeof PRESENTATION_ADAPTER_VERSION;
|
|
989
|
+
readonly target: TTarget;
|
|
990
|
+
/** Last model this session presented (or the boot model). A copy — mutating it does not update the cart. */
|
|
991
|
+
readonly model: PresentationModel<TView>;
|
|
992
|
+
readonly phase: PresentationPhase;
|
|
993
|
+
readonly paused: boolean;
|
|
994
|
+
present(model: PresentationModel<TView>): void;
|
|
995
|
+
start(): Promise<void>;
|
|
996
|
+
pause(): void;
|
|
997
|
+
resume(): void;
|
|
998
|
+
/** Point at a new handle after `runtime.mount` / `harness.remount`. */
|
|
999
|
+
retarget(target: TTarget): void;
|
|
1000
|
+
destroy(): void;
|
|
1001
|
+
};
|
|
1002
|
+
type AttachPresentationAdapterOptions<TView = PresentationView> = {
|
|
1003
|
+
model?: PresentationModel<TView>;
|
|
1004
|
+
/**
|
|
1005
|
+
* Dispatch `model` onto the mailbox. Default `true` when `model` is set,
|
|
1006
|
+
* `false` otherwise (leave the cart's current state alone).
|
|
1007
|
+
*/
|
|
1008
|
+
present?: boolean;
|
|
1009
|
+
};
|
|
1010
|
+
type MountPresentationAdapterOptions<TView = PresentationView> = {
|
|
1011
|
+
cart?: AnimationCart<PresentationCartState<TView>>;
|
|
1012
|
+
onEvent?: HostEventListener;
|
|
1013
|
+
model?: PresentationModel<TView>;
|
|
1014
|
+
initialState?: MountOptions<PresentationCartState<TView>>['initialState'];
|
|
1015
|
+
};
|
|
1016
|
+
declare function isPresentationPhase(value: unknown): value is PresentationPhase;
|
|
1017
|
+
declare function isPresentationModel(value: unknown): value is PresentationModel;
|
|
1018
|
+
declare function createPresentationModelEvent<TView = PresentationView>(model: PresentationModel<TView>, extras?: Pick<EventInput, 'correlationId' | 'causationId' | 'idempotencyKey'>): EventInput;
|
|
1019
|
+
/**
|
|
1020
|
+
* Minimal presentation cart. Hit-tests `view.regions` while `phase === 'ready'`.
|
|
1021
|
+
* Hosts with a custom view shape may pass their own cart to `mountPresentationAdapter`.
|
|
1022
|
+
* `title` is inspectable state; only `background` is painted.
|
|
1023
|
+
*/
|
|
1024
|
+
declare function createReferencePresentationCart<TView = PresentationView>(): AnimationCart<PresentationCartState<TView>>;
|
|
1025
|
+
declare function attachPresentationAdapter<TView = PresentationView, TTarget extends PresentationAdapterTarget = PresentationAdapterTarget>(target: TTarget, options?: AttachPresentationAdapterOptions<TView>): PresentationAdapter<TView, TTarget>;
|
|
1026
|
+
/** Mount a presentation cart and return the host-facing adapter. */
|
|
1027
|
+
declare function mountPresentationAdapter<TView = PresentationView>(runtime: CyberArtRuntime, options?: MountPresentationAdapterOptions<TView>): PresentationAdapter<TView, CartHandle>;
|
|
1028
|
+
|
|
1029
|
+
/**
|
|
1030
|
+
* Copyright (c) 2026 Aaron Boyarsky
|
|
1031
|
+
* SPDX-License-Identifier: LicenseRef-CyberArt-Engine
|
|
1032
|
+
* See packages/engine/LICENSE
|
|
1033
|
+
*
|
|
1034
|
+
* Deterministic presentation cue / timeline. Carts step this with a frame
|
|
1035
|
+
* index; there are no wall-clock timers. Lifecycle event type names are
|
|
1036
|
+
* stable for later contract registries.
|
|
1037
|
+
*/
|
|
1038
|
+
declare const CUE_STARTED_EVENT: "cue.started";
|
|
1039
|
+
declare const CUE_COMPLETED_EVENT: "cue.completed";
|
|
1040
|
+
declare const CUE_CANCELLED_EVENT: "cue.cancelled";
|
|
1041
|
+
declare const CUE_REPLACED_EVENT: "cue.replaced";
|
|
1042
|
+
declare const CUE_LIFECYCLE_EVENTS: readonly ["cue.started", "cue.completed", "cue.cancelled", "cue.replaced"];
|
|
1043
|
+
type CueLifecycleType = (typeof CUE_LIFECYCLE_EVENTS)[number];
|
|
1044
|
+
type CueEasing = 'linear' | 'ease-out';
|
|
1045
|
+
type CueDuplicatePolicy = 'ignore' | 'replace' | 'reject';
|
|
1046
|
+
type CueRepeatPolicy = {
|
|
1047
|
+
count: number;
|
|
1048
|
+
} | {
|
|
1049
|
+
forever: true;
|
|
1050
|
+
};
|
|
1051
|
+
type CueReducedMotionPolicy = 'skip' | 'complete' | {
|
|
1052
|
+
durationFrames: number;
|
|
1053
|
+
};
|
|
1054
|
+
type CueSpec = {
|
|
1055
|
+
name: string;
|
|
1056
|
+
idempotencyKey: string;
|
|
1057
|
+
/** Frame when the cue is eligible to start (before delay). Default: play frame. */
|
|
1058
|
+
startFrame?: number;
|
|
1059
|
+
durationFrames: number;
|
|
1060
|
+
delayFrames?: number;
|
|
1061
|
+
easing?: CueEasing;
|
|
1062
|
+
repeat?: CueRepeatPolicy;
|
|
1063
|
+
/**
|
|
1064
|
+
* When the timeline is in reduced-motion mode: skip (complete immediately),
|
|
1065
|
+
* complete (same), or a shorter duration. Default `complete`.
|
|
1066
|
+
*/
|
|
1067
|
+
reducedMotion?: CueReducedMotionPolicy;
|
|
1068
|
+
onDuplicate?: CueDuplicatePolicy;
|
|
1069
|
+
};
|
|
1070
|
+
type CuePhase = 'scheduled' | 'active' | 'completed' | 'cancelled';
|
|
1071
|
+
type CueView = {
|
|
1072
|
+
name: string;
|
|
1073
|
+
idempotencyKey: string;
|
|
1074
|
+
phase: CuePhase;
|
|
1075
|
+
startFrame: number;
|
|
1076
|
+
durationFrames: number;
|
|
1077
|
+
delayFrames: number;
|
|
1078
|
+
easing: CueEasing;
|
|
1079
|
+
progress: number;
|
|
1080
|
+
repeatIndex: number;
|
|
1081
|
+
};
|
|
1082
|
+
type CueLifecycleEvent = {
|
|
1083
|
+
type: CueLifecycleType;
|
|
1084
|
+
atFrame: number;
|
|
1085
|
+
name: string;
|
|
1086
|
+
idempotencyKey: string;
|
|
1087
|
+
progress: number;
|
|
1088
|
+
};
|
|
1089
|
+
type CueTimelineSnapshot = {
|
|
1090
|
+
frame: number;
|
|
1091
|
+
reducedMotion: boolean;
|
|
1092
|
+
cues: CueView[];
|
|
1093
|
+
events: CueLifecycleEvent[];
|
|
1094
|
+
};
|
|
1095
|
+
type PlayCueResult = {
|
|
1096
|
+
ok: true;
|
|
1097
|
+
cue: CueView;
|
|
1098
|
+
} | {
|
|
1099
|
+
ok: false;
|
|
1100
|
+
reason: 'duplicate' | 'invalid';
|
|
1101
|
+
detail: string;
|
|
1102
|
+
};
|
|
1103
|
+
type CreatePresentationTimelineOptions = {
|
|
1104
|
+
/** Host-controlled reduced-motion / reduced-sensory flag. Not a CSS query. */
|
|
1105
|
+
reducedMotion?: boolean;
|
|
1106
|
+
originFrame?: number;
|
|
1107
|
+
};
|
|
1108
|
+
type PresentationTimeline = {
|
|
1109
|
+
play(spec: CueSpec): PlayCueResult;
|
|
1110
|
+
step(frames?: number): CueLifecycleEvent[];
|
|
1111
|
+
cancel(idempotencyKey: string): boolean;
|
|
1112
|
+
reset(): void;
|
|
1113
|
+
snapshot(): CueTimelineSnapshot;
|
|
1114
|
+
get(idempotencyKey: string): CueView | undefined;
|
|
1115
|
+
readonly frame: number;
|
|
1116
|
+
readonly reducedMotion: boolean;
|
|
1117
|
+
};
|
|
1118
|
+
declare function isCueLifecycleType(value: unknown): value is CueLifecycleType;
|
|
1119
|
+
declare function applyCueEasing(t: number, easing: CueEasing): number;
|
|
1120
|
+
declare function createPresentationTimeline(options?: CreatePresentationTimelineOptions): PresentationTimeline;
|
|
1121
|
+
|
|
1122
|
+
export { ASSET_FAILED_EVENT, ASSET_FAILURE_CODES, ASSET_KINDS, ASSET_READY_EVENT, type AnimationCart, type AnimationTiming, type AppliedAction, type AssetCorsMode, type AssetDeclaration, type AssetFailure, type AssetFailureCode, type AssetItemStatus, type AssetKind, type AssetPreloadSnapshot, type AssetPreloader, type AssetProvenance, type AssetResolveRequest, type AssetResolver, type AssetRuntimeOptions, type AttachOptions, type AttachPresentationAdapterOptions, type AudioLibraryId, type AudioLibrarySpec, CUE_CANCELLED_EVENT, CUE_COMPLETED_EVENT, CUE_LIFECYCLE_EVENTS, CUE_REPLACED_EVENT, CUE_STARTED_EVENT, CYBERART_CANVAS_ATTR, type CartHandle, type CartSnapshot, type CartStateBundle, type CartStateHotkeyOptions, type CartStateMessageHandler, type CartStatePersister, type Clock, type ClockSnapshot, type ContractDiagnostic, type ContractFieldType, type ContractRegistry, type CreateAssetPreloaderOptions, type CreatePresentationTimelineOptions, type CreateRuntimeOptions, type CueDuplicatePolicy, type CueEasing, type CueLifecycleEvent, type CueLifecycleType, type CuePhase, type CueReducedMotionPolicy, type CueRepeatPolicy, type CueSpec, type CueTimelineSnapshot, type CueView, type CyberArtRuntime, DEFAULT_MAX_HOPS, type DefineContractResult, type DeterministicRuntimeOptions, type DimensionContext, EVENT_ENVELOPE_VERSION, type EventContract, type EventContractManifest, type EventEnvelope, type EventInput, type EventKind, type EventRouter, type EventRouterOptions, type FixtureAssetCatalog, type FixtureAssetRecord, type FrameErrorInfo, HostChannel, type HostEvent, type HostEventListener, type HostedAssetResolverOptions, INVALID_PRESENTATION_MODEL_MESSAGE, type ImportCartStateExtras, IncompatibleCartStateError, type InferredPayload, KeyboardManager, type MountOptions, type MountPresentationAdapterOptions, type NormalizeContext, type NormalizeResult, PRESENTATION_ADAPTER_VERSION, PRESENTATION_MODEL_EVENT, PRESENTATION_PHASES, PRESENTATION_SUBSCRIBE_PATTERNS, PRESENTATION_UNSUPPORTED_EVENT, type PayloadFieldSpec, type PayloadSchema, type PayloadValidation, type PlayCueResult, type PointerClick, PointerManager, type PresentationAdapter, type PresentationAdapterTarget, type PresentationCartState, type PresentationModel, type PresentationPhase, type PresentationRegion, type PresentationTimeline, type PresentationView, type PublishExtras, REJECTED_EVENT_TYPE, Random, type RandomState, type RejectionPayload, type RejectionReason, type ReplayMetadata, type ResolvedAsset, SILENT_ASSET_FALLBACK_REF, type SchemaCompatibility, type ScriptedAction, type TokenData, type ValidateResult, type VirtualClock, applyCueEasing, assetStatusEvent, attachCartStatePersistence, attachPresentationAdapter, canonicalizeSeed, comparePayloadSchemas, createAssetFailure, createAssetPreloader, createContractRegistry, createEventRouter, createFixtureAssetResolver, createHostedAssetResolver, createPresentationModelEvent, createPresentationTimeline, createReferencePresentationCart, createRuntime, createVirtualClock, createWallClock, defineDiagnostic, defineIntent, defineStateEvent, deriveAttachOptions, describeReplayMismatch, familyPatternForType, inferEventKind, isAssetFailure, isAssetFailureCode, isAssetKind, isCueLifecycleType, isPresentationModel, isPresentationPhase, kindSegmentInType, matchEventPattern, mountPresentationAdapter, normalizeEvent, registerCartStateHotkeys, resolveRuntimeSeed, rewriteHostedAssetRef, verifyAttachOptions };
|