@11labs/client 0.1.3 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/README.md +118 -15
  2. package/dist/BaseConversation.d.ts +76 -0
  3. package/dist/TextConversation.d.ts +4 -0
  4. package/dist/VoiceConversation.d.ts +27 -0
  5. package/dist/dist/BaseConversation.d.ts +80 -0
  6. package/dist/dist/TextConversation.d.ts +4 -0
  7. package/dist/dist/VoiceConversation.d.ts +27 -0
  8. package/dist/dist/index.d.ts +12 -0
  9. package/dist/dist/lib.cjs +2 -0
  10. package/dist/dist/lib.cjs.map +1 -0
  11. package/dist/dist/lib.modern.js +2 -0
  12. package/dist/dist/lib.modern.js.map +1 -0
  13. package/dist/dist/lib.module.js +2 -0
  14. package/dist/dist/lib.module.js.map +1 -0
  15. package/dist/dist/lib.umd.js +2 -0
  16. package/dist/dist/lib.umd.js.map +1 -0
  17. package/dist/dist/utils/BaseConnection.d.ts +99 -0
  18. package/dist/dist/utils/ConnectionFactory.d.ts +2 -0
  19. package/dist/dist/utils/WebRTCConnection.d.ts +23 -0
  20. package/dist/dist/utils/WebSocketConnection.d.ts +13 -0
  21. package/dist/dist/utils/applyDelay.d.ts +2 -0
  22. package/dist/dist/utils/audio.d.ts +2 -0
  23. package/dist/dist/utils/audioConcatProcessor.d.ts +1 -0
  24. package/dist/dist/utils/compatibility.d.ts +2 -0
  25. package/dist/dist/utils/createWorkletModuleLoader.d.ts +1 -0
  26. package/dist/dist/utils/events.d.ts +125 -0
  27. package/dist/dist/utils/input.d.ts +14 -0
  28. package/dist/dist/utils/output.d.ts +10 -0
  29. package/dist/dist/utils/overrides.d.ts +4 -0
  30. package/dist/dist/utils/postOverallFeedback.d.ts +1 -0
  31. package/dist/dist/utils/rawAudioProcessor.d.ts +1 -0
  32. package/dist/dist/version.d.ts +1 -0
  33. package/dist/index.d.ts +9 -77
  34. package/dist/lib.cjs +1 -1
  35. package/dist/lib.cjs.map +1 -1
  36. package/dist/lib.modern.js +1 -1
  37. package/dist/lib.modern.js.map +1 -1
  38. package/dist/lib.module.js +1 -1
  39. package/dist/lib.module.js.map +1 -1
  40. package/dist/lib.umd.js +1 -1
  41. package/dist/lib.umd.js.map +1 -1
  42. package/dist/utils/BaseConnection.d.ts +94 -0
  43. package/dist/utils/ConnectionFactory.d.ts +2 -0
  44. package/dist/utils/WebRTCConnection.d.ts +19 -0
  45. package/dist/utils/WebSocketConnection.d.ts +12 -0
  46. package/dist/utils/applyDelay.d.ts +2 -0
  47. package/dist/utils/events.d.ts +20 -3
  48. package/dist/utils/input.d.ts +1 -1
  49. package/dist/utils/output.d.ts +1 -1
  50. package/dist/utils/overrides.d.ts +4 -0
  51. package/dist/utils/postOverallFeedback.d.ts +1 -0
  52. package/dist/version.d.ts +1 -0
  53. package/package.json +17 -12
  54. package/LICENSE +0 -21
  55. package/dist/utils/connection.d.ts +0 -65
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lib.cjs","sources":["../src/BaseConversation.ts","../src/utils/BaseConnection.ts","../src/version.ts","../src/utils/events.ts","../src/utils/overrides.ts","../src/utils/WebSocketConnection.ts","../src/utils/audio.ts","../src/utils/createWorkletModuleLoader.ts","../src/utils/rawAudioProcessor.ts","../src/utils/WebRTCConnection.ts","../src/utils/ConnectionFactory.ts","../src/utils/compatibility.ts","../src/utils/applyDelay.ts","../src/TextConversation.ts","../src/utils/input.ts","../src/utils/audioConcatProcessor.ts","../src/utils/output.ts","../src/VoiceConversation.ts","../src/index.ts","../src/utils/postOverallFeedback.ts"],"sourcesContent":["import type {\n BaseConnection,\n DisconnectionDetails,\n OnDisconnectCallback,\n SessionConfig,\n} from \"./utils/BaseConnection\";\nimport type {\n AgentAudioEvent,\n AgentResponseEvent,\n ClientToolCallEvent,\n IncomingSocketEvent,\n InternalTentativeAgentResponseEvent,\n InterruptionEvent,\n UserTranscriptionEvent,\n VadScoreEvent,\n} from \"./utils/events\";\nimport type { InputConfig } from \"./utils/input\";\n\nexport type Role = \"user\" | \"ai\";\n\nexport type Mode = \"speaking\" | \"listening\";\n\nexport type Status =\n | \"connecting\"\n | \"connected\"\n | \"disconnecting\"\n | \"disconnected\";\n\nexport type Options = SessionConfig &\n Callbacks &\n ClientToolsConfig &\n InputConfig;\n\nexport type PartialOptions = SessionConfig &\n Partial<Callbacks> &\n Partial<ClientToolsConfig> &\n Partial<InputConfig>;\n\nexport type ClientToolsConfig = {\n clientTools: Record<\n string,\n (\n parameters: any\n ) => Promise<string | number | void> | string | number | void\n >;\n};\n\nexport type Callbacks = {\n onConnect: (props: { conversationId: string }) => void;\n // internal debug events, not to be used\n onDebug: (props: any) => void;\n onDisconnect: OnDisconnectCallback;\n onError: (message: string, context?: any) => void;\n onMessage: (props: { message: string; source: Role }) => void;\n onAudio?: (base64Audio: string) => void;\n onModeChange: (prop: { mode: Mode }) => void;\n onStatusChange: (prop: { status: Status }) => void;\n onCanSendFeedbackChange: (prop: { canSendFeedback: boolean }) => void;\n onUnhandledClientToolCall?: (\n params: ClientToolCallEvent[\"client_tool_call\"]\n ) => void;\n onVadScore?: (props: { vadScore: number }) => void;\n};\n\nconst EMPTY_FREQUENCY_DATA = new Uint8Array(0);\n\nexport class BaseConversation {\n protected lastInterruptTimestamp = 0;\n protected mode: Mode = \"listening\";\n protected status: Status = \"connecting\";\n protected volume = 1;\n protected currentEventId = 1;\n protected lastFeedbackEventId = 0;\n protected canSendFeedback = false;\n\n protected static getFullOptions(partialOptions: PartialOptions): Options {\n return {\n clientTools: {},\n onConnect: () => {},\n onDebug: () => {},\n onDisconnect: () => {},\n onError: () => {},\n onMessage: () => {},\n onAudio: () => {},\n onModeChange: () => {},\n onStatusChange: () => {},\n onCanSendFeedbackChange: () => {},\n ...partialOptions,\n };\n }\n\n protected constructor(\n protected readonly options: Options,\n protected readonly connection: BaseConnection\n ) {\n this.options.onConnect({ conversationId: connection.conversationId });\n this.connection.onMessage(this.onMessage);\n this.connection.onDisconnect(this.endSessionWithDetails);\n this.connection.onModeChange(mode => this.updateMode(mode));\n this.updateStatus(\"connected\");\n }\n\n public endSession() {\n return this.endSessionWithDetails({ reason: \"user\" });\n }\n\n private endSessionWithDetails = async (details: DisconnectionDetails) => {\n if (this.status !== \"connected\" && this.status !== \"connecting\") return;\n this.updateStatus(\"disconnecting\");\n await this.handleEndSession();\n this.updateStatus(\"disconnected\");\n this.options.onDisconnect(details);\n };\n\n protected async handleEndSession() {\n this.connection.close();\n }\n\n protected updateMode(mode: Mode) {\n if (mode !== this.mode) {\n this.mode = mode;\n this.options.onModeChange({ mode });\n }\n }\n\n protected updateStatus(status: Status) {\n if (status !== this.status) {\n this.status = status;\n this.options.onStatusChange({ status });\n }\n }\n\n protected updateCanSendFeedback() {\n const canSendFeedback = this.currentEventId !== this.lastFeedbackEventId;\n if (this.canSendFeedback !== canSendFeedback) {\n this.canSendFeedback = canSendFeedback;\n this.options.onCanSendFeedbackChange({ canSendFeedback });\n }\n }\n\n protected handleInterruption(event: InterruptionEvent) {\n if (event.interruption_event) {\n this.lastInterruptTimestamp = event.interruption_event.event_id;\n }\n }\n\n protected handleAgentResponse(event: AgentResponseEvent) {\n this.options.onMessage({\n source: \"ai\",\n message: event.agent_response_event.agent_response,\n });\n }\n\n protected handleUserTranscript(event: UserTranscriptionEvent) {\n this.options.onMessage({\n source: \"user\",\n message: event.user_transcription_event.user_transcript,\n });\n }\n\n protected handleTentativeAgentResponse(\n event: InternalTentativeAgentResponseEvent\n ) {\n this.options.onDebug({\n type: \"tentative_agent_response\",\n response:\n event.tentative_agent_response_internal_event.tentative_agent_response,\n });\n }\n\n protected handleVadScore(event: VadScoreEvent) {\n if (this.options.onVadScore) {\n this.options.onVadScore({\n vadScore: event.vad_score_event.vad_score,\n });\n }\n }\n\n protected async handleClientToolCall(event: ClientToolCallEvent) {\n if (\n Object.prototype.hasOwnProperty.call(\n this.options.clientTools,\n event.client_tool_call.tool_name\n )\n ) {\n try {\n const result =\n (await this.options.clientTools[event.client_tool_call.tool_name](\n event.client_tool_call.parameters\n )) ?? \"Client tool execution successful.\"; // default client-tool call response\n\n // The API expects result to be a string, so we need to convert it if it's not already a string\n const formattedResult =\n typeof result === \"object\" ? JSON.stringify(result) : String(result);\n\n this.connection.sendMessage({\n type: \"client_tool_result\",\n tool_call_id: event.client_tool_call.tool_call_id,\n result: formattedResult,\n is_error: false,\n });\n } catch (e) {\n this.onError(\n `Client tool execution failed with following error: ${(e as Error)?.message}`,\n {\n clientToolName: event.client_tool_call.tool_name,\n }\n );\n this.connection.sendMessage({\n type: \"client_tool_result\",\n tool_call_id: event.client_tool_call.tool_call_id,\n result: `Client tool execution failed: ${(e as Error)?.message}`,\n is_error: true,\n });\n }\n } else {\n if (this.options.onUnhandledClientToolCall) {\n this.options.onUnhandledClientToolCall(event.client_tool_call);\n\n return;\n }\n\n this.onError(\n `Client tool with name ${event.client_tool_call.tool_name} is not defined on client`,\n {\n clientToolName: event.client_tool_call.tool_name,\n }\n );\n this.connection.sendMessage({\n type: \"client_tool_result\",\n tool_call_id: event.client_tool_call.tool_call_id,\n result: `Client tool with name ${event.client_tool_call.tool_name} is not defined on client`,\n is_error: true,\n });\n }\n }\n\n protected handleAudio(event: AgentAudioEvent) {}\n\n private onMessage = async (parsedEvent: IncomingSocketEvent) => {\n switch (parsedEvent.type) {\n case \"interruption\": {\n this.handleInterruption(parsedEvent);\n return;\n }\n case \"agent_response\": {\n this.handleAgentResponse(parsedEvent);\n return;\n }\n case \"user_transcript\": {\n this.handleUserTranscript(parsedEvent);\n return;\n }\n case \"internal_tentative_agent_response\": {\n this.handleTentativeAgentResponse(parsedEvent);\n return;\n }\n case \"client_tool_call\": {\n await this.handleClientToolCall(parsedEvent);\n return;\n }\n case \"audio\": {\n this.handleAudio(parsedEvent);\n return;\n }\n\n case \"vad_score\": {\n this.handleVadScore(parsedEvent);\n return;\n }\n\n case \"ping\": {\n this.connection.sendMessage({\n type: \"pong\",\n event_id: parsedEvent.ping_event.event_id,\n });\n // parsedEvent.ping_event.ping_ms can be used on client side, for example\n // to warn if ping is too high that experience might be degraded.\n return;\n }\n\n // unhandled events are expected to be internal events\n default: {\n this.options.onDebug(parsedEvent);\n return;\n }\n }\n };\n\n private onError(message: string, context?: any) {\n console.error(message, context);\n this.options.onError(message, context);\n }\n\n public getId() {\n return this.connection.conversationId;\n }\n\n public isOpen() {\n return this.status === \"connected\";\n }\n\n public setVolume = ({ volume }: { volume: number }) => {\n this.volume = volume;\n };\n\n public setMicMuted(isMuted: boolean) {\n this.connection.setMicMuted(isMuted);\n }\n\n public getInputByteFrequencyData() {\n return EMPTY_FREQUENCY_DATA;\n }\n\n public getOutputByteFrequencyData() {\n return EMPTY_FREQUENCY_DATA;\n }\n\n public getInputVolume() {\n return 0;\n }\n\n public getOutputVolume() {\n return 0;\n }\n\n public sendFeedback(like: boolean) {\n if (!this.canSendFeedback) {\n console.warn(\n this.lastFeedbackEventId === 0\n ? \"Cannot send feedback: the conversation has not started yet.\"\n : \"Cannot send feedback: feedback has already been sent for the current response.\"\n );\n return;\n }\n\n this.connection.sendMessage({\n type: \"feedback\",\n score: like ? \"like\" : \"dislike\",\n event_id: this.currentEventId,\n });\n this.lastFeedbackEventId = this.currentEventId;\n this.updateCanSendFeedback();\n }\n\n public sendContextualUpdate(text: string) {\n this.connection.sendMessage({\n type: \"contextual_update\",\n text,\n });\n }\n\n public sendUserMessage(text: string) {\n this.connection.sendMessage({\n type: \"user_message\",\n text,\n });\n }\n\n public sendUserActivity() {\n this.connection.sendMessage({\n type: \"user_activity\",\n });\n }\n\n public sendMCPToolApprovalResult(toolCallId: string, isApproved: boolean) {\n this.connection.sendMessage({\n type: \"mcp_tool_approval_result\",\n tool_call_id: toolCallId,\n is_approved: isApproved,\n });\n }\n}\n","import type { IncomingSocketEvent, OutgoingSocketEvent } from \"./events\";\nimport type { Mode } from \"../BaseConversation\";\n\nexport type Language =\n | \"en\"\n | \"ja\"\n | \"zh\"\n | \"de\"\n | \"hi\"\n | \"fr\"\n | \"ko\"\n | \"pt\"\n | \"pt-br\"\n | \"it\"\n | \"es\"\n | \"id\"\n | \"nl\"\n | \"tr\"\n | \"pl\"\n | \"sv\"\n | \"bg\"\n | \"ro\"\n | \"ar\"\n | \"cs\"\n | \"el\"\n | \"fi\"\n | \"ms\"\n | \"da\"\n | \"ta\"\n | \"uk\"\n | \"ru\"\n | \"hu\"\n | \"hr\"\n | \"sk\"\n | \"no\"\n | \"vi\"\n | \"tl\";\n\nexport type DelayConfig = {\n default: number;\n android?: number;\n ios?: number;\n};\n\nexport type FormatConfig = {\n format: \"pcm\" | \"ulaw\";\n sampleRate: number;\n};\n\nexport type DisconnectionDetails =\n | {\n reason: \"error\";\n message: string;\n context: Event;\n }\n | {\n reason: \"agent\";\n context: CloseEvent;\n }\n | {\n reason: \"user\";\n };\n\nexport type OnDisconnectCallback = (details: DisconnectionDetails) => void;\nexport type OnMessageCallback = (event: IncomingSocketEvent) => void;\n\nexport type BaseSessionConfig = {\n origin?: string;\n authorization?: string;\n livekitUrl?: string;\n overrides?: {\n agent?: {\n prompt?: {\n prompt?: string;\n };\n firstMessage?: string;\n language?: Language;\n };\n tts?: {\n voiceId?: string;\n };\n conversation?: {\n textOnly?: boolean;\n };\n client?: {\n source?: string;\n version?: string;\n };\n };\n customLlmExtraBody?: unknown;\n dynamicVariables?: Record<string, string | number | boolean>;\n useWakeLock?: boolean;\n connectionDelay?: DelayConfig;\n textOnly?: boolean;\n userId?: string;\n};\n\nexport type ConnectionType = \"websocket\" | \"webrtc\";\n\nexport type PublicSessionConfig = BaseSessionConfig & {\n agentId: string;\n connectionType: ConnectionType;\n signedUrl?: never;\n conversationToken?: never;\n};\n\nexport type PrivateWebSocketSessionConfig = BaseSessionConfig & {\n signedUrl: string;\n connectionType?: \"websocket\";\n agentId?: never;\n conversationToken?: never;\n};\n\nexport type PrivateWebRTCSessionConfig = BaseSessionConfig & {\n conversationToken: string;\n connectionType?: \"webrtc\";\n agentId?: never;\n signedUrl?: never;\n};\n\n// Union type for all possible session configurations\nexport type SessionConfig =\n | PublicSessionConfig\n | PrivateWebSocketSessionConfig\n | PrivateWebRTCSessionConfig;\n\nexport abstract class BaseConnection {\n public abstract readonly conversationId: string;\n public abstract readonly inputFormat: FormatConfig;\n public abstract readonly outputFormat: FormatConfig;\n\n protected queue: IncomingSocketEvent[] = [];\n protected disconnectionDetails: DisconnectionDetails | null = null;\n protected onDisconnectCallback: OnDisconnectCallback | null = null;\n protected onMessageCallback: OnMessageCallback | null = null;\n protected onModeChangeCallback: ((mode: Mode) => void) | null = null;\n protected onDebug?: (info: unknown) => void;\n\n constructor(config: { onDebug?: (info: unknown) => void } = {}) {\n this.onDebug = config.onDebug;\n }\n\n protected debug(info: unknown) {\n if (this.onDebug) this.onDebug(info);\n }\n\n public abstract close(): void;\n public abstract sendMessage(message: OutgoingSocketEvent): void;\n public abstract setMicMuted(isMuted: boolean): Promise<void>;\n\n public onMessage(callback: OnMessageCallback) {\n this.onMessageCallback = callback;\n const queue = this.queue;\n this.queue = [];\n\n if (queue.length > 0) {\n // Make sure the queue is flushed after the constructors finishes and\n // classes are initialized.\n queueMicrotask(() => {\n queue.forEach(callback);\n });\n }\n }\n\n public onDisconnect(callback: OnDisconnectCallback) {\n this.onDisconnectCallback = callback;\n const details = this.disconnectionDetails;\n if (details) {\n // Make sure the event is triggered after the constructors finishes and\n // classes are initialized.\n queueMicrotask(() => {\n callback(details);\n });\n }\n }\n\n public onModeChange(callback: (mode: Mode) => void) {\n this.onModeChangeCallback = callback;\n }\n\n protected updateMode(mode: Mode) {\n this.onModeChangeCallback?.(mode);\n }\n\n protected disconnect(details: DisconnectionDetails) {\n if (!this.disconnectionDetails) {\n this.disconnectionDetails = details;\n this.onDisconnectCallback?.(details);\n }\n }\n\n protected handleMessage(parsedEvent: IncomingSocketEvent) {\n if (this.onMessageCallback) {\n this.onMessageCallback(parsedEvent);\n } else {\n this.queue.push(parsedEvent);\n }\n }\n}\n\nexport function parseFormat(format: string): FormatConfig {\n const [formatPart, sampleRatePart] = format.split(\"_\");\n if (![\"pcm\", \"ulaw\"].includes(formatPart)) {\n throw new Error(`Invalid format: ${format}`);\n }\n\n const sampleRate = Number.parseInt(sampleRatePart);\n if (Number.isNaN(sampleRate)) {\n throw new Error(`Invalid sample rate: ${sampleRatePart}`);\n }\n\n return {\n format: formatPart as FormatConfig[\"format\"],\n sampleRate,\n };\n}\n","// This file is auto-generated during build\nexport const PACKAGE_VERSION = \"0.5.0\";\n","import type { Language } from \"./connection\";\nimport type { CONVERSATION_INITIATION_CLIENT_DATA_TYPE } from \"./overrides\";\n\nexport type UserTranscriptionEvent = {\n type: \"user_transcript\";\n user_transcription_event: { user_transcript: string };\n};\nexport type AgentResponseEvent = {\n type: \"agent_response\";\n agent_response_event: { agent_response: string };\n};\nexport type AgentAudioEvent = {\n type: \"audio\";\n audio_event: {\n audio_base_64: string;\n event_id: number;\n };\n};\nexport type InterruptionEvent = {\n type: \"interruption\";\n interruption_event: {\n event_id: number;\n };\n};\nexport type InternalTentativeAgentResponseEvent = {\n type: \"internal_tentative_agent_response\";\n tentative_agent_response_internal_event: {\n tentative_agent_response: string;\n };\n};\nexport type ConfigEvent = {\n type: \"conversation_initiation_metadata\";\n conversation_initiation_metadata_event: {\n conversation_id: string;\n agent_output_audio_format: string;\n user_input_audio_format?: string;\n };\n};\nexport type PingEvent = {\n type: \"ping\";\n ping_event: {\n event_id: number;\n ping_ms?: number;\n };\n};\nexport type ClientToolCallEvent = {\n type: \"client_tool_call\";\n client_tool_call: {\n tool_name: string;\n tool_call_id: string;\n parameters: any;\n expects_response: boolean;\n };\n};\nexport type VadScoreEvent = {\n type: \"vad_score\";\n vad_score_event: {\n vad_score: number;\n };\n};\n\n// TODO correction missing\nexport type IncomingSocketEvent =\n | UserTranscriptionEvent\n | AgentResponseEvent\n | AgentAudioEvent\n | InterruptionEvent\n | InternalTentativeAgentResponseEvent\n | ConfigEvent\n | PingEvent\n | ClientToolCallEvent\n | VadScoreEvent;\n\nexport type PongEvent = {\n type: \"pong\";\n event_id: number;\n};\nexport type UserAudioEvent = {\n user_audio_chunk: string;\n};\nexport type UserFeedbackEvent = {\n type: \"feedback\";\n score: \"like\" | \"dislike\";\n event_id: number;\n};\nexport type ClientToolResultEvent = {\n type: \"client_tool_result\";\n tool_call_id: string;\n result: any;\n is_error: boolean;\n};\nexport type InitiationClientDataEvent = {\n type: typeof CONVERSATION_INITIATION_CLIENT_DATA_TYPE;\n conversation_config_override?: {\n agent?: {\n prompt?: {\n prompt?: string;\n };\n first_message?: string;\n language?: Language;\n };\n tts?: {\n voice_id?: string;\n };\n conversation?: {\n text_only?: boolean;\n };\n };\n custom_llm_extra_body?: any;\n dynamic_variables?: Record<string, string | number | boolean>;\n user_id?: string;\n source_info?: {\n source?: string;\n version?: string;\n };\n};\nexport type ContextualUpdateEvent = {\n type: \"contextual_update\";\n text: string;\n};\nexport type UserMessageEvent = {\n type: \"user_message\";\n text: string;\n};\nexport type UserActivityEvent = {\n type: \"user_activity\";\n};\nexport type MCPToolApprovalResultEvent = {\n type: \"mcp_tool_approval_result\";\n tool_call_id: string;\n is_approved: boolean;\n};\nexport type OutgoingSocketEvent =\n | PongEvent\n | UserAudioEvent\n | InitiationClientDataEvent\n | UserFeedbackEvent\n | ClientToolResultEvent\n | ContextualUpdateEvent\n | UserMessageEvent\n | UserActivityEvent\n | MCPToolApprovalResultEvent;\n\nexport function isValidSocketEvent(event: any): event is IncomingSocketEvent {\n return !!event.type;\n}\n","import type { SessionConfig } from \"./BaseConnection\";\nimport type { InitiationClientDataEvent } from \"./events\";\n\nexport const CONVERSATION_INITIATION_CLIENT_DATA_TYPE =\n \"conversation_initiation_client_data\";\n\nexport function constructOverrides(\n config: SessionConfig\n): InitiationClientDataEvent {\n const overridesEvent: InitiationClientDataEvent = {\n type: CONVERSATION_INITIATION_CLIENT_DATA_TYPE,\n };\n\n if (config.overrides) {\n overridesEvent.conversation_config_override = {\n agent: {\n prompt: config.overrides.agent?.prompt,\n first_message: config.overrides.agent?.firstMessage,\n language: config.overrides.agent?.language,\n },\n tts: {\n voice_id: config.overrides.tts?.voiceId,\n },\n conversation: {\n text_only: config.overrides.conversation?.textOnly,\n },\n };\n }\n\n if (config.customLlmExtraBody) {\n overridesEvent.custom_llm_extra_body = config.customLlmExtraBody;\n }\n\n if (config.dynamicVariables) {\n overridesEvent.dynamic_variables = config.dynamicVariables;\n }\n\n if (config.userId) {\n overridesEvent.user_id = config.userId;\n }\n\n if (config.overrides?.client) {\n overridesEvent.source_info = {\n source: config.overrides.client.source,\n version: config.overrides.client.version,\n };\n }\n\n return overridesEvent;\n}\n","import {\n BaseConnection,\n type SessionConfig,\n type FormatConfig,\n parseFormat,\n} from \"./BaseConnection\";\nimport { PACKAGE_VERSION } from \"../version\";\nimport {\n type ConfigEvent,\n isValidSocketEvent,\n type OutgoingSocketEvent,\n} from \"./events\";\nimport { constructOverrides } from \"./overrides\";\n\nconst MAIN_PROTOCOL = \"convai\";\nconst WSS_API_ORIGIN = \"wss://api.elevenlabs.io\";\nconst WSS_API_PATHNAME = \"/v1/convai/conversation?agent_id=\";\n\nexport class WebSocketConnection extends BaseConnection {\n public readonly conversationId: string;\n public readonly inputFormat: FormatConfig;\n public readonly outputFormat: FormatConfig;\n\n private constructor(\n private readonly socket: WebSocket,\n conversationId: string,\n inputFormat: FormatConfig,\n outputFormat: FormatConfig\n ) {\n super();\n this.conversationId = conversationId;\n this.inputFormat = inputFormat;\n this.outputFormat = outputFormat;\n\n this.socket.addEventListener(\"error\", event => {\n // In case the error event is followed by a close event, we want the\n // latter to be the one that disconnects the session as it contains more\n // useful information.\n setTimeout(\n () =>\n this.disconnect({\n reason: \"error\",\n message: \"The connection was closed due to a socket error.\",\n context: event,\n }),\n 0\n );\n });\n\n this.socket.addEventListener(\"close\", event => {\n this.disconnect(\n event.code === 1000\n ? {\n reason: \"agent\",\n context: event,\n }\n : {\n reason: \"error\",\n message:\n event.reason || \"The connection was closed by the server.\",\n context: event,\n }\n );\n });\n\n this.socket.addEventListener(\"message\", event => {\n try {\n const parsedEvent = JSON.parse(event.data);\n if (!isValidSocketEvent(parsedEvent)) {\n return;\n }\n this.handleMessage(parsedEvent);\n } catch (_) {}\n });\n }\n\n public static async create(\n config: SessionConfig\n ): Promise<WebSocketConnection> {\n let socket: WebSocket | null = null;\n\n try {\n const origin = config.origin ?? WSS_API_ORIGIN;\n let url: string;\n\n const version = config.overrides?.client?.version || PACKAGE_VERSION;\n const source = config.overrides?.client?.source || \"js_sdk\";\n\n if (config.signedUrl) {\n const separator = config.signedUrl.includes(\"?\") ? \"&\" : \"?\";\n url = `${config.signedUrl}${separator}source=${source}&version=${version}`;\n } else {\n url = `${origin}${WSS_API_PATHNAME}${config.agentId}&source=${source}&version=${version}`;\n }\n\n const protocols = [MAIN_PROTOCOL];\n if (config.authorization) {\n protocols.push(`bearer.${config.authorization}`);\n }\n socket = new WebSocket(url, protocols);\n\n const conversationConfig = await new Promise<\n ConfigEvent[\"conversation_initiation_metadata_event\"]\n >((resolve, reject) => {\n socket!.addEventListener(\n \"open\",\n () => {\n const overridesEvent = constructOverrides(config);\n\n socket?.send(JSON.stringify(overridesEvent));\n },\n { once: true }\n );\n\n socket!.addEventListener(\"error\", event => {\n // In case the error event is followed by a close event, we want the\n // latter to be the one that rejects the promise as it contains more\n // useful information.\n setTimeout(() => reject(event), 0);\n });\n\n socket!.addEventListener(\"close\", reject);\n\n socket!.addEventListener(\n \"message\",\n (event: MessageEvent) => {\n const message = JSON.parse(event.data);\n\n if (!isValidSocketEvent(message)) {\n return;\n }\n\n if (message.type === \"conversation_initiation_metadata\") {\n resolve(message.conversation_initiation_metadata_event);\n } else {\n console.warn(\n \"First received message is not conversation metadata.\"\n );\n }\n },\n { once: true }\n );\n });\n\n const {\n conversation_id,\n agent_output_audio_format,\n user_input_audio_format,\n } = conversationConfig;\n\n const inputFormat = parseFormat(user_input_audio_format ?? \"pcm_16000\");\n const outputFormat = parseFormat(agent_output_audio_format);\n\n return new WebSocketConnection(\n socket,\n conversation_id,\n inputFormat,\n outputFormat\n );\n } catch (error) {\n socket?.close();\n throw error;\n }\n }\n\n public close() {\n this.socket.close();\n }\n\n public sendMessage(message: OutgoingSocketEvent) {\n this.socket.send(JSON.stringify(message));\n }\n\n public async setMicMuted(isMuted: boolean): Promise<void> {\n console.warn(\n `WebSocket connection setMicMuted called with ${isMuted}, but this is handled by VoiceConversation`\n );\n }\n}\n","export function arrayBufferToBase64(b: ArrayBufferLike) {\n const buffer = new Uint8Array(b);\n // @ts-ignore\n const base64Data = window.btoa(String.fromCharCode(...buffer));\n return base64Data;\n}\n\nexport function base64ToArrayBuffer(base64: string): ArrayBuffer {\n const binaryString = window.atob(base64);\n const len = binaryString.length;\n const bytes = new Uint8Array(len);\n for (let i = 0; i < len; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n return bytes.buffer;\n}\n","const URLCache = new Map<string, string>();\n\nexport function createWorkletModuleLoader(name: string, sourceCode: string) {\n return async (worklet: AudioWorklet) => {\n const url = URLCache.get(name);\n if (url) {\n return worklet.addModule(url);\n }\n\n const blob = new Blob([sourceCode], { type: \"application/javascript\" });\n const blobURL = URL.createObjectURL(blob);\n try {\n await worklet.addModule(blobURL);\n URLCache.set(name, blobURL);\n return;\n } catch {\n URL.revokeObjectURL(blobURL);\n }\n\n try {\n // Attempting to start a conversation in Safari inside an iframe will\n // throw a CORS error because the blob:// protocol is considered\n // cross-origin. In such cases, fall back to using a base64 data URL:\n const base64 = btoa(sourceCode);\n const moduleURL = `data:application/javascript;base64,${base64}`;\n await worklet.addModule(moduleURL);\n URLCache.set(name, moduleURL);\n } catch (error) {\n throw new Error(\n `Failed to load the ${name} worklet module. Make sure the browser supports AudioWorklets.`\n );\n }\n };\n}\n","/*\n * ulaw encoding logic taken from the wavefile library\n * https://github.com/rochars/wavefile/blob/master/lib/codecs/mulaw.js\n */\n\nimport { createWorkletModuleLoader } from \"./createWorkletModuleLoader\";\n\nexport const loadRawAudioProcessor = createWorkletModuleLoader(\n \"raw-audio-processor\",\n // language=JavaScript\n `\nconst BIAS = 0x84;\nconst CLIP = 32635;\nconst encodeTable = [\n 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,\n 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,\n 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,\n 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,\n 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,\n 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,\n 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,\n 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7\n];\n\nfunction encodeSample(sample) {\n let sign;\n let exponent;\n let mantissa;\n let muLawSample;\n sign = (sample >> 8) & 0x80;\n if (sign !== 0) sample = -sample;\n sample = sample + BIAS;\n if (sample > CLIP) sample = CLIP;\n exponent = encodeTable[(sample>>7) & 0xFF];\n mantissa = (sample >> (exponent+3)) & 0x0F;\n muLawSample = ~(sign | (exponent << 4) | mantissa);\n \n return muLawSample;\n}\n\nclass RawAudioProcessor extends AudioWorkletProcessor {\n constructor() {\n super();\n \n this.port.onmessage = ({ data }) => {\n switch (data.type) {\n case \"setFormat\":\n this.isMuted = false;\n this.buffer = []; // Initialize an empty buffer\n this.bufferSize = data.sampleRate / 4;\n this.format = data.format;\n\n if (globalThis.LibSampleRate && sampleRate !== data.sampleRate) {\n globalThis.LibSampleRate.create(1, sampleRate, data.sampleRate).then(resampler => {\n this.resampler = resampler;\n });\n }\n break;\n case \"setMuted\":\n this.isMuted = data.isMuted;\n break;\n }\n };\n }\n process(inputs) {\n if (!this.buffer) {\n return true;\n }\n \n const input = inputs[0]; // Get the first input node\n if (input.length > 0) {\n let channelData = input[0]; // Get the first channel's data\n\n // Resample the audio if necessary\n if (this.resampler) {\n channelData = this.resampler.full(channelData);\n }\n\n // Add channel data to the buffer\n this.buffer.push(...channelData);\n // Get max volume \n let sum = 0.0;\n for (let i = 0; i < channelData.length; i++) {\n sum += channelData[i] * channelData[i];\n }\n const maxVolume = Math.sqrt(sum / channelData.length);\n // Check if buffer size has reached or exceeded the threshold\n if (this.buffer.length >= this.bufferSize) {\n const float32Array = this.isMuted \n ? new Float32Array(this.buffer.length)\n : new Float32Array(this.buffer);\n\n let encodedArray = this.format === \"ulaw\"\n ? new Uint8Array(float32Array.length)\n : new Int16Array(float32Array.length);\n\n // Iterate through the Float32Array and convert each sample to PCM16\n for (let i = 0; i < float32Array.length; i++) {\n // Clamp the value to the range [-1, 1]\n let sample = Math.max(-1, Math.min(1, float32Array[i]));\n\n // Scale the sample to the range [-32768, 32767]\n let value = sample < 0 ? sample * 32768 : sample * 32767;\n if (this.format === \"ulaw\") {\n value = encodeSample(Math.round(value));\n }\n\n encodedArray[i] = value;\n }\n\n // Send the buffered data to the main script\n this.port.postMessage([encodedArray, maxVolume]);\n\n // Clear the buffer after sending\n this.buffer = [];\n }\n }\n return true; // Continue processing\n }\n}\nregisterProcessor(\"raw-audio-processor\", RawAudioProcessor);\n`\n);\n","import {\n BaseConnection,\n type SessionConfig,\n type FormatConfig,\n parseFormat,\n} from \"./BaseConnection\";\nimport { PACKAGE_VERSION } from \"../version\";\nimport { isValidSocketEvent, type OutgoingSocketEvent } from \"./events\";\nimport { Room, RoomEvent, Track, ConnectionState } from \"livekit-client\";\nimport type {\n RemoteAudioTrack,\n Participant,\n TrackPublication,\n} from \"livekit-client\";\nimport {\n constructOverrides,\n CONVERSATION_INITIATION_CLIENT_DATA_TYPE,\n} from \"./overrides\";\nimport { arrayBufferToBase64 } from \"./audio\";\nimport { loadRawAudioProcessor } from \"./rawAudioProcessor\";\n\nconst DEFAULT_LIVEKIT_WS_URL = \"wss://livekit.rtc.elevenlabs.io\";\nconst HTTPS_API_ORIGIN = \"https://api.elevenlabs.io\";\n\n// Convert WSS origin to HTTPS for API calls\nfunction convertWssToHttps(origin: string): string {\n return origin.replace(/^wss:\\/\\//, \"https://\");\n}\n\nexport type ConnectionConfig = SessionConfig & {\n onDebug?: (info: unknown) => void;\n};\n\nexport class WebRTCConnection extends BaseConnection {\n public conversationId: string;\n public readonly inputFormat: FormatConfig;\n public readonly outputFormat: FormatConfig;\n\n private room: Room;\n private isConnected = false;\n private audioEventId = 1;\n private audioCaptureContext: AudioContext | null = null;\n\n private constructor(\n room: Room,\n conversationId: string,\n inputFormat: FormatConfig,\n outputFormat: FormatConfig,\n config: { onDebug?: (info: unknown) => void } = {}\n ) {\n super(config);\n this.room = room;\n this.conversationId = conversationId;\n this.inputFormat = inputFormat;\n this.outputFormat = outputFormat;\n\n this.setupRoomEventListeners();\n }\n\n public static async create(\n config: ConnectionConfig\n ): Promise<WebRTCConnection> {\n let conversationToken: string;\n\n // Handle different authentication scenarios\n if (\"conversationToken\" in config && config.conversationToken) {\n // Direct token provided\n conversationToken = config.conversationToken;\n } else if (\"agentId\" in config && config.agentId) {\n // Agent ID provided - fetch token from API\n try {\n const version = config.overrides?.client?.version || PACKAGE_VERSION;\n const source = config.overrides?.client?.source || \"js_sdk\";\n const configOrigin = config.origin ?? HTTPS_API_ORIGIN;\n const origin = convertWssToHttps(configOrigin); //origin is wss, not https\n const url = `${origin}/v1/convai/conversation/token?agent_id=${config.agentId}&source=${source}&version=${version}`;\n const response = await fetch(url);\n\n if (!response.ok) {\n throw new Error(\n `ElevenLabs API returned ${response.status} ${response.statusText}`\n );\n }\n\n const data = await response.json();\n conversationToken = data.token;\n\n if (!conversationToken) {\n throw new Error(\"No conversation token received from API\");\n }\n } catch (error) {\n let msg = error instanceof Error ? error.message : String(error);\n if (error instanceof Error && error.message.includes(\"401\")) {\n msg =\n \"Your agent has authentication enabled, but no signed URL or conversation token was provided.\";\n }\n\n throw new Error(\n `Failed to fetch conversation token for agent ${config.agentId}: ${msg}`\n );\n }\n } else {\n throw new Error(\n \"Either conversationToken or agentId is required for WebRTC connection\"\n );\n }\n\n const room = new Room();\n\n try {\n // Create connection instance first to set up event listeners\n const conversationId = `room_${Date.now()}`;\n const inputFormat = parseFormat(\"pcm_48000\");\n const outputFormat = parseFormat(\"pcm_48000\");\n const connection = new WebRTCConnection(\n room,\n conversationId,\n inputFormat,\n outputFormat,\n config\n );\n\n // Use configurable LiveKit URL or default if not provided\n const livekitUrl = config.livekitUrl || DEFAULT_LIVEKIT_WS_URL;\n\n // Connect to the LiveKit room and wait for the Connected event\n await room.connect(livekitUrl, conversationToken);\n\n // Wait for the Connected event to ensure isConnected is true\n await new Promise<void>(resolve => {\n if (connection.isConnected) {\n resolve();\n } else {\n const onConnected = () => {\n room.off(RoomEvent.Connected, onConnected);\n resolve();\n };\n room.on(RoomEvent.Connected, onConnected);\n }\n });\n\n if (room.name) {\n connection.conversationId =\n room.name.match(/(conv_[a-zA-Z0-9]+)/)?.[0] || room.name;\n }\n\n // Enable microphone and send overrides\n await room.localParticipant.setMicrophoneEnabled(true);\n\n const overridesEvent = constructOverrides(config);\n\n connection.debug({\n type: CONVERSATION_INITIATION_CLIENT_DATA_TYPE,\n message: overridesEvent,\n });\n\n await connection.sendMessage(overridesEvent);\n\n return connection;\n } catch (error) {\n await room.disconnect();\n throw error;\n }\n }\n\n private setupRoomEventListeners() {\n this.room.on(RoomEvent.Connected, async () => {\n this.isConnected = true;\n console.info(\"WebRTC room connected\");\n });\n\n this.room.on(RoomEvent.Disconnected, reason => {\n this.isConnected = false;\n this.disconnect({\n reason: \"agent\",\n context: new CloseEvent(\"close\", { reason: reason?.toString() }),\n });\n });\n\n this.room.on(RoomEvent.ConnectionStateChanged, state => {\n if (state === ConnectionState.Disconnected) {\n this.isConnected = false;\n this.disconnect({\n reason: \"error\",\n message: `LiveKit connection state changed to ${state}`,\n context: new Event(\"connection_state_changed\"),\n });\n }\n });\n\n // Handle incoming data messages\n this.room.on(\n RoomEvent.DataReceived,\n (payload: Uint8Array, _participant) => {\n try {\n const message = JSON.parse(new TextDecoder().decode(payload));\n\n // Filter out audio messages for WebRTC - they're handled via audio tracks\n if (message.type === \"audio\") {\n return;\n }\n\n if (isValidSocketEvent(message)) {\n this.handleMessage(message);\n } else {\n console.warn(\"Invalid socket event received:\", message);\n }\n } catch (error) {\n console.warn(\"Failed to parse incoming data message:\", error);\n console.warn(\"Raw payload:\", new TextDecoder().decode(payload));\n }\n }\n );\n\n this.room.on(\n RoomEvent.TrackSubscribed,\n async (\n track: Track,\n _publication: TrackPublication,\n participant: Participant\n ) => {\n if (\n track.kind === Track.Kind.Audio &&\n participant.identity.includes(\"agent\")\n ) {\n // Play the audio track\n const remoteAudioTrack = track as RemoteAudioTrack;\n const audioElement = remoteAudioTrack.attach();\n audioElement.autoplay = true;\n audioElement.controls = false;\n\n // Add to DOM (hidden) to ensure it plays\n audioElement.style.display = \"none\";\n document.body.appendChild(audioElement);\n\n // Set up audio capture for onAudio callback\n await this.setupAudioCapture(remoteAudioTrack);\n }\n }\n );\n\n this.room.on(\n RoomEvent.ActiveSpeakersChanged,\n async (speakers: Participant[]) => {\n if (speakers.length > 0) {\n const participant = speakers[0];\n if (participant.identity.includes(\"agent\")) {\n this.updateMode(\"speaking\");\n }\n } else {\n this.updateMode(\"listening\");\n }\n }\n );\n }\n\n public close() {\n if (this.isConnected) {\n try {\n // Explicitly stop all local tracks before disconnecting to ensure microphone is released\n this.room.localParticipant.audioTrackPublications.forEach(\n publication => {\n if (publication.track) {\n publication.track.stop();\n }\n }\n );\n } catch (error) {\n console.warn(\"Error stopping local tracks:\", error);\n }\n\n // Clean up audio capture context (non-blocking)\n if (this.audioCaptureContext) {\n this.audioCaptureContext.close().catch(error => {\n console.warn(\"Error closing audio capture context:\", error);\n });\n this.audioCaptureContext = null;\n }\n\n this.room.disconnect();\n }\n }\n\n public async sendMessage(message: OutgoingSocketEvent) {\n if (!this.isConnected || !this.room.localParticipant) {\n console.warn(\n \"Cannot send message: room not connected or no local participant\"\n );\n return;\n }\n\n // In WebRTC mode, audio is sent via published tracks, not data messages\n if (\"user_audio_chunk\" in message) {\n // Ignore audio data messages - audio flows through WebRTC tracks\n return;\n }\n\n try {\n const encoder = new TextEncoder();\n const data = encoder.encode(JSON.stringify(message));\n\n await this.room.localParticipant.publishData(data, { reliable: true });\n } catch (error) {\n this.debug({\n type: \"send_message_error\",\n message: {\n message,\n error,\n },\n });\n console.error(\"Failed to send message via WebRTC:\", error);\n }\n }\n\n // Get the room instance for advanced usage\n public getRoom(): Room {\n return this.room;\n }\n\n public async setMicMuted(isMuted: boolean): Promise<void> {\n if (!this.isConnected || !this.room.localParticipant) {\n console.warn(\n \"Cannot set microphone muted: room not connected or no local participant\"\n );\n return;\n }\n\n // Get the microphone track publication\n const micTrackPublication = this.room.localParticipant.getTrackPublication(\n Track.Source.Microphone\n );\n\n if (micTrackPublication?.track) {\n try {\n // Use LiveKit's built-in track muting\n if (isMuted) {\n await micTrackPublication.track.mute();\n } else {\n await micTrackPublication.track.unmute();\n }\n } catch (_error) {\n // If track muting fails, fall back to participant-level control\n await this.room.localParticipant.setMicrophoneEnabled(!isMuted);\n }\n } else {\n // No track found, use participant-level control directly\n await this.room.localParticipant.setMicrophoneEnabled(!isMuted);\n }\n }\n\n private async setupAudioCapture(track: RemoteAudioTrack) {\n try {\n // Create audio context for processing\n const audioContext = new AudioContext();\n this.audioCaptureContext = audioContext;\n\n // Create MediaStream from the track\n const mediaStream = new MediaStream([track.mediaStreamTrack]);\n\n // Create audio source from the stream\n const source = audioContext.createMediaStreamSource(mediaStream);\n\n // Load the raw audio processor worklet (reuse existing processor)\n await loadRawAudioProcessor(audioContext.audioWorklet);\n\n // Create worklet node for audio processing\n const worklet = new AudioWorkletNode(audioContext, \"raw-audio-processor\");\n\n // Configure the processor for the output format\n worklet.port.postMessage({\n type: \"setFormat\",\n format: this.outputFormat.format,\n sampleRate: this.outputFormat.sampleRate,\n });\n\n // Handle processed audio data\n worklet.port.onmessage = (event: MessageEvent) => {\n const [audioData, maxVolume] = event.data;\n\n // Only send audio if there's significant volume (not just silence)\n const volumeThreshold = 0.01;\n\n if (maxVolume > volumeThreshold) {\n // Convert to base64\n const base64Audio = arrayBufferToBase64(audioData.buffer);\n\n // Use sequential event ID for proper feedback tracking\n const eventId = this.audioEventId++;\n\n // Trigger the onAudio callback by simulating an audio event\n this.handleMessage({\n type: \"audio\",\n audio_event: {\n audio_base_64: base64Audio,\n event_id: eventId,\n },\n });\n }\n };\n\n // Connect the audio processing chain\n source.connect(worklet);\n } catch (error) {\n console.warn(\"Failed to set up audio capture:\", error);\n }\n }\n}\n","import type {\n BaseConnection,\n SessionConfig,\n ConnectionType,\n} from \"./BaseConnection\";\nimport { WebSocketConnection } from \"./WebSocketConnection\";\nimport { WebRTCConnection } from \"./WebRTCConnection\";\n\nfunction determineConnectionType(config: SessionConfig): ConnectionType {\n // If connectionType is explicitly specified, use it\n if (config.connectionType) {\n return config.connectionType;\n }\n\n // If conversationToken is provided, use WebRTC\n if (\"conversationToken\" in config && config.conversationToken) {\n return \"webrtc\";\n }\n\n // Default to WebSocket for backward compatibility\n return \"websocket\";\n}\n\nexport async function createConnection(\n config: SessionConfig\n): Promise<BaseConnection> {\n const connectionType = determineConnectionType(config);\n\n switch (connectionType) {\n case \"websocket\":\n return WebSocketConnection.create(config);\n case \"webrtc\":\n return WebRTCConnection.create(config);\n default:\n throw new Error(`Unknown connection type: ${connectionType}`);\n }\n}\n","export function isIosDevice() {\n return (\n [\n \"iPad Simulator\",\n \"iPhone Simulator\",\n \"iPod Simulator\",\n \"iPad\",\n \"iPhone\",\n \"iPod\",\n ].includes(navigator.platform) ||\n // iPad on iOS 13 detection\n (navigator.userAgent.includes(\"Mac\") && \"ontouchend\" in document)\n );\n}\n\nexport function isAndroidDevice() {\n return /android/i.test(navigator.userAgent);\n}\n","import { isAndroidDevice, isIosDevice } from \"./compatibility\";\nimport type { DelayConfig } from \"./connection\";\n\nexport async function applyDelay(\n delayConfig: DelayConfig = {\n default: 0,\n // Give the Android AudioManager enough time to switch to the correct audio mode\n android: 3_000,\n }\n) {\n let delay = delayConfig.default;\n if (isAndroidDevice()) {\n delay = delayConfig.android ?? delay;\n } else if (isIosDevice()) {\n delay = delayConfig.ios ?? delay;\n }\n\n if (delay > 0) {\n await new Promise(resolve => setTimeout(resolve, delay));\n }\n}\n","import { createConnection } from \"./utils/ConnectionFactory\";\nimport type { BaseConnection } from \"./utils/BaseConnection\";\nimport { applyDelay } from \"./utils/applyDelay\";\nimport { BaseConversation, type PartialOptions } from \"./BaseConversation\";\n\nexport class TextConversation extends BaseConversation {\n public static async startSession(\n options: PartialOptions\n ): Promise<TextConversation> {\n const fullOptions = BaseConversation.getFullOptions(options);\n\n fullOptions.onStatusChange({ status: \"connecting\" });\n fullOptions.onCanSendFeedbackChange({ canSendFeedback: false });\n\n let connection: BaseConnection | null = null;\n try {\n await applyDelay(fullOptions.connectionDelay);\n connection = await createConnection(options);\n return new TextConversation(fullOptions, connection);\n } catch (error) {\n fullOptions.onStatusChange({ status: \"disconnected\" });\n connection?.close();\n throw error;\n }\n }\n}\n","import { loadRawAudioProcessor } from \"./rawAudioProcessor\";\nimport type { FormatConfig } from \"./connection\";\nimport { isIosDevice } from \"./compatibility\";\n\nexport type InputConfig = {\n preferHeadphonesForIosDevices?: boolean;\n};\n\nconst LIBSAMPLERATE_JS =\n \"https://cdn.jsdelivr.net/npm/@alexanderolsen/libsamplerate-js@2.1.2/dist/libsamplerate.worklet.js\";\n\nexport class Input {\n public static async create({\n sampleRate,\n format,\n preferHeadphonesForIosDevices,\n }: FormatConfig & InputConfig): Promise<Input> {\n let context: AudioContext | null = null;\n let inputStream: MediaStream | null = null;\n\n try {\n const options: MediaTrackConstraints = {\n sampleRate: { ideal: sampleRate },\n echoCancellation: true,\n noiseSuppression: true,\n };\n\n if (isIosDevice() && preferHeadphonesForIosDevices) {\n const availableDevices =\n await window.navigator.mediaDevices.enumerateDevices();\n const idealDevice = availableDevices.find(\n d =>\n // cautious to include \"bluetooth\" in the search\n // as might trigger bluetooth speakers\n d.kind === \"audioinput\" &&\n [\"airpod\", \"headphone\", \"earphone\"].find(keyword =>\n d.label.toLowerCase().includes(keyword)\n )\n );\n if (idealDevice) {\n options.deviceId = { ideal: idealDevice.deviceId };\n }\n }\n\n const supportsSampleRateConstraint =\n navigator.mediaDevices.getSupportedConstraints().sampleRate;\n\n context = new window.AudioContext(\n supportsSampleRateConstraint ? { sampleRate } : {}\n );\n const analyser = context.createAnalyser();\n if (!supportsSampleRateConstraint) {\n await context.audioWorklet.addModule(LIBSAMPLERATE_JS);\n }\n await loadRawAudioProcessor(context.audioWorklet);\n\n const constraints = { voiceIsolation: true, ...options };\n inputStream = await navigator.mediaDevices.getUserMedia({\n audio: constraints,\n });\n\n const source = context.createMediaStreamSource(inputStream);\n const worklet = new AudioWorkletNode(context, \"raw-audio-processor\");\n worklet.port.postMessage({ type: \"setFormat\", format, sampleRate });\n\n source.connect(analyser);\n analyser.connect(worklet);\n\n await context.resume();\n\n return new Input(context, analyser, worklet, inputStream);\n } catch (error) {\n inputStream?.getTracks().forEach(track => track.stop());\n context?.close();\n throw error;\n }\n }\n\n private constructor(\n public readonly context: AudioContext,\n public readonly analyser: AnalyserNode,\n public readonly worklet: AudioWorkletNode,\n public readonly inputStream: MediaStream\n ) {}\n\n public async close() {\n this.inputStream.getTracks().forEach(track => track.stop());\n await this.context.close();\n }\n\n public setMuted(isMuted: boolean) {\n this.worklet.port.postMessage({ type: \"setMuted\", isMuted });\n }\n}\n","/*\n * ulaw decoding logic taken from the wavefile library\n * https://github.com/rochars/wavefile/blob/master/lib/codecs/mulaw.js\n */\n\nimport { createWorkletModuleLoader } from \"./createWorkletModuleLoader\";\n\nexport const loadAudioConcatProcessor = createWorkletModuleLoader(\n \"audio-concat-processor\",\n // language=JavaScript\n `\nconst decodeTable = [0,132,396,924,1980,4092,8316,16764];\n\nexport function decodeSample(muLawSample) {\n let sign;\n let exponent;\n let mantissa;\n let sample;\n muLawSample = ~muLawSample;\n sign = (muLawSample & 0x80);\n exponent = (muLawSample >> 4) & 0x07;\n mantissa = muLawSample & 0x0F;\n sample = decodeTable[exponent] + (mantissa << (exponent+3));\n if (sign !== 0) sample = -sample;\n\n return sample;\n}\n\nclass AudioConcatProcessor extends AudioWorkletProcessor {\n constructor() {\n super();\n this.buffers = []; // Initialize an empty buffer\n this.cursor = 0;\n this.currentBuffer = null;\n this.wasInterrupted = false;\n this.finished = false;\n \n this.port.onmessage = ({ data }) => {\n switch (data.type) {\n case \"setFormat\":\n this.format = data.format;\n break;\n case \"buffer\":\n this.wasInterrupted = false;\n this.buffers.push(\n this.format === \"ulaw\"\n ? new Uint8Array(data.buffer)\n : new Int16Array(data.buffer)\n );\n break;\n case \"interrupt\":\n this.wasInterrupted = true;\n break;\n case \"clearInterrupted\":\n if (this.wasInterrupted) {\n this.wasInterrupted = false;\n this.buffers = [];\n this.currentBuffer = null;\n }\n }\n };\n }\n process(_, outputs) {\n let finished = false;\n const output = outputs[0][0];\n for (let i = 0; i < output.length; i++) {\n if (!this.currentBuffer) {\n if (this.buffers.length === 0) {\n finished = true;\n break;\n }\n this.currentBuffer = this.buffers.shift();\n this.cursor = 0;\n }\n\n let value = this.currentBuffer[this.cursor];\n if (this.format === \"ulaw\") {\n value = decodeSample(value);\n }\n output[i] = value / 32768;\n this.cursor++;\n\n if (this.cursor >= this.currentBuffer.length) {\n this.currentBuffer = null;\n }\n }\n\n if (this.finished !== finished) {\n this.finished = finished;\n this.port.postMessage({ type: \"process\", finished });\n }\n\n return true; // Continue processing\n }\n}\n\nregisterProcessor(\"audio-concat-processor\", AudioConcatProcessor);\n`\n);\n","import { loadAudioConcatProcessor } from \"./audioConcatProcessor\";\nimport type { FormatConfig } from \"./connection\";\n\nexport class Output {\n public static async create({\n sampleRate,\n format,\n }: FormatConfig): Promise<Output> {\n let context: AudioContext | null = null;\n try {\n context = new AudioContext({ sampleRate });\n const analyser = context.createAnalyser();\n const gain = context.createGain();\n gain.connect(analyser);\n analyser.connect(context.destination);\n await loadAudioConcatProcessor(context.audioWorklet);\n const worklet = new AudioWorkletNode(context, \"audio-concat-processor\");\n worklet.port.postMessage({ type: \"setFormat\", format });\n worklet.connect(gain);\n\n await context.resume();\n\n return new Output(context, analyser, gain, worklet);\n } catch (error) {\n context?.close();\n throw error;\n }\n }\n\n private constructor(\n public readonly context: AudioContext,\n public readonly analyser: AnalyserNode,\n public readonly gain: GainNode,\n public readonly worklet: AudioWorkletNode\n ) {}\n\n public async close() {\n await this.context.close();\n }\n}\n","import { arrayBufferToBase64, base64ToArrayBuffer } from \"./utils/audio\";\nimport { Input } from \"./utils/input\";\nimport { Output } from \"./utils/output\";\nimport { createConnection } from \"./utils/ConnectionFactory\";\nimport type { BaseConnection } from \"./utils/BaseConnection\";\nimport { WebRTCConnection } from \"./utils/WebRTCConnection\";\nimport type { AgentAudioEvent, InterruptionEvent } from \"./utils/events\";\nimport { applyDelay } from \"./utils/applyDelay\";\nimport {\n BaseConversation,\n type Options,\n type PartialOptions,\n} from \"./BaseConversation\";\n\nexport class VoiceConversation extends BaseConversation {\n public static async startSession(\n options: PartialOptions\n ): Promise<VoiceConversation> {\n const fullOptions = BaseConversation.getFullOptions(options);\n\n fullOptions.onStatusChange({ status: \"connecting\" });\n fullOptions.onCanSendFeedbackChange({ canSendFeedback: false });\n\n let input: Input | null = null;\n let connection: BaseConnection | null = null;\n let output: Output | null = null;\n let preliminaryInputStream: MediaStream | null = null;\n\n let wakeLock: WakeLockSentinel | null = null;\n if (options.useWakeLock ?? true) {\n try {\n wakeLock = await navigator.wakeLock.request(\"screen\");\n } catch (e) {\n // Wake Lock is not required for the conversation to work\n }\n }\n\n try {\n // some browsers won't allow calling getSupportedConstraints or enumerateDevices\n // before getting approval for microphone access\n preliminaryInputStream = await navigator.mediaDevices.getUserMedia({\n audio: true,\n });\n\n await applyDelay(fullOptions.connectionDelay);\n connection = await createConnection(options);\n [input, output] = await Promise.all([\n Input.create({\n ...connection.inputFormat,\n preferHeadphonesForIosDevices: options.preferHeadphonesForIosDevices,\n }),\n Output.create(connection.outputFormat),\n ]);\n\n preliminaryInputStream?.getTracks().forEach(track => track.stop());\n preliminaryInputStream = null;\n\n return new VoiceConversation(\n fullOptions,\n connection,\n input,\n output,\n wakeLock\n );\n } catch (error) {\n fullOptions.onStatusChange({ status: \"disconnected\" });\n preliminaryInputStream?.getTracks().forEach(track => track.stop());\n connection?.close();\n await input?.close();\n await output?.close();\n try {\n await wakeLock?.release();\n wakeLock = null;\n } catch (e) {}\n throw error;\n }\n }\n\n private inputFrequencyData?: Uint8Array;\n private outputFrequencyData?: Uint8Array;\n\n protected constructor(\n options: Options,\n connection: BaseConnection,\n public readonly input: Input,\n public readonly output: Output,\n public wakeLock: WakeLockSentinel | null\n ) {\n super(options, connection);\n this.input.worklet.port.onmessage = this.onInputWorkletMessage;\n this.output.worklet.port.onmessage = this.onOutputWorkletMessage;\n }\n\n protected override async handleEndSession() {\n await super.handleEndSession();\n try {\n await this.wakeLock?.release();\n this.wakeLock = null;\n } catch (e) {}\n\n await this.input.close();\n await this.output.close();\n }\n\n protected override handleInterruption(event: InterruptionEvent) {\n super.handleInterruption(event);\n this.fadeOutAudio();\n }\n\n protected override handleAudio(event: AgentAudioEvent) {\n if (this.lastInterruptTimestamp <= event.audio_event.event_id) {\n this.options.onAudio?.(event.audio_event.audio_base_64);\n\n // Only play audio through the output worklet for WebSocket connections\n // WebRTC connections handle audio playback directly through LiveKit tracks\n if (!(this.connection instanceof WebRTCConnection)) {\n this.addAudioBase64Chunk(event.audio_event.audio_base_64);\n }\n\n this.currentEventId = event.audio_event.event_id;\n this.updateCanSendFeedback();\n this.updateMode(\"speaking\");\n }\n }\n\n private onInputWorkletMessage = (event: MessageEvent): void => {\n const rawAudioPcmData = event.data[0];\n\n // TODO: When supported, maxVolume can be used to avoid sending silent audio\n // const maxVolume = event.data[1];\n\n if (this.status === \"connected\") {\n this.connection.sendMessage({\n user_audio_chunk: arrayBufferToBase64(rawAudioPcmData.buffer),\n });\n }\n };\n\n private onOutputWorkletMessage = ({ data }: MessageEvent): void => {\n if (data.type === \"process\") {\n this.updateMode(data.finished ? \"listening\" : \"speaking\");\n }\n };\n\n private addAudioBase64Chunk = (chunk: string) => {\n this.output.gain.gain.value = this.volume;\n this.output.worklet.port.postMessage({ type: \"clearInterrupted\" });\n this.output.worklet.port.postMessage({\n type: \"buffer\",\n buffer: base64ToArrayBuffer(chunk),\n });\n };\n\n private fadeOutAudio = () => {\n // mute agent\n this.updateMode(\"listening\");\n this.output.worklet.port.postMessage({ type: \"interrupt\" });\n this.output.gain.gain.exponentialRampToValueAtTime(\n 0.0001,\n this.output.context.currentTime + 2\n );\n\n // reset volume back\n setTimeout(() => {\n this.output.gain.gain.value = this.volume;\n this.output.worklet.port.postMessage({ type: \"clearInterrupted\" });\n }, 2000); // Adjust the duration as needed\n };\n\n private calculateVolume = (frequencyData: Uint8Array) => {\n if (frequencyData.length === 0) {\n return 0;\n }\n\n // TODO: Currently this averages all frequencies, but we should probably\n // bias towards the frequencies that are more typical for human voice\n let volume = 0;\n for (let i = 0; i < frequencyData.length; i++) {\n volume += frequencyData[i] / 255;\n }\n volume /= frequencyData.length;\n\n return volume < 0 ? 0 : volume > 1 ? 1 : volume;\n };\n\n public setMicMuted(isMuted: boolean) {\n // Use LiveKit track muting for WebRTC connections\n if (this.connection instanceof WebRTCConnection) {\n this.connection.setMicMuted(isMuted);\n } else {\n // Use input muting for WebSocket connections\n this.input.setMuted(isMuted);\n }\n }\n\n public getInputByteFrequencyData() {\n this.inputFrequencyData ??= new Uint8Array(\n this.input.analyser.frequencyBinCount\n );\n this.input.analyser.getByteFrequencyData(this.inputFrequencyData);\n return this.inputFrequencyData;\n }\n\n public getOutputByteFrequencyData() {\n this.outputFrequencyData ??= new Uint8Array(\n this.output.analyser.frequencyBinCount\n );\n this.output.analyser.getByteFrequencyData(this.outputFrequencyData);\n return this.outputFrequencyData;\n }\n\n public getInputVolume() {\n return this.calculateVolume(this.getInputByteFrequencyData());\n }\n\n public getOutputVolume() {\n return this.calculateVolume(this.getOutputByteFrequencyData());\n }\n}\n","import { BaseConversation, type PartialOptions } from \"./BaseConversation\";\nimport { TextConversation } from \"./TextConversation\";\nimport { VoiceConversation } from \"./VoiceConversation\";\n\nexport type {\n Mode,\n Role,\n Options,\n PartialOptions,\n ClientToolsConfig,\n Callbacks,\n Status,\n} from \"./BaseConversation\";\nexport type { InputConfig } from \"./utils/input\";\nexport type { IncomingSocketEvent, VadScoreEvent } from \"./utils/events\";\nexport type {\n SessionConfig,\n BaseSessionConfig,\n DisconnectionDetails,\n Language,\n ConnectionType,\n} from \"./utils/BaseConnection\";\nexport { createConnection } from \"./utils/ConnectionFactory\";\nexport { WebSocketConnection } from \"./utils/WebSocketConnection\";\nexport { WebRTCConnection } from \"./utils/WebRTCConnection\";\nexport { postOverallFeedback } from \"./utils/postOverallFeedback\";\n\nexport class Conversation extends BaseConversation {\n public static startSession(options: PartialOptions): Promise<Conversation> {\n return options.textOnly\n ? TextConversation.startSession(options)\n : VoiceConversation.startSession(options);\n }\n}\n","const HTTPS_API_ORIGIN = \"https://api.elevenlabs.io\";\n\nexport function postOverallFeedback(\n conversationId: string,\n like: boolean,\n origin: string = HTTPS_API_ORIGIN\n) {\n return fetch(`${origin}/v1/convai/conversations/${conversationId}/feedback`, {\n method: \"POST\",\n body: JSON.stringify({\n feedback: like ? \"like\" : \"dislike\",\n }),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n });\n}\n"],"names":["EMPTY_FREQUENCY_DATA","Uint8Array","BaseConversation","options","connection","_this3","_this","this","_this2","lastInterruptTimestamp","mode","status","volume","currentEventId","lastFeedbackEventId","canSendFeedback","endSessionWithDetails","details","Promise","resolve","updateStatus","handleEndSession","then","onDisconnect","e","reject","onMessage","parsedEvent","type","handleInterruption","handleAgentResponse","handleUserTranscript","handleTentativeAgentResponse","handleClientToolCall","handleAudio","handleVadScore","sendMessage","event_id","ping_event","onDebug","setVolume","_ref","onConnect","conversationId","onModeChange","updateMode","getFullOptions","partialOptions","_extends","clientTools","onError","onAudio","onStatusChange","onCanSendFeedbackChange","_proto","prototype","endSession","reason","close","updateCanSendFeedback","event","interruption_event","source","message","agent_response_event","agent_response","user_transcription_event","user_transcript","response","tentative_agent_response_internal_event","tentative_agent_response","onVadScore","vadScore","vad_score_event","vad_score","_this5","Object","hasOwnProperty","call","client_tool_call","tool_name","_temp","parameters","result","formattedResult","JSON","stringify","String","tool_call_id","is_error","_catch","clientToolName","onUnhandledClientToolCall","context","console","error","getId","isOpen","setMicMuted","isMuted","getInputByteFrequencyData","getOutputByteFrequencyData","getInputVolume","getOutputVolume","sendFeedback","like","score","warn","sendContextualUpdate","text","sendUserMessage","sendUserActivity","sendMCPToolApprovalResult","toolCallId","isApproved","is_approved","BaseConnection","config","queue","disconnectionDetails","onDisconnectCallback","onMessageCallback","onModeChangeCallback","debug","info","callback","length","queueMicrotask","forEach","_this$onModeChangeCal","disconnect","_this$onDisconnectCal","handleMessage","push","parseFormat","format","_format$split","split","formatPart","sampleRatePart","includes","Error","sampleRate","Number","parseInt","isNaN","PACKAGE_VERSION","isValidSocketEvent","CONVERSATION_INITIATION_CLIENT_DATA_TYPE","constructOverrides","_config$overrides","_config$overrides$age","_config$overrides$age2","_config$overrides$age3","_config$overrides$tts","_config$overrides$con","overridesEvent","overrides","conversation_config_override","agent","prompt","first_message","firstMessage","language","tts","voice_id","voiceId","conversation","text_only","textOnly","customLlmExtraBody","custom_llm_extra_body","dynamicVariables","dynamic_variables","userId","user_id","client","source_info","version","WebSocketConnection","_BaseConnection","socket","inputFormat","outputFormat","addEventListener","setTimeout","code","parse","data","_","_inheritsLoose","create","_config$origin","_config$overrides2","url","origin","signedUrl","separator","agentId","protocols","authorization","WebSocket","_socket","send","once","conversation_initiation_metadata_event","conversationConfig","conversation_id","agent_output_audio_format","user_input_audio_format","_socket2","arrayBufferToBase64","b","buffer","window","btoa","fromCharCode","apply","base64ToArrayBuffer","base64","binaryString","atob","len","bytes","i","charCodeAt","URLCache","Map","createWorkletModuleLoader","name","sourceCode","worklet","_exit","_temp2","_result","moduleURL","addModule","set","get","blob","Blob","blobURL","URL","createObjectURL","revokeObjectURL","loadRawAudioProcessor","WebRTCConnection","room","isConnected","audioEventId","audioCaptureContext","setupRoomEventListeners","conversationToken","_result3","Room","Date","now","connect","livekitUrl","onConnected","off","RoomEvent","Connected","on","_room$name$match","match","localParticipant","setMicrophoneEnabled","replace","convertWssToHttps","fetch","ok","statusText","json","token","msg","_this4","Disconnected","CloseEvent","toString","ConnectionStateChanged","state","ConnectionState","Event","DataReceived","payload","_participant","TextDecoder","decode","TrackSubscribed","track","_publication","participant","_temp3","kind","Track","Kind","Audio","identity","remoteAudioTrack","audioElement","attach","autoplay","controls","style","display","document","body","appendChild","setupAudioCapture","ActiveSpeakersChanged","speakers","audioTrackPublications","publication","stop","_this6","_temp4","TextEncoder","encode","publishData","reliable","getRoom","_this7","micTrackPublication","getTrackPublication","Source","Microphone","_temp5","mute","unmute","_this8","_temp6","audioContext","AudioContext","mediaStream","MediaStream","mediaStreamTrack","createMediaStreamSource","audioWorklet","AudioWorkletNode","port","postMessage","onmessage","_event$data","base64Audio","maxVolume","eventId","audio_event","audio_base_64","createConnection","connectionType","determineConnectionType","isIosDevice","navigator","platform","userAgent","applyDelay","delayConfig","default","android","_delayConfig$android","delay","test","_delayConfig$ios","ios","TextConversation","_BaseConversation","arguments","startSession","fullOptions","connectionDelay","_createConnection","_connection","Input","analyser","inputStream","preferHeadphonesForIosDevices","constraints","voiceIsolation","mediaDevices","getUserMedia","audio","_navigator$mediaDevic","resume","supportsSampleRateConstraint","getSupportedConstraints","createAnalyser","ideal","echoCancellation","noiseSuppression","enumerateDevices","availableDevices","idealDevice","find","d","keyword","label","toLowerCase","deviceId","_inputStream","_context","getTracks","setMuted","loadAudioConcatProcessor","Output","gain","createGain","destination","VoiceConversation","input","output","wakeLock","inputFrequencyData","outputFrequencyData","onInputWorkletMessage","user_audio_chunk","onOutputWorkletMessage","finished","addAudioBase64Chunk","chunk","value","fadeOutAudio","exponentialRampToValueAtTime","currentTime","calculateVolume","frequencyData","preliminaryInputStream","all","_Promise$all","_preliminaryInputStre","_preliminaryInputStre2","_input","_output","_wakeLock","release","_options$useWakeLock","useWakeLock","request","_navigator$wakeLock$r","_temp7","_this2$wakeLock","_this$options$onAudio","_this$options","_this$inputFrequencyD","frequencyBinCount","getByteFrequencyData","Conversation","method","feedback","headers"],"mappings":"ycAgEA,IAAMA,EAAuB,IAAIC,WAAW,GAE/BC,0BAyBX,SAAAA,EACqBC,EACAC,GAA0BC,IAAAA,OAAAC,EAczCC,KAAIC,EAuIJD,KAAIA,KAtJWJ,aACAC,EAAAA,KAAAA,uBA1BXK,uBAAyB,EAACF,KAC1BG,KAAa,YACbC,KAAAA,OAAiB,aAAYJ,KAC7BK,OAAS,OACTC,eAAiB,EACjBC,KAAAA,oBAAsB,EAACP,KACvBQ,iBAAkB,OAiCpBC,sBAAqB,SAAUC,GAAiC,IACtE,MAAoB,cAAhBX,EAAKK,QAA0C,eAAhBL,EAAKK,OAAyBO,QAAAC,WACjEb,EAAKc,aAAa,iBAAiBF,QAAAC,QAC7Bb,EAAKe,oBAAkBC,gBAC7BhB,EAAKc,aAAa,gBAClBd,EAAKH,QAAQoB,aAAaN,EAAS,GACrC,CAAC,MAAAO,GAAA,OAAAN,QAAAO,OAAAD,EAAA,CAAA,EAAAjB,KA+HOmB,UAAmBC,SAAAA,GAAoC,IAC7D,OAAQA,EAAYC,MAClB,IAAK,eAEH,OADApB,EAAKqB,mBAAmBF,GACxBT,QAAAC,UAEF,IAAK,iBAEH,OADAX,EAAKsB,oBAAoBH,GACzBT,QAAAC,UAEF,IAAK,kBAEH,OADAX,EAAKuB,qBAAqBJ,GAC1BT,QAAAC,UAEF,IAAK,oCAEH,OADAX,EAAKwB,6BAA6BL,GAClCT,QAAAC,UAEF,IAAK,mBAAoB,OAAAD,QAAAC,QACjBX,EAAKyB,qBAAqBN,IAAYL,mBAG9C,IAAK,QAEH,OADAd,EAAK0B,YAAYP,GACjBT,QAAAC,UAGF,IAAK,YAEH,OADAX,EAAK2B,eAAeR,GACpBT,QAAAC,UAGF,IAAK,OAOH,OANAX,EAAKJ,WAAWgC,YAAY,CAC1BR,KAAM,OACNS,SAAUV,EAAYW,WAAWD,WAInCnB,QAAAC,UAIF,QAEE,OADAX,EAAKL,QAAQoC,QAAQZ,GACrBT,QAAAC,UAGN,CAAC,MAAAK,GAAA,OAAAN,QAAAO,OAAAD,EAAA,CAAA,EAAAjB,KAeMiC,UAAY,SAAAC,GACjBpC,EAAKO,OADqB6B,EAAN7B,MAEtB,EApNqBL,KAAOJ,QAAPA,EACAI,KAAUH,WAAVA,EAEnBG,KAAKJ,QAAQuC,UAAU,CAAEC,eAAgBvC,EAAWuC,iBACpDpC,KAAKH,WAAWsB,UAAUnB,KAAKmB,WAC/BnB,KAAKH,WAAWmB,aAAahB,KAAKS,uBAClCT,KAAKH,WAAWwC,aAAa,SAAAlC,GAAQ,OAAAL,EAAKwC,WAAWnC,EAAK,GAC1DH,KAAKa,aAAa,YACpB,CAAClB,EAzBgB4C,eAAP,SAAsBC,GAC9B,OAAAC,EAAA,CACEC,YAAa,GACbP,UAAW,aACXH,QAAS,WAAQ,EACjBhB,aAAc,WAAQ,EACtB2B,QAAS,WAAK,EACdxB,UAAW,WAAK,EAChByB,QAAS,WAAQ,EACjBP,aAAc,aACdQ,eAAgB,WAAK,EACrBC,wBAAyB,WAAQ,GAC9BN,EAEP,EAACO,IAAAA,EAAApD,EAAAqD,UA0RA,OA1RAD,EAaME,WAAA,WACL,YAAYxC,sBAAsB,CAAEyC,OAAQ,QAC9C,EAACH,EAUejC,4BAAgB,IACN,OAAxBd,KAAKH,WAAWsD,QAAQxC,QAAAC,SAC1B,CAAC,MAAAK,GAAA,OAAAN,QAAAO,OAAAD,EAAA,CAAA,EAAA8B,EAEST,WAAA,SAAWnC,GACfA,IAASH,KAAKG,OAChBH,KAAKG,KAAOA,EACZH,KAAKJ,QAAQyC,aAAa,CAAElC,KAAAA,IAEhC,EAAC4C,EAESlC,aAAA,SAAaT,GACjBA,IAAWJ,KAAKI,SAClBJ,KAAKI,OAASA,EACdJ,KAAKJ,QAAQiD,eAAe,CAAEzC,OAAAA,IAElC,EAAC2C,EAESK,sBAAA,WACR,IAAM5C,EAAkBR,KAAKM,iBAAmBN,KAAKO,oBACjDP,KAAKQ,kBAAoBA,IAC3BR,KAAKQ,gBAAkBA,EACvBR,KAAKJ,QAAQkD,wBAAwB,CAAEtC,gBAAAA,IAE3C,EAACuC,EAESzB,mBAAA,SAAmB+B,GACvBA,EAAMC,qBACRtD,KAAKE,uBAAyBmD,EAAMC,mBAAmBxB,SAE3D,EAACiB,EAESxB,oBAAA,SAAoB8B,GAC5BrD,KAAKJ,QAAQuB,UAAU,CACrBoC,OAAQ,KACRC,QAASH,EAAMI,qBAAqBC,gBAExC,EAACX,EAESvB,qBAAA,SAAqB6B,GAC7BrD,KAAKJ,QAAQuB,UAAU,CACrBoC,OAAQ,OACRC,QAASH,EAAMM,yBAAyBC,iBAE5C,EAACb,EAEStB,6BAAA,SACR4B,GAEArD,KAAKJ,QAAQoC,QAAQ,CACnBX,KAAM,2BACNwC,SACER,EAAMS,wCAAwCC,0BAEpD,EAAChB,EAESnB,eAAA,SAAeyB,GACnBrD,KAAKJ,QAAQoE,YACfhE,KAAKJ,QAAQoE,WAAW,CACtBC,SAAUZ,EAAMa,gBAAgBC,WAGtC,EAACpB,EAEerB,qBAAoB,SAAC2B,GAA0B,IAAA,IAAAe,EAGzDpE,YAAIW,QAAAC,QADNyD,WAAAA,GAAAA,OAAOrB,UAAUsB,eAAeC,KAC9BH,EAAKxE,QAAQ8C,YACbW,EAAMmB,iBAAiBC,gBACxBC,0BAEG/D,QAAAC,QAEOwD,EAAKxE,QAAQ8C,YAAYW,EAAMmB,iBAAiBC,WACrDpB,EAAMmB,iBAAiBG,aACxB5D,KAHG6D,SAAAA,GAMN,IAAMC,EACc,iBAAXD,EAAsBE,KAAKC,UAAUH,GAAUI,OAAOJ,GAE/DR,EAAKvE,WAAWgC,YAAY,CAC1BR,KAAM,qBACN4D,aAAc5B,EAAMmB,iBAAiBS,aACrCL,OAAQC,EACRK,UAAU,GACT,4DAjBJC,CAEG,EAgBH,SAAQlE,GACPmD,EAAKzB,QACoD1B,uDAAAA,MAAAA,OAAAA,EAAAA,EAAauC,SACpE,CACE4B,eAAgB/B,EAAMmB,iBAAiBC,YAG3CL,EAAKvE,WAAWgC,YAAY,CAC1BR,KAAM,qBACN4D,aAAc5B,EAAMmB,iBAAiBS,aACrCL,OAA0C3D,wCAAAA,SAAAA,EAAauC,SACvD0B,UAAU,GAEd,GAAC,GAAAR,GAAAA,EAAA3D,KAAA,OAAA2D,EAAA3D,wBAED,GAAIqD,EAAKxE,QAAQyF,0BAGf,YAFAjB,EAAKxE,QAAQyF,0BAA0BhC,EAAMmB,kBAK/CJ,EAAKzB,QACsBU,yBAAAA,EAAMmB,iBAAiBC,UAChD,4BAAA,CACEW,eAAgB/B,EAAMmB,iBAAiBC,YAG3CL,EAAKvE,WAAWgC,YAAY,CAC1BR,KAAM,qBACN4D,aAAc5B,EAAMmB,iBAAiBS,aACrCL,OAAM,yBAA2BvB,EAAMmB,iBAAiBC,UAAS,4BACjES,UAAU,GACT,EArDHb,GAuDJ,CAAC,MAAApD,GAAAN,OAAAA,QAAAO,OAAAD,EAAA8B,CAAAA,EAAAA,EAESpB,YAAA,SAAY0B,GAA0B,EAAAN,EAoDxCJ,QAAA,SAAQa,EAAiB8B,GAC/BC,QAAQC,MAAMhC,EAAS8B,GACvBtF,KAAKJ,QAAQ+C,QAAQa,EAAS8B,EAChC,EAACvC,EAEM0C,MAAA,WACL,OAAOzF,KAAKH,WAAWuC,cACzB,EAACW,EAEM2C,OAAA,WACL,MAAuB,cAAZ1F,KAACI,MACd,EAAC2C,EAMM4C,YAAA,SAAYC,GACjB5F,KAAKH,WAAW8F,YAAYC,EAC9B,EAAC7C,EAEM8C,0BAAA,WACL,OAAOpG,CACT,EAACsD,EAEM+C,2BAAA,WACL,OAAOrG,CACT,EAACsD,EAEMgD,eAAA,WACL,OAAO,CACT,EAAChD,EAEMiD,gBAAA,WACL,OAAO,CACT,EAACjD,EAEMkD,aAAA,SAAaC,GACblG,KAAKQ,iBASVR,KAAKH,WAAWgC,YAAY,CAC1BR,KAAM,WACN8E,MAAOD,EAAO,OAAS,UACvBpE,SAAU9B,KAAKM,iBAEjBN,KAAKO,oBAAsBP,KAAKM,eAChCN,KAAKoD,yBAdHmC,QAAQa,KACuB,IAA7BpG,KAAKO,oBACD,8DACA,iFAYV,EAACwC,EAEMsD,qBAAA,SAAqBC,GAC1BtG,KAAKH,WAAWgC,YAAY,CAC1BR,KAAM,oBACNiF,KAAAA,GAEJ,EAACvD,EAEMwD,gBAAA,SAAgBD,GACrBtG,KAAKH,WAAWgC,YAAY,CAC1BR,KAAM,eACNiF,KAAAA,GAEJ,EAACvD,EAEMyD,iBAAA,WACLxG,KAAKH,WAAWgC,YAAY,CAC1BR,KAAM,iBAEV,EAAC0B,EAEM0D,0BAAA,SAA0BC,EAAoBC,GACnD3G,KAAKH,WAAWgC,YAAY,CAC1BR,KAAM,2BACN4D,aAAcyB,EACdE,YAAaD,GAEjB,EAAChH,CAAA,ICrPmBkH,eAAc,WAYlC,SAAAA,EAAYC,YAAAA,IAAAA,EAAgD,CAAA,GAAE9G,KAPpD+G,MAA+B,QAC/BC,qBAAoD,KACpDC,KAAAA,qBAAoD,KAAIjH,KACxDkH,kBAA8C,UAC9CC,qBAAsD,KACtDnF,KAAAA,eAGRhC,KAAKgC,QAAU8E,EAAO9E,OACxB,CAAC,IAAAe,EAAA8D,EAAA7D,iBAAAD,EAESqE,MAAA,SAAMC,GACVrH,KAAKgC,SAAShC,KAAKgC,QAAQqF,EACjC,EAACtE,EAMM5B,UAAA,SAAUmG,GACftH,KAAKkH,kBAAoBI,EACzB,IAAMP,EAAQ/G,KAAK+G,MACnB/G,KAAK+G,MAAQ,GAETA,EAAMQ,OAAS,GAGjBC,eAAe,WACbT,EAAMU,QAAQH,EAChB,EAEJ,EAACvE,EAEM/B,aAAA,SAAasG,GAClBtH,KAAKiH,qBAAuBK,EAC5B,IAAM5G,EAAUV,KAAKgH,qBACjBtG,GAGF8G,eAAe,WACbF,EAAS5G,EACX,EAEJ,EAACqC,EAEMV,aAAA,SAAaiF,GAClBtH,KAAKmH,qBAAuBG,CAC9B,EAACvE,EAEST,WAAA,SAAWnC,GAAU,IAAAuH,EAC7BA,OAAAA,EAAI1H,KAACmH,uBAALO,EAAAnD,KAAAvE,KAA4BG,EAC9B,EAAC4C,EAES4E,WAAA,SAAWjH,OACakH,EAA3B5H,KAAKgH,uBACRhH,KAAKgH,qBAAuBtG,EACH,OAAzBkH,EAAA5H,KAAKiH,uBAALW,EAAArD,UAA4B7D,GAEhC,EAACqC,EAES8E,cAAA,SAAczG,GAClBpB,KAAKkH,kBACPlH,KAAKkH,kBAAkB9F,GAEvBpB,KAAK+G,MAAMe,KAAK1G,EAEpB,EAACyF,CAAA,CAvEiC,GA0EpB,SAAAkB,EAAYC,GAC1B,IAAAC,EAAqCD,EAAOE,MAAM,KAA3CC,EAAUF,KAAEG,EAAcH,EACjC,GAAA,IAAK,CAAC,MAAO,QAAQI,SAASF,GAC5B,MAAM,IAAIG,MAAK,mBAAoBN,GAGrC,IAAMO,EAAaC,OAAOC,SAASL,GACnC,GAAII,OAAOE,MAAMH,GACf,UAAUD,8BAA8BF,GAG1C,MAAO,CACLJ,OAAQG,EACRI,WAAAA,EAEJ,CCtNa,IAAAI,EAAkB,QC8If,SAAAC,EAAmBvF,GACjC,QAASA,EAAMhC,IACjB,CC9IO,IAAMwH,EACX,sCAEc,SAAAC,EACdhC,GAAqB,IAAAiC,EAMCC,EAAAC,EAAAC,EAAAC,EAAAC,EAJhBC,EAA4C,CAChDhI,KAAMwH,GAsCR,OAnCI/B,EAAOwC,YACTD,EAAeE,6BAA+B,CAC5CC,MAAO,CACLC,OAAQT,OAAFA,EAAElC,EAAOwC,UAAUE,YAAjBR,EAAAA,EAAwBS,OAChCC,cAAeT,OAAFA,EAAEnC,EAAOwC,UAAUE,YAAjBP,EAAAA,EAAwBU,aACvCC,SAAgC,OAAxBV,EAAEpC,EAAOwC,UAAUE,YAAK,EAAtBN,EAAwBU,UAEpCC,IAAK,CACHC,SAA8B,OAAtBX,EAAErC,EAAOwC,UAAUO,UAAG,EAApBV,EAAsBY,SAElCC,aAAc,CACZC,UAAwC,OAA/Bb,EAAEtC,EAAOwC,UAAUU,mBAAY,EAA7BZ,EAA+Bc,YAK5CpD,EAAOqD,qBACTd,EAAee,sBAAwBtD,EAAOqD,oBAG5CrD,EAAOuD,mBACThB,EAAeiB,kBAAoBxD,EAAOuD,kBAGxCvD,EAAOyD,SACTlB,EAAemB,QAAU1D,EAAOyD,QAG9BxB,OAAJA,EAAIjC,EAAOwC,YAAPP,EAAkB0B,SACpBpB,EAAeqB,YAAc,CAC3BnH,OAAQuD,EAAOwC,UAAUmB,OAAOlH,OAChCoH,QAAS7D,EAAOwC,UAAUmB,OAAOE,UAI9BtB,CACT,CCnCA,IAIauB,eAAoBC,SAAAA,GAK/B,SAAAD,EACmBE,EACjB1I,EACA2I,EACAC,GAA0BjL,IAAAA,EA8CvB,OA5CHA,EAAA8K,EAAAtG,KAAAvE,OAAQD,MALS+K,YAAA,EAAA/K,EALHqC,oBAAc,EAAArC,EACdgL,mBAAWhL,EACXiL,kBAGGjL,EAAAA,EAAM+K,OAANA,EAMjB/K,EAAKqC,eAAiBA,EACtBrC,EAAKgL,YAAcA,EACnBhL,EAAKiL,aAAeA,EAEpBjL,EAAK+K,OAAOG,iBAAiB,QAAS,SAAA5H,GAIpC6H,WACE,WACE,OAAAnL,EAAK4H,WAAW,CACdzE,OAAQ,QACRM,QAAS,mDACT8B,QAASjC,GACT,EACJ,EAEJ,GAEAtD,EAAK+K,OAAOG,iBAAiB,QAAS,SAAA5H,GACpCtD,EAAK4H,WACY,MAAftE,EAAM8H,KACF,CACEjI,OAAQ,QACRoC,QAASjC,GAEX,CACEH,OAAQ,QACRM,QACEH,EAAMH,QAAU,2CAClBoC,QAASjC,GAGnB,GAEAtD,EAAK+K,OAAOG,iBAAiB,UAAW,SAAA5H,GACtC,IACE,IAAMjC,EAAc0D,KAAKsG,MAAM/H,EAAMgI,MACrC,IAAKzC,EAAmBxH,GACtB,OAEFrB,EAAK8H,cAAczG,EACrB,CAAE,MAAOkK,GAAG,CACd,GAAGvL,CACL,CAACwL,EAAAX,EAAAC,GAAAD,EAEmBY,OAAA,SAClB1E,GAAqB,IAErB,IAAIgE,EAA2B,KAAK,OAAAnK,QAAAC,2CAEhC6K,IAAAA,EAAA1C,EAAA2C,EAEEC,EADEC,EAAsBH,OAAhBA,EAAG3E,EAAO8E,QAAMH,EAnEX,0BAsEXd,GAA0B,OAAhB5B,EAAAjC,EAAOwC,mBAASP,EAAhBA,EAAkB0B,eAAlB1B,EAA0B4B,UAAWhC,EAC/CpF,GAAyBmI,OAAhBA,EAAA5E,EAAOwC,mBAASoC,EAAhBA,EAAkBjB,eAAlBiB,EAA0BnI,SAAU,SAEnD,GAAIuD,EAAO+E,UAAW,CACpB,IAAMC,EAAYhF,EAAO+E,UAAUxD,SAAS,KAAO,IAAM,IACzDsD,EAAS7E,GAAAA,EAAO+E,UAAYC,EAAS,UAAUvI,EAAM,YAAYoH,CACnE,MACEgB,EAASC,EA5EQ,oCA4EoB9E,EAAOiF,mBAAkBxI,EAAM,YAAYoH,EAGlF,IAAMqB,EAAY,CAjFF,UAqFuB,OAHnClF,EAAOmF,eACTD,EAAUlE,KAAehB,UAAAA,EAAOmF,eAElCnB,EAAS,IAAIoB,UAAUP,EAAKK,GAAWrL,QAAAC,QAEN,IAAID,QAEnC,SAACC,EAASM,GACV4J,EAAQG,iBACN,OACA,WAAKkB,IAAAA,EACG9C,EAAiBP,EAAmBhC,GAEpC,OAANqF,EAAArB,IAAAqB,EAAQC,KAAKtH,KAAKC,UAAUsE,GAC9B,EACA,CAAEgD,MAAM,IAGVvB,EAAQG,iBAAiB,QAAS,SAAA5H,GAIhC6H,WAAW,kBAAMhK,EAAOmC,EAAM,EAAE,EAClC,GAEAyH,EAAQG,iBAAiB,QAAS/J,GAElC4J,EAAQG,iBACN,UACA,SAAC5H,GACC,IAAMG,EAAUsB,KAAKsG,MAAM/H,EAAMgI,MAE5BzC,EAAmBpF,KAIH,qCAAjBA,EAAQnC,KACVT,EAAQ4C,EAAQ8I,wCAEhB/G,QAAQa,KACN,wDAGN,EACA,CAAEiG,MAAM,GAEZ,IAAEtL,KAAA,SAzCIwL,GA2CN,IACEC,EAGED,EAHFC,gBACAC,EAEEF,EAFFE,0BACAC,EACEH,EADFG,wBAGI3B,EAAchD,EAAY2E,MAAAA,EAAAA,EAA2B,aACrD1B,EAAejD,EAAY0E,GAEjC,OAAO,IAAI7B,EACTE,EACA0B,EACAzB,EACAC,EACA,EACJ,6DAhFoC7F,YAgF3BK,OAAOmH,EAEd,MADM,OAANA,EAAA7B,IAAA6B,EAAQxJ,QACFqC,CACR,GACF,CAAC,MAAAvE,GAAA,OAAAN,QAAAO,OAAAD,EAAA,CAAA,EAAA,IAAA8B,EAAA6H,EAAA5H,UAcA,OAdAD,EAEMI,MAAA,WACLnD,KAAK8K,OAAO3H,OACd,EAACJ,EAEMlB,YAAA,SAAY2B,GACjBxD,KAAK8K,OAAOsB,KAAKtH,KAAKC,UAAUvB,GAClC,EAACT,EAEY4C,qBAAYC,GAAgB,IAGrC,OAFFL,QAAQa,qDAC0CR,EAAO,8CACvDjF,QAAAC,SACJ,CAAC,MAAAK,GAAAN,OAAAA,QAAAO,OAAAD,EAAA,CAAA,EAAA2J,CAAA,CA/J8BC,CAAQhE,GClBnC,SAAU+F,EAAoBC,GAClC,IAAMC,EAAS,IAAIpN,WAAWmN,GAG9B,OADmBE,OAAOC,KAAKhI,OAAOiI,aAAYC,MAAnBlI,OAAuB8H,GAExD,CAEgB,SAAAK,EAAoBC,GAIlC,IAHA,IAAMC,EAAeN,OAAOO,KAAKF,GAC3BG,EAAMF,EAAa9F,OACnBiG,EAAQ,IAAI9N,WAAW6N,GACpBE,EAAI,EAAGA,EAAIF,EAAKE,IACvBD,EAAMC,GAAKJ,EAAaK,WAAWD,GAErC,OAAOD,EAAMV,MACf,wFCfA,IAAMa,EAAW,IAAIC,IAEL,SAAAC,EAA0BC,EAAcC,GACtD,OAAcC,SAAAA,GAAyB,IAAA,IA4BpCC,EA5BoCC,EAAA,SAAAC,GAAAF,OAAAA,EAAAE,EAAAhJ,EAAA,WAoBnC,IACMiJ,EAAkDhB,sCADzCJ,KAAKe,GAC6C,OAAApN,QAAAC,QAC3DoN,EAAQK,UAAUD,IAAUrN,gBAClC4M,EAASW,IAAIR,EAAMM,EAAW,EAChC,EAAgB,WACd,MAAM,IAAI9F,4BACcwF,EAAI,iEAE9B,EAACG,EA3BKtC,EAAMgC,EAASY,IAAIT,GACzB,GAAInC,EACF,OAAAhL,QAAAC,QAAOoN,EAAQK,UAAU1C,IAG3B,IAAM6C,EAAO,IAAIC,KAAK,CAACV,GAAa,CAAE1M,KAAM,2BACtCqN,EAAUC,IAAIC,gBAAgBJ,GAAM9J,EAAAS,EACtC,WAAA,OAAAxE,QAAAC,QACIoN,EAAQK,UAAUK,IAAQ3N,gBAChC4M,EAASW,IAAIR,EAAMY,GAAST,EAE9B,CAAA,EAAA,EAAQ,WACNU,IAAIE,gBAAgBH,EACtB,GAAC/N,OAAAA,QAAAC,QAAA8D,GAAAA,EAAA3D,KAAA2D,EAAA3D,KAAAmN,GAAAA,EAAAxJ,GAeH,CAAC,MAAAzD,GAAA,OAAAN,QAAAO,OAAAD,EACH,CAAA,CAAA,CC1BO,IAAM6N,EAAwBjB,EACnC,uyHCyBW,IAAAkB,eAAiB,SAAAlE,GAU5B,SAAAkE,EACEC,EACA5M,EACA2I,EACAC,EACAlE,GAAkD/G,IAAAA,EAQnB,YAR/B+G,IAAAA,IAAAA,EAAgD,CAAE,IAElD/G,EAAA8K,EAAAtG,KAAMuC,KAAAA,IAAO9G,MAhBRoC,oBAAc,EAAArC,EACLgL,iBAAW,EAAAhL,EACXiL,kBAAY,EAAAjL,EAEpBiP,UAAI,EAAAjP,EACJkP,aAAc,EAAKlP,EACnBmP,aAAe,EAACnP,EAChBoP,oBAA2C,KAUjDpP,EAAKiP,KAAOA,EACZjP,EAAKqC,eAAiBA,EACtBrC,EAAKgL,YAAcA,EACnBhL,EAAKiL,aAAeA,EAEpBjL,EAAKqP,0BAA0BrP,CACjC,CAACwL,EAAAwD,EAAAlE,GAAAkE,EAEmBvD,OAAM,SACxB1E,GAAwB,IAAA,IAEpBuI,EAFoBnB,EAAAA,SAAAoB,GA+CxB,IAAMN,EAAO,IAAIO,EAAMA,KAAC,OAAApK,EAEpB,WAEF,IAAM/C,EAAc,QAAWoN,KAAKC,MAC9B1E,EAAchD,EAAY,aAC1BiD,EAAejD,EAAY,aAC3BlI,EAAa,IAAIkP,EACrBC,EACA5M,EACA2I,EACAC,EACAlE,GAI6D,OAAAnG,QAAAC,QAGzDoO,EAAKU,QAHQ5I,EAAO6I,YAtGD,kCAyGMN,IAAkBtO,KAAAJ,WAAAA,OAAAA,QAAAC,QAG3C,IAAID,QAAc,SAAAC,GACtB,GAAIf,EAAWoP,YACbrO,QACK,CACL,IAAMgP,EAAc,WAClBZ,EAAKa,IAAIC,EAAAA,UAAUC,UAAWH,GAC9BhP,GACF,EACAoO,EAAKgB,GAAGF,EAAAA,UAAUC,UAAWH,EAC/B,CACF,IAAE7O,KAEF,WAAekP,IAAAA,EAGd,OAHGjB,EAAKlB,OACPjO,EAAWuC,gBACT6N,OAAAA,EAAAjB,EAAKlB,KAAKoC,MAAM,6BAAhBD,EAAAA,EAAyC,KAAMjB,EAAKlB,MACvDnN,QAAAC,QAGKoO,EAAKmB,iBAAiBC,sBAAqB,IAAKrP,KAEtD,WAAA,IAAMsI,EAAiBP,EAAmBhC,GAKvC,OAHHjH,EAAWuH,MAAM,CACf/F,KAAMwH,EACNrF,QAAS6F,IACR1I,QAAAC,QAEGf,EAAWgC,YAAYwH,IAAetI,KAE5C,WAAA,OAAOlB,CAAW,QACpB,EAAC,SAAQ2F,GAAO7E,OAAAA,QAAAC,QACRoO,EAAKrH,cAAY5G,KACvB,WAAA,MAAMyE,CAAM,EACd,EAACyI,EApG6BvJ,EAG1B,WAAA,KAAA,sBAAuBoC,KAAUA,EAAOuI,kBAEG,OAAA,WAAA,GACpC,YAAavI,GAAUA,EAAOiF,QAAO5G,OAAAA,EAE1C,WAAA,IAAA4D,EAAA2C,EAAAD,EACId,GAA0B,OAAhB5B,EAAAjC,EAAOwC,YAAiB,OAARP,EAAhBA,EAAkB0B,aAAM,EAAxB1B,EAA0B4B,UAAWhC,EAC/CpF,GAAyBmI,OAAhBA,EAAA5E,EAAOwC,YAAPoC,OAAgBA,EAAhBA,EAAkBjB,aAAlBiB,EAAAA,EAA0BnI,SAAU,SAE7CqI,EAjDd,SAA2BA,GACzB,OAAOA,EAAOyE,QAAQ,YAAa,WACrC,CA+CuBC,CADmB7E,OAAhBA,EAAG3E,EAAO8E,QAAMH,EAnDjB,6BAqDmG,OAAA9K,QAAAC,QAC7F2P,MADR3E,EAAgD9E,0CAAAA,EAAOiF,QAAkBxI,WAAAA,EAAkBoH,YAAAA,IACzE5J,KAAA,SAA3B8C,GAEN,IAAKA,EAAS2M,GACZ,MAAU,IAAAlI,MAAK,2BACczE,EAASzD,OAAM,IAAIyD,EAAS4M,YAE1D,OAAA9P,QAAAC,QAEkBiD,EAAS6M,QAAM3P,KAA5BsK,SAAAA,GACyB,KAA/BgE,EAAoBhE,EAAKsF,OAGvB,MAAU,IAAArI,MAAM,0CAEpB,EAAA,EAAA,EAAS9C,SAAAA,GACP,IAAIoL,EAAMpL,aAAiB8C,MAAQ9C,EAAMhC,QAAUwB,OAAOQ,GAM1D,MALIA,aAAiB8C,OAAS9C,EAAMhC,QAAQ6E,SAAS,SACnDuI,EACE,gGAGM,IAAAtI,MAAK,gDACmCxB,EAAOiF,QAAO,KAAK6E,EAEvE,GAEA,MAAM,IAAItI,MACR,wEACA,CArC2C,GAA7C+G,EAAoBvI,EAAOuI,iBAqCzB,CAvCA,GAuCA,OAAA1O,QAAAC,QAAA8D,GAAAA,EAAA3D,KAAA2D,EAAA3D,KAAAmN,GAAAA,IA2DN,CAAC,MAAAjN,GAAAN,OAAAA,QAAAO,OAAAD,EAAA8B,CAAAA,EAAAA,IAAAA,EAAAgM,EAAA/L,UAkPA,OAlPAD,EAEOqM,wBAAA,WAAuBtP,IAAAA,EAAAG,KAAAA,EAE3BD,KAAI6Q,EAqEM7Q,KAAIoE,EAWRpE,KAjFRA,KAAKgP,KAAKgB,GAAGF,EAASA,UAACC,UAAsB,WAAA,IAEL,OADtC9P,EAAKgP,aAAc,EACnB1J,QAAQ8B,KAAK,yBAAyB1G,QAAAC,SACxC,CAAC,MAAAK,GAAA,OAAAN,QAAAO,OAAAD,EAAC,CAAA,GAEFjB,KAAKgP,KAAKgB,GAAGF,EAAAA,UAAUgB,aAAc,SAAA5N,GACnCpD,EAAKmP,aAAc,EACnBnP,EAAK6H,WAAW,CACdzE,OAAQ,QACRoC,QAAS,IAAIyL,WAAW,QAAS,CAAE7N,OAAQA,MAAAA,OAAAA,EAAAA,EAAQ8N,cAEvD,GAEAhR,KAAKgP,KAAKgB,GAAGF,EAASA,UAACmB,uBAAwB,SAAAC,GACzCA,IAAUC,EAAeA,gBAACL,eAC5BhR,EAAKmP,aAAc,EACnBnP,EAAK6H,WAAW,CACdzE,OAAQ,QACRM,QAAgD0N,uCAAAA,EAChD5L,QAAS,IAAI8L,MAAM,8BAGzB,GAGApR,KAAKgP,KAAKgB,GACRF,EAASA,UAACuB,aACV,SAACC,EAAqBC,GACpB,IACE,IAAM/N,EAAUsB,KAAKsG,OAAM,IAAIoG,aAAcC,OAAOH,IAGpD,GAAqB,UAAjB9N,EAAQnC,KACV,OAGEuH,EAAmBpF,GACrB1D,EAAK+H,cAAcrE,GAEnB+B,QAAQa,KAAK,iCAAkC5C,EAEnD,CAAE,MAAOgC,GACPD,QAAQa,KAAK,yCAA0CZ,GACvDD,QAAQa,KAAK,gBAAgB,IAAIoL,aAAcC,OAAOH,GACxD,CACF,GAGFtR,KAAKgP,KAAKgB,GACRF,EAASA,UAAC4B,gBAAe,SAEvBC,EACAC,EACAC,GAAwB,IACtBC,IAAAA,EAEAH,WAAAA,GAAAA,EAAMI,OAASC,EAAAA,MAAMC,KAAKC,OAC1BL,EAAYM,SAAS9J,SAAS,SAG9B,CAAA,IAAM+J,EAAmBT,EACnBU,EAAeD,EAAiBE,SAME,OALxCD,EAAaE,UAAW,EACxBF,EAAaG,UAAW,EAGxBH,EAAaI,MAAMC,QAAU,OAC7BC,SAASC,KAAKC,YAAYR,GAAc1R,QAAAC,QAGlCiQ,EAAKiC,kBAAkBV,IAAiBrR,KAAA,WAAA,EAAA,CAAA,CAd9C4Q,GAc8C,OAAAhR,QAAAC,QAAAkR,GAAAA,EAAA/Q,KAAA+Q,EAAA/Q,KAAA,WAAA,QAAA,EAElD,CAAC,MAAAE,GAAA,OAAAN,QAAAO,OAAAD,EAAA,CAAA,GAGHjB,KAAKgP,KAAKgB,GACRF,EAASA,UAACiD,sBACHC,SAAAA,GAA2B,IAQ/B,OAPGA,EAASzL,OAAS,EACAyL,EAAS,GACbb,SAAS9J,SAAS,UAChCjE,EAAK9B,WAAW,YAGlB8B,EAAK9B,WAAW,aACjB3B,QAAAC,SACH,CAAC,MAAAK,GAAA,OAAAN,QAAAO,OAAAD,EAAA,CAAA,EAEL,EAAC8B,EAEMI,MAAA,WACL,GAAInD,KAAKiP,YAAa,CACpB,IAEEjP,KAAKgP,KAAKmB,iBAAiB8C,uBAAuBxL,QAChD,SAAAyL,GACMA,EAAYvB,OACduB,EAAYvB,MAAMwB,MAEtB,EAEJ,CAAE,MAAO3N,GACPD,QAAQa,KAAK,+BAAgCZ,EAC/C,CAGIxF,KAAKmP,sBACPnP,KAAKmP,oBAAoBhM,QAAO,MAAO,SAAAqC,GACrCD,QAAQa,KAAK,uCAAwCZ,EACvD,GACAxF,KAAKmP,oBAAsB,MAG7BnP,KAAKgP,KAAKrH,YACZ,CACF,EAAC5E,EAEYlB,YAAA,SAAY2B,GAA4B,IAAA,IAAA4P,EAC9CpT,KAAL,IAAKoT,EAAKnE,cAAgBmE,EAAKpE,KAAKmB,iBAIlC,OAHA5K,QAAQa,KACN,mEAEFzF,QAAAC,UAIF,GAAI,qBAAsB4C,EAExB,OAAA7C,QAAAC,UACD,IAAAyS,EAAAlO,EAAA,WAGC,IACMkG,GADU,IAAIiI,aACCC,OAAOzO,KAAKC,UAAUvB,IAAU,OAAA7C,QAAAC,QAE/CwS,EAAKpE,KAAKmB,iBAAiBqD,YAAYnI,EAAM,CAAEoI,UAAU,KAAO1S,KAAA,aACxE,EAAC,SAAQyE,GACP4N,EAAKhM,MAAM,CACT/F,KAAM,qBACNmC,QAAS,CACPA,QAAAA,EACAgC,MAAAA,KAGJD,QAAQC,MAAM,qCAAsCA,EACtD,GAAC7E,OAAAA,QAAAC,QAAAyS,GAAAA,EAAAtS,KAAAsS,EAAAtS,KACH,WAAA,QAAA,EAAA,CAAC,MAAAE,GAAA,OAAAN,QAAAO,OAAAD,EAAA,CAAA,EAAA8B,EAGM2Q,QAAA,WACL,OAAW1T,KAACgP,IACd,EAACjM,EAEY4C,YAAA,SAAYC,GAAgB,IAAA+N,IAAAA,EAClC3T,KAAL,IAAK2T,EAAK1E,cAAgB0E,EAAK3E,KAAKmB,iBAIlC,OAHA5K,QAAQa,KACN,2EAEFzF,QAAAC,UAIF,IAAMgT,EAAsBD,EAAK3E,KAAKmB,iBAAiB0D,oBACrD7B,EAAKA,MAAC8B,OAAOC,YACb,OAAApT,QAAAC,QAEEgT,MAAAA,GAAAA,EAAqBjC,MAAKxM,EAAA,WACxB6O,IAAAA,EAEEpO,EAAOjF,QAAAC,QACHgT,EAAoBjC,MAAMsC,QAAMlT,KAAAJ,WAAAA,GAAAA,QAAAC,QAEhCgT,EAAoBjC,MAAMuC,UAAQnT,KAAA,cAAA,GAAAiT,GAAAA,EAAAjT,KAAA,OAAAiT,EAAAjT,KAAA,WAAA,EAE5C,EAAC,WAAgBJ,OAAAA,QAAAC,QAET+S,EAAK3E,KAAKmB,iBAAiBC,sBAAsBxK,IAAQ7E,KACjE,WAAA,EAAA,GAACJ,QAAAC,QAGK+S,EAAK3E,KAAKmB,iBAAiBC,sBAAsBxK,IAAQ7E,KAEnE,WAAA,GAAA,CAAC,MAAAE,GAAAN,OAAAA,QAAAO,OAAAD,EAAA,CAAA,EAAA8B,EAEa+P,kBAAiB,SAACnB,GAAuB,IAAA,IAAAwC,EAInDnU,KAAIoU,EAAAjP,EAAA,WADJ,IAAMkP,EAAe,IAAIC,aACzBH,EAAKhF,oBAAsBkF,EAG3B,IAAME,EAAc,IAAIC,YAAY,CAAC7C,EAAM8C,mBAGrClR,EAAS8Q,EAAaK,wBAAwBH,GAAa,OAAA5T,QAAAC,QAG3DkO,EAAsBuF,EAAaM,eAAa5T,KAGtD,WAAA,IAAMiN,EAAU,IAAI4G,iBAAiBP,EAAc,uBAGnDrG,EAAQ6G,KAAKC,YAAY,CACvBzT,KAAM,YACN2G,OAAQmM,EAAKnJ,aAAahD,OAC1BO,WAAY4L,EAAKnJ,aAAazC,aAIhCyF,EAAQ6G,KAAKE,UAAY,SAAC1R,GACxB,IAAA2R,EAA+B3R,EAAMgI,KAKrC,GAL2B2J,EAG3B,GAAwB,IAES,CAE/B,IAAMC,EAAcrI,EAPNoI,EAAEE,GAOkCpI,QAG5CqI,EAAUhB,EAAKjF,eAGrBiF,EAAKtM,cAAc,CACjBxG,KAAM,QACN+T,YAAa,CACXC,cAAeJ,EACfnT,SAAUqT,IAGhB,CACF,EAGA5R,EAAOmM,QAAQ1B,EAAS,EAC1B,EAASxI,SAAAA,GACPD,QAAQa,KAAK,kCAAmCZ,EAClD,GAAC,OAAA7E,QAAAC,QAAAwT,GAAAA,EAAArT,KAAAqT,EAAArT,KAAA,WAAA,QAAA,EACH,CAAC,MAAAE,GAAA,OAAAN,QAAAO,OAAAD,EAAA,CAAA,EAAA8N,CAAA,CApX2B,CAAQlI,GCVhByO,EAAgB,SACpCxO,GAAqB,IAErB,IAAMyO,EAlBR,SAAiCzO,GAE/B,OAAIA,EAAOyO,eACFzO,EAAOyO,eAIZ,sBAAuBzO,GAAUA,EAAOuI,kBACnC,SAIF,WACT,CAKyBmG,CAAwB1O,GAE/C,OAAQyO,GACN,IAAK,YACH,OAAA5U,QAAAC,QAAOgK,EAAoBY,OAAO1E,IACpC,IAAK,SACH,OAAAnG,QAAAC,QAAOmO,EAAiBvD,OAAO1E,IACjC,QACE,MAAU,IAAAwB,MAAkCiN,4BAAAA,GAElD,CAAC,MAAAtU,GAAA,OAAAN,QAAAO,OAAAD,EAAA,CAAA,WCpCewU,IACd,MACE,CACE,iBACA,mBACA,iBACA,OACA,SACA,QACApN,SAASqN,UAAUC,WAEpBD,UAAUE,UAAUvN,SAAS,QAAU,eAAgBsK,QAE5D,CCVsB,IAAAkD,EAAU,SAC9BC,QAAAA,IAAAA,IAAAA,EAA2B,CACzBC,QAAS,EAETC,QAAS,MACV,IAED,IACuBC,EADnBC,EAAQJ,EAAW,QACvB,GDKO,WAAWK,KAAKT,UAAUE,WCJ/BM,EAA2BD,OAAtBA,EAAGH,EAAYE,SAAOC,EAAIC,OACtBT,GAAAA,IAAe,CAAAW,IAAAA,EACxBF,EAAuBE,OAAlBA,EAAGN,EAAYO,KAAGD,EAAIF,CAC7B,CAAC,IAAAxR,EAAA,WAAA,GAEGwR,EAAQ,EAAC,OAAAvV,QAAAC,QACL,IAAID,QAAQ,SAAAC,UAAWsK,WAAWtK,EAASsV,EAAM,IAACnV,KAAAJ,WAAAA,EAAAA,CAHzD,GAGyDA,OAAAA,QAAAC,QAAA8D,GAAAA,EAAA3D,KAAA2D,EAAA3D,KAE5D,WAAA,QAAA,EAAA,CAAC,MAAAE,GAAAN,OAAAA,QAAAO,OAAAD,EAAA,CAAA,ECfYqV,eAAiB,SAAAC,GAAAD,SAAAA,IAAAC,OAAAA,EAAArJ,MAAAsJ,KAAAA,YAAAjL,IAAAA,CAmB3B,OAnB2BA,EAAA+K,EAAAC,GAAAD,EACRG,aAAY,SAC9B7W,GAAuB,IAEvB,IAAM8W,EAAc/W,EAAiB4C,eAAe3C,GAEpD8W,EAAY7T,eAAe,CAAEzC,OAAQ,eACrCsW,EAAY5T,wBAAwB,CAAEtC,iBAAiB,IAEvD,IAAIX,EAAoC,KAAK,OAAAc,QAAAC,gCACzCD,QAAAC,QACIiV,EAAWa,EAAYC,kBAAgB5V,KAAAJ,WAAAA,OAAAA,QAAAC,QAC1B0U,EAAiB1V,IAAQmB,KAAA6V,SAAAA,GAC5C,OAAO,IAAIN,EAAiBI,EAD5B7W,EAAU+W,EAC2C,EACvD,4DAL6CzR,CACzC,EAIKK,SAAAA,GAAOqR,IAAAA,EAGd,MAFAH,EAAY7T,eAAe,CAAEzC,OAAQ,iBAC3B,OAAVyW,EAAAhX,IAAAgX,EAAY1T,QACNqC,CACR,GACF,CAAC,MAAAvE,GAAA,OAAAN,QAAAO,OAAAD,EAAA,CAAA,EAAAqV,CAAA,CAnB2B,CAAQ3W,GCMzBmX,eAAK,WAmEhB,SAAAA,EACkBxR,EACAyR,EACA/I,EACAgJ,GAAwBhX,KAHxBsF,aACAyR,EAAAA,KAAAA,cACA/I,EAAAA,KAAAA,oBACAgJ,iBAAA,EAHAhX,KAAOsF,QAAPA,EACAtF,KAAQ+W,SAARA,EACA/W,KAAOgO,QAAPA,EACAhO,KAAWgX,YAAXA,CACf,CAACF,EAvEgBtL,OAAA,SAAMtJ,GACxB,IAAAqG,EAAUrG,EAAVqG,WACAP,EAAM9F,EAAN8F,OACAiP,EAA6B/U,EAA7B+U,8BAC2B,IAC3B,IAAI3R,EAA+B,KAC/B0R,EAAkC,KAAK,OAAArW,QAAAC,2CAEvCyS,SAAAA,IAAAnF,SAAAA,WAAAvN,QAAAC,QAkCIkO,EAAsBxJ,EAAQqP,eAAa5T,gBAEjD,IAAMmW,EAAWzU,EAAK0U,CAAAA,gBAAgB,GAASvX,GAAU,OAAAe,QAAAC,QACrC8U,UAAU0B,aAAaC,aAAa,CACtDC,MAAOJ,KACPnW,KAAA,SAAAwW,GAEF,IAAMhU,EAAS+B,EAAQoP,wBAJvBsC,EAAWO,GAKLvJ,EAAU,IAAI4G,iBAAiBtP,EAAS,uBAIpB,OAH1B0I,EAAQ6G,KAAKC,YAAY,CAAEzT,KAAM,YAAa2G,OAAAA,EAAQO,WAAAA,IAEtDhF,EAAOmM,QAAQqH,GACfA,EAASrH,QAAQ1B,GAASrN,QAAAC,QAEpB0E,EAAQkS,UAAQzW,KAEtB,WAAA,WAAW+V,EAAMxR,EAASyR,EAAU/I,EAASgJ,EAAa,EAAA,EAAA,EAAA,CA1B1D,IAAMS,EACJ/B,UAAU0B,aAAaM,0BAA0BnP,WAK7CwO,GAHNzR,EAAU,IAAIyH,OAAOuH,aACnBmD,EAA+B,CAAElP,WAAAA,GAAe,KAEzBoP,iBAAiBjT,EACtC,WAAA,IAAC+S,EAA4B,OAAA9W,QAAAC,QACzB0E,EAAQqP,aAAatG,UA3CjC,sGA2C4DtN,KAAA2D,WAAAA,EAAAA,CADpD,GACoDA,OAAAA,GAAAA,EAAA3D,KAAA2D,EAAA3D,KAAAmN,GAAAA,GAAA,CA/BxD,IAAMtO,EAAiC,CACrC2I,WAAY,CAAEqP,MAAOrP,GACrBsP,kBAAkB,EAClBC,kBAAkB,GAClBhG,gBAEE2D,KAAiBwB,EAA6BtW,OAAAA,QAAAC,QAExCmM,OAAO2I,UAAU0B,aAAaW,oBAAkBhX,KADlDiX,SAAAA,GAEN,IAAMC,EAAcD,EAAiBE,KACnC,SAAAC,GAGEA,MAAW,eAAXA,EAAEpG,MACF,CAAC,SAAU,YAAa,YAAYmG,KAAK,SAAAE,GAAO,OAC9CD,EAAEE,MAAMC,cAAcjQ,SAAS+P,EAAQ,EAE5C,GACGH,IACFrY,EAAQ2Y,SAAW,CAAEX,MAAOK,EAAYM,UAAWzG,EAAAA,IAAAA,OAAAA,GAAAA,EAAA/Q,KAAA+Q,EAAA/Q,KAAAsS,GAAAA,GA+BzD,6DArD2ClO,GAqDlCK,SAAAA,GAAOgT,IAAAA,EAAAC,EAGd,MAFW,OAAXD,EAAAxB,IAAAwB,EAAaE,YAAYjR,QAAQ,SAAAkK,UAASA,EAAMwB,MAAM,UACtDsF,EAAAnT,IAAAmT,EAAStV,QACHqC,CACR,GACF,CAAC,MAAAvE,GAAA,OAAAN,QAAAO,OAAAD,SAAA8B,EAAA+T,EAAA9T,iBAAAD,EASYI,MAAK,WAAA,IAC4C,OAA5DnD,KAAKgX,YAAY0B,YAAYjR,QAAQ,SAAAkK,UAASA,EAAMwB,MAAM,GAAExS,QAAAC,QAA5DZ,KACWsF,QAAQnC,SAAOpC,KAAA,WAAA,EAC5B,CAAC,MAAAE,GAAAN,OAAAA,QAAAO,OAAAD,EAAA,CAAA,EAAA8B,EAEM4V,SAAA,SAAS/S,GACd5F,KAAKgO,QAAQ6G,KAAKC,YAAY,CAAEzT,KAAM,WAAYuE,QAAAA,GACpD,EAACkR,CAAA,CAjFe,GCJL8B,EAA2B/K,EACtC,2zECLWgL,0BA0BX,SAAAA,EACkBvT,EACAyR,EACA+B,EACA9K,QAHA1I,aAAA,EAAAtF,KACA+W,cAAA,EAAA/W,KACA8Y,UACA9K,EAAAA,KAAAA,eAHAhO,KAAOsF,QAAPA,EACAtF,KAAQ+W,SAARA,EACA/W,KAAI8Y,KAAJA,EACA9Y,KAAOgO,QAAPA,CACf,QAAC6K,EA9BgBrN,OAAM,SAAAtJ,GACxB,IAAAqG,EAAUrG,EAAVqG,WACAP,EAAM9F,EAAN8F,WAEA,IAAI1C,EAA+B,KAAK,OAAA3E,QAAAC,iCAGhCmW,GADNzR,EAAU,IAAIgP,aAAa,CAAE/L,WAAAA,KACJoP,kBACnBmB,EAAOxT,EAAQyT,cAChBrJ,QAAQqH,GACbA,EAASrH,QAAQpK,EAAQ0T,aAAarY,QAAAC,QAChCgY,EAAyBtT,EAAQqP,eAAa5T,KAAA,WACpD,IAAMiN,EAAU,IAAI4G,iBAAiBtP,EAAS,0BAExB,OADtB0I,EAAQ6G,KAAKC,YAAY,CAAEzT,KAAM,YAAa2G,OAAAA,IAC9CgG,EAAQ0B,QAAQoJ,GAAMnY,QAAAC,QAEhB0E,EAAQkS,UAAQzW,gBAEtB,OAAO,IAAI8X,EAAOvT,EAASyR,EAAU+B,EAAM9K,EAAS,EACtD,yBAdI,IAEI+I,EACA+B,sCAJgC3T,CACpC,EAcKK,SAAAA,GAAOiT,IAAAA,EAEd,MADO,OAAPA,EAAAnT,IAAAmT,EAAStV,QACHqC,CACR,GACF,CAAC,MAAAvE,GAAAN,OAAAA,QAAAO,OAAAD,EAAA8B,CAAAA,EAAA8V,EAAA7V,UASYG,iBAAK,IACNxC,OAAAA,QAAAC,QAAJZ,KAAKsF,QAAQnC,SAAOpC,KAC5B,aAAA,CAAC,MAAAE,UAAAN,QAAAO,OAAAD,KAAA4X,CAAA,+FCxBUI,wBAAkB1C,GAmE7B,SAAA0C,EACErZ,EACAC,EACgBqZ,EACAC,EACTC,GAAiCrZ,IAAAA,EAIyB,OAFjEA,EAAAwW,EAAAhS,KAAM3E,KAAAA,EAASC,IAAYE,MAJXmZ,WAAA,EAAAnZ,EACAoZ,cAAApZ,EACTqZ,cAAA,EAAArZ,EARDsZ,0BAAkBtZ,EAClBuZ,yBAAmBvZ,EAAAA,EA8CnBwZ,sBAAwB,SAAClW,GAMX,cAAhBtD,EAAKK,QACPL,EAAKF,WAAWgC,YAAY,CAC1B2X,iBAAkB5M,EAPEvJ,EAAMgI,KAAK,GAOuByB,SAG5D,EAAC/M,EAEO0Z,uBAAyB,SAAAvX,OAAGmJ,EAAInJ,EAAJmJ,KAChB,YAAdA,EAAKhK,MACPtB,EAAKuC,WAAW+I,EAAKqO,SAAW,YAAc,WAElD,EAAC3Z,EAEO4Z,oBAAsB,SAACC,GAC7B7Z,EAAKoZ,OAAOL,KAAKA,KAAKe,MAAQ9Z,EAAKM,OACnCN,EAAKoZ,OAAOnL,QAAQ6G,KAAKC,YAAY,CAAEzT,KAAM,qBAC7CtB,EAAKoZ,OAAOnL,QAAQ6G,KAAKC,YAAY,CACnCzT,KAAM,SACNyL,OAAQK,EAAoByM,IAEhC,EAAC7Z,EAEO+Z,aAAe,WAErB/Z,EAAKuC,WAAW,aAChBvC,EAAKoZ,OAAOnL,QAAQ6G,KAAKC,YAAY,CAAEzT,KAAM,cAC7CtB,EAAKoZ,OAAOL,KAAKA,KAAKiB,6BACpB,KACAha,EAAKoZ,OAAO7T,QAAQ0U,YAAc,GAIpC9O,WAAW,WACTnL,EAAKoZ,OAAOL,KAAKA,KAAKe,MAAQ9Z,EAAKM,OACnCN,EAAKoZ,OAAOnL,QAAQ6G,KAAKC,YAAY,CAAEzT,KAAM,oBAC/C,EAAG,IACL,EAACtB,EAEOka,gBAAkB,SAACC,GACzB,GAA6B,IAAzBA,EAAc3S,OAChB,OACF,EAKA,IADA,IAAIlH,EAAS,EACJoN,EAAI,EAAGA,EAAIyM,EAAc3S,OAAQkG,IACxCpN,GAAU6Z,EAAczM,GAAK,IAI/B,OAFApN,GAAU6Z,EAAc3S,QAER,EAAI,EAAIlH,EAAS,EAAI,EAAIA,CAC3C,EAnGkBN,EAAKmZ,MAALA,EACAnZ,EAAMoZ,OAANA,EACTpZ,EAAQqZ,SAARA,EAGPrZ,EAAKmZ,MAAMlL,QAAQ6G,KAAKE,UAAYhV,EAAKwZ,sBACzCxZ,EAAKoZ,OAAOnL,QAAQ6G,KAAKE,UAAYhV,EAAK0Z,uBAAuB1Z,CACnE,CAACwL,EAAA0N,EAAA1C,GAAA0C,EA5EmBxC,sBAClB7W,GAAuB,QAAAoU,EAAA,WAAA7O,OAAAA,aAqBnBxE,OAAAA,QAAAC,QAG6B8U,UAAU0B,aAAaC,aAAa,CACjEC,OAAO,KACPvW,KAAAwW,SAAAA,GAAC,OAFH4C,EAAsB5C,EAEnB5W,QAAAC,QAEGiV,EAAWa,EAAYC,kBAAgB5V,KAAA,WAAA,OAAAJ,QAAAC,QAC1B0U,EAAiB1V,IAAQmB,KAAA,SAAA6V,GAAC,OAA7C/W,EAAU+W,EAAmCjW,QAAAC,QACrBD,QAAQyZ,IAAI,CAClCtD,EAAMtL,OAAM/I,EAAA,CAAA,EACP5C,EAAWkL,aACdkM,8BAA+BrX,EAAQqX,iCAEzC4B,EAAOrN,OAAO3L,EAAWmL,iBACzBjK,KAAAsZ,SAAAA,OAAAC,EAKF,OAXCpB,EAAKmB,EAAElB,GAAAA,EAAMkB,EAAA,GAQQ,OAAtBC,EAAAH,IAAAG,EAAwB5B,YAAYjR,QAAQ,SAAAkK,GAAK,OAAIA,EAAMwB,MAAM,GACjEgH,EAAyB,KAElB,IAAIlB,EACTvC,EACA7W,EACAqZ,EACAC,EACAC,EACA,EAAA,EAAA,EAAA,EACJ,EAAS5T,SAAAA,GAAO,IAAA+U,EAAA1D,EAAA2D,EAGM,OAFpB9D,EAAY7T,eAAe,CAAEzC,OAAQ,iBACrCma,OAAAA,EAAAJ,IAAAI,EAAwB7B,YAAYjR,QAAQ,SAAAkK,GAAS,OAAAA,EAAMwB,MAAM,UACjE0D,EAAAhX,IAAAgX,EAAY1T,QAAQxC,QAAAC,QACd4Z,OADcA,EACdtB,QAAAsB,EAAAA,EAAOrX,SAAOpC,KAAA0Z,WAAAA,IAAAA,SAAA9Z,QAAAC,eAAA6Z,EACdtB,UAAAsB,EAAQtX,SAAOpC,KAAA,WAAA,SAAA+Q,IAKrB,MAAMtM,CAAM,KAAA0I,EAAA/I,EAJR,WAAA,IAAAuV,EAAA,OAAA/Z,QAAAC,QACI8Z,OADJA,EACItB,QAAAsB,EAAAA,EAAUC,WAAS5Z,KACzBqY,WAAAA,EAAW,IAAK,EAClB,EAAC,cAAA,OAAAlL,GAAAA,EAAAnN,KAAAmN,EAAAnN,KAAA+Q,GAAAA,GAEH,EAAA,EAAA,IAzDM4E,EAAc/W,EAAiB4C,eAAe3C,GAEpD8W,EAAY7T,eAAe,CAAEzC,OAAQ,eACrCsW,EAAY5T,wBAAwB,CAAEtC,iBAAiB,IAEvD,IAAI0Y,EAAsB,KACtBrZ,EAAoC,KACpCsZ,EAAwB,KACxBgB,EAA6C,KAE7Cf,EAAoC,KAAK/F,EAAA,SAAAuH,GAAAA,GACtB,OADsBA,EACzChb,EAAQib,cAAWD,OAAQlW,EAAAS,EAAA,kBACzBxE,QAAAC,QACe8U,UAAU0D,SAAS0B,QAAQ,WAAS/Z,KAAAga,SAAAA,GAArD3B,EAAQ2B,CAA8C,EACxD,EAACrW,cAAAA,GAAAA,GAAAA,EAAA3D,KAAA2D,OAAAA,EAAA3D,oBAJ0C,UAI1CJ,QAAAC,QAAAyS,GAAAA,EAAAtS,KAAAsS,EAAAtS,KAAAiT,GAAAA,IA4CL,CAAC,MAAA/S,GAAA,OAAAN,QAAAO,OAAAD,EAAA,CAAA,EAAA,IAAA8B,EAAAkW,EAAAjW,UA6IAiW,OA7IAlW,EAiBwBjC,iBAAA,eAAgBb,IAAAA,cAAAU,QAAAC,QAAA2V,EAAAvT,UAC3BlC,iBAAgByD,KAAAtE,IAAAc,KAAA,WAAA,SAAAia,IAAA,OAAAra,QAAAC,QAMtBX,EAAKiZ,MAAM/V,SAAOpC,KAAA,WAAA,OAAAJ,QAAAC,QAClBX,EAAKkZ,OAAOhW,SAAOpC,KAAA,WAAA,EAAA,EAAA,CAAA,IAAAqT,EAAAjP,EANrB,WAAA,IAAA8V,EAAAta,OAAAA,QAAAC,QACiB,OADjBqa,EACIhb,EAAKmZ,eAAQ,EAAb6B,EAAeN,WAAS5Z,KAC9Bd,WAAAA,EAAKmZ,SAAW,IAAK,EACvB,EAAChF,WAAAA,GAAAA,OAAAA,GAAAA,EAAArT,KAAAqT,EAAArT,KAAAia,GAAAA,GAIH,EAAA,CAAC,MAAA/Z,GAAA,OAAAN,QAAAO,OAAAD,EAAA,CAAA,EAAA8B,EAEkBzB,mBAAA,SAAmB+B,GACpCkT,EAAAvT,UAAM1B,mBAAkBiD,KAAClB,KAAAA,GACzBrD,KAAK8Z,cACP,EAAC/W,EAEkBpB,YAAA,SAAY0B,GACkC,IAAA6X,EAAAC,EAA3Dnb,KAAKE,wBAA0BmD,EAAM+R,YAAYtT,WAC/B,OAApBoZ,GAAAC,OAAKvb,SAAQgD,UAAbsY,EAAA3W,KAAA4W,EAAuB9X,EAAM+R,YAAYC,eAInCrV,KAAKH,sBAAsBkP,GAC/B/O,KAAK2Z,oBAAoBtW,EAAM+R,YAAYC,eAG7CrV,KAAKM,eAAiB+C,EAAM+R,YAAYtT,SACxC9B,KAAKoD,wBACLpD,KAAKsC,WAAW,YAEpB,EAACS,EA8DM4C,YAAA,SAAYC,GAEb5F,KAAKH,sBAAsBkP,EAC7B/O,KAAKH,WAAW8F,YAAYC,GAG5B5F,KAAKkZ,MAAMP,SAAS/S,EAExB,EAAC7C,EAEM8C,0BAAA,WAKL,OAJuBuV,MAAnBpb,KAACqZ,qBAALrZ,KAAKqZ,mBAAuB,IAAI3Z,WAC9BM,KAAKkZ,MAAMnC,SAASsE,oBAEtBrb,KAAKkZ,MAAMnC,SAASuE,qBAAqBtb,KAAKqZ,oBACvCrZ,KAAKqZ,kBACd,EAACtW,EAEM+C,2BAAA,WAKL,aAJA9F,KAAKsZ,sBAALtZ,KAAKsZ,oBAAwB,IAAI5Z,WAC/BM,KAAKmZ,OAAOpC,SAASsE,oBAEvBrb,KAAKmZ,OAAOpC,SAASuE,qBAAqBtb,KAAKsZ,qBACpCtZ,KAACsZ,mBACd,EAACvW,EAEMgD,eAAA,WACL,OAAO/F,KAAKia,gBAAgBja,KAAK6F,4BACnC,EAAC9C,EAEMiD,gBAAA,WACL,OAAOhG,KAAKia,gBAAgBja,KAAK8F,6BACnC,EAACmT,CAAA,EA3MoCtZ,qCCab,SAAA4W,GAAAgF,SAAAA,WAAAhF,EAAArJ,MAAAlN,KAAAwW,YAAAjL,IAAAA,CAKvBgQ,OALuBhQ,EAAAgQ,EAAAhF,GAAAgF,EACV9E,aAAP,SAAoB7W,GACzB,OAAOA,EAAQsK,SACXoM,EAAiBG,aAAa7W,GAC9BqZ,EAAkBxC,aAAa7W,EACrC,EAAC2b,CAAA,CALuB,CAAQ5b,mHCzBlB,SACdyC,EACA8D,EACA0F,GAEA,YAFAA,IAAAA,IAAAA,EALuB,6BAOhB2E,MAAS3E,EAAkCxJ,4BAAAA,EAA2B,YAAA,CAC3EoZ,OAAQ,OACR5I,KAAM9N,KAAKC,UAAU,CACnB0W,SAAUvV,EAAO,OAAS,YAE5BwV,QAAS,CACP,eAAgB,qBAGtB"}
@@ -0,0 +1,2 @@
1
+ import{Room as e,RoomEvent as t,ConnectionState as n,Track as o}from"livekit-client";function s(){return s=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var o in n)({}).hasOwnProperty.call(n,o)&&(e[o]=n[o])}return e},s.apply(null,arguments)}const a=new Uint8Array(0);class i{static getFullOptions(e){return s({clientTools:{},onConnect:()=>{},onDebug:()=>{},onDisconnect:()=>{},onError:()=>{},onMessage:()=>{},onAudio:()=>{},onModeChange:()=>{},onStatusChange:()=>{},onCanSendFeedbackChange:()=>{}},e)}constructor(e,t){var n=this;this.options=void 0,this.connection=void 0,this.lastInterruptTimestamp=0,this.mode="listening",this.status="connecting",this.volume=1,this.currentEventId=1,this.lastFeedbackEventId=0,this.canSendFeedback=!1,this.endSessionWithDetails=async function(e){"connected"!==n.status&&"connecting"!==n.status||(n.updateStatus("disconnecting"),await n.handleEndSession(),n.updateStatus("disconnected"),n.options.onDisconnect(e))},this.onMessage=async function(e){switch(e.type){case"interruption":return void n.handleInterruption(e);case"agent_response":return void n.handleAgentResponse(e);case"user_transcript":return void n.handleUserTranscript(e);case"internal_tentative_agent_response":return void n.handleTentativeAgentResponse(e);case"client_tool_call":return void await n.handleClientToolCall(e);case"audio":return void n.handleAudio(e);case"vad_score":return void n.handleVadScore(e);case"ping":return void n.connection.sendMessage({type:"pong",event_id:e.ping_event.event_id});default:return void n.options.onDebug(e)}},this.setVolume=({volume:e})=>{this.volume=e},this.options=e,this.connection=t,this.options.onConnect({conversationId:t.conversationId}),this.connection.onMessage(this.onMessage),this.connection.onDisconnect(this.endSessionWithDetails),this.connection.onModeChange(e=>this.updateMode(e)),this.updateStatus("connected")}endSession(){return this.endSessionWithDetails({reason:"user"})}async handleEndSession(){this.connection.close()}updateMode(e){e!==this.mode&&(this.mode=e,this.options.onModeChange({mode:e}))}updateStatus(e){e!==this.status&&(this.status=e,this.options.onStatusChange({status:e}))}updateCanSendFeedback(){const e=this.currentEventId!==this.lastFeedbackEventId;this.canSendFeedback!==e&&(this.canSendFeedback=e,this.options.onCanSendFeedbackChange({canSendFeedback:e}))}handleInterruption(e){e.interruption_event&&(this.lastInterruptTimestamp=e.interruption_event.event_id)}handleAgentResponse(e){this.options.onMessage({source:"ai",message:e.agent_response_event.agent_response})}handleUserTranscript(e){this.options.onMessage({source:"user",message:e.user_transcription_event.user_transcript})}handleTentativeAgentResponse(e){this.options.onDebug({type:"tentative_agent_response",response:e.tentative_agent_response_internal_event.tentative_agent_response})}handleVadScore(e){this.options.onVadScore&&this.options.onVadScore({vadScore:e.vad_score_event.vad_score})}async handleClientToolCall(e){if(Object.prototype.hasOwnProperty.call(this.options.clientTools,e.client_tool_call.tool_name))try{var t;const n=null!=(t=await this.options.clientTools[e.client_tool_call.tool_name](e.client_tool_call.parameters))?t:"Client tool execution successful.",o="object"==typeof n?JSON.stringify(n):String(n);this.connection.sendMessage({type:"client_tool_result",tool_call_id:e.client_tool_call.tool_call_id,result:o,is_error:!1})}catch(t){this.onError(`Client tool execution failed with following error: ${null==t?void 0:t.message}`,{clientToolName:e.client_tool_call.tool_name}),this.connection.sendMessage({type:"client_tool_result",tool_call_id:e.client_tool_call.tool_call_id,result:`Client tool execution failed: ${null==t?void 0:t.message}`,is_error:!0})}else{if(this.options.onUnhandledClientToolCall)return void this.options.onUnhandledClientToolCall(e.client_tool_call);this.onError(`Client tool with name ${e.client_tool_call.tool_name} is not defined on client`,{clientToolName:e.client_tool_call.tool_name}),this.connection.sendMessage({type:"client_tool_result",tool_call_id:e.client_tool_call.tool_call_id,result:`Client tool with name ${e.client_tool_call.tool_name} is not defined on client`,is_error:!0})}}handleAudio(e){}onError(e,t){console.error(e,t),this.options.onError(e,t)}getId(){return this.connection.conversationId}isOpen(){return"connected"===this.status}setMicMuted(e){this.connection.setMicMuted(e)}getInputByteFrequencyData(){return a}getOutputByteFrequencyData(){return a}getInputVolume(){return 0}getOutputVolume(){return 0}sendFeedback(e){this.canSendFeedback?(this.connection.sendMessage({type:"feedback",score:e?"like":"dislike",event_id:this.currentEventId}),this.lastFeedbackEventId=this.currentEventId,this.updateCanSendFeedback()):console.warn(0===this.lastFeedbackEventId?"Cannot send feedback: the conversation has not started yet.":"Cannot send feedback: feedback has already been sent for the current response.")}sendContextualUpdate(e){this.connection.sendMessage({type:"contextual_update",text:e})}sendUserMessage(e){this.connection.sendMessage({type:"user_message",text:e})}sendUserActivity(){this.connection.sendMessage({type:"user_activity"})}sendMCPToolApprovalResult(e,t){this.connection.sendMessage({type:"mcp_tool_approval_result",tool_call_id:e,is_approved:t})}}class r{constructor(e={}){this.queue=[],this.disconnectionDetails=null,this.onDisconnectCallback=null,this.onMessageCallback=null,this.onModeChangeCallback=null,this.onDebug=void 0,this.onDebug=e.onDebug}debug(e){this.onDebug&&this.onDebug(e)}onMessage(e){this.onMessageCallback=e;const t=this.queue;this.queue=[],t.length>0&&queueMicrotask(()=>{t.forEach(e)})}onDisconnect(e){this.onDisconnectCallback=e;const t=this.disconnectionDetails;t&&queueMicrotask(()=>{e(t)})}onModeChange(e){this.onModeChangeCallback=e}updateMode(e){var t;null==(t=this.onModeChangeCallback)||t.call(this,e)}disconnect(e){var t;this.disconnectionDetails||(this.disconnectionDetails=e,null==(t=this.onDisconnectCallback)||t.call(this,e))}handleMessage(e){this.onMessageCallback?this.onMessageCallback(e):this.queue.push(e)}}function c(e){const[t,n]=e.split("_");if(!["pcm","ulaw"].includes(t))throw new Error(`Invalid format: ${e}`);const o=Number.parseInt(n);if(Number.isNaN(o))throw new Error(`Invalid sample rate: ${n}`);return{format:t,sampleRate:o}}const l="0.5.0";function u(e){return!!e.type}const d="conversation_initiation_client_data";function h(e){var t;const n={type:d};var o,s,a,i,r;return e.overrides&&(n.conversation_config_override={agent:{prompt:null==(o=e.overrides.agent)?void 0:o.prompt,first_message:null==(s=e.overrides.agent)?void 0:s.firstMessage,language:null==(a=e.overrides.agent)?void 0:a.language},tts:{voice_id:null==(i=e.overrides.tts)?void 0:i.voiceId},conversation:{text_only:null==(r=e.overrides.conversation)?void 0:r.textOnly}}),e.customLlmExtraBody&&(n.custom_llm_extra_body=e.customLlmExtraBody),e.dynamicVariables&&(n.dynamic_variables=e.dynamicVariables),e.userId&&(n.user_id=e.userId),null!=(t=e.overrides)&&t.client&&(n.source_info={source:e.overrides.client.source,version:e.overrides.client.version}),n}class p extends r{constructor(e,t,n,o){super(),this.socket=void 0,this.conversationId=void 0,this.inputFormat=void 0,this.outputFormat=void 0,this.socket=e,this.conversationId=t,this.inputFormat=n,this.outputFormat=o,this.socket.addEventListener("error",e=>{setTimeout(()=>this.disconnect({reason:"error",message:"The connection was closed due to a socket error.",context:e}),0)}),this.socket.addEventListener("close",e=>{this.disconnect(1e3===e.code?{reason:"agent",context:e}:{reason:"error",message:e.reason||"The connection was closed by the server.",context:e})}),this.socket.addEventListener("message",e=>{try{const t=JSON.parse(e.data);if(!u(t))return;this.handleMessage(t)}catch(e){}})}static async create(e){let t=null;try{var n,o,s;const a=null!=(n=e.origin)?n:"wss://api.elevenlabs.io";let i;const r=(null==(o=e.overrides)||null==(o=o.client)?void 0:o.version)||l,d=(null==(s=e.overrides)||null==(s=s.client)?void 0:s.source)||"js_sdk";if(e.signedUrl){const t=e.signedUrl.includes("?")?"&":"?";i=`${e.signedUrl}${t}source=${d}&version=${r}`}else i=`${a}/v1/convai/conversation?agent_id=${e.agentId}&source=${d}&version=${r}`;const m=["convai"];e.authorization&&m.push(`bearer.${e.authorization}`),t=new WebSocket(i,m);const v=await new Promise((n,o)=>{t.addEventListener("open",()=>{var n;const o=h(e);null==(n=t)||n.send(JSON.stringify(o))},{once:!0}),t.addEventListener("error",e=>{setTimeout(()=>o(e),0)}),t.addEventListener("close",o),t.addEventListener("message",e=>{const t=JSON.parse(e.data);u(t)&&("conversation_initiation_metadata"===t.type?n(t.conversation_initiation_metadata_event):console.warn("First received message is not conversation metadata."))},{once:!0})}),{conversation_id:g,agent_output_audio_format:f,user_input_audio_format:w}=v,y=c(null!=w?w:"pcm_16000"),_=c(f);return new p(t,g,y,_)}catch(e){var a;throw null==(a=t)||a.close(),e}}close(){this.socket.close()}sendMessage(e){this.socket.send(JSON.stringify(e))}async setMicMuted(e){console.warn(`WebSocket connection setMicMuted called with ${e}, but this is handled by VoiceConversation`)}}function m(e){const t=new Uint8Array(e);return window.btoa(String.fromCharCode(...t))}function v(e){const t=window.atob(e),n=t.length,o=new Uint8Array(n);for(let e=0;e<n;e++)o[e]=t.charCodeAt(e);return o.buffer}const g=new Map;function f(e,t){return async n=>{const o=g.get(e);if(o)return n.addModule(o);const s=new Blob([t],{type:"application/javascript"}),a=URL.createObjectURL(s);try{return await n.addModule(a),void g.set(e,a)}catch(e){URL.revokeObjectURL(a)}try{const o=`data:application/javascript;base64,${btoa(t)}`;await n.addModule(o),g.set(e,o)}catch(t){throw new Error(`Failed to load the ${e} worklet module. Make sure the browser supports AudioWorklets.`)}}}const w=f("raw-audio-processor",'\nconst BIAS = 0x84;\nconst CLIP = 32635;\nconst encodeTable = [\n 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,\n 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,\n 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,\n 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,\n 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,\n 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,\n 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,\n 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7\n];\n\nfunction encodeSample(sample) {\n let sign;\n let exponent;\n let mantissa;\n let muLawSample;\n sign = (sample >> 8) & 0x80;\n if (sign !== 0) sample = -sample;\n sample = sample + BIAS;\n if (sample > CLIP) sample = CLIP;\n exponent = encodeTable[(sample>>7) & 0xFF];\n mantissa = (sample >> (exponent+3)) & 0x0F;\n muLawSample = ~(sign | (exponent << 4) | mantissa);\n \n return muLawSample;\n}\n\nclass RawAudioProcessor extends AudioWorkletProcessor {\n constructor() {\n super();\n \n this.port.onmessage = ({ data }) => {\n switch (data.type) {\n case "setFormat":\n this.isMuted = false;\n this.buffer = []; // Initialize an empty buffer\n this.bufferSize = data.sampleRate / 4;\n this.format = data.format;\n\n if (globalThis.LibSampleRate && sampleRate !== data.sampleRate) {\n globalThis.LibSampleRate.create(1, sampleRate, data.sampleRate).then(resampler => {\n this.resampler = resampler;\n });\n }\n break;\n case "setMuted":\n this.isMuted = data.isMuted;\n break;\n }\n };\n }\n process(inputs) {\n if (!this.buffer) {\n return true;\n }\n \n const input = inputs[0]; // Get the first input node\n if (input.length > 0) {\n let channelData = input[0]; // Get the first channel\'s data\n\n // Resample the audio if necessary\n if (this.resampler) {\n channelData = this.resampler.full(channelData);\n }\n\n // Add channel data to the buffer\n this.buffer.push(...channelData);\n // Get max volume \n let sum = 0.0;\n for (let i = 0; i < channelData.length; i++) {\n sum += channelData[i] * channelData[i];\n }\n const maxVolume = Math.sqrt(sum / channelData.length);\n // Check if buffer size has reached or exceeded the threshold\n if (this.buffer.length >= this.bufferSize) {\n const float32Array = this.isMuted \n ? new Float32Array(this.buffer.length)\n : new Float32Array(this.buffer);\n\n let encodedArray = this.format === "ulaw"\n ? new Uint8Array(float32Array.length)\n : new Int16Array(float32Array.length);\n\n // Iterate through the Float32Array and convert each sample to PCM16\n for (let i = 0; i < float32Array.length; i++) {\n // Clamp the value to the range [-1, 1]\n let sample = Math.max(-1, Math.min(1, float32Array[i]));\n\n // Scale the sample to the range [-32768, 32767]\n let value = sample < 0 ? sample * 32768 : sample * 32767;\n if (this.format === "ulaw") {\n value = encodeSample(Math.round(value));\n }\n\n encodedArray[i] = value;\n }\n\n // Send the buffered data to the main script\n this.port.postMessage([encodedArray, maxVolume]);\n\n // Clear the buffer after sending\n this.buffer = [];\n }\n }\n return true; // Continue processing\n }\n}\nregisterProcessor("raw-audio-processor", RawAudioProcessor);\n');class y extends r{constructor(e,t,n,o,s={}){super(s),this.conversationId=void 0,this.inputFormat=void 0,this.outputFormat=void 0,this.room=void 0,this.isConnected=!1,this.audioEventId=1,this.audioCaptureContext=null,this.room=e,this.conversationId=t,this.inputFormat=n,this.outputFormat=o,this.setupRoomEventListeners()}static async create(n){let o;if("conversationToken"in n&&n.conversationToken)o=n.conversationToken;else{if(!("agentId"in n)||!n.agentId)throw new Error("Either conversationToken or agentId is required for WebRTC connection");try{var s,a,i;const e=(null==(s=n.overrides)||null==(s=s.client)?void 0:s.version)||l,t=(null==(a=n.overrides)||null==(a=a.client)?void 0:a.source)||"js_sdk",c=`${r=null!=(i=n.origin)?i:"https://api.elevenlabs.io",r.replace(/^wss:\/\//,"https://")}/v1/convai/conversation/token?agent_id=${n.agentId}&source=${t}&version=${e}`,u=await fetch(c);if(!u.ok)throw new Error(`ElevenLabs API returned ${u.status} ${u.statusText}`);if(o=(await u.json()).token,!o)throw new Error("No conversation token received from API")}catch(e){let t=e instanceof Error?e.message:String(e);throw e instanceof Error&&e.message.includes("401")&&(t="Your agent has authentication enabled, but no signed URL or conversation token was provided."),new Error(`Failed to fetch conversation token for agent ${n.agentId}: ${t}`)}}var r;const u=new e;try{const e=`room_${Date.now()}`,s=c("pcm_48000"),a=c("pcm_48000"),i=new y(u,e,s,a,n),r=n.livekitUrl||"wss://livekit.rtc.elevenlabs.io";var p;await u.connect(r,o),await new Promise(e=>{if(i.isConnected)e();else{const n=()=>{u.off(t.Connected,n),e()};u.on(t.Connected,n)}}),u.name&&(i.conversationId=(null==(p=u.name.match(/(conv_[a-zA-Z0-9]+)/))?void 0:p[0])||u.name),await u.localParticipant.setMicrophoneEnabled(!0);const l=h(n);return i.debug({type:d,message:l}),await i.sendMessage(l),i}catch(e){throw await u.disconnect(),e}}setupRoomEventListeners(){var e=this;this.room.on(t.Connected,async function(){e.isConnected=!0,console.info("WebRTC room connected")}),this.room.on(t.Disconnected,e=>{this.isConnected=!1,this.disconnect({reason:"agent",context:new CloseEvent("close",{reason:null==e?void 0:e.toString()})})}),this.room.on(t.ConnectionStateChanged,e=>{e===n.Disconnected&&(this.isConnected=!1,this.disconnect({reason:"error",message:`LiveKit connection state changed to ${e}`,context:new Event("connection_state_changed")}))}),this.room.on(t.DataReceived,(e,t)=>{try{const t=JSON.parse((new TextDecoder).decode(e));if("audio"===t.type)return;u(t)?this.handleMessage(t):console.warn("Invalid socket event received:",t)}catch(t){console.warn("Failed to parse incoming data message:",t),console.warn("Raw payload:",(new TextDecoder).decode(e))}}),this.room.on(t.TrackSubscribed,async function(t,n,s){if(t.kind===o.Kind.Audio&&s.identity.includes("agent")){const n=t,o=n.attach();o.autoplay=!0,o.controls=!1,o.style.display="none",document.body.appendChild(o),await e.setupAudioCapture(n)}}),this.room.on(t.ActiveSpeakersChanged,async function(t){t.length>0?t[0].identity.includes("agent")&&e.updateMode("speaking"):e.updateMode("listening")})}close(){if(this.isConnected){try{this.room.localParticipant.audioTrackPublications.forEach(e=>{e.track&&e.track.stop()})}catch(e){console.warn("Error stopping local tracks:",e)}this.audioCaptureContext&&(this.audioCaptureContext.close().catch(e=>{console.warn("Error closing audio capture context:",e)}),this.audioCaptureContext=null),this.room.disconnect()}}async sendMessage(e){if(this.isConnected&&this.room.localParticipant){if(!("user_audio_chunk"in e))try{const t=(new TextEncoder).encode(JSON.stringify(e));await this.room.localParticipant.publishData(t,{reliable:!0})}catch(t){this.debug({type:"send_message_error",message:{message:e,error:t}}),console.error("Failed to send message via WebRTC:",t)}}else console.warn("Cannot send message: room not connected or no local participant")}getRoom(){return this.room}async setMicMuted(e){if(!this.isConnected||!this.room.localParticipant)return void console.warn("Cannot set microphone muted: room not connected or no local participant");const t=this.room.localParticipant.getTrackPublication(o.Source.Microphone);if(null!=t&&t.track)try{e?await t.track.mute():await t.track.unmute()}catch(t){await this.room.localParticipant.setMicrophoneEnabled(!e)}else await this.room.localParticipant.setMicrophoneEnabled(!e)}async setupAudioCapture(e){try{const t=new AudioContext;this.audioCaptureContext=t;const n=new MediaStream([e.mediaStreamTrack]),o=t.createMediaStreamSource(n);await w(t.audioWorklet);const s=new AudioWorkletNode(t,"raw-audio-processor");s.port.postMessage({type:"setFormat",format:this.outputFormat.format,sampleRate:this.outputFormat.sampleRate}),s.port.onmessage=e=>{const[t,n]=e.data;if(n>.01){const e=m(t.buffer),n=this.audioEventId++;this.handleMessage({type:"audio",audio_event:{audio_base_64:e,event_id:n}})}},o.connect(s)}catch(e){console.warn("Failed to set up audio capture:",e)}}}async function _(e){const t=function(e){return e.connectionType?e.connectionType:"conversationToken"in e&&e.conversationToken?"webrtc":"websocket"}(e);switch(t){case"websocket":return p.create(e);case"webrtc":return y.create(e);default:throw new Error(`Unknown connection type: ${t}`)}}function b(){return["iPad Simulator","iPhone Simulator","iPod Simulator","iPad","iPhone","iPod"].includes(navigator.platform)||navigator.userAgent.includes("Mac")&&"ontouchend"in document}async function k(e={default:0,android:3e3}){let t=e.default;var n;if(/android/i.test(navigator.userAgent))t=null!=(n=e.android)?n:t;else if(b()){var o;t=null!=(o=e.ios)?o:t}t>0&&await new Promise(e=>setTimeout(e,t))}class C extends i{static async startSession(e){const t=i.getFullOptions(e);t.onStatusChange({status:"connecting"}),t.onCanSendFeedbackChange({canSendFeedback:!1});let n=null;try{return await k(t.connectionDelay),n=await _(e),new C(t,n)}catch(e){var o;throw t.onStatusChange({status:"disconnected"}),null==(o=n)||o.close(),e}}}class M{static async create({sampleRate:e,format:t,preferHeadphonesForIosDevices:n}){let o=null,a=null;try{const i={sampleRate:{ideal:e},echoCancellation:!0,noiseSuppression:!0};if(b()&&n){const e=(await window.navigator.mediaDevices.enumerateDevices()).find(e=>"audioinput"===e.kind&&["airpod","headphone","earphone"].find(t=>e.label.toLowerCase().includes(t)));e&&(i.deviceId={ideal:e.deviceId})}const r=navigator.mediaDevices.getSupportedConstraints().sampleRate;o=new window.AudioContext(r?{sampleRate:e}:{});const c=o.createAnalyser();r||await o.audioWorklet.addModule("https://cdn.jsdelivr.net/npm/@alexanderolsen/libsamplerate-js@2.1.2/dist/libsamplerate.worklet.js"),await w(o.audioWorklet);const l=s({voiceIsolation:!0},i);a=await navigator.mediaDevices.getUserMedia({audio:l});const u=o.createMediaStreamSource(a),d=new AudioWorkletNode(o,"raw-audio-processor");return d.port.postMessage({type:"setFormat",format:t,sampleRate:e}),u.connect(c),c.connect(d),await o.resume(),new M(o,c,d,a)}catch(e){var i,r;throw null==(i=a)||i.getTracks().forEach(e=>e.stop()),null==(r=o)||r.close(),e}}constructor(e,t,n,o){this.context=void 0,this.analyser=void 0,this.worklet=void 0,this.inputStream=void 0,this.context=e,this.analyser=t,this.worklet=n,this.inputStream=o}async close(){this.inputStream.getTracks().forEach(e=>e.stop()),await this.context.close()}setMuted(e){this.worklet.port.postMessage({type:"setMuted",isMuted:e})}}const S=f("audio-concat-processor",'\nconst decodeTable = [0,132,396,924,1980,4092,8316,16764];\n\nexport function decodeSample(muLawSample) {\n let sign;\n let exponent;\n let mantissa;\n let sample;\n muLawSample = ~muLawSample;\n sign = (muLawSample & 0x80);\n exponent = (muLawSample >> 4) & 0x07;\n mantissa = muLawSample & 0x0F;\n sample = decodeTable[exponent] + (mantissa << (exponent+3));\n if (sign !== 0) sample = -sample;\n\n return sample;\n}\n\nclass AudioConcatProcessor extends AudioWorkletProcessor {\n constructor() {\n super();\n this.buffers = []; // Initialize an empty buffer\n this.cursor = 0;\n this.currentBuffer = null;\n this.wasInterrupted = false;\n this.finished = false;\n \n this.port.onmessage = ({ data }) => {\n switch (data.type) {\n case "setFormat":\n this.format = data.format;\n break;\n case "buffer":\n this.wasInterrupted = false;\n this.buffers.push(\n this.format === "ulaw"\n ? new Uint8Array(data.buffer)\n : new Int16Array(data.buffer)\n );\n break;\n case "interrupt":\n this.wasInterrupted = true;\n break;\n case "clearInterrupted":\n if (this.wasInterrupted) {\n this.wasInterrupted = false;\n this.buffers = [];\n this.currentBuffer = null;\n }\n }\n };\n }\n process(_, outputs) {\n let finished = false;\n const output = outputs[0][0];\n for (let i = 0; i < output.length; i++) {\n if (!this.currentBuffer) {\n if (this.buffers.length === 0) {\n finished = true;\n break;\n }\n this.currentBuffer = this.buffers.shift();\n this.cursor = 0;\n }\n\n let value = this.currentBuffer[this.cursor];\n if (this.format === "ulaw") {\n value = decodeSample(value);\n }\n output[i] = value / 32768;\n this.cursor++;\n\n if (this.cursor >= this.currentBuffer.length) {\n this.currentBuffer = null;\n }\n }\n\n if (this.finished !== finished) {\n this.finished = finished;\n this.port.postMessage({ type: "process", finished });\n }\n\n return true; // Continue processing\n }\n}\n\nregisterProcessor("audio-concat-processor", AudioConcatProcessor);\n');class F{static async create({sampleRate:e,format:t}){let n=null;try{n=new AudioContext({sampleRate:e});const o=n.createAnalyser(),s=n.createGain();s.connect(o),o.connect(n.destination),await S(n.audioWorklet);const a=new AudioWorkletNode(n,"audio-concat-processor");return a.port.postMessage({type:"setFormat",format:t}),a.connect(s),await n.resume(),new F(n,o,s,a)}catch(e){var o;throw null==(o=n)||o.close(),e}}constructor(e,t,n,o){this.context=void 0,this.analyser=void 0,this.gain=void 0,this.worklet=void 0,this.context=e,this.analyser=t,this.gain=n,this.worklet=o}async close(){await this.context.close()}}class I extends i{static async startSession(e){var t;const n=i.getFullOptions(e);n.onStatusChange({status:"connecting"}),n.onCanSendFeedbackChange({canSendFeedback:!1});let o=null,a=null,r=null,c=null,l=null;if(null==(t=e.useWakeLock)||t)try{l=await navigator.wakeLock.request("screen")}catch(e){}try{var u;return c=await navigator.mediaDevices.getUserMedia({audio:!0}),await k(n.connectionDelay),a=await _(e),[o,r]=await Promise.all([M.create(s({},a.inputFormat,{preferHeadphonesForIosDevices:e.preferHeadphonesForIosDevices})),F.create(a.outputFormat)]),null==(u=c)||u.getTracks().forEach(e=>e.stop()),c=null,new I(n,a,o,r,l)}catch(e){var d,h,p,m;n.onStatusChange({status:"disconnected"}),null==(d=c)||d.getTracks().forEach(e=>e.stop()),null==(h=a)||h.close(),await(null==(p=o)?void 0:p.close()),await(null==(m=r)?void 0:m.close());try{var v;await(null==(v=l)?void 0:v.release()),l=null}catch(e){}throw e}}constructor(e,t,n,o,s){super(e,t),this.input=void 0,this.output=void 0,this.wakeLock=void 0,this.inputFrequencyData=void 0,this.outputFrequencyData=void 0,this.onInputWorkletMessage=e=>{"connected"===this.status&&this.connection.sendMessage({user_audio_chunk:m(e.data[0].buffer)})},this.onOutputWorkletMessage=({data:e})=>{"process"===e.type&&this.updateMode(e.finished?"listening":"speaking")},this.addAudioBase64Chunk=e=>{this.output.gain.gain.value=this.volume,this.output.worklet.port.postMessage({type:"clearInterrupted"}),this.output.worklet.port.postMessage({type:"buffer",buffer:v(e)})},this.fadeOutAudio=()=>{this.updateMode("listening"),this.output.worklet.port.postMessage({type:"interrupt"}),this.output.gain.gain.exponentialRampToValueAtTime(1e-4,this.output.context.currentTime+2),setTimeout(()=>{this.output.gain.gain.value=this.volume,this.output.worklet.port.postMessage({type:"clearInterrupted"})},2e3)},this.calculateVolume=e=>{if(0===e.length)return 0;let t=0;for(let n=0;n<e.length;n++)t+=e[n]/255;return t/=e.length,t<0?0:t>1?1:t},this.input=n,this.output=o,this.wakeLock=s,this.input.worklet.port.onmessage=this.onInputWorkletMessage,this.output.worklet.port.onmessage=this.onOutputWorkletMessage}async handleEndSession(){await super.handleEndSession();try{var e;await(null==(e=this.wakeLock)?void 0:e.release()),this.wakeLock=null}catch(e){}await this.input.close(),await this.output.close()}handleInterruption(e){super.handleInterruption(e),this.fadeOutAudio()}handleAudio(e){var t,n;this.lastInterruptTimestamp<=e.audio_event.event_id&&(null==(t=(n=this.options).onAudio)||t.call(n,e.audio_event.audio_base_64),this.connection instanceof y||this.addAudioBase64Chunk(e.audio_event.audio_base_64),this.currentEventId=e.audio_event.event_id,this.updateCanSendFeedback(),this.updateMode("speaking"))}setMicMuted(e){this.connection instanceof y?this.connection.setMicMuted(e):this.input.setMuted(e)}getInputByteFrequencyData(){return null!=this.inputFrequencyData||(this.inputFrequencyData=new Uint8Array(this.input.analyser.frequencyBinCount)),this.input.analyser.getByteFrequencyData(this.inputFrequencyData),this.inputFrequencyData}getOutputByteFrequencyData(){return null!=this.outputFrequencyData||(this.outputFrequencyData=new Uint8Array(this.output.analyser.frequencyBinCount)),this.output.analyser.getByteFrequencyData(this.outputFrequencyData),this.outputFrequencyData}getInputVolume(){return this.calculateVolume(this.getInputByteFrequencyData())}getOutputVolume(){return this.calculateVolume(this.getOutputByteFrequencyData())}}function x(e,t,n="https://api.elevenlabs.io"){return fetch(`${n}/v1/convai/conversations/${e}/feedback`,{method:"POST",body:JSON.stringify({feedback:t?"like":"dislike"}),headers:{"Content-Type":"application/json"}})}class D extends i{static startSession(e){return e.textOnly?C.startSession(e):I.startSession(e)}}export{D as Conversation,y as WebRTCConnection,p as WebSocketConnection,_ as createConnection,x as postOverallFeedback};
2
+ //# sourceMappingURL=lib.modern.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lib.modern.js","sources":["../src/BaseConversation.ts","../src/utils/BaseConnection.ts","../src/version.ts","../src/utils/events.ts","../src/utils/overrides.ts","../src/utils/WebSocketConnection.ts","../src/utils/audio.ts","../src/utils/createWorkletModuleLoader.ts","../src/utils/rawAudioProcessor.ts","../src/utils/WebRTCConnection.ts","../src/utils/ConnectionFactory.ts","../src/utils/compatibility.ts","../src/utils/applyDelay.ts","../src/TextConversation.ts","../src/utils/input.ts","../src/utils/audioConcatProcessor.ts","../src/utils/output.ts","../src/VoiceConversation.ts","../src/utils/postOverallFeedback.ts","../src/index.ts"],"sourcesContent":["import type {\n BaseConnection,\n DisconnectionDetails,\n OnDisconnectCallback,\n SessionConfig,\n} from \"./utils/BaseConnection\";\nimport type {\n AgentAudioEvent,\n AgentResponseEvent,\n ClientToolCallEvent,\n IncomingSocketEvent,\n InternalTentativeAgentResponseEvent,\n InterruptionEvent,\n UserTranscriptionEvent,\n VadScoreEvent,\n} from \"./utils/events\";\nimport type { InputConfig } from \"./utils/input\";\n\nexport type Role = \"user\" | \"ai\";\n\nexport type Mode = \"speaking\" | \"listening\";\n\nexport type Status =\n | \"connecting\"\n | \"connected\"\n | \"disconnecting\"\n | \"disconnected\";\n\nexport type Options = SessionConfig &\n Callbacks &\n ClientToolsConfig &\n InputConfig;\n\nexport type PartialOptions = SessionConfig &\n Partial<Callbacks> &\n Partial<ClientToolsConfig> &\n Partial<InputConfig>;\n\nexport type ClientToolsConfig = {\n clientTools: Record<\n string,\n (\n parameters: any\n ) => Promise<string | number | void> | string | number | void\n >;\n};\n\nexport type Callbacks = {\n onConnect: (props: { conversationId: string }) => void;\n // internal debug events, not to be used\n onDebug: (props: any) => void;\n onDisconnect: OnDisconnectCallback;\n onError: (message: string, context?: any) => void;\n onMessage: (props: { message: string; source: Role }) => void;\n onAudio?: (base64Audio: string) => void;\n onModeChange: (prop: { mode: Mode }) => void;\n onStatusChange: (prop: { status: Status }) => void;\n onCanSendFeedbackChange: (prop: { canSendFeedback: boolean }) => void;\n onUnhandledClientToolCall?: (\n params: ClientToolCallEvent[\"client_tool_call\"]\n ) => void;\n onVadScore?: (props: { vadScore: number }) => void;\n};\n\nconst EMPTY_FREQUENCY_DATA = new Uint8Array(0);\n\nexport class BaseConversation {\n protected lastInterruptTimestamp = 0;\n protected mode: Mode = \"listening\";\n protected status: Status = \"connecting\";\n protected volume = 1;\n protected currentEventId = 1;\n protected lastFeedbackEventId = 0;\n protected canSendFeedback = false;\n\n protected static getFullOptions(partialOptions: PartialOptions): Options {\n return {\n clientTools: {},\n onConnect: () => {},\n onDebug: () => {},\n onDisconnect: () => {},\n onError: () => {},\n onMessage: () => {},\n onAudio: () => {},\n onModeChange: () => {},\n onStatusChange: () => {},\n onCanSendFeedbackChange: () => {},\n ...partialOptions,\n };\n }\n\n protected constructor(\n protected readonly options: Options,\n protected readonly connection: BaseConnection\n ) {\n this.options.onConnect({ conversationId: connection.conversationId });\n this.connection.onMessage(this.onMessage);\n this.connection.onDisconnect(this.endSessionWithDetails);\n this.connection.onModeChange(mode => this.updateMode(mode));\n this.updateStatus(\"connected\");\n }\n\n public endSession() {\n return this.endSessionWithDetails({ reason: \"user\" });\n }\n\n private endSessionWithDetails = async (details: DisconnectionDetails) => {\n if (this.status !== \"connected\" && this.status !== \"connecting\") return;\n this.updateStatus(\"disconnecting\");\n await this.handleEndSession();\n this.updateStatus(\"disconnected\");\n this.options.onDisconnect(details);\n };\n\n protected async handleEndSession() {\n this.connection.close();\n }\n\n protected updateMode(mode: Mode) {\n if (mode !== this.mode) {\n this.mode = mode;\n this.options.onModeChange({ mode });\n }\n }\n\n protected updateStatus(status: Status) {\n if (status !== this.status) {\n this.status = status;\n this.options.onStatusChange({ status });\n }\n }\n\n protected updateCanSendFeedback() {\n const canSendFeedback = this.currentEventId !== this.lastFeedbackEventId;\n if (this.canSendFeedback !== canSendFeedback) {\n this.canSendFeedback = canSendFeedback;\n this.options.onCanSendFeedbackChange({ canSendFeedback });\n }\n }\n\n protected handleInterruption(event: InterruptionEvent) {\n if (event.interruption_event) {\n this.lastInterruptTimestamp = event.interruption_event.event_id;\n }\n }\n\n protected handleAgentResponse(event: AgentResponseEvent) {\n this.options.onMessage({\n source: \"ai\",\n message: event.agent_response_event.agent_response,\n });\n }\n\n protected handleUserTranscript(event: UserTranscriptionEvent) {\n this.options.onMessage({\n source: \"user\",\n message: event.user_transcription_event.user_transcript,\n });\n }\n\n protected handleTentativeAgentResponse(\n event: InternalTentativeAgentResponseEvent\n ) {\n this.options.onDebug({\n type: \"tentative_agent_response\",\n response:\n event.tentative_agent_response_internal_event.tentative_agent_response,\n });\n }\n\n protected handleVadScore(event: VadScoreEvent) {\n if (this.options.onVadScore) {\n this.options.onVadScore({\n vadScore: event.vad_score_event.vad_score,\n });\n }\n }\n\n protected async handleClientToolCall(event: ClientToolCallEvent) {\n if (\n Object.prototype.hasOwnProperty.call(\n this.options.clientTools,\n event.client_tool_call.tool_name\n )\n ) {\n try {\n const result =\n (await this.options.clientTools[event.client_tool_call.tool_name](\n event.client_tool_call.parameters\n )) ?? \"Client tool execution successful.\"; // default client-tool call response\n\n // The API expects result to be a string, so we need to convert it if it's not already a string\n const formattedResult =\n typeof result === \"object\" ? JSON.stringify(result) : String(result);\n\n this.connection.sendMessage({\n type: \"client_tool_result\",\n tool_call_id: event.client_tool_call.tool_call_id,\n result: formattedResult,\n is_error: false,\n });\n } catch (e) {\n this.onError(\n `Client tool execution failed with following error: ${(e as Error)?.message}`,\n {\n clientToolName: event.client_tool_call.tool_name,\n }\n );\n this.connection.sendMessage({\n type: \"client_tool_result\",\n tool_call_id: event.client_tool_call.tool_call_id,\n result: `Client tool execution failed: ${(e as Error)?.message}`,\n is_error: true,\n });\n }\n } else {\n if (this.options.onUnhandledClientToolCall) {\n this.options.onUnhandledClientToolCall(event.client_tool_call);\n\n return;\n }\n\n this.onError(\n `Client tool with name ${event.client_tool_call.tool_name} is not defined on client`,\n {\n clientToolName: event.client_tool_call.tool_name,\n }\n );\n this.connection.sendMessage({\n type: \"client_tool_result\",\n tool_call_id: event.client_tool_call.tool_call_id,\n result: `Client tool with name ${event.client_tool_call.tool_name} is not defined on client`,\n is_error: true,\n });\n }\n }\n\n protected handleAudio(event: AgentAudioEvent) {}\n\n private onMessage = async (parsedEvent: IncomingSocketEvent) => {\n switch (parsedEvent.type) {\n case \"interruption\": {\n this.handleInterruption(parsedEvent);\n return;\n }\n case \"agent_response\": {\n this.handleAgentResponse(parsedEvent);\n return;\n }\n case \"user_transcript\": {\n this.handleUserTranscript(parsedEvent);\n return;\n }\n case \"internal_tentative_agent_response\": {\n this.handleTentativeAgentResponse(parsedEvent);\n return;\n }\n case \"client_tool_call\": {\n await this.handleClientToolCall(parsedEvent);\n return;\n }\n case \"audio\": {\n this.handleAudio(parsedEvent);\n return;\n }\n\n case \"vad_score\": {\n this.handleVadScore(parsedEvent);\n return;\n }\n\n case \"ping\": {\n this.connection.sendMessage({\n type: \"pong\",\n event_id: parsedEvent.ping_event.event_id,\n });\n // parsedEvent.ping_event.ping_ms can be used on client side, for example\n // to warn if ping is too high that experience might be degraded.\n return;\n }\n\n // unhandled events are expected to be internal events\n default: {\n this.options.onDebug(parsedEvent);\n return;\n }\n }\n };\n\n private onError(message: string, context?: any) {\n console.error(message, context);\n this.options.onError(message, context);\n }\n\n public getId() {\n return this.connection.conversationId;\n }\n\n public isOpen() {\n return this.status === \"connected\";\n }\n\n public setVolume = ({ volume }: { volume: number }) => {\n this.volume = volume;\n };\n\n public setMicMuted(isMuted: boolean) {\n this.connection.setMicMuted(isMuted);\n }\n\n public getInputByteFrequencyData() {\n return EMPTY_FREQUENCY_DATA;\n }\n\n public getOutputByteFrequencyData() {\n return EMPTY_FREQUENCY_DATA;\n }\n\n public getInputVolume() {\n return 0;\n }\n\n public getOutputVolume() {\n return 0;\n }\n\n public sendFeedback(like: boolean) {\n if (!this.canSendFeedback) {\n console.warn(\n this.lastFeedbackEventId === 0\n ? \"Cannot send feedback: the conversation has not started yet.\"\n : \"Cannot send feedback: feedback has already been sent for the current response.\"\n );\n return;\n }\n\n this.connection.sendMessage({\n type: \"feedback\",\n score: like ? \"like\" : \"dislike\",\n event_id: this.currentEventId,\n });\n this.lastFeedbackEventId = this.currentEventId;\n this.updateCanSendFeedback();\n }\n\n public sendContextualUpdate(text: string) {\n this.connection.sendMessage({\n type: \"contextual_update\",\n text,\n });\n }\n\n public sendUserMessage(text: string) {\n this.connection.sendMessage({\n type: \"user_message\",\n text,\n });\n }\n\n public sendUserActivity() {\n this.connection.sendMessage({\n type: \"user_activity\",\n });\n }\n\n public sendMCPToolApprovalResult(toolCallId: string, isApproved: boolean) {\n this.connection.sendMessage({\n type: \"mcp_tool_approval_result\",\n tool_call_id: toolCallId,\n is_approved: isApproved,\n });\n }\n}\n","import type { IncomingSocketEvent, OutgoingSocketEvent } from \"./events\";\nimport type { Mode } from \"../BaseConversation\";\n\nexport type Language =\n | \"en\"\n | \"ja\"\n | \"zh\"\n | \"de\"\n | \"hi\"\n | \"fr\"\n | \"ko\"\n | \"pt\"\n | \"pt-br\"\n | \"it\"\n | \"es\"\n | \"id\"\n | \"nl\"\n | \"tr\"\n | \"pl\"\n | \"sv\"\n | \"bg\"\n | \"ro\"\n | \"ar\"\n | \"cs\"\n | \"el\"\n | \"fi\"\n | \"ms\"\n | \"da\"\n | \"ta\"\n | \"uk\"\n | \"ru\"\n | \"hu\"\n | \"hr\"\n | \"sk\"\n | \"no\"\n | \"vi\"\n | \"tl\";\n\nexport type DelayConfig = {\n default: number;\n android?: number;\n ios?: number;\n};\n\nexport type FormatConfig = {\n format: \"pcm\" | \"ulaw\";\n sampleRate: number;\n};\n\nexport type DisconnectionDetails =\n | {\n reason: \"error\";\n message: string;\n context: Event;\n }\n | {\n reason: \"agent\";\n context: CloseEvent;\n }\n | {\n reason: \"user\";\n };\n\nexport type OnDisconnectCallback = (details: DisconnectionDetails) => void;\nexport type OnMessageCallback = (event: IncomingSocketEvent) => void;\n\nexport type BaseSessionConfig = {\n origin?: string;\n authorization?: string;\n livekitUrl?: string;\n overrides?: {\n agent?: {\n prompt?: {\n prompt?: string;\n };\n firstMessage?: string;\n language?: Language;\n };\n tts?: {\n voiceId?: string;\n };\n conversation?: {\n textOnly?: boolean;\n };\n client?: {\n source?: string;\n version?: string;\n };\n };\n customLlmExtraBody?: unknown;\n dynamicVariables?: Record<string, string | number | boolean>;\n useWakeLock?: boolean;\n connectionDelay?: DelayConfig;\n textOnly?: boolean;\n userId?: string;\n};\n\nexport type ConnectionType = \"websocket\" | \"webrtc\";\n\nexport type PublicSessionConfig = BaseSessionConfig & {\n agentId: string;\n connectionType: ConnectionType;\n signedUrl?: never;\n conversationToken?: never;\n};\n\nexport type PrivateWebSocketSessionConfig = BaseSessionConfig & {\n signedUrl: string;\n connectionType?: \"websocket\";\n agentId?: never;\n conversationToken?: never;\n};\n\nexport type PrivateWebRTCSessionConfig = BaseSessionConfig & {\n conversationToken: string;\n connectionType?: \"webrtc\";\n agentId?: never;\n signedUrl?: never;\n};\n\n// Union type for all possible session configurations\nexport type SessionConfig =\n | PublicSessionConfig\n | PrivateWebSocketSessionConfig\n | PrivateWebRTCSessionConfig;\n\nexport abstract class BaseConnection {\n public abstract readonly conversationId: string;\n public abstract readonly inputFormat: FormatConfig;\n public abstract readonly outputFormat: FormatConfig;\n\n protected queue: IncomingSocketEvent[] = [];\n protected disconnectionDetails: DisconnectionDetails | null = null;\n protected onDisconnectCallback: OnDisconnectCallback | null = null;\n protected onMessageCallback: OnMessageCallback | null = null;\n protected onModeChangeCallback: ((mode: Mode) => void) | null = null;\n protected onDebug?: (info: unknown) => void;\n\n constructor(config: { onDebug?: (info: unknown) => void } = {}) {\n this.onDebug = config.onDebug;\n }\n\n protected debug(info: unknown) {\n if (this.onDebug) this.onDebug(info);\n }\n\n public abstract close(): void;\n public abstract sendMessage(message: OutgoingSocketEvent): void;\n public abstract setMicMuted(isMuted: boolean): Promise<void>;\n\n public onMessage(callback: OnMessageCallback) {\n this.onMessageCallback = callback;\n const queue = this.queue;\n this.queue = [];\n\n if (queue.length > 0) {\n // Make sure the queue is flushed after the constructors finishes and\n // classes are initialized.\n queueMicrotask(() => {\n queue.forEach(callback);\n });\n }\n }\n\n public onDisconnect(callback: OnDisconnectCallback) {\n this.onDisconnectCallback = callback;\n const details = this.disconnectionDetails;\n if (details) {\n // Make sure the event is triggered after the constructors finishes and\n // classes are initialized.\n queueMicrotask(() => {\n callback(details);\n });\n }\n }\n\n public onModeChange(callback: (mode: Mode) => void) {\n this.onModeChangeCallback = callback;\n }\n\n protected updateMode(mode: Mode) {\n this.onModeChangeCallback?.(mode);\n }\n\n protected disconnect(details: DisconnectionDetails) {\n if (!this.disconnectionDetails) {\n this.disconnectionDetails = details;\n this.onDisconnectCallback?.(details);\n }\n }\n\n protected handleMessage(parsedEvent: IncomingSocketEvent) {\n if (this.onMessageCallback) {\n this.onMessageCallback(parsedEvent);\n } else {\n this.queue.push(parsedEvent);\n }\n }\n}\n\nexport function parseFormat(format: string): FormatConfig {\n const [formatPart, sampleRatePart] = format.split(\"_\");\n if (![\"pcm\", \"ulaw\"].includes(formatPart)) {\n throw new Error(`Invalid format: ${format}`);\n }\n\n const sampleRate = Number.parseInt(sampleRatePart);\n if (Number.isNaN(sampleRate)) {\n throw new Error(`Invalid sample rate: ${sampleRatePart}`);\n }\n\n return {\n format: formatPart as FormatConfig[\"format\"],\n sampleRate,\n };\n}\n","// This file is auto-generated during build\nexport const PACKAGE_VERSION = \"0.5.0\";\n","import type { Language } from \"./connection\";\nimport type { CONVERSATION_INITIATION_CLIENT_DATA_TYPE } from \"./overrides\";\n\nexport type UserTranscriptionEvent = {\n type: \"user_transcript\";\n user_transcription_event: { user_transcript: string };\n};\nexport type AgentResponseEvent = {\n type: \"agent_response\";\n agent_response_event: { agent_response: string };\n};\nexport type AgentAudioEvent = {\n type: \"audio\";\n audio_event: {\n audio_base_64: string;\n event_id: number;\n };\n};\nexport type InterruptionEvent = {\n type: \"interruption\";\n interruption_event: {\n event_id: number;\n };\n};\nexport type InternalTentativeAgentResponseEvent = {\n type: \"internal_tentative_agent_response\";\n tentative_agent_response_internal_event: {\n tentative_agent_response: string;\n };\n};\nexport type ConfigEvent = {\n type: \"conversation_initiation_metadata\";\n conversation_initiation_metadata_event: {\n conversation_id: string;\n agent_output_audio_format: string;\n user_input_audio_format?: string;\n };\n};\nexport type PingEvent = {\n type: \"ping\";\n ping_event: {\n event_id: number;\n ping_ms?: number;\n };\n};\nexport type ClientToolCallEvent = {\n type: \"client_tool_call\";\n client_tool_call: {\n tool_name: string;\n tool_call_id: string;\n parameters: any;\n expects_response: boolean;\n };\n};\nexport type VadScoreEvent = {\n type: \"vad_score\";\n vad_score_event: {\n vad_score: number;\n };\n};\n\n// TODO correction missing\nexport type IncomingSocketEvent =\n | UserTranscriptionEvent\n | AgentResponseEvent\n | AgentAudioEvent\n | InterruptionEvent\n | InternalTentativeAgentResponseEvent\n | ConfigEvent\n | PingEvent\n | ClientToolCallEvent\n | VadScoreEvent;\n\nexport type PongEvent = {\n type: \"pong\";\n event_id: number;\n};\nexport type UserAudioEvent = {\n user_audio_chunk: string;\n};\nexport type UserFeedbackEvent = {\n type: \"feedback\";\n score: \"like\" | \"dislike\";\n event_id: number;\n};\nexport type ClientToolResultEvent = {\n type: \"client_tool_result\";\n tool_call_id: string;\n result: any;\n is_error: boolean;\n};\nexport type InitiationClientDataEvent = {\n type: typeof CONVERSATION_INITIATION_CLIENT_DATA_TYPE;\n conversation_config_override?: {\n agent?: {\n prompt?: {\n prompt?: string;\n };\n first_message?: string;\n language?: Language;\n };\n tts?: {\n voice_id?: string;\n };\n conversation?: {\n text_only?: boolean;\n };\n };\n custom_llm_extra_body?: any;\n dynamic_variables?: Record<string, string | number | boolean>;\n user_id?: string;\n source_info?: {\n source?: string;\n version?: string;\n };\n};\nexport type ContextualUpdateEvent = {\n type: \"contextual_update\";\n text: string;\n};\nexport type UserMessageEvent = {\n type: \"user_message\";\n text: string;\n};\nexport type UserActivityEvent = {\n type: \"user_activity\";\n};\nexport type MCPToolApprovalResultEvent = {\n type: \"mcp_tool_approval_result\";\n tool_call_id: string;\n is_approved: boolean;\n};\nexport type OutgoingSocketEvent =\n | PongEvent\n | UserAudioEvent\n | InitiationClientDataEvent\n | UserFeedbackEvent\n | ClientToolResultEvent\n | ContextualUpdateEvent\n | UserMessageEvent\n | UserActivityEvent\n | MCPToolApprovalResultEvent;\n\nexport function isValidSocketEvent(event: any): event is IncomingSocketEvent {\n return !!event.type;\n}\n","import type { SessionConfig } from \"./BaseConnection\";\nimport type { InitiationClientDataEvent } from \"./events\";\n\nexport const CONVERSATION_INITIATION_CLIENT_DATA_TYPE =\n \"conversation_initiation_client_data\";\n\nexport function constructOverrides(\n config: SessionConfig\n): InitiationClientDataEvent {\n const overridesEvent: InitiationClientDataEvent = {\n type: CONVERSATION_INITIATION_CLIENT_DATA_TYPE,\n };\n\n if (config.overrides) {\n overridesEvent.conversation_config_override = {\n agent: {\n prompt: config.overrides.agent?.prompt,\n first_message: config.overrides.agent?.firstMessage,\n language: config.overrides.agent?.language,\n },\n tts: {\n voice_id: config.overrides.tts?.voiceId,\n },\n conversation: {\n text_only: config.overrides.conversation?.textOnly,\n },\n };\n }\n\n if (config.customLlmExtraBody) {\n overridesEvent.custom_llm_extra_body = config.customLlmExtraBody;\n }\n\n if (config.dynamicVariables) {\n overridesEvent.dynamic_variables = config.dynamicVariables;\n }\n\n if (config.userId) {\n overridesEvent.user_id = config.userId;\n }\n\n if (config.overrides?.client) {\n overridesEvent.source_info = {\n source: config.overrides.client.source,\n version: config.overrides.client.version,\n };\n }\n\n return overridesEvent;\n}\n","import {\n BaseConnection,\n type SessionConfig,\n type FormatConfig,\n parseFormat,\n} from \"./BaseConnection\";\nimport { PACKAGE_VERSION } from \"../version\";\nimport {\n type ConfigEvent,\n isValidSocketEvent,\n type OutgoingSocketEvent,\n} from \"./events\";\nimport { constructOverrides } from \"./overrides\";\n\nconst MAIN_PROTOCOL = \"convai\";\nconst WSS_API_ORIGIN = \"wss://api.elevenlabs.io\";\nconst WSS_API_PATHNAME = \"/v1/convai/conversation?agent_id=\";\n\nexport class WebSocketConnection extends BaseConnection {\n public readonly conversationId: string;\n public readonly inputFormat: FormatConfig;\n public readonly outputFormat: FormatConfig;\n\n private constructor(\n private readonly socket: WebSocket,\n conversationId: string,\n inputFormat: FormatConfig,\n outputFormat: FormatConfig\n ) {\n super();\n this.conversationId = conversationId;\n this.inputFormat = inputFormat;\n this.outputFormat = outputFormat;\n\n this.socket.addEventListener(\"error\", event => {\n // In case the error event is followed by a close event, we want the\n // latter to be the one that disconnects the session as it contains more\n // useful information.\n setTimeout(\n () =>\n this.disconnect({\n reason: \"error\",\n message: \"The connection was closed due to a socket error.\",\n context: event,\n }),\n 0\n );\n });\n\n this.socket.addEventListener(\"close\", event => {\n this.disconnect(\n event.code === 1000\n ? {\n reason: \"agent\",\n context: event,\n }\n : {\n reason: \"error\",\n message:\n event.reason || \"The connection was closed by the server.\",\n context: event,\n }\n );\n });\n\n this.socket.addEventListener(\"message\", event => {\n try {\n const parsedEvent = JSON.parse(event.data);\n if (!isValidSocketEvent(parsedEvent)) {\n return;\n }\n this.handleMessage(parsedEvent);\n } catch (_) {}\n });\n }\n\n public static async create(\n config: SessionConfig\n ): Promise<WebSocketConnection> {\n let socket: WebSocket | null = null;\n\n try {\n const origin = config.origin ?? WSS_API_ORIGIN;\n let url: string;\n\n const version = config.overrides?.client?.version || PACKAGE_VERSION;\n const source = config.overrides?.client?.source || \"js_sdk\";\n\n if (config.signedUrl) {\n const separator = config.signedUrl.includes(\"?\") ? \"&\" : \"?\";\n url = `${config.signedUrl}${separator}source=${source}&version=${version}`;\n } else {\n url = `${origin}${WSS_API_PATHNAME}${config.agentId}&source=${source}&version=${version}`;\n }\n\n const protocols = [MAIN_PROTOCOL];\n if (config.authorization) {\n protocols.push(`bearer.${config.authorization}`);\n }\n socket = new WebSocket(url, protocols);\n\n const conversationConfig = await new Promise<\n ConfigEvent[\"conversation_initiation_metadata_event\"]\n >((resolve, reject) => {\n socket!.addEventListener(\n \"open\",\n () => {\n const overridesEvent = constructOverrides(config);\n\n socket?.send(JSON.stringify(overridesEvent));\n },\n { once: true }\n );\n\n socket!.addEventListener(\"error\", event => {\n // In case the error event is followed by a close event, we want the\n // latter to be the one that rejects the promise as it contains more\n // useful information.\n setTimeout(() => reject(event), 0);\n });\n\n socket!.addEventListener(\"close\", reject);\n\n socket!.addEventListener(\n \"message\",\n (event: MessageEvent) => {\n const message = JSON.parse(event.data);\n\n if (!isValidSocketEvent(message)) {\n return;\n }\n\n if (message.type === \"conversation_initiation_metadata\") {\n resolve(message.conversation_initiation_metadata_event);\n } else {\n console.warn(\n \"First received message is not conversation metadata.\"\n );\n }\n },\n { once: true }\n );\n });\n\n const {\n conversation_id,\n agent_output_audio_format,\n user_input_audio_format,\n } = conversationConfig;\n\n const inputFormat = parseFormat(user_input_audio_format ?? \"pcm_16000\");\n const outputFormat = parseFormat(agent_output_audio_format);\n\n return new WebSocketConnection(\n socket,\n conversation_id,\n inputFormat,\n outputFormat\n );\n } catch (error) {\n socket?.close();\n throw error;\n }\n }\n\n public close() {\n this.socket.close();\n }\n\n public sendMessage(message: OutgoingSocketEvent) {\n this.socket.send(JSON.stringify(message));\n }\n\n public async setMicMuted(isMuted: boolean): Promise<void> {\n console.warn(\n `WebSocket connection setMicMuted called with ${isMuted}, but this is handled by VoiceConversation`\n );\n }\n}\n","export function arrayBufferToBase64(b: ArrayBufferLike) {\n const buffer = new Uint8Array(b);\n // @ts-ignore\n const base64Data = window.btoa(String.fromCharCode(...buffer));\n return base64Data;\n}\n\nexport function base64ToArrayBuffer(base64: string): ArrayBuffer {\n const binaryString = window.atob(base64);\n const len = binaryString.length;\n const bytes = new Uint8Array(len);\n for (let i = 0; i < len; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n return bytes.buffer;\n}\n","const URLCache = new Map<string, string>();\n\nexport function createWorkletModuleLoader(name: string, sourceCode: string) {\n return async (worklet: AudioWorklet) => {\n const url = URLCache.get(name);\n if (url) {\n return worklet.addModule(url);\n }\n\n const blob = new Blob([sourceCode], { type: \"application/javascript\" });\n const blobURL = URL.createObjectURL(blob);\n try {\n await worklet.addModule(blobURL);\n URLCache.set(name, blobURL);\n return;\n } catch {\n URL.revokeObjectURL(blobURL);\n }\n\n try {\n // Attempting to start a conversation in Safari inside an iframe will\n // throw a CORS error because the blob:// protocol is considered\n // cross-origin. In such cases, fall back to using a base64 data URL:\n const base64 = btoa(sourceCode);\n const moduleURL = `data:application/javascript;base64,${base64}`;\n await worklet.addModule(moduleURL);\n URLCache.set(name, moduleURL);\n } catch (error) {\n throw new Error(\n `Failed to load the ${name} worklet module. Make sure the browser supports AudioWorklets.`\n );\n }\n };\n}\n","/*\n * ulaw encoding logic taken from the wavefile library\n * https://github.com/rochars/wavefile/blob/master/lib/codecs/mulaw.js\n */\n\nimport { createWorkletModuleLoader } from \"./createWorkletModuleLoader\";\n\nexport const loadRawAudioProcessor = createWorkletModuleLoader(\n \"raw-audio-processor\",\n // language=JavaScript\n `\nconst BIAS = 0x84;\nconst CLIP = 32635;\nconst encodeTable = [\n 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,\n 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,\n 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,\n 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,\n 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,\n 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,\n 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,\n 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7\n];\n\nfunction encodeSample(sample) {\n let sign;\n let exponent;\n let mantissa;\n let muLawSample;\n sign = (sample >> 8) & 0x80;\n if (sign !== 0) sample = -sample;\n sample = sample + BIAS;\n if (sample > CLIP) sample = CLIP;\n exponent = encodeTable[(sample>>7) & 0xFF];\n mantissa = (sample >> (exponent+3)) & 0x0F;\n muLawSample = ~(sign | (exponent << 4) | mantissa);\n \n return muLawSample;\n}\n\nclass RawAudioProcessor extends AudioWorkletProcessor {\n constructor() {\n super();\n \n this.port.onmessage = ({ data }) => {\n switch (data.type) {\n case \"setFormat\":\n this.isMuted = false;\n this.buffer = []; // Initialize an empty buffer\n this.bufferSize = data.sampleRate / 4;\n this.format = data.format;\n\n if (globalThis.LibSampleRate && sampleRate !== data.sampleRate) {\n globalThis.LibSampleRate.create(1, sampleRate, data.sampleRate).then(resampler => {\n this.resampler = resampler;\n });\n }\n break;\n case \"setMuted\":\n this.isMuted = data.isMuted;\n break;\n }\n };\n }\n process(inputs) {\n if (!this.buffer) {\n return true;\n }\n \n const input = inputs[0]; // Get the first input node\n if (input.length > 0) {\n let channelData = input[0]; // Get the first channel's data\n\n // Resample the audio if necessary\n if (this.resampler) {\n channelData = this.resampler.full(channelData);\n }\n\n // Add channel data to the buffer\n this.buffer.push(...channelData);\n // Get max volume \n let sum = 0.0;\n for (let i = 0; i < channelData.length; i++) {\n sum += channelData[i] * channelData[i];\n }\n const maxVolume = Math.sqrt(sum / channelData.length);\n // Check if buffer size has reached or exceeded the threshold\n if (this.buffer.length >= this.bufferSize) {\n const float32Array = this.isMuted \n ? new Float32Array(this.buffer.length)\n : new Float32Array(this.buffer);\n\n let encodedArray = this.format === \"ulaw\"\n ? new Uint8Array(float32Array.length)\n : new Int16Array(float32Array.length);\n\n // Iterate through the Float32Array and convert each sample to PCM16\n for (let i = 0; i < float32Array.length; i++) {\n // Clamp the value to the range [-1, 1]\n let sample = Math.max(-1, Math.min(1, float32Array[i]));\n\n // Scale the sample to the range [-32768, 32767]\n let value = sample < 0 ? sample * 32768 : sample * 32767;\n if (this.format === \"ulaw\") {\n value = encodeSample(Math.round(value));\n }\n\n encodedArray[i] = value;\n }\n\n // Send the buffered data to the main script\n this.port.postMessage([encodedArray, maxVolume]);\n\n // Clear the buffer after sending\n this.buffer = [];\n }\n }\n return true; // Continue processing\n }\n}\nregisterProcessor(\"raw-audio-processor\", RawAudioProcessor);\n`\n);\n","import {\n BaseConnection,\n type SessionConfig,\n type FormatConfig,\n parseFormat,\n} from \"./BaseConnection\";\nimport { PACKAGE_VERSION } from \"../version\";\nimport { isValidSocketEvent, type OutgoingSocketEvent } from \"./events\";\nimport { Room, RoomEvent, Track, ConnectionState } from \"livekit-client\";\nimport type {\n RemoteAudioTrack,\n Participant,\n TrackPublication,\n} from \"livekit-client\";\nimport {\n constructOverrides,\n CONVERSATION_INITIATION_CLIENT_DATA_TYPE,\n} from \"./overrides\";\nimport { arrayBufferToBase64 } from \"./audio\";\nimport { loadRawAudioProcessor } from \"./rawAudioProcessor\";\n\nconst DEFAULT_LIVEKIT_WS_URL = \"wss://livekit.rtc.elevenlabs.io\";\nconst HTTPS_API_ORIGIN = \"https://api.elevenlabs.io\";\n\n// Convert WSS origin to HTTPS for API calls\nfunction convertWssToHttps(origin: string): string {\n return origin.replace(/^wss:\\/\\//, \"https://\");\n}\n\nexport type ConnectionConfig = SessionConfig & {\n onDebug?: (info: unknown) => void;\n};\n\nexport class WebRTCConnection extends BaseConnection {\n public conversationId: string;\n public readonly inputFormat: FormatConfig;\n public readonly outputFormat: FormatConfig;\n\n private room: Room;\n private isConnected = false;\n private audioEventId = 1;\n private audioCaptureContext: AudioContext | null = null;\n\n private constructor(\n room: Room,\n conversationId: string,\n inputFormat: FormatConfig,\n outputFormat: FormatConfig,\n config: { onDebug?: (info: unknown) => void } = {}\n ) {\n super(config);\n this.room = room;\n this.conversationId = conversationId;\n this.inputFormat = inputFormat;\n this.outputFormat = outputFormat;\n\n this.setupRoomEventListeners();\n }\n\n public static async create(\n config: ConnectionConfig\n ): Promise<WebRTCConnection> {\n let conversationToken: string;\n\n // Handle different authentication scenarios\n if (\"conversationToken\" in config && config.conversationToken) {\n // Direct token provided\n conversationToken = config.conversationToken;\n } else if (\"agentId\" in config && config.agentId) {\n // Agent ID provided - fetch token from API\n try {\n const version = config.overrides?.client?.version || PACKAGE_VERSION;\n const source = config.overrides?.client?.source || \"js_sdk\";\n const configOrigin = config.origin ?? HTTPS_API_ORIGIN;\n const origin = convertWssToHttps(configOrigin); //origin is wss, not https\n const url = `${origin}/v1/convai/conversation/token?agent_id=${config.agentId}&source=${source}&version=${version}`;\n const response = await fetch(url);\n\n if (!response.ok) {\n throw new Error(\n `ElevenLabs API returned ${response.status} ${response.statusText}`\n );\n }\n\n const data = await response.json();\n conversationToken = data.token;\n\n if (!conversationToken) {\n throw new Error(\"No conversation token received from API\");\n }\n } catch (error) {\n let msg = error instanceof Error ? error.message : String(error);\n if (error instanceof Error && error.message.includes(\"401\")) {\n msg =\n \"Your agent has authentication enabled, but no signed URL or conversation token was provided.\";\n }\n\n throw new Error(\n `Failed to fetch conversation token for agent ${config.agentId}: ${msg}`\n );\n }\n } else {\n throw new Error(\n \"Either conversationToken or agentId is required for WebRTC connection\"\n );\n }\n\n const room = new Room();\n\n try {\n // Create connection instance first to set up event listeners\n const conversationId = `room_${Date.now()}`;\n const inputFormat = parseFormat(\"pcm_48000\");\n const outputFormat = parseFormat(\"pcm_48000\");\n const connection = new WebRTCConnection(\n room,\n conversationId,\n inputFormat,\n outputFormat,\n config\n );\n\n // Use configurable LiveKit URL or default if not provided\n const livekitUrl = config.livekitUrl || DEFAULT_LIVEKIT_WS_URL;\n\n // Connect to the LiveKit room and wait for the Connected event\n await room.connect(livekitUrl, conversationToken);\n\n // Wait for the Connected event to ensure isConnected is true\n await new Promise<void>(resolve => {\n if (connection.isConnected) {\n resolve();\n } else {\n const onConnected = () => {\n room.off(RoomEvent.Connected, onConnected);\n resolve();\n };\n room.on(RoomEvent.Connected, onConnected);\n }\n });\n\n if (room.name) {\n connection.conversationId =\n room.name.match(/(conv_[a-zA-Z0-9]+)/)?.[0] || room.name;\n }\n\n // Enable microphone and send overrides\n await room.localParticipant.setMicrophoneEnabled(true);\n\n const overridesEvent = constructOverrides(config);\n\n connection.debug({\n type: CONVERSATION_INITIATION_CLIENT_DATA_TYPE,\n message: overridesEvent,\n });\n\n await connection.sendMessage(overridesEvent);\n\n return connection;\n } catch (error) {\n await room.disconnect();\n throw error;\n }\n }\n\n private setupRoomEventListeners() {\n this.room.on(RoomEvent.Connected, async () => {\n this.isConnected = true;\n console.info(\"WebRTC room connected\");\n });\n\n this.room.on(RoomEvent.Disconnected, reason => {\n this.isConnected = false;\n this.disconnect({\n reason: \"agent\",\n context: new CloseEvent(\"close\", { reason: reason?.toString() }),\n });\n });\n\n this.room.on(RoomEvent.ConnectionStateChanged, state => {\n if (state === ConnectionState.Disconnected) {\n this.isConnected = false;\n this.disconnect({\n reason: \"error\",\n message: `LiveKit connection state changed to ${state}`,\n context: new Event(\"connection_state_changed\"),\n });\n }\n });\n\n // Handle incoming data messages\n this.room.on(\n RoomEvent.DataReceived,\n (payload: Uint8Array, _participant) => {\n try {\n const message = JSON.parse(new TextDecoder().decode(payload));\n\n // Filter out audio messages for WebRTC - they're handled via audio tracks\n if (message.type === \"audio\") {\n return;\n }\n\n if (isValidSocketEvent(message)) {\n this.handleMessage(message);\n } else {\n console.warn(\"Invalid socket event received:\", message);\n }\n } catch (error) {\n console.warn(\"Failed to parse incoming data message:\", error);\n console.warn(\"Raw payload:\", new TextDecoder().decode(payload));\n }\n }\n );\n\n this.room.on(\n RoomEvent.TrackSubscribed,\n async (\n track: Track,\n _publication: TrackPublication,\n participant: Participant\n ) => {\n if (\n track.kind === Track.Kind.Audio &&\n participant.identity.includes(\"agent\")\n ) {\n // Play the audio track\n const remoteAudioTrack = track as RemoteAudioTrack;\n const audioElement = remoteAudioTrack.attach();\n audioElement.autoplay = true;\n audioElement.controls = false;\n\n // Add to DOM (hidden) to ensure it plays\n audioElement.style.display = \"none\";\n document.body.appendChild(audioElement);\n\n // Set up audio capture for onAudio callback\n await this.setupAudioCapture(remoteAudioTrack);\n }\n }\n );\n\n this.room.on(\n RoomEvent.ActiveSpeakersChanged,\n async (speakers: Participant[]) => {\n if (speakers.length > 0) {\n const participant = speakers[0];\n if (participant.identity.includes(\"agent\")) {\n this.updateMode(\"speaking\");\n }\n } else {\n this.updateMode(\"listening\");\n }\n }\n );\n }\n\n public close() {\n if (this.isConnected) {\n try {\n // Explicitly stop all local tracks before disconnecting to ensure microphone is released\n this.room.localParticipant.audioTrackPublications.forEach(\n publication => {\n if (publication.track) {\n publication.track.stop();\n }\n }\n );\n } catch (error) {\n console.warn(\"Error stopping local tracks:\", error);\n }\n\n // Clean up audio capture context (non-blocking)\n if (this.audioCaptureContext) {\n this.audioCaptureContext.close().catch(error => {\n console.warn(\"Error closing audio capture context:\", error);\n });\n this.audioCaptureContext = null;\n }\n\n this.room.disconnect();\n }\n }\n\n public async sendMessage(message: OutgoingSocketEvent) {\n if (!this.isConnected || !this.room.localParticipant) {\n console.warn(\n \"Cannot send message: room not connected or no local participant\"\n );\n return;\n }\n\n // In WebRTC mode, audio is sent via published tracks, not data messages\n if (\"user_audio_chunk\" in message) {\n // Ignore audio data messages - audio flows through WebRTC tracks\n return;\n }\n\n try {\n const encoder = new TextEncoder();\n const data = encoder.encode(JSON.stringify(message));\n\n await this.room.localParticipant.publishData(data, { reliable: true });\n } catch (error) {\n this.debug({\n type: \"send_message_error\",\n message: {\n message,\n error,\n },\n });\n console.error(\"Failed to send message via WebRTC:\", error);\n }\n }\n\n // Get the room instance for advanced usage\n public getRoom(): Room {\n return this.room;\n }\n\n public async setMicMuted(isMuted: boolean): Promise<void> {\n if (!this.isConnected || !this.room.localParticipant) {\n console.warn(\n \"Cannot set microphone muted: room not connected or no local participant\"\n );\n return;\n }\n\n // Get the microphone track publication\n const micTrackPublication = this.room.localParticipant.getTrackPublication(\n Track.Source.Microphone\n );\n\n if (micTrackPublication?.track) {\n try {\n // Use LiveKit's built-in track muting\n if (isMuted) {\n await micTrackPublication.track.mute();\n } else {\n await micTrackPublication.track.unmute();\n }\n } catch (_error) {\n // If track muting fails, fall back to participant-level control\n await this.room.localParticipant.setMicrophoneEnabled(!isMuted);\n }\n } else {\n // No track found, use participant-level control directly\n await this.room.localParticipant.setMicrophoneEnabled(!isMuted);\n }\n }\n\n private async setupAudioCapture(track: RemoteAudioTrack) {\n try {\n // Create audio context for processing\n const audioContext = new AudioContext();\n this.audioCaptureContext = audioContext;\n\n // Create MediaStream from the track\n const mediaStream = new MediaStream([track.mediaStreamTrack]);\n\n // Create audio source from the stream\n const source = audioContext.createMediaStreamSource(mediaStream);\n\n // Load the raw audio processor worklet (reuse existing processor)\n await loadRawAudioProcessor(audioContext.audioWorklet);\n\n // Create worklet node for audio processing\n const worklet = new AudioWorkletNode(audioContext, \"raw-audio-processor\");\n\n // Configure the processor for the output format\n worklet.port.postMessage({\n type: \"setFormat\",\n format: this.outputFormat.format,\n sampleRate: this.outputFormat.sampleRate,\n });\n\n // Handle processed audio data\n worklet.port.onmessage = (event: MessageEvent) => {\n const [audioData, maxVolume] = event.data;\n\n // Only send audio if there's significant volume (not just silence)\n const volumeThreshold = 0.01;\n\n if (maxVolume > volumeThreshold) {\n // Convert to base64\n const base64Audio = arrayBufferToBase64(audioData.buffer);\n\n // Use sequential event ID for proper feedback tracking\n const eventId = this.audioEventId++;\n\n // Trigger the onAudio callback by simulating an audio event\n this.handleMessage({\n type: \"audio\",\n audio_event: {\n audio_base_64: base64Audio,\n event_id: eventId,\n },\n });\n }\n };\n\n // Connect the audio processing chain\n source.connect(worklet);\n } catch (error) {\n console.warn(\"Failed to set up audio capture:\", error);\n }\n }\n}\n","import type {\n BaseConnection,\n SessionConfig,\n ConnectionType,\n} from \"./BaseConnection\";\nimport { WebSocketConnection } from \"./WebSocketConnection\";\nimport { WebRTCConnection } from \"./WebRTCConnection\";\n\nfunction determineConnectionType(config: SessionConfig): ConnectionType {\n // If connectionType is explicitly specified, use it\n if (config.connectionType) {\n return config.connectionType;\n }\n\n // If conversationToken is provided, use WebRTC\n if (\"conversationToken\" in config && config.conversationToken) {\n return \"webrtc\";\n }\n\n // Default to WebSocket for backward compatibility\n return \"websocket\";\n}\n\nexport async function createConnection(\n config: SessionConfig\n): Promise<BaseConnection> {\n const connectionType = determineConnectionType(config);\n\n switch (connectionType) {\n case \"websocket\":\n return WebSocketConnection.create(config);\n case \"webrtc\":\n return WebRTCConnection.create(config);\n default:\n throw new Error(`Unknown connection type: ${connectionType}`);\n }\n}\n","export function isIosDevice() {\n return (\n [\n \"iPad Simulator\",\n \"iPhone Simulator\",\n \"iPod Simulator\",\n \"iPad\",\n \"iPhone\",\n \"iPod\",\n ].includes(navigator.platform) ||\n // iPad on iOS 13 detection\n (navigator.userAgent.includes(\"Mac\") && \"ontouchend\" in document)\n );\n}\n\nexport function isAndroidDevice() {\n return /android/i.test(navigator.userAgent);\n}\n","import { isAndroidDevice, isIosDevice } from \"./compatibility\";\nimport type { DelayConfig } from \"./connection\";\n\nexport async function applyDelay(\n delayConfig: DelayConfig = {\n default: 0,\n // Give the Android AudioManager enough time to switch to the correct audio mode\n android: 3_000,\n }\n) {\n let delay = delayConfig.default;\n if (isAndroidDevice()) {\n delay = delayConfig.android ?? delay;\n } else if (isIosDevice()) {\n delay = delayConfig.ios ?? delay;\n }\n\n if (delay > 0) {\n await new Promise(resolve => setTimeout(resolve, delay));\n }\n}\n","import { createConnection } from \"./utils/ConnectionFactory\";\nimport type { BaseConnection } from \"./utils/BaseConnection\";\nimport { applyDelay } from \"./utils/applyDelay\";\nimport { BaseConversation, type PartialOptions } from \"./BaseConversation\";\n\nexport class TextConversation extends BaseConversation {\n public static async startSession(\n options: PartialOptions\n ): Promise<TextConversation> {\n const fullOptions = BaseConversation.getFullOptions(options);\n\n fullOptions.onStatusChange({ status: \"connecting\" });\n fullOptions.onCanSendFeedbackChange({ canSendFeedback: false });\n\n let connection: BaseConnection | null = null;\n try {\n await applyDelay(fullOptions.connectionDelay);\n connection = await createConnection(options);\n return new TextConversation(fullOptions, connection);\n } catch (error) {\n fullOptions.onStatusChange({ status: \"disconnected\" });\n connection?.close();\n throw error;\n }\n }\n}\n","import { loadRawAudioProcessor } from \"./rawAudioProcessor\";\nimport type { FormatConfig } from \"./connection\";\nimport { isIosDevice } from \"./compatibility\";\n\nexport type InputConfig = {\n preferHeadphonesForIosDevices?: boolean;\n};\n\nconst LIBSAMPLERATE_JS =\n \"https://cdn.jsdelivr.net/npm/@alexanderolsen/libsamplerate-js@2.1.2/dist/libsamplerate.worklet.js\";\n\nexport class Input {\n public static async create({\n sampleRate,\n format,\n preferHeadphonesForIosDevices,\n }: FormatConfig & InputConfig): Promise<Input> {\n let context: AudioContext | null = null;\n let inputStream: MediaStream | null = null;\n\n try {\n const options: MediaTrackConstraints = {\n sampleRate: { ideal: sampleRate },\n echoCancellation: true,\n noiseSuppression: true,\n };\n\n if (isIosDevice() && preferHeadphonesForIosDevices) {\n const availableDevices =\n await window.navigator.mediaDevices.enumerateDevices();\n const idealDevice = availableDevices.find(\n d =>\n // cautious to include \"bluetooth\" in the search\n // as might trigger bluetooth speakers\n d.kind === \"audioinput\" &&\n [\"airpod\", \"headphone\", \"earphone\"].find(keyword =>\n d.label.toLowerCase().includes(keyword)\n )\n );\n if (idealDevice) {\n options.deviceId = { ideal: idealDevice.deviceId };\n }\n }\n\n const supportsSampleRateConstraint =\n navigator.mediaDevices.getSupportedConstraints().sampleRate;\n\n context = new window.AudioContext(\n supportsSampleRateConstraint ? { sampleRate } : {}\n );\n const analyser = context.createAnalyser();\n if (!supportsSampleRateConstraint) {\n await context.audioWorklet.addModule(LIBSAMPLERATE_JS);\n }\n await loadRawAudioProcessor(context.audioWorklet);\n\n const constraints = { voiceIsolation: true, ...options };\n inputStream = await navigator.mediaDevices.getUserMedia({\n audio: constraints,\n });\n\n const source = context.createMediaStreamSource(inputStream);\n const worklet = new AudioWorkletNode(context, \"raw-audio-processor\");\n worklet.port.postMessage({ type: \"setFormat\", format, sampleRate });\n\n source.connect(analyser);\n analyser.connect(worklet);\n\n await context.resume();\n\n return new Input(context, analyser, worklet, inputStream);\n } catch (error) {\n inputStream?.getTracks().forEach(track => track.stop());\n context?.close();\n throw error;\n }\n }\n\n private constructor(\n public readonly context: AudioContext,\n public readonly analyser: AnalyserNode,\n public readonly worklet: AudioWorkletNode,\n public readonly inputStream: MediaStream\n ) {}\n\n public async close() {\n this.inputStream.getTracks().forEach(track => track.stop());\n await this.context.close();\n }\n\n public setMuted(isMuted: boolean) {\n this.worklet.port.postMessage({ type: \"setMuted\", isMuted });\n }\n}\n","/*\n * ulaw decoding logic taken from the wavefile library\n * https://github.com/rochars/wavefile/blob/master/lib/codecs/mulaw.js\n */\n\nimport { createWorkletModuleLoader } from \"./createWorkletModuleLoader\";\n\nexport const loadAudioConcatProcessor = createWorkletModuleLoader(\n \"audio-concat-processor\",\n // language=JavaScript\n `\nconst decodeTable = [0,132,396,924,1980,4092,8316,16764];\n\nexport function decodeSample(muLawSample) {\n let sign;\n let exponent;\n let mantissa;\n let sample;\n muLawSample = ~muLawSample;\n sign = (muLawSample & 0x80);\n exponent = (muLawSample >> 4) & 0x07;\n mantissa = muLawSample & 0x0F;\n sample = decodeTable[exponent] + (mantissa << (exponent+3));\n if (sign !== 0) sample = -sample;\n\n return sample;\n}\n\nclass AudioConcatProcessor extends AudioWorkletProcessor {\n constructor() {\n super();\n this.buffers = []; // Initialize an empty buffer\n this.cursor = 0;\n this.currentBuffer = null;\n this.wasInterrupted = false;\n this.finished = false;\n \n this.port.onmessage = ({ data }) => {\n switch (data.type) {\n case \"setFormat\":\n this.format = data.format;\n break;\n case \"buffer\":\n this.wasInterrupted = false;\n this.buffers.push(\n this.format === \"ulaw\"\n ? new Uint8Array(data.buffer)\n : new Int16Array(data.buffer)\n );\n break;\n case \"interrupt\":\n this.wasInterrupted = true;\n break;\n case \"clearInterrupted\":\n if (this.wasInterrupted) {\n this.wasInterrupted = false;\n this.buffers = [];\n this.currentBuffer = null;\n }\n }\n };\n }\n process(_, outputs) {\n let finished = false;\n const output = outputs[0][0];\n for (let i = 0; i < output.length; i++) {\n if (!this.currentBuffer) {\n if (this.buffers.length === 0) {\n finished = true;\n break;\n }\n this.currentBuffer = this.buffers.shift();\n this.cursor = 0;\n }\n\n let value = this.currentBuffer[this.cursor];\n if (this.format === \"ulaw\") {\n value = decodeSample(value);\n }\n output[i] = value / 32768;\n this.cursor++;\n\n if (this.cursor >= this.currentBuffer.length) {\n this.currentBuffer = null;\n }\n }\n\n if (this.finished !== finished) {\n this.finished = finished;\n this.port.postMessage({ type: \"process\", finished });\n }\n\n return true; // Continue processing\n }\n}\n\nregisterProcessor(\"audio-concat-processor\", AudioConcatProcessor);\n`\n);\n","import { loadAudioConcatProcessor } from \"./audioConcatProcessor\";\nimport type { FormatConfig } from \"./connection\";\n\nexport class Output {\n public static async create({\n sampleRate,\n format,\n }: FormatConfig): Promise<Output> {\n let context: AudioContext | null = null;\n try {\n context = new AudioContext({ sampleRate });\n const analyser = context.createAnalyser();\n const gain = context.createGain();\n gain.connect(analyser);\n analyser.connect(context.destination);\n await loadAudioConcatProcessor(context.audioWorklet);\n const worklet = new AudioWorkletNode(context, \"audio-concat-processor\");\n worklet.port.postMessage({ type: \"setFormat\", format });\n worklet.connect(gain);\n\n await context.resume();\n\n return new Output(context, analyser, gain, worklet);\n } catch (error) {\n context?.close();\n throw error;\n }\n }\n\n private constructor(\n public readonly context: AudioContext,\n public readonly analyser: AnalyserNode,\n public readonly gain: GainNode,\n public readonly worklet: AudioWorkletNode\n ) {}\n\n public async close() {\n await this.context.close();\n }\n}\n","import { arrayBufferToBase64, base64ToArrayBuffer } from \"./utils/audio\";\nimport { Input } from \"./utils/input\";\nimport { Output } from \"./utils/output\";\nimport { createConnection } from \"./utils/ConnectionFactory\";\nimport type { BaseConnection } from \"./utils/BaseConnection\";\nimport { WebRTCConnection } from \"./utils/WebRTCConnection\";\nimport type { AgentAudioEvent, InterruptionEvent } from \"./utils/events\";\nimport { applyDelay } from \"./utils/applyDelay\";\nimport {\n BaseConversation,\n type Options,\n type PartialOptions,\n} from \"./BaseConversation\";\n\nexport class VoiceConversation extends BaseConversation {\n public static async startSession(\n options: PartialOptions\n ): Promise<VoiceConversation> {\n const fullOptions = BaseConversation.getFullOptions(options);\n\n fullOptions.onStatusChange({ status: \"connecting\" });\n fullOptions.onCanSendFeedbackChange({ canSendFeedback: false });\n\n let input: Input | null = null;\n let connection: BaseConnection | null = null;\n let output: Output | null = null;\n let preliminaryInputStream: MediaStream | null = null;\n\n let wakeLock: WakeLockSentinel | null = null;\n if (options.useWakeLock ?? true) {\n try {\n wakeLock = await navigator.wakeLock.request(\"screen\");\n } catch (e) {\n // Wake Lock is not required for the conversation to work\n }\n }\n\n try {\n // some browsers won't allow calling getSupportedConstraints or enumerateDevices\n // before getting approval for microphone access\n preliminaryInputStream = await navigator.mediaDevices.getUserMedia({\n audio: true,\n });\n\n await applyDelay(fullOptions.connectionDelay);\n connection = await createConnection(options);\n [input, output] = await Promise.all([\n Input.create({\n ...connection.inputFormat,\n preferHeadphonesForIosDevices: options.preferHeadphonesForIosDevices,\n }),\n Output.create(connection.outputFormat),\n ]);\n\n preliminaryInputStream?.getTracks().forEach(track => track.stop());\n preliminaryInputStream = null;\n\n return new VoiceConversation(\n fullOptions,\n connection,\n input,\n output,\n wakeLock\n );\n } catch (error) {\n fullOptions.onStatusChange({ status: \"disconnected\" });\n preliminaryInputStream?.getTracks().forEach(track => track.stop());\n connection?.close();\n await input?.close();\n await output?.close();\n try {\n await wakeLock?.release();\n wakeLock = null;\n } catch (e) {}\n throw error;\n }\n }\n\n private inputFrequencyData?: Uint8Array;\n private outputFrequencyData?: Uint8Array;\n\n protected constructor(\n options: Options,\n connection: BaseConnection,\n public readonly input: Input,\n public readonly output: Output,\n public wakeLock: WakeLockSentinel | null\n ) {\n super(options, connection);\n this.input.worklet.port.onmessage = this.onInputWorkletMessage;\n this.output.worklet.port.onmessage = this.onOutputWorkletMessage;\n }\n\n protected override async handleEndSession() {\n await super.handleEndSession();\n try {\n await this.wakeLock?.release();\n this.wakeLock = null;\n } catch (e) {}\n\n await this.input.close();\n await this.output.close();\n }\n\n protected override handleInterruption(event: InterruptionEvent) {\n super.handleInterruption(event);\n this.fadeOutAudio();\n }\n\n protected override handleAudio(event: AgentAudioEvent) {\n if (this.lastInterruptTimestamp <= event.audio_event.event_id) {\n this.options.onAudio?.(event.audio_event.audio_base_64);\n\n // Only play audio through the output worklet for WebSocket connections\n // WebRTC connections handle audio playback directly through LiveKit tracks\n if (!(this.connection instanceof WebRTCConnection)) {\n this.addAudioBase64Chunk(event.audio_event.audio_base_64);\n }\n\n this.currentEventId = event.audio_event.event_id;\n this.updateCanSendFeedback();\n this.updateMode(\"speaking\");\n }\n }\n\n private onInputWorkletMessage = (event: MessageEvent): void => {\n const rawAudioPcmData = event.data[0];\n\n // TODO: When supported, maxVolume can be used to avoid sending silent audio\n // const maxVolume = event.data[1];\n\n if (this.status === \"connected\") {\n this.connection.sendMessage({\n user_audio_chunk: arrayBufferToBase64(rawAudioPcmData.buffer),\n });\n }\n };\n\n private onOutputWorkletMessage = ({ data }: MessageEvent): void => {\n if (data.type === \"process\") {\n this.updateMode(data.finished ? \"listening\" : \"speaking\");\n }\n };\n\n private addAudioBase64Chunk = (chunk: string) => {\n this.output.gain.gain.value = this.volume;\n this.output.worklet.port.postMessage({ type: \"clearInterrupted\" });\n this.output.worklet.port.postMessage({\n type: \"buffer\",\n buffer: base64ToArrayBuffer(chunk),\n });\n };\n\n private fadeOutAudio = () => {\n // mute agent\n this.updateMode(\"listening\");\n this.output.worklet.port.postMessage({ type: \"interrupt\" });\n this.output.gain.gain.exponentialRampToValueAtTime(\n 0.0001,\n this.output.context.currentTime + 2\n );\n\n // reset volume back\n setTimeout(() => {\n this.output.gain.gain.value = this.volume;\n this.output.worklet.port.postMessage({ type: \"clearInterrupted\" });\n }, 2000); // Adjust the duration as needed\n };\n\n private calculateVolume = (frequencyData: Uint8Array) => {\n if (frequencyData.length === 0) {\n return 0;\n }\n\n // TODO: Currently this averages all frequencies, but we should probably\n // bias towards the frequencies that are more typical for human voice\n let volume = 0;\n for (let i = 0; i < frequencyData.length; i++) {\n volume += frequencyData[i] / 255;\n }\n volume /= frequencyData.length;\n\n return volume < 0 ? 0 : volume > 1 ? 1 : volume;\n };\n\n public setMicMuted(isMuted: boolean) {\n // Use LiveKit track muting for WebRTC connections\n if (this.connection instanceof WebRTCConnection) {\n this.connection.setMicMuted(isMuted);\n } else {\n // Use input muting for WebSocket connections\n this.input.setMuted(isMuted);\n }\n }\n\n public getInputByteFrequencyData() {\n this.inputFrequencyData ??= new Uint8Array(\n this.input.analyser.frequencyBinCount\n );\n this.input.analyser.getByteFrequencyData(this.inputFrequencyData);\n return this.inputFrequencyData;\n }\n\n public getOutputByteFrequencyData() {\n this.outputFrequencyData ??= new Uint8Array(\n this.output.analyser.frequencyBinCount\n );\n this.output.analyser.getByteFrequencyData(this.outputFrequencyData);\n return this.outputFrequencyData;\n }\n\n public getInputVolume() {\n return this.calculateVolume(this.getInputByteFrequencyData());\n }\n\n public getOutputVolume() {\n return this.calculateVolume(this.getOutputByteFrequencyData());\n }\n}\n","const HTTPS_API_ORIGIN = \"https://api.elevenlabs.io\";\n\nexport function postOverallFeedback(\n conversationId: string,\n like: boolean,\n origin: string = HTTPS_API_ORIGIN\n) {\n return fetch(`${origin}/v1/convai/conversations/${conversationId}/feedback`, {\n method: \"POST\",\n body: JSON.stringify({\n feedback: like ? \"like\" : \"dislike\",\n }),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n });\n}\n","import { BaseConversation, type PartialOptions } from \"./BaseConversation\";\nimport { TextConversation } from \"./TextConversation\";\nimport { VoiceConversation } from \"./VoiceConversation\";\n\nexport type {\n Mode,\n Role,\n Options,\n PartialOptions,\n ClientToolsConfig,\n Callbacks,\n Status,\n} from \"./BaseConversation\";\nexport type { InputConfig } from \"./utils/input\";\nexport type { IncomingSocketEvent, VadScoreEvent } from \"./utils/events\";\nexport type {\n SessionConfig,\n BaseSessionConfig,\n DisconnectionDetails,\n Language,\n ConnectionType,\n} from \"./utils/BaseConnection\";\nexport { createConnection } from \"./utils/ConnectionFactory\";\nexport { WebSocketConnection } from \"./utils/WebSocketConnection\";\nexport { WebRTCConnection } from \"./utils/WebRTCConnection\";\nexport { postOverallFeedback } from \"./utils/postOverallFeedback\";\n\nexport class Conversation extends BaseConversation {\n public static startSession(options: PartialOptions): Promise<Conversation> {\n return options.textOnly\n ? TextConversation.startSession(options)\n : VoiceConversation.startSession(options);\n }\n}\n"],"names":["EMPTY_FREQUENCY_DATA","Uint8Array","BaseConversation","getFullOptions","partialOptions","_extends","clientTools","onConnect","onDebug","onDisconnect","onError","onMessage","onAudio","onModeChange","onStatusChange","onCanSendFeedbackChange","constructor","options","connection","_this","this","lastInterruptTimestamp","mode","status","volume","currentEventId","lastFeedbackEventId","canSendFeedback","endSessionWithDetails","async","details","updateStatus","handleEndSession","parsedEvent","type","handleInterruption","handleAgentResponse","handleUserTranscript","handleTentativeAgentResponse","handleClientToolCall","handleAudio","handleVadScore","sendMessage","event_id","ping_event","setVolume","conversationId","updateMode","endSession","reason","close","updateCanSendFeedback","event","interruption_event","source","message","agent_response_event","agent_response","user_transcription_event","user_transcript","response","tentative_agent_response_internal_event","tentative_agent_response","onVadScore","vadScore","vad_score_event","vad_score","Object","prototype","hasOwnProperty","call","client_tool_call","tool_name","_await$this$options$c","result","parameters","formattedResult","JSON","stringify","String","tool_call_id","is_error","e","clientToolName","onUnhandledClientToolCall","context","console","error","getId","isOpen","setMicMuted","isMuted","getInputByteFrequencyData","getOutputByteFrequencyData","getInputVolume","getOutputVolume","sendFeedback","like","score","warn","sendContextualUpdate","text","sendUserMessage","sendUserActivity","sendMCPToolApprovalResult","toolCallId","isApproved","is_approved","BaseConnection","config","queue","disconnectionDetails","onDisconnectCallback","onMessageCallback","onModeChangeCallback","debug","info","callback","length","queueMicrotask","forEach","_this$onModeChangeCal","disconnect","_this$onDisconnectCal","handleMessage","push","parseFormat","format","formatPart","sampleRatePart","split","includes","Error","sampleRate","Number","parseInt","isNaN","PACKAGE_VERSION","isValidSocketEvent","CONVERSATION_INITIATION_CLIENT_DATA_TYPE","constructOverrides","_config$overrides","overridesEvent","_config$overrides$age","_config$overrides$age2","_config$overrides$age3","_config$overrides$tts","_config$overrides$con","overrides","conversation_config_override","agent","prompt","first_message","firstMessage","language","tts","voice_id","voiceId","conversation","text_only","textOnly","customLlmExtraBody","custom_llm_extra_body","dynamicVariables","dynamic_variables","userId","user_id","client","source_info","version","WebSocketConnection","socket","inputFormat","outputFormat","super","addEventListener","setTimeout","code","parse","data","_","create","_config$origin","_config$overrides2","origin","url","signedUrl","separator","agentId","protocols","authorization","WebSocket","conversationConfig","Promise","resolve","reject","_socket","send","once","conversation_initiation_metadata_event","conversation_id","agent_output_audio_format","user_input_audio_format","_socket2","arrayBufferToBase64","b","buffer","window","btoa","fromCharCode","base64ToArrayBuffer","base64","binaryString","atob","len","bytes","i","charCodeAt","URLCache","Map","createWorkletModuleLoader","name","sourceCode","get","worklet","addModule","blob","Blob","blobURL","URL","createObjectURL","set","_unused","revokeObjectURL","moduleURL","loadRawAudioProcessor","WebRTCConnection","room","isConnected","audioEventId","audioCaptureContext","setupRoomEventListeners","conversationToken","replace","fetch","ok","statusText","json","token","msg","Room","Date","now","livekitUrl","_room$name$match","connect","onConnected","off","RoomEvent","Connected","on","match","localParticipant","setMicrophoneEnabled","Disconnected","CloseEvent","toString","ConnectionStateChanged","state","ConnectionState","Event","DataReceived","payload","_participant","TextDecoder","decode","TrackSubscribed","track","_publication","participant","kind","Track","Kind","Audio","identity","remoteAudioTrack","audioElement","attach","autoplay","controls","style","display","document","body","appendChild","setupAudioCapture","ActiveSpeakersChanged","speakers","audioTrackPublications","publication","stop","catch","TextEncoder","encode","publishData","reliable","getRoom","micTrackPublication","getTrackPublication","Source","Microphone","mute","unmute","_error","audioContext","AudioContext","mediaStream","MediaStream","mediaStreamTrack","createMediaStreamSource","audioWorklet","AudioWorkletNode","port","postMessage","onmessage","audioData","maxVolume","base64Audio","eventId","audio_event","audio_base_64","createConnection","connectionType","determineConnectionType","isIosDevice","navigator","platform","userAgent","applyDelay","delayConfig","default","android","delay","_delayConfig$android","test","_delayConfig$ios","ios","TextConversation","startSession","fullOptions","connectionDelay","_connection","Input","preferHeadphonesForIosDevices","inputStream","ideal","echoCancellation","noiseSuppression","idealDevice","mediaDevices","enumerateDevices","find","d","keyword","label","toLowerCase","deviceId","supportsSampleRateConstraint","getSupportedConstraints","analyser","createAnalyser","constraints","voiceIsolation","getUserMedia","audio","resume","_inputStream","_context","getTracks","setMuted","loadAudioConcatProcessor","Output","gain","createGain","destination","VoiceConversation","_options$useWakeLock","input","output","preliminaryInputStream","wakeLock","useWakeLock","request","_preliminaryInputStre","all","_preliminaryInputStre2","_input","_output","_wakeLock","release","inputFrequencyData","outputFrequencyData","onInputWorkletMessage","user_audio_chunk","onOutputWorkletMessage","finished","addAudioBase64Chunk","chunk","value","fadeOutAudio","exponentialRampToValueAtTime","currentTime","calculateVolume","frequencyData","_this$wakeLock","_this$options$onAudio","_this$options","_this$inputFrequencyD","frequencyBinCount","getByteFrequencyData","_this$outputFrequency","postOverallFeedback","method","feedback","headers","Conversation"],"mappings":"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"}