UNPKG

agents

Version:

A home for your AI agents

932 lines (925 loc) 47.7 kB
import { i as _classPrivateFieldInitSpec, n as _classPrivateFieldSet2, r as _assertClassBrand, t as _classPrivateFieldGet2 } from "../classPrivateFieldGet2-DZBYAB34.js"; import { t as _classPrivateMethodInitSpec } from "../classPrivateMethodInitSpec-qMjJ6sHQ.js"; import { VOICE_PROTOCOL_VERSION } from "./types.js"; import { toVoiceError } from "./errors.js"; import { t as ClientDiagnostics } from "../diagnostics-C4jcz3VK.js"; import { PartySocket } from "partysocket"; //#region src/voice/client.ts function camelCaseToKebabCase(str) { if (str === str.toUpperCase() && str !== str.toLowerCase()) return str.toLowerCase().replace(/_/g, "-"); let kebabified = str.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`); kebabified = kebabified.startsWith("-") ? kebabified.slice(1) : kebabified; return kebabified.replace(/_/g, "-").replace(/-$/, ""); } const UNSUPPORTED_OUTPUT_DEVICE_ERROR = "Audio output device selection is not supported in this browser."; const OUTPUT_DEVICE_SWITCH_ERROR = "Could not switch audio output device."; const WORKLET_PROCESSOR = ` class AudioCaptureProcessor extends AudioWorkletProcessor { constructor() { super(); this.buffer = []; this.sampleRate = sampleRate; this.targetRate = 16000; this.ratio = this.sampleRate / this.targetRate; } process(inputs) { const input = inputs[0]; if (!input || !input[0]) return true; const channelData = input[0]; // Linear interpolation resampling (e.g. 48kHz → 16kHz). // Nearest-neighbor (picking every Nth sample) introduces aliasing // artifacts, especially on sibilants (s, f, th). Linear interpolation // blends adjacent samples, acting as a basic low-pass filter. for (let i = 0; i < channelData.length; i += this.ratio) { const idx = Math.floor(i); const frac = i - idx; if (idx + 1 < channelData.length) { this.buffer.push(channelData[idx] * (1 - frac) + channelData[idx + 1] * frac); } else if (idx < channelData.length) { this.buffer.push(channelData[idx]); } } if (this.buffer.length >= 1600) { const chunk = new Float32Array(this.buffer); this.port.postMessage({ type: 'audio', samples: chunk }, [chunk.buffer]); this.buffer = []; } return true; } } registerProcessor('audio-capture-processor', AudioCaptureProcessor); `; function floatTo16BitPCM(samples) { const buffer = /* @__PURE__ */ new ArrayBuffer(samples.length * 2); const view = new DataView(buffer); for (let i = 0; i < samples.length; i++) { const s = Math.max(-1, Math.min(1, samples[i])); view.setInt16(i * 2, s < 0 ? s * 32768 : s * 32767, true); } return buffer; } function computeRMS(samples) { let sum = 0; for (let i = 0; i < samples.length; i++) sum += samples[i] * samples[i]; return Math.sqrt(sum / samples.length); } var _socket = /* @__PURE__ */ new WeakMap(); var _options = /* @__PURE__ */ new WeakMap(); /** * Default VoiceTransport backed by PartySocket (reconnecting WebSocket). * Created automatically when no custom transport is provided. */ var WebSocketVoiceTransport = class { constructor(options) { _classPrivateFieldInitSpec(this, _socket, null); _classPrivateFieldInitSpec(this, _options, void 0); this.onopen = null; this.onclose = null; this.onerror = null; this.onmessage = null; _classPrivateFieldSet2(_options, this, options); } get connected() { return _classPrivateFieldGet2(_socket, this)?.readyState === WebSocket.OPEN; } sendJSON(data) { if (_classPrivateFieldGet2(_socket, this)?.readyState === WebSocket.OPEN) _classPrivateFieldGet2(_socket, this).send(JSON.stringify(data)); } sendBinary(data) { if (_classPrivateFieldGet2(_socket, this)?.readyState === WebSocket.OPEN) _classPrivateFieldGet2(_socket, this).send(data); } connect() { if (_classPrivateFieldGet2(_socket, this)) return; const socket = new PartySocket({ party: camelCaseToKebabCase(_classPrivateFieldGet2(_options, this).agent), room: _classPrivateFieldGet2(_options, this).name ?? "default", host: _classPrivateFieldGet2(_options, this).host ?? window.location.host, prefix: "agents", query: _classPrivateFieldGet2(_options, this).query }); socket.onopen = () => this.onopen?.(); socket.onclose = (event) => this.onclose?.(event ? { code: event.code, reason: event.reason, wasClean: event.wasClean } : void 0); socket.onerror = (event) => this.onerror?.(event); socket.onmessage = (event) => { this.onmessage?.(event.data); }; _classPrivateFieldSet2(_socket, this, socket); } disconnect() { _classPrivateFieldGet2(_socket, this)?.close(); _classPrivateFieldSet2(_socket, this, null); } }; var _status = /* @__PURE__ */ new WeakMap(); var _transcript = /* @__PURE__ */ new WeakMap(); var _metrics = /* @__PURE__ */ new WeakMap(); var _turnMetrics = /* @__PURE__ */ new WeakMap(); var _audioLevel = /* @__PURE__ */ new WeakMap(); var _isMuted = /* @__PURE__ */ new WeakMap(); var _connected = /* @__PURE__ */ new WeakMap(); var _error = /* @__PURE__ */ new WeakMap(); var _outputDeviceError = /* @__PURE__ */ new WeakMap(); var _lastCustomMessage = /* @__PURE__ */ new WeakMap(); var _audioFormat = /* @__PURE__ */ new WeakMap(); var _sampleRate = /* @__PURE__ */ new WeakMap(); var _interimTranscript = /* @__PURE__ */ new WeakMap(); var _serverProtocolVersion = /* @__PURE__ */ new WeakMap(); var _inCall = /* @__PURE__ */ new WeakMap(); var _callGeneration = /* @__PURE__ */ new WeakMap(); var _serverCallAcknowledged = /* @__PURE__ */ new WeakMap(); var _diagnostics = /* @__PURE__ */ new WeakMap(); var _audioReceivedForCurrentTurn = /* @__PURE__ */ new WeakMap(); var _diagnosticTurnId = /* @__PURE__ */ new WeakMap(); var _silenceThreshold = /* @__PURE__ */ new WeakMap(); var _silenceDurationMs = /* @__PURE__ */ new WeakMap(); var _interruptThreshold = /* @__PURE__ */ new WeakMap(); var _interruptChunks = /* @__PURE__ */ new WeakMap(); var _maxTranscriptMessages = /* @__PURE__ */ new WeakMap(); var _transport = /* @__PURE__ */ new WeakMap(); var _options2 = /* @__PURE__ */ new WeakMap(); var _audioContext = /* @__PURE__ */ new WeakMap(); var _workletRegistered = /* @__PURE__ */ new WeakMap(); var _workletNode = /* @__PURE__ */ new WeakMap(); var _stream = /* @__PURE__ */ new WeakMap(); var _silenceTimer = /* @__PURE__ */ new WeakMap(); var _isSpeaking = /* @__PURE__ */ new WeakMap(); var _playbackQueue = /* @__PURE__ */ new WeakMap(); var _isPlaying = /* @__PURE__ */ new WeakMap(); var _isScheduling = /* @__PURE__ */ new WeakMap(); var _scheduledSources = /* @__PURE__ */ new WeakMap(); var _playbackCursor = /* @__PURE__ */ new WeakMap(); var _lastPlaybackEnd = /* @__PURE__ */ new WeakMap(); var _playbackElement = /* @__PURE__ */ new WeakMap(); var _playbackDestination = /* @__PURE__ */ new WeakMap(); var _playbackDestinationPromise = /* @__PURE__ */ new WeakMap(); var _useDefaultPlaybackDestination = /* @__PURE__ */ new WeakMap(); var _outputDeviceId = /* @__PURE__ */ new WeakMap(); var _outputDeviceSwitchGeneration = /* @__PURE__ */ new WeakMap(); var _playbackOutputGeneration = /* @__PURE__ */ new WeakMap(); var _playbackGeneration = /* @__PURE__ */ new WeakMap(); var _interruptChunkCount = /* @__PURE__ */ new WeakMap(); var _listeners = /* @__PURE__ */ new WeakMap(); var _VoiceClient_brand = /* @__PURE__ */ new WeakSet(); var VoiceClient = class { constructor(options) { _classPrivateMethodInitSpec(this, _VoiceClient_brand); _classPrivateFieldInitSpec(this, _status, "idle"); _classPrivateFieldInitSpec(this, _transcript, []); _classPrivateFieldInitSpec(this, _metrics, null); _classPrivateFieldInitSpec(this, _turnMetrics, null); _classPrivateFieldInitSpec(this, _audioLevel, 0); _classPrivateFieldInitSpec(this, _isMuted, false); _classPrivateFieldInitSpec(this, _connected, false); _classPrivateFieldInitSpec(this, _error, null); _classPrivateFieldInitSpec(this, _outputDeviceError, null); _classPrivateFieldInitSpec(this, _lastCustomMessage, null); _classPrivateFieldInitSpec(this, _audioFormat, null); _classPrivateFieldInitSpec(this, _sampleRate, 16e3); _classPrivateFieldInitSpec(this, _interimTranscript, null); _classPrivateFieldInitSpec(this, _serverProtocolVersion, null); _classPrivateFieldInitSpec(this, _inCall, false); _classPrivateFieldInitSpec(this, _callGeneration, 0); _classPrivateFieldInitSpec(this, _serverCallAcknowledged, false); _classPrivateFieldInitSpec(this, _diagnostics, new ClientDiagnostics()); _classPrivateFieldInitSpec(this, _audioReceivedForCurrentTurn, false); _classPrivateFieldInitSpec(this, _diagnosticTurnId, null); _classPrivateFieldInitSpec(this, _silenceThreshold, void 0); _classPrivateFieldInitSpec(this, _silenceDurationMs, void 0); _classPrivateFieldInitSpec(this, _interruptThreshold, void 0); _classPrivateFieldInitSpec(this, _interruptChunks, void 0); _classPrivateFieldInitSpec(this, _maxTranscriptMessages, void 0); _classPrivateFieldInitSpec(this, _transport, null); _classPrivateFieldInitSpec(this, _options2, void 0); _classPrivateFieldInitSpec(this, _audioContext, null); _classPrivateFieldInitSpec(this, _workletRegistered, false); _classPrivateFieldInitSpec(this, _workletNode, null); _classPrivateFieldInitSpec(this, _stream, null); _classPrivateFieldInitSpec(this, _silenceTimer, null); _classPrivateFieldInitSpec(this, _isSpeaking, false); _classPrivateFieldInitSpec(this, _playbackQueue, []); _classPrivateFieldInitSpec(this, _isPlaying, false); _classPrivateFieldInitSpec(this, _isScheduling, false); _classPrivateFieldInitSpec(this, _scheduledSources, /* @__PURE__ */ new Set()); _classPrivateFieldInitSpec(this, _playbackCursor, 0); _classPrivateFieldInitSpec(this, _lastPlaybackEnd, null); _classPrivateFieldInitSpec(this, _playbackElement, null); _classPrivateFieldInitSpec(this, _playbackDestination, null); _classPrivateFieldInitSpec(this, _playbackDestinationPromise, null); _classPrivateFieldInitSpec(this, _useDefaultPlaybackDestination, false); _classPrivateFieldInitSpec(this, _outputDeviceId, void 0); _classPrivateFieldInitSpec(this, _outputDeviceSwitchGeneration, 0); _classPrivateFieldInitSpec(this, _playbackOutputGeneration, 0); _classPrivateFieldInitSpec(this, _playbackGeneration, 0); _classPrivateFieldInitSpec(this, _interruptChunkCount, 0); _classPrivateFieldInitSpec(this, _listeners, /* @__PURE__ */ new Map()); _classPrivateFieldSet2(_options2, this, options); _classPrivateFieldSet2(_silenceThreshold, this, options.silenceThreshold ?? .04); _classPrivateFieldSet2(_silenceDurationMs, this, options.silenceDurationMs ?? 500); _classPrivateFieldSet2(_interruptThreshold, this, options.interruptThreshold ?? .05); _classPrivateFieldSet2(_interruptChunks, this, options.interruptChunks ?? 2); _classPrivateFieldSet2(_maxTranscriptMessages, this, options.maxTranscriptMessages ?? 200); _classPrivateFieldSet2(_outputDeviceId, this, options.outputDeviceId ?? "default"); } get status() { return _classPrivateFieldGet2(_status, this); } get transcript() { return _classPrivateFieldGet2(_transcript, this); } get metrics() { return _classPrivateFieldGet2(_metrics, this); } /** Last stable terminal summary received for any speech or text turn. */ get turnMetrics() { return _classPrivateFieldGet2(_turnMetrics, this); } get audioLevel() { return _classPrivateFieldGet2(_audioLevel, this); } get isMuted() { return _classPrivateFieldGet2(_isMuted, this); } get connected() { return _classPrivateFieldGet2(_connected, this); } get error() { return _classPrivateFieldGet2(_error, this); } get outputDeviceError() { return _classPrivateFieldGet2(_outputDeviceError, this); } /** * The current interim (partial) transcript from streaming STT. * Updates in real time as the user speaks. Cleared when the final * transcript is produced or the call reaches a terminal reset. * null when no interim text is available. */ get interimTranscript() { return _classPrivateFieldGet2(_interimTranscript, this); } /** * The protocol version reported by the server. * null until the server sends its welcome message. */ get serverProtocolVersion() { return _classPrivateFieldGet2(_serverProtocolVersion, this); } addEventListener(event, listener) { let set = _classPrivateFieldGet2(_listeners, this).get(event); if (!set) { set = /* @__PURE__ */ new Set(); _classPrivateFieldGet2(_listeners, this).set(event, set); } set.add(listener); } removeEventListener(event, listener) { _classPrivateFieldGet2(_listeners, this).get(event)?.delete(listener); } connect() { if (_classPrivateFieldGet2(_transport, this)) return; const transport = _classPrivateFieldGet2(_options2, this).transport ?? new WebSocketVoiceTransport({ agent: _classPrivateFieldGet2(_options2, this).agent, name: _classPrivateFieldGet2(_options2, this).name, host: _classPrivateFieldGet2(_options2, this).host, query: _classPrivateFieldGet2(_options2, this).query }); transport.onopen = () => { _classPrivateFieldSet2(_connected, this, true); _classPrivateFieldSet2(_error, this, null); transport.sendJSON({ type: "hello", protocol_version: 1 }); _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "connectionchange", true); _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "error", null); if (_classPrivateFieldGet2(_inCall, this)) { _classPrivateFieldSet2(_serverCallAcknowledged, this, false); transport.sendJSON({ type: "start_call" }); } }; transport.onclose = (info) => { _classPrivateFieldGet2(_diagnostics, this).emit("connection.closed", { ...info?.code === void 0 ? {} : { code: info.code }, clean: info?.wasClean ?? false }); _classPrivateFieldSet2(_connected, this, false); _assertClassBrand(_VoiceClient_brand, this, _clearInterimTranscript).call(this); _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "connectionchange", false); _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "connectiondiagnostic", { type: "close", ...info }); }; transport.onerror = (cause) => { _classPrivateFieldGet2(_diagnostics, this).emit("connection.error", { error: toVoiceError(cause, "Connection failed") }); _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "connectiondiagnostic", { type: "error", cause }); _classPrivateFieldSet2(_error, this, "Connection lost. Reconnecting..."); _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "error", _classPrivateFieldGet2(_error, this)); }; transport.onmessage = (data) => { if (typeof data === "string") _assertClassBrand(_VoiceClient_brand, this, _handleJSONMessage).call(this, data); else if (data instanceof Blob) data.arrayBuffer().then((buffer) => { _assertClassBrand(_VoiceClient_brand, this, _recordAudioReceived).call(this, buffer.byteLength); _classPrivateFieldGet2(_playbackQueue, this).push(buffer); _assertClassBrand(_VoiceClient_brand, this, _processPlaybackQueue).call(this); }); else if (data instanceof ArrayBuffer) { _assertClassBrand(_VoiceClient_brand, this, _recordAudioReceived).call(this, data.byteLength); _classPrivateFieldGet2(_playbackQueue, this).push(data); _assertClassBrand(_VoiceClient_brand, this, _processPlaybackQueue).call(this); } }; _classPrivateFieldSet2(_transport, this, transport); transport.connect(); } disconnect() { this.endCall(); _classPrivateFieldGet2(_diagnostics, this).emit("connection.disconnecting"); _classPrivateFieldGet2(_transport, this)?.disconnect(); _classPrivateFieldSet2(_transport, this, null); _classPrivateFieldSet2(_connected, this, false); _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "connectionchange", false); } async startCall() { var _this$callGeneration; if (!_classPrivateFieldGet2(_transport, this)?.connected) { _classPrivateFieldSet2(_error, this, "Cannot start call: not connected. Call connect() first."); _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "error", _classPrivateFieldGet2(_error, this)); return; } if (_classPrivateFieldGet2(_inCall, this)) return; _assertClassBrand(_VoiceClient_brand, this, _clearInterimTranscript).call(this); const callGeneration = _classPrivateFieldSet2(_callGeneration, this, (_this$callGeneration = _classPrivateFieldGet2(_callGeneration, this), ++_this$callGeneration)); _classPrivateFieldSet2(_inCall, this, true); _classPrivateFieldSet2(_serverCallAcknowledged, this, false); _classPrivateFieldSet2(_error, this, null); _classPrivateFieldSet2(_metrics, this, null); _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "error", null); _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "metricschange", null); const startMsg = { type: "start_call" }; if (_classPrivateFieldGet2(_options2, this).preferredFormat) startMsg.preferred_format = _classPrivateFieldGet2(_options2, this).preferredFormat; _classPrivateFieldGet2(_diagnostics, this).emit("call.starting"); _classPrivateFieldGet2(_transport, this).sendJSON(startMsg); const ctx = await _assertClassBrand(_VoiceClient_brand, this, _getAudioContext).call(this); if (_assertClassBrand(_VoiceClient_brand, this, _abortStaleCallStartup).call(this, callGeneration)) return; await _assertClassBrand(_VoiceClient_brand, this, _getPlaybackDestination).call(this, ctx); if (_assertClassBrand(_VoiceClient_brand, this, _abortStaleCallStartup).call(this, callGeneration)) return; if (_classPrivateFieldGet2(_options2, this).audioInput) { _classPrivateFieldGet2(_diagnostics, this).emit("microphone.starting", { source: "custom" }); _classPrivateFieldGet2(_options2, this).audioInput.onAudioLevel = (rms) => _assertClassBrand(_VoiceClient_brand, this, _processAudioLevel).call(this, rms); _classPrivateFieldGet2(_options2, this).audioInput.onAudioData = (pcm) => { if (_classPrivateFieldGet2(_transport, this)?.connected && !_classPrivateFieldGet2(_isMuted, this)) _classPrivateFieldGet2(_transport, this).sendBinary(pcm); }; await _classPrivateFieldGet2(_options2, this).audioInput.start(); _classPrivateFieldGet2(_diagnostics, this).emit("microphone.ready", { source: "custom" }); } else await _assertClassBrand(_VoiceClient_brand, this, _startMic).call(this); if (!_assertClassBrand(_VoiceClient_brand, this, _abortStaleCallStartup).call(this, callGeneration)) _classPrivateFieldGet2(_diagnostics, this).emit("call.local_ready"); } endCall() { var _this$callGeneration2; const wasInCall = _classPrivateFieldGet2(_inCall, this); _classPrivateFieldSet2(_callGeneration, this, (_this$callGeneration2 = _classPrivateFieldGet2(_callGeneration, this), _this$callGeneration2++, _this$callGeneration2)); _classPrivateFieldSet2(_inCall, this, false); _classPrivateFieldSet2(_serverCallAcknowledged, this, false); if (_classPrivateFieldGet2(_transport, this)?.connected) _classPrivateFieldGet2(_transport, this).sendJSON({ type: "end_call" }); _assertClassBrand(_VoiceClient_brand, this, _stopLocalCall).call(this); _assertClassBrand(_VoiceClient_brand, this, _clearInterimTranscript).call(this); _classPrivateFieldSet2(_status, this, "idle"); _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "statuschange", "idle"); if (wasInCall) _classPrivateFieldGet2(_diagnostics, this).emit("call.ended", { reason: "requested" }); } toggleMute() { _classPrivateFieldSet2(_isMuted, this, !_classPrivateFieldGet2(_isMuted, this)); if (_classPrivateFieldGet2(_isMuted, this)) { _classPrivateFieldSet2(_audioLevel, this, 0); _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "audiolevelchange", 0); } if (_classPrivateFieldGet2(_isMuted, this) && _classPrivateFieldGet2(_isSpeaking, this)) { _classPrivateFieldSet2(_isSpeaking, this, false); if (_classPrivateFieldGet2(_silenceTimer, this)) { clearTimeout(_classPrivateFieldGet2(_silenceTimer, this)); _classPrivateFieldSet2(_silenceTimer, this, null); } if (_classPrivateFieldGet2(_transport, this)?.connected) _classPrivateFieldGet2(_transport, this).sendJSON({ type: "end_of_speech" }); } _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "mutechange", _classPrivateFieldGet2(_isMuted, this)); } /** * Send a text message to the agent. The agent processes it through * `onTurn()` (bypassing STT) and responds with text transcript and * TTS audio (if in a call) or text-only (if not). */ sendText(text) { if (_classPrivateFieldGet2(_transport, this)?.connected) _classPrivateFieldGet2(_transport, this).sendJSON({ type: "text_message", text }); } /** * Send arbitrary JSON to the agent. Use this for app-level messages * that are not part of the voice protocol (e.g. `{ type: "kick_speaker" }`). * The server receives these in the consumer's `onMessage()` handler. */ sendJSON(data) { if (_classPrivateFieldGet2(_transport, this)?.connected) _classPrivateFieldGet2(_transport, this).sendJSON(data); } /** * Set the preferred audio output device for assistant playback. * Unsupported browsers continue playing through the default output. */ async setOutputDevice(outputDeviceId) { var _this$outputDeviceSwi; _classPrivateFieldSet2(_outputDeviceId, this, outputDeviceId ?? "default"); const generation = _classPrivateFieldSet2(_outputDeviceSwitchGeneration, this, (_this$outputDeviceSwi = _classPrivateFieldGet2(_outputDeviceSwitchGeneration, this), ++_this$outputDeviceSwi)); if (_classPrivateFieldGet2(_playbackElement, this)) await _assertClassBrand(_VoiceClient_brand, this, _applyOutputDevice).call(this, _classPrivateFieldGet2(_playbackElement, this), generation); } /** * The last custom (non-voice-protocol) message received from the server. * Listen for the `"custommessage"` event to be notified when this changes. */ get lastCustomMessage() { return _classPrivateFieldGet2(_lastCustomMessage, this); } /** * The audio format the server declared for binary payloads. * Set when the server sends `audio_config` at call start. */ get audioFormat() { return _classPrivateFieldGet2(_audioFormat, this); } /** * The sample rate (Hz) the server declared for raw pcm16 payloads. * Set when the server sends `audio_config` at call start. Defaults to 16000. */ get sampleRate() { return _classPrivateFieldGet2(_sampleRate, this); } }; function _emit(event, data) { const set = _classPrivateFieldGet2(_listeners, this).get(event); if (set) for (const listener of set) listener(data); } function _trimTranscript() { if (_classPrivateFieldGet2(_transcript, this).length > _classPrivateFieldGet2(_maxTranscriptMessages, this)) _classPrivateFieldSet2(_transcript, this, _classPrivateFieldGet2(_transcript, this).slice(-_classPrivateFieldGet2(_maxTranscriptMessages, this))); } function _setOutputDeviceError(error) { if (_classPrivateFieldGet2(_outputDeviceError, this) === error) return; _classPrivateFieldSet2(_outputDeviceError, this, error); _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "outputdeviceerror", error); } function _clearInterimTranscript() { _classPrivateFieldSet2(_interimTranscript, this, null); _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "interimtranscript", null); } function _isCurrentCallStartup(callGeneration) { return _classPrivateFieldGet2(_inCall, this) && _classPrivateFieldGet2(_callGeneration, this) === callGeneration; } function _abortStaleCallStartup(callGeneration) { if (_assertClassBrand(_VoiceClient_brand, this, _isCurrentCallStartup).call(this, callGeneration)) return false; if (!_classPrivateFieldGet2(_inCall, this)) _assertClassBrand(_VoiceClient_brand, this, _stopLocalCall).call(this); return true; } function _stopLocalCall() { if (_classPrivateFieldGet2(_options2, this).audioInput) { _classPrivateFieldGet2(_options2, this).audioInput.stop(); _classPrivateFieldGet2(_options2, this).audioInput.onAudioLevel = null; _classPrivateFieldGet2(_options2, this).audioInput.onAudioData = null; } else _assertClassBrand(_VoiceClient_brand, this, _stopMic).call(this); _assertClassBrand(_VoiceClient_brand, this, _stopPlayback).call(this); _assertClassBrand(_VoiceClient_brand, this, _closeAudioContext).call(this); _assertClassBrand(_VoiceClient_brand, this, _resetDetection).call(this); } function _recordAudioReceived(bytes) { if (_classPrivateFieldGet2(_audioReceivedForCurrentTurn, this)) return; _classPrivateFieldSet2(_audioReceivedForCurrentTurn, this, true); _classPrivateFieldGet2(_diagnostics, this).emit("audio.received", { bytes, ..._classPrivateFieldGet2(_diagnosticTurnId, this) === null ? {} : { turn_id: _classPrivateFieldGet2(_diagnosticTurnId, this) } }); } function _handleJSONMessage(data) { let msg; try { msg = JSON.parse(data); } catch { return; } switch (msg.type) { case "welcome": { const diagnosticsEnabled = (typeof msg.diagnostics === "object" && msg.diagnostics !== null ? msg.diagnostics : null)?.browser_console === true; _classPrivateFieldGet2(_diagnostics, this).setEnabled(diagnosticsEnabled); if (diagnosticsEnabled) _classPrivateFieldGet2(_diagnostics, this).emit("connection.ready", { protocol_version: msg.protocol_version }); _classPrivateFieldSet2(_serverProtocolVersion, this, msg.protocol_version); if (msg.protocol_version !== 1) console.warn(`[VoiceClient] Protocol version mismatch: client=1, server=${msg.protocol_version}`); break; } case "diagnostic": if (typeof msg.event === "string" && typeof msg.timestamp === "number" && Number.isFinite(msg.timestamp)) { const data = typeof msg.data === "object" && msg.data !== null ? msg.data : void 0; if (msg.event === "audio.first_sent" && typeof data?.turn_id === "string") { _classPrivateFieldSet2(_diagnosticTurnId, this, data.turn_id); _classPrivateFieldSet2(_audioReceivedForCurrentTurn, this, false); } _classPrivateFieldGet2(_diagnostics, this).receive({ event: msg.event, timestamp: msg.timestamp, ...data === void 0 ? {} : { data } }); } break; case "audio_config": _classPrivateFieldSet2(_serverCallAcknowledged, this, true); _classPrivateFieldSet2(_audioFormat, this, msg.format); _classPrivateFieldSet2(_sampleRate, this, typeof msg.sampleRate === "number" && msg.sampleRate > 0 ? msg.sampleRate : 16e3); break; case "status": _classPrivateFieldSet2(_status, this, msg.status); if (msg.status === "thinking" || msg.status === "speaking") { _classPrivateFieldSet2(_audioReceivedForCurrentTurn, this, false); if (msg.status === "thinking") _classPrivateFieldSet2(_diagnosticTurnId, this, null); } if (msg.status === "idle" && _classPrivateFieldGet2(_inCall, this)) { var _this$callGeneration4; if (!(_classPrivateFieldGet2(_serverCallAcknowledged, this) || _classPrivateFieldGet2(_error, this) !== null)) { _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "statuschange", _classPrivateFieldGet2(_status, this)); break; } _classPrivateFieldSet2(_callGeneration, this, (_this$callGeneration4 = _classPrivateFieldGet2(_callGeneration, this), _this$callGeneration4++, _this$callGeneration4)); _classPrivateFieldSet2(_inCall, this, false); _classPrivateFieldSet2(_serverCallAcknowledged, this, false); _assertClassBrand(_VoiceClient_brand, this, _stopLocalCall).call(this); _assertClassBrand(_VoiceClient_brand, this, _clearInterimTranscript).call(this); } if (msg.status === "listening") { _classPrivateFieldSet2(_serverCallAcknowledged, this, true); _classPrivateFieldSet2(_error, this, null); _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "error", null); } else if (msg.status === "thinking" || msg.status === "speaking") _classPrivateFieldSet2(_serverCallAcknowledged, this, true); _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "statuschange", _classPrivateFieldGet2(_status, this)); break; case "transcript_interim": _classPrivateFieldSet2(_interimTranscript, this, msg.text); _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "interimtranscript", _classPrivateFieldGet2(_interimTranscript, this)); break; case "playback_interrupt": _assertClassBrand(_VoiceClient_brand, this, _stopPlayback).call(this, "server_interrupt"); break; case "transcript": _classPrivateFieldSet2(_interimTranscript, this, null); _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "interimtranscript", null); if (msg.role === "user" && _classPrivateFieldGet2(_isPlaying, this)) _assertClassBrand(_VoiceClient_brand, this, _stopPlayback).call(this, "user_utterance"); _classPrivateFieldSet2(_transcript, this, [..._classPrivateFieldGet2(_transcript, this), { role: msg.role, text: msg.text, timestamp: Date.now() }]); _assertClassBrand(_VoiceClient_brand, this, _trimTranscript).call(this); _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "transcriptchange", _classPrivateFieldGet2(_transcript, this)); break; case "transcript_start": _classPrivateFieldSet2(_transcript, this, [..._classPrivateFieldGet2(_transcript, this), { role: "assistant", text: "", timestamp: Date.now() }]); _assertClassBrand(_VoiceClient_brand, this, _trimTranscript).call(this); _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "transcriptchange", _classPrivateFieldGet2(_transcript, this)); break; case "transcript_delta": { if (_classPrivateFieldGet2(_transcript, this).length === 0) break; const updated = [..._classPrivateFieldGet2(_transcript, this)]; const last = updated[updated.length - 1]; if (last.role === "assistant") { updated[updated.length - 1] = { ...last, text: last.text + msg.text }; _classPrivateFieldSet2(_transcript, this, updated); _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "transcriptchange", _classPrivateFieldGet2(_transcript, this)); } break; } case "transcript_end": { if (_classPrivateFieldGet2(_transcript, this).length === 0) break; const updated = [..._classPrivateFieldGet2(_transcript, this)]; const last = updated[updated.length - 1]; if (last.role === "assistant") { updated[updated.length - 1] = { ...last, text: msg.text }; _classPrivateFieldSet2(_transcript, this, updated); _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "transcriptchange", _classPrivateFieldGet2(_transcript, this)); } break; } case "metrics": _classPrivateFieldSet2(_metrics, this, { llm_ms: msg.llm_ms, tts_ms: msg.tts_ms, first_audio_ms: msg.first_audio_ms, total_ms: msg.total_ms }); _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "metricschange", _classPrivateFieldGet2(_metrics, this)); break; case "turn_metrics": { const { type: _type, ...payload } = msg; const metrics = payload; _classPrivateFieldSet2(_turnMetrics, this, metrics); _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "turnmetrics", metrics); break; } case "completion_outcome": { const outcome = { code: msg.code, stage: "llm", ...msg.finishReason !== void 0 ? { finishReason: msg.finishReason } : {}, partialOutput: msg.partialOutput }; _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "completionoutcome", outcome); break; } case "error": { const voiceError = { message: msg.message, ...msg.code !== void 0 ? { code: msg.code } : {}, ...msg.stage !== void 0 ? { stage: msg.stage } : {}, ...msg.retryable !== void 0 ? { retryable: msg.retryable } : {} }; _classPrivateFieldSet2(_error, this, voiceError.message); _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "voiceerror", voiceError); _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "error", _classPrivateFieldGet2(_error, this)); break; } default: _classPrivateFieldSet2(_lastCustomMessage, this, msg); _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "custommessage", msg); break; } } /** Get or create the shared AudioContext. */ async function _getAudioContext() { if (!_classPrivateFieldGet2(_audioContext, this)) _classPrivateFieldSet2(_audioContext, this, new AudioContext({ sampleRate: 48e3 })); if (_classPrivateFieldGet2(_audioContext, this).state === "suspended") await _classPrivateFieldGet2(_audioContext, this).resume(); return _classPrivateFieldGet2(_audioContext, this); } /** Close the AudioContext and release resources. */ function _closeAudioContext() { if (_classPrivateFieldGet2(_audioContext, this)) { _assertClassBrand(_VoiceClient_brand, this, _closePlaybackOutput).call(this); _classPrivateFieldGet2(_audioContext, this).close().catch(() => {}); _classPrivateFieldSet2(_audioContext, this, null); _classPrivateFieldSet2(_workletRegistered, this, false); } } async function _getPlaybackDestination(ctx) { if (_classPrivateFieldGet2(_playbackDestinationPromise, this)) return _classPrivateFieldGet2(_playbackDestinationPromise, this); if (_classPrivateFieldGet2(_playbackDestination, this)) return _classPrivateFieldGet2(_playbackDestination, this); if (_classPrivateFieldGet2(_useDefaultPlaybackDestination, this)) return ctx.destination; const outputGeneration = _classPrivateFieldGet2(_playbackOutputGeneration, this); const promise = _assertClassBrand(_VoiceClient_brand, this, _initializePlaybackDestination).call(this, ctx, outputGeneration); _classPrivateFieldSet2(_playbackDestinationPromise, this, promise); try { return await promise; } finally { if (_classPrivateFieldGet2(_playbackDestinationPromise, this) === promise) _classPrivateFieldSet2(_playbackDestinationPromise, this, null); } } async function _initializePlaybackDestination(ctx, outputGeneration) { try { const destination = ctx.createMediaStreamDestination(); const audio = new Audio(); audio.autoplay = true; audio.srcObject = destination.stream; _classPrivateFieldSet2(_playbackElement, this, audio); _classPrivateFieldSet2(_playbackDestination, this, destination); await _assertClassBrand(_VoiceClient_brand, this, _applyOutputDevice).call(this, audio, _classPrivateFieldGet2(_outputDeviceSwitchGeneration, this)); if (!_assertClassBrand(_VoiceClient_brand, this, _isCurrentPlaybackOutput).call(this, audio, outputGeneration)) { _assertClassBrand(_VoiceClient_brand, this, _releasePlaybackElement).call(this, audio); return ctx.destination; } await audio.play(); if (!_assertClassBrand(_VoiceClient_brand, this, _isCurrentPlaybackOutput).call(this, audio, outputGeneration)) { _assertClassBrand(_VoiceClient_brand, this, _releasePlaybackElement).call(this, audio); return ctx.destination; } return destination; } catch (err) { console.warn("[VoiceClient] HTMLAudioElement playback output unavailable; using default AudioContext destination.", err); _assertClassBrand(_VoiceClient_brand, this, _closePlaybackOutput).call(this); _classPrivateFieldSet2(_useDefaultPlaybackDestination, this, true); return ctx.destination; } } function _isCurrentPlaybackOutput(audio, outputGeneration) { return _classPrivateFieldGet2(_playbackElement, this) === audio && _classPrivateFieldGet2(_playbackOutputGeneration, this) === outputGeneration; } async function _applyOutputDevice(audio, generation) { const sinkId = _classPrivateFieldGet2(_outputDeviceId, this); const setSinkId = audio.setSinkId; if (!setSinkId) { if (sinkId === "default") { _assertClassBrand(_VoiceClient_brand, this, _setOutputDeviceError).call(this, null); return; } _assertClassBrand(_VoiceClient_brand, this, _setOutputDeviceError).call(this, UNSUPPORTED_OUTPUT_DEVICE_ERROR); return; } try { await setSinkId.call(audio, sinkId); if (generation !== _classPrivateFieldGet2(_outputDeviceSwitchGeneration, this) || sinkId !== _classPrivateFieldGet2(_outputDeviceId, this)) { if (_classPrivateFieldGet2(_playbackElement, this) === audio) await _assertClassBrand(_VoiceClient_brand, this, _applyOutputDevice).call(this, audio, _classPrivateFieldGet2(_outputDeviceSwitchGeneration, this)); return; } if (_classPrivateFieldGet2(_outputDeviceError, this) === UNSUPPORTED_OUTPUT_DEVICE_ERROR || _classPrivateFieldGet2(_outputDeviceError, this) === OUTPUT_DEVICE_SWITCH_ERROR) _assertClassBrand(_VoiceClient_brand, this, _setOutputDeviceError).call(this, null); } catch { if (generation !== _classPrivateFieldGet2(_outputDeviceSwitchGeneration, this) || sinkId !== _classPrivateFieldGet2(_outputDeviceId, this)) { if (_classPrivateFieldGet2(_playbackElement, this) === audio) await _assertClassBrand(_VoiceClient_brand, this, _applyOutputDevice).call(this, audio, _classPrivateFieldGet2(_outputDeviceSwitchGeneration, this)); return; } _assertClassBrand(_VoiceClient_brand, this, _setOutputDeviceError).call(this, OUTPUT_DEVICE_SWITCH_ERROR); } } function _closePlaybackOutput() { var _this$playbackOutputG; _classPrivateFieldSet2(_playbackOutputGeneration, this, (_this$playbackOutputG = _classPrivateFieldGet2(_playbackOutputGeneration, this), _this$playbackOutputG++, _this$playbackOutputG)); if (_classPrivateFieldGet2(_playbackElement, this)) { _assertClassBrand(_VoiceClient_brand, this, _releasePlaybackElement).call(this, _classPrivateFieldGet2(_playbackElement, this)); _classPrivateFieldSet2(_playbackElement, this, null); } _classPrivateFieldSet2(_playbackDestination, this, null); _classPrivateFieldSet2(_playbackDestinationPromise, this, null); _classPrivateFieldSet2(_useDefaultPlaybackDestination, this, false); } function _releasePlaybackElement(audio) { audio.pause(); audio.srcObject = null; } async function _playAudio(audioData, generation) { try { const ctx = await _assertClassBrand(_VoiceClient_brand, this, _getAudioContext).call(this); let audioBuffer; if (_classPrivateFieldGet2(_audioFormat, this) === "pcm16") { const int16 = new Int16Array(audioData); audioBuffer = ctx.createBuffer(1, int16.length, _classPrivateFieldGet2(_sampleRate, this)); const channel = audioBuffer.getChannelData(0); for (let i = 0; i < int16.length; i++) channel[i] = int16[i] / 32768; } else audioBuffer = await ctx.decodeAudioData(audioData.slice(0)); if (generation !== _classPrivateFieldGet2(_playbackGeneration, this)) return; if (_classPrivateFieldGet2(_playbackElement, this) && _classPrivateFieldGet2(_scheduledSources, this).size === 0 && _classPrivateFieldGet2(_lastPlaybackEnd, this) !== null && ctx.currentTime - _classPrivateFieldGet2(_lastPlaybackEnd, this) > .3) _assertClassBrand(_VoiceClient_brand, this, _closePlaybackOutput).call(this); const destination = await _assertClassBrand(_VoiceClient_brand, this, _getPlaybackDestination).call(this, ctx); if (generation !== _classPrivateFieldGet2(_playbackGeneration, this)) return; const source = ctx.createBufferSource(); source.buffer = audioBuffer; source.connect(destination); _classPrivateFieldGet2(_scheduledSources, this).add(source); source.onended = () => { _classPrivateFieldGet2(_scheduledSources, this).delete(source); if (generation === _classPrivateFieldGet2(_playbackGeneration, this) && !_classPrivateFieldGet2(_isScheduling, this) && _classPrivateFieldGet2(_scheduledSources, this).size === 0 && _classPrivateFieldGet2(_playbackQueue, this).length === 0) { _classPrivateFieldSet2(_isPlaying, this, false); _classPrivateFieldGet2(_diagnostics, this).emit("playback.completed"); } }; const startAt = Math.max(ctx.currentTime, _classPrivateFieldGet2(_playbackCursor, this)); _classPrivateFieldSet2(_playbackCursor, this, startAt + audioBuffer.duration); _classPrivateFieldSet2(_lastPlaybackEnd, this, _classPrivateFieldGet2(_playbackCursor, this)); source.start(startAt); } catch (err) { _classPrivateFieldGet2(_diagnostics, this).emit("playback.error", { error: toVoiceError(err, "Playback failed") }); console.error("[VoiceClient] Audio playback error:", err); } } async function _processPlaybackQueue() { if (_classPrivateFieldGet2(_isScheduling, this) || _classPrivateFieldGet2(_playbackQueue, this).length === 0) return; _classPrivateFieldSet2(_isScheduling, this, true); _classPrivateFieldSet2(_isPlaying, this, true); _classPrivateFieldGet2(_diagnostics, this).emit("playback.started", { chunks: _classPrivateFieldGet2(_playbackQueue, this).length }); const generation = _classPrivateFieldGet2(_playbackGeneration, this); while (generation === _classPrivateFieldGet2(_playbackGeneration, this) && _classPrivateFieldGet2(_playbackQueue, this).length > 0) { const audioData = _classPrivateFieldGet2(_playbackQueue, this).shift(); await _assertClassBrand(_VoiceClient_brand, this, _playAudio).call(this, audioData, generation); } if (generation === _classPrivateFieldGet2(_playbackGeneration, this)) { _classPrivateFieldSet2(_isScheduling, this, false); if (_classPrivateFieldGet2(_scheduledSources, this).size === 0) _classPrivateFieldSet2(_isPlaying, this, false); } } function _stopPlayback(reason = "stopped") { var _this$playbackGenerat; const wasActive = _classPrivateFieldGet2(_isPlaying, this) || _classPrivateFieldGet2(_isScheduling, this) || _classPrivateFieldGet2(_playbackQueue, this).length > 0 || _classPrivateFieldGet2(_scheduledSources, this).size > 0; _classPrivateFieldSet2(_playbackGeneration, this, (_this$playbackGenerat = _classPrivateFieldGet2(_playbackGeneration, this), _this$playbackGenerat++, _this$playbackGenerat)); const sources = [..._classPrivateFieldGet2(_scheduledSources, this)]; _classPrivateFieldGet2(_scheduledSources, this).clear(); for (const source of sources) try { source.stop(); } catch {} _classPrivateFieldSet2(_playbackQueue, this, []); _classPrivateFieldSet2(_isPlaying, this, false); _classPrivateFieldSet2(_isScheduling, this, false); _classPrivateFieldSet2(_playbackCursor, this, 0); _classPrivateFieldSet2(_lastPlaybackEnd, this, _classPrivateFieldGet2(_audioContext, this) ? _classPrivateFieldGet2(_audioContext, this).currentTime : null); if (wasActive) _classPrivateFieldGet2(_diagnostics, this).emit("playback.stopped", { reason }); } async function _startMic() { _classPrivateFieldGet2(_diagnostics, this).emit("microphone.starting", { source: "browser" }); try { const stream = await navigator.mediaDevices.getUserMedia({ audio: { sampleRate: { ideal: 48e3 }, channelCount: 1, echoCancellation: true, noiseSuppression: true, autoGainControl: true } }); _classPrivateFieldSet2(_stream, this, stream); const ctx = await _assertClassBrand(_VoiceClient_brand, this, _getAudioContext).call(this); if (!_classPrivateFieldGet2(_workletRegistered, this)) { const blob = new Blob([WORKLET_PROCESSOR], { type: "application/javascript" }); const workletUrl = URL.createObjectURL(blob); await ctx.audioWorklet.addModule(workletUrl); URL.revokeObjectURL(workletUrl); _classPrivateFieldSet2(_workletRegistered, this, true); } const source = ctx.createMediaStreamSource(stream); const workletNode = new AudioWorkletNode(ctx, "audio-capture-processor"); _classPrivateFieldSet2(_workletNode, this, workletNode); workletNode.port.onmessage = (event) => { if (event.data.type === "audio" && !_classPrivateFieldGet2(_isMuted, this)) { const samples = event.data.samples; const rms = computeRMS(samples); const pcm = floatTo16BitPCM(samples); if (_classPrivateFieldGet2(_transport, this)?.connected) _classPrivateFieldGet2(_transport, this).sendBinary(pcm); _assertClassBrand(_VoiceClient_brand, this, _processAudioLevel).call(this, rms); } }; source.connect(workletNode); workletNode.connect(ctx.destination); _classPrivateFieldGet2(_diagnostics, this).emit("microphone.ready", { source: "browser" }); } catch (err) { _classPrivateFieldGet2(_diagnostics, this).emit("microphone.error", { error: toVoiceError(err, "Microphone failed") }); console.error("[VoiceClient] Mic error:", err); _classPrivateFieldSet2(_error, this, "Microphone access denied. Please allow microphone access and try again."); _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "error", _classPrivateFieldGet2(_error, this)); } } function _stopMic() { const wasActive = _classPrivateFieldGet2(_workletNode, this) !== null || _classPrivateFieldGet2(_stream, this) !== null; _classPrivateFieldGet2(_workletNode, this)?.disconnect(); _classPrivateFieldSet2(_workletNode, this, null); _classPrivateFieldGet2(_stream, this)?.getTracks().forEach((track) => track.stop()); _classPrivateFieldSet2(_stream, this, null); if (wasActive) _classPrivateFieldGet2(_diagnostics, this).emit("microphone.stopped"); _assertClassBrand(_VoiceClient_brand, this, _resetDetection).call(this); } function _processAudioLevel(rms) { if (_classPrivateFieldGet2(_isMuted, this)) return; _classPrivateFieldSet2(_audioLevel, this, rms); _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "audiolevelchange", rms); if (_classPrivateFieldGet2(_isPlaying, this) && rms > _classPrivateFieldGet2(_interruptThreshold, this)) { var _this$interruptChunkC; _classPrivateFieldSet2(_interruptChunkCount, this, (_this$interruptChunkC = _classPrivateFieldGet2(_interruptChunkCount, this), _this$interruptChunkC++, _this$interruptChunkC)); if (_classPrivateFieldGet2(_interruptChunkCount, this) >= _classPrivateFieldGet2(_interruptChunks, this)) { _classPrivateFieldGet2(_diagnostics, this).emit("speech.interrupt_detected"); _assertClassBrand(_VoiceClient_brand, this, _stopPlayback).call(this, "speech_interrupt"); _classPrivateFieldSet2(_interruptChunkCount, this, 0); if (_classPrivateFieldGet2(_transport, this)?.connected) _classPrivateFieldGet2(_transport, this).sendJSON({ type: "interrupt" }); } } else _classPrivateFieldSet2(_interruptChunkCount, this, 0); if (rms > _classPrivateFieldGet2(_silenceThreshold, this)) { if (!_classPrivateFieldGet2(_isSpeaking, this)) { _classPrivateFieldSet2(_isSpeaking, this, true); _classPrivateFieldGet2(_diagnostics, this).emit("speech.started"); if (_classPrivateFieldGet2(_transport, this)?.connected) _classPrivateFieldGet2(_transport, this).sendJSON({ type: "start_of_speech" }); } if (_classPrivateFieldGet2(_silenceTimer, this)) { clearTimeout(_classPrivateFieldGet2(_silenceTimer, this)); _classPrivateFieldSet2(_silenceTimer, this, null); } } else if (_classPrivateFieldGet2(_isSpeaking, this)) { if (!_classPrivateFieldGet2(_silenceTimer, this)) _classPrivateFieldSet2(_silenceTimer, this, setTimeout(() => { _classPrivateFieldSet2(_isSpeaking, this, false); _classPrivateFieldSet2(_silenceTimer, this, null); _classPrivateFieldGet2(_diagnostics, this).emit("speech.ended"); if (_classPrivateFieldGet2(_transport, this)?.connected) _classPrivateFieldGet2(_transport, this).sendJSON({ type: "end_of_speech" }); }, _classPrivateFieldGet2(_silenceDurationMs, this))); } } function _resetDetection() { if (_classPrivateFieldGet2(_silenceTimer, this)) { clearTimeout(_classPrivateFieldGet2(_silenceTimer, this)); _classPrivateFieldSet2(_silenceTimer, this, null); } _classPrivateFieldSet2(_isSpeaking, this, false); _classPrivateFieldSet2(_interruptChunkCount, this, 0); _classPrivateFieldSet2(_audioLevel, this, 0); _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "audiolevelchange", 0); } //#endregion export { VOICE_PROTOCOL_VERSION, VoiceClient, WebSocketVoiceTransport }; //# sourceMappingURL=client.js.map