@cyberart-io/engine 0.0.4 → 0.0.6
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 +102 -21
- package/dist/headless.d.ts +779 -68
- package/dist/headless.js +1 -1
- package/dist/index.d.ts +1144 -9
- package/dist/index.js +1 -1
- package/docs/asset-resolver.md +4 -4
- package/docs/audio.md +152 -0
- package/docs/browser-harness.md +126 -0
- package/docs/capability-manifest.md +18 -7
- package/docs/compositor.md +103 -0
- package/docs/deterministic-mode.md +1 -1
- package/docs/events.md +75 -13
- package/docs/executable-modules.md +112 -0
- package/docs/headless-harness.md +44 -14
- package/docs/midi.md +128 -0
- package/docs/presentation-adapter.md +8 -8
- package/docs/presentation-cue.md +2 -2
- package/docs/replay-inspector.md +88 -0
- package/docs/runtime-group.md +9 -7
- package/docs/snapshots.md +102 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -48,7 +48,7 @@ type TokenData = {
|
|
|
48
48
|
*
|
|
49
49
|
* A full 64-hex hash (optional `0x`) is returned unchanged aside from a
|
|
50
50
|
* lowercase `0x` prefix — this is the kaleidoscope / Art Blocks path.
|
|
51
|
-
* Any other seed (including the
|
|
51
|
+
* Any other seed (including the numeric example `42`) is mixed into
|
|
52
52
|
* a 64-hex hash so `Random` always sees the same shape.
|
|
53
53
|
*/
|
|
54
54
|
declare function canonicalizeSeed(seed: string | number): string;
|
|
@@ -256,8 +256,8 @@ type NormalizeResult = NormalizeSuccess | NormalizeFailure;
|
|
|
256
256
|
/**
|
|
257
257
|
* `kind` on the input wins. Otherwise persistence types are intents, then
|
|
258
258
|
* the first dotted segment that is `intent` | `state` | `diagnostic`.
|
|
259
|
-
* `
|
|
260
|
-
* is not one); put the kind in the name, e.g. `
|
|
259
|
+
* `host.presentation.*` does not infer a kind (the presentation segment
|
|
260
|
+
* is not one); put the kind in the name, e.g. `host.presentation.intent.*`.
|
|
261
261
|
*/
|
|
262
262
|
declare function inferEventKind(input: EventInput): EventKind | undefined;
|
|
263
263
|
declare function matchEventPattern(pattern: string, type: string): boolean;
|
|
@@ -406,6 +406,153 @@ declare class IncompatibleCartStateError extends Error {
|
|
|
406
406
|
constructor(message: string);
|
|
407
407
|
}
|
|
408
408
|
|
|
409
|
+
/**
|
|
410
|
+
* Copyright (c) 2026 Aaron Boyarsky
|
|
411
|
+
* SPDX-License-Identifier: LicenseRef-CyberArt-Engine
|
|
412
|
+
* See packages/engine/LICENSE
|
|
413
|
+
*
|
|
414
|
+
* Versioned snapshot envelope. Schema 1 is the previous engine-owned
|
|
415
|
+
* `CartStateBundle` (`CART_STATE_BUNDLE_VERSION = 1`). Schema 2 wraps that
|
|
416
|
+
* blob in `engineState` and separates host-owned payload. Hosts persist
|
|
417
|
+
* the JSON; this module is not a database.
|
|
418
|
+
*/
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* Current envelope schema. Independent of `CART_STATE_BUNDLE_VERSION` (still
|
|
422
|
+
* 1 inside `engineState`) and of the npm package version.
|
|
423
|
+
*/
|
|
424
|
+
declare const SNAPSHOT_SCHEMA_VERSION: 2;
|
|
425
|
+
/** Previous supported schema: a raw `CartStateBundle`. */
|
|
426
|
+
declare const LEGACY_SNAPSHOT_SCHEMA_VERSION: 1;
|
|
427
|
+
/**
|
|
428
|
+
* Snapshot runtime id stamped on new envelopes. Documented independently of
|
|
429
|
+
* `packages/engine/package.json` so a schema bump does not require an npm
|
|
430
|
+
* release, and vice versa. Currently `'0.0.5'` to match the published package.
|
|
431
|
+
*/
|
|
432
|
+
declare const ENGINE_SNAPSHOT_RUNTIME = "0.0.5";
|
|
433
|
+
/** Carts without an authored version stamp this exact string. */
|
|
434
|
+
declare const UNVERSIONED_CART_VERSION = "0";
|
|
435
|
+
type SnapshotDiagnostic = {
|
|
436
|
+
code: string;
|
|
437
|
+
detail: string;
|
|
438
|
+
path?: string;
|
|
439
|
+
};
|
|
440
|
+
type SnapshotCartRef = {
|
|
441
|
+
id: string;
|
|
442
|
+
version: string;
|
|
443
|
+
generative?: boolean;
|
|
444
|
+
};
|
|
445
|
+
type SnapshotModuleRef = {
|
|
446
|
+
id: string;
|
|
447
|
+
version: string;
|
|
448
|
+
};
|
|
449
|
+
type SnapshotClock = {
|
|
450
|
+
framesElapsed: number;
|
|
451
|
+
elapsedSinceStart?: number;
|
|
452
|
+
now?: number;
|
|
453
|
+
frameRate?: number;
|
|
454
|
+
};
|
|
455
|
+
type SnapshotAssetRef = {
|
|
456
|
+
id: string;
|
|
457
|
+
version?: string;
|
|
458
|
+
ref?: string;
|
|
459
|
+
};
|
|
460
|
+
type SnapshotIntegrity = {
|
|
461
|
+
alg: string;
|
|
462
|
+
hash: string;
|
|
463
|
+
};
|
|
464
|
+
type SnapshotProvenance = {
|
|
465
|
+
source?: string;
|
|
466
|
+
integrity?: SnapshotIntegrity;
|
|
467
|
+
};
|
|
468
|
+
type SnapshotEnvelope = {
|
|
469
|
+
schemaVersion: typeof SNAPSHOT_SCHEMA_VERSION;
|
|
470
|
+
runtimeVersion: string;
|
|
471
|
+
cart: SnapshotCartRef;
|
|
472
|
+
seed: string;
|
|
473
|
+
clock: SnapshotClock;
|
|
474
|
+
engineState: CartStateBundle;
|
|
475
|
+
createdAt: string;
|
|
476
|
+
modules?: SnapshotModuleRef[];
|
|
477
|
+
rng?: RandomState;
|
|
478
|
+
hostState?: unknown;
|
|
479
|
+
hostStateRef?: string;
|
|
480
|
+
assets?: SnapshotAssetRef[];
|
|
481
|
+
provenance?: SnapshotProvenance;
|
|
482
|
+
};
|
|
483
|
+
type LegacySnapshot = {
|
|
484
|
+
schemaVersion: number;
|
|
485
|
+
engineState: CartStateBundle;
|
|
486
|
+
seed: string;
|
|
487
|
+
clock: SnapshotClock;
|
|
488
|
+
cart?: SnapshotCartRef;
|
|
489
|
+
};
|
|
490
|
+
type VersionedSnapshot = SnapshotEnvelope | LegacySnapshot;
|
|
491
|
+
type SnapshotEnvelopeInput = {
|
|
492
|
+
schemaVersion?: number;
|
|
493
|
+
runtimeVersion?: string;
|
|
494
|
+
cart: SnapshotCartRef;
|
|
495
|
+
seed: string;
|
|
496
|
+
clock: SnapshotClock;
|
|
497
|
+
engineState: CartStateBundle;
|
|
498
|
+
createdAt?: string;
|
|
499
|
+
modules?: SnapshotModuleRef[];
|
|
500
|
+
rng?: RandomState;
|
|
501
|
+
hostState?: unknown;
|
|
502
|
+
hostStateRef?: string;
|
|
503
|
+
assets?: SnapshotAssetRef[];
|
|
504
|
+
provenance?: SnapshotProvenance;
|
|
505
|
+
};
|
|
506
|
+
type ExportSnapshotOptions = {
|
|
507
|
+
cartVersion?: string;
|
|
508
|
+
modules?: SnapshotModuleRef[];
|
|
509
|
+
hostState?: unknown;
|
|
510
|
+
hostStateRef?: string;
|
|
511
|
+
assets?: SnapshotAssetRef[];
|
|
512
|
+
createdAt?: string;
|
|
513
|
+
provenance?: SnapshotProvenance;
|
|
514
|
+
runtimeVersion?: string;
|
|
515
|
+
};
|
|
516
|
+
type DefineSnapshotResult = {
|
|
517
|
+
ok: true;
|
|
518
|
+
snapshot: SnapshotEnvelope;
|
|
519
|
+
} | {
|
|
520
|
+
ok: false;
|
|
521
|
+
errors: SnapshotDiagnostic[];
|
|
522
|
+
};
|
|
523
|
+
type ParseSnapshotResult = {
|
|
524
|
+
ok: true;
|
|
525
|
+
snapshot: VersionedSnapshot;
|
|
526
|
+
} | {
|
|
527
|
+
ok: false;
|
|
528
|
+
errors: SnapshotDiagnostic[];
|
|
529
|
+
};
|
|
530
|
+
type ValidateSnapshotResult = {
|
|
531
|
+
ok: true;
|
|
532
|
+
snapshot: SnapshotEnvelope;
|
|
533
|
+
} | {
|
|
534
|
+
ok: false;
|
|
535
|
+
errors: SnapshotDiagnostic[];
|
|
536
|
+
};
|
|
537
|
+
declare function cloneSnapshotJson<T>(value: T): T;
|
|
538
|
+
/**
|
|
539
|
+
* True when `value` is the previous engine-owned blob, not an envelope.
|
|
540
|
+
* Envelopes are discriminated by `schemaVersion`.
|
|
541
|
+
*/
|
|
542
|
+
declare function isLegacyCartStateBundle(value: unknown): value is CartStateBundle;
|
|
543
|
+
declare function isSnapshotEnvelope(value: unknown): value is SnapshotEnvelope;
|
|
544
|
+
declare function isVersionedSnapshot(value: unknown): value is VersionedSnapshot;
|
|
545
|
+
declare function detectSnapshotSchemaVersion(value: unknown): number | undefined;
|
|
546
|
+
declare function defineSnapshot(input: SnapshotEnvelopeInput): DefineSnapshotResult;
|
|
547
|
+
declare function snapshotFromCartBundle(bundle: CartStateBundle, extras?: ExportSnapshotOptions & {
|
|
548
|
+
rng?: RandomState;
|
|
549
|
+
clock?: SnapshotClock;
|
|
550
|
+
}): DefineSnapshotResult;
|
|
551
|
+
declare function parseSnapshot(input: SnapshotEnvelope | CartStateBundle | LegacySnapshot | string | unknown): ParseSnapshotResult;
|
|
552
|
+
declare function validateSnapshot(value: unknown): ValidateSnapshotResult;
|
|
553
|
+
declare function snapshotErrorsToMessage(errors: SnapshotDiagnostic[]): string;
|
|
554
|
+
declare function engineStateFromEnvelope(snapshot: SnapshotEnvelope): CartStateBundle;
|
|
555
|
+
|
|
409
556
|
/**
|
|
410
557
|
* Copyright (c) 2026 Aaron Boyarsky
|
|
411
558
|
* SPDX-License-Identifier: LicenseRef-CyberArt-Engine
|
|
@@ -617,6 +764,86 @@ declare function createFixtureAssetResolver(catalog: FixtureAssetCatalog): Asset
|
|
|
617
764
|
declare function createHostedAssetResolver(options: HostedAssetResolverOptions): AssetResolver;
|
|
618
765
|
declare function createAssetPreloader(options: CreateAssetPreloaderOptions): AssetPreloader;
|
|
619
766
|
|
|
767
|
+
declare const DEFAULT_DUCK_GAIN = 0.25;
|
|
768
|
+
type AudioUnlockState = 'locked' | 'unlocking' | 'unlocked' | 'failed';
|
|
769
|
+
type AudioUnlockStatus = {
|
|
770
|
+
state: AudioUnlockState;
|
|
771
|
+
error?: string;
|
|
772
|
+
};
|
|
773
|
+
type AudioAssetStatus = 'ready' | 'failed';
|
|
774
|
+
type AudioChannelInspect = {
|
|
775
|
+
id: string;
|
|
776
|
+
participantId?: string;
|
|
777
|
+
gain: number;
|
|
778
|
+
muted: boolean;
|
|
779
|
+
duckGain: number;
|
|
780
|
+
priority: number;
|
|
781
|
+
effectiveGain: number;
|
|
782
|
+
};
|
|
783
|
+
type AudioBrokerInspect = {
|
|
784
|
+
status: AudioUnlockStatus;
|
|
785
|
+
reducedSensory: boolean;
|
|
786
|
+
muted: boolean;
|
|
787
|
+
authorized: string[];
|
|
788
|
+
channels: AudioChannelInspect[];
|
|
789
|
+
assets: Record<string, AudioAssetStatus>;
|
|
790
|
+
};
|
|
791
|
+
type AudioBrokerNotice = {
|
|
792
|
+
type: 'asset';
|
|
793
|
+
id: string;
|
|
794
|
+
status: AudioAssetStatus;
|
|
795
|
+
} | {
|
|
796
|
+
type: 'teardown';
|
|
797
|
+
participantId: string;
|
|
798
|
+
} | {
|
|
799
|
+
type: 'mute';
|
|
800
|
+
} | {
|
|
801
|
+
type: 'destroy';
|
|
802
|
+
};
|
|
803
|
+
type AudioBrokerListener = (notice: AudioBrokerNotice) => void;
|
|
804
|
+
type ActiveAudioCue = {
|
|
805
|
+
idempotencyKey: string;
|
|
806
|
+
channelId: string;
|
|
807
|
+
participantId?: string;
|
|
808
|
+
priority: number;
|
|
809
|
+
};
|
|
810
|
+
type CreateAudioBrokerOptions = {
|
|
811
|
+
/**
|
|
812
|
+
* Called once on the first `unlock()`. Inject in tests. Default dynamically
|
|
813
|
+
* loads the Tone adapter (never a static `import 'tone'`).
|
|
814
|
+
*/
|
|
815
|
+
toneStart?: () => Promise<void>;
|
|
816
|
+
/** Host reduced-sensory flag. Skips playback; cue events still record. */
|
|
817
|
+
reducedSensory?: boolean;
|
|
818
|
+
};
|
|
819
|
+
type AudioBroker = {
|
|
820
|
+
unlock(): Promise<AudioUnlockStatus>;
|
|
821
|
+
status(): AudioUnlockStatus;
|
|
822
|
+
authorize(participantId: string): void;
|
|
823
|
+
revoke(participantId: string): void;
|
|
824
|
+
isAuthorized(participantId: string | undefined): boolean;
|
|
825
|
+
setChannelGain(channelId: string, gain: number, participantId?: string): void;
|
|
826
|
+
setPriority(channelId: string, priority: number, participantId?: string): void;
|
|
827
|
+
mute(): void;
|
|
828
|
+
unmute(): void;
|
|
829
|
+
muteChannel(channelId: string, participantId?: string): void;
|
|
830
|
+
unmuteChannel(channelId: string): void;
|
|
831
|
+
duck(channelId: string, gain?: number): void;
|
|
832
|
+
unduck(channelId: string): void;
|
|
833
|
+
effectiveGain(channelId: string): number;
|
|
834
|
+
handleHostEvent(event: HostEvent): void;
|
|
835
|
+
assetStatus(id: string): AudioAssetStatus | undefined;
|
|
836
|
+
noteCueStarted(cue: ActiveAudioCue): void;
|
|
837
|
+
noteCueEnded(idempotencyKey: string): void;
|
|
838
|
+
teardown(participantId: string): void;
|
|
839
|
+
onNotice(listener: AudioBrokerListener): () => void;
|
|
840
|
+
inspect(): AudioBrokerInspect;
|
|
841
|
+
destroy(): void;
|
|
842
|
+
readonly reducedSensory: boolean;
|
|
843
|
+
readonly muted: boolean;
|
|
844
|
+
};
|
|
845
|
+
declare function createAudioBroker(options?: CreateAudioBrokerOptions): AudioBroker;
|
|
846
|
+
|
|
620
847
|
/**
|
|
621
848
|
* Copyright (c) 2026 Aaron Boyarsky
|
|
622
849
|
* SPDX-License-Identifier: LicenseRef-CyberArt-Engine
|
|
@@ -661,6 +888,17 @@ type CreateRuntimeOptions = {
|
|
|
661
888
|
* scripted `{ type: 'asset' }` actions own delivery timing.
|
|
662
889
|
*/
|
|
663
890
|
assets?: AssetRuntimeOptions;
|
|
891
|
+
/**
|
|
892
|
+
* Shared page-level unlock broker. Optional. Carts that only set
|
|
893
|
+
* `metadata.audio: 'tone'` keep the existing `start()` / `unlockAudio()`
|
|
894
|
+
* path when this is omitted.
|
|
895
|
+
*/
|
|
896
|
+
audioBroker?: AudioBroker;
|
|
897
|
+
/**
|
|
898
|
+
* Runtime-group participant id to authorize on this runtime. Teardown of
|
|
899
|
+
* this id does not close Tone for remaining carts.
|
|
900
|
+
*/
|
|
901
|
+
audioParticipantId?: string;
|
|
664
902
|
};
|
|
665
903
|
type MountOptions<T = unknown> = {
|
|
666
904
|
/** Boot overrides passed as `customState` into `getDefaultState`. Not a live-state replay. */
|
|
@@ -691,7 +929,12 @@ type CartHandle = {
|
|
|
691
929
|
getCartState(): unknown;
|
|
692
930
|
exportState(): Promise<CartStateBundle>;
|
|
693
931
|
exportStateJSON(): Promise<string>;
|
|
694
|
-
importState(bundle: CartStateBundle | string, extras?: {
|
|
932
|
+
importState(bundle: CartStateBundle | SnapshotEnvelope | string, extras?: {
|
|
933
|
+
framebuffer?: ImageData | null;
|
|
934
|
+
}): Promise<void>;
|
|
935
|
+
exportSnapshot(options?: ExportSnapshotOptions): Promise<SnapshotEnvelope>;
|
|
936
|
+
exportSnapshotJSON(options?: ExportSnapshotOptions): Promise<string>;
|
|
937
|
+
importSnapshot(input: SnapshotEnvelope | CartStateBundle | string, extras?: {
|
|
695
938
|
framebuffer?: ImageData | null;
|
|
696
939
|
}): Promise<void>;
|
|
697
940
|
peekExportedFramebuffer(): ImageData | null;
|
|
@@ -732,6 +975,8 @@ type CyberArtRuntime = {
|
|
|
732
975
|
* Survives cart remount; `destroy()` disposes it.
|
|
733
976
|
*/
|
|
734
977
|
readonly assets: AssetPreloader | undefined;
|
|
978
|
+
/** Shared broker when `createRuntime({ audioBroker })` was set. */
|
|
979
|
+
readonly audioBroker: AudioBroker | undefined;
|
|
735
980
|
onError?: (error: unknown, info: FrameErrorInfo) => void;
|
|
736
981
|
};
|
|
737
982
|
declare function createRuntime(options: CreateRuntimeOptions): CyberArtRuntime;
|
|
@@ -749,7 +994,7 @@ type ImportCartStateExtras = {
|
|
|
749
994
|
};
|
|
750
995
|
type CartStatePersister = {
|
|
751
996
|
exportState: () => Promise<CartStateBundle>;
|
|
752
|
-
importState: (bundle: CartStateBundle | string, extras?: ImportCartStateExtras) => Promise<void>;
|
|
997
|
+
importState: (bundle: CartStateBundle | SnapshotEnvelope | string, extras?: ImportCartStateExtras) => Promise<void>;
|
|
753
998
|
peekExportedFramebuffer?: () => ImageData | null;
|
|
754
999
|
/** Live token hash; used to look up a generative cart's per-hash save. */
|
|
755
1000
|
peekSeed?: () => string | undefined;
|
|
@@ -783,6 +1028,53 @@ type CartStateHotkeyOptions = {
|
|
|
783
1028
|
*/
|
|
784
1029
|
declare function registerCartStateHotkeys(keyboardManager: KeyboardManager, hostChannel: HostChannel, options?: CartStateHotkeyOptions): void;
|
|
785
1030
|
|
|
1031
|
+
/**
|
|
1032
|
+
* Copyright (c) 2026 Aaron Boyarsky
|
|
1033
|
+
* SPDX-License-Identifier: LicenseRef-CyberArt-Engine
|
|
1034
|
+
* See packages/engine/LICENSE
|
|
1035
|
+
*
|
|
1036
|
+
* Step-by-step snapshot migrations. The original object is never mutated.
|
|
1037
|
+
* Hosts own persistence; this registry only transforms envelopes in memory.
|
|
1038
|
+
*/
|
|
1039
|
+
|
|
1040
|
+
type SnapshotMigration = {
|
|
1041
|
+
from: number;
|
|
1042
|
+
to: number;
|
|
1043
|
+
migrate: (snapshot: unknown) => unknown;
|
|
1044
|
+
};
|
|
1045
|
+
type SnapshotMigrationRegistry = {
|
|
1046
|
+
migrations: readonly SnapshotMigration[];
|
|
1047
|
+
get(from: number): SnapshotMigration | undefined;
|
|
1048
|
+
};
|
|
1049
|
+
type ApplySnapshotMigrationsResult = {
|
|
1050
|
+
ok: true;
|
|
1051
|
+
snapshot: SnapshotEnvelope;
|
|
1052
|
+
} | {
|
|
1053
|
+
ok: false;
|
|
1054
|
+
errors: SnapshotDiagnostic[];
|
|
1055
|
+
};
|
|
1056
|
+
type ResolveImportableCartStateResult = {
|
|
1057
|
+
ok: true;
|
|
1058
|
+
bundle: CartStateBundle;
|
|
1059
|
+
snapshot?: SnapshotEnvelope;
|
|
1060
|
+
} | {
|
|
1061
|
+
ok: false;
|
|
1062
|
+
errors: SnapshotDiagnostic[];
|
|
1063
|
+
};
|
|
1064
|
+
declare function createEngineSnapshotMigrations(): SnapshotMigration[];
|
|
1065
|
+
declare function createSnapshotMigrationRegistry(options?: {
|
|
1066
|
+
migrations?: SnapshotMigration[];
|
|
1067
|
+
}): SnapshotMigrationRegistry;
|
|
1068
|
+
declare function defaultSnapshotMigrationRegistry(): SnapshotMigrationRegistry;
|
|
1069
|
+
declare function applySnapshotMigrations(snapshot: unknown, registry?: SnapshotMigrationRegistry): ApplySnapshotMigrationsResult;
|
|
1070
|
+
/**
|
|
1071
|
+
* Detect envelope vs legacy cart bundle. Envelopes migrate first; raw
|
|
1072
|
+
* `CartStateBundle` objects pass through so existing exportState/importState
|
|
1073
|
+
* callers keep working.
|
|
1074
|
+
*/
|
|
1075
|
+
declare function resolveImportableCartState(input: unknown, registry?: SnapshotMigrationRegistry): ResolveImportableCartStateResult;
|
|
1076
|
+
declare function restoreSnapshotFromUnknown(input: unknown, registry?: SnapshotMigrationRegistry): ApplySnapshotMigrationsResult;
|
|
1077
|
+
|
|
786
1078
|
/**
|
|
787
1079
|
* Copyright (c) 2026 Aaron Boyarsky
|
|
788
1080
|
* SPDX-License-Identifier: LicenseRef-CyberArt-Engine
|
|
@@ -815,15 +1107,49 @@ type EventRouterOptions = {
|
|
|
815
1107
|
maxHops?: number;
|
|
816
1108
|
maxCorrelationPerTurn?: number;
|
|
817
1109
|
maxIndex?: number;
|
|
1110
|
+
/** Bound on the decision trace (oldest dropped). Default 256. */
|
|
1111
|
+
maxDecisions?: number;
|
|
818
1112
|
};
|
|
819
1113
|
type PublishExtras = {
|
|
820
1114
|
cause?: EventEnvelope;
|
|
821
1115
|
};
|
|
1116
|
+
type RouterParticipantInspect = {
|
|
1117
|
+
id: string;
|
|
1118
|
+
emit: string[];
|
|
1119
|
+
subscribe: string[];
|
|
1120
|
+
authoritative: boolean;
|
|
1121
|
+
};
|
|
1122
|
+
type RouterDecisionOutcome = 'accepted' | 'rejected' | 'duplicate';
|
|
1123
|
+
type RouterDecisionReason = RejectionReason | 'duplicate';
|
|
1124
|
+
type RouterDecision = {
|
|
1125
|
+
outcome: RouterDecisionOutcome;
|
|
1126
|
+
reason?: RouterDecisionReason;
|
|
1127
|
+
detail?: string;
|
|
1128
|
+
source: string;
|
|
1129
|
+
type: string;
|
|
1130
|
+
kind?: EventKind;
|
|
1131
|
+
envelopeId?: string;
|
|
1132
|
+
priorEnvelopeId?: string;
|
|
1133
|
+
target?: string;
|
|
1134
|
+
deliveredTo: string[];
|
|
1135
|
+
hops?: number;
|
|
1136
|
+
seq?: number;
|
|
1137
|
+
correlationId?: string;
|
|
1138
|
+
causationId?: string;
|
|
1139
|
+
idempotencyKey?: string;
|
|
1140
|
+
schemaVersion?: number;
|
|
1141
|
+
payload?: unknown;
|
|
1142
|
+
turn: number;
|
|
1143
|
+
time: number;
|
|
1144
|
+
};
|
|
822
1145
|
type EventRouter = {
|
|
823
1146
|
attach(id: string, channel: HostChannel, options?: AttachOptions): void;
|
|
824
1147
|
detach(id: string): void;
|
|
825
1148
|
publish(event: EventInput, extras?: PublishExtras): EventEnvelope | undefined;
|
|
826
1149
|
subscribe(patterns: string[], listener: (event: EventEnvelope) => void): () => void;
|
|
1150
|
+
subscribeDecision(listener: (decision: RouterDecision) => void): () => void;
|
|
1151
|
+
inspectParticipants(): RouterParticipantInspect[];
|
|
1152
|
+
inspectDecisions(): RouterDecision[];
|
|
827
1153
|
turn(): void;
|
|
828
1154
|
};
|
|
829
1155
|
declare function createEventRouter(options?: EventRouterOptions): EventRouter;
|
|
@@ -836,7 +1162,7 @@ declare function createEventRouter(options?: EventRouterOptions): EventRouter;
|
|
|
836
1162
|
* One contract definition drives TypeScript payload types, runtime
|
|
837
1163
|
* validation, router permission checks, and machine-readable manifests.
|
|
838
1164
|
* Kind must appear as a dotted segment of `type` so names like
|
|
839
|
-
* `
|
|
1165
|
+
* `host.presentation.cue.started` fail at definition time instead of
|
|
840
1166
|
* silently inferring a bogus kind.
|
|
841
1167
|
*/
|
|
842
1168
|
|
|
@@ -931,7 +1257,7 @@ declare function createContractRegistry(contracts: EventContract[]): ContractReg
|
|
|
931
1257
|
*
|
|
932
1258
|
* Versioned presentation-adapter contract. Hosts own canonical state and
|
|
933
1259
|
* push a render model; Cyberart presents it and emits interaction intents.
|
|
934
|
-
*
|
|
1260
|
+
* Host domain concepts stay in the host.
|
|
935
1261
|
*/
|
|
936
1262
|
|
|
937
1263
|
declare const PRESENTATION_ADAPTER_VERSION: 1;
|
|
@@ -946,7 +1272,7 @@ declare const PRESENTATION_PHASES: readonly ["loading", "ready", "error", "unsup
|
|
|
946
1272
|
type PresentationPhase = (typeof PRESENTATION_PHASES)[number];
|
|
947
1273
|
/**
|
|
948
1274
|
* Recommended router `subscribe` for a presentation cart. Intent type names
|
|
949
|
-
* are host-owned (`
|
|
1275
|
+
* are host-owned (`host.intent.*`); do not put domain objects in `target`.
|
|
950
1276
|
*/
|
|
951
1277
|
declare const PRESENTATION_SUBSCRIBE_PATTERNS: readonly ["presentation.state.*", "cyberart.diagnostic.rejected"];
|
|
952
1278
|
declare const INVALID_PRESENTATION_MODEL_MESSAGE = "Presentation adapter: model is invalid or not JSON-serializable";
|
|
@@ -1119,6 +1445,100 @@ declare function isCueLifecycleType(value: unknown): value is CueLifecycleType;
|
|
|
1119
1445
|
declare function applyCueEasing(t: number, easing: CueEasing): number;
|
|
1120
1446
|
declare function createPresentationTimeline(options?: CreatePresentationTimelineOptions): PresentationTimeline;
|
|
1121
1447
|
|
|
1448
|
+
/**
|
|
1449
|
+
* Copyright (c) 2026 Aaron Boyarsky
|
|
1450
|
+
* SPDX-License-Identifier: LicenseRef-CyberArt-Engine
|
|
1451
|
+
* See packages/engine/LICENSE
|
|
1452
|
+
*
|
|
1453
|
+
* Deterministic audio-cue timeline. Scheduling is frame-stepped via
|
|
1454
|
+
* `createPresentationTimeline`; PCM output is not part of the event trace.
|
|
1455
|
+
*/
|
|
1456
|
+
|
|
1457
|
+
declare const AUDIO_CUE_SCHEDULED_EVENT: "audio.cue.scheduled";
|
|
1458
|
+
declare const AUDIO_CUE_STARTED_EVENT: "audio.cue.started";
|
|
1459
|
+
declare const AUDIO_CUE_SKIPPED_EVENT: "audio.cue.skipped";
|
|
1460
|
+
declare const AUDIO_CUE_FAILED_EVENT: "audio.cue.failed";
|
|
1461
|
+
declare const AUDIO_CUE_EVENTS: readonly ["audio.cue.scheduled", "audio.cue.started", "audio.cue.skipped", "audio.cue.failed"];
|
|
1462
|
+
type AudioCueEventType = (typeof AUDIO_CUE_EVENTS)[number];
|
|
1463
|
+
type AudioCueSkipReason = 'reduced-sensory' | 'muted' | 'unauthorized';
|
|
1464
|
+
type AudioCueFailReason = 'asset-failed' | 'torn-down' | 'invalid';
|
|
1465
|
+
type AudioCueReason = AudioCueSkipReason | AudioCueFailReason;
|
|
1466
|
+
type AudioCueSpec = CueSpec & {
|
|
1467
|
+
assetId: string;
|
|
1468
|
+
channelId?: string;
|
|
1469
|
+
participantId?: string;
|
|
1470
|
+
priority?: number;
|
|
1471
|
+
gain?: number;
|
|
1472
|
+
};
|
|
1473
|
+
type AudioCueView = CueView & {
|
|
1474
|
+
assetId: string;
|
|
1475
|
+
channelId: string;
|
|
1476
|
+
participantId?: string;
|
|
1477
|
+
priority: number;
|
|
1478
|
+
audioPhase: 'scheduled' | 'started' | 'skipped' | 'failed' | 'completed';
|
|
1479
|
+
};
|
|
1480
|
+
type AudioCueEvent = {
|
|
1481
|
+
type: AudioCueEventType;
|
|
1482
|
+
atFrame: number;
|
|
1483
|
+
name: string;
|
|
1484
|
+
idempotencyKey: string;
|
|
1485
|
+
assetId: string;
|
|
1486
|
+
channelId: string;
|
|
1487
|
+
participantId?: string;
|
|
1488
|
+
reason?: AudioCueReason;
|
|
1489
|
+
progress: number;
|
|
1490
|
+
};
|
|
1491
|
+
type AudioCueTimelineSnapshot = {
|
|
1492
|
+
frame: number;
|
|
1493
|
+
reducedSensory: boolean;
|
|
1494
|
+
cues: AudioCueView[];
|
|
1495
|
+
events: AudioCueEvent[];
|
|
1496
|
+
};
|
|
1497
|
+
type PlayAudioCueResult = {
|
|
1498
|
+
ok: true;
|
|
1499
|
+
cue: AudioCueView;
|
|
1500
|
+
} | {
|
|
1501
|
+
ok: false;
|
|
1502
|
+
reason: 'duplicate' | 'invalid';
|
|
1503
|
+
detail: string;
|
|
1504
|
+
};
|
|
1505
|
+
type CreateAudioCueTimelineOptions = {
|
|
1506
|
+
broker?: AudioBroker;
|
|
1507
|
+
reducedSensory?: boolean;
|
|
1508
|
+
originFrame?: number;
|
|
1509
|
+
};
|
|
1510
|
+
type AudioCueTimeline = {
|
|
1511
|
+
play(spec: AudioCueSpec): PlayAudioCueResult;
|
|
1512
|
+
step(frames?: number): AudioCueEvent[];
|
|
1513
|
+
cancel(idempotencyKey: string): boolean;
|
|
1514
|
+
reset(): void;
|
|
1515
|
+
snapshot(): AudioCueTimelineSnapshot;
|
|
1516
|
+
get(idempotencyKey: string): AudioCueView | undefined;
|
|
1517
|
+
dispose(): void;
|
|
1518
|
+
readonly frame: number;
|
|
1519
|
+
readonly reducedSensory: boolean;
|
|
1520
|
+
};
|
|
1521
|
+
type HeadlessAudioAdapter = {
|
|
1522
|
+
readonly broker: AudioBroker;
|
|
1523
|
+
readonly timeline: AudioCueTimeline;
|
|
1524
|
+
unlock(): Promise<AudioUnlockStatus>;
|
|
1525
|
+
play(spec: AudioCueSpec): PlayAudioCueResult;
|
|
1526
|
+
step(frames?: number): AudioCueEvent[];
|
|
1527
|
+
handleHostEvent(event: HostEvent): void;
|
|
1528
|
+
snapshot(): AudioCueTimelineSnapshot & {
|
|
1529
|
+
unlock: AudioUnlockStatus;
|
|
1530
|
+
muted: boolean;
|
|
1531
|
+
};
|
|
1532
|
+
destroy(): void;
|
|
1533
|
+
};
|
|
1534
|
+
declare function isAudioCueEventType(value: unknown): value is AudioCueEventType;
|
|
1535
|
+
declare function createAudioCueTimeline(options?: CreateAudioCueTimelineOptions): AudioCueTimeline;
|
|
1536
|
+
declare function scheduleAudioCue(timeline: AudioCueTimeline, spec: AudioCueSpec): PlayAudioCueResult;
|
|
1537
|
+
declare function createHeadlessAudioAdapter(options?: {
|
|
1538
|
+
reducedSensory?: boolean;
|
|
1539
|
+
originFrame?: number;
|
|
1540
|
+
}): HeadlessAudioAdapter;
|
|
1541
|
+
|
|
1122
1542
|
/**
|
|
1123
1543
|
* Copyright (c) 2026 Aaron Boyarsky
|
|
1124
1544
|
* SPDX-License-Identifier: LicenseRef-CyberArt-Engine
|
|
@@ -1137,6 +1557,10 @@ declare const CAPABILITY_ASSET_KINDS: readonly ["image", "audio", "font", "sprit
|
|
|
1137
1557
|
type CapabilityAssetKind = (typeof CAPABILITY_ASSET_KINDS)[number];
|
|
1138
1558
|
declare const CAPABILITY_INTEGRATIONS: readonly ["tone", "midi"];
|
|
1139
1559
|
type CapabilityIntegration = (typeof CAPABILITY_INTEGRATIONS)[number];
|
|
1560
|
+
declare const CAPABILITY_BLEND_MODES: readonly ["source-over", "screen"];
|
|
1561
|
+
type CapabilityBlendMode = (typeof CAPABILITY_BLEND_MODES)[number];
|
|
1562
|
+
declare const CAPABILITY_CLEAR_POLICIES: readonly ["transparent", "opaque"];
|
|
1563
|
+
type CapabilityClearPolicy = (typeof CAPABILITY_CLEAR_POLICIES)[number];
|
|
1140
1564
|
type CapabilityDiagnostic = {
|
|
1141
1565
|
code: string;
|
|
1142
1566
|
detail: string;
|
|
@@ -1159,6 +1583,24 @@ type CapabilityPermissions = {
|
|
|
1159
1583
|
subscribe: string[];
|
|
1160
1584
|
authoritative?: boolean;
|
|
1161
1585
|
};
|
|
1586
|
+
/** Optional surface requirements. Omitted on existing manifests. */
|
|
1587
|
+
type CapabilitySurfaceRequirements = {
|
|
1588
|
+
alpha?: boolean;
|
|
1589
|
+
clearPolicy?: CapabilityClearPolicy;
|
|
1590
|
+
};
|
|
1591
|
+
/** Optional compositor/layer requirements. Omitted on existing manifests. */
|
|
1592
|
+
type CapabilityLayerRequirements = {
|
|
1593
|
+
compositor?: boolean;
|
|
1594
|
+
blend?: CapabilityBlendMode[];
|
|
1595
|
+
};
|
|
1596
|
+
/** Optional executable-module refs. Omitted on existing manifests. */
|
|
1597
|
+
type CapabilityModuleRef = {
|
|
1598
|
+
id: string;
|
|
1599
|
+
version: string;
|
|
1600
|
+
};
|
|
1601
|
+
type CapabilityModuleRequirements = {
|
|
1602
|
+
refs?: CapabilityModuleRef[];
|
|
1603
|
+
};
|
|
1162
1604
|
type CapabilityManifest = {
|
|
1163
1605
|
version: typeof CAPABILITY_MANIFEST_VERSION;
|
|
1164
1606
|
id: string;
|
|
@@ -1170,6 +1612,9 @@ type CapabilityManifest = {
|
|
|
1170
1612
|
emittedEvents: string[];
|
|
1171
1613
|
permissions: CapabilityPermissions;
|
|
1172
1614
|
integrations: CapabilityIntegration[];
|
|
1615
|
+
surface?: CapabilitySurfaceRequirements;
|
|
1616
|
+
layers?: CapabilityLayerRequirements;
|
|
1617
|
+
modules?: CapabilityModuleRequirements;
|
|
1173
1618
|
};
|
|
1174
1619
|
type CapabilityManifestInput = {
|
|
1175
1620
|
version?: number;
|
|
@@ -1182,6 +1627,9 @@ type CapabilityManifestInput = {
|
|
|
1182
1627
|
emittedEvents: string[];
|
|
1183
1628
|
permissions: CapabilityPermissions;
|
|
1184
1629
|
integrations: CapabilityIntegration[];
|
|
1630
|
+
surface?: CapabilitySurfaceRequirements;
|
|
1631
|
+
layers?: CapabilityLayerRequirements;
|
|
1632
|
+
modules?: CapabilityModuleRequirements;
|
|
1185
1633
|
};
|
|
1186
1634
|
type HostCapabilities = {
|
|
1187
1635
|
contractVersion: number;
|
|
@@ -1190,6 +1638,11 @@ type HostCapabilities = {
|
|
|
1190
1638
|
managers?: CapabilityManager[];
|
|
1191
1639
|
emit?: string[];
|
|
1192
1640
|
subscribe?: string[];
|
|
1641
|
+
surface?: CapabilitySurfaceRequirements & {
|
|
1642
|
+
clearPolicy?: CapabilityClearPolicy | CapabilityClearPolicy[];
|
|
1643
|
+
};
|
|
1644
|
+
layers?: CapabilityLayerRequirements;
|
|
1645
|
+
modules?: CapabilityModuleRequirements;
|
|
1193
1646
|
};
|
|
1194
1647
|
type DefineCapabilityManifestResult = {
|
|
1195
1648
|
ok: true;
|
|
@@ -1440,6 +1893,10 @@ type CreateRuntimeGroupOptions = {
|
|
|
1440
1893
|
now?: () => number;
|
|
1441
1894
|
/** Extra router options. Group injects shared `createId` / `now` unless set here. */
|
|
1442
1895
|
router?: EventRouterOptions;
|
|
1896
|
+
/** Bound on the accepted-event trace (oldest dropped). Default 1024. */
|
|
1897
|
+
maxTrace?: number;
|
|
1898
|
+
/** Shared page-level audio unlock broker. Optional. */
|
|
1899
|
+
audioBroker?: AudioBroker;
|
|
1443
1900
|
};
|
|
1444
1901
|
type RuntimeGroupParticipantInspect = {
|
|
1445
1902
|
state: unknown;
|
|
@@ -1447,6 +1904,9 @@ type RuntimeGroupParticipantInspect = {
|
|
|
1447
1904
|
errors: RuntimeGroupFrameError[];
|
|
1448
1905
|
kind: RuntimeGroupKind;
|
|
1449
1906
|
clock: ClockSnapshot;
|
|
1907
|
+
emit: string[];
|
|
1908
|
+
subscribe: string[];
|
|
1909
|
+
authoritative: boolean;
|
|
1450
1910
|
};
|
|
1451
1911
|
type RuntimeGroupDiagnostics = {
|
|
1452
1912
|
paused: boolean;
|
|
@@ -1472,16 +1932,691 @@ type RuntimeGroup = {
|
|
|
1472
1932
|
readonly router: EventRouter;
|
|
1473
1933
|
readonly origin: number;
|
|
1474
1934
|
readonly paused: boolean;
|
|
1935
|
+
readonly audioBroker: AudioBroker | undefined;
|
|
1475
1936
|
participant(id: string): RuntimeGroupParticipantHandle;
|
|
1476
1937
|
step(frames?: number): Promise<void>;
|
|
1477
1938
|
pause(): void;
|
|
1478
1939
|
resume(): void;
|
|
1479
1940
|
reset(): void;
|
|
1941
|
+
/** Shared viewport. Sets each container and canvas buffer size. Does not clear sibling pixels on detach. */
|
|
1942
|
+
resize(width: number, height: number): void;
|
|
1943
|
+
/** Tear down one participant without destroying the group or blanking siblings. */
|
|
1944
|
+
detach(id: string): void;
|
|
1480
1945
|
dispatch(participantId: string, event: HostEvent): void;
|
|
1481
1946
|
publish(event: EventInput, extras?: PublishExtras): EventEnvelope | undefined;
|
|
1947
|
+
inspectParticipants(): Array<RouterParticipantInspect & {
|
|
1948
|
+
kind: RuntimeGroupKind;
|
|
1949
|
+
}>;
|
|
1482
1950
|
inspect(): Promise<RuntimeGroupInspect>;
|
|
1483
1951
|
destroy(): void;
|
|
1484
1952
|
};
|
|
1485
1953
|
declare function createRuntimeGroup(options: CreateRuntimeGroupOptions): RuntimeGroup;
|
|
1486
1954
|
|
|
1487
|
-
|
|
1955
|
+
declare const REPLAY_INSPECTOR_SCHEMA_VERSION: 1;
|
|
1956
|
+
declare const DEFAULT_MAX_INSPECTOR_RECORDS = 512;
|
|
1957
|
+
declare const REDACTED_VALUE = "[REDACTED]";
|
|
1958
|
+
type ReplayTraceFilter = {
|
|
1959
|
+
types?: string[];
|
|
1960
|
+
sources?: string[];
|
|
1961
|
+
outcomes?: RouterDecisionOutcome[];
|
|
1962
|
+
correlationId?: string;
|
|
1963
|
+
};
|
|
1964
|
+
type CreateReplayInspectorOptions = {
|
|
1965
|
+
redactedKeys?: string[];
|
|
1966
|
+
maxRecords?: number;
|
|
1967
|
+
/** Optional contracts so records can include payload schema version. */
|
|
1968
|
+
registry?: Pick<ContractRegistry, 'get'>;
|
|
1969
|
+
};
|
|
1970
|
+
type InspectorRecord = {
|
|
1971
|
+
index: number;
|
|
1972
|
+
turn: number;
|
|
1973
|
+
time: number;
|
|
1974
|
+
outcome: RouterDecisionOutcome;
|
|
1975
|
+
reason?: RouterDecisionReason;
|
|
1976
|
+
detail?: string;
|
|
1977
|
+
source: string;
|
|
1978
|
+
target?: string;
|
|
1979
|
+
type: string;
|
|
1980
|
+
kind?: EventKind;
|
|
1981
|
+
envelopeId?: string;
|
|
1982
|
+
priorEnvelopeId?: string;
|
|
1983
|
+
correlationId?: string;
|
|
1984
|
+
causationId?: string;
|
|
1985
|
+
hops?: number;
|
|
1986
|
+
seq?: number;
|
|
1987
|
+
idempotencyKey?: string;
|
|
1988
|
+
schemaVersion?: number;
|
|
1989
|
+
payloadSchemaVersion?: number;
|
|
1990
|
+
deliveredTo: string[];
|
|
1991
|
+
payload?: unknown;
|
|
1992
|
+
};
|
|
1993
|
+
type CausationTreeNode = {
|
|
1994
|
+
envelopeId?: string;
|
|
1995
|
+
type: string;
|
|
1996
|
+
source: string;
|
|
1997
|
+
outcome: RouterDecisionOutcome;
|
|
1998
|
+
reason?: RouterDecisionReason;
|
|
1999
|
+
children: CausationTreeNode[];
|
|
2000
|
+
};
|
|
2001
|
+
type ReplayParticipantSummary = {
|
|
2002
|
+
id: string;
|
|
2003
|
+
kind?: RuntimeGroupKind;
|
|
2004
|
+
emit: string[];
|
|
2005
|
+
subscribe: string[];
|
|
2006
|
+
authoritative: boolean;
|
|
2007
|
+
seed?: string;
|
|
2008
|
+
clock?: ClockSnapshot;
|
|
2009
|
+
state?: unknown;
|
|
2010
|
+
errorCount: number;
|
|
2011
|
+
lastError?: string;
|
|
2012
|
+
};
|
|
2013
|
+
type ReplayInspectorReport = {
|
|
2014
|
+
schemaVersion: typeof REPLAY_INSPECTOR_SCHEMA_VERSION;
|
|
2015
|
+
participants: ReplayParticipantSummary[];
|
|
2016
|
+
records: InspectorRecord[];
|
|
2017
|
+
trees: CausationTreeNode[];
|
|
2018
|
+
dropped: number;
|
|
2019
|
+
};
|
|
2020
|
+
type ReplayTapeAction = {
|
|
2021
|
+
kind: 'publish';
|
|
2022
|
+
event: EventInput;
|
|
2023
|
+
extras?: PublishExtras;
|
|
2024
|
+
} | {
|
|
2025
|
+
kind: 'dispatch';
|
|
2026
|
+
participantId: string;
|
|
2027
|
+
event: HostEvent;
|
|
2028
|
+
} | {
|
|
2029
|
+
kind: 'step';
|
|
2030
|
+
frames: number;
|
|
2031
|
+
} | {
|
|
2032
|
+
kind: 'asset';
|
|
2033
|
+
participantId: string;
|
|
2034
|
+
event: HostEvent;
|
|
2035
|
+
};
|
|
2036
|
+
type ReplayInspectorExport = {
|
|
2037
|
+
schemaVersion: typeof REPLAY_INSPECTOR_SCHEMA_VERSION;
|
|
2038
|
+
origin: number;
|
|
2039
|
+
redactedKeys: string[];
|
|
2040
|
+
participants: ReplayParticipantSummary[];
|
|
2041
|
+
tape: ReplayTapeAction[];
|
|
2042
|
+
records: InspectorRecord[];
|
|
2043
|
+
snapshots: Record<string, unknown>;
|
|
2044
|
+
};
|
|
2045
|
+
type ReplayCompareResult = {
|
|
2046
|
+
ok: true;
|
|
2047
|
+
} | {
|
|
2048
|
+
ok: false;
|
|
2049
|
+
detail: string;
|
|
2050
|
+
};
|
|
2051
|
+
type BoundReplaySession = {
|
|
2052
|
+
publish(event: EventInput, extras?: PublishExtras): EventEnvelope | undefined;
|
|
2053
|
+
dispatch(participantId: string, event: HostEvent): void;
|
|
2054
|
+
step(frames?: number): Promise<void>;
|
|
2055
|
+
report(): Promise<ReplayInspectorReport>;
|
|
2056
|
+
exportTrace(filter?: ReplayTraceFilter): Promise<ReplayInspectorExport>;
|
|
2057
|
+
unbind(): void;
|
|
2058
|
+
};
|
|
2059
|
+
type ReplayInspector = {
|
|
2060
|
+
watchRouter(router: EventRouter): () => void;
|
|
2061
|
+
bind(group: RuntimeGroup): BoundReplaySession;
|
|
2062
|
+
importTrace(exported: ReplayInspectorExport | string): void;
|
|
2063
|
+
exportTrace(filter?: ReplayTraceFilter): ReplayInspectorExport;
|
|
2064
|
+
report(filter?: ReplayTraceFilter): ReplayInspectorReport;
|
|
2065
|
+
causationTree(correlationId?: string): CausationTreeNode[];
|
|
2066
|
+
records(): InspectorRecord[];
|
|
2067
|
+
reset(): void;
|
|
2068
|
+
destroy(): void;
|
|
2069
|
+
};
|
|
2070
|
+
declare function compareReplayTraces(expected: InspectorRecord[], actual: InspectorRecord[]): ReplayCompareResult;
|
|
2071
|
+
declare function createReplayInspector(options?: CreateReplayInspectorOptions): ReplayInspector;
|
|
2072
|
+
declare function replayExportedTrace(exported: ReplayInspectorExport, group: RuntimeGroup, options?: CreateReplayInspectorOptions): Promise<{
|
|
2073
|
+
inspector: ReplayInspector;
|
|
2074
|
+
report: ReplayInspectorReport;
|
|
2075
|
+
}>;
|
|
2076
|
+
|
|
2077
|
+
declare const COMPOSITOR_BLEND_MODES: readonly ["source-over", "screen"];
|
|
2078
|
+
type CompositorBlendMode = (typeof COMPOSITOR_BLEND_MODES)[number];
|
|
2079
|
+
declare const COMPOSITOR_CLEAR_POLICIES: readonly ["transparent", "opaque"];
|
|
2080
|
+
type CompositorClearPolicy = (typeof COMPOSITOR_CLEAR_POLICIES)[number];
|
|
2081
|
+
type CompositorPointerEvents = 'auto' | 'none';
|
|
2082
|
+
type CompositorClip = {
|
|
2083
|
+
x: number;
|
|
2084
|
+
y: number;
|
|
2085
|
+
width: number;
|
|
2086
|
+
height: number;
|
|
2087
|
+
};
|
|
2088
|
+
type CompositorLayerConfig = {
|
|
2089
|
+
id: string;
|
|
2090
|
+
order: number;
|
|
2091
|
+
visible?: boolean;
|
|
2092
|
+
opacity?: number;
|
|
2093
|
+
blend?: CompositorBlendMode;
|
|
2094
|
+
clip?: CompositorClip;
|
|
2095
|
+
pointerEvents?: CompositorPointerEvents;
|
|
2096
|
+
clearPolicy?: CompositorClearPolicy;
|
|
2097
|
+
};
|
|
2098
|
+
type CompositorLayerInspect = {
|
|
2099
|
+
id: string;
|
|
2100
|
+
order: number;
|
|
2101
|
+
visible: boolean;
|
|
2102
|
+
opacity: number;
|
|
2103
|
+
blend: CompositorBlendMode;
|
|
2104
|
+
clip: CompositorClip | null;
|
|
2105
|
+
pointerEvents: CompositorPointerEvents;
|
|
2106
|
+
clearPolicy: CompositorClearPolicy;
|
|
2107
|
+
};
|
|
2108
|
+
type CompositorHostOptions = {
|
|
2109
|
+
/** Back-layer pixels. Scaled nearest-neighbor to the compositor viewport. */
|
|
2110
|
+
image?: ImageData;
|
|
2111
|
+
/** Opaque CSS `#rgb` / `#rrggbb` fill when `image` is omitted. */
|
|
2112
|
+
color?: string;
|
|
2113
|
+
};
|
|
2114
|
+
type CreateCompositorOptions = {
|
|
2115
|
+
group: RuntimeGroup;
|
|
2116
|
+
layers: CompositorLayerConfig[];
|
|
2117
|
+
width?: number;
|
|
2118
|
+
height?: number;
|
|
2119
|
+
dpr?: number;
|
|
2120
|
+
host?: CompositorHostOptions;
|
|
2121
|
+
/**
|
|
2122
|
+
* Host surface clear. Default `transparent` — never fill black.
|
|
2123
|
+
* Per-layer `clearPolicy: 'transparent'` knocks out RGB 0,0,0 backing
|
|
2124
|
+
* pixels so opaque cart canvases can stack over a host image.
|
|
2125
|
+
*/
|
|
2126
|
+
clearPolicy?: CompositorClearPolicy;
|
|
2127
|
+
/**
|
|
2128
|
+
* When true (default), compose into a compositor-owned canvas.
|
|
2129
|
+
* When false, require `target` and draw there.
|
|
2130
|
+
*/
|
|
2131
|
+
offscreen?: boolean;
|
|
2132
|
+
target?: HTMLCanvasElement;
|
|
2133
|
+
};
|
|
2134
|
+
type ComposedFrame = {
|
|
2135
|
+
imageData: ImageData;
|
|
2136
|
+
pngDataUrl: string;
|
|
2137
|
+
width: number;
|
|
2138
|
+
height: number;
|
|
2139
|
+
declaredOrder: CompositorLayerInspect[];
|
|
2140
|
+
};
|
|
2141
|
+
type CompositorInspect = {
|
|
2142
|
+
viewport: {
|
|
2143
|
+
width: number;
|
|
2144
|
+
height: number;
|
|
2145
|
+
dpr: number;
|
|
2146
|
+
};
|
|
2147
|
+
clearPolicy: CompositorClearPolicy;
|
|
2148
|
+
layers: CompositorLayerInspect[];
|
|
2149
|
+
declaredOrder: string[];
|
|
2150
|
+
};
|
|
2151
|
+
type Compositor = {
|
|
2152
|
+
readonly canvas: HTMLCanvasElement;
|
|
2153
|
+
readonly width: number;
|
|
2154
|
+
readonly height: number;
|
|
2155
|
+
readonly dpr: number;
|
|
2156
|
+
compose(): ImageData;
|
|
2157
|
+
captureComposedFrame(): ComposedFrame;
|
|
2158
|
+
/**
|
|
2159
|
+
* Shared CSS viewport. Updates group canvas buffer size (`width * dpr`).
|
|
2160
|
+
* Layer order/blend survive. Carts that cache layout from `DimensionContext`
|
|
2161
|
+
* need `group.reset()` (or remount) so they rebuild at the new size.
|
|
2162
|
+
*/
|
|
2163
|
+
resize(width: number, height: number, dpr?: number): void;
|
|
2164
|
+
setLayer(id: string, patch: Partial<Omit<CompositorLayerConfig, 'id'>>): void;
|
|
2165
|
+
layer(id: string): CompositorLayerInspect;
|
|
2166
|
+
layers(): CompositorLayerInspect[];
|
|
2167
|
+
pointerTarget(x: number, y: number): string | undefined;
|
|
2168
|
+
unmountLayer(id: string): void;
|
|
2169
|
+
inspect(): CompositorInspect;
|
|
2170
|
+
destroy(): void;
|
|
2171
|
+
};
|
|
2172
|
+
declare function createCompositor(options: CreateCompositorOptions): Compositor;
|
|
2173
|
+
|
|
2174
|
+
/**
|
|
2175
|
+
* Copyright (c) 2026 Aaron Boyarsky
|
|
2176
|
+
* SPDX-License-Identifier: LicenseRef-CyberArt-Engine
|
|
2177
|
+
* See packages/engine/LICENSE
|
|
2178
|
+
*
|
|
2179
|
+
* Trusted, versioned executable-module host. Factories are registered by
|
|
2180
|
+
* exact id+version; the host allowlists which refs may load. Untrusted
|
|
2181
|
+
* source strings are not compiled. Per-module failures do not stop siblings.
|
|
2182
|
+
*/
|
|
2183
|
+
declare const EXECUTABLE_MODULE_ERROR_CODES: readonly ["invalid-ref", "unknown-module", "version-mismatch", "not-allowlisted", "load-failed", "invoke-failed", "timeout", "rate-limited", "destroyed"];
|
|
2184
|
+
type ExecutableModuleErrorCode = (typeof EXECUTABLE_MODULE_ERROR_CODES)[number];
|
|
2185
|
+
type ExecutableModuleRef = {
|
|
2186
|
+
id: string;
|
|
2187
|
+
version: string;
|
|
2188
|
+
};
|
|
2189
|
+
type ExecutableModuleError = {
|
|
2190
|
+
code: ExecutableModuleErrorCode;
|
|
2191
|
+
detail: string;
|
|
2192
|
+
ref?: ExecutableModuleRef;
|
|
2193
|
+
};
|
|
2194
|
+
type ExecutableModuleDiagnostic = ExecutableModuleError;
|
|
2195
|
+
type ExecutableModuleCapabilities = {
|
|
2196
|
+
readonly [key: string]: unknown;
|
|
2197
|
+
};
|
|
2198
|
+
type ExecutableModuleInvokeContext = {
|
|
2199
|
+
signal: AbortSignal;
|
|
2200
|
+
turn: number;
|
|
2201
|
+
};
|
|
2202
|
+
type ExecutableModuleInstance = {
|
|
2203
|
+
invoke(input: unknown, context: ExecutableModuleInvokeContext): unknown | Promise<unknown>;
|
|
2204
|
+
destroy?: () => void;
|
|
2205
|
+
};
|
|
2206
|
+
type ExecutableModuleFactory = (capabilities: ExecutableModuleCapabilities) => ExecutableModuleInstance;
|
|
2207
|
+
type ExecutableModuleRegistration = {
|
|
2208
|
+
id: string;
|
|
2209
|
+
version: string;
|
|
2210
|
+
create: ExecutableModuleFactory;
|
|
2211
|
+
capabilities?: ExecutableModuleCapabilities;
|
|
2212
|
+
};
|
|
2213
|
+
type ExecutableModuleLimits = {
|
|
2214
|
+
/** Cooperative timeout; the invoke AbortSignal aborts after this many ms. */
|
|
2215
|
+
maxInvokeMs?: number;
|
|
2216
|
+
maxInvokesPerTurn?: number;
|
|
2217
|
+
};
|
|
2218
|
+
type CreateExecutableModuleHostOptions = {
|
|
2219
|
+
allowlist: readonly ExecutableModuleRef[];
|
|
2220
|
+
modules: readonly ExecutableModuleRegistration[];
|
|
2221
|
+
limits?: ExecutableModuleLimits;
|
|
2222
|
+
/** Default capability bag. Frozen per module; class instances stay shared handles. */
|
|
2223
|
+
capabilities?: ExecutableModuleCapabilities;
|
|
2224
|
+
};
|
|
2225
|
+
type ExecutableModuleInvokeResult = {
|
|
2226
|
+
ok: true;
|
|
2227
|
+
value: unknown;
|
|
2228
|
+
} | {
|
|
2229
|
+
ok: false;
|
|
2230
|
+
error: ExecutableModuleError;
|
|
2231
|
+
};
|
|
2232
|
+
type ExecutableModuleLoadResult = {
|
|
2233
|
+
ok: true;
|
|
2234
|
+
ref: ExecutableModuleRef;
|
|
2235
|
+
} | {
|
|
2236
|
+
ok: false;
|
|
2237
|
+
error: ExecutableModuleError;
|
|
2238
|
+
};
|
|
2239
|
+
type ExecutableModuleHostInspect = {
|
|
2240
|
+
allowlist: ExecutableModuleRef[];
|
|
2241
|
+
registered: ExecutableModuleRef[];
|
|
2242
|
+
loaded: ExecutableModuleRef[];
|
|
2243
|
+
turn: number;
|
|
2244
|
+
invokesThisTurn: number;
|
|
2245
|
+
diagnostics: ExecutableModuleDiagnostic[];
|
|
2246
|
+
};
|
|
2247
|
+
type ExecutableModuleHost = {
|
|
2248
|
+
load(ref: ExecutableModuleRef): ExecutableModuleLoadResult;
|
|
2249
|
+
invoke(ref: ExecutableModuleRef, input?: unknown): Promise<ExecutableModuleInvokeResult>;
|
|
2250
|
+
beginTurn(): void;
|
|
2251
|
+
inspect(): ExecutableModuleHostInspect;
|
|
2252
|
+
destroy(): void;
|
|
2253
|
+
};
|
|
2254
|
+
declare function createExecutableModuleHost(options: CreateExecutableModuleHostOptions): ExecutableModuleHost;
|
|
2255
|
+
|
|
2256
|
+
/**
|
|
2257
|
+
* Copyright (c) 2026 Aaron Boyarsky
|
|
2258
|
+
* SPDX-License-Identifier: LicenseRef-CyberArt-Engine
|
|
2259
|
+
* See packages/engine/LICENSE
|
|
2260
|
+
*
|
|
2261
|
+
* Opt-in DOM/browser host harness. Mounts a caller-supplied host into a
|
|
2262
|
+
* viewport, optionally wires a runtime group and compositor, and dispatches
|
|
2263
|
+
* pointer/keyboard through layout coordinates. Does not import Node built-ins
|
|
2264
|
+
* and does not encode host-product event types or fixtures.
|
|
2265
|
+
*/
|
|
2266
|
+
|
|
2267
|
+
declare const DEFAULT_BROWSER_VIEWPORT: {
|
|
2268
|
+
readonly width: 320;
|
|
2269
|
+
readonly height: 180;
|
|
2270
|
+
readonly deviceScaleFactor: 1;
|
|
2271
|
+
};
|
|
2272
|
+
type BrowserInputModality = 'pointer' | 'keyboard' | 'touch';
|
|
2273
|
+
type BrowserViewport = {
|
|
2274
|
+
width: number;
|
|
2275
|
+
height: number;
|
|
2276
|
+
deviceScaleFactor?: number;
|
|
2277
|
+
};
|
|
2278
|
+
type BrowserHarnessAction = {
|
|
2279
|
+
type: 'viewport';
|
|
2280
|
+
width: number;
|
|
2281
|
+
height: number;
|
|
2282
|
+
dpr: number;
|
|
2283
|
+
} | {
|
|
2284
|
+
type: 'click';
|
|
2285
|
+
x: number;
|
|
2286
|
+
y: number;
|
|
2287
|
+
selector?: string;
|
|
2288
|
+
} | {
|
|
2289
|
+
type: 'key';
|
|
2290
|
+
key: string;
|
|
2291
|
+
} | {
|
|
2292
|
+
type: 'step';
|
|
2293
|
+
frames: number;
|
|
2294
|
+
} | {
|
|
2295
|
+
type: 'advance';
|
|
2296
|
+
ms: number;
|
|
2297
|
+
} | {
|
|
2298
|
+
type: 'reducedMotion';
|
|
2299
|
+
value: boolean;
|
|
2300
|
+
} | {
|
|
2301
|
+
type: 'inputModality';
|
|
2302
|
+
value: BrowserInputModality;
|
|
2303
|
+
};
|
|
2304
|
+
type BrowserHarnessScreenshot = {
|
|
2305
|
+
imageData: ImageData | null;
|
|
2306
|
+
pngDataUrl: string | null;
|
|
2307
|
+
html: string;
|
|
2308
|
+
declaredOrder: string[];
|
|
2309
|
+
};
|
|
2310
|
+
type BrowserA11ySnapshot = {
|
|
2311
|
+
focus: {
|
|
2312
|
+
tag: string;
|
|
2313
|
+
id: string;
|
|
2314
|
+
role: string | null;
|
|
2315
|
+
name: string;
|
|
2316
|
+
};
|
|
2317
|
+
live: string;
|
|
2318
|
+
html: string;
|
|
2319
|
+
};
|
|
2320
|
+
type BrowserReproductionMetadata = {
|
|
2321
|
+
seed: string;
|
|
2322
|
+
viewport: {
|
|
2323
|
+
width: number;
|
|
2324
|
+
height: number;
|
|
2325
|
+
dpr: number;
|
|
2326
|
+
};
|
|
2327
|
+
reducedMotion: boolean;
|
|
2328
|
+
inputModality: BrowserInputModality;
|
|
2329
|
+
actions: BrowserHarnessAction[];
|
|
2330
|
+
};
|
|
2331
|
+
type BrowserCompositorConfig = Omit<CreateCompositorOptions, 'group' | 'width' | 'height' | 'dpr'>;
|
|
2332
|
+
type BrowserHarnessMountContext = {
|
|
2333
|
+
root: HTMLElement;
|
|
2334
|
+
layout: PresentationLayout;
|
|
2335
|
+
reducedMotion: boolean;
|
|
2336
|
+
inputModality: BrowserInputModality;
|
|
2337
|
+
placeRegion(id: string, element: HTMLElement): PixelRect | undefined;
|
|
2338
|
+
};
|
|
2339
|
+
type BrowserHarnessRuntimeContext = BrowserHarnessMountContext & {
|
|
2340
|
+
group: RuntimeGroup | undefined;
|
|
2341
|
+
compositor: Compositor | undefined;
|
|
2342
|
+
publish(event: EventInput): EventEnvelope | undefined;
|
|
2343
|
+
};
|
|
2344
|
+
type BrowserHostSession = {
|
|
2345
|
+
participants?: RuntimeGroupParticipantConfig[];
|
|
2346
|
+
compositor?: BrowserCompositorConfig;
|
|
2347
|
+
hostState?: () => unknown;
|
|
2348
|
+
ready?: (ctx: BrowserHarnessRuntimeContext) => void;
|
|
2349
|
+
relayout?: (ctx: BrowserHarnessRuntimeContext) => void;
|
|
2350
|
+
destroy?: () => void;
|
|
2351
|
+
};
|
|
2352
|
+
type CreateBrowserHarnessOptions = {
|
|
2353
|
+
seed?: string;
|
|
2354
|
+
viewport?: BrowserViewport;
|
|
2355
|
+
reducedMotion?: boolean;
|
|
2356
|
+
inputModality?: BrowserInputModality;
|
|
2357
|
+
origin?: number;
|
|
2358
|
+
createId?: () => string;
|
|
2359
|
+
geometry?: GeometryDocument;
|
|
2360
|
+
contentWidth?: number;
|
|
2361
|
+
contentHeight?: number;
|
|
2362
|
+
fit?: PresentationFitMode;
|
|
2363
|
+
mount?: (ctx: BrowserHarnessMountContext) => BrowserHostSession | void;
|
|
2364
|
+
};
|
|
2365
|
+
type BrowserHarnessInspect = {
|
|
2366
|
+
host: unknown;
|
|
2367
|
+
layout: PresentationLayout;
|
|
2368
|
+
events: EventEnvelope[];
|
|
2369
|
+
participantEvents: Record<string, HostEvent[]>;
|
|
2370
|
+
state: Record<string, unknown>;
|
|
2371
|
+
focus: BrowserA11ySnapshot['focus'];
|
|
2372
|
+
scrollTop: number;
|
|
2373
|
+
clock: {
|
|
2374
|
+
framesElapsed: number;
|
|
2375
|
+
};
|
|
2376
|
+
};
|
|
2377
|
+
type BrowserHarness = {
|
|
2378
|
+
readonly root: HTMLElement;
|
|
2379
|
+
readonly group: RuntimeGroup | undefined;
|
|
2380
|
+
readonly compositor: Compositor | undefined;
|
|
2381
|
+
readonly layout: PresentationLayout;
|
|
2382
|
+
readonly events: readonly EventEnvelope[];
|
|
2383
|
+
goto(url?: string): void;
|
|
2384
|
+
setViewport(width: number, height: number, dpr?: number): void;
|
|
2385
|
+
setReducedMotion(value: boolean): void;
|
|
2386
|
+
setInputModality(value: BrowserInputModality): void;
|
|
2387
|
+
click(selectorOrX: string | number, y?: number): void;
|
|
2388
|
+
key(key: string): void;
|
|
2389
|
+
focus(selector: string): void;
|
|
2390
|
+
step(frames?: number): Promise<void>;
|
|
2391
|
+
advance(ms: number): Promise<void>;
|
|
2392
|
+
screenshot(): BrowserHarnessScreenshot;
|
|
2393
|
+
accessibilitySnapshot(): BrowserA11ySnapshot;
|
|
2394
|
+
inspect(): Promise<BrowserHarnessInspect>;
|
|
2395
|
+
reproduction(): BrowserReproductionMetadata;
|
|
2396
|
+
captureComposedFrame(): ComposedFrame;
|
|
2397
|
+
destroy(): void;
|
|
2398
|
+
};
|
|
2399
|
+
declare function createBrowserHarness(options?: CreateBrowserHarnessOptions): BrowserHarness;
|
|
2400
|
+
|
|
2401
|
+
/**
|
|
2402
|
+
* Copyright (c) 2026 Aaron Boyarsky
|
|
2403
|
+
* SPDX-License-Identifier: LicenseRef-CyberArt-Engine
|
|
2404
|
+
* See packages/engine/LICENSE
|
|
2405
|
+
*
|
|
2406
|
+
* Playwright-shaped adapter over `createBrowserHarness`. Same method names as
|
|
2407
|
+
* a Playwright `Page` (`goto`, `setViewportSize`, `click`, `screenshot`) so CI
|
|
2408
|
+
* can swap engines later without `@playwright/test` as an engine dependency.
|
|
2409
|
+
*/
|
|
2410
|
+
|
|
2411
|
+
type PlaywrightCompatibleViewport = {
|
|
2412
|
+
width: number;
|
|
2413
|
+
height: number;
|
|
2414
|
+
deviceScaleFactor?: number;
|
|
2415
|
+
};
|
|
2416
|
+
type PlaywrightCompatibleAdapter = {
|
|
2417
|
+
goto(url?: string): Promise<void>;
|
|
2418
|
+
setViewportSize(viewport: PlaywrightCompatibleViewport): Promise<void>;
|
|
2419
|
+
click(selector: string): Promise<void>;
|
|
2420
|
+
screenshot(): Promise<BrowserHarnessScreenshot>;
|
|
2421
|
+
keyboard: {
|
|
2422
|
+
press(key: string): Promise<void>;
|
|
2423
|
+
};
|
|
2424
|
+
locator(selector: string): {
|
|
2425
|
+
click(): Promise<void>;
|
|
2426
|
+
focus(): Promise<void>;
|
|
2427
|
+
};
|
|
2428
|
+
close(): Promise<void>;
|
|
2429
|
+
};
|
|
2430
|
+
declare function createPlaywrightCompatibleAdapter(harness: BrowserHarness): PlaywrightCompatibleAdapter;
|
|
2431
|
+
|
|
2432
|
+
/**
|
|
2433
|
+
* Copyright (c) 2026 Aaron Boyarsky
|
|
2434
|
+
* SPDX-License-Identifier: LicenseRef-CyberArt-Engine
|
|
2435
|
+
* See packages/engine/LICENSE
|
|
2436
|
+
*
|
|
2437
|
+
* Host-owned MIDI controller I/O. Carts and hosts construct MidiManager;
|
|
2438
|
+
* the runtime does not pass it into getDefaultState. Live Web MIDI is
|
|
2439
|
+
* optional — inject and send work in headless/jsdom through a test port.
|
|
2440
|
+
*/
|
|
2441
|
+
/** Note Off command nibble (status = this | channel). */
|
|
2442
|
+
declare const MIDI_NOTE_OFF = 128;
|
|
2443
|
+
/** Note On command nibble (status = this | channel). */
|
|
2444
|
+
declare const MIDI_NOTE_ON = 144;
|
|
2445
|
+
/** Control Change command nibble (status = this | channel). */
|
|
2446
|
+
declare const MIDI_CONTROL_CHANGE = 176;
|
|
2447
|
+
/** Pitch Bend command nibble (status = this | channel). */
|
|
2448
|
+
declare const MIDI_PITCH_BEND = 224;
|
|
2449
|
+
declare const MIDI_CHANNEL_MIN = 0;
|
|
2450
|
+
declare const MIDI_CHANNEL_MAX = 15;
|
|
2451
|
+
declare const MIDI_DATA_MAX = 127;
|
|
2452
|
+
declare const MIDI_PITCH_CENTER = 8192;
|
|
2453
|
+
declare const MIDI_PITCH_MAX = 16383;
|
|
2454
|
+
/** Channel index 0–15 (MIDI channels 1–16). */
|
|
2455
|
+
type MidiChannel = number;
|
|
2456
|
+
/** Channel-voice status byte: command in the high nibble, channel 0–15 in the low. */
|
|
2457
|
+
type MidiStatusByte = number;
|
|
2458
|
+
type MidiNoteMessage = {
|
|
2459
|
+
kind: 'noteon' | 'noteoff';
|
|
2460
|
+
channel: number;
|
|
2461
|
+
note: number;
|
|
2462
|
+
velocity: number;
|
|
2463
|
+
status: MidiStatusByte;
|
|
2464
|
+
data: Uint8Array;
|
|
2465
|
+
};
|
|
2466
|
+
type MidiCcMessage = {
|
|
2467
|
+
kind: 'cc';
|
|
2468
|
+
channel: number;
|
|
2469
|
+
controller: number;
|
|
2470
|
+
value: number;
|
|
2471
|
+
status: MidiStatusByte;
|
|
2472
|
+
data: Uint8Array;
|
|
2473
|
+
};
|
|
2474
|
+
type MidiPitchMessage = {
|
|
2475
|
+
kind: 'pitch';
|
|
2476
|
+
channel: number;
|
|
2477
|
+
/** 14-bit pitch bend, 0–16383. Center is 8192. */
|
|
2478
|
+
value: number;
|
|
2479
|
+
status: MidiStatusByte;
|
|
2480
|
+
data: Uint8Array;
|
|
2481
|
+
};
|
|
2482
|
+
type MidiRawMessage = {
|
|
2483
|
+
kind: 'raw';
|
|
2484
|
+
channel?: number;
|
|
2485
|
+
status: MidiStatusByte;
|
|
2486
|
+
data: Uint8Array;
|
|
2487
|
+
};
|
|
2488
|
+
type MidiMessage = MidiNoteMessage | MidiCcMessage | MidiPitchMessage | MidiRawMessage;
|
|
2489
|
+
type MidiVoiceInput = {
|
|
2490
|
+
kind: 'noteon' | 'noteoff';
|
|
2491
|
+
channel: number;
|
|
2492
|
+
note: number;
|
|
2493
|
+
velocity?: number;
|
|
2494
|
+
} | {
|
|
2495
|
+
kind: 'cc';
|
|
2496
|
+
channel: number;
|
|
2497
|
+
controller: number;
|
|
2498
|
+
value: number;
|
|
2499
|
+
} | {
|
|
2500
|
+
kind: 'pitch';
|
|
2501
|
+
channel: number;
|
|
2502
|
+
value: number;
|
|
2503
|
+
};
|
|
2504
|
+
type MidiInjectInput = MidiVoiceInput | MidiMessage | Uint8Array | readonly number[];
|
|
2505
|
+
type MidiSubscribeKind = 'note' | 'cc' | 'pitch' | 'raw' | '*';
|
|
2506
|
+
type MidiSubscribeListener = (message: MidiMessage) => void;
|
|
2507
|
+
type MidiOutputPort = {
|
|
2508
|
+
send(data: number[], timestamp?: number): void;
|
|
2509
|
+
};
|
|
2510
|
+
type MidiInputLike = {
|
|
2511
|
+
addEventListener(type: string, listener: (event: Event | {
|
|
2512
|
+
data?: Uint8Array | null;
|
|
2513
|
+
}) => void): void;
|
|
2514
|
+
removeEventListener(type: string, listener: (event: Event | {
|
|
2515
|
+
data?: Uint8Array | null;
|
|
2516
|
+
}) => void): void;
|
|
2517
|
+
};
|
|
2518
|
+
type MidiAccessLike = {
|
|
2519
|
+
readonly inputs: {
|
|
2520
|
+
forEach(callback: (input: MidiInputLike) => void): void;
|
|
2521
|
+
};
|
|
2522
|
+
readonly outputs: {
|
|
2523
|
+
forEach(callback: (output: MidiOutputPort) => void): void;
|
|
2524
|
+
};
|
|
2525
|
+
readonly sysexEnabled: boolean;
|
|
2526
|
+
addEventListener?(type: string, listener: EventListener): void;
|
|
2527
|
+
removeEventListener?(type: string, listener: EventListener): void;
|
|
2528
|
+
};
|
|
2529
|
+
type MidiRequestAccess = (options?: {
|
|
2530
|
+
sysex?: boolean;
|
|
2531
|
+
}) => Promise<MidiAccessLike>;
|
|
2532
|
+
type MidiAccessFailureReason = 'unavailable' | 'denied' | 'destroyed';
|
|
2533
|
+
type MidiAccessResult = {
|
|
2534
|
+
ok: true;
|
|
2535
|
+
inputs: number;
|
|
2536
|
+
outputs: number;
|
|
2537
|
+
sysexEnabled: boolean;
|
|
2538
|
+
} | {
|
|
2539
|
+
ok: false;
|
|
2540
|
+
reason: MidiAccessFailureReason;
|
|
2541
|
+
detail?: string;
|
|
2542
|
+
};
|
|
2543
|
+
type MidiSendFailureReason = 'no-port' | 'invalid' | 'destroyed';
|
|
2544
|
+
type MidiSendResult = {
|
|
2545
|
+
ok: true;
|
|
2546
|
+
data: Uint8Array;
|
|
2547
|
+
} | {
|
|
2548
|
+
ok: false;
|
|
2549
|
+
reason: MidiSendFailureReason;
|
|
2550
|
+
detail?: string;
|
|
2551
|
+
};
|
|
2552
|
+
type MidiManagerOptions = {
|
|
2553
|
+
/** Fake or real output. Tests pass a recording port. */
|
|
2554
|
+
output?: MidiOutputPort;
|
|
2555
|
+
/**
|
|
2556
|
+
* Override Web MIDI request. Tests inject a fake or a rejecting
|
|
2557
|
+
* function. When omitted, uses `navigator.requestMIDIAccess`.
|
|
2558
|
+
*/
|
|
2559
|
+
requestMIDIAccess?: MidiRequestAccess;
|
|
2560
|
+
};
|
|
2561
|
+
declare function isMidiChannel(value: unknown): value is number;
|
|
2562
|
+
declare function isMidiData(value: unknown): value is number;
|
|
2563
|
+
declare function midiStatus(command: number, channel: number): MidiStatusByte;
|
|
2564
|
+
declare function midiChannelFromStatus(status: MidiStatusByte): number;
|
|
2565
|
+
declare function encodeMidiMessage(input: MidiVoiceInput): Uint8Array | undefined;
|
|
2566
|
+
declare function parseMidiBytes(data: Uint8Array | readonly number[]): MidiMessage | undefined;
|
|
2567
|
+
/**
|
|
2568
|
+
* Live MIDI in and out for a host or cart. Missing Web MIDI or a denied
|
|
2569
|
+
* permission is a structured result — constructing this never throws.
|
|
2570
|
+
*/
|
|
2571
|
+
declare class MidiManager {
|
|
2572
|
+
private output;
|
|
2573
|
+
private readonly outputOwned;
|
|
2574
|
+
private adoptedHardwareOutput;
|
|
2575
|
+
private readonly requestMIDIAccess;
|
|
2576
|
+
private listeners;
|
|
2577
|
+
private readonly attachedInputs;
|
|
2578
|
+
private access;
|
|
2579
|
+
private inputCount;
|
|
2580
|
+
private outputCount;
|
|
2581
|
+
private destroyed;
|
|
2582
|
+
constructor(options?: MidiManagerOptions);
|
|
2583
|
+
/**
|
|
2584
|
+
* Subscribe to parsed inbound messages. `note` matches note-on and
|
|
2585
|
+
* note-off. Returns an unsubscribe function.
|
|
2586
|
+
*/
|
|
2587
|
+
subscribe(kind: MidiSubscribeKind, listener: MidiSubscribeListener): () => void;
|
|
2588
|
+
/**
|
|
2589
|
+
* Deliver a message without Web MIDI hardware. Deterministic hosts and
|
|
2590
|
+
* tests call this instead of waiting on a controller.
|
|
2591
|
+
*/
|
|
2592
|
+
inject(input: MidiInjectInput): void;
|
|
2593
|
+
sendNoteOn(channel: number, note: number, velocity?: number): MidiSendResult;
|
|
2594
|
+
sendNoteOff(channel: number, note: number, velocity?: number): MidiSendResult;
|
|
2595
|
+
sendCc(channel: number, controller: number, value: number): MidiSendResult;
|
|
2596
|
+
sendPitch(channel: number, value: number): MidiSendResult;
|
|
2597
|
+
/** Send raw bytes through the output port. */
|
|
2598
|
+
send(data: Uint8Array | readonly number[]): MidiSendResult;
|
|
2599
|
+
/**
|
|
2600
|
+
* Wrap `navigator.requestMIDIAccess` when present. Missing API or a
|
|
2601
|
+
* denied permission returns `{ ok: false }` — it does not throw.
|
|
2602
|
+
*/
|
|
2603
|
+
requestAccess(options?: {
|
|
2604
|
+
sysex?: boolean;
|
|
2605
|
+
}): Promise<MidiAccessResult>;
|
|
2606
|
+
/**
|
|
2607
|
+
* Remove hardware listeners and subscribers. Idempotent. Further inject
|
|
2608
|
+
* is a no-op; send / requestAccess return `{ reason: 'destroyed' }`.
|
|
2609
|
+
*/
|
|
2610
|
+
destroy(): void;
|
|
2611
|
+
private sendEncoded;
|
|
2612
|
+
private write;
|
|
2613
|
+
private dispatch;
|
|
2614
|
+
private deliverBytes;
|
|
2615
|
+
private onHardwareMessage;
|
|
2616
|
+
private onAccessStateChange;
|
|
2617
|
+
private attachAccess;
|
|
2618
|
+
private syncPorts;
|
|
2619
|
+
private detachHardware;
|
|
2620
|
+
}
|
|
2621
|
+
|
|
2622
|
+
export { ANCHOR_ORIGINS, ASSET_FAILED_EVENT, ASSET_FAILURE_CODES, ASSET_KINDS, ASSET_READY_EVENT, AUDIO_CUE_EVENTS, AUDIO_CUE_FAILED_EVENT, AUDIO_CUE_SCHEDULED_EVENT, AUDIO_CUE_SKIPPED_EVENT, AUDIO_CUE_STARTED_EVENT, type ActiveAudioCue, type AnchorOrigin, type AnimationCart, type AnimationTiming, type AppliedAction, type ApplySnapshotMigrationsResult, 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 AudioAssetStatus, type AudioBroker, type AudioBrokerInspect, type AudioBrokerListener, type AudioBrokerNotice, type AudioChannelInspect, type AudioCueEvent, type AudioCueEventType, type AudioCueFailReason, type AudioCueReason, type AudioCueSkipReason, type AudioCueSpec, type AudioCueTimeline, type AudioCueTimelineSnapshot, type AudioCueView, type AudioLibraryId, type AudioLibrarySpec, type AudioUnlockState, type AudioUnlockStatus, type BoundReplaySession, type BrowserA11ySnapshot, type BrowserCompositorConfig, type BrowserHarness, type BrowserHarnessAction, type BrowserHarnessInspect, type BrowserHarnessMountContext, type BrowserHarnessRuntimeContext, type BrowserHarnessScreenshot, type BrowserHostSession, type BrowserInputModality, type BrowserReproductionMetadata, type BrowserViewport, CAPABILITY_ASSET_KINDS, CAPABILITY_BLEND_MODES, CAPABILITY_CLEAR_POLICIES, CAPABILITY_INTEGRATIONS, CAPABILITY_MANAGERS, CAPABILITY_MANIFEST_VERSION, CAPABILITY_PHASES, COMPOSITOR_BLEND_MODES, COMPOSITOR_CLEAR_POLICIES, COORDINATE_SPACES, CUE_CANCELLED_EVENT, CUE_COMPLETED_EVENT, CUE_LIFECYCLE_EVENTS, CUE_REPLACED_EVENT, CUE_STARTED_EVENT, CYBERART_CANVAS_ATTR, type CapabilityAssetDeclarationSummary, type CapabilityAssetKind, type CapabilityAssetSummary, type CapabilityBlendMode, type CapabilityClearPolicy, type CapabilityDiagnostic, type CapabilityIntegration, type CapabilityLayerRequirements, type CapabilityManager, type CapabilityManifest, type CapabilityManifestInput, type CapabilityModuleRef, type CapabilityModuleRequirements, type CapabilityPermissions, type CapabilityPhase, type CapabilityRuntime, type CapabilitySurfaceRequirements, type CartHandle, type CartSnapshot, type CartStateBundle, type CartStateHotkeyOptions, type CartStateMessageHandler, type CartStatePersister, type CausationTreeNode, type Clock, type ClockSnapshot, type ComposedFrame, type Compositor, type CompositorBlendMode, type CompositorClearPolicy, type CompositorClip, type CompositorHostOptions, type CompositorInspect, type CompositorLayerConfig, type CompositorLayerInspect, type CompositorPointerEvents, type ContractDiagnostic, type ContractFieldType, type ContractRegistry, type CoordinateSpace, type CreateAssetPreloaderOptions, type CreateAudioBrokerOptions, type CreateAudioCueTimelineOptions, type CreateBrowserHarnessOptions, type CreateCompositorOptions, type CreateExecutableModuleHostOptions, type CreatePresentationLayoutInput, type CreatePresentationTimelineOptions, type CreateReplayInspectorOptions, type CreateRuntimeGroupOptions, 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_BROWSER_VIEWPORT, DEFAULT_DUCK_GAIN, DEFAULT_GROUP_HEIGHT, DEFAULT_GROUP_WIDTH, DEFAULT_MAX_HOPS, DEFAULT_MAX_INSPECTOR_RECORDS, type DebugDrawCall, type DefineCapabilityManifestResult, type DefineContractResult, type DefineSnapshotResult, type DeterministicRuntimeOptions, type DimensionContext, ENGINE_SNAPSHOT_RUNTIME, EVENT_ENVELOPE_VERSION, EXECUTABLE_MODULE_ERROR_CODES, type EventContract, type EventContractManifest, type EventEnvelope, type EventInput, type EventKind, type EventRouter, type EventRouterOptions, type ExecutableModuleCapabilities, type ExecutableModuleDiagnostic, type ExecutableModuleError, type ExecutableModuleErrorCode, type ExecutableModuleFactory, type ExecutableModuleHost, type ExecutableModuleHostInspect, type ExecutableModuleInstance, type ExecutableModuleInvokeContext, type ExecutableModuleInvokeResult, type ExecutableModuleLimits, type ExecutableModuleLoadResult, type ExecutableModuleRef, type ExecutableModuleRegistration, type ExportSnapshotOptions, type FixtureAssetCatalog, type FixtureAssetRecord, type FrameErrorInfo, GEOMETRY_CONTRACT_VERSION, type GeometryAnchor, type GeometryDebugContext, type GeometryDiagnostic, type GeometryDocument, type GeometryHitbox, type GeometryPadding, type GeometrySafeArea, type GeometryValidation, type HeadlessAudioAdapter, type HostCapabilities, HostChannel, type HostEvent, type HostEventListener, type HostedAssetResolverOptions, INVALID_PRESENTATION_MODEL_MESSAGE, type ImportCartStateExtras, IncompatibleCartStateError, type InferredPayload, type InspectorRecord, KeyboardManager, LEGACY_SNAPSHOT_SCHEMA_VERSION, type LandmarkRegisterResult, type LandmarkRegistry, type LegacySnapshot, MIDI_CHANNEL_MAX, MIDI_CHANNEL_MIN, MIDI_CONTROL_CHANGE, MIDI_DATA_MAX, MIDI_NOTE_OFF, MIDI_NOTE_ON, MIDI_PITCH_BEND, MIDI_PITCH_CENTER, MIDI_PITCH_MAX, type MidiAccessFailureReason, type MidiAccessLike, type MidiAccessResult, type MidiCcMessage, type MidiChannel, type MidiInjectInput, type MidiInputLike, MidiManager, type MidiManagerOptions, type MidiMessage, type MidiNoteMessage, type MidiOutputPort, type MidiPitchMessage, type MidiRawMessage, type MidiRequestAccess, type MidiSendFailureReason, type MidiSendResult, type MidiStatusByte, type MidiSubscribeKind, type MidiSubscribeListener, type MidiVoiceInput, type MountOptions, type MountPresentationAdapterOptions, type NormalizeContext, type NormalizeResult, type NormalizedPoint, type NormalizedPolygon, type NormalizedRect, PRESENTATION_ADAPTER_VERSION, PRESENTATION_MODEL_EVENT, PRESENTATION_PHASES, PRESENTATION_SUBSCRIBE_PATTERNS, PRESENTATION_UNSUPPORTED_EVENT, type ParseSnapshotResult, type PayloadFieldSpec, type PayloadSchema, type PayloadValidation, type PixelPoint, type PixelRect, type PlayAudioCueResult, type PlayCueResult, type PlaywrightCompatibleAdapter, type PlaywrightCompatibleViewport, type PointerClick, PointerManager, type PointerSpace, type PresentationAdapter, type PresentationAdapterTarget, type PresentationCartState, type PresentationFitMode, type PresentationLayout, type PresentationModel, type PresentationPhase, type PresentationRegion, type PresentationTimeline, type PresentationView, type PublishExtras, REDACTED_VALUE, REJECTED_EVENT_TYPE, REPLAY_INSPECTOR_SCHEMA_VERSION, ROUND_TRIP_TOLERANCE, ROUND_TRIP_TOLERANCE_CANVAS_PX, Random, type RandomState, type RejectionPayload, type RejectionReason, type ReplayCompareResult, type ReplayInspector, type ReplayInspectorExport, type ReplayInspectorReport, type ReplayMetadata, type ReplayParticipantSummary, type ReplayTapeAction, type ReplayTraceFilter, type ResolveImportableCartStateResult, type ResolvedAsset, type RouterDecision, type RouterDecisionOutcome, type RouterDecisionReason, type RouterParticipantInspect, type RuntimeGroup, type RuntimeGroupCapability, type RuntimeGroupDiagnostics, type RuntimeGroupFrameError, type RuntimeGroupInspect, type RuntimeGroupKind, type RuntimeGroupParticipantConfig, type RuntimeGroupParticipantHandle, type RuntimeGroupParticipantInspect, SILENT_ASSET_FALLBACK_REF, SNAPSHOT_SCHEMA_VERSION, type SchemaCompatibility, type ScriptedAction, type SnapshotAssetRef, type SnapshotCartRef, type SnapshotClock, type SnapshotDiagnostic, type SnapshotEnvelope, type SnapshotEnvelopeInput, type SnapshotIntegrity, type SnapshotMigration, type SnapshotMigrationRegistry, type SnapshotModuleRef, type SnapshotProvenance, type TokenData, UNVERSIONED_CART_VERSION, type ValidateCapabilityManifestResult, type ValidateResult, type ValidateSnapshotResult, type VersionedSnapshot, type VirtualClock, applyCueEasing, applySnapshotMigrations, assetStatusEvent, assetToNormalized, attachCartStatePersistence, attachPresentationAdapter, canonicalizeSeed, canvasToCss, canvasToNormalized, toJSON as capabilityManifestToJSON, cloneSnapshotJson, comparePayloadSchemas, compareReplayTraces, createAssetFailure, createAssetPreloader, createAudioBroker, createAudioCueTimeline, createBrowserHarness, createCompositor, createContractRegistry, createEngineSnapshotMigrations, createEventRouter, createExecutableModuleHost, createFixtureAssetResolver, createHeadlessAudioAdapter, createHostedAssetResolver, createLandmarkRegistry, createPlaywrightCompatibleAdapter, createPresentationLayout, createPresentationModelEvent, createPresentationTimeline, createReferencePresentationCart, createReplayInspector, createRuntime, createRuntimeGroup, createSnapshotMigrationRegistry, createVirtualClock, createWallClock, cssToCanvas, cssToNormalized, defaultSnapshotMigrationRegistry, defineCapabilityManifest, defineDiagnostic, defineIntent, defineSnapshot, defineStateEvent, deriveAttachOptions, describeReplayMismatch, detectSnapshotSchemaVersion, drawGeometryDebug, encodeMidiMessage, engineStateFromEnvelope, familyPatternForType, inferEventKind, isAssetFailure, isAssetFailureCode, isAssetKind, isAudioCueEventType, isCueLifecycleType, isLegacyCartStateBundle, isMidiChannel, isMidiData, isPresentationModel, isPresentationPhase, isSnapshotEnvelope, isVersionedSnapshot, kindSegmentInType, matchEventPattern, midiChannelFromStatus, midiStatus, mountPresentationAdapter, normalizeEvent, normalizedToAsset, normalizedToCanvas, normalizedToCss, parseCapabilityManifest, parseGeometry, parseMidiBytes, parseSnapshot, pointFromOrigin, pointerToRegion, rectToCanvas, rectToCss, regionToViewport, registerCartStateHotkeys, replayExportedTrace, resolveImportableCartState, resolveRuntimeSeed, restoreSnapshotFromUnknown, rewriteHostedAssetRef, scheduleAudioCue, serializeGeometry, snapshotErrorsToMessage, snapshotFromCartBundle, validateCapabilityManifest, validateGeometry, validateSnapshot, verifyAttachOptions };
|