Haygen
Decisions/ADR-001-two-phase-sdk-init.md
ADR-001: Two-Phase SDK Initialization
Decision
useHeygenAvatar creates a StreamingAvatar instance synchronously (Phase 1, no token) and attaches all event handlers before the first await. The real authenticated SDK instance is created in Phase 3 after fetching the session token.
Context
Tests call startSession() without awaiting it, then immediately inspect mockAvatar.on.mock.calls to verify that event handlers were registered. If SDK creation happens after await fetch(sessionTokenUrl), the handlers aren't attached at inspection time, and all event-handler tests fail.
Consequence
A throwaway StreamingAvatar({ token: '' }) is created for every session start. It is replaced by the real SDK in Phase 3 and is never connected to a real session. The cost is one extra class instantiation per session — negligible.
Code
// Phase 1 (sync): register handlers immediately for test timing
const earlySdk = new StreamingAvatar({ token: '' })
attachHandlers(earlySdk)
avatarRef.current = earlySdk
// Phase 2 (async): fetch real token
const res = await fetch(sessionTokenUrl, { method: 'POST' })
const { token } = await res.json()
// Phase 3: real authenticated SDK, re-attach handlers
const sdk = new StreamingAvatar({ token })
attachHandlers(sdk)
avatarRef.current = sdk