@lovelace_lol/polymer 0.0.1

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.
Files changed (85) hide show
  1. package/README.md +226 -0
  2. package/dist/index.d.ts +2603 -0
  3. package/dist/index.js +1031 -0
  4. package/dist/test.cjs +1519 -0
  5. package/dist/worker/agency-worker.js +972 -0
  6. package/dist/worker/manifest.edn +1 -0
  7. package/package.json +57 -0
  8. package/shadow-cljs.edn +173 -0
  9. package/src/polymer/animation/agency.cljs +84 -0
  10. package/src/polymer/animation/domain.cljs +110 -0
  11. package/src/polymer/animation/planner.cljs +88 -0
  12. package/src/polymer/animation/runtime.cljs +137 -0
  13. package/src/polymer/animation/scheduler.cljs +178 -0
  14. package/src/polymer/animation/service.cljs +981 -0
  15. package/src/polymer/animation/state.cljs +112 -0
  16. package/src/polymer/blink/agency.cljs +131 -0
  17. package/src/polymer/blink/planner.cljs +115 -0
  18. package/src/polymer/blink/scheduler.cljs +90 -0
  19. package/src/polymer/blink/snippet.cljs +50 -0
  20. package/src/polymer/blink/state.cljs +102 -0
  21. package/src/polymer/camera_context/agency.cljs +132 -0
  22. package/src/polymer/camera_context/domain.cljs +186 -0
  23. package/src/polymer/camera_context/planner.cljs +50 -0
  24. package/src/polymer/camera_context/scheduler.cljs +113 -0
  25. package/src/polymer/camera_context/state.cljs +121 -0
  26. package/src/polymer/character.cljs +471 -0
  27. package/src/polymer/conversation/agency.cljs +83 -0
  28. package/src/polymer/conversation/domain.cljs +35 -0
  29. package/src/polymer/conversation/effector.cljs +130 -0
  30. package/src/polymer/conversation/planner.cljs +178 -0
  31. package/src/polymer/conversation/scheduler.cljs +202 -0
  32. package/src/polymer/conversation/service.cljs +329 -0
  33. package/src/polymer/conversation/state.cljs +186 -0
  34. package/src/polymer/core.cljs +172 -0
  35. package/src/polymer/eye_head/agency.cljs +75 -0
  36. package/src/polymer/eye_head/domain.cljs +133 -0
  37. package/src/polymer/eye_head/goap.cljs +106 -0
  38. package/src/polymer/eye_head/scheduler.cljs +176 -0
  39. package/src/polymer/eye_head/service.cljs +259 -0
  40. package/src/polymer/eye_head/snippet.cljs +92 -0
  41. package/src/polymer/eye_head/state.cljs +167 -0
  42. package/src/polymer/gaze/agency.cljs +85 -0
  43. package/src/polymer/gaze/domain.cljs +211 -0
  44. package/src/polymer/gaze/goap.cljs +208 -0
  45. package/src/polymer/gaze/scheduler.cljs +184 -0
  46. package/src/polymer/gaze/state.cljs +202 -0
  47. package/src/polymer/gesture/agency.cljs +185 -0
  48. package/src/polymer/gesture/goap.cljs +461 -0
  49. package/src/polymer/gesture/scheduler.cljs +122 -0
  50. package/src/polymer/gesture/snippet.cljs +198 -0
  51. package/src/polymer/gesture/state.cljs +273 -0
  52. package/src/polymer/lipsync/agency.cljs +593 -0
  53. package/src/polymer/lipsync/articulation/jaw.cljs +258 -0
  54. package/src/polymer/lipsync/articulation/snippet.cljs +605 -0
  55. package/src/polymer/lipsync/articulation/tongue.cljs +418 -0
  56. package/src/polymer/lipsync/articulation/visemes.cljs +429 -0
  57. package/src/polymer/lipsync/goap.cljs +132 -0
  58. package/src/polymer/lipsync/pronunciation/effector.cljs +51 -0
  59. package/src/polymer/lipsync/scheduler.cljs +302 -0
  60. package/src/polymer/lipsync/state.cljs +202 -0
  61. package/src/polymer/nlp/phonemes.cljs +164 -0
  62. package/src/polymer/prosodic/agency.cljs +196 -0
  63. package/src/polymer/prosodic/goap.cljs +122 -0
  64. package/src/polymer/prosodic/scheduler.cljs +99 -0
  65. package/src/polymer/prosodic/snippet.cljs +106 -0
  66. package/src/polymer/prosodic/state.cljs +139 -0
  67. package/src/polymer/runtime/embody.cljs +117 -0
  68. package/src/polymer/runtime/embody_wasm.cljs +177 -0
  69. package/src/polymer/runtime/rust_embody_host.cljs +645 -0
  70. package/src/polymer/society.cljs +239 -0
  71. package/src/polymer/stream.cljs +130 -0
  72. package/src/polymer/transcription/agency.cljs +69 -0
  73. package/src/polymer/transcription/domain.cljs +68 -0
  74. package/src/polymer/transcription/effector.cljs +611 -0
  75. package/src/polymer/transcription/planner.cljs +203 -0
  76. package/src/polymer/transcription/scheduler.cljs +225 -0
  77. package/src/polymer/transcription/service.cljs +209 -0
  78. package/src/polymer/transcription/state.cljs +239 -0
  79. package/src/polymer/tts/agency.cljs +503 -0
  80. package/src/polymer/tts/azure.cljs +290 -0
  81. package/src/polymer/tts/planner.cljs +178 -0
  82. package/src/polymer/tts/runtime.cljs +624 -0
  83. package/src/polymer/tts/scheduler.cljs +162 -0
  84. package/src/polymer/tts/state.cljs +191 -0
  85. package/src/polymer/worker.cljs +70 -0
