idlePassiveTimeoutMs moves out of a one-off deriveAvatarState options
type into $lib/humanoid/config.ts's AnimationConfig, with
DEFAULT_ANIMATION_CONFIG and resolveAnimationConfig(overrides) merging
partial overrides onto it. Documents the convention in HUMANOID.md so
future knobs ported from the Unreal Engine avatar app's animation
systems land in this same interface instead of scattered options.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Ported animation systems (from an Unreal Engine avatar app) key idle
behavior directly off this distinction, so it moves from an unbuilt
extension point to a core state. The pure state.ts reducer stays
timer-free (idleActive -> idlePassive rides in on an explicit
idle_timeout signal); deriveAvatarState in the client wrapper owns the
actual clock via a configurable idlePassiveTimeoutMs (default 30s).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Wraps RealtimeClient with reconnect-on-drop (ResilientRealtimeClient), adds
a MockRealtimeProvider so client/animation work doesn't need a live OpenAI
key, and introduces "optional package" as a third module-layering kind
alongside core/project — humanoid is the first instance, providing a
renderer-agnostic avatar-state reducer and ARKit blend-shape animation
compositor that future eye look-at/blink/lip-sync libraries can build on
without forcing that surface onto non-humanoid (e.g. 2D) projects.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>