@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
package/dist/voice/agent.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/voice/agent.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { AudioFrame } from '@livekit/rtc-node';\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport { ReadableStream } from 'node:stream/web';\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 { ReadonlyChatContext } from '../llm/chat_context.js';\nimport type { ChatMessage, FunctionCall } from '../llm/index.js';\nimport {\n type ChatChunk,\n ChatContext,\n LLM,\n RealtimeModel,\n type ToolChoice,\n type ToolContext,\n} from '../llm/index.js';\nimport { log } from '../log.js';\nimport type { STT, SpeechEvent } from '../stt/index.js';\nimport { StreamAdapter as STTStreamAdapter } from '../stt/index.js';\nimport { SentenceTokenizer as BasicSentenceTokenizer } from '../tokenize/basic/index.js';\nimport type { TTS } from '../tts/index.js';\nimport { SynthesizeStream, StreamAdapter as TTSStreamAdapter } from '../tts/index.js';\nimport { USERDATA_TIMED_TRANSCRIPT } from '../types.js';\nimport { Future, Task } from '../utils.js';\nimport type { VAD } from '../vad.js';\nimport { type AgentActivity, agentActivityStorage } from './agent_activity.js';\nimport type { AgentSession, TurnDetectionMode } from './agent_session.js';\nimport type { TimedString } from './io.js';\nimport type { SpeechHandle } from './speech_handle.js';\n\nexport const functionCallStorage = new AsyncLocalStorage<{ functionCall?: FunctionCall }>();\nexport const speechHandleStorage = new AsyncLocalStorage<SpeechHandle>();\nconst activityTaskInfoStorage = new WeakMap<Task<any>, _ActivityTaskInfo>();\n\ntype _ActivityTaskInfo = {\n functionCall: FunctionCall | null;\n speechHandle: SpeechHandle | null;\n inlineTask: boolean;\n};\n\n/** @internal */\nexport function _setActivityTaskInfo<T>(\n task: Task<T>,\n options: {\n functionCall?: FunctionCall | null;\n speechHandle?: SpeechHandle | null;\n inlineTask?: boolean;\n },\n): void {\n const info = activityTaskInfoStorage.get(task) ?? {\n functionCall: null,\n speechHandle: null,\n inlineTask: false,\n };\n\n if (Object.hasOwn(options, 'functionCall')) {\n info.functionCall = options.functionCall ?? null;\n }\n if (Object.hasOwn(options, 'speechHandle')) {\n info.speechHandle = options.speechHandle ?? null;\n }\n if (Object.hasOwn(options, 'inlineTask')) {\n info.inlineTask = options.inlineTask ?? false;\n }\n\n activityTaskInfoStorage.set(task, info);\n}\n\n/** @internal */\nexport function _getActivityTaskInfo<T>(task: Task<T>): _ActivityTaskInfo | undefined {\n return activityTaskInfoStorage.get(task);\n}\nexport const STOP_RESPONSE_SYMBOL = Symbol('StopResponse');\n\nexport class StopResponse extends Error {\n constructor() {\n super();\n this.name = 'StopResponse';\n\n Object.defineProperty(this, STOP_RESPONSE_SYMBOL, {\n value: true,\n });\n }\n}\n\nexport function isStopResponse(value: unknown): value is StopResponse {\n return (\n value !== undefined &&\n value !== null &&\n typeof value === 'object' &&\n STOP_RESPONSE_SYMBOL in value\n );\n}\n\nexport interface ModelSettings {\n /** The tool choice to use when calling the LLM. */\n toolChoice?: ToolChoice;\n}\n\nexport interface AgentOptions<UserData> {\n id?: string;\n instructions: string;\n chatCtx?: ChatContext;\n tools?: ToolContext<UserData>;\n turnDetection?: TurnDetectionMode;\n stt?: STT | STTModelString;\n vad?: VAD;\n llm?: LLM | RealtimeModel | LLMModels;\n tts?: TTS | TTSModelString;\n allowInterruptions?: boolean;\n minConsecutiveSpeechDelay?: number;\n useTtsAlignedTranscript?: boolean;\n}\n\nexport class Agent<UserData = any> {\n private _id: string;\n private turnDetection?: TurnDetectionMode;\n private _stt?: STT;\n private _vad?: VAD;\n private _llm?: LLM | RealtimeModel;\n private _tts?: TTS;\n private _useTtsAlignedTranscript?: boolean;\n\n /** @internal */\n _agentActivity?: AgentActivity;\n\n /** @internal */\n _chatCtx: ChatContext;\n\n /** @internal */\n _instructions: string;\n\n /** @internal */\n _tools?: ToolContext<UserData>;\n\n constructor({\n id,\n instructions,\n chatCtx,\n tools,\n turnDetection,\n stt,\n vad,\n llm,\n tts,\n useTtsAlignedTranscript,\n }: AgentOptions<UserData>) {\n if (id) {\n this._id = id;\n } else {\n // Convert class name to snake_case\n const className = this.constructor.name;\n if (className === 'Agent') {\n this._id = 'default_agent';\n } else {\n this._id = className\n .replace(/([A-Z])/g, '_$1')\n .toLowerCase()\n .replace(/^_/, '');\n }\n }\n\n this._instructions = instructions;\n this._tools = { ...tools };\n this._chatCtx = chatCtx\n ? chatCtx.copy({\n toolCtx: this._tools,\n })\n : ChatContext.empty();\n\n this.turnDetection = turnDetection;\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._useTtsAlignedTranscript = useTtsAlignedTranscript;\n\n this._agentActivity = undefined;\n }\n\n get vad(): VAD | undefined {\n return this._vad;\n }\n\n get stt(): STT | undefined {\n return this._stt;\n }\n\n get llm(): LLM | RealtimeModel | undefined {\n return this._llm;\n }\n\n get tts(): TTS | undefined {\n return this._tts;\n }\n\n get useTtsAlignedTranscript(): boolean | undefined {\n return this._useTtsAlignedTranscript;\n }\n\n get chatCtx(): ReadonlyChatContext {\n return new ReadonlyChatContext(this._chatCtx.items);\n }\n\n get id(): string {\n return this._id;\n }\n\n get instructions(): string {\n return this._instructions;\n }\n\n get toolCtx(): ToolContext<UserData> {\n return { ...this._tools };\n }\n\n get session(): AgentSession<UserData> {\n return this.getActivityOrThrow().agentSession as AgentSession<UserData>;\n }\n\n async onEnter(): Promise<void> {}\n\n async onExit(): Promise<void> {}\n\n async transcriptionNode(\n text: ReadableStream<string | TimedString>,\n modelSettings: ModelSettings,\n ): Promise<ReadableStream<string | TimedString> | null> {\n return Agent.default.transcriptionNode(this, text, modelSettings);\n }\n\n async onUserTurnCompleted(_chatCtx: ChatContext, _newMessage: ChatMessage): Promise<void> {}\n\n async sttNode(\n audio: ReadableStream<AudioFrame>,\n modelSettings: ModelSettings,\n ): Promise<ReadableStream<SpeechEvent | string> | null> {\n return Agent.default.sttNode(this, audio, modelSettings);\n }\n\n async llmNode(\n chatCtx: ChatContext,\n toolCtx: ToolContext,\n modelSettings: ModelSettings,\n ): Promise<ReadableStream<ChatChunk | string> | null> {\n return Agent.default.llmNode(this, chatCtx, toolCtx, modelSettings);\n }\n\n async ttsNode(\n text: ReadableStream<string>,\n modelSettings: ModelSettings,\n ): Promise<ReadableStream<AudioFrame> | null> {\n return Agent.default.ttsNode(this, text, modelSettings);\n }\n\n async realtimeAudioOutputNode(\n audio: ReadableStream<AudioFrame>,\n modelSettings: ModelSettings,\n ): Promise<ReadableStream<AudioFrame> | null> {\n return Agent.default.realtimeAudioOutputNode(this, audio, modelSettings);\n }\n\n // realtime_audio_output_node\n\n getActivityOrThrow(): AgentActivity {\n if (!this._agentActivity) {\n throw new Error('Agent activity not found');\n }\n return this._agentActivity;\n }\n\n async updateChatCtx(chatCtx: ChatContext): Promise<void> {\n if (!this._agentActivity) {\n this._chatCtx = chatCtx.copy({ toolCtx: this.toolCtx });\n return;\n }\n\n this._agentActivity.updateChatCtx(chatCtx);\n }\n\n static default = {\n async sttNode(\n agent: Agent,\n audio: ReadableStream<AudioFrame>,\n _modelSettings: ModelSettings,\n ): Promise<ReadableStream<SpeechEvent | string> | null> {\n const activity = agent.getActivityOrThrow();\n if (!activity.stt) {\n throw new Error('sttNode called but no STT node is available');\n }\n\n let wrappedStt = activity.stt;\n\n if (!wrappedStt.capabilities.streaming) {\n const vad = agent.vad || activity.vad;\n if (!vad) {\n throw new Error(\n 'STT does not support streaming, add a VAD to the AgentTask/VoiceAgent to enable streaming',\n );\n }\n wrappedStt = new STTStreamAdapter(wrappedStt, vad);\n }\n\n const connOptions = activity.agentSession.connOptions.sttConnOptions;\n const stream = wrappedStt.stream({ connOptions });\n\n // Set startTimeOffset to provide linear timestamps across reconnections\n const audioInputStartedAt =\n activity.agentSession._recorderIO?.recordingStartedAt ?? // Use recording start time if available\n activity.agentSession._startedAt ?? // Fallback to session start time\n Date.now(); // Fallback to current time\n\n stream.startTimeOffset = (Date.now() - audioInputStartedAt) / 1000;\n\n stream.updateInputStream(audio);\n\n let cleaned = false;\n const cleanup = () => {\n if (cleaned) return;\n cleaned = true;\n stream.detachInputStream();\n stream.close();\n };\n\n return new ReadableStream({\n async start(controller) {\n try {\n for await (const event of stream) {\n controller.enqueue(event);\n }\n controller.close();\n } finally {\n // Always clean up the STT stream, whether it ends naturally or is cancelled\n cleanup();\n }\n },\n cancel() {\n cleanup();\n },\n });\n },\n\n async llmNode(\n agent: Agent,\n chatCtx: ChatContext,\n toolCtx: ToolContext,\n modelSettings: ModelSettings,\n ): Promise<ReadableStream<ChatChunk | string> | null> {\n const activity = agent.getActivityOrThrow();\n if (!activity.llm) {\n throw new Error('llmNode called but no LLM node is available');\n }\n\n if (!(activity.llm instanceof LLM)) {\n throw new Error(\n 'llmNode should only be used with LLM (non-multimodal/realtime APIs) nodes',\n );\n }\n\n const { toolChoice } = modelSettings;\n const connOptions = activity.agentSession.connOptions.llmConnOptions;\n\n // parallelToolCalls is not passed here - it will use the value from LLM's modelOptions\n // This allows users to configure it via: new inference.LLM({ modelOptions: { parallel_tool_calls: false } })\n const stream = activity.llm.chat({\n chatCtx,\n toolCtx,\n toolChoice,\n connOptions,\n });\n\n let cleaned = false;\n const cleanup = () => {\n if (cleaned) return;\n cleaned = true;\n stream.close();\n };\n\n return new ReadableStream({\n async start(controller) {\n try {\n for await (const chunk of stream) {\n controller.enqueue(chunk);\n }\n controller.close();\n } finally {\n cleanup();\n }\n },\n cancel() {\n cleanup();\n },\n });\n },\n\n async ttsNode(\n agent: Agent,\n text: ReadableStream<string>,\n _modelSettings: ModelSettings,\n ): Promise<ReadableStream<AudioFrame> | null> {\n const activity = agent.getActivityOrThrow();\n if (!activity.tts) {\n throw new Error('ttsNode called but no TTS node is available');\n }\n\n let wrappedTts = activity.tts;\n\n if (!activity.tts.capabilities.streaming) {\n wrappedTts = new TTSStreamAdapter(wrappedTts, new BasicSentenceTokenizer());\n }\n\n const connOptions = activity.agentSession.connOptions.ttsConnOptions;\n const stream = wrappedTts.stream({ connOptions });\n stream.updateInputStream(text);\n\n let cleaned = false;\n const cleanup = () => {\n if (cleaned) return;\n cleaned = true;\n stream.close();\n };\n\n return new ReadableStream({\n async start(controller) {\n try {\n for await (const chunk of stream) {\n if (chunk === SynthesizeStream.END_OF_STREAM) {\n break;\n }\n // Attach timed transcripts to frame.userdata\n if (chunk.timedTranscripts && chunk.timedTranscripts.length > 0) {\n chunk.frame.userdata[USERDATA_TIMED_TRANSCRIPT] = chunk.timedTranscripts;\n }\n controller.enqueue(chunk.frame);\n }\n controller.close();\n } finally {\n cleanup();\n }\n },\n cancel() {\n cleanup();\n },\n });\n },\n\n async transcriptionNode(\n agent: Agent,\n text: ReadableStream<string | TimedString>,\n _modelSettings: ModelSettings,\n ): Promise<ReadableStream<string | TimedString> | null> {\n return text;\n },\n\n async realtimeAudioOutputNode(\n _agent: Agent,\n audio: ReadableStream<AudioFrame>,\n _modelSettings: ModelSettings,\n ): Promise<ReadableStream<AudioFrame> | null> {\n return audio;\n },\n };\n}\n\nexport class AgentTask<ResultT = unknown, UserData = any> extends Agent<UserData> {\n private started = false;\n private future = new Future<ResultT>();\n\n #logger = log();\n\n get done(): boolean {\n return this.future.done;\n }\n\n complete(result: ResultT | Error): void {\n if (this.future.done) {\n throw new Error(`${this.constructor.name} is already done`);\n }\n\n if (result instanceof Error) {\n this.future.reject(result);\n } else {\n this.future.resolve(result);\n }\n\n const speechHandle = speechHandleStorage.getStore();\n if (speechHandle) {\n speechHandle._maybeRunFinalOutput = result;\n }\n }\n\n async run(): Promise<ResultT> {\n if (this.started) {\n throw new Error(\n `Task ${this.constructor.name} has already started and cannot be awaited multiple times`,\n );\n }\n this.started = true;\n\n const currentTask = Task.current();\n if (!currentTask) {\n throw new Error(`${this.constructor.name} must be executed inside a Task context`);\n }\n\n const taskInfo = _getActivityTaskInfo(currentTask);\n if (!taskInfo || !taskInfo.inlineTask) {\n throw new Error(\n `${this.constructor.name} should only be awaited inside function tools or the onEnter/onExit methods of an Agent`,\n );\n }\n\n const speechHandle = speechHandleStorage.getStore();\n const oldActivity = agentActivityStorage.getStore();\n if (!oldActivity) {\n throw new Error(`${this.constructor.name} must be executed inside an AgentActivity context`);\n }\n\n currentTask.addDoneCallback(() => {\n if (this.future.done) return;\n\n // If the Task finished before the AgentTask was completed, complete the AgentTask with an error.\n this.#logger.error(`The Task finished before ${this.constructor.name} was completed.`);\n this.complete(new Error(`The Task finished before ${this.constructor.name} was completed.`));\n });\n\n const oldAgent = oldActivity.agent;\n const session = oldActivity.agentSession;\n\n const blockedTasks: Task<any>[] = [currentTask];\n const onEnterTask = oldActivity._onEnterTask;\n\n if (onEnterTask && !onEnterTask.done && onEnterTask !== currentTask) {\n blockedTasks.push(onEnterTask);\n }\n\n if (\n taskInfo.functionCall &&\n oldActivity.llm instanceof RealtimeModel &&\n !oldActivity.llm.capabilities.manualFunctionCalls\n ) {\n this.#logger.error(\n `Realtime model does not support resuming function calls from chat context, ` +\n `using AgentTask inside a function tool may have unexpected behavior.`,\n );\n }\n\n await session._updateActivity(this, {\n previousActivity: 'pause',\n newActivity: 'start',\n blockedTasks,\n });\n\n let runState = session._globalRunState;\n if (speechHandle && runState && !runState.done()) {\n // Only unwatch the parent speech handle if there are other handles keeping the run alive.\n // When watchedHandleCount is 1 (only the parent), unwatching would drop it to 0 and\n // mark the run done prematurely — before function_call_output and assistant message arrive.\n if (runState._watchedHandleCount() > 1) {\n runState._unwatchHandle(speechHandle);\n }\n // it is OK to call _markDoneIfNeeded here, the above _updateActivity will call onEnter\n // and newly added handles keep the run alive.\n runState._markDoneIfNeeded();\n }\n\n try {\n return await this.future.await;\n } finally {\n // runState could have changed after future resolved\n runState = session._globalRunState;\n\n if (session.currentAgent !== this) {\n this.#logger.warn(\n `${this.constructor.name} completed, but the agent has changed in the meantime. ` +\n `Ignoring handoff to the previous agent, likely due to AgentSession.updateAgent being invoked.`,\n );\n await oldActivity.close();\n } else {\n if (speechHandle && runState && !runState.done()) {\n runState._watchHandle(speechHandle);\n }\n\n const mergedChatCtx = oldAgent._chatCtx.merge(this._chatCtx, {\n excludeFunctionCall: true,\n excludeInstructions: true,\n });\n oldAgent._chatCtx.items = mergedChatCtx.items;\n\n await session._updateActivity(oldAgent, {\n previousActivity: 'close',\n newActivity: 'resume',\n waitOnEnter: false,\n });\n }\n }\n }\n}\n"],"mappings":"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","names":["InferenceSTT","InferenceLLM","InferenceTTS","STTStreamAdapter","TTSStreamAdapter","BasicSentenceTokenizer"]}
|
|
1
|
+
{"version":3,"sources":["../../src/voice/agent.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { AudioFrame } from '@livekit/rtc-node';\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport { ReadableStream } from 'node:stream/web';\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 { ReadonlyChatContext } from '../llm/chat_context.js';\nimport type { ChatMessage, FunctionCall } from '../llm/index.js';\nimport {\n type ChatChunk,\n ChatContext,\n LLM,\n RealtimeModel,\n type ToolChoice,\n type ToolContext,\n} from '../llm/index.js';\nimport { log } from '../log.js';\nimport type { STT, SpeechEvent } from '../stt/index.js';\nimport { StreamAdapter as STTStreamAdapter } from '../stt/index.js';\nimport { SentenceTokenizer as BasicSentenceTokenizer } from '../tokenize/basic/index.js';\nimport type { TTS } from '../tts/index.js';\nimport { SynthesizeStream, StreamAdapter as TTSStreamAdapter } from '../tts/index.js';\nimport { USERDATA_TIMED_TRANSCRIPT } from '../types.js';\nimport { Future, Task } from '../utils.js';\nimport type { VAD } from '../vad.js';\nimport { type AgentActivity, agentActivityStorage } from './agent_activity.js';\nimport type { AgentSession, TurnDetectionMode } from './agent_session.js';\nimport type { TimedString } from './io.js';\nimport type { SpeechHandle } from './speech_handle.js';\n\nexport const functionCallStorage = new AsyncLocalStorage<{ functionCall?: FunctionCall }>();\nexport const speechHandleStorage = new AsyncLocalStorage<SpeechHandle>();\nconst activityTaskInfoStorage = new WeakMap<Task<any>, _ActivityTaskInfo>();\n\ntype _ActivityTaskInfo = {\n functionCall: FunctionCall | null;\n speechHandle: SpeechHandle | null;\n inlineTask: boolean;\n};\n\n/** @internal */\nexport function _setActivityTaskInfo<T>(\n task: Task<T>,\n options: {\n functionCall?: FunctionCall | null;\n speechHandle?: SpeechHandle | null;\n inlineTask?: boolean;\n },\n): void {\n const info = activityTaskInfoStorage.get(task) ?? {\n functionCall: null,\n speechHandle: null,\n inlineTask: false,\n };\n\n if (Object.hasOwn(options, 'functionCall')) {\n info.functionCall = options.functionCall ?? null;\n }\n if (Object.hasOwn(options, 'speechHandle')) {\n info.speechHandle = options.speechHandle ?? null;\n }\n if (Object.hasOwn(options, 'inlineTask')) {\n info.inlineTask = options.inlineTask ?? false;\n }\n\n activityTaskInfoStorage.set(task, info);\n}\n\n/** @internal */\nexport function _getActivityTaskInfo<T>(task: Task<T>): _ActivityTaskInfo | undefined {\n return activityTaskInfoStorage.get(task);\n}\nexport const STOP_RESPONSE_SYMBOL = Symbol('StopResponse');\n\nexport class StopResponse extends Error {\n constructor() {\n super();\n this.name = 'StopResponse';\n\n Object.defineProperty(this, STOP_RESPONSE_SYMBOL, {\n value: true,\n });\n }\n}\n\nexport function isStopResponse(value: unknown): value is StopResponse {\n return (\n value !== undefined &&\n value !== null &&\n typeof value === 'object' &&\n STOP_RESPONSE_SYMBOL in value\n );\n}\n\nexport interface ModelSettings {\n /** The tool choice to use when calling the LLM. */\n toolChoice?: ToolChoice;\n}\n\nexport interface AgentOptions<UserData> {\n id?: string;\n instructions: string;\n chatCtx?: ChatContext;\n tools?: ToolContext<UserData>;\n turnDetection?: TurnDetectionMode;\n stt?: STT | STTModelString;\n vad?: VAD;\n llm?: LLM | RealtimeModel | LLMModels;\n tts?: TTS | TTSModelString;\n allowInterruptions?: boolean;\n minConsecutiveSpeechDelay?: number;\n useTtsAlignedTranscript?: boolean;\n}\n\nexport class Agent<UserData = any> {\n private _id: string;\n private turnDetection?: TurnDetectionMode;\n private _stt?: STT;\n private _vad?: VAD;\n private _llm?: LLM | RealtimeModel;\n private _tts?: TTS;\n private _useTtsAlignedTranscript?: boolean;\n\n /** @internal */\n _agentActivity?: AgentActivity;\n\n /** @internal */\n _chatCtx: ChatContext;\n\n /** @internal */\n _instructions: string;\n\n /** @internal */\n _tools?: ToolContext<UserData>;\n\n constructor({\n id,\n instructions,\n chatCtx,\n tools,\n turnDetection,\n stt,\n vad,\n llm,\n tts,\n useTtsAlignedTranscript,\n }: AgentOptions<UserData>) {\n if (id) {\n this._id = id;\n } else {\n // Convert class name to snake_case\n const className = this.constructor.name;\n if (className === 'Agent') {\n this._id = 'default_agent';\n } else {\n this._id = className\n .replace(/([A-Z])/g, '_$1')\n .toLowerCase()\n .replace(/^_/, '');\n }\n }\n\n this._instructions = instructions;\n this._tools = { ...tools };\n this._chatCtx = chatCtx\n ? chatCtx.copy({\n toolCtx: this._tools,\n })\n : ChatContext.empty();\n\n this.turnDetection = turnDetection;\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._useTtsAlignedTranscript = useTtsAlignedTranscript;\n\n this._agentActivity = undefined;\n }\n\n get vad(): VAD | undefined {\n return this._vad;\n }\n\n get stt(): STT | undefined {\n return this._stt;\n }\n\n get llm(): LLM | RealtimeModel | undefined {\n return this._llm;\n }\n\n get tts(): TTS | undefined {\n return this._tts;\n }\n\n get useTtsAlignedTranscript(): boolean | undefined {\n return this._useTtsAlignedTranscript;\n }\n\n get chatCtx(): ReadonlyChatContext {\n return new ReadonlyChatContext(this._chatCtx.items);\n }\n\n get id(): string {\n return this._id;\n }\n\n get instructions(): string {\n return this._instructions;\n }\n\n get toolCtx(): ToolContext<UserData> {\n return { ...this._tools };\n }\n\n get session(): AgentSession<UserData> {\n return this.getActivityOrThrow().agentSession as AgentSession<UserData>;\n }\n\n async onEnter(): Promise<void> {}\n\n async onExit(): Promise<void> {}\n\n async transcriptionNode(\n text: ReadableStream<string | TimedString>,\n modelSettings: ModelSettings,\n ): Promise<ReadableStream<string | TimedString> | null> {\n return Agent.default.transcriptionNode(this, text, modelSettings);\n }\n\n async onUserTurnCompleted(_chatCtx: ChatContext, _newMessage: ChatMessage): Promise<void> {}\n\n async sttNode(\n audio: ReadableStream<AudioFrame>,\n modelSettings: ModelSettings,\n ): Promise<ReadableStream<SpeechEvent | string> | null> {\n return Agent.default.sttNode(this, audio, modelSettings);\n }\n\n async llmNode(\n chatCtx: ChatContext,\n toolCtx: ToolContext,\n modelSettings: ModelSettings,\n ): Promise<ReadableStream<ChatChunk | string> | null> {\n return Agent.default.llmNode(this, chatCtx, toolCtx, modelSettings);\n }\n\n async ttsNode(\n text: ReadableStream<string>,\n modelSettings: ModelSettings,\n ): Promise<ReadableStream<AudioFrame> | null> {\n return Agent.default.ttsNode(this, text, modelSettings);\n }\n\n async realtimeAudioOutputNode(\n audio: ReadableStream<AudioFrame>,\n modelSettings: ModelSettings,\n ): Promise<ReadableStream<AudioFrame> | null> {\n return Agent.default.realtimeAudioOutputNode(this, audio, modelSettings);\n }\n\n // realtime_audio_output_node\n\n getActivityOrThrow(): AgentActivity {\n if (!this._agentActivity) {\n throw new Error('Agent activity not found');\n }\n return this._agentActivity;\n }\n\n async updateChatCtx(chatCtx: ChatContext): Promise<void> {\n if (!this._agentActivity) {\n this._chatCtx = chatCtx.copy({ toolCtx: this.toolCtx });\n return;\n }\n\n this._agentActivity.updateChatCtx(chatCtx);\n }\n\n // TODO(parity): Add when AgentConfigUpdate is ported to ChatContext.\n async updateTools(tools: ToolContext): Promise<void> {\n if (!this._agentActivity) {\n this._tools = { ...tools };\n this._chatCtx = this._chatCtx.copy({ toolCtx: this._tools });\n return;\n }\n\n await this._agentActivity.updateTools(tools);\n }\n\n static default = {\n async sttNode(\n agent: Agent,\n audio: ReadableStream<AudioFrame>,\n _modelSettings: ModelSettings,\n ): Promise<ReadableStream<SpeechEvent | string> | null> {\n const activity = agent.getActivityOrThrow();\n if (!activity.stt) {\n throw new Error('sttNode called but no STT node is available');\n }\n\n let wrappedStt = activity.stt;\n\n if (!wrappedStt.capabilities.streaming) {\n const vad = agent.vad || activity.vad;\n if (!vad) {\n throw new Error(\n 'STT does not support streaming, add a VAD to the AgentTask/VoiceAgent to enable streaming',\n );\n }\n wrappedStt = new STTStreamAdapter(wrappedStt, vad);\n }\n\n const connOptions = activity.agentSession.connOptions.sttConnOptions;\n const stream = wrappedStt.stream({ connOptions });\n\n // Set startTimeOffset to provide linear timestamps across reconnections\n const audioInputStartedAt =\n activity.agentSession._recorderIO?.recordingStartedAt ?? // Use recording start time if available\n activity.agentSession._startedAt ?? // Fallback to session start time\n Date.now(); // Fallback to current time\n\n stream.startTimeOffset = (Date.now() - audioInputStartedAt) / 1000;\n\n stream.updateInputStream(audio);\n\n let cleaned = false;\n const cleanup = () => {\n if (cleaned) return;\n cleaned = true;\n stream.detachInputStream();\n stream.close();\n };\n\n return new ReadableStream({\n async start(controller) {\n try {\n for await (const event of stream) {\n controller.enqueue(event);\n }\n controller.close();\n } finally {\n // Always clean up the STT stream, whether it ends naturally or is cancelled\n cleanup();\n }\n },\n cancel() {\n cleanup();\n },\n });\n },\n\n async llmNode(\n agent: Agent,\n chatCtx: ChatContext,\n toolCtx: ToolContext,\n modelSettings: ModelSettings,\n ): Promise<ReadableStream<ChatChunk | string> | null> {\n const activity = agent.getActivityOrThrow();\n if (!activity.llm) {\n throw new Error('llmNode called but no LLM node is available');\n }\n\n if (!(activity.llm instanceof LLM)) {\n throw new Error(\n 'llmNode should only be used with LLM (non-multimodal/realtime APIs) nodes',\n );\n }\n\n const { toolChoice } = modelSettings;\n const connOptions = activity.agentSession.connOptions.llmConnOptions;\n\n // parallelToolCalls is not passed here - it will use the value from LLM's modelOptions\n // This allows users to configure it via: new inference.LLM({ modelOptions: { parallel_tool_calls: false } })\n const stream = activity.llm.chat({\n chatCtx,\n toolCtx,\n toolChoice,\n connOptions,\n });\n\n let cleaned = false;\n const cleanup = () => {\n if (cleaned) return;\n cleaned = true;\n stream.close();\n };\n\n return new ReadableStream({\n async start(controller) {\n try {\n for await (const chunk of stream) {\n controller.enqueue(chunk);\n }\n controller.close();\n } finally {\n cleanup();\n }\n },\n cancel() {\n cleanup();\n },\n });\n },\n\n async ttsNode(\n agent: Agent,\n text: ReadableStream<string>,\n _modelSettings: ModelSettings,\n ): Promise<ReadableStream<AudioFrame> | null> {\n const activity = agent.getActivityOrThrow();\n if (!activity.tts) {\n throw new Error('ttsNode called but no TTS node is available');\n }\n\n let wrappedTts = activity.tts;\n\n if (!activity.tts.capabilities.streaming) {\n wrappedTts = new TTSStreamAdapter(wrappedTts, new BasicSentenceTokenizer());\n }\n\n const connOptions = activity.agentSession.connOptions.ttsConnOptions;\n const stream = wrappedTts.stream({ connOptions });\n stream.updateInputStream(text);\n\n let cleaned = false;\n const cleanup = () => {\n if (cleaned) return;\n cleaned = true;\n stream.close();\n };\n\n return new ReadableStream({\n async start(controller) {\n try {\n for await (const chunk of stream) {\n if (chunk === SynthesizeStream.END_OF_STREAM) {\n break;\n }\n // Attach timed transcripts to frame.userdata\n if (chunk.timedTranscripts && chunk.timedTranscripts.length > 0) {\n chunk.frame.userdata[USERDATA_TIMED_TRANSCRIPT] = chunk.timedTranscripts;\n }\n controller.enqueue(chunk.frame);\n }\n controller.close();\n } finally {\n cleanup();\n }\n },\n cancel() {\n cleanup();\n },\n });\n },\n\n async transcriptionNode(\n agent: Agent,\n text: ReadableStream<string | TimedString>,\n _modelSettings: ModelSettings,\n ): Promise<ReadableStream<string | TimedString> | null> {\n return text;\n },\n\n async realtimeAudioOutputNode(\n _agent: Agent,\n audio: ReadableStream<AudioFrame>,\n _modelSettings: ModelSettings,\n ): Promise<ReadableStream<AudioFrame> | null> {\n return audio;\n },\n };\n}\n\nexport class AgentTask<ResultT = unknown, UserData = any> extends Agent<UserData> {\n private started = false;\n private future = new Future<ResultT>();\n\n #logger = log();\n\n get done(): boolean {\n return this.future.done;\n }\n\n complete(result: ResultT | Error): void {\n if (this.future.done) {\n throw new Error(`${this.constructor.name} is already done`);\n }\n\n if (result instanceof Error) {\n this.future.reject(result);\n } else {\n this.future.resolve(result);\n }\n\n const speechHandle = speechHandleStorage.getStore();\n if (speechHandle) {\n speechHandle._maybeRunFinalOutput = result;\n }\n }\n\n async run(): Promise<ResultT> {\n if (this.started) {\n throw new Error(\n `Task ${this.constructor.name} has already started and cannot be awaited multiple times`,\n );\n }\n this.started = true;\n\n const currentTask = Task.current();\n if (!currentTask) {\n throw new Error(`${this.constructor.name} must be executed inside a Task context`);\n }\n\n const taskInfo = _getActivityTaskInfo(currentTask);\n if (!taskInfo || !taskInfo.inlineTask) {\n throw new Error(\n `${this.constructor.name} should only be awaited inside function tools or the onEnter/onExit methods of an Agent`,\n );\n }\n\n const speechHandle = speechHandleStorage.getStore();\n const oldActivity = agentActivityStorage.getStore();\n if (!oldActivity) {\n throw new Error(`${this.constructor.name} must be executed inside an AgentActivity context`);\n }\n\n currentTask.addDoneCallback(() => {\n if (this.future.done) return;\n\n // If the Task finished before the AgentTask was completed, complete the AgentTask with an error.\n this.#logger.error(`The Task finished before ${this.constructor.name} was completed.`);\n this.complete(new Error(`The Task finished before ${this.constructor.name} was completed.`));\n });\n\n const oldAgent = oldActivity.agent;\n const session = oldActivity.agentSession;\n\n const blockedTasks: Task<any>[] = [currentTask];\n const onEnterTask = oldActivity._onEnterTask;\n\n if (onEnterTask && !onEnterTask.done && onEnterTask !== currentTask) {\n blockedTasks.push(onEnterTask);\n }\n\n if (\n taskInfo.functionCall &&\n oldActivity.llm instanceof RealtimeModel &&\n !oldActivity.llm.capabilities.manualFunctionCalls\n ) {\n this.#logger.error(\n `Realtime model does not support resuming function calls from chat context, ` +\n `using AgentTask inside a function tool may have unexpected behavior.`,\n );\n }\n\n await session._updateActivity(this, {\n previousActivity: 'pause',\n newActivity: 'start',\n blockedTasks,\n });\n\n let runState = session._globalRunState;\n if (speechHandle && runState && !runState.done()) {\n // Only unwatch the parent speech handle if there are other handles keeping the run alive.\n // When watchedHandleCount is 1 (only the parent), unwatching would drop it to 0 and\n // mark the run done prematurely — before function_call_output and assistant message arrive.\n if (runState._watchedHandleCount() > 1) {\n runState._unwatchHandle(speechHandle);\n }\n // it is OK to call _markDoneIfNeeded here, the above _updateActivity will call onEnter\n // and newly added handles keep the run alive.\n runState._markDoneIfNeeded();\n }\n\n try {\n return await this.future.await;\n } finally {\n // runState could have changed after future resolved\n runState = session._globalRunState;\n\n if (session.currentAgent !== this) {\n this.#logger.warn(\n `${this.constructor.name} completed, but the agent has changed in the meantime. ` +\n `Ignoring handoff to the previous agent, likely due to AgentSession.updateAgent being invoked.`,\n );\n await oldActivity.close();\n } else {\n if (speechHandle && runState && !runState.done()) {\n runState._watchHandle(speechHandle);\n }\n\n const mergedChatCtx = oldAgent._chatCtx.merge(this._chatCtx, {\n excludeFunctionCall: true,\n excludeInstructions: true,\n });\n oldAgent._chatCtx.items = mergedChatCtx.items;\n\n await session._updateActivity(oldAgent, {\n previousActivity: 'close',\n newActivity: 'resume',\n waitOnEnter: false,\n });\n }\n }\n }\n}\n"],"mappings":"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","names":["InferenceSTT","InferenceLLM","InferenceTTS","STTStreamAdapter","TTSStreamAdapter","BasicSentenceTokenizer"]}
|
package/dist/voice/agent.d.cts
CHANGED
|
@@ -92,6 +92,7 @@ export declare class Agent<UserData = any> {
|
|
|
92
92
|
realtimeAudioOutputNode(audio: ReadableStream<AudioFrame>, modelSettings: ModelSettings): Promise<ReadableStream<AudioFrame> | null>;
|
|
93
93
|
getActivityOrThrow(): AgentActivity;
|
|
94
94
|
updateChatCtx(chatCtx: ChatContext): Promise<void>;
|
|
95
|
+
updateTools(tools: ToolContext): Promise<void>;
|
|
95
96
|
static default: {
|
|
96
97
|
sttNode(agent: Agent, audio: ReadableStream<AudioFrame>, _modelSettings: ModelSettings): Promise<ReadableStream<SpeechEvent | string> | null>;
|
|
97
98
|
llmNode(agent: Agent, chatCtx: ChatContext, toolCtx: ToolContext, modelSettings: ModelSettings): Promise<ReadableStream<ChatChunk | string> | null>;
|
package/dist/voice/agent.d.ts
CHANGED
|
@@ -92,6 +92,7 @@ export declare class Agent<UserData = any> {
|
|
|
92
92
|
realtimeAudioOutputNode(audio: ReadableStream<AudioFrame>, modelSettings: ModelSettings): Promise<ReadableStream<AudioFrame> | null>;
|
|
93
93
|
getActivityOrThrow(): AgentActivity;
|
|
94
94
|
updateChatCtx(chatCtx: ChatContext): Promise<void>;
|
|
95
|
+
updateTools(tools: ToolContext): Promise<void>;
|
|
95
96
|
static default: {
|
|
96
97
|
sttNode(agent: Agent, audio: ReadableStream<AudioFrame>, _modelSettings: ModelSettings): Promise<ReadableStream<SpeechEvent | string> | null>;
|
|
97
98
|
llmNode(agent: Agent, chatCtx: ChatContext, toolCtx: ToolContext, modelSettings: ModelSettings): Promise<ReadableStream<ChatChunk | string> | null>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/voice/agent.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/voice/agent.ts"],"names":[],"mappings":"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"}
|
package/dist/voice/agent.js
CHANGED
|
@@ -182,6 +182,15 @@ class Agent {
|
|
|
182
182
|
}
|
|
183
183
|
this._agentActivity.updateChatCtx(chatCtx);
|
|
184
184
|
}
|
|
185
|
+
// TODO(parity): Add when AgentConfigUpdate is ported to ChatContext.
|
|
186
|
+
async updateTools(tools) {
|
|
187
|
+
if (!this._agentActivity) {
|
|
188
|
+
this._tools = { ...tools };
|
|
189
|
+
this._chatCtx = this._chatCtx.copy({ toolCtx: this._tools });
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
await this._agentActivity.updateTools(tools);
|
|
193
|
+
}
|
|
185
194
|
static default = {
|
|
186
195
|
async sttNode(agent, audio, _modelSettings) {
|
|
187
196
|
var _a;
|
package/dist/voice/agent.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/voice/agent.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { AudioFrame } from '@livekit/rtc-node';\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport { ReadableStream } from 'node:stream/web';\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 { ReadonlyChatContext } from '../llm/chat_context.js';\nimport type { ChatMessage, FunctionCall } from '../llm/index.js';\nimport {\n type ChatChunk,\n ChatContext,\n LLM,\n RealtimeModel,\n type ToolChoice,\n type ToolContext,\n} from '../llm/index.js';\nimport { log } from '../log.js';\nimport type { STT, SpeechEvent } from '../stt/index.js';\nimport { StreamAdapter as STTStreamAdapter } from '../stt/index.js';\nimport { SentenceTokenizer as BasicSentenceTokenizer } from '../tokenize/basic/index.js';\nimport type { TTS } from '../tts/index.js';\nimport { SynthesizeStream, StreamAdapter as TTSStreamAdapter } from '../tts/index.js';\nimport { USERDATA_TIMED_TRANSCRIPT } from '../types.js';\nimport { Future, Task } from '../utils.js';\nimport type { VAD } from '../vad.js';\nimport { type AgentActivity, agentActivityStorage } from './agent_activity.js';\nimport type { AgentSession, TurnDetectionMode } from './agent_session.js';\nimport type { TimedString } from './io.js';\nimport type { SpeechHandle } from './speech_handle.js';\n\nexport const functionCallStorage = new AsyncLocalStorage<{ functionCall?: FunctionCall }>();\nexport const speechHandleStorage = new AsyncLocalStorage<SpeechHandle>();\nconst activityTaskInfoStorage = new WeakMap<Task<any>, _ActivityTaskInfo>();\n\ntype _ActivityTaskInfo = {\n functionCall: FunctionCall | null;\n speechHandle: SpeechHandle | null;\n inlineTask: boolean;\n};\n\n/** @internal */\nexport function _setActivityTaskInfo<T>(\n task: Task<T>,\n options: {\n functionCall?: FunctionCall | null;\n speechHandle?: SpeechHandle | null;\n inlineTask?: boolean;\n },\n): void {\n const info = activityTaskInfoStorage.get(task) ?? {\n functionCall: null,\n speechHandle: null,\n inlineTask: false,\n };\n\n if (Object.hasOwn(options, 'functionCall')) {\n info.functionCall = options.functionCall ?? null;\n }\n if (Object.hasOwn(options, 'speechHandle')) {\n info.speechHandle = options.speechHandle ?? null;\n }\n if (Object.hasOwn(options, 'inlineTask')) {\n info.inlineTask = options.inlineTask ?? false;\n }\n\n activityTaskInfoStorage.set(task, info);\n}\n\n/** @internal */\nexport function _getActivityTaskInfo<T>(task: Task<T>): _ActivityTaskInfo | undefined {\n return activityTaskInfoStorage.get(task);\n}\nexport const STOP_RESPONSE_SYMBOL = Symbol('StopResponse');\n\nexport class StopResponse extends Error {\n constructor() {\n super();\n this.name = 'StopResponse';\n\n Object.defineProperty(this, STOP_RESPONSE_SYMBOL, {\n value: true,\n });\n }\n}\n\nexport function isStopResponse(value: unknown): value is StopResponse {\n return (\n value !== undefined &&\n value !== null &&\n typeof value === 'object' &&\n STOP_RESPONSE_SYMBOL in value\n );\n}\n\nexport interface ModelSettings {\n /** The tool choice to use when calling the LLM. */\n toolChoice?: ToolChoice;\n}\n\nexport interface AgentOptions<UserData> {\n id?: string;\n instructions: string;\n chatCtx?: ChatContext;\n tools?: ToolContext<UserData>;\n turnDetection?: TurnDetectionMode;\n stt?: STT | STTModelString;\n vad?: VAD;\n llm?: LLM | RealtimeModel | LLMModels;\n tts?: TTS | TTSModelString;\n allowInterruptions?: boolean;\n minConsecutiveSpeechDelay?: number;\n useTtsAlignedTranscript?: boolean;\n}\n\nexport class Agent<UserData = any> {\n private _id: string;\n private turnDetection?: TurnDetectionMode;\n private _stt?: STT;\n private _vad?: VAD;\n private _llm?: LLM | RealtimeModel;\n private _tts?: TTS;\n private _useTtsAlignedTranscript?: boolean;\n\n /** @internal */\n _agentActivity?: AgentActivity;\n\n /** @internal */\n _chatCtx: ChatContext;\n\n /** @internal */\n _instructions: string;\n\n /** @internal */\n _tools?: ToolContext<UserData>;\n\n constructor({\n id,\n instructions,\n chatCtx,\n tools,\n turnDetection,\n stt,\n vad,\n llm,\n tts,\n useTtsAlignedTranscript,\n }: AgentOptions<UserData>) {\n if (id) {\n this._id = id;\n } else {\n // Convert class name to snake_case\n const className = this.constructor.name;\n if (className === 'Agent') {\n this._id = 'default_agent';\n } else {\n this._id = className\n .replace(/([A-Z])/g, '_$1')\n .toLowerCase()\n .replace(/^_/, '');\n }\n }\n\n this._instructions = instructions;\n this._tools = { ...tools };\n this._chatCtx = chatCtx\n ? chatCtx.copy({\n toolCtx: this._tools,\n })\n : ChatContext.empty();\n\n this.turnDetection = turnDetection;\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._useTtsAlignedTranscript = useTtsAlignedTranscript;\n\n this._agentActivity = undefined;\n }\n\n get vad(): VAD | undefined {\n return this._vad;\n }\n\n get stt(): STT | undefined {\n return this._stt;\n }\n\n get llm(): LLM | RealtimeModel | undefined {\n return this._llm;\n }\n\n get tts(): TTS | undefined {\n return this._tts;\n }\n\n get useTtsAlignedTranscript(): boolean | undefined {\n return this._useTtsAlignedTranscript;\n }\n\n get chatCtx(): ReadonlyChatContext {\n return new ReadonlyChatContext(this._chatCtx.items);\n }\n\n get id(): string {\n return this._id;\n }\n\n get instructions(): string {\n return this._instructions;\n }\n\n get toolCtx(): ToolContext<UserData> {\n return { ...this._tools };\n }\n\n get session(): AgentSession<UserData> {\n return this.getActivityOrThrow().agentSession as AgentSession<UserData>;\n }\n\n async onEnter(): Promise<void> {}\n\n async onExit(): Promise<void> {}\n\n async transcriptionNode(\n text: ReadableStream<string | TimedString>,\n modelSettings: ModelSettings,\n ): Promise<ReadableStream<string | TimedString> | null> {\n return Agent.default.transcriptionNode(this, text, modelSettings);\n }\n\n async onUserTurnCompleted(_chatCtx: ChatContext, _newMessage: ChatMessage): Promise<void> {}\n\n async sttNode(\n audio: ReadableStream<AudioFrame>,\n modelSettings: ModelSettings,\n ): Promise<ReadableStream<SpeechEvent | string> | null> {\n return Agent.default.sttNode(this, audio, modelSettings);\n }\n\n async llmNode(\n chatCtx: ChatContext,\n toolCtx: ToolContext,\n modelSettings: ModelSettings,\n ): Promise<ReadableStream<ChatChunk | string> | null> {\n return Agent.default.llmNode(this, chatCtx, toolCtx, modelSettings);\n }\n\n async ttsNode(\n text: ReadableStream<string>,\n modelSettings: ModelSettings,\n ): Promise<ReadableStream<AudioFrame> | null> {\n return Agent.default.ttsNode(this, text, modelSettings);\n }\n\n async realtimeAudioOutputNode(\n audio: ReadableStream<AudioFrame>,\n modelSettings: ModelSettings,\n ): Promise<ReadableStream<AudioFrame> | null> {\n return Agent.default.realtimeAudioOutputNode(this, audio, modelSettings);\n }\n\n // realtime_audio_output_node\n\n getActivityOrThrow(): AgentActivity {\n if (!this._agentActivity) {\n throw new Error('Agent activity not found');\n }\n return this._agentActivity;\n }\n\n async updateChatCtx(chatCtx: ChatContext): Promise<void> {\n if (!this._agentActivity) {\n this._chatCtx = chatCtx.copy({ toolCtx: this.toolCtx });\n return;\n }\n\n this._agentActivity.updateChatCtx(chatCtx);\n }\n\n static default = {\n async sttNode(\n agent: Agent,\n audio: ReadableStream<AudioFrame>,\n _modelSettings: ModelSettings,\n ): Promise<ReadableStream<SpeechEvent | string> | null> {\n const activity = agent.getActivityOrThrow();\n if (!activity.stt) {\n throw new Error('sttNode called but no STT node is available');\n }\n\n let wrappedStt = activity.stt;\n\n if (!wrappedStt.capabilities.streaming) {\n const vad = agent.vad || activity.vad;\n if (!vad) {\n throw new Error(\n 'STT does not support streaming, add a VAD to the AgentTask/VoiceAgent to enable streaming',\n );\n }\n wrappedStt = new STTStreamAdapter(wrappedStt, vad);\n }\n\n const connOptions = activity.agentSession.connOptions.sttConnOptions;\n const stream = wrappedStt.stream({ connOptions });\n\n // Set startTimeOffset to provide linear timestamps across reconnections\n const audioInputStartedAt =\n activity.agentSession._recorderIO?.recordingStartedAt ?? // Use recording start time if available\n activity.agentSession._startedAt ?? // Fallback to session start time\n Date.now(); // Fallback to current time\n\n stream.startTimeOffset = (Date.now() - audioInputStartedAt) / 1000;\n\n stream.updateInputStream(audio);\n\n let cleaned = false;\n const cleanup = () => {\n if (cleaned) return;\n cleaned = true;\n stream.detachInputStream();\n stream.close();\n };\n\n return new ReadableStream({\n async start(controller) {\n try {\n for await (const event of stream) {\n controller.enqueue(event);\n }\n controller.close();\n } finally {\n // Always clean up the STT stream, whether it ends naturally or is cancelled\n cleanup();\n }\n },\n cancel() {\n cleanup();\n },\n });\n },\n\n async llmNode(\n agent: Agent,\n chatCtx: ChatContext,\n toolCtx: ToolContext,\n modelSettings: ModelSettings,\n ): Promise<ReadableStream<ChatChunk | string> | null> {\n const activity = agent.getActivityOrThrow();\n if (!activity.llm) {\n throw new Error('llmNode called but no LLM node is available');\n }\n\n if (!(activity.llm instanceof LLM)) {\n throw new Error(\n 'llmNode should only be used with LLM (non-multimodal/realtime APIs) nodes',\n );\n }\n\n const { toolChoice } = modelSettings;\n const connOptions = activity.agentSession.connOptions.llmConnOptions;\n\n // parallelToolCalls is not passed here - it will use the value from LLM's modelOptions\n // This allows users to configure it via: new inference.LLM({ modelOptions: { parallel_tool_calls: false } })\n const stream = activity.llm.chat({\n chatCtx,\n toolCtx,\n toolChoice,\n connOptions,\n });\n\n let cleaned = false;\n const cleanup = () => {\n if (cleaned) return;\n cleaned = true;\n stream.close();\n };\n\n return new ReadableStream({\n async start(controller) {\n try {\n for await (const chunk of stream) {\n controller.enqueue(chunk);\n }\n controller.close();\n } finally {\n cleanup();\n }\n },\n cancel() {\n cleanup();\n },\n });\n },\n\n async ttsNode(\n agent: Agent,\n text: ReadableStream<string>,\n _modelSettings: ModelSettings,\n ): Promise<ReadableStream<AudioFrame> | null> {\n const activity = agent.getActivityOrThrow();\n if (!activity.tts) {\n throw new Error('ttsNode called but no TTS node is available');\n }\n\n let wrappedTts = activity.tts;\n\n if (!activity.tts.capabilities.streaming) {\n wrappedTts = new TTSStreamAdapter(wrappedTts, new BasicSentenceTokenizer());\n }\n\n const connOptions = activity.agentSession.connOptions.ttsConnOptions;\n const stream = wrappedTts.stream({ connOptions });\n stream.updateInputStream(text);\n\n let cleaned = false;\n const cleanup = () => {\n if (cleaned) return;\n cleaned = true;\n stream.close();\n };\n\n return new ReadableStream({\n async start(controller) {\n try {\n for await (const chunk of stream) {\n if (chunk === SynthesizeStream.END_OF_STREAM) {\n break;\n }\n // Attach timed transcripts to frame.userdata\n if (chunk.timedTranscripts && chunk.timedTranscripts.length > 0) {\n chunk.frame.userdata[USERDATA_TIMED_TRANSCRIPT] = chunk.timedTranscripts;\n }\n controller.enqueue(chunk.frame);\n }\n controller.close();\n } finally {\n cleanup();\n }\n },\n cancel() {\n cleanup();\n },\n });\n },\n\n async transcriptionNode(\n agent: Agent,\n text: ReadableStream<string | TimedString>,\n _modelSettings: ModelSettings,\n ): Promise<ReadableStream<string | TimedString> | null> {\n return text;\n },\n\n async realtimeAudioOutputNode(\n _agent: Agent,\n audio: ReadableStream<AudioFrame>,\n _modelSettings: ModelSettings,\n ): Promise<ReadableStream<AudioFrame> | null> {\n return audio;\n },\n };\n}\n\nexport class AgentTask<ResultT = unknown, UserData = any> extends Agent<UserData> {\n private started = false;\n private future = new Future<ResultT>();\n\n #logger = log();\n\n get done(): boolean {\n return this.future.done;\n }\n\n complete(result: ResultT | Error): void {\n if (this.future.done) {\n throw new Error(`${this.constructor.name} is already done`);\n }\n\n if (result instanceof Error) {\n this.future.reject(result);\n } else {\n this.future.resolve(result);\n }\n\n const speechHandle = speechHandleStorage.getStore();\n if (speechHandle) {\n speechHandle._maybeRunFinalOutput = result;\n }\n }\n\n async run(): Promise<ResultT> {\n if (this.started) {\n throw new Error(\n `Task ${this.constructor.name} has already started and cannot be awaited multiple times`,\n );\n }\n this.started = true;\n\n const currentTask = Task.current();\n if (!currentTask) {\n throw new Error(`${this.constructor.name} must be executed inside a Task context`);\n }\n\n const taskInfo = _getActivityTaskInfo(currentTask);\n if (!taskInfo || !taskInfo.inlineTask) {\n throw new Error(\n `${this.constructor.name} should only be awaited inside function tools or the onEnter/onExit methods of an Agent`,\n );\n }\n\n const speechHandle = speechHandleStorage.getStore();\n const oldActivity = agentActivityStorage.getStore();\n if (!oldActivity) {\n throw new Error(`${this.constructor.name} must be executed inside an AgentActivity context`);\n }\n\n currentTask.addDoneCallback(() => {\n if (this.future.done) return;\n\n // If the Task finished before the AgentTask was completed, complete the AgentTask with an error.\n this.#logger.error(`The Task finished before ${this.constructor.name} was completed.`);\n this.complete(new Error(`The Task finished before ${this.constructor.name} was completed.`));\n });\n\n const oldAgent = oldActivity.agent;\n const session = oldActivity.agentSession;\n\n const blockedTasks: Task<any>[] = [currentTask];\n const onEnterTask = oldActivity._onEnterTask;\n\n if (onEnterTask && !onEnterTask.done && onEnterTask !== currentTask) {\n blockedTasks.push(onEnterTask);\n }\n\n if (\n taskInfo.functionCall &&\n oldActivity.llm instanceof RealtimeModel &&\n !oldActivity.llm.capabilities.manualFunctionCalls\n ) {\n this.#logger.error(\n `Realtime model does not support resuming function calls from chat context, ` +\n `using AgentTask inside a function tool may have unexpected behavior.`,\n );\n }\n\n await session._updateActivity(this, {\n previousActivity: 'pause',\n newActivity: 'start',\n blockedTasks,\n });\n\n let runState = session._globalRunState;\n if (speechHandle && runState && !runState.done()) {\n // Only unwatch the parent speech handle if there are other handles keeping the run alive.\n // When watchedHandleCount is 1 (only the parent), unwatching would drop it to 0 and\n // mark the run done prematurely — before function_call_output and assistant message arrive.\n if (runState._watchedHandleCount() > 1) {\n runState._unwatchHandle(speechHandle);\n }\n // it is OK to call _markDoneIfNeeded here, the above _updateActivity will call onEnter\n // and newly added handles keep the run alive.\n runState._markDoneIfNeeded();\n }\n\n try {\n return await this.future.await;\n } finally {\n // runState could have changed after future resolved\n runState = session._globalRunState;\n\n if (session.currentAgent !== this) {\n this.#logger.warn(\n `${this.constructor.name} completed, but the agent has changed in the meantime. ` +\n `Ignoring handoff to the previous agent, likely due to AgentSession.updateAgent being invoked.`,\n );\n await oldActivity.close();\n } else {\n if (speechHandle && runState && !runState.done()) {\n runState._watchHandle(speechHandle);\n }\n\n const mergedChatCtx = oldAgent._chatCtx.merge(this._chatCtx, {\n excludeFunctionCall: true,\n excludeInstructions: true,\n });\n oldAgent._chatCtx.items = mergedChatCtx.items;\n\n await session._updateActivity(oldAgent, {\n previousActivity: 'close',\n newActivity: 'resume',\n waitOnEnter: false,\n });\n }\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/voice/agent.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { AudioFrame } from '@livekit/rtc-node';\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport { ReadableStream } from 'node:stream/web';\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 { ReadonlyChatContext } from '../llm/chat_context.js';\nimport type { ChatMessage, FunctionCall } from '../llm/index.js';\nimport {\n type ChatChunk,\n ChatContext,\n LLM,\n RealtimeModel,\n type ToolChoice,\n type ToolContext,\n} from '../llm/index.js';\nimport { log } from '../log.js';\nimport type { STT, SpeechEvent } from '../stt/index.js';\nimport { StreamAdapter as STTStreamAdapter } from '../stt/index.js';\nimport { SentenceTokenizer as BasicSentenceTokenizer } from '../tokenize/basic/index.js';\nimport type { TTS } from '../tts/index.js';\nimport { SynthesizeStream, StreamAdapter as TTSStreamAdapter } from '../tts/index.js';\nimport { USERDATA_TIMED_TRANSCRIPT } from '../types.js';\nimport { Future, Task } from '../utils.js';\nimport type { VAD } from '../vad.js';\nimport { type AgentActivity, agentActivityStorage } from './agent_activity.js';\nimport type { AgentSession, TurnDetectionMode } from './agent_session.js';\nimport type { TimedString } from './io.js';\nimport type { SpeechHandle } from './speech_handle.js';\n\nexport const functionCallStorage = new AsyncLocalStorage<{ functionCall?: FunctionCall }>();\nexport const speechHandleStorage = new AsyncLocalStorage<SpeechHandle>();\nconst activityTaskInfoStorage = new WeakMap<Task<any>, _ActivityTaskInfo>();\n\ntype _ActivityTaskInfo = {\n functionCall: FunctionCall | null;\n speechHandle: SpeechHandle | null;\n inlineTask: boolean;\n};\n\n/** @internal */\nexport function _setActivityTaskInfo<T>(\n task: Task<T>,\n options: {\n functionCall?: FunctionCall | null;\n speechHandle?: SpeechHandle | null;\n inlineTask?: boolean;\n },\n): void {\n const info = activityTaskInfoStorage.get(task) ?? {\n functionCall: null,\n speechHandle: null,\n inlineTask: false,\n };\n\n if (Object.hasOwn(options, 'functionCall')) {\n info.functionCall = options.functionCall ?? null;\n }\n if (Object.hasOwn(options, 'speechHandle')) {\n info.speechHandle = options.speechHandle ?? null;\n }\n if (Object.hasOwn(options, 'inlineTask')) {\n info.inlineTask = options.inlineTask ?? false;\n }\n\n activityTaskInfoStorage.set(task, info);\n}\n\n/** @internal */\nexport function _getActivityTaskInfo<T>(task: Task<T>): _ActivityTaskInfo | undefined {\n return activityTaskInfoStorage.get(task);\n}\nexport const STOP_RESPONSE_SYMBOL = Symbol('StopResponse');\n\nexport class StopResponse extends Error {\n constructor() {\n super();\n this.name = 'StopResponse';\n\n Object.defineProperty(this, STOP_RESPONSE_SYMBOL, {\n value: true,\n });\n }\n}\n\nexport function isStopResponse(value: unknown): value is StopResponse {\n return (\n value !== undefined &&\n value !== null &&\n typeof value === 'object' &&\n STOP_RESPONSE_SYMBOL in value\n );\n}\n\nexport interface ModelSettings {\n /** The tool choice to use when calling the LLM. */\n toolChoice?: ToolChoice;\n}\n\nexport interface AgentOptions<UserData> {\n id?: string;\n instructions: string;\n chatCtx?: ChatContext;\n tools?: ToolContext<UserData>;\n turnDetection?: TurnDetectionMode;\n stt?: STT | STTModelString;\n vad?: VAD;\n llm?: LLM | RealtimeModel | LLMModels;\n tts?: TTS | TTSModelString;\n allowInterruptions?: boolean;\n minConsecutiveSpeechDelay?: number;\n useTtsAlignedTranscript?: boolean;\n}\n\nexport class Agent<UserData = any> {\n private _id: string;\n private turnDetection?: TurnDetectionMode;\n private _stt?: STT;\n private _vad?: VAD;\n private _llm?: LLM | RealtimeModel;\n private _tts?: TTS;\n private _useTtsAlignedTranscript?: boolean;\n\n /** @internal */\n _agentActivity?: AgentActivity;\n\n /** @internal */\n _chatCtx: ChatContext;\n\n /** @internal */\n _instructions: string;\n\n /** @internal */\n _tools?: ToolContext<UserData>;\n\n constructor({\n id,\n instructions,\n chatCtx,\n tools,\n turnDetection,\n stt,\n vad,\n llm,\n tts,\n useTtsAlignedTranscript,\n }: AgentOptions<UserData>) {\n if (id) {\n this._id = id;\n } else {\n // Convert class name to snake_case\n const className = this.constructor.name;\n if (className === 'Agent') {\n this._id = 'default_agent';\n } else {\n this._id = className\n .replace(/([A-Z])/g, '_$1')\n .toLowerCase()\n .replace(/^_/, '');\n }\n }\n\n this._instructions = instructions;\n this._tools = { ...tools };\n this._chatCtx = chatCtx\n ? chatCtx.copy({\n toolCtx: this._tools,\n })\n : ChatContext.empty();\n\n this.turnDetection = turnDetection;\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._useTtsAlignedTranscript = useTtsAlignedTranscript;\n\n this._agentActivity = undefined;\n }\n\n get vad(): VAD | undefined {\n return this._vad;\n }\n\n get stt(): STT | undefined {\n return this._stt;\n }\n\n get llm(): LLM | RealtimeModel | undefined {\n return this._llm;\n }\n\n get tts(): TTS | undefined {\n return this._tts;\n }\n\n get useTtsAlignedTranscript(): boolean | undefined {\n return this._useTtsAlignedTranscript;\n }\n\n get chatCtx(): ReadonlyChatContext {\n return new ReadonlyChatContext(this._chatCtx.items);\n }\n\n get id(): string {\n return this._id;\n }\n\n get instructions(): string {\n return this._instructions;\n }\n\n get toolCtx(): ToolContext<UserData> {\n return { ...this._tools };\n }\n\n get session(): AgentSession<UserData> {\n return this.getActivityOrThrow().agentSession as AgentSession<UserData>;\n }\n\n async onEnter(): Promise<void> {}\n\n async onExit(): Promise<void> {}\n\n async transcriptionNode(\n text: ReadableStream<string | TimedString>,\n modelSettings: ModelSettings,\n ): Promise<ReadableStream<string | TimedString> | null> {\n return Agent.default.transcriptionNode(this, text, modelSettings);\n }\n\n async onUserTurnCompleted(_chatCtx: ChatContext, _newMessage: ChatMessage): Promise<void> {}\n\n async sttNode(\n audio: ReadableStream<AudioFrame>,\n modelSettings: ModelSettings,\n ): Promise<ReadableStream<SpeechEvent | string> | null> {\n return Agent.default.sttNode(this, audio, modelSettings);\n }\n\n async llmNode(\n chatCtx: ChatContext,\n toolCtx: ToolContext,\n modelSettings: ModelSettings,\n ): Promise<ReadableStream<ChatChunk | string> | null> {\n return Agent.default.llmNode(this, chatCtx, toolCtx, modelSettings);\n }\n\n async ttsNode(\n text: ReadableStream<string>,\n modelSettings: ModelSettings,\n ): Promise<ReadableStream<AudioFrame> | null> {\n return Agent.default.ttsNode(this, text, modelSettings);\n }\n\n async realtimeAudioOutputNode(\n audio: ReadableStream<AudioFrame>,\n modelSettings: ModelSettings,\n ): Promise<ReadableStream<AudioFrame> | null> {\n return Agent.default.realtimeAudioOutputNode(this, audio, modelSettings);\n }\n\n // realtime_audio_output_node\n\n getActivityOrThrow(): AgentActivity {\n if (!this._agentActivity) {\n throw new Error('Agent activity not found');\n }\n return this._agentActivity;\n }\n\n async updateChatCtx(chatCtx: ChatContext): Promise<void> {\n if (!this._agentActivity) {\n this._chatCtx = chatCtx.copy({ toolCtx: this.toolCtx });\n return;\n }\n\n this._agentActivity.updateChatCtx(chatCtx);\n }\n\n // TODO(parity): Add when AgentConfigUpdate is ported to ChatContext.\n async updateTools(tools: ToolContext): Promise<void> {\n if (!this._agentActivity) {\n this._tools = { ...tools };\n this._chatCtx = this._chatCtx.copy({ toolCtx: this._tools });\n return;\n }\n\n await this._agentActivity.updateTools(tools);\n }\n\n static default = {\n async sttNode(\n agent: Agent,\n audio: ReadableStream<AudioFrame>,\n _modelSettings: ModelSettings,\n ): Promise<ReadableStream<SpeechEvent | string> | null> {\n const activity = agent.getActivityOrThrow();\n if (!activity.stt) {\n throw new Error('sttNode called but no STT node is available');\n }\n\n let wrappedStt = activity.stt;\n\n if (!wrappedStt.capabilities.streaming) {\n const vad = agent.vad || activity.vad;\n if (!vad) {\n throw new Error(\n 'STT does not support streaming, add a VAD to the AgentTask/VoiceAgent to enable streaming',\n );\n }\n wrappedStt = new STTStreamAdapter(wrappedStt, vad);\n }\n\n const connOptions = activity.agentSession.connOptions.sttConnOptions;\n const stream = wrappedStt.stream({ connOptions });\n\n // Set startTimeOffset to provide linear timestamps across reconnections\n const audioInputStartedAt =\n activity.agentSession._recorderIO?.recordingStartedAt ?? // Use recording start time if available\n activity.agentSession._startedAt ?? // Fallback to session start time\n Date.now(); // Fallback to current time\n\n stream.startTimeOffset = (Date.now() - audioInputStartedAt) / 1000;\n\n stream.updateInputStream(audio);\n\n let cleaned = false;\n const cleanup = () => {\n if (cleaned) return;\n cleaned = true;\n stream.detachInputStream();\n stream.close();\n };\n\n return new ReadableStream({\n async start(controller) {\n try {\n for await (const event of stream) {\n controller.enqueue(event);\n }\n controller.close();\n } finally {\n // Always clean up the STT stream, whether it ends naturally or is cancelled\n cleanup();\n }\n },\n cancel() {\n cleanup();\n },\n });\n },\n\n async llmNode(\n agent: Agent,\n chatCtx: ChatContext,\n toolCtx: ToolContext,\n modelSettings: ModelSettings,\n ): Promise<ReadableStream<ChatChunk | string> | null> {\n const activity = agent.getActivityOrThrow();\n if (!activity.llm) {\n throw new Error('llmNode called but no LLM node is available');\n }\n\n if (!(activity.llm instanceof LLM)) {\n throw new Error(\n 'llmNode should only be used with LLM (non-multimodal/realtime APIs) nodes',\n );\n }\n\n const { toolChoice } = modelSettings;\n const connOptions = activity.agentSession.connOptions.llmConnOptions;\n\n // parallelToolCalls is not passed here - it will use the value from LLM's modelOptions\n // This allows users to configure it via: new inference.LLM({ modelOptions: { parallel_tool_calls: false } })\n const stream = activity.llm.chat({\n chatCtx,\n toolCtx,\n toolChoice,\n connOptions,\n });\n\n let cleaned = false;\n const cleanup = () => {\n if (cleaned) return;\n cleaned = true;\n stream.close();\n };\n\n return new ReadableStream({\n async start(controller) {\n try {\n for await (const chunk of stream) {\n controller.enqueue(chunk);\n }\n controller.close();\n } finally {\n cleanup();\n }\n },\n cancel() {\n cleanup();\n },\n });\n },\n\n async ttsNode(\n agent: Agent,\n text: ReadableStream<string>,\n _modelSettings: ModelSettings,\n ): Promise<ReadableStream<AudioFrame> | null> {\n const activity = agent.getActivityOrThrow();\n if (!activity.tts) {\n throw new Error('ttsNode called but no TTS node is available');\n }\n\n let wrappedTts = activity.tts;\n\n if (!activity.tts.capabilities.streaming) {\n wrappedTts = new TTSStreamAdapter(wrappedTts, new BasicSentenceTokenizer());\n }\n\n const connOptions = activity.agentSession.connOptions.ttsConnOptions;\n const stream = wrappedTts.stream({ connOptions });\n stream.updateInputStream(text);\n\n let cleaned = false;\n const cleanup = () => {\n if (cleaned) return;\n cleaned = true;\n stream.close();\n };\n\n return new ReadableStream({\n async start(controller) {\n try {\n for await (const chunk of stream) {\n if (chunk === SynthesizeStream.END_OF_STREAM) {\n break;\n }\n // Attach timed transcripts to frame.userdata\n if (chunk.timedTranscripts && chunk.timedTranscripts.length > 0) {\n chunk.frame.userdata[USERDATA_TIMED_TRANSCRIPT] = chunk.timedTranscripts;\n }\n controller.enqueue(chunk.frame);\n }\n controller.close();\n } finally {\n cleanup();\n }\n },\n cancel() {\n cleanup();\n },\n });\n },\n\n async transcriptionNode(\n agent: Agent,\n text: ReadableStream<string | TimedString>,\n _modelSettings: ModelSettings,\n ): Promise<ReadableStream<string | TimedString> | null> {\n return text;\n },\n\n async realtimeAudioOutputNode(\n _agent: Agent,\n audio: ReadableStream<AudioFrame>,\n _modelSettings: ModelSettings,\n ): Promise<ReadableStream<AudioFrame> | null> {\n return audio;\n },\n };\n}\n\nexport class AgentTask<ResultT = unknown, UserData = any> extends Agent<UserData> {\n private started = false;\n private future = new Future<ResultT>();\n\n #logger = log();\n\n get done(): boolean {\n return this.future.done;\n }\n\n complete(result: ResultT | Error): void {\n if (this.future.done) {\n throw new Error(`${this.constructor.name} is already done`);\n }\n\n if (result instanceof Error) {\n this.future.reject(result);\n } else {\n this.future.resolve(result);\n }\n\n const speechHandle = speechHandleStorage.getStore();\n if (speechHandle) {\n speechHandle._maybeRunFinalOutput = result;\n }\n }\n\n async run(): Promise<ResultT> {\n if (this.started) {\n throw new Error(\n `Task ${this.constructor.name} has already started and cannot be awaited multiple times`,\n );\n }\n this.started = true;\n\n const currentTask = Task.current();\n if (!currentTask) {\n throw new Error(`${this.constructor.name} must be executed inside a Task context`);\n }\n\n const taskInfo = _getActivityTaskInfo(currentTask);\n if (!taskInfo || !taskInfo.inlineTask) {\n throw new Error(\n `${this.constructor.name} should only be awaited inside function tools or the onEnter/onExit methods of an Agent`,\n );\n }\n\n const speechHandle = speechHandleStorage.getStore();\n const oldActivity = agentActivityStorage.getStore();\n if (!oldActivity) {\n throw new Error(`${this.constructor.name} must be executed inside an AgentActivity context`);\n }\n\n currentTask.addDoneCallback(() => {\n if (this.future.done) return;\n\n // If the Task finished before the AgentTask was completed, complete the AgentTask with an error.\n this.#logger.error(`The Task finished before ${this.constructor.name} was completed.`);\n this.complete(new Error(`The Task finished before ${this.constructor.name} was completed.`));\n });\n\n const oldAgent = oldActivity.agent;\n const session = oldActivity.agentSession;\n\n const blockedTasks: Task<any>[] = [currentTask];\n const onEnterTask = oldActivity._onEnterTask;\n\n if (onEnterTask && !onEnterTask.done && onEnterTask !== currentTask) {\n blockedTasks.push(onEnterTask);\n }\n\n if (\n taskInfo.functionCall &&\n oldActivity.llm instanceof RealtimeModel &&\n !oldActivity.llm.capabilities.manualFunctionCalls\n ) {\n this.#logger.error(\n `Realtime model does not support resuming function calls from chat context, ` +\n `using AgentTask inside a function tool may have unexpected behavior.`,\n );\n }\n\n await session._updateActivity(this, {\n previousActivity: 'pause',\n newActivity: 'start',\n blockedTasks,\n });\n\n let runState = session._globalRunState;\n if (speechHandle && runState && !runState.done()) {\n // Only unwatch the parent speech handle if there are other handles keeping the run alive.\n // When watchedHandleCount is 1 (only the parent), unwatching would drop it to 0 and\n // mark the run done prematurely — before function_call_output and assistant message arrive.\n if (runState._watchedHandleCount() > 1) {\n runState._unwatchHandle(speechHandle);\n }\n // it is OK to call _markDoneIfNeeded here, the above _updateActivity will call onEnter\n // and newly added handles keep the run alive.\n runState._markDoneIfNeeded();\n }\n\n try {\n return await this.future.await;\n } finally {\n // runState could have changed after future resolved\n runState = session._globalRunState;\n\n if (session.currentAgent !== this) {\n this.#logger.warn(\n `${this.constructor.name} completed, but the agent has changed in the meantime. ` +\n `Ignoring handoff to the previous agent, likely due to AgentSession.updateAgent being invoked.`,\n );\n await oldActivity.close();\n } else {\n if (speechHandle && runState && !runState.done()) {\n runState._watchHandle(speechHandle);\n }\n\n const mergedChatCtx = oldAgent._chatCtx.merge(this._chatCtx, {\n excludeFunctionCall: true,\n excludeInstructions: true,\n });\n oldAgent._chatCtx.items = mergedChatCtx.items;\n\n await session._updateActivity(oldAgent, {\n previousActivity: 'close',\n newActivity: 'resume',\n waitOnEnter: false,\n });\n }\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -19,7 +19,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
19
19
|
var agent_activity_exports = {};
|
|
20
20
|
__export(agent_activity_exports, {
|
|
21
21
|
AgentActivity: () => AgentActivity,
|
|
22
|
-
agentActivityStorage: () => agentActivityStorage
|
|
22
|
+
agentActivityStorage: () => agentActivityStorage,
|
|
23
|
+
onEnterStorage: () => onEnterStorage
|
|
23
24
|
});
|
|
24
25
|
module.exports = __toCommonJS(agent_activity_exports);
|
|
25
26
|
var import_mutex = require("@livekit/mutex");
|
|
@@ -46,6 +47,7 @@ var import_generation = require("./generation.cjs");
|
|
|
46
47
|
var import_speech_handle = require("./speech_handle.cjs");
|
|
47
48
|
var import_utils2 = require("./utils.cjs");
|
|
48
49
|
const agentActivityStorage = new import_node_async_hooks.AsyncLocalStorage();
|
|
50
|
+
const onEnterStorage = new import_node_async_hooks.AsyncLocalStorage();
|
|
49
51
|
class AgentActivity {
|
|
50
52
|
agent;
|
|
51
53
|
agentSession;
|
|
@@ -245,11 +247,14 @@ class AgentActivity {
|
|
|
245
247
|
this._resumeSchedulingTask();
|
|
246
248
|
if (runOnEnter) {
|
|
247
249
|
this._onEnterTask = this.createSpeechTask({
|
|
248
|
-
taskFn: () =>
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
250
|
+
taskFn: () => onEnterStorage.run(
|
|
251
|
+
{ session: this.agentSession, agent: this.agent },
|
|
252
|
+
() => import_telemetry.tracer.startActiveSpan(async () => this.agent.onEnter(), {
|
|
253
|
+
name: "on_enter",
|
|
254
|
+
context: import_api.trace.setSpan(import_api.ROOT_CONTEXT, startSpan),
|
|
255
|
+
attributes: { [import_telemetry.traceTypes.ATTR_AGENT_LABEL]: this.agent.id }
|
|
256
|
+
})
|
|
257
|
+
),
|
|
253
258
|
inlineTask: true,
|
|
254
259
|
name: "AgentActivity_onEnter"
|
|
255
260
|
});
|
|
@@ -315,6 +320,16 @@ class AgentActivity {
|
|
|
315
320
|
});
|
|
316
321
|
}
|
|
317
322
|
}
|
|
323
|
+
// TODO: Add when AgentConfigUpdate is ported to ChatContext.
|
|
324
|
+
async updateTools(tools) {
|
|
325
|
+
this.agent._tools = { ...tools };
|
|
326
|
+
if (this.realtimeSession) {
|
|
327
|
+
await this.realtimeSession.updateTools(tools);
|
|
328
|
+
}
|
|
329
|
+
if (this.llm instanceof import_llm.LLM) {
|
|
330
|
+
await this.updateChatCtx(this.agent._chatCtx.copy({ toolCtx: tools }));
|
|
331
|
+
}
|
|
332
|
+
}
|
|
318
333
|
updateOptions({ toolChoice }) {
|
|
319
334
|
if (toolChoice !== void 0) {
|
|
320
335
|
this.toolChoice = toolChoice;
|
|
@@ -326,13 +341,27 @@ class AgentActivity {
|
|
|
326
341
|
attachAudioInput(audioStream) {
|
|
327
342
|
void this.audioStream.close();
|
|
328
343
|
this.audioStream = new import_multi_input_stream.MultiInputStream();
|
|
344
|
+
const aecWarmupAudioFilter = new import_web.TransformStream({
|
|
345
|
+
transform: (frame, controller) => {
|
|
346
|
+
const shouldDiscardForAecWarmup = this.agentSession.agentState === "speaking" && this.agentSession._aecWarmupRemaining > 0;
|
|
347
|
+
if (!shouldDiscardForAecWarmup) {
|
|
348
|
+
controller.enqueue(frame);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
});
|
|
329
352
|
this.audioStreamId = this.audioStream.addInputStream(audioStream);
|
|
330
|
-
|
|
331
|
-
|
|
353
|
+
if (this.realtimeSession && this.audioRecognition) {
|
|
354
|
+
const [realtimeAudioStream, recognitionAudioStream] = this.audioStream.stream.pipeThrough(aecWarmupAudioFilter).tee();
|
|
332
355
|
this.realtimeSession.setInputAudioStream(realtimeAudioStream);
|
|
333
|
-
}
|
|
334
|
-
if (this.audioRecognition) {
|
|
335
356
|
this.audioRecognition.setInputAudioStream(recognitionAudioStream);
|
|
357
|
+
} else if (this.realtimeSession) {
|
|
358
|
+
this.realtimeSession.setInputAudioStream(
|
|
359
|
+
this.audioStream.stream.pipeThrough(aecWarmupAudioFilter)
|
|
360
|
+
);
|
|
361
|
+
} else if (this.audioRecognition) {
|
|
362
|
+
this.audioRecognition.setInputAudioStream(
|
|
363
|
+
this.audioStream.stream.pipeThrough(aecWarmupAudioFilter)
|
|
364
|
+
);
|
|
336
365
|
}
|
|
337
366
|
}
|
|
338
367
|
detachAudioInput() {
|
|
@@ -528,6 +557,9 @@ class AgentActivity {
|
|
|
528
557
|
}
|
|
529
558
|
interruptByAudioActivity() {
|
|
530
559
|
var _a, _b;
|
|
560
|
+
if (this.agentSession._aecWarmupRemaining > 0) {
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
531
563
|
if (this.llm instanceof import_llm.RealtimeModel && this.llm.capabilities.turnDetection) {
|
|
532
564
|
return;
|
|
533
565
|
}
|
|
@@ -806,11 +838,18 @@ class AgentActivity {
|
|
|
806
838
|
instructions = `${this.agent.instructions}
|
|
807
839
|
${instructions}`;
|
|
808
840
|
}
|
|
841
|
+
const onEnterData = onEnterStorage.getStore();
|
|
842
|
+
const shouldFilterTools = (onEnterData == null ? void 0 : onEnterData.agent) === this.agent && (onEnterData == null ? void 0 : onEnterData.session) === this.agentSession;
|
|
843
|
+
const tools = shouldFilterTools ? Object.fromEntries(
|
|
844
|
+
Object.entries(this.agent.toolCtx).filter(
|
|
845
|
+
([, fnTool]) => !(fnTool.flags & import_llm.ToolFlag.IGNORE_ON_ENTER)
|
|
846
|
+
)
|
|
847
|
+
) : this.agent.toolCtx;
|
|
809
848
|
const task = this.createSpeechTask({
|
|
810
849
|
taskFn: (abortController) => this.pipelineReplyTask(
|
|
811
850
|
handle,
|
|
812
851
|
chatCtx ?? this.agent.chatCtx,
|
|
813
|
-
|
|
852
|
+
tools,
|
|
814
853
|
{
|
|
815
854
|
toolChoice: toOaiToolChoice(toolChoice !== void 0 ? toolChoice : this.toolChoice)
|
|
816
855
|
},
|
|
@@ -839,7 +878,16 @@ ${instructions}`;
|
|
|
839
878
|
speech.interrupt(force);
|
|
840
879
|
}
|
|
841
880
|
(_a = this.realtimeSession) == null ? void 0 : _a.interrupt();
|
|
842
|
-
if (
|
|
881
|
+
if (force) {
|
|
882
|
+
for (const task of this.speechTasks) {
|
|
883
|
+
task.cancel();
|
|
884
|
+
}
|
|
885
|
+
if (currentSpeech && !currentSpeech.done()) {
|
|
886
|
+
currentSpeech._markDone();
|
|
887
|
+
}
|
|
888
|
+
this.speechQueue.clear();
|
|
889
|
+
future.resolve();
|
|
890
|
+
} else if (currentSpeech === void 0) {
|
|
843
891
|
future.resolve();
|
|
844
892
|
} else {
|
|
845
893
|
currentSpeech.addDoneCallback(() => {
|
|
@@ -1207,9 +1255,7 @@ ${instructions}`;
|
|
|
1207
1255
|
audioOutput.clearBuffer();
|
|
1208
1256
|
}
|
|
1209
1257
|
replyAbortController.abort();
|
|
1210
|
-
await
|
|
1211
|
-
tasks.map((task) => task.cancelAndWait(AgentActivity.REPLY_TASK_CANCEL_TIMEOUT))
|
|
1212
|
-
);
|
|
1258
|
+
await (0, import_utils.cancelAndWait)(tasks, AgentActivity.REPLY_TASK_CANCEL_TIMEOUT);
|
|
1213
1259
|
let forwardedText = (textOut == null ? void 0 : textOut.text) || "";
|
|
1214
1260
|
if (audioOutput) {
|
|
1215
1261
|
const playbackEv = await audioOutput.waitForPlayout();
|
|
@@ -1839,6 +1885,10 @@ ${instructions}`;
|
|
|
1839
1885
|
const unlock = await this.lock.lock();
|
|
1840
1886
|
try {
|
|
1841
1887
|
this.cancelPreemptiveGeneration();
|
|
1888
|
+
await (0, import_utils.cancelAndWait)(Array.from(this.speechTasks), AgentActivity.REPLY_TASK_CANCEL_TIMEOUT);
|
|
1889
|
+
if (this._currentSpeech && !this._currentSpeech.done()) {
|
|
1890
|
+
this._currentSpeech._markDone();
|
|
1891
|
+
}
|
|
1842
1892
|
await this._closeSessionResources();
|
|
1843
1893
|
if (this._mainTask) {
|
|
1844
1894
|
await this._mainTask.cancelAndWait();
|
|
@@ -1890,6 +1940,7 @@ function toOaiToolChoice(toolChoice) {
|
|
|
1890
1940
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1891
1941
|
0 && (module.exports = {
|
|
1892
1942
|
AgentActivity,
|
|
1893
|
-
agentActivityStorage
|
|
1943
|
+
agentActivityStorage,
|
|
1944
|
+
onEnterStorage
|
|
1894
1945
|
});
|
|
1895
1946
|
//# sourceMappingURL=agent_activity.cjs.map
|