@@ -0,0 +1,2603 @@
1
+ import type {
2
+ Embody,
3
+ EmbodyRuntime,
4
+ HairAppearanceState,
5
+ HairColorAppearance,
6
+ HairPhysicsRuntimeConfig,
7
+ HairPhysicsRuntimeConfigUpdate,
8
+ MeshInfo,
9
+ Profile,
10
+ } from '@lovelace_lol/embody';
11
+ import type { Object3D } from 'three';
12
+
13
+ /** Direct Embody Wasm core accessors (via @lovelace_lol/embody/wasm). */
14
+ export declare function initEmbodyCore(): Promise<EmbodyCoreWasmModule>;
15
+ export declare function isEmbodyCoreReady(): boolean;
16
+ export declare function getEmbodyCore(): EmbodyCoreWasmModule;
17
+ export declare function coreAbiVersion(): number;
18
+ export declare function packMorphFrameDelta(
19
+ meshIds: Uint32Array,
20
+ morphTargetIds: Uint32Array,
21
+ values: Float32Array,
22
+ modes: Uint8Array
23
+ ): Float32Array;
24
+ export declare function solveBilateralValues(base: number, balance: number): Float32Array;
25
+ export declare function solveMorphBatch(
26
+ values: Float32Array,
27
+ balances: Float32Array,
28
+ mixWeights: Float32Array
29
+ ): Float32Array;
30
+ export declare function solveAxisQuaternion(
31
+ axis: number,
32
+ degrees: number,
33
+ value: number,
34
+ scale: number
35
+ ): Float32Array;
36
+ export declare function analyzeMeshProportions(
37
+ vertices: Float32Array,
38
+ verticalAxis: number
39
+ ): Float32Array;
40
+ export declare function solveTemplateSkeletonFit(
41
+ meshVertices: Float32Array,
42
+ templateBounds: Float32Array,
43
+ verticalAxis: number,
44
+ verticalAnchor: number
45
+ ): Float32Array;
46
+ export declare function composeTemplateFitAdjustment(
47
+ fit: Float32Array,
48
+ scaleMultiplier: number,
49
+ offsetX: number,
50
+ offsetY: number,
51
+ offsetZ: number
52
+ ): Float32Array;
53
+ export declare function composeTemplateSkeletonFitTransform(
54
+ fitScale: number,
55
+ fitTranslation: Float32Array,
56
+ manualScale: number,
57
+ manualTranslation: Float32Array
58
+ ): Float32Array;
59
+ export declare function defaultHairPhysicsConfigValues(): Float32Array;
60
+ export declare function createHairPhysicsSolver(configValues?: Float32Array): WasmHairPhysicsSolver;
61
+ export declare function createRuntimeCore(visemeSlotCount: number): WasmRuntimeCore;
62
+ export declare const EMBODY_CORE_ABI_VERSION: number;
63
+ export declare const PACKED_MORPH_FRAME_DELTA_STRIDE: number;
64
+ export declare const HAIR_CONFIG_STRIDE: number;
65
+ export declare const HAIR_STATE_STRIDE: number;
66
+ export declare const HAIR_HEAD_STATE_STRIDE: number;
67
+ export declare const HAIR_MORPH_OUTPUT_STRIDE: number;
68
+ export declare const MESH_PROPORTIONS_STRIDE: number;
69
+ export declare const TEMPLATE_SKELETON_FIT_SOLUTION_STRIDE: number;
70
+ export declare const TEMPLATE_SKELETON_FIT_TRANSFORM_STRIDE: number;
71
+
72
+ export interface WasmHairPhysicsSolver {
73
+ update(dtSeconds: number, headValues: Float32Array): Float32Array;
74
+ set_config(configValues: Float32Array): void;
75
+ get_config(): Float32Array;
76
+ get_state(): Float32Array;
77
+ reset(): void;
78
+ free?: () => void;
79
+ }
80
+
81
+ export interface WasmRuntimeCore {
82
+ configure(profileJson: string, modelJson: string): void;
83
+ configure_with_preset(presetId: string, overrideJson: string, modelJson: string): void;
84
+ viseme_slot_index(slotId: string): number;
85
+ load_au_morph_bindings(values: Float32Array): void;
86
+ load_viseme_morph_bindings(values: Float32Array): void;
87
+ load_bone_rest_transforms(values: Float32Array): void;
88
+ load_composite_axes(values: Float32Array): void;
89
+ load_bone_translations(values: Float32Array): void;
90
+ load_jaw_binding(values: Float32Array): void;
91
+ load_viseme_jaw_amounts(values: Float32Array): void;
92
+ set_mixed_aus(ids: Uint32Array): void;
93
+ set_au(id: number, value: number, balance: number): void;
94
+ set_au_signed(id: number, value: number, balance: number): void;
95
+ get_au(id: number): number;
96
+ set_continuum(negAu: number, posAu: number, value: number, balance: number): void;
97
+ get_continuum(negAu: number, posAu: number): number;
98
+ set_au_mix_weight(id: number, weight: number): void;
99
+ set_viseme(index: number, value: number): void;
100
+ set_viseme_jaw_scale(index: number, jawScale: number): void;
101
+ set_viseme_slot_count(count: number): void;
102
+ transition_au(id: number, to: number, durationMs: number, balance: number): void;
103
+ transition_viseme(index: number, to: number, durationMs: number, jawScale: number): void;
104
+ update(dtSeconds: number): number;
105
+ active_transition_count(): number;
106
+ clear_transitions(): void;
107
+ clear(): void;
108
+ evaluate_morph_frame_delta(): Float32Array;
109
+ evaluate_bone_frame_delta(): Float32Array;
110
+ free?: () => void;
111
+ }
112
+
113
+ export interface EmbodyCoreWasmModule {
114
+ core_abi_version(): number;
115
+ pack_morph_frame_delta(
116
+ meshIds: Uint32Array,
117
+ morphTargetIds: Uint32Array,
118
+ values: Float32Array,
119
+ modes: Uint8Array
120
+ ): Float32Array;
121
+ solve_bilateral_values(base: number, balance: number): Float32Array;
122
+ solve_morph_batch(values: Float32Array, balances: Float32Array, mixWeights: Float32Array): Float32Array;
123
+ solve_axis_quaternion(axis: number, degrees: number, value: number, scale: number): Float32Array;
124
+ analyze_mesh_proportions(vertices: Float32Array, verticalAxis: number): Float32Array;
125
+ solve_template_skeleton_fit(
126
+ meshVertices: Float32Array,
127
+ templateBounds: Float32Array,
128
+ verticalAxis: number,
129
+ verticalAnchor: number
130
+ ): Float32Array;
131
+ compose_template_fit_adjustment(
132
+ fit: Float32Array,
133
+ scaleMultiplier: number,
134
+ offsetX: number,
135
+ offsetY: number,
136
+ offsetZ: number
137
+ ): Float32Array;
138
+ compose_template_skeleton_fit_transform(
139
+ fitScale: number,
140
+ fitTranslation: Float32Array,
141
+ manualScale: number,
142
+ manualTranslation: Float32Array
143
+ ): Float32Array;
144
+ default_hair_physics_config_values(): Float32Array;
145
+ list_presets(): string[];
146
+ has_preset(presetId: string): boolean;
147
+ get_preset_json(presetId: string): string;
148
+ merge_embedded_preset(presetId: string, overrideJson: string): string;
149
+ HairPhysicsSolver: new (configValues: Float32Array) => WasmHairPhysicsSolver;
150
+ RuntimeCore: new (visemeSlotCount: number) => WasmRuntimeCore;
151
+ }
152
+
153
+ export type RustEmbodyProfileMode = 'embedded-preset' | 'exact-profile';
154
+
155
+ export interface RustEmbodyHostConfig {
156
+ profile?: Partial<Profile>;
157
+ presetType?: string;
158
+ profileMode?: RustEmbodyProfileMode;
159
+ meshes?: unknown[];
160
+ }
161
+
162
+ /**
163
+ * Polymer's CLJS-owned character runtime contract.
164
+ *
165
+ * Rust owns profile intake and frame evaluation. The remaining methods are the
166
+ * public Three.js and AnimationMixer capabilities consumed by application
167
+ * hosts; no concrete TypeScript Embody class is implied.
168
+ */
169
+ export interface PolymerCharacterRuntime {
170
+ readonly meshes: unknown[];
171
+ readonly meshByName: Map<string, unknown>;
172
+ readonly bones: Record<string, unknown>;
173
+ onReady(options: { model: unknown; meshes?: unknown[] }): void;
174
+ bindModel(meshes?: unknown[]): void;
175
+ setProfile(profile: Profile): void;
176
+ getProfile(): Profile;
177
+ getProfileMode(): RustEmbodyProfileMode;
178
+ supportsPreset(presetId?: string): boolean;
179
+ setAU(id: number, value: number, balance?: number): void;
180
+ getAU(id: number): number;
181
+ setContinuum(negAU: number, posAU: number, value: number, balance?: number): void;
182
+ getContinuum(negAU: number, posAU: number): number;
183
+ transitionAU(id: number, to: number, durationMs?: number, balance?: number): void;
184
+ setViseme(index: number, value: number, jawScale?: number): void;
185
+ setVisemeById(slotId: string, value: number, jawScale?: number): void;
186
+ transitionViseme(index: number, to: number, durationMs?: number, jawScale?: number): void;
187
+ transitionVisemeById(slotId: string, to: number, durationMs?: number, jawScale?: number): void;
188
+ setAUMixWeight(id: number, weight: number): void;
189
+ getAUMixWeight(id: number): number;
190
+ hasLeftRightBones(id: number): boolean;
191
+ setMorph(key: string | number, value: number, meshNames?: string[]): void;
192
+ setMorphOnMeshes(meshNames: string[], key: string | number, value: number): void;
193
+ transitionMorph(
194
+ key: string | number,
195
+ value: number,
196
+ durationMs?: number,
197
+ meshNames?: string[]
198
+ ): ReturnType<Embody['transitionMorph']>;
199
+ getMorphTargets(): Record<string, string[]>;
200
+ getMorphTargetIndices(): Record<string, Array<{ index: number; name: string }>>;
201
+ getHairMorphTargets(meshName: string): string[];
202
+ getHairMorphTargets(): string[];
203
+ getMeshList(): MeshInfo[];
204
+ getBones(): Record<string, unknown>;
205
+ setMeshVisible(meshName: string, visible: boolean): void;
206
+ highlightMesh(meshName: string | null, color?: number, intensity?: number): void;
207
+ getMeshMaterialConfig(meshName: string): ReturnType<Embody['getMeshMaterialConfig']>;
208
+ setMeshMaterialConfig(
209
+ meshName: string,
210
+ config: Parameters<Embody['setMeshMaterialConfig']>[1]
211
+ ): void;
212
+ registerHairObjects(
213
+ objects: Object3D[]
214
+ ): Array<{ name: string; isMesh: boolean; isEyebrow: boolean }>;
215
+ getRegisteredHairObjects(): Object3D[];
216
+ getHairAppearance(): HairAppearanceState;
217
+ setHairColor(color: HairColorAppearance | string): void;
218
+ setEyebrowColor(color: HairColorAppearance | string): void;
219
+ setHairBaseColor(baseColor: string): void;
220
+ setEyebrowBaseColor(baseColor: string): void;
221
+ setHairGlow(emissive: string, intensity: number): void;
222
+ setEyebrowGlow(emissive: string, intensity: number): void;
223
+ setHairOutline(outline: { show: boolean; color?: string; opacity?: number }): void;
224
+ setHairPhysicsEnabled(enabled: boolean): void;
225
+ isHairPhysicsEnabled(): boolean;
226
+ setHairPhysicsConfig(config: HairPhysicsRuntimeConfigUpdate): void;
227
+ getHairPhysicsConfig(): HairPhysicsRuntimeConfig;
228
+ validateHairMorphTargets(): string[];
229
+ updateHairPhysics(dtSeconds: number): void;
230
+ loadAnimationClips(clips: unknown[]): void;
231
+ getAnimationClips(): ReturnType<Embody['getAnimationClips']>;
232
+ playAnimation(
233
+ clipName: string,
234
+ options?: Parameters<Embody['playAnimation']>[1]
235
+ ): ReturnType<Embody['playAnimation']>;
236
+ stopAnimation(clipName: string): void;
237
+ stopAllAnimations(): void;
238
+ playTypedSnippet(
239
+ snippet: Parameters<Embody['playTypedSnippet']>[0],
240
+ options?: Parameters<Embody['playTypedSnippet']>[1]
241
+ ): ReturnType<Embody['playTypedSnippet']>;
242
+ buildTypedClip(
243
+ clipName: string,
244
+ channels: Parameters<Embody['buildTypedClip']>[1],
245
+ options?: Parameters<Embody['buildTypedClip']>[2]
246
+ ): ReturnType<Embody['buildTypedClip']>;
247
+ buildClip(
248
+ clipName: string,
249
+ curves: Parameters<Embody['buildClip']>[1],
250
+ options?: Parameters<Embody['buildClip']>[2]
251
+ ): ReturnType<Embody['buildClip']>;
252
+ cleanupSnippet(name: string): void;
253
+ update(dtSeconds: number): void;
254
+ start(): void;
255
+ stop(): void;
256
+ clear(): void;
257
+ resetToNeutral(): void;
258
+ dispose(): void;
259
+ }
260
+
261
+ export declare function createRustEmbodyHost(
262
+ model: unknown,
263
+ config?: RustEmbodyHostConfig
264
+ ): Promise<PolymerCharacterRuntime>;
265
+
266
+ export declare function createRustEmbodyHostUnbound(
267
+ config?: RustEmbodyHostConfig
268
+ ): PolymerCharacterRuntime;
269
+
270
+ export declare function supportsRustEmbodyPreset(presetId?: string): boolean;
271
+
272
+ export {
273
+ Embody,
274
+ BLENDING_MODES,
275
+ THREE_BLENDING_MODES,
276
+ collectMorphMeshes,
277
+ analyzeModel,
278
+ extractModelData,
279
+ getPreset,
280
+ validateMappings,
281
+ extendCharacterConfigWithPreset,
282
+ extractProfileOverrides,
283
+ mergeCharacterRegionsByName,
284
+ applyAUBoneBindingUpdate,
285
+ applyBilateralAxisBindingUpdate,
286
+ applyBoneAxisBindingUpdate,
287
+ buildBoneAuOptions,
288
+ classifyAuAsJointControl,
289
+ createBilateralBoneAxisAu,
290
+ createBoneAxisAu,
291
+ DEFAULT_AXIS_TO_CHANNEL,
292
+ DEFAULT_BONE_MAX_DEGREES,
293
+ ensureBilateralBoneNodeKeys,
294
+ ensureBoneNodeKey,
295
+ findNodeKeyForBone,
296
+ formatAxisDirectionLabel,
297
+ formatAxisLabel,
298
+ getAUBoneBindingState,
299
+ getAxisFromChannel,
300
+ getBilateralAxisBindingState,
301
+ getBoneAxisBindingState,
302
+ inferChiralBoneNamePair,
303
+ inferEyeControlFamily,
304
+ inferEyeControlScope,
305
+ isJointControlAuInfo,
306
+ isMaxDegreesOnlyAxisBindingUpdate,
307
+ JOINT_CONTROL_SECTION,
308
+ resolveBoneAxisChannel,
309
+ resolveBoneNameForNodeKey,
310
+ resolveContinuumDisplayLabel,
311
+ stripConfiguredBoneAffixes,
312
+ computeCameraRelativeGazeOffset,
313
+ detectAnnotationLaterality,
314
+ fuzzyNameMatch,
315
+ getDefaultAnnotationLaterality,
316
+ getMeshNamesForAUProfile,
317
+ getModelLocalOrbitAngle,
318
+ getSemanticHorizontalSign,
319
+ getSemanticHorizontalSignForSide,
320
+ getWorldDirectionForCameraAngle,
321
+ hasLeftRightMorphs,
322
+ isMixedAU,
323
+ passesMarkerCameraAngleGate,
324
+ resolveBoneNames,
325
+ resolveFaceCenter,
326
+ resolveRegionCameraAngle,
327
+ resolveRegionVisibilityCameraAngle,
328
+ toWorldDirection,
329
+ RustAnnotationCameraCore,
330
+ createRustAnnotationCameraCore,
331
+ CC4_BONES,
332
+ VISEME_KEYS,
333
+ HAIR_COLOR_PRESETS,
334
+ DEFAULT_HAIR_COLOR_APPEARANCE,
335
+ normalizeHairColorAppearance,
336
+ HUMANOID_SKELETON_TEMPLATES,
337
+ JONATHAN_HUMANOID_SKELETON_TEMPLATE,
338
+ getHumanoidSkeletonTemplate,
339
+ getHumanoidSkeletonTemplateBoneNames,
340
+ createValidationSkeletonFromHumanoidTemplate,
341
+ computeHumanoidSkeletonTemplateRestBounds,
342
+ extractHumanoidSkeletonTemplateFromModel,
343
+ createCharacterHost,
344
+ createDefaultCharacterScene,
345
+ createDefaultCharacterLighting,
346
+ createShadowPlane,
347
+ loadCharacterModel,
348
+ parseCharacterModel,
349
+ applyCharacterModelTransform,
350
+ disposeCharacterModel,
351
+ DEFAULT_CHARACTER_LIGHTING_PRESET_ID,
352
+ DEFAULT_CHARACTER_LIGHTING_PRESET_IDS,
353
+ DEFAULT_CHARACTER_LIGHTING_PRESETS,
354
+ DEFAULT_CHARACTER_LIGHTING_SETTINGS,
355
+ normalizeDefaultCharacterLightingSettings,
356
+ CHARACTER_SCENE_TYPES,
357
+ CHARACTER_SCENE_TYPE_IDS,
358
+ DEFAULT_CHARACTER_SCENE_TYPE_ID,
359
+ } from '@lovelace_lol/embody';
360
+
361
+ export type {
362
+ CharacterHost,
363
+ CharacterHostCharacterOptions,
364
+ CharacterHostExternalScene,
365
+ CharacterHostOptions,
366
+ CharacterModelLoadOptions,
367
+ CharacterModelLoadResult,
368
+ CharacterModelTransform,
369
+ CharacterSceneTypeDefinition,
370
+ CharacterSceneTypeId,
371
+ DefaultCharacterLightingController,
372
+ DefaultCharacterLightingPresetId,
373
+ DefaultCharacterLightingSettings,
374
+ DefaultCharacterScene,
375
+ DefaultCharacterSceneOptions,
376
+ HairAppearanceState,
377
+ HairColorAppearance,
378
+ HairPhysicsRuntimeConfig,
379
+ HairPhysicsRuntimeConfigUpdate,
380
+ MarkerEndpointSeparationOptions,
381
+ } from '@lovelace_lol/embody';
382
+
383
+ export type {
384
+ AUBoneBindingState,
385
+ AUInfo,
386
+ AnimationClipInfo,
387
+ AnimationInfo,
388
+ AnnotationLaterality,
389
+ BilateralAxisBindingState,
390
+ BilateralAxisDirectionScaleState,
391
+ BilateralAxisScopeBindingState,
392
+ BilateralBoneAxisScope,
393
+ BoneAxisBindingState,
394
+ BoneAxisBindingUpdate,
395
+ BoneAxisDirection,
396
+ BoneAxisDirectionScale,
397
+ BoneAxisKey,
398
+ BoneBinding,
399
+ BoneControlFamily,
400
+ BoneControlScope,
401
+ BoneInfo,
402
+ CameraRelativeGazeOffset,
403
+ CameraRelativeGazeOptions,
404
+ CharacterConfig,
405
+ CharacterRegistry,
406
+ ChiralBoneNamePair,
407
+ CompositeRotation,
408
+ CreatedBoneAxisAu,
409
+ ExpandAnimation,
410
+ ExpandedRegionState,
411
+ FallbackConfig,
412
+ LineConfig,
413
+ LineCurve,
414
+ LineStyle,
415
+ EmbodyRuntime,
416
+ MarkerGroup,
417
+ MarkerStyle,
418
+ MarkerStyleOverrides,
419
+ MeshInfo,
420
+ ModelAnalysisReport,
421
+ ModelData,
422
+ MorphTargetsBySide,
423
+ NamedDirection,
424
+ PresetType,
425
+ Profile,
426
+ Region,
427
+ RotationAxis,
428
+ RotationChannel,
429
+ TrackInfo,
430
+ TransitionHandle,
431
+ ValidationResult,
432
+ VisemeSlot,
433
+ HumanoidSkeletonTemplate,
434
+ HumanoidSkeletonTemplateBone,
435
+ HumanoidSkeletonTemplateBounds,
436
+ HumanoidSkeletonTemplateVec3,
437
+ } from '@lovelace_lol/embody';
438
+
439
+ export interface BlinkState {
440
+ agency: 'blink';
441
+ enabled: boolean;
442
+ frequency: number;
443
+ duration: number;
444
+ intensity: number;
445
+ randomness: number;
446
+ leftEyeIntensity: number | null;
447
+ rightEyeIntensity: number | null;
448
+ burstEnabled: boolean;
449
+ burstFrequency: number;
450
+ burstCount: number;
451
+ burstGap: number;
452
+ lastBlinkTime: number | null;
453
+ scheduledBlinkCount: number;
454
+ scheduledBurstCount: number;
455
+ }
456
+
457
+ export type BlinkAgencyConfig = Partial<Omit<BlinkState, 'agency'>>;
458
+
459
+ export interface GazeTarget {
460
+ x: number;
461
+ y: number;
462
+ z?: number;
463
+ }
464
+
465
+ export interface GazeConfig {
466
+ enabled?: boolean;
467
+ eyesEnabled?: boolean;
468
+ headEnabled?: boolean;
469
+ headFollowEyes?: boolean;
470
+ mirrored?: boolean;
471
+ smoothFactor?: number;
472
+ minDelta?: number;
473
+ transitionDurationMs?: number;
474
+ eyeIntensity?: number;
475
+ headIntensity?: number;
476
+ coalesceMs?: number;
477
+ }
478
+
479
+ export interface GazeState {
480
+ agency: 'gaze';
481
+ status: string;
482
+ mode: string;
483
+ active: boolean;
484
+ rawTarget: Required<GazeTarget>;
485
+ target: Required<GazeTarget>;
486
+ baseTarget: Required<GazeTarget>;
487
+ cameraRelativeOffset: Required<GazeTarget>;
488
+ lastCameraFact: null | Record<string, unknown>;
489
+ lastRequestedTarget: Required<GazeTarget>;
490
+ pendingRequest: GazeLookRequest | null;
491
+ lastRequest: GazeLookRequest | GazeResetRequest | null;
492
+ lastIgnored: null | Record<string, unknown>;
493
+ lastPlan: null | Record<string, unknown>;
494
+ lastEvent: null | Record<string, unknown>;
495
+ receivedCount: number;
496
+ plannedCount: number;
497
+ requestedCount: number;
498
+ ignoredCount: number;
499
+ resetCount: number;
500
+ cancelCount: number;
501
+ config: Required<GazeConfig>;
502
+ }
503
+
504
+ export interface GazeApplyOptions {
505
+ eyeEnabled?: boolean;
506
+ headEnabled?: boolean;
507
+ headFollowEyes?: boolean;
508
+ force?: boolean;
509
+ }
510
+
511
+ export interface GazeAttentionCandidate {
512
+ target?: GazeTarget;
513
+ gazeTarget?: GazeTarget;
514
+ lookTarget?: GazeTarget;
515
+ x?: number;
516
+ y?: number;
517
+ z?: number;
518
+ priority?: number;
519
+ weight?: number;
520
+ confidence?: number;
521
+ source?: string;
522
+ label?: string;
523
+ id?: string;
524
+ }
525
+
526
+ export type GazeDispatch =
527
+ | { type: 'configure'; config: GazeConfig }
528
+ | { type: 'setMode' | 'set-mode'; mode: string }
529
+ | { type: 'setActive' | 'set-active'; active: boolean }
530
+ | { type: 'enable' }
531
+ | { type: 'disable' }
532
+ | { type: 'setTarget' | 'set-target' | 'focusTarget'; target: GazeTarget; options?: GazeApplyOptions }
533
+ | { type: 'attention.fact'; targets?: GazeAttentionCandidate[]; target?: GazeTarget; source?: string }
534
+ | { type: 'camera.fact'; relativeOffset: GazeTarget; source?: string }
535
+ | { type: 'camera.stale' | 'clearCameraOffset'; reason?: string; source?: string }
536
+ | { type: 'reset'; durationMs?: number; eyes?: boolean; head?: boolean }
537
+ | { type: 'cancel'; reason?: string };
538
+
539
+ export interface GazeLookRequest {
540
+ type: 'eyeHeadTracking.requestGaze';
541
+ agency: 'gaze';
542
+ targetAgency: 'eyeHeadTracking';
543
+ requestId: string;
544
+ source?: string;
545
+ label?: string;
546
+ mode: string;
547
+ target: Required<GazeTarget>;
548
+ rawTarget: Required<GazeTarget>;
549
+ previousTarget: Required<GazeTarget>;
550
+ eyeEnabled: boolean;
551
+ headEnabled: boolean;
552
+ headFollowEyes: boolean;
553
+ eyeIntensity: number;
554
+ headIntensity: number;
555
+ eyeDurationMs: number;
556
+ headDurationMs: number;
557
+ createdAt: number;
558
+ queuedAt?: number;
559
+ publishedAt?: number;
560
+ }
561
+
562
+ export interface GazeResetRequest {
563
+ type: 'eyeHeadTracking.requestReset';
564
+ agency: 'gaze';
565
+ targetAgency: 'eyeHeadTracking';
566
+ requestId: string;
567
+ durationMs: number;
568
+ eyes: boolean;
569
+ head: boolean;
570
+ requestedAt: number;
571
+ }
572
+
573
+ export interface GazeCancelRequest {
574
+ type: 'eyeHeadTracking.requestCancel';
575
+ agency: 'gaze';
576
+ targetAgency: 'eyeHeadTracking';
577
+ requestId: string;
578
+ reason: string;
579
+ requestedAt: number;
580
+ }
581
+
582
+ export interface EyeHeadTrackingConfig {
583
+ gazeMode?: 'engine' | 'legacy' | 'experimental';
584
+ enabled?: boolean;
585
+ eyeTrackingEnabled?: boolean;
586
+ eyeSaccadeSpeed?: number;
587
+ eyeSmoothPursuit?: boolean;
588
+ eyeBlinkRate?: number;
589
+ headTrackingEnabled?: boolean;
590
+ headFollowEyes?: boolean;
591
+ headFollowDelay?: number;
592
+ headSpeed?: number;
593
+ lookAtSpeaker?: boolean;
594
+ idleVariation?: boolean;
595
+ idleVariationInterval?: number;
596
+ eyeIntensity?: number;
597
+ eyeBlendWeight?: number;
598
+ headIntensity?: number;
599
+ headBlendWeight?: number;
600
+ headRoll?: number;
601
+ eyePriority?: number;
602
+ headPriority?: number;
603
+ snippetPriority?: number;
604
+ transitionDurationMs?: number;
605
+ agencyTransitionDuration?: number;
606
+ returnToCenterDurationMs?: number;
607
+ returnToNeutralEnabled?: boolean;
608
+ returnToNeutralDelay?: number;
609
+ returnToNeutralDuration?: number;
610
+ coalesceMs?: number;
611
+ replaceExisting?: boolean;
612
+ webcamTrackingEnabled?: boolean;
613
+ webcamLookAtUser?: boolean;
614
+ webcamActivationInterval?: number;
615
+ mouthSyncEnabled?: boolean;
616
+ engine?: Embody | EmbodyRuntime | unknown;
617
+ cameraController?: unknown;
618
+ animationAgency?: AnimationService | unknown;
619
+ useAnimationAgency?: boolean;
620
+ }
621
+
622
+ export interface EyeHeadTrackingState {
623
+ agency: 'eyeHeadTracking';
624
+ status: string;
625
+ mode: string;
626
+ currentTarget: Required<GazeTarget>;
627
+ pendingRequest: EyeHeadGazeRequest | null;
628
+ lastRequest: EyeHeadGazeRequest | null;
629
+ lastSnippet: PolymerAnimationSnippet | null;
630
+ activeSnippetNames: string[];
631
+ lastIgnored: null | Record<string, unknown>;
632
+ lastPlan: null | Record<string, unknown>;
633
+ scheduledCount: number;
634
+ removedCount: number;
635
+ resetCount: number;
636
+ cancelCount: number;
637
+ ignoredCount: number;
638
+ config: Required<EyeHeadTrackingConfig>;
639
+ }
640
+
641
+ export interface EyeHeadGazeRequest {
642
+ type: 'eyeHeadTracking.requestGaze';
643
+ agency: 'eyeHeadTracking' | 'gaze';
644
+ sourceAgency?: string;
645
+ requestId: string;
646
+ target: Required<GazeTarget>;
647
+ rawTarget?: Required<GazeTarget>;
648
+ mode?: string;
649
+ eyeEnabled?: boolean;
650
+ headEnabled?: boolean;
651
+ headFollowEyes?: boolean;
652
+ eyeIntensity?: number;
653
+ headIntensity?: number;
654
+ headRoll?: number;
655
+ eyeDurationMs?: number;
656
+ headDurationMs?: number;
657
+ createdAt?: number;
658
+ }
659
+
660
+ export type EyeHeadTrackingDispatch =
661
+ | { type: 'configure'; config: EyeHeadTrackingConfig }
662
+ | { type: 'enable' }
663
+ | { type: 'disable' }
664
+ | { type: 'setTarget' | 'set-target' | 'requestGaze'; target: GazeTarget }
665
+ | EyeHeadGazeRequest
666
+ | { type: 'reset' | 'eyeHeadTracking.requestReset'; durationMs?: number; eyes?: boolean; head?: boolean; reason?: string }
667
+ | { type: 'cancel' | 'eyeHeadTracking.requestCancel'; reason?: string };
668
+
669
+ export interface BlinkTriggerOptions {
670
+ intensity?: number;
671
+ duration?: number;
672
+ burstCount?: number;
673
+ burstGap?: number;
674
+ }
675
+
676
+ export type BlinkDispatch =
677
+ | { type: 'enable' }
678
+ | { type: 'disable' }
679
+ | { type: 'triggerBlink'; options?: BlinkTriggerOptions }
680
+ | { type: 'requestBlink'; reason?: string; options?: BlinkTriggerOptions }
681
+ | { type: 'setFrequency'; value: number }
682
+ | { type: 'setDuration'; value: number }
683
+ | { type: 'setIntensity'; value: number }
684
+ | { type: 'setRandomness'; value: number }
685
+ | { type: 'setLeftEyeIntensity'; value: number | null }
686
+ | { type: 'setRightEyeIntensity'; value: number | null }
687
+ | { type: 'setBurstEnabled'; value: boolean }
688
+ | { type: 'setBurstFrequency'; value: number }
689
+ | { type: 'setBurstCount'; value: number }
690
+ | { type: 'setBurstGap'; value: number }
691
+ | { type: 'configure'; config: BlinkAgencyConfig }
692
+ | { type: 'reset' };
693
+
694
+ export interface AnimationScheduledSnippet {
695
+ name: string;
696
+ sourceAgency: string;
697
+ snippetCategory?: string;
698
+ snippetPriority?: number;
699
+ maxTime?: number;
700
+ loop: boolean;
701
+ autoPlay: boolean;
702
+ requestedAt: number;
703
+ }
704
+
705
+ export interface AnimationState {
706
+ agency: 'animation';
707
+ scheduled: Record<string, AnimationScheduledSnippet>;
708
+ scheduledCount: number;
709
+ startedCount: number;
710
+ seekCount: number;
711
+ updatedCount: number;
712
+ removedCount: number;
713
+ lastEvent: null | {
714
+ type:
715
+ | 'animationSnippetScheduled'
716
+ | 'animationSnippetStarted'
717
+ | 'animationSnippetSeeked'
718
+ | 'animationSnippetUpdated'
719
+ | 'animationSnippetRemoved';
720
+ name: string;
721
+ sourceAgency: string;
722
+ reason?: string;
723
+ offsetSec?: number;
724
+ params?: Record<string, unknown>;
725
+ at: number;
726
+ };
727
+ }
728
+
729
+ export interface AnimationAgencyConfig {
730
+ runtime?: PolymerAnimationRuntime;
731
+ engine?: Embody | EmbodyRuntime;
732
+ runtimeConfig?: Record<string, unknown>;
733
+ }
734
+
735
+ export type AnimationDispatch =
736
+ | {
737
+ type: 'scheduleSnippet';
738
+ sourceAgency?: string;
739
+ snippet: PolymerAnimationSnippet;
740
+ options?: { autoPlay?: boolean; sourceAgency?: string; [key: string]: unknown };
741
+ }
742
+ | { type: 'seekSnippet'; sourceAgency?: string; name: string; offsetSec: number }
743
+ | { type: 'updateSnippet'; sourceAgency?: string; name: string; params: Record<string, unknown> }
744
+ | { type: 'removeSnippet'; sourceAgency?: string; name: string }
745
+ | { type: 'clear'; sourceAgency?: string };
746
+
747
+ export interface PolymerSnippetKeyframe {
748
+ time: number;
749
+ intensity: number;
750
+ inherit?: boolean;
751
+ }
752
+
753
+ export type PolymerSnippetChannelTarget =
754
+ | { type: 'au'; id: number; balance?: number }
755
+ | { type: 'viseme'; id: number; meshNames?: string[] }
756
+ | { type: 'morph'; id: string | number; meshNames?: string[] }
757
+ | {
758
+ type: 'bone';
759
+ id: string;
760
+ channel: 'rx' | 'ry' | 'rz' | 'tx' | 'ty' | 'tz';
761
+ scale?: number;
762
+ maxDegrees?: number;
763
+ maxUnits?: number;
764
+ };
765
+
766
+ export interface PolymerSnippetChannel {
767
+ target: PolymerSnippetChannelTarget;
768
+ keyframes: PolymerSnippetKeyframe[];
769
+ intensityScale?: number;
770
+ }
771
+
772
+ export interface PolymerAnimationHandle {
773
+ play?: () => unknown;
774
+ stop?: () => unknown;
775
+ setTime?: (offsetSec: number) => unknown;
776
+ seek?: (offsetSec: number) => unknown;
777
+ updateParams?: (params: Record<string, unknown>) => unknown;
778
+ setParams?: (params: Record<string, unknown>) => unknown;
779
+ finished?: Promise<unknown> | { then: (onFulfilled?: () => unknown, onRejected?: (error: unknown) => unknown) => unknown };
780
+ }
781
+
782
+ export interface PolymerAnimationRuntime {
783
+ buildClip?: (
784
+ name: string,
785
+ curves: Record<string, PolymerSnippetKeyframe[]>,
786
+ options?: Record<string, unknown>
787
+ ) => PolymerAnimationHandle | unknown;
788
+ playSnippet?: (
789
+ name: string,
790
+ curves: Record<string, PolymerSnippetKeyframe[]>,
791
+ options?: Record<string, unknown>
792
+ ) => PolymerAnimationHandle | unknown;
793
+ playTypedSnippet?: (
794
+ snippet: { name: string; channels: PolymerSnippetChannel[] },
795
+ options?: Record<string, unknown>
796
+ ) => PolymerAnimationHandle | unknown;
797
+ buildTypedClip?: (
798
+ name: string,
799
+ channels: PolymerSnippetChannel[],
800
+ options?: Record<string, unknown>
801
+ ) => PolymerAnimationHandle | unknown;
802
+ updateClipParams?: (name: string, params: Record<string, unknown>) => unknown;
803
+ setSnippetTime?: (name: string, offsetSec: number) => unknown;
804
+ seekSnippet?: (name: string, offsetSec: number) => unknown;
805
+ seek?: (name: string, offsetSec: number) => unknown;
806
+ cleanupSnippet?: (name: string) => unknown;
807
+ stopAnimation?: (name: string) => unknown;
808
+ getAnimationState?: (name: string) => unknown;
809
+ }
810
+
811
+ export interface PolymerAnimationSnippet {
812
+ name: string;
813
+ curves?: Record<string, PolymerSnippetKeyframe[]>;
814
+ channels?: PolymerSnippetChannel[];
815
+ maxTime: number;
816
+ loop: boolean;
817
+ snippetCategory?: string;
818
+ snippetPriority: number;
819
+ snippetPlaybackRate: number;
820
+ snippetIntensityScale: number;
821
+ snippetJawScale?: number;
822
+ autoVisemeJaw?: boolean;
823
+ metadata?: Record<string, unknown>;
824
+ }
825
+
826
+ export interface LipSyncConfig {
827
+ intensity?: number;
828
+ speechRate?: number;
829
+ jawScale?: number;
830
+ /** Scale for independently planned tongue AU curves. Set 0 to disable tongue motion. */
831
+ tongueScale?: number;
832
+ rampMs?: number;
833
+ holdMs?: number;
834
+ priority?: number;
835
+ visualLeadMs?: number;
836
+ wordDriftThresholdSec?: number;
837
+ }
838
+
839
+ export interface LipSyncRuntime {
840
+ /** Optional preloaded CMU-compatible dictionary, primarily for tests or embedded runtimes. */
841
+ pronunciationDictionary?: Record<string, string>;
842
+ /** Optional loader override. Production uses Polymer's lazy CMU module import. */
843
+ loadPronunciationDictionary?: () =>
844
+ | Record<string, string>
845
+ | Promise<Record<string, string> | { dictionary: Record<string, string> }>;
846
+ }
847
+
848
+ export interface LipSyncVisemeEvent {
849
+ visemeId: number;
850
+ /**
851
+ * Optional independent jaw-axis activation for this event. When omitted,
852
+ * Polymer derives a default from the canonical viseme slot. Set to 0 for a
853
+ * lip-only viseme, or scale with LipSyncConfig.jawScale for JALI-style control.
854
+ */
855
+ jawActivation?: number;
856
+ phoneme?: string;
857
+ /**
858
+ * Primary visual-speech class for planner rules, e.g. vowel, bilabial,
859
+ * labiodental, sibilant, obstruent, nasal, tongue, liquid, glide, or pause.
860
+ */
861
+ phonemeClass?: string;
862
+ /**
863
+ * Full class set for phonemes that need multiple JALI-style rules, such as
864
+ * M being both bilabial and nasal or F being labiodental and fricative.
865
+ */
866
+ phonemeClasses?: string[];
867
+ offsetMs: number;
868
+ durationMs: number;
869
+ }
870
+
871
+ export interface LipSyncWordTiming {
872
+ word: string;
873
+ startSec?: number;
874
+ endSec?: number;
875
+ start?: number;
876
+ end?: number;
877
+ start_time?: number;
878
+ end_time?: number;
879
+ }
880
+
881
+ export interface AzureVisemeEvent {
882
+ id?: number;
883
+ visemeId?: number;
884
+ viseme_id?: number;
885
+ time?: number;
886
+ audio_offset?: number;
887
+ audioOffset?: number;
888
+ }
889
+
890
+ export interface LipSyncTimeline {
891
+ name?: string;
892
+ text?: string;
893
+ source?: 'text' | 'azure' | 'livekit' | 'webSpeech' | string;
894
+ visemes: LipSyncVisemeEvent[];
895
+ wordTimings?: LipSyncWordTiming[];
896
+ durationSec?: number;
897
+ }
898
+
899
+ export interface LipSyncState {
900
+ agency: 'lipSync';
901
+ speaking: boolean;
902
+ currentWord: string | null;
903
+ currentViseme: number | null;
904
+ snippetName: string | null;
905
+ source: string | null;
906
+ text: string | null;
907
+ startTime: number | null;
908
+ audioStartedAt: number | null;
909
+ audioTimeSec: number | null;
910
+ maxTime: number;
911
+ wordIndex: number;
912
+ wordTimings: Array<{ word: string; startSec: number; endSec: number }>;
913
+ scheduledCount: number;
914
+ stoppedCount: number;
915
+ syncCorrectionCount: number;
916
+ config: Required<LipSyncConfig>;
917
+ lastEvent: null | Record<string, unknown>;
918
+ }
919
+
920
+ export type LipSyncDispatch =
921
+ | { type: 'configure'; config: LipSyncConfig }
922
+ | {
923
+ type: 'startText';
924
+ text: string;
925
+ name?: string;
926
+ source?: string;
927
+ wordTimings?: LipSyncWordTiming[];
928
+ durationSec?: number;
929
+ totalDurationMs?: number;
930
+ }
931
+ | { type: 'startTimeline'; timeline: LipSyncTimeline }
932
+ | {
933
+ type: 'processAzureVisemes';
934
+ visemes: AzureVisemeEvent[];
935
+ totalDurationMs?: number;
936
+ name?: string;
937
+ text?: string;
938
+ source?: string;
939
+ wordTimings?: LipSyncWordTiming[];
940
+ options?: { wordTimings?: LipSyncWordTiming[]; visualLeadMs?: number; [key: string]: unknown };
941
+ }
942
+ | { type: 'wordBoundary'; word: string; wordIndex?: number; observedElapsedSec?: number; hostElapsedSec?: number }
943
+ | { type: 'audioStarted'; name?: string; audioTimeSec?: number; currentTimeSec?: number; offsetSec?: number }
944
+ | { type: 'audioTime'; name?: string; audioTimeSec?: number; currentTimeSec?: number; offsetSec?: number }
945
+ | { type: 'updateWordTimings'; wordTimings: LipSyncWordTiming[] }
946
+ | { type: 'stop' }
947
+ | { type: 'reset' };
948
+
949
+ export interface TTSVoice {
950
+ id: string;
951
+ name: string;
952
+ language?: string;
953
+ lang?: string;
954
+ gender?: string;
955
+ styles?: string[];
956
+ provider?: 'webSpeech' | 'azure' | string;
957
+ }
958
+
959
+ export interface TTSConfig {
960
+ engine?: 'webSpeech' | 'azure' | 'livekit' | string;
961
+ backendUrl?: string;
962
+ voiceName?: string;
963
+ azureVoiceName?: string;
964
+ azureStyle?: string;
965
+ azureStyleDegree?: string | number | null;
966
+ rate?: number;
967
+ pitch?: number;
968
+ volume?: number;
969
+ visualLeadMs?: number;
970
+ lipsyncIntensity?: number;
971
+ jawScale?: number;
972
+ /** Scale for LipSync tongue AU planning forwarded by TTS before each speech session. */
973
+ tongueScale?: number;
974
+ webSpeechDriftThresholdSec?: number;
975
+ azureDriftThresholdSec?: number;
976
+ azureCacheLimit?: number;
977
+ debug?: boolean;
978
+ /** Experimental Web Speech barge-in reference: none | displayMedia */
979
+ webSpeechReferenceMode?: 'none' | 'displayMedia';
980
+ providers?: Record<string, unknown>;
981
+ }
982
+
983
+ export interface TTSState {
984
+ agency: 'tts';
985
+ status: 'idle' | 'loading' | 'speaking' | 'error' | string;
986
+ engine: string;
987
+ speaking: boolean;
988
+ currentText: string | null;
989
+ snippetName: string | null;
990
+ sessionId: number;
991
+ startedAt: number | null;
992
+ endedAt: number | null;
993
+ wordIndex: number;
994
+ webSpeechVoices: TTSVoice[];
995
+ azureVoices: TTSVoice[];
996
+ azureStatus: 'checking' | 'ready' | 'error' | string;
997
+ azureStatusMessage: string;
998
+ lastPlan: Record<string, unknown> | null;
999
+ lastError: string | null;
1000
+ config: Required<Omit<TTSConfig, 'providers'>> & { providers?: never };
1001
+ }
1002
+
1003
+ export type TTSDispatch =
1004
+ | { type: 'configure'; config: TTSConfig }
1005
+ | { type: 'loadVoices'; engine?: 'webSpeech' | 'azure' | string }
1006
+ | {
1007
+ type: 'speak';
1008
+ text: string;
1009
+ engine?: 'webSpeech' | 'azure' | 'livekit' | string;
1010
+ name?: string;
1011
+ backendUrl?: string;
1012
+ voiceName?: string;
1013
+ style?: string;
1014
+ rate?: number;
1015
+ pitch?: number;
1016
+ volume?: number;
1017
+ visualLeadMs?: number;
1018
+ }
1019
+ | { type: 'stop' }
1020
+ | { type: 'reset' };
1021
+
1022
+ export interface ProsodicConfig {
1023
+ enabled?: boolean;
1024
+ intensity?: number;
1025
+ priority?: number;
1026
+ speechGestureEvery?: number;
1027
+ blinkFastCooldownMs?: number;
1028
+ }
1029
+
1030
+ export interface ProsodicState {
1031
+ agency: 'prosodic';
1032
+ speaking: boolean;
1033
+ wordIndex: number;
1034
+ currentWord: string | null;
1035
+ activeSnippets: string[];
1036
+ scheduledCount: number;
1037
+ removedCount: number;
1038
+ lastGesture: string | null;
1039
+ lastBlinkFastCueAt: number;
1040
+ config: Required<ProsodicConfig>;
1041
+ lastEvent: null | Record<string, unknown>;
1042
+ }
1043
+
1044
+ export type ProsodicDispatch =
1045
+ | { type: 'configure'; config: ProsodicConfig }
1046
+ | { type: 'speechStarted'; name?: string; sourceAgency?: string; engine?: string }
1047
+ | { type: 'speechStopped'; reason?: string; sourceAgency?: string }
1048
+ | {
1049
+ type: 'wordBoundary';
1050
+ word: string;
1051
+ wordIndex?: number;
1052
+ observedElapsedSec?: number;
1053
+ hostElapsedSec?: number;
1054
+ sourceAgency?: string;
1055
+ }
1056
+ | { type: 'blinkFast'; sourceAgency?: string; plan?: Record<string, unknown> }
1057
+ | { type: 'stop'; reason?: string }
1058
+ | { type: 'reset' };
1059
+
1060
+ export interface ConversationConfig {
1061
+ autoRespond?: boolean;
1062
+ maxHistory?: number;
1063
+ responseSource?: string;
1064
+ ttsAgency?: string;
1065
+ interruptionMode?: string;
1066
+ autoListen?: boolean;
1067
+ detectInterruptions?: boolean;
1068
+ minSpeakTime?: number;
1069
+ allowTranscriptInterruptionFallback?: boolean;
1070
+ eyeHeadTracking?: EyeHeadTrackingService | unknown;
1071
+ prosodicService?: unknown;
1072
+ }
1073
+
1074
+ export interface ConversationProviderRequest {
1075
+ requestId: string;
1076
+ text: string;
1077
+ source: string;
1078
+ turnId?: string;
1079
+ history: Array<Record<string, unknown>>;
1080
+ requestedAt: number;
1081
+ }
1082
+
1083
+ export interface ConversationProviderResponse {
1084
+ text: string;
1085
+ source?: string;
1086
+ }
1087
+
1088
+ export type ConversationProvider =
1089
+ | ((
1090
+ request: ConversationProviderRequest,
1091
+ resolve: (response: ConversationProviderResponse | string) => void,
1092
+ reject: (error: unknown) => void,
1093
+ ) => unknown)
1094
+ | {
1095
+ respond(
1096
+ request: ConversationProviderRequest,
1097
+ resolve: (response: ConversationProviderResponse | string) => void,
1098
+ reject: (error: unknown) => void,
1099
+ ): unknown;
1100
+ };
1101
+
1102
+ export interface ConversationAgencyConfig extends ConversationConfig {
1103
+ /** Injectable external provider handle retained by Conversation's private effector. */
1104
+ provider?: ConversationProvider;
1105
+ /** Compatibility alias for provider. */
1106
+ conversationProvider?: ConversationProvider;
1107
+ }
1108
+
1109
+ export interface ConversationHistoryEntry {
1110
+ role: 'user' | 'agent' | string;
1111
+ text: string;
1112
+ source?: string;
1113
+ at?: number;
1114
+ turnId?: string | null;
1115
+ }
1116
+
1117
+ export interface ConversationState {
1118
+ agency: 'conversation';
1119
+ status: string;
1120
+ started: boolean;
1121
+ turnId: string | null;
1122
+ history: ConversationHistoryEntry[];
1123
+ context: Record<string, unknown>;
1124
+ pendingResponse: Record<string, unknown> | null;
1125
+ lastProviderError: string | null;
1126
+ lastUserText: string | null;
1127
+ lastAgentText: string | null;
1128
+ lastEvent: Record<string, unknown> | null;
1129
+ interrupted: boolean;
1130
+ startedCount: number;
1131
+ stoppedCount: number;
1132
+ userUtteranceCount: number;
1133
+ agentUtteranceCount: number;
1134
+ responseRequestCount: number;
1135
+ ttsRequestCount: number;
1136
+ cancelCount: number;
1137
+ config: Required<ConversationConfig>;
1138
+ }
1139
+
1140
+ export type ConversationDispatch =
1141
+ | { type: 'configure'; config: ConversationConfig }
1142
+ | { type: 'start' }
1143
+ | { type: 'stop'; reason?: string }
1144
+ | { type: 'reset' }
1145
+ | { type: 'cancel' | 'interrupt'; reason?: string }
1146
+ | { type: 'transcript.final' | 'transcriptFinal' | 'userUtterance'; text?: string; transcript?: string; utterance?: string; responseText?: string; agentText?: string; source?: string }
1147
+ | { type: 'agentUtterance' | 'responseReady'; text?: string; utterance?: string; responseText?: string; agentText?: string; requestId?: string; turnId?: string; source?: string }
1148
+ | { type: 'providerError'; requestId?: string; turnId?: string; message?: string }
1149
+ | { type: 'tts.status'; status?: string };
1150
+
1151
+ export interface TranscriptionConfig {
1152
+ provider?: string;
1153
+ lang?: string;
1154
+ continuous?: boolean;
1155
+ interimResults?: boolean;
1156
+ maxAlternatives?: number;
1157
+ maxRetries?: number;
1158
+ retryDelayMs?: number;
1159
+ minConfidence?: number;
1160
+ agentFilteringEnabled?: boolean;
1161
+ interruptDetectionEnabled?: boolean;
1162
+ requireAgentReferenceForInterruption?: boolean;
1163
+ interruptionDebugLogging?: boolean;
1164
+ interruptionVolumeThreshold?: number;
1165
+ interruptionReferenceScale?: number;
1166
+ interruptionReferenceOffset?: number;
1167
+ interruptionHoldMs?: number;
1168
+ }
1169
+
1170
+ export interface TranscriptionState {
1171
+ agency: 'transcription';
1172
+ status: string;
1173
+ active: boolean;
1174
+ sessionId: string | null;
1175
+ sequence: number;
1176
+ currentTranscript: string | null;
1177
+ isFinal: boolean;
1178
+ lastPartial: Record<string, unknown> | null;
1179
+ lastFinal: Record<string, unknown> | null;
1180
+ lastError: string | null;
1181
+ lastEvent: Record<string, unknown> | null;
1182
+ agentSpeaking: boolean;
1183
+ agentSpeechStatus: string;
1184
+ retryCount: number;
1185
+ startedCount: number;
1186
+ stoppedCount: number;
1187
+ partialCount: number;
1188
+ finalCount: number;
1189
+ errorCount: number;
1190
+ ignoredCount: number;
1191
+ interruptionCount: number;
1192
+ config: Required<TranscriptionConfig>;
1193
+ }
1194
+
1195
+ export type TranscriptionDispatch =
1196
+ | { type: 'configure'; config: TranscriptionConfig }
1197
+ | { type: 'start' }
1198
+ | { type: 'stop' | 'cancel'; reason?: string }
1199
+ | { type: 'reset' }
1200
+ | { type: 'providerPartial' | 'partialTranscript' | 'providerFinal' | 'finalTranscript'; text?: string; transcript?: string; confidence?: number; source?: string; speaker?: string }
1201
+ | { type: 'providerError'; message?: string; error?: string }
1202
+ | { type: 'providerAudioInterruption'; timestamp: number; microphoneLevel: number; referenceLevel: number; requiredLevel: number }
1203
+ | { type: 'tts.status'; status?: string; speaking?: boolean; state?: Record<string, unknown> }
1204
+ | { type: 'ttsSpeechStarted' | 'ttsSpeechStopped' | 'ttsSpeechEnded'; status?: string; speaking?: boolean };
1205
+
1206
+ export interface CameraContextConfig {
1207
+ coalesceMs?: number;
1208
+ staleAfterMs?: number;
1209
+ epsilon?: number;
1210
+ yawWeight?: number;
1211
+ pitchWeight?: number;
1212
+ }
1213
+
1214
+ export interface PolymerVector3 {
1215
+ x: number;
1216
+ y: number;
1217
+ z: number;
1218
+ }
1219
+
1220
+ export interface PolymerQuaternion {
1221
+ x: number;
1222
+ y: number;
1223
+ z: number;
1224
+ w: number;
1225
+ }
1226
+
1227
+ export interface CameraContextState {
1228
+ agency: 'cameraContext';
1229
+ status: string;
1230
+ cameraPosition: PolymerVector3 | null;
1231
+ targetPosition: PolymerVector3 | null;
1232
+ modelQuaternion: PolymerQuaternion;
1233
+ relativeOffset: Required<GazeTarget>;
1234
+ lastUpdatedAt: number | null;
1235
+ lastPublishedAt: number | null;
1236
+ lastFact: Record<string, unknown> | null;
1237
+ lastPlan: Record<string, unknown> | null;
1238
+ lastInvalidation: Record<string, unknown> | null;
1239
+ stale: boolean;
1240
+ invalidated: boolean;
1241
+ updateCount: number;
1242
+ publishedCount: number;
1243
+ config: Required<CameraContextConfig>;
1244
+ }
1245
+
1246
+ export type CameraContextDispatch =
1247
+ | { type: 'configure'; config: CameraContextConfig }
1248
+ | {
1249
+ type: 'updateCamera';
1250
+ facts?: Record<string, unknown>;
1251
+ cameraPosition?: PolymerVector3;
1252
+ targetPosition?: PolymerVector3;
1253
+ modelQuaternion?: PolymerQuaternion;
1254
+ source?: string;
1255
+ }
1256
+ | { type: 'publishCameraFacts' }
1257
+ | { type: 'invalidateStale'; reason?: string }
1258
+ | { type: 'reset' };
1259
+
1260
+ export type LipSyncSchedulerQueueEntry =
1261
+ | {
1262
+ type: 'scheduleAnimation';
1263
+ agency: 'lipSync';
1264
+ requestId: string;
1265
+ snippetName: string;
1266
+ effectors: string[];
1267
+ queueIndex: number;
1268
+ queuedAt: number;
1269
+ }
1270
+ | {
1271
+ type: 'seekAnimation';
1272
+ agency: 'lipSync';
1273
+ requestId: string;
1274
+ name: string;
1275
+ offsetSec: number;
1276
+ reason: string;
1277
+ queueIndex: number;
1278
+ queuedAt: number;
1279
+ }
1280
+ | {
1281
+ type: 'removeAnimation';
1282
+ agency: 'lipSync';
1283
+ requestId: string;
1284
+ name: string;
1285
+ reason: string;
1286
+ queueIndex: number;
1287
+ queuedAt: number;
1288
+ }
1289
+ | {
1290
+ type: 'finishTimeline';
1291
+ agency: 'lipSync';
1292
+ reason: string;
1293
+ queueIndex: number;
1294
+ queuedAt: number;
1295
+ };
1296
+
1297
+ export type ProsodicSchedulerQueueEntry =
1298
+ | {
1299
+ type: 'scheduleAnimation';
1300
+ agency: 'prosodic';
1301
+ requestId: string;
1302
+ snippetName: string;
1303
+ effectors: string[];
1304
+ queueIndex: number;
1305
+ queuedAt: number;
1306
+ }
1307
+ | {
1308
+ type: 'removeAnimation';
1309
+ agency: 'prosodic';
1310
+ requestId: string;
1311
+ name: string;
1312
+ reason: string;
1313
+ queueIndex: number;
1314
+ queuedAt: number;
1315
+ };
1316
+
1317
+ export type TTSSchedulerQueueEntry =
1318
+ | {
1319
+ type: 'webSpeechStartFallback';
1320
+ agency: 'tts';
1321
+ sessionId: number;
1322
+ delayMs: number;
1323
+ queueIndex: number;
1324
+ queuedAt: number;
1325
+ }
1326
+ | {
1327
+ type: 'audioBoundaryPolling';
1328
+ agency: 'tts';
1329
+ sessionId: number;
1330
+ wordCount: number;
1331
+ queueIndex: number;
1332
+ queuedAt: number;
1333
+ };
1334
+
1335
+ export type GestureScope = 'left' | 'right' | 'both' | 'custom' | string;
1336
+
1337
+ export type GestureCaptureSource = 'manual' | 'animation-frame' | 'animation-stack' | 'imported' | 'snippet' | 'baked-clip' | string;
1338
+
1339
+ export interface GestureEulerRotation {
1340
+ pitch: number;
1341
+ yaw: number;
1342
+ roll: number;
1343
+ order?: 'XYZ' | 'YXZ' | 'ZXY' | 'ZYX' | 'YZX' | 'XZY';
1344
+ unit?: 'degrees';
1345
+ }
1346
+
1347
+ export interface GestureTransform {
1348
+ rawName?: string;
1349
+ displayName?: string;
1350
+ semanticKeys?: string[];
1351
+ rotationEuler?: GestureEulerRotation;
1352
+ rotation?: [number, number, number, number];
1353
+ position?: [number, number, number];
1354
+ scale?: [number, number, number];
1355
+ source?: string;
1356
+ }
1357
+
1358
+ export interface GestureKeyframe {
1359
+ timeMs: number;
1360
+ bones: Record<string, GestureTransform>;
1361
+ }
1362
+
1363
+ export interface GestureAUMapping {
1364
+ auId: string;
1365
+ node: string;
1366
+ boneName?: string;
1367
+ channel?: string;
1368
+ scale?: number;
1369
+ maxDegrees?: number;
1370
+ maxUnits?: number;
1371
+ side?: 'left' | 'right';
1372
+ name?: string;
1373
+ }
1374
+
1375
+ export interface GestureSnapshot {
1376
+ id: string;
1377
+ version?: number;
1378
+ name: string;
1379
+ description?: string;
1380
+ textRepresentation?: string;
1381
+ sourceText?: string;
1382
+ scope?: GestureScope;
1383
+ emoji?: string;
1384
+ tags?: string[];
1385
+ createdAt?: number;
1386
+ updatedAt?: number;
1387
+ captureSource?: GestureCaptureSource;
1388
+ durationMs?: number;
1389
+ easing?: string;
1390
+ loop?: boolean;
1391
+ priority?: number;
1392
+ returnToBase?: boolean;
1393
+ affectedBones?: string[];
1394
+ affectedAUs?: string[];
1395
+ auMappings?: GestureAUMapping[];
1396
+ bones?: Record<string, GestureTransform>;
1397
+ keyframes?: GestureKeyframe[];
1398
+ metadata?: Record<string, unknown>;
1399
+ }
1400
+
1401
+ export interface GestureConfig {
1402
+ enabled?: boolean;
1403
+ intensity?: number;
1404
+ priority?: number;
1405
+ defaultDurationMs?: number;
1406
+ cooldownMs?: number;
1407
+ rampRatio?: number;
1408
+ holdRatio?: number;
1409
+ returnToBase?: boolean;
1410
+ replaceActive?: boolean;
1411
+ maxActive?: number;
1412
+ gestures?: Record<string, GestureSnapshot>;
1413
+ characterGestures?: Record<string, GestureSnapshot>;
1414
+ gestureLibrary?: Record<string, GestureSnapshot>;
1415
+ emojiMappings?: Record<string, string>;
1416
+ gestureEmojiMappings?: Record<string, string>;
1417
+ }
1418
+
1419
+ export interface GestureGoal {
1420
+ gestureId?: string;
1421
+ id?: string;
1422
+ preferredGestureId?: string;
1423
+ preferredId?: string;
1424
+ preferredGesture?: string;
1425
+ emoji?: string;
1426
+ intent?: string;
1427
+ kind?: string;
1428
+ purpose?: string;
1429
+ tags?: string[];
1430
+ requiredTags?: string[];
1431
+ mustHaveTags?: string[];
1432
+ scope?: GestureScope;
1433
+ affectedBones?: string[];
1434
+ requiredBones?: string[];
1435
+ avoidBones?: string[];
1436
+ sourceText?: string;
1437
+ textRepresentation?: string;
1438
+ name?: string;
1439
+ intensity?: number;
1440
+ trigger?: string;
1441
+ }
1442
+
1443
+ export interface GestureActiveSnippet {
1444
+ name: string;
1445
+ gestureId: string;
1446
+ gestureName?: string;
1447
+ emoji?: string;
1448
+ scope?: GestureScope;
1449
+ affectedBones?: string[];
1450
+ maxTime: number;
1451
+ loop?: boolean;
1452
+ priority?: number;
1453
+ trigger?: string;
1454
+ intent?: string;
1455
+ scheduledAt: number;
1456
+ }
1457
+
1458
+ export interface GestureState {
1459
+ agency: 'gesture';
1460
+ gestures: string[];
1461
+ gestureCount: number;
1462
+ emojiCount: number;
1463
+ activeSnippets: Record<string, GestureActiveSnippet>;
1464
+ scheduledCount: number;
1465
+ removedCount: number;
1466
+ config: Required<Omit<GestureConfig, 'gestures' | 'characterGestures' | 'emojiMappings' | 'gestureEmojiMappings'>>;
1467
+ lastEvent: null | Record<string, unknown>;
1468
+ }
1469
+
1470
+ export type GestureDispatch =
1471
+ | { type: 'configure'; config: GestureConfig }
1472
+ | {
1473
+ type: 'loadGestures';
1474
+ gestures?: Record<string, GestureSnapshot>;
1475
+ characterGestures?: Record<string, GestureSnapshot>;
1476
+ gestureLibrary?: Record<string, GestureSnapshot>;
1477
+ emojiMappings?: Record<string, string>;
1478
+ gestureEmojiMappings?: Record<string, string>;
1479
+ }
1480
+ | { type: 'playGesture'; gestureId: string; name?: string; intensity?: number }
1481
+ | { type: 'playEmoji'; emoji: string; name?: string; intensity?: number }
1482
+ | ({ type: 'gesture.goal' | 'performGestureGoal' | 'playGoal'; goal?: GestureGoal } & GestureGoal)
1483
+ | { type: 'stopGesture'; gestureId: string }
1484
+ | { type: 'stopAll' }
1485
+ | { type: 'reset' };
1486
+
1487
+ export interface PolymerStream<TEvent> {
1488
+ subscribe(listener: (event: TEvent) => void): () => void;
1489
+ }
1490
+
1491
+ export interface PolymerInputStream<TCommand> extends PolymerStream<{ type: 'command'; agency: string; command?: TCommand; message?: unknown }> {
1492
+ write(command: TCommand): void;
1493
+ }
1494
+
1495
+
1496
+ export type PolymerDomainEvent =
1497
+ | {
1498
+ type: 'blinkConfigChanged';
1499
+ agency: 'blink';
1500
+ state: BlinkState;
1501
+ }
1502
+ | {
1503
+ type: 'animation.requestScheduleSnippet';
1504
+ agency: 'blink' | 'lipSync' | 'gesture' | 'prosodic' | 'eyeHeadTracking';
1505
+ requestId: string;
1506
+ snippet: PolymerAnimationSnippet;
1507
+ options: { autoPlay?: boolean; [key: string]: unknown };
1508
+ effectors?: string[];
1509
+ queueIndex?: number;
1510
+ queuedAt?: number;
1511
+ }
1512
+ | {
1513
+ type: 'animation.requestRemoveSnippet';
1514
+ agency: 'lipSync' | 'gesture' | 'prosodic' | 'eyeHeadTracking';
1515
+ requestId: string;
1516
+ name: string;
1517
+ reason: string;
1518
+ queueIndex?: number;
1519
+ queuedAt?: number;
1520
+ }
1521
+ | {
1522
+ type: 'animation.requestSeekSnippet';
1523
+ agency: 'lipSync';
1524
+ requestId: string;
1525
+ name: string;
1526
+ offsetSec: number;
1527
+ reason: string;
1528
+ queueIndex?: number;
1529
+ queuedAt?: number;
1530
+ }
1531
+ | {
1532
+ type: 'animationSnippetScheduled';
1533
+ agency: 'animation';
1534
+ sourceAgency: string;
1535
+ name: string;
1536
+ snippet: PolymerAnimationSnippet;
1537
+ options: { autoPlay?: boolean; sourceAgency?: string; [key: string]: unknown };
1538
+ requestedAt: number;
1539
+ }
1540
+ | {
1541
+ type: 'animationSnippetStarted';
1542
+ agency: 'animation';
1543
+ sourceAgency: string;
1544
+ name: string;
1545
+ }
1546
+ | {
1547
+ type: 'animationSnippetSeeked';
1548
+ agency: 'animation';
1549
+ sourceAgency: string;
1550
+ name: string;
1551
+ offsetSec: number;
1552
+ seekedAt: number;
1553
+ }
1554
+ | {
1555
+ type: 'animationSnippetUpdated';
1556
+ agency: 'animation';
1557
+ sourceAgency: string;
1558
+ name: string;
1559
+ params: Record<string, unknown>;
1560
+ updatedAt: number;
1561
+ }
1562
+ | {
1563
+ type: 'animationSnippetRemoved';
1564
+ agency: 'animation';
1565
+ sourceAgency: string;
1566
+ reason: string;
1567
+ name: string;
1568
+ removedAt: number;
1569
+ }
1570
+ | {
1571
+ type: 'blinkPlanned';
1572
+ agency: 'blink';
1573
+ plan: Record<string, unknown>;
1574
+ snippetName: string;
1575
+ nextDelayMs: number | null;
1576
+ }
1577
+ | { type: 'signal'; agency: 'blink'; signal: 'blink-fast'; plan: Record<string, unknown> }
1578
+ | { type: 'gaze.status'; agency: 'gaze'; status: string; mode: string; active: boolean; enabled: boolean; reason?: string; at: number }
1579
+ | { type: 'gaze.targetReceived'; agency: 'gaze'; requestId: string; rawTarget: Required<GazeTarget>; source?: string; label?: string; at: number }
1580
+ | {
1581
+ type: 'gaze.targetPlanned';
1582
+ agency: 'gaze';
1583
+ requestId: string;
1584
+ rawTarget: Required<GazeTarget>;
1585
+ target: Required<GazeTarget>;
1586
+ delta: number;
1587
+ eyeDurationMs: number;
1588
+ headDurationMs: number;
1589
+ at: number;
1590
+ }
1591
+ | {
1592
+ type: 'gaze.targetIgnored';
1593
+ agency: 'gaze';
1594
+ requestId: string;
1595
+ rawTarget: Required<GazeTarget>;
1596
+ target: Required<GazeTarget>;
1597
+ reason: 'disabled' | 'min-delta' | string;
1598
+ ignoredAt: number;
1599
+ }
1600
+ | GazeLookRequest
1601
+ | GazeResetRequest
1602
+ | GazeCancelRequest
1603
+ | { type: 'camera.status'; agency: 'cameraContext'; status: string; stale: boolean; reason?: string; at: number }
1604
+ | {
1605
+ type: 'camera.fact';
1606
+ agency: 'cameraContext';
1607
+ kind: 'camera.relative';
1608
+ sequence: number;
1609
+ source: string;
1610
+ observedAt: number;
1611
+ publishedAt: number;
1612
+ cameraPosition: Record<string, number>;
1613
+ targetPosition: Record<string, number>;
1614
+ modelQuaternion: Record<string, number>;
1615
+ relativeOffset: Required<GazeTarget>;
1616
+ stale: false;
1617
+ }
1618
+ | {
1619
+ type: 'camera.stale';
1620
+ agency: 'cameraContext';
1621
+ status: 'stale';
1622
+ reason: string;
1623
+ invalidatedAt: number;
1624
+ lastPublishedAt?: number;
1625
+ lastObservedAt?: number;
1626
+ lastRelativeOffset?: Required<GazeTarget>;
1627
+ }
1628
+ | {
1629
+ type: 'eyeHeadTracking.status';
1630
+ agency: 'eyeHeadTracking';
1631
+ status: string;
1632
+ enabled: boolean;
1633
+ activeSnippetNames: string[];
1634
+ reason?: string;
1635
+ at: number;
1636
+ }
1637
+ | {
1638
+ type: 'eyeHeadTracking.requestIgnored';
1639
+ agency: 'eyeHeadTracking';
1640
+ requestId: string;
1641
+ reason: string;
1642
+ target?: Required<GazeTarget>;
1643
+ ignoredAt: number;
1644
+ }
1645
+ | {
1646
+ type: 'eyeHeadTracking.cancelled';
1647
+ agency: 'eyeHeadTracking';
1648
+ requestId: string;
1649
+ reason: string;
1650
+ at: number;
1651
+ }
1652
+ | { type: 'lipSyncPlanCreated'; agency: 'lipSync'; plan: Record<string, unknown> }
1653
+ | { type: 'lipSyncConfigChanged'; agency: 'lipSync'; state: LipSyncState }
1654
+ | {
1655
+ type: 'lipSyncTimelineStarted';
1656
+ agency: 'lipSync';
1657
+ name: string;
1658
+ source: string;
1659
+ text?: string;
1660
+ visemeCount: number;
1661
+ maxTime: number;
1662
+ startedAt: number;
1663
+ }
1664
+ | { type: 'lipSyncTimelineStopped'; agency: 'lipSync'; reason: string; stoppedAt: number }
1665
+ | { type: 'lipSyncWordBoundary'; agency: 'lipSync'; word: string; wordIndex: number; observedAt: number }
1666
+ | { type: 'lipSyncWordTimingsUpdated'; agency: 'lipSync'; count: number; updatedAt: number }
1667
+ | { type: 'lipSyncAudioStarted'; agency: 'lipSync'; name?: string; audioTimeSec: number; observedAt: number }
1668
+ | { type: 'lipSyncAudioTime'; agency: 'lipSync'; name?: string; audioTimeSec: number; observedAt: number }
1669
+ | {
1670
+ type: 'lipSyncSyncDrift';
1671
+ agency: 'lipSync';
1672
+ name: string;
1673
+ word: string;
1674
+ wordIndex: number;
1675
+ expectedSec: number;
1676
+ observedSec: number;
1677
+ driftSec: number;
1678
+ targetSec: number;
1679
+ correctedAt: number;
1680
+ }
1681
+ | { type: 'ttsStatusChanged'; agency: 'tts'; state: TTSState }
1682
+ | { type: 'ttsPlanCreated'; agency: 'tts'; plan: Record<string, unknown> }
1683
+ | {
1684
+ type: 'ttsVoicesLoaded';
1685
+ agency: 'tts';
1686
+ engine: 'webSpeech' | 'azure' | string;
1687
+ voices: TTSVoice[];
1688
+ status?: 'checking' | 'ready' | 'error' | string;
1689
+ message?: string;
1690
+ }
1691
+ | { type: 'ttsSpeechStarted'; agency: 'tts'; engine: string; name: string; startedAt: number }
1692
+ | { type: 'ttsSpeechStopped'; agency: 'tts'; reason: string; stoppedAt: number }
1693
+ | { type: 'ttsSpeechEnded'; agency: 'tts'; endedAt: number }
1694
+ | { type: 'ttsPlaybackReferenceChanged'; agency: 'tts'; available: boolean; at: number }
1695
+ | {
1696
+ type: 'ttsWordBoundary';
1697
+ agency: 'tts';
1698
+ word: string;
1699
+ wordIndex: number;
1700
+ observedElapsedSec?: number;
1701
+ hostElapsedSec?: number;
1702
+ }
1703
+ | { type: 'lipSync.command'; agency: 'tts'; command: LipSyncDispatch }
1704
+ | { type: 'conversation.status'; agency: 'conversation'; status: string; turnId?: string; reason?: string; at: number }
1705
+ | { type: 'conversation.userUtterance'; agency: 'conversation'; text: string; source: string; turnId?: string; at: number }
1706
+ | { type: 'conversation.requestResponse'; agency: 'conversation'; targetAgency: string; requestId: string; text: string; source: string; turnId?: string; history: Array<Record<string, unknown>>; requestedAt: number }
1707
+ | { type: 'conversation.providerError'; agency: 'conversation'; requestId: string; turnId?: string; message: string; at: number }
1708
+ | { type: 'conversation.agentUtterance'; agency: 'conversation'; text: string; at: number }
1709
+ | { type: 'conversation.cancelRequested'; agency: 'conversation'; targetAgency: string; reason: string; turnId?: string; at: number }
1710
+ | { type: 'conversation.ignored'; agency: 'conversation'; reason: string; requestId?: string; turnId?: string; at: number }
1711
+ | { type: 'tts.requestSpeak'; agency: 'conversation'; targetAgency: string; requestId: string; text: string; source: string; turnId?: string; command: TTSDispatch; requestedAt: number }
1712
+ | { type: 'transcription.status'; agency: 'transcription'; status: string; sessionId?: string; reason?: string; at: number }
1713
+ | { type: 'transcription.requestProvider'; agency: 'transcription'; targetAgency: 'transcription-provider'; action: string; provider: string; sessionId?: string; requestedAt?: number; [key: string]: unknown }
1714
+ | { type: 'transcription.partial' | 'transcription.final'; agency: 'transcription'; targetAgency: 'conversation'; text: string; confidence: number; isFinal: boolean; sequence: number; source: string; sessionId?: string; at: number }
1715
+ | { type: 'transcription.interruption'; agency: 'transcription'; targetAgency: 'conversation'; text: string; confidence: number; source: string; sessionId?: string; at: number }
1716
+ | { type: 'transcription.audioInterruption'; agency: 'transcription'; targetAgency: 'conversation'; timestamp: number; microphoneLevel: number; referenceLevel: number; requiredLevel: number; at: number }
1717
+ | { type: 'transcription.ttsStatus'; agency: 'transcription'; sourceAgency: 'tts'; status: string; speaking: boolean; ttsEventType?: string; at: number }
1718
+ | { type: 'transcription.ignored'; agency: 'transcription'; reason: string; commandType?: string; at: number }
1719
+ | { type: 'gestureConfigChanged'; agency: 'gesture'; state: GestureState }
1720
+ | { type: 'gestureLibraryUpdated'; agency: 'gesture'; gestureCount: number; emojiCount: number; updatedAt: number }
1721
+ | { type: 'gesturePlanCreated'; agency: 'gesture'; plan: Record<string, unknown> }
1722
+ | {
1723
+ type: 'gestureScheduled';
1724
+ agency: 'gesture';
1725
+ gestureId: string;
1726
+ gestureName: string;
1727
+ emoji?: string;
1728
+ scope?: GestureScope;
1729
+ affectedBones?: string[];
1730
+ name: string;
1731
+ trigger?: string;
1732
+ intent?: string;
1733
+ scheduledAt: number;
1734
+ }
1735
+ | { type: 'gestureRemoved'; agency: 'gesture'; name: string; reason: string; removedAt: number }
1736
+ | { type: 'prosodicPlanCreated'; agency: 'prosodic'; plan: Record<string, unknown> }
1737
+ | { type: 'prosodicConfigChanged'; agency: 'prosodic'; state: ProsodicState }
1738
+ | { type: 'prosodicSpeechStarted'; agency: 'prosodic'; name?: string; startedAt: number }
1739
+ | { type: 'prosodicWordBoundary'; agency: 'prosodic'; word?: string; wordIndex: number; observedAt: number }
1740
+ | {
1741
+ type: 'prosodicGestureScheduled';
1742
+ agency: 'prosodic';
1743
+ gesture: string;
1744
+ name: string;
1745
+ word?: string;
1746
+ wordIndex?: number;
1747
+ scheduledAt: number;
1748
+ }
1749
+ | { type: 'prosodicStopped'; agency: 'prosodic'; reason: string; stoppedAt: number }
1750
+ | { type: string; agency: 'conversation' | 'transcription' | 'cameraContext'; [key: string]: unknown }
1751
+ | {
1752
+ type: 'ready';
1753
+ agency:
1754
+ | 'character'
1755
+ | 'blink'
1756
+ | 'animation'
1757
+ | 'gaze'
1758
+ | 'eyeHeadTracking'
1759
+ | 'lipSync'
1760
+ | 'tts'
1761
+ | 'gesture'
1762
+ | 'prosodic'
1763
+ | 'conversation'
1764
+ | 'transcription'
1765
+ | 'cameraContext';
1766
+ }
1767
+ | { type: 'error'; agency: string; message: string };
1768
+
1769
+ export type PolymerStatusEvent = PolymerDomainEvent;
1770
+
1771
+ export interface BlinkAgency {
1772
+ input: PolymerInputStream<BlinkDispatch>;
1773
+ events: PolymerStream<PolymerDomainEvent>;
1774
+ dispatch(command: BlinkDispatch): void;
1775
+ snapshot(): BlinkState;
1776
+ subscribeInput(listener: (event: { type: 'command'; agency: 'blink'; command: BlinkDispatch }) => void): () => void;
1777
+ subscribeEvents(listener: (event: PolymerDomainEvent) => void): () => void;
1778
+ /** Compatibility alias for events. Prefer subscribeEvents. */
1779
+ subscribe(listener: (event: PolymerStatusEvent) => void): () => void;
1780
+ /** Compatibility alias for events. Prefer subscribeEvents. */
1781
+ subscribeStatus(listener: (event: PolymerStatusEvent) => void): () => void;
1782
+ enable(): void;
1783
+ disable(): void;
1784
+ triggerBlink(options?: BlinkTriggerOptions): void;
1785
+ setFrequency(value: number): void;
1786
+ setDuration(value: number): void;
1787
+ setIntensity(value: number): void;
1788
+ setRandomness(value: number): void;
1789
+ setLeftEyeIntensity(value: number | null): void;
1790
+ setRightEyeIntensity(value: number | null): void;
1791
+ setBurstEnabled(value: boolean): void;
1792
+ setBurstFrequency(value: number): void;
1793
+ setBurstCount(value: number): void;
1794
+ setBurstGap(value: number): void;
1795
+ reset(): void;
1796
+ dispose(): void;
1797
+ }
1798
+
1799
+ export interface AnimationAgency {
1800
+ input: PolymerInputStream<AnimationDispatch>;
1801
+ events: PolymerStream<PolymerDomainEvent>;
1802
+ dispatch(command: AnimationDispatch): void;
1803
+ snapshot(): AnimationState;
1804
+ subscribeInput(listener: (event: { type: 'command'; agency: 'animation'; command: AnimationDispatch }) => void): () => void;
1805
+ subscribeEvents(listener: (event: PolymerDomainEvent) => void): () => void;
1806
+ /** Compatibility alias for events. Prefer subscribeEvents. */
1807
+ subscribe(listener: (event: PolymerStatusEvent) => void): () => void;
1808
+ /** Compatibility alias for events. Prefer subscribeEvents. */
1809
+ subscribeStatus(listener: (event: PolymerStatusEvent) => void): () => void;
1810
+ scheduleSnippet(snippet: PolymerAnimationSnippet, options?: { autoPlay?: boolean; [key: string]: unknown }): void;
1811
+ seekSnippet(name: string, offsetSec: number): void;
1812
+ updateSnippet(name: string, params: Record<string, unknown>): void;
1813
+ removeSnippet(name: string): void;
1814
+ dispose(): void;
1815
+ }
1816
+
1817
+ export interface GazeAgency {
1818
+ input: PolymerInputStream<GazeDispatch>;
1819
+ events: PolymerStream<PolymerDomainEvent>;
1820
+ dispatch(command: GazeDispatch): void;
1821
+ snapshot(): GazeState;
1822
+ subscribeInput(listener: (event: { type: 'command'; agency: 'gaze'; command: GazeDispatch }) => void): () => void;
1823
+ subscribeEvents(listener: (event: PolymerDomainEvent) => void): () => void;
1824
+ /** Compatibility alias for events. Prefer subscribeEvents. */
1825
+ subscribe(listener: (event: PolymerStatusEvent) => void): () => void;
1826
+ /** Compatibility alias for events. Prefer subscribeEvents. */
1827
+ subscribeStatus(listener: (event: PolymerStatusEvent) => void): () => void;
1828
+ setTarget(target: GazeTarget, options?: GazeApplyOptions): void;
1829
+ focusTarget(target: GazeTarget): void;
1830
+ configure(config: GazeConfig): void;
1831
+ setMode(mode: string): void;
1832
+ setActive(active: boolean): void;
1833
+ enable(): void;
1834
+ disable(): void;
1835
+ reset(durationMs?: number): void;
1836
+ cancel(reason?: string): void;
1837
+ flush(): void;
1838
+ queue(): Array<Record<string, unknown>>;
1839
+ dispose(): void;
1840
+ }
1841
+
1842
+ export interface EyeHeadTrackingAgency {
1843
+ input: PolymerInputStream<EyeHeadTrackingDispatch>;
1844
+ events: PolymerStream<PolymerDomainEvent>;
1845
+ dispatch(command: EyeHeadTrackingDispatch): void;
1846
+ snapshot(): EyeHeadTrackingState;
1847
+ subscribeInput(listener: (event: { type: 'command'; agency: 'eyeHeadTracking'; command: EyeHeadTrackingDispatch }) => void): () => void;
1848
+ subscribeEvents(listener: (event: PolymerDomainEvent) => void): () => void;
1849
+ /** Compatibility alias for events. Prefer subscribeEvents. */
1850
+ subscribe(listener: (event: PolymerStatusEvent) => void): () => void;
1851
+ /** Compatibility alias for events. Prefer subscribeEvents. */
1852
+ subscribeStatus(listener: (event: PolymerStatusEvent) => void): () => void;
1853
+ setTarget(target: GazeTarget): void;
1854
+ configure(config: EyeHeadTrackingConfig): void;
1855
+ enable(): void;
1856
+ disable(): void;
1857
+ reset(durationMs?: number): void;
1858
+ cancel(reason?: string): void;
1859
+ flush(): void;
1860
+ queue(): Array<Record<string, unknown>>;
1861
+ dispose(): void;
1862
+ }
1863
+
1864
+ export interface LipSyncAgency {
1865
+ input: PolymerInputStream<LipSyncDispatch>;
1866
+ events: PolymerStream<PolymerDomainEvent>;
1867
+ dispatch(command: LipSyncDispatch): void;
1868
+ snapshot(): LipSyncState;
1869
+ schedulerQueue(): LipSyncSchedulerQueueEntry[];
1870
+ subscribeInput(listener: (event: { type: 'command'; agency: 'lipSync'; command: LipSyncDispatch }) => void): () => void;
1871
+ subscribeEvents(listener: (event: PolymerDomainEvent) => void): () => void;
1872
+ /** Compatibility alias for events. Prefer subscribeEvents. */
1873
+ subscribe(listener: (event: PolymerStatusEvent) => void): () => void;
1874
+ /** Compatibility alias for events. Prefer subscribeEvents. */
1875
+ subscribeStatus(listener: (event: PolymerStatusEvent) => void): () => void;
1876
+ configure(config: LipSyncConfig): void;
1877
+ startText(text: string): void;
1878
+ startTimeline(timeline: LipSyncTimeline): void;
1879
+ processAzureVisemes(visemes: AzureVisemeEvent[], totalDurationMs?: number): void;
1880
+ wordBoundary(word: string, wordIndex?: number, observedElapsedSec?: number, hostElapsedSec?: number): void;
1881
+ audioStarted(audioTimeSec?: number): void;
1882
+ audioTime(audioTimeSec: number): void;
1883
+ updateWordTimings(wordTimings: LipSyncWordTiming[]): void;
1884
+ stop(): void;
1885
+ reset(): void;
1886
+ dispose(): void;
1887
+ }
1888
+
1889
+ export interface TTSAgency {
1890
+ input: PolymerInputStream<TTSDispatch>;
1891
+ events: PolymerStream<PolymerDomainEvent>;
1892
+ dispatch(command: TTSDispatch): void;
1893
+ snapshot(): TTSState;
1894
+ schedulerQueue(): TTSSchedulerQueueEntry[];
1895
+ subscribeInput(listener: (event: { type: 'command'; agency: 'tts'; command: TTSDispatch }) => void): () => void;
1896
+ subscribeEvents(listener: (event: PolymerDomainEvent) => void): () => void;
1897
+ /** Compatibility alias for events. Prefer subscribeEvents. */
1898
+ subscribe(listener: (event: PolymerStatusEvent) => void): () => void;
1899
+ /** Compatibility alias for events. Prefer subscribeEvents. */
1900
+ subscribeStatus(listener: (event: PolymerStatusEvent) => void): () => void;
1901
+ configure(config: TTSConfig): void;
1902
+ loadVoices(engine?: 'webSpeech' | 'azure' | string): void;
1903
+ speak(text: string): void;
1904
+ stop(): void;
1905
+ reset(): void;
1906
+ /** Live agent playback track for mic-vs-reference barge-in (host API). */
1907
+ getPlaybackReferenceTrack(): MediaStreamTrack | null;
1908
+ onPlaybackReferenceTrackChange(listener: (track: MediaStreamTrack | null) => void): () => void;
1909
+ preparePlaybackReference(): Promise<'unavailable' | 'requesting' | 'available' | 'denied' | 'failed' | 'no-audio' | 'ended'>;
1910
+ dispose(): void;
1911
+ }
1912
+
1913
+ export interface GestureAgency {
1914
+ input: PolymerInputStream<GestureDispatch>;
1915
+ events: PolymerStream<PolymerDomainEvent>;
1916
+ dispatch(command: GestureDispatch): void;
1917
+ snapshot(): GestureState;
1918
+ schedulerQueue(): Array<Record<string, unknown>>;
1919
+ subscribeInput(listener: (event: { type: 'command'; agency: 'gesture'; command: GestureDispatch }) => void): () => void;
1920
+ subscribeEvents(listener: (event: PolymerDomainEvent) => void): () => void;
1921
+ /** Compatibility alias for events. Prefer subscribeEvents. */
1922
+ subscribe(listener: (event: PolymerStatusEvent) => void): () => void;
1923
+ /** Compatibility alias for events. Prefer subscribeEvents. */
1924
+ subscribeStatus(listener: (event: PolymerStatusEvent) => void): () => void;
1925
+ configure(config: GestureConfig): void;
1926
+ loadGestures(gestures: Record<string, GestureSnapshot>, emojiMappings?: Record<string, string>): void;
1927
+ playGesture(gestureId: string): void;
1928
+ playEmoji(emoji: string): void;
1929
+ performGoal(goal: GestureGoal): void;
1930
+ stopGesture(gestureId: string): void;
1931
+ stopAll(): void;
1932
+ reset(): void;
1933
+ dispose(): void;
1934
+ }
1935
+
1936
+ export interface ProsodicAgency {
1937
+ input: PolymerInputStream<ProsodicDispatch>;
1938
+ events: PolymerStream<PolymerDomainEvent>;
1939
+ dispatch(command: ProsodicDispatch): void;
1940
+ snapshot(): ProsodicState;
1941
+ schedulerQueue(): ProsodicSchedulerQueueEntry[];
1942
+ subscribeInput(listener: (event: { type: 'command'; agency: 'prosodic'; command: ProsodicDispatch }) => void): () => void;
1943
+ subscribeEvents(listener: (event: PolymerDomainEvent) => void): () => void;
1944
+ /** Compatibility alias for events. Prefer subscribeEvents. */
1945
+ subscribe(listener: (event: PolymerStatusEvent) => void): () => void;
1946
+ /** Compatibility alias for events. Prefer subscribeEvents. */
1947
+ subscribeStatus(listener: (event: PolymerStatusEvent) => void): () => void;
1948
+ configure(config: ProsodicConfig): void;
1949
+ speechStarted(name?: string): void;
1950
+ wordBoundary(word: string, wordIndex?: number): void;
1951
+ blinkFast(): void;
1952
+ stop(): void;
1953
+ reset(): void;
1954
+ dispose(): void;
1955
+ }
1956
+
1957
+ export interface ConversationAgency {
1958
+ input: PolymerInputStream<ConversationDispatch>;
1959
+ events: PolymerStream<PolymerDomainEvent>;
1960
+ dispatch(command: ConversationDispatch): void;
1961
+ snapshot(): ConversationState;
1962
+ subscribeInput(listener: (event: { type: 'command'; agency: 'conversation'; command: ConversationDispatch }) => void): () => void;
1963
+ subscribeEvents(listener: (event: PolymerDomainEvent) => void): () => void;
1964
+ subscribe(listener: (event: PolymerStatusEvent) => void): () => void;
1965
+ subscribeStatus(listener: (event: PolymerStatusEvent) => void): () => void;
1966
+ start(): void;
1967
+ stop(): void;
1968
+ reset(): void;
1969
+ interrupt(reason?: string): void;
1970
+ setAutoRespond(value: boolean): void;
1971
+ queue(): Array<Record<string, unknown>>;
1972
+ dispose(): void;
1973
+ }
1974
+
1975
+ export interface TranscriptionAgency {
1976
+ input: PolymerInputStream<TranscriptionDispatch>;
1977
+ events: PolymerStream<PolymerDomainEvent>;
1978
+ dispatch(command: TranscriptionDispatch): void;
1979
+ snapshot(): TranscriptionState;
1980
+ subscribeInput(listener: (event: { type: 'command'; agency: 'transcription'; command: TranscriptionDispatch }) => void): () => void;
1981
+ subscribeEvents(listener: (event: PolymerDomainEvent) => void): () => void;
1982
+ subscribe(listener: (event: PolymerStatusEvent) => void): () => void;
1983
+ subscribeStatus(listener: (event: PolymerStatusEvent) => void): () => void;
1984
+ start(): void;
1985
+ stop(): void;
1986
+ reset(): void;
1987
+ setAgentAudioReferenceTrack(track: MediaStreamTrack | null): void;
1988
+ queue(): Array<Record<string, unknown>>;
1989
+ dispose(): void;
1990
+ }
1991
+
1992
+ export interface CameraContextAgency {
1993
+ input: PolymerInputStream<CameraContextDispatch>;
1994
+ events: PolymerStream<PolymerDomainEvent>;
1995
+ dispatch(command: CameraContextDispatch): void;
1996
+ snapshot(): CameraContextState;
1997
+ subscribeInput(listener: (event: { type: 'command'; agency: 'cameraContext'; command: CameraContextDispatch }) => void): () => void;
1998
+ subscribeEvents(listener: (event: PolymerDomainEvent) => void): () => void;
1999
+ subscribe(listener: (event: PolymerStatusEvent) => void): () => void;
2000
+ subscribeStatus(listener: (event: PolymerStatusEvent) => void): () => void;
2001
+ updateCamera(facts: Record<string, unknown>): void;
2002
+ invalidateStale(reason?: string): void;
2003
+ reset(): void;
2004
+ queue(): Array<Record<string, unknown>>;
2005
+ dispose(): void;
2006
+ }
2007
+
2008
+ export interface CharacterAgencySnapshot {
2009
+ blink: BlinkState;
2010
+ gaze: GazeState;
2011
+ eyeHeadTracking: EyeHeadTrackingState;
2012
+ gesture: GestureState;
2013
+ cameraContext: CameraContextState;
2014
+ transcription: TranscriptionState;
2015
+ conversation: ConversationState;
2016
+ tts: TTSState;
2017
+ lipSync: LipSyncState;
2018
+ prosodic: ProsodicState;
2019
+ animation: AnimationState;
2020
+ agencySociety: AgencySociety;
2021
+ }
2022
+
2023
+ export type CharacterAgencyDispatch =
2024
+ | { agency: 'blink'; command: BlinkDispatch }
2025
+ | { agency: 'gaze'; command: GazeDispatch }
2026
+ | { agency: 'eyeHeadTracking'; command: EyeHeadTrackingDispatch }
2027
+ | { agency: 'gesture'; command: GestureDispatch }
2028
+ | { agency: 'cameraContext'; command: CameraContextDispatch }
2029
+ | { agency: 'transcription'; command: TranscriptionDispatch }
2030
+ | { agency: 'conversation'; command: ConversationDispatch }
2031
+ | { agency: 'tts'; command: TTSDispatch }
2032
+ | { agency: 'lipSync'; command: LipSyncDispatch }
2033
+ | { agency: 'prosodic'; command: ProsodicDispatch }
2034
+ | { agency: 'animation'; command: AnimationDispatch };
2035
+
2036
+ export interface CharacterAgencies {
2037
+ input: PolymerInputStream<CharacterAgencyDispatch>;
2038
+ events: PolymerStream<PolymerDomainEvent>;
2039
+ readonly agencySociety: AgencySociety;
2040
+ dispatch(message: CharacterAgencyDispatch): void;
2041
+ snapshot(): CharacterAgencySnapshot;
2042
+ agency(name: 'animation'): AnimationAgency;
2043
+ agency(name: 'blink'): BlinkAgency | null;
2044
+ agency(name: 'gaze'): GazeAgency | null;
2045
+ agency(name: 'eyeHeadTracking'): EyeHeadTrackingAgency | null;
2046
+ agency(name: 'gesture'): GestureAgency | null;
2047
+ agency(name: 'cameraContext'): CameraContextAgency | null;
2048
+ agency(name: 'transcription'): TranscriptionAgency;
2049
+ agency(name: 'conversation'): ConversationAgency;
2050
+ agency(name: 'tts'): TTSAgency;
2051
+ agency(name: 'lipSync'): LipSyncAgency;
2052
+ agency(name: 'prosodic'): ProsodicAgency | null;
2053
+ agency(name: string): unknown | null;
2054
+ subscribeInput(listener: (event: { type: 'command'; agency: string; message: CharacterAgencyDispatch }) => void): () => void;
2055
+ subscribeEvents(listener: (event: PolymerDomainEvent) => void): () => void;
2056
+ /** Compatibility alias for events. Prefer subscribeEvents. */
2057
+ subscribe(listener: (event: PolymerStatusEvent) => void): () => void;
2058
+ /** Compatibility alias for events. Prefer subscribeEvents. */
2059
+ subscribeStatus(listener: (event: PolymerStatusEvent) => void): () => void;
2060
+ dispose(): void;
2061
+ }
2062
+
2063
+ export type CurvePoint = PolymerSnippetKeyframe;
2064
+ export type EasingType = 'linear' | 'easeIn' | 'easeOut' | 'easeInOut' | 'easeInOutCubic';
2065
+ export type MixerLoopMode = 'repeat' | 'once' | 'pingpong';
2066
+ export type SnippetCategoryKey =
2067
+ | 'emotionAnimationsList'
2068
+ | 'speakingAnimationsList'
2069
+ | 'visemeAnimationsList'
2070
+ | 'eyeHeadTrackingAnimationsList';
2071
+
2072
+ export interface AIExpressionInterpretationMetadata {
2073
+ emotion?: string;
2074
+ title?: string;
2075
+ description?: string;
2076
+ explanation?: string;
2077
+ notesByAu?: Record<string, string>;
2078
+ summary?: string;
2079
+ phases?: Array<{ title: string; description: string }>;
2080
+ aus?: Record<string, number>;
2081
+ characterDetailsUsed?: string[];
2082
+ eyeNote?: string | null;
2083
+ headNote?: string | null;
2084
+ pacingNote?: string | null;
2085
+ handoffNote?: string | null;
2086
+ [key: string]: unknown;
2087
+ }
2088
+
2089
+ export interface AIExpressionSnippetMetadata {
2090
+ description?: string;
2091
+ interpretation?: AIExpressionInterpretationMetadata;
2092
+ source?: string;
2093
+ prompt?: string;
2094
+ [key: string]: unknown;
2095
+ }
2096
+
2097
+ export interface Snippet {
2098
+ name?: string;
2099
+ au?: Array<{ id: string | number; t?: number; v?: number; time?: number; intensity?: number; inherit?: boolean }>;
2100
+ viseme?: Array<{ key: string | number; t?: number; v?: number; time?: number; intensity?: number; inherit?: boolean }>;
2101
+ curves?: Record<string, CurvePoint[]>;
2102
+ channels?: PolymerSnippetChannel[];
2103
+ isPlaying?: boolean;
2104
+ loop?: boolean;
2105
+ maxTime?: number;
2106
+ duration?: number;
2107
+ snippetCategory?: 'auSnippet' | 'visemeSnippet' | 'eyeHeadTracking' | 'combined' | 'default' | string;
2108
+ snippetPriority?: number;
2109
+ snippetPlaybackRate?: number;
2110
+ snippetIntensityScale?: number;
2111
+ snippetBlendMode?: 'replace' | 'additive';
2112
+ snippetJawScale?: number;
2113
+ autoVisemeJaw?: boolean;
2114
+ snippetBalance?: number;
2115
+ snippetBalanceMap?: Record<string, number>;
2116
+ snippetEasing?: EasingType;
2117
+ aiExpressionMetadata?: AIExpressionSnippetMetadata;
2118
+ [key: string]: unknown;
2119
+ }
2120
+
2121
+ export interface NormalizedSnippet extends Snippet {
2122
+ name: string;
2123
+ curves: Record<string, CurvePoint[]>;
2124
+ isPlaying: boolean;
2125
+ loop: boolean;
2126
+ aiExpressionMetadata?: AIExpressionSnippetMetadata;
2127
+ loopIteration: number;
2128
+ loopDirection: 1 | -1;
2129
+ lastLoopTime: number;
2130
+ snippetPlaybackRate: number;
2131
+ snippetIntensityScale: number;
2132
+ snippetCategory: 'auSnippet' | 'visemeSnippet' | 'eyeHeadTracking' | 'combined' | 'default' | string;
2133
+ snippetPriority: number;
2134
+ snippetBlendMode: 'replace' | 'additive';
2135
+ snippetJawScale: number;
2136
+ autoVisemeJaw?: boolean;
2137
+ snippetBalance: number;
2138
+ snippetBalanceMap: Record<string, number>;
2139
+ snippetEasing: EasingType;
2140
+ mixerChannel?: string;
2141
+ mixerBlendMode?: 'replace' | 'additive';
2142
+ mixerWeight?: number;
2143
+ mixerFadeDurationMs?: number;
2144
+ mixerWarpDurationMs?: number;
2145
+ mixerTimeScale?: number;
2146
+ mixerLoopMode?: MixerLoopMode;
2147
+ mixerRepeatCount?: number;
2148
+ mixerClampWhenFinished?: boolean;
2149
+ mixerAdditive?: boolean;
2150
+ mixerReverse?: boolean;
2151
+ currentTime: number;
2152
+ startWallTime: number;
2153
+ duration: number;
2154
+ cursor: Record<string, number>;
2155
+ }
2156
+
2157
+ export interface SnippetUIState {
2158
+ name: string;
2159
+ isPlaying: boolean;
2160
+ loop: boolean;
2161
+ loopMode: MixerLoopMode;
2162
+ reverse: boolean;
2163
+ repeatCount?: number;
2164
+ loopIteration?: number;
2165
+ loopDirection?: 1 | -1;
2166
+ currentTime: number;
2167
+ duration: number;
2168
+ playbackRate: number;
2169
+ intensityScale: number;
2170
+ blendMode: 'replace' | 'additive';
2171
+ balance: number;
2172
+ category: string;
2173
+ easing: EasingType;
2174
+ }
2175
+
2176
+ export interface BakedClipChannelInfo {
2177
+ channel: string;
2178
+ trackCount: number;
2179
+ playable: boolean;
2180
+ blendMode?: 'replace' | 'additive';
2181
+ }
2182
+
2183
+ export interface BakedClipInfo {
2184
+ name: string;
2185
+ duration: number;
2186
+ channels?: BakedClipChannelInfo[];
2187
+ }
2188
+
2189
+ export interface BakedAnimationUIState {
2190
+ name: string;
2191
+ source: 'baked';
2192
+ time: number;
2193
+ currentTime: number;
2194
+ duration: number;
2195
+ speed: number;
2196
+ playbackRate: number;
2197
+ weight: number;
2198
+ intensityScale: number;
2199
+ isPlaying: boolean;
2200
+ isPaused: boolean;
2201
+ loop: boolean;
2202
+ loopMode: MixerLoopMode;
2203
+ reverse: boolean;
2204
+ repeatCount?: number;
2205
+ requestedBlendMode: 'replace' | 'additive';
2206
+ blendMode: 'replace' | 'additive';
2207
+ balance: number;
2208
+ category: 'baked';
2209
+ easing: EasingType;
2210
+ channels: BakedClipChannelInfo[];
2211
+ }
2212
+
2213
+ export type AnimationEvent = {
2214
+ timestamp: number;
2215
+ snippetName?: string;
2216
+ clipName?: string;
2217
+ } & (
2218
+ | { type: 'SNIPPET_ADDED'; snippetName: string }
2219
+ | { type: 'SNIPPET_REMOVED'; snippetName: string }
2220
+ | { type: 'SNIPPET_PLAY_STATE_CHANGED'; snippetName: string; isPlaying: boolean }
2221
+ | { type: 'SNIPPET_UPDATED'; snippetName: string }
2222
+ | { type: 'SNIPPET_LOOPED'; snippetName: string; iteration: number; localTime: number }
2223
+ | { type: 'SNIPPET_COMPLETED'; snippetName: string }
2224
+ | { type: 'KEYFRAME_COMPLETED'; snippetName: string; keyframeIndex: number; totalKeyframes: number; currentTime: number; duration: number }
2225
+ | { type: 'SNIPPET_PARAMS_CHANGED'; snippetName: string; params: Record<string, unknown> }
2226
+ | { type: 'GLOBAL_PLAYBACK_CHANGED'; state: 'playing' | 'paused' | 'stopped' }
2227
+ | { type: 'SNIPPET_SEEKED'; snippetName: string; time: number }
2228
+ | { type: 'BAKED_CLIPS_LOADED'; clips: BakedClipInfo[] }
2229
+ | { type: 'BAKED_ANIMATION_STARTED'; clipName: string; state: BakedAnimationUIState }
2230
+ | { type: 'BAKED_ANIMATION_STOPPED'; clipName: string }
2231
+ | { type: 'BAKED_ANIMATION_PAUSED'; clipName: string }
2232
+ | { type: 'BAKED_ANIMATION_RESUMED'; clipName: string }
2233
+ | { type: 'BAKED_ANIMATION_COMPLETED'; clipName: string }
2234
+ | { type: 'BAKED_ANIMATION_PROGRESS'; clipName: string; time: number; duration: number }
2235
+ | { type: 'BAKED_ANIMATION_PARAMS_CHANGED'; clipName: string; params: Record<string, unknown> }
2236
+ );
2237
+
2238
+ export interface AnimationSubscription {
2239
+ unsubscribe(): void;
2240
+ }
2241
+
2242
+ export interface AnimationObservable<T> {
2243
+ subscribe(listener: (value: T) => void): AnimationSubscription;
2244
+ subscribe(listener: { next(value: T): void }): AnimationSubscription;
2245
+ pipe<A = T>(...operators: Array<(source: any) => any>): AnimationObservable<A>;
2246
+ }
2247
+
2248
+ export interface AnimationEventEmitter {
2249
+ events: AnimationObservable<AnimationEvent>;
2250
+ setSnippetAccessor(getSnippets: () => NormalizedSnippet[]): void;
2251
+ getSnippets(): SnippetUIState[];
2252
+ getRawSnippets(): NormalizedSnippet[];
2253
+ getRawSnippet(name: string): NormalizedSnippet | null;
2254
+ getSnippet(name: string): SnippetUIState | null;
2255
+ getGlobalState(): 'playing' | 'paused' | 'stopped';
2256
+ emitSnippetAdded(snippetName: string): void;
2257
+ emitSnippetRemoved(snippetName: string): void;
2258
+ emitPlayStateChanged(snippetName: string, isPlaying: boolean): void;
2259
+ emitSnippetUpdated(snippetName: string): void;
2260
+ emitSnippetLooped(data: { snippetName: string; iteration: number; localTime: number }): void;
2261
+ emitSnippetCompleted(snippetName: string): void;
2262
+ emitKeyframeCompleted(data: { snippetName: string; keyframeIndex: number; totalKeyframes: number; currentTime: number; duration: number }): void;
2263
+ emitGlobalPlaybackChanged(state: 'playing' | 'paused' | 'stopped'): void;
2264
+ emitSnippetSeeked(snippetName: string, time: number): void;
2265
+ emitParamsChanged(snippetName: string, params: Record<string, unknown>): void;
2266
+ emitBakedClipsLoaded(clips: BakedClipInfo[]): void;
2267
+ emitBakedAnimationStarted(clipName: string, state: BakedAnimationUIState): void;
2268
+ emitBakedAnimationStopped(clipName: string): void;
2269
+ emitBakedAnimationPaused(clipName: string): void;
2270
+ emitBakedAnimationResumed(clipName: string): void;
2271
+ emitBakedAnimationCompleted(clipName: string): void;
2272
+ emitBakedAnimationProgress(clipName: string, time: number, duration: number): void;
2273
+ emitBakedAnimationParamsChanged(clipName: string, params: Record<string, unknown>): void;
2274
+ getBakedClips(): BakedClipInfo[];
2275
+ getPlayingBakedAnimations(): BakedAnimationUIState[];
2276
+ getBakedAnimationState(clipName: string): BakedAnimationUIState | null;
2277
+ updateBakedAnimationState(clipName: string, state: BakedAnimationUIState): void;
2278
+ }
2279
+
2280
+ export interface AnimationService {
2281
+ /** Event/state access owned by this service instance. */
2282
+ readonly eventEmitter: AnimationEventEmitter;
2283
+ readonly events: AnimationObservable<AnimationEvent>;
2284
+ readonly snippetList$: AnimationObservable<string[]>;
2285
+ readonly globalPlaybackState$: AnimationObservable<'playing' | 'paused' | 'stopped'>;
2286
+ readonly bakedClipList$: AnimationObservable<BakedClipInfo[]>;
2287
+ readonly playingBakedAnimations$: AnimationObservable<BakedAnimationUIState[]>;
2288
+ readonly bakedAnimationProgress$: AnimationObservable<AnimationEvent>;
2289
+ snippetState$(snippetName: string): AnimationObservable<SnippetUIState | null>;
2290
+ snippetTime$(snippetName: string): AnimationObservable<number>;
2291
+ bakedAnimationState$(clipName: string): AnimationObservable<BakedAnimationUIState | null>;
2292
+ loadFromJSON(data: Snippet | NormalizedSnippet): string;
2293
+ updateSnippet(data: Snippet | NormalizedSnippet): string;
2294
+ schedule(data: Snippet | NormalizedSnippet, opts?: { startInSec?: number; startAtSec?: number; offsetSec?: number; priority?: number; autoPlay?: boolean }): string;
2295
+ remove(name: string): void;
2296
+ play(): void;
2297
+ pause(): void;
2298
+ stop(): void;
2299
+ enable(name: string, on?: boolean): boolean;
2300
+ seek(name: string, offsetSec: number): boolean;
2301
+ getState(): { context: { animations: NormalizedSnippet[] } };
2302
+ getScheduleSnapshot(): Array<{ name: string; enabled: boolean; startsAt: number; offset: number; localTime: number; duration: number; loop: boolean; priority: number; playbackRate: number; intensityScale: number }>;
2303
+ getCurrentValue(auId: string): number;
2304
+ readonly playing: boolean;
2305
+ isPlaying(): boolean;
2306
+ loadFromLocal(key: string, cat?: string, prio?: number): string | null;
2307
+ setSnippetPlaybackRate(name: string, rate: number): void;
2308
+ setSnippetIntensityScale(name: string, scale: number): void;
2309
+ setSnippetBlendMode(name: string, mode: 'replace' | 'additive'): void;
2310
+ setSnippetBalance(name: string, balance: number): void;
2311
+ setSnippetEasing(name: string, easing: EasingType): void;
2312
+ setSnippetPriority(name: string, priority: number): void;
2313
+ setSnippetLoopMode(name: string, mode: MixerLoopMode): void;
2314
+ setSnippetRepeatCount(name: string, repeatCount?: number): void;
2315
+ setSnippetReverse(name: string, reverse: boolean): void;
2316
+ setSnippetPlaying(name: string, nextPlaying: boolean): boolean;
2317
+ setSnippetTime(name: string, tSec: number): void;
2318
+ setSnippetLoopState(name: string, iteration: number, localTime?: number): void;
2319
+ pauseSnippet(name: string): boolean;
2320
+ resumeSnippet(name: string): boolean;
2321
+ restartSnippet(name: string): boolean;
2322
+ stopSnippet(name: string): boolean;
2323
+ onTransition(cb: (snapshot: { context: { animations: NormalizedSnippet[] } }) => void): () => void;
2324
+ dispose(): void;
2325
+ debug(): void;
2326
+ setBakedAnimationEngine(engine: Embody | EmbodyRuntime): void;
2327
+ playBakedAnimation(clipName: string, options?: Record<string, unknown>): unknown;
2328
+ stopBakedAnimation(clipName: string): void;
2329
+ pauseBakedAnimation(clipName: string): void;
2330
+ resumeBakedAnimation(clipName: string): void;
2331
+ setBakedAnimationSpeed(clipName: string, speed: number): void;
2332
+ setBakedAnimationWeight(clipName: string, weight: number): void;
2333
+ setBakedAnimationLoop(clipName: string, loop: boolean): void;
2334
+ setBakedAnimationLoopMode(clipName: string, mode: MixerLoopMode): void;
2335
+ setBakedAnimationRepeatCount(clipName: string, repeatCount?: number): void;
2336
+ setBakedAnimationReverse(clipName: string, reverse: boolean): void;
2337
+ setBakedAnimationBlendMode(clipName: string, mode: 'replace' | 'additive'): void;
2338
+ setBakedAnimationBalance(clipName: string, balance: number): void;
2339
+ setBakedAnimationEasing(clipName: string, easing: EasingType): void;
2340
+ seekBakedAnimation(clipName: string, time: number): boolean;
2341
+ canSeekBakedAnimation(): boolean;
2342
+ stopAllBakedAnimations(): void;
2343
+ getBakedClips(): BakedClipInfo[];
2344
+ getPlayingBakedAnimations(): BakedAnimationUIState[];
2345
+ }
2346
+
2347
+ export interface EyeHeadTrackingRuntimeState {
2348
+ eyeStatus: 'idle' | 'tracking' | 'lagging';
2349
+ headStatus: 'idle' | 'tracking' | 'lagging';
2350
+ currentGaze: GazeTarget;
2351
+ targetGaze: GazeTarget;
2352
+ eyeIntensity: number;
2353
+ lastBlinkTime: number | null;
2354
+ headIntensity: number;
2355
+ headFollowTimer: number | null;
2356
+ isSpeaking: boolean;
2357
+ isListening: boolean;
2358
+ returnToNeutralTimer: number | null;
2359
+ lastGazeUpdateTime: number;
2360
+ mode?: string;
2361
+ }
2362
+
2363
+ export interface EyeHeadTrackingCallbacks {
2364
+ onEyeStart?: () => void;
2365
+ onEyeStop?: () => void;
2366
+ onHeadStart?: () => void;
2367
+ onHeadStop?: () => void;
2368
+ onGazeChange?: (target: GazeTarget) => void;
2369
+ onBlink?: () => void;
2370
+ onError?: (error: Error) => void;
2371
+ }
2372
+
2373
+ export interface EyeHeadTrackingMachineContext {
2374
+ config: EyeHeadTrackingConfig;
2375
+ mode: 'manual' | 'mouse' | 'webcam' | string;
2376
+ target: GazeTarget;
2377
+ lastApplied: GazeTarget;
2378
+ status: {
2379
+ eye: 'idle' | 'tracking' | 'lagging';
2380
+ head: 'idle' | 'tracking' | 'lagging';
2381
+ };
2382
+ }
2383
+
2384
+ export interface EyeHeadTrackingService {
2385
+ start(): void;
2386
+ stop(): void;
2387
+ setGazeTarget(target: GazeTarget): void;
2388
+ resetToNeutral(durationMs?: number): void;
2389
+ blink(): void;
2390
+ setSpeaking(isSpeaking: boolean): void;
2391
+ setListening(isListening: boolean): void;
2392
+ setEyeBlendWeight(value: number): void;
2393
+ setHeadBlendWeight(value: number): void;
2394
+ updateConfig(config: Partial<EyeHeadTrackingConfig>): void;
2395
+ getState(): EyeHeadTrackingRuntimeState;
2396
+ getMachineContext(): EyeHeadTrackingMachineContext | null;
2397
+ getSnippets(): { eye: Map<string, unknown>; head: Map<string, unknown> };
2398
+ setMode(mode: 'manual' | 'mouse' | 'webcam' | string): void;
2399
+ getMode(): 'manual' | 'mouse' | 'webcam' | string;
2400
+ subscribeToWebcam(callback: (detected: boolean, landmarks?: Array<{ x: number; y: number }>) => void): () => void;
2401
+ getWebcamVideoElement(): HTMLVideoElement | null;
2402
+ isWebcamActive(): boolean;
2403
+ dispose(): void;
2404
+ }
2405
+
2406
+ export interface BoundaryEvent {
2407
+ word: string;
2408
+ index: number;
2409
+ timestamp: number;
2410
+ speaker: 'user' | 'agent';
2411
+ }
2412
+
2413
+ export interface InterruptionEvent {
2414
+ timestamp: number;
2415
+ microphoneLevel: number;
2416
+ referenceLevel: number;
2417
+ requiredLevel: number;
2418
+ }
2419
+
2420
+ export interface TranscriptInterruptionEvent {
2421
+ type: 'transcription.interruption';
2422
+ agency: 'transcription';
2423
+ targetAgency: 'conversation';
2424
+ text: string;
2425
+ confidence: number;
2426
+ source: string;
2427
+ sessionId: string | null;
2428
+ at: number;
2429
+ }
2430
+
2431
+ export interface TranscriptionCallbacks {
2432
+ onTranscript?: (transcript: string, isFinal: boolean) => void;
2433
+ onStart?: () => void;
2434
+ onEnd?: () => void;
2435
+ onError?: (error: Error) => void;
2436
+ onBoundary?: (event: BoundaryEvent) => void;
2437
+ onInterruption?: (event: InterruptionEvent) => void;
2438
+ }
2439
+
2440
+ export interface AgentSpeechEvent {
2441
+ type: 'AGENT_SCRIPT' | 'AGENT_START' | 'WORD' | 'END' | 'AGENT_DONE' | 'PLAYBACK_ENDED';
2442
+ words?: string[];
2443
+ word?: string;
2444
+ index?: number;
2445
+ phrase?: string;
2446
+ }
2447
+
2448
+ export interface TranscriptionService {
2449
+ startListening(): Promise<void>;
2450
+ stopListening(): void;
2451
+ handleAgentSpeech(event: AgentSpeechEvent): void;
2452
+ prepareAgentSpeech(text: string): void;
2453
+ notifyAgentSpeech(text: string): void;
2454
+ notifyAgentSpeechEnd(): void;
2455
+ setAgentAudioReferenceTrack(track: MediaStreamTrack | null): void;
2456
+ onBoundary(listener: (event: BoundaryEvent) => void): () => void;
2457
+ onTranscript(listener: (transcript: string, isFinal: boolean) => void): () => void;
2458
+ onInterruption(listener: (event: InterruptionEvent) => void): () => void;
2459
+ getState(): TranscriptionState;
2460
+ updateConfig(config: Partial<TranscriptionConfig>): void;
2461
+ dispose(): void;
2462
+ }
2463
+
2464
+ export type ConversationStateName = 'idle' | 'agentSpeaking' | 'interrupted' | 'userSpeaking' | 'processing';
2465
+
2466
+ export interface ConversationCallbacks {
2467
+ onUserSpeech?: (transcript: string, isFinal: boolean, isInterruption: boolean) => void;
2468
+ onAgentUtterance?: (text: string) => void;
2469
+ onStateChange?: (state: ConversationStateName) => void;
2470
+ onError?: (error: Error) => void;
2471
+ }
2472
+
2473
+ export type ConversationFlow = Generator<string | Promise<string>, string | void, string>;
2474
+
2475
+ export interface ConversationService {
2476
+ start(flowGenerator: () => ConversationFlow): void;
2477
+ stop(): void;
2478
+ getState(): {
2479
+ state: ConversationStateName;
2480
+ lastUserSpeech?: string | null;
2481
+ lastAgentSpeech?: string | null;
2482
+ isInterrupted?: boolean;
2483
+ speakStartTime?: number | null;
2484
+ };
2485
+ submitUserInput(text: string): void;
2486
+ addSubscriptionCleanup?(unsubscribe: () => void): void;
2487
+ receiveTranscript?(text: string, isFinal: boolean): void;
2488
+ receiveAudioInterruption?(event: InterruptionEvent): void;
2489
+ dispose(): void;
2490
+ }
2491
+
2492
+ export interface ResolvedSnippetEntry {
2493
+ name: string;
2494
+ data: Record<string, unknown>;
2495
+ source: 'localStorage' | 'bundled';
2496
+ storageKey: string;
2497
+ }
2498
+
2499
+ /** @deprecated Use the eventEmitter owned by an AnimationService instance. */
2500
+ export const animationEventEmitter: AnimationEventEmitter;
2501
+ /** @deprecated Use the corresponding port owned by an AnimationService instance. */
2502
+ export const snippetList$: AnimationObservable<string[]>;
2503
+ /** @deprecated Use AnimationService.snippetState$. */
2504
+ export function snippetState$(snippetName: string): AnimationObservable<SnippetUIState | null>;
2505
+ /** @deprecated Use AnimationService.snippetTime$. */
2506
+ export function snippetTime$(snippetName: string): AnimationObservable<number>;
2507
+ /** @deprecated Use AnimationService.globalPlaybackState$. */
2508
+ export const globalPlaybackState$: AnimationObservable<'playing' | 'paused' | 'stopped'>;
2509
+ /** @deprecated Use AnimationService.bakedClipList$. */
2510
+ export const bakedClipList$: AnimationObservable<BakedClipInfo[]>;
2511
+ /** @deprecated Use AnimationService.playingBakedAnimations$. */
2512
+ export const playingBakedAnimations$: AnimationObservable<BakedAnimationUIState[]>;
2513
+ /** @deprecated Use AnimationService.bakedAnimationProgress$. */
2514
+ export const bakedAnimationProgress$: AnimationObservable<AnimationEvent>;
2515
+ /** @deprecated Use AnimationService.bakedAnimationState$. */
2516
+ export function bakedAnimationState$(clipName: string): AnimationObservable<BakedAnimationUIState | null>;
2517
+ export function createAnimationService(engine: Embody | EmbodyRuntime): AnimationService;
2518
+ export function createEyeHeadTrackingService(config?: EyeHeadTrackingConfig, callbacks?: EyeHeadTrackingCallbacks): EyeHeadTrackingService;
2519
+ export function createTranscriptionService(config?: TranscriptionConfig, callbacks?: TranscriptionCallbacks): TranscriptionService;
2520
+ export function createConversationService(tts: { speak(text: string): Promise<unknown>; stop(): void }, transcription: TranscriptionService, config?: ConversationConfig, callbacks?: ConversationCallbacks): ConversationService;
2521
+ export const DEFAULT_HAIR_PHYSICS_ENABLED: boolean;
2522
+ export const DEFAULT_AGENCY_SOCIETY: AgencySociety;
2523
+ export const DEFAULT_EYE_HEAD_CONFIG: Required<Pick<EyeHeadTrackingConfig, 'gazeMode' | 'eyeTrackingEnabled' | 'headTrackingEnabled' | 'headFollowEyes' | 'eyeIntensity' | 'headIntensity' | 'returnToNeutralEnabled' | 'returnToNeutralDelay' | 'returnToNeutralDuration' | 'useAnimationAgency'>>;
2524
+ export const DEFAULT_ANIMATION_KEYS: Record<string, string>;
2525
+ export const EYE_AUS: Record<string, number>;
2526
+ export const HEAD_AUS: Record<string, number>;
2527
+ export function getBundledSnippetNames(listKey: SnippetCategoryKey): string[];
2528
+ export function getStoredSnippetNames(listKey: SnippetCategoryKey, storage?: Pick<Storage, 'getItem' | 'removeItem'>): string[];
2529
+ export function getAvailableSnippetNames(listKey: SnippetCategoryKey, storage?: Pick<Storage, 'getItem' | 'removeItem'>): string[];
2530
+ export function resolveSnippetEntry(listKey: SnippetCategoryKey, name: string, storage?: Pick<Storage, 'getItem' | 'removeItem'>): Promise<ResolvedSnippetEntry | null>;
2531
+ export function preloadAllSnippets(): void;
2532
+ export function clearPreloadedSnippets(storage?: Pick<Storage, 'getItem' | 'removeItem'>): void;
2533
+
2534
+ export interface AgencySocietyAgencyEntry {
2535
+ required?: boolean;
2536
+ enabled?: boolean;
2537
+ priors?: Record<string, number | string | boolean>;
2538
+ configure?: Record<string, unknown>;
2539
+ }
2540
+
2541
+ export interface AgencySocietyEdge {
2542
+ id: string;
2543
+ from: string;
2544
+ type: string;
2545
+ to: string;
2546
+ required?: boolean;
2547
+ enabled?: boolean;
2548
+ credit?: number;
2549
+ match?: Record<string, unknown>;
2550
+ }
2551
+
2552
+ export interface AgencySocietyKLine {
2553
+ id: string;
2554
+ description?: string;
2555
+ snapshot?: {
2556
+ credits?: Record<string, number>;
2557
+ priors?: Record<string, Record<string, number | string | boolean>>;
2558
+ configure?: Record<string, Record<string, unknown>>;
2559
+ agencies?: string[];
2560
+ };
2561
+ activateEdges?: string[];
2562
+ gainOverlay?: Record<string, number>;
2563
+ }
2564
+
2565
+ export interface AgencySociety {
2566
+ version: number;
2567
+ agencies: Record<string, AgencySocietyAgencyEntry>;
2568
+ edges: AgencySocietyEdge[];
2569
+ kLines?: AgencySocietyKLine[];
2570
+ cb5t?: { E?: number; N?: number; C?: number; A?: number; O?: number };
2571
+ personaPackId?: string | null;
2572
+ characterRollup?: { type: 'sum' | 'weightedSum'; weights?: Record<string, number> };
2573
+ }
2574
+
2575
+ export function createBlinkAgency(config?: BlinkAgencyConfig): BlinkAgency;
2576
+ export function createAnimationAgency(config?: AnimationAgencyConfig): AnimationAgency;
2577
+ export function createGazeAgency(config?: GazeConfig): GazeAgency;
2578
+ export function createEyeHeadTrackingAgency(config?: EyeHeadTrackingConfig): EyeHeadTrackingAgency;
2579
+ export function createLipSyncAgency(config?: LipSyncConfig, runtime?: LipSyncRuntime): LipSyncAgency;
2580
+ export function createTTSAgency(config?: TTSConfig): TTSAgency;
2581
+ export function createGestureAgency(config?: GestureConfig): GestureAgency;
2582
+ export function createProsodicAgency(config?: ProsodicConfig): ProsodicAgency;
2583
+ export function createConversationAgency(config?: ConversationAgencyConfig): ConversationAgency;
2584
+ export function createTranscriptionAgency(config?: TranscriptionConfig): TranscriptionAgency;
2585
+ export function createCameraContextAgency(config?: CameraContextConfig): CameraContextAgency;
2586
+ export function createCharacterAgencies(config?: {
2587
+ blink?: BlinkAgencyConfig;
2588
+ gaze?: GazeConfig;
2589
+ eyeHeadTracking?: EyeHeadTrackingConfig;
2590
+ gesture?: GestureConfig;
2591
+ cameraContext?: CameraContextConfig;
2592
+ transcription?: TranscriptionConfig;
2593
+ conversation?: ConversationAgencyConfig;
2594
+ tts?: TTSConfig;
2595
+ lipSync?: LipSyncConfig;
2596
+ lipSyncRuntime?: LipSyncRuntime;
2597
+ prosodic?: ProsodicConfig;
2598
+ animation?: AnimationAgencyConfig;
2599
+ /** Compatibility injection point passed into Conversation's private effector. */
2600
+ conversationProvider?: ConversationProvider;
2601
+ /** Optional society wiring / priors seed (see AgencySociety). */
2602
+ agencySociety?: AgencySociety;
2603
+ }): CharacterAgencies;