Class SpeechProviderResolver

Central resolver for speech providers (STT, TTS, VAD, wake-word).

Resolution Algorithm

  1. Registration — Providers are registered via register() with a unique id, a kind (stt/tts/vad/wake-word), a numeric priority, and a boolean isConfigured flag.

  2. Filtering — When a consumer calls resolveSTT(), resolveTTS(), resolveVAD(), or resolveWakeWord(), the resolver filters registrations by kind and isConfigured === true.

  3. Requirements matching — Optional ProviderRequirements further filter by streaming, local, and features capabilities from the provider's catalog entry.

  4. Priority ordering — Remaining candidates are sorted by ascending priority (lower number = tried first). Core providers default to 100, extensions to 200, and user-preferred providers get boosted to 50+.

  5. Fallback wrapping — When config.stt.fallback or config.tts.fallback is true and multiple candidates survive, they are wrapped in a FallbackSTTProxy or FallbackTTSProxy that tries each in order, emitting provider_fallback events on failure.

Priority Tiers

Tier Priority Range Source
User-preferred 50–59 config.stt.preferred / config.tts.preferred
Core 100 Built-in provider catalog
Extension 200 Discovered via ExtensionManager

Events

Event Payload When
provider_registered { id, kind, source } A provider is registered via register()

See

Example

const resolver = new SpeechProviderResolver(
{ stt: { preferred: ['deepgram-batch'], fallback: true } },
process.env,
);
await resolver.refresh();
const stt = resolver.resolveSTT({ features: ['diarization'] });

Hierarchy

  • EventEmitter
    • SpeechProviderResolver

Constructors

  • Creates a new SpeechProviderResolver.

    Parameters

    • Optional config: SpeechResolverConfig

      Optional resolver configuration controlling preferred providers and fallback behaviour for each provider kind.

    • env: Record<string, undefined | string> = process.env

      Environment variable map used to check whether a provider's required API keys are present. Defaults to process.env so unit tests can inject a controlled map without polluting the real environment.

    Returns SpeechProviderResolver

    Example

    // Production: use real env vars
    const resolver = new SpeechProviderResolver({ stt: { fallback: true } });

    // Testing: inject controlled env
    const resolver = new SpeechProviderResolver(undefined, { OPENAI_API_KEY: 'test' });

Methods

  • Register a provider, overwriting any existing registration with the same id.

    Emits a provider_registered event with { id, kind, source } so that listeners (e.g. UI dashboards, logging middleware) can track what's available.

    Parameters

    • reg: ProviderRegistration

      The full registration object including the provider instance, catalog entry, priority, and configuration status.

    Returns void

    Example

    resolver.register({
    id: 'custom-stt',
    kind: 'stt',
    provider: myCustomProvider,
    catalogEntry: { id: 'custom-stt', kind: 'stt', label: 'Custom', envVars: [], local: false, description: '' },
    isConfigured: true,
    priority: 150,
    source: 'extension',
    });
  • List all registrations for a given provider kind, sorted ascending by priority (lower number = higher priority = tried first).

    This returns both configured and unconfigured providers — use .filter(r => r.isConfigured) if you only want usable ones.

    Parameters

    Returns ProviderRegistration[]

    A new array of registrations sorted by ascending priority.

    Example

    const allSTT = resolver.listProviders('stt');
    const configured = allSTT.filter(r => r.isConfigured);
    console.log(`${configured.length} of ${allSTT.length} STT providers ready`);
  • Resolve the best STT provider matching optional ProviderRequirements.

    When config.stt.fallback is true and multiple candidates exist, wraps them in a FallbackSTTProxy that tries providers in priority order. Otherwise returns the single highest-priority match.

    Parameters

    • Optional requirements: ProviderRequirements

      Optional filtering criteria (streaming, local, features, preferredIds).

    Returns SpeechToTextProvider

    The resolved STT provider, possibly wrapped in a FallbackSTTProxy.

    Throws

    When no configured STT provider matches the requirements.

    See

    Example

    // Simple: best available
    const stt = resolver.resolveSTT();

    // With requirements
    const stt = resolver.resolveSTT({ streaming: true, features: ['diarization'] });

    // With explicit preference ordering
    const stt = resolver.resolveSTT({ preferredIds: ['deepgram-batch', 'openai-whisper'] });
  • Resolve the highest-priority configured VAD provider.

    VAD providers don't support fallback chains because voice activity detection is a real-time frame-by-frame operation where mid-session provider switching would cause state inconsistency.

    Returns SpeechVadProvider

    The resolved VAD provider instance.

    Throws

    When no VAD provider is registered and configured.

    Example

    const vad = resolver.resolveVAD();
    const decision = vad.processFrame(audioFrame);
  • Resolve the highest-priority configured wake-word provider, or null when none is registered.

    Returns null instead of throwing because wake-word detection is an optional feature — many deployments operate without it.

    Returns null | WakeWordProvider

    The resolved wake-word provider, or null if none is available.

    Example

    const wakeWord = resolver.resolveWakeWord();
    if (wakeWord) {
    const detection = await wakeWord.detect(frame, sampleRate);
    }
  • Populate the resolver by registering core providers from the static catalog, optionally discovering extension providers, and applying user-configured preferred priorities.

    The three-phase refresh sequence is:

    1. registerCoreProviders() — register all built-in providers from the static catalog, marking each as configured/unconfigured based on env vars.
    2. discoverExtensionProviders() — if an ExtensionManager is provided, discover and register any additional speech providers from extensions.
    3. applyPreferredPriorities() — boost priority for providers listed in the user's config.stt.preferred / config.tts.preferred arrays.

    Parameters

    • Optional extensionManager: any

      Optional object exposing getDescriptorsByKind(kind). Uses any type because the ExtensionManager interface is defined in the extensions package and importing it here would create a circular dependency.

    Returns Promise<void>

    Example

    const resolver = new SpeechProviderResolver(config, process.env);
    await resolver.refresh(extensionManager);
    // Now all providers are registered and ready to resolve.