import { BaseStreamingTurnDetector } from "../../inference/eot/base.js";
import { log } from "../../log.js";
import {
} from "../agent_session.js";
import {
  defaultEndpointingOptions,
  streamingEndpointingOptions
} from "./endpointing.js";
import { defaultInterruptionOptions } from "./interruption.js";
import { defaultPreemptiveGenerationOptions } from "./preemptive_generation.js";
import { defaultTurnHandlingOptions } from "./turn_handling.js";
import { defaultUserTurnLimitOptions } from "./user_turn_limit.js";
const defaultSessionOptions = {
  maxToolSteps: 3,
  userAwayTimeout: 15,
  aecWarmupDuration: 3e3,
  ttsReadIdleTimeout: 1e4,
  forwardAudioIdleTimeout: 1e4,
  turnHandling: {},
  useTtsAlignedTranscript: true,
  ttsTextTransforms: ["filter_markdown", "filter_emoji"]
};
const defaultLegacyVoiceOptions = {
  minEndpointingDelay: defaultTurnHandlingOptions.endpointing.minDelay,
  maxEndpointingDelay: defaultTurnHandlingOptions.endpointing.maxDelay,
  maxToolSteps: defaultSessionOptions.maxToolSteps
};
function migrateLegacyOptions(legacyOptions) {
  var _a, _b, _c, _d, _e;
  const logger = log();
  const {
    voiceOptions,
    turnDetection,
    stt,
    vad,
    llm,
    tts,
    userData,
    connOptions,
    ...sessionOptions
  } = legacyOptions;
  if (voiceOptions !== void 0) {
    logger.warn(
      "voiceOptions is deprecated, use top-level SessionOptions fields on AgentSessionOptions instead"
    );
  }
  const turnHandling = {
    interruption: {
      discardAudioIfUninterruptible: voiceOptions == null ? void 0 : voiceOptions.discardAudioIfUninterruptible,
      minDuration: voiceOptions == null ? void 0 : voiceOptions.minInterruptionDuration,
      minWords: voiceOptions == null ? void 0 : voiceOptions.minInterruptionWords,
      ...(_a = sessionOptions.turnHandling) == null ? void 0 : _a.interruption
    },
    endpointing: {
      minDelay: voiceOptions == null ? void 0 : voiceOptions.minEndpointingDelay,
      maxDelay: voiceOptions == null ? void 0 : voiceOptions.maxEndpointingDelay,
      ...(_b = sessionOptions.turnHandling) == null ? void 0 : _b.endpointing
    },
    preemptiveGeneration: {
      ...(_c = sessionOptions.turnHandling) == null ? void 0 : _c.preemptiveGeneration
    },
    userTurnLimit: {
      ...(_d = sessionOptions.turnHandling) == null ? void 0 : _d.userTurnLimit
    },
    // Preserve an explicit `null` (opt-out) distinctly from `undefined` (not
    // given). `??` would collapse both, so only fall back to the deprecated
    // top-level `turnDetection` when `turnHandling.turnDetection` is absent.
    turnDetection: ((_e = sessionOptions == null ? void 0 : sessionOptions.turnHandling) == null ? void 0 : _e.turnDetection) !== void 0 ? sessionOptions.turnHandling.turnDetection : turnDetection
  };
  if ((voiceOptions == null ? void 0 : voiceOptions.allowInterruptions) === false && turnHandling.interruption.enabled === void 0) {
    turnHandling.interruption.enabled = false;
  }
  const migratedVoiceOptions = {};
  if ((voiceOptions == null ? void 0 : voiceOptions.maxToolSteps) !== void 0) {
    migratedVoiceOptions.maxToolSteps = voiceOptions.maxToolSteps;
  }
  if ((voiceOptions == null ? void 0 : voiceOptions.userAwayTimeout) !== void 0) {
    migratedVoiceOptions.userAwayTimeout = voiceOptions.userAwayTimeout;
  }
  const deprecatedPreemptiveGen = legacyOptions.preemptiveGeneration ?? (voiceOptions == null ? void 0 : voiceOptions.preemptiveGeneration);
  if (deprecatedPreemptiveGen !== void 0) {
    logger.warn(
      "preemptiveGeneration as a top-level option is deprecated, use turnHandling.preemptiveGeneration instead"
    );
    if (turnHandling.preemptiveGeneration.enabled === void 0) {
      turnHandling.preemptiveGeneration = {
        ...turnHandling.preemptiveGeneration,
        enabled: deprecatedPreemptiveGen
      };
    }
  }
  const legacyVoiceOptions = { ...defaultLegacyVoiceOptions, ...voiceOptions };
  const agentSessionOptions = {
    stt,
    vad,
    llm,
    tts,
    userData,
    connOptions,
    ...defaultSessionOptions,
    ...migratedVoiceOptions,
    ...sessionOptions,
    turnHandling: mergeWithDefaults(turnHandling),
    // repopulate the deprecated voice options with migrated options for backwards compatibility
    voiceOptions: legacyVoiceOptions
  };
  return { agentSessionOptions, legacyVoiceOptions };
}
function stripUndefined(obj) {
  return Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== void 0));
}
function resolveEndpointing(overrides, turnDetection) {
  const base = turnDetection instanceof BaseStreamingTurnDetector ? streamingEndpointingOptions : defaultEndpointingOptions;
  return { ...base, ...stripUndefined(overrides) };
}
function mergeWithDefaults(config) {
  const endpointingOverrides = stripUndefined(config.endpointing);
  return {
    // Keep an explicit `null` (opt-out) — only an absent value falls back to
    // the default, so the constructor can tell opt-out from not-given.
    turnDetection: config.turnDetection === void 0 ? defaultTurnHandlingOptions.turnDetection : config.turnDetection,
    // Resolve endpointing defaults against the effective detector: an omitted
    // `turnDetection` auto-provisions the streaming TurnDetector (→ tighter
    // streaming defaults), while `null` opt-out or a non-streaming mode keeps
    // the legacy defaults. Activities re-resolve per-detector from `endpointingOverrides`.
    endpointing: {
      ...config.turnDetection === void 0 || config.turnDetection instanceof BaseStreamingTurnDetector ? streamingEndpointingOptions : defaultEndpointingOptions,
      ...endpointingOverrides
    },
    endpointingOverrides,
    interruption: { ...defaultInterruptionOptions, ...stripUndefined(config.interruption) },
    preemptiveGeneration: {
      ...defaultPreemptiveGenerationOptions,
      ...stripUndefined(config.preemptiveGeneration ?? {})
    },
    userTurnLimit: {
      ...defaultUserTurnLimitOptions,
      ...stripUndefined(config.userTurnLimit ?? {})
    }
  };
}
function migrateTurnHandling(opts) {
  if (opts.turnHandling !== void 0) {
    return opts.turnHandling;
  }
  const migrated = {};
  const endpointing = {};
  if (opts.minEndpointingDelay !== void 0) {
    endpointing.minDelay = opts.minEndpointingDelay;
  }
  if (opts.maxEndpointingDelay !== void 0) {
    endpointing.maxDelay = opts.maxEndpointingDelay;
  }
  if (Object.keys(endpointing).length > 0) {
    migrated.endpointing = endpointing;
  }
  const interruption = {};
  if (opts.allowInterruptions === false) {
    interruption.enabled = false;
  }
  if (Object.keys(interruption).length > 0) {
    migrated.interruption = interruption;
  }
  if (opts.turnDetection !== void 0) {
    migrated.turnDetection = opts.turnDetection;
  }
  if (opts.preemptiveGeneration !== void 0) {
    migrated.preemptiveGeneration = { enabled: opts.preemptiveGeneration };
  }
  return {
    ...migrated.endpointing ? { endpointing: migrated.endpointing } : {},
    ...migrated.interruption ? { interruption: migrated.interruption } : {},
    ...migrated.turnDetection !== void 0 ? { turnDetection: migrated.turnDetection } : {},
    ...migrated.preemptiveGeneration ? { preemptiveGeneration: migrated.preemptiveGeneration } : {}
  };
}
export {
  mergeWithDefaults,
  migrateLegacyOptions,
  migrateTurnHandling,
  resolveEndpointing,
  stripUndefined
};
//# sourceMappingURL=utils.js.map