@lokutor/sdk 1.0.0 → 1.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/dist/index.d.mts CHANGED
@@ -47,7 +47,7 @@ interface LokutorConfig {
47
47
  serverUrl?: string;
48
48
  onTranscription?: (text: string) => void;
49
49
  onResponse?: (text: string) => void;
50
- onAudio?: (data: Buffer) => void;
50
+ onAudio?: (data: Uint8Array) => void;
51
51
  onStatus?: (status: string) => void;
52
52
  onError?: (error: any) => void;
53
53
  }
@@ -98,7 +98,7 @@ declare class VoiceAgentClient {
98
98
  * Send raw PCM audio data to the server
99
99
  * @param audioData Int16 PCM audio buffer
100
100
  */
101
- sendAudio(audioData: Buffer | Uint8Array): void;
101
+ sendAudio(audioData: Uint8Array): void;
102
102
  /**
103
103
  * Handle incoming binary data (audio response)
104
104
  */
@@ -109,7 +109,7 @@ declare class VoiceAgentClient {
109
109
  private handleTextMessage;
110
110
  private audioListeners;
111
111
  private emit;
112
- onAudio(callback: (data: Buffer) => void): void;
112
+ onAudio(callback: (data: Uint8Array) => void): void;
113
113
  /**
114
114
  * Disconnect from the server
115
115
  */
@@ -121,9 +121,6 @@ declare class VoiceAgentClient {
121
121
  declare class TTSClient {
122
122
  private apiKey;
123
123
  private serverUrl;
124
- private onAudioCallback?;
125
- private onVisemesCallback?;
126
- private onErrorCallback?;
127
124
  constructor(config: {
128
125
  apiKey: string;
129
126
  serverUrl?: string;
@@ -141,7 +138,7 @@ declare class TTSClient {
141
138
  speed?: number;
142
139
  steps?: number;
143
140
  visemes?: boolean;
144
- onAudio?: (data: Buffer) => void;
141
+ onAudio?: (data: Uint8Array) => void;
145
142
  onVisemes?: (visemes: any[]) => void;
146
143
  onError?: (error: any) => void;
147
144
  }): Promise<void>;
@@ -157,7 +154,7 @@ declare function simpleConversation(config: LokutorConfig & {
157
154
  */
158
155
  declare function simpleTTS(options: SynthesizeOptions & {
159
156
  apiKey: string;
160
- onAudio: (buf: Buffer) => void;
157
+ onAudio: (buf: Uint8Array) => void;
161
158
  }): Promise<void>;
162
159
 
163
160
  export { AUDIO_CONFIG, DEFAULT_URLS, Language, type LokutorConfig, type SynthesizeOptions, TTSClient, VoiceAgentClient, VoiceStyle, simpleConversation, simpleTTS };
package/dist/index.d.ts CHANGED
@@ -47,7 +47,7 @@ interface LokutorConfig {
47
47
  serverUrl?: string;
48
48
  onTranscription?: (text: string) => void;
49
49
  onResponse?: (text: string) => void;
50
- onAudio?: (data: Buffer) => void;
50
+ onAudio?: (data: Uint8Array) => void;
51
51
  onStatus?: (status: string) => void;
52
52
  onError?: (error: any) => void;
53
53
  }
@@ -98,7 +98,7 @@ declare class VoiceAgentClient {
98
98
  * Send raw PCM audio data to the server
99
99
  * @param audioData Int16 PCM audio buffer
100
100
  */
101
- sendAudio(audioData: Buffer | Uint8Array): void;
101
+ sendAudio(audioData: Uint8Array): void;
102
102
  /**
103
103
  * Handle incoming binary data (audio response)
104
104
  */
@@ -109,7 +109,7 @@ declare class VoiceAgentClient {
109
109
  private handleTextMessage;
110
110
  private audioListeners;
111
111
  private emit;
112
- onAudio(callback: (data: Buffer) => void): void;
112
+ onAudio(callback: (data: Uint8Array) => void): void;
113
113
  /**
114
114
  * Disconnect from the server
115
115
  */
@@ -121,9 +121,6 @@ declare class VoiceAgentClient {
121
121
  declare class TTSClient {
122
122
  private apiKey;
123
123
  private serverUrl;
124
- private onAudioCallback?;
125
- private onVisemesCallback?;
126
- private onErrorCallback?;
127
124
  constructor(config: {
128
125
  apiKey: string;
129
126
  serverUrl?: string;
@@ -141,7 +138,7 @@ declare class TTSClient {
141
138
  speed?: number;
142
139
  steps?: number;
143
140
  visemes?: boolean;
144
- onAudio?: (data: Buffer) => void;
141
+ onAudio?: (data: Uint8Array) => void;
145
142
  onVisemes?: (visemes: any[]) => void;
146
143
  onError?: (error: any) => void;
147
144
  }): Promise<void>;
@@ -157,7 +154,7 @@ declare function simpleConversation(config: LokutorConfig & {
157
154
  */
158
155
  declare function simpleTTS(options: SynthesizeOptions & {
159
156
  apiKey: string;
160
- onAudio: (buf: Buffer) => void;
157
+ onAudio: (buf: Uint8Array) => void;
161
158
  }): Promise<void>;
162
159
 
163
160
  export { AUDIO_CONFIG, DEFAULT_URLS, Language, type LokutorConfig, type SynthesizeOptions, TTSClient, VoiceAgentClient, VoiceStyle, simpleConversation, simpleTTS };
package/dist/index.js CHANGED
@@ -67,7 +67,14 @@ var DEFAULT_URLS = {
67
67
  };
68
68
 
69
69
  // src/client.ts
70
- var import_ws = require("ws");
70
+ function base64ToUint8Array(base64) {
71
+ const binaryString = atob(base64);
72
+ const bytes = new Uint8Array(binaryString.length);
73
+ for (let i = 0; i < binaryString.length; i++) {
74
+ bytes[i] = binaryString.charCodeAt(i);
75
+ }
76
+ return bytes;
77
+ }
71
78
  var VoiceAgentClient = class {
72
79
  ws = null;
73
80
  apiKey;
@@ -100,36 +107,36 @@ var VoiceAgentClient = class {
100
107
  async connect() {
101
108
  return new Promise((resolve, reject) => {
102
109
  try {
103
- console.log(`\u{1F517} Connecting to ${this.serverUrl}...`);
104
- const headers = {};
110
+ let url = this.serverUrl;
105
111
  if (this.apiKey) {
106
- headers["X-API-Key"] = this.apiKey;
112
+ const separator = url.includes("?") ? "&" : "?";
113
+ url += `${separator}api_key=${this.apiKey}`;
107
114
  }
108
- this.ws = new import_ws.WebSocket(this.serverUrl, {
109
- headers
110
- });
111
- this.ws.on("open", () => {
115
+ console.log(`\u{1F517} Connecting to ${this.serverUrl}...`);
116
+ this.ws = new WebSocket(url);
117
+ this.ws.binaryType = "arraybuffer";
118
+ this.ws.onopen = () => {
112
119
  this.isConnected = true;
113
120
  console.log("\u2705 Connected to voice agent!");
114
121
  this.sendConfig();
115
122
  resolve(true);
116
- });
117
- this.ws.on("message", (data, isBinary) => {
118
- if (isBinary) {
119
- this.handleBinaryMessage(data);
123
+ };
124
+ this.ws.onmessage = async (event) => {
125
+ if (event.data instanceof ArrayBuffer) {
126
+ this.handleBinaryMessage(new Uint8Array(event.data));
120
127
  } else {
121
- this.handleTextMessage(data.toString());
128
+ this.handleTextMessage(event.data.toString());
122
129
  }
123
- });
124
- this.ws.on("error", (err) => {
130
+ };
131
+ this.ws.onerror = (err) => {
125
132
  console.error("\u274C WebSocket error:", err);
126
133
  if (this.onError) this.onError(err);
127
134
  if (!this.isConnected) reject(err);
128
- });
129
- this.ws.on("close", () => {
135
+ };
136
+ this.ws.onclose = () => {
130
137
  this.isConnected = false;
131
138
  console.log("Disconnected");
132
- });
139
+ };
133
140
  } catch (err) {
134
141
  if (this.onError) this.onError(err);
135
142
  reject(err);
@@ -152,7 +159,7 @@ var VoiceAgentClient = class {
152
159
  */
153
160
  sendAudio(audioData) {
154
161
  if (this.ws && this.isConnected) {
155
- this.ws.send(audioData, { binary: true });
162
+ this.ws.send(audioData);
156
163
  }
157
164
  }
158
165
  /**
@@ -170,7 +177,7 @@ var VoiceAgentClient = class {
170
177
  switch (msg.type) {
171
178
  case "audio":
172
179
  if (msg.data) {
173
- const buffer = Buffer.from(msg.data, "base64");
180
+ const buffer = base64ToUint8Array(msg.data);
174
181
  this.handleBinaryMessage(buffer);
175
182
  }
176
183
  break;
@@ -224,9 +231,6 @@ var VoiceAgentClient = class {
224
231
  var TTSClient = class {
225
232
  apiKey;
226
233
  serverUrl;
227
- onAudioCallback;
228
- onVisemesCallback;
229
- onErrorCallback;
230
234
  constructor(config) {
231
235
  this.apiKey = config.apiKey;
232
236
  this.serverUrl = config.serverUrl || DEFAULT_URLS.TTS;
@@ -240,12 +244,14 @@ var TTSClient = class {
240
244
  synthesize(options) {
241
245
  return new Promise((resolve, reject) => {
242
246
  try {
243
- const headers = {};
247
+ let url = this.serverUrl;
244
248
  if (this.apiKey) {
245
- headers["X-API-Key"] = this.apiKey;
249
+ const separator = url.includes("?") ? "&" : "?";
250
+ url += `${separator}api_key=${this.apiKey}`;
246
251
  }
247
- const ws = new import_ws.WebSocket(this.serverUrl, { headers });
248
- ws.on("open", () => {
252
+ const ws = new WebSocket(url);
253
+ ws.binaryType = "arraybuffer";
254
+ ws.onopen = () => {
249
255
  const req = {
250
256
  text: options.text,
251
257
  voice: options.voice || "F1" /* F1 */,
@@ -255,27 +261,27 @@ var TTSClient = class {
255
261
  visemes: options.visemes || false
256
262
  };
257
263
  ws.send(JSON.stringify(req));
258
- });
259
- ws.on("message", (data, isBinary) => {
260
- if (isBinary) {
261
- if (options.onAudio) options.onAudio(data);
264
+ };
265
+ ws.onmessage = async (event) => {
266
+ if (event.data instanceof ArrayBuffer) {
267
+ if (options.onAudio) options.onAudio(new Uint8Array(event.data));
262
268
  } else {
263
269
  try {
264
- const msg = JSON.parse(data.toString());
270
+ const msg = JSON.parse(event.data.toString());
265
271
  if (Array.isArray(msg) && options.onVisemes) {
266
272
  options.onVisemes(msg);
267
273
  }
268
274
  } catch (e) {
269
275
  }
270
276
  }
271
- });
272
- ws.on("error", (err) => {
277
+ };
278
+ ws.onerror = (err) => {
273
279
  if (options.onError) options.onError(err);
274
280
  reject(err);
275
- });
276
- ws.on("close", () => {
281
+ };
282
+ ws.onclose = () => {
277
283
  resolve();
278
- });
284
+ };
279
285
  } catch (err) {
280
286
  if (options.onError) options.onError(err);
281
287
  reject(err);
package/dist/index.mjs CHANGED
@@ -34,7 +34,14 @@ var DEFAULT_URLS = {
34
34
  };
35
35
 
36
36
  // src/client.ts
37
- import { WebSocket } from "ws";
37
+ function base64ToUint8Array(base64) {
38
+ const binaryString = atob(base64);
39
+ const bytes = new Uint8Array(binaryString.length);
40
+ for (let i = 0; i < binaryString.length; i++) {
41
+ bytes[i] = binaryString.charCodeAt(i);
42
+ }
43
+ return bytes;
44
+ }
38
45
  var VoiceAgentClient = class {
39
46
  ws = null;
40
47
  apiKey;
@@ -67,36 +74,36 @@ var VoiceAgentClient = class {
67
74
  async connect() {
68
75
  return new Promise((resolve, reject) => {
69
76
  try {
70
- console.log(`\u{1F517} Connecting to ${this.serverUrl}...`);
71
- const headers = {};
77
+ let url = this.serverUrl;
72
78
  if (this.apiKey) {
73
- headers["X-API-Key"] = this.apiKey;
79
+ const separator = url.includes("?") ? "&" : "?";
80
+ url += `${separator}api_key=${this.apiKey}`;
74
81
  }
75
- this.ws = new WebSocket(this.serverUrl, {
76
- headers
77
- });
78
- this.ws.on("open", () => {
82
+ console.log(`\u{1F517} Connecting to ${this.serverUrl}...`);
83
+ this.ws = new WebSocket(url);
84
+ this.ws.binaryType = "arraybuffer";
85
+ this.ws.onopen = () => {
79
86
  this.isConnected = true;
80
87
  console.log("\u2705 Connected to voice agent!");
81
88
  this.sendConfig();
82
89
  resolve(true);
83
- });
84
- this.ws.on("message", (data, isBinary) => {
85
- if (isBinary) {
86
- this.handleBinaryMessage(data);
90
+ };
91
+ this.ws.onmessage = async (event) => {
92
+ if (event.data instanceof ArrayBuffer) {
93
+ this.handleBinaryMessage(new Uint8Array(event.data));
87
94
  } else {
88
- this.handleTextMessage(data.toString());
95
+ this.handleTextMessage(event.data.toString());
89
96
  }
90
- });
91
- this.ws.on("error", (err) => {
97
+ };
98
+ this.ws.onerror = (err) => {
92
99
  console.error("\u274C WebSocket error:", err);
93
100
  if (this.onError) this.onError(err);
94
101
  if (!this.isConnected) reject(err);
95
- });
96
- this.ws.on("close", () => {
102
+ };
103
+ this.ws.onclose = () => {
97
104
  this.isConnected = false;
98
105
  console.log("Disconnected");
99
- });
106
+ };
100
107
  } catch (err) {
101
108
  if (this.onError) this.onError(err);
102
109
  reject(err);
@@ -119,7 +126,7 @@ var VoiceAgentClient = class {
119
126
  */
120
127
  sendAudio(audioData) {
121
128
  if (this.ws && this.isConnected) {
122
- this.ws.send(audioData, { binary: true });
129
+ this.ws.send(audioData);
123
130
  }
124
131
  }
125
132
  /**
@@ -137,7 +144,7 @@ var VoiceAgentClient = class {
137
144
  switch (msg.type) {
138
145
  case "audio":
139
146
  if (msg.data) {
140
- const buffer = Buffer.from(msg.data, "base64");
147
+ const buffer = base64ToUint8Array(msg.data);
141
148
  this.handleBinaryMessage(buffer);
142
149
  }
143
150
  break;
@@ -191,9 +198,6 @@ var VoiceAgentClient = class {
191
198
  var TTSClient = class {
192
199
  apiKey;
193
200
  serverUrl;
194
- onAudioCallback;
195
- onVisemesCallback;
196
- onErrorCallback;
197
201
  constructor(config) {
198
202
  this.apiKey = config.apiKey;
199
203
  this.serverUrl = config.serverUrl || DEFAULT_URLS.TTS;
@@ -207,12 +211,14 @@ var TTSClient = class {
207
211
  synthesize(options) {
208
212
  return new Promise((resolve, reject) => {
209
213
  try {
210
- const headers = {};
214
+ let url = this.serverUrl;
211
215
  if (this.apiKey) {
212
- headers["X-API-Key"] = this.apiKey;
216
+ const separator = url.includes("?") ? "&" : "?";
217
+ url += `${separator}api_key=${this.apiKey}`;
213
218
  }
214
- const ws = new WebSocket(this.serverUrl, { headers });
215
- ws.on("open", () => {
219
+ const ws = new WebSocket(url);
220
+ ws.binaryType = "arraybuffer";
221
+ ws.onopen = () => {
216
222
  const req = {
217
223
  text: options.text,
218
224
  voice: options.voice || "F1" /* F1 */,
@@ -222,27 +228,27 @@ var TTSClient = class {
222
228
  visemes: options.visemes || false
223
229
  };
224
230
  ws.send(JSON.stringify(req));
225
- });
226
- ws.on("message", (data, isBinary) => {
227
- if (isBinary) {
228
- if (options.onAudio) options.onAudio(data);
231
+ };
232
+ ws.onmessage = async (event) => {
233
+ if (event.data instanceof ArrayBuffer) {
234
+ if (options.onAudio) options.onAudio(new Uint8Array(event.data));
229
235
  } else {
230
236
  try {
231
- const msg = JSON.parse(data.toString());
237
+ const msg = JSON.parse(event.data.toString());
232
238
  if (Array.isArray(msg) && options.onVisemes) {
233
239
  options.onVisemes(msg);
234
240
  }
235
241
  } catch (e) {
236
242
  }
237
243
  }
238
- });
239
- ws.on("error", (err) => {
244
+ };
245
+ ws.onerror = (err) => {
240
246
  if (options.onError) options.onError(err);
241
247
  reject(err);
242
- });
243
- ws.on("close", () => {
248
+ };
249
+ ws.onclose = () => {
244
250
  resolve();
245
- });
251
+ };
246
252
  } catch (err) {
247
253
  if (options.onError) options.onError(err);
248
254
  reject(err);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lokutor/sdk",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "JavaScript/TypeScript SDK for Lokutor Real-time Voice AI",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -27,14 +27,11 @@
27
27
  ],
28
28
  "author": "Lokutor AI",
29
29
  "license": "MIT",
30
- "dependencies": {
31
- "ws": "^8.16.0"
32
- },
30
+ "dependencies": {},
33
31
  "devDependencies": {
34
32
  "@types/node": "^20.10.0",
35
- "@types/ws": "^8.5.10",
36
33
  "tsup": "^8.0.1",
37
34
  "typescript": "^5.3.2",
38
35
  "vitest": "^1.0.1"
39
36
  }
40
- }
37
+ }