@vizij/runtime-react 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1,27 +1,69 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as react from 'react';
3
3
  import { ReactNode, PropsWithChildren } from 'react';
4
- import { GraphRegistrationConfig, GraphSubscriptions, AnimationSetup, ValueJSON, CreateOrchOptions, MergeStrategyOptions, ShapeJSON } from '@vizij/orchestrator-react';
4
+ import { ValueJSON } from '@vizij/value-json';
5
5
  import { IrGraph } from '@vizij/node-graph-authoring';
6
- import { AnimatableValue, RawValue } from '@vizij/utils';
6
+ import { RawValue, AnimatableValue } from '@vizij/utils';
7
7
  import { World, VizijBundleExtension, VizijProps } from '@vizij/render';
8
8
 
9
+ /** Value shape hint. Accepted through the public surface, unused by the device. */
10
+ type ShapeJSON = Record<string, unknown>;
11
+ /** Paths a graph reads/writes — metadata for output tracking and seeding. */
12
+ type GraphSubscriptions = {
13
+ inputs?: string[];
14
+ outputs?: string[];
15
+ };
16
+ /** A Vizij graph spec handled structurally (nodes/edges arrays of records). */
17
+ type GraphSpecLike = {
18
+ nodes?: Array<Record<string, unknown>>;
19
+ edges?: Array<Record<string, unknown>>;
20
+ metadata?: unknown;
21
+ [key: string]: unknown;
22
+ };
23
+ /** One graph source composed into the device's behavior. */
24
+ type GraphRegistrationConfig = {
25
+ id?: string;
26
+ spec: GraphSpecLike;
27
+ subs?: GraphSubscriptions;
28
+ };
29
+ /** Per-source merge options. Composition is last-writer-wins today (VIZ-53). */
30
+ type MergeStrategyOptions = Record<string, unknown>;
31
+ /** Player/instance setup carried by animation assets; consumed by the JS clip pipeline. */
32
+ type AnimationSetup = {
33
+ animation?: unknown;
34
+ player?: Record<string, unknown>;
35
+ instance?: Record<string, unknown>;
36
+ };
9
37
  type PoseDefinition = {
10
38
  id: string;
11
39
  name?: string;
12
40
  description?: string;
13
41
  group?: string | null;
42
+ groupId?: string | null;
43
+ groupIds?: string[];
14
44
  values: Record<string, number | undefined>;
15
45
  };
46
+ type PoseBlendMode = "average" | "additive";
47
+ type PoseGroupDefinition = {
48
+ id: string;
49
+ name: string;
50
+ path: string;
51
+ blendMode?: PoseBlendMode;
52
+ };
16
53
  type PoseRigConfig = {
17
54
  version: number;
18
55
  faceId?: string | null;
19
56
  title?: string;
20
57
  description?: string;
58
+ poseGroups?: PoseGroupDefinition[];
59
+ crossGroupBlendMode?: PoseBlendMode;
21
60
  neutralInputs: Record<string, number>;
22
61
  poses: PoseDefinition[];
23
- metadata?: Record<string, unknown>;
24
- [key: string]: unknown;
62
+ metadata?: Record<string, unknown> | {
63
+ createdAt: string;
64
+ updatedAt: string;
65
+ author?: string;
66
+ };
25
67
  };
