{"version":3,"sources":["../../src/voice/agent_session.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { type JsonObject, Struct } from '@bufbuild/protobuf';\nimport { Mutex } from '@livekit/mutex';\nimport { AgentSession as pb } from '@livekit/protocol';\nimport {\n  type AudioFrame,\n  ParticipantKind,\n  type RemoteParticipant,\n  type Room,\n} from '@livekit/rtc-node';\nimport { type Throws, ThrowsPromise } from '@livekit/throws-transformer/throws';\nimport type { TypedEventEmitter as TypedEmitter } from '@livekit/typed-emitter';\nimport type { Context, Span } from '@opentelemetry/api';\nimport { context as otelContext, trace } from '@opentelemetry/api';\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport { EventEmitter } from 'node:events';\nimport type { ReadableStream } from 'node:stream/web';\nimport type { z } from 'zod';\nimport type { BaseStreamingTurnDetector } from '../inference/eot/base.js';\nimport {\n  LLM as InferenceLLM,\n  STT as InferenceSTT,\n  TTS as InferenceTTS,\n  TurnDetector as InferenceTurnDetector,\n  VAD as InferenceVAD,\n  type LLMModels,\n  type STTModelString,\n  type TTSModelString,\n} from '../inference/index.js';\nimport type { OverlappingSpeechEvent } from '../inference/interruption/types.js';\nimport { getJobContext } from '../job.js';\nimport type { FunctionCall, FunctionCallOutput } from '../llm/chat_context.js';\nimport {\n  AgentHandoffItem,\n  ChatContext,\n  ChatMessage,\n  type Instructions,\n  concatInstructions,\n} from '../llm/chat_context.js';\nimport type {\n  LLM,\n  RealtimeModel,\n  RealtimeModelError,\n  ToolChoice,\n  ToolContextEntry,\n  ToolContextLike,\n} from '../llm/index.js';\nimport {\n  DuplexModel,\n  DuplexRealtimeAdapter,\n  ToolContext,\n  ToolError,\n  toToolContext,\n} from '../llm/index.js';\nimport { LLM as BaseLLM } from '../llm/llm.js';\nimport type { LLMError } from '../llm/llm.js';\nimport { log } from '../log.js';\nimport { type ModelUsage, ModelUsageCollector, filterZeroValues } from '../metrics/model_usage.js';\nimport { SimulationMode } from '../simulation.js';\nimport type { STT } from '../stt/index.js';\nimport type { STTError } from '../stt/stt.js';\nimport { genAI, traceTypes, tracer } from '../telemetry/index.js';\nimport {\n  DEFAULT_SPEECH_STEERING_OPTIONS,\n  type SpeechSteeringOptions,\n  steeringInstructions,\n} from '../tts/provider_format.js';\nimport type { TTS, TTSError } from '../tts/tts.js';\nimport {\n  DEFAULT_API_CONNECT_OPTIONS,\n  DEFAULT_SESSION_CONNECT_OPTIONS,\n  type ResolvedSessionConnectOptions,\n  type SessionConnectOptions,\n  recordingEnabled,\n} from '../types.js';\nimport { Event, Task, asError } from '../utils.js';\nimport type { VAD } from '../vad.js';\nimport { type Agent, AgentTask } from './agent.js';\nimport {\n  AgentActivity,\n  type ReusableResources,\n  cleanupReusableResources,\n  isSchedulingPausedError,\n} from './agent_activity.js';\nimport type { AMD, AMDPredictionEvent } from './amd.js';\nimport type { _TurnDetector } from './audio_recognition.js';\nimport { AgentsConsole } from './console_io.js';\nimport {\n  type AgentEvent,\n  type AgentFalseInterruptionEvent,\n  AgentSessionEventTypes,\n  type AgentState,\n  type AgentStateChangedEvent,\n  type CloseEvent,\n  CloseReason,\n  type ConversationItemAddedEvent,\n  type EotPredictionEvent,\n  type ErrorEvent,\n  type FunctionToolsExecutedEvent,\n  type MetricsCollectedEvent,\n  type SessionUsageUpdatedEvent,\n  type ShutdownReason,\n  type SpeechCreatedEvent,\n  type UserInputTranscribedEvent,\n  type UserState,\n  type UserStateChangedEvent,\n  type UserTranscriptionTimeoutEvent,\n  createAgentStateChangedEvent,\n  createCloseEvent,\n  createConversationItemAddedEvent,\n  createUserStateChangedEvent,\n} from './events.js';\nimport { AgentInput, AgentOutput } from './io.js';\nimport {\n  KeytermDetector,\n  type KeytermsOptions,\n  resolveKeytermsOptions,\n} from './keyterm_detection.js';\nimport { RecorderIO } from './recorder_io/index.js';\nimport { RoomSessionTransport, SessionHost } from './remote_session.js';\nimport { RoomIO, type RoomInputOptions, type RoomOutputOptions } from './room_io/index.js';\nimport type { UnknownUserData } from './run_context.js';\nimport type { SpeechHandle } from './speech_handle.js';\nimport { type RunOutputOptions, RunResult } from './testing/run_result.js';\nimport {\n  type AsyncToolOptions,\n  type ToolHandlingOptions,\n  resolveAsyncToolOptions,\n} from './tool_executor.js';\nimport type { TextTransform } from './transcription/text_transforms.js';\nimport type { EndpointingOptions } from './turn_config/endpointing.js';\nimport type { InterruptionOptions } from './turn_config/interruption.js';\nimport type {\n  InternalTurnHandlingOptions,\n  TurnHandlingOptions,\n} from './turn_config/turn_handling.js';\nimport { migrateLegacyOptions, stripUndefined } from './turn_config/utils.js';\nimport { setParticipantSpanAttributes } from './utils.js';\n\nconst SIP_RULE_ID_ATTR = 'sip.ruleID';\nconst DEFAULT_AEC_WARMUP_DURATION = 3000;\nconst LOOP_STALL_EVENT = 'event_loop_blocked';\n\nexport interface AgentSessionUsage {\n  /** List of usage summaries, one per model/provider combination. */\n  modelUsage: Array<Partial<ModelUsage>>;\n}\n\n/**\n * Granular control over which recording features are active.\n *\n * Recording keys default to `true` when omitted, so `{ logs: false }` means \"record\n * everything except logs\". Redaction defaults to the project setting; `false` is ignored when\n * redaction is enabled globally for the project. Pass to {@link AgentSession.start} as `record`:\n *\n * - `record: true` — all on (backward compatible)\n * - `record: false` — all off (backward compatible)\n * - `record: { audio: true, traces: false }` — granular\n * - `record: { redaction: true }` — enable redaction for the session\n */\nexport interface RecordingOptions {\n  /** Record session audio. Defaults to `true`. */\n  audio?: boolean;\n  /** Export OpenTelemetry trace spans. Defaults to `true`. */\n  traces?: boolean;\n  /** Export OpenTelemetry logs. Defaults to `true`. */\n  logs?: boolean;\n  /** Upload the conversation transcript (chat history). Defaults to `true`. */\n  transcript?: boolean;\n  /** Enable redaction. `false` does not disable project redaction. */\n  redaction?: boolean;\n}\n\n/** @internal Recording options with every category resolved to a boolean. */\nexport type ResolvedRecordingOptions = Required<RecordingOptions>;\n\nconst RECORDING_ALL_ON: ResolvedRecordingOptions = {\n  audio: true,\n  traces: true,\n  logs: true,\n  transcript: true,\n  redaction: false,\n};\n\nconst RECORDING_ALL_OFF: ResolvedRecordingOptions = {\n  audio: false,\n  traces: false,\n  logs: false,\n  transcript: false,\n  redaction: false,\n};\n\nconst idleHoldStorage = new AsyncLocalStorage<boolean>();\n\n/**\n * Resolve a `record` argument into explicit per-category flags. A boolean turns\n * every category on or off; a partial object is merged onto all-on so omitted\n * keys default to `true`.\n *\n * @internal\n */\nexport function resolveRecordingOptions(\n  record: boolean | RecordingOptions,\n): ResolvedRecordingOptions {\n  if (typeof record === 'boolean') {\n    return { ...(record ? RECORDING_ALL_ON : RECORDING_ALL_OFF) };\n  }\n  return { ...RECORDING_ALL_ON, ...record };\n}\n\nexport interface InternalSessionOptions<UserData> extends AgentSessionOptions<UserData> {\n  turnHandling: InternalTurnHandlingOptions;\n  useTtsAlignedTranscript: boolean;\n  maxToolSteps: number;\n  userAwayTimeout: number | null;\n  transcriptionTimeout: number | null;\n  ttsReadIdleTimeout: number;\n  forwardAudioIdleTimeout: number;\n  ttsTextTransforms: readonly TextTransform[] | null;\n  /** Resolved per-category recording options for this session. */\n  recordingOptions: ResolvedRecordingOptions;\n}\n\nexport const defaultAgentSessionOptions = {\n  maxToolSteps: 3,\n  userAwayTimeout: 15.0,\n  transcriptionTimeout: null,\n  aecWarmupDuration: 3000,\n  ttsReadIdleTimeout: 10_000,\n  forwardAudioIdleTimeout: 10_000,\n  turnHandling: {},\n  useTtsAlignedTranscript: true,\n  ttsTextTransforms: ['filter_markdown', 'filter_emoji'],\n  expressive: false,\n} as const satisfies AgentSessionOptions;\n\n/** @deprecated {@link VoiceOptions} has been flattened onto to {@link AgentSessionOptions} */\nexport type VoiceOptions = {\n  maxToolSteps: number;\n  /** @deprecated Use {@link AgentSessionOptions.turnHandling}.preemptiveGeneration instead. */\n  preemptiveGeneration?: boolean;\n  userAwayTimeout?: number | null;\n  /** @deprecated Use {@link AgentSessionOptions.turnHandling}.interruption.mode instead. */\n  allowInterruptions?: boolean;\n  /** @deprecated Use {@link AgentSessionOptions.turnHandling}.interruption.discardAudioIfUninterruptible instead. */\n  discardAudioIfUninterruptible?: boolean;\n  /** @deprecated Use {@link AgentSessionOptions.turnHandling}.interruption.minDuration instead. */\n  minInterruptionDuration?: number;\n  /** @deprecated Use {@link AgentSessionOptions.turnHandling}.interruption.minWords instead. */\n  minInterruptionWords?: number;\n  /** @deprecated Use {@link AgentSessionOptions.turnHandling}.endpointing.minDelay instead. */\n  minEndpointingDelay?: number;\n  /** @deprecated Use {@link AgentSessionOptions.turnHandling}.endpointing.maxDelay instead. */\n  maxEndpointingDelay?: number;\n};\n\nexport type TurnDetectionMode =\n  | 'stt'\n  | 'vad'\n  | 'realtime_llm'\n  | 'manual'\n  | _TurnDetector\n  | BaseStreamingTurnDetector;\n\nexport type AgentSessionCallbacks = {\n  [AgentSessionEventTypes.UserInputTranscribed]: (ev: UserInputTranscribedEvent) => void;\n  [AgentSessionEventTypes.UserTranscriptionTimeout]: (ev: UserTranscriptionTimeoutEvent) => void;\n  [AgentSessionEventTypes.AgentStateChanged]: (ev: AgentStateChangedEvent) => void;\n  [AgentSessionEventTypes.UserStateChanged]: (ev: UserStateChangedEvent) => void;\n  [AgentSessionEventTypes.ConversationItemAdded]: (ev: ConversationItemAddedEvent) => void;\n  [AgentSessionEventTypes.FunctionToolsExecuted]: (ev: FunctionToolsExecutedEvent) => void;\n  [AgentSessionEventTypes.MetricsCollected]: (ev: MetricsCollectedEvent) => void;\n  [AgentSessionEventTypes.SessionUsageUpdated]: (ev: SessionUsageUpdatedEvent) => void;\n  [AgentSessionEventTypes.DebugMessage]: (ev: pb.DebugMessage) => void;\n  [AgentSessionEventTypes.SpeechCreated]: (ev: SpeechCreatedEvent) => void;\n  [AgentSessionEventTypes.AgentFalseInterruption]: (ev: AgentFalseInterruptionEvent) => void;\n  [AgentSessionEventTypes.Error]: (ev: ErrorEvent) => void;\n  [AgentSessionEventTypes.Close]: (ev: CloseEvent) => void;\n  [AgentSessionEventTypes.OverlappingSpeech]: (ev: OverlappingSpeechEvent) => void;\n  [AgentSessionEventTypes.EotPrediction]: (ev: EotPredictionEvent) => void;\n};\n\nexport type AgentSessionOptions<UserData = UnknownUserData> = {\n  stt?: STT | STTModelString;\n  /**\n   * Voice Activity Detection. When omitted, `AgentSession` auto-provisions a\n   * bundled `inference.VAD({ model: 'silero' })` and marks it as the default\n   * (so sites that check whether the user supplied a VAD treat the bundled\n   * one as absent). Pass `null` to opt out entirely.\n   */\n  vad?: VAD | null;\n  llm?: LLM | RealtimeModel | DuplexModel | LLMModels;\n  tts?: TTS | TTSModelString;\n  userData?: UserData;\n  connOptions?: SessionConnectOptions;\n  tools?: ToolContextLike<UserData>;\n  toolHandling?: ToolHandlingOptions;\n\n  /** @deprecated use turnHandling.turnDetection instead */\n  turnDetection?: TurnDetectionMode;\n  /** @deprecated use top-level SessionOptions fields instead */\n  voiceOptions?: Partial<VoiceOptions>;\n\n  maxToolSteps?: number;\n  /**\n   * @deprecated Use `turnHandling.preemptiveGeneration` instead.\n   * When set, migrated into `turnHandling.preemptiveGeneration.enabled`.\n   */\n  preemptiveGeneration?: boolean;\n\n  /**\n   * If set, set the user state as \"away\" after this amount of time after user and agent are\n   * silent. Set to `null` to disable.\n   * @defaultValue 15.0\n   */\n  userAwayTimeout?: number | null;\n\n  /**\n   * Emit `user_transcription_timeout` when VAD detects user speech during the user's turn but no\n   * non-empty final transcript arrives within this many milliseconds after the speech ends. This\n   * can happen because STT failed or because audio was intentionally withheld from STT, such as\n   * during AEC warmup or uninterruptible agent speech. A non-empty final transcript satisfies the\n   * timeout for the current turn even if adaptive interruption detection later discards it as a\n   * backchannel. Requires both VAD and STT. Set to `null` to disable.\n   * @defaultValue null\n   */\n  transcriptionTimeout?: number | null;\n\n  /**\n   * Duration in milliseconds for AEC (Acoustic Echo Cancellation) warmup, during which\n   * interruptions from audio activity are suppressed. Set to `null` to disable.\n   * Defaults to 3000, or `null` for outbound SIP calls.\n   */\n  aecWarmupDuration?: number | null;\n\n  /**\n   * Maximum time in milliseconds to wait for the next frame on the TTS audio stream\n   * inside `performTTSInference`. Applies to every read, including the first.\n   * If exceeded, the TTS stream is forcibly closed and a stall warning is logged.\n   * @defaultValue 10000\n   */\n  ttsReadIdleTimeout?: number;\n\n  /**\n   * Maximum time in milliseconds to wait for the next frame while forwarding TTS\n   * audio to the audio output inside `performAudioForwarding`. Applies to every read,\n   * including the first. If exceeded, forwarding is forcibly closed and a stall\n   * warning is logged.\n   * @defaultValue 10000\n   */\n  forwardAudioIdleTimeout?: number;\n\n  /**\n   * Configuration for turn handling.\n   */\n  turnHandling?: Partial<TurnHandlingOptions>;\n\n  /**\n   * Keyterm biasing for the STT. Holds static `keyterms` plus `keytermDetection`\n   * (LLM extraction). Applies to STTs that accept a term list; on others it warns\n   * and is ignored.\n   */\n  keytermsOptions?: KeytermsOptions;\n\n  useTtsAlignedTranscript?: boolean;\n\n  /**\n   * Transforms to apply to TTS input text. Built-in transforms are `filter_markdown`\n   * and `filter_emoji`; pass `null` to disable text transforms.\n   */\n  ttsTextTransforms?: readonly TextTransform[] | null;\n\n  /**\n   * Let the LLM steer how the agent sounds.\n   *\n   * When enabled, the provider's markup guide is injected into the LLM prompt so it can\n   * emit inline delivery tags (emotion, pacing, non-verbal sounds), which are rendered by\n   * the TTS and stripped from the transcript. Pass an {@link ExpressiveOptions} object to\n   * steer or override the injected instructions. Requires an\n   * {@link inference.TTS | inference TTS} with a model that declares a markup dialect; it\n   * stays off otherwise.\n   *\n   * @defaultValue false\n   */\n  expressive?: boolean | ExpressiveOptions;\n};\n\n/**\n * Configuration for the expressive pipeline, passed as `AgentSession({ expressive: ... })`.\n *\n * Controls how TTS markup instructions are injected into the LLM when expressive is\n * enabled. All keys are optional; common shapes:\n *\n * - `{ speechSteering: {...} }` — steer delivery and non-verbal sounds on top of the\n *   provider-agnostic default instructions.\n * - `{ ttsInstructionsTemplate: '...' }` — a fully custom prompt.\n * - `{ ttsInstructionsAppend: '...' }` — your own rules appended to the template.\n *\n * Any explicit template overrides the default; unset parts fall back to the\n * provider-agnostic default.\n */\nexport interface ExpressiveOptions {\n  speechSteering?: SpeechSteeringOptions;\n  ttsInstructionsTemplate?: Instructions | string;\n  ttsInstructionsAppend?: string;\n}\n\n/** The placeholder the expressive template substitutes the provider's markup guide into. */\nexport const TTS_INSTRUCTIONS_PLACEHOLDER = '{tts.markup.llm_instructions}';\n\nexport const DEFAULT_EXPRESSIVE_OPTIONS: ExpressiveOptions = {\n  ttsInstructionsTemplate:\n    'You can control how you speak using the following formatting tags. ' +\n    'Use them when appropriate to make your speech more expressive and natural:\\n\\n' +\n    TTS_INSTRUCTIONS_PLACEHOLDER,\n  speechSteering: DEFAULT_SPEECH_STEERING_OPTIONS,\n};\n\nfunction appendInstructions(template: Instructions | string, extra: string): Instructions | string {\n  // concatenate the *raw* template text so any {placeholders} survive until render\n  return concatInstructions(template, '\\n\\n' + extra);\n}\n\n/**\n * Resolve a user {@link ExpressiveOptions} to a concrete options object for a provider.\n *\n * Starts from `defaults`, renders `speechSteering` into per-provider delivery guidelines\n * appended to the template, then applies any explicit `ttsInstructionsTemplate` override\n * and `ttsInstructionsAppend` (last, so the user's free-form rules always win). Steering\n * fields the user doesn't set fall back to `defaults`' `speechSteering`, so an explicit\n * value always wins over a default. The returned object always has\n * `ttsInstructionsTemplate` and `speechSteering` (never `ttsInstructionsAppend`);\n * `speechSteering` passes through so injection can filter the advertised markup vocabulary\n * (`TTSMarkup.llmInstructions`) with it.\n */\nexport function resolveExpressiveOptions(\n  expr: ExpressiveOptions,\n  options: { providerKey: string; defaults: ExpressiveOptions },\n): ExpressiveOptions {\n  const { providerKey, defaults } = options;\n  let ttsTemplate = expr.ttsInstructionsTemplate ?? defaults.ttsInstructionsTemplate!;\n\n  const steering: SpeechSteeringOptions = {\n    ...(defaults.speechSteering ?? {}),\n    ...(expr.speechSteering ?? {}),\n  };\n  const fragment = steeringInstructions(providerKey, steering);\n  if (fragment) {\n    ttsTemplate = appendInstructions(ttsTemplate, fragment);\n  }\n\n  if (expr.ttsInstructionsAppend) {\n    ttsTemplate = appendInstructions(ttsTemplate, expr.ttsInstructionsAppend);\n  }\n\n  return { ttsInstructionsTemplate: ttsTemplate, speechSteering: steering };\n}\n\nexport type AgentSessionUpdateOptions = {\n  /** Change expressive TTS delivery for subsequent replies. */\n  expressive?: boolean | ExpressiveOptions;\n  /** Configuration updates for turn handling. */\n  turnHandling?: {\n    /**\n     * Strategy for deciding when the user has finished speaking.\n     *\n     * - `undefined`: leave the current turn detection setting unchanged.\n     * - `null`: clear the current turn detection setting and return to automatic selection.\n     * - `TurnDetectionMode`: set the turn detection strategy to the provided value.\n     */\n    turnDetection?: TurnDetectionMode | null;\n    /** Endpointing options to merge into the current session defaults. */\n    endpointing?: Partial<EndpointingOptions>;\n  };\n  /**\n   * @deprecated use turnHandling.turnDetection instead.\n   *\n   * - `undefined`: leave the current turn detection setting unchanged.\n   * - `null`: clear the current turn detection setting and return to automatic selection.\n   * - `TurnDetectionMode`: set the turn detection strategy to the provided value.\n   */\n  turnDetection?: TurnDetectionMode | null;\n\n  /**\n   * Replace the user-defined keyterms applied to the STT. Auto-detected keyterms\n   * are left untouched.\n   */\n  keyterms?: string[];\n};\n\ntype ActivityTransitionOptions = {\n  previousActivity?: 'close' | 'pause';\n  newActivity?: 'start' | 'resume';\n  blockedTasks?: Task<any>[];\n  waitOnEnter?: boolean;\n};\n\n/** True when the surrounding job runs under a text simulation (the simulated\n * user interacts over text streams only). */\nfunction resolveTextOnly(): boolean {\n  const jobCtx = getJobContext(false);\n  const simCtx = jobCtx?.simulationContext();\n  return simCtx !== undefined && simCtx.simulationMode === SimulationMode.TEXT;\n}\n\nexport class AgentSession<\n  UserData = UnknownUserData,\n> extends (EventEmitter as new () => TypedEmitter<AgentSessionCallbacks>) {\n  vad?: VAD;\n  stt?: STT;\n  llm?: LLM | RealtimeModel;\n  tts?: TTS;\n  turnDetection?: TurnDetectionMode;\n\n  /** @deprecated use {@link sessionOptions } instead */\n  readonly options: VoiceOptions;\n\n  readonly sessionOptions: InternalSessionOptions<UserData>;\n\n  private readonly activityLock = new Mutex();\n\n  private agent?: Agent;\n  private activity?: AgentActivity;\n  private nextActivity?: AgentActivity;\n  private updateActivityTask?: Task<void>;\n  private started = false;\n  private sessionHost?: SessionHost;\n\n  private _chatCtx: ChatContext;\n  private _userData: UserData | undefined;\n  private _toolCtx: ToolContext<UserData>;\n  private _userState: UserState = 'listening';\n  private _agentState: AgentState = 'initializing';\n\n  private _input: AgentInput;\n  private _output: AgentOutput;\n\n  private closing = false;\n  private closingController = new AbortController();\n  private closingTask: Promise<void> | null = null;\n  private userAwayTimer: NodeJS.Timeout | null = null;\n  private idleHolds = 0;\n  private idleReleased = new Event();\n\n  private _aecWarmupTimer: NodeJS.Timeout | null = null;\n  private readonly _aecWarmupDurationExplicit: boolean;\n\n  /**\n   * The session's expressive setting, as the user passed it.\n   * @internal\n   */\n  _expressive: boolean | ExpressiveOptions = false;\n\n  /**\n   * Whether the markup guide has been injected at least once this session.\n   *\n   * Latches on: it is what licenses the history scrub on a later expressive-off turn\n   * (a handoff to a TTS without a markup dialect builds a fresh `AgentActivity`, so the\n   * flag has to outlive it). Sessions that never enabled expressive keep it `false` and\n   * are never scrubbed.\n   *\n   * @internal\n   */\n  _expressiveEverActive = false;\n\n  /**\n   * Whether the \"template has no markup-guide placeholder\" warning has been emitted.\n   *\n   * Session-scoped so a misconfigured template warns once rather than once per turn, and\n   * survives a handoff (which builds a fresh `AgentActivity`).\n   *\n   * @internal\n   */\n  _warnedExpressiveTemplate = false;\n\n  // Connection options for STT, LLM, and TTS\n  private _connOptions: ResolvedSessionConnectOptions;\n\n  // Unrecoverable error counts, reset after agent speaking\n  private llmErrorCounts = 0;\n  private ttsErrorCounts = 0;\n\n  private sessionSpan?: Span;\n  private agentSpeakingSpan?: Span;\n  private loopStallCount = 0;\n  private loopStallTotal = 0;\n  private loopStallMax = 0;\n\n  private _interruptionDetection?: InterruptionOptions['mode'];\n\n  /**\n   * True iff this session auto-provisioned the bundled silero VAD because the\n   * caller passed no `vad=`. Set once in the constructor; immutable from then\n   * on. Read it via `AgentActivity.usingDefaultVad` from voice-pipeline code.\n   *\n   * @internal\n   */\n  _usingDefaultVad: boolean = false;\n\n  /** @internal True when the current job is a text simulation. */\n  get _textOnly(): boolean {\n    return resolveTextOnly();\n  }\n\n  /** @internal */\n  _usageCollector: ModelUsageCollector = new ModelUsageCollector();\n\n  /** @internal */\n  readonly _keytermDetector: KeytermDetector;\n\n  /** @internal */\n  _roomIO?: RoomIO;\n\n  /**\n   * Currently active AMD instance, if one was constructed against this session.\n   * Mirrors python `AgentSession._amd`. Useful for tests, telemetry, and\n   * higher-level helpers that need to introspect classification state.\n   */\n  private _amd: AMD | null = null;\n\n  /** @internal */\n  _aecWarmupRemaining = 0;\n\n  /** @internal */\n  _recorderIO?: RecorderIO;\n\n  /** @internal */\n  rootSpanContext?: Context;\n\n  /** @internal */\n  _recordedEvents: AgentEvent[] = [];\n\n  /** @internal */\n  _asyncToolOptions: AsyncToolOptions = resolveAsyncToolOptions();\n\n  /** @internal */\n  _sessionToolsetsSetup = false;\n\n  /** @internal True when any recording category is enabled. */\n  get _enableRecording(): boolean {\n    return recordingEnabled(this.sessionOptions.recordingOptions);\n  }\n\n  /** @internal True when project or session redaction is enabled. */\n  _redactionEnabled = false;\n\n  /** @internal Whether the realtime audio-redaction warning was emitted for this session. */\n  _warnedRealtimeAudioRedaction = false;\n\n  /** @internal - Timestamp when the session started (milliseconds) */\n  _startedAt?: number;\n\n  /** @internal - Whether `start()` has been called and completed. */\n  get _started(): boolean {\n    return this.started;\n  }\n\n  /** @internal - Whether the session is closing/draining. */\n  get _closing(): boolean {\n    return this.closing;\n  }\n\n  /**\n   * Aborted when shutdown starts, before the activity drains or Agent.onExit() runs.\n   * Use this signal to release work that activity teardown can await.\n   * The Close event fires after activity teardown and cannot release those waits.\n   * The signal stays aborted after close; read it again when starting a new run.\n   * @internal\n   */\n  get _closingSignal(): AbortSignal {\n    return this.closingController.signal;\n  }\n\n  /** @internal - Current run state for testing */\n  _globalRunState?: RunResult;\n\n  /** @internal */\n  _userSpeakingSpan?: Span;\n\n  private logger = log();\n\n  constructor(options: AgentSessionOptions<UserData> = {}) {\n    super();\n\n    this._aecWarmupDurationExplicit = options.aecWarmupDuration !== undefined;\n    const { agentSessionOptions: opts, legacyVoiceOptions } =\n      migrateLegacyOptions<UserData>(options);\n\n    const {\n      vad,\n      stt,\n      llm,\n      tts,\n      userData,\n      connOptions,\n      tools,\n      toolHandling,\n      expressive,\n      ...resolvedSessionOptions\n    } = opts;\n    this._expressive = expressive ?? false;\n    // Merge user-provided connOptions with defaults\n    this._connOptions = {\n      sttConnOptions: { ...DEFAULT_API_CONNECT_OPTIONS, ...connOptions?.sttConnOptions },\n      llmConnOptions: { ...DEFAULT_API_CONNECT_OPTIONS, ...connOptions?.llmConnOptions },\n      ttsConnOptions: { ...DEFAULT_API_CONNECT_OPTIONS, ...connOptions?.ttsConnOptions },\n      maxUnrecoverableErrors:\n        connOptions?.maxUnrecoverableErrors ??\n        DEFAULT_SESSION_CONNECT_OPTIONS.maxUnrecoverableErrors,\n    };\n\n    // VAD: undefined → auto-provision bundled inference.VAD (silero). The\n    // `_usingDefaultVad` marker is the single source of truth for \"this VAD\n    // was framework-provisioned\" — code paths that should ignore a default\n    // VAD read it via `AgentActivity.usingDefaultVad`. null → leave VAD off\n    // entirely. Otherwise use what the caller supplied.\n    this._usingDefaultVad = vad === undefined;\n    if (vad === undefined) {\n      this.vad = new InferenceVAD({ model: 'silero' });\n    } else if (vad === null) {\n      this.vad = undefined;\n    } else {\n      this.vad = vad;\n    }\n\n    if (typeof stt === 'string') {\n      this.stt = InferenceSTT.fromModelString(stt);\n    } else {\n      this.stt = stt;\n    }\n\n    if (typeof llm === 'string') {\n      this.llm = InferenceLLM.fromModelString(llm);\n    } else if (llm instanceof DuplexModel) {\n      this.llm = new DuplexRealtimeAdapter(llm);\n    } else {\n      this.llm = llm;\n    }\n\n    // Eagerly establish DNS/TLS to the LLM provider so the first inference request is faster.\n    if (this.llm instanceof BaseLLM) {\n      this.llm.prewarm();\n    }\n\n    if (typeof tts === 'string') {\n      this.tts = InferenceTTS.fromModelString(tts);\n    } else {\n      this.tts = tts;\n    }\n\n    // Default turn_detection: when the caller didn't pin a mode or supply a\n    // detector instance (`undefined`/not-given), fall back to a fresh\n    // inference.TurnDetector so every session ships with audio EOT\n    // out of the box. An explicit `null` opts out entirely — no detector is\n    // built.\n    const configuredTurnDetection = resolvedSessionOptions.turnHandling.turnDetection;\n    this.turnDetection =\n      configuredTurnDetection === null\n        ? undefined\n        : configuredTurnDetection ?? new InferenceTurnDetector();\n    // The session report serializes `sessionOptions`, so record the effective detector there\n    // (Python keeps the eager default in `AgentSessionOptions.turn_handling` the same way).\n    resolvedSessionOptions.turnHandling.turnDetection =\n      configuredTurnDetection === null ? null : this.turnDetection;\n    this._interruptionDetection = resolvedSessionOptions.turnHandling.interruption?.mode;\n    this._userData = userData;\n    this._toolCtx = toToolContext(tools) ?? ToolContext.empty<UserData>();\n    this._asyncToolOptions = resolveAsyncToolOptions(toolHandling?.asyncOptions);\n\n    // configurable IO\n    this._input = new AgentInput(this.onAudioInputChanged, (enabled) =>\n      this.onAudioEnabledChanged(enabled),\n    );\n    this._output = new AgentOutput(this.onAudioOutputChanged, this.onTextOutputChanged);\n\n    // This is the \"global\" chat context, it holds the entire conversation history\n    this._chatCtx = ChatContext.empty();\n    this.sessionOptions = resolvedSessionOptions;\n\n    const keytermsOptions = resolveKeytermsOptions(this.sessionOptions.keytermsOptions);\n    this._keytermDetector = new KeytermDetector({\n      staticKeyterms: keytermsOptions.keyterms,\n      options: keytermsOptions.keytermDetection,\n    });\n\n    this.options = legacyVoiceOptions;\n    this._aecWarmupRemaining = this.sessionOptions.aecWarmupDuration ?? 0;\n\n    this._onUserInputTranscribed = this._onUserInputTranscribed.bind(this);\n    this.on(AgentSessionEventTypes.UserInputTranscribed, this._onUserInputTranscribed);\n    this.idleReleased.set();\n  }\n\n  emit<K extends keyof AgentSessionCallbacks>(\n    event: K,\n    ...args: Parameters<AgentSessionCallbacks[K]>\n  ): boolean {\n    // Only retain events when recording is actually enabled. Otherwise this\n    // array grows unbounded for the entire (potentially hours-long) session,\n    // pinning every event's graph (SpeechHandle, OTel spans/contexts, streams)\n    // and leaking memory even though the events are never reported. The buffer\n    // is only consumed by makeSessionReport() when recording is enabled.\n    if (this._enableRecording) {\n      const eventData = args[0] as AgentEvent;\n      this._recordedEvents.push(eventData);\n    }\n    return super.emit(event, ...args);\n  }\n\n  get input(): AgentInput {\n    return this._input;\n  }\n\n  get output(): AgentOutput {\n    return this._output;\n  }\n\n  get userData(): UserData {\n    if (this._userData === undefined) {\n      throw new Error('Voice agent userData is not set');\n    }\n\n    return this._userData;\n  }\n\n  get history(): ChatContext {\n    return this._chatCtx;\n  }\n\n  /** The effective keyterms (user-defined + auto-detected) currently applied to the STT. */\n  get keyterms(): string[] {\n    return this._keytermDetector.keyterms;\n  }\n\n  /** Connection options for STT, LLM, and TTS. */\n  get connOptions(): ResolvedSessionConnectOptions {\n    return this._connOptions;\n  }\n\n  get interruptionDetection() {\n    return this._interruptionDetection;\n  }\n\n  /**\n   * Returns usage summaries for this session, one per model/provider combination.\n   */\n  get usage(): AgentSessionUsage {\n    // Skip zero fields for more concise usage display (matches python behavior).\n    return { modelUsage: this._usageCollector.flatten().map(filterZeroValues) };\n  }\n\n  get useTtsAlignedTranscript(): boolean {\n    return this.sessionOptions.useTtsAlignedTranscript;\n  }\n\n  set userData(value: UserData) {\n    this._userData = value;\n  }\n\n  private async _startImpl({\n    agent,\n    room,\n    inputOptions,\n    outputOptions,\n    span,\n  }: {\n    agent: Agent;\n    room?: Room;\n    inputOptions?: Partial<RoomInputOptions>;\n    outputOptions?: Partial<RoomOutputOptions>;\n    span: Span;\n  }): Promise<void> {\n    span.setAttribute(traceTypes.ATTR_AGENT_LABEL, agent.id);\n\n    this.agent = agent;\n    this._updateAgentState('initializing');\n\n    const tasks: Promise<void>[] = [];\n\n    const consoleInst = AgentsConsole.getInstance();\n    if (consoleInst.enabled && !consoleInst.ioAcquired) {\n      if (this.input.audio || this.output.audio) {\n        this.logger.warn(\n          'agent started with the console subcommand, but input.audio/output.audio is already set, overriding...',\n        );\n      }\n\n      consoleInst.acquireIo(this);\n\n      if (consoleInst.transport) {\n        this.sessionHost = new SessionHost(\n          consoleInst.transport,\n          consoleInst.audioInput,\n          consoleInst.audioOutput,\n        );\n        this.sessionHost.registerSession(this);\n      }\n    } else if (room && !this._roomIO) {\n      if (this._textOnly) {\n        // Under a text simulation the simulated user interacts over text\n        // streams only: no audio I/O. STT/TTS/VAD are dropped in the\n        // constructor.\n        this.logger.info('text simulation: disabling STT/TTS/VAD and audio I/O');\n        inputOptions = { ...inputOptions, audioEnabled: false };\n        outputOptions = { ...outputOptions, audioEnabled: false };\n      }\n\n      // Check for existing input/output configuration and warn if needed\n      if (this.input.audio && inputOptions?.audioEnabled !== false) {\n        this.logger.warn(\n          'RoomIO audio input is enabled; preserving and using the existing input.audio',\n        );\n      }\n\n      if (this.output.audio && outputOptions?.audioEnabled !== false) {\n        this.logger.warn(\n          'RoomIO audio output is enabled; preserving and using the existing output.audio',\n        );\n      }\n\n      if (this.output.transcription && outputOptions?.transcriptionEnabled !== false) {\n        this.logger.warn(\n          'RoomIO transcription output is enabled; preserving and using the existing output.transcription',\n        );\n      }\n\n      this._roomIO = new RoomIO({\n        agentSession: this,\n        room,\n        inputOptions,\n        outputOptions,\n      });\n\n      this._roomIO.start();\n\n      const transport = new RoomSessionTransport(room, this._roomIO);\n      this.sessionHost = new SessionHost(transport);\n      this.sessionHost.registerSession(this);\n    }\n\n    const ctx = getJobContext(false);\n\n    if (ctx) {\n      if (room && ctx.room === room && !room.isConnected) {\n        this.logger.debug('Auto-connecting to room via job context');\n        tasks.push(ctx.connect());\n      }\n\n      // `lk console --record` forces audio recording even if the session was\n      // started with `record: false`.\n      const consoleForcesRecord = consoleInst.enabled && consoleInst.record;\n      if (\n        this.input.audio &&\n        this.output.audio &&\n        (this.sessionOptions.recordingOptions.audio || consoleForcesRecord)\n      ) {\n        this._recorderIO = new RecorderIO({ agentSession: this });\n        this.input.audio = this._recorderIO.recordInput(this.input.audio);\n        this.output.audio = this._recorderIO.recordOutput(this.output.audio);\n\n        // Start recording to the session directory. In console mode the disk\n        // write is gated on --record.\n        if (consoleForcesRecord || !consoleInst.enabled) {\n          const sessionDir = ctx.sessionDirectory;\n          if (sessionDir) {\n            tasks.push(this._recorderIO.start(`${sessionDir}/audio.ogg`));\n          }\n        }\n      }\n    }\n\n    // TODO(AJS-265): add shutdown callback to job context\n    // Initial start does not wait on onEnter\n    tasks.push(this._updateActivity(this.agent, { waitOnEnter: false }));\n\n    const startupResults = await ThrowsPromise.allSettled(tasks);\n    for (const result of startupResults) {\n      if (result.status === 'rejected') throw result.reason;\n    }\n\n    if (this.sessionHost) {\n      await this.sessionHost.start();\n    }\n\n    // Log used IO configuration\n    this.logger.debug(\n      `using audio io: ${this.input.audio ? '`' + this.input.audio.constructor.name + '`' : '(none)'} -> \\`AgentSession\\` -> ${this.output.audio ? '`' + this.output.audio.constructor.name + '`' : '(none)'}`,\n    );\n\n    if (\n      this.sessionOptions.turnHandling.interruption.resumeFalseInterruption &&\n      this.output.audio &&\n      !this.output.audio.canPause\n    ) {\n      this.logger.warn(\n        {\n          audioOutput: this.output.audio.constructor.name,\n        },\n        'resumeFalseInterruption is enabled but audio output does not support pause, it will be ignored',\n      );\n    }\n\n    this.logger.debug(\n      `using transcript io: \\`AgentSession\\` -> ${this.output.transcription ? '`' + this.output.transcription.constructor.name + '`' : '(none)'}`,\n    );\n\n    this.started = true;\n    this._startedAt = Date.now();\n    this._updateAgentState('listening');\n  }\n\n  async start({\n    agent,\n    room,\n    inputOptions,\n    outputOptions,\n    record,\n  }: {\n    agent: Agent;\n    room?: Room;\n    inputOptions?: Partial<RoomInputOptions>;\n    outputOptions?: Partial<RoomOutputOptions>;\n    record?: boolean | RecordingOptions;\n  }): Promise<void> {\n    if (this.started) {\n      return;\n    }\n\n    this.closing = false;\n    if (this.closingController.signal.aborted) {\n      this.closingController = new AbortController();\n    }\n    this._usageCollector = new ModelUsageCollector();\n    this.loopStallCount = 0;\n    this.loopStallTotal = 0;\n    this.loopStallMax = 0;\n\n    const ctx = getJobContext(false);\n\n    if (ctx) {\n      const recordIsGiven = record !== undefined;\n      if (record === undefined) {\n        // defer to the server-side setting for recording\n        record = ctx.job.enableRecording;\n      }\n\n      this.sessionOptions.recordingOptions = resolveRecordingOptions(record);\n      if (this._textOnly) {\n        this.sessionOptions.recordingOptions.audio = false;\n      }\n\n      // Only one AgentSession per job can be the primary (and therefore record).\n      // Designate the primary before initRecording so a demoted secondary session\n      // never configures cloud recording. Mirrors Python's start() ordering.\n      if (ctx._primaryAgentSession === undefined || ctx._primaryAgentSession === this) {\n        ctx._primaryAgentSession = this;\n      } else if (recordingEnabled(this.sessionOptions.recordingOptions)) {\n        if (recordIsGiven) {\n          throw new Error(\n            'Only one `AgentSession` can be the primary at a time. If you want to ignore primary designation, use `session.start({ record: false })`.',\n          );\n        }\n        // record was not given: silently disable recording for the secondary session\n        this.sessionOptions.recordingOptions = resolveRecordingOptions(false);\n      }\n\n      if (this._enableRecording) {\n        await ctx.initRecording(this.sessionOptions.recordingOptions);\n      }\n    }\n\n    this._redactionEnabled = Boolean(\n      ctx?.job.enableRedaction || this.sessionOptions.recordingOptions.redaction,\n    );\n\n    this.sessionSpan = tracer.startSpan({\n      name: 'agent_session',\n    });\n    // the session is the convention's workflow: agent turns (`invoke_agent`), inference\n    // (`chat`) and tool spans (`execute_tool`) nest underneath it\n    genAI.setWorkflowAttributes(this.sessionSpan, { name: 'agent_session' });\n\n    this.rootSpanContext = trace.setSpan(otelContext.active(), this.sessionSpan);\n\n    try {\n      await this._startImpl({\n        agent,\n        room,\n        inputOptions,\n        outputOptions,\n        span: this.sessionSpan,\n      });\n    } catch (error) {\n      this._closeSoon({ reason: CloseReason.ERROR });\n      await this.closingTask;\n      throw error;\n    }\n  }\n\n  updateAgent(agent: Agent): void {\n    this.agent = agent;\n\n    if (!this.started) {\n      return;\n    }\n\n    // immediately block the old activity from accepting new user turns\n    // during the transition window (before drain() formally pauses scheduling)\n    this.activity?.blockNewTurns();\n\n    const _updateActivityTask = async (oldTask: Task<void> | undefined, agent: Agent) => {\n      if (oldTask) {\n        try {\n          await oldTask.result;\n        } catch (error) {\n          this.logger.error(error, 'previous updateAgent transition failed');\n        }\n      }\n\n      await this._updateActivity(agent, { waitOnEnter: false });\n\n      // Watch onEnter so run() captures its output without awaiting long-lived\n      // onEnter flows that need a future user turn to complete.\n      const onEnterTask = this.activity?._onEnterTask;\n      const runState = this._globalRunState;\n      if (onEnterTask && runState && !runState.done()) {\n        runState._watchHandle(onEnterTask);\n      }\n    };\n\n    const oldTask = this.updateActivityTask;\n    this.updateActivityTask = Task.from(\n      async () => _updateActivityTask(oldTask, agent),\n      undefined,\n      'AgentSession_updateActivityTask',\n    );\n\n    const runState = this._globalRunState;\n    if (runState) {\n      // Don't mark the RunResult as done, if there is currently an agent transition happening.\n      // (used to make sure we're correctly adding the AgentHandoffResult before completion)\n      runState._watchHandle(this.updateActivityTask);\n    }\n  }\n\n  commitUserTurn() {\n    if (!this.activity) {\n      throw new Error('AgentSession is not running');\n    }\n\n    this.activity.commitUserTurn();\n  }\n\n  clearUserTurn() {\n    if (!this.activity) {\n      throw new Error('AgentSession is not running');\n    }\n    this.activity.clearUserTurn();\n  }\n\n  say(\n    text: string | ReadableStream<string>,\n    options?: {\n      audio?: ReadableStream<AudioFrame>;\n      allowInterruptions?: boolean;\n      addToChatCtx?: boolean;\n    },\n  ): SpeechHandle {\n    if (!this.activity) {\n      throw new Error('AgentSession is not running');\n    }\n\n    const doSay = (activity: AgentActivity, nextActivity?: AgentActivity) => {\n      if (activity.schedulingPaused) {\n        if (!nextActivity) {\n          throw new Error('AgentSession is closing, cannot use say()');\n        }\n        // Keep Python parity: the queued activity creates the refused speech, then its paused\n        // scheduler interrupts the handle so the speech task can settle.\n        return nextActivity.say(text, options);\n      }\n      return activity.say(text, options);\n    };\n\n    const runState = this._globalRunState;\n    let handle: SpeechHandle;\n\n    // attach to the session span if called outside of the AgentSession\n    const activeSpan = trace.getActiveSpan();\n    if (!activeSpan && this.rootSpanContext) {\n      handle = otelContext.with(this.rootSpanContext, () =>\n        doSay(this.activity!, this.nextActivity),\n      );\n    } else {\n      handle = doSay(this.activity, this.nextActivity);\n    }\n\n    if (runState) {\n      runState._watchHandle(handle);\n    }\n\n    return handle;\n  }\n\n  /**\n   * Interrupt the current speech generation.\n   *\n   * A queued speech created with `allowInterruptions: false` keeps playing, along with the ones\n   * behind it, unless `force` is set.\n   *\n   * @returns A future that completes when the interruption is fully processed.\n   * @throws Error if the session is not running, or if the speech currently playing disallows\n   * interruptions and `force` is false.\n   */\n  interrupt(options?: { force?: boolean }) {\n    if (!this.activity) {\n      throw new Error('AgentSession is not running');\n    }\n\n    return this.activity.interrupt(options);\n  }\n\n  /** @internal — emit a debug/trace payload to the debugger/recorder. */\n  _emitDebugMessage(payload: JsonObject): void {\n    const debugMessage = new pb.DebugMessage({ payload: Struct.fromJson(payload) });\n    super.emit(AgentSessionEventTypes.DebugMessage, debugMessage);\n  }\n\n  /**\n   * The currently bound `AMD` instance, or `null` if AMD is not in use.\n   * Mirrors python `AgentSession.amd`.\n   */\n  get amd(): AMD | null {\n    return this._amd;\n  }\n\n  /** @internal — used by AMD to register/unregister itself with the session. */\n  _setAmd(amd: AMD | null): void {\n    this._amd = amd;\n  }\n\n  /**\n   * The currently running activity, or `undefined` when none is active. Mirrors\n   * python `session._activity` — exposed so tightly-coupled internals (e.g. AMD)\n   * can read activity state such as the endpointing delay.\n   * @internal\n   */\n  get _activity(): AgentActivity | undefined {\n    return this.activity;\n  }\n\n  /**\n   * @internal — forwarded to {@link SessionHost} so a connected\n   * {@link RemoteSession} peer receives an `amd_prediction` event when AMD\n   * settles. Mirrors python `AgentSession._session_host._on_amd_prediction`.\n   */\n  _onAmdPrediction(event: AMDPredictionEvent): void {\n    this.sessionHost?._onAmdPrediction(event);\n  }\n\n  /**\n   * @internal — returns a tee'd branch of the active participant audio stream\n   * for AMD's dedicated STT. Returns `undefined` when no `AgentActivity` is\n   * running yet (the AMD STT pump retries until an activity is available).\n   */\n  _subscribeAudioStream(): ReadableStream<AudioFrame> | undefined {\n    return this.activity?.subscribeAudioStream();\n  }\n\n  pauseReplyAuthorization(): void {\n    if (!this.activity) {\n      throw new Error('AgentSession is not running');\n    }\n\n    this.activity.pauseReplyAuthorization();\n  }\n\n  /**\n   * Resume automatic replies after pauseReplyAuthorization().\n   * @throws Error if the session is not running.\n   */\n  resumeReplyAuthorization(): Throws<void, Error> {\n    if (!this.activity) {\n      throw new Error('AgentSession is not running');\n    }\n\n    return this.activity.resumeReplyAuthorization();\n  }\n\n  updateOptions(options: AgentSessionUpdateOptions = {}): void {\n    if (options.expressive !== undefined) {\n      this._expressive = options.expressive;\n    }\n    if (options.keyterms !== undefined) {\n      this._keytermDetector.setStaticKeyterms(options.keyterms);\n    }\n\n    const endpointing = options.turnHandling?.endpointing;\n    const turnDetection =\n      options.turnHandling?.turnDetection !== undefined\n        ? options.turnHandling.turnDetection\n        : options.turnDetection;\n    const hasTurnDetection = turnDetection !== undefined;\n    const normalizedTurnDetection = turnDetection ?? undefined;\n\n    if (endpointing !== undefined) {\n      const stripped = stripUndefined(endpointing);\n      this.sessionOptions.turnHandling.endpointing = {\n        ...this.sessionOptions.turnHandling.endpointing,\n        ...stripped,\n      };\n      // record the explicit keys so a fresh activity (built on agent handoff)\n      // re-resolves with them instead of falling back to defaults.\n      this.sessionOptions.turnHandling.endpointingOverrides = {\n        ...this.sessionOptions.turnHandling.endpointingOverrides,\n        ...stripped,\n      };\n    }\n\n    if (hasTurnDetection) {\n      this.turnDetection = normalizedTurnDetection;\n      this.sessionOptions.turnHandling.turnDetection = normalizedTurnDetection;\n    }\n\n    if (this.activity) {\n      const activityOptions: Parameters<AgentActivity['updateOptions']>[0] = {};\n      if (endpointing !== undefined) {\n        activityOptions.endpointing = this.sessionOptions.turnHandling.endpointing;\n      }\n      if (hasTurnDetection) {\n        activityOptions.turnDetection = turnDetection;\n      }\n      this.activity.updateOptions(activityOptions);\n    }\n  }\n\n  generateReply(options?: {\n    userInput?: string | ChatMessage;\n    chatCtx?: ChatContext;\n    instructions?: string | Instructions;\n    toolChoice?: ToolChoice;\n    allowInterruptions?: boolean;\n    /** The input modality used for generating the reply. Defaults to `\"text\"`. */\n    inputModality?: 'audio' | 'text';\n  }): SpeechHandle {\n    if (!this.activity) {\n      throw new Error('AgentSession is not running');\n    }\n\n    const userMessage =\n      options?.userInput instanceof ChatMessage\n        ? options.userInput\n        : options?.userInput\n          ? new ChatMessage({\n              role: 'user',\n              content: options.userInput,\n            })\n          : undefined;\n\n    const inputDetails = { modality: options?.inputModality ?? 'text' } as const;\n\n    const doGenerateReply = (activity: AgentActivity, nextActivity?: AgentActivity) => {\n      if (activity.schedulingPaused) {\n        if (!nextActivity) {\n          throw new Error('AgentSession is closing, cannot use generateReply()');\n        }\n        return nextActivity.generateReply({ userMessage, ...options, inputDetails });\n      }\n\n      // Handoff can race with scheduling pause between the check above and generateReply().\n      // If that happens, retry on the next activity instead of surfacing an avoidable error.\n      try {\n        return activity.generateReply({ userMessage, ...options, inputDetails });\n      } catch (error) {\n        const canFallback = nextActivity !== undefined && isSchedulingPausedError(error);\n        if (!canFallback) {\n          throw error;\n        }\n        this.logger.debug(\n          { error },\n          'generateReply scheduling raced with handoff drain; retrying on next activity',\n        );\n        return nextActivity.generateReply({ userMessage, ...options, inputDetails });\n      }\n    };\n\n    // attach to the session span if called outside of the AgentSession\n    const activeSpan = trace.getActiveSpan();\n    let handle: SpeechHandle;\n    if (!activeSpan && this.rootSpanContext) {\n      handle = otelContext.with(this.rootSpanContext, () =>\n        doGenerateReply(this.activity!, this.nextActivity),\n      );\n    } else {\n      handle = doGenerateReply(this.activity!, this.nextActivity);\n    }\n\n    if (this._globalRunState) {\n      this._globalRunState._watchHandle(handle);\n    }\n\n    return handle;\n  }\n\n  /**\n   * Run a test with user input and return a result for assertions.\n   *\n   * This method is primarily used for testing agent behavior without\n   * requiring a real room connection.\n   *\n   * @example\n   * ```typescript\n   * const result = await session.run({ userInput: 'Hello' });\n   * result.expect.nextEvent().isMessage({ role: 'assistant' });\n   * result.expect.noMoreEvents();\n   * ```\n   *\n   * @param options - Run options including user input and optional output type.\n   *   When `outputType` is set and the turn ends without structured output, the\n   *   run re-prompts the model up to `outputOptions.maxRetries` times (default 2)\n   *   before rejecting with `UnexpectedModelBehavior`. Pass `outputOptions: null`\n   *   to disable retries entirely.\n   * @returns A RunResult that resolves when the agent finishes responding\n   */\n  run<T = unknown>({\n    userInput,\n    inputModality,\n    outputType,\n    outputOptions,\n  }: {\n    userInput: string;\n    inputModality?: 'audio' | 'text';\n    outputType?: z.ZodType<T>;\n    outputOptions?: RunOutputOptions | null;\n  }): RunResult<T> {\n    if (this._globalRunState && !this._globalRunState.done()) {\n      throw new Error('nested runs are not supported');\n    }\n\n    const runState = new RunResult<T>({\n      userInput,\n      outputType,\n      outputOptions,\n      session: this,\n    });\n\n    this._globalRunState = runState;\n\n    // Defer generateReply through the activityLock to ensure any in-progress\n    // activity transition (e.g. AgentTask started from onEnter) completes first.\n    // TS Task.from starts onEnter synchronously, so the transition may already be\n    // mid-flight by the time run() is called after session.start() resolves.\n    // Acquiring and immediately releasing the lock guarantees FIFO ordering:\n    // the transition's lock section finishes before we route generateReply.\n    (async () => {\n      try {\n        const unlock = await this.activityLock.lock();\n        unlock();\n        this.generateReply({ userInput, inputModality });\n      } catch (e) {\n        runState._reject(asError(e));\n      }\n    })();\n\n    return runState;\n  }\n\n  /** @internal */\n  async _updateActivity(agent: Agent, options: ActivityTransitionOptions = {}): Promise<void> {\n    const { previousActivity = 'close', newActivity = 'start', blockedTasks = [] } = options;\n    const waitOnEnter = options.waitOnEnter ?? newActivity === 'start';\n\n    const runWithContext = async () => {\n      const unlock = await this.activityLock.lock();\n      let onEnterTask: Task<void> | undefined;\n      let reusableResources: ReusableResources | undefined;\n\n      try {\n        if (this.closing && newActivity === 'start') {\n          this.logger.warn({ agentId: agent.id }, 'Session is closing, skipping start of activity');\n          return;\n        }\n\n        this.agent = agent;\n        const prevActivityObj = this.activity;\n\n        if (newActivity === 'start') {\n          const prevAgent = prevActivityObj?.agent;\n          if (\n            agent._agentActivity &&\n            // allow updating the same agent that is running\n            (agent !== prevAgent || previousActivity !== 'close')\n          ) {\n            throw new Error('Cannot start agent: an activity is already running');\n          }\n          this.nextActivity = new AgentActivity(agent, this);\n        } else if (newActivity === 'resume') {\n          if (!agent._agentActivity) {\n            throw new Error('Cannot resume agent: no existing activity to resume');\n          }\n          this.nextActivity = agent._agentActivity;\n        }\n\n        if (prevActivityObj && prevActivityObj !== this.nextActivity) {\n          if (previousActivity === 'pause') {\n            reusableResources = await prevActivityObj.pause({\n              blockedTasks,\n              newActivity: this.nextActivity,\n            });\n          } else {\n            prevActivityObj.blockNewTurns();\n            reusableResources = await prevActivityObj.drain({\n              newActivity: this.nextActivity,\n            });\n            await prevActivityObj.close();\n          }\n        }\n\n        if (this.closing && newActivity === 'start') {\n          this.logger.warn(\n            { agentId: this.nextActivity?.agent.id },\n            'Session is closing, skipping start of next activity',\n          );\n          if (reusableResources) {\n            await cleanupReusableResources(reusableResources, this.logger);\n            reusableResources = undefined;\n          }\n          this.nextActivity = undefined;\n          this.activity = undefined;\n          return;\n        }\n\n        this.activity = this.nextActivity;\n        this.nextActivity = undefined;\n\n        const runState = this._globalRunState;\n        const handoffItem = new AgentHandoffItem({\n          oldAgentId: prevActivityObj?.agent.id,\n          newAgentId: agent.id,\n        });\n\n        if (runState) {\n          runState._agentHandoff({\n            item: handoffItem,\n            oldAgent: prevActivityObj?.agent,\n            newAgent: this.activity!.agent,\n          });\n        }\n\n        this._conversationItemAdded(handoffItem);\n        this.logger.debug(\n          { previousAgentId: prevActivityObj?.agent.id, newAgentId: agent.id },\n          'Agent handoff inserted into chat context',\n        );\n\n        const activity = this.activity!;\n        if (newActivity === 'start') {\n          await activity.start({ reuseResources: reusableResources });\n        } else {\n          await activity.resume({ reuseResources: reusableResources });\n        }\n        reusableResources = undefined;\n\n        onEnterTask = activity._onEnterTask;\n\n        if (this._input.audio) {\n          activity.attachAudioInput(this._input.audio.stream);\n        }\n      } catch (error) {\n        // JS safeguard: session cleanup owns the detached resources until the next activity\n        // starts successfully, preventing leaks when handoff fails mid-transition.\n        if (reusableResources) {\n          await cleanupReusableResources(reusableResources, this.logger);\n        }\n        throw error;\n      } finally {\n        unlock();\n      }\n\n      if (waitOnEnter) {\n        if (!onEnterTask) {\n          throw new Error('expected onEnter task to be available while waitOnEnter=true');\n        }\n        await onEnterTask.result;\n      }\n    };\n\n    // Run within session span context if available\n    if (this.rootSpanContext) {\n      return otelContext.with(this.rootSpanContext, runWithContext);\n    }\n\n    return runWithContext();\n  }\n\n  get chatCtx(): ChatContext {\n    return this._chatCtx.copy();\n  }\n\n  get agentState(): AgentState {\n    return this._agentState;\n  }\n\n  get userState(): UserState {\n    return this._userState;\n  }\n\n  get currentAgent(): Agent {\n    if (!this.agent) {\n      throw new Error('AgentSession is not running');\n    }\n\n    return this.agent;\n  }\n\n  get toolCtx(): ToolContext<UserData> {\n    return this._toolCtx.copy();\n  }\n\n  get tools(): readonly ToolContextEntry<UserData>[] {\n    return this._toolCtx.tools;\n  }\n\n  async waitForIdle(): Promise<AgentActivity> {\n    while (true) {\n      if (this.closingTask) {\n        throw new Error('AgentSession is closing');\n      }\n      const activity = this.activity;\n      if (!activity) {\n        throw new Error('AgentSession has no active AgentActivity');\n      }\n      try {\n        await activity.waitForIdle();\n        return activity;\n      } catch (error) {\n        if (this.activity === activity) {\n          throw error;\n        }\n      }\n    }\n  }\n\n  async waitForIdleAndHold<T>(fn: (activity: AgentActivity) => Promise<T> | T): Promise<T> {\n    const activity = await this.waitForIdle();\n    this.idleHolds += 1;\n    this.idleReleased.clear();\n    try {\n      return await idleHoldStorage.run(true, () => fn(activity));\n    } finally {\n      this.idleHolds -= 1;\n      if (this.idleHolds === 0) {\n        this.idleReleased.set();\n      }\n    }\n  }\n\n  /**\n   * Wait until any foreground idle-hold (`waitForIdleAndHold`) is released.\n   * Returns `true` if it actually waited for a release — callers use that to\n   * re-verify idleness, since work may have resumed during the hold.\n   * @internal\n   */\n  async _waitForIdleHoldReleased(): Promise<boolean> {\n    if (this.idleHolds > 0 && !idleHoldStorage.getStore()) {\n      await this.idleReleased.wait();\n      return true;\n    }\n    return false;\n  }\n\n  async close(): Promise<void> {\n    this._closeSoon({ reason: CloseReason.USER_INITIATED });\n    await this.closingTask;\n  }\n\n  shutdown(options?: { drain?: boolean; reason?: ShutdownReason }): void {\n    const { drain = true, reason = CloseReason.USER_INITIATED } = options ?? {};\n\n    this._closeSoon({\n      reason,\n      drain,\n    });\n  }\n\n  /** @internal */\n  _closeSoon({\n    reason,\n    drain = false,\n    error = null,\n  }: {\n    reason: ShutdownReason;\n    drain?: boolean;\n    error?: RealtimeModelError | STTError | TTSError | LLMError | null;\n  }): void {\n    if (this.closingTask) {\n      return;\n    }\n    this.closingTask = this.closeImpl(reason, error, drain).finally(() => {\n      this.closingTask = null;\n    });\n  }\n\n  /** @internal */\n  _onError(error: RealtimeModelError | STTError | TTSError | LLMError): void {\n    if (this.closingTask || error.recoverable) {\n      return;\n    }\n\n    // Track error counts per type to implement max_unrecoverable_errors logic\n    if (error.type === 'llm_error') {\n      this.llmErrorCounts += 1;\n      if (this.llmErrorCounts <= this._connOptions.maxUnrecoverableErrors) {\n        return;\n      }\n    } else if (error.type === 'tts_error') {\n      this.ttsErrorCounts += 1;\n      if (this.ttsErrorCounts <= this._connOptions.maxUnrecoverableErrors) {\n        return;\n      }\n    }\n\n    this.logger.error(error, 'AgentSession is closing due to an unrecoverable error');\n\n    this.closingTask = (async () => {\n      await this.closeImpl(CloseReason.ERROR, error);\n    })().then(() => {\n      this.closingTask = null;\n    });\n  }\n\n  /** @internal */\n  _conversationItemAdded(item: ChatMessage | AgentHandoffItem): void {\n    this._chatCtx.insert(item);\n    this.emit(AgentSessionEventTypes.ConversationItemAdded, createConversationItemAddedEvent(item));\n  }\n\n  /** @internal */\n  _toolItemsAdded(items: (FunctionCall | FunctionCallOutput)[]): void {\n    this._chatCtx.insert(items);\n  }\n\n  /** @internal */\n  _updateAgentState(state: AgentState, options?: { startTime?: number; otelContext?: Context }) {\n    if (this._agentState === state) {\n      return;\n    }\n\n    if (state === 'speaking') {\n      this.llmErrorCounts = 0;\n      this.ttsErrorCounts = 0;\n\n      if (this.agentSpeakingSpan === undefined) {\n        this.agentSpeakingSpan = tracer.startSpan({\n          name: 'agent_speaking',\n          context: options?.otelContext ?? this.rootSpanContext,\n          startTime: options?.startTime,\n        });\n\n        const localParticipant = this._roomIO?.localParticipant;\n        if (localParticipant) {\n          setParticipantSpanAttributes(this.agentSpeakingSpan, localParticipant);\n        }\n      }\n    } else if (this.agentSpeakingSpan !== undefined) {\n      // TODO(brian): PR4 - Set ATTR_END_TIME attribute if available\n      this.agentSpeakingSpan.end();\n      this.agentSpeakingSpan = undefined;\n    }\n\n    if (state === 'speaking' && this._aecWarmupRemaining > 0 && this._aecWarmupTimer === null) {\n      this._aecWarmupTimer = setTimeout(() => this._onAecWarmupExpired(), this._aecWarmupRemaining);\n      this.logger.debug(\n        { warmupDurationMs: this._aecWarmupRemaining },\n        'aec warmup active, disabling interruptions',\n      );\n    }\n\n    const oldState = this._agentState;\n    this._agentState = state;\n\n    // Handle user away timer based on state changes\n    if (state === 'listening' && this._userState === 'listening') {\n      this._setUserAwayTimer();\n    } else {\n      this._cancelUserAwayTimer();\n    }\n\n    this.emit(\n      AgentSessionEventTypes.AgentStateChanged,\n      createAgentStateChangedEvent(oldState, state),\n    );\n  }\n\n  /** @internal */\n  _updateUserState(\n    state: UserState,\n    options?: { lastSpeakingTime?: number; otelContext?: Context },\n  ) {\n    if (this._userState === state) {\n      return;\n    }\n\n    if (state === 'speaking' && this._userSpeakingSpan === undefined) {\n      this._userSpeakingSpan = tracer.startSpan({\n        name: 'user_speaking',\n        context: options?.otelContext ?? this.rootSpanContext,\n        startTime: options?.lastSpeakingTime,\n      });\n\n      const linked = this._roomIO?.linkedParticipant;\n      if (linked) {\n        setParticipantSpanAttributes(this._userSpeakingSpan, linked);\n      }\n    } else if (this._userSpeakingSpan !== undefined) {\n      this._userSpeakingSpan.end(options?.lastSpeakingTime);\n      this._userSpeakingSpan = undefined;\n    }\n\n    const oldState = this._userState;\n    this._userState = state;\n\n    // Handle user away timer based on state changes\n    if (state === 'listening' && this._agentState === 'listening') {\n      this._setUserAwayTimer();\n    } else {\n      this._cancelUserAwayTimer();\n    }\n\n    this.emit(\n      AgentSessionEventTypes.UserStateChanged,\n      createUserStateChangedEvent(oldState, state),\n    );\n  }\n\n  // -- User changed input/output streams/sinks --\n  private onAudioInputChanged(): void {\n    if (!this.started) {\n      return;\n    }\n\n    if (this.activity && this._input.audio) {\n      this.activity.attachAudioInput(this._input.audio.stream);\n    }\n  }\n\n  private onAudioEnabledChanged(enabled: boolean): void {\n    if (!enabled && this._userState === 'speaking') {\n      if (this.activity) {\n        this.activity.onEndOfSpeech(undefined);\n      } else {\n        this._updateUserState('listening');\n      }\n    }\n  }\n\n  private onAudioOutputChanged(): void {\n    if (\n      this.started &&\n      this.sessionOptions.turnHandling.interruption.resumeFalseInterruption &&\n      this.output.audio &&\n      !this.output.audio.canPause\n    ) {\n      this.logger.warn(\n        {\n          audioOutput: this.output.audio.constructor.name,\n        },\n        'resumeFalseInterruption is enabled, but the audio output does not support pause, ignored',\n      );\n    }\n  }\n\n  private onTextOutputChanged(): void {}\n\n  private _setUserAwayTimer(): void {\n    this._cancelUserAwayTimer();\n\n    if (\n      this.sessionOptions.userAwayTimeout === null ||\n      this.sessionOptions.userAwayTimeout === undefined\n    ) {\n      return;\n    }\n\n    if (this._roomIO && !this._roomIO.isParticipantAvailable) {\n      return;\n    }\n\n    this.userAwayTimer = setTimeout(() => {\n      this.logger.debug('User away timeout triggered');\n      this._updateUserState('away');\n    }, this.sessionOptions.userAwayTimeout * 1000);\n  }\n\n  private _cancelUserAwayTimer(): void {\n    if (this.userAwayTimer !== null) {\n      clearTimeout(this.userAwayTimer);\n      this.userAwayTimer = null;\n    }\n  }\n\n  /** @internal */\n  _onAecWarmupExpired(): void {\n    if (this._aecWarmupRemaining > 0) {\n      this.logger.debug('aec warmup expired, re-enabling interruptions');\n    }\n\n    this._aecWarmupRemaining = 0;\n    if (this._aecWarmupTimer !== null) {\n      clearTimeout(this._aecWarmupTimer);\n      this._aecWarmupTimer = null;\n    }\n  }\n\n  /** @internal */\n  _onRoomIOParticipantLinked(participant: RemoteParticipant): void {\n    if (this._aecWarmupDurationExplicit) {\n      return;\n    }\n\n    const isOutboundSip =\n      participant.info.kind === ParticipantKind.SIP && !participant.attributes[SIP_RULE_ID_ATTR];\n    this.sessionOptions.aecWarmupDuration = isOutboundSip ? null : DEFAULT_AEC_WARMUP_DURATION;\n    this._aecWarmupRemaining = this.sessionOptions.aecWarmupDuration ?? 0;\n\n    if (isOutboundSip && this._aecWarmupTimer !== null) {\n      clearTimeout(this._aecWarmupTimer);\n      this._aecWarmupTimer = null;\n    }\n  }\n\n  /** @internal */\n  _recordLoopStall(durationInS: number, timestampMs: number, cause: string): void {\n    const span = this.sessionSpan;\n    if (!span?.isRecording()) {\n      return;\n    }\n\n    this.loopStallCount += 1;\n    this.loopStallTotal += durationInS;\n    this.loopStallMax = Math.max(this.loopStallMax, durationInS);\n    span.addEvent(\n      LOOP_STALL_EVENT,\n      {\n        [traceTypes.ATTR_BLOCKING_DURATION]: durationInS,\n        [traceTypes.ATTR_BLOCKING_CAUSE]: cause,\n      },\n      timestampMs,\n    );\n    span.setAttributes({\n      [traceTypes.ATTR_BLOCKING_COUNT]: this.loopStallCount,\n      [traceTypes.ATTR_BLOCKING_TOTAL_DURATION]: this.loopStallTotal,\n      [traceTypes.ATTR_BLOCKING_MAX_DURATION]: this.loopStallMax,\n    });\n  }\n\n  private _onUserInputTranscribed(ev: UserInputTranscribedEvent): void {\n    if (this.closing) return;\n    if (ev.isFinal && this._userState !== 'speaking') {\n      if (this._userState === 'away') {\n        this.logger.debug('User returned from away state due to speech input');\n        this._updateUserState('listening');\n      } else if (this._userState === 'listening' && this._agentState === 'listening') {\n        this._setUserAwayTimer();\n      }\n    }\n  }\n\n  private async closeImpl(\n    reason: ShutdownReason,\n    error: RealtimeModelError | LLMError | TTSError | STTError | null = null,\n    drain: boolean = false,\n  ): Promise<void> {\n    if (this.rootSpanContext) {\n      return otelContext.with(this.rootSpanContext, async () => {\n        await this.closeImplInner(reason, error, drain);\n      });\n    }\n\n    return this.closeImplInner(reason, error, drain);\n  }\n\n  private async closeImplInner(\n    reason: ShutdownReason,\n    error: RealtimeModelError | LLMError | TTSError | STTError | null = null,\n    drain: boolean = false,\n  ): Promise<void> {\n    const wasStarted = this.started;\n    if (!wasStarted && !this.activity && !this.sessionSpan) {\n      return;\n    }\n\n    this.closing = true;\n    // Set closingTask before listeners can call close() again.\n    await Promise.resolve();\n    this.closingController.abort();\n    this._cancelUserAwayTimer();\n    this._onAecWarmupExpired();\n\n    let activity = this.activity;\n    // Let inline tasks finish their handoffs before closing the resumed parent.\n    while (wasStarted && activity?.agent instanceof AgentTask) {\n      const task = activity.agent;\n      activity.interrupt({ force: true });\n      if (!task.done) {\n        task.complete(new ToolError(`AgentTask ${task.id} is cancelled`));\n      }\n      await task._waitForInactive();\n      // A concurrent updateAgent can prevent the task from resuming its parent.\n      // In that case its activity still needs the normal exit and close sequence.\n      if (task._agentActivity === activity) {\n        await activity.drain();\n        await activity.close();\n      }\n      if (!task._oldAgent) break;\n      activity = task._oldAgent._agentActivity;\n    }\n\n    if (wasStarted && activity) {\n      if (!drain) {\n        try {\n          await activity.interrupt({ force: true }).await;\n        } catch (error) {\n          this.logger.warn({ error }, 'Error interrupting activity');\n        }\n      }\n\n      await activity.drain();\n      // wait any uninterruptible speech to finish\n      await activity.currentSpeech?.waitForPlayout();\n\n      if (reason !== CloseReason.ERROR) {\n        activity.commitUserTurn({ audioDetached: true, throwIfNotReady: false });\n      }\n\n      try {\n        activity.detachAudioInput();\n      } catch (error) {\n        // Ignore detach errors during cleanup - source may not have been set\n      }\n    }\n\n    // Close recorder before detaching inputs/outputs (keep reference for session report)\n    if (this._recorderIO) {\n      await this._recorderIO.close();\n    }\n\n    // detach the inputs and outputs\n    this.input.audio = null;\n    this.output.audio = null;\n    this.output.transcription = null;\n\n    await activity?.close();\n    this.activity = undefined;\n\n    const sessionToolsets = this._toolCtx.toolsets;\n    await Promise.allSettled(sessionToolsets.map((toolset) => toolset.aclose()));\n    this._sessionToolsetsSetup = false;\n\n    if (this.sessionSpan) {\n      this.sessionSpan.end();\n      this.sessionSpan = undefined;\n    }\n\n    if (this._userSpeakingSpan) {\n      this._userSpeakingSpan.end();\n      this._userSpeakingSpan = undefined;\n    }\n\n    if (this.agentSpeakingSpan) {\n      this.agentSpeakingSpan.end();\n      this.agentSpeakingSpan = undefined;\n    }\n\n    this.started = false;\n\n    if (wasStarted) this.emit(AgentSessionEventTypes.Close, createCloseEvent(reason, error));\n\n    this._userState = 'listening';\n    this._agentState = 'initializing';\n    this.rootSpanContext = undefined;\n    this.llmErrorCounts = 0;\n    this.ttsErrorCounts = 0;\n\n    await this.sessionHost?.close();\n    this.sessionHost = undefined;\n\n    await this._roomIO?.close();\n    this._roomIO = undefined;\n\n    this.logger.info({ reason, error }, 'AgentSession closed');\n  }\n}\n"],"mappings":"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","names":["import_llm","import_utils","InferenceVAD","InferenceSTT","InferenceLLM","BaseLLM","InferenceTTS","InferenceTurnDetector","otelContext","oldTask","agent","_a","runState","pb","error"]}