@mastra/voice-openai-realtime 0.11.12 → 0.12.0-beta.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/CHANGELOG.md CHANGED
@@ -1,31 +1,67 @@
1
1
  # @mastra/voice-openai-realtime
2
2
 
3
- ## 0.11.12
3
+ ## 0.12.0-beta.0
4
4
 
5
- ### Patch Changes
5
+ ### Minor Changes
6
6
 
7
- - update peerdeps ([`5ca1cca`](https://github.com/mastra-ai/mastra/commit/5ca1ccac61ffa7141e6d9fa8f22d3ad4d03bf5dc))
7
+ - Bump minimum required Node.js version to 22.13.0 ([#9706](https://github.com/mastra-ai/mastra/pull/9706))
8
8
 
9
- - Updated dependencies [[`5ca1cca`](https://github.com/mastra-ai/mastra/commit/5ca1ccac61ffa7141e6d9fa8f22d3ad4d03bf5dc), [`6d7e90d`](https://github.com/mastra-ai/mastra/commit/6d7e90db09713e6250f4d6c3d3cff1b4740e50f9), [`f78b908`](https://github.com/mastra-ai/mastra/commit/f78b9080e11af765969b36b4a619761056030840), [`23c2614`](https://github.com/mastra-ai/mastra/commit/23c26140fdbf04b8c59e8d7d52106d67dad962ec), [`e365eda`](https://github.com/mastra-ai/mastra/commit/e365eda45795b43707310531cac1e2ce4e5a0712)]:
10
- - @mastra/core@0.24.0
9
+ - Rename RuntimeContext to RequestContext ([#9511](https://github.com/mastra-ai/mastra/pull/9511))
11
10
 
12
- ## 0.11.12-alpha.0
11
+ - Update peer dependencies to match core package version bump (1.0.0) ([#9587](https://github.com/mastra-ai/mastra/pull/9587))
13
12
 
14
13
  ### Patch Changes
15
14
 
16
- - update peerdeps ([`5ca1cca`](https://github.com/mastra-ai/mastra/commit/5ca1ccac61ffa7141e6d9fa8f22d3ad4d03bf5dc))
15
+ - Update peer dependencies to match core package version bump (1.0.0) ([#9237](https://github.com/mastra-ai/mastra/pull/9237))
17
16
 
18
- - Updated dependencies [[`5ca1cca`](https://github.com/mastra-ai/mastra/commit/5ca1ccac61ffa7141e6d9fa8f22d3ad4d03bf5dc), [`6d7e90d`](https://github.com/mastra-ai/mastra/commit/6d7e90db09713e6250f4d6c3d3cff1b4740e50f9), [`f78b908`](https://github.com/mastra-ai/mastra/commit/f78b9080e11af765969b36b4a619761056030840), [`23c2614`](https://github.com/mastra-ai/mastra/commit/23c26140fdbf04b8c59e8d7d52106d67dad962ec), [`e365eda`](https://github.com/mastra-ai/mastra/commit/e365eda45795b43707310531cac1e2ce4e5a0712)]:
19
- - @mastra/core@0.24.0-alpha.0
17
+ - Update tool execution signature ([#9587](https://github.com/mastra-ai/mastra/pull/9587))
20
18
 
21
- ## 0.11.11
19
+ Consolidated the 3 different execution contexts to one
22
20
 
23
- ### Patch Changes
21
+ ```typescript
22
+ // before depending on the context the tool was executed in
23
+ tool.execute({ context: data });
24
+ tool.execute({ context: { inputData: data } });
25
+ tool.execute(data);
24
26
 
25
- - Fix peerdependencies ([`eb7c1c8`](https://github.com/mastra-ai/mastra/commit/eb7c1c8c592d8fb16dfd250e337d9cdc73c8d5de))
27
+ // now, for all contexts
28
+ tool.execute(data, context);
29
+ ```
26
30
 
27
- - Updated dependencies []:
28
- - @mastra/core@0.23.1
31
+ **Before:**
32
+
33
+ ```typescript
34
+ inputSchema: z.object({ something: z.string() }),
35
+ execute: async ({ context, tracingContext, runId, ... }) => {
36
+ return doSomething(context.string);
37
+ }
38
+ ```
39
+
40
+ **After:**
41
+
42
+ ```typescript
43
+ inputSchema: z.object({ something: z.string() }),
44
+ execute: async (inputData, context) => {
45
+ const { agent, mcp, workflow, ...sharedContext } = context
46
+
47
+ // context that only an agent would get like toolCallId, messages, suspend, resume, etc
48
+ if (agent) {
49
+ doSomething(inputData.something, agent)
50
+ // context that only a workflow would get like runId, state, suspend, resume, etc
51
+ } else if (workflow) {
52
+ doSomething(inputData.something, workflow)
53
+ // context that only a workflow would get like "extra", "elicitation"
54
+ } else if (mcp) {
55
+ doSomething(inputData.something, mcp)
56
+ } else {
57
+ // Running a tool in no execution context
58
+ return doSomething(inputData.something);
59
+ }
60
+ }
61
+ ```
62
+
63
+ - Updated dependencies [[`39c9743`](https://github.com/mastra-ai/mastra/commit/39c97432d084294f8ba85fbf3ef28098ff21459e), [`f743dbb`](https://github.com/mastra-ai/mastra/commit/f743dbb8b40d1627b5c10c0e6fc154f4ebb6e394), [`fec5129`](https://github.com/mastra-ai/mastra/commit/fec5129de7fc64423ea03661a56cef31dc747a0d), [`0491e7c`](https://github.com/mastra-ai/mastra/commit/0491e7c9b714cb0ba22187ee062147ec2dd7c712), [`f6f4903`](https://github.com/mastra-ai/mastra/commit/f6f4903397314f73362061dc5a3e8e7c61ea34aa), [`0e8ed46`](https://github.com/mastra-ai/mastra/commit/0e8ed467c54d6901a6a365f270ec15d6faadb36c), [`6c049d9`](https://github.com/mastra-ai/mastra/commit/6c049d94063fdcbd5b81c4912a2bf82a92c9cc0b), [`2f897df`](https://github.com/mastra-ai/mastra/commit/2f897df208508f46f51b7625e5dd20c37f93e0e3), [`3443770`](https://github.com/mastra-ai/mastra/commit/3443770662df8eb24c9df3589b2792d78cfcb811), [`f0a07e0`](https://github.com/mastra-ai/mastra/commit/f0a07e0111b3307c5fabfa4094c5c2cfb734fbe6), [`aaa40e7`](https://github.com/mastra-ai/mastra/commit/aaa40e788628b319baa8e889407d11ad626547fa), [`1521d71`](https://github.com/mastra-ai/mastra/commit/1521d716e5daedc74690c983fbd961123c56756b), [`9e1911d`](https://github.com/mastra-ai/mastra/commit/9e1911db2b4db85e0e768c3f15e0d61e319869f6), [`ebac155`](https://github.com/mastra-ai/mastra/commit/ebac15564a590117db7078233f927a7e28a85106), [`dd1c38d`](https://github.com/mastra-ai/mastra/commit/dd1c38d1b75f1b695c27b40d8d9d6ed00d5e0f6f), [`5948e6a`](https://github.com/mastra-ai/mastra/commit/5948e6a5146c83666ba3f294b2be576c82a513fb), [`8940859`](https://github.com/mastra-ai/mastra/commit/89408593658199b4ad67f7b65e888f344e64a442), [`e629310`](https://github.com/mastra-ai/mastra/commit/e629310f1a73fa236d49ec7a1d1cceb6229dc7cc), [`4c6b492`](https://github.com/mastra-ai/mastra/commit/4c6b492c4dd591c6a592520c1f6855d6e936d71f), [`dff01d8`](https://github.com/mastra-ai/mastra/commit/dff01d81ce1f4e4087cfac20fa868e6db138dd14), [`9d819d5`](https://github.com/mastra-ai/mastra/commit/9d819d54b61481639f4008e4694791bddf187edd), [`71c8d6c`](https://github.com/mastra-ai/mastra/commit/71c8d6c161253207b2b9588bdadb7eed604f7253), [`6179a9b`](https://github.com/mastra-ai/mastra/commit/6179a9ba36ffac326de3cc3c43cdc8028d37c251), [`00f4921`](https://github.com/mastra-ai/mastra/commit/00f4921dd2c91a1e5446799599ef7116a8214a1a), [`ca8041c`](https://github.com/mastra-ai/mastra/commit/ca8041cce0379fda22ed293a565bcb5b6ddca68a), [`7051bf3`](https://github.com/mastra-ai/mastra/commit/7051bf38b3b122a069008f861f7bfc004a6d9f6e), [`a8f1494`](https://github.com/mastra-ai/mastra/commit/a8f1494f4bbdc2770bcf327d4c7d869e332183f1), [`0793497`](https://github.com/mastra-ai/mastra/commit/079349753620c40246ffd673e3f9d7d9820beff3), [`5df9cce`](https://github.com/mastra-ai/mastra/commit/5df9cce1a753438413f64c11eeef8f845745c2a8), [`a854ede`](https://github.com/mastra-ai/mastra/commit/a854ede62bf5ac0945a624ac48913dd69c73aabf), [`c576fc0`](https://github.com/mastra-ai/mastra/commit/c576fc0b100b2085afded91a37c97a0ea0ec09c7), [`3defc80`](https://github.com/mastra-ai/mastra/commit/3defc80cf2b88a1b7fc1cc4ddcb91e982a614609), [`16153fe`](https://github.com/mastra-ai/mastra/commit/16153fe7eb13c99401f48e6ca32707c965ee28b9), [`9f4a683`](https://github.com/mastra-ai/mastra/commit/9f4a6833e88b52574665c028fd5508ad5c2f6004), [`bc94344`](https://github.com/mastra-ai/mastra/commit/bc943444a1342d8a662151b7bce1df7dae32f59c), [`57d157f`](https://github.com/mastra-ai/mastra/commit/57d157f0b163a95c3e6c9eae31bdb11d1bfc64f9), [`903f67d`](https://github.com/mastra-ai/mastra/commit/903f67d184504a273893818c02b961f5423a79ad), [`2a90c55`](https://github.com/mastra-ai/mastra/commit/2a90c55a86a9210697d5adaab5ee94584b079adc), [`eb09742`](https://github.com/mastra-ai/mastra/commit/eb09742197f66c4c38154c3beec78313e69760b2), [`96d35f6`](https://github.com/mastra-ai/mastra/commit/96d35f61376bc2b1bf148648a2c1985bd51bef55), [`5cbe88a`](https://github.com/mastra-ai/mastra/commit/5cbe88aefbd9f933bca669fd371ea36bf939ac6d), [`a1bd7b8`](https://github.com/mastra-ai/mastra/commit/a1bd7b8571db16b94eb01588f451a74758c96d65), [`d78b38d`](https://github.com/mastra-ai/mastra/commit/d78b38d898fce285260d3bbb4befade54331617f), [`0633100`](https://github.com/mastra-ai/mastra/commit/0633100a911ad22f5256471bdf753da21c104742), [`c710c16`](https://github.com/mastra-ai/mastra/commit/c710c1652dccfdc4111c8412bca7a6bb1d48b441), [`354ad0b`](https://github.com/mastra-ai/mastra/commit/354ad0b7b1b8183ac567f236a884fc7ede6d7138), [`cfae733`](https://github.com/mastra-ai/mastra/commit/cfae73394f4920635e6c919c8e95ff9a0788e2e5), [`e3dfda7`](https://github.com/mastra-ai/mastra/commit/e3dfda7b11bf3b8c4bb55637028befb5f387fc74), [`844ea5d`](https://github.com/mastra-ai/mastra/commit/844ea5dc0c248961e7bf73629ae7dcff503e853c), [`398fde3`](https://github.com/mastra-ai/mastra/commit/398fde3f39e707cda79372cdae8f9870e3b57c8d), [`f0f8f12`](https://github.com/mastra-ai/mastra/commit/f0f8f125c308f2d0fd36942ef652fd852df7522f), [`0d7618b`](https://github.com/mastra-ai/mastra/commit/0d7618bc650bf2800934b243eca5648f4aeed9c2), [`7b763e5`](https://github.com/mastra-ai/mastra/commit/7b763e52fc3eaf699c2a99f2adf418dd46e4e9a5), [`d36cfbb`](https://github.com/mastra-ai/mastra/commit/d36cfbbb6565ba5f827883cc9bb648eb14befdc1), [`3697853`](https://github.com/mastra-ai/mastra/commit/3697853deeb72017d90e0f38a93c1e29221aeca0), [`b2e45ec`](https://github.com/mastra-ai/mastra/commit/b2e45eca727a8db01a81ba93f1a5219c7183c839), [`d6d49f7`](https://github.com/mastra-ai/mastra/commit/d6d49f7b8714fa19a52ff9c7cf7fb7e73751901e), [`a534e95`](https://github.com/mastra-ai/mastra/commit/a534e9591f83b3cc1ebff99c67edf4cda7bf81d3), [`9d0e7fe`](https://github.com/mastra-ai/mastra/commit/9d0e7feca8ed98de959f53476ee1456073673348), [`53d927c`](https://github.com/mastra-ai/mastra/commit/53d927cc6f03bff33655b7e2b788da445a08731d), [`3f2faf2`](https://github.com/mastra-ai/mastra/commit/3f2faf2e2d685d6c053cc5af1bf9fedf267b2ce5), [`22f64bc`](https://github.com/mastra-ai/mastra/commit/22f64bc1d37149480b58bf2fefe35b79a1e3e7d5), [`83d5942`](https://github.com/mastra-ai/mastra/commit/83d5942669ce7bba4a6ca4fd4da697a10eb5ebdc), [`b7959e6`](https://github.com/mastra-ai/mastra/commit/b7959e6e25a46b480f9ea2217c4c6c588c423791), [`bda6370`](https://github.com/mastra-ai/mastra/commit/bda637009360649aaf579919e7873e33553c273e), [`d7acd8e`](https://github.com/mastra-ai/mastra/commit/d7acd8e987b5d7eff4fd98b0906c17c06a2e83d5), [`c7f1f7d`](https://github.com/mastra-ai/mastra/commit/c7f1f7d24f61f247f018cc2d1f33bf63212959a7), [`0bddc6d`](https://github.com/mastra-ai/mastra/commit/0bddc6d8dbd6f6008c0cba2e4960a2da75a55af1), [`735d8c1`](https://github.com/mastra-ai/mastra/commit/735d8c1c0d19fbc09e6f8b66cf41bc7655993838), [`acf322e`](https://github.com/mastra-ai/mastra/commit/acf322e0f1fd0189684cf529d91c694bea918a45), [`c942802`](https://github.com/mastra-ai/mastra/commit/c942802a477a925b01859a7b8688d4355715caaa), [`a0c8c1b`](https://github.com/mastra-ai/mastra/commit/a0c8c1b87d4fee252aebda73e8637fbe01d761c9), [`cc34739`](https://github.com/mastra-ai/mastra/commit/cc34739c34b6266a91bea561119240a7acf47887), [`c218bd3`](https://github.com/mastra-ai/mastra/commit/c218bd3759e32423735b04843a09404572631014), [`2c4438b`](https://github.com/mastra-ai/mastra/commit/2c4438b87817ab7eed818c7990fef010475af1a3), [`2b8893c`](https://github.com/mastra-ai/mastra/commit/2b8893cb108ef9acb72ee7835cd625610d2c1a4a), [`8e5c75b`](https://github.com/mastra-ai/mastra/commit/8e5c75bdb1d08a42d45309a4c72def4b6890230f), [`e59e0d3`](https://github.com/mastra-ai/mastra/commit/e59e0d32afb5fcf2c9f3c00c8f81f6c21d3a63fa), [`fa8409b`](https://github.com/mastra-ai/mastra/commit/fa8409bc39cfd8ba6643b9db5269b90b22e2a2f7), [`173c535`](https://github.com/mastra-ai/mastra/commit/173c535c0645b0da404fe09f003778f0b0d4e019)]:
64
+ - @mastra/core@1.0.0-beta.0
29
65
 
30
66
  ## 0.11.10
31
67
 
package/README.md CHANGED
@@ -137,7 +137,7 @@ export const menuTool = createTool({
137
137
  query: z.string(),
138
138
  })
139
139
  .required(),
140
- execute: async ({ context }) => {
140
+ execute: async (inputData, context) => {
141
141
  // Implement menu search functionality
142
142
  },
143
143
  });
package/dist/index.cjs CHANGED
@@ -120,7 +120,7 @@ var OpenAIRealtimeVoice = class extends voice.MastraVoice {
120
120
  debug;
121
121
  queue = [];
122
122
  transcriber;
123
- runtimeContext;
123
+ requestContext;
124
124
  /**
125
125
  * Returns a list of available voice speakers.
126
126
  *
@@ -325,10 +325,10 @@ var OpenAIRealtimeVoice = class extends voice.MastraVoice {
325
325
  * // Now ready for voice interactions
326
326
  * ```
327
327
  */
328
- async connect({ runtimeContext } = {}) {
328
+ async connect({ requestContext } = {}) {
329
329
  const url = `${this.options.url || DEFAULT_URL}?model=${this.options.model || DEFAULT_MODEL}`;
330
330
  const apiKey = this.options.apiKey || process.env.OPENAI_API_KEY;
331
- this.runtimeContext = runtimeContext;
331
+ this.requestContext = requestContext;
332
332
  this.ws = new ws.WebSocket(url, void 0, {
333
333
  headers: {
334
334
  Authorization: "Bearer " + apiKey,
@@ -575,7 +575,7 @@ var OpenAIRealtimeVoice = class extends voice.MastraVoice {
575
575
  });
576
576
  }
577
577
  const result = await tool?.execute?.(
578
- { context, runtimeContext: this.runtimeContext },
578
+ { context, requestContext: this.requestContext },
579
579
  {
580
580
  toolCallId: output.call_id,
581
581
  messages: []
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils.ts","../src/index.ts"],"names":["zodToJsonSchema","Readable","MastraVoice","EventEmitter","buffer","WebSocket","ev","PassThrough"],"mappings":"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","file":"index.cjs","sourcesContent":["import { Readable } from 'stream';\nimport type { ToolsInput } from '@mastra/core/agent';\nimport { zodToJsonSchema } from 'zod-to-json-schema';\n\nexport type OpenAIExecuteFunction = (args: any) => Promise<any>;\ntype ToolDefinition = {\n type: 'function';\n name: string;\n description: string;\n parameters: {\n [key: string]: any;\n };\n};\n\ntype TTools = ToolsInput;\nexport const transformTools = (tools?: TTools) => {\n const openaiTools: { openaiTool: ToolDefinition; execute: OpenAIExecuteFunction }[] = [];\n for (const [name, tool] of Object.entries(tools || {})) {\n let parameters: { [key: string]: any };\n\n if ('inputSchema' in tool && tool.inputSchema) {\n if (isZodObject(tool.inputSchema)) {\n parameters = zodToJsonSchema(tool.inputSchema);\n delete parameters.$schema;\n } else {\n parameters = tool.inputSchema;\n }\n } else if ('parameters' in tool) {\n if (isZodObject(tool.parameters)) {\n parameters = zodToJsonSchema(tool.parameters);\n delete parameters.$schema;\n } else {\n parameters = tool.parameters;\n }\n } else {\n console.warn(`Tool ${name} has neither inputSchema nor parameters, skipping`);\n continue;\n }\n const openaiTool: ToolDefinition = {\n type: 'function',\n name,\n description: tool.description || `Tool: ${name}`,\n parameters,\n };\n\n if (tool.execute) {\n // Create an adapter function that works with both ToolAction and VercelTool execute functions\n const executeAdapter = async (args: any) => {\n try {\n if (!tool.execute) {\n throw new Error(`Tool ${name} has no execute function`);\n }\n\n // For ToolAction, the first argument is a context object with the args in a 'context' property\n if ('inputSchema' in tool) {\n return await tool.execute(\n { context: args },\n {\n toolCallId: 'unknown',\n messages: [],\n },\n );\n }\n // For VercelTool, pass args directly\n else {\n // Create a minimal ToolExecutionOptions object with required properties\n const options = {\n toolCallId: 'unknown',\n messages: [],\n };\n return await tool.execute(args, options);\n }\n } catch (error) {\n console.error(`Error executing tool ${name}:`, error);\n throw error;\n }\n };\n openaiTools.push({ openaiTool, execute: executeAdapter });\n } else {\n console.warn(`Tool ${name} has no execute function, skipping`);\n }\n }\n return openaiTools;\n};\n\nexport const isReadableStream = (obj: unknown) => {\n return (\n obj &&\n obj instanceof Readable &&\n typeof obj.read === 'function' &&\n typeof obj.pipe === 'function' &&\n obj.readable === true\n );\n};\n\nfunction isZodObject(schema: unknown) {\n return (\n !!schema &&\n typeof schema === 'object' &&\n '_def' in schema &&\n schema._def &&\n typeof schema._def === 'object' &&\n 'typeName' in schema._def &&\n schema._def.typeName === 'ZodObject'\n );\n}\n","import { EventEmitter } from 'events';\nimport { PassThrough } from 'stream';\nimport type { ToolsInput } from '@mastra/core/agent';\nimport type { RuntimeContext } from '@mastra/core/runtime-context';\nimport { MastraVoice } from '@mastra/core/voice';\nimport type { Realtime, RealtimeServerEvents } from 'openai-realtime-api';\nimport { WebSocket } from 'ws';\nimport { isReadableStream, transformTools } from './utils';\n\n/**\n * Event callback function type\n */\ntype EventCallback = (...args: any[]) => void;\n\ntype StreamWithId = PassThrough & { id: string };\n\n/**\n * Map of event types to their callback arrays\n */\ntype EventMap = {\n transcribing: [{ text: string }];\n writing: [{ text: string }];\n speaking: [{ audio: string }];\n speaker: [StreamWithId];\n error: [Error];\n} & {\n [key: string]: EventCallback[];\n};\n\n/** Default voice for text-to-speech. 'alloy' provides a neutral, balanced voice suitable for most use cases */\nconst DEFAULT_VOICE: Realtime.Voice = 'alloy';\n\nconst DEFAULT_TRANSCRIBER: Realtime.AudioTranscriptionModel = 'whisper-1';\n\nconst DEFAULT_URL = 'wss://api.openai.com/v1/realtime';\n\n/**\n * Default model for real-time voice interactions.\n * This model is optimized for low-latency responses while maintaining high quality output.\n */\nconst DEFAULT_MODEL = 'gpt-4o-mini-realtime-preview-2024-12-17';\n\n// /**\n// * Default Voice Activity Detection (VAD) configuration.\n// * These settings control how the system detects speech segments.\n// *\n// * @property {string} type - Uses server-side VAD for better accuracy\n// * @property {number} threshold - Speech detection sensitivity (0.5 = balanced)\n// * @property {number} prefix_padding_ms - Includes 1 second of audio before speech\n// * @property {number} silence_duration_ms - Waits 1 second of silence before ending turn\n// */\n// const DEFAULT_VAD_CONFIG = {\n// type: 'server_vad',\n// threshold: 0.5,\n// prefix_padding_ms: 1000,\n// silence_duration_ms: 1000,\n// } as Realtime.TurnDetection;\n\ntype TTools = ToolsInput;\n\n/**\n * Available voice options for text-to-speech.\n * Each voice has unique characteristics suitable for different use cases:\n * - alloy: Neutral and balanced\n * - echo: Warm and natural\n * - shimmer: Clear and expressive\n * - And more...\n */\nconst VOICES = ['alloy', 'ash', 'ballad', 'coral', 'echo', 'sage', 'shimmer', 'verse'];\n\ntype RealtimeClientServerEventMap = {\n [K in RealtimeServerEvents.EventType]: [RealtimeServerEvents.EventMap[K]];\n} & {\n ['conversation.item.input_audio_transcription.delta']: [{ delta: string; response_id: string }];\n ['conversation.item.input_audio_transcription.done']: [{ response_id: string }];\n};\n\n/**\n * OpenAIRealtimeVoice provides real-time voice interaction capabilities using OpenAI's\n * WebSocket-based API. It supports:\n * - Real-time text-to-speech\n * - Speech-to-text (transcription)\n * - Voice activity detection\n * - Multiple voice options\n * - Event-based audio streaming\n *\n * The class manages WebSocket connections, audio streaming, and event handling\n * for seamless voice interactions.\n *\n * @extends MastraVoice\n *\n * @example\n * ```typescript\n * const voice = new OpenAIRealtimeVoice({\n * apiKey: process.env.OPENAI_API_KEY,\n * model: 'gpt-4o-mini-realtime'\n * });\n *\n * await voice.open();\n * voice.on('speaking', (audioData) => {\n * // Handle audio data\n * });\n *\n * await voice.speak('Hello, how can I help you today?');\n * ```\n */\nexport class OpenAIRealtimeVoice extends MastraVoice {\n private ws?: WebSocket;\n private state: 'close' | 'open';\n private client: EventEmitter<RealtimeClientServerEventMap>;\n private events: EventMap;\n private instructions?: string;\n private tools?: TTools;\n private debug: boolean;\n private queue: unknown[] = [];\n private transcriber: Realtime.AudioTranscriptionModel;\n private runtimeContext?: RuntimeContext;\n /**\n * Creates a new instance of OpenAIRealtimeVoice.\n *\n * @param options - Configuration options for the voice instance\n * @param options.url - The base URL for the OpenAI Realtime API\n * @param options.model - The model ID to use (defaults to GPT-4 Mini Realtime)\n * @param options.apiKey - OpenAI API key. Falls back to process.env.OPENAI_API_KEY\n * @param options.speaker - Voice ID to use (defaults to 'alloy')\n * @param options.debug - Enable debug mode\n *\n * @example\n * ```typescript\n * const voice = new OpenAIRealtimeVoice({\n * apiKey: 'your-api-key',\n * model: 'gpt-4o-mini-realtime',\n * speaker: 'alloy'\n * });\n * ```\n */\n constructor(\n private options: {\n model?: string;\n url?: string;\n apiKey?: string;\n speaker?: Realtime.Voice;\n transcriber?: Realtime.AudioTranscriptionModel;\n debug?: boolean;\n } = {},\n ) {\n super();\n\n this.client = new EventEmitter();\n this.state = 'close';\n this.events = {} as EventMap;\n this.speaker = options.speaker || DEFAULT_VOICE;\n this.transcriber = options.transcriber || DEFAULT_TRANSCRIBER;\n this.debug = options.debug || false;\n }\n\n /**\n * Returns a list of available voice speakers.\n *\n * @returns Promise resolving to an array of voice objects, each containing at least a voiceId\n *\n * @example\n * ```typescript\n * const speakers = await voice.getSpeakers();\n * // speakers = [{ voiceId: 'alloy' }, { voiceId: 'echo' }, ...]\n * ```\n */\n getSpeakers(): Promise<Array<{ voiceId: string; [key: string]: any }>> {\n return Promise.resolve(VOICES.map(v => ({ voiceId: v })));\n }\n\n /**\n * Disconnects from the OpenAI realtime session and cleans up resources.\n * Should be called when you're done with the voice instance.\n *\n * @example\n * ```typescript\n * voice.close(); // Disconnects and cleans up\n * ```\n */\n close() {\n if (!this.ws) return;\n this.ws.close();\n this.state = 'close';\n }\n\n /**\n * Equips the voice instance with a set of instructions.\n * Instructions allow the model to perform additional actions during conversations.\n *\n * @param instructions - Optional instructions to addInstructions\n * @returns Transformed instructions ready for use with the model\n *\n * @example\n * ```typescript\n * voice.addInstructions('You are a helpful assistant.');\n * ```\n */\n addInstructions(instructions?: string) {\n this.instructions = instructions;\n }\n\n /**\n * Equips the voice instance with a set of tools.\n * Tools allow the model to perform additional actions during conversations.\n *\n * @param tools - Optional tools configuration to addTools\n * @returns Transformed tools configuration ready for use with the model\n *\n * @example\n * ```typescript\n * const tools = {\n * search: async (query: string) => { ... },\n * calculate: (expression: string) => { ... }\n * };\n * voice.addTools(tools);\n * ```\n */\n addTools(tools?: TTools) {\n this.tools = tools || {};\n }\n\n /**\n * Emits a speaking event using the configured voice model.\n * Can accept either a string or a readable stream as input.\n *\n * @param input - The text to convert to speech, or a readable stream containing the text\n * @param options - Optional configuration for this specific speech request\n * @param options.speaker - Override the voice to use for this specific request\n *\n * @throws {Error} If the input text is empty\n *\n * @example\n * ```typescript\n * // Simple text to speech\n * await voice.speak('Hello world');\n *\n * // With custom voice\n * await voice.speak('Hello world', { speaker: 'echo' });\n *\n * // Using a stream\n * const stream = fs.createReadStream('text.txt');\n * await voice.speak(stream);\n * ```\n */\n async speak(input: string | NodeJS.ReadableStream, options?: { speaker?: Realtime.Voice }): Promise<void> {\n if (typeof input !== 'string') {\n const chunks: Buffer[] = [];\n for await (const chunk of input) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));\n }\n input = Buffer.concat(chunks).toString('utf-8');\n }\n\n if (input.trim().length === 0) {\n throw new Error('Input text is empty');\n }\n\n this.sendEvent('response.create', {\n response: {\n instructions: `Repeat the following text: ${input}`,\n voice: options?.speaker ? options.speaker : undefined,\n },\n });\n }\n\n /**\n * Updates the session configuration for the voice instance.\n * This can be used to modify voice settings, turn detection, and other parameters.\n *\n * @param sessionConfig - New session configuration to apply\n *\n * @example\n * ```typescript\n * voice.updateConfig({\n * voice: 'echo',\n * turn_detection: {\n * type: 'server_vad',\n * threshold: 0.5,\n * silence_duration_ms: 1000\n * }\n * });\n * ```\n */\n updateConfig(sessionConfig: unknown): void {\n this.sendEvent('session.update', { session: sessionConfig });\n }\n\n /**\n * Checks if listening capabilities are enabled.\n *\n * @returns {Promise<{ enabled: boolean }>}\n */\n async getListener() {\n return { enabled: true };\n }\n\n /**\n * Processes audio input for speech recognition.\n * Takes a readable stream of audio data and emits a writing event.\n * The output of the writing event is int16 audio data.\n *\n * @param audioData - Readable stream containing the audio data to process\n * @param options - Optional configuration for audio processing\n *\n * @throws {Error} If the audio data format is not supported\n *\n * @example\n * ```typescript\n * // Process audio from a file\n * const audioStream = fs.createReadStream('audio.raw');\n * await voice.listen(audioStream);\n *\n * // Process audio with options\n * await voice.listen(microphoneStream, {\n * format: 'int16',\n * sampleRate: 24000\n * });\n * ```\n */\n async listen(audioData: NodeJS.ReadableStream): Promise<void> {\n if (isReadableStream(audioData)) {\n const chunks: Buffer[] = [];\n for await (const chunk of audioData) {\n const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n chunks.push(buffer);\n }\n\n const buffer = Buffer.concat(chunks);\n const int16Array = new Int16Array(buffer.buffer, buffer.byteOffset ?? 0, (buffer.byteLength ?? 0) / 2);\n const base64Audio = this.int16ArrayToBase64(int16Array);\n\n this.sendEvent('conversation.item.create', {\n item: {\n type: 'message',\n role: 'user',\n content: [{ type: 'input_audio', audio: base64Audio }],\n },\n });\n\n this.sendEvent('response.create', {\n response: {\n modalities: ['text'],\n instructions: `ONLY repeat the input and DO NOT say anything else`,\n },\n });\n } else {\n this.emit('error', new Error('Unsupported audio data format'));\n }\n }\n\n waitForOpen() {\n return new Promise(resolve => {\n this.ws?.on('open', resolve);\n });\n }\n\n waitForSessionCreated() {\n return new Promise(resolve => {\n this.client.on('session.created', resolve);\n });\n }\n\n /**\n * Establishes a connection to the OpenAI realtime service.\n * Must be called before using speak, listen, or relay functions.\n *\n * @throws {Error} If connection fails or session creation times out\n *\n * @example\n * ```typescript\n * await voice.open();\n * // Now ready for voice interactions\n * ```\n */\n async connect({ runtimeContext }: { runtimeContext?: RuntimeContext } = {}) {\n const url = `${this.options.url || DEFAULT_URL}?model=${this.options.model || DEFAULT_MODEL}`;\n const apiKey = this.options.apiKey || process.env.OPENAI_API_KEY;\n this.runtimeContext = runtimeContext;\n\n this.ws = new WebSocket(url, undefined, {\n headers: {\n Authorization: 'Bearer ' + apiKey,\n 'OpenAI-Beta': 'realtime=v1',\n },\n });\n\n this.setupEventListeners();\n await Promise.all([this.waitForOpen(), this.waitForSessionCreated()]);\n\n const openaiTools = transformTools(this.tools);\n this.updateConfig({\n instructions: this.instructions,\n tools: openaiTools.map(t => t.openaiTool),\n input_audio_transcription: {\n model: this.transcriber,\n },\n voice: this.speaker,\n });\n this.state = 'open';\n }\n\n disconnect() {\n this.state = 'close';\n this.ws?.close();\n }\n\n /**\n * Streams audio data in real-time to the OpenAI service.\n * Useful for continuous audio streaming scenarios like live microphone input.\n * Must be in 'open' state before calling this method.\n *\n * @param audioData - Readable stream of audio data to relay\n * @throws {Error} If audio format is not supported\n *\n * @example\n * ```typescript\n * // First connect\n * await voice.open();\n *\n * // Then relay audio\n * const micStream = getMicrophoneStream();\n * await voice.relay(micStream);\n * ```\n */\n async send(audioData: NodeJS.ReadableStream | Int16Array, eventId?: string): Promise<void> {\n if (!this.state || this.state !== 'open') {\n console.warn('Cannot relay audio when not open. Call open() first.');\n return;\n }\n\n if (isReadableStream(audioData)) {\n const stream = audioData as NodeJS.ReadableStream;\n stream.on('data', chunk => {\n try {\n const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n this.sendEvent('input_audio_buffer.append', { audio: buffer.toString('base64'), event_id: eventId });\n } catch (err) {\n this.emit('error', err);\n }\n });\n } else if (audioData instanceof Int16Array) {\n try {\n const base64Audio = this.int16ArrayToBase64(audioData);\n this.sendEvent('input_audio_buffer.append', { audio: base64Audio, event_id: eventId });\n } catch (err) {\n this.emit('error', err);\n }\n } else {\n this.emit('error', new Error('Unsupported audio data format'));\n }\n }\n\n /**\n * Sends a response to the OpenAI Realtime API.\n *\n * Trigger a response to the real-time session.\n *\n * @param {Object} params - The parameters object\n * @param {Realtime.ResponseConfig} params.options - Configuration options for the response\n * @returns {Promise<void>} A promise that resolves when the response has been sent\n *\n * @example\n * // Send a simple text response\n * await realtimeVoice.answer({\n * options: {\n * content: \"Hello, how can I help you today?\",\n * voice: \"alloy\"\n * }\n * });\n */\n async answer({ options }: { options?: Realtime.ResponseConfig }) {\n this.sendEvent('response.create', { response: options ?? {} });\n }\n\n /**\n * Registers an event listener for voice events.\n * Available events: 'speaking', 'writing, 'error'\n * Can listen to OpenAI Realtime events by prefixing with 'openAIRealtime:'\n * Such as 'openAIRealtime:conversation.item.completed', 'openAIRealtime:conversation.updated', etc.\n *\n * @param event - Name of the event to listen for\n * @param callback - Function to call when the event occurs\n *\n * @example\n * ```typescript\n * // Listen for speech events\n * voice.on('speaking', (audioData: Int16Array) => {\n * // Handle audio data\n * });\n *\n * // Handle errors\n * voice.on('error', (error: Error) => {\n * console.error('Voice error:', error);\n * });\n * ```\n */\n on(event: string, callback: EventCallback): void {\n if (!this.events[event]) {\n this.events[event] = [];\n }\n this.events[event].push(callback);\n }\n\n /**\n * Removes a previously registered event listener.\n *\n * @param event - Name of the event to stop listening to\n * @param callback - The specific callback function to remove\n *\n * @example\n * ```typescript\n * // Create event handler\n * const handleSpeech = (audioData: Int16Array) => {\n * // Handle audio data\n * };\n *\n * // Add listener\n * voice.on('speaking', handleSpeech);\n *\n * // Later, remove the listener\n * voice.off('speaking', handleSpeech);\n * ```\n */\n off(event: string, callback: EventCallback): void {\n if (!this.events[event]) return;\n\n const index = this.events[event].indexOf(callback);\n if (index !== -1) {\n this.events[event].splice(index, 1);\n }\n }\n\n /**\n * Emit an event with arguments\n * @param event Event name\n * @param args Arguments to pass to the callbacks\n */\n private emit(event: string, ...args: any[]): void {\n if (!this.events[event]) return;\n\n for (const callback of this.events[event]) {\n callback(...args);\n }\n }\n\n private setupEventListeners(): void {\n const speakerStreams = new Map<string, StreamWithId>();\n\n if (!this.ws) {\n throw new Error('WebSocket not initialized');\n }\n\n this.ws.on('message', message => {\n const data = JSON.parse(message.toString());\n this.client.emit(data.type, data);\n\n if (this.debug) {\n const { delta, ...fields } = data;\n console.info(data.type, fields, delta?.length < 100 ? delta : '');\n }\n });\n\n this.client.on('session.created', ev => {\n this.emit('session.created', ev);\n\n const queue = this.queue.splice(0, this.queue.length);\n for (const ev of queue) {\n this.ws?.send(JSON.stringify(ev));\n }\n });\n this.client.on('session.updated', ev => {\n this.emit('session.updated', ev);\n });\n this.client.on('response.created', ev => {\n this.emit('response.created', ev);\n\n const speakerStream = new PassThrough() as StreamWithId;\n\n speakerStream.id = ev.response.id;\n\n speakerStreams.set(ev.response.id, speakerStream);\n this.emit('speaker', speakerStream);\n });\n this.client.on('conversation.item.input_audio_transcription.delta', ev => {\n this.emit('writing', { text: ev.delta, response_id: ev.response_id, role: 'user' });\n });\n this.client.on('conversation.item.input_audio_transcription.done', ev => {\n this.emit('writing', { text: '\\n', response_id: ev.response_id, role: 'user' });\n });\n this.client.on('response.audio.delta', ev => {\n const audio = Buffer.from(ev.delta, 'base64');\n this.emit('speaking', { audio, response_id: ev.response_id });\n\n const stream = speakerStreams.get(ev.response_id);\n stream?.write(audio);\n });\n this.client.on('response.audio.done', ev => {\n this.emit('speaking.done', { response_id: ev.response_id });\n\n const stream = speakerStreams.get(ev.response_id);\n stream?.end();\n });\n this.client.on('response.audio_transcript.delta', ev => {\n this.emit('writing', { text: ev.delta, response_id: ev.response_id, role: 'assistant' });\n });\n this.client.on('response.audio_transcript.done', ev => {\n this.emit('writing', { text: '\\n', response_id: ev.response_id, role: 'assistant' });\n });\n this.client.on('response.text.delta', ev => {\n this.emit('writing', { text: ev.delta, response_id: ev.response_id, role: 'assistant' });\n });\n this.client.on('response.text.done', ev => {\n this.emit('writing', { text: '\\n', response_id: ev.response_id, role: 'assistant' });\n });\n this.client.on('response.done', async ev => {\n await this.handleFunctionCalls(ev);\n this.emit('response.done', ev);\n speakerStreams.delete(ev.response.id);\n });\n this.client.on('error', async ev => {\n this.emit('error', ev);\n });\n }\n\n private async handleFunctionCalls(ev: any) {\n for (const output of ev.response?.output ?? []) {\n if (output.type === 'function_call') {\n await this.handleFunctionCall(output);\n }\n }\n }\n\n private async handleFunctionCall(output: any) {\n try {\n const context = JSON.parse(output.arguments);\n const tool = this.tools?.[output.name];\n if (!tool) {\n console.warn(`Tool \"${output.name}\" not found`);\n return;\n }\n\n if (tool?.execute) {\n this.emit('tool-call-start', {\n toolCallId: output.call_id,\n toolName: output.name,\n toolDescription: tool.description,\n args: context,\n });\n }\n\n const result = await tool?.execute?.(\n { context, runtimeContext: this.runtimeContext },\n {\n toolCallId: output.call_id,\n messages: [],\n },\n );\n\n this.emit('tool-call-result', {\n toolCallId: output.call_id,\n toolName: output.name,\n toolDescription: tool.description,\n args: context,\n result,\n });\n\n this.sendEvent('conversation.item.create', {\n item: {\n type: 'function_call_output',\n call_id: output.call_id,\n output: JSON.stringify(result),\n },\n });\n } catch (e) {\n const err = e as Error;\n console.warn(`Error calling tool \"${output.name}\":`, err.message);\n this.sendEvent('conversation.item.create', {\n item: {\n type: 'function_call_output',\n call_id: output.call_id,\n output: JSON.stringify({ error: err.message }),\n },\n });\n } finally {\n this.sendEvent('response.create', {});\n }\n }\n\n private int16ArrayToBase64(int16Array: Int16Array): string {\n const buffer = new ArrayBuffer(int16Array.length * 2);\n const view = new DataView(buffer);\n for (let i = 0; i < int16Array.length; i++) {\n view.setInt16(i * 2, int16Array[i]!, true);\n }\n const uint8Array = new Uint8Array(buffer);\n let binary = '';\n for (let i = 0; i < uint8Array.length; i++) {\n binary += String.fromCharCode(uint8Array[i]!);\n }\n return btoa(binary);\n }\n\n private sendEvent(type: string, data: any) {\n if (!this.ws || this.ws.readyState !== this.ws.OPEN) {\n this.queue.push({ type: type, ...data });\n } else {\n this.ws?.send(\n JSON.stringify({\n type: type,\n ...data,\n }),\n );\n }\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/utils.ts","../src/index.ts"],"names":["zodToJsonSchema","Readable","MastraVoice","EventEmitter","buffer","WebSocket","ev","PassThrough"],"mappings":"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","file":"index.cjs","sourcesContent":["import { Readable } from 'stream';\nimport type { ToolsInput } from '@mastra/core/agent';\nimport { zodToJsonSchema } from 'zod-to-json-schema';\n\nexport type OpenAIExecuteFunction = (args: any) => Promise<any>;\ntype ToolDefinition = {\n type: 'function';\n name: string;\n description: string;\n parameters: {\n [key: string]: any;\n };\n};\n\ntype TTools = ToolsInput;\nexport const transformTools = (tools?: TTools) => {\n const openaiTools: { openaiTool: ToolDefinition; execute: OpenAIExecuteFunction }[] = [];\n for (const [name, tool] of Object.entries(tools || {})) {\n let parameters: { [key: string]: any };\n\n if ('inputSchema' in tool && tool.inputSchema) {\n if (isZodObject(tool.inputSchema)) {\n parameters = zodToJsonSchema(tool.inputSchema);\n delete parameters.$schema;\n } else {\n parameters = tool.inputSchema;\n }\n } else if ('parameters' in tool) {\n if (isZodObject(tool.parameters)) {\n parameters = zodToJsonSchema(tool.parameters);\n delete parameters.$schema;\n } else {\n parameters = tool.parameters;\n }\n } else {\n console.warn(`Tool ${name} has neither inputSchema nor parameters, skipping`);\n continue;\n }\n const openaiTool: ToolDefinition = {\n type: 'function',\n name,\n description: tool.description || `Tool: ${name}`,\n parameters,\n };\n\n if (tool.execute) {\n // Create an adapter function that works with both ToolAction and VercelTool execute functions\n const executeAdapter = async (args: any) => {\n try {\n if (!tool.execute) {\n throw new Error(`Tool ${name} has no execute function`);\n }\n\n // For ToolAction, the first argument is a context object with the args in a 'context' property\n if ('inputSchema' in tool) {\n return await tool.execute(\n { context: args },\n {\n toolCallId: 'unknown',\n messages: [],\n },\n );\n }\n // For VercelTool, pass args directly\n else {\n // Create a minimal ToolExecutionOptions object with required properties\n const options = {\n toolCallId: 'unknown',\n messages: [],\n };\n return await tool.execute(args, options);\n }\n } catch (error) {\n console.error(`Error executing tool ${name}:`, error);\n throw error;\n }\n };\n openaiTools.push({ openaiTool, execute: executeAdapter });\n } else {\n console.warn(`Tool ${name} has no execute function, skipping`);\n }\n }\n return openaiTools;\n};\n\nexport const isReadableStream = (obj: unknown) => {\n return (\n obj &&\n obj instanceof Readable &&\n typeof obj.read === 'function' &&\n typeof obj.pipe === 'function' &&\n obj.readable === true\n );\n};\n\nfunction isZodObject(schema: unknown) {\n return (\n !!schema &&\n typeof schema === 'object' &&\n '_def' in schema &&\n schema._def &&\n typeof schema._def === 'object' &&\n 'typeName' in schema._def &&\n schema._def.typeName === 'ZodObject'\n );\n}\n","import { EventEmitter } from 'events';\nimport { PassThrough } from 'stream';\nimport type { ToolsInput } from '@mastra/core/agent';\nimport type { RequestContext } from '@mastra/core/request-context';\nimport { MastraVoice } from '@mastra/core/voice';\nimport type { Realtime, RealtimeServerEvents } from 'openai-realtime-api';\nimport { WebSocket } from 'ws';\nimport { isReadableStream, transformTools } from './utils';\n\n/**\n * Event callback function type\n */\ntype EventCallback = (...args: any[]) => void;\n\ntype StreamWithId = PassThrough & { id: string };\n\n/**\n * Map of event types to their callback arrays\n */\ntype EventMap = {\n transcribing: [{ text: string }];\n writing: [{ text: string }];\n speaking: [{ audio: string }];\n speaker: [StreamWithId];\n error: [Error];\n} & {\n [key: string]: EventCallback[];\n};\n\n/** Default voice for text-to-speech. 'alloy' provides a neutral, balanced voice suitable for most use cases */\nconst DEFAULT_VOICE: Realtime.Voice = 'alloy';\n\nconst DEFAULT_TRANSCRIBER: Realtime.AudioTranscriptionModel = 'whisper-1';\n\nconst DEFAULT_URL = 'wss://api.openai.com/v1/realtime';\n\n/**\n * Default model for real-time voice interactions.\n * This model is optimized for low-latency responses while maintaining high quality output.\n */\nconst DEFAULT_MODEL = 'gpt-4o-mini-realtime-preview-2024-12-17';\n\n// /**\n// * Default Voice Activity Detection (VAD) configuration.\n// * These settings control how the system detects speech segments.\n// *\n// * @property {string} type - Uses server-side VAD for better accuracy\n// * @property {number} threshold - Speech detection sensitivity (0.5 = balanced)\n// * @property {number} prefix_padding_ms - Includes 1 second of audio before speech\n// * @property {number} silence_duration_ms - Waits 1 second of silence before ending turn\n// */\n// const DEFAULT_VAD_CONFIG = {\n// type: 'server_vad',\n// threshold: 0.5,\n// prefix_padding_ms: 1000,\n// silence_duration_ms: 1000,\n// } as Realtime.TurnDetection;\n\ntype TTools = ToolsInput;\n\n/**\n * Available voice options for text-to-speech.\n * Each voice has unique characteristics suitable for different use cases:\n * - alloy: Neutral and balanced\n * - echo: Warm and natural\n * - shimmer: Clear and expressive\n * - And more...\n */\nconst VOICES = ['alloy', 'ash', 'ballad', 'coral', 'echo', 'sage', 'shimmer', 'verse'];\n\ntype RealtimeClientServerEventMap = {\n [K in RealtimeServerEvents.EventType]: [RealtimeServerEvents.EventMap[K]];\n} & {\n ['conversation.item.input_audio_transcription.delta']: [{ delta: string; response_id: string }];\n ['conversation.item.input_audio_transcription.done']: [{ response_id: string }];\n};\n\n/**\n * OpenAIRealtimeVoice provides real-time voice interaction capabilities using OpenAI's\n * WebSocket-based API. It supports:\n * - Real-time text-to-speech\n * - Speech-to-text (transcription)\n * - Voice activity detection\n * - Multiple voice options\n * - Event-based audio streaming\n *\n * The class manages WebSocket connections, audio streaming, and event handling\n * for seamless voice interactions.\n *\n * @extends MastraVoice\n *\n * @example\n * ```typescript\n * const voice = new OpenAIRealtimeVoice({\n * apiKey: process.env.OPENAI_API_KEY,\n * model: 'gpt-4o-mini-realtime'\n * });\n *\n * await voice.open();\n * voice.on('speaking', (audioData) => {\n * // Handle audio data\n * });\n *\n * await voice.speak('Hello, how can I help you today?');\n * ```\n */\nexport class OpenAIRealtimeVoice extends MastraVoice {\n private ws?: WebSocket;\n private state: 'close' | 'open';\n private client: EventEmitter<RealtimeClientServerEventMap>;\n private events: EventMap;\n private instructions?: string;\n private tools?: TTools;\n private debug: boolean;\n private queue: unknown[] = [];\n private transcriber: Realtime.AudioTranscriptionModel;\n private requestContext?: RequestContext;\n /**\n * Creates a new instance of OpenAIRealtimeVoice.\n *\n * @param options - Configuration options for the voice instance\n * @param options.url - The base URL for the OpenAI Realtime API\n * @param options.model - The model ID to use (defaults to GPT-4 Mini Realtime)\n * @param options.apiKey - OpenAI API key. Falls back to process.env.OPENAI_API_KEY\n * @param options.speaker - Voice ID to use (defaults to 'alloy')\n * @param options.debug - Enable debug mode\n *\n * @example\n * ```typescript\n * const voice = new OpenAIRealtimeVoice({\n * apiKey: 'your-api-key',\n * model: 'gpt-4o-mini-realtime',\n * speaker: 'alloy'\n * });\n * ```\n */\n constructor(\n private options: {\n model?: string;\n url?: string;\n apiKey?: string;\n speaker?: Realtime.Voice;\n transcriber?: Realtime.AudioTranscriptionModel;\n debug?: boolean;\n } = {},\n ) {\n super();\n\n this.client = new EventEmitter();\n this.state = 'close';\n this.events = {} as EventMap;\n this.speaker = options.speaker || DEFAULT_VOICE;\n this.transcriber = options.transcriber || DEFAULT_TRANSCRIBER;\n this.debug = options.debug || false;\n }\n\n /**\n * Returns a list of available voice speakers.\n *\n * @returns Promise resolving to an array of voice objects, each containing at least a voiceId\n *\n * @example\n * ```typescript\n * const speakers = await voice.getSpeakers();\n * // speakers = [{ voiceId: 'alloy' }, { voiceId: 'echo' }, ...]\n * ```\n */\n getSpeakers(): Promise<Array<{ voiceId: string; [key: string]: any }>> {\n return Promise.resolve(VOICES.map(v => ({ voiceId: v })));\n }\n\n /**\n * Disconnects from the OpenAI realtime session and cleans up resources.\n * Should be called when you're done with the voice instance.\n *\n * @example\n * ```typescript\n * voice.close(); // Disconnects and cleans up\n * ```\n */\n close() {\n if (!this.ws) return;\n this.ws.close();\n this.state = 'close';\n }\n\n /**\n * Equips the voice instance with a set of instructions.\n * Instructions allow the model to perform additional actions during conversations.\n *\n * @param instructions - Optional instructions to addInstructions\n * @returns Transformed instructions ready for use with the model\n *\n * @example\n * ```typescript\n * voice.addInstructions('You are a helpful assistant.');\n * ```\n */\n addInstructions(instructions?: string) {\n this.instructions = instructions;\n }\n\n /**\n * Equips the voice instance with a set of tools.\n * Tools allow the model to perform additional actions during conversations.\n *\n * @param tools - Optional tools configuration to addTools\n * @returns Transformed tools configuration ready for use with the model\n *\n * @example\n * ```typescript\n * const tools = {\n * search: async (query: string) => { ... },\n * calculate: (expression: string) => { ... }\n * };\n * voice.addTools(tools);\n * ```\n */\n addTools(tools?: TTools) {\n this.tools = tools || {};\n }\n\n /**\n * Emits a speaking event using the configured voice model.\n * Can accept either a string or a readable stream as input.\n *\n * @param input - The text to convert to speech, or a readable stream containing the text\n * @param options - Optional configuration for this specific speech request\n * @param options.speaker - Override the voice to use for this specific request\n *\n * @throws {Error} If the input text is empty\n *\n * @example\n * ```typescript\n * // Simple text to speech\n * await voice.speak('Hello world');\n *\n * // With custom voice\n * await voice.speak('Hello world', { speaker: 'echo' });\n *\n * // Using a stream\n * const stream = fs.createReadStream('text.txt');\n * await voice.speak(stream);\n * ```\n */\n async speak(input: string | NodeJS.ReadableStream, options?: { speaker?: Realtime.Voice }): Promise<void> {\n if (typeof input !== 'string') {\n const chunks: Buffer[] = [];\n for await (const chunk of input) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));\n }\n input = Buffer.concat(chunks).toString('utf-8');\n }\n\n if (input.trim().length === 0) {\n throw new Error('Input text is empty');\n }\n\n this.sendEvent('response.create', {\n response: {\n instructions: `Repeat the following text: ${input}`,\n voice: options?.speaker ? options.speaker : undefined,\n },\n });\n }\n\n /**\n * Updates the session configuration for the voice instance.\n * This can be used to modify voice settings, turn detection, and other parameters.\n *\n * @param sessionConfig - New session configuration to apply\n *\n * @example\n * ```typescript\n * voice.updateConfig({\n * voice: 'echo',\n * turn_detection: {\n * type: 'server_vad',\n * threshold: 0.5,\n * silence_duration_ms: 1000\n * }\n * });\n * ```\n */\n updateConfig(sessionConfig: unknown): void {\n this.sendEvent('session.update', { session: sessionConfig });\n }\n\n /**\n * Checks if listening capabilities are enabled.\n *\n * @returns {Promise<{ enabled: boolean }>}\n */\n async getListener() {\n return { enabled: true };\n }\n\n /**\n * Processes audio input for speech recognition.\n * Takes a readable stream of audio data and emits a writing event.\n * The output of the writing event is int16 audio data.\n *\n * @param audioData - Readable stream containing the audio data to process\n * @param options - Optional configuration for audio processing\n *\n * @throws {Error} If the audio data format is not supported\n *\n * @example\n * ```typescript\n * // Process audio from a file\n * const audioStream = fs.createReadStream('audio.raw');\n * await voice.listen(audioStream);\n *\n * // Process audio with options\n * await voice.listen(microphoneStream, {\n * format: 'int16',\n * sampleRate: 24000\n * });\n * ```\n */\n async listen(audioData: NodeJS.ReadableStream): Promise<void> {\n if (isReadableStream(audioData)) {\n const chunks: Buffer[] = [];\n for await (const chunk of audioData) {\n const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n chunks.push(buffer);\n }\n\n const buffer = Buffer.concat(chunks);\n const int16Array = new Int16Array(buffer.buffer, buffer.byteOffset ?? 0, (buffer.byteLength ?? 0) / 2);\n const base64Audio = this.int16ArrayToBase64(int16Array);\n\n this.sendEvent('conversation.item.create', {\n item: {\n type: 'message',\n role: 'user',\n content: [{ type: 'input_audio', audio: base64Audio }],\n },\n });\n\n this.sendEvent('response.create', {\n response: {\n modalities: ['text'],\n instructions: `ONLY repeat the input and DO NOT say anything else`,\n },\n });\n } else {\n this.emit('error', new Error('Unsupported audio data format'));\n }\n }\n\n waitForOpen() {\n return new Promise(resolve => {\n this.ws?.on('open', resolve);\n });\n }\n\n waitForSessionCreated() {\n return new Promise(resolve => {\n this.client.on('session.created', resolve);\n });\n }\n\n /**\n * Establishes a connection to the OpenAI realtime service.\n * Must be called before using speak, listen, or relay functions.\n *\n * @throws {Error} If connection fails or session creation times out\n *\n * @example\n * ```typescript\n * await voice.open();\n * // Now ready for voice interactions\n * ```\n */\n async connect({ requestContext }: { requestContext?: RequestContext } = {}) {\n const url = `${this.options.url || DEFAULT_URL}?model=${this.options.model || DEFAULT_MODEL}`;\n const apiKey = this.options.apiKey || process.env.OPENAI_API_KEY;\n this.requestContext = requestContext;\n\n this.ws = new WebSocket(url, undefined, {\n headers: {\n Authorization: 'Bearer ' + apiKey,\n 'OpenAI-Beta': 'realtime=v1',\n },\n });\n\n this.setupEventListeners();\n await Promise.all([this.waitForOpen(), this.waitForSessionCreated()]);\n\n const openaiTools = transformTools(this.tools);\n this.updateConfig({\n instructions: this.instructions,\n tools: openaiTools.map(t => t.openaiTool),\n input_audio_transcription: {\n model: this.transcriber,\n },\n voice: this.speaker,\n });\n this.state = 'open';\n }\n\n disconnect() {\n this.state = 'close';\n this.ws?.close();\n }\n\n /**\n * Streams audio data in real-time to the OpenAI service.\n * Useful for continuous audio streaming scenarios like live microphone input.\n * Must be in 'open' state before calling this method.\n *\n * @param audioData - Readable stream of audio data to relay\n * @throws {Error} If audio format is not supported\n *\n * @example\n * ```typescript\n * // First connect\n * await voice.open();\n *\n * // Then relay audio\n * const micStream = getMicrophoneStream();\n * await voice.relay(micStream);\n * ```\n */\n async send(audioData: NodeJS.ReadableStream | Int16Array, eventId?: string): Promise<void> {\n if (!this.state || this.state !== 'open') {\n console.warn('Cannot relay audio when not open. Call open() first.');\n return;\n }\n\n if (isReadableStream(audioData)) {\n const stream = audioData as NodeJS.ReadableStream;\n stream.on('data', chunk => {\n try {\n const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n this.sendEvent('input_audio_buffer.append', { audio: buffer.toString('base64'), event_id: eventId });\n } catch (err) {\n this.emit('error', err);\n }\n });\n } else if (audioData instanceof Int16Array) {\n try {\n const base64Audio = this.int16ArrayToBase64(audioData);\n this.sendEvent('input_audio_buffer.append', { audio: base64Audio, event_id: eventId });\n } catch (err) {\n this.emit('error', err);\n }\n } else {\n this.emit('error', new Error('Unsupported audio data format'));\n }\n }\n\n /**\n * Sends a response to the OpenAI Realtime API.\n *\n * Trigger a response to the real-time session.\n *\n * @param {Object} params - The parameters object\n * @param {Realtime.ResponseConfig} params.options - Configuration options for the response\n * @returns {Promise<void>} A promise that resolves when the response has been sent\n *\n * @example\n * // Send a simple text response\n * await realtimeVoice.answer({\n * options: {\n * content: \"Hello, how can I help you today?\",\n * voice: \"alloy\"\n * }\n * });\n */\n async answer({ options }: { options?: Realtime.ResponseConfig }) {\n this.sendEvent('response.create', { response: options ?? {} });\n }\n\n /**\n * Registers an event listener for voice events.\n * Available events: 'speaking', 'writing, 'error'\n * Can listen to OpenAI Realtime events by prefixing with 'openAIRealtime:'\n * Such as 'openAIRealtime:conversation.item.completed', 'openAIRealtime:conversation.updated', etc.\n *\n * @param event - Name of the event to listen for\n * @param callback - Function to call when the event occurs\n *\n * @example\n * ```typescript\n * // Listen for speech events\n * voice.on('speaking', (audioData: Int16Array) => {\n * // Handle audio data\n * });\n *\n * // Handle errors\n * voice.on('error', (error: Error) => {\n * console.error('Voice error:', error);\n * });\n * ```\n */\n on(event: string, callback: EventCallback): void {\n if (!this.events[event]) {\n this.events[event] = [];\n }\n this.events[event].push(callback);\n }\n\n /**\n * Removes a previously registered event listener.\n *\n * @param event - Name of the event to stop listening to\n * @param callback - The specific callback function to remove\n *\n * @example\n * ```typescript\n * // Create event handler\n * const handleSpeech = (audioData: Int16Array) => {\n * // Handle audio data\n * };\n *\n * // Add listener\n * voice.on('speaking', handleSpeech);\n *\n * // Later, remove the listener\n * voice.off('speaking', handleSpeech);\n * ```\n */\n off(event: string, callback: EventCallback): void {\n if (!this.events[event]) return;\n\n const index = this.events[event].indexOf(callback);\n if (index !== -1) {\n this.events[event].splice(index, 1);\n }\n }\n\n /**\n * Emit an event with arguments\n * @param event Event name\n * @param args Arguments to pass to the callbacks\n */\n private emit(event: string, ...args: any[]): void {\n if (!this.events[event]) return;\n\n for (const callback of this.events[event]) {\n callback(...args);\n }\n }\n\n private setupEventListeners(): void {\n const speakerStreams = new Map<string, StreamWithId>();\n\n if (!this.ws) {\n throw new Error('WebSocket not initialized');\n }\n\n this.ws.on('message', message => {\n const data = JSON.parse(message.toString());\n this.client.emit(data.type, data);\n\n if (this.debug) {\n const { delta, ...fields } = data;\n console.info(data.type, fields, delta?.length < 100 ? delta : '');\n }\n });\n\n this.client.on('session.created', ev => {\n this.emit('session.created', ev);\n\n const queue = this.queue.splice(0, this.queue.length);\n for (const ev of queue) {\n this.ws?.send(JSON.stringify(ev));\n }\n });\n this.client.on('session.updated', ev => {\n this.emit('session.updated', ev);\n });\n this.client.on('response.created', ev => {\n this.emit('response.created', ev);\n\n const speakerStream = new PassThrough() as StreamWithId;\n\n speakerStream.id = ev.response.id;\n\n speakerStreams.set(ev.response.id, speakerStream);\n this.emit('speaker', speakerStream);\n });\n this.client.on('conversation.item.input_audio_transcription.delta', ev => {\n this.emit('writing', { text: ev.delta, response_id: ev.response_id, role: 'user' });\n });\n this.client.on('conversation.item.input_audio_transcription.done', ev => {\n this.emit('writing', { text: '\\n', response_id: ev.response_id, role: 'user' });\n });\n this.client.on('response.audio.delta', ev => {\n const audio = Buffer.from(ev.delta, 'base64');\n this.emit('speaking', { audio, response_id: ev.response_id });\n\n const stream = speakerStreams.get(ev.response_id);\n stream?.write(audio);\n });\n this.client.on('response.audio.done', ev => {\n this.emit('speaking.done', { response_id: ev.response_id });\n\n const stream = speakerStreams.get(ev.response_id);\n stream?.end();\n });\n this.client.on('response.audio_transcript.delta', ev => {\n this.emit('writing', { text: ev.delta, response_id: ev.response_id, role: 'assistant' });\n });\n this.client.on('response.audio_transcript.done', ev => {\n this.emit('writing', { text: '\\n', response_id: ev.response_id, role: 'assistant' });\n });\n this.client.on('response.text.delta', ev => {\n this.emit('writing', { text: ev.delta, response_id: ev.response_id, role: 'assistant' });\n });\n this.client.on('response.text.done', ev => {\n this.emit('writing', { text: '\\n', response_id: ev.response_id, role: 'assistant' });\n });\n this.client.on('response.done', async ev => {\n await this.handleFunctionCalls(ev);\n this.emit('response.done', ev);\n speakerStreams.delete(ev.response.id);\n });\n this.client.on('error', async ev => {\n this.emit('error', ev);\n });\n }\n\n private async handleFunctionCalls(ev: any) {\n for (const output of ev.response?.output ?? []) {\n if (output.type === 'function_call') {\n await this.handleFunctionCall(output);\n }\n }\n }\n\n private async handleFunctionCall(output: any) {\n try {\n const context = JSON.parse(output.arguments);\n const tool = this.tools?.[output.name];\n if (!tool) {\n console.warn(`Tool \"${output.name}\" not found`);\n return;\n }\n\n if (tool?.execute) {\n this.emit('tool-call-start', {\n toolCallId: output.call_id,\n toolName: output.name,\n toolDescription: tool.description,\n args: context,\n });\n }\n\n const result = await tool?.execute?.(\n { context, requestContext: this.requestContext },\n {\n toolCallId: output.call_id,\n messages: [],\n },\n );\n\n this.emit('tool-call-result', {\n toolCallId: output.call_id,\n toolName: output.name,\n toolDescription: tool.description,\n args: context,\n result,\n });\n\n this.sendEvent('conversation.item.create', {\n item: {\n type: 'function_call_output',\n call_id: output.call_id,\n output: JSON.stringify(result),\n },\n });\n } catch (e) {\n const err = e as Error;\n console.warn(`Error calling tool \"${output.name}\":`, err.message);\n this.sendEvent('conversation.item.create', {\n item: {\n type: 'function_call_output',\n call_id: output.call_id,\n output: JSON.stringify({ error: err.message }),\n },\n });\n } finally {\n this.sendEvent('response.create', {});\n }\n }\n\n private int16ArrayToBase64(int16Array: Int16Array): string {\n const buffer = new ArrayBuffer(int16Array.length * 2);\n const view = new DataView(buffer);\n for (let i = 0; i < int16Array.length; i++) {\n view.setInt16(i * 2, int16Array[i]!, true);\n }\n const uint8Array = new Uint8Array(buffer);\n let binary = '';\n for (let i = 0; i < uint8Array.length; i++) {\n binary += String.fromCharCode(uint8Array[i]!);\n }\n return btoa(binary);\n }\n\n private sendEvent(type: string, data: any) {\n if (!this.ws || this.ws.readyState !== this.ws.OPEN) {\n this.queue.push({ type: type, ...data });\n } else {\n this.ws?.send(\n JSON.stringify({\n type: type,\n ...data,\n }),\n );\n }\n }\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { ToolsInput } from '@mastra/core/agent';
2
- import type { RuntimeContext } from '@mastra/core/runtime-context';
2
+ import type { RequestContext } from '@mastra/core/request-context';
3
3
  import { MastraVoice } from '@mastra/core/voice';
4
4
  import type { Realtime } from 'openai-realtime-api';
5
5
  /**
@@ -47,7 +47,7 @@ export declare class OpenAIRealtimeVoice extends MastraVoice {
47
47
  private debug;
48
48
  private queue;
49
49
  private transcriber;
50
- private runtimeContext?;
50
+ private requestContext?;
51
51
  /**
52
52
  * Creates a new instance of OpenAIRealtimeVoice.
53
53
  *
@@ -221,8 +221,8 @@ export declare class OpenAIRealtimeVoice extends MastraVoice {
221
221
  * // Now ready for voice interactions
222
222
  * ```
223
223
  */
224
- connect({ runtimeContext }?: {
225
- runtimeContext?: RuntimeContext;
224
+ connect({ requestContext }?: {
225
+ requestContext?: RequestContext;
226
226
  }): Promise<void>;
227
227
  disconnect(): void;
228
228
  /**
package/dist/index.js CHANGED
@@ -118,7 +118,7 @@ var OpenAIRealtimeVoice = class extends MastraVoice {
118
118
  debug;
119
119
  queue = [];
120
120
  transcriber;
121
- runtimeContext;
121
+ requestContext;
122
122
  /**
123
123
  * Returns a list of available voice speakers.
124
124
  *
@@ -323,10 +323,10 @@ var OpenAIRealtimeVoice = class extends MastraVoice {
323
323
  * // Now ready for voice interactions
324
324
  * ```
325
325
  */
326
- async connect({ runtimeContext } = {}) {
326
+ async connect({ requestContext } = {}) {
327
327
  const url = `${this.options.url || DEFAULT_URL}?model=${this.options.model || DEFAULT_MODEL}`;
328
328
  const apiKey = this.options.apiKey || process.env.OPENAI_API_KEY;
329
- this.runtimeContext = runtimeContext;
329
+ this.requestContext = requestContext;
330
330
  this.ws = new WebSocket(url, void 0, {
331
331
  headers: {
332
332
  Authorization: "Bearer " + apiKey,
@@ -573,7 +573,7 @@ var OpenAIRealtimeVoice = class extends MastraVoice {
573
573
  });
574
574
  }
575
575
  const result = await tool?.execute?.(
576
- { context, runtimeContext: this.runtimeContext },
576
+ { context, requestContext: this.requestContext },
577
577
  {
578
578
  toolCallId: output.call_id,
579
579
  messages: []
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils.ts","../src/index.ts"],"names":["buffer","ev"],"mappings":";;;;;;;AAeO,IAAM,cAAA,GAAiB,CAAC,KAAA,KAAmB;AAChD,EAAA,MAAM,cAAgF,EAAC;AACvF,EAAA,KAAA,MAAW,CAAC,MAAM,IAAI,CAAA,IAAK,OAAO,OAAA,CAAQ,KAAA,IAAS,EAAE,CAAA,EAAG;AACtD,IAAA,IAAI,UAAA;AAEJ,IAAA,IAAI,aAAA,IAAiB,IAAA,IAAQ,IAAA,CAAK,WAAA,EAAa;AAC7C,MAAA,IAAI,WAAA,CAAY,IAAA,CAAK,WAAW,CAAA,EAAG;AACjC,QAAA,UAAA,GAAa,eAAA,CAAgB,KAAK,WAAW,CAAA;AAC7C,QAAA,OAAO,UAAA,CAAW,OAAA;AAAA,MACpB,CAAA,MAAO;AACL,QAAA,UAAA,GAAa,IAAA,CAAK,WAAA;AAAA,MACpB;AAAA,IACF,CAAA,MAAA,IAAW,gBAAgB,IAAA,EAAM;AAC/B,MAAA,IAAI,WAAA,CAAY,IAAA,CAAK,UAAU,CAAA,EAAG;AAChC,QAAA,UAAA,GAAa,eAAA,CAAgB,KAAK,UAAU,CAAA;AAC5C,QAAA,OAAO,UAAA,CAAW,OAAA;AAAA,MACpB,CAAA,MAAO;AACL,QAAA,UAAA,GAAa,IAAA,CAAK,UAAA;AAAA,MACpB;AAAA,IACF,CAAA,MAAO;AACL,MAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,KAAA,EAAQ,IAAI,CAAA,iDAAA,CAAmD,CAAA;AAC5E,MAAA;AAAA,IACF;AACA,IAAA,MAAM,UAAA,GAA6B;AAAA,MACjC,IAAA,EAAM,UAAA;AAAA,MACN,IAAA;AAAA,MACA,WAAA,EAAa,IAAA,CAAK,WAAA,IAAe,CAAA,MAAA,EAAS,IAAI,CAAA,CAAA;AAAA,MAC9C;AAAA,KACF;AAEA,IAAA,IAAI,KAAK,OAAA,EAAS;AAEhB,MAAA,MAAM,cAAA,GAAiB,OAAO,IAAA,KAAc;AAC1C,QAAA,IAAI;AACF,UAAA,IAAI,CAAC,KAAK,OAAA,EAAS;AACjB,YAAA,MAAM,IAAI,KAAA,CAAM,CAAA,KAAA,EAAQ,IAAI,CAAA,wBAAA,CAA0B,CAAA;AAAA,UACxD;AAGA,UAAA,IAAI,iBAAiB,IAAA,EAAM;AACzB,YAAA,OAAO,MAAM,IAAA,CAAK,OAAA;AAAA,cAChB,EAAE,SAAS,IAAA,EAAK;AAAA,cAChB;AAAA,gBACE,UAAA,EAAY,SAAA;AAAA,gBACZ,UAAU;AAAC;AACb,aACF;AAAA,UACF,CAAA,MAEK;AAEH,YAAA,MAAM,OAAA,GAAU;AAAA,cACd,UAAA,EAAY,SAAA;AAAA,cACZ,UAAU;AAAC,aACb;AACA,YAAA,OAAO,MAAM,IAAA,CAAK,OAAA,CAAQ,IAAA,EAAM,OAAO,CAAA;AAAA,UACzC;AAAA,QACF,SAAS,KAAA,EAAO;AACd,UAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,qBAAA,EAAwB,IAAI,CAAA,CAAA,CAAA,EAAK,KAAK,CAAA;AACpD,UAAA,MAAM,KAAA;AAAA,QACR;AAAA,MACF,CAAA;AACA,MAAA,WAAA,CAAY,IAAA,CAAK,EAAE,UAAA,EAAY,OAAA,EAAS,gBAAgB,CAAA;AAAA,IAC1D,CAAA,MAAO;AACL,MAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,KAAA,EAAQ,IAAI,CAAA,kCAAA,CAAoC,CAAA;AAAA,IAC/D;AAAA,EACF;AACA,EAAA,OAAO,WAAA;AACT,CAAA;AAEO,IAAM,gBAAA,GAAmB,CAAC,GAAA,KAAiB;AAChD,EAAA,OACE,GAAA,IACA,GAAA,YAAe,QAAA,IACf,OAAO,GAAA,CAAI,IAAA,KAAS,UAAA,IACpB,OAAO,GAAA,CAAI,IAAA,KAAS,UAAA,IACpB,GAAA,CAAI,QAAA,KAAa,IAAA;AAErB,CAAA;AAEA,SAAS,YAAY,MAAA,EAAiB;AACpC,EAAA,OACE,CAAC,CAAC,MAAA,IACF,OAAO,MAAA,KAAW,QAAA,IAClB,UAAU,MAAA,IACV,MAAA,CAAO,QACP,OAAO,MAAA,CAAO,SAAS,QAAA,IACvB,UAAA,IAAc,OAAO,IAAA,IACrB,MAAA,CAAO,KAAK,QAAA,KAAa,WAAA;AAE7B;;;AC3EA,IAAM,aAAA,GAAgC,OAAA;AAEtC,IAAM,mBAAA,GAAwD,WAAA;AAE9D,IAAM,WAAA,GAAc,kCAAA;AAMpB,IAAM,aAAA,GAAgB,yCAAA;AA4BtB,IAAM,MAAA,GAAS,CAAC,OAAA,EAAS,KAAA,EAAO,UAAU,OAAA,EAAS,MAAA,EAAQ,MAAA,EAAQ,SAAA,EAAW,OAAO,CAAA;AAsC9E,IAAM,mBAAA,GAAN,cAAkC,WAAA,CAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA8BnD,WAAA,CACU,OAAA,GAOJ,EAAC,EACL;AACA,IAAA,KAAA,EAAM;AATE,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAWR,IAAA,IAAA,CAAK,MAAA,GAAS,IAAI,YAAA,EAAa;AAC/B,IAAA,IAAA,CAAK,KAAA,GAAQ,OAAA;AACb,IAAA,IAAA,CAAK,SAAS,EAAC;AACf,IAAA,IAAA,CAAK,OAAA,GAAU,QAAQ,OAAA,IAAW,aAAA;AAClC,IAAA,IAAA,CAAK,WAAA,GAAc,QAAQ,WAAA,IAAe,mBAAA;AAC1C,IAAA,IAAA,CAAK,KAAA,GAAQ,QAAQ,KAAA,IAAS,KAAA;AAAA,EAChC;AAAA,EA/CQ,EAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA,YAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,QAAmB,EAAC;AAAA,EACpB,WAAA;AAAA,EACA,cAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmDR,WAAA,GAAuE;AACrE,IAAA,OAAO,OAAA,CAAQ,QAAQ,MAAA,CAAO,GAAA,CAAI,QAAM,EAAE,OAAA,EAAS,CAAA,EAAE,CAAE,CAAC,CAAA;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,KAAA,GAAQ;AACN,IAAA,IAAI,CAAC,KAAK,EAAA,EAAI;AACd,IAAA,IAAA,CAAK,GAAG,KAAA,EAAM;AACd,IAAA,IAAA,CAAK,KAAA,GAAQ,OAAA;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,gBAAgB,YAAA,EAAuB;AACrC,IAAA,IAAA,CAAK,YAAA,GAAe,YAAA;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,SAAS,KAAA,EAAgB;AACvB,IAAA,IAAA,CAAK,KAAA,GAAQ,SAAS,EAAC;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAyBA,MAAM,KAAA,CAAM,KAAA,EAAuC,OAAA,EAAuD;AACxG,IAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,MAAA,MAAM,SAAmB,EAAC;AAC1B,MAAA,WAAA,MAAiB,SAAS,KAAA,EAAO;AAC/B,QAAA,MAAA,CAAO,IAAA,CAAK,MAAA,CAAO,QAAA,CAAS,KAAK,CAAA,GAAI,KAAA,GAAQ,MAAA,CAAO,IAAA,CAAK,MAAA,CAAO,KAAK,CAAC,CAAC,CAAA;AAAA,MACzE;AACA,MAAA,KAAA,GAAQ,MAAA,CAAO,MAAA,CAAO,MAAM,CAAA,CAAE,SAAS,OAAO,CAAA;AAAA,IAChD;AAEA,IAAA,IAAI,KAAA,CAAM,IAAA,EAAK,CAAE,MAAA,KAAW,CAAA,EAAG;AAC7B,MAAA,MAAM,IAAI,MAAM,qBAAqB,CAAA;AAAA,IACvC;AAEA,IAAA,IAAA,CAAK,UAAU,iBAAA,EAAmB;AAAA,MAChC,QAAA,EAAU;AAAA,QACR,YAAA,EAAc,8BAA8B,KAAK,CAAA,CAAA;AAAA,QACjD,KAAA,EAAO,OAAA,EAAS,OAAA,GAAU,OAAA,CAAQ,OAAA,GAAU;AAAA;AAC9C,KACD,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBA,aAAa,aAAA,EAA8B;AACzC,IAAA,IAAA,CAAK,SAAA,CAAU,gBAAA,EAAkB,EAAE,OAAA,EAAS,eAAe,CAAA;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,WAAA,GAAc;AAClB,IAAA,OAAO,EAAE,SAAS,IAAA,EAAK;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAyBA,MAAM,OAAO,SAAA,EAAiD;AAC5D,IAAA,IAAI,gBAAA,CAAiB,SAAS,CAAA,EAAG;AAC/B,MAAA,MAAM,SAAmB,EAAC;AAC1B,MAAA,WAAA,MAAiB,SAAS,SAAA,EAAW;AACnC,QAAA,MAAMA,OAAAA,GAAS,OAAO,QAAA,CAAS,KAAK,IAAI,KAAA,GAAQ,MAAA,CAAO,KAAK,KAAK,CAAA;AACjE,QAAA,MAAA,CAAO,KAAKA,OAAM,CAAA;AAAA,MACpB;AAEA,MAAA,MAAM,MAAA,GAAS,MAAA,CAAO,MAAA,CAAO,MAAM,CAAA;AACnC,MAAA,MAAM,UAAA,GAAa,IAAI,UAAA,CAAW,MAAA,CAAO,MAAA,EAAQ,MAAA,CAAO,UAAA,IAAc,CAAA,EAAA,CAAI,MAAA,CAAO,UAAA,IAAc,CAAA,IAAK,CAAC,CAAA;AACrG,MAAA,MAAM,WAAA,GAAc,IAAA,CAAK,kBAAA,CAAmB,UAAU,CAAA;AAEtD,MAAA,IAAA,CAAK,UAAU,0BAAA,EAA4B;AAAA,QACzC,IAAA,EAAM;AAAA,UACJ,IAAA,EAAM,SAAA;AAAA,UACN,IAAA,EAAM,MAAA;AAAA,UACN,SAAS,CAAC,EAAE,MAAM,aAAA,EAAe,KAAA,EAAO,aAAa;AAAA;AACvD,OACD,CAAA;AAED,MAAA,IAAA,CAAK,UAAU,iBAAA,EAAmB;AAAA,QAChC,QAAA,EAAU;AAAA,UACR,UAAA,EAAY,CAAC,MAAM,CAAA;AAAA,UACnB,YAAA,EAAc,CAAA,kDAAA;AAAA;AAChB,OACD,CAAA;AAAA,IACH,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,IAAA,CAAK,OAAA,EAAS,IAAI,KAAA,CAAM,+BAA+B,CAAC,CAAA;AAAA,IAC/D;AAAA,EACF;AAAA,EAEA,WAAA,GAAc;AACZ,IAAA,OAAO,IAAI,QAAQ,CAAA,OAAA,KAAW;AAC5B,MAAA,IAAA,CAAK,EAAA,EAAI,EAAA,CAAG,MAAA,EAAQ,OAAO,CAAA;AAAA,IAC7B,CAAC,CAAA;AAAA,EACH;AAAA,EAEA,qBAAA,GAAwB;AACtB,IAAA,OAAO,IAAI,QAAQ,CAAA,OAAA,KAAW;AAC5B,MAAA,IAAA,CAAK,MAAA,CAAO,EAAA,CAAG,iBAAA,EAAmB,OAAO,CAAA;AAAA,IAC3C,CAAC,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,OAAA,CAAQ,EAAE,cAAA,EAAe,GAAyC,EAAC,EAAG;AAC1E,IAAA,MAAM,GAAA,GAAM,CAAA,EAAG,IAAA,CAAK,OAAA,CAAQ,GAAA,IAAO,WAAW,CAAA,OAAA,EAAU,IAAA,CAAK,OAAA,CAAQ,KAAA,IAAS,aAAa,CAAA,CAAA;AAC3F,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,OAAA,CAAQ,MAAA,IAAU,QAAQ,GAAA,CAAI,cAAA;AAClD,IAAA,IAAA,CAAK,cAAA,GAAiB,cAAA;AAEtB,IAAA,IAAA,CAAK,EAAA,GAAK,IAAI,SAAA,CAAU,GAAA,EAAK,MAAA,EAAW;AAAA,MACtC,OAAA,EAAS;AAAA,QACP,eAAe,SAAA,GAAY,MAAA;AAAA,QAC3B,aAAA,EAAe;AAAA;AACjB,KACD,CAAA;AAED,IAAA,IAAA,CAAK,mBAAA,EAAoB;AACzB,IAAA,MAAM,OAAA,CAAQ,IAAI,CAAC,IAAA,CAAK,aAAY,EAAG,IAAA,CAAK,qBAAA,EAAuB,CAAC,CAAA;AAEpE,IAAA,MAAM,WAAA,GAAc,cAAA,CAAe,IAAA,CAAK,KAAK,CAAA;AAC7C,IAAA,IAAA,CAAK,YAAA,CAAa;AAAA,MAChB,cAAc,IAAA,CAAK,YAAA;AAAA,MACnB,KAAA,EAAO,WAAA,CAAY,GAAA,CAAI,CAAA,CAAA,KAAK,EAAE,UAAU,CAAA;AAAA,MACxC,yBAAA,EAA2B;AAAA,QACzB,OAAO,IAAA,CAAK;AAAA,OACd;AAAA,MACA,OAAO,IAAA,CAAK;AAAA,KACb,CAAA;AACD,IAAA,IAAA,CAAK,KAAA,GAAQ,MAAA;AAAA,EACf;AAAA,EAEA,UAAA,GAAa;AACX,IAAA,IAAA,CAAK,KAAA,GAAQ,OAAA;AACb,IAAA,IAAA,CAAK,IAAI,KAAA,EAAM;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBA,MAAM,IAAA,CAAK,SAAA,EAA+C,OAAA,EAAiC;AACzF,IAAA,IAAI,CAAC,IAAA,CAAK,KAAA,IAAS,IAAA,CAAK,UAAU,MAAA,EAAQ;AACxC,MAAA,OAAA,CAAQ,KAAK,sDAAsD,CAAA;AACnE,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,gBAAA,CAAiB,SAAS,CAAA,EAAG;AAC/B,MAAA,MAAM,MAAA,GAAS,SAAA;AACf,MAAA,MAAA,CAAO,EAAA,CAAG,QAAQ,CAAA,KAAA,KAAS;AACzB,QAAA,IAAI;AACF,UAAA,MAAM,MAAA,GAAS,OAAO,QAAA,CAAS,KAAK,IAAI,KAAA,GAAQ,MAAA,CAAO,KAAK,KAAK,CAAA;AACjE,UAAA,IAAA,CAAK,SAAA,CAAU,2BAAA,EAA6B,EAAE,KAAA,EAAO,MAAA,CAAO,SAAS,QAAQ,CAAA,EAAG,QAAA,EAAU,OAAA,EAAS,CAAA;AAAA,QACrG,SAAS,GAAA,EAAK;AACZ,UAAA,IAAA,CAAK,IAAA,CAAK,SAAS,GAAG,CAAA;AAAA,QACxB;AAAA,MACF,CAAC,CAAA;AAAA,IACH,CAAA,MAAA,IAAW,qBAAqB,UAAA,EAAY;AAC1C,MAAA,IAAI;AACF,QAAA,MAAM,WAAA,GAAc,IAAA,CAAK,kBAAA,CAAmB,SAAS,CAAA;AACrD,QAAA,IAAA,CAAK,UAAU,2BAAA,EAA6B,EAAE,OAAO,WAAA,EAAa,QAAA,EAAU,SAAS,CAAA;AAAA,MACvF,SAAS,GAAA,EAAK;AACZ,QAAA,IAAA,CAAK,IAAA,CAAK,SAAS,GAAG,CAAA;AAAA,MACxB;AAAA,IACF,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,IAAA,CAAK,OAAA,EAAS,IAAI,KAAA,CAAM,+BAA+B,CAAC,CAAA;AAAA,IAC/D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBA,MAAM,MAAA,CAAO,EAAE,OAAA,EAAQ,EAA0C;AAC/D,IAAA,IAAA,CAAK,UAAU,iBAAA,EAAmB,EAAE,UAAU,OAAA,IAAW,IAAI,CAAA;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwBA,EAAA,CAAG,OAAe,QAAA,EAA+B;AAC/C,IAAA,IAAI,CAAC,IAAA,CAAK,MAAA,CAAO,KAAK,CAAA,EAAG;AACvB,MAAA,IAAA,CAAK,MAAA,CAAO,KAAK,CAAA,GAAI,EAAC;AAAA,IACxB;AACA,IAAA,IAAA,CAAK,MAAA,CAAO,KAAK,CAAA,CAAE,IAAA,CAAK,QAAQ,CAAA;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBA,GAAA,CAAI,OAAe,QAAA,EAA+B;AAChD,IAAA,IAAI,CAAC,IAAA,CAAK,MAAA,CAAO,KAAK,CAAA,EAAG;AAEzB,IAAA,MAAM,QAAQ,IAAA,CAAK,MAAA,CAAO,KAAK,CAAA,CAAE,QAAQ,QAAQ,CAAA;AACjD,IAAA,IAAI,UAAU,EAAA,EAAI;AAChB,MAAA,IAAA,CAAK,MAAA,CAAO,KAAK,CAAA,CAAE,MAAA,CAAO,OAAO,CAAC,CAAA;AAAA,IACpC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,IAAA,CAAK,UAAkB,IAAA,EAAmB;AAChD,IAAA,IAAI,CAAC,IAAA,CAAK,MAAA,CAAO,KAAK,CAAA,EAAG;AAEzB,IAAA,KAAA,MAAW,QAAA,IAAY,IAAA,CAAK,MAAA,CAAO,KAAK,CAAA,EAAG;AACzC,MAAA,QAAA,CAAS,GAAG,IAAI,CAAA;AAAA,IAClB;AAAA,EACF;AAAA,EAEQ,mBAAA,GAA4B;AAClC,IAAA,MAAM,cAAA,uBAAqB,GAAA,EAA0B;AAErD,IAAA,IAAI,CAAC,KAAK,EAAA,EAAI;AACZ,MAAA,MAAM,IAAI,MAAM,2BAA2B,CAAA;AAAA,IAC7C;AAEA,IAAA,IAAA,CAAK,EAAA,CAAG,EAAA,CAAG,SAAA,EAAW,CAAA,OAAA,KAAW;AAC/B,MAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,OAAA,CAAQ,UAAU,CAAA;AAC1C,MAAA,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,IAAA,CAAK,IAAA,EAAM,IAAI,CAAA;AAEhC,MAAA,IAAI,KAAK,KAAA,EAAO;AACd,QAAA,MAAM,EAAE,KAAA,EAAO,GAAG,MAAA,EAAO,GAAI,IAAA;AAC7B,QAAA,OAAA,CAAQ,IAAA,CAAK,KAAK,IAAA,EAAM,MAAA,EAAQ,OAAO,MAAA,GAAS,GAAA,GAAM,QAAQ,EAAE,CAAA;AAAA,MAClE;AAAA,IACF,CAAC,CAAA;AAED,IAAA,IAAA,CAAK,MAAA,CAAO,EAAA,CAAG,iBAAA,EAAmB,CAAA,EAAA,KAAM;AACtC,MAAA,IAAA,CAAK,IAAA,CAAK,mBAAmB,EAAE,CAAA;AAE/B,MAAA,MAAM,QAAQ,IAAA,CAAK,KAAA,CAAM,OAAO,CAAA,EAAG,IAAA,CAAK,MAAM,MAAM,CAAA;AACpD,MAAA,KAAA,MAAWC,OAAM,KAAA,EAAO;AACtB,QAAA,IAAA,CAAK,EAAA,EAAI,IAAA,CAAK,IAAA,CAAK,SAAA,CAAUA,GAAE,CAAC,CAAA;AAAA,MAClC;AAAA,IACF,CAAC,CAAA;AACD,IAAA,IAAA,CAAK,MAAA,CAAO,EAAA,CAAG,iBAAA,EAAmB,CAAA,EAAA,KAAM;AACtC,MAAA,IAAA,CAAK,IAAA,CAAK,mBAAmB,EAAE,CAAA;AAAA,IACjC,CAAC,CAAA;AACD,IAAA,IAAA,CAAK,MAAA,CAAO,EAAA,CAAG,kBAAA,EAAoB,CAAA,EAAA,KAAM;AACvC,MAAA,IAAA,CAAK,IAAA,CAAK,oBAAoB,EAAE,CAAA;AAEhC,MAAA,MAAM,aAAA,GAAgB,IAAI,WAAA,EAAY;AAEtC,MAAA,aAAA,CAAc,EAAA,GAAK,GAAG,QAAA,CAAS,EAAA;AAE/B,MAAA,cAAA,CAAe,GAAA,CAAI,EAAA,CAAG,QAAA,CAAS,EAAA,EAAI,aAAa,CAAA;AAChD,MAAA,IAAA,CAAK,IAAA,CAAK,WAAW,aAAa,CAAA;AAAA,IACpC,CAAC,CAAA;AACD,IAAA,IAAA,CAAK,MAAA,CAAO,EAAA,CAAG,mDAAA,EAAqD,CAAA,EAAA,KAAM;AACxE,MAAA,IAAA,CAAK,IAAA,CAAK,SAAA,EAAW,EAAE,IAAA,EAAM,EAAA,CAAG,KAAA,EAAO,WAAA,EAAa,EAAA,CAAG,WAAA,EAAa,IAAA,EAAM,MAAA,EAAQ,CAAA;AAAA,IACpF,CAAC,CAAA;AACD,IAAA,IAAA,CAAK,MAAA,CAAO,EAAA,CAAG,kDAAA,EAAoD,CAAA,EAAA,KAAM;AACvE,MAAA,IAAA,CAAK,IAAA,CAAK,SAAA,EAAW,EAAE,IAAA,EAAM,IAAA,EAAM,aAAa,EAAA,CAAG,WAAA,EAAa,IAAA,EAAM,MAAA,EAAQ,CAAA;AAAA,IAChF,CAAC,CAAA;AACD,IAAA,IAAA,CAAK,MAAA,CAAO,EAAA,CAAG,sBAAA,EAAwB,CAAA,EAAA,KAAM;AAC3C,MAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,IAAA,CAAK,EAAA,CAAG,OAAO,QAAQ,CAAA;AAC5C,MAAA,IAAA,CAAK,KAAK,UAAA,EAAY,EAAE,OAAO,WAAA,EAAa,EAAA,CAAG,aAAa,CAAA;AAE5D,MAAA,MAAM,MAAA,GAAS,cAAA,CAAe,GAAA,CAAI,EAAA,CAAG,WAAW,CAAA;AAChD,MAAA,MAAA,EAAQ,MAAM,KAAK,CAAA;AAAA,IACrB,CAAC,CAAA;AACD,IAAA,IAAA,CAAK,MAAA,CAAO,EAAA,CAAG,qBAAA,EAAuB,CAAA,EAAA,KAAM;AAC1C,MAAA,IAAA,CAAK,KAAK,eAAA,EAAiB,EAAE,WAAA,EAAa,EAAA,CAAG,aAAa,CAAA;AAE1D,MAAA,MAAM,MAAA,GAAS,cAAA,CAAe,GAAA,CAAI,EAAA,CAAG,WAAW,CAAA;AAChD,MAAA,MAAA,EAAQ,GAAA,EAAI;AAAA,IACd,CAAC,CAAA;AACD,IAAA,IAAA,CAAK,MAAA,CAAO,EAAA,CAAG,iCAAA,EAAmC,CAAA,EAAA,KAAM;AACtD,MAAA,IAAA,CAAK,IAAA,CAAK,SAAA,EAAW,EAAE,IAAA,EAAM,EAAA,CAAG,KAAA,EAAO,WAAA,EAAa,EAAA,CAAG,WAAA,EAAa,IAAA,EAAM,WAAA,EAAa,CAAA;AAAA,IACzF,CAAC,CAAA;AACD,IAAA,IAAA,CAAK,MAAA,CAAO,EAAA,CAAG,gCAAA,EAAkC,CAAA,EAAA,KAAM;AACrD,MAAA,IAAA,CAAK,IAAA,CAAK,SAAA,EAAW,EAAE,IAAA,EAAM,IAAA,EAAM,aAAa,EAAA,CAAG,WAAA,EAAa,IAAA,EAAM,WAAA,EAAa,CAAA;AAAA,IACrF,CAAC,CAAA;AACD,IAAA,IAAA,CAAK,MAAA,CAAO,EAAA,CAAG,qBAAA,EAAuB,CAAA,EAAA,KAAM;AAC1C,MAAA,IAAA,CAAK,IAAA,CAAK,SAAA,EAAW,EAAE,IAAA,EAAM,EAAA,CAAG,KAAA,EAAO,WAAA,EAAa,EAAA,CAAG,WAAA,EAAa,IAAA,EAAM,WAAA,EAAa,CAAA;AAAA,IACzF,CAAC,CAAA;AACD,IAAA,IAAA,CAAK,MAAA,CAAO,EAAA,CAAG,oBAAA,EAAsB,CAAA,EAAA,KAAM;AACzC,MAAA,IAAA,CAAK,IAAA,CAAK,SAAA,EAAW,EAAE,IAAA,EAAM,IAAA,EAAM,aAAa,EAAA,CAAG,WAAA,EAAa,IAAA,EAAM,WAAA,EAAa,CAAA;AAAA,IACrF,CAAC,CAAA;AACD,IAAA,IAAA,CAAK,MAAA,CAAO,EAAA,CAAG,eAAA,EAAiB,OAAM,EAAA,KAAM;AAC1C,MAAA,MAAM,IAAA,CAAK,oBAAoB,EAAE,CAAA;AACjC,MAAA,IAAA,CAAK,IAAA,CAAK,iBAAiB,EAAE,CAAA;AAC7B,MAAA,cAAA,CAAe,MAAA,CAAO,EAAA,CAAG,QAAA,CAAS,EAAE,CAAA;AAAA,IACtC,CAAC,CAAA;AACD,IAAA,IAAA,CAAK,MAAA,CAAO,EAAA,CAAG,OAAA,EAAS,OAAM,EAAA,KAAM;AAClC,MAAA,IAAA,CAAK,IAAA,CAAK,SAAS,EAAE,CAAA;AAAA,IACvB,CAAC,CAAA;AAAA,EACH;AAAA,EAEA,MAAc,oBAAoB,EAAA,EAAS;AACzC,IAAA,KAAA,MAAW,MAAA,IAAU,EAAA,CAAG,QAAA,EAAU,MAAA,IAAU,EAAC,EAAG;AAC9C,MAAA,IAAI,MAAA,CAAO,SAAS,eAAA,EAAiB;AACnC,QAAA,MAAM,IAAA,CAAK,mBAAmB,MAAM,CAAA;AAAA,MACtC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,mBAAmB,MAAA,EAAa;AAC5C,IAAA,IAAI;AACF,MAAA,MAAM,OAAA,GAAU,IAAA,CAAK,KAAA,CAAM,MAAA,CAAO,SAAS,CAAA;AAC3C,MAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,GAAQ,MAAA,CAAO,IAAI,CAAA;AACrC,MAAA,IAAI,CAAC,IAAA,EAAM;AACT,QAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,MAAA,EAAS,MAAA,CAAO,IAAI,CAAA,WAAA,CAAa,CAAA;AAC9C,QAAA;AAAA,MACF;AAEA,MAAA,IAAI,MAAM,OAAA,EAAS;AACjB,QAAA,IAAA,CAAK,KAAK,iBAAA,EAAmB;AAAA,UAC3B,YAAY,MAAA,CAAO,OAAA;AAAA,UACnB,UAAU,MAAA,CAAO,IAAA;AAAA,UACjB,iBAAiB,IAAA,CAAK,WAAA;AAAA,UACtB,IAAA,EAAM;AAAA,SACP,CAAA;AAAA,MACH;AAEA,MAAA,MAAM,MAAA,GAAS,MAAM,IAAA,EAAM,OAAA;AAAA,QACzB,EAAE,OAAA,EAAS,cAAA,EAAgB,IAAA,CAAK,cAAA,EAAe;AAAA,QAC/C;AAAA,UACE,YAAY,MAAA,CAAO,OAAA;AAAA,UACnB,UAAU;AAAC;AACb,OACF;AAEA,MAAA,IAAA,CAAK,KAAK,kBAAA,EAAoB;AAAA,QAC5B,YAAY,MAAA,CAAO,OAAA;AAAA,QACnB,UAAU,MAAA,CAAO,IAAA;AAAA,QACjB,iBAAiB,IAAA,CAAK,WAAA;AAAA,QACtB,IAAA,EAAM,OAAA;AAAA,QACN;AAAA,OACD,CAAA;AAED,MAAA,IAAA,CAAK,UAAU,0BAAA,EAA4B;AAAA,QACzC,IAAA,EAAM;AAAA,UACJ,IAAA,EAAM,sBAAA;AAAA,UACN,SAAS,MAAA,CAAO,OAAA;AAAA,UAChB,MAAA,EAAQ,IAAA,CAAK,SAAA,CAAU,MAAM;AAAA;AAC/B,OACD,CAAA;AAAA,IACH,SAAS,CAAA,EAAG;AACV,MAAA,MAAM,GAAA,GAAM,CAAA;AACZ,MAAA,OAAA,CAAQ,KAAK,CAAA,oBAAA,EAAuB,MAAA,CAAO,IAAI,CAAA,EAAA,CAAA,EAAM,IAAI,OAAO,CAAA;AAChE,MAAA,IAAA,CAAK,UAAU,0BAAA,EAA4B;AAAA,QACzC,IAAA,EAAM;AAAA,UACJ,IAAA,EAAM,sBAAA;AAAA,UACN,SAAS,MAAA,CAAO,OAAA;AAAA,UAChB,QAAQ,IAAA,CAAK,SAAA,CAAU,EAAE,KAAA,EAAO,GAAA,CAAI,SAAS;AAAA;AAC/C,OACD,CAAA;AAAA,IACH,CAAA,SAAE;AACA,MAAA,IAAA,CAAK,SAAA,CAAU,iBAAA,EAAmB,EAAE,CAAA;AAAA,IACtC;AAAA,EACF;AAAA,EAEQ,mBAAmB,UAAA,EAAgC;AACzD,IAAA,MAAM,MAAA,GAAS,IAAI,WAAA,CAAY,UAAA,CAAW,SAAS,CAAC,CAAA;AACpD,IAAA,MAAM,IAAA,GAAO,IAAI,QAAA,CAAS,MAAM,CAAA;AAChC,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,UAAA,CAAW,QAAQ,CAAA,EAAA,EAAK;AAC1C,MAAA,IAAA,CAAK,SAAS,CAAA,GAAI,CAAA,EAAG,UAAA,CAAW,CAAC,GAAI,IAAI,CAAA;AAAA,IAC3C;AACA,IAAA,MAAM,UAAA,GAAa,IAAI,UAAA,CAAW,MAAM,CAAA;AACxC,IAAA,IAAI,MAAA,GAAS,EAAA;AACb,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,UAAA,CAAW,QAAQ,CAAA,EAAA,EAAK;AAC1C,MAAA,MAAA,IAAU,MAAA,CAAO,YAAA,CAAa,UAAA,CAAW,CAAC,CAAE,CAAA;AAAA,IAC9C;AACA,IAAA,OAAO,KAAK,MAAM,CAAA;AAAA,EACpB;AAAA,EAEQ,SAAA,CAAU,MAAc,IAAA,EAAW;AACzC,IAAA,IAAI,CAAC,KAAK,EAAA,IAAM,IAAA,CAAK,GAAG,UAAA,KAAe,IAAA,CAAK,GAAG,IAAA,EAAM;AACnD,MAAA,IAAA,CAAK,MAAM,IAAA,CAAK,EAAE,IAAA,EAAY,GAAG,MAAM,CAAA;AAAA,IACzC,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,EAAA,EAAI,IAAA;AAAA,QACP,KAAK,SAAA,CAAU;AAAA,UACb,IAAA;AAAA,UACA,GAAG;AAAA,SACJ;AAAA,OACH;AAAA,IACF;AAAA,EACF;AACF","file":"index.js","sourcesContent":["import { Readable } from 'stream';\nimport type { ToolsInput } from '@mastra/core/agent';\nimport { zodToJsonSchema } from 'zod-to-json-schema';\n\nexport type OpenAIExecuteFunction = (args: any) => Promise<any>;\ntype ToolDefinition = {\n type: 'function';\n name: string;\n description: string;\n parameters: {\n [key: string]: any;\n };\n};\n\ntype TTools = ToolsInput;\nexport const transformTools = (tools?: TTools) => {\n const openaiTools: { openaiTool: ToolDefinition; execute: OpenAIExecuteFunction }[] = [];\n for (const [name, tool] of Object.entries(tools || {})) {\n let parameters: { [key: string]: any };\n\n if ('inputSchema' in tool && tool.inputSchema) {\n if (isZodObject(tool.inputSchema)) {\n parameters = zodToJsonSchema(tool.inputSchema);\n delete parameters.$schema;\n } else {\n parameters = tool.inputSchema;\n }\n } else if ('parameters' in tool) {\n if (isZodObject(tool.parameters)) {\n parameters = zodToJsonSchema(tool.parameters);\n delete parameters.$schema;\n } else {\n parameters = tool.parameters;\n }\n } else {\n console.warn(`Tool ${name} has neither inputSchema nor parameters, skipping`);\n continue;\n }\n const openaiTool: ToolDefinition = {\n type: 'function',\n name,\n description: tool.description || `Tool: ${name}`,\n parameters,\n };\n\n if (tool.execute) {\n // Create an adapter function that works with both ToolAction and VercelTool execute functions\n const executeAdapter = async (args: any) => {\n try {\n if (!tool.execute) {\n throw new Error(`Tool ${name} has no execute function`);\n }\n\n // For ToolAction, the first argument is a context object with the args in a 'context' property\n if ('inputSchema' in tool) {\n return await tool.execute(\n { context: args },\n {\n toolCallId: 'unknown',\n messages: [],\n },\n );\n }\n // For VercelTool, pass args directly\n else {\n // Create a minimal ToolExecutionOptions object with required properties\n const options = {\n toolCallId: 'unknown',\n messages: [],\n };\n return await tool.execute(args, options);\n }\n } catch (error) {\n console.error(`Error executing tool ${name}:`, error);\n throw error;\n }\n };\n openaiTools.push({ openaiTool, execute: executeAdapter });\n } else {\n console.warn(`Tool ${name} has no execute function, skipping`);\n }\n }\n return openaiTools;\n};\n\nexport const isReadableStream = (obj: unknown) => {\n return (\n obj &&\n obj instanceof Readable &&\n typeof obj.read === 'function' &&\n typeof obj.pipe === 'function' &&\n obj.readable === true\n );\n};\n\nfunction isZodObject(schema: unknown) {\n return (\n !!schema &&\n typeof schema === 'object' &&\n '_def' in schema &&\n schema._def &&\n typeof schema._def === 'object' &&\n 'typeName' in schema._def &&\n schema._def.typeName === 'ZodObject'\n );\n}\n","import { EventEmitter } from 'events';\nimport { PassThrough } from 'stream';\nimport type { ToolsInput } from '@mastra/core/agent';\nimport type { RuntimeContext } from '@mastra/core/runtime-context';\nimport { MastraVoice } from '@mastra/core/voice';\nimport type { Realtime, RealtimeServerEvents } from 'openai-realtime-api';\nimport { WebSocket } from 'ws';\nimport { isReadableStream, transformTools } from './utils';\n\n/**\n * Event callback function type\n */\ntype EventCallback = (...args: any[]) => void;\n\ntype StreamWithId = PassThrough & { id: string };\n\n/**\n * Map of event types to their callback arrays\n */\ntype EventMap = {\n transcribing: [{ text: string }];\n writing: [{ text: string }];\n speaking: [{ audio: string }];\n speaker: [StreamWithId];\n error: [Error];\n} & {\n [key: string]: EventCallback[];\n};\n\n/** Default voice for text-to-speech. 'alloy' provides a neutral, balanced voice suitable for most use cases */\nconst DEFAULT_VOICE: Realtime.Voice = 'alloy';\n\nconst DEFAULT_TRANSCRIBER: Realtime.AudioTranscriptionModel = 'whisper-1';\n\nconst DEFAULT_URL = 'wss://api.openai.com/v1/realtime';\n\n/**\n * Default model for real-time voice interactions.\n * This model is optimized for low-latency responses while maintaining high quality output.\n */\nconst DEFAULT_MODEL = 'gpt-4o-mini-realtime-preview-2024-12-17';\n\n// /**\n// * Default Voice Activity Detection (VAD) configuration.\n// * These settings control how the system detects speech segments.\n// *\n// * @property {string} type - Uses server-side VAD for better accuracy\n// * @property {number} threshold - Speech detection sensitivity (0.5 = balanced)\n// * @property {number} prefix_padding_ms - Includes 1 second of audio before speech\n// * @property {number} silence_duration_ms - Waits 1 second of silence before ending turn\n// */\n// const DEFAULT_VAD_CONFIG = {\n// type: 'server_vad',\n// threshold: 0.5,\n// prefix_padding_ms: 1000,\n// silence_duration_ms: 1000,\n// } as Realtime.TurnDetection;\n\ntype TTools = ToolsInput;\n\n/**\n * Available voice options for text-to-speech.\n * Each voice has unique characteristics suitable for different use cases:\n * - alloy: Neutral and balanced\n * - echo: Warm and natural\n * - shimmer: Clear and expressive\n * - And more...\n */\nconst VOICES = ['alloy', 'ash', 'ballad', 'coral', 'echo', 'sage', 'shimmer', 'verse'];\n\ntype RealtimeClientServerEventMap = {\n [K in RealtimeServerEvents.EventType]: [RealtimeServerEvents.EventMap[K]];\n} & {\n ['conversation.item.input_audio_transcription.delta']: [{ delta: string; response_id: string }];\n ['conversation.item.input_audio_transcription.done']: [{ response_id: string }];\n};\n\n/**\n * OpenAIRealtimeVoice provides real-time voice interaction capabilities using OpenAI's\n * WebSocket-based API. It supports:\n * - Real-time text-to-speech\n * - Speech-to-text (transcription)\n * - Voice activity detection\n * - Multiple voice options\n * - Event-based audio streaming\n *\n * The class manages WebSocket connections, audio streaming, and event handling\n * for seamless voice interactions.\n *\n * @extends MastraVoice\n *\n * @example\n * ```typescript\n * const voice = new OpenAIRealtimeVoice({\n * apiKey: process.env.OPENAI_API_KEY,\n * model: 'gpt-4o-mini-realtime'\n * });\n *\n * await voice.open();\n * voice.on('speaking', (audioData) => {\n * // Handle audio data\n * });\n *\n * await voice.speak('Hello, how can I help you today?');\n * ```\n */\nexport class OpenAIRealtimeVoice extends MastraVoice {\n private ws?: WebSocket;\n private state: 'close' | 'open';\n private client: EventEmitter<RealtimeClientServerEventMap>;\n private events: EventMap;\n private instructions?: string;\n private tools?: TTools;\n private debug: boolean;\n private queue: unknown[] = [];\n private transcriber: Realtime.AudioTranscriptionModel;\n private runtimeContext?: RuntimeContext;\n /**\n * Creates a new instance of OpenAIRealtimeVoice.\n *\n * @param options - Configuration options for the voice instance\n * @param options.url - The base URL for the OpenAI Realtime API\n * @param options.model - The model ID to use (defaults to GPT-4 Mini Realtime)\n * @param options.apiKey - OpenAI API key. Falls back to process.env.OPENAI_API_KEY\n * @param options.speaker - Voice ID to use (defaults to 'alloy')\n * @param options.debug - Enable debug mode\n *\n * @example\n * ```typescript\n * const voice = new OpenAIRealtimeVoice({\n * apiKey: 'your-api-key',\n * model: 'gpt-4o-mini-realtime',\n * speaker: 'alloy'\n * });\n * ```\n */\n constructor(\n private options: {\n model?: string;\n url?: string;\n apiKey?: string;\n speaker?: Realtime.Voice;\n transcriber?: Realtime.AudioTranscriptionModel;\n debug?: boolean;\n } = {},\n ) {\n super();\n\n this.client = new EventEmitter();\n this.state = 'close';\n this.events = {} as EventMap;\n this.speaker = options.speaker || DEFAULT_VOICE;\n this.transcriber = options.transcriber || DEFAULT_TRANSCRIBER;\n this.debug = options.debug || false;\n }\n\n /**\n * Returns a list of available voice speakers.\n *\n * @returns Promise resolving to an array of voice objects, each containing at least a voiceId\n *\n * @example\n * ```typescript\n * const speakers = await voice.getSpeakers();\n * // speakers = [{ voiceId: 'alloy' }, { voiceId: 'echo' }, ...]\n * ```\n */\n getSpeakers(): Promise<Array<{ voiceId: string; [key: string]: any }>> {\n return Promise.resolve(VOICES.map(v => ({ voiceId: v })));\n }\n\n /**\n * Disconnects from the OpenAI realtime session and cleans up resources.\n * Should be called when you're done with the voice instance.\n *\n * @example\n * ```typescript\n * voice.close(); // Disconnects and cleans up\n * ```\n */\n close() {\n if (!this.ws) return;\n this.ws.close();\n this.state = 'close';\n }\n\n /**\n * Equips the voice instance with a set of instructions.\n * Instructions allow the model to perform additional actions during conversations.\n *\n * @param instructions - Optional instructions to addInstructions\n * @returns Transformed instructions ready for use with the model\n *\n * @example\n * ```typescript\n * voice.addInstructions('You are a helpful assistant.');\n * ```\n */\n addInstructions(instructions?: string) {\n this.instructions = instructions;\n }\n\n /**\n * Equips the voice instance with a set of tools.\n * Tools allow the model to perform additional actions during conversations.\n *\n * @param tools - Optional tools configuration to addTools\n * @returns Transformed tools configuration ready for use with the model\n *\n * @example\n * ```typescript\n * const tools = {\n * search: async (query: string) => { ... },\n * calculate: (expression: string) => { ... }\n * };\n * voice.addTools(tools);\n * ```\n */\n addTools(tools?: TTools) {\n this.tools = tools || {};\n }\n\n /**\n * Emits a speaking event using the configured voice model.\n * Can accept either a string or a readable stream as input.\n *\n * @param input - The text to convert to speech, or a readable stream containing the text\n * @param options - Optional configuration for this specific speech request\n * @param options.speaker - Override the voice to use for this specific request\n *\n * @throws {Error} If the input text is empty\n *\n * @example\n * ```typescript\n * // Simple text to speech\n * await voice.speak('Hello world');\n *\n * // With custom voice\n * await voice.speak('Hello world', { speaker: 'echo' });\n *\n * // Using a stream\n * const stream = fs.createReadStream('text.txt');\n * await voice.speak(stream);\n * ```\n */\n async speak(input: string | NodeJS.ReadableStream, options?: { speaker?: Realtime.Voice }): Promise<void> {\n if (typeof input !== 'string') {\n const chunks: Buffer[] = [];\n for await (const chunk of input) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));\n }\n input = Buffer.concat(chunks).toString('utf-8');\n }\n\n if (input.trim().length === 0) {\n throw new Error('Input text is empty');\n }\n\n this.sendEvent('response.create', {\n response: {\n instructions: `Repeat the following text: ${input}`,\n voice: options?.speaker ? options.speaker : undefined,\n },\n });\n }\n\n /**\n * Updates the session configuration for the voice instance.\n * This can be used to modify voice settings, turn detection, and other parameters.\n *\n * @param sessionConfig - New session configuration to apply\n *\n * @example\n * ```typescript\n * voice.updateConfig({\n * voice: 'echo',\n * turn_detection: {\n * type: 'server_vad',\n * threshold: 0.5,\n * silence_duration_ms: 1000\n * }\n * });\n * ```\n */\n updateConfig(sessionConfig: unknown): void {\n this.sendEvent('session.update', { session: sessionConfig });\n }\n\n /**\n * Checks if listening capabilities are enabled.\n *\n * @returns {Promise<{ enabled: boolean }>}\n */\n async getListener() {\n return { enabled: true };\n }\n\n /**\n * Processes audio input for speech recognition.\n * Takes a readable stream of audio data and emits a writing event.\n * The output of the writing event is int16 audio data.\n *\n * @param audioData - Readable stream containing the audio data to process\n * @param options - Optional configuration for audio processing\n *\n * @throws {Error} If the audio data format is not supported\n *\n * @example\n * ```typescript\n * // Process audio from a file\n * const audioStream = fs.createReadStream('audio.raw');\n * await voice.listen(audioStream);\n *\n * // Process audio with options\n * await voice.listen(microphoneStream, {\n * format: 'int16',\n * sampleRate: 24000\n * });\n * ```\n */\n async listen(audioData: NodeJS.ReadableStream): Promise<void> {\n if (isReadableStream(audioData)) {\n const chunks: Buffer[] = [];\n for await (const chunk of audioData) {\n const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n chunks.push(buffer);\n }\n\n const buffer = Buffer.concat(chunks);\n const int16Array = new Int16Array(buffer.buffer, buffer.byteOffset ?? 0, (buffer.byteLength ?? 0) / 2);\n const base64Audio = this.int16ArrayToBase64(int16Array);\n\n this.sendEvent('conversation.item.create', {\n item: {\n type: 'message',\n role: 'user',\n content: [{ type: 'input_audio', audio: base64Audio }],\n },\n });\n\n this.sendEvent('response.create', {\n response: {\n modalities: ['text'],\n instructions: `ONLY repeat the input and DO NOT say anything else`,\n },\n });\n } else {\n this.emit('error', new Error('Unsupported audio data format'));\n }\n }\n\n waitForOpen() {\n return new Promise(resolve => {\n this.ws?.on('open', resolve);\n });\n }\n\n waitForSessionCreated() {\n return new Promise(resolve => {\n this.client.on('session.created', resolve);\n });\n }\n\n /**\n * Establishes a connection to the OpenAI realtime service.\n * Must be called before using speak, listen, or relay functions.\n *\n * @throws {Error} If connection fails or session creation times out\n *\n * @example\n * ```typescript\n * await voice.open();\n * // Now ready for voice interactions\n * ```\n */\n async connect({ runtimeContext }: { runtimeContext?: RuntimeContext } = {}) {\n const url = `${this.options.url || DEFAULT_URL}?model=${this.options.model || DEFAULT_MODEL}`;\n const apiKey = this.options.apiKey || process.env.OPENAI_API_KEY;\n this.runtimeContext = runtimeContext;\n\n this.ws = new WebSocket(url, undefined, {\n headers: {\n Authorization: 'Bearer ' + apiKey,\n 'OpenAI-Beta': 'realtime=v1',\n },\n });\n\n this.setupEventListeners();\n await Promise.all([this.waitForOpen(), this.waitForSessionCreated()]);\n\n const openaiTools = transformTools(this.tools);\n this.updateConfig({\n instructions: this.instructions,\n tools: openaiTools.map(t => t.openaiTool),\n input_audio_transcription: {\n model: this.transcriber,\n },\n voice: this.speaker,\n });\n this.state = 'open';\n }\n\n disconnect() {\n this.state = 'close';\n this.ws?.close();\n }\n\n /**\n * Streams audio data in real-time to the OpenAI service.\n * Useful for continuous audio streaming scenarios like live microphone input.\n * Must be in 'open' state before calling this method.\n *\n * @param audioData - Readable stream of audio data to relay\n * @throws {Error} If audio format is not supported\n *\n * @example\n * ```typescript\n * // First connect\n * await voice.open();\n *\n * // Then relay audio\n * const micStream = getMicrophoneStream();\n * await voice.relay(micStream);\n * ```\n */\n async send(audioData: NodeJS.ReadableStream | Int16Array, eventId?: string): Promise<void> {\n if (!this.state || this.state !== 'open') {\n console.warn('Cannot relay audio when not open. Call open() first.');\n return;\n }\n\n if (isReadableStream(audioData)) {\n const stream = audioData as NodeJS.ReadableStream;\n stream.on('data', chunk => {\n try {\n const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n this.sendEvent('input_audio_buffer.append', { audio: buffer.toString('base64'), event_id: eventId });\n } catch (err) {\n this.emit('error', err);\n }\n });\n } else if (audioData instanceof Int16Array) {\n try {\n const base64Audio = this.int16ArrayToBase64(audioData);\n this.sendEvent('input_audio_buffer.append', { audio: base64Audio, event_id: eventId });\n } catch (err) {\n this.emit('error', err);\n }\n } else {\n this.emit('error', new Error('Unsupported audio data format'));\n }\n }\n\n /**\n * Sends a response to the OpenAI Realtime API.\n *\n * Trigger a response to the real-time session.\n *\n * @param {Object} params - The parameters object\n * @param {Realtime.ResponseConfig} params.options - Configuration options for the response\n * @returns {Promise<void>} A promise that resolves when the response has been sent\n *\n * @example\n * // Send a simple text response\n * await realtimeVoice.answer({\n * options: {\n * content: \"Hello, how can I help you today?\",\n * voice: \"alloy\"\n * }\n * });\n */\n async answer({ options }: { options?: Realtime.ResponseConfig }) {\n this.sendEvent('response.create', { response: options ?? {} });\n }\n\n /**\n * Registers an event listener for voice events.\n * Available events: 'speaking', 'writing, 'error'\n * Can listen to OpenAI Realtime events by prefixing with 'openAIRealtime:'\n * Such as 'openAIRealtime:conversation.item.completed', 'openAIRealtime:conversation.updated', etc.\n *\n * @param event - Name of the event to listen for\n * @param callback - Function to call when the event occurs\n *\n * @example\n * ```typescript\n * // Listen for speech events\n * voice.on('speaking', (audioData: Int16Array) => {\n * // Handle audio data\n * });\n *\n * // Handle errors\n * voice.on('error', (error: Error) => {\n * console.error('Voice error:', error);\n * });\n * ```\n */\n on(event: string, callback: EventCallback): void {\n if (!this.events[event]) {\n this.events[event] = [];\n }\n this.events[event].push(callback);\n }\n\n /**\n * Removes a previously registered event listener.\n *\n * @param event - Name of the event to stop listening to\n * @param callback - The specific callback function to remove\n *\n * @example\n * ```typescript\n * // Create event handler\n * const handleSpeech = (audioData: Int16Array) => {\n * // Handle audio data\n * };\n *\n * // Add listener\n * voice.on('speaking', handleSpeech);\n *\n * // Later, remove the listener\n * voice.off('speaking', handleSpeech);\n * ```\n */\n off(event: string, callback: EventCallback): void {\n if (!this.events[event]) return;\n\n const index = this.events[event].indexOf(callback);\n if (index !== -1) {\n this.events[event].splice(index, 1);\n }\n }\n\n /**\n * Emit an event with arguments\n * @param event Event name\n * @param args Arguments to pass to the callbacks\n */\n private emit(event: string, ...args: any[]): void {\n if (!this.events[event]) return;\n\n for (const callback of this.events[event]) {\n callback(...args);\n }\n }\n\n private setupEventListeners(): void {\n const speakerStreams = new Map<string, StreamWithId>();\n\n if (!this.ws) {\n throw new Error('WebSocket not initialized');\n }\n\n this.ws.on('message', message => {\n const data = JSON.parse(message.toString());\n this.client.emit(data.type, data);\n\n if (this.debug) {\n const { delta, ...fields } = data;\n console.info(data.type, fields, delta?.length < 100 ? delta : '');\n }\n });\n\n this.client.on('session.created', ev => {\n this.emit('session.created', ev);\n\n const queue = this.queue.splice(0, this.queue.length);\n for (const ev of queue) {\n this.ws?.send(JSON.stringify(ev));\n }\n });\n this.client.on('session.updated', ev => {\n this.emit('session.updated', ev);\n });\n this.client.on('response.created', ev => {\n this.emit('response.created', ev);\n\n const speakerStream = new PassThrough() as StreamWithId;\n\n speakerStream.id = ev.response.id;\n\n speakerStreams.set(ev.response.id, speakerStream);\n this.emit('speaker', speakerStream);\n });\n this.client.on('conversation.item.input_audio_transcription.delta', ev => {\n this.emit('writing', { text: ev.delta, response_id: ev.response_id, role: 'user' });\n });\n this.client.on('conversation.item.input_audio_transcription.done', ev => {\n this.emit('writing', { text: '\\n', response_id: ev.response_id, role: 'user' });\n });\n this.client.on('response.audio.delta', ev => {\n const audio = Buffer.from(ev.delta, 'base64');\n this.emit('speaking', { audio, response_id: ev.response_id });\n\n const stream = speakerStreams.get(ev.response_id);\n stream?.write(audio);\n });\n this.client.on('response.audio.done', ev => {\n this.emit('speaking.done', { response_id: ev.response_id });\n\n const stream = speakerStreams.get(ev.response_id);\n stream?.end();\n });\n this.client.on('response.audio_transcript.delta', ev => {\n this.emit('writing', { text: ev.delta, response_id: ev.response_id, role: 'assistant' });\n });\n this.client.on('response.audio_transcript.done', ev => {\n this.emit('writing', { text: '\\n', response_id: ev.response_id, role: 'assistant' });\n });\n this.client.on('response.text.delta', ev => {\n this.emit('writing', { text: ev.delta, response_id: ev.response_id, role: 'assistant' });\n });\n this.client.on('response.text.done', ev => {\n this.emit('writing', { text: '\\n', response_id: ev.response_id, role: 'assistant' });\n });\n this.client.on('response.done', async ev => {\n await this.handleFunctionCalls(ev);\n this.emit('response.done', ev);\n speakerStreams.delete(ev.response.id);\n });\n this.client.on('error', async ev => {\n this.emit('error', ev);\n });\n }\n\n private async handleFunctionCalls(ev: any) {\n for (const output of ev.response?.output ?? []) {\n if (output.type === 'function_call') {\n await this.handleFunctionCall(output);\n }\n }\n }\n\n private async handleFunctionCall(output: any) {\n try {\n const context = JSON.parse(output.arguments);\n const tool = this.tools?.[output.name];\n if (!tool) {\n console.warn(`Tool \"${output.name}\" not found`);\n return;\n }\n\n if (tool?.execute) {\n this.emit('tool-call-start', {\n toolCallId: output.call_id,\n toolName: output.name,\n toolDescription: tool.description,\n args: context,\n });\n }\n\n const result = await tool?.execute?.(\n { context, runtimeContext: this.runtimeContext },\n {\n toolCallId: output.call_id,\n messages: [],\n },\n );\n\n this.emit('tool-call-result', {\n toolCallId: output.call_id,\n toolName: output.name,\n toolDescription: tool.description,\n args: context,\n result,\n });\n\n this.sendEvent('conversation.item.create', {\n item: {\n type: 'function_call_output',\n call_id: output.call_id,\n output: JSON.stringify(result),\n },\n });\n } catch (e) {\n const err = e as Error;\n console.warn(`Error calling tool \"${output.name}\":`, err.message);\n this.sendEvent('conversation.item.create', {\n item: {\n type: 'function_call_output',\n call_id: output.call_id,\n output: JSON.stringify({ error: err.message }),\n },\n });\n } finally {\n this.sendEvent('response.create', {});\n }\n }\n\n private int16ArrayToBase64(int16Array: Int16Array): string {\n const buffer = new ArrayBuffer(int16Array.length * 2);\n const view = new DataView(buffer);\n for (let i = 0; i < int16Array.length; i++) {\n view.setInt16(i * 2, int16Array[i]!, true);\n }\n const uint8Array = new Uint8Array(buffer);\n let binary = '';\n for (let i = 0; i < uint8Array.length; i++) {\n binary += String.fromCharCode(uint8Array[i]!);\n }\n return btoa(binary);\n }\n\n private sendEvent(type: string, data: any) {\n if (!this.ws || this.ws.readyState !== this.ws.OPEN) {\n this.queue.push({ type: type, ...data });\n } else {\n this.ws?.send(\n JSON.stringify({\n type: type,\n ...data,\n }),\n );\n }\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/utils.ts","../src/index.ts"],"names":["buffer","ev"],"mappings":"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","file":"index.js","sourcesContent":["import { Readable } from 'stream';\nimport type { ToolsInput } from '@mastra/core/agent';\nimport { zodToJsonSchema } from 'zod-to-json-schema';\n\nexport type OpenAIExecuteFunction = (args: any) => Promise<any>;\ntype ToolDefinition = {\n type: 'function';\n name: string;\n description: string;\n parameters: {\n [key: string]: any;\n };\n};\n\ntype TTools = ToolsInput;\nexport const transformTools = (tools?: TTools) => {\n const openaiTools: { openaiTool: ToolDefinition; execute: OpenAIExecuteFunction }[] = [];\n for (const [name, tool] of Object.entries(tools || {})) {\n let parameters: { [key: string]: any };\n\n if ('inputSchema' in tool && tool.inputSchema) {\n if (isZodObject(tool.inputSchema)) {\n parameters = zodToJsonSchema(tool.inputSchema);\n delete parameters.$schema;\n } else {\n parameters = tool.inputSchema;\n }\n } else if ('parameters' in tool) {\n if (isZodObject(tool.parameters)) {\n parameters = zodToJsonSchema(tool.parameters);\n delete parameters.$schema;\n } else {\n parameters = tool.parameters;\n }\n } else {\n console.warn(`Tool ${name} has neither inputSchema nor parameters, skipping`);\n continue;\n }\n const openaiTool: ToolDefinition = {\n type: 'function',\n name,\n description: tool.description || `Tool: ${name}`,\n parameters,\n };\n\n if (tool.execute) {\n // Create an adapter function that works with both ToolAction and VercelTool execute functions\n const executeAdapter = async (args: any) => {\n try {\n if (!tool.execute) {\n throw new Error(`Tool ${name} has no execute function`);\n }\n\n // For ToolAction, the first argument is a context object with the args in a 'context' property\n if ('inputSchema' in tool) {\n return await tool.execute(\n { context: args },\n {\n toolCallId: 'unknown',\n messages: [],\n },\n );\n }\n // For VercelTool, pass args directly\n else {\n // Create a minimal ToolExecutionOptions object with required properties\n const options = {\n toolCallId: 'unknown',\n messages: [],\n };\n return await tool.execute(args, options);\n }\n } catch (error) {\n console.error(`Error executing tool ${name}:`, error);\n throw error;\n }\n };\n openaiTools.push({ openaiTool, execute: executeAdapter });\n } else {\n console.warn(`Tool ${name} has no execute function, skipping`);\n }\n }\n return openaiTools;\n};\n\nexport const isReadableStream = (obj: unknown) => {\n return (\n obj &&\n obj instanceof Readable &&\n typeof obj.read === 'function' &&\n typeof obj.pipe === 'function' &&\n obj.readable === true\n );\n};\n\nfunction isZodObject(schema: unknown) {\n return (\n !!schema &&\n typeof schema === 'object' &&\n '_def' in schema &&\n schema._def &&\n typeof schema._def === 'object' &&\n 'typeName' in schema._def &&\n schema._def.typeName === 'ZodObject'\n );\n}\n","import { EventEmitter } from 'events';\nimport { PassThrough } from 'stream';\nimport type { ToolsInput } from '@mastra/core/agent';\nimport type { RequestContext } from '@mastra/core/request-context';\nimport { MastraVoice } from '@mastra/core/voice';\nimport type { Realtime, RealtimeServerEvents } from 'openai-realtime-api';\nimport { WebSocket } from 'ws';\nimport { isReadableStream, transformTools } from './utils';\n\n/**\n * Event callback function type\n */\ntype EventCallback = (...args: any[]) => void;\n\ntype StreamWithId = PassThrough & { id: string };\n\n/**\n * Map of event types to their callback arrays\n */\ntype EventMap = {\n transcribing: [{ text: string }];\n writing: [{ text: string }];\n speaking: [{ audio: string }];\n speaker: [StreamWithId];\n error: [Error];\n} & {\n [key: string]: EventCallback[];\n};\n\n/** Default voice for text-to-speech. 'alloy' provides a neutral, balanced voice suitable for most use cases */\nconst DEFAULT_VOICE: Realtime.Voice = 'alloy';\n\nconst DEFAULT_TRANSCRIBER: Realtime.AudioTranscriptionModel = 'whisper-1';\n\nconst DEFAULT_URL = 'wss://api.openai.com/v1/realtime';\n\n/**\n * Default model for real-time voice interactions.\n * This model is optimized for low-latency responses while maintaining high quality output.\n */\nconst DEFAULT_MODEL = 'gpt-4o-mini-realtime-preview-2024-12-17';\n\n// /**\n// * Default Voice Activity Detection (VAD) configuration.\n// * These settings control how the system detects speech segments.\n// *\n// * @property {string} type - Uses server-side VAD for better accuracy\n// * @property {number} threshold - Speech detection sensitivity (0.5 = balanced)\n// * @property {number} prefix_padding_ms - Includes 1 second of audio before speech\n// * @property {number} silence_duration_ms - Waits 1 second of silence before ending turn\n// */\n// const DEFAULT_VAD_CONFIG = {\n// type: 'server_vad',\n// threshold: 0.5,\n// prefix_padding_ms: 1000,\n// silence_duration_ms: 1000,\n// } as Realtime.TurnDetection;\n\ntype TTools = ToolsInput;\n\n/**\n * Available voice options for text-to-speech.\n * Each voice has unique characteristics suitable for different use cases:\n * - alloy: Neutral and balanced\n * - echo: Warm and natural\n * - shimmer: Clear and expressive\n * - And more...\n */\nconst VOICES = ['alloy', 'ash', 'ballad', 'coral', 'echo', 'sage', 'shimmer', 'verse'];\n\ntype RealtimeClientServerEventMap = {\n [K in RealtimeServerEvents.EventType]: [RealtimeServerEvents.EventMap[K]];\n} & {\n ['conversation.item.input_audio_transcription.delta']: [{ delta: string; response_id: string }];\n ['conversation.item.input_audio_transcription.done']: [{ response_id: string }];\n};\n\n/**\n * OpenAIRealtimeVoice provides real-time voice interaction capabilities using OpenAI's\n * WebSocket-based API. It supports:\n * - Real-time text-to-speech\n * - Speech-to-text (transcription)\n * - Voice activity detection\n * - Multiple voice options\n * - Event-based audio streaming\n *\n * The class manages WebSocket connections, audio streaming, and event handling\n * for seamless voice interactions.\n *\n * @extends MastraVoice\n *\n * @example\n * ```typescript\n * const voice = new OpenAIRealtimeVoice({\n * apiKey: process.env.OPENAI_API_KEY,\n * model: 'gpt-4o-mini-realtime'\n * });\n *\n * await voice.open();\n * voice.on('speaking', (audioData) => {\n * // Handle audio data\n * });\n *\n * await voice.speak('Hello, how can I help you today?');\n * ```\n */\nexport class OpenAIRealtimeVoice extends MastraVoice {\n private ws?: WebSocket;\n private state: 'close' | 'open';\n private client: EventEmitter<RealtimeClientServerEventMap>;\n private events: EventMap;\n private instructions?: string;\n private tools?: TTools;\n private debug: boolean;\n private queue: unknown[] = [];\n private transcriber: Realtime.AudioTranscriptionModel;\n private requestContext?: RequestContext;\n /**\n * Creates a new instance of OpenAIRealtimeVoice.\n *\n * @param options - Configuration options for the voice instance\n * @param options.url - The base URL for the OpenAI Realtime API\n * @param options.model - The model ID to use (defaults to GPT-4 Mini Realtime)\n * @param options.apiKey - OpenAI API key. Falls back to process.env.OPENAI_API_KEY\n * @param options.speaker - Voice ID to use (defaults to 'alloy')\n * @param options.debug - Enable debug mode\n *\n * @example\n * ```typescript\n * const voice = new OpenAIRealtimeVoice({\n * apiKey: 'your-api-key',\n * model: 'gpt-4o-mini-realtime',\n * speaker: 'alloy'\n * });\n * ```\n */\n constructor(\n private options: {\n model?: string;\n url?: string;\n apiKey?: string;\n speaker?: Realtime.Voice;\n transcriber?: Realtime.AudioTranscriptionModel;\n debug?: boolean;\n } = {},\n ) {\n super();\n\n this.client = new EventEmitter();\n this.state = 'close';\n this.events = {} as EventMap;\n this.speaker = options.speaker || DEFAULT_VOICE;\n this.transcriber = options.transcriber || DEFAULT_TRANSCRIBER;\n this.debug = options.debug || false;\n }\n\n /**\n * Returns a list of available voice speakers.\n *\n * @returns Promise resolving to an array of voice objects, each containing at least a voiceId\n *\n * @example\n * ```typescript\n * const speakers = await voice.getSpeakers();\n * // speakers = [{ voiceId: 'alloy' }, { voiceId: 'echo' }, ...]\n * ```\n */\n getSpeakers(): Promise<Array<{ voiceId: string; [key: string]: any }>> {\n return Promise.resolve(VOICES.map(v => ({ voiceId: v })));\n }\n\n /**\n * Disconnects from the OpenAI realtime session and cleans up resources.\n * Should be called when you're done with the voice instance.\n *\n * @example\n * ```typescript\n * voice.close(); // Disconnects and cleans up\n * ```\n */\n close() {\n if (!this.ws) return;\n this.ws.close();\n this.state = 'close';\n }\n\n /**\n * Equips the voice instance with a set of instructions.\n * Instructions allow the model to perform additional actions during conversations.\n *\n * @param instructions - Optional instructions to addInstructions\n * @returns Transformed instructions ready for use with the model\n *\n * @example\n * ```typescript\n * voice.addInstructions('You are a helpful assistant.');\n * ```\n */\n addInstructions(instructions?: string) {\n this.instructions = instructions;\n }\n\n /**\n * Equips the voice instance with a set of tools.\n * Tools allow the model to perform additional actions during conversations.\n *\n * @param tools - Optional tools configuration to addTools\n * @returns Transformed tools configuration ready for use with the model\n *\n * @example\n * ```typescript\n * const tools = {\n * search: async (query: string) => { ... },\n * calculate: (expression: string) => { ... }\n * };\n * voice.addTools(tools);\n * ```\n */\n addTools(tools?: TTools) {\n this.tools = tools || {};\n }\n\n /**\n * Emits a speaking event using the configured voice model.\n * Can accept either a string or a readable stream as input.\n *\n * @param input - The text to convert to speech, or a readable stream containing the text\n * @param options - Optional configuration for this specific speech request\n * @param options.speaker - Override the voice to use for this specific request\n *\n * @throws {Error} If the input text is empty\n *\n * @example\n * ```typescript\n * // Simple text to speech\n * await voice.speak('Hello world');\n *\n * // With custom voice\n * await voice.speak('Hello world', { speaker: 'echo' });\n *\n * // Using a stream\n * const stream = fs.createReadStream('text.txt');\n * await voice.speak(stream);\n * ```\n */\n async speak(input: string | NodeJS.ReadableStream, options?: { speaker?: Realtime.Voice }): Promise<void> {\n if (typeof input !== 'string') {\n const chunks: Buffer[] = [];\n for await (const chunk of input) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));\n }\n input = Buffer.concat(chunks).toString('utf-8');\n }\n\n if (input.trim().length === 0) {\n throw new Error('Input text is empty');\n }\n\n this.sendEvent('response.create', {\n response: {\n instructions: `Repeat the following text: ${input}`,\n voice: options?.speaker ? options.speaker : undefined,\n },\n });\n }\n\n /**\n * Updates the session configuration for the voice instance.\n * This can be used to modify voice settings, turn detection, and other parameters.\n *\n * @param sessionConfig - New session configuration to apply\n *\n * @example\n * ```typescript\n * voice.updateConfig({\n * voice: 'echo',\n * turn_detection: {\n * type: 'server_vad',\n * threshold: 0.5,\n * silence_duration_ms: 1000\n * }\n * });\n * ```\n */\n updateConfig(sessionConfig: unknown): void {\n this.sendEvent('session.update', { session: sessionConfig });\n }\n\n /**\n * Checks if listening capabilities are enabled.\n *\n * @returns {Promise<{ enabled: boolean }>}\n */\n async getListener() {\n return { enabled: true };\n }\n\n /**\n * Processes audio input for speech recognition.\n * Takes a readable stream of audio data and emits a writing event.\n * The output of the writing event is int16 audio data.\n *\n * @param audioData - Readable stream containing the audio data to process\n * @param options - Optional configuration for audio processing\n *\n * @throws {Error} If the audio data format is not supported\n *\n * @example\n * ```typescript\n * // Process audio from a file\n * const audioStream = fs.createReadStream('audio.raw');\n * await voice.listen(audioStream);\n *\n * // Process audio with options\n * await voice.listen(microphoneStream, {\n * format: 'int16',\n * sampleRate: 24000\n * });\n * ```\n */\n async listen(audioData: NodeJS.ReadableStream): Promise<void> {\n if (isReadableStream(audioData)) {\n const chunks: Buffer[] = [];\n for await (const chunk of audioData) {\n const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n chunks.push(buffer);\n }\n\n const buffer = Buffer.concat(chunks);\n const int16Array = new Int16Array(buffer.buffer, buffer.byteOffset ?? 0, (buffer.byteLength ?? 0) / 2);\n const base64Audio = this.int16ArrayToBase64(int16Array);\n\n this.sendEvent('conversation.item.create', {\n item: {\n type: 'message',\n role: 'user',\n content: [{ type: 'input_audio', audio: base64Audio }],\n },\n });\n\n this.sendEvent('response.create', {\n response: {\n modalities: ['text'],\n instructions: `ONLY repeat the input and DO NOT say anything else`,\n },\n });\n } else {\n this.emit('error', new Error('Unsupported audio data format'));\n }\n }\n\n waitForOpen() {\n return new Promise(resolve => {\n this.ws?.on('open', resolve);\n });\n }\n\n waitForSessionCreated() {\n return new Promise(resolve => {\n this.client.on('session.created', resolve);\n });\n }\n\n /**\n * Establishes a connection to the OpenAI realtime service.\n * Must be called before using speak, listen, or relay functions.\n *\n * @throws {Error} If connection fails or session creation times out\n *\n * @example\n * ```typescript\n * await voice.open();\n * // Now ready for voice interactions\n * ```\n */\n async connect({ requestContext }: { requestContext?: RequestContext } = {}) {\n const url = `${this.options.url || DEFAULT_URL}?model=${this.options.model || DEFAULT_MODEL}`;\n const apiKey = this.options.apiKey || process.env.OPENAI_API_KEY;\n this.requestContext = requestContext;\n\n this.ws = new WebSocket(url, undefined, {\n headers: {\n Authorization: 'Bearer ' + apiKey,\n 'OpenAI-Beta': 'realtime=v1',\n },\n });\n\n this.setupEventListeners();\n await Promise.all([this.waitForOpen(), this.waitForSessionCreated()]);\n\n const openaiTools = transformTools(this.tools);\n this.updateConfig({\n instructions: this.instructions,\n tools: openaiTools.map(t => t.openaiTool),\n input_audio_transcription: {\n model: this.transcriber,\n },\n voice: this.speaker,\n });\n this.state = 'open';\n }\n\n disconnect() {\n this.state = 'close';\n this.ws?.close();\n }\n\n /**\n * Streams audio data in real-time to the OpenAI service.\n * Useful for continuous audio streaming scenarios like live microphone input.\n * Must be in 'open' state before calling this method.\n *\n * @param audioData - Readable stream of audio data to relay\n * @throws {Error} If audio format is not supported\n *\n * @example\n * ```typescript\n * // First connect\n * await voice.open();\n *\n * // Then relay audio\n * const micStream = getMicrophoneStream();\n * await voice.relay(micStream);\n * ```\n */\n async send(audioData: NodeJS.ReadableStream | Int16Array, eventId?: string): Promise<void> {\n if (!this.state || this.state !== 'open') {\n console.warn('Cannot relay audio when not open. Call open() first.');\n return;\n }\n\n if (isReadableStream(audioData)) {\n const stream = audioData as NodeJS.ReadableStream;\n stream.on('data', chunk => {\n try {\n const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n this.sendEvent('input_audio_buffer.append', { audio: buffer.toString('base64'), event_id: eventId });\n } catch (err) {\n this.emit('error', err);\n }\n });\n } else if (audioData instanceof Int16Array) {\n try {\n const base64Audio = this.int16ArrayToBase64(audioData);\n this.sendEvent('input_audio_buffer.append', { audio: base64Audio, event_id: eventId });\n } catch (err) {\n this.emit('error', err);\n }\n } else {\n this.emit('error', new Error('Unsupported audio data format'));\n }\n }\n\n /**\n * Sends a response to the OpenAI Realtime API.\n *\n * Trigger a response to the real-time session.\n *\n * @param {Object} params - The parameters object\n * @param {Realtime.ResponseConfig} params.options - Configuration options for the response\n * @returns {Promise<void>} A promise that resolves when the response has been sent\n *\n * @example\n * // Send a simple text response\n * await realtimeVoice.answer({\n * options: {\n * content: \"Hello, how can I help you today?\",\n * voice: \"alloy\"\n * }\n * });\n */\n async answer({ options }: { options?: Realtime.ResponseConfig }) {\n this.sendEvent('response.create', { response: options ?? {} });\n }\n\n /**\n * Registers an event listener for voice events.\n * Available events: 'speaking', 'writing, 'error'\n * Can listen to OpenAI Realtime events by prefixing with 'openAIRealtime:'\n * Such as 'openAIRealtime:conversation.item.completed', 'openAIRealtime:conversation.updated', etc.\n *\n * @param event - Name of the event to listen for\n * @param callback - Function to call when the event occurs\n *\n * @example\n * ```typescript\n * // Listen for speech events\n * voice.on('speaking', (audioData: Int16Array) => {\n * // Handle audio data\n * });\n *\n * // Handle errors\n * voice.on('error', (error: Error) => {\n * console.error('Voice error:', error);\n * });\n * ```\n */\n on(event: string, callback: EventCallback): void {\n if (!this.events[event]) {\n this.events[event] = [];\n }\n this.events[event].push(callback);\n }\n\n /**\n * Removes a previously registered event listener.\n *\n * @param event - Name of the event to stop listening to\n * @param callback - The specific callback function to remove\n *\n * @example\n * ```typescript\n * // Create event handler\n * const handleSpeech = (audioData: Int16Array) => {\n * // Handle audio data\n * };\n *\n * // Add listener\n * voice.on('speaking', handleSpeech);\n *\n * // Later, remove the listener\n * voice.off('speaking', handleSpeech);\n * ```\n */\n off(event: string, callback: EventCallback): void {\n if (!this.events[event]) return;\n\n const index = this.events[event].indexOf(callback);\n if (index !== -1) {\n this.events[event].splice(index, 1);\n }\n }\n\n /**\n * Emit an event with arguments\n * @param event Event name\n * @param args Arguments to pass to the callbacks\n */\n private emit(event: string, ...args: any[]): void {\n if (!this.events[event]) return;\n\n for (const callback of this.events[event]) {\n callback(...args);\n }\n }\n\n private setupEventListeners(): void {\n const speakerStreams = new Map<string, StreamWithId>();\n\n if (!this.ws) {\n throw new Error('WebSocket not initialized');\n }\n\n this.ws.on('message', message => {\n const data = JSON.parse(message.toString());\n this.client.emit(data.type, data);\n\n if (this.debug) {\n const { delta, ...fields } = data;\n console.info(data.type, fields, delta?.length < 100 ? delta : '');\n }\n });\n\n this.client.on('session.created', ev => {\n this.emit('session.created', ev);\n\n const queue = this.queue.splice(0, this.queue.length);\n for (const ev of queue) {\n this.ws?.send(JSON.stringify(ev));\n }\n });\n this.client.on('session.updated', ev => {\n this.emit('session.updated', ev);\n });\n this.client.on('response.created', ev => {\n this.emit('response.created', ev);\n\n const speakerStream = new PassThrough() as StreamWithId;\n\n speakerStream.id = ev.response.id;\n\n speakerStreams.set(ev.response.id, speakerStream);\n this.emit('speaker', speakerStream);\n });\n this.client.on('conversation.item.input_audio_transcription.delta', ev => {\n this.emit('writing', { text: ev.delta, response_id: ev.response_id, role: 'user' });\n });\n this.client.on('conversation.item.input_audio_transcription.done', ev => {\n this.emit('writing', { text: '\\n', response_id: ev.response_id, role: 'user' });\n });\n this.client.on('response.audio.delta', ev => {\n const audio = Buffer.from(ev.delta, 'base64');\n this.emit('speaking', { audio, response_id: ev.response_id });\n\n const stream = speakerStreams.get(ev.response_id);\n stream?.write(audio);\n });\n this.client.on('response.audio.done', ev => {\n this.emit('speaking.done', { response_id: ev.response_id });\n\n const stream = speakerStreams.get(ev.response_id);\n stream?.end();\n });\n this.client.on('response.audio_transcript.delta', ev => {\n this.emit('writing', { text: ev.delta, response_id: ev.response_id, role: 'assistant' });\n });\n this.client.on('response.audio_transcript.done', ev => {\n this.emit('writing', { text: '\\n', response_id: ev.response_id, role: 'assistant' });\n });\n this.client.on('response.text.delta', ev => {\n this.emit('writing', { text: ev.delta, response_id: ev.response_id, role: 'assistant' });\n });\n this.client.on('response.text.done', ev => {\n this.emit('writing', { text: '\\n', response_id: ev.response_id, role: 'assistant' });\n });\n this.client.on('response.done', async ev => {\n await this.handleFunctionCalls(ev);\n this.emit('response.done', ev);\n speakerStreams.delete(ev.response.id);\n });\n this.client.on('error', async ev => {\n this.emit('error', ev);\n });\n }\n\n private async handleFunctionCalls(ev: any) {\n for (const output of ev.response?.output ?? []) {\n if (output.type === 'function_call') {\n await this.handleFunctionCall(output);\n }\n }\n }\n\n private async handleFunctionCall(output: any) {\n try {\n const context = JSON.parse(output.arguments);\n const tool = this.tools?.[output.name];\n if (!tool) {\n console.warn(`Tool \"${output.name}\" not found`);\n return;\n }\n\n if (tool?.execute) {\n this.emit('tool-call-start', {\n toolCallId: output.call_id,\n toolName: output.name,\n toolDescription: tool.description,\n args: context,\n });\n }\n\n const result = await tool?.execute?.(\n { context, requestContext: this.requestContext },\n {\n toolCallId: output.call_id,\n messages: [],\n },\n );\n\n this.emit('tool-call-result', {\n toolCallId: output.call_id,\n toolName: output.name,\n toolDescription: tool.description,\n args: context,\n result,\n });\n\n this.sendEvent('conversation.item.create', {\n item: {\n type: 'function_call_output',\n call_id: output.call_id,\n output: JSON.stringify(result),\n },\n });\n } catch (e) {\n const err = e as Error;\n console.warn(`Error calling tool \"${output.name}\":`, err.message);\n this.sendEvent('conversation.item.create', {\n item: {\n type: 'function_call_output',\n call_id: output.call_id,\n output: JSON.stringify({ error: err.message }),\n },\n });\n } finally {\n this.sendEvent('response.create', {});\n }\n }\n\n private int16ArrayToBase64(int16Array: Int16Array): string {\n const buffer = new ArrayBuffer(int16Array.length * 2);\n const view = new DataView(buffer);\n for (let i = 0; i < int16Array.length; i++) {\n view.setInt16(i * 2, int16Array[i]!, true);\n }\n const uint8Array = new Uint8Array(buffer);\n let binary = '';\n for (let i = 0; i < uint8Array.length; i++) {\n binary += String.fromCharCode(uint8Array[i]!);\n }\n return btoa(binary);\n }\n\n private sendEvent(type: string, data: any) {\n if (!this.ws || this.ws.readyState !== this.ws.OPEN) {\n this.queue.push({ type: type, ...data });\n } else {\n this.ws?.send(\n JSON.stringify({\n type: type,\n ...data,\n }),\n );\n }\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mastra/voice-openai-realtime",
3
- "version": "0.11.12",
3
+ "version": "0.12.0-beta.0",
4
4
  "description": "Mastra OpenAI Realtime API integration",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -37,12 +37,12 @@
37
37
  "typescript": "^5.8.3",
38
38
  "vitest": "^3.2.4",
39
39
  "zod": "^3.25.76",
40
- "@internal/lint": "0.0.58",
41
- "@internal/types-builder": "0.0.33",
42
- "@mastra/core": "0.24.0"
40
+ "@internal/lint": "0.0.53",
41
+ "@internal/types-builder": "0.0.28",
42
+ "@mastra/core": "1.0.0-beta.0"
43
43
  },
44
44
  "peerDependencies": {
45
- "@mastra/core": ">=0.18.1-0 <0.25.0-0",
45
+ "@mastra/core": ">=1.0.0-0 <2.0.0-0",
46
46
  "zod": "^3.25.0 || ^4.0.0"
47
47
  },
48
48
  "homepage": "https://mastra.ai",
@@ -54,12 +54,8 @@
54
54
  "bugs": {
55
55
  "url": "https://github.com/mastra-ai/mastra/issues"
56
56
  },
57
- "publishConfig": {
58
- "access": "public",
59
- "publish-branch": [
60
- "main",
61
- "0.x"
62
- ]
57
+ "engines": {
58
+ "node": ">=22.13.0"
63
59
  },
64
60
  "scripts": {
65
61
  "build": "tsup --silent --config tsup.config.ts",