26
68
  type RootBounds = {
27
69
  center: {
@@ -45,8 +87,8 @@ type VizijGlbAsset = {
45
87
  rootBounds?: RootBounds;
46
88
  } | {
47
89
  kind: "world";
48
- world: World;
49
- animatables: Record<string, AnimatableValue>;
90
+ world: World | Record<string, unknown>;
91
+ animatables: Record<string, AnimatableValue> | Record<string, unknown>;
50
92
  bundle?: VizijBundleExtension | null;
51
93
  };
52
94
  type VizijGraphAsset = {
@@ -72,10 +114,15 @@ type VizijInputMetadata = {
72
114
  type AnimationKeyframeLike = {
73
115
  time?: number;
74
116
  value?: number;
117
+ inTangent?: number | null;
118
+ outTangent?: number | null;
119
+ [key: string]: unknown;
75
120
  };
76
121
  type AnimationTrackLike = {
77
122
  channel: string;
78
123
  keyframes?: AnimationKeyframeLike[];
124
+ interpolation?: "linear" | "step" | "cubic" | string;
125
+ [key: string]: unknown;
79
126
  };
80
127
  type AnimationClipLike = {
81
128
  id?: string;
@@ -90,6 +137,13 @@ type VizijAnimationAsset = {
90
137
  setup?: Partial<AnimationSetup>;
91
138
  weight?: number;
92
139
  };
140
+ type VizijProgramAsset = {
141
+ id: string;
142
+ label?: string;
143
+ graph: VizijGraphAsset;
144
+ resetValues?: Record<string, number>;
145
+ metadata?: Record<string, unknown>;
146
+ };
93
147
  type VizijAssetBundle = {
94
148
  namespace?: string;
95
149
  faceId?: string;
@@ -101,6 +155,7 @@ type VizijAssetBundle = {
101
155
  stageNeutralFilter?: (id: string, path: string) => boolean;
102
156
  };
103
157
  animations?: VizijAnimationAsset[];
158
+ programs?: VizijProgramAsset[];
104
159
  initialInputs?: Record<string, ValueJSON>;
105
160
  metadata?: Record<string, unknown>;
106
161
  bundle?: VizijBundleExtension | null;
@@ -108,7 +163,7 @@ type VizijAssetBundle = {
108
163
  type RuntimeError = {
109
164
  message: string;
110
165
  cause?: unknown;
111
- phase?: "assets" | "orchestrator" | "registration" | "animation" | "bridge" | "driver" | "unknown";
166
+ phase?: "assets" | "engine" | "registration" | "animation" | "bridge" | "driver" | "unknown";
112
167
  timestamp: number;
113
168
  };
114
169
  type VizijRuntimeStatus = {
@@ -139,6 +194,22 @@ type PlayAnimationOptions = {
139
194
  speed?: number;
140
195
  reset?: boolean;
141
196
  };
197
+ type StopAnimationOptions = {
198
+ clearOutputs?: boolean;
199
+ };
200
+ type AnimationPlaybackState = {
201
+ time: number;
202
+ duration: number;
203
+ playing: boolean;
204
+ loop: boolean;
205
+ speed: number;
206
+ };
207
+ type StopProgramOptions = {
208
+ resetOutputs?: boolean;
209
+ };
210
+ type ProgramPlaybackState = {
211
+ state: "playing" | "paused" | "stopped";
212
+ };
142
213
  type InputDriverLifecycle = {
143
214
  start: () => void;
144
215
  stop: () => void;
@@ -151,23 +222,64 @@ type InputDriverContext = {
151
222
  faceId?: string;
152
223
  };
153
224
  type InputDriverFactory = (ctx: InputDriverContext) => InputDriverLifecycle;
225
+ type RuntimeOutputWrite = {
226
+ id: string;
227
+ namespace: string;
228
+ value: RawValue;
229
+ currentValue?: RawValue;
230
+ };
154
231
  type VizijRuntimeFaceProps = Omit<VizijProps, "rootId" | "namespace"> & {
155
232
  namespaceOverride?: string;
156
233
  };
157
234
  type VizijRuntimeContextValue = VizijRuntimeStatus & {
158
235
  assetBundle: VizijAssetBundle;
159
236
  setInput: (path: string, value: ValueJSON, shape?: ShapeJSON) => void;
237
+ /** Current engine-store value of a path (read-your-own-write included). */
238
+ getValueSnapshot: (path: string) => ValueJSON | undefined;
239
+ /**
240
+ * A snapshot of EVERY key currently in the device store, as path → Value in
241
+ * arora's serde JSON shape (pass-through from the device; not `ValueJSON`).
242
+ * `undefined` until the device exists. For mirrors/bridges that forward the
243
+ * whole store (e.g. the standalone's native-store bridge), not for per-path
244
+ * sampling — use `getValueSnapshot` for that.
245
+ */
246
+ getStoreSnapshot: () => Record<string, unknown> | undefined;
247
+ /**
248
+ * Notifies with each step's drained store changes (path → Value in arora's
249
+ * serde JSON shape; `null` for a cleared key). The change-driven counterpart
250
+ * to `getStoreSnapshot` for store bridges: seed from the snapshot, then stay
251
+ * current from these. Returns an unsubscribe function.
252
+ */
253
+ subscribeToStoreChanges: (listener: (changes: Record<string, unknown>) => void) => () => void;
254
+ /**
255
+ * Notifies after each engine step, once the step's store changes have been
256
+ * applied. Pair with `getValueSnapshot` to sample values step-aligned.
257
+ * Returns an unsubscribe function.
258
+ */
259
+ subscribeToStep: (listener: () => void) => () => void;
260
+ setGraphBundle: (bundle: RuntimeGraphBundle, options?: {
261
+ tier?: "auto" | "assets" | "graphs";
262
+ }) => void;
160
263
  setValue: (id: string, namespace: string, value: RawValue | ((prev: RawValue | undefined) => RawValue | undefined)) => void;
161
264
  stagePoseNeutral: (force?: boolean) => void;
162
265
  animateValue: (path: string, target: ValueJSON, options?: AnimateValueOptions) => Promise<void>;
163
266
  cancelAnimation: (path: string) => void;
164
267
  registerInputDriver: (id: string, factory: InputDriverFactory) => InputDriverLifecycle;
165
268
  playAnimation: (id: string, options?: PlayAnimationOptions) => Promise<void>;
166
- stopAnimation: (id: string) => void;
269
+ pauseAnimation: (id: string) => void;
270
+ seekAnimation: (id: string, timeSeconds: number) => void;
271
+ setAnimationLoop: (id: string, enabled: boolean) => void;
272
+ getAnimationState: (id: string) => AnimationPlaybackState | null;
273
+ stopAnimation: (id: string, options?: StopAnimationOptions) => void;
274
+ playProgram: (id: string) => void;
275
+ pauseProgram: (id: string) => void;
276
+ stopProgram: (id: string, options?: StopProgramOptions) => void;
277
+ getProgramState: (id: string) => ProgramPlaybackState | null;
278
+ setAnimationActive: (active: boolean) => void;
279
+ isAnimationActive: () => boolean;
167
280
  step: (dt: number, opts?: {
168
281
  forceRuntime?: boolean;
169
282
  }) => void;
170
- advanceAnimations: (dt: number) => void;
171
283
  inputConstraints: Record<string, {
172
284
  min?: number;
173
285
  max?: number;
@@ -179,29 +291,107 @@ type VizijRuntimeProviderProps = {
179
291
  children: ReactNode;
180
292
  namespace?: string;
181
293
  faceId?: string;
294
+ updateTier?: RuntimeUpdateTier;
182
295
  autoCreate?: boolean;
183
- createOptions?: CreateOrchOptions;
184
296
  autostart?: boolean;
185
- driveOrchestrator?: boolean;
297
+ /**
298
+ * Whether this provider's device paces itself: when true the device is
299
+ * handed to its own `run()` loop at boot and the provider only pumps its
300
+ * changes; when false the device advances solely on `step(dt,
301
+ * { forceRuntime: true })` calls from the host. A device handed to `run()`
302
+ * keeps its loop even if this later turns false.
303
+ */
304
+ driveRuntime?: boolean;
186
305
  mergeStrategy?: MergeStrategyOptions;
187
306
  onRegisterControllers?: (ids: {
188
307
  graphs: string[];
189
308
  anims: string[];
190
309
  }) => void;
191
310
  onStatusChange?: (status: VizijRuntimeStatus) => void;
192
- orchestratorScope?: "auto" | "shared" | "isolated";
311
+ transformOutputWrite?: (write: RuntimeOutputWrite) => RuntimeOutputWrite | null;
312
+ };
313
+ type RuntimeUpdateTier = "auto" | "assets" | "graphs";
314
+ type RuntimeUpdatePlan = {
315
+ reloadAssets: boolean;
316
+ reregisterGraphs: boolean;
317
+ };
318
+ type RuntimeGraphBundle = {
319
+ rig?: VizijGraphAsset;
320
+ pose?: VizijAssetBundle["pose"];
321
+ animations?: VizijAnimationAsset[];
322
+ programs?: VizijProgramAsset[];
193
323
  };
194
324
 
195
325
  type ProviderProps = PropsWithChildren<VizijRuntimeProviderProps>;
196
- declare function VizijRuntimeProvider({ assetBundle, children, namespace: namespaceProp, faceId: faceIdProp, autoCreate, createOptions, autostart, driveOrchestrator, mergeStrategy, onRegisterControllers, onStatusChange, orchestratorScope, }: ProviderProps): react_jsx_runtime.JSX.Element;
326
+ declare function VizijRuntimeProvider({ assetBundle, children, namespace: namespaceProp, faceId: faceIdProp, updateTier, autoCreate, autostart, driveRuntime, mergeStrategy, onRegisterControllers, onStatusChange, transformOutputWrite, }: ProviderProps): react_jsx_runtime.JSX.Element;
197
327
 
198
328
  declare function VizijRuntimeFaceInner({ namespaceOverride, ...props }: VizijRuntimeFaceProps): react_jsx_runtime.JSX.Element | null;
199
329
  declare const VizijRuntimeFace: react.MemoExoticComponent<typeof VizijRuntimeFaceInner>;
200
330
 
201
331
  declare function useVizijRuntime(): VizijRuntimeContextValue;
202
332
 
333
+ declare function useOptionalVizijRuntime(): VizijRuntimeContextValue | null;
334
+
203
335
  declare function useVizijOutputs(paths: string[]): Record<string, RawValue | undefined>;
204
336
 
205
337
  declare function useRigInput(path: string): [RawValue | undefined, (value: ValueJSON, shape?: ShapeJSON) => void];
206
338
 
207
- export { type AnimateValueOptions, type AnimationClipLike, type AnimationKeyframeLike, type AnimationTrackLike, type InputDriverContext, type InputDriverFactory, type InputDriverLifecycle, type PlayAnimationOptions, type PoseDefinition, type PoseRigConfig, type RootBounds, type VizijAnimationAsset, type VizijAssetBundle, type VizijGlbAsset, type VizijGraphAsset, VizijRuntimeFace, type VizijRuntimeFaceProps, VizijRuntimeProvider, type VizijRuntimeProviderProps, type VizijRuntimeStatus, useRigInput, useVizijOutputs, useVizijRuntime };
339
+ declare function resolveRuntimeUpdatePlan(previous: VizijAssetBundle | null, next: VizijAssetBundle, tier: RuntimeUpdateTier): RuntimeUpdatePlan;
340
+
341
+ declare const POSE_WEIGHT_INPUT_PATH_PREFIX = "/poses/";
342
+ declare const VISEME_POSE_KEYS: readonly ["a", "at", "b", "e", "e_2", "f", "i", "k", "m", "o", "o_2", "p", "r", "s", "t", "t_2", "u"];
343
+ declare const EXPRESSIVE_EMOTION_POSE_KEYS: readonly ["concerned", "happy", "sad", "sleepy", "surprise"];
344
+ declare const EMOTION_POSE_KEYS: readonly ["concerned", "happy", "neutral", "sad", "sleepy", "surprise", "angry"];
345
+ type PoseSemanticKind = "emotion" | "viseme" | "other";
346
+ declare function buildRigInputPath(faceId: string, path: string): string;
347
+ declare function buildPoseWeightInputPathSegment(poseId: string | null | undefined): string;
348
+ declare function buildPoseWeightRelativePath(poseId: string | null | undefined): string;
349
+ declare function buildPoseWeightPathMap(poses: PoseDefinition[], faceId: string | null | undefined): Map<string, string>;
350
+ declare function normalizePoseSemanticKey(value: string | null | undefined): string | null;
351
+ declare function getPoseSemanticKey(pose: Pick<PoseDefinition, "id" | "name">): string | null;
352
+ declare function resolvePoseMembership(pose: Pick<PoseDefinition, "group" | "groupId" | "groupIds">, groups: PoseGroupDefinition[] | undefined): {
353
+ groupIds: string[];
354
+ primaryGroupId: string | null;
355
+ primaryGroupPath: string | null;
356
+ groupPathsById: Record<string, string>;
357
+ };
358
+ declare function resolvePoseSemantics(pose: Pick<PoseDefinition, "id" | "name" | "group" | "groupId" | "groupIds">, groups: PoseGroupDefinition[] | undefined): {
359
+ key: string | null;
360
+ kind: PoseSemanticKind;
361
+ membership: ReturnType<typeof resolvePoseMembership>;
362
+ };
363
+ declare function filterPosesBySemanticKind(poses: PoseDefinition[], groups: PoseGroupDefinition[] | undefined, kind: PoseSemanticKind): PoseDefinition[];
364
+ declare function buildSemanticPoseWeightPathMap(poses: PoseDefinition[], groups: PoseGroupDefinition[] | undefined, faceId: string | null | undefined, kind: Exclude<PoseSemanticKind, "other">): Map<string, string>;
365
+
366
+ type InputConstraint = {
367
+ min?: number;
368
+ max?: number;
369
+ defaultValue?: number;
370
+ };
371
+ type FaceScalarControl = {
372
+ path: string;
373
+ min: number;
374
+ max: number;
375
+ defaultValue: number;
376
+ };
377
+ type ResolvedFaceControls = {
378
+ faceId: string;
379
+ gazeSource: "standard-vizij" | "standard" | "propsrig" | "coupled-gaze" | "none";
380
+ blinkSource: "lids" | "blink" | "none";
381
+ eyes: {
382
+ leftX: FaceScalarControl | null;
383
+ leftY: FaceScalarControl | null;
384
+ rightX: FaceScalarControl | null;
385
+ rightY: FaceScalarControl | null;
386
+ };
387
+ eyelids: {
388
+ leftUpper: FaceScalarControl | null;
389
+ rightUpper: FaceScalarControl | null;
390
+ };
391
+ blink: FaceScalarControl | null;
392
+ };
393
+ declare function resolveFaceControls(assetBundle: VizijAssetBundle, runtimeFaceId?: string | null, inputConstraints?: Record<string, InputConstraint>): ResolvedFaceControls;
394
+ declare function mapNormalizedControlValue(control: FaceScalarControl, normalizedValue: number): number;
395
+ declare function mapUnitControlValue(control: FaceScalarControl, unitValue: number): number;
396
+
397
+ export { type AnimateValueOptions, type AnimationClipLike, type AnimationKeyframeLike, type AnimationPlaybackState, type AnimationTrackLike, EMOTION_POSE_KEYS, EXPRESSIVE_EMOTION_POSE_KEYS, type FaceScalarControl, type InputDriverContext, type InputDriverFactory, type InputDriverLifecycle, POSE_WEIGHT_INPUT_PATH_PREFIX, type PlayAnimationOptions, type PoseDefinition, type PoseGroupDefinition, type PoseRigConfig, type ProgramPlaybackState, type RootBounds, type RuntimeGraphBundle, type RuntimeOutputWrite, type RuntimeUpdatePlan, type RuntimeUpdateTier, type StopProgramOptions, VISEME_POSE_KEYS, type VizijAnimationAsset, type VizijAssetBundle, type VizijGlbAsset, type VizijGraphAsset, type VizijProgramAsset, VizijRuntimeFace, type VizijRuntimeFaceProps, VizijRuntimeProvider, type VizijRuntimeProviderProps, type VizijRuntimeStatus, buildPoseWeightInputPathSegment, buildPoseWeightPathMap, buildPoseWeightRelativePath, buildRigInputPath, buildSemanticPoseWeightPathMap, filterPosesBySemanticKind, getPoseSemanticKey, mapNormalizedControlValue, mapUnitControlValue, normalizePoseSemanticKey, resolveFaceControls, resolvePoseMembership, resolvePoseSemantics, resolveRuntimeUpdatePlan, useOptionalVizijRuntime, useRigInput, useVizijOutputs, useVizijRuntime };
package/dist/index.d.ts CHANGED
@@ -1,27 +1,69 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as react from 'react';
3
3
  import { ReactNode, PropsWithChildren } from 'react';
4
- import { GraphRegistrationConfig, GraphSubscriptions, AnimationSetup, ValueJSON, CreateOrchOptions, MergeStrategyOptions, ShapeJSON } from '@vizij/orchestrator-react';
4
+ import { ValueJSON } from '@vizij/value-json';
5
5
  import { IrGraph } from '@vizij/node-graph-authoring';
6
- import { AnimatableValue, RawValue } from '@vizij/utils';
6
+ import { RawValue, AnimatableValue } from '@vizij/utils';
7
7
  import { World, VizijBundleExtension, VizijProps } from '@vizij/render';
8
8
 
9
+ /** Value shape hint. Accepted through the public surface, unused by the device. */
10
+ type ShapeJSON = Record<string, unknown>;
11
+ /** Paths a graph reads/writes — metadata for output tracking and seeding. */
12
+ type GraphSubscriptions = {
13
+ inputs?: string[];
14
+ outputs?: string[];
15
+ };
16
+ /** A Vizij graph spec handled structurally (nodes/edges arrays of records). */
17
+ type GraphSpecLike = {
18
+ nodes?: Array<Record<string, unknown>>;
19
+ edges?: Array<Record<string, unknown>>;
20
+ metadata?: unknown;
21
+ [key: string]: unknown;
22
+ };
23
+ /** One graph source composed into the device's behavior. */
24
+ type GraphRegistrationConfig = {
25
+ id?: string;
26
+ spec: GraphSpecLike;
27
+ subs?: GraphSubscriptions;
28
+ };
29
+ /** Per-source merge options. Composition is last-writer-wins today (VIZ-53). */
30
+ type MergeStrategyOptions = Record<string, unknown>;
31
+ /** Player/instance setup carried by animation assets; consumed by the JS clip pipeline. */
32
+ type AnimationSetup = {
33
+ animation?: unknown;
34
+ player?: Record<string, unknown>;
35
+ instance?: Record<string, unknown>;
36
+ };
9
37
  type PoseDefinition = {
10
38
  id: string;
11
39
  name?: string;
12
40
  description?: string;
13
41
  group?: string | null;
42
+ groupId?: string | null;
43
+ groupIds?: string[];
14
44
  values: Record<string, number | undefined>;
15
45
  };
46
+ type PoseBlendMode = "average" | "additive";
47
+ type PoseGroupDefinition = {
48
+ id: string;
49
+ name: string;
50
+ path: string;
51
+ blendMode?: PoseBlendMode;
52
+ };
16
53
  type PoseRigConfig = {
17
54
  version: number;
18
55
  faceId?: string | null;
19
56
  title?: string;
20
57
  description?: string;
58
+ poseGroups?: PoseGroupDefinition[];
59
+ crossGroupBlendMode?: PoseBlendMode;
21
60
  neutralInputs: Record<string, number>;
22
61
  poses: PoseDefinition[];
23
- metadata?: Record<string, unknown>;
24
- [key: string]: unknown;
62
+ metadata?: Record<string, unknown> | {
63
+ createdAt: string;
64
+ updatedAt: string;
65
+ author?: string;
66
+ };
25
67
  };
26
68
  type RootBounds = {
27
69
  center: {
@@ -45,8 +87,8 @@ type VizijGlbAsset = {
45
87
  rootBounds?: RootBounds;
46
88
  } | {
47
89
  kind: "world";
48
- world: World;
49
- animatables: Record<string, AnimatableValue>;
90
+ world: World | Record<string, unknown>;
91
+ animatables: Record<string, AnimatableValue> | Record<string, unknown>;
50
92
  bundle?: VizijBundleExtension | null;
51
93
  };
52
94
  type VizijGraphAsset = {
@@ -72,10 +114,15 @@ type VizijInputMetadata = {
72
114
  type AnimationKeyframeLike = {
73
115
  time?: number;
74
116
  value?: number;
117
+ inTangent?: number | null;
118
+ outTangent?: number | null;
119
+ [key: string]: unknown;
75
120
  };
76
121
  type AnimationTrackLike = {
77
122
  channel: string;
78
123
  keyframes?: AnimationKeyframeLike[];
124
+ interpolation?: "linear" | "step" | "cubic" | string;
125
+ [key: string]: unknown;
79
126
  };
80
127
  type AnimationClipLike = {
81
128
  id?: string;
@@ -90,6 +137,13 @@ type VizijAnimationAsset = {
90
137
  setup?: Partial<AnimationSetup>;
91
138
  weight?: number;
92
139
  };
140
+ type VizijProgramAsset = {
141
+ id: string;
142
+ label?: string;
143
+ graph: VizijGraphAsset;
144
+ resetValues?: Record<string, number>;
145
+ metadata?: Record<string, unknown>;
146
+ };
93
147
  type VizijAssetBundle = {
94
148
  namespace?: string;
95
149
  faceId?: string;
@@ -101,6 +155,7 @@ type VizijAssetBundle = {
101
155
  stageNeutralFilter?: (id: string, path: string) => boolean;
102
156
  };
103
157
  animations?: VizijAnimationAsset[];
158
+ programs?: VizijProgramAsset[];
104
159
  initialInputs?: Record<string, ValueJSON>;
105
160
  metadata?: Record<string, unknown>;
106
161
  bundle?: VizijBundleExtension | null;
@@ -108,7 +163,7 @@ type VizijAssetBundle = {
108
163
  type RuntimeError = {
109
164
  message: string;
110
165
  cause?: unknown;
111
- phase?: "assets" | "orchestrator" | "registration" | "animation" | "bridge" | "driver" | "unknown";
166
+ phase?: "assets" | "engine" | "registration" | "animation" | "bridge" | "driver" | "unknown";
112
167
  timestamp: number;
113
168
  };
114
169
  type VizijRuntimeStatus = {
@@ -139,6 +194,22 @@ type PlayAnimationOptions = {
139
194
  speed?: number;
140
195
  reset?: boolean;
141
196
  };
197
+ type StopAnimationOptions = {
198
+ clearOutputs?: boolean;
199
+ };
200
+ type AnimationPlaybackState = {
201
+ time: number;
202
+ duration: number;
203
+ playing: boolean;
204
+ loop: boolean;
205
+ speed: number;
206
+ };
207
+ type StopProgramOptions = {
208
+ resetOutputs?: boolean;
209
+ };
210
+ type ProgramPlaybackState = {
211
+ state: "playing" | "paused" | "stopped";
212
+ };
142
213
  type InputDriverLifecycle = {
143
214
  start: () => void;
144
215
  stop: () => void;
@@ -151,23 +222,64 @@ type InputDriverContext = {
151
222
  faceId?: string;
152
223
  };
153
224
  type InputDriverFactory = (ctx: InputDriverContext) => InputDriverLifecycle;
225
+ type RuntimeOutputWrite = {
226
+ id: string;
227
+ namespace: string;
228
+ value: RawValue;
229
+ currentValue?: RawValue;
230
+ };
154
231
  type VizijRuntimeFaceProps = Omit<VizijProps, "rootId" | "namespace"> & {
155
232
  namespaceOverride?: string;
156
233
  };
157
234
  type VizijRuntimeContextValue = VizijRuntimeStatus & {
158
235
  assetBundle: VizijAssetBundle;
159
236
  setInput: (path: string, value: ValueJSON, shape?: ShapeJSON) => void;
237
+ /** Current engine-store value of a path (read-your-own-write included). */
238
+ getValueSnapshot: (path: string) => ValueJSON | undefined;
239
+ /**
240
+ * A snapshot of EVERY key currently in the device store, as path → Value in
241
+ * arora's serde JSON shape (pass-through from the device; not `ValueJSON`).
242
+ * `undefined` until the device exists. For mirrors/bridges that forward the
243
+ * whole store (e.g. the standalone's native-store bridge), not for per-path
244
+ * sampling — use `getValueSnapshot` for that.
245
+ */
246
+ getStoreSnapshot: () => Record<string, unknown> | undefined;
247
+ /**
248
+ * Notifies with each step's drained store changes (path → Value in arora's
249
+ * serde JSON shape; `null` for a cleared key). The change-driven counterpart
250
+ * to `getStoreSnapshot` for store bridges: seed from the snapshot, then stay
251
+ * current from these. Returns an unsubscribe function.
252
+ */
253
+ subscribeToStoreChanges: (listener: (changes: Record<string, unknown>) => void) => () => void;
254
+ /**
255
+ * Notifies after each engine step, once the step's store changes have been
256
+ * applied. Pair with `getValueSnapshot` to sample values step-aligned.
257
+ * Returns an unsubscribe function.
258
+ */
259
+ subscribeToStep: (listener: () => void) => () => void;
260
+ setGraphBundle: (bundle: RuntimeGraphBundle, options?: {
261
+ tier?: "auto" | "assets" | "graphs";
262
+ }) => void;
160
263
  setValue: (id: string, namespace: string, value: RawValue | ((prev: RawValue | undefined) => RawValue | undefined)) => void;
161
264
  stagePoseNeutral: (force?: boolean) => void;
162
265
  animateValue: (path: string, target: ValueJSON, options?: AnimateValueOptions) => Promise<void>;
163
266
  cancelAnimation: (path: string) => void;
164
267
  registerInputDriver: (id: string, factory: InputDriverFactory) => InputDriverLifecycle;
165
268
  playAnimation: (id: string, options?: PlayAnimationOptions) => Promise<void>;
166
- stopAnimation: (id: string) => void;
269
+ pauseAnimation: (id: string) => void;
270
+ seekAnimation: (id: string, timeSeconds: number) => void;
271
+ setAnimationLoop: (id: string, enabled: boolean) => void;
272
+ getAnimationState: (id: string) => AnimationPlaybackState | null;
273
+ stopAnimation: (id: string, options?: StopAnimationOptions) => void;
274
+ playProgram: (id: string) => void;
275
+ pauseProgram: (id: string) => void;
276
+ stopProgram: (id: string, options?: StopProgramOptions) => void;
277
+ getProgramState: (id: string) => ProgramPlaybackState | null;
278
+ setAnimationActive: (active: boolean) => void;
279
+ isAnimationActive: () => boolean;
167
280
  step: (dt: number, opts?: {
168
281
  forceRuntime?: boolean;
169
282
  }) => void;
170
- advanceAnimations: (dt: number) => void;
171
283
  inputConstraints: Record<string, {
172
284
  min?: number;
173
285
  max?: number;
@@ -179,29 +291,107 @@ type VizijRuntimeProviderProps = {
179
291
  children: ReactNode;
180
292
  namespace?: string;
181
293
  faceId?: string;
294
+ updateTier?: RuntimeUpdateTier;
182
295
  autoCreate?: boolean;
183
- createOptions?: CreateOrchOptions;
184
296
  autostart?: boolean;
185
- driveOrchestrator?: boolean;
297
+ /**
298
+ * Whether this provider's device paces itself: when true the device is
299
+ * handed to its own `run()` loop at boot and the provider only pumps its
300
+ * changes; when false the device advances solely on `step(dt,
301
+ * { forceRuntime: true })` calls from the host. A device handed to `run()`
302
+ * keeps its loop even if this later turns false.
303
+ */
304
+ driveRuntime?: boolean;
186
305
  mergeStrategy?: MergeStrategyOptions;
187
306
  onRegisterControllers?: (ids: {
188
307
  graphs: string[];
189
308
  anims: string[];
190
309
  }) => void;
191
310
  onStatusChange?: (status: VizijRuntimeStatus) => void;
192
- orchestratorScope?: "auto" | "shared" | "isolated";
311
+ transformOutputWrite?: (write: RuntimeOutputWrite) => RuntimeOutputWrite | null;
312
+ };
313
+ type RuntimeUpdateTier = "auto" | "assets" | "graphs";
314
+ type RuntimeUpdatePlan = {
315
+ reloadAssets: boolean;
316
+ reregisterGraphs: boolean;
317
+ };
318
+ type RuntimeGraphBundle = {
319
+ rig?: VizijGraphAsset;
320
+ pose?: VizijAssetBundle["pose"];
321
+ animations?: VizijAnimationAsset[];
322
+ programs?: VizijProgramAsset[];
193
323
  };
194
324
 
195
325
  type ProviderProps = PropsWithChildren<VizijRuntimeProviderProps>;
196
- declare function VizijRuntimeProvider({ assetBundle, children, namespace: namespaceProp, faceId: faceIdProp, autoCreate, createOptions, autostart, driveOrchestrator, mergeStrategy, onRegisterControllers, onStatusChange, orchestratorScope, }: ProviderProps): react_jsx_runtime.JSX.Element;
326
+ declare function VizijRuntimeProvider({ assetBundle, children, namespace: namespaceProp, faceId: faceIdProp, updateTier, autoCreate, autostart, driveRuntime, mergeStrategy, onRegisterControllers, onStatusChange, transformOutputWrite, }: ProviderProps): react_jsx_runtime.JSX.Element;
197
327
 
198
328
  declare function VizijRuntimeFaceInner({ namespaceOverride, ...props }: VizijRuntimeFaceProps): react_jsx_runtime.JSX.Element | null;
199
329
  declare const VizijRuntimeFace: react.MemoExoticComponent<typeof VizijRuntimeFaceInner>;
200
330
 
201
331
  declare function useVizijRuntime(): VizijRuntimeContextValue;
202
332
 
333
+ declare function useOptionalVizijRuntime(): VizijRuntimeContextValue | null;
334
+
203
335
  declare function useVizijOutputs(paths: string[]): Record<string, RawValue | undefined>;
204
336
 
205
337
  declare function useRigInput(path: string): [RawValue | undefined, (value: ValueJSON, shape?: ShapeJSON) => void];
206
338
 
207
- export { type AnimateValueOptions, type AnimationClipLike, type AnimationKeyframeLike, type AnimationTrackLike, type InputDriverContext, type InputDriverFactory, type InputDriverLifecycle, type PlayAnimationOptions, type PoseDefinition, type PoseRigConfig, type RootBounds, type VizijAnimationAsset, type VizijAssetBundle, type VizijGlbAsset, type VizijGraphAsset, VizijRuntimeFace, type VizijRuntimeFaceProps, VizijRuntimeProvider, type VizijRuntimeProviderProps, type VizijRuntimeStatus, useRigInput, useVizijOutputs, useVizijRuntime };
339
+ declare function resolveRuntimeUpdatePlan(previous: VizijAssetBundle | null, next: VizijAssetBundle, tier: RuntimeUpdateTier): RuntimeUpdatePlan;
340
+
341
+ declare const POSE_WEIGHT_INPUT_PATH_PREFIX = "/poses/";
342
+ declare const VISEME_POSE_KEYS: readonly ["a", "at", "b", "e", "e_2", "f", "i", "k", "m", "o", "o_2", "p", "r", "s", "t", "t_2", "u"];
343
+ declare const EXPRESSIVE_EMOTION_POSE_KEYS: readonly ["concerned", "happy", "sad", "sleepy", "surprise"];
344
+ declare const EMOTION_POSE_KEYS: readonly ["concerned", "happy", "neutral", "sad", "sleepy", "surprise", "angry"];
345
+ type PoseSemanticKind = "emotion" | "viseme" | "other";
346
+ declare function buildRigInputPath(faceId: string, path: string): string;
347
+ declare function buildPoseWeightInputPathSegment(poseId: string | null | undefined): string;
348
+ declare function buildPoseWeightRelativePath(poseId: string | null | undefined): string;
349
+ declare function buildPoseWeightPathMap(poses: PoseDefinition[], faceId: string | null | undefined): Map<string, string>;
350
+ declare function normalizePoseSemanticKey(value: string | null | undefined): string | null;
351
+ declare function getPoseSemanticKey(pose: Pick<PoseDefinition, "id" | "name">): string | null;
352
+ declare function resolvePoseMembership(pose: Pick<PoseDefinition, "group" | "groupId" | "groupIds">, groups: PoseGroupDefinition[] | undefined): {
353
+ groupIds: string[];
354
+ primaryGroupId: string | null;
355
+ primaryGroupPath: string | null;
356
+ groupPathsById: Record<string, string>;
357
+ };
358
+ declare function resolvePoseSemantics(pose: Pick<PoseDefinition, "id" | "name" | "group" | "groupId" | "groupIds">, groups: PoseGroupDefinition[] | undefined): {
359
+ key: string | null;
360
+ kind: PoseSemanticKind;
361
+ membership: ReturnType<typeof resolvePoseMembership>;
362
+ };
363
+ declare function filterPosesBySemanticKind(poses: PoseDefinition[], groups: PoseGroupDefinition[] | undefined, kind: PoseSemanticKind): PoseDefinition[];
364
+ declare function buildSemanticPoseWeightPathMap(poses: PoseDefinition[], groups: PoseGroupDefinition[] | undefined, faceId: string | null | undefined, kind: Exclude<PoseSemanticKind, "other">): Map<string, string>;
365
+
366
+ type InputConstraint = {
367
+ min?: number;
368
+ max?: number;
369
+ defaultValue?: number;
370
+ };
371
+ type FaceScalarControl = {
372
+ path: string;
373
+ min: number;
374
+ max: number;
375
+ defaultValue: number;
376
+ };
377
+ type ResolvedFaceControls = {
378
+ faceId: string;
379
+ gazeSource: "standard-vizij" | "standard" | "propsrig" | "coupled-gaze" | "none";
380
+ blinkSource: "lids" | "blink" | "none";
381
+ eyes: {
382
+ leftX: FaceScalarControl | null;
383
+ leftY: FaceScalarControl | null;
384
+ rightX: FaceScalarControl | null;
385
+ rightY: FaceScalarControl | null;
386
+ };
387
+ eyelids: {
388
+ leftUpper: FaceScalarControl | null;
389
+ rightUpper: FaceScalarControl | null;
390
+ };
391
+ blink: FaceScalarControl | null;
392
+ };
393
+ declare function resolveFaceControls(assetBundle: VizijAssetBundle, runtimeFaceId?: string | null, inputConstraints?: Record<string, InputConstraint>): ResolvedFaceControls;
394
+ declare function mapNormalizedControlValue(control: FaceScalarControl, normalizedValue: number): number;
395
+ declare function mapUnitControlValue(control: FaceScalarControl, unitValue: number): number;
396
+
397
+ export { type AnimateValueOptions, type AnimationClipLike, type AnimationKeyframeLike, type AnimationPlaybackState, type AnimationTrackLike, EMOTION_POSE_KEYS, EXPRESSIVE_EMOTION_POSE_KEYS, type FaceScalarControl, type InputDriverContext, type InputDriverFactory, type InputDriverLifecycle, POSE_WEIGHT_INPUT_PATH_PREFIX, type PlayAnimationOptions, type PoseDefinition, type PoseGroupDefinition, type PoseRigConfig, type ProgramPlaybackState, type RootBounds, type RuntimeGraphBundle, type RuntimeOutputWrite, type RuntimeUpdatePlan, type RuntimeUpdateTier, type StopProgramOptions, VISEME_POSE_KEYS, type VizijAnimationAsset, type VizijAssetBundle, type VizijGlbAsset, type VizijGraphAsset, type VizijProgramAsset, VizijRuntimeFace, type VizijRuntimeFaceProps, VizijRuntimeProvider, type VizijRuntimeProviderProps, type VizijRuntimeStatus, buildPoseWeightInputPathSegment, buildPoseWeightPathMap, buildPoseWeightRelativePath, buildRigInputPath, buildSemanticPoseWeightPathMap, filterPosesBySemanticKind, getPoseSemanticKey, mapNormalizedControlValue, mapUnitControlValue, normalizePoseSemanticKey, resolveFaceControls, resolvePoseMembership, resolvePoseSemantics, resolveRuntimeUpdatePlan, useOptionalVizijRuntime, useRigInput, useVizijOutputs, useVizijRuntime };