@cyberart-io/engine 0.0.2 → 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/dist/index.d.ts CHANGED
@@ -255,7 +255,9 @@ type NormalizeFailure = {
255
255
  type NormalizeResult = NormalizeSuccess | NormalizeFailure;
256
256
  /**
257
257
  * `kind` on the input wins. Otherwise persistence types are intents, then
258
- * the second dotted segment of `type` if it is a known kind.
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.*`.
259
261
  */
260
262
  declare function inferEventKind(input: EventInput): EventKind | undefined;
261
263
  declare function matchEventPattern(pattern: string, type: string): boolean;
@@ -281,11 +283,18 @@ type HostEventListener = (event: HostEvent) => void;
281
283
  declare class HostChannel {
282
284
  private inbound;
283
285
  private listeners;
286
+ private closed;
284
287
  dispatch(event: HostEvent): void;
285
288
  consume(): HostEvent[];
286
289
  emit(event: HostEvent): void;
287
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. */
288
294
  clear(): void;
295
+ /** Permanent close. Further dispatch / emit / consume / onEvent throw. */
296
+ close(): void;
297
+ private requireOpen;
289
298
  }
290
299
 
291
300
  /**
@@ -404,6 +413,8 @@ declare class IncompatibleCartStateError extends Error {
404
413
  *
405
414
  * Host-controlled time, input, and asset completion for deterministic replays.
406
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.
407
418
  */
408
419
 
409
420
  declare const ASSET_READY_EVENT = "cyberart.asset.ready";
@@ -428,6 +439,7 @@ type ScriptedAction = {
428
439
  type: 'asset';
429
440
  id: string;
430
441
  status: 'ready' | 'failed';
442
+ /** Optional structured failure or resolved resource. Envelope is unchanged. */
431
443
  detail?: unknown;
432
444
  });
