@mastra/voice-openai-realtime 0.2.0-alpha.2 → 0.2.0-alpha.3

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.
@@ -1,23 +1,23 @@
1
1
 
2
- > @mastra/voice-openai-realtime@0.2.0-alpha.2 build /home/runner/work/mastra/mastra/voice/openai-realtime-api
2
+ > @mastra/voice-openai-realtime@0.2.0-alpha.3 build /home/runner/work/mastra/mastra/voice/openai-realtime-api
3
3
  > tsup src/index.ts --format esm,cjs --experimental-dts --clean --treeshake
4
4
 
5
5
  CLI Building entry: src/index.ts
6
6
  CLI Using tsconfig: tsconfig.json
7
7
  CLI tsup v8.4.0
8
8
  TSC Build start
9
- TSC ⚡️ Build success in 7564ms
9
+ TSC ⚡️ Build success in 10105ms
10
10
  DTS Build start
11
11
  CLI Target: es2022
12
12
  Analysis will use the bundled TypeScript version 5.8.2
13
13
  Writing package typings: /home/runner/work/mastra/mastra/voice/openai-realtime-api/dist/_tsup-dts-rollup.d.ts
14
14
  Analysis will use the bundled TypeScript version 5.8.2
15
15
  Writing package typings: /home/runner/work/mastra/mastra/voice/openai-realtime-api/dist/_tsup-dts-rollup.d.cts
16
- DTS ⚡️ Build success in 11137ms
16
+ DTS ⚡️ Build success in 11772ms
17
17
  CLI Cleaning output folder
18
18
  ESM Build start
19
19
  CJS Build start
20
- ESM dist/index.js 18.58 KB
21
- ESM ⚡️ Build success in 700ms
22
- CJS dist/index.cjs 18.64 KB
23
- CJS ⚡️ Build success in 920ms
20
+ ESM dist/index.js 18.72 KB
21
+ ESM ⚡️ Build success in 762ms
22
+ CJS dist/index.cjs 18.77 KB
23
+ CJS ⚡️ Build success in 764ms
package/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # @mastra/voice-openai-realtime
2
2
 
3
+ ## 0.2.0-alpha.3
4
+
5
+ ### Minor Changes
6
+
7
+ - 9aaa64b: Don't connect the ws connection until connect is called
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [9ee4293]
12
+ - @mastra/core@0.8.4-alpha.2
13
+
3
14
  ## 0.2.0-alpha.2
4
15
 
5
16
  ### Minor Changes
@@ -43,7 +43,8 @@ export declare type OpenAIExecuteFunction = (args: any) => Promise<any>;
43
43
  * ```
44
44
  */
45
45
  export declare class OpenAIRealtimeVoice extends MastraVoice {
46
- private ws;
46
+ private options;
47
+ private ws?;
47
48
  private state;
48
49
  private client;
49
50
  private events;
@@ -43,7 +43,8 @@ export declare type OpenAIExecuteFunction = (args: any) => Promise<any>;
43
43
  * ```
44
44
  */
