@aihumanity/voice-sdk 0.1.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.
- package/LICENSE +21 -0
- package/README.md +486 -0
- package/dist/VoiceCall-_BBARIQT.d.ts +276 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +485 -0
- package/dist/index.js.map +1 -0
- package/dist/react.d.ts +60 -0
- package/dist/react.js +572 -0
- package/dist/react.js.map +1 -0
- package/dist/widget.d.ts +68 -0
- package/dist/widget.js +781 -0
- package/dist/widget.js.map +1 -0
- package/package.json +87 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/client.ts","../src/emitter.ts","../src/types.ts","../src/VoiceCall.ts","../src/widget.ts"],"names":["url","res","CallStatus"],"mappings":"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","file":"widget.js","sourcesContent":["import type { JoinUrlResponse, VoiceCallOptions } from \"./types.js\";\n\n/**\n * POSTs to the join-url endpoint and returns the parsed response.\n *\n * Auth resolution order:\n * 1. `fetchJoinUrl` — fully custom fetcher, takes precedence over everything.\n * 2. `publicKey` — browser-direct auth via `X-Public-Key` header + browser Origin.\n * Hits `/v1/voice/joinurl` (the new SDK-aware endpoint).\n * 3. `authToken` — Bearer JWT, used with the legacy `/ultravox/secure/joinurl` endpoint\n * (or a custom `joinUrlPath`). Suitable for server-side / Netlify fn use.\n *\n * Throws on non-2xx or missing joinUrl.\n */\nexport async function fetchJoinUrl(\n opts: VoiceCallOptions,\n): Promise<JoinUrlResponse> {\n if (opts.fetchJoinUrl) {\n return opts.fetchJoinUrl();\n }\n\n if (!opts.apiUrl) {\n throw new Error(\"[aihumanity/voice-sdk] apiUrl is required when fetchJoinUrl is not provided.\");\n }\n\n const baseUrl = opts.apiUrl.replace(/\\/+$/, \"\");\n\n const body: Record<string, unknown> = {\n username: opts.username,\n agentName: opts.agentName,\n ...(opts.extraJoinUrlBody ?? {}),\n };\n\n if (opts.dataConnection) {\n body.dataConnection = {\n websocketUrl: opts.dataConnection.websocketUrl,\n audioConfig: {\n sampleRate: opts.dataConnection.audioConfig?.sampleRate ?? 16000,\n channelMode:\n opts.dataConnection.audioConfig?.channelMode ??\n \"CHANNEL_MODE_SEPARATED\",\n },\n // Spread user-supplied flags first, then apply defaults for the two\n // most common flags so they're always present if not explicitly set.\n dataMessages: {\n ...(opts.dataConnection.dataMessages ?? {}),\n userStartedSpeaking:\n opts.dataConnection.dataMessages?.userStartedSpeaking ?? true,\n userStoppedSpeaking:\n opts.dataConnection.dataMessages?.userStoppedSpeaking ?? true,\n },\n };\n }\n\n // ── Public key (browser-direct, no backend) ──────────────────────────────\n if (opts.publicKey) {\n const url = baseUrl + (opts.joinUrlPath ?? \"/v1/voice/joinurl\");\n const res = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-Public-Key\": opts.publicKey,\n },\n body: JSON.stringify(body),\n });\n return parseJoinUrlResponse(res);\n }\n\n // ── Bearer token (server-side / Netlify fn) ───────────────────────────────\n const token =\n typeof opts.authToken === \"function\"\n ? await opts.authToken()\n : opts.authToken;\n\n if (!token) {\n throw new Error(\n \"[aihumanity/voice-sdk] Provide publicKey (for browser-direct) or authToken (for server-side).\",\n );\n }\n\n const path = opts.joinUrlPath ?? \"/ultravox/secure/joinurl\";\n const url = baseUrl + path;\n\n const res = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify(body),\n });\n\n return parseJoinUrlResponse(res);\n}\n\nasync function parseJoinUrlResponse(res: Response): Promise<JoinUrlResponse> {\n const text = await res.text();\n if (!res.ok) {\n throw new Error(\n `[aihumanity/voice-sdk] joinUrl request failed (${res.status}): ${text}`,\n );\n }\n\n let parsed: JoinUrlResponse;\n try {\n parsed = JSON.parse(text);\n } catch {\n throw new Error(\n `[aihumanity/voice-sdk] joinUrl response was not valid JSON: ${text}`,\n );\n }\n\n if (!parsed.joinUrl) {\n throw new Error(\n \"[aihumanity/voice-sdk] joinUrl response did not include `joinUrl`.\",\n );\n }\n return parsed;\n}\n","import type { VoiceCallEvents, VoiceCallListener } from \"./types.js\";\n\n/**\n * Tiny strongly-typed event emitter. Avoids dragging in `eventemitter3` etc.\n * Every method returns the emitter, except `on` which returns an unsubscribe\n * function for ergonomic React effect cleanup.\n */\nexport class TypedEmitter {\n private readonly listeners = new Map<\n keyof VoiceCallEvents,\n Set<(payload: unknown) => void>\n >();\n\n on<K extends keyof VoiceCallEvents>(\n event: K,\n listener: VoiceCallListener<K>,\n ): () => void {\n let set = this.listeners.get(event);\n if (!set) {\n set = new Set();\n this.listeners.set(event, set);\n }\n set.add(listener as (payload: unknown) => void);\n return () => this.off(event, listener);\n }\n\n off<K extends keyof VoiceCallEvents>(\n event: K,\n listener: VoiceCallListener<K>,\n ): void {\n this.listeners.get(event)?.delete(listener as (payload: unknown) => void);\n }\n\n once<K extends keyof VoiceCallEvents>(\n event: K,\n listener: VoiceCallListener<K>,\n ): () => void {\n const off = this.on(event, ((payload: VoiceCallEvents[K]) => {\n off();\n listener(payload);\n }) as VoiceCallListener<K>);\n return off;\n }\n\n emit<K extends keyof VoiceCallEvents>(\n event: K,\n payload: VoiceCallEvents[K],\n ): void {\n const set = this.listeners.get(event);\n if (!set) return;\n // Snapshot to allow listeners to off() during emit.\n for (const fn of Array.from(set)) {\n try {\n fn(payload);\n } catch (err) {\n // Don't let one bad listener kill the loop.\n // eslint-disable-next-line no-console\n console.error(\"[aihumanity/voice-sdk] listener error:\", err);\n }\n }\n }\n\n removeAllListeners(): void {\n this.listeners.clear();\n }\n}\n","/**\n * Public types shared across the SDK.\n *\n * Status names are aligned with Ultravox's session-status enum so the SDK is\n * a thin, semantic wrapper.\n */\n\n/** Coarse-grained call lifecycle states the SDK exposes to consumers. */\nexport enum CallStatus {\n /** No active call; ready to start. */\n IDLE = \"idle\",\n /** Backend is being asked for a joinUrl, or WebRTC is connecting. */\n CONNECTING = \"connecting\",\n /** Call is live; agent is ready to listen. */\n CONNECTED = \"connected\",\n /** Microphone is open and capturing user speech. */\n LISTENING = \"listening\",\n /** Agent is processing the user's last utterance. */\n THINKING = \"thinking\",\n /** Agent is speaking. */\n SPEAKING = \"speaking\",\n /** Call is being torn down. */\n DISCONNECTING = \"disconnecting\",\n /** Call ended (terminal — same as IDLE for new calls). */\n DISCONNECTED = \"disconnected\",\n}\n\n/** Speaker role on a transcript line. Mirrors ultravox-client's `Role`. */\nexport enum Speaker {\n USER = \"user\",\n AGENT = \"agent\",\n}\n\nexport interface Transcript {\n /** Spoken text. May grow over time as more partials arrive. */\n text: string;\n /** Whether this is the final, locked-in version of the utterance. */\n isFinal: boolean;\n /** Who spoke. */\n speaker: Speaker;\n /** voice or text. */\n medium: \"voice\" | \"text\";\n /** Sequence number for ordering. */\n ordinal: number;\n}\n\n/**\n * Audio format the data-connection (emotion / analytics) WebSocket expects.\n * Matches the Ultravox `dataConnection.audioConfig` schema.\n */\nexport interface AudioConfig {\n /** PCM sample rate. Default 16000. */\n sampleRate?: number;\n /**\n * \"CHANNEL_MODE_SEPARATED\" sends user/agent as separate channels;\n * \"CHANNEL_MODE_MIXED\" sends a single mixed stream.\n */\n channelMode?: \"CHANNEL_MODE_SEPARATED\" | \"CHANNEL_MODE_MIXED\";\n}\n\n/** Which speech-activity events the data WebSocket should receive. */\nexport interface DataMessageFlags {\n userStartedSpeaking?: boolean;\n userStoppedSpeaking?: boolean;\n agentStartedSpeaking?: boolean;\n agentStoppedSpeaking?: boolean;\n}\n\n/**\n * Optional data-connection block. When provided the eimi backend will open a\n * server-to-server WebSocket so user audio bytes can be analyzed (e.g. for\n * vocal emotion) and the result fed back as a data message.\n */\nexport interface DataConnectionConfig {\n /** wss:// URL the backend should open for raw user audio. */\n websocketUrl: string;\n audioConfig?: AudioConfig;\n dataMessages?: DataMessageFlags;\n}\n\n/** Options for starting a call. */\nexport interface VoiceCallOptions {\n /**\n * Base URL of the eimi backend. Example: \"https://api.eimi.ai\".\n * Required unless `fetchJoinUrl` is provided.\n */\n apiUrl?: string;\n /**\n * Bearer token used to authenticate with eimi backend. Can be a string or a\n * function that resolves one (handy for short-lived JWTs you fetch from\n * your own backend). Required unless `fetchJoinUrl` or `publicKey` is provided.\n */\n authToken?: string | (() => string | Promise<string>);\n /**\n * Publishable API key ID for browser-direct (no-backend) auth.\n *\n * When provided the SDK sends `X-Public-Key: <publicKey>` and relies on the\n * browser's `Origin` header for domain validation on the server. The server\n * checks the origin against the developer's registered `allowedOrigins` list.\n *\n * Use this when you have no server-side proxy. Register your site's origin in\n * the developer portal first. Hits `/v1/voice/joinurl` by default (override\n * with `joinUrlPath`).\n *\n * Unlike `authToken`, this key ID is safe to embed in browser JS — it grants\n * no access outside your registered origins.\n */\n publicKey?: string;\n /** Agent name configured in eimi backend, e.g. \"DavidChiu\". */\n agentName?: string;\n /** Username the call should be billed/attributed to. */\n username?: string;\n /** Optional emotion / analytics WebSocket config. */\n dataConnection?: DataConnectionConfig;\n /**\n * Override the join-url path. Defaults to \"/ultravox/secure/joinurl\".\n * Useful if your deployment routes through a proxy.\n */\n joinUrlPath?: string;\n /**\n * Optional fully custom fetcher. If provided, the SDK calls this function\n * instead of building a request itself. Must resolve to `{ joinUrl, callId? }`.\n * When this is provided, `apiUrl` and `authToken` are not required.\n */\n fetchJoinUrl?: () => Promise<JoinUrlResponse>;\n /** Extra fields forwarded in the join-url request body. */\n extraJoinUrlBody?: Record<string, unknown>;\n /**\n * Pattern used to extract an emotion label out of `experimental_message`\n * data payloads. Default looks for \"[EMOTION_CONTEXT] ... : <label>\".\n * The first capture group becomes the emotion label.\n */\n emotionPattern?: RegExp;\n /**\n * Optional polling callback for emotion data. When provided, the SDK polls\n * this function at `emotionPollIntervalMs` while the call is live.\n * Use this when emotion is injected server-side (not via experimental_message).\n * Receives the `callId` and optional `sessionToken` from the join response.\n * Should return the emotion label string or null.\n */\n pollEmotion?: (callId: string, sessionToken?: string) => Promise<string | null>;\n /**\n * How often (ms) to call `pollEmotion`. Default 15000 (15 s).\n * Ignored if `pollEmotion` is not set.\n */\n emotionPollIntervalMs?: number;\n /** AudioContext to reuse. The SDK will create one if omitted. */\n audioContext?: AudioContext;\n /** Pass-through to ultravox-client. */\n additionalMessages?: Set<string>;\n}\n\n/** Whatever the eimi backend (or your custom fetcher) returns. */\nexport interface JoinUrlResponse {\n joinUrl: string;\n callId?: string;\n /**\n * Short-lived token scoped to this call. Returned by eimi backend when\n * session-based auth is configured. Used by `pollEmotion` for direct\n * browser→backend calls without needing a service token.\n */\n sessionToken?: string;\n /**\n * Server-side summary of whether the data connection / emotion bridge was\n * wired up. Surface mirrors what eimi backend currently returns.\n */\n emotion?: {\n dataConnectionEnabled?: boolean;\n audioEnabled?: boolean;\n emotionBridgeConfigured?: boolean;\n autoSendEnabled?: boolean;\n [k: string]: unknown;\n };\n [k: string]: unknown;\n}\n\n/** Map of event name -> listener payload type for the VoiceCall emitter. */\nexport interface VoiceCallEvents {\n /** Coarse call status changed. Always fires on real transitions. */\n status: CallStatus;\n /** Underlying Ultravox status changed (kept for power users). */\n raw_status: string;\n /** A transcript was added or updated. */\n transcript: Transcript;\n /** Full transcript array snapshot, fired after every transcript update. */\n transcripts: Transcript[];\n /** Vocal emotion label extracted from a data message or poll. */\n emotion: { label: string; raw: unknown };\n /** Any data message from the agent / data connection. */\n data_message: unknown;\n /** Mic mute state changed. */\n mic_muted: boolean;\n /** Speaker mute state changed. */\n speaker_muted: boolean;\n /** Agent has saved/persisted contact info (heuristic on transcript). */\n contact_saved: void;\n /** A non-fatal warning (e.g., emotion bridge not configured). */\n warning: string;\n /** A fatal error during start/operation. */\n error: Error;\n /** Call has fully ended. */\n ended: void;\n}\n\n/** Type of listener for a given VoiceCall event. */\nexport type VoiceCallListener<K extends keyof VoiceCallEvents> = (\n payload: VoiceCallEvents[K],\n) => void;\n","import {\n UltravoxSession,\n UltravoxSessionStatus,\n type Transcript as UvTranscript,\n} from \"ultravox-client\";\n\nimport { fetchJoinUrl } from \"./client.js\";\nimport { TypedEmitter } from \"./emitter.js\";\nimport {\n CallStatus,\n Speaker,\n type JoinUrlResponse,\n type Transcript,\n type VoiceCallEvents,\n type VoiceCallListener,\n type VoiceCallOptions,\n} from \"./types.js\";\n\n/** Default regex used to pick an emotion label out of an `experimental_message`. */\nconst DEFAULT_EMOTION_PATTERN = /\\[EMOTION_CONTEXT\\][^:]*:\\s*(\\w+)/i;\n\n/** Heuristic phrase the agent says when it has saved the user's contact info. */\nconst CONTACT_SAVED_PATTERN =\n /I['']ve (noted|saved|got|recorded) your (contact|info|details|number|email)/i;\n\n/** Live call statuses — polling starts on first entry. */\nconst LIVE_STATUSES = new Set<CallStatus>([\n CallStatus.CONNECTED,\n CallStatus.LISTENING,\n CallStatus.THINKING,\n CallStatus.SPEAKING,\n]);\n\n/**\n * High-level voice call wrapper.\n *\n * ```ts\n * const call = new VoiceCall({ apiUrl, authToken, agentName, username });\n * call.on(\"status\", s => console.log(s));\n * call.on(\"transcript\", t => console.log(t.speaker, t.text));\n * call.on(\"emotion\", e => console.log(\"emotion:\", e.label));\n * await call.start();\n * // ... later\n * await call.end();\n * ```\n */\nexport class VoiceCall {\n private readonly emitter = new TypedEmitter();\n private readonly opts: VoiceCallOptions;\n private session: UltravoxSession | null = null;\n\n private _status: CallStatus = CallStatus.IDLE;\n private _callId: string | null = null;\n private _sessionToken: string | null = null;\n private _transcripts: Transcript[] = [];\n private _lastEmotion: string | null = null;\n private _contactSaved = false;\n private _starting = false;\n private _emotionMeta: JoinUrlResponse[\"emotion\"] | null = null;\n private _pollTimer: ReturnType<typeof setInterval> | null = null;\n\n constructor(opts: VoiceCallOptions) {\n this.opts = opts;\n }\n\n // ── Public read-only state ────────────────────────────────────────────────\n\n get status(): CallStatus {\n return this._status;\n }\n\n get callId(): string | null {\n return this._callId;\n }\n\n get sessionToken(): string | null {\n return this._sessionToken;\n }\n\n get transcripts(): Transcript[] {\n return this._transcripts.slice();\n }\n\n get lastEmotion(): string | null {\n return this._lastEmotion;\n }\n\n get contactSaved(): boolean {\n return this._contactSaved;\n }\n\n get isMicMuted(): boolean {\n return this.session?.isMicMuted ?? false;\n }\n\n get isSpeakerMuted(): boolean {\n return this.session?.isSpeakerMuted ?? false;\n }\n\n /** Server-reported wiring info from the join-url response, if any. */\n get emotionMeta(): JoinUrlResponse[\"emotion\"] | null {\n return this._emotionMeta;\n }\n\n /** Underlying ultravox-client session. Use sparingly — for power users. */\n get rawSession(): UltravoxSession | null {\n return this.session;\n }\n\n // ── Event API ─────────────────────────────────────────────────────────────\n\n on<K extends keyof VoiceCallEvents>(\n event: K,\n listener: VoiceCallListener<K>,\n ): () => void {\n return this.emitter.on(event, listener);\n }\n\n off<K extends keyof VoiceCallEvents>(\n event: K,\n listener: VoiceCallListener<K>,\n ): void {\n this.emitter.off(event, listener);\n }\n\n once<K extends keyof VoiceCallEvents>(\n event: K,\n listener: VoiceCallListener<K>,\n ): () => void {\n return this.emitter.once(event, listener);\n }\n\n // ── Control ───────────────────────────────────────────────────────────────\n\n /**\n * Fetches a joinUrl from the backend, opens an Ultravox session, and starts\n * the call. Resolves once `joinCall` has been kicked off (the call goes\n * \"live\" asynchronously via status events).\n */\n async start(): Promise<void> {\n if (this._starting) return;\n if (this._status !== CallStatus.IDLE && this._status !== CallStatus.DISCONNECTED) {\n return;\n }\n\n this._starting = true;\n this.resetMutableState();\n this.setStatus(CallStatus.CONNECTING);\n\n try {\n const payload = await fetchJoinUrl(this.opts);\n this._callId = payload.callId ?? null;\n this._sessionToken = payload.sessionToken ?? null;\n this._emotionMeta = payload.emotion ?? null;\n this.surfaceEmotionWarnings(payload);\n\n const session = new UltravoxSession({\n audioContext: this.opts.audioContext,\n additionalMessages: this.opts.additionalMessages,\n });\n this.session = session;\n this.attachSessionListeners(session);\n\n session.joinCall(payload.joinUrl);\n } catch (err) {\n const e = err instanceof Error ? err : new Error(String(err));\n this.emitter.emit(\"error\", e);\n this.setStatus(CallStatus.IDLE);\n } finally {\n this._starting = false;\n }\n }\n\n /** Hangs up. Resolves when ultravox-client confirms disconnection. */\n async end(): Promise<void> {\n if (!this.session) return;\n this.setStatus(CallStatus.DISCONNECTING);\n try {\n await this.session.leaveCall();\n } catch (err) {\n this.emitter.emit(\n \"error\",\n err instanceof Error ? err : new Error(String(err)),\n );\n }\n }\n\n muteMic(): void {\n this.session?.muteMic();\n this.emitter.emit(\"mic_muted\", true);\n }\n\n unmuteMic(): void {\n this.session?.unmuteMic();\n this.emitter.emit(\"mic_muted\", false);\n }\n\n toggleMicMute(): boolean {\n if (!this.session) return false;\n this.session.toggleMicMute();\n const muted = this.session.isMicMuted;\n this.emitter.emit(\"mic_muted\", muted);\n return muted;\n }\n\n muteSpeaker(): void {\n this.session?.muteSpeaker();\n this.emitter.emit(\"speaker_muted\", true);\n }\n\n unmuteSpeaker(): void {\n this.session?.unmuteSpeaker();\n this.emitter.emit(\"speaker_muted\", false);\n }\n\n toggleSpeakerMute(): boolean {\n if (!this.session) return false;\n this.session.toggleSpeakerMute();\n const muted = this.session.isSpeakerMuted;\n this.emitter.emit(\"speaker_muted\", muted);\n return muted;\n }\n\n /** Sends a text message into the call (no spoken audio from the user). */\n sendText(text: string, deferResponse = false): void {\n this.session?.sendText(text, deferResponse);\n }\n\n /** Sends an arbitrary data message over Ultravox's data channel. */\n sendData(obj: unknown): void {\n this.session?.sendData(obj);\n }\n\n /** Removes all listeners and aborts any active session. */\n dispose(): void {\n this.stopEmotionPolling();\n void this.session?.leaveCall().catch(() => {});\n this.session = null;\n this.emitter.removeAllListeners();\n this._status = CallStatus.IDLE;\n }\n\n // ── Internals ─────────────────────────────────────────────────────────────\n\n private resetMutableState(): void {\n this._callId = null;\n this._sessionToken = null;\n this._transcripts = [];\n this._lastEmotion = null;\n this._contactSaved = false;\n this._emotionMeta = null;\n this.stopEmotionPolling();\n }\n\n private attachSessionListeners(session: UltravoxSession): void {\n session.addEventListener(\"status\", () => this.handleStatusChange(session));\n session.addEventListener(\"transcripts\", () => this.handleTranscripts(session));\n session.addEventListener(\"experimental_message\", (evt) =>\n this.handleDataMessage(evt),\n );\n }\n\n private handleStatusChange(session: UltravoxSession): void {\n const raw = session.status;\n this.emitter.emit(\"raw_status\", String(raw));\n\n const prevStatus = this._status;\n let next: CallStatus;\n switch (raw) {\n case UltravoxSessionStatus.CONNECTING:\n next = CallStatus.CONNECTING;\n break;\n case UltravoxSessionStatus.IDLE:\n // IDLE in ultravox-client = \"connected, waiting\" — the call IS live.\n next = CallStatus.CONNECTED;\n break;\n case UltravoxSessionStatus.LISTENING:\n next = CallStatus.LISTENING;\n break;\n case UltravoxSessionStatus.THINKING:\n next = CallStatus.THINKING;\n break;\n case UltravoxSessionStatus.SPEAKING:\n next = CallStatus.SPEAKING;\n break;\n case UltravoxSessionStatus.DISCONNECTING:\n next = CallStatus.DISCONNECTING;\n break;\n case UltravoxSessionStatus.DISCONNECTED:\n next = CallStatus.DISCONNECTED;\n break;\n default:\n next = this._status;\n }\n\n this.setStatus(next);\n\n // Start emotion polling on the first transition into a live state.\n const wasLive = LIVE_STATUSES.has(prevStatus);\n const nowLive = LIVE_STATUSES.has(next);\n if (!wasLive && nowLive && this._callId && this.opts.pollEmotion) {\n this.startEmotionPolling();\n }\n\n if (next === CallStatus.DISCONNECTED) {\n this.stopEmotionPolling();\n this.session = null;\n this.emitter.emit(\"ended\", undefined);\n // Settle back to IDLE so the caller can restart cleanly.\n this.setStatus(CallStatus.IDLE);\n }\n }\n\n private handleTranscripts(session: UltravoxSession): void {\n const raw = session.transcripts ?? [];\n const mapped: Transcript[] = raw.map(toPublicTranscript);\n const previous = this._transcripts;\n this._transcripts = mapped;\n\n // Emit `transcript` for any new or updated entries.\n for (let i = 0; i < mapped.length; i++) {\n const cur = mapped[i];\n if (!cur) continue;\n const prev = previous[i];\n if (\n !prev ||\n prev.text !== cur.text ||\n prev.isFinal !== cur.isFinal\n ) {\n this.emitter.emit(\"transcript\", cur);\n }\n }\n this.emitter.emit(\"transcripts\", mapped);\n\n // Heuristic: detect \"I've saved your contact info\" style confirmation.\n if (!this._contactSaved) {\n const saved = mapped.some(\n (t) =>\n t.speaker === Speaker.AGENT &&\n t.text &&\n CONTACT_SAVED_PATTERN.test(t.text),\n );\n if (saved) {\n this._contactSaved = true;\n this.emitter.emit(\"contact_saved\", undefined);\n }\n }\n }\n\n private handleDataMessage(evt: Event): void {\n // ultravox-client surfaces this as UltravoxDataMessageEvent with `.message`.\n // Some SDK versions use `.data` so we read both for safety.\n const anyEvt = evt as Event & { message?: unknown; data?: unknown };\n const raw = anyEvt.message ?? anyEvt.data ?? evt;\n this.emitter.emit(\"data_message\", raw);\n\n const text = typeof raw === \"string\" ? raw : safeStringify(raw);\n const pattern = this.opts.emotionPattern ?? DEFAULT_EMOTION_PATTERN;\n const match = text.match(pattern);\n if (match && match[1]) {\n const label = match[1].toLowerCase();\n this._lastEmotion = label;\n this.emitter.emit(\"emotion\", { label, raw });\n }\n }\n\n private startEmotionPolling(): void {\n this.stopEmotionPolling();\n if (!this.opts.pollEmotion || !this._callId) return;\n\n const callId = this._callId;\n const sessionToken = this._sessionToken ?? undefined;\n const interval = this.opts.emotionPollIntervalMs ?? 15000;\n\n const poll = async () => {\n try {\n const label = await this.opts.pollEmotion!(callId, sessionToken);\n if (label) {\n const normalized = label.toLowerCase();\n this._lastEmotion = normalized;\n this.emitter.emit(\"emotion\", { label: normalized, raw: label });\n }\n } catch {\n // non-fatal — polling errors are silent\n }\n };\n\n poll(); // immediate first fetch\n this._pollTimer = setInterval(poll, interval);\n }\n\n private stopEmotionPolling(): void {\n if (this._pollTimer !== null) {\n clearInterval(this._pollTimer);\n this._pollTimer = null;\n }\n }\n\n private setStatus(next: CallStatus): void {\n if (next === this._status) return;\n this._status = next;\n this.emitter.emit(\"status\", next);\n }\n\n private surfaceEmotionWarnings(payload: JoinUrlResponse): void {\n const e = payload.emotion;\n if (!e) return;\n if (e.dataConnectionEnabled === false) {\n this.emitter.emit(\n \"warning\",\n \"dataConnection not enabled — check emotion WebSocket URL.\",\n );\n }\n if (e.audioEnabled === false) {\n this.emitter.emit(\n \"warning\",\n \"audio not enabled — audioConfig missing on backend request.\",\n );\n }\n if (e.emotionBridgeConfigured === false) {\n this.emitter.emit(\n \"warning\",\n \"emotionBridge not configured on the backend.\",\n );\n }\n if (e.autoSendEnabled === false) {\n this.emitter.emit(\n \"warning\",\n \"auto-send not enabled — emotion will not feed back into the agent.\",\n );\n }\n }\n}\n\nfunction toPublicTranscript(t: UvTranscript): Transcript {\n return {\n text: t.text,\n isFinal: t.isFinal,\n speaker: t.speaker as unknown as Speaker,\n medium: t.medium as unknown as \"voice\" | \"text\",\n ordinal: t.ordinal,\n };\n}\n\nfunction safeStringify(v: unknown): string {\n try {\n return JSON.stringify(v);\n } catch {\n return String(v);\n }\n}\n","/**\n * Floating voice-call widget — a vanilla, framework-free port of the\n * `FloatingDavid` panel from aihumanity.io. Mount with one call:\n *\n * ```ts\n * import { mountFloatingWidget } from \"@aihumanity/voice-sdk/widget\";\n * mountFloatingWidget({\n * apiUrl: \"https://api.eimi.ai\",\n * authToken: \"ey...\",\n * agentName: \"DavidChiu\",\n * username: \"aihumanity-website\",\n * persona: { name: \"David Chiu\", title: \"Founder & CEO · AIHumanity\", initials: \"DC\" },\n * });\n * ```\n *\n * It injects a single shadow-DOM root so it can never collide with host page\n * styles.\n */\n\nimport { VoiceCall } from \"./VoiceCall.js\";\nimport { CallStatus, type VoiceCallOptions } from \"./types.js\";\n\nexport interface FloatingWidgetPersona {\n name: string;\n title?: string;\n /** 1–3 character monogram shown in the avatar circle. */\n initials?: string;\n /** Tagline shown when idle. */\n intro?: string;\n /** Footer attribution text. */\n footer?: string;\n}\n\nexport interface FloatingWidgetOptions extends VoiceCallOptions {\n persona?: FloatingWidgetPersona;\n /** DOM node to mount into. Defaults to `document.body`. */\n container?: HTMLElement;\n /** Show the small \"Talk to {name}\" tooltip when idle. Default true. */\n showTooltip?: boolean;\n}\n\nexport interface FloatingWidgetHandle {\n /** Programmatically open the panel and start a call. */\n open(): void;\n /** Hang up if active and close the panel. */\n close(): void;\n /** Tear the widget out of the DOM. */\n destroy(): void;\n /** Underlying VoiceCall — for advanced wiring. */\n call: VoiceCall;\n}\n\nconst EMOTION_META: Record<\n string,\n { color: string; bg: string; border: string; label: string }\n> = {\n happy: { color: \"#4ade80\", bg: \"rgba(74,222,128,0.10)\", border: \"rgba(74,222,128,0.28)\", label: \"Happy\" },\n excited: { color: \"#facc15\", bg: \"rgba(250,204,21,0.10)\", border: \"rgba(250,204,21,0.28)\", label: \"Excited\" },\n joy: { color: \"#4ade80\", bg: \"rgba(74,222,128,0.10)\", border: \"rgba(74,222,128,0.28)\", label: \"Joyful\" },\n confident: { color: \"#6ddcff\", bg: \"rgba(109,220,255,0.10)\", border: \"rgba(109,220,255,0.28)\", label: \"Confident\" },\n neutral: { color: \"#a0a0b8\", bg: \"rgba(160,160,184,0.08)\", border: \"rgba(160,160,184,0.22)\", label: \"Neutral\" },\n calm: { color: \"#93c5fd\", bg: \"rgba(147,197,253,0.08)\", border: \"rgba(147,197,253,0.22)\", label: \"Calm\" },\n curious: { color: \"#c4b5fd\", bg: \"rgba(196,181,253,0.08)\", border: \"rgba(196,181,253,0.22)\", label: \"Curious\" },\n sad: { color: \"#818cf8\", bg: \"rgba(129,140,248,0.10)\", border: \"rgba(129,140,248,0.28)\", label: \"Sad\" },\n anxious: { color: \"#fb923c\", bg: \"rgba(251,146,60,0.10)\", border: \"rgba(251,146,60,0.28)\", label: \"Anxious\" },\n stressed: { color: \"#fb923c\", bg: \"rgba(251,146,60,0.10)\", border: \"rgba(251,146,60,0.28)\", label: \"Stressed\" },\n angry: { color: \"#f87171\", bg: \"rgba(248,113,113,0.10)\", border: \"rgba(248,113,113,0.28)\", label: \"Angry\" },\n fear: { color: \"#f87171\", bg: \"rgba(248,113,113,0.10)\", border: \"rgba(248,113,113,0.28)\", label: \"Fearful\" },\n disgust: { color: \"#fb923c\", bg: \"rgba(251,146,60,0.10)\", border: \"rgba(251,146,60,0.28)\", label: \"Disgust\" },\n};\n\nconst STYLE = `\n:host { all: initial; }\n* { box-sizing: border-box; font-family: ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif; }\n\n@keyframes spin { to { transform: rotate(360deg); } }\n@keyframes pulse { 0%,100%{box-shadow:0 0 0 6px rgba(255,77,77,0.25),0 4px 20px rgba(192,57,43,0.5);} 50%{box-shadow:0 0 0 10px rgba(255,77,77,0.1),0 4px 24px rgba(192,57,43,0.6);} }\n@keyframes wave { from{transform:scaleY(1);} to{transform:scaleY(2.2);} }\n@keyframes pop { 0%{transform:scale(0.85);opacity:0;} 60%{transform:scale(1.06);} 100%{transform:scale(1);opacity:1;} }\n@keyframes dot { 0%,100%{opacity:1;} 50%{opacity:.3;} }\n\n.fab {\n position: fixed; bottom: 28px; right: 28px; z-index: 2147483600;\n width: 60px; height: 60px; border-radius: 50%; border: none; cursor: pointer;\n display: flex; align-items: center; justify-content: center;\n background: linear-gradient(135deg, #6ddcff, #7e60f8);\n box-shadow: 0 4px 20px rgba(126,96,248,0.4);\n transition: background .3s, box-shadow .3s;\n}\n.fab.live {\n background: linear-gradient(135deg, #ff4d4d, #c0392b);\n animation: pulse 2s ease-in-out infinite;\n}\n.fab svg { stroke: #fff; }\n.spinner { width: 20px; height: 20px; border: 2px solid #2a2a3a; border-top: 2px solid #6ddcff; border-radius: 50%; animation: spin .8s linear infinite; }\n\n.tooltip {\n position: fixed; bottom: 36px; right: 98px; z-index: 2147483599;\n background: #0d0d14; border: 1px solid #2a2a3a; border-radius: 10px;\n padding: 6px 12px; font-size: 0.8rem; color: #e0e0e0; white-space: nowrap;\n pointer-events: none;\n}\n\n.panel {\n position: fixed; bottom: 100px; right: 28px; z-index: 2147483600;\n width: 300px; background: #0d0d14; border: 1px solid #1e1e2e;\n border-radius: 18px; box-shadow: 0 8px 40px rgba(0,0,0,0.6); overflow: hidden;\n color: #fff;\n}\n.panel header {\n background: linear-gradient(135deg, rgba(109,220,255,0.08), rgba(126,96,248,0.12));\n border-bottom: 1px solid #1e1e2e; padding: 16px 20px;\n display: flex; align-items: center; gap: 12px;\n}\n.avatar {\n width: 44px; height: 44px; border-radius: 50%;\n background: linear-gradient(135deg, #6ddcff, #7e60f8);\n display: flex; align-items: center; justify-content: center;\n font-weight: 700; color: #fff; font-size: 1rem; flex-shrink: 0;\n transition: box-shadow .3s;\n}\n.avatar.live { box-shadow: 0 0 0 3px rgba(109,220,255,0.3); }\n.title { font-weight: 700; font-size: 0.95rem; }\n.subtitle { font-size: 0.72rem; color: #7e60f8; letter-spacing: 0.08em; margin-top: 1px; }\n.close {\n margin-left: auto; background: none; border: none; cursor: pointer;\n color: #555; padding: 4px; line-height: 1;\n}\n\n.body { padding: 20px; text-align: center; }\n.intro { font-size: 0.85rem; color: #a0a0b8; line-height: 1.6; margin: 0 0 20px; }\n.error { font-size: 0.78rem; color: #ff6b6b; margin-bottom: 12px; }\n\n.start-btn {\n width: 100%; padding: 12px; border-radius: 12px; border: none; cursor: pointer;\n background: linear-gradient(135deg, #6ddcff, #7e60f8);\n color: #fff; font-weight: 700; font-size: 0.9rem;\n display: flex; align-items: center; justify-content: center; gap: 8px;\n}\n.start-btn[disabled] { opacity: 0.5; cursor: not-allowed; }\n\n.busy { display: flex; flex-direction: column; align-items: center; gap: 14px; padding: 12px 0; }\n.busy p { font-size: 0.85rem; color: #a0a0b8; margin: 0; }\n\n.live-status { font-size: 0.82rem; color: #6ddcff; margin: 0 0 4px; letter-spacing: 0.04em; }\n\n.waveform { display: flex; align-items: center; gap: 3px; height: 24px; justify-content: center; margin-bottom: 12px; }\n.waveform > div {\n width: 3px; border-radius: 2px;\n background: linear-gradient(180deg, #6ddcff, #7e60f8);\n height: 4px;\n}\n.waveform.active > div { animation: wave .6s ease-in-out infinite alternate; }\n.waveform.active > div:nth-child(2) { animation-duration: .7s; }\n.waveform.active > div:nth-child(3) { animation-duration: .8s; }\n.waveform.active > div:nth-child(4) { animation-duration: .9s; }\n.waveform.active > div:nth-child(5) { animation-duration: 1s; }\n\n.badge {\n display: inline-flex; align-items: center; gap: 6px;\n background: rgba(109,220,255,0.08); border: 1px solid rgba(109,220,255,0.2);\n border-radius: 20px; padding: 4px 12px; margin-bottom: 14px;\n font-size: 0.72rem; color: #6ddcff;\n}\n\n.emotion {\n display: inline-flex; align-items: center; gap: 6px;\n border-radius: 20px; padding: 5px 12px; margin-bottom: 10px;\n font-size: 0.7rem; font-weight: 600; letter-spacing: 0.04em;\n animation: pop .35s cubic-bezier(0.34,1.56,0.64,1) both;\n}\n.emotion .dot { width: 6px; height: 6px; border-radius: 50%; animation: dot 1.6s ease-in-out infinite; flex-shrink: 0; }\n\n.actions { display: flex; gap: 10px; margin-top: 12px; }\n.actions button {\n flex: 1; padding: 10px; border-radius: 10px; border: 1px solid #2a2a3a;\n background: transparent; color: #a0a0b8; cursor: pointer;\n font-size: 0.82rem; display: flex; align-items: center; justify-content: center; gap: 6px;\n}\n.actions .end { background: #3d1a1a; color: #ff6b6b; border: none; }\n.actions .mute.muted { background: #2a2a3a; color: #6ddcff; }\n\nfooter { border-top: 1px solid #1a1a28; padding: 10px 20px; font-size: 0.7rem; color: #444; text-align: center; }\n\n.hidden { display: none !important; }\n`;\n\nconst MIC_SVG = `<svg width=\"26\" height=\"26\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"9\" y=\"2\" width=\"6\" height=\"11\" rx=\"3\"/><path d=\"M5 10a7 7 0 0 0 14 0\"/><line x1=\"12\" y1=\"19\" x2=\"12\" y2=\"22\"/><line x1=\"8\" y1=\"22\" x2=\"16\" y2=\"22\"/></svg>`;\nconst HANGUP_SVG = `<svg width=\"26\" height=\"26\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M10.68 13.31a16 16 0 0 0 3.41 2.6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7 2 2 0 0 1 1.72 2v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07A19.42 19.42 0 0 1 4.43 9.58 19.79 19.79 0 0 1 1.36.94a2 2 0 0 1 2-.18l3 .01a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11z\"/><line x1=\"23\" y1=\"1\" x2=\"1\" y2=\"23\"/></svg>`;\nconst CLOSE_SVG = `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/></svg>`;\nconst CHECK_SVG = `<svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\"><polyline points=\"20 6 9 17 4 12\"/></svg>`;\nconst MUTE_ON_SVG = `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"><line x1=\"1\" y1=\"1\" x2=\"23\" y2=\"23\"/><path d=\"M9 9v3a3 3 0 0 0 5.12 2.12M15 9.34V4a3 3 0 0 0-5.94-.6\"/><path d=\"M17 16.95A7 7 0 0 1 5 12v-2m14 0v2a7 7 0 0 1-.11 1.23\"/><line x1=\"12\" y1=\"19\" x2=\"12\" y2=\"22\"/></svg>`;\nconst MUTE_OFF_SVG = `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"><rect x=\"9\" y=\"2\" width=\"6\" height=\"11\" rx=\"3\"/><path d=\"M5 10a7 7 0 0 0 14 0\"/><line x1=\"12\" y1=\"19\" x2=\"12\" y2=\"22\"/></svg>`;\n\n/**\n * Mounts the floating widget. Returns a handle for programmatic control.\n *\n * @example\n * ```ts\n * const widget = mountFloatingWidget({\n * apiUrl: \"https://api.eimi.ai\",\n * authToken: \"...\",\n * agentName: \"DavidChiu\",\n * username: \"aihumanity-website\",\n * });\n * // widget.open();\n * // widget.destroy();\n * ```\n */\nexport function mountFloatingWidget(\n options: FloatingWidgetOptions,\n): FloatingWidgetHandle {\n const persona: Required<FloatingWidgetPersona> = {\n name: options.persona?.name ?? \"the founder\",\n title: options.persona?.title ?? \"AI voice assistant\",\n initials:\n options.persona?.initials ??\n (options.persona?.name ?? \"AI\")\n .split(/\\s+/)\n .map((s) => s[0]?.toUpperCase() ?? \"\")\n .slice(0, 2)\n .join(\"\"),\n intro:\n options.persona?.intro ??\n `Have a real-time voice conversation with ${options.persona?.name ?? \"the agent\"}.`,\n footer: options.persona?.footer ?? \"Powered by AIHumanity · Ultravox voice AI\",\n };\n\n const container = options.container ?? document.body;\n const host = document.createElement(\"div\");\n host.style.position = \"fixed\";\n host.style.zIndex = \"2147483600\";\n container.appendChild(host);\n const root = host.attachShadow({ mode: \"open\" });\n\n // Build DOM.\n const styleEl = document.createElement(\"style\");\n styleEl.textContent = STYLE;\n root.appendChild(styleEl);\n\n const fab = document.createElement(\"button\");\n fab.className = \"fab\";\n fab.title = `Talk to ${persona.name}`;\n fab.innerHTML = MIC_SVG;\n root.appendChild(fab);\n\n const tooltip = document.createElement(\"div\");\n tooltip.className = \"tooltip\";\n tooltip.textContent = `Talk to ${persona.name}`;\n if (options.showTooltip === false) tooltip.classList.add(\"hidden\");\n root.appendChild(tooltip);\n\n const panel = document.createElement(\"div\");\n panel.className = \"panel hidden\";\n panel.innerHTML = `\n <header>\n <div class=\"avatar\">${escapeHtml(persona.initials)}</div>\n <div>\n <div class=\"title\">${escapeHtml(persona.name)}</div>\n <div class=\"subtitle\">${escapeHtml(persona.title)}</div>\n </div>\n <button class=\"close\" aria-label=\"Close\">${CLOSE_SVG}</button>\n </header>\n <div class=\"body\">\n <div class=\"state-idle\">\n <p class=\"intro\">${escapeHtml(persona.intro)}</p>\n <p class=\"error hidden\"></p>\n <button class=\"start-btn\">${MIC_SVG}<span>Start Conversation</span></button>\n </div>\n <div class=\"state-busy busy hidden\"><div class=\"spinner\"></div><p class=\"busy-label\">Connecting…</p></div>\n <div class=\"state-live hidden\">\n <div class=\"waveform active\">\n <div></div><div></div><div></div><div></div><div></div>\n </div>\n <p class=\"live-status\">Live · Speaking with ${escapeHtml(persona.name)}</p>\n <div class=\"badge contact-saved hidden\">${CHECK_SVG}<span>Contact info saved</span></div>\n <div class=\"emotion hidden\"></div>\n <div class=\"actions\">\n <button class=\"mute\">${MUTE_OFF_SVG}<span>Mute</span></button>\n <button class=\"end\">${HANGUP_SVG}<span>End Call</span></button>\n </div>\n </div>\n </div>\n <footer>${escapeHtml(persona.footer)}</footer>\n `;\n root.appendChild(panel);\n\n // Refs.\n const $ = <T extends Element>(sel: string): T =>\n panel.querySelector(sel) as T;\n const closeBtn = $<HTMLButtonElement>(\".close\");\n const idleEl = $<HTMLElement>(\".state-idle\");\n const busyEl = $<HTMLElement>(\".state-busy\");\n const liveEl = $<HTMLElement>(\".state-live\");\n const errorEl = $<HTMLElement>(\".error\");\n const startBtn = $<HTMLButtonElement>(\".start-btn\");\n const busyLabel = $<HTMLElement>(\".busy-label\");\n const muteBtn = $<HTMLButtonElement>(\".mute\");\n const endBtn = $<HTMLButtonElement>(\".end\");\n const savedBadge = $<HTMLElement>(\".contact-saved\");\n const emotionEl = $<HTMLElement>(\".emotion\");\n const avatarEl = $<HTMLElement>(\".avatar\");\n const footerEl = panel.querySelector(\"footer\") as HTMLElement;\n\n // VoiceCall instance.\n const call = new VoiceCall(options);\n\n let panelOpen = false;\n let isLive = false;\n\n function setPanelOpen(open: boolean) {\n panelOpen = open;\n panel.classList.toggle(\"hidden\", !open);\n if (open) tooltip.classList.add(\"hidden\");\n else if (options.showTooltip !== false && !isLive) tooltip.classList.remove(\"hidden\");\n }\n\n function render() {\n const s = call.status;\n const busy =\n s === CallStatus.CONNECTING || s === CallStatus.DISCONNECTING;\n const live =\n s === CallStatus.CONNECTED ||\n s === CallStatus.LISTENING ||\n s === CallStatus.THINKING ||\n s === CallStatus.SPEAKING;\n isLive = live;\n\n fab.classList.toggle(\"live\", live);\n fab.title = live ? \"End call\" : `Talk to ${persona.name}`;\n fab.innerHTML = busy\n ? `<div class=\"spinner\"></div>`\n : live\n ? HANGUP_SVG\n : MIC_SVG;\n\n avatarEl.classList.toggle(\"live\", live);\n idleEl.classList.toggle(\"hidden\", busy || live);\n busyEl.classList.toggle(\"hidden\", !busy);\n liveEl.classList.toggle(\"hidden\", !live);\n footerEl.classList.toggle(\"hidden\", live || busy);\n\n busyLabel.textContent =\n s === CallStatus.CONNECTING\n ? `Connecting to ${persona.name}…`\n : \"Ending call…\";\n }\n\n // ── Event wiring ─────────────────────────────────────────────────────────\n fab.addEventListener(\"click\", () => {\n if (isLive || call.status === CallStatus.CONNECTING) {\n void call.end();\n } else {\n setPanelOpen(!panelOpen);\n }\n });\n closeBtn.addEventListener(\"click\", () => setPanelOpen(false));\n startBtn.addEventListener(\"click\", () => {\n setPanelOpen(true);\n errorEl.classList.add(\"hidden\");\n void call.start();\n });\n endBtn.addEventListener(\"click\", () => void call.end());\n muteBtn.addEventListener(\"click\", () => call.toggleMicMute());\n\n call.on(\"status\", () => render());\n call.on(\"error\", (err) => {\n errorEl.textContent = err.message;\n errorEl.classList.remove(\"hidden\");\n });\n call.on(\"contact_saved\", () => savedBadge.classList.remove(\"hidden\"));\n call.on(\"emotion\", ({ label }) => {\n const meta = EMOTION_META[label] ?? {\n color: \"#a0a0b8\",\n bg: \"rgba(160,160,184,0.08)\",\n border: \"rgba(160,160,184,0.22)\",\n label: label.charAt(0).toUpperCase() + label.slice(1),\n };\n emotionEl.classList.remove(\"hidden\");\n emotionEl.style.background = meta.bg;\n emotionEl.style.border = `1px solid ${meta.border}`;\n emotionEl.style.color = meta.color;\n emotionEl.innerHTML = `<span class=\"dot\" style=\"background:${meta.color}\"></span>${escapeHtml(meta.label)}`;\n });\n call.on(\"mic_muted\", (m) => {\n muteBtn.classList.toggle(\"muted\", m);\n muteBtn.innerHTML = `${m ? MUTE_ON_SVG : MUTE_OFF_SVG}<span>${m ? \"Unmute\" : \"Mute\"}</span>`;\n });\n call.on(\"ended\", () => {\n savedBadge.classList.add(\"hidden\");\n emotionEl.classList.add(\"hidden\");\n muteBtn.classList.remove(\"muted\");\n muteBtn.innerHTML = `${MUTE_OFF_SVG}<span>Mute</span>`;\n });\n\n render();\n\n return {\n open() {\n setPanelOpen(true);\n void call.start();\n },\n close() {\n void call.end();\n setPanelOpen(false);\n },\n destroy() {\n call.dispose();\n host.remove();\n },\n call,\n };\n}\n\nfunction escapeHtml(s: string): string {\n return s\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n\nexport { VoiceCall } from \"./VoiceCall.js\";\nexport { CallStatus } from \"./types.js\";\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@aihumanity/voice-sdk",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "JavaScript SDK for AIHumanity / eimi voice AI calls — wraps Ultravox with call-state tracking, transcripts, and emotion detection.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "AIHumanity",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/fdchiu/aihumanity-voice-sdk.git"
|
|
13
|
+
},
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/fdchiu/aihumanity-voice-sdk/issues"
|
|
16
|
+
},
|
|
17
|
+
"homepage": "https://github.com/fdchiu/aihumanity-voice-sdk#readme",
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"README.md",
|
|
21
|
+
"LICENSE"
|
|
22
|
+
],
|
|
23
|
+
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"default": "./dist/index.js"
|
|
27
|
+
},
|
|
28
|
+
"./react": {
|
|
29
|
+
"types": "./dist/react.d.ts",
|
|
30
|
+
"default": "./dist/react.js"
|
|
31
|
+
},
|
|
32
|
+
"./widget": {
|
|
33
|
+
"types": "./dist/widget.d.ts",
|
|
34
|
+
"default": "./dist/widget.js"
|
|
35
|
+
},
|
|
36
|
+
"./package.json": "./package.json"
|
|
37
|
+
},
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=18"
|
|
40
|
+
},
|
|
41
|
+
"scripts": {
|
|
42
|
+
"build": "tsup",
|
|
43
|
+
"prebuild:iife": "find dist -name '*.d.ts' -delete && find dist -name '*.map' -delete",
|
|
44
|
+
"build:iife": "tsup --config tsup.iife.config.ts",
|
|
45
|
+
"build:all": "npm run build && npm run build:iife",
|
|
46
|
+
"check": "npm run typecheck && npm run build",
|
|
47
|
+
"typecheck": "tsc --noEmit",
|
|
48
|
+
"dev": "tsup --watch",
|
|
49
|
+
"clean": "rm -rf dist",
|
|
50
|
+
"demo": "npm run build:all && npx http-server -p 5173 -c-1 .",
|
|
51
|
+
"prepack": "npm run typecheck && npm run build"
|
|
52
|
+
},
|
|
53
|
+
"keywords": [
|
|
54
|
+
"ultravox",
|
|
55
|
+
"voice",
|
|
56
|
+
"ai",
|
|
57
|
+
"sdk",
|
|
58
|
+
"webrtc",
|
|
59
|
+
"transcript",
|
|
60
|
+
"emotion",
|
|
61
|
+
"aihumanity",
|
|
62
|
+
"eimi"
|
|
63
|
+
],
|
|
64
|
+
"dependencies": {
|
|
65
|
+
"ultravox-client": "^0.5.0"
|
|
66
|
+
},
|
|
67
|
+
"peerDependencies": {
|
|
68
|
+
"react": ">=17.0.0"
|
|
69
|
+
},
|
|
70
|
+
"peerDependenciesMeta": {
|
|
71
|
+
"react": {
|
|
72
|
+
"optional": true
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
"devDependencies": {
|
|
76
|
+
"@types/react": "^18.2.0",
|
|
77
|
+
"react": "^18.2.0",
|
|
78
|
+
"tsup": "^8.0.0",
|
|
79
|
+
"typescript": "^5.4.0"
|
|
80
|
+
},
|
|
81
|
+
"overrides": {
|
|
82
|
+
"csstype": "3.1.3"
|
|
83
|
+
},
|
|
84
|
+
"publishConfig": {
|
|
85
|
+
"access": "public"
|
|
86
|
+
}
|
|
87
|
+
}
|