@vogent/vogent-web-client 0.1.3 → 0.1.5

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 ADDED
@@ -0,0 +1,265 @@
1
+ # Vogent Web Client
2
+
3
+ A TypeScript/JavaScript client library for integrating Vogent into web applications.
4
+
5
+ ## Installation
6
+
7
+ ### Bun
8
+ ```bash
9
+ bun add @vogent/vogent-web-client
10
+ ```
11
+
12
+ ### NPM
13
+ ```bash
14
+ npm install @vogent/vogent-web-client
15
+ ```
16
+
17
+ ### Yarn
18
+ ```bash
19
+ yarn add @vogent/vogent-web-client
20
+ ```
21
+
22
+ ## Prerequisites
23
+
24
+ Before using VogentCall, you need to obtain the following from the Vogent API:
25
+ - `sessionId`: Unique session identifier
26
+ - `dialId`: Unique dial/call identifier
27
+ - `token`: Authentication token
28
+
29
+ You may call the [Create Dial](https://docs.vogent.ai/api-reference/create-a-new-dial) endpoint on the browser to create a browser dial (not a phone call), **but you must be using a public API key**. Do not use a private API key on the client.
30
+
31
+ ## Usage
32
+
33
+ ```typescript
34
+ import { VogentCall } from '@vogent/vogent-web-client';
35
+
36
+ // First, create a dial using the Vogent API
37
+ const response = await fetch('https://api.vogent.ai/api/dials', {
38
+ method: 'POST',
39
+ headers: {
40
+ 'Authorization': 'Bearer pub_vogent_...', // Make sure this is a public key, and not a private key.
41
+ 'Content-Type': 'application/json'
42
+ },
43
+ body: JSON.stringify({
44
+ callAgentId: 'your_call_agent_id',
45
+ browserCall: true // Set to true for web-based calls
46
+ })
47
+ });
48
+
49
+ const { dialToken, sessionId, dialId } = await response.json();
50
+
51
+ // Create a new call instance with the dial details
52
+ const call = new VogentCall({
53
+ sessionId: sessionId,
54
+ dialId: dialId,
55
+ token: dialToken
56
+ });
57
+
58
+ // Start the call
59
+ await call.start();
60
+
61
+ // Connect audio
62
+ const audioConn = await call.connectAudio();
63
+
64
+ // Monitor transcripts in real-time
65
+ const unsubscribe = call.monitorTranscript((transcript) => {
66
+ transcript.forEach(({ text, speaker }) => {
67
+ console.log(`${speaker}: ${text}`);
68
+ });
69
+ });
70
+
71
+ // Listen for status changes
72
+ call.on('status', (status) => {
73
+ console.log('Call status:', status);
74
+ });
75
+
76
+ // When done, clean up
77
+ unsubscribe();
78
+ await call.hangup();
79
+ ```
80
+
81
+ ## API Reference
82
+
83
+ ### Constructor
84
+
85
+ ```typescript
86
+ new VogentCall(dialDetails, config?)
87
+ ```
88
+
89
+ **Parameters:**
90
+
91
+ - `dialDetails` (required):
92
+ - `sessionId` (string): Unique session identifier
93
+ - `dialId` (string): Unique dial/call identifier
94
+ - `token` (string): Authentication token
95
+
96
+ - `config` (optional):
97
+ - `baseUrl` (string): API base URL (defaults to 'https://api.vogent.ai')
98
+
99
+ **Example:**
100
+
101
+ ```typescript
102
+ const call = new VogentCall(
103
+ {
104
+ sessionId: "session_123",
105
+ dialId: "dial_456",
106
+ token: "auth_token_789"
107
+ },
108
+ {
109
+ baseUrl: "https://api.vogent.ai" // optional
110
+ }
111
+ );
112
+ ```
113
+
114
+ ### Methods
115
+
116
+ #### `start()`
117
+
118
+ Starts the call session. Note: This does not connect audio automatically.
119
+
120
+ ```typescript
121
+ await call.start();
122
+ ```
123
+
124
+ **Returns:** `Promise<void>`
125
+
126
+ ---
127
+
128
+ #### `connectAudio(liveListen?)`
129
+
130
+ Establishes the audio connection for the call.
131
+
132
+ ```typescript
133
+ const audioConn = await call.connectAudio();
134
+ ```
135
+
136
+ **Parameters:**
137
+ - `liveListen` (boolean, optional): Set to `true` for monitoring legs (e.g., humans listening to the call who the AI should not interact with). Defaults to `false`.
138
+
139
+ **Returns:** `Promise<VogentAudioConn>` - Audio connection handle
140
+
141
+ **Example:**
142
+
143
+ ```typescript
144
+ // Regular participant
145
+ const audioConn = await call.connectAudio();
146
+
147
+ // Monitor-only participant (live listening)
148
+ const monitorConn = await call.connectAudio(true);
149
+ ```
150
+
151
+ ---
152
+
153
+ #### `monitorTranscript(callback)`
154
+
155
+ Subscribes to real-time transcript updates.
156
+
157
+ ```typescript
158
+ const unsubscribe = call.monitorTranscript((transcript) => {
159
+ // Handle transcript updates
160
+ });
161
+ ```
162
+
163
+ **Parameters:**
164
+ - `callback` (function): Called with transcript updates. Receives an array of transcript objects.
165
+
166
+ **Transcript Object:**
167
+ ```typescript
168
+ type Transcript = {
169
+ text: string; // The transcript text
170
+ speaker: string; // 'HUMAN', 'AI', or 'IVR' (if IVR detection is enabled)
171
+ }[];
172
+ ```
173
+
174
+ **Returns:** `() => void` - Unsubscribe function
175
+
176
+ **Example:**
177
+
178
+ ```typescript
179
+ const unsubscribe = call.monitorTranscript((transcript) => {
180
+ transcript.forEach(({ text, speaker }) => {
181
+ if (speaker === 'AI') {
182
+ console.log('AI said:', text);
183
+ } else if (speaker === 'HUMAN') {
184
+ console.log('Human said:', text);
185
+ }
186
+ });
187
+ });
188
+
189
+ // Later, when you want to stop monitoring
190
+ unsubscribe();
191
+ ```
192
+
193
+ ---
194
+
195
+ #### `on(event, callback)`
196
+
197
+ Registers an event handler for call status changes.
198
+
199
+ ```typescript
200
+ call.on('status', (status) => {
201
+ console.log('Status changed:', status);
202
+ });
203
+ ```
204
+
205
+ **Parameters:**
206
+ - `event` (string): Currently only supports `'status'`
207
+ - `callback` (function): Called when the dial status changes
208
+ ---
209
+
210
+ #### `setPaused(paused)`
211
+
212
+ Pauses or resumes the AI during the call.
213
+
214
+ ```typescript
215
+ await call.setPaused(true); // Pause the AI
216
+ await call.setPaused(false); // Resume the AI
217
+ ```
218
+
219
+ **Parameters:**
220
+ - `paused` (boolean): `true` to pause the AI, `false` to resume
221
+
222
+ **Returns:** `Promise<void>`
223
+
224
+ ---
225
+
226
+ #### `hangup()`
227
+
228
+ Ends the current call.
229
+
230
+ ```typescript
231
+ await call.hangup();
232
+ ```
233
+
234
+ **Returns:** `Promise<void>`
235
+
236
+ ## Utilities
237
+
238
+ ### `dialStatusIsComplete(status)`
239
+
240
+ Helper function to check if a dial status indicates the call has completed.
241
+
242
+ ```typescript
243
+ import { dialStatusIsComplete } from '@vogent/vogent-web-client';
244
+
245
+ call.on('status', (status) => {
246
+ if (dialStatusIsComplete(status)) {
247
+ console.log('Call is complete');
248
+ // Clean up resources
249
+ }
250
+ });
251
+ ```
252
+
253
+ ## TypeScript Support
254
+
255
+ This library is written in TypeScript and includes full type definitions.
256
+
257
+ ```typescript
258
+ import { VogentCall, Transcript, VogentAudioConn } from '@vogent/vogent-web-client';
259
+ ```
260
+
261
+ ## Support
262
+
263
+ For more information and support:
264
+ - Documentation: [https://docs.vogent.ai](https://docs.vogent.ai)
265
+ - Issues: Please report issues on the GitHub repository
@@ -71,7 +71,7 @@ export declare class VogentCall {
71
71
  * @param dialDetails.dialId - Unique dial/call identifier
72
72
  * @param dialDetails.token - Authentication token
73
73
  * @param config - Configuration options
74
- * @param config.baseUrl - API base URL (defaults to 'https://api.getelto.com')
74
+ * @param config.baseUrl - API base URL (defaults to 'https://api.vogent.ai')
75
75
  */
76
76
  constructor(dialDetails: {
77
77
  sessionId: string;
@@ -39,7 +39,7 @@
39
39
  * @see {@link https://docs.vogent.ai} for complete server documentation
40
40
  * @module VogentCall
41
41
  */
42
- import { ApolloClient, createHttpLink, InMemoryCache, split } from '@apollo/client/core';
42
+ import { ApolloClient, createHttpLink, InMemoryCache, split, } from '@apollo/client/core';
43
43
  import { setContext } from '@apollo/client/link/context';
44
44
  import { GraphQLWsLink } from '@apollo/client/link/subscriptions';
45
45
  import { getMainDefinition } from '@apollo/client/utilities';
@@ -60,15 +60,15 @@ export class VogentCall {
60
60
  * @param dialDetails.dialId - Unique dial/call identifier
61
61
  * @param dialDetails.token - Authentication token
62
62
  * @param config - Configuration options
63
- * @param config.baseUrl - API base URL (defaults to 'https://api.getelto.com')
63
+ * @param config.baseUrl - API base URL (defaults to 'https://api.vogent.ai')
64
64
  */
65
65
  constructor(dialDetails, config = {
66
- baseUrl: 'https://api.getelto.com',
66
+ baseUrl: 'https://api.vogent.ai',
67
67
  }) {
68
68
  this._handlers = [];
69
69
  this.sessionId = dialDetails.sessionId;
70
70
  this.dialId = dialDetails.dialId;
71
- let token = dialDetails.token;
71
+ const token = dialDetails.token;
72
72
  const authLink = setContext((_, { headers }) => {
73
73
  return {
74
74
  headers: {
@@ -82,9 +82,9 @@ export class VogentCall {
82
82
  uri: `${this.baseUrl}/query`,
83
83
  headers: {
84
84
  Authorization: `Bearer ${token}`,
85
- }
85
+ },
86
86
  });
87
- const wsBaseUrl = this.baseUrl.replace('https://', 'wss://').replace("http://", "ws://");
87
+ const wsBaseUrl = this.baseUrl.replace('https://', 'wss://').replace('http://', 'ws://');
88
88
  const wsLink = new GraphQLWsLink(createClient({
89
89
  url: `${wsBaseUrl}/query`,
90
90
  connectionParams: () => ({
@@ -175,12 +175,13 @@ export class VogentCall {
175
175
  input: {
176
176
  type: BrowserDialTokenType.DialSession,
177
177
  dialSessionId: this.sessionId,
178
+ liveListen: liveListen,
178
179
  },
179
180
  },
180
181
  });
181
182
  let d;
182
183
  if (token.data.browserDialToken.telephonyProvider === 'livekit') {
183
- d = await LivekitDevice.getDevice(token.data.browserDialToken.token, token.data.browserDialToken.url);
184
+ d = await LivekitDevice.getDevice(token.data.browserDialToken.token, token.data.browserDialToken.url ?? '');
184
185
  }
185
186
  else {
186
187
  d = await VonageDevice.getDevice(token.data.browserDialToken.token, true);
@@ -1,5 +1,5 @@
1
- import { RemoteParticipant, RemoteTrack, RemoteTrackPublication, Room } from 'livekit-client';
2
1
  import { VogentAudioConn } from './VogentDevice';
2
+ import { RemoteParticipant, RemoteTrack, RemoteTrackPublication, Room } from 'livekit-client';
3
3
  export declare class LivekitCall {
4
4
  _room: Room;
5
5
  _params: any;
@@ -8,8 +8,6 @@ export declare class LivekitCall {
8
8
  fn: (...args: any[]) => void;
9
9
  }[];
10
10
  constructor(room: Room);
11
- handleTrackSubscribed(track: RemoteTrack, _publication: RemoteTrackPublication, _participant: RemoteParticipant): void;
12
- handleTrackUnsubscribed(track: RemoteTrack, _publication: RemoteTrackPublication, _participant: RemoteParticipant): void;
13
11
  mute(status: boolean): void;
14
12
  sendDigits(k: string): void;
15
13
  disconnect(): void;
@@ -23,5 +21,7 @@ export declare class LivekitDevice {
23
21
  private constructor();
24
22
  static getDevice(sessionToken: string, url: string): Promise<LivekitDevice>;
25
23
  disconnect(): void;
24
+ handleTrackSubscribed(track: RemoteTrack, _publication: RemoteTrackPublication, _participant: RemoteParticipant): void;
25
+ handleTrackUnsubscribed(track: RemoteTrack, _publication: RemoteTrackPublication, _participant: RemoteParticipant): void;
26
26
  connect(_p: any): Promise<VogentAudioConn>;
27
27
  }
@@ -4,28 +4,6 @@ export class LivekitCall {
4
4
  this._room = room;
5
5
  this._params = {};
6
6
  this._handlers = [];
7
- this._room
8
- .on(RoomEvent.TrackSubscribed, (...args) => {
9
- this.handleTrackSubscribed(...args);
10
- })
11
- .on(RoomEvent.TrackUnsubscribed, (...args) => this.handleTrackUnsubscribed(...args))
12
- .on(RoomEvent.Disconnected, () => this.disconnect());
13
- }
14
- handleTrackSubscribed(track, _publication, _participant) {
15
- console.log('Track subscribed', track);
16
- if (track.kind === 'audio') {
17
- const audioElement = track.attach();
18
- document.body.appendChild(audioElement);
19
- audioElement.style.display = 'none';
20
- }
21
- if (_participant.identity === 'livekit-ai-processor') {
22
- this.sendEvent('track-added', track.mediaStreamTrack);
23
- }
24
- }
25
- handleTrackUnsubscribed(track, _publication, _participant) {
26
- if (track.kind === 'audio') {
27
- console.log('Track unsubscribed', track);
28
- }
29
7
  }
30
8
  mute(status) {
31
9
  if (status) {
@@ -70,6 +48,13 @@ export class LivekitDevice {
70
48
  this._url = url;
71
49
  // speeds up connection attempt
72
50
  this._room.prepareConnection(this._url, this._token);
51
+ this._room
52
+ .on(RoomEvent.TrackSubscribed, this.handleTrackSubscribed)
53
+ .on(RoomEvent.TrackUnsubscribed, this.handleTrackUnsubscribed)
54
+ .on(RoomEvent.Disconnected, (reason) => {
55
+ console.log('Disconnected', reason);
56
+ this.disconnect();
57
+ });
73
58
  }
74
59
  static async getDevice(sessionToken, url) {
75
60
  const room = new Room();
@@ -78,6 +63,18 @@ export class LivekitDevice {
78
63
  disconnect() {
79
64
  this._room.disconnect();
80
65
  }
66
+ handleTrackSubscribed(track, _publication, _participant) {
67
+ if (track.kind === 'audio') {
68
+ const audioElement = track.attach();
69
+ document.body.appendChild(audioElement);
70
+ audioElement.style.display = 'none';
71
+ }
72
+ }
73
+ handleTrackUnsubscribed(track, _publication, _participant) {
74
+ if (track.kind === 'audio') {
75
+ // console.log('Track unsubscribed', track);
76
+ }
77
+ }
81
78
  async connect(_p) {
82
79
  await this._room.connect(this._url, this._token, {});
83
80
  const lkcall = new LivekitCall(this._room);
@@ -14,7 +14,7 @@ export declare class VonageCall {
14
14
  sendDigits(k: string): void;
15
15
  disconnect(): void;
16
16
  sendEvent(evName: string, ...args: any[]): void;
17
- on(ev: 'mute' | 'disconnect', fn: (...args: any[]) => void): void;
17
+ on(ev: 'mute' | 'disconnect' | 'track-added', fn: (...args: any[]) => void): void;
18
18
  }
19
19
  export declare class VonageDevice {
20
20
  _sessionId: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vogent/vogent-web-client",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "license": "MIT",
5
5
  "dependencies": {
6
6
  "@apollo/client": "^3.12.4",
@@ -9,20 +9,41 @@
9
9
  "graphql-ws": "^5.16.0",
10
10
  "livekit-client": "2.15.8"
11
11
  },
12
- "main": "dist/index.js",
13
- "types": "dist/index.d.ts",
12
+ "main": "src/index.ts",
13
+ "types": "src/index.ts",
14
14
  "files": [
15
- "dist"
15
+ "dist",
16
+ "src"
16
17
  ],
17
18
  "exports": {
18
19
  ".": {
19
- "types": "./dist/index.d.ts",
20
- "default": "./dist/index.js"
20
+ "types": "./src/index.ts",
21
+ "default": "./src/index.ts"
22
+ }
23
+ },
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "github:vogent/vogent-web-client"
27
+ },
28
+ "publishConfig": {
29
+ "main": "dist/index.js",
30
+ "types": "dist/index.d.ts",
31
+ "files": [
32
+ "dist"
33
+ ],
34
+ "exports": {
35
+ ".": {
36
+ "types": "./dist/index.d.ts",
37
+ "default": "./dist/index.js"
38
+ }
21
39
  }
22
40
  },
23
41
  "scripts": {
24
- "build": "tsc",
25
- "prepublishOnly": "yarn build"
42
+ "build": "bun run tsc",
43
+ "prepublishOnly": "bun run build",
44
+ "release:patch": "bun version patch && git push && git push --tags",
45
+ "release:minor": "bun version minor && git push && git push --tags",
46
+ "release:major": "bun version major && git push && git push --tags"
26
47
  },
27
48
  "devDependencies": {
28
49
  "@graphql-codegen/cli": "^5.0.3",