45
45
  export declare class OpenAIRealtimeVoice extends MastraVoice {
46
- private ws;
46
+ private options;
47
+ private ws?;
47
48
  private state;
48
49
  private client;
49
50
  private events;
package/dist/index.cjs CHANGED
@@ -76,15 +76,6 @@ var DEFAULT_URL = "wss://api.openai.com/v1/realtime";
76
76
  var DEFAULT_MODEL = "gpt-4o-mini-realtime-preview-2024-12-17";
77
77
  var VOICES = ["alloy", "ash", "ballad", "coral", "echo", "sage", "shimmer", "verse"];
78
78
  var OpenAIRealtimeVoice = class extends voice.MastraVoice {
79
- ws;
80
- state;
81
- client;
82
- events;
83
- instructions;
84
- tools;
85
- debug;
86
- queue = [];
87
- transcriber;
88
79
  /**
89
80
  * Creates a new instance of OpenAIRealtimeVoice.
90
81
  *
@@ -108,22 +99,23 @@ var OpenAIRealtimeVoice = class extends voice.MastraVoice {
108
99
  */
109
100
  constructor(options = {}) {
110
101
  super();
111
- const url = `${options.url || DEFAULT_URL}?model=${options.model || DEFAULT_MODEL}`;
112
- const apiKey = options.apiKey || process.env.OPENAI_API_KEY;
113
- this.ws = new ws.WebSocket(url, void 0, {
114
- headers: {
115
- Authorization: "Bearer " + apiKey,
116
- "OpenAI-Beta": "realtime=v1"
117
- }
118
- });
102
+ this.options = options;
119
103
  this.client = new events.EventEmitter();
120
104
  this.state = "close";
121
105
  this.events = {};
122
106
  this.speaker = options.speaker || DEFAULT_VOICE;
123
107
  this.transcriber = options.transcriber || DEFAULT_TRANSCRIBER;
124
108
  this.debug = options.debug || false;
125
- this.setupEventListeners();
126
109
  }
110
+ ws;
111
+ state;
112
+ client;
113
+ events;
114
+ instructions;
115
+ tools;
116
+ debug;
117
+ queue = [];
118
+ transcriber;
127
119
  /**
128
120
  * Returns a list of available voice speakers.
129
121
  *
@@ -300,7 +292,7 @@ var OpenAIRealtimeVoice = class extends voice.MastraVoice {
300
292
  }
301
293
  waitForOpen() {
302
294
  return new Promise((resolve) => {
303
- this.ws.on("open", resolve);
295
+ this.ws?.on("open", resolve);
304
296
  });
305
297
  }
306
298
  waitForSessionCreated() {
@@ -321,6 +313,15 @@ var OpenAIRealtimeVoice = class extends voice.MastraVoice {
321
313
  * ```
322
314
  */
323
315
  async connect() {
316
+ const url = `${this.options.url || DEFAULT_URL}?model=${this.options.model || DEFAULT_MODEL}`;
317
+ const apiKey = this.options.apiKey || process.env.OPENAI_API_KEY;
318
+ this.ws = new ws.WebSocket(url, void 0, {
319
+ headers: {
320
+ Authorization: "Bearer " + apiKey,
321
+ "OpenAI-Beta": "realtime=v1"
322
+ }
323
+ });
324
+ this.setupEventListeners();
324
325
  await this.waitForOpen();
325
326
  await this.waitForSessionCreated();
326
327
  const openaiTools = transformTools(this.tools);
@@ -466,6 +467,9 @@ var OpenAIRealtimeVoice = class extends voice.MastraVoice {
466
467
  }
467
468
  setupEventListeners() {
468
469
  const speakerStreams = /* @__PURE__ */ new Map();
470
+ if (!this.ws) {
471
+ throw new Error("WebSocket not initialized");
472
+ }
469
473
  this.ws.on("message", (message) => {
470
474
  const data = JSON.parse(message.toString());
471
475
  this.client.emit(data.type, data);
@@ -478,7 +482,7 @@ var OpenAIRealtimeVoice = class extends voice.MastraVoice {
478
482
  this.emit("session.created", ev);
479
483
  const queue = this.queue.splice(0, this.queue.length);
480
484
  for (const ev2 of queue) {
481
- this.ws.send(JSON.stringify(ev2));
485
+ this.ws?.send(JSON.stringify(ev2));
482
486
  }
483
487
  });
484
488
  this.client.on("session.updated", (ev) => {
@@ -589,10 +593,10 @@ var OpenAIRealtimeVoice = class extends voice.MastraVoice {
589
593
  return btoa(binary);
590
594
  }
591
595
  sendEvent(type, data) {
592
- if (this.ws.readyState !== this.ws.OPEN) {
596
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN) {
593
597
  this.queue.push({ type, ...data });
594
598
  } else {
595
- this.ws.send(
599
+ this.ws?.send(
596
600
  JSON.stringify({
597
601
  type,
598
602
  ...data
package/dist/index.js CHANGED
@@ -74,15 +74,6 @@ var DEFAULT_URL = "wss://api.openai.com/v1/realtime";
74
74
  var DEFAULT_MODEL = "gpt-4o-mini-realtime-preview-2024-12-17";
75
75
  var VOICES = ["alloy", "ash", "ballad", "coral", "echo", "sage", "shimmer", "verse"];
76
76
  var OpenAIRealtimeVoice = class extends MastraVoice {
77
- ws;
78
- state;
79
- client;
80
- events;
81
- instructions;
82
- tools;
83
- debug;
84
- queue = [];
85
- transcriber;
86
77
  /**
87
78
  * Creates a new instance of OpenAIRealtimeVoice.
88
79
  *
@@ -106,22 +97,23 @@ var OpenAIRealtimeVoice = class extends MastraVoice {
106
97
  */
107
98
  constructor(options = {}) {
108
99
  super();
109
- const url = `${options.url || DEFAULT_URL}?model=${options.model || DEFAULT_MODEL}`;
110
- const apiKey = options.apiKey || process.env.OPENAI_API_KEY;
111
- this.ws = new WebSocket(url, void 0, {
112
- headers: {
113
- Authorization: "Bearer " + apiKey,
114
- "OpenAI-Beta": "realtime=v1"
115
- }
116
- });
100
+ this.options = options;
117
101
  this.client = new EventEmitter();
118
102
  this.state = "close";
119
103
  this.events = {};
120
104
  this.speaker = options.speaker || DEFAULT_VOICE;
121
105
  this.transcriber = options.transcriber || DEFAULT_TRANSCRIBER;
122
106
  this.debug = options.debug || false;
123
- this.setupEventListeners();
124
107
  }
108
+ ws;
109
+ state;
110
+ client;
111
+ events;
112
+ instructions;
113
+ tools;
114
+ debug;
115
+ queue = [];
116
+ transcriber;
125
117
  /**
126
118
  * Returns a list of available voice speakers.
127
119
  *
@@ -298,7 +290,7 @@ var OpenAIRealtimeVoice = class extends MastraVoice {
298
290
  }
299
291
  waitForOpen() {
300
292
  return new Promise((resolve) => {
301
- this.ws.on("open", resolve);
293
+ this.ws?.on("open", resolve);
302
294
  });
303
295
  }
304
296
  waitForSessionCreated() {
@@ -319,6 +311,15 @@ var OpenAIRealtimeVoice = class extends MastraVoice {
319
311
  * ```
320
312
  */
321
313
  async connect() {
314
+ const url = `${this.options.url || DEFAULT_URL}?model=${this.options.model || DEFAULT_MODEL}`;
315
+ const apiKey = this.options.apiKey || process.env.OPENAI_API_KEY;
316
+ this.ws = new WebSocket(url, void 0, {
317
+ headers: {
318
+ Authorization: "Bearer " + apiKey,
319
+ "OpenAI-Beta": "realtime=v1"
320
+ }
321
+ });
322
+ this.setupEventListeners();
322
323
  await this.waitForOpen();
323
324
  await this.waitForSessionCreated();
324
325
  const openaiTools = transformTools(this.tools);
@@ -464,6 +465,9 @@ var OpenAIRealtimeVoice = class extends MastraVoice {
464
465
  }
465
466
  setupEventListeners() {
466
467
  const speakerStreams = /* @__PURE__ */ new Map();
468
+ if (!this.ws) {
469
+ throw new Error("WebSocket not initialized");
470
+ }
467
471
  this.ws.on("message", (message) => {
468
472
  const data = JSON.parse(message.toString());
469
473
  this.client.emit(data.type, data);
@@ -476,7 +480,7 @@ var OpenAIRealtimeVoice = class extends MastraVoice {
476
480
  this.emit("session.created", ev);
477
481
  const queue = this.queue.splice(0, this.queue.length);
478
482
  for (const ev2 of queue) {
479
- this.ws.send(JSON.stringify(ev2));
483
+ this.ws?.send(JSON.stringify(ev2));
480
484
  }
481
485
  });
482
486
  this.client.on("session.updated", (ev) => {
@@ -587,10 +591,10 @@ var OpenAIRealtimeVoice = class extends MastraVoice {
587
591
  return btoa(binary);
588
592
  }
589
593
  sendEvent(type, data) {
590
- if (this.ws.readyState !== this.ws.OPEN) {
594
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN) {
591
595
  this.queue.push({ type, ...data });
592
596
  } else {
593
- this.ws.send(
597
+ this.ws?.send(
594
598
  JSON.stringify({
595
599
  type,
596
600
  ...data
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mastra/voice-openai-realtime",
3
- "version": "0.2.0-alpha.2",
3
+ "version": "0.2.0-alpha.3",
4
4
  "description": "Mastra OpenAI Realtime API integration",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -23,7 +23,7 @@
23
23
  "openai-realtime-api": "^1.0.7",
24
24
  "ws": "^8.18.1",
25
25
  "zod-to-json-schema": "^3.24.5",
26
- "@mastra/core": "^0.8.4-alpha.1"
26
+ "@mastra/core": "^0.8.4-alpha.2"
27
27
  },
28
28
  "devDependencies": {
29
29
  "@microsoft/api-extractor": "^7.52.2",
package/src/index.ts CHANGED
@@ -106,7 +106,7 @@ type RealtimeClientServerEventMap = {
106
106
  * ```
107
107
  */
108
108
  export class OpenAIRealtimeVoice extends MastraVoice {
109
- private ws: WebSocket;
109
+ private ws?: WebSocket;
110
110
  private state: 'close' | 'open';
111
111
  private client: EventEmitter<RealtimeClientServerEventMap>;
112
112
  private events: EventMap;
@@ -138,7 +138,7 @@ export class OpenAIRealtimeVoice extends MastraVoice {
138
138
  * ```
139
139
  */
140
140
  constructor(
141
- options: {
141
+ private options: {
142
142
  model?: string;
143
143
  url?: string;
144
144
  apiKey?: string;
@@ -149,22 +149,12 @@ export class OpenAIRealtimeVoice extends MastraVoice {
149
149
  ) {
150
150
  super();
151
151
 
152
- const url = `${options.url || DEFAULT_URL}?model=${options.model || DEFAULT_MODEL}`;
153
- const apiKey = options.apiKey || process.env.OPENAI_API_KEY;
154
- this.ws = new WebSocket(url, undefined, {
155
- headers: {
156
- Authorization: 'Bearer ' + apiKey,
157
- 'OpenAI-Beta': 'realtime=v1',
158
- },
159
- });
160
-
161
152
  this.client = new EventEmitter();
162
153
  this.state = 'close';
163
154
  this.events = {} as EventMap;
164
155
  this.speaker = options.speaker || DEFAULT_VOICE;
165
156
  this.transcriber = options.transcriber || DEFAULT_TRANSCRIBER;
166
157
  this.debug = options.debug || false;
167
- this.setupEventListeners();
168
158
  }
169
159
 
170
160
  /**
@@ -355,7 +345,7 @@ export class OpenAIRealtimeVoice extends MastraVoice {
355
345
 
356
346
  waitForOpen() {
357
347
  return new Promise(resolve => {
358
- this.ws.on('open', resolve);
348
+ this.ws?.on('open', resolve);
359
349
  });
360
350
  }
361
351
 
@@ -378,6 +368,16 @@ export class OpenAIRealtimeVoice extends MastraVoice {
378
368
  * ```
379
369
  */
380
370
  async connect() {
371
+ const url = `${this.options.url || DEFAULT_URL}?model=${this.options.model || DEFAULT_MODEL}`;
372
+ const apiKey = this.options.apiKey || process.env.OPENAI_API_KEY;
373
+ this.ws = new WebSocket(url, undefined, {
374
+ headers: {
375
+ Authorization: 'Bearer ' + apiKey,
376
+ 'OpenAI-Beta': 'realtime=v1',
377
+ },
378
+ });
379
+
380
+ this.setupEventListeners();
381
381
  await this.waitForOpen();
382
382
  await this.waitForSessionCreated();
383
383
 
@@ -534,6 +534,10 @@ export class OpenAIRealtimeVoice extends MastraVoice {
534
534
  private setupEventListeners(): void {
535
535
  const speakerStreams = new Map<string, StreamWithId>();
536
536
 
537
+ if (!this.ws) {
538
+ throw new Error('WebSocket not initialized');
539
+ }
540
+
537
541
  this.ws.on('message', message => {
538
542
  const data = JSON.parse(message.toString());
539
543
  this.client.emit(data.type, data);
@@ -549,7 +553,7 @@ export class OpenAIRealtimeVoice extends MastraVoice {
549
553
 
550
554
  const queue = this.queue.splice(0, this.queue.length);
551
555
  for (const ev of queue) {
552
- this.ws.send(JSON.stringify(ev));
556
+ this.ws?.send(JSON.stringify(ev));
553
557
  }
554
558
  });
555
559
  this.client.on('session.updated', ev => {
@@ -669,10 +673,10 @@ export class OpenAIRealtimeVoice extends MastraVoice {
669
673
  }
670
674
 
671
675
  private sendEvent(type: string, data: any) {
672
- if (this.ws.readyState !== this.ws.OPEN) {
676
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN) {
673
677
  this.queue.push({ type: type, ...data });
674
678
  } else {
675
- this.ws.send(
679
+ this.ws?.send(
676
680
  JSON.stringify({
677
681
  type: type,
678
682
  ...data,