433
445
  type DeterministicRuntimeOptions = {
@@ -460,6 +472,151 @@ type AppliedAction = {
460
472
  */
461
473
  declare function describeReplayMismatch(a: ReplayMetadata, b: ReplayMetadata): string[];
462
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
+
463
620
  /**
464
621
  * Copyright (c) 2026 Aaron Boyarsky
465
622
  * SPDX-License-Identifier: LicenseRef-CyberArt-Engine
@@ -497,6 +654,13 @@ type CreateRuntimeOptions = {
497
654
  * token hash drive the piece as they do today.
498
655
  */
499
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;
500
664
  };
501
665
  type MountOptions<T = unknown> = {
502
666
  /** Boot overrides passed as `customState` into `getDefaultState`. Not a live-state replay. */
@@ -558,72 +722,20 @@ type CyberArtRuntime = {
558
722
  unlockAudio(): Promise<void>;
559
723
  destroy(): void;
560
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;
561
735
  onError?: (error: unknown, info: FrameErrorInfo) => void;
562
736
  };
563
737
  declare function createRuntime(options: CreateRuntimeOptions): CyberArtRuntime;
564
738
 
565
- /**
566
- * Copyright (c) 2026 Aaron Boyarsky
567
- * SPDX-License-Identifier: LicenseRef-CyberArt-Engine
568
- * See packages/engine/LICENSE
569
- *
570
- * CI / agent harness around production `createRuntime({ deterministic })`.
571
- * `installHeadlessCanvas` is test-only — do not call it from Player or kaleidoscope.
572
- */
573
-
574
- /** 1×1 PNG so `captureFrame(path)` writes a file that actually opens. */
575
- declare const HEADLESS_PNG_DATA_URL = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==";
576
- declare const DEFAULT_HEADLESS_WIDTH = 320;
577
- declare const DEFAULT_HEADLESS_HEIGHT = 180;
578
- /**
579
- * Documented jsdom canvas install. Mutates `HTMLCanvasElement.prototype`.
580
- * Idempotent. Not for production playback.
581
- */
582
- declare function installHeadlessCanvas(): void;
583
- type HeadlessFrameError = {
584
- error: unknown;
585
- info: FrameErrorInfo;
586
- };
587
- type HeadlessInspect = {
588
- state: unknown;
589
- events: HostEvent[];
590
- errors: HeadlessFrameError[];
591
- replay: ReplayMetadata;
592
- clock: ClockSnapshot;
593
- };
594
- type CreateHeadlessHarnessOptions<T = unknown> = {
595
- cart: AnimationCart<T>;
596
- seed?: CreateRuntimeOptions['seed'];
597
- width?: number;
598
- height?: number;
599
- /** Virtual clock origin in ms. Default 0. */
600
- origin?: number;
601
- actions?: ScriptedAction[];
602
- initialState?: Partial<T>;
603
- gameManager?: unknown;
604
- onEvent?: HostEventListener;
605
- onError?: (error: unknown, info: FrameErrorInfo) => void;
606
- };
607
- type HeadlessHarness<T = unknown> = {
608
- readonly runtime: CyberArtRuntime;
609
- readonly container: HTMLElement;
610
- readonly events: readonly HostEvent[];
611
- readonly errors: readonly HeadlessFrameError[];
612
- readonly cart: CartHandle;
613
- step(frames?: number): Promise<void>;
614
- advance(ms: number): Promise<void>;
615
- schedule(action: ScriptedAction): void;
616
- dispatch(event: HostEvent): void;
617
- key(key: string): void;
618
- /** Pointer-down at the next frame. Use `schedule` for move/up. Canvas pixels, not CSS. */
619
- click(x: number, y: number): void;
620
- inspect(): Promise<HeadlessInspect>;
621
- captureFrame(path?: string): Promise<CartSnapshot>;
622
- remount(options?: MountOptions<T>): CartHandle;
623
- destroy(): void;
624
- };
625
- declare function createHeadlessHarness<T>(options: CreateHeadlessHarnessOptions<T>): HeadlessHarness<T>;
626
-
627
739
  /**
628
740
  * Copyright (c) 2026 Aaron Boyarsky
629
741
  * SPDX-License-Identifier: LicenseRef-CyberArt-Engine
@@ -716,4 +828,295 @@ type EventRouter = {
716
828
  };
717
829
  declare function createEventRouter(options?: EventRouterOptions): EventRouter;
718
830
 
719
- export { ASSET_FAILED_EVENT, ASSET_READY_EVENT, type AnimationCart, type AnimationTiming, type AppliedAction, type AttachOptions, type AudioLibraryId, type AudioLibrarySpec, CYBERART_CANVAS_ATTR, type CartHandle, type CartSnapshot, type CartStateBundle, type CartStateHotkeyOptions, type CartStateMessageHandler, type CartStatePersister, type Clock, type ClockSnapshot, type CreateHeadlessHarnessOptions, type CreateRuntimeOptions, type CyberArtRuntime, DEFAULT_HEADLESS_HEIGHT, DEFAULT_HEADLESS_WIDTH, DEFAULT_MAX_HOPS, type DeterministicRuntimeOptions, type DimensionContext, EVENT_ENVELOPE_VERSION, type EventEnvelope, type EventInput, type EventKind, type EventRouter, type EventRouterOptions, type FrameErrorInfo, HEADLESS_PNG_DATA_URL, type HeadlessFrameError, type HeadlessHarness, type HeadlessInspect, HostChannel, type HostEvent, type HostEventListener, type ImportCartStateExtras, IncompatibleCartStateError, KeyboardManager, type MountOptions, type NormalizeContext, type NormalizeResult, type PointerClick, PointerManager, type PublishExtras, REJECTED_EVENT_TYPE, Random, type RandomState, type RejectionPayload, type RejectionReason, type ReplayMetadata, type ScriptedAction, type TokenData, type ValidateResult, type VirtualClock, attachCartStatePersistence, canonicalizeSeed, createEventRouter, createHeadlessHarness, createRuntime, createVirtualClock, createWallClock, describeReplayMismatch, inferEventKind, installHeadlessCanvas, matchEventPattern, normalizeEvent, registerCartStateHotkeys, resolveRuntimeSeed };
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 };