@keyframelabs/elements 0.0.5 → 0.0.7

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/README.md CHANGED
@@ -71,7 +71,7 @@ view.disconnect();
71
71
 
72
72
  ## Supported agents and real-time LLMs
73
73
 
74
- Supports ElevenLabs Agents, Cartesia Line, and Gemini Live.
74
+ Supports Cartesia, ElevenLabs, Vapi, Gemini Live (closed alpha), OpenAI Realtime (closed alpha).
75
75
 
76
76
  For `PersonaEmbed`, this is determined by the values you set in the Keyframe platform dashboard.
77
77
 
@@ -145,10 +145,10 @@ type SessionDetails = {
145
145
  };
146
146
 
147
147
  type VoiceAgentDetails = {
148
- type: 'gemini' | 'elevenlabs' | 'cartesia';
148
+ type: 'cartesia' | 'elevenlabs' | 'vapi' | 'gemini' | 'openai';
149
149
  token?: string; // For gemini, cartesia
150
150
  agent_id?: string; // For elevenlabs, cartesia
151
- signed_url?: string; // For elevenlabs
151
+ signed_url?: string; // For elevenlabs, vapi
152
152
  };
153
153
  ```
154
154
 
@@ -1,6 +1,7 @@
1
1
  import { GeminiLiveAgent, GeminiLiveConfig } from './gemini-live';
2
2
  import { ElevenLabsAgent, ElevenLabsConfig } from './elevenlabs';
3
3
  import { CartesiaAgent, CartesiaConfig } from './cartesia';
4
+ import { VapiAgent, VapiConfig } from './vapi';
4
5
  /**
5
6
  * Agent implementations for voice AI platforms.
6
7
  *
@@ -12,9 +13,10 @@ export type { Agent, AgentConfig, AgentEventMap, AgentState } from './types';
12
13
  export { GeminiLiveAgent, type GeminiLiveConfig };
13
14
  export { ElevenLabsAgent, type ElevenLabsConfig };
14
15
  export { CartesiaAgent, type CartesiaConfig };
16
+ export { VapiAgent, type VapiConfig };
15
17
  export { SAMPLE_RATE, base64ToBytes, bytesToBase64, resamplePcm, createEventEmitter, floatTo16BitPCM } from './audio-utils';
16
18
  /** Supported agent types */
17
- export type AgentType = 'gemini' | 'elevenlabs' | 'cartesia';
19
+ export type AgentType = 'gemini' | 'elevenlabs' | 'cartesia' | 'vapi';
18
20
  /** Agent type metadata */
19
21
  export interface AgentTypeInfo {
20
22
  id: AgentType;
@@ -28,9 +30,10 @@ export interface AgentConfigMap {
28
30
  gemini: GeminiLiveConfig;
29
31
  elevenlabs: ElevenLabsConfig;
30
32
  cartesia: CartesiaConfig;
33
+ vapi: VapiConfig;
31
34
  }
32
35
  /** Union type of all agent instances */
33
- export type AnyAgent = GeminiLiveAgent | ElevenLabsAgent | CartesiaAgent;
36
+ export type AnyAgent = GeminiLiveAgent | ElevenLabsAgent | CartesiaAgent | VapiAgent;
34
37
  /**
35
38
  * Create an agent instance by type.
36
39
  *
@@ -43,6 +46,7 @@ export type AnyAgent = GeminiLiveAgent | ElevenLabsAgent | CartesiaAgent;
43
46
  export declare function createAgent(type: 'gemini'): GeminiLiveAgent;
44
47
  export declare function createAgent(type: 'elevenlabs'): ElevenLabsAgent;
45
48
  export declare function createAgent(type: 'cartesia'): CartesiaAgent;
49
+ export declare function createAgent(type: 'vapi'): VapiAgent;
46
50
  export declare function createAgent(type: AgentType): AnyAgent;
47
51
  /**
48
52
  * Get agent type metadata by ID.
@@ -0,0 +1,30 @@
1
+ import { AgentConfig } from './types';
2
+ import { BaseAgent } from './base';
3
+ /** Vapi specific configuration */
4
+ export interface VapiConfig extends AgentConfig {
5
+ /** Pre-authenticated WebSocket URL from backend (same concept as ElevenLabs signed_url) */
6
+ signedUrl: string;
7
+ }
8
+ /**
9
+ * Vapi WebSocket Transport agent implementation.
10
+ *
11
+ * Handles WebSocket connection to Vapi and converts
12
+ * audio responses to events that Persona SDK can consume.
13
+ */
14
+ export declare class VapiAgent extends BaseAgent {
15
+ protected readonly agentName = "Vapi";
16
+ private vapiSampleRate;
17
+ connect(config: VapiConfig): Promise<void>;
18
+ /**
19
+ * Handle binary audio data from Vapi.
20
+ * Vapi sends raw PCM 16-bit little-endian audio.
21
+ */
22
+ private handleBinaryAudio;
23
+ protected handleParsedMessage(message: unknown): void;
24
+ sendAudio(pcmData: Uint8Array): void;
25
+ /**
26
+ * Send a control message to end the call.
27
+ */
28
+ hangup(): void;
29
+ close(): void;
30
+ }
package/dist/index.js CHANGED
@@ -1,28 +1,28 @@
1
1
  import { createClient as v } from "@keyframelabs/sdk";
2
- const c = 24e3;
3
- function p(i) {
2
+ const h = 24e3;
3
+ function g(i) {
4
4
  const e = atob(i), t = new Uint8Array(e.length);
5
5
  for (let s = 0; s < e.length; s++)
6
6
  t[s] = e.charCodeAt(s);
7
7
  return t;
8
8
  }
9
- function g(i) {
9
+ function m(i) {
10
10
  let e = "";
11
11
  for (let t = 0; t < i.length; t++)
12
12
  e += String.fromCharCode(i[t]);
13
13
  return btoa(e);
14
14
  }
15
- function d(i, e, t) {
15
+ function c(i, e, t) {
16
16
  if (e === t)
17
17
  return i;
18
- const s = new Int16Array(i.buffer, i.byteOffset, i.length / 2), n = e / t, a = Math.floor(s.length / n), r = new Int16Array(a);
19
- for (let o = 0; o < a; o++) {
20
- const _ = o * n, u = Math.floor(_), w = Math.min(u + 1, s.length - 1), S = _ - u;
21
- r[o] = Math.round(
22
- s[u] * (1 - S) + s[w] * S
18
+ const s = new Int16Array(i.buffer, i.byteOffset, i.length / 2), n = e / t, a = Math.floor(s.length / n), o = new Int16Array(a);
19
+ for (let r = 0; r < a; r++) {
20
+ const S = r * n, p = Math.floor(S), f = Math.min(p + 1, s.length - 1), _ = S - p;
21
+ o[r] = Math.round(
22
+ s[p] * (1 - _) + s[f] * _
23
23
  );
24
24
  }
25
- return new Uint8Array(r.buffer);
25
+ return new Uint8Array(o.buffer);
26
26
  }
27
27
  function b() {
28
28
  const i = /* @__PURE__ */ new Map();
@@ -41,7 +41,7 @@ function b() {
41
41
  }
42
42
  };
43
43
  }
44
- function y(i) {
44
+ function w(i) {
45
45
  const e = new Int16Array(i.length);
46
46
  for (let t = 0; t < i.length; t++) {
47
47
  const s = Math.max(-1, Math.min(1, i[t]));
@@ -50,7 +50,7 @@ function y(i) {
50
50
  return new Uint8Array(e.buffer);
51
51
  }
52
52
  const I = 16e3;
53
- class m {
53
+ class u {
54
54
  ws = null;
55
55
  _state = "idle";
56
56
  events = b();
@@ -113,8 +113,8 @@ class m {
113
113
  this.events.emit("closed", { code: e, reason: t });
114
114
  }
115
115
  }
116
- const C = "gemini-2.5-flash-native-audio-preview-12-2025", E = "wss://generativelanguage.googleapis.com/ws/google.ai.generativelanguage.v1beta.GenerativeService.BidiGenerateContent", A = "wss://generativelanguage.googleapis.com/ws/google.ai.generativelanguage.v1alpha.GenerativeService.BidiGenerateContentConstrained";
117
- class k extends m {
116
+ const E = "gemini-2.5-flash-native-audio-preview-12-2025", C = "wss://generativelanguage.googleapis.com/ws/google.ai.generativelanguage.v1beta.GenerativeService.BidiGenerateContent", k = "wss://generativelanguage.googleapis.com/ws/google.ai.generativelanguage.v1alpha.GenerativeService.BidiGenerateContentConstrained";
117
+ class A extends u {
118
118
  agentName = "GeminiLive";
119
119
  async connect(e) {
120
120
  if (this.ws)
@@ -122,10 +122,10 @@ class k extends m {
122
122
  if (!e.apiKey)
123
123
  throw new Error("Gemini API key is required");
124
124
  e.inputSampleRate && (this.inputSampleRate = e.inputSampleRate);
125
- const t = e.model ?? C, n = (e.authType ?? "api_key") === "ephemeral_token" ? `${A}?access_token=${encodeURIComponent(e.apiKey)}` : `${E}?key=${encodeURIComponent(e.apiKey)}`;
126
- return new Promise((a, r) => {
125
+ const t = e.model ?? E, n = (e.authType ?? "api_key") === "ephemeral_token" ? `${k}?access_token=${encodeURIComponent(e.apiKey)}` : `${C}?key=${encodeURIComponent(e.apiKey)}`;
126
+ return new Promise((a, o) => {
127
127
  this.ws = new WebSocket(n), this.ws.onopen = () => {
128
- const o = {
128
+ const r = {
129
129
  setup: {
130
130
  model: `models/${t}`,
131
131
  generationConfig: {
@@ -134,13 +134,13 @@ class k extends m {
134
134
  systemInstruction: e.systemPrompt ? { parts: [{ text: e.systemPrompt }] } : void 0
135
135
  }
136
136
  };
137
- this.ws.send(JSON.stringify(o)), this.setState("listening"), a();
137
+ this.ws.send(JSON.stringify(r)), this.setState("listening"), a();
138
138
  }, this.ws.onerror = () => {
139
- r(new Error("Failed to connect to Gemini Live"));
140
- }, this.ws.onclose = (o) => {
141
- this.ws = null, this.setState("idle"), this.emitClosed(o.code, o.reason);
142
- }, this.ws.onmessage = (o) => {
143
- this.handleMessage(o.data);
139
+ o(new Error("Failed to connect to Gemini Live"));
140
+ }, this.ws.onclose = (r) => {
141
+ this.ws = null, this.setState("idle"), this.emitClosed(r.code, r.reason);
142
+ }, this.ws.onmessage = (r) => {
143
+ this.handleMessage(r.data);
144
144
  };
145
145
  });
146
146
  }
@@ -159,7 +159,7 @@ class k extends m {
159
159
  this._state !== "speaking" && (this.events.emit("turnStart", void 0), this.setState("speaking"));
160
160
  for (const n of s.modelTurn.parts) {
161
161
  if (n.inlineData?.data) {
162
- const a = p(n.inlineData.data);
162
+ const a = g(n.inlineData.data);
163
163
  this.events.emit("audio", a);
164
164
  }
165
165
  n.text && this.events.emit("transcript", {
@@ -181,7 +181,7 @@ class k extends m {
181
181
  mediaChunks: [
182
182
  {
183
183
  mimeType: `audio/pcm;rate=${this.inputSampleRate}`,
184
- data: g(e)
184
+ data: m(e)
185
185
  }
186
186
  ]
187
187
  }
@@ -190,7 +190,7 @@ class k extends m {
190
190
  }
191
191
  }
192
192
  const R = "wss://api.elevenlabs.io/v1/convai/conversation";
193
- class M extends m {
193
+ class M extends u {
194
194
  agentName = "ElevenLabs";
195
195
  outputSampleRate = 24e3;
196
196
  // Default, updated from metadata
@@ -272,15 +272,15 @@ class M extends m {
272
272
  if (!t?.audio_base_64 || (t.event_id ?? 0) <= this.lastInterruptId)
273
273
  return;
274
274
  this._state !== "speaking" && (this.events.emit("turnStart", void 0), this.setState("speaking"));
275
- let n = p(t.audio_base_64);
276
- this.outputSampleRate !== c && (n = d(n, this.outputSampleRate, c));
275
+ let n = g(t.audio_base_64);
276
+ this.outputSampleRate !== h && (n = c(n, this.outputSampleRate, h));
277
277
  const a = 4800;
278
278
  if (n.length <= a)
279
279
  this.events.emit("audio", n);
280
280
  else
281
- for (let r = 0; r < n.length; r += a) {
282
- const o = n.slice(r, Math.min(r + a, n.length));
283
- this.events.emit("audio", o);
281
+ for (let o = 0; o < n.length; o += a) {
282
+ const r = n.slice(o, Math.min(o + a, n.length));
283
+ this.events.emit("audio", r);
284
284
  }
285
285
  }
286
286
  handleUserTranscript(e) {
@@ -307,8 +307,8 @@ class M extends m {
307
307
  if (!this.ws || this.ws.readyState !== WebSocket.OPEN || !this.initialized)
308
308
  return;
309
309
  let t = e;
310
- this.sourceInputSampleRate !== this.expectedInputSampleRate && (t = d(e, this.sourceInputSampleRate, this.expectedInputSampleRate)), this.ws.send(JSON.stringify({
311
- user_audio_chunk: g(t)
310
+ this.sourceInputSampleRate !== this.expectedInputSampleRate && (t = c(e, this.sourceInputSampleRate, this.expectedInputSampleRate)), this.ws.send(JSON.stringify({
311
+ user_audio_chunk: m(t)
312
312
  }));
313
313
  }
314
314
  /**
@@ -342,7 +342,7 @@ class M extends m {
342
342
  }
343
343
  }
344
344
  const x = "wss://api.cartesia.ai/agents/stream", P = "2025-04-16";
345
- class T extends m {
345
+ class T extends u {
346
346
  agentName = "Cartesia";
347
347
  // Audio configuration
348
348
  cartesiaInputFormat = "pcm_16000";
@@ -423,8 +423,8 @@ class T extends m {
423
423
  handleMediaOutput(e) {
424
424
  if (!e.media?.payload) return;
425
425
  this._state !== "speaking" && (this.events.emit("turnStart", void 0), this.setState("speaking"));
426
- let t = p(e.media.payload);
427
- this.cartesiaOutputRate !== c && (t = d(t, this.cartesiaOutputRate, c)), this.events.emit("audio", t);
426
+ let t = g(e.media.payload);
427
+ this.cartesiaOutputRate !== h && (t = c(t, this.cartesiaOutputRate, h)), this.events.emit("audio", t);
428
428
  }
429
429
  handleClear() {
430
430
  this.events.emit("interrupted", void 0), this.setState("listening");
@@ -434,11 +434,11 @@ class T extends m {
434
434
  return;
435
435
  let t = e;
436
436
  const s = parseInt(this.cartesiaInputFormat.split("_")[1]);
437
- this.inputSampleRate !== s && (t = d(e, this.inputSampleRate, s)), this.ws.send(JSON.stringify({
437
+ this.inputSampleRate !== s && (t = c(e, this.inputSampleRate, s)), this.ws.send(JSON.stringify({
438
438
  event: "media_input",
439
439
  stream_id: this.streamId,
440
440
  media: {
441
- payload: g(t)
441
+ payload: m(t)
442
442
  }
443
443
  }));
444
444
  }
@@ -446,27 +446,109 @@ class T extends m {
446
446
  this.stopHeartbeat(), this.isReady = !1, this.streamId = null, super.close();
447
447
  }
448
448
  }
449
- const O = [
449
+ class O extends u {
450
+ agentName = "Vapi";
451
+ // Audio configuration - Vapi uses 16kHz PCM by default
452
+ vapiSampleRate = 16e3;
453
+ async connect(e) {
454
+ if (this.ws)
455
+ throw new Error("Already connected");
456
+ if (!e.signedUrl)
457
+ throw new Error("Vapi signed URL is required");
458
+ return e.inputSampleRate && (this.inputSampleRate = e.inputSampleRate), new Promise((t, s) => {
459
+ this.ws = new WebSocket(e.signedUrl), this.ws.binaryType = "arraybuffer", this.ws.onopen = () => {
460
+ this.setState("listening"), t();
461
+ }, this.ws.onerror = () => {
462
+ s(new Error("Failed to connect to Vapi"));
463
+ }, this.ws.onclose = (n) => {
464
+ this.ws = null, this.setState("idle"), this.emitClosed(n.code, n.reason);
465
+ }, this.ws.onmessage = (n) => {
466
+ n.data instanceof ArrayBuffer ? this.handleBinaryAudio(n.data) : this.handleMessage(n.data);
467
+ };
468
+ });
469
+ }
470
+ /**
471
+ * Handle binary audio data from Vapi.
472
+ * Vapi sends raw PCM 16-bit little-endian audio.
473
+ */
474
+ handleBinaryAudio(e) {
475
+ this._state !== "speaking" && (this.events.emit("turnStart", void 0), this.setState("speaking"));
476
+ const t = new Uint8Array(e), s = this.vapiSampleRate !== h ? c(t, this.vapiSampleRate, h) : t;
477
+ this.events.emit("audio", s);
478
+ }
479
+ handleParsedMessage(e) {
480
+ const t = e;
481
+ switch (t.type) {
482
+ case "conversation-update":
483
+ t.role === "user" && t.transcript ? this.events.emit("transcript", {
484
+ role: "user",
485
+ text: t.transcript,
486
+ isFinal: !0
487
+ }) : t.role === "assistant" && t.transcript && this.events.emit("transcript", {
488
+ role: "assistant",
489
+ text: t.transcript,
490
+ isFinal: !0
491
+ });
492
+ break;
493
+ case "speech-update":
494
+ t.status === "started" ? (this.events.emit("turnStart", void 0), this.setState("speaking")) : t.status === "stopped" && (this.events.emit("turnEnd", void 0), this.setState("listening"));
495
+ break;
496
+ case "transcript":
497
+ this.events.emit("transcript", {
498
+ role: t.role === "user" ? "user" : "assistant",
499
+ text: t.transcript || "",
500
+ isFinal: t.transcriptType === "final"
501
+ });
502
+ break;
503
+ case "hang":
504
+ case "end-of-call-report":
505
+ this.events.emit("turnEnd", void 0), this.setState("idle");
506
+ break;
507
+ case "error":
508
+ console.error("[Vapi] Server error:", t);
509
+ break;
510
+ }
511
+ }
512
+ sendAudio(e) {
513
+ if (!this.ws || this.ws.readyState !== WebSocket.OPEN)
514
+ return;
515
+ let t = e;
516
+ this.inputSampleRate !== this.vapiSampleRate && (t = c(e, this.inputSampleRate, this.vapiSampleRate)), this.ws.send(t.buffer);
517
+ }
518
+ /**
519
+ * Send a control message to end the call.
520
+ */
521
+ hangup() {
522
+ this.ws && this.ws.readyState === WebSocket.OPEN && this.ws.send(JSON.stringify({ type: "end-call" }));
523
+ }
524
+ close() {
525
+ this.hangup(), super.close();
526
+ }
527
+ }
528
+ const N = [
450
529
  { id: "gemini", name: "Gemini Live", description: "Google Gemini Live API" },
451
530
  { id: "elevenlabs", name: "ElevenLabs", description: "ElevenLabs Conversational AI" },
452
- { id: "cartesia", name: "Cartesia", description: "Cartesia Agents API" }
531
+ { id: "cartesia", name: "Cartesia", description: "Cartesia Agents API" },
532
+ { id: "vapi", name: "Vapi", description: "Vapi WebSocket Transport" }
453
533
  ];
454
- function f(i) {
534
+ function y(i) {
455
535
  switch (i) {
456
536
  case "gemini":
457
- return new k();
537
+ return new A();
458
538
  case "elevenlabs":
459
539
  return new M();
460
540
  case "cartesia":
461
541
  return new T();
542
+ case "vapi":
543
+ return new O();
462
544
  default:
463
545
  throw new Error(`Unknown agent type: ${i}`);
464
546
  }
465
547
  }
466
548
  function L(i) {
467
- return O.find((e) => e.id === i);
549
+ return N.find((e) => e.id === i);
468
550
  }
469
- class D extends Error {
551
+ class U extends Error {
470
552
  status;
471
553
  payload;
472
554
  url;
@@ -475,7 +557,7 @@ class D extends Error {
475
557
  }
476
558
  }
477
559
  const l = /* @__PURE__ */ new Set();
478
- class U {
560
+ class F {
479
561
  apiBaseUrl;
480
562
  publishableKey;
481
563
  callbacks;
@@ -568,7 +650,7 @@ class U {
568
650
  s = await t.json();
569
651
  } catch {
570
652
  }
571
- throw new D({
653
+ throw new U({
572
654
  message: s?.message ?? "create_session failed",
573
655
  status: t.status,
574
656
  payload: s,
@@ -602,7 +684,7 @@ class U {
602
684
  onClose: () => {
603
685
  this.mounted && this.callbacks.onDisconnect?.();
604
686
  }
605
- }), this.agent = f(e.voice_agent_details.type), this.agent.on("audio", (t) => this.session?.sendAudio(t)), this.agent.on("interrupted", () => this.session?.interrupt()), this.agent.on("stateChange", (t) => this.setAgentState(t)), this.agent.on("closed", () => {
687
+ }), this.agent = y(e.voice_agent_details.type), this.agent.on("audio", (t) => this.session?.sendAudio(t)), this.agent.on("interrupted", () => this.session?.interrupt()), this.agent.on("stateChange", (t) => this.setAgentState(t)), this.agent.on("closed", () => {
606
688
  this.mounted && this.callbacks.onDisconnect?.();
607
689
  }), await this.session.connect();
608
690
  }
@@ -613,7 +695,7 @@ class U {
613
695
  const e = this.audioContext.createMediaStreamSource(this.stream);
614
696
  this.processor = this.audioContext.createScriptProcessor(4096, 1, 1), this.processor.onaudioprocess = (t) => {
615
697
  if (!this._isMuted) {
616
- const s = y(t.inputBuffer.getChannelData(0));
698
+ const s = w(t.inputBuffer.getChannelData(0));
617
699
  this.agent?.sendAudio(s);
618
700
  }
619
701
  }, e.connect(this.processor), this.processor.connect(this.audioContext.destination);
@@ -629,17 +711,20 @@ class U {
629
711
  ...t,
630
712
  agentId: e.agent_id,
631
713
  signedUrl: e.signed_url
632
- }) : e.type === "cartesia" && await this.agent.connect({
714
+ }) : e.type === "cartesia" ? await this.agent.connect({
633
715
  ...t,
634
716
  agentId: e.agent_id,
635
717
  apiKey: e.token
718
+ }) : e.type === "vapi" && await this.agent.connect({
719
+ ...t,
720
+ signedUrl: e.signed_url
636
721
  });
637
722
  }
638
723
  cleanup() {
639
724
  this.stream?.getTracks().forEach((e) => e.stop()), this.processor?.disconnect(), this.audioContext?.close(), this.agent?.close(), this.session?.close(), this.stream = null, this.processor = null, this.audioContext = null, this.agent = null, this.session = null;
640
725
  }
641
726
  }
642
- const h = /* @__PURE__ */ new Set();
727
+ const d = /* @__PURE__ */ new Set();
643
728
  class K {
644
729
  voiceAgentDetails;
645
730
  sessionDetails;
@@ -684,24 +769,24 @@ class K {
684
769
  }
685
770
  /** Connect to the session */
686
771
  async connect() {
687
- if (h.has(this.connectionId)) {
772
+ if (d.has(this.connectionId)) {
688
773
  console.log("[PersonaView] Connection already in progress, skipping");
689
774
  return;
690
775
  }
691
- h.add(this.connectionId), this.mounted = !0, this.setStatus("connecting");
776
+ d.add(this.connectionId), this.mounted = !0, this.setStatus("connecting");
692
777
  try {
693
778
  if (await this.initSession(), await this.initMicrophone(), await this.connectAgent(), !this.mounted) {
694
- this.cleanup(), h.delete(this.connectionId);
779
+ this.cleanup(), d.delete(this.connectionId);
695
780
  return;
696
781
  }
697
782
  this.setStatus("connected");
698
783
  } catch (e) {
699
- h.delete(this.connectionId), console.error("[PersonaView]", e), this.mounted && (this.setStatus("error"), this.callbacks.onError?.(e));
784
+ d.delete(this.connectionId), console.error("[PersonaView]", e), this.mounted && (this.setStatus("error"), this.callbacks.onError?.(e));
700
785
  }
701
786
  }
702
787
  /** Disconnect and cleanup */
703
788
  disconnect() {
704
- this.mounted = !1, h.delete(this.connectionId), this.cleanup(), this.setStatus("disconnected");
789
+ this.mounted = !1, d.delete(this.connectionId), this.cleanup(), this.setStatus("disconnected");
705
790
  }
706
791
  /** Toggle microphone mute */
707
792
  toggleMute() {
@@ -734,7 +819,7 @@ class K {
734
819
  onClose: () => {
735
820
  this.mounted && this.callbacks.onDisconnect?.();
736
821
  }
737
- }), this.agent = f(this.voiceAgentDetails.type), this.agent.on("audio", (e) => this.session?.sendAudio(e)), this.agent.on("interrupted", () => this.session?.interrupt()), this.agent.on("stateChange", (e) => this.setAgentState(e)), this.agent.on("closed", () => {
822
+ }), this.agent = y(this.voiceAgentDetails.type), this.agent.on("audio", (e) => this.session?.sendAudio(e)), this.agent.on("interrupted", () => this.session?.interrupt()), this.agent.on("stateChange", (e) => this.setAgentState(e)), this.agent.on("closed", () => {
738
823
  this.mounted && this.callbacks.onDisconnect?.();
739
824
  }), await this.session.connect();
740
825
  }
@@ -745,7 +830,7 @@ class K {
745
830
  const e = this.audioContext.createMediaStreamSource(this.stream);
746
831
  this.processor = this.audioContext.createScriptProcessor(4096, 1, 1), this.processor.onaudioprocess = (t) => {
747
832
  if (!this._isMuted) {
748
- const s = y(t.inputBuffer.getChannelData(0));
833
+ const s = w(t.inputBuffer.getChannelData(0));
749
834
  this.agent?.sendAudio(s);
750
835
  }
751
836
  }, e.connect(this.processor), this.processor.connect(this.audioContext.destination);
@@ -761,10 +846,13 @@ class K {
761
846
  ...t,
762
847
  agentId: e.agent_id,
763
848
  signedUrl: e.signed_url
764
- }) : e.type === "cartesia" && await this.agent.connect({
849
+ }) : e.type === "cartesia" ? await this.agent.connect({
765
850
  ...t,
766
851
  agentId: e.agent_id,
767
852
  apiKey: e.token
853
+ }) : e.type === "vapi" && await this.agent.connect({
854
+ ...t,
855
+ signedUrl: e.signed_url
768
856
  });
769
857
  }
770
858
  cleanup() {
@@ -772,20 +860,20 @@ class K {
772
860
  }
773
861
  }
774
862
  export {
775
- O as AGENT_REGISTRY,
776
- m as BaseAgent,
863
+ N as AGENT_REGISTRY,
864
+ u as BaseAgent,
777
865
  T as CartesiaAgent,
778
866
  M as ElevenLabsAgent,
779
- k as GeminiLiveAgent,
780
- D as KeyframeApiError,
781
- U as PersonaEmbed,
867
+ A as GeminiLiveAgent,
868
+ U as KeyframeApiError,
869
+ F as PersonaEmbed,
782
870
  K as PersonaView,
783
- c as SAMPLE_RATE,
784
- p as base64ToBytes,
785
- g as bytesToBase64,
786
- f as createAgent,
871
+ h as SAMPLE_RATE,
872
+ g as base64ToBytes,
873
+ m as bytesToBase64,
874
+ y as createAgent,
787
875
  b as createEventEmitter,
788
- y as floatTo16BitPCM,
876
+ w as floatTo16BitPCM,
789
877
  L as getAgentInfo,
790
- d as resamplePcm
878
+ c as resamplePcm
791
879
  };
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
7
- "version": "0.0.5",
7
+ "version": "0.0.7",
8
8
  "type": "module",
9
9
  "main": "./dist/index.js",
10
10
  "types": "./dist/index.d.ts",