{"version":3,"sources":["../src/client/index.ts","../src/client/client.ts","../src/audio/service.ts","../src/audio/worker/AudioWorklet.ts","../src/client/types.ts","../src/index.ts"],"sourcesContent":["import { Client } from \"./client\";\nimport { Config } from \"./types\";\n\nexport function createClient(config: Config) {\n  return new Client(config);\n}\n\nexport async function createMicrophoneAudioTrack(sampleRate: number, config?: Config): Promise<MediaStream> {\n  const audioConstraints = {\n    sampleRate: sampleRate,\n    echoCancellation: true,\n    noiseSuppression: true,\n    channelCount: 1,\n    autoGainControl: true,\n    latency: 0,\n    ...(config?.audioSource?.constraints || {}),\n  };\n\n  if (config?.audioSource?.deviceId) {\n    audioConstraints.deviceId = config.audioSource.deviceId;\n  }\n\n  return (navigator.mediaDevices as any).getUserMedia({\n    audio: audioConstraints,\n  });\n}","import { EventEmitter } from \"eventemitter3\";\nimport { AudioService } from \"../audio/service\";\nimport { LatencyEstimator } from \"../audio/latency_estimator\";\nimport { AgentConfig, AgentState, ClientEvents, ClientInterface, Config } from \"./types\";\n\n// const HOST = \"wss://gateway.millis.ai:8080/\";\n// const HOST = \"ws://54.177.98.36:8080/\";\n// const HOST = \"ws://betaapi.tmatehq.com:8080/\";\nconst HOST = \"wss://api-west.millis.ai:8080/millis\";\n// const HOST = \"ws://localhost:8080/millis\";\n\nexport interface IMessage {\n  method: string;\n  data?: string;\n  payload?: any;\n}\n\nexport interface IStartPayload {\n  // call_id?: string,\n  agent: {\n    agent_id?: string,\n    agent_config?: AgentConfig,\n  },\n  metadata?: object,\n  include_metadata_in_prompt?: boolean,\n  session_continuation?: {\n    session_id?: string\n  }\n}\n\nenum State {\n  IDLE,\n  READY,\n  GOT_READY_EVENT,\n  GOT_FIRST_AUDIO\n}\n\nexport class Client extends EventEmitter<ClientEvents> implements ClientInterface {\n  private config: Config;\n  private ws: WebSocket | null;\n  private audioService: AudioService | null;\n  private startAnswering: number = 0;\n  private count: number = 0;\n  private latencyEstimator: LatencyEstimator | null;\n  private agentState: AgentState = AgentState.IDLE;\n  private state: State = State.IDLE;\n  private muted: boolean = false;\n  private readyPayload: object | undefined = undefined;\n\n  constructor(config: Config) {\n    super();\n    this.ws = null;\n    this.audioService = null;\n    this.latencyEstimator = null;\n    const defaultConfig = {\n      debug: false\n    }\n    this.config = {...defaultConfig, ...config};\n    this.print('init');\n  }\n\n  private reset() {\n    this.state = State.IDLE;\n    this.agentState = AgentState.IDLE;\n    this.count = 0;\n    this.startAnswering = 0;\n    this.muted = false;\n  }\n\n  private print(message: string) {\n    if (this.config.debug) {\n      console.log(\"[millis]\", message);\n    }\n  }\n\n  private connect(payload: IStartPayload) {\n    this.print('starting websocket');\n    this.ws = new WebSocket(this.config.endPoint || HOST);\n    this.ws.binaryType = \"arraybuffer\";\n\n    this.ws.onopen = () => {\n      this.print('websocket connected, sending initiate message');\n      this.emit(\"onopen\");\n      this.send(JSON.stringify({\n        \"method\": \"initiate\",\n        \"data\": {\n          public_key: this.config.publicKey,\n          agent: payload.agent,\n          metadata: payload.metadata,\n          include_metadata_in_prompt: payload.include_metadata_in_prompt,\n          session_continuation: payload.session_continuation\n        }}));\n    };\n\n    this.ws.onmessage = (event) => {\n      if (event.data instanceof ArrayBuffer) {\n        this.print('audio data received');\n        // this.config.isTest && this.latencyEstimator?.onAudio();\n        if (this.startAnswering > 0) {\n          this.emit(\"onlatency\", Date.now() - this.startAnswering);\n          this.print('latency: ' + (Date.now() - this.startAnswering));\n          this.startAnswering = 0;\n          this.switchState(AgentState.ANSWER);\n        }\n        if (!this.config.isBenchmark) {\n          const audio = new Uint8Array(event.data);\n          this.audioService?.play(audio);\n          this.emit(\"onaudio\", audio);\n        }\n      } else {\n        const message: IMessage = JSON.parse(event.data);\n        if (message.method === \"onready\") {\n          this.onready(message.payload);\n          return;\n        }\n        if (!this.handle(message)) {\n          this.emit(message.method as keyof ClientEvents, message.data as any, message.payload);\n        }\n        this.print(`received ${message.method}`);\n      }\n    };\n    this.ws.onclose = (event: CloseEvent) => {\n      this.stop();\n      this.emit(\"onclose\", event);\n      this.print('websocket disconnected');\n      this.switchState(AgentState.IDLE);\n    };\n    this.ws.onerror = (event: Event) => {\n      this.stop();\n      this.emit(\"onerror\", event);\n      this.print('websocket error: ' + event);\n    };\n  }\n\n  public send(data: Uint8Array | string) {\n    if (this.ws?.readyState === 1) {\n      this.ws.send(data);\n    }\n  }\n\n  private handle(message: IMessage) {\n    switch(message.method) {\n      case \"start_answering\":\n        this.startAnswering = Date.now();\n        this.switchState(AgentState.PREPARE_ANSWER);\n        return true;\n      case \"clear\":\n        this.audioService?.reset();\n        this.switchState(AgentState.IDLE);\n        return true;\n      case \"pause\":\n        this.audioService?.setpause(true);\n        this.switchState(AgentState.PAUSE);\n        return true;\n      case \"unpause\":\n        this.audioService?.setpause(false);\n        this.switchState(AgentState.ANSWER);\n        return true;\n      case \"pong\":\n        this.print(\"Ping rtt \" + (Date.now() - Number(message.data)))\n        return true;\n    }\n    return false;\n  }\n\n  private onready(payload?: object) {\n    // if (this.config.isTest) {\n    //   this.latencyEstimator = new LatencyEstimator(this);\n    //   this.latencyEstimator.start();\n    // }\n    this.readyPayload = payload;\n    this.switchState(AgentState.IDLE);\n    this.switchConnectionState(State.GOT_READY_EVENT);\n  }\n\n  public async start(payload: IStartPayload | AgentConfig | string, metadata?: object, includeMetadataInPrompt?: boolean) {\n    this.print('starting conversation');\n    this.audioService = new AudioService(this.config);\n    this.audioService.on(\"data\", (audio: Uint8Array) => {\n      // if (this.config.isTest && this.latencyEstimator?.isTesting()) {\n      //   return;\n      // }\n      if (this.muted) {\n        audio.fill(0);\n      } else {\n        this.print('sending audio data');\n      }\n      this.send(audio);\n      this.count++;\n      if (this.count % 1000 == 0) {\n        this.print('sending ping');\n        this.send(JSON.stringify({\"method\": \"ping\", \"data\": Date.now().toString()}));\n      }\n      this.switchConnectionState(State.GOT_FIRST_AUDIO);\n    });\n    this.audioService.on(\"analyzer\", (analyzer) => {\n      this.emit(\"analyzer\", analyzer);\n    });\n    this.audioService.on(\"useraudioready\", (analyzer) => {\n      this.print('user audio ready');\n      this.emit(\"useraudioready\", analyzer);\n    });\n    this.audioService.on(\"playback_finished\", () => {\n      if (this.agentState === AgentState.ANSWER) {\n        this.switchState(AgentState.IDLE);\n      }\n    })\n\n    this.print('starting audio service');\n    await this.audioService.start();\n    this.print('audio service started');\n    let finalPayload: IStartPayload;\n    if (typeof payload === \"object\" && ('agent' in payload || 'call_id' in payload)) {\n      finalPayload = payload as IStartPayload;\n    } else {\n      finalPayload = {agent: typeof payload === \"string\" ? {agent_id: payload} : {agent_config: payload as AgentConfig}};\n      if (metadata) {\n        finalPayload.metadata = metadata;\n      }\n      if (includeMetadataInPrompt) {\n        finalPayload.include_metadata_in_prompt = includeMetadataInPrompt;\n      }\n    }\n    this.connect(finalPayload);\n  }\n\n  public async stop() {\n    if (this.audioService) {\n      this.print('stopping audio service');\n      this.audioService.stop();\n      this.audioService = null;\n      this.print('audio service stopped');\n    }\n    this.ws?.close();\n    this.reset();\n  }\n\n  public mute() {\n    this.muted = true;\n  }\n\n  public unmute() {\n    this.muted = false;\n  }\n\n  private switchState(state: AgentState) {\n    this.agentState = state;\n    this.emit(\"onagentstate\", state);\n  }\n\n  private switchConnectionState(newState: State) {\n    if (this.state === State.IDLE) {\n      this.state = newState;\n    } else if ((this.state === State.GOT_FIRST_AUDIO && newState === State.GOT_READY_EVENT)\n      || (this.state === State.GOT_READY_EVENT && newState === State.GOT_FIRST_AUDIO)) {\n      this.state = State.READY;\n      this.emit(\"onready\", this.readyPayload);\n    }\n  }\n}\n","import EventEmitter from \"eventemitter3\";\nimport { createMicrophoneAudioTrack } from \"../client\";\nimport { workletCode } from \"./worker/AudioWorklet\";\nimport { create, ConverterType } from '@alexanderolsen/libsamplerate-js';\nimport { Config } from \"../client/types\";\n\nconst SAMPLE_RATE = 16000;\n\nexport class AudioService extends EventEmitter {\n  private config: Config;\n  private audioContext: AudioContext | null = null;\n  private stream: MediaStream | null = null;\n\n  // Chrome\n  private audioNode: AudioWorkletNode | null = null;\n\n  // Others\n  private captureNode: ScriptProcessorNode | null = null;\n  private audioData: Float32Array[] = [];\n  private audioDataIndex: number = 0;\n  private pause: boolean = false;\n  private inputResampler: any | null;\n  private outputResampler: any | null;\n  private needResample: boolean = false;\n  private resamplerCreated: boolean = false;\n\n  constructor(config: Config) {\n    super();\n    this.config = config;\n  }\n\n  private print(message: string) {\n    if (this.config.debug) {\n      console.log(\"[millis audio service]\", message);\n    }\n  }\n\n  public async start() {\n    const sampleRate = SAMPLE_RATE;\n    if (this.isFirefox()) {\n      // TODO assume firefox doesn't use audioworklet\n      this.audioContext = new AudioContext({ latencyHint: \"interactive\" });\n      this.needResample = true;\n    } else {\n      this.needResample = false;\n      this.audioContext = new AudioContext({ latencyHint: \"interactive\", sampleRate: sampleRate });\n    }\n    this.print(\"starting audio service, firefox: \" + this.isFirefox() + \", need resample: \" + this.needResample);\n\n    try {\n      this.print(\"requesting microphone permission\");\n      this.stream = await createMicrophoneAudioTrack(sampleRate, this.config);\n      this.print(\"microphone permission granted\");\n    } catch (error) {\n      this.print(\"microphone permission denied\");\n      throw new Error(\"User didn't give microphone permission\");\n    }\n\n    this.print(\"starting audio capture and playback processor, worklet: \" + this.isAudioWorkletSupported());\n    if (this.isAudioWorkletSupported()) {\n      this.print(\"Starting audio worklet\");\n      this.audioContext.resume();\n      const blob = new Blob([workletCode], { type: \"application/javascript\" });\n      const blobURL = URL.createObjectURL(blob);\n      await this.audioContext.audioWorklet.addModule(blobURL);\n      this.print(\"Audio worklet loaded\");\n      this.audioNode = new AudioWorkletNode(\n        this.audioContext,\n        \"capture-and-playback-processor\",\n      );\n      this.print(\"Audio worklet setup\");\n\n      this.audioNode.port.onmessage = (e) => {\n        if (e.data instanceof Uint8Array) {\n          this.emit(\"data\", e.data);\n        } else if (e.data === \"playback_finished\") {\n          this.onPlaybackFinished();\n        }\n      };\n\n      const source = this.audioContext.createMediaStreamSource(this.stream);\n      source.connect(this.audioNode);\n      this.audioNode.connect(this.audioContext.destination);\n      const userAnalyser = this.audioContext.createAnalyser();\n      source.connect(userAnalyser);\n      this.emit(\"useraudioready\", {\n        analyser: userAnalyser,\n        stream: this.stream\n      });\n\n      const analyser = this.audioContext.createAnalyser();\n      this.audioNode.connect(analyser);\n      analyser.connect(this.audioContext.destination);\n      this.emit(\"analyzer\", analyser);\n    } else {\n      this.print(\"Starting audio capture node\");\n      const source = this.audioContext.createMediaStreamSource(this.stream);\n      this.captureNode = this.audioContext.createScriptProcessor(2048, 1, 1);\n      this.captureNode.onaudioprocess = (audioProcessingEvent: AudioProcessingEvent) => {\n\n        if (this.captureNode && this.audioContext) {\n          // Resample inputData\n          if (this.needResample && !this.resamplerCreated) {\n            let converterType = ConverterType.SRC_SINC_FASTEST;\n            let nChannels = 1;\n            this.resamplerCreated = true;\n            create(nChannels, this.audioContext.sampleRate, sampleRate, {\n              converterType: converterType, // default SRC_SINC_FASTEST. see API for more\n            }).then((src: any) => {\n              this.inputResampler = src;\n            });\n            create(nChannels, sampleRate, this.audioContext.sampleRate, {\n              converterType: converterType, // default SRC_SINC_FASTEST. see API for more\n            }).then((src: any) => {\n              this.outputResampler = src;\n            });\n          }\n          var inputData = audioProcessingEvent.inputBuffer.getChannelData(0);\n          var resampledAudio = null;\n          if (this.inputResampler != null) {\n            resampledAudio = this.inputResampler.full(inputData);\n          } else {\n            resampledAudio = inputData;\n          }\n          const pcmData = convertFloat32ToUint8(resampledAudio);\n          this.emit(\"data\", pcmData);\n\n          // Playback here\n          const outputBuffer = audioProcessingEvent.outputBuffer;\n          const outputChannel = outputBuffer.getChannelData(0);\n          for (let i = 0; i < outputChannel.length; ++i) {\n            if (this.audioData.length > 0 && !this.pause) {\n              outputChannel[i] = this.audioData[0][this.audioDataIndex++];\n              if (this.audioDataIndex === this.audioData[0].length) {\n                this.audioData.shift();\n                this.audioDataIndex = 0;\n                if (this.audioData.length == 0) {\n                  this.onPlaybackFinished();\n                }\n              }\n            } else {\n              outputChannel[i] = 0;\n            }\n          }\n        }\n      };\n      source.connect(this.captureNode);\n      this.captureNode.connect(this.audioContext.destination);\n      this.print(\"Audio capture node setup\");\n      const userAnalyser = this.audioContext.createAnalyser();\n      source.connect(userAnalyser);\n      this.emit(\"useraudioready\", {\n        analyser: userAnalyser,\n        stream: this.stream\n      });\n      const analyser = this.audioContext.createAnalyser();\n      this.captureNode.connect(analyser);\n      analyser.connect(this.audioContext.destination);\n      this.emit(\"analyzer\", analyser);\n    }\n  }\n\n  public async stop() {\n    this.audioContext?.suspend();\n    this.audioContext?.close();\n\n    if (this.isAudioWorkletSupported()) {\n      this.audioNode?.disconnect();\n      this.audioNode = null;\n    } else {\n      if (this.captureNode) {\n        this.captureNode.disconnect();\n        this.captureNode.onaudioprocess = null;\n        this.captureNode = null;\n        this.audioData = [];\n        this.audioDataIndex = 0;\n      }\n    }\n    this.stream?.getTracks().forEach((track) => track.stop());\n    this.audioContext = null;\n    this.stream = null;\n  }\n\n  public play(audio: Uint8Array) {\n    if (this.isAudioWorkletSupported()) {\n      this.audioNode?.port.postMessage(audio);\n    } else {\n      const float32Data = convertUint8ToFloat32(audio);\n      var resampledAudio = null;\n      if (this.outputResampler != null) {\n        // Resample output samples\n        resampledAudio = this.outputResampler.full(float32Data);\n      } else {\n        resampledAudio = float32Data;\n      }\n      this.audioData.push(resampledAudio);\n    }\n  }\n\n  public setpause(pause: boolean) {\n    if (this.isAudioWorkletSupported()) {\n      this.audioNode?.port.postMessage(pause ? \"pause\" : \"unpause\");\n    } else {\n      this.pause = pause;\n    }\n  }\n\n  public reset() {\n    if (this.isAudioWorkletSupported()) {\n      this.audioNode?.port.postMessage(\"clear\");\n    } else {\n      this.audioData = [];\n      this.audioDataIndex = 0;\n    }\n  }\n\n  private onPlaybackFinished() {\n    this.emit(\"playback_finished\");\n  }\n\n  private isAudioWorkletSupported(): boolean {\n    return /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor);\n  }\n  private isFirefox(): boolean {\n    return /Firefox/.test(navigator.userAgent);\n  }\n}\n\nexport function convertUint8ToFloat32(array: Uint8Array): Float32Array {\n  const targetArray = new Float32Array(array.byteLength / 2);\n\n  // A DataView is used to read our 16-bit little-endian samples out of the Uint8Array buffer\n  const sourceDataView = new DataView(array.buffer);\n\n  // Loop through, get values, and divide by 32,768\n  for (let i = 0; i < targetArray.length; i++) {\n    targetArray[i] = sourceDataView.getInt16(i * 2, true) / Math.pow(2, 16 - 1);\n  }\n  return targetArray;\n}\n\nexport function convertFloat32ToUint8(array: Float32Array): Uint8Array {\n  const buffer = new ArrayBuffer(array.length * 2);\n  const view = new DataView(buffer);\n\n  for (let i = 0; i < array.length; i++) {\n    const value = (array[i] as number) * 32768;\n    view.setInt16(i * 2, value, true); // true for little-endian\n  }\n\n  return new Uint8Array(buffer);\n}","export const workletCode = `\nclass captureAndPlaybackProcessor extends AudioWorkletProcessor {\n    audioData = [];\n    index = 0;\n    pause = false;\n\n    constructor() {\n      super();\n      //set listener to receive audio data, data is float32 array.\n      this.port.onmessage = (e) => {\n        if (e.data === \"clear\") {\n          // Clear all buffer.\n          this.audioData = [];\n          this.index = 0;\n        } else if (e.data === \"pause\") {\n          this.pause = true;\n        } else if (e.data === \"unpause\") {\n          this.pause = false;\n        } else if (e.data.length > 0) {\n          this.audioData.push(this.convertUint8ToFloat32(e.data));\n        }\n      };\n    }\n\n    convertUint8ToFloat32(array) {\n      const targetArray = new Float32Array(array.byteLength / 2);\n\n      // A DataView is used to read our 16-bit little-endian samples out of the Uint8Array buffer\n      const sourceDataView = new DataView(array.buffer);\n\n      // Loop through, get values, and divide by 32,768\n      for (let i = 0; i < targetArray.length; i++) {\n        targetArray[i] = sourceDataView.getInt16(i * 2, true) / Math.pow(2, 16 - 1);\n      }\n      return targetArray;\n    }\n\n    convertFloat32ToUint8(array) {\n      const buffer = new ArrayBuffer(array.length * 2);\n      const view = new DataView(buffer);\n\n      for (let i = 0; i < array.length; i++) {\n        const value = array[i] * 32768;\n        view.setInt16(i * 2, value, true); // true for little-endian\n      }\n\n      return new Uint8Array(buffer);\n    }\n\n    process(inputs, outputs, parameters) {\n      // Capture\n      const input = inputs[0];\n      const inputChannel1 = input[0];\n      const inputChannel2 = input[1];\n      this.port.postMessage(this.convertFloat32ToUint8(inputChannel1));\n\n      // Playback\n      const output = outputs[0];\n      const outputChannel1 = output[0];\n      const outputChannel2 = output[1];\n      // start playback.\n      for (let i = 0; i < outputChannel1.length; ++i) {\n        if (this.audioData.length > 0 && !this.pause) {\n          outputChannel1[i] = this.audioData[0][this.index];\n          outputChannel2[i] = this.audioData[0][this.index];\n          this.index++;\n          if (this.index == this.audioData[0].length) {\n            this.audioData.shift();\n            this.index = 0;\n            if (this.audioData.length == 0) {\n              this.port.postMessage(\"playback_finished\");\n            }\n          }\n        } else {\n          outputChannel1[i] = 0;\n          outputChannel2[i] = 0;\n        }\n      }\n\n      return true;\n    }\n  }\n\n  registerProcessor(\n    \"capture-and-playback-processor\",\n    captureAndPlaybackProcessor,\n  );\n`;","import { IStartPayload } from \"./client\";\n\nexport interface Config {\n  publicKey: string;\n  endPoint?: string;\n  debug?: boolean;\n  audioSource?: {\n    deviceId?: string;\n    constraints?: MediaTrackConstraints;\n  };\n\n  [key: string]: any;\n}\n\nexport type VoiceProvider = 'elevenlabs' | 'rime' | 'openai' | 'cartesia' | 'playht' | 'neets' | 'deepgram' | 'dubverse';\n\ninterface Tool { // Main structure for defining a function.\n  name: string;           // Function name, formatted as a valid identifier (no spaces, begins with a letter)\n  description: string;    // Detailed description to help the agent understand when to use the function\n  webhook: string;        // The URL of the webhook to which the request will be sent\n  header: object;         // Any necessary headers for the webhook request. Ex: {\"Content-Type\": \"application/json\"}\n  params: Param[];        // Array of `Param` objects, defining the parameters needed by the function\n}\n\ninterface Param {\n  name: string;           // Valid parameter name, no spaces, starts with a letter, can use underscores or camelCase\n  type: \"string\" | \"number\" | \"boolean\";        // The data type of the parameter (e.g., string, number, boolean)\n  description: string;    // Detailed description of the parameter\n  required: boolean;      // Whether this parameter is mandatory\n}\n\nexport interface Voice {\n  provider: VoiceProvider;\n  voice_id: string;\n}\n\ninterface AgentSetting {\n  first_message?: string;\n  vad_threshold?: number;\n  privacy_settings?: {\n    opt_out_data_collection: boolean;\n  };\n  session_timeout?: {\n    max_duration: number;\n    max_idle: number;\n    message?: string;\n  },\n  custom_vocabulary?: {\n    keywords?: object;\n  };\n  flow?: {\n    user_start_first?: boolean;\n    interruption?: {\n      allowed: boolean;\n      keep_interruption_message: boolean;\n    };\n    response_delay?: number;\n  }\n}\n\ninterface WebhookSetting {\n  session_data_webhook?: string;\n  extra_prompt_webhook?: string;\n}\n\ntype AllSettings = AgentSetting & WebhookSetting;\n\nexport interface AgentConfig extends AllSettings {\n  prompt?: string;\n  voice?: Voice;\n  tools?: Tool[];\n  language?: string;\n  custom_llm_websocket?: string;\n  llm?: {model: string};\n  [key: string]: any;\n}\n\nexport interface ClientEvents {\n  'onopen': () => void;\n  'onready': (payload?: { session_id?: string }) => void;\n  'onsessionended': () => void;\n  'onaudio': (audio: Uint8Array) => void;\n  'onresponsetext': (text: string, payload: { is_final?: boolean }) => void;\n  'ontranscript': (text: string, payload: { is_final?: boolean }) => void;\n  'analyzer': (analyzer: AnalyserNode) => void;\n  'useraudioready': (data: { analyser: AnalyserNode, stream: MediaStream }) => void;\n  'onlatency': (latency: number) => void;\n  'onclose': (event: CloseEvent) => void;\n  'onerror': (error: Event) => void;\n  'onagentstate': (state: AgentState) => void;\n  'ai_action': (action: any) => void;\n  [key: string]: any;\n}\n\nexport interface ClientInterface {\n  start(payload: IStartPayload | AgentConfig | string, metadata?: object, includeMetadataInPrompt?: boolean): Promise<void>;\n  stop(): Promise<void>;\n  mute(): void;\n  unmute(): void;\n}\n\nexport enum AgentState {\n  IDLE = \"idle\",\n  PREPARE_ANSWER = \"prepare_answer\",\n  ANSWER = \"answer\",\n  PAUSE = \"pause\",\n}","import * as Millis from \"./client\";\nexport * from \"./client/types\";\n\nexport default Millis;\n"],"mappings":"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","names":["client_exports","__export","createClient","createMicrophoneAudioTrack","EventEmitter","EventEmitter","workletCode","create","ConverterType","SAMPLE_RATE","AudioService","EventEmitter","config","message","__async","sampleRate","createMicrophoneAudioTrack","error","blob","workletCode","blobURL","e","source","userAnalyser","analyser","audioProcessingEvent","converterType","ConverterType","nChannels","create","src","inputData","resampledAudio","pcmData","convertFloat32ToUint8","outputChannel","i","_a","_b","_c","_d","track","audio","float32Data","convertUint8ToFloat32","pause","array","targetArray","sourceDataView","buffer","view","value","AgentState","HOST","Client","EventEmitter","config","defaultConfig","__spreadValues","message","payload","HOST","event","_a","audio","data","_b","_c","metadata","includeMetadataInPrompt","__async","AudioService","analyzer","finalPayload","state","newState","createClient","config","Client","createMicrophoneAudioTrack","sampleRate","__async","_a","_b","audioConstraints","__spreadValues","src_default","client_exports"]}