@livekit/agents 1.0.47 → 1.0.49
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.
- package/dist/beta/index.cjs +29 -0
- package/dist/beta/index.cjs.map +1 -0
- package/dist/beta/index.d.cts +2 -0
- package/dist/beta/index.d.ts +2 -0
- package/dist/beta/index.d.ts.map +1 -0
- package/dist/beta/index.js +7 -0
- package/dist/beta/index.js.map +1 -0
- package/dist/beta/workflows/index.cjs +29 -0
- package/dist/beta/workflows/index.cjs.map +1 -0
- package/dist/beta/workflows/index.d.cts +2 -0
- package/dist/beta/workflows/index.d.ts +2 -0
- package/dist/beta/workflows/index.d.ts.map +1 -0
- package/dist/beta/workflows/index.js +7 -0
- package/dist/beta/workflows/index.js.map +1 -0
- package/dist/beta/workflows/task_group.cjs +162 -0
- package/dist/beta/workflows/task_group.cjs.map +1 -0
- package/dist/beta/workflows/task_group.d.cts +32 -0
- package/dist/beta/workflows/task_group.d.ts +32 -0
- package/dist/beta/workflows/task_group.d.ts.map +1 -0
- package/dist/beta/workflows/task_group.js +138 -0
- package/dist/beta/workflows/task_group.js.map +1 -0
- package/dist/cpu.cjs +189 -0
- package/dist/cpu.cjs.map +1 -0
- package/dist/cpu.d.cts +24 -0
- package/dist/cpu.d.ts +24 -0
- package/dist/cpu.d.ts.map +1 -0
- package/dist/cpu.js +152 -0
- package/dist/cpu.js.map +1 -0
- package/dist/cpu.test.cjs +227 -0
- package/dist/cpu.test.cjs.map +1 -0
- package/dist/cpu.test.js +204 -0
- package/dist/cpu.test.js.map +1 -0
- package/dist/index.cjs +3 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/inference/api_protos.d.cts +59 -59
- package/dist/inference/api_protos.d.ts +59 -59
- package/dist/inference/llm.cjs.map +1 -1
- package/dist/inference/llm.d.cts +1 -1
- package/dist/inference/llm.d.ts +1 -1
- package/dist/inference/llm.d.ts.map +1 -1
- package/dist/inference/llm.js.map +1 -1
- package/dist/inference/tts.cjs.map +1 -1
- package/dist/inference/tts.d.cts +6 -0
- package/dist/inference/tts.d.ts +6 -0
- package/dist/inference/tts.d.ts.map +1 -1
- package/dist/inference/tts.js.map +1 -1
- package/dist/llm/chat_context.cjs +89 -1
- package/dist/llm/chat_context.cjs.map +1 -1
- package/dist/llm/chat_context.d.cts +10 -1
- package/dist/llm/chat_context.d.ts +10 -1
- package/dist/llm/chat_context.d.ts.map +1 -1
- package/dist/llm/chat_context.js +89 -1
- package/dist/llm/chat_context.js.map +1 -1
- package/dist/llm/chat_context.test.cjs +43 -0
- package/dist/llm/chat_context.test.cjs.map +1 -1
- package/dist/llm/chat_context.test.js +43 -0
- package/dist/llm/chat_context.test.js.map +1 -1
- package/dist/llm/index.cjs +2 -0
- package/dist/llm/index.cjs.map +1 -1
- package/dist/llm/index.d.cts +1 -1
- package/dist/llm/index.d.ts +1 -1
- package/dist/llm/index.d.ts.map +1 -1
- package/dist/llm/index.js +3 -1
- package/dist/llm/index.js.map +1 -1
- package/dist/llm/provider_format/index.d.cts +1 -1
- package/dist/llm/provider_format/index.d.ts +1 -1
- package/dist/llm/tool_context.cjs +7 -0
- package/dist/llm/tool_context.cjs.map +1 -1
- package/dist/llm/tool_context.d.cts +10 -2
- package/dist/llm/tool_context.d.ts +10 -2
- package/dist/llm/tool_context.d.ts.map +1 -1
- package/dist/llm/tool_context.js +6 -0
- package/dist/llm/tool_context.js.map +1 -1
- package/dist/utils.cjs +1 -0
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +1 -0
- package/dist/utils.js.map +1 -1
- package/dist/version.cjs +1 -1
- package/dist/version.js +1 -1
- package/dist/voice/agent.cjs +9 -0
- package/dist/voice/agent.cjs.map +1 -1
- package/dist/voice/agent.d.cts +1 -0
- package/dist/voice/agent.d.ts +1 -0
- package/dist/voice/agent.d.ts.map +1 -1
- package/dist/voice/agent.js +9 -0
- package/dist/voice/agent.js.map +1 -1
- package/dist/voice/agent_activity.cjs +67 -16
- package/dist/voice/agent_activity.cjs.map +1 -1
- package/dist/voice/agent_activity.d.cts +7 -0
- package/dist/voice/agent_activity.d.ts +7 -0
- package/dist/voice/agent_activity.d.ts.map +1 -1
- package/dist/voice/agent_activity.js +68 -17
- package/dist/voice/agent_activity.js.map +1 -1
- package/dist/voice/agent_session.cjs +27 -1
- package/dist/voice/agent_session.cjs.map +1 -1
- package/dist/voice/agent_session.d.cts +6 -0
- package/dist/voice/agent_session.d.ts +6 -0
- package/dist/voice/agent_session.d.ts.map +1 -1
- package/dist/voice/agent_session.js +27 -1
- package/dist/voice/agent_session.js.map +1 -1
- package/dist/voice/room_io/room_io.cjs +11 -2
- package/dist/voice/room_io/room_io.cjs.map +1 -1
- package/dist/voice/room_io/room_io.d.ts.map +1 -1
- package/dist/voice/room_io/room_io.js +12 -3
- package/dist/voice/room_io/room_io.js.map +1 -1
- package/dist/voice/testing/fake_llm.cjs +127 -0
- package/dist/voice/testing/fake_llm.cjs.map +1 -0
- package/dist/voice/testing/fake_llm.d.cts +30 -0
- package/dist/voice/testing/fake_llm.d.ts +30 -0
- package/dist/voice/testing/fake_llm.d.ts.map +1 -0
- package/dist/voice/testing/fake_llm.js +103 -0
- package/dist/voice/testing/fake_llm.js.map +1 -0
- package/dist/voice/testing/index.cjs +3 -0
- package/dist/voice/testing/index.cjs.map +1 -1
- package/dist/voice/testing/index.d.cts +1 -0
- package/dist/voice/testing/index.d.ts +1 -0
- package/dist/voice/testing/index.d.ts.map +1 -1
- package/dist/voice/testing/index.js +2 -0
- package/dist/voice/testing/index.js.map +1 -1
- package/dist/worker.cjs +6 -29
- package/dist/worker.cjs.map +1 -1
- package/dist/worker.d.ts.map +1 -1
- package/dist/worker.js +6 -19
- package/dist/worker.js.map +1 -1
- package/package.json +1 -1
- package/src/beta/index.ts +9 -0
- package/src/beta/workflows/index.ts +9 -0
- package/src/beta/workflows/task_group.ts +194 -0
- package/src/cpu.test.ts +239 -0
- package/src/cpu.ts +173 -0
- package/src/index.ts +2 -1
- package/src/inference/llm.ts +2 -0
- package/src/inference/tts.ts +8 -1
- package/src/llm/chat_context.test.ts +48 -0
- package/src/llm/chat_context.ts +123 -0
- package/src/llm/index.ts +1 -0
- package/src/llm/tool_context.ts +14 -0
- package/src/utils.ts +5 -0
- package/src/voice/agent.ts +11 -0
- package/src/voice/agent_activity.ts +102 -16
- package/src/voice/agent_session.ts +33 -2
- package/src/voice/room_io/room_io.ts +14 -3
- package/src/voice/testing/fake_llm.ts +138 -0
- package/src/voice/testing/index.ts +2 -0
- package/src/worker.ts +34 -50
|
@@ -48,6 +48,7 @@ const defaultVoiceOptions = {
|
|
|
48
48
|
maxToolSteps: 3,
|
|
49
49
|
preemptiveGeneration: false,
|
|
50
50
|
userAwayTimeout: 15,
|
|
51
|
+
aecWarmupDuration: 3e3,
|
|
51
52
|
useTtsAlignedTranscript: true
|
|
52
53
|
};
|
|
53
54
|
class AgentSession extends import_node_events.EventEmitter {
|
|
@@ -74,6 +75,7 @@ class AgentSession extends import_node_events.EventEmitter {
|
|
|
74
75
|
_output;
|
|
75
76
|
closingTask = null;
|
|
76
77
|
userAwayTimer = null;
|
|
78
|
+
_aecWarmupTimer = null;
|
|
77
79
|
// Connection options for STT, LLM, and TTS
|
|
78
80
|
_connOptions;
|
|
79
81
|
// Unrecoverable error counts, reset after agent speaking
|
|
@@ -83,6 +85,8 @@ class AgentSession extends import_node_events.EventEmitter {
|
|
|
83
85
|
userSpeakingSpan;
|
|
84
86
|
agentSpeakingSpan;
|
|
85
87
|
/** @internal */
|
|
88
|
+
_aecWarmupRemaining = 0;
|
|
89
|
+
/** @internal */
|
|
86
90
|
_recorderIO;
|
|
87
91
|
/** @internal */
|
|
88
92
|
rootSpanContext;
|
|
@@ -134,6 +138,7 @@ class AgentSession extends import_node_events.EventEmitter {
|
|
|
134
138
|
this._output = new import_io.AgentOutput(this.onAudioOutputChanged, this.onTextOutputChanged);
|
|
135
139
|
this._chatCtx = import_chat_context.ChatContext.empty();
|
|
136
140
|
this.options = { ...defaultVoiceOptions, ...voiceOptions };
|
|
141
|
+
this._aecWarmupRemaining = this.options.aecWarmupDuration ?? 0;
|
|
137
142
|
this._onUserInputTranscribed = this._onUserInputTranscribed.bind(this);
|
|
138
143
|
this.on(import_events.AgentSessionEventTypes.UserInputTranscribed, this._onUserInputTranscribed);
|
|
139
144
|
}
|
|
@@ -526,7 +531,9 @@ class AgentSession extends import_node_events.EventEmitter {
|
|
|
526
531
|
if (this.closingTask) {
|
|
527
532
|
return;
|
|
528
533
|
}
|
|
529
|
-
this.closeImpl(reason, error, drain)
|
|
534
|
+
this.closingTask = this.closeImpl(reason, error, drain).finally(() => {
|
|
535
|
+
this.closingTask = null;
|
|
536
|
+
});
|
|
530
537
|
}
|
|
531
538
|
/** @internal */
|
|
532
539
|
_onError(error) {
|
|
@@ -584,6 +591,13 @@ class AgentSession extends import_node_events.EventEmitter {
|
|
|
584
591
|
this.agentSpeakingSpan.end();
|
|
585
592
|
this.agentSpeakingSpan = void 0;
|
|
586
593
|
}
|
|
594
|
+
if (state === "speaking" && this._aecWarmupRemaining > 0 && this._aecWarmupTimer === null) {
|
|
595
|
+
this._aecWarmupTimer = setTimeout(() => this._onAecWarmupExpired(), this._aecWarmupRemaining);
|
|
596
|
+
this.logger.debug(
|
|
597
|
+
{ warmupDurationMs: this._aecWarmupRemaining },
|
|
598
|
+
"aec warmup active, disabling interruptions"
|
|
599
|
+
);
|
|
600
|
+
}
|
|
587
601
|
const oldState = this._agentState;
|
|
588
602
|
this._agentState = state;
|
|
589
603
|
if (state === "listening" && this.userState === "listening") {
|
|
@@ -660,6 +674,17 @@ class AgentSession extends import_node_events.EventEmitter {
|
|
|
660
674
|
this.userAwayTimer = null;
|
|
661
675
|
}
|
|
662
676
|
}
|
|
677
|
+
/** @internal */
|
|
678
|
+
_onAecWarmupExpired() {
|
|
679
|
+
if (this._aecWarmupRemaining > 0) {
|
|
680
|
+
this.logger.debug("aec warmup expired, re-enabling interruptions");
|
|
681
|
+
}
|
|
682
|
+
this._aecWarmupRemaining = 0;
|
|
683
|
+
if (this._aecWarmupTimer !== null) {
|
|
684
|
+
clearTimeout(this._aecWarmupTimer);
|
|
685
|
+
this._aecWarmupTimer = null;
|
|
686
|
+
}
|
|
687
|
+
}
|
|
663
688
|
_onUserInputTranscribed(ev) {
|
|
664
689
|
if (this.userState === "away" && ev.isFinal) {
|
|
665
690
|
this.logger.debug("User returned from away state due to speech input");
|
|
@@ -680,6 +705,7 @@ class AgentSession extends import_node_events.EventEmitter {
|
|
|
680
705
|
return;
|
|
681
706
|
}
|
|
682
707
|
this._cancelUserAwayTimer();
|
|
708
|
+
this._onAecWarmupExpired();
|
|
683
709
|
this.off(import_events.AgentSessionEventTypes.UserInputTranscribed, this._onUserInputTranscribed);
|
|
684
710
|
if (this.activity) {
|
|
685
711
|
if (!drain) {
|
|
@@ -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 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 { 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 { RoomIO, type RoomInputOptions, type RoomOutputOptions } from './room_io/index.js';\nimport type { UnknownUserData } from './run_context.js';\nimport type { SpeechHandle } from './speech_handle.js';\nimport { RunResult } from './testing/run_result.js';\nimport { setParticipantSpanAttributes } from './utils.js';\n\nexport interface VoiceOptions {\n allowInterruptions: boolean;\n discardAudioIfUninterruptible: boolean;\n minInterruptionDuration: number;\n minInterruptionWords: number;\n minEndpointingDelay: number;\n maxEndpointingDelay: number;\n maxToolSteps: number;\n preemptiveGeneration: boolean;\n userAwayTimeout?: number | null;\n useTtsAlignedTranscript: boolean;\n}\n\nconst defaultVoiceOptions: VoiceOptions = {\n allowInterruptions: true,\n discardAudioIfUninterruptible: true,\n minInterruptionDuration: 500,\n minInterruptionWords: 0,\n minEndpointingDelay: 500,\n maxEndpointingDelay: 6000,\n maxToolSteps: 3,\n preemptiveGeneration: false,\n userAwayTimeout: 15.0,\n useTtsAlignedTranscript: true,\n} as const;\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};\n\nexport type AgentSessionOptions<UserData = UnknownUserData> = {\n turnDetection?: TurnDetectionMode;\n stt?: STT | STTModelString;\n vad?: VAD;\n llm?: LLM | RealtimeModel | LLMModels;\n tts?: TTS | TTSModelString;\n userData?: UserData;\n voiceOptions?: Partial<VoiceOptions>;\n connOptions?: SessionConnectOptions;\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 readonly options: VoiceOptions;\n\n private agent?: Agent;\n private activity?: AgentActivity;\n private nextActivity?: AgentActivity;\n private updateActivityTask?: Task<void>;\n private started = false;\n private userState: UserState = 'listening';\n private readonly activityLock = new Mutex();\n\n /** @internal */\n _roomIO?: RoomIO;\n private logger = log();\n\n private _chatCtx: ChatContext;\n private _userData: UserData | undefined;\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 // 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 userSpeakingSpan?: Span;\n private agentSpeakingSpan?: Span;\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 constructor(opts: AgentSessionOptions<UserData>) {\n super();\n\n const {\n vad,\n stt,\n llm,\n tts,\n turnDetection,\n userData,\n voiceOptions = defaultVoiceOptions,\n connOptions,\n } = opts;\n\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 = turnDetection;\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.options = { ...defaultVoiceOptions, ...voiceOptions };\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 useTtsAlignedTranscript(): boolean {\n return this.options.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 this._roomIO.start();\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 // 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 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 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.closeImpl(reason, error, drain);\n }\n\n /** @internal */\n _onError(error: RealtimeModelError | STTError | TTSError | LLMError): void {\n if (this.closingTask || error.recoverable) {\n return;\n }\n\n // Track error counts per type to implement max_unrecoverable_errors logic\n if (error.type === 'llm_error') {\n this.llmErrorCounts += 1;\n if (this.llmErrorCounts <= this._connOptions.maxUnrecoverableErrors) {\n return;\n }\n } else if (error.type === 'tts_error') {\n this.ttsErrorCounts += 1;\n if (this.ttsErrorCounts <= this._connOptions.maxUnrecoverableErrors) {\n return;\n }\n }\n\n this.logger.error(error, 'AgentSession is closing due to 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 // Reset error counts when agent starts 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 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(state: UserState, lastSpeakingTime?: number) {\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: this.rootSpanContext,\n startTime: 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(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 (this.options.userAwayTimeout === null || this.options.userAwayTimeout === undefined) {\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.options.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 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: RealtimeModelError | LLMError | TTSError | STTError | null = null,\n drain: boolean = false,\n ): Promise<void> {\n if (this.rootSpanContext) {\n return otelContext.with(this.rootSpanContext, async () => {\n await this.closeImplInner(reason, error, drain);\n });\n }\n\n return this.closeImplInner(reason, error, drain);\n }\n\n private async closeImplInner(\n reason: ShutdownReason,\n error: RealtimeModelError | LLMError | TTSError | STTError | null = null,\n drain: boolean = false,\n ): Promise<void> {\n if (!this.started) {\n return;\n }\n\n this._cancelUserAwayTimer();\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 // Uninterruptible speech can throw during forced interruption.\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._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":["import_utils","InferenceSTT","InferenceLLM","InferenceTTS","oldTask","agent","otelContext","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 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 { 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 { RoomIO, type RoomInputOptions, type RoomOutputOptions } from './room_io/index.js';\nimport type { UnknownUserData } from './run_context.js';\nimport type { SpeechHandle } from './speech_handle.js';\nimport { RunResult } from './testing/run_result.js';\nimport { setParticipantSpanAttributes } from './utils.js';\n\nexport interface VoiceOptions {\n allowInterruptions: boolean;\n discardAudioIfUninterruptible: boolean;\n minInterruptionDuration: number;\n minInterruptionWords: number;\n minEndpointingDelay: number;\n maxEndpointingDelay: number;\n maxToolSteps: number;\n preemptiveGeneration: boolean;\n userAwayTimeout?: number | null;\n aecWarmupDuration: number | null;\n useTtsAlignedTranscript: boolean;\n}\n\nconst defaultVoiceOptions: VoiceOptions = {\n allowInterruptions: true,\n discardAudioIfUninterruptible: true,\n minInterruptionDuration: 500,\n minInterruptionWords: 0,\n minEndpointingDelay: 500,\n maxEndpointingDelay: 6000,\n maxToolSteps: 3,\n preemptiveGeneration: false,\n userAwayTimeout: 15.0,\n aecWarmupDuration: 3000,\n useTtsAlignedTranscript: true,\n} as const;\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};\n\nexport type AgentSessionOptions<UserData = UnknownUserData> = {\n turnDetection?: TurnDetectionMode;\n stt?: STT | STTModelString;\n vad?: VAD;\n llm?: LLM | RealtimeModel | LLMModels;\n tts?: TTS | TTSModelString;\n userData?: UserData;\n voiceOptions?: Partial<VoiceOptions>;\n connOptions?: SessionConnectOptions;\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 readonly options: VoiceOptions;\n\n private agent?: Agent;\n private activity?: AgentActivity;\n private nextActivity?: AgentActivity;\n private updateActivityTask?: Task<void>;\n private started = false;\n private userState: UserState = 'listening';\n private readonly activityLock = new Mutex();\n\n /** @internal */\n _roomIO?: RoomIO;\n private logger = log();\n\n private _chatCtx: ChatContext;\n private _userData: UserData | undefined;\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 userSpeakingSpan?: Span;\n private agentSpeakingSpan?: Span;\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 constructor(opts: AgentSessionOptions<UserData>) {\n super();\n\n const {\n vad,\n stt,\n llm,\n tts,\n turnDetection,\n userData,\n voiceOptions = defaultVoiceOptions,\n connOptions,\n } = opts;\n\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 = turnDetection;\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.options = { ...defaultVoiceOptions, ...voiceOptions };\n this._aecWarmupRemaining = this.options.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 useTtsAlignedTranscript(): boolean {\n return this.options.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 this._roomIO.start();\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 // 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 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 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(error: RealtimeModelError | STTError | TTSError | LLMError): void {\n if (this.closingTask || error.recoverable) {\n return;\n }\n\n // Track error counts per type to implement max_unrecoverable_errors logic\n if (error.type === 'llm_error') {\n this.llmErrorCounts += 1;\n if (this.llmErrorCounts <= this._connOptions.maxUnrecoverableErrors) {\n return;\n }\n } else if (error.type === 'tts_error') {\n this.ttsErrorCounts += 1;\n if (this.ttsErrorCounts <= this._connOptions.maxUnrecoverableErrors) {\n return;\n }\n }\n\n this.logger.error(error, 'AgentSession is closing due to 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 // Reset error counts when agent starts 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(state: UserState, lastSpeakingTime?: number) {\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: this.rootSpanContext,\n startTime: 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(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 (this.options.userAwayTimeout === null || this.options.userAwayTimeout === undefined) {\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.options.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: RealtimeModelError | LLMError | TTSError | STTError | null = null,\n drain: boolean = false,\n ): Promise<void> {\n if (this.rootSpanContext) {\n return otelContext.with(this.rootSpanContext, async () => {\n await this.closeImplInner(reason, error, drain);\n });\n }\n\n return this.closeImplInner(reason, error, drain);\n }\n\n private async closeImplInner(\n reason: ShutdownReason,\n error: RealtimeModelError | LLMError | TTSError | STTError | null = null,\n drain: boolean = false,\n ): Promise<void> {\n 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._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":["import_utils","InferenceSTT","InferenceLLM","InferenceTTS","oldTask","agent","otelContext","error"]}
|
|
@@ -34,6 +34,7 @@ export interface VoiceOptions {
|
|
|
34
34
|
maxToolSteps: number;
|
|
35
35
|
preemptiveGeneration: boolean;
|
|
36
36
|
userAwayTimeout?: number | null;
|
|
37
|
+
aecWarmupDuration: number | null;
|
|
37
38
|
useTtsAlignedTranscript: boolean;
|
|
38
39
|
}
|
|
39
40
|
export type TurnDetectionMode = 'stt' | 'vad' | 'realtime_llm' | 'manual' | _TurnDetector;
|
|
@@ -89,6 +90,7 @@ export declare class AgentSession<UserData = UnknownUserData> extends AgentSessi
|
|
|
89
90
|
private _output;
|
|
90
91
|
private closingTask;
|
|
91
92
|
private userAwayTimer;
|
|
93
|
+
private _aecWarmupTimer;
|
|
92
94
|
private _connOptions;
|
|
93
95
|
private llmErrorCounts;
|
|
94
96
|
private ttsErrorCounts;
|
|
@@ -96,6 +98,8 @@ export declare class AgentSession<UserData = UnknownUserData> extends AgentSessi
|
|
|
96
98
|
private userSpeakingSpan?;
|
|
97
99
|
private agentSpeakingSpan?;
|
|
98
100
|
/** @internal */
|
|
101
|
+
_aecWarmupRemaining: number;
|
|
102
|
+
/** @internal */
|
|
99
103
|
_recorderIO?: RecorderIO;
|
|
100
104
|
/** @internal */
|
|
101
105
|
rootSpanContext?: Context;
|
|
@@ -196,6 +200,8 @@ export declare class AgentSession<UserData = UnknownUserData> extends AgentSessi
|
|
|
196
200
|
private onTextOutputChanged;
|
|
197
201
|
private _setUserAwayTimer;
|
|
198
202
|
private _cancelUserAwayTimer;
|
|
203
|
+
/** @internal */
|
|
204
|
+
_onAecWarmupExpired(): void;
|
|
199
205
|
private _onUserInputTranscribed;
|
|
200
206
|
private closeImpl;
|
|
201
207
|
private closeImplInner;
|
|
@@ -34,6 +34,7 @@ export interface VoiceOptions {
|
|
|
34
34
|
maxToolSteps: number;
|
|
35
35
|
preemptiveGeneration: boolean;
|
|
36
36
|
userAwayTimeout?: number | null;
|
|
37
|
+
aecWarmupDuration: number | null;
|
|
37
38
|
useTtsAlignedTranscript: boolean;
|
|
38
39
|
}
|
|
39
40
|
export type TurnDetectionMode = 'stt' | 'vad' | 'realtime_llm' | 'manual' | _TurnDetector;
|
|
@@ -89,6 +90,7 @@ export declare class AgentSession<UserData = UnknownUserData> extends AgentSessi
|
|
|
89
90
|
private _output;
|
|
90
91
|
private closingTask;
|
|
91
92
|
private userAwayTimer;
|
|
93
|
+
private _aecWarmupTimer;
|
|
92
94
|
private _connOptions;
|
|
93
95
|
private llmErrorCounts;
|
|
94
96
|
private ttsErrorCounts;
|
|
@@ -96,6 +98,8 @@ export declare class AgentSession<UserData = UnknownUserData> extends AgentSessi
|
|
|
96
98
|
private userSpeakingSpan?;
|
|
97
99
|
private agentSpeakingSpan?;
|
|
98
100
|
/** @internal */
|
|
101
|
+
_aecWarmupRemaining: number;
|
|
102
|
+
/** @internal */
|
|
99
103
|
_recorderIO?: RecorderIO;
|
|
100
104
|
/** @internal */
|
|
101
105
|
rootSpanContext?: Context;
|
|
@@ -196,6 +200,8 @@ export declare class AgentSession<UserData = UnknownUserData> extends AgentSessi
|
|
|
196
200
|
private onTextOutputChanged;
|
|
197
201
|
private _setUserAwayTimer;
|
|
198
202
|
private _cancelUserAwayTimer;
|
|
203
|
+
/** @internal */
|
|
204
|
+
_onAecWarmupExpired(): void;
|
|
199
205
|
private _onUserInputTranscribed;
|
|
200
206
|
private closeImpl;
|
|
201
207
|
private closeImplInner;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent_session.d.ts","sourceRoot":"","sources":["../../src/voice/agent_session.ts"],"names":[],"mappings":";AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,KAAK,EAAE,iBAAiB,IAAI,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAChF,OAAO,KAAK,EAAE,OAAO,EAAQ,MAAM,oBAAoB,CAAC;AAGxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,EAIL,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,KAAK,cAAc,EACpB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC/E,OAAO,EAAoB,WAAW,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACpF,OAAO,KAAK,EAAE,GAAG,EAAE,aAAa,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC1F,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,OAAO,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAGL,KAAK,6BAA6B,EAClC,KAAK,qBAAqB,EAC3B,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACnC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EACL,KAAK,UAAU,EACf,sBAAsB,EACtB,KAAK,UAAU,EACf,KAAK,sBAAsB,EAC3B,KAAK,UAAU,EAEf,KAAK,0BAA0B,EAC/B,KAAK,UAAU,EACf,KAAK,0BAA0B,EAC/B,KAAK,qBAAqB,EAC1B,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC9B,KAAK,SAAS,EACd,KAAK,qBAAqB,EAK3B,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,KAAK,gBAAgB,EAAE,KAAK,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC3F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAGpD,MAAM,WAAW,YAAY;IAC3B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,6BAA6B,EAAE,OAAO,CAAC;IACvC,uBAAuB,EAAE,MAAM,CAAC;IAChC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,uBAAuB,EAAE,OAAO,CAAC;CAClC;
|
|
1
|
+
{"version":3,"file":"agent_session.d.ts","sourceRoot":"","sources":["../../src/voice/agent_session.ts"],"names":[],"mappings":"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"}
|
|
@@ -39,6 +39,7 @@ const defaultVoiceOptions = {
|
|
|
39
39
|
maxToolSteps: 3,
|
|
40
40
|
preemptiveGeneration: false,
|
|
41
41
|
userAwayTimeout: 15,
|
|
42
|
+
aecWarmupDuration: 3e3,
|
|
42
43
|
useTtsAlignedTranscript: true
|
|
43
44
|
};
|
|
44
45
|
class AgentSession extends EventEmitter {
|
|
@@ -65,6 +66,7 @@ class AgentSession extends EventEmitter {
|
|
|
65
66
|
_output;
|
|
66
67
|
closingTask = null;
|
|
67
68
|
userAwayTimer = null;
|
|
69
|
+
_aecWarmupTimer = null;
|
|
68
70
|
// Connection options for STT, LLM, and TTS
|
|
69
71
|
_connOptions;
|
|
70
72
|
// Unrecoverable error counts, reset after agent speaking
|
|
@@ -74,6 +76,8 @@ class AgentSession extends EventEmitter {
|
|
|
74
76
|
userSpeakingSpan;
|
|
75
77
|
agentSpeakingSpan;
|
|
76
78
|
/** @internal */
|
|
79
|
+
_aecWarmupRemaining = 0;
|
|
80
|
+
/** @internal */
|
|
77
81
|
_recorderIO;
|
|
78
82
|
/** @internal */
|
|
79
83
|
rootSpanContext;
|
|
@@ -125,6 +129,7 @@ class AgentSession extends EventEmitter {
|
|
|
125
129
|
this._output = new AgentOutput(this.onAudioOutputChanged, this.onTextOutputChanged);
|
|
126
130
|
this._chatCtx = ChatContext.empty();
|
|
127
131
|
this.options = { ...defaultVoiceOptions, ...voiceOptions };
|
|
132
|
+
this._aecWarmupRemaining = this.options.aecWarmupDuration ?? 0;
|
|
128
133
|
this._onUserInputTranscribed = this._onUserInputTranscribed.bind(this);
|
|
129
134
|
this.on(AgentSessionEventTypes.UserInputTranscribed, this._onUserInputTranscribed);
|
|
130
135
|
}
|
|
@@ -517,7 +522,9 @@ class AgentSession extends EventEmitter {
|
|
|
517
522
|
if (this.closingTask) {
|
|
518
523
|
return;
|
|
519
524
|
}
|
|
520
|
-
this.closeImpl(reason, error, drain)
|
|
525
|
+
this.closingTask = this.closeImpl(reason, error, drain).finally(() => {
|
|
526
|
+
this.closingTask = null;
|
|
527
|
+
});
|
|
521
528
|
}
|
|
522
529
|
/** @internal */
|
|
523
530
|
_onError(error) {
|
|
@@ -575,6 +582,13 @@ class AgentSession extends EventEmitter {
|
|
|
575
582
|
this.agentSpeakingSpan.end();
|
|
576
583
|
this.agentSpeakingSpan = void 0;
|
|
577
584
|
}
|
|
585
|
+
if (state === "speaking" && this._aecWarmupRemaining > 0 && this._aecWarmupTimer === null) {
|
|
586
|
+
this._aecWarmupTimer = setTimeout(() => this._onAecWarmupExpired(), this._aecWarmupRemaining);
|
|
587
|
+
this.logger.debug(
|
|
588
|
+
{ warmupDurationMs: this._aecWarmupRemaining },
|
|
589
|
+
"aec warmup active, disabling interruptions"
|
|
590
|
+
);
|
|
591
|
+
}
|
|
578
592
|
const oldState = this._agentState;
|
|
579
593
|
this._agentState = state;
|
|
580
594
|
if (state === "listening" && this.userState === "listening") {
|
|
@@ -651,6 +665,17 @@ class AgentSession extends EventEmitter {
|
|
|
651
665
|
this.userAwayTimer = null;
|
|
652
666
|
}
|
|
653
667
|
}
|
|
668
|
+
/** @internal */
|
|
669
|
+
_onAecWarmupExpired() {
|
|
670
|
+
if (this._aecWarmupRemaining > 0) {
|
|
671
|
+
this.logger.debug("aec warmup expired, re-enabling interruptions");
|
|
672
|
+
}
|
|
673
|
+
this._aecWarmupRemaining = 0;
|
|
674
|
+
if (this._aecWarmupTimer !== null) {
|
|
675
|
+
clearTimeout(this._aecWarmupTimer);
|
|
676
|
+
this._aecWarmupTimer = null;
|
|
677
|
+
}
|
|
678
|
+
}
|
|
654
679
|
_onUserInputTranscribed(ev) {
|
|
655
680
|
if (this.userState === "away" && ev.isFinal) {
|
|
656
681
|
this.logger.debug("User returned from away state due to speech input");
|
|
@@ -671,6 +696,7 @@ class AgentSession extends EventEmitter {
|
|
|
671
696
|
return;
|
|
672
697
|
}
|
|
673
698
|
this._cancelUserAwayTimer();
|
|
699
|
+
this._onAecWarmupExpired();
|
|
674
700
|
this.off(AgentSessionEventTypes.UserInputTranscribed, this._onUserInputTranscribed);
|
|
675
701
|
if (this.activity) {
|
|
676
702
|
if (!drain) {
|