@livekit/agents 1.2.1 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/dist/audio.cjs +10 -0
  2. package/dist/audio.cjs.map +1 -1
  3. package/dist/audio.d.cts +1 -1
  4. package/dist/audio.d.ts +1 -1
  5. package/dist/audio.d.ts.map +1 -1
  6. package/dist/audio.js +10 -0
  7. package/dist/audio.js.map +1 -1
  8. package/dist/inference/api_protos.d.cts +26 -26
  9. package/dist/inference/api_protos.d.ts +26 -26
  10. package/dist/inference/tts.cjs +14 -1
  11. package/dist/inference/tts.cjs.map +1 -1
  12. package/dist/inference/tts.d.ts.map +1 -1
  13. package/dist/inference/tts.js +24 -3
  14. package/dist/inference/tts.js.map +1 -1
  15. package/dist/ipc/job_proc_lazy_main.cjs +7 -2
  16. package/dist/ipc/job_proc_lazy_main.cjs.map +1 -1
  17. package/dist/ipc/job_proc_lazy_main.js +7 -2
  18. package/dist/ipc/job_proc_lazy_main.js.map +1 -1
  19. package/dist/ipc/supervised_proc.cjs +4 -1
  20. package/dist/ipc/supervised_proc.cjs.map +1 -1
  21. package/dist/ipc/supervised_proc.d.ts.map +1 -1
  22. package/dist/ipc/supervised_proc.js +4 -1
  23. package/dist/ipc/supervised_proc.js.map +1 -1
  24. package/dist/ipc/supervised_proc.test.cjs +82 -0
  25. package/dist/ipc/supervised_proc.test.cjs.map +1 -1
  26. package/dist/ipc/supervised_proc.test.js +82 -0
  27. package/dist/ipc/supervised_proc.test.js.map +1 -1
  28. package/dist/job.cjs +2 -1
  29. package/dist/job.cjs.map +1 -1
  30. package/dist/job.d.ts.map +1 -1
  31. package/dist/job.js +2 -1
  32. package/dist/job.js.map +1 -1
  33. package/dist/utils.cjs +28 -0
  34. package/dist/utils.cjs.map +1 -1
  35. package/dist/utils.d.cts +18 -0
  36. package/dist/utils.d.ts +18 -0
  37. package/dist/utils.d.ts.map +1 -1
  38. package/dist/utils.js +25 -0
  39. package/dist/utils.js.map +1 -1
  40. package/dist/version.cjs +1 -1
  41. package/dist/version.js +1 -1
  42. package/dist/voice/agent_activity.cjs +10 -0
  43. package/dist/voice/agent_activity.cjs.map +1 -1
  44. package/dist/voice/agent_activity.d.ts.map +1 -1
  45. package/dist/voice/agent_activity.js +11 -0
  46. package/dist/voice/agent_activity.js.map +1 -1
  47. package/dist/voice/agent_session.cjs +1 -1
  48. package/dist/voice/agent_session.cjs.map +1 -1
  49. package/dist/voice/agent_session.d.cts +4 -2
  50. package/dist/voice/agent_session.d.ts +4 -2
  51. package/dist/voice/agent_session.d.ts.map +1 -1
  52. package/dist/voice/agent_session.js +1 -1
  53. package/dist/voice/agent_session.js.map +1 -1
  54. package/dist/voice/events.cjs +11 -0
  55. package/dist/voice/events.cjs.map +1 -1
  56. package/dist/voice/events.d.cts +12 -1
  57. package/dist/voice/events.d.ts +12 -1
  58. package/dist/voice/events.d.ts.map +1 -1
  59. package/dist/voice/events.js +10 -0
  60. package/dist/voice/events.js.map +1 -1
  61. package/dist/voice/generation.cjs +23 -4
  62. package/dist/voice/generation.cjs.map +1 -1
  63. package/dist/voice/generation.d.ts.map +1 -1
  64. package/dist/voice/generation.js +32 -5
  65. package/dist/voice/generation.js.map +1 -1
  66. package/dist/voice/generation_tts_timeout.test.cjs +85 -0
  67. package/dist/voice/generation_tts_timeout.test.cjs.map +1 -0
  68. package/dist/voice/generation_tts_timeout.test.js +84 -0
  69. package/dist/voice/generation_tts_timeout.test.js.map +1 -0
  70. package/dist/voice/index.cjs.map +1 -1
  71. package/dist/voice/index.d.cts +1 -1
  72. package/dist/voice/index.d.ts +1 -1
  73. package/dist/voice/index.d.ts.map +1 -1
  74. package/dist/voice/index.js +3 -1
  75. package/dist/voice/index.js.map +1 -1
  76. package/dist/voice/recorder_io/recorder_io.cjs +1 -2
  77. package/dist/voice/recorder_io/recorder_io.cjs.map +1 -1
  78. package/dist/voice/recorder_io/recorder_io.d.ts.map +1 -1
  79. package/dist/voice/recorder_io/recorder_io.js +2 -3
  80. package/dist/voice/recorder_io/recorder_io.js.map +1 -1
  81. package/dist/voice/report.cjs +1 -1
  82. package/dist/voice/report.cjs.map +1 -1
  83. package/dist/voice/report.js +1 -1
  84. package/dist/voice/report.js.map +1 -1
  85. package/dist/voice/report.test.cjs +70 -0
  86. package/dist/voice/report.test.cjs.map +1 -1
  87. package/dist/voice/report.test.js +70 -0
  88. package/dist/voice/report.test.js.map +1 -1
  89. package/dist/voice/room_io/room_io.cjs +5 -1
  90. package/dist/voice/room_io/room_io.cjs.map +1 -1
  91. package/dist/voice/room_io/room_io.d.ts.map +1 -1
  92. package/dist/voice/room_io/room_io.js +5 -1
  93. package/dist/voice/room_io/room_io.js.map +1 -1
  94. package/dist/voice/room_io/room_io.test.cjs +18 -0
  95. package/dist/voice/room_io/room_io.test.cjs.map +1 -0
  96. package/dist/voice/room_io/room_io.test.js +17 -0
  97. package/dist/voice/room_io/room_io.test.js.map +1 -0
  98. package/package.json +1 -1
  99. package/src/audio.ts +12 -1
  100. package/src/inference/tts.ts +25 -3
  101. package/src/ipc/job_proc_lazy_main.ts +7 -2
  102. package/src/ipc/supervised_proc.test.ts +96 -0
  103. package/src/ipc/supervised_proc.ts +8 -1
  104. package/src/job.ts +1 -0
  105. package/src/utils.ts +43 -0
  106. package/src/voice/agent_activity.ts +11 -0
  107. package/src/voice/agent_session.ts +13 -7
  108. package/src/voice/events.ts +21 -0
  109. package/src/voice/generation.ts +35 -8
  110. package/src/voice/generation_tts_timeout.test.ts +112 -0
  111. package/src/voice/index.ts +6 -1
  112. package/src/voice/recorder_io/recorder_io.ts +2 -7
  113. package/src/voice/report.test.ts +78 -0
  114. package/src/voice/report.ts +1 -1
  115. package/src/voice/room_io/room_io.test.ts +38 -0
  116. package/src/voice/room_io/room_io.ts +7 -2
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/voice/agent_session.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { Mutex } from '@livekit/mutex';\nimport type { AudioFrame, Room } from '@livekit/rtc-node';\nimport type { TypedEventEmitter as TypedEmitter } from '@livekit/typed-emitter';\nimport type { Context, Span } from '@opentelemetry/api';\nimport { ROOT_CONTEXT, context as otelContext, trace } from '@opentelemetry/api';\nimport { EventEmitter } from 'node:events';\nimport type { ReadableStream } from 'node:stream/web';\nimport type { z } from 'zod';\nimport {\n LLM as InferenceLLM,\n STT as InferenceSTT,\n TTS as InferenceTTS,\n type LLMModels,\n type STTModelString,\n type TTSModelString,\n} from '../inference/index.js';\nimport type { InterruptionDetectionError } from '../inference/interruption/errors.js';\nimport type { OverlappingSpeechEvent } from '../inference/interruption/types.js';\nimport { type JobContext, getJobContext } from '../job.js';\nimport type { FunctionCall, FunctionCallOutput } from '../llm/chat_context.js';\nimport { AgentHandoffItem, ChatContext, ChatMessage } from '../llm/chat_context.js';\nimport type { LLM, RealtimeModel, RealtimeModelError, ToolChoice } from '../llm/index.js';\nimport type { LLMError } from '../llm/llm.js';\nimport { log } from '../log.js';\nimport { type ModelUsage, ModelUsageCollector, filterZeroValues } from '../metrics/model_usage.js';\nimport type { STT } from '../stt/index.js';\nimport type { STTError } from '../stt/stt.js';\nimport { traceTypes, tracer } from '../telemetry/index.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} from '../types.js';\nimport { Task } from '../utils.js';\nimport type { VAD } from '../vad.js';\nimport type { Agent } from './agent.js';\nimport { AgentActivity } from './agent_activity.js';\nimport type { _TurnDetector } from './audio_recognition.js';\nimport {\n type AgentEvent,\n AgentSessionEventTypes,\n type AgentState,\n type AgentStateChangedEvent,\n type CloseEvent,\n CloseReason,\n type ConversationItemAddedEvent,\n type ErrorEvent,\n type FunctionToolsExecutedEvent,\n type MetricsCollectedEvent,\n type ShutdownReason,\n type SpeechCreatedEvent,\n type UserInputTranscribedEvent,\n type UserState,\n type UserStateChangedEvent,\n createAgentStateChangedEvent,\n createCloseEvent,\n createConversationItemAddedEvent,\n createUserStateChangedEvent,\n} from './events.js';\nimport { AgentInput, AgentOutput } from './io.js';\nimport { RecorderIO } from './recorder_io/index.js';\nimport { RoomSessionTransport, SessionHost } from './remote_session.js';\nimport {\n DEFAULT_TEXT_INPUT_CALLBACK,\n RoomIO,\n type RoomInputOptions,\n type RoomOutputOptions,\n} from './room_io/index.js';\nimport type { UnknownUserData } from './run_context.js';\nimport type { SpeechHandle } from './speech_handle.js';\nimport { RunResult } from './testing/run_result.js';\nimport type { InterruptionOptions } from './turn_config/interruption.js';\nimport type {\n InternalTurnHandlingOptions,\n TurnHandlingOptions,\n} from './turn_config/turn_handling.js';\nimport { migrateLegacyOptions } from './turn_config/utils.js';\nimport { setParticipantSpanAttributes } from './utils.js';\n\nexport interface AgentSessionUsage {\n /** List of usage summaries, one per model/provider combination. */\n modelUsage: Array<Partial<ModelUsage>>;\n}\n\nexport interface InternalSessionOptions<UserData> extends AgentSessionOptions<UserData> {\n turnHandling: InternalTurnHandlingOptions;\n useTtsAlignedTranscript: boolean;\n maxToolSteps: number;\n userAwayTimeout: number | null;\n}\n\nexport const defaultAgentSessionOptions = {\n maxToolSteps: 3,\n preemptiveGeneration: true,\n userAwayTimeout: 15.0,\n aecWarmupDuration: 3000,\n turnHandling: {},\n useTtsAlignedTranscript: true,\n} as const satisfies AgentSessionOptions;\n\n/** @deprecated {@link VoiceOptions} has been flattened onto to {@link AgentSessionOptions} */\nexport type VoiceOptions = {\n maxToolSteps: number;\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 = 'stt' | 'vad' | 'realtime_llm' | 'manual' | _TurnDetector;\n\nexport type AgentSessionCallbacks = {\n [AgentSessionEventTypes.UserInputTranscribed]: (ev: UserInputTranscribedEvent) => 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.SpeechCreated]: (ev: SpeechCreatedEvent) => void;\n [AgentSessionEventTypes.Error]: (ev: ErrorEvent) => void;\n [AgentSessionEventTypes.Close]: (ev: CloseEvent) => void;\n [AgentSessionEventTypes.OverlappingSpeech]: (ev: OverlappingSpeechEvent) => void;\n};\n\nexport type AgentSessionOptions<UserData = UnknownUserData> = {\n stt?: STT | STTModelString;\n vad?: VAD;\n llm?: LLM | RealtimeModel | LLMModels;\n tts?: TTS | TTSModelString;\n userData?: UserData;\n connOptions?: SessionConnectOptions;\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 * Whether to speculatively begin LLM and TTS requests before an end-of-turn is detected.\n * When `true`, the agent sends inference calls as soon as a user transcript is received rather\n * than waiting for a definitive turn boundary. This can reduce response latency by overlapping\n * model inference with user audio, but may incur extra compute if the user interrupts or\n * revises mid-utterance.\n * @defaultValue true\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 * Duration in milliseconds for AEC (Acoustic Echo Cancellation) warmup, during which\n * interruptions from audio activity are suppressed. Set to `null` to disable.\n * @defaultValue 3000\n */\n aecWarmupDuration?: number | null;\n\n /**\n * Configuration for turn handling.\n */\n turnHandling?: Partial<TurnHandlingOptions>;\n\n useTtsAlignedTranscript?: boolean;\n};\n\ntype ActivityTransitionOptions = {\n previousActivity?: 'close' | 'pause';\n newActivity?: 'start' | 'resume';\n blockedTasks?: Task<any>[];\n waitOnEnter?: boolean;\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 _userState: UserState = 'listening';\n private _agentState: AgentState = 'initializing';\n\n private _input: AgentInput;\n private _output: AgentOutput;\n\n private closingTask: Promise<void> | null = null;\n private userAwayTimer: NodeJS.Timeout | null = null;\n\n private _aecWarmupTimer: NodeJS.Timeout | null = null;\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\n private _interruptionDetection?: InterruptionOptions['mode'];\n\n /** @internal */\n _usageCollector: ModelUsageCollector = new ModelUsageCollector();\n\n /** @internal */\n _roomIO?: RoomIO;\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 _enableRecording = false;\n\n /** @internal - Timestamp when the session started (milliseconds) */\n _startedAt?: number;\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 const { agentSessionOptions: opts, legacyVoiceOptions } =\n migrateLegacyOptions<UserData>(options);\n\n const { vad, stt, llm, tts, userData, connOptions, ...resolvedSessionOptions } = opts;\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 this.vad = vad;\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 {\n this.llm = llm;\n }\n\n if (typeof tts === 'string') {\n this.tts = InferenceTTS.fromModelString(tts);\n } else {\n this.tts = tts;\n }\n\n this.turnDetection = resolvedSessionOptions.turnHandling.turnDetection;\n this._interruptionDetection = resolvedSessionOptions.turnHandling.interruption?.mode;\n this._userData = userData;\n\n // configurable IO\n this._input = new AgentInput(this.onAudioInputChanged);\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 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 }\n\n emit<K extends keyof AgentSessionCallbacks>(\n event: K,\n ...args: Parameters<AgentSessionCallbacks[K]>\n ): boolean {\n const eventData = args[0] as AgentEvent;\n this._recordedEvents.push(eventData);\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 /** 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 if (room && !this._roomIO) {\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 but input.audio is already set, ignoring..',\n );\n }\n\n if (this.output.audio && outputOptions?.audioEnabled !== false) {\n this.logger.warn(\n 'RoomIO audio output is enabled but output.audio is already set, ignoring..',\n );\n }\n\n if (this.output.transcription && outputOptions?.transcriptionEnabled !== false) {\n this.logger.warn(\n 'RoomIO transcription output is enabled but output.transcription is already set, ignoring..',\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 if (inputOptions?.textEnabled !== false) {\n this.sessionHost.registerTextInput(\n inputOptions?.textInputCallback ?? DEFAULT_TEXT_INPUT_CALLBACK,\n );\n }\n }\n\n let ctx: JobContext | undefined = undefined;\n try {\n ctx = getJobContext();\n } catch {\n // JobContext is not available in evals\n }\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 if (ctx._primaryAgentSession === undefined) {\n ctx._primaryAgentSession = this;\n } else if (this._enableRecording) {\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\n if (this.input.audio && this.output.audio && this._enableRecording) {\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 session directory\n const sessionDir = ctx.sessionDirectory;\n if (sessionDir) {\n tasks.push(this._recorderIO.start(`${sessionDir}/audio.ogg`));\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 await Promise.allSettled(tasks);\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 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;\n }): Promise<void> {\n if (this.started) {\n return;\n }\n\n this._usageCollector = new ModelUsageCollector();\n\n let ctx: JobContext | undefined = undefined;\n try {\n ctx = getJobContext();\n\n if (record === undefined) {\n record = ctx.job.enableRecording;\n }\n\n this._enableRecording = record;\n\n if (this._enableRecording) {\n ctx.initRecording();\n }\n } catch (error) {\n // JobContext is not available in evals\n this.logger.warn('JobContext is not available');\n }\n\n this.sessionSpan = tracer.startSpan({\n name: 'agent_session',\n context: ROOT_CONTEXT,\n });\n\n this.rootSpanContext = trace.setSpan(ROOT_CONTEXT, this.sessionSpan);\n\n await this._startImpl({\n agent,\n room,\n inputOptions,\n outputOptions,\n span: this.sessionSpan,\n });\n }\n\n updateAgent(agent: Agent): void {\n this.agent = agent;\n\n if (!this.started) {\n return;\n }\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);\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 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 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 generateReply(options?: {\n userInput?: string;\n instructions?: string;\n toolChoice?: ToolChoice;\n allowInterruptions?: boolean;\n }): SpeechHandle {\n if (!this.activity) {\n throw new Error('AgentSession is not running');\n }\n\n const userMessage = options?.userInput\n ? new ChatMessage({\n role: 'user',\n content: options.userInput,\n })\n : undefined;\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 });\n }\n return activity.generateReply({ userMessage, ...options });\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 * @returns A RunResult that resolves when the agent finishes responding\n */\n run<T = unknown>({\n userInput,\n outputType,\n }: {\n userInput: string;\n outputType?: z.ZodType<T>;\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 });\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 });\n } catch (e) {\n runState._reject(e instanceof Error ? e : new Error(String(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\n try {\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 await prevActivityObj.pause({ blockedTasks });\n } else {\n await prevActivityObj.drain();\n await prevActivityObj.close();\n }\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._chatCtx.insert(handoffItem);\n this.logger.debug(\n { previousAgentId: prevActivityObj?.agent.id, newAgentId: agent.id },\n 'Agent handoff inserted into chat context',\n );\n\n if (newActivity === 'start') {\n await this.activity!.start();\n } else {\n await this.activity!.resume();\n }\n\n onEnterTask = this.activity!._onEnterTask;\n\n if (this._input.audio) {\n this.activity!.attachAudioInput(this._input.audio.stream);\n }\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 async close(): Promise<void> {\n await this.closeImpl(CloseReason.USER_INITIATED);\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(\n error: RealtimeModelError | STTError | TTSError | LLMError | InterruptionDetectionError,\n ): 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 } else if (error.type === 'interruption_detection_error') {\n this.logger.error(error.toString());\n return;\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): 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 onAudioOutputChanged(): void {}\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 private _onUserInputTranscribed(ev: UserInputTranscribedEvent): void {\n if (this._userState === 'away' && ev.isFinal) {\n this.logger.debug('User returned from away state due to speech input');\n this._updateUserState('listening');\n }\n }\n\n private async closeImpl(\n reason: ShutdownReason,\n error:\n | RealtimeModelError\n | LLMError\n | TTSError\n | STTError\n | InterruptionDetectionError\n | 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:\n | RealtimeModelError\n | LLMError\n | TTSError\n | STTError\n | InterruptionDetectionError\n | null = null,\n drain: boolean = false,\n ): Promise<void> {\n if (!this.started) {\n return;\n }\n\n this._cancelUserAwayTimer();\n this._onAecWarmupExpired();\n this.off(AgentSessionEventTypes.UserInputTranscribed, this._onUserInputTranscribed);\n\n if (this.activity) {\n if (!drain) {\n try {\n await this.activity.interrupt({ force: true }).await;\n } catch (error) {\n this.logger.warn({ error }, 'Error interrupting activity');\n }\n }\n\n await this.activity.drain();\n // wait any uninterruptible speech to finish\n await this.activity.currentSpeech?.waitForPlayout();\n\n if (reason !== CloseReason.ERROR) {\n this.activity.commitUserTurn({ audioDetached: true, throwIfNotReady: false });\n }\n\n try {\n this.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 this.sessionHost?.close();\n this.sessionHost = undefined;\n\n await this._roomIO?.close();\n this._roomIO = undefined;\n\n await this.activity?.close();\n this.activity = undefined;\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 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 this.logger.info({ reason, error }, 'AgentSession closed');\n }\n}\n"],"mappings":"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","names":["oldTask","agent","error"]}
1
+ {"version":3,"sources":["../../src/voice/agent_session.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { Mutex } from '@livekit/mutex';\nimport type { AudioFrame, Room } from '@livekit/rtc-node';\nimport type { TypedEventEmitter as TypedEmitter } from '@livekit/typed-emitter';\nimport type { Context, Span } from '@opentelemetry/api';\nimport { ROOT_CONTEXT, context as otelContext, trace } from '@opentelemetry/api';\nimport { EventEmitter } from 'node:events';\nimport type { ReadableStream } from 'node:stream/web';\nimport type { z } from 'zod';\nimport {\n LLM as InferenceLLM,\n STT as InferenceSTT,\n TTS as InferenceTTS,\n type LLMModels,\n type STTModelString,\n type TTSModelString,\n} from '../inference/index.js';\nimport type { InterruptionDetectionError } from '../inference/interruption/errors.js';\nimport type { OverlappingSpeechEvent } from '../inference/interruption/types.js';\nimport { type JobContext, getJobContext } from '../job.js';\nimport type { FunctionCall, FunctionCallOutput } from '../llm/chat_context.js';\nimport { AgentHandoffItem, ChatContext, ChatMessage } from '../llm/chat_context.js';\nimport type { LLM, RealtimeModel, RealtimeModelError, ToolChoice } from '../llm/index.js';\nimport type { LLMError } from '../llm/llm.js';\nimport { log } from '../log.js';\nimport { type ModelUsage, ModelUsageCollector, filterZeroValues } from '../metrics/model_usage.js';\nimport type { STT } from '../stt/index.js';\nimport type { STTError } from '../stt/stt.js';\nimport { traceTypes, tracer } from '../telemetry/index.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} from '../types.js';\nimport { Task } from '../utils.js';\nimport type { VAD } from '../vad.js';\nimport type { Agent } from './agent.js';\nimport { AgentActivity } from './agent_activity.js';\nimport type { _TurnDetector } from './audio_recognition.js';\nimport {\n type AgentEvent,\n AgentSessionEventTypes,\n type AgentState,\n type AgentStateChangedEvent,\n type CloseEvent,\n CloseReason,\n type ConversationItemAddedEvent,\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 createAgentStateChangedEvent,\n createCloseEvent,\n createConversationItemAddedEvent,\n createUserStateChangedEvent,\n} from './events.js';\nimport { AgentInput, AgentOutput } from './io.js';\nimport { RecorderIO } from './recorder_io/index.js';\nimport { RoomSessionTransport, SessionHost } from './remote_session.js';\nimport {\n DEFAULT_TEXT_INPUT_CALLBACK,\n RoomIO,\n type RoomInputOptions,\n type RoomOutputOptions,\n} from './room_io/index.js';\nimport type { UnknownUserData } from './run_context.js';\nimport type { SpeechHandle } from './speech_handle.js';\nimport { RunResult } from './testing/run_result.js';\nimport type { InterruptionOptions } from './turn_config/interruption.js';\nimport type {\n InternalTurnHandlingOptions,\n TurnHandlingOptions,\n} from './turn_config/turn_handling.js';\nimport { migrateLegacyOptions } from './turn_config/utils.js';\nimport { setParticipantSpanAttributes } from './utils.js';\n\nexport interface AgentSessionUsage {\n /** List of usage summaries, one per model/provider combination. */\n modelUsage: Array<Partial<ModelUsage>>;\n}\n\nexport interface InternalSessionOptions<UserData> extends AgentSessionOptions<UserData> {\n turnHandling: InternalTurnHandlingOptions;\n useTtsAlignedTranscript: boolean;\n maxToolSteps: number;\n userAwayTimeout: number | null;\n}\n\nexport const defaultAgentSessionOptions = {\n maxToolSteps: 3,\n preemptiveGeneration: true,\n userAwayTimeout: 15.0,\n aecWarmupDuration: 3000,\n turnHandling: {},\n useTtsAlignedTranscript: true,\n} as const satisfies AgentSessionOptions;\n\n/** @deprecated {@link VoiceOptions} has been flattened onto to {@link AgentSessionOptions} */\nexport type VoiceOptions = {\n maxToolSteps: number;\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 = 'stt' | 'vad' | 'realtime_llm' | 'manual' | _TurnDetector;\n\nexport type AgentSessionCallbacks = {\n [AgentSessionEventTypes.UserInputTranscribed]: (ev: UserInputTranscribedEvent) => 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.SpeechCreated]: (ev: SpeechCreatedEvent) => void;\n [AgentSessionEventTypes.Error]: (ev: ErrorEvent) => void;\n [AgentSessionEventTypes.Close]: (ev: CloseEvent) => void;\n [AgentSessionEventTypes.OverlappingSpeech]: (ev: OverlappingSpeechEvent) => void;\n};\n\nexport type AgentSessionOptions<UserData = UnknownUserData> = {\n stt?: STT | STTModelString;\n vad?: VAD;\n llm?: LLM | RealtimeModel | LLMModels;\n tts?: TTS | TTSModelString;\n userData?: UserData;\n connOptions?: SessionConnectOptions;\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 * Whether to speculatively begin LLM and TTS requests before an end-of-turn is detected.\n * When `true`, the agent sends inference calls as soon as a user transcript is received rather\n * than waiting for a definitive turn boundary. This can reduce response latency by overlapping\n * model inference with user audio, but may incur extra compute if the user interrupts or\n * revises mid-utterance.\n * @defaultValue true\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 * Duration in milliseconds for AEC (Acoustic Echo Cancellation) warmup, during which\n * interruptions from audio activity are suppressed. Set to `null` to disable.\n * @defaultValue 3000\n */\n aecWarmupDuration?: number | null;\n\n /**\n * Configuration for turn handling.\n */\n turnHandling?: Partial<TurnHandlingOptions>;\n\n useTtsAlignedTranscript?: boolean;\n};\n\ntype ActivityTransitionOptions = {\n previousActivity?: 'close' | 'pause';\n newActivity?: 'start' | 'resume';\n blockedTasks?: Task<any>[];\n waitOnEnter?: boolean;\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 _userState: UserState = 'listening';\n private _agentState: AgentState = 'initializing';\n\n private _input: AgentInput;\n private _output: AgentOutput;\n\n private closingTask: Promise<void> | null = null;\n private userAwayTimer: NodeJS.Timeout | null = null;\n\n private _aecWarmupTimer: NodeJS.Timeout | null = null;\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\n private _interruptionDetection?: InterruptionOptions['mode'];\n\n /** @internal */\n _usageCollector: ModelUsageCollector = new ModelUsageCollector();\n\n /** @internal */\n _roomIO?: RoomIO;\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 _enableRecording = false;\n\n /** @internal - Timestamp when the session started (milliseconds) */\n _startedAt?: number;\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 const { agentSessionOptions: opts, legacyVoiceOptions } =\n migrateLegacyOptions<UserData>(options);\n\n const { vad, stt, llm, tts, userData, connOptions, ...resolvedSessionOptions } = opts;\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 this.vad = vad;\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 {\n this.llm = llm;\n }\n\n if (typeof tts === 'string') {\n this.tts = InferenceTTS.fromModelString(tts);\n } else {\n this.tts = tts;\n }\n\n this.turnDetection = resolvedSessionOptions.turnHandling.turnDetection;\n this._interruptionDetection = resolvedSessionOptions.turnHandling.interruption?.mode;\n this._userData = userData;\n\n // configurable IO\n this._input = new AgentInput(this.onAudioInputChanged);\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 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 }\n\n emit<K extends keyof AgentSessionCallbacks>(\n event: K,\n ...args: Parameters<AgentSessionCallbacks[K]>\n ): boolean {\n const eventData = args[0] as AgentEvent;\n this._recordedEvents.push(eventData);\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 /** 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 if (room && !this._roomIO) {\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 but input.audio is already set, ignoring..',\n );\n }\n\n if (this.output.audio && outputOptions?.audioEnabled !== false) {\n this.logger.warn(\n 'RoomIO audio output is enabled but output.audio is already set, ignoring..',\n );\n }\n\n if (this.output.transcription && outputOptions?.transcriptionEnabled !== false) {\n this.logger.warn(\n 'RoomIO transcription output is enabled but output.transcription is already set, ignoring..',\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 if (inputOptions?.textEnabled !== false) {\n this.sessionHost.registerTextInput(\n inputOptions?.textInputCallback ?? DEFAULT_TEXT_INPUT_CALLBACK,\n );\n }\n }\n\n let ctx: JobContext | undefined = undefined;\n try {\n ctx = getJobContext();\n } catch {\n // JobContext is not available in evals\n }\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 if (ctx._primaryAgentSession === undefined) {\n ctx._primaryAgentSession = this;\n } else if (this._enableRecording) {\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\n if (this.input.audio && this.output.audio && this._enableRecording) {\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 session directory\n const sessionDir = ctx.sessionDirectory;\n if (sessionDir) {\n tasks.push(this._recorderIO.start(`${sessionDir}/audio.ogg`));\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 await Promise.allSettled(tasks);\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 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;\n }): Promise<void> {\n if (this.started) {\n return;\n }\n\n this._usageCollector = new ModelUsageCollector();\n\n let ctx: JobContext | undefined = undefined;\n try {\n ctx = getJobContext();\n\n if (record === undefined) {\n record = ctx.job.enableRecording;\n }\n\n this._enableRecording = record;\n\n if (this._enableRecording) {\n ctx.initRecording();\n }\n } catch (error) {\n // JobContext is not available in evals\n this.logger.warn('JobContext is not available');\n }\n\n this.sessionSpan = tracer.startSpan({\n name: 'agent_session',\n context: ROOT_CONTEXT,\n });\n\n this.rootSpanContext = trace.setSpan(ROOT_CONTEXT, this.sessionSpan);\n\n await this._startImpl({\n agent,\n room,\n inputOptions,\n outputOptions,\n span: this.sessionSpan,\n });\n }\n\n updateAgent(agent: Agent): void {\n this.agent = agent;\n\n if (!this.started) {\n return;\n }\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);\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 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 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 generateReply(options?: {\n userInput?: string | ChatMessage;\n chatCtx?: ChatContext;\n instructions?: string;\n toolChoice?: ToolChoice;\n allowInterruptions?: boolean;\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 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 });\n }\n return activity.generateReply({ userMessage, ...options });\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 * @returns A RunResult that resolves when the agent finishes responding\n */\n run<T = unknown>({\n userInput,\n outputType,\n }: {\n userInput: string;\n outputType?: z.ZodType<T>;\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 });\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 });\n } catch (e) {\n runState._reject(e instanceof Error ? e : new Error(String(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\n try {\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 await prevActivityObj.pause({ blockedTasks });\n } else {\n await prevActivityObj.drain();\n await prevActivityObj.close();\n }\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._chatCtx.insert(handoffItem);\n this.logger.debug(\n { previousAgentId: prevActivityObj?.agent.id, newAgentId: agent.id },\n 'Agent handoff inserted into chat context',\n );\n\n if (newActivity === 'start') {\n await this.activity!.start();\n } else {\n await this.activity!.resume();\n }\n\n onEnterTask = this.activity!._onEnterTask;\n\n if (this._input.audio) {\n this.activity!.attachAudioInput(this._input.audio.stream);\n }\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 async close(): Promise<void> {\n await this.closeImpl(CloseReason.USER_INITIATED);\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(\n error: RealtimeModelError | STTError | TTSError | LLMError | InterruptionDetectionError,\n ): 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 } else if (error.type === 'interruption_detection_error') {\n this.logger.error(error.toString());\n return;\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): 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 onAudioOutputChanged(): void {}\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 private _onUserInputTranscribed(ev: UserInputTranscribedEvent): void {\n if (this._userState === 'away' && ev.isFinal) {\n this.logger.debug('User returned from away state due to speech input');\n this._updateUserState('listening');\n }\n }\n\n private async closeImpl(\n reason: ShutdownReason,\n error:\n | RealtimeModelError\n | LLMError\n | TTSError\n | STTError\n | InterruptionDetectionError\n | 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:\n | RealtimeModelError\n | LLMError\n | TTSError\n | STTError\n | InterruptionDetectionError\n | null = null,\n drain: boolean = false,\n ): Promise<void> {\n if (!this.started) {\n return;\n }\n\n this._cancelUserAwayTimer();\n this._onAecWarmupExpired();\n this.off(AgentSessionEventTypes.UserInputTranscribed, this._onUserInputTranscribed);\n\n if (this.activity) {\n if (!drain) {\n try {\n await this.activity.interrupt({ force: true }).await;\n } catch (error) {\n this.logger.warn({ error }, 'Error interrupting activity');\n }\n }\n\n await this.activity.drain();\n // wait any uninterruptible speech to finish\n await this.activity.currentSpeech?.waitForPlayout();\n\n if (reason !== CloseReason.ERROR) {\n this.activity.commitUserTurn({ audioDetached: true, throwIfNotReady: false });\n }\n\n try {\n this.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 this.sessionHost?.close();\n this.sessionHost = undefined;\n\n await this._roomIO?.close();\n this._roomIO = undefined;\n\n await this.activity?.close();\n this.activity = undefined;\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 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 this.logger.info({ reason, error }, 'AgentSession closed');\n }\n}\n"],"mappings":"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","names":["oldTask","agent","error"]}
@@ -26,6 +26,7 @@ __export(events_exports, {
26
26
  createErrorEvent: () => createErrorEvent,
27
27
  createFunctionToolsExecutedEvent: () => createFunctionToolsExecutedEvent,
28
28
  createMetricsCollectedEvent: () => createMetricsCollectedEvent,
29
+ createSessionUsageUpdatedEvent: () => createSessionUsageUpdatedEvent,
29
30
  createSpeechCreatedEvent: () => createSpeechCreatedEvent,
30
31
  createUserInputTranscribedEvent: () => createUserInputTranscribedEvent,
31
32
  createUserStateChangedEvent: () => createUserStateChangedEvent,
@@ -39,6 +40,7 @@ var AgentSessionEventTypes = /* @__PURE__ */ ((AgentSessionEventTypes2) => {
39
40
  AgentSessionEventTypes2["ConversationItemAdded"] = "conversation_item_added";
40
41
  AgentSessionEventTypes2["FunctionToolsExecuted"] = "function_tools_executed";
41
42
  AgentSessionEventTypes2["MetricsCollected"] = "metrics_collected";
43
+ AgentSessionEventTypes2["SessionUsageUpdated"] = "session_usage_updated";
42
44
  AgentSessionEventTypes2["SpeechCreated"] = "speech_created";
43
45
  AgentSessionEventTypes2["OverlappingSpeech"] = "overlapping_speech";
44
46
  AgentSessionEventTypes2["Error"] = "error";
@@ -86,6 +88,14 @@ const createMetricsCollectedEvent = ({
86
88
  metrics,
87
89
  createdAt
88
90
  });
91
+ const createSessionUsageUpdatedEvent = ({
92
+ usage,
93
+ createdAt = Date.now()
94
+ }) => ({
95
+ type: "session_usage_updated",
96
+ usage,
97
+ createdAt
98
+ });
89
99
  const createConversationItemAddedEvent = (item, createdAt = Date.now()) => ({
90
100
  type: "conversation_item_added",
91
101
  item,
@@ -140,6 +150,7 @@ const createCloseEvent = (reason, error = null, createdAt = Date.now()) => ({
140
150
  createErrorEvent,
141
151
  createFunctionToolsExecutedEvent,
142
152
  createMetricsCollectedEvent,
153
+ createSessionUsageUpdatedEvent,
143
154
  createSpeechCreatedEvent,
144
155
  createUserInputTranscribedEvent,
145
156
  createUserStateChangedEvent,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/voice/events.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { InterruptionDetectionError } from '../inference/interruption/errors.js';\nimport type { OverlappingSpeechEvent } from '../inference/interruption/types.js';\nimport type { LanguageCode } from '../language.js';\nimport type {\n ChatMessage,\n FunctionCall,\n FunctionCallOutput,\n LLM,\n RealtimeModel,\n RealtimeModelError,\n} from '../llm/index.js';\nimport type { LLMError } from '../llm/llm.js';\nimport type { AgentMetrics } from '../metrics/base.js';\nimport type { STT } from '../stt/index.js';\nimport type { STTError } from '../stt/stt.js';\nimport type { TTS } from '../tts/index.js';\nimport type { TTSError } from '../tts/tts.js';\nimport type { SpeechHandle } from './speech_handle.js';\n\nexport enum AgentSessionEventTypes {\n UserInputTranscribed = 'user_input_transcribed',\n AgentStateChanged = 'agent_state_changed',\n UserStateChanged = 'user_state_changed',\n ConversationItemAdded = 'conversation_item_added',\n FunctionToolsExecuted = 'function_tools_executed',\n MetricsCollected = 'metrics_collected',\n SpeechCreated = 'speech_created',\n OverlappingSpeech = 'overlapping_speech',\n Error = 'error',\n Close = 'close',\n}\n\nexport type UserState = 'speaking' | 'listening' | 'away';\nexport type AgentState = 'initializing' | 'idle' | 'listening' | 'thinking' | 'speaking';\n\nexport enum CloseReason {\n ERROR = 'error',\n JOB_SHUTDOWN = 'job_shutdown',\n PARTICIPANT_DISCONNECTED = 'participant_disconnected',\n USER_INITIATED = 'user_initiated',\n}\n\nexport type ShutdownReason = CloseReason | string;\n\nexport type SpeechSource = 'say' | 'generate_reply' | 'tool_response';\n\nexport type UserStateChangedEvent = {\n type: 'user_state_changed';\n oldState: UserState;\n newState: UserState;\n createdAt: number;\n};\n\nexport const createUserStateChangedEvent = (\n oldState: UserState,\n newState: UserState,\n createdAt: number = Date.now(),\n): UserStateChangedEvent => ({\n type: 'user_state_changed',\n oldState,\n newState,\n createdAt,\n});\n\nexport type AgentStateChangedEvent = {\n type: 'agent_state_changed';\n oldState: AgentState;\n newState: AgentState;\n createdAt: number;\n};\n\nexport const createAgentStateChangedEvent = (\n oldState: AgentState,\n newState: AgentState,\n createdAt: number = Date.now(),\n): AgentStateChangedEvent => ({\n type: 'agent_state_changed',\n oldState,\n newState,\n createdAt,\n});\n\nexport type UserInputTranscribedEvent = {\n type: 'user_input_transcribed';\n transcript: string;\n isFinal: boolean;\n // TODO(AJS-106): add multi participant support\n /** Not supported yet. Always null by default. */\n speakerId: string | null;\n createdAt: number;\n language: LanguageCode | null;\n};\n\nexport const createUserInputTranscribedEvent = ({\n transcript,\n isFinal,\n speakerId = null,\n language = null,\n createdAt = Date.now(),\n}: {\n transcript: string;\n isFinal: boolean;\n speakerId?: string | null;\n language?: LanguageCode | null;\n createdAt?: number;\n}): UserInputTranscribedEvent => ({\n type: 'user_input_transcribed',\n transcript,\n isFinal,\n speakerId,\n language,\n createdAt,\n});\n\nexport type MetricsCollectedEvent = {\n type: 'metrics_collected';\n metrics: AgentMetrics;\n createdAt: number;\n};\n\nexport const createMetricsCollectedEvent = ({\n metrics,\n createdAt = Date.now(),\n}: {\n metrics: AgentMetrics;\n createdAt?: number;\n}): MetricsCollectedEvent => ({\n type: 'metrics_collected',\n metrics,\n createdAt,\n});\n\nexport type ConversationItemAddedEvent = {\n type: 'conversation_item_added';\n item: ChatMessage;\n createdAt: number;\n};\n\nexport const createConversationItemAddedEvent = (\n item: ChatMessage,\n createdAt: number = Date.now(),\n): ConversationItemAddedEvent => ({\n type: 'conversation_item_added',\n item,\n createdAt,\n});\n\nexport type FunctionToolsExecutedEvent = {\n type: 'function_tools_executed';\n functionCalls: FunctionCall[];\n functionCallOutputs: FunctionCallOutput[];\n createdAt: number;\n};\n\nexport const createFunctionToolsExecutedEvent = ({\n functionCalls,\n functionCallOutputs,\n createdAt = Date.now(),\n}: {\n functionCalls: FunctionCall[];\n functionCallOutputs: FunctionCallOutput[];\n createdAt?: number;\n}): FunctionToolsExecutedEvent => {\n return {\n type: 'function_tools_executed',\n functionCalls,\n functionCallOutputs,\n createdAt,\n };\n};\n\nexport const zipFunctionCallsAndOutputs = (\n event: FunctionToolsExecutedEvent,\n): Array<[FunctionCall, FunctionCallOutput]> => {\n return event.functionCalls.map((call, index) => [call, event.functionCallOutputs[index]!]);\n};\n\nexport type SpeechCreatedEvent = {\n type: 'speech_created';\n /**\n * True if the speech was created using public methods like `say` or `generate_reply`\n */\n userInitiated: boolean;\n /**\n * Source indicating how the speech handle was created\n */\n source: SpeechSource;\n /**\n * The speech handle that was created\n */\n // TODO(shubhra): we need to make sure this doesn't get serialized\n speechHandle: SpeechHandle;\n /**\n * The timestamp when the speech handle was created\n */\n createdAt: number;\n};\n\nexport const createSpeechCreatedEvent = ({\n userInitiated,\n source,\n speechHandle,\n createdAt = Date.now(),\n}: {\n userInitiated: boolean;\n source: SpeechSource;\n speechHandle: SpeechHandle;\n createdAt?: number;\n}): SpeechCreatedEvent => ({\n type: 'speech_created',\n userInitiated,\n source,\n speechHandle,\n createdAt,\n});\n\nexport type ErrorEvent = {\n type: 'error';\n error: RealtimeModelError | STTError | TTSError | LLMError | InterruptionDetectionError | unknown;\n source: LLM | STT | TTS | RealtimeModel | unknown;\n createdAt: number;\n};\n\nexport const createErrorEvent = (\n error: RealtimeModelError | STTError | TTSError | LLMError | InterruptionDetectionError | unknown,\n source: LLM | STT | TTS | RealtimeModel | unknown,\n createdAt: number = Date.now(),\n): ErrorEvent => ({\n type: 'error',\n error,\n source,\n createdAt,\n});\n\nexport type CloseEvent = {\n type: 'close';\n error: RealtimeModelError | STTError | TTSError | LLMError | InterruptionDetectionError | null;\n reason: ShutdownReason;\n createdAt: number;\n};\n\nexport const createCloseEvent = (\n reason: ShutdownReason,\n error:\n | RealtimeModelError\n | STTError\n | TTSError\n | LLMError\n | InterruptionDetectionError\n | null = null,\n createdAt: number = Date.now(),\n): CloseEvent => ({\n type: 'close',\n error,\n reason,\n createdAt,\n});\n\nexport type AgentEvent =\n | UserInputTranscribedEvent\n | UserStateChangedEvent\n | AgentStateChangedEvent\n | MetricsCollectedEvent\n | ConversationItemAddedEvent\n | FunctionToolsExecutedEvent\n | SpeechCreatedEvent\n | OverlappingSpeechEvent\n | ErrorEvent\n | CloseEvent;\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAsBO,IAAK,yBAAL,kBAAKA,4BAAL;AACL,EAAAA,wBAAA,0BAAuB;AACvB,EAAAA,wBAAA,uBAAoB;AACpB,EAAAA,wBAAA,sBAAmB;AACnB,EAAAA,wBAAA,2BAAwB;AACxB,EAAAA,wBAAA,2BAAwB;AACxB,EAAAA,wBAAA,sBAAmB;AACnB,EAAAA,wBAAA,mBAAgB;AAChB,EAAAA,wBAAA,uBAAoB;AACpB,EAAAA,wBAAA,WAAQ;AACR,EAAAA,wBAAA,WAAQ;AAVE,SAAAA;AAAA,GAAA;AAgBL,IAAK,cAAL,kBAAKC,iBAAL;AACL,EAAAA,aAAA,WAAQ;AACR,EAAAA,aAAA,kBAAe;AACf,EAAAA,aAAA,8BAA2B;AAC3B,EAAAA,aAAA,oBAAiB;AAJP,SAAAA;AAAA,GAAA;AAkBL,MAAM,8BAA8B,CACzC,UACA,UACA,YAAoB,KAAK,IAAI,OACF;AAAA,EAC3B,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AACF;AASO,MAAM,+BAA+B,CAC1C,UACA,UACA,YAAoB,KAAK,IAAI,OACD;AAAA,EAC5B,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AACF;AAaO,MAAM,kCAAkC,CAAC;AAAA,EAC9C;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,YAAY,KAAK,IAAI;AACvB,OAMkC;AAAA,EAChC,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAQO,MAAM,8BAA8B,CAAC;AAAA,EAC1C;AAAA,EACA,YAAY,KAAK,IAAI;AACvB,OAG8B;AAAA,EAC5B,MAAM;AAAA,EACN;AAAA,EACA;AACF;AAQO,MAAM,mCAAmC,CAC9C,MACA,YAAoB,KAAK,IAAI,OACG;AAAA,EAChC,MAAM;AAAA,EACN;AAAA,EACA;AACF;AASO,MAAM,mCAAmC,CAAC;AAAA,EAC/C;AAAA,EACA;AAAA,EACA,YAAY,KAAK,IAAI;AACvB,MAIkC;AAChC,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEO,MAAM,6BAA6B,CACxC,UAC8C;AAC9C,SAAO,MAAM,cAAc,IAAI,CAAC,MAAM,UAAU,CAAC,MAAM,MAAM,oBAAoB,KAAK,CAAE,CAAC;AAC3F;AAuBO,MAAM,2BAA2B,CAAC;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY,KAAK,IAAI;AACvB,OAK2B;AAAA,EACzB,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AASO,MAAM,mBAAmB,CAC9B,OACA,QACA,YAAoB,KAAK,IAAI,OACb;AAAA,EAChB,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AACF;AASO,MAAM,mBAAmB,CAC9B,QACA,QAMW,MACX,YAAoB,KAAK,IAAI,OACb;AAAA,EAChB,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AACF;","names":["AgentSessionEventTypes","CloseReason"]}
1
+ {"version":3,"sources":["../../src/voice/events.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { InterruptionDetectionError } from '../inference/interruption/errors.js';\nimport type { OverlappingSpeechEvent } from '../inference/interruption/types.js';\nimport type { LanguageCode } from '../language.js';\nimport type {\n ChatMessage,\n FunctionCall,\n FunctionCallOutput,\n LLM,\n RealtimeModel,\n RealtimeModelError,\n} from '../llm/index.js';\nimport type { LLMError } from '../llm/llm.js';\nimport type { AgentMetrics } from '../metrics/base.js';\nimport type { STT } from '../stt/index.js';\nimport type { STTError } from '../stt/stt.js';\nimport type { TTS } from '../tts/index.js';\nimport type { TTSError } from '../tts/tts.js';\nimport type { AgentSessionUsage } from './agent_session.js';\nimport type { SpeechHandle } from './speech_handle.js';\n\nexport enum AgentSessionEventTypes {\n UserInputTranscribed = 'user_input_transcribed',\n AgentStateChanged = 'agent_state_changed',\n UserStateChanged = 'user_state_changed',\n ConversationItemAdded = 'conversation_item_added',\n FunctionToolsExecuted = 'function_tools_executed',\n MetricsCollected = 'metrics_collected',\n SessionUsageUpdated = 'session_usage_updated',\n SpeechCreated = 'speech_created',\n OverlappingSpeech = 'overlapping_speech',\n Error = 'error',\n Close = 'close',\n}\n\nexport type UserState = 'speaking' | 'listening' | 'away';\nexport type AgentState = 'initializing' | 'idle' | 'listening' | 'thinking' | 'speaking';\n\nexport enum CloseReason {\n ERROR = 'error',\n JOB_SHUTDOWN = 'job_shutdown',\n PARTICIPANT_DISCONNECTED = 'participant_disconnected',\n USER_INITIATED = 'user_initiated',\n}\n\nexport type ShutdownReason = CloseReason | string;\n\nexport type SpeechSource = 'say' | 'generate_reply' | 'tool_response';\n\nexport type UserStateChangedEvent = {\n type: 'user_state_changed';\n oldState: UserState;\n newState: UserState;\n createdAt: number;\n};\n\nexport const createUserStateChangedEvent = (\n oldState: UserState,\n newState: UserState,\n createdAt: number = Date.now(),\n): UserStateChangedEvent => ({\n type: 'user_state_changed',\n oldState,\n newState,\n createdAt,\n});\n\nexport type AgentStateChangedEvent = {\n type: 'agent_state_changed';\n oldState: AgentState;\n newState: AgentState;\n createdAt: number;\n};\n\nexport const createAgentStateChangedEvent = (\n oldState: AgentState,\n newState: AgentState,\n createdAt: number = Date.now(),\n): AgentStateChangedEvent => ({\n type: 'agent_state_changed',\n oldState,\n newState,\n createdAt,\n});\n\nexport type UserInputTranscribedEvent = {\n type: 'user_input_transcribed';\n transcript: string;\n isFinal: boolean;\n // TODO(AJS-106): add multi participant support\n /** Not supported yet. Always null by default. */\n speakerId: string | null;\n createdAt: number;\n language: LanguageCode | null;\n};\n\nexport const createUserInputTranscribedEvent = ({\n transcript,\n isFinal,\n speakerId = null,\n language = null,\n createdAt = Date.now(),\n}: {\n transcript: string;\n isFinal: boolean;\n speakerId?: string | null;\n language?: LanguageCode | null;\n createdAt?: number;\n}): UserInputTranscribedEvent => ({\n type: 'user_input_transcribed',\n transcript,\n isFinal,\n speakerId,\n language,\n createdAt,\n});\n\nexport type MetricsCollectedEvent = {\n type: 'metrics_collected';\n metrics: AgentMetrics;\n createdAt: number;\n};\n\nexport const createMetricsCollectedEvent = ({\n metrics,\n createdAt = Date.now(),\n}: {\n metrics: AgentMetrics;\n createdAt?: number;\n}): MetricsCollectedEvent => ({\n type: 'metrics_collected',\n metrics,\n createdAt,\n});\n\nexport type SessionUsageUpdatedEvent = {\n type: 'session_usage_updated';\n usage: AgentSessionUsage;\n createdAt: number;\n};\n\nexport const createSessionUsageUpdatedEvent = ({\n usage,\n createdAt = Date.now(),\n}: {\n usage: AgentSessionUsage;\n createdAt?: number;\n}): SessionUsageUpdatedEvent => ({\n type: 'session_usage_updated',\n usage,\n createdAt,\n});\n\nexport type ConversationItemAddedEvent = {\n type: 'conversation_item_added';\n item: ChatMessage;\n createdAt: number;\n};\n\nexport const createConversationItemAddedEvent = (\n item: ChatMessage,\n createdAt: number = Date.now(),\n): ConversationItemAddedEvent => ({\n type: 'conversation_item_added',\n item,\n createdAt,\n});\n\nexport type FunctionToolsExecutedEvent = {\n type: 'function_tools_executed';\n functionCalls: FunctionCall[];\n functionCallOutputs: FunctionCallOutput[];\n createdAt: number;\n};\n\nexport const createFunctionToolsExecutedEvent = ({\n functionCalls,\n functionCallOutputs,\n createdAt = Date.now(),\n}: {\n functionCalls: FunctionCall[];\n functionCallOutputs: FunctionCallOutput[];\n createdAt?: number;\n}): FunctionToolsExecutedEvent => {\n return {\n type: 'function_tools_executed',\n functionCalls,\n functionCallOutputs,\n createdAt,\n };\n};\n\nexport const zipFunctionCallsAndOutputs = (\n event: FunctionToolsExecutedEvent,\n): Array<[FunctionCall, FunctionCallOutput]> => {\n return event.functionCalls.map((call, index) => [call, event.functionCallOutputs[index]!]);\n};\n\nexport type SpeechCreatedEvent = {\n type: 'speech_created';\n /**\n * True if the speech was created using public methods like `say` or `generate_reply`\n */\n userInitiated: boolean;\n /**\n * Source indicating how the speech handle was created\n */\n source: SpeechSource;\n /**\n * The speech handle that was created\n */\n // TODO(shubhra): we need to make sure this doesn't get serialized\n speechHandle: SpeechHandle;\n /**\n * The timestamp when the speech handle was created\n */\n createdAt: number;\n};\n\nexport const createSpeechCreatedEvent = ({\n userInitiated,\n source,\n speechHandle,\n createdAt = Date.now(),\n}: {\n userInitiated: boolean;\n source: SpeechSource;\n speechHandle: SpeechHandle;\n createdAt?: number;\n}): SpeechCreatedEvent => ({\n type: 'speech_created',\n userInitiated,\n source,\n speechHandle,\n createdAt,\n});\n\nexport type ErrorEvent = {\n type: 'error';\n error: RealtimeModelError | STTError | TTSError | LLMError | InterruptionDetectionError | unknown;\n source: LLM | STT | TTS | RealtimeModel | unknown;\n createdAt: number;\n};\n\nexport const createErrorEvent = (\n error: RealtimeModelError | STTError | TTSError | LLMError | InterruptionDetectionError | unknown,\n source: LLM | STT | TTS | RealtimeModel | unknown,\n createdAt: number = Date.now(),\n): ErrorEvent => ({\n type: 'error',\n error,\n source,\n createdAt,\n});\n\nexport type CloseEvent = {\n type: 'close';\n error: RealtimeModelError | STTError | TTSError | LLMError | InterruptionDetectionError | null;\n reason: ShutdownReason;\n createdAt: number;\n};\n\nexport const createCloseEvent = (\n reason: ShutdownReason,\n error:\n | RealtimeModelError\n | STTError\n | TTSError\n | LLMError\n | InterruptionDetectionError\n | null = null,\n createdAt: number = Date.now(),\n): CloseEvent => ({\n type: 'close',\n error,\n reason,\n createdAt,\n});\n\nexport type AgentEvent =\n | UserInputTranscribedEvent\n | UserStateChangedEvent\n | AgentStateChangedEvent\n | MetricsCollectedEvent\n | SessionUsageUpdatedEvent\n | ConversationItemAddedEvent\n | FunctionToolsExecutedEvent\n | SpeechCreatedEvent\n | OverlappingSpeechEvent\n | ErrorEvent\n | CloseEvent;\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAuBO,IAAK,yBAAL,kBAAKA,4BAAL;AACL,EAAAA,wBAAA,0BAAuB;AACvB,EAAAA,wBAAA,uBAAoB;AACpB,EAAAA,wBAAA,sBAAmB;AACnB,EAAAA,wBAAA,2BAAwB;AACxB,EAAAA,wBAAA,2BAAwB;AACxB,EAAAA,wBAAA,sBAAmB;AACnB,EAAAA,wBAAA,yBAAsB;AACtB,EAAAA,wBAAA,mBAAgB;AAChB,EAAAA,wBAAA,uBAAoB;AACpB,EAAAA,wBAAA,WAAQ;AACR,EAAAA,wBAAA,WAAQ;AAXE,SAAAA;AAAA,GAAA;AAiBL,IAAK,cAAL,kBAAKC,iBAAL;AACL,EAAAA,aAAA,WAAQ;AACR,EAAAA,aAAA,kBAAe;AACf,EAAAA,aAAA,8BAA2B;AAC3B,EAAAA,aAAA,oBAAiB;AAJP,SAAAA;AAAA,GAAA;AAkBL,MAAM,8BAA8B,CACzC,UACA,UACA,YAAoB,KAAK,IAAI,OACF;AAAA,EAC3B,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AACF;AASO,MAAM,+BAA+B,CAC1C,UACA,UACA,YAAoB,KAAK,IAAI,OACD;AAAA,EAC5B,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AACF;AAaO,MAAM,kCAAkC,CAAC;AAAA,EAC9C;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,YAAY,KAAK,IAAI;AACvB,OAMkC;AAAA,EAChC,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAQO,MAAM,8BAA8B,CAAC;AAAA,EAC1C;AAAA,EACA,YAAY,KAAK,IAAI;AACvB,OAG8B;AAAA,EAC5B,MAAM;AAAA,EACN;AAAA,EACA;AACF;AAQO,MAAM,iCAAiC,CAAC;AAAA,EAC7C;AAAA,EACA,YAAY,KAAK,IAAI;AACvB,OAGiC;AAAA,EAC/B,MAAM;AAAA,EACN;AAAA,EACA;AACF;AAQO,MAAM,mCAAmC,CAC9C,MACA,YAAoB,KAAK,IAAI,OACG;AAAA,EAChC,MAAM;AAAA,EACN;AAAA,EACA;AACF;AASO,MAAM,mCAAmC,CAAC;AAAA,EAC/C;AAAA,EACA;AAAA,EACA,YAAY,KAAK,IAAI;AACvB,MAIkC;AAChC,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEO,MAAM,6BAA6B,CACxC,UAC8C;AAC9C,SAAO,MAAM,cAAc,IAAI,CAAC,MAAM,UAAU,CAAC,MAAM,MAAM,oBAAoB,KAAK,CAAE,CAAC;AAC3F;AAuBO,MAAM,2BAA2B,CAAC;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY,KAAK,IAAI;AACvB,OAK2B;AAAA,EACzB,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AASO,MAAM,mBAAmB,CAC9B,OACA,QACA,YAAoB,KAAK,IAAI,OACb;AAAA,EAChB,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AACF;AASO,MAAM,mBAAmB,CAC9B,QACA,QAMW,MACX,YAAoB,KAAK,IAAI,OACb;AAAA,EAChB,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AACF;","names":["AgentSessionEventTypes","CloseReason"]}
@@ -8,6 +8,7 @@ import type { STT } from '../stt/index.js';
8
8
  import type { STTError } from '../stt/stt.js';
9
9
  import type { TTS } from '../tts/index.js';
10
10
  import type { TTSError } from '../tts/tts.js';
11
+ import type { AgentSessionUsage } from './agent_session.js';
11
12
  import type { SpeechHandle } from './speech_handle.js';
12
13
  export declare enum AgentSessionEventTypes {
13
14
  UserInputTranscribed = "user_input_transcribed",
@@ -16,6 +17,7 @@ export declare enum AgentSessionEventTypes {
16
17
  ConversationItemAdded = "conversation_item_added",
17
18
  FunctionToolsExecuted = "function_tools_executed",
18
19
  MetricsCollected = "metrics_collected",
20
+ SessionUsageUpdated = "session_usage_updated",
19
21
  SpeechCreated = "speech_created",
20
22
  OverlappingSpeech = "overlapping_speech",
21
23
  Error = "error",
@@ -70,6 +72,15 @@ export declare const createMetricsCollectedEvent: ({ metrics, createdAt, }: {
70
72
  metrics: AgentMetrics;
71
73
  createdAt?: number;
72
74
  }) => MetricsCollectedEvent;
75
+ export type SessionUsageUpdatedEvent = {
76
+ type: 'session_usage_updated';
77
+ usage: AgentSessionUsage;
78
+ createdAt: number;
79
+ };
80
+ export declare const createSessionUsageUpdatedEvent: ({ usage, createdAt, }: {
81
+ usage: AgentSessionUsage;
82
+ createdAt?: number;
83
+ }) => SessionUsageUpdatedEvent;
73
84
  export type ConversationItemAddedEvent = {
74
85
  type: 'conversation_item_added';
75
86
  item: ChatMessage;
@@ -127,5 +138,5 @@ export type CloseEvent = {
127
138
  createdAt: number;
128
139
  };
129
140
  export declare const createCloseEvent: (reason: ShutdownReason, error?: RealtimeModelError | STTError | TTSError | LLMError | InterruptionDetectionError | null, createdAt?: number) => CloseEvent;
130
- export type AgentEvent = UserInputTranscribedEvent | UserStateChangedEvent | AgentStateChangedEvent | MetricsCollectedEvent | ConversationItemAddedEvent | FunctionToolsExecutedEvent | SpeechCreatedEvent | OverlappingSpeechEvent | ErrorEvent | CloseEvent;
141
+ export type AgentEvent = UserInputTranscribedEvent | UserStateChangedEvent | AgentStateChangedEvent | MetricsCollectedEvent | SessionUsageUpdatedEvent | ConversationItemAddedEvent | FunctionToolsExecutedEvent | SpeechCreatedEvent | OverlappingSpeechEvent | ErrorEvent | CloseEvent;
131
142
  //# sourceMappingURL=events.d.ts.map
@@ -8,6 +8,7 @@ import type { STT } from '../stt/index.js';
8
8
  import type { STTError } from '../stt/stt.js';
9
9
  import type { TTS } from '../tts/index.js';
10
10
  import type { TTSError } from '../tts/tts.js';
11
+ import type { AgentSessionUsage } from './agent_session.js';
11
12
  import type { SpeechHandle } from './speech_handle.js';
12
13
  export declare enum AgentSessionEventTypes {
13
14
  UserInputTranscribed = "user_input_transcribed",
@@ -16,6 +17,7 @@ export declare enum AgentSessionEventTypes {
16
17
  ConversationItemAdded = "conversation_item_added",
17
18
  FunctionToolsExecuted = "function_tools_executed",
18
19
  MetricsCollected = "metrics_collected",
20
+ SessionUsageUpdated = "session_usage_updated",
19
21
  SpeechCreated = "speech_created",
20
22
  OverlappingSpeech = "overlapping_speech",
21
23
  Error = "error",
@@ -70,6 +72,15 @@ export declare const createMetricsCollectedEvent: ({ metrics, createdAt, }: {
70
72
  metrics: AgentMetrics;
71
73
  createdAt?: number;
72
74
  }) => MetricsCollectedEvent;
75
+ export type SessionUsageUpdatedEvent = {
76
+ type: 'session_usage_updated';
77
+ usage: AgentSessionUsage;
78
+ createdAt: number;
79
+ };
80
+ export declare const createSessionUsageUpdatedEvent: ({ usage, createdAt, }: {
81
+ usage: AgentSessionUsage;
82
+ createdAt?: number;
83
+ }) => SessionUsageUpdatedEvent;
73
84
  export type ConversationItemAddedEvent = {
74
85
  type: 'conversation_item_added';
75
86
  item: ChatMessage;
@@ -127,5 +138,5 @@ export type CloseEvent = {
127
138
  createdAt: number;
128
139
  };
129
140
  export declare const createCloseEvent: (reason: ShutdownReason, error?: RealtimeModelError | STTError | TTSError | LLMError | InterruptionDetectionError | null, createdAt?: number) => CloseEvent;
130
- export type AgentEvent = UserInputTranscribedEvent | UserStateChangedEvent | AgentStateChangedEvent | MetricsCollectedEvent | ConversationItemAddedEvent | FunctionToolsExecutedEvent | SpeechCreatedEvent | OverlappingSpeechEvent | ErrorEvent | CloseEvent;
141
+ export type AgentEvent = UserInputTranscribedEvent | UserStateChangedEvent | AgentStateChangedEvent | MetricsCollectedEvent | SessionUsageUpdatedEvent | ConversationItemAddedEvent | FunctionToolsExecutedEvent | SpeechCreatedEvent | OverlappingSpeechEvent | ErrorEvent | CloseEvent;
131
142
  //# sourceMappingURL=events.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/voice/events.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/voice/events.ts"],"names":[],"mappings":"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"}
@@ -5,6 +5,7 @@ var AgentSessionEventTypes = /* @__PURE__ */ ((AgentSessionEventTypes2) => {
5
5
  AgentSessionEventTypes2["ConversationItemAdded"] = "conversation_item_added";
6
6
  AgentSessionEventTypes2["FunctionToolsExecuted"] = "function_tools_executed";
7
7
  AgentSessionEventTypes2["MetricsCollected"] = "metrics_collected";
8
+ AgentSessionEventTypes2["SessionUsageUpdated"] = "session_usage_updated";
8
9
  AgentSessionEventTypes2["SpeechCreated"] = "speech_created";
9
10
  AgentSessionEventTypes2["OverlappingSpeech"] = "overlapping_speech";
10
11
  AgentSessionEventTypes2["Error"] = "error";
@@ -52,6 +53,14 @@ const createMetricsCollectedEvent = ({
52
53
  metrics,
53
54
  createdAt
54
55
  });
56
+ const createSessionUsageUpdatedEvent = ({
57
+ usage,
58
+ createdAt = Date.now()
59
+ }) => ({
60
+ type: "session_usage_updated",
61
+ usage,
62
+ createdAt
63
+ });
55
64
  const createConversationItemAddedEvent = (item, createdAt = Date.now()) => ({
56
65
  type: "conversation_item_added",
57
66
  item,
@@ -105,6 +114,7 @@ export {
105
114
  createErrorEvent,
106
115
  createFunctionToolsExecutedEvent,
107
116
  createMetricsCollectedEvent,
117
+ createSessionUsageUpdatedEvent,
108
118
  createSpeechCreatedEvent,
109
119
  createUserInputTranscribedEvent,
110
120
  createUserStateChangedEvent,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/voice/events.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { InterruptionDetectionError } from '../inference/interruption/errors.js';\nimport type { OverlappingSpeechEvent } from '../inference/interruption/types.js';\nimport type { LanguageCode } from '../language.js';\nimport type {\n ChatMessage,\n FunctionCall,\n FunctionCallOutput,\n LLM,\n RealtimeModel,\n RealtimeModelError,\n} from '../llm/index.js';\nimport type { LLMError } from '../llm/llm.js';\nimport type { AgentMetrics } from '../metrics/base.js';\nimport type { STT } from '../stt/index.js';\nimport type { STTError } from '../stt/stt.js';\nimport type { TTS } from '../tts/index.js';\nimport type { TTSError } from '../tts/tts.js';\nimport type { SpeechHandle } from './speech_handle.js';\n\nexport enum AgentSessionEventTypes {\n UserInputTranscribed = 'user_input_transcribed',\n AgentStateChanged = 'agent_state_changed',\n UserStateChanged = 'user_state_changed',\n ConversationItemAdded = 'conversation_item_added',\n FunctionToolsExecuted = 'function_tools_executed',\n MetricsCollected = 'metrics_collected',\n SpeechCreated = 'speech_created',\n OverlappingSpeech = 'overlapping_speech',\n Error = 'error',\n Close = 'close',\n}\n\nexport type UserState = 'speaking' | 'listening' | 'away';\nexport type AgentState = 'initializing' | 'idle' | 'listening' | 'thinking' | 'speaking';\n\nexport enum CloseReason {\n ERROR = 'error',\n JOB_SHUTDOWN = 'job_shutdown',\n PARTICIPANT_DISCONNECTED = 'participant_disconnected',\n USER_INITIATED = 'user_initiated',\n}\n\nexport type ShutdownReason = CloseReason | string;\n\nexport type SpeechSource = 'say' | 'generate_reply' | 'tool_response';\n\nexport type UserStateChangedEvent = {\n type: 'user_state_changed';\n oldState: UserState;\n newState: UserState;\n createdAt: number;\n};\n\nexport const createUserStateChangedEvent = (\n oldState: UserState,\n newState: UserState,\n createdAt: number = Date.now(),\n): UserStateChangedEvent => ({\n type: 'user_state_changed',\n oldState,\n newState,\n createdAt,\n});\n\nexport type AgentStateChangedEvent = {\n type: 'agent_state_changed';\n oldState: AgentState;\n newState: AgentState;\n createdAt: number;\n};\n\nexport const createAgentStateChangedEvent = (\n oldState: AgentState,\n newState: AgentState,\n createdAt: number = Date.now(),\n): AgentStateChangedEvent => ({\n type: 'agent_state_changed',\n oldState,\n newState,\n createdAt,\n});\n\nexport type UserInputTranscribedEvent = {\n type: 'user_input_transcribed';\n transcript: string;\n isFinal: boolean;\n // TODO(AJS-106): add multi participant support\n /** Not supported yet. Always null by default. */\n speakerId: string | null;\n createdAt: number;\n language: LanguageCode | null;\n};\n\nexport const createUserInputTranscribedEvent = ({\n transcript,\n isFinal,\n speakerId = null,\n language = null,\n createdAt = Date.now(),\n}: {\n transcript: string;\n isFinal: boolean;\n speakerId?: string | null;\n language?: LanguageCode | null;\n createdAt?: number;\n}): UserInputTranscribedEvent => ({\n type: 'user_input_transcribed',\n transcript,\n isFinal,\n speakerId,\n language,\n createdAt,\n});\n\nexport type MetricsCollectedEvent = {\n type: 'metrics_collected';\n metrics: AgentMetrics;\n createdAt: number;\n};\n\nexport const createMetricsCollectedEvent = ({\n metrics,\n createdAt = Date.now(),\n}: {\n metrics: AgentMetrics;\n createdAt?: number;\n}): MetricsCollectedEvent => ({\n type: 'metrics_collected',\n metrics,\n createdAt,\n});\n\nexport type ConversationItemAddedEvent = {\n type: 'conversation_item_added';\n item: ChatMessage;\n createdAt: number;\n};\n\nexport const createConversationItemAddedEvent = (\n item: ChatMessage,\n createdAt: number = Date.now(),\n): ConversationItemAddedEvent => ({\n type: 'conversation_item_added',\n item,\n createdAt,\n});\n\nexport type FunctionToolsExecutedEvent = {\n type: 'function_tools_executed';\n functionCalls: FunctionCall[];\n functionCallOutputs: FunctionCallOutput[];\n createdAt: number;\n};\n\nexport const createFunctionToolsExecutedEvent = ({\n functionCalls,\n functionCallOutputs,\n createdAt = Date.now(),\n}: {\n functionCalls: FunctionCall[];\n functionCallOutputs: FunctionCallOutput[];\n createdAt?: number;\n}): FunctionToolsExecutedEvent => {\n return {\n type: 'function_tools_executed',\n functionCalls,\n functionCallOutputs,\n createdAt,\n };\n};\n\nexport const zipFunctionCallsAndOutputs = (\n event: FunctionToolsExecutedEvent,\n): Array<[FunctionCall, FunctionCallOutput]> => {\n return event.functionCalls.map((call, index) => [call, event.functionCallOutputs[index]!]);\n};\n\nexport type SpeechCreatedEvent = {\n type: 'speech_created';\n /**\n * True if the speech was created using public methods like `say` or `generate_reply`\n */\n userInitiated: boolean;\n /**\n * Source indicating how the speech handle was created\n */\n source: SpeechSource;\n /**\n * The speech handle that was created\n */\n // TODO(shubhra): we need to make sure this doesn't get serialized\n speechHandle: SpeechHandle;\n /**\n * The timestamp when the speech handle was created\n */\n createdAt: number;\n};\n\nexport const createSpeechCreatedEvent = ({\n userInitiated,\n source,\n speechHandle,\n createdAt = Date.now(),\n}: {\n userInitiated: boolean;\n source: SpeechSource;\n speechHandle: SpeechHandle;\n createdAt?: number;\n}): SpeechCreatedEvent => ({\n type: 'speech_created',\n userInitiated,\n source,\n speechHandle,\n createdAt,\n});\n\nexport type ErrorEvent = {\n type: 'error';\n error: RealtimeModelError | STTError | TTSError | LLMError | InterruptionDetectionError | unknown;\n source: LLM | STT | TTS | RealtimeModel | unknown;\n createdAt: number;\n};\n\nexport const createErrorEvent = (\n error: RealtimeModelError | STTError | TTSError | LLMError | InterruptionDetectionError | unknown,\n source: LLM | STT | TTS | RealtimeModel | unknown,\n createdAt: number = Date.now(),\n): ErrorEvent => ({\n type: 'error',\n error,\n source,\n createdAt,\n});\n\nexport type CloseEvent = {\n type: 'close';\n error: RealtimeModelError | STTError | TTSError | LLMError | InterruptionDetectionError | null;\n reason: ShutdownReason;\n createdAt: number;\n};\n\nexport const createCloseEvent = (\n reason: ShutdownReason,\n error:\n | RealtimeModelError\n | STTError\n | TTSError\n | LLMError\n | InterruptionDetectionError\n | null = null,\n createdAt: number = Date.now(),\n): CloseEvent => ({\n type: 'close',\n error,\n reason,\n createdAt,\n});\n\nexport type AgentEvent =\n | UserInputTranscribedEvent\n | UserStateChangedEvent\n | AgentStateChangedEvent\n | MetricsCollectedEvent\n | ConversationItemAddedEvent\n | FunctionToolsExecutedEvent\n | SpeechCreatedEvent\n | OverlappingSpeechEvent\n | ErrorEvent\n | CloseEvent;\n"],"mappings":"AAsBO,IAAK,yBAAL,kBAAKA,4BAAL;AACL,EAAAA,wBAAA,0BAAuB;AACvB,EAAAA,wBAAA,uBAAoB;AACpB,EAAAA,wBAAA,sBAAmB;AACnB,EAAAA,wBAAA,2BAAwB;AACxB,EAAAA,wBAAA,2BAAwB;AACxB,EAAAA,wBAAA,sBAAmB;AACnB,EAAAA,wBAAA,mBAAgB;AAChB,EAAAA,wBAAA,uBAAoB;AACpB,EAAAA,wBAAA,WAAQ;AACR,EAAAA,wBAAA,WAAQ;AAVE,SAAAA;AAAA,GAAA;AAgBL,IAAK,cAAL,kBAAKC,iBAAL;AACL,EAAAA,aAAA,WAAQ;AACR,EAAAA,aAAA,kBAAe;AACf,EAAAA,aAAA,8BAA2B;AAC3B,EAAAA,aAAA,oBAAiB;AAJP,SAAAA;AAAA,GAAA;AAkBL,MAAM,8BAA8B,CACzC,UACA,UACA,YAAoB,KAAK,IAAI,OACF;AAAA,EAC3B,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AACF;AASO,MAAM,+BAA+B,CAC1C,UACA,UACA,YAAoB,KAAK,IAAI,OACD;AAAA,EAC5B,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AACF;AAaO,MAAM,kCAAkC,CAAC;AAAA,EAC9C;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,YAAY,KAAK,IAAI;AACvB,OAMkC;AAAA,EAChC,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAQO,MAAM,8BAA8B,CAAC;AAAA,EAC1C;AAAA,EACA,YAAY,KAAK,IAAI;AACvB,OAG8B;AAAA,EAC5B,MAAM;AAAA,EACN;AAAA,EACA;AACF;AAQO,MAAM,mCAAmC,CAC9C,MACA,YAAoB,KAAK,IAAI,OACG;AAAA,EAChC,MAAM;AAAA,EACN;AAAA,EACA;AACF;AASO,MAAM,mCAAmC,CAAC;AAAA,EAC/C;AAAA,EACA;AAAA,EACA,YAAY,KAAK,IAAI;AACvB,MAIkC;AAChC,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEO,MAAM,6BAA6B,CACxC,UAC8C;AAC9C,SAAO,MAAM,cAAc,IAAI,CAAC,MAAM,UAAU,CAAC,MAAM,MAAM,oBAAoB,KAAK,CAAE,CAAC;AAC3F;AAuBO,MAAM,2BAA2B,CAAC;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY,KAAK,IAAI;AACvB,OAK2B;AAAA,EACzB,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AASO,MAAM,mBAAmB,CAC9B,OACA,QACA,YAAoB,KAAK,IAAI,OACb;AAAA,EAChB,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AACF;AASO,MAAM,mBAAmB,CAC9B,QACA,QAMW,MACX,YAAoB,KAAK,IAAI,OACb;AAAA,EAChB,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AACF;","names":["AgentSessionEventTypes","CloseReason"]}
1
+ {"version":3,"sources":["../../src/voice/events.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { InterruptionDetectionError } from '../inference/interruption/errors.js';\nimport type { OverlappingSpeechEvent } from '../inference/interruption/types.js';\nimport type { LanguageCode } from '../language.js';\nimport type {\n ChatMessage,\n FunctionCall,\n FunctionCallOutput,\n LLM,\n RealtimeModel,\n RealtimeModelError,\n} from '../llm/index.js';\nimport type { LLMError } from '../llm/llm.js';\nimport type { AgentMetrics } from '../metrics/base.js';\nimport type { STT } from '../stt/index.js';\nimport type { STTError } from '../stt/stt.js';\nimport type { TTS } from '../tts/index.js';\nimport type { TTSError } from '../tts/tts.js';\nimport type { AgentSessionUsage } from './agent_session.js';\nimport type { SpeechHandle } from './speech_handle.js';\n\nexport enum AgentSessionEventTypes {\n UserInputTranscribed = 'user_input_transcribed',\n AgentStateChanged = 'agent_state_changed',\n UserStateChanged = 'user_state_changed',\n ConversationItemAdded = 'conversation_item_added',\n FunctionToolsExecuted = 'function_tools_executed',\n MetricsCollected = 'metrics_collected',\n SessionUsageUpdated = 'session_usage_updated',\n SpeechCreated = 'speech_created',\n OverlappingSpeech = 'overlapping_speech',\n Error = 'error',\n Close = 'close',\n}\n\nexport type UserState = 'speaking' | 'listening' | 'away';\nexport type AgentState = 'initializing' | 'idle' | 'listening' | 'thinking' | 'speaking';\n\nexport enum CloseReason {\n ERROR = 'error',\n JOB_SHUTDOWN = 'job_shutdown',\n PARTICIPANT_DISCONNECTED = 'participant_disconnected',\n USER_INITIATED = 'user_initiated',\n}\n\nexport type ShutdownReason = CloseReason | string;\n\nexport type SpeechSource = 'say' | 'generate_reply' | 'tool_response';\n\nexport type UserStateChangedEvent = {\n type: 'user_state_changed';\n oldState: UserState;\n newState: UserState;\n createdAt: number;\n};\n\nexport const createUserStateChangedEvent = (\n oldState: UserState,\n newState: UserState,\n createdAt: number = Date.now(),\n): UserStateChangedEvent => ({\n type: 'user_state_changed',\n oldState,\n newState,\n createdAt,\n});\n\nexport type AgentStateChangedEvent = {\n type: 'agent_state_changed';\n oldState: AgentState;\n newState: AgentState;\n createdAt: number;\n};\n\nexport const createAgentStateChangedEvent = (\n oldState: AgentState,\n newState: AgentState,\n createdAt: number = Date.now(),\n): AgentStateChangedEvent => ({\n type: 'agent_state_changed',\n oldState,\n newState,\n createdAt,\n});\n\nexport type UserInputTranscribedEvent = {\n type: 'user_input_transcribed';\n transcript: string;\n isFinal: boolean;\n // TODO(AJS-106): add multi participant support\n /** Not supported yet. Always null by default. */\n speakerId: string | null;\n createdAt: number;\n language: LanguageCode | null;\n};\n\nexport const createUserInputTranscribedEvent = ({\n transcript,\n isFinal,\n speakerId = null,\n language = null,\n createdAt = Date.now(),\n}: {\n transcript: string;\n isFinal: boolean;\n speakerId?: string | null;\n language?: LanguageCode | null;\n createdAt?: number;\n}): UserInputTranscribedEvent => ({\n type: 'user_input_transcribed',\n transcript,\n isFinal,\n speakerId,\n language,\n createdAt,\n});\n\nexport type MetricsCollectedEvent = {\n type: 'metrics_collected';\n metrics: AgentMetrics;\n createdAt: number;\n};\n\nexport const createMetricsCollectedEvent = ({\n metrics,\n createdAt = Date.now(),\n}: {\n metrics: AgentMetrics;\n createdAt?: number;\n}): MetricsCollectedEvent => ({\n type: 'metrics_collected',\n metrics,\n createdAt,\n});\n\nexport type SessionUsageUpdatedEvent = {\n type: 'session_usage_updated';\n usage: AgentSessionUsage;\n createdAt: number;\n};\n\nexport const createSessionUsageUpdatedEvent = ({\n usage,\n createdAt = Date.now(),\n}: {\n usage: AgentSessionUsage;\n createdAt?: number;\n}): SessionUsageUpdatedEvent => ({\n type: 'session_usage_updated',\n usage,\n createdAt,\n});\n\nexport type ConversationItemAddedEvent = {\n type: 'conversation_item_added';\n item: ChatMessage;\n createdAt: number;\n};\n\nexport const createConversationItemAddedEvent = (\n item: ChatMessage,\n createdAt: number = Date.now(),\n): ConversationItemAddedEvent => ({\n type: 'conversation_item_added',\n item,\n createdAt,\n});\n\nexport type FunctionToolsExecutedEvent = {\n type: 'function_tools_executed';\n functionCalls: FunctionCall[];\n functionCallOutputs: FunctionCallOutput[];\n createdAt: number;\n};\n\nexport const createFunctionToolsExecutedEvent = ({\n functionCalls,\n functionCallOutputs,\n createdAt = Date.now(),\n}: {\n functionCalls: FunctionCall[];\n functionCallOutputs: FunctionCallOutput[];\n createdAt?: number;\n}): FunctionToolsExecutedEvent => {\n return {\n type: 'function_tools_executed',\n functionCalls,\n functionCallOutputs,\n createdAt,\n };\n};\n\nexport const zipFunctionCallsAndOutputs = (\n event: FunctionToolsExecutedEvent,\n): Array<[FunctionCall, FunctionCallOutput]> => {\n return event.functionCalls.map((call, index) => [call, event.functionCallOutputs[index]!]);\n};\n\nexport type SpeechCreatedEvent = {\n type: 'speech_created';\n /**\n * True if the speech was created using public methods like `say` or `generate_reply`\n */\n userInitiated: boolean;\n /**\n * Source indicating how the speech handle was created\n */\n source: SpeechSource;\n /**\n * The speech handle that was created\n */\n // TODO(shubhra): we need to make sure this doesn't get serialized\n speechHandle: SpeechHandle;\n /**\n * The timestamp when the speech handle was created\n */\n createdAt: number;\n};\n\nexport const createSpeechCreatedEvent = ({\n userInitiated,\n source,\n speechHandle,\n createdAt = Date.now(),\n}: {\n userInitiated: boolean;\n source: SpeechSource;\n speechHandle: SpeechHandle;\n createdAt?: number;\n}): SpeechCreatedEvent => ({\n type: 'speech_created',\n userInitiated,\n source,\n speechHandle,\n createdAt,\n});\n\nexport type ErrorEvent = {\n type: 'error';\n error: RealtimeModelError | STTError | TTSError | LLMError | InterruptionDetectionError | unknown;\n source: LLM | STT | TTS | RealtimeModel | unknown;\n createdAt: number;\n};\n\nexport const createErrorEvent = (\n error: RealtimeModelError | STTError | TTSError | LLMError | InterruptionDetectionError | unknown,\n source: LLM | STT | TTS | RealtimeModel | unknown,\n createdAt: number = Date.now(),\n): ErrorEvent => ({\n type: 'error',\n error,\n source,\n createdAt,\n});\n\nexport type CloseEvent = {\n type: 'close';\n error: RealtimeModelError | STTError | TTSError | LLMError | InterruptionDetectionError | null;\n reason: ShutdownReason;\n createdAt: number;\n};\n\nexport const createCloseEvent = (\n reason: ShutdownReason,\n error:\n | RealtimeModelError\n | STTError\n | TTSError\n | LLMError\n | InterruptionDetectionError\n | null = null,\n createdAt: number = Date.now(),\n): CloseEvent => ({\n type: 'close',\n error,\n reason,\n createdAt,\n});\n\nexport type AgentEvent =\n | UserInputTranscribedEvent\n | UserStateChangedEvent\n | AgentStateChangedEvent\n | MetricsCollectedEvent\n | SessionUsageUpdatedEvent\n | ConversationItemAddedEvent\n | FunctionToolsExecutedEvent\n | SpeechCreatedEvent\n | OverlappingSpeechEvent\n | ErrorEvent\n | CloseEvent;\n"],"mappings":"AAuBO,IAAK,yBAAL,kBAAKA,4BAAL;AACL,EAAAA,wBAAA,0BAAuB;AACvB,EAAAA,wBAAA,uBAAoB;AACpB,EAAAA,wBAAA,sBAAmB;AACnB,EAAAA,wBAAA,2BAAwB;AACxB,EAAAA,wBAAA,2BAAwB;AACxB,EAAAA,wBAAA,sBAAmB;AACnB,EAAAA,wBAAA,yBAAsB;AACtB,EAAAA,wBAAA,mBAAgB;AAChB,EAAAA,wBAAA,uBAAoB;AACpB,EAAAA,wBAAA,WAAQ;AACR,EAAAA,wBAAA,WAAQ;AAXE,SAAAA;AAAA,GAAA;AAiBL,IAAK,cAAL,kBAAKC,iBAAL;AACL,EAAAA,aAAA,WAAQ;AACR,EAAAA,aAAA,kBAAe;AACf,EAAAA,aAAA,8BAA2B;AAC3B,EAAAA,aAAA,oBAAiB;AAJP,SAAAA;AAAA,GAAA;AAkBL,MAAM,8BAA8B,CACzC,UACA,UACA,YAAoB,KAAK,IAAI,OACF;AAAA,EAC3B,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AACF;AASO,MAAM,+BAA+B,CAC1C,UACA,UACA,YAAoB,KAAK,IAAI,OACD;AAAA,EAC5B,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AACF;AAaO,MAAM,kCAAkC,CAAC;AAAA,EAC9C;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,YAAY,KAAK,IAAI;AACvB,OAMkC;AAAA,EAChC,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAQO,MAAM,8BAA8B,CAAC;AAAA,EAC1C;AAAA,EACA,YAAY,KAAK,IAAI;AACvB,OAG8B;AAAA,EAC5B,MAAM;AAAA,EACN;AAAA,EACA;AACF;AAQO,MAAM,iCAAiC,CAAC;AAAA,EAC7C;AAAA,EACA,YAAY,KAAK,IAAI;AACvB,OAGiC;AAAA,EAC/B,MAAM;AAAA,EACN;AAAA,EACA;AACF;AAQO,MAAM,mCAAmC,CAC9C,MACA,YAAoB,KAAK,IAAI,OACG;AAAA,EAChC,MAAM;AAAA,EACN;AAAA,EACA;AACF;AASO,MAAM,mCAAmC,CAAC;AAAA,EAC/C;AAAA,EACA;AAAA,EACA,YAAY,KAAK,IAAI;AACvB,MAIkC;AAChC,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEO,MAAM,6BAA6B,CACxC,UAC8C;AAC9C,SAAO,MAAM,cAAc,IAAI,CAAC,MAAM,UAAU,CAAC,MAAM,MAAM,oBAAoB,KAAK,CAAE,CAAC;AAC3F;AAuBO,MAAM,2BAA2B,CAAC;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY,KAAK,IAAI;AACvB,OAK2B;AAAA,EACzB,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AASO,MAAM,mBAAmB,CAC9B,OACA,QACA,YAAoB,KAAK,IAAI,OACb;AAAA,EAChB,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AACF;AASO,MAAM,mBAAmB,CAC9B,QACA,QAMW,MACX,YAAoB,KAAK,IAAI,OACb;AAAA,EAChB,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AACF;","names":["AgentSessionEventTypes","CloseReason"]}
@@ -46,6 +46,7 @@ var import_utils = require("../utils.cjs");
46
46
  var import_agent = require("./agent.cjs");
47
47
  var import_io = require("./io.cjs");
48
48
  var import_run_context = require("./run_context.cjs");
49
+ const TTS_READ_IDLE_TIMEOUT_MS = 1e4;
49
50
  class _LLMGenerationData {
50
51
  constructor(textStream, toolCallStream) {
51
52
  this.textStream = textStream;
@@ -410,6 +411,7 @@ function performLLMInference(node, chatCtx, toolCtx, modelSettings, controller,
410
411
  ];
411
412
  }
412
413
  function performTTSInference(node, text, modelSettings, controller, model, provider) {
414
+ const logger = (0, import_log.log)();
413
415
  const audioStream = new import_identity_transform.IdentityTransform();
414
416
  const outputWriter = audioStream.writable.getWriter();
415
417
  const audioOutputStream = audioStream.readable;
@@ -471,7 +473,10 @@ function performTTSInference(node, text, modelSettings, controller, model, provi
471
473
  if (signal.aborted) {
472
474
  break;
473
475
  }
474
- const { done, value: frame } = await ttsStreamReader.read();
476
+ const { done, value: frame } = await (0, import_utils.waitUntilTimeout)(
477
+ ttsStreamReader.read(),
478
+ TTS_READ_IDLE_TIMEOUT_MS
479
+ );
475
480
  if (done) {
476
481
  break;
477
482
  }
@@ -499,10 +504,13 @@ function performTTSInference(node, text, modelSettings, controller, model, provi
499
504
  pushedDuration += frameDuration;
500
505
  }
501
506
  } catch (error) {
502
- if (error instanceof DOMException && error.name === "AbortError") {
507
+ if (error instanceof import_utils.IdleTimeoutError) {
508
+ logger.warn("TTS stream stalled after producing audio, forcing close");
509
+ } else if (error instanceof DOMException && error.name === "AbortError") {
503
510
  return;
511
+ } else {
512
+ throw error;
504
513
  }
505
- throw error;
506
514
  } finally {
507
515
  if (!timedTextsFut.done) {
508
516
  timedTextsFut.resolve(null);
@@ -564,8 +572,10 @@ function performTextForwarding(source, controller, textOutput) {
564
572
  ];
565
573
  }
566
574
  async function forwardAudio(ttsStream, audioOutput, out, signal) {
575
+ const logger = (0, import_log.log)();
567
576
  const reader = ttsStream.getReader();
568
577
  let resampler = null;
578
+ const FORWARD_AUDIO_IDLE_TIMEOUT_MS = 1e4;
569
579
  const onPlaybackStarted = (ev) => {
570
580
  if (!out.firstFrameFut.done) {
571
581
  out.firstFrameFut.resolve(ev.createdAt);
@@ -578,7 +588,10 @@ async function forwardAudio(ttsStream, audioOutput, out, signal) {
578
588
  if (signal == null ? void 0 : signal.aborted) {
579
589
  break;
580
590
  }
581
- const { done, value: frame } = await reader.read();
591
+ const { done, value: frame } = await (0, import_utils.waitUntilTimeout)(
592
+ reader.read(),
593
+ FORWARD_AUDIO_IDLE_TIMEOUT_MS
594
+ );
582
595
  if (done) break;
583
596
  out.audio.push(frame);
584
597
  if (!out.firstFrameFut.done && audioOutput.sampleRate && audioOutput.sampleRate !== frame.sampleRate && !resampler) {
@@ -597,6 +610,12 @@ async function forwardAudio(ttsStream, audioOutput, out, signal) {
597
610
  await audioOutput.captureFrame(f);
598
611
  }
599
612
  }
613
+ } catch (e) {
614
+ if (e instanceof import_utils.IdleTimeoutError) {
615
+ logger.warn("audio forwarding stalled waiting for TTS frames, forcing close");
616
+ } else {
617
+ throw e;
618
+ }
600
619
  } finally {
601
620
  audioOutput.off(import_io.AudioOutput.EVENT_PLAYBACK_STARTED, onPlaybackStarted);
602
621
  if (!out.firstFrameFut.done) {