@vapi-ai/web 1.1.6 → 1.1.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.
@@ -0,0 +1,17 @@
1
+ /// <reference types="node" />
2
+ import EventEmitter from "events";
3
+ declare global {
4
+ interface Window {
5
+ ManagedMediaSource: any;
6
+ }
7
+ }
8
+ declare class AtomicMediaSource extends EventEmitter {
9
+ mediaSource: any;
10
+ sourceBuffer: SourceBuffer | null;
11
+ private operationsQueue;
12
+ constructor();
13
+ appendBuffer(buffer: ArrayBuffer): void;
14
+ clearBuffer(): void;
15
+ private createOperationQueue;
16
+ }
17
+ export default AtomicMediaSource;
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const async_1 = __importDefault(require("async"));
7
+ const events_1 = __importDefault(require("events"));
8
+ // ManagedMediaSource needed for iOS Safari
9
+ function getMediaSource() {
10
+ if (window.ManagedMediaSource) {
11
+ return new window.ManagedMediaSource();
12
+ }
13
+ if (window.MediaSource) {
14
+ return new window.MediaSource();
15
+ }
16
+ return null;
17
+ }
18
+ class AtomicMediaSource extends events_1.default {
19
+ constructor() {
20
+ super();
21
+ this.sourceBuffer = null;
22
+ this.mediaSource = getMediaSource();
23
+ this.operationsQueue = this.createOperationQueue();
24
+ if (!this.mediaSource) {
25
+ console.error("MediaSource is not supported in your browser.");
26
+ // Display a message to the user, or handle this situation in another way
27
+ return;
28
+ }
29
+ this.mediaSource.addEventListener("sourceopen", () => {
30
+ this.mediaSource.duration = Number.POSITIVE_INFINITY;
31
+ this.sourceBuffer = this.mediaSource.addSourceBuffer('audio/webm; codecs="opus"');
32
+ if (this.sourceBuffer) {
33
+ this.sourceBuffer.mode = "sequence";
34
+ }
35
+ });
36
+ }
37
+ appendBuffer(buffer) {
38
+ this.operationsQueue.push(() => {
39
+ return new Promise((resolve, reject) => {
40
+ if (this.sourceBuffer) {
41
+ this.sourceBuffer.addEventListener("updateend", () => {
42
+ resolve();
43
+ }, { once: true });
44
+ this.sourceBuffer.appendBuffer(buffer);
45
+ }
46
+ else {
47
+ reject();
48
+ }
49
+ });
50
+ });
51
+ }
52
+ clearBuffer() {
53
+ // this.operationsQueue.push(() => {
54
+ // return new Promise((resolve, reject) => {
55
+ // if (this.sourceBuffer) {
56
+ // this.sourceBuffer.addEventListener(
57
+ // "updateend",
58
+ // () => {
59
+ // resolve();
60
+ // },
61
+ // { once: true }
62
+ // );
63
+ // if (this.sourceBuffer.buffered.length > 0) {
64
+ // this.sourceBuffer.remove(0, this.sourceBuffer.buffered.end(0));
65
+ // }
66
+ // } else {
67
+ // reject();
68
+ // }
69
+ // });
70
+ // });
71
+ }
72
+ createOperationQueue() {
73
+ return async_1.default.queue((task, callback) => {
74
+ task().then(() => callback());
75
+ }, 1);
76
+ }
77
+ }
78
+ exports.default = AtomicMediaSource;
@@ -0,0 +1,10 @@
1
+ /// <reference types="node" />
2
+ import EventEmitter from "events";
3
+ export declare class ContinuousPlayer extends EventEmitter {
4
+ private atomic;
5
+ private audio;
6
+ constructor();
7
+ start(): void;
8
+ playChunk(audioData: ArrayBuffer): void;
9
+ clear(): void;
10
+ }
package/dist/player.js ADDED
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ContinuousPlayer = void 0;
7
+ const AtomicMediaSource_1 = __importDefault(require("./AtomicMediaSource"));
8
+ const events_1 = __importDefault(require("events"));
9
+ class ContinuousPlayer extends events_1.default {
10
+ constructor() {
11
+ super();
12
+ this.audio = document.createElement("audio");
13
+ this.audio.addEventListener("playing", () => this.emit("speech-start"));
14
+ this.audio.addEventListener("play", () => this.emit("speech-start"));
15
+ this.audio.addEventListener("canplay", () => {
16
+ this.audio.play();
17
+ });
18
+ this.audio.addEventListener("waiting", () => this.emit("speech-end"));
19
+ this.atomic = new AtomicMediaSource_1.default();
20
+ this.audio.src = URL.createObjectURL(this.atomic.mediaSource);
21
+ document.body.appendChild(this.audio);
22
+ }
23
+ start() {
24
+ this.audio.play();
25
+ }
26
+ playChunk(audioData) {
27
+ var _a;
28
+ (_a = this.atomic.sourceBuffer) === null || _a === void 0 ? void 0 : _a.addEventListener("updateend", () => {
29
+ this.audio.play().catch((error) => console.error("Play error:", error));
30
+ }, { once: true });
31
+ this.atomic.appendBuffer(audioData);
32
+ }
33
+ clear() {
34
+ this.audio.pause();
35
+ this.atomic.clearBuffer();
36
+ }
37
+ }
38
+ exports.ContinuousPlayer = ContinuousPlayer;
package/dist/vapi.d.ts CHANGED
@@ -10,7 +10,12 @@ export interface ControlMessages {
10
10
  type: 'control';
11
11
  control: 'mute-assistant' | 'unmute-assistant';
12
12
  }
13
- type VapiClientToServerMessage = AddMessageMessage | ControlMessages;
13
+ export interface SayMessage {
14
+ type: 'say';
15
+ message: string;
16
+ endCallAfterSpoken?: boolean;
17
+ }
18
+ type VapiClientToServerMessage = AddMessageMessage | ControlMessages | SayMessage;
14
19
  type VapiEventNames = 'call-end' | 'call-start' | 'volume-level' | 'speech-start' | 'speech-end' | 'message' | 'error';
15
20
  type VapiEventListeners = {
16
21
  'call-end': () => void;
@@ -42,5 +47,6 @@ export default class Vapi extends VapiEventEmitter {
42
47
  send(message: VapiClientToServerMessage): void;
43
48
  setMuted(mute: boolean): void;
44
49
  isMuted(): boolean;
50
+ say(message: string, endCallAfterSpoken?: boolean): void;
45
51
  }
46
52
  export {};
package/dist/vapi.js CHANGED
@@ -218,5 +218,12 @@ class Vapi extends VapiEventEmitter {
218
218
  throw error;
219
219
  }
220
220
  }
221
+ say(message, endCallAfterSpoken) {
222
+ this.send({
223
+ type: 'say',
224
+ message,
225
+ endCallAfterSpoken
226
+ });
227
+ }
221
228
  }
222
229
  exports.default = Vapi;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vapi-ai/web",
3
- "version": "1.1.6",
3
+ "version": "1.1.7",
4
4
  "description": "",
5
5
  "main": "dist/vapi.js",
6
6
  "types": "dist/vapi.d.ts",
package/vapi.ts CHANGED
@@ -50,7 +50,13 @@ export interface ControlMessages {
50
50
  control: 'mute-assistant' | 'unmute-assistant';
51
51
  }
52
52
 
53
- type VapiClientToServerMessage = AddMessageMessage | ControlMessages;
53
+ export interface SayMessage {
54
+ type: 'say';
55
+ message: string;
56
+ endCallAfterSpoken?: boolean;
57
+ }
58
+
59
+ type VapiClientToServerMessage = AddMessageMessage | ControlMessages | SayMessage;
54
60
 
55
61
  type VapiEventNames =
56
62
  | 'call-end'
@@ -275,4 +281,12 @@ export default class Vapi extends VapiEventEmitter {
275
281
  throw error;
276
282
  }
277
283
  }
284
+
285
+ public say(message: string, endCallAfterSpoken?: boolean) {
286
+ this.send({
287
+ type:'say',
288
+ message,
289
+ endCallAfterSpoken
290
+ })
291
+ }
278
292
  }