{"version":3,"sources":["../src/index.ts","../src/calls.ts","../src/caller-id.ts"],"sourcesContent":["export { MyChatBotCalls } from \"./calls\";\nexport { defaultCallerId } from \"./caller-id\";\nexport type {\n  CallsConfig,\n  ConnectionType,\n  StartOptions,\n  CallStatus,\n  CallEvent,\n  CallEventPayload,\n  CallEventCallback,\n  ClientToolParameter,\n  ClientToolDefinition,\n  ClientTools,\n  CallOverrides,\n  Language,\n} from \"./types\";\n","import { Conversation } from \"@elevenlabs/client\";\nimport { defaultCallerId } from \"./caller-id\";\nimport type {\n  CallsConfig,\n  StartOptions,\n  CallStatus,\n  CallEvent,\n  CallEventCallback,\n  CallEventPayload,\n  ClientTools,\n} from \"./types\";\n\n/**\n * Normalize anything thrown into the shape of the 'error' event payload.\n * The underlying ElevenLabs client may reject with non-Error values — most\n * notably a raw CloseEvent when the WebSocket fails (offline, server\n * unreachable, etc.) — which would otherwise have no .message or .name and\n * collapse to a useless generic string. Surface code/reason/type instead.\n */\nfunction normalizeError(\n  err: unknown,\n  fallbackMessage: string\n): { message: string; name?: string; cause: unknown } {\n  if (err instanceof Error) {\n    return {\n      message: err.message || fallbackMessage,\n      name: err.name,\n      cause: err,\n    };\n  }\n  if (typeof CloseEvent !== \"undefined\" && err instanceof CloseEvent) {\n    const reason = err.reason ? `, ${err.reason}` : \"\";\n    return {\n      message: `WebSocket closed (code ${err.code}${reason})`,\n      name: \"CloseEvent\",\n      cause: err,\n    };\n  }\n  if (typeof Event !== \"undefined\" && err instanceof Event) {\n    return {\n      message: `${err.type} event`,\n      name: err.constructor?.name || \"Event\",\n      cause: err,\n    };\n  }\n  if (typeof err === \"string\") {\n    return { message: err || fallbackMessage, cause: err };\n  }\n  if (err && typeof err === \"object\") {\n    const anyErr = err as { message?: unknown; name?: unknown };\n    const message =\n      typeof anyErr.message === \"string\" && anyErr.message\n        ? anyErr.message\n        : fallbackMessage;\n    const name = typeof anyErr.name === \"string\" ? anyErr.name : undefined;\n    return { message, name, cause: err };\n  }\n  return { message: fallbackMessage, cause: err };\n}\n\nexport class MyChatBotCalls {\n  private config: CallsConfig;\n  private conversation: Conversation | null = null;\n  private currentStatus: CallStatus = \"idle\";\n  private micMuted = false;\n  private currentlySpeaking = false;\n  private listeners: Map<CallEvent, Set<CallEventCallback<any>>> = new Map();\n\n  constructor(config: CallsConfig) {\n    if (!config.agentId) {\n      throw new Error(\"[@mychatbot/client] agentId is required\");\n    }\n    this.config = config;\n  }\n\n  get status(): CallStatus {\n    return this.currentStatus;\n  }\n\n  get muted(): boolean {\n    return this.micMuted;\n  }\n\n  get isSpeaking(): boolean {\n    return this.currentlySpeaking;\n  }\n\n  private emit<E extends CallEvent>(\n    event: E,\n    payload: CallEventPayload[E]\n  ): void {\n    const cbs = this.listeners.get(event);\n    if (cbs) {\n      cbs.forEach((cb) => {\n        try {\n          cb(payload);\n        } catch (e) {\n          console.error(`[@mychatbot/client] Error in ${event} listener:`, e);\n        }\n      });\n    }\n  }\n\n  private setStatus(s: CallStatus): void {\n    this.currentStatus = s;\n    this.emit(\"statusChange\", { status: s });\n  }\n\n  async start(opts?: StartOptions): Promise<void> {\n    const callerId = opts?.callerId || defaultCallerId();\n\n    if (\n      this.currentStatus === \"connected\" ||\n      this.currentStatus === \"connecting\"\n    ) {\n      console.warn(\"[@mychatbot/client] Already in a call\");\n      return;\n    }\n\n    this.setStatus(\"connecting\");\n\n    try {\n      await navigator.mediaDevices.getUserMedia({ audio: true });\n    } catch (err: unknown) {\n      this.setStatus(\"idle\");\n      this.emit(\"error\", normalizeError(err, \"Microphone access denied\"));\n      return;\n    }\n\n    // Build client tool definitions for API registration (strip handlers).\n    const clientTools = opts?.clientTools;\n    let clientToolDefs: any[] | undefined;\n    if (clientTools && Object.keys(clientTools).length > 0) {\n      clientToolDefs = Object.entries(clientTools).map(([name, tool]) => ({\n        name,\n        ...tool.definition,\n      }));\n    }\n\n    // Pre-register the session so chat/client records exist for MCP tools.\n    // Also sends client tool definitions for auto-sync.\n    // The response includes client_context which we inject as a dynamic variable\n    // since the initiation webhook is not fired for WebSDK calls.\n    let serverDynVars: Record<string, string> = {};\n    try {\n      const apiUrl = this.config.apiUrl || \"https://api.mychatbot.app\";\n      const body: Record<string, any> = {\n        agent_id: this.config.agentId,\n        caller_id: callerId,\n      };\n      if (clientToolDefs) {\n        body.client_tools = clientToolDefs;\n      }\n      const res = await fetch(`${apiUrl}/calls/register-session`, {\n        method: \"POST\",\n        headers: { \"Content-Type\": \"application/json\" },\n        body: JSON.stringify(body),\n      });\n      if (res.ok) {\n        const data = await res.json();\n        if (data.client_context) {\n          serverDynVars.client_context = data.client_context;\n        }\n      }\n    } catch (e) {\n      console.warn(\"[@mychatbot/client] Failed to register session:\", e);\n      // Non-fatal: the call can still proceed, MCP tools may not work on first call\n    }\n\n    // Build clientTools handler map from our ClientTools definitions.\n    const elClientTools: Record<string, (params: any) => Promise<any> | any> =\n      {};\n    if (clientTools) {\n      for (const [name, tool] of Object.entries(clientTools)) {\n        elClientTools[name] = tool.handler;\n      }\n    }\n\n    try {\n      this.conversation = await Conversation.startSession({\n        agentId: this.config.agentId,\n        connectionType: this.config.connectionType || \"websocket\",\n        userId: callerId,\n        dynamicVariables: {\n          user_id: callerId,\n          ...serverDynVars,\n          ...opts?.dynamicVariables,\n        },\n        ...(Object.keys(elClientTools).length > 0 && {\n          clientTools: elClientTools,\n        }),\n        ...(opts?.overrides && { overrides: opts.overrides }),\n        onConnect: (props: { conversationId: string }) => {\n          this.setStatus(\"connected\");\n          this.emit(\"connect\", props);\n        },\n        onDisconnect: (details: any) => {\n          this.setStatus(\"idle\");\n          this.currentlySpeaking = false;\n          this.conversation = null;\n          this.emit(\"disconnect\", {\n            reason: details?.reason || \"unknown\",\n          });\n        },\n        onError: (message: string) => {\n          this.emit(\"error\", { message });\n        },\n        onModeChange: (props: { mode: \"speaking\" | \"listening\" }) => {\n          this.currentlySpeaking = props.mode === \"speaking\";\n          this.emit(\"modeChange\", props);\n        },\n        onMessage: (props: { message: string; source: string }) => {\n          this.emit(\"message\", {\n            message: props.message,\n            role: props.source as \"user\" | \"agent\",\n          });\n        },\n      });\n    } catch (err: unknown) {\n      this.setStatus(\"idle\");\n      this.conversation = null;\n      this.emit(\"error\", normalizeError(err, \"Failed to start call\"));\n    }\n  }\n\n  async stop(): Promise<void> {\n    if (!this.conversation) return;\n    this.setStatus(\"disconnecting\");\n    try {\n      await this.conversation.endSession();\n    } catch {\n      // endSession may throw if already disconnected\n    }\n    this.conversation = null;\n    this.currentlySpeaking = false;\n    this.setStatus(\"idle\");\n  }\n\n  toggleMute(): void {\n    if (!this.conversation) return;\n    this.micMuted = !this.micMuted;\n    this.conversation.setMicMuted(this.micMuted);\n  }\n\n  /** Raw output (agent) audio frequency data for visualization. */\n  getOutputByteFrequencyData(): Uint8Array | undefined {\n    return this.conversation?.getOutputByteFrequencyData();\n  }\n\n  /** Raw input (user mic) audio frequency data for visualization. */\n  getInputByteFrequencyData(): Uint8Array | undefined {\n    return this.conversation?.getInputByteFrequencyData();\n  }\n\n  on<E extends CallEvent>(event: E, callback: CallEventCallback<E>): void {\n    if (!this.listeners.has(event)) {\n      this.listeners.set(event, new Set());\n    }\n    this.listeners.get(event)!.add(callback);\n  }\n\n  off<E extends CallEvent>(event: E, callback: CallEventCallback<E>): void {\n    this.listeners.get(event)?.delete(callback);\n  }\n}\n","const STORAGE_KEY = \"mcb_caller_id\";\n\n/**\n * Returns a persistent caller ID from localStorage.\n * Generates and stores a new one if none exists.\n * Falls back to a random ID if localStorage is unavailable.\n */\nexport function defaultCallerId(): string {\n  try {\n    let id = localStorage.getItem(STORAGE_KEY);\n    if (!id) {\n      id =\n        \"mcb_\" +\n        Date.now().toString(36) +\n        \"_\" +\n        Math.random().toString(36).substring(2, 11);\n      localStorage.setItem(STORAGE_KEY, id);\n    }\n    return id;\n  } catch {\n    return (\n      \"mcb_\" +\n      Date.now().toString(36) +\n      \"_\" +\n      Math.random().toString(36).substring(2, 11)\n    );\n  }\n}\n"],"mappings":"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","names":[]}