{"version":3,"sources":["../../../src/inference/eot/detector.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2026 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Audio end-of-turn detector with `turn-detector-v1` → `turn-detector-v1-mini`\n * (cloud → local) fallback.\n */\nimport type { InferenceExecutor } from '../../ipc/inference_executor.js';\nimport { getJobContext } from '../../job.js';\nimport { log } from '../../log.js';\nimport { type APIConnectOptions, DEFAULT_API_CONNECT_OPTIONS } from '../../types.js';\nimport { isDevMode, isHosted, resolveEnvVar } from '../../utils.js';\nimport { getDefaultInferenceUrl } from '../utils.js';\nimport {\n  BaseStreamingTurnDetector,\n  type BaseStreamingTurnDetectorOptions,\n  BaseStreamingTurnDetectorStream,\n  DEFAULT_SAMPLE_RATE,\n  type StreamingTurnDetectionTransport,\n  SwapAbortError,\n} from './base.js';\nimport { ThresholdOptions, type TurnDetectorModel, type TurnDetectorVersion } from './languages.js';\nimport { CloudTransport, type CloudTransportOptions, LocalTransport } from './transports.js';\n\nexport interface TurnDetectorOptions {\n  /**\n   * Which turn-detector version to run. `'v1'` is the full cloud model (served\n   * over the inference gateway; model name `'turn-detector-v1'`); `'v1-mini'`\n   * is the local in-process model (`'turn-detector-v1-mini'`). When omitted,\n   * auto-selects `'v1'` on hosted/dev environments (falling back to `'v1-mini'`\n   * if cloud creds are missing) and `'v1-mini'` otherwise.\n   */\n  version?: TurnDetectorVersion;\n  unlikelyThreshold?: number | Record<string, number>;\n  /**\n   * Backchannel threshold(s): above this, a pause is a backchannel opportunity.\n   * Server-driven and cloud-only by default; this is an override seam. A scalar\n   * applies to every language; a map is layered over the server defaults.\n   */\n  backchannelThreshold?: number | Record<string, number>;\n  baseUrl?: string;\n  apiKey?: string;\n  apiSecret?: string;\n  /** Sample rate (Hz). Defaults to 16000. */\n  sampleRate?: number;\n  connOptions?: APIConnectOptions;\n  /**\n   * Inference executor that runs the local `turn-detector-v1-mini` model in the\n   * shared inference process. Defaults to the current job's\n   * `getJobContext().inferenceExecutor`. `undefined` (no job context / binding\n   * unavailable) degrades the local model to a positive-default prediction.\n   * Mainly an override seam for tests.\n   */\n  executor?: InferenceExecutor;\n}\n\nexport class TurnDetector extends BaseStreamingTurnDetector {\n  protected _model: TurnDetectorModel;\n  protected _cloudOpts: CloudTransportOptions | undefined;\n  protected _executor: InferenceExecutor | undefined;\n\n  constructor(opts: TurnDetectorOptions = {}) {\n    // auto = caller didn't pin a version; missing cloud creds warn-and-\n    // fall-back instead of raising.\n    const auto = opts.version === undefined;\n    const resolvedVersion: TurnDetectorVersion =\n      opts.version ?? (isHosted() || isDevMode() ? 'v1' : 'v1-mini');\n    let resolvedModel: TurnDetectorModel = `turn-detector-${resolvedVersion}`;\n\n    let cloudOpts: CloudTransportOptions | undefined;\n    if (resolvedVersion === 'v1') {\n      const baseUrl = resolveEnvVar(\n        opts.baseUrl,\n        ['LIVEKIT_INFERENCE_URL'],\n        getDefaultInferenceUrl(),\n      );\n      const apiKey = resolveEnvVar(opts.apiKey, ['LIVEKIT_INFERENCE_API_KEY', 'LIVEKIT_API_KEY']);\n      const apiSecret = resolveEnvVar(opts.apiSecret, [\n        'LIVEKIT_INFERENCE_API_SECRET',\n        'LIVEKIT_API_SECRET',\n      ]);\n      const missing: string[] = [];\n      if (!baseUrl) missing.push('LIVEKIT_INFERENCE_URL');\n      if (!apiKey) missing.push('LIVEKIT_API_KEY');\n      if (!apiSecret) missing.push('LIVEKIT_API_SECRET');\n      if (missing.length > 0) {\n        if (auto) {\n          log().warn(\n            { missing },\n            \"LIVEKIT_INFERENCE_URL is set but creds are missing; falling back to 'v1-mini'\",\n          );\n          resolvedModel = 'turn-detector-v1-mini';\n        } else {\n          throw new Error(\n            `TurnDetector(version='v1') requires ${missing.join(', ')} ` +\n              '(env or constructor argument).',\n          );\n        }\n      } else {\n        cloudOpts = {\n          baseUrl,\n          apiKey,\n          apiSecret,\n          connOptions: opts.connOptions ?? DEFAULT_API_CONNECT_OPTIONS,\n        };\n      }\n    }\n\n    const detectorOpts: BaseStreamingTurnDetectorOptions = {\n      sampleRate: opts.sampleRate ?? DEFAULT_SAMPLE_RATE,\n      thresholds: new ThresholdOptions(\n        resolvedModel,\n        opts.unlikelyThreshold,\n        opts.backchannelThreshold,\n      ),\n    };\n    super(detectorOpts);\n    this._model = resolvedModel;\n    this._cloudOpts = cloudOpts;\n    this._warnThresholdOverride();\n    // Default to the current job's shared inference executor. `getJobContext`\n    // throws outside a job (tests, standalone) — degrade to `undefined`\n    // (the local model then resolves a positive default) rather than throwing.\n    if (opts.executor !== undefined) {\n      this._executor = opts.executor;\n    } else {\n      try {\n        this._executor = getJobContext().inferenceExecutor;\n      } catch {\n        this._executor = undefined;\n      }\n    }\n  }\n\n  /** Current model name. Starts at the construction-time selection and flips to\n   * `'turn-detector-v1-mini'` after a cloud→local fallback: the detector and its\n   * (single) active stream share one mutable `ThresholdOptions`, and the\n   * stream writes the swap back here so EOU metrics and `audio_recognition`\n   * see a consistent view. The fallback is one-way and sticky. */\n  override get model(): TurnDetectorModel {\n    return this._model;\n  }\n\n  /**\n   * What the session report shows for this detector (`telemetry.DescribesOptions`): the model\n   * and where it runs, plus the threshold overrides when the user set any. Server-calibrated\n   * defaults are not repeated here; credentials and endpoints never.\n   */\n  describeOptions(): Readonly<Record<string, unknown>> {\n    const options: Record<string, unknown> = {\n      model: this.model,\n      provider: this.provider,\n      sampleRate: this._opts.sampleRate,\n      // a `v1` detector always degrades to the local model on cloud failure; there is no\n      // `localFallback` opt-out on this side yet\n      localFallback: true,\n    };\n    if (this._opts.thresholds.overrides !== undefined) {\n      options.thresholdOverrides = this._opts.thresholds.overrides;\n    }\n    if (this._opts.thresholds.backchannelOverrides !== undefined) {\n      options.backchannelThresholdOverrides = this._opts.thresholds.backchannelOverrides;\n    }\n    return options;\n  }\n\n  /** @internal Written by the active stream on cloud→local fallback. */\n  _setModel(model: TurnDetectorModel): void {\n    this._model = model;\n  }\n\n  /**\n   * Plain config snapshot for serialization and observability.\n   */\n  toJSON(): Record<string, unknown> {\n    return {\n      model: this._model,\n      sampleRate: this._opts.sampleRate,\n      thresholds: this._opts.thresholds.toJSON(),\n      cloud: this._cloudOpts\n        ? { baseUrl: this._cloudOpts.baseUrl, connOptions: this._cloudOpts.connOptions }\n        : undefined,\n    };\n  }\n\n  protected _warnThresholdOverride(): void {\n    const overrides = this._opts.thresholds.overrides;\n    if (overrides !== undefined) {\n      log().warn(\n        { unlikelyThreshold: overrides },\n        'a non-default turn detection threshold was provided; the server provides calibrated ' +\n          'defaults and overriding them may be suboptimal',\n      );\n    }\n    const bcOverrides = this._opts.thresholds.backchannelOverrides;\n    if (bcOverrides !== undefined) {\n      log().warn(\n        { backchannelThreshold: bcOverrides },\n        'a non-default backchannel threshold was provided; the server provides calibrated ' +\n          'defaults and overriding them may be suboptimal',\n      );\n    }\n  }\n\n  /** Replace the user threshold override at runtime. The shared\n   * `ThresholdOptions` re-resolves against the current (server or shipped)\n   * defaults, so an active stream picks it up immediately. */\n  updateOptions(\n    opts: {\n      unlikelyThreshold?: number | Record<string, number>;\n      backchannelThreshold?: number | Record<string, number>;\n    } = {},\n  ): void {\n    if (opts.unlikelyThreshold !== undefined) {\n      this._opts.thresholds.updateOverrides(opts.unlikelyThreshold);\n    }\n    if (opts.backchannelThreshold !== undefined) {\n      this._opts.thresholds.updateBackchannelOverrides(opts.backchannelThreshold);\n    }\n    this._warnThresholdOverride();\n  }\n\n  override stream(opts: { connOptions?: APIConnectOptions } = {}): BaseStreamingTurnDetectorStream {\n    const cloudOpts =\n      this._cloudOpts !== undefined\n        ? { ...this._cloudOpts, connOptions: opts.connOptions ?? this._cloudOpts.connOptions }\n        : undefined;\n    const stream = new TurnDetectorStreamImpl({\n      detector: this,\n      opts: this._opts,\n      cloudOpts,\n      model: this._model,\n      executor: this._executor,\n    });\n    this._streams.add(stream);\n    return stream;\n  }\n}\n\nexport interface TurnDetectorStreamImplArgs {\n  detector: TurnDetector;\n  opts: BaseStreamingTurnDetectorOptions;\n  cloudOpts: CloudTransportOptions | undefined;\n  model: TurnDetectorModel;\n  /** Shared inference executor for the `turn-detector-v1-mini` (local) model\n   * (undefined degrades to a positive-default prediction). */\n  executor?: InferenceExecutor;\n  /** Optional transport override (for tests). When omitted, a transport is\n   * constructed from `model` + `cloudOpts`. */\n  transport?: StreamingTurnDetectionTransport;\n}\n\n/**\n * Stream that owns the `turn-detector-v1` → `turn-detector-v1-mini` (cloud →\n * local) fallback FSM. On cloud transport failure (`transport.run()` raises, or\n * `predictEndOfTurn` times out), the stream swaps the transport and rescales\n * per-language thresholds in place on the shared `ThresholdOptions`, then writes\n * the model swap back to the owning detector so its view stays consistent.\n */\nexport class TurnDetectorStreamImpl extends BaseStreamingTurnDetectorStream {\n  protected _model: TurnDetectorModel;\n  protected _cloudOpts: CloudTransportOptions | undefined;\n  protected _executor: InferenceExecutor | undefined;\n  protected _isFallback = false;\n  protected _warnedCloudFailure = false;\n  protected _warnedLocalFailure = false;\n  private _detLogger = log();\n\n  constructor(args: TurnDetectorStreamImplArgs) {\n    const transport =\n      args.transport ??\n      (args.model === 'turn-detector-v1'\n        ? new CloudTransport({\n            detector: args.detector,\n            opts: args.opts,\n            cloudOpts: args.cloudOpts!,\n          })\n        : new LocalTransport({ opts: args.opts, executor: args.executor }));\n    super({ detector: args.detector, opts: args.opts, transport });\n    this._model = args.model;\n    this._cloudOpts = args.cloudOpts;\n    this._executor = args.executor;\n  }\n\n  /** This stream's *current* model name (flips to `'turn-detector-v1-mini'`\n   * after a cloud→local fallback). The swap is also written back to the owning\n   * detector, which shares this stream's mutable `ThresholdOptions`. */\n  override get model(): TurnDetectorModel {\n    return this._model;\n  }\n\n  get isFallback(): boolean {\n    return this._isFallback;\n  }\n\n  /** @internal Test-visible. */\n  get warnedCloudFailure(): boolean {\n    return this._warnedCloudFailure;\n  }\n  /** @internal Test-visible. */\n  get warnedLocalFailure(): boolean {\n    return this._warnedLocalFailure;\n  }\n  /** @internal Test-visible. */\n  get transport(): StreamingTurnDetectionTransport {\n    return this._transport;\n  }\n\n  /** @internal Test-visible: same logic as the path taken when `_run` catches\n   * a cloud transport error. Tests call this directly to verify the warning\n   * dedupe across multiple invocations on the same stream. */\n  _fallBackToLocal(reason: Error): void {\n    if (!this._warnedCloudFailure) {\n      this._detLogger.warn(\n        { reason: reason.message },\n        'cloud turn detector failed; falling back to local mini model',\n      );\n      this._warnedCloudFailure = true;\n    }\n    this._emitDefaultForInflight();\n    try {\n      this._transport.detach();\n    } catch {\n      // ignore detach errors during swap\n    }\n    // Mutate the shared `ThresholdOptions` in place so the rescaled local\n    // thresholds + model swap are visible to the owning detector (read by EOU\n    // metrics and `audio_recognition`) without a copy-back. Safe because only\n    // one active stream per detector is supported, and the swap is sticky.\n    this._opts.thresholds._toLocalFallback();\n    if (this._detector instanceof TurnDetector) {\n      this._detector._setModel('turn-detector-v1-mini');\n    }\n    this._transport = new LocalTransport({ opts: this._opts, executor: this._executor });\n    this._transport.attach(this);\n    this._model = 'turn-detector-v1-mini';\n    this._isFallback = true;\n  }\n\n  /** @internal Test-visible: same logic as the path taken when `_run` sees a\n   * local transport error. */\n  _onLocalFailure(reason: Error): void {\n    if (!this._warnedLocalFailure) {\n      this._detLogger.warn(\n        { reason: reason.message },\n        'local audio turn detector failed; defaulting to 1.0 and retrying on next turn',\n      );\n      this._warnedLocalFailure = true;\n    }\n    this._emitDefaultForInflight();\n  }\n\n  protected _emitDefaultForInflight(): void {\n    // Positive default so any waiter commits after minEndpointingDelay.\n    const requestId = this._requestId;\n    if (requestId !== undefined) {\n      this._resolvePrediction(requestId, 1.0);\n    }\n  }\n\n  override async aclose(): Promise<void> {\n    // Detach the transport first so the cloud send channel closes and its\n    // background sender/recv tasks tear down, then run the base teardown\n    // (which closes the audio channel and cancels the main task).\n    try {\n      this._transport.detach();\n    } catch {\n      // ignore detach errors during teardown\n    }\n    await super.aclose();\n  }\n\n  protected override async _run(): Promise<void> {\n    while (true) {\n      try {\n        await this._raceWithSwap(this._transport.run());\n        return;\n      } catch (err) {\n        if (err instanceof SwapAbortError) {\n          if (this._closing) return;\n          // A swap already happened (e.g. predict timeout → fallback).\n          // The new transport is mounted; loop and run it. Routing the\n          // swap through `SwapAbortError` (rather than through the\n          // cloud/local branch below) is what prevents the \"timeout\n          // flips model mid-await\" misclassification — the catch\n          // exits early before ever consulting `_model`.\n          continue;\n        }\n        const e = err instanceof Error ? err : new Error(String(err));\n        if (this._model === 'turn-detector-v1') {\n          this._fallBackToLocal(e);\n          continue;\n        }\n        this._onLocalFailure(e);\n        return;\n      }\n    }\n  }\n\n  protected override _onPredictTimeout(): void {\n    if (this._model === 'turn-detector-v1') {\n      // Signal the swap BEFORE mutating model/transport state. The\n      // race in `_raceWithSwap` is rejected with `SwapAbortError`\n      // immediately, so the main loop exits through the\n      // SwapAbortError branch and never consults `_model` for a\n      // classification that would race with the assignment below.\n      this._signalSwap();\n      this._fallBackToLocal(new Error('predict_end_of_turn'));\n    }\n  }\n}\n"],"mappings":"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","names":["import_utils"]}