@sayna-ai/node-sdk 0.0.9 → 0.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,UAAW,SAAQ,KAAK;gBACvB,OAAO,EAAE,MAAM;CAK5B;AAED;;GAEG;AACH,qBAAa,sBAAuB,SAAQ,UAAU;gBACxC,OAAO,GAAE,MAA2C;CAKjE;AAED;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,UAAU;gBAE9C,OAAO,GAAE,MAA0F;CAMtG;AAED;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,UAAU;IAClD,SAAyB,KAAK,CAAC,EAAE,OAAO,CAAC;gBAE7B,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;CAM7C;AAED;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,UAAU;gBACtC,OAAO,EAAE,MAAM;CAK5B;AAED;;GAEG;AACH,qBAAa,gBAAiB,SAAQ,UAAU;gBAClC,OAAO,EAAE,MAAM;CAK5B"}
@@ -11,8 +11,8 @@ export * from "./webhook-receiver";
11
11
  * instantiation and connection, returning a ready-to-use client.
12
12
  *
13
13
  * @param url - The Sayna server URL (e.g., "https://api.sayna.ai")
14
- * @param sttConfig - Speech-to-text configuration
15
- * @param ttsConfig - Text-to-speech configuration
14
+ * @param sttConfig - Speech-to-text configuration (required when withoutAudio=false)
15
+ * @param ttsConfig - Text-to-speech configuration (required when withoutAudio=false)
16
16
  * @param livekitConfig - Optional LiveKit room configuration
17
17
  * @param withoutAudio - If true, disables audio streaming (default: false)
18
18
  * @param apiKey - Optional API key used to authorize HTTP and WebSocket calls (defaults to SAYNA_API_KEY env)
@@ -63,5 +63,5 @@ export * from "./webhook-receiver";
63
63
  * await client.disconnect();
64
64
  * ```
65
65
  */
66
- export declare function saynaConnect(url: string, sttConfig: STTConfig, ttsConfig: TTSConfig, livekitConfig?: LiveKitConfig, withoutAudio?: boolean, apiKey?: string): Promise<SaynaClient>;
66
+ export declare function saynaConnect(url: string, sttConfig?: STTConfig, ttsConfig?: TTSConfig, livekitConfig?: LiveKitConfig, withoutAudio?: boolean, apiKey?: string): Promise<SaynaClient>;
67
67
  //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAEnE,cAAc,gBAAgB,CAAC;AAC/B,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,oBAAoB,CAAC;AAEnC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,SAAS,EACrB,SAAS,CAAC,EAAE,SAAS,EACrB,aAAa,CAAC,EAAE,aAAa,EAC7B,YAAY,GAAE,OAAe,EAC7B,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,WAAW,CAAC,CAWtB"}
package/dist/index.js CHANGED
@@ -72,6 +72,7 @@ class SaynaClient {
72
72
  messageCallback;
73
73
  participantDisconnectedCallback;
74
74
  ttsPlaybackCompleteCallback;
75
+ sipTransferErrorCallback;
75
76
  readyPromiseResolve;
76
77
  readyPromiseReject;
77
78
  constructor(url, sttConfig, ttsConfig, livekitConfig, withoutAudio = false, apiKey, streamId) {
@@ -204,6 +205,18 @@ class SaynaClient {
204
205
  }
205
206
  break;
206
207
  }
208
+ case "sip_transfer_error": {
209
+ const sipTransferError = data;
210
+ if (this.sipTransferErrorCallback) {
211
+ await this.sipTransferErrorCallback(sipTransferError);
212
+ } else if (this.errorCallback) {
213
+ await this.errorCallback({
214
+ type: "error",
215
+ message: sipTransferError.message
216
+ });
217
+ }
218
+ break;
219
+ }
207
220
  case "message": {
208
221
  const messageData = data;
209
222
  if (this.messageCallback) {
@@ -225,6 +238,15 @@ class SaynaClient {
225
238
  }
226
239
  break;
227
240
  }
241
+ default: {
242
+ const unknownMessage = data;
243
+ const errorMessage = `Unknown message type received: ${unknownMessage.type}`;
244
+ if (this.errorCallback) {
245
+ await this.errorCallback({ type: "error", message: errorMessage });
246
+ } else {
247
+ console.warn(errorMessage);
248
+ }
249
+ }
228
250
  }
229
251
  } catch (error) {
230
252
  if (this.errorCallback) {
@@ -337,6 +359,9 @@ class SaynaClient {
337
359
  registerOnTtsPlaybackComplete(callback) {
338
360
  this.ttsPlaybackCompleteCallback = callback;
339
361
  }
362
+ registerOnSipTransferError(callback) {
363
+ this.sipTransferErrorCallback = callback;
364
+ }
340
365
  speak(text, flush = true, allowInterruption = true) {
341
366
  if (!this.isConnected || !this.websocket) {
342
367
  throw new SaynaNotConnectedError;
@@ -404,6 +429,26 @@ class SaynaClient {
404
429
  throw new SaynaConnectionError("Failed to send message", error);
405
430
  }
406
431
  }
432
+ sipTransfer(transferTo) {
433
+ if (!this.isConnected || !this.websocket) {
434
+ throw new SaynaNotConnectedError;
435
+ }
436
+ if (!this.isReady) {
437
+ throw new SaynaNotReadyError;
438
+ }
439
+ if (typeof transferTo !== "string" || transferTo.trim().length === 0) {
440
+ throw new SaynaValidationError("transfer_to must be a non-empty string");
441
+ }
442
+ try {
443
+ const sipTransferMessage = {
444
+ type: "sip_transfer",
445
+ transfer_to: transferTo.trim()
446
+ };
447
+ this.websocket.send(JSON.stringify(sipTransferMessage));
448
+ } catch (error) {
449
+ throw new SaynaConnectionError("Failed to send SIP transfer command", error);
450
+ }
451
+ }
407
452
  async health() {
408
453
  return this.fetchFromSayna("");
409
454
  }
@@ -651,4 +696,4 @@ export {
651
696
  SaynaClient
652
697
  };
653
698
 
654
- //# debugId=439FAA862268544264756E2164756E21
699
+ //# debugId=5692EE242C83976364756E2164756E21
package/dist/index.js.map CHANGED
@@ -3,11 +3,11 @@
3
3
  "sources": ["../src/errors.ts", "../src/sayna-client.ts", "../src/webhook-receiver.ts", "../src/index.ts"],
4
4
  "sourcesContent": [
5
5
  "/**\n * Base error class for all Sayna SDK errors.\n */\nexport class SaynaError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"SaynaError\";\n Object.setPrototypeOf(this, SaynaError.prototype);\n }\n}\n\n/**\n * Error thrown when attempting to use the client before it's connected.\n */\nexport class SaynaNotConnectedError extends SaynaError {\n constructor(message: string = \"Not connected to Sayna WebSocket\") {\n super(message);\n this.name = \"SaynaNotConnectedError\";\n Object.setPrototypeOf(this, SaynaNotConnectedError.prototype);\n }\n}\n\n/**\n * Error thrown when attempting operations before the client is ready.\n */\nexport class SaynaNotReadyError extends SaynaError {\n constructor(\n message: string = \"Sayna voice providers are not ready. Wait for the connection to be established.\"\n ) {\n super(message);\n this.name = \"SaynaNotReadyError\";\n Object.setPrototypeOf(this, SaynaNotReadyError.prototype);\n }\n}\n\n/**\n * Error thrown when WebSocket connection fails.\n */\nexport class SaynaConnectionError extends SaynaError {\n public override readonly cause?: unknown;\n\n constructor(message: string, cause?: unknown) {\n super(message);\n this.name = \"SaynaConnectionError\";\n this.cause = cause;\n Object.setPrototypeOf(this, SaynaConnectionError.prototype);\n }\n}\n\n/**\n * Error thrown when invalid parameters are provided.\n */\nexport class SaynaValidationError extends SaynaError {\n constructor(message: string) {\n super(message);\n this.name = \"SaynaValidationError\";\n Object.setPrototypeOf(this, SaynaValidationError.prototype);\n }\n}\n\n/**\n * Error thrown when the server returns an error.\n */\nexport class SaynaServerError extends SaynaError {\n constructor(message: string) {\n super(message);\n this.name = \"SaynaServerError\";\n Object.setPrototypeOf(this, SaynaServerError.prototype);\n }\n}\n",
6
- "import type {\n STTConfig,\n TTSConfig,\n LiveKitConfig,\n ConfigMessage,\n SpeakMessage,\n ClearMessage,\n SendMessageMessage,\n STTResultMessage,\n ErrorMessage,\n OutgoingMessage,\n SaynaMessage,\n Participant,\n VoicesResponse,\n HealthResponse,\n LiveKitTokenResponse,\n SipHook,\n SipHooksResponse,\n} from \"./types\";\nimport {\n SaynaNotConnectedError,\n SaynaNotReadyError,\n SaynaConnectionError,\n SaynaValidationError,\n SaynaServerError,\n} from \"./errors\";\n\n// Node.js 18+ has native fetch support\ndeclare const fetch: typeof globalThis.fetch;\n\n/**\n * Event handler for speech-to-text results.\n */\nexport type STTResultHandler = (\n result: STTResultMessage\n) => void | Promise<void>;\n\n/**\n * Event handler for text-to-speech audio data.\n */\nexport type TTSAudioHandler = (audio: ArrayBuffer) => void | Promise<void>;\n\n/**\n * Event handler for error messages.\n */\nexport type ErrorHandler = (error: ErrorMessage) => void | Promise<void>;\n\n/**\n * Event handler for participant messages.\n */\nexport type MessageHandler = (message: SaynaMessage) => void | Promise<void>;\n\n/**\n * Event handler for participant disconnections.\n */\nexport type ParticipantDisconnectedHandler = (\n participant: Participant\n) => void | Promise<void>;\n\n/**\n * Event handler for TTS playback completion.\n */\nexport type TTSPlaybackCompleteHandler = (\n timestamp: number\n) => void | Promise<void>;\n\n/**\n * Client for connecting to Sayna WebSocket server for real-time voice interactions.\n *\n * @example\n * ```typescript\n * const client = await saynaConnect(\n * \"https://api.sayna.ai\",\n * sttConfig,\n * ttsConfig\n * );\n *\n * client.registerOnSttResult((result) => {\n * console.log(\"Transcription:\", result.transcript);\n * });\n *\n * await client.speak(\"Hello, world!\");\n * ```\n */\nexport class SaynaClient {\n private url: string;\n private sttConfig?: STTConfig;\n private ttsConfig?: TTSConfig;\n private livekitConfig?: LiveKitConfig;\n private withoutAudio: boolean;\n private apiKey?: string;\n private websocket?: WebSocket;\n private isConnected: boolean = false;\n private isReady: boolean = false;\n private _livekitRoomName?: string;\n private _livekitUrl?: string;\n private _saynaParticipantIdentity?: string;\n private _saynaParticipantName?: string;\n private _streamId?: string;\n private inputStreamId?: string;\n private sttCallback?: STTResultHandler;\n private ttsCallback?: TTSAudioHandler;\n private errorCallback?: ErrorHandler;\n private messageCallback?: MessageHandler;\n private participantDisconnectedCallback?: ParticipantDisconnectedHandler;\n private ttsPlaybackCompleteCallback?: TTSPlaybackCompleteHandler;\n private readyPromiseResolve?: () => void;\n private readyPromiseReject?: (error: Error) => void;\n\n /**\n * Creates a new SaynaClient instance.\n *\n * @param url - The Sayna server URL (e.g., \"https://api.sayna.ai\")\n * @param sttConfig - Speech-to-text configuration (required when withoutAudio=false)\n * @param ttsConfig - Text-to-speech configuration (required when withoutAudio=false)\n * @param livekitConfig - Optional LiveKit room configuration\n * @param withoutAudio - If true, disables audio streaming (default: false)\n * @param apiKey - Optional API key used to authorize HTTP and WebSocket calls (defaults to SAYNA_API_KEY env)\n * @param streamId - Optional session identifier for recording paths; server generates a UUID when omitted\n *\n * @throws {SaynaValidationError} If URL is invalid or if audio configs are missing when audio is enabled\n */\n constructor(\n url: string,\n sttConfig?: STTConfig,\n ttsConfig?: TTSConfig,\n livekitConfig?: LiveKitConfig,\n withoutAudio: boolean = false,\n apiKey?: string,\n streamId?: string\n ) {\n // Validate URL\n if (!url || typeof url !== \"string\") {\n throw new SaynaValidationError(\"URL must be a non-empty string\");\n }\n if (\n !url.startsWith(\"http://\") &&\n !url.startsWith(\"https://\") &&\n !url.startsWith(\"ws://\") &&\n !url.startsWith(\"wss://\")\n ) {\n throw new SaynaValidationError(\n \"URL must start with http://, https://, ws://, or wss://\"\n );\n }\n\n // Validate audio config requirements\n if (!withoutAudio) {\n if (!sttConfig || !ttsConfig) {\n throw new SaynaValidationError(\n \"sttConfig and ttsConfig are required when withoutAudio=false (audio streaming enabled). \" +\n \"Either provide both configs or set withoutAudio=true for non-audio use cases.\"\n );\n }\n }\n\n this.url = url;\n this.sttConfig = sttConfig;\n this.ttsConfig = ttsConfig;\n this.livekitConfig = livekitConfig;\n this.withoutAudio = withoutAudio;\n this.apiKey = apiKey ?? process.env.SAYNA_API_KEY;\n this.inputStreamId = streamId;\n }\n\n /**\n * Establishes connection to the Sayna WebSocket server.\n *\n * @throws {SaynaConnectionError} If connection fails\n * @returns Promise that resolves when the connection is ready\n */\n async connect(): Promise<void> {\n if (this.isConnected) {\n return;\n }\n\n // Convert HTTP(S) URL to WebSocket URL\n const wsUrl =\n this.url.replace(/^https:\\/\\//, \"wss://\").replace(/^http:\\/\\//, \"ws://\") +\n (this.url.endsWith(\"/\") ? \"ws\" : \"/ws\");\n\n return new Promise((resolve, reject) => {\n this.readyPromiseResolve = resolve;\n this.readyPromiseReject = reject;\n\n try {\n const headers = this.apiKey\n ? { Authorization: `Bearer ${this.apiKey}` }\n : undefined;\n\n const WebSocketConstructor = WebSocket as unknown as {\n new (\n url: string,\n protocols?: string | string[],\n options?: { headers?: Record<string, string> }\n ): WebSocket;\n };\n\n this.websocket = headers\n ? new WebSocketConstructor(wsUrl, undefined, { headers })\n : new WebSocket(wsUrl);\n\n this.websocket.onopen = () => {\n this.isConnected = true;\n\n // Send initial configuration\n const configMessage: ConfigMessage = {\n type: \"config\",\n stream_id: this.inputStreamId,\n stt_config: this.sttConfig,\n tts_config: this.ttsConfig,\n livekit: this.livekitConfig,\n audio: !this.withoutAudio,\n };\n\n try {\n if (this.websocket) {\n this.websocket.send(JSON.stringify(configMessage));\n }\n } catch (error) {\n this.cleanup();\n const err = new SaynaConnectionError(\n \"Failed to send configuration\",\n error\n );\n if (this.readyPromiseReject) {\n this.readyPromiseReject(err);\n }\n }\n };\n\n this.websocket.onmessage = async (event) => {\n try {\n if (\n event.data instanceof Blob ||\n event.data instanceof ArrayBuffer\n ) {\n // Binary TTS audio data\n const buffer =\n event.data instanceof Blob\n ? await event.data.arrayBuffer()\n : event.data;\n if (this.ttsCallback) {\n await this.ttsCallback(buffer);\n }\n } else {\n // JSON control messages\n if (typeof event.data !== \"string\") {\n throw new Error(\"Expected string data for JSON messages\");\n }\n const data = JSON.parse(event.data) as OutgoingMessage;\n await this.handleJsonMessage(data);\n }\n } catch (error) {\n // Log parse errors but don't break the connection\n if (this.errorCallback) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n await this.errorCallback({\n type: \"error\",\n message: `Failed to process message: ${errorMessage}`,\n });\n }\n }\n };\n\n this.websocket.onerror = () => {\n const error = new SaynaConnectionError(\"WebSocket connection error\");\n if (this.readyPromiseReject && !this.isReady) {\n this.readyPromiseReject(error);\n }\n };\n\n this.websocket.onclose = (event) => {\n const wasReady = this.isReady;\n this.cleanup();\n\n // If connection closed before ready, reject the promise\n if (!wasReady && this.readyPromiseReject) {\n this.readyPromiseReject(\n new SaynaConnectionError(\n `WebSocket closed before ready (code: ${event.code}, reason: ${event.reason || \"none\"})`\n )\n );\n }\n };\n } catch (error) {\n reject(new SaynaConnectionError(\"Failed to create WebSocket\", error));\n }\n });\n }\n\n /**\n * Handles incoming JSON messages from the WebSocket.\n * @internal\n */\n private async handleJsonMessage(data: OutgoingMessage): Promise<void> {\n const messageType = data.type;\n\n try {\n switch (messageType) {\n case \"ready\": {\n const readyMsg = data;\n this.isReady = true;\n this._livekitRoomName = readyMsg.livekit_room_name;\n this._livekitUrl = readyMsg.livekit_url;\n this._saynaParticipantIdentity = readyMsg.sayna_participant_identity;\n this._saynaParticipantName = readyMsg.sayna_participant_name;\n this._streamId = readyMsg.stream_id;\n if (this.readyPromiseResolve) {\n this.readyPromiseResolve();\n }\n break;\n }\n\n case \"stt_result\": {\n const sttResult = data;\n if (this.sttCallback) {\n await this.sttCallback(sttResult);\n }\n break;\n }\n\n case \"error\": {\n const errorMsg = data;\n if (this.errorCallback) {\n await this.errorCallback(errorMsg);\n }\n if (this.readyPromiseReject && !this.isReady) {\n this.readyPromiseReject(new SaynaServerError(errorMsg.message));\n }\n break;\n }\n\n case \"message\": {\n const messageData = data;\n if (this.messageCallback) {\n await this.messageCallback(messageData.message);\n }\n break;\n }\n\n case \"participant_disconnected\": {\n const participantMsg = data;\n if (this.participantDisconnectedCallback) {\n await this.participantDisconnectedCallback(\n participantMsg.participant\n );\n }\n break;\n }\n\n case \"tts_playback_complete\": {\n const ttsPlaybackCompleteMsg = data;\n if (this.ttsPlaybackCompleteCallback) {\n await this.ttsPlaybackCompleteCallback(\n ttsPlaybackCompleteMsg.timestamp\n );\n }\n break;\n }\n }\n } catch (error) {\n // Notify error callback if handler fails\n if (this.errorCallback) {\n await this.errorCallback({\n type: \"error\",\n message: `Handler error: ${error instanceof Error ? error.message : String(error)}`,\n });\n }\n }\n }\n\n /**\n * Cleans up internal state.\n * @internal\n */\n private cleanup(): void {\n this.isConnected = false;\n this.isReady = false;\n this._livekitRoomName = undefined;\n this._livekitUrl = undefined;\n this._saynaParticipantIdentity = undefined;\n this._saynaParticipantName = undefined;\n this._streamId = undefined;\n }\n\n /**\n * Converts WebSocket URL to HTTP URL for REST API calls.\n * @internal\n */\n private getHttpUrl(): string {\n return this.url\n .replace(/^ws:\\/\\//, \"http://\")\n .replace(/^wss:\\/\\//, \"https://\");\n }\n\n /**\n * Generic fetch helper for making REST API calls to Sayna server.\n * Handles URL construction, headers, error responses, and type conversion.\n * @internal\n *\n * @param endpoint - API endpoint path (e.g., \"/voices\", \"/speak\")\n * @param options - Fetch options including method, body, headers, etc.\n * @param responseType - Expected response type: \"json\" or \"arrayBuffer\"\n * @returns Promise resolving to the parsed response\n * @throws {SaynaConnectionError} If the network request fails\n * @throws {SaynaServerError} If the server returns an error response\n */\n private async fetchFromSayna<T>(\n endpoint: string,\n options: RequestInit = {},\n responseType: \"json\" | \"arrayBuffer\" = \"json\"\n ): Promise<T> {\n const httpUrl = this.getHttpUrl();\n const url = `${httpUrl}${httpUrl.endsWith(\"/\") ? \"\" : \"/\"}${endpoint.startsWith(\"/\") ? endpoint.slice(1) : endpoint}`;\n\n // Merge default headers with user-provided headers\n const headers: Record<string, string> = {\n ...(options.headers as Record<string, string>),\n };\n\n // Add Authorization header when an API key is provided, unless user supplied one\n const hasAuthHeader = Object.keys(headers).some(\n (key) => key.toLowerCase() === \"authorization\"\n );\n if (this.apiKey && !hasAuthHeader) {\n headers[\"Authorization\"] = `Bearer ${this.apiKey}`;\n }\n\n // Add Content-Type for JSON requests if not already set\n if (options.method === \"POST\" && options.body && !headers[\"Content-Type\"]) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n\n try {\n const response = await fetch(url, {\n ...options,\n headers,\n });\n\n if (!response.ok) {\n // Try to parse error message from JSON response\n let errorMessage: string;\n try {\n const errorData: unknown = await response.json();\n errorMessage =\n errorData &&\n typeof errorData === \"object\" &&\n \"error\" in errorData &&\n typeof errorData.error === \"string\"\n ? errorData.error\n : `Request failed: ${response.status} ${response.statusText}`;\n } catch {\n errorMessage = `Request failed: ${response.status} ${response.statusText}`;\n }\n throw new SaynaServerError(errorMessage);\n }\n\n // Parse response based on expected type\n if (responseType === \"arrayBuffer\") {\n return (await response.arrayBuffer()) as T;\n } else {\n return (await response.json()) as T;\n }\n } catch (error) {\n // Re-throw SaynaServerError as-is\n if (error instanceof SaynaServerError) {\n throw error;\n }\n // Wrap other errors in SaynaConnectionError\n throw new SaynaConnectionError(`Failed to fetch from ${endpoint}`, error);\n }\n }\n\n /**\n * Disconnects from the Sayna WebSocket server and cleans up resources.\n */\n disconnect(): void {\n if (this.websocket) {\n // Remove event handlers to prevent memory leaks\n this.websocket.onopen = null;\n this.websocket.onmessage = null;\n this.websocket.onerror = null;\n this.websocket.onclose = null;\n\n if (this.websocket.readyState === WebSocket.OPEN) {\n this.websocket.close(1000, \"Client disconnect\");\n }\n\n this.websocket = undefined;\n }\n\n this.cleanup();\n }\n\n /**\n * Sends audio data to the server for speech recognition.\n *\n * @param audioData - Raw audio data as ArrayBuffer\n * @throws {SaynaNotConnectedError} If not connected\n * @throws {SaynaNotReadyError} If connection is not ready\n */\n onAudioInput(audioData: ArrayBuffer): void {\n if (!this.isConnected || !this.websocket) {\n throw new SaynaNotConnectedError();\n }\n\n if (!this.isReady) {\n throw new SaynaNotReadyError();\n }\n\n if (!(audioData instanceof ArrayBuffer)) {\n throw new SaynaValidationError(\"audioData must be an ArrayBuffer\");\n }\n\n if (audioData.byteLength === 0) {\n throw new SaynaValidationError(\"audioData cannot be empty\");\n }\n\n try {\n this.websocket.send(audioData);\n } catch (error) {\n throw new SaynaConnectionError(\"Failed to send audio data\", error);\n }\n }\n\n /**\n * Registers a callback for speech-to-text results.\n *\n * @param callback - Function to call when STT results are received\n */\n registerOnSttResult(callback: STTResultHandler): void {\n this.sttCallback = callback;\n }\n\n /**\n * Registers a callback for text-to-speech audio data.\n *\n * @param callback - Function to call when TTS audio is received\n */\n registerOnTtsAudio(callback: TTSAudioHandler): void {\n this.ttsCallback = callback;\n }\n\n /**\n * Registers a callback for error messages.\n *\n * @param callback - Function to call when errors occur\n */\n registerOnError(callback: ErrorHandler): void {\n this.errorCallback = callback;\n }\n\n /**\n * Registers a callback for participant messages.\n *\n * @param callback - Function to call when messages are received\n */\n registerOnMessage(callback: MessageHandler): void {\n this.messageCallback = callback;\n }\n\n /**\n * Registers a callback for participant disconnection events.\n *\n * @param callback - Function to call when a participant disconnects\n */\n registerOnParticipantDisconnected(\n callback: ParticipantDisconnectedHandler\n ): void {\n this.participantDisconnectedCallback = callback;\n }\n\n /**\n * Registers a callback for TTS playback completion.\n *\n * @param callback - Function to call when TTS playback is complete\n */\n registerOnTtsPlaybackComplete(callback: TTSPlaybackCompleteHandler): void {\n this.ttsPlaybackCompleteCallback = callback;\n }\n\n /**\n * Sends text to be synthesized as speech.\n *\n * @param text - Text to synthesize\n * @param flush - Whether to flush the TTS queue before speaking (default: true)\n * @param allowInterruption - Whether this speech can be interrupted (default: true)\n * @throws {SaynaNotConnectedError} If not connected\n * @throws {SaynaNotReadyError} If connection is not ready\n * @throws {SaynaValidationError} If text is not a string\n */\n speak(\n text: string,\n flush: boolean = true,\n allowInterruption: boolean = true\n ): void {\n if (!this.isConnected || !this.websocket) {\n throw new SaynaNotConnectedError();\n }\n\n if (!this.isReady) {\n throw new SaynaNotReadyError();\n }\n\n if (typeof text !== \"string\") {\n throw new SaynaValidationError(\"text must be a string\");\n }\n\n try {\n const speakMessage: SpeakMessage = {\n type: \"speak\",\n text,\n flush,\n allow_interruption: allowInterruption,\n };\n this.websocket.send(JSON.stringify(speakMessage));\n } catch (error) {\n throw new SaynaConnectionError(\"Failed to send speak command\", error);\n }\n }\n\n /**\n * Clears the text-to-speech queue.\n *\n * @throws {SaynaNotConnectedError} If not connected\n * @throws {SaynaNotReadyError} If connection is not ready\n */\n clear(): void {\n if (!this.isConnected || !this.websocket) {\n throw new SaynaNotConnectedError();\n }\n\n if (!this.isReady) {\n throw new SaynaNotReadyError();\n }\n\n try {\n const clearMessage: ClearMessage = {\n type: \"clear\",\n };\n this.websocket.send(JSON.stringify(clearMessage));\n } catch (error) {\n throw new SaynaConnectionError(\"Failed to send clear command\", error);\n }\n }\n\n /**\n * Flushes the TTS queue by sending an empty speak command.\n *\n * @param allowInterruption - Whether the flush can be interrupted (default: true)\n * @throws {SaynaNotConnectedError} If not connected\n * @throws {SaynaNotReadyError} If connection is not ready\n */\n ttsFlush(allowInterruption: boolean = true): void {\n this.speak(\"\", true, allowInterruption);\n }\n\n /**\n * Sends a message to the Sayna session.\n *\n * @param message - Message content\n * @param role - Message role (e.g., \"user\", \"assistant\")\n * @param topic - Optional topic identifier\n * @param debug - Optional debug metadata\n * @throws {SaynaNotConnectedError} If not connected\n * @throws {SaynaNotReadyError} If connection is not ready\n * @throws {SaynaValidationError} If parameters are invalid\n */\n sendMessage(\n message: string,\n role: string,\n topic?: string,\n debug?: Record<string, unknown>\n ): void {\n if (!this.isConnected || !this.websocket) {\n throw new SaynaNotConnectedError();\n }\n\n if (!this.isReady) {\n throw new SaynaNotReadyError();\n }\n\n if (typeof message !== \"string\") {\n throw new SaynaValidationError(\"message must be a string\");\n }\n\n if (typeof role !== \"string\") {\n throw new SaynaValidationError(\"role must be a string\");\n }\n\n try {\n const sendMsg: SendMessageMessage = {\n type: \"send_message\",\n message,\n role,\n topic,\n debug,\n };\n this.websocket.send(JSON.stringify(sendMsg));\n } catch (error) {\n throw new SaynaConnectionError(\"Failed to send message\", error);\n }\n }\n\n /**\n * Performs a health check on the Sayna server.\n *\n * @returns Promise that resolves with the health status\n * @throws {SaynaConnectionError} If the request fails\n * @throws {SaynaServerError} If server returns an error\n *\n * @example\n * ```typescript\n * const health = await client.health();\n * console.log(health.status); // \"OK\"\n * ```\n */\n async health(): Promise<HealthResponse> {\n return this.fetchFromSayna<HealthResponse>(\"\");\n }\n\n /**\n * Retrieves the catalogue of text-to-speech voices grouped by provider.\n *\n * @returns Promise that resolves with voices organized by provider\n * @throws {SaynaConnectionError} If the request fails\n * @throws {SaynaServerError} If server returns an error\n *\n * @example\n * ```typescript\n * const voices = await client.getVoices();\n * for (const [provider, voiceList] of Object.entries(voices)) {\n * console.log(`${provider}:`, voiceList.map(v => v.name));\n * }\n * ```\n */\n async getVoices(): Promise<VoicesResponse> {\n return this.fetchFromSayna<VoicesResponse>(\"voices\");\n }\n\n /**\n * Synthesizes text into audio using the REST API endpoint.\n * This is a standalone synthesis method that doesn't require an active WebSocket connection.\n *\n * @param text - Text to synthesize\n * @param ttsConfig - Text-to-speech configuration\n * @returns Promise that resolves with the audio data as ArrayBuffer\n * @throws {SaynaValidationError} If text is empty\n * @throws {SaynaConnectionError} If the request fails\n * @throws {SaynaServerError} If server returns an error\n *\n * @example\n * ```typescript\n * const audioBuffer = await client.speakRest(\"Hello, world!\", {\n * provider: \"elevenlabs\",\n * voice_id: \"21m00Tcm4TlvDq8ikWAM\",\n * model: \"eleven_turbo_v2\",\n * speaking_rate: 1.0,\n * audio_format: \"mp3\",\n * sample_rate: 24000,\n * connection_timeout: 30,\n * request_timeout: 60,\n * pronunciations: []\n * });\n * ```\n */\n async speakRest(text: string, ttsConfig: TTSConfig): Promise<ArrayBuffer> {\n if (!text || text.trim().length === 0) {\n throw new SaynaValidationError(\"Text cannot be empty\");\n }\n\n return this.fetchFromSayna<ArrayBuffer>(\n \"speak\",\n {\n method: \"POST\",\n body: JSON.stringify({\n text,\n tts_config: ttsConfig,\n }),\n },\n \"arrayBuffer\"\n );\n }\n\n /**\n * Issues a LiveKit access token for a participant.\n *\n * @param roomName - LiveKit room to join or create\n * @param participantName - Display name assigned to the participant\n * @param participantIdentity - Unique identifier for the participant\n * @returns Promise that resolves with the LiveKit token and connection details\n * @throws {SaynaValidationError} If any parameter is empty\n * @throws {SaynaConnectionError} If the request fails\n * @throws {SaynaServerError} If server returns an error\n *\n * @example\n * ```typescript\n * const tokenInfo = await client.getLiveKitToken(\n * \"my-room\",\n * \"John Doe\",\n * \"user-123\"\n * );\n * console.log(\"Token:\", tokenInfo.token);\n * console.log(\"LiveKit URL:\", tokenInfo.livekit_url);\n * ```\n */\n async getLiveKitToken(\n roomName: string,\n participantName: string,\n participantIdentity: string\n ): Promise<LiveKitTokenResponse> {\n if (!roomName || roomName.trim().length === 0) {\n throw new SaynaValidationError(\"room_name cannot be empty\");\n }\n\n if (!participantName || participantName.trim().length === 0) {\n throw new SaynaValidationError(\"participant_name cannot be empty\");\n }\n\n if (!participantIdentity || participantIdentity.trim().length === 0) {\n throw new SaynaValidationError(\"participant_identity cannot be empty\");\n }\n\n return this.fetchFromSayna<LiveKitTokenResponse>(\"livekit/token\", {\n method: \"POST\",\n body: JSON.stringify({\n room_name: roomName,\n participant_name: participantName,\n participant_identity: participantIdentity,\n }),\n });\n }\n\n /**\n * Downloads the recorded audio file for a completed session.\n *\n * @param streamId - The session identifier (obtained from the `streamId` getter after connection)\n * @returns Promise that resolves with the audio data as ArrayBuffer (OGG format)\n * @throws {SaynaValidationError} If streamId is empty\n * @throws {SaynaConnectionError} If the network request fails\n * @throws {SaynaServerError} If the recording is not found or server returns an error\n *\n * @example\n * ```typescript\n * // After a session completes, download the recording\n * const audioBuffer = await client.getRecording(client.streamId!);\n *\n * // Save to file (Node.js)\n * import { writeFile } from \"fs/promises\";\n * await writeFile(\"recording.ogg\", Buffer.from(audioBuffer));\n * ```\n */\n async getRecording(streamId: string): Promise<ArrayBuffer> {\n if (!streamId || streamId.trim().length === 0) {\n throw new SaynaValidationError(\"streamId cannot be empty\");\n }\n\n return this.fetchFromSayna<ArrayBuffer>(\n `recording/${encodeURIComponent(streamId)}`,\n { method: \"GET\" },\n \"arrayBuffer\"\n );\n }\n\n /**\n * Retrieves all configured SIP webhook hooks from the runtime cache.\n *\n * @returns Promise that resolves with the list of configured SIP hooks\n * @throws {SaynaConnectionError} If the request fails\n * @throws {SaynaServerError} If server returns an error (e.g., 500 if reading cache fails)\n *\n * @example\n * ```typescript\n * const response = await client.getSipHooks();\n * for (const hook of response.hooks) {\n * console.log(`Host: ${hook.host}, URL: ${hook.url}`);\n * }\n * ```\n */\n async getSipHooks(): Promise<SipHooksResponse> {\n return this.fetchFromSayna<SipHooksResponse>(\"sip/hooks\");\n }\n\n /**\n * Sets or updates SIP webhook hooks in the runtime cache.\n *\n * Hooks with matching hosts will be replaced; new hosts will be added.\n * The response contains the merged list of all hooks (existing + new).\n *\n * @param hooks - Array of SIP hook configurations to add or replace\n * @returns Promise that resolves with the merged list of all configured hooks\n * @throws {SaynaValidationError} If hooks array is empty or contains invalid entries\n * @throws {SaynaConnectionError} If the request fails\n * @throws {SaynaServerError} If server returns an error (e.g., 400 for duplicate hosts, 500 for cache errors)\n *\n * @example\n * ```typescript\n * const response = await client.setSipHooks([\n * { host: \"example.com\", url: \"https://webhook.example.com/events\" },\n * { host: \"another.com\", url: \"https://webhook.another.com/events\" }\n * ]);\n * console.log(\"Total hooks configured:\", response.hooks.length);\n * ```\n */\n async setSipHooks(hooks: SipHook[]): Promise<SipHooksResponse> {\n if (!Array.isArray(hooks)) {\n throw new SaynaValidationError(\"hooks must be an array\");\n }\n\n if (hooks.length === 0) {\n throw new SaynaValidationError(\"hooks array cannot be empty\");\n }\n\n for (const [i, hook] of hooks.entries()) {\n if (\n !hook.host ||\n typeof hook.host !== \"string\" ||\n hook.host.trim().length === 0\n ) {\n throw new SaynaValidationError(\n `hooks[${i}].host must be a non-empty string`\n );\n }\n if (\n !hook.url ||\n typeof hook.url !== \"string\" ||\n hook.url.trim().length === 0\n ) {\n throw new SaynaValidationError(\n `hooks[${i}].url must be a non-empty string`\n );\n }\n }\n\n return this.fetchFromSayna<SipHooksResponse>(\"sip/hooks\", {\n method: \"POST\",\n body: JSON.stringify({ hooks }),\n });\n }\n\n /**\n * Deletes SIP webhook hooks by host name from the runtime cache.\n *\n * If a deleted host exists in the original server configuration,\n * it will revert to its config value after deletion.\n *\n * @param hosts - Array of host names to remove (case-insensitive)\n * @returns Promise that resolves with the updated list of hooks after deletion\n * @throws {SaynaValidationError} If hosts array is empty or contains invalid entries\n * @throws {SaynaConnectionError} If the request fails\n * @throws {SaynaServerError} If server returns an error (e.g., 400 for empty hosts, 500 for cache errors)\n *\n * @example\n * ```typescript\n * const response = await client.deleteSipHooks([\"example.com\", \"another.com\"]);\n * console.log(\"Remaining hooks:\", response.hooks.length);\n * ```\n */\n async deleteSipHooks(hosts: string[]): Promise<SipHooksResponse> {\n if (!Array.isArray(hosts)) {\n throw new SaynaValidationError(\"hosts must be an array\");\n }\n\n if (hosts.length === 0) {\n throw new SaynaValidationError(\"hosts array cannot be empty\");\n }\n\n for (const [i, host] of hosts.entries()) {\n if (!host || typeof host !== \"string\" || host.trim().length === 0) {\n throw new SaynaValidationError(\n `hosts[${i}] must be a non-empty string`\n );\n }\n }\n\n return this.fetchFromSayna<SipHooksResponse>(\"sip/hooks\", {\n method: \"DELETE\",\n body: JSON.stringify({ hosts }),\n });\n }\n\n /**\n * Whether the client is ready to send/receive data.\n */\n get ready(): boolean {\n return this.isReady;\n }\n\n /**\n * Whether the client is connected to the WebSocket.\n */\n get connected(): boolean {\n return this.isConnected;\n }\n\n /**\n * LiveKit room name acknowledged by the server, if available.\n */\n get livekitRoomName(): string | undefined {\n return this._livekitRoomName;\n }\n\n /**\n * LiveKit WebSocket URL configured on the server, if available.\n */\n get livekitUrl(): string | undefined {\n return this._livekitUrl;\n }\n\n /**\n * Identity assigned to the agent participant when LiveKit is enabled, if available.\n */\n get saynaParticipantIdentity(): string | undefined {\n return this._saynaParticipantIdentity;\n }\n\n /**\n * Display name assigned to the agent participant when LiveKit is enabled, if available.\n */\n get saynaParticipantName(): string | undefined {\n return this._saynaParticipantName;\n }\n\n /**\n * Session identifier returned by the server.\n * This can be used to download recordings or correlate session data.\n * The value is available after the connection is ready.\n */\n get streamId(): string | undefined {\n return this._streamId;\n }\n}\n",
6
+ "import type {\n STTConfig,\n TTSConfig,\n LiveKitConfig,\n ConfigMessage,\n SpeakMessage,\n ClearMessage,\n SendMessageMessage,\n STTResultMessage,\n ErrorMessage,\n SipTransferErrorMessage,\n SipTransferMessage,\n OutgoingMessage,\n SaynaMessage,\n Participant,\n VoicesResponse,\n HealthResponse,\n LiveKitTokenResponse,\n SipHook,\n SipHooksResponse,\n} from \"./types\";\nimport {\n SaynaNotConnectedError,\n SaynaNotReadyError,\n SaynaConnectionError,\n SaynaValidationError,\n SaynaServerError,\n} from \"./errors\";\n\n// Node.js 18+ has native fetch support\ndeclare const fetch: typeof globalThis.fetch;\n\n/**\n * Event handler for speech-to-text results.\n */\nexport type STTResultHandler = (\n result: STTResultMessage\n) => void | Promise<void>;\n\n/**\n * Event handler for text-to-speech audio data.\n */\nexport type TTSAudioHandler = (audio: ArrayBuffer) => void | Promise<void>;\n\n/**\n * Event handler for error messages.\n */\nexport type ErrorHandler = (error: ErrorMessage) => void | Promise<void>;\n\n/**\n * Event handler for participant messages.\n */\nexport type MessageHandler = (message: SaynaMessage) => void | Promise<void>;\n\n/**\n * Event handler for participant disconnections.\n */\nexport type ParticipantDisconnectedHandler = (\n participant: Participant\n) => void | Promise<void>;\n\n/**\n * Event handler for TTS playback completion.\n */\nexport type TTSPlaybackCompleteHandler = (\n timestamp: number\n) => void | Promise<void>;\n\n/**\n * Event handler for SIP transfer specific errors.\n */\nexport type SipTransferErrorHandler = (\n error: SipTransferErrorMessage\n) => void | Promise<void>;\n\n/**\n * Client for connecting to Sayna WebSocket server for real-time voice interactions.\n *\n * @example\n * ```typescript\n * const client = await saynaConnect(\n * \"https://api.sayna.ai\",\n * sttConfig,\n * ttsConfig\n * );\n *\n * client.registerOnSttResult((result) => {\n * console.log(\"Transcription:\", result.transcript);\n * });\n *\n * await client.speak(\"Hello, world!\");\n * ```\n */\nexport class SaynaClient {\n private url: string;\n private sttConfig?: STTConfig;\n private ttsConfig?: TTSConfig;\n private livekitConfig?: LiveKitConfig;\n private withoutAudio: boolean;\n private apiKey?: string;\n private websocket?: WebSocket;\n private isConnected: boolean = false;\n private isReady: boolean = false;\n private _livekitRoomName?: string;\n private _livekitUrl?: string;\n private _saynaParticipantIdentity?: string;\n private _saynaParticipantName?: string;\n private _streamId?: string;\n private inputStreamId?: string;\n private sttCallback?: STTResultHandler;\n private ttsCallback?: TTSAudioHandler;\n private errorCallback?: ErrorHandler;\n private messageCallback?: MessageHandler;\n private participantDisconnectedCallback?: ParticipantDisconnectedHandler;\n private ttsPlaybackCompleteCallback?: TTSPlaybackCompleteHandler;\n private sipTransferErrorCallback?: SipTransferErrorHandler;\n private readyPromiseResolve?: () => void;\n private readyPromiseReject?: (error: Error) => void;\n\n /**\n * Creates a new SaynaClient instance.\n *\n * @param url - The Sayna server URL (e.g., \"https://api.sayna.ai\")\n * @param sttConfig - Speech-to-text configuration (required when withoutAudio=false)\n * @param ttsConfig - Text-to-speech configuration (required when withoutAudio=false)\n * @param livekitConfig - Optional LiveKit room configuration\n * @param withoutAudio - If true, disables audio streaming (default: false)\n * @param apiKey - Optional API key used to authorize HTTP and WebSocket calls (defaults to SAYNA_API_KEY env)\n * @param streamId - Optional session identifier for recording paths; server generates a UUID when omitted\n *\n * @throws {SaynaValidationError} If URL is invalid or if audio configs are missing when audio is enabled\n */\n constructor(\n url: string,\n sttConfig?: STTConfig,\n ttsConfig?: TTSConfig,\n livekitConfig?: LiveKitConfig,\n withoutAudio: boolean = false,\n apiKey?: string,\n streamId?: string\n ) {\n // Validate URL\n if (!url || typeof url !== \"string\") {\n throw new SaynaValidationError(\"URL must be a non-empty string\");\n }\n if (\n !url.startsWith(\"http://\") &&\n !url.startsWith(\"https://\") &&\n !url.startsWith(\"ws://\") &&\n !url.startsWith(\"wss://\")\n ) {\n throw new SaynaValidationError(\n \"URL must start with http://, https://, ws://, or wss://\"\n );\n }\n\n // Validate audio config requirements\n if (!withoutAudio) {\n if (!sttConfig || !ttsConfig) {\n throw new SaynaValidationError(\n \"sttConfig and ttsConfig are required when withoutAudio=false (audio streaming enabled). \" +\n \"Either provide both configs or set withoutAudio=true for non-audio use cases.\"\n );\n }\n }\n\n this.url = url;\n this.sttConfig = sttConfig;\n this.ttsConfig = ttsConfig;\n this.livekitConfig = livekitConfig;\n this.withoutAudio = withoutAudio;\n this.apiKey = apiKey ?? process.env.SAYNA_API_KEY;\n this.inputStreamId = streamId;\n }\n\n /**\n * Establishes connection to the Sayna WebSocket server.\n *\n * @throws {SaynaConnectionError} If connection fails\n * @returns Promise that resolves when the connection is ready\n */\n async connect(): Promise<void> {\n if (this.isConnected) {\n return;\n }\n\n // Convert HTTP(S) URL to WebSocket URL\n const wsUrl =\n this.url.replace(/^https:\\/\\//, \"wss://\").replace(/^http:\\/\\//, \"ws://\") +\n (this.url.endsWith(\"/\") ? \"ws\" : \"/ws\");\n\n return new Promise((resolve, reject) => {\n this.readyPromiseResolve = resolve;\n this.readyPromiseReject = reject;\n\n try {\n const headers = this.apiKey\n ? { Authorization: `Bearer ${this.apiKey}` }\n : undefined;\n\n const WebSocketConstructor = WebSocket as unknown as {\n new (\n url: string,\n protocols?: string | string[],\n options?: { headers?: Record<string, string> }\n ): WebSocket;\n };\n\n this.websocket = headers\n ? new WebSocketConstructor(wsUrl, undefined, { headers })\n : new WebSocket(wsUrl);\n\n this.websocket.onopen = () => {\n this.isConnected = true;\n\n // Send initial configuration\n const configMessage: ConfigMessage = {\n type: \"config\",\n stream_id: this.inputStreamId,\n stt_config: this.sttConfig,\n tts_config: this.ttsConfig,\n livekit: this.livekitConfig,\n audio: !this.withoutAudio,\n };\n\n try {\n if (this.websocket) {\n this.websocket.send(JSON.stringify(configMessage));\n }\n } catch (error) {\n this.cleanup();\n const err = new SaynaConnectionError(\n \"Failed to send configuration\",\n error\n );\n if (this.readyPromiseReject) {\n this.readyPromiseReject(err);\n }\n }\n };\n\n this.websocket.onmessage = async (event) => {\n try {\n if (\n event.data instanceof Blob ||\n event.data instanceof ArrayBuffer\n ) {\n // Binary TTS audio data\n const buffer =\n event.data instanceof Blob\n ? await event.data.arrayBuffer()\n : event.data;\n if (this.ttsCallback) {\n await this.ttsCallback(buffer);\n }\n } else {\n // JSON control messages\n if (typeof event.data !== \"string\") {\n throw new Error(\"Expected string data for JSON messages\");\n }\n const data = JSON.parse(event.data) as OutgoingMessage;\n await this.handleJsonMessage(data);\n }\n } catch (error) {\n // Log parse errors but don't break the connection\n if (this.errorCallback) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n await this.errorCallback({\n type: \"error\",\n message: `Failed to process message: ${errorMessage}`,\n });\n }\n }\n };\n\n this.websocket.onerror = () => {\n const error = new SaynaConnectionError(\"WebSocket connection error\");\n if (this.readyPromiseReject && !this.isReady) {\n this.readyPromiseReject(error);\n }\n };\n\n this.websocket.onclose = (event) => {\n const wasReady = this.isReady;\n this.cleanup();\n\n // If connection closed before ready, reject the promise\n if (!wasReady && this.readyPromiseReject) {\n this.readyPromiseReject(\n new SaynaConnectionError(\n `WebSocket closed before ready (code: ${event.code}, reason: ${event.reason || \"none\"})`\n )\n );\n }\n };\n } catch (error) {\n reject(new SaynaConnectionError(\"Failed to create WebSocket\", error));\n }\n });\n }\n\n /**\n * Handles incoming JSON messages from the WebSocket.\n * @internal\n */\n private async handleJsonMessage(data: OutgoingMessage): Promise<void> {\n const messageType = data.type;\n\n try {\n switch (messageType) {\n case \"ready\": {\n const readyMsg = data;\n this.isReady = true;\n this._livekitRoomName = readyMsg.livekit_room_name;\n this._livekitUrl = readyMsg.livekit_url;\n this._saynaParticipantIdentity = readyMsg.sayna_participant_identity;\n this._saynaParticipantName = readyMsg.sayna_participant_name;\n this._streamId = readyMsg.stream_id;\n if (this.readyPromiseResolve) {\n this.readyPromiseResolve();\n }\n break;\n }\n\n case \"stt_result\": {\n const sttResult = data;\n if (this.sttCallback) {\n await this.sttCallback(sttResult);\n }\n break;\n }\n\n case \"error\": {\n const errorMsg = data;\n if (this.errorCallback) {\n await this.errorCallback(errorMsg);\n }\n if (this.readyPromiseReject && !this.isReady) {\n this.readyPromiseReject(new SaynaServerError(errorMsg.message));\n }\n break;\n }\n\n case \"sip_transfer_error\": {\n const sipTransferError = data;\n if (this.sipTransferErrorCallback) {\n await this.sipTransferErrorCallback(sipTransferError);\n } else if (this.errorCallback) {\n await this.errorCallback({\n type: \"error\",\n message: sipTransferError.message,\n });\n }\n break;\n }\n\n case \"message\": {\n const messageData = data;\n if (this.messageCallback) {\n await this.messageCallback(messageData.message);\n }\n break;\n }\n\n case \"participant_disconnected\": {\n const participantMsg = data;\n if (this.participantDisconnectedCallback) {\n await this.participantDisconnectedCallback(\n participantMsg.participant\n );\n }\n break;\n }\n\n case \"tts_playback_complete\": {\n const ttsPlaybackCompleteMsg = data;\n if (this.ttsPlaybackCompleteCallback) {\n await this.ttsPlaybackCompleteCallback(\n ttsPlaybackCompleteMsg.timestamp\n );\n }\n break;\n }\n\n default: {\n const unknownMessage = data as { type: string };\n const errorMessage = `Unknown message type received: ${unknownMessage.type}`;\n if (this.errorCallback) {\n await this.errorCallback({ type: \"error\", message: errorMessage });\n } else {\n console.warn(errorMessage);\n }\n }\n }\n } catch (error) {\n // Notify error callback if handler fails\n if (this.errorCallback) {\n await this.errorCallback({\n type: \"error\",\n message: `Handler error: ${error instanceof Error ? error.message : String(error)}`,\n });\n }\n }\n }\n\n /**\n * Cleans up internal state.\n * @internal\n */\n private cleanup(): void {\n this.isConnected = false;\n this.isReady = false;\n this._livekitRoomName = undefined;\n this._livekitUrl = undefined;\n this._saynaParticipantIdentity = undefined;\n this._saynaParticipantName = undefined;\n this._streamId = undefined;\n }\n\n /**\n * Converts WebSocket URL to HTTP URL for REST API calls.\n * @internal\n */\n private getHttpUrl(): string {\n return this.url\n .replace(/^ws:\\/\\//, \"http://\")\n .replace(/^wss:\\/\\//, \"https://\");\n }\n\n /**\n * Generic fetch helper for making REST API calls to Sayna server.\n * Handles URL construction, headers, error responses, and type conversion.\n * @internal\n *\n * @param endpoint - API endpoint path (e.g., \"/voices\", \"/speak\")\n * @param options - Fetch options including method, body, headers, etc.\n * @param responseType - Expected response type: \"json\" or \"arrayBuffer\"\n * @returns Promise resolving to the parsed response\n * @throws {SaynaConnectionError} If the network request fails\n * @throws {SaynaServerError} If the server returns an error response\n */\n private async fetchFromSayna<T>(\n endpoint: string,\n options: RequestInit = {},\n responseType: \"json\" | \"arrayBuffer\" = \"json\"\n ): Promise<T> {\n const httpUrl = this.getHttpUrl();\n const url = `${httpUrl}${httpUrl.endsWith(\"/\") ? \"\" : \"/\"}${endpoint.startsWith(\"/\") ? endpoint.slice(1) : endpoint}`;\n\n // Merge default headers with user-provided headers\n const headers: Record<string, string> = {\n ...(options.headers as Record<string, string>),\n };\n\n // Add Authorization header when an API key is provided, unless user supplied one\n const hasAuthHeader = Object.keys(headers).some(\n (key) => key.toLowerCase() === \"authorization\"\n );\n if (this.apiKey && !hasAuthHeader) {\n headers[\"Authorization\"] = `Bearer ${this.apiKey}`;\n }\n\n // Add Content-Type for JSON requests if not already set\n if (options.method === \"POST\" && options.body && !headers[\"Content-Type\"]) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n\n try {\n const response = await fetch(url, {\n ...options,\n headers,\n });\n\n if (!response.ok) {\n // Try to parse error message from JSON response\n let errorMessage: string;\n try {\n const errorData: unknown = await response.json();\n errorMessage =\n errorData &&\n typeof errorData === \"object\" &&\n \"error\" in errorData &&\n typeof errorData.error === \"string\"\n ? errorData.error\n : `Request failed: ${response.status} ${response.statusText}`;\n } catch {\n errorMessage = `Request failed: ${response.status} ${response.statusText}`;\n }\n throw new SaynaServerError(errorMessage);\n }\n\n // Parse response based on expected type\n if (responseType === \"arrayBuffer\") {\n return (await response.arrayBuffer()) as T;\n } else {\n return (await response.json()) as T;\n }\n } catch (error) {\n // Re-throw SaynaServerError as-is\n if (error instanceof SaynaServerError) {\n throw error;\n }\n // Wrap other errors in SaynaConnectionError\n throw new SaynaConnectionError(`Failed to fetch from ${endpoint}`, error);\n }\n }\n\n /**\n * Disconnects from the Sayna WebSocket server and cleans up resources.\n */\n disconnect(): void {\n if (this.websocket) {\n // Remove event handlers to prevent memory leaks\n this.websocket.onopen = null;\n this.websocket.onmessage = null;\n this.websocket.onerror = null;\n this.websocket.onclose = null;\n\n if (this.websocket.readyState === WebSocket.OPEN) {\n this.websocket.close(1000, \"Client disconnect\");\n }\n\n this.websocket = undefined;\n }\n\n this.cleanup();\n }\n\n /**\n * Sends audio data to the server for speech recognition.\n *\n * @param audioData - Raw audio data as ArrayBuffer\n * @throws {SaynaNotConnectedError} If not connected\n * @throws {SaynaNotReadyError} If connection is not ready\n */\n onAudioInput(audioData: ArrayBuffer): void {\n if (!this.isConnected || !this.websocket) {\n throw new SaynaNotConnectedError();\n }\n\n if (!this.isReady) {\n throw new SaynaNotReadyError();\n }\n\n if (!(audioData instanceof ArrayBuffer)) {\n throw new SaynaValidationError(\"audioData must be an ArrayBuffer\");\n }\n\n if (audioData.byteLength === 0) {\n throw new SaynaValidationError(\"audioData cannot be empty\");\n }\n\n try {\n this.websocket.send(audioData);\n } catch (error) {\n throw new SaynaConnectionError(\"Failed to send audio data\", error);\n }\n }\n\n /**\n * Registers a callback for speech-to-text results.\n *\n * @param callback - Function to call when STT results are received\n */\n registerOnSttResult(callback: STTResultHandler): void {\n this.sttCallback = callback;\n }\n\n /**\n * Registers a callback for text-to-speech audio data.\n *\n * @param callback - Function to call when TTS audio is received\n */\n registerOnTtsAudio(callback: TTSAudioHandler): void {\n this.ttsCallback = callback;\n }\n\n /**\n * Registers a callback for error messages.\n *\n * @param callback - Function to call when errors occur\n */\n registerOnError(callback: ErrorHandler): void {\n this.errorCallback = callback;\n }\n\n /**\n * Registers a callback for participant messages.\n *\n * @param callback - Function to call when messages are received\n */\n registerOnMessage(callback: MessageHandler): void {\n this.messageCallback = callback;\n }\n\n /**\n * Registers a callback for participant disconnection events.\n *\n * @param callback - Function to call when a participant disconnects\n */\n registerOnParticipantDisconnected(\n callback: ParticipantDisconnectedHandler\n ): void {\n this.participantDisconnectedCallback = callback;\n }\n\n /**\n * Registers a callback for TTS playback completion.\n *\n * @param callback - Function to call when TTS playback is complete\n */\n registerOnTtsPlaybackComplete(callback: TTSPlaybackCompleteHandler): void {\n this.ttsPlaybackCompleteCallback = callback;\n }\n\n /**\n * Registers a callback for SIP transfer specific errors.\n *\n * @param callback - Function to call when a SIP transfer error message is received\n */\n registerOnSipTransferError(callback: SipTransferErrorHandler): void {\n this.sipTransferErrorCallback = callback;\n }\n\n /**\n * Sends text to be synthesized as speech.\n *\n * @param text - Text to synthesize\n * @param flush - Whether to flush the TTS queue before speaking (default: true)\n * @param allowInterruption - Whether this speech can be interrupted (default: true)\n * @throws {SaynaNotConnectedError} If not connected\n * @throws {SaynaNotReadyError} If connection is not ready\n * @throws {SaynaValidationError} If text is not a string\n */\n speak(\n text: string,\n flush: boolean = true,\n allowInterruption: boolean = true\n ): void {\n if (!this.isConnected || !this.websocket) {\n throw new SaynaNotConnectedError();\n }\n\n if (!this.isReady) {\n throw new SaynaNotReadyError();\n }\n\n if (typeof text !== \"string\") {\n throw new SaynaValidationError(\"text must be a string\");\n }\n\n try {\n const speakMessage: SpeakMessage = {\n type: \"speak\",\n text,\n flush,\n allow_interruption: allowInterruption,\n };\n this.websocket.send(JSON.stringify(speakMessage));\n } catch (error) {\n throw new SaynaConnectionError(\"Failed to send speak command\", error);\n }\n }\n\n /**\n * Clears the text-to-speech queue.\n *\n * @throws {SaynaNotConnectedError} If not connected\n * @throws {SaynaNotReadyError} If connection is not ready\n */\n clear(): void {\n if (!this.isConnected || !this.websocket) {\n throw new SaynaNotConnectedError();\n }\n\n if (!this.isReady) {\n throw new SaynaNotReadyError();\n }\n\n try {\n const clearMessage: ClearMessage = {\n type: \"clear\",\n };\n this.websocket.send(JSON.stringify(clearMessage));\n } catch (error) {\n throw new SaynaConnectionError(\"Failed to send clear command\", error);\n }\n }\n\n /**\n * Flushes the TTS queue by sending an empty speak command.\n *\n * @param allowInterruption - Whether the flush can be interrupted (default: true)\n * @throws {SaynaNotConnectedError} If not connected\n * @throws {SaynaNotReadyError} If connection is not ready\n */\n ttsFlush(allowInterruption: boolean = true): void {\n this.speak(\"\", true, allowInterruption);\n }\n\n /**\n * Sends a message to the Sayna session.\n *\n * @param message - Message content\n * @param role - Message role (e.g., \"user\", \"assistant\")\n * @param topic - Optional topic identifier\n * @param debug - Optional debug metadata\n * @throws {SaynaNotConnectedError} If not connected\n * @throws {SaynaNotReadyError} If connection is not ready\n * @throws {SaynaValidationError} If parameters are invalid\n */\n sendMessage(\n message: string,\n role: string,\n topic?: string,\n debug?: Record<string, unknown>\n ): void {\n if (!this.isConnected || !this.websocket) {\n throw new SaynaNotConnectedError();\n }\n\n if (!this.isReady) {\n throw new SaynaNotReadyError();\n }\n\n if (typeof message !== \"string\") {\n throw new SaynaValidationError(\"message must be a string\");\n }\n\n if (typeof role !== \"string\") {\n throw new SaynaValidationError(\"role must be a string\");\n }\n\n try {\n const sendMsg: SendMessageMessage = {\n type: \"send_message\",\n message,\n role,\n topic,\n debug,\n };\n this.websocket.send(JSON.stringify(sendMsg));\n } catch (error) {\n throw new SaynaConnectionError(\"Failed to send message\", error);\n }\n }\n\n /**\n * Initiates a SIP transfer for the active LiveKit session.\n *\n * @param transferTo - Destination phone number or extension to transfer to\n * @throws {SaynaNotConnectedError} If not connected\n * @throws {SaynaNotReadyError} If connection is not ready\n * @throws {SaynaValidationError} If transferTo is not a non-empty string\n */\n sipTransfer(transferTo: string): void {\n if (!this.isConnected || !this.websocket) {\n throw new SaynaNotConnectedError();\n }\n\n if (!this.isReady) {\n throw new SaynaNotReadyError();\n }\n\n if (typeof transferTo !== \"string\" || transferTo.trim().length === 0) {\n throw new SaynaValidationError(\"transfer_to must be a non-empty string\");\n }\n\n try {\n const sipTransferMessage: SipTransferMessage = {\n type: \"sip_transfer\",\n transfer_to: transferTo.trim(),\n };\n this.websocket.send(JSON.stringify(sipTransferMessage));\n } catch (error) {\n throw new SaynaConnectionError(\n \"Failed to send SIP transfer command\",\n error\n );\n }\n }\n\n /**\n * Performs a health check on the Sayna server.\n *\n * @returns Promise that resolves with the health status\n * @throws {SaynaConnectionError} If the request fails\n * @throws {SaynaServerError} If server returns an error\n *\n * @example\n * ```typescript\n * const health = await client.health();\n * console.log(health.status); // \"OK\"\n * ```\n */\n async health(): Promise<HealthResponse> {\n return this.fetchFromSayna<HealthResponse>(\"\");\n }\n\n /**\n * Retrieves the catalogue of text-to-speech voices grouped by provider.\n *\n * @returns Promise that resolves with voices organized by provider\n * @throws {SaynaConnectionError} If the request fails\n * @throws {SaynaServerError} If server returns an error\n *\n * @example\n * ```typescript\n * const voices = await client.getVoices();\n * for (const [provider, voiceList] of Object.entries(voices)) {\n * console.log(`${provider}:`, voiceList.map(v => v.name));\n * }\n * ```\n */\n async getVoices(): Promise<VoicesResponse> {\n return this.fetchFromSayna<VoicesResponse>(\"voices\");\n }\n\n /**\n * Synthesizes text into audio using the REST API endpoint.\n * This is a standalone synthesis method that doesn't require an active WebSocket connection.\n *\n * @param text - Text to synthesize\n * @param ttsConfig - Text-to-speech configuration\n * @returns Promise that resolves with the audio data as ArrayBuffer\n * @throws {SaynaValidationError} If text is empty\n * @throws {SaynaConnectionError} If the request fails\n * @throws {SaynaServerError} If server returns an error\n *\n * @example\n * ```typescript\n * const audioBuffer = await client.speakRest(\"Hello, world!\", {\n * provider: \"elevenlabs\",\n * voice_id: \"21m00Tcm4TlvDq8ikWAM\",\n * model: \"eleven_turbo_v2\",\n * speaking_rate: 1.0,\n * audio_format: \"mp3\",\n * sample_rate: 24000,\n * connection_timeout: 30,\n * request_timeout: 60,\n * pronunciations: []\n * });\n * ```\n */\n async speakRest(text: string, ttsConfig: TTSConfig): Promise<ArrayBuffer> {\n if (!text || text.trim().length === 0) {\n throw new SaynaValidationError(\"Text cannot be empty\");\n }\n\n return this.fetchFromSayna<ArrayBuffer>(\n \"speak\",\n {\n method: \"POST\",\n body: JSON.stringify({\n text,\n tts_config: ttsConfig,\n }),\n },\n \"arrayBuffer\"\n );\n }\n\n /**\n * Issues a LiveKit access token for a participant.\n *\n * @param roomName - LiveKit room to join or create\n * @param participantName - Display name assigned to the participant\n * @param participantIdentity - Unique identifier for the participant\n * @returns Promise that resolves with the LiveKit token and connection details\n * @throws {SaynaValidationError} If any parameter is empty\n * @throws {SaynaConnectionError} If the request fails\n * @throws {SaynaServerError} If server returns an error\n *\n * @example\n * ```typescript\n * const tokenInfo = await client.getLiveKitToken(\n * \"my-room\",\n * \"John Doe\",\n * \"user-123\"\n * );\n * console.log(\"Token:\", tokenInfo.token);\n * console.log(\"LiveKit URL:\", tokenInfo.livekit_url);\n * ```\n */\n async getLiveKitToken(\n roomName: string,\n participantName: string,\n participantIdentity: string\n ): Promise<LiveKitTokenResponse> {\n if (!roomName || roomName.trim().length === 0) {\n throw new SaynaValidationError(\"room_name cannot be empty\");\n }\n\n if (!participantName || participantName.trim().length === 0) {\n throw new SaynaValidationError(\"participant_name cannot be empty\");\n }\n\n if (!participantIdentity || participantIdentity.trim().length === 0) {\n throw new SaynaValidationError(\"participant_identity cannot be empty\");\n }\n\n return this.fetchFromSayna<LiveKitTokenResponse>(\"livekit/token\", {\n method: \"POST\",\n body: JSON.stringify({\n room_name: roomName,\n participant_name: participantName,\n participant_identity: participantIdentity,\n }),\n });\n }\n\n /**\n * Downloads the recorded audio file for a completed session.\n *\n * @param streamId - The session identifier (obtained from the `streamId` getter after connection)\n * @returns Promise that resolves with the audio data as ArrayBuffer (OGG format)\n * @throws {SaynaValidationError} If streamId is empty\n * @throws {SaynaConnectionError} If the network request fails\n * @throws {SaynaServerError} If the recording is not found or server returns an error\n *\n * @example\n * ```typescript\n * // After a session completes, download the recording\n * const audioBuffer = await client.getRecording(client.streamId!);\n *\n * // Save to file (Node.js)\n * import { writeFile } from \"fs/promises\";\n * await writeFile(\"recording.ogg\", Buffer.from(audioBuffer));\n * ```\n */\n async getRecording(streamId: string): Promise<ArrayBuffer> {\n if (!streamId || streamId.trim().length === 0) {\n throw new SaynaValidationError(\"streamId cannot be empty\");\n }\n\n return this.fetchFromSayna<ArrayBuffer>(\n `recording/${encodeURIComponent(streamId)}`,\n { method: \"GET\" },\n \"arrayBuffer\"\n );\n }\n\n /**\n * Retrieves all configured SIP webhook hooks from the runtime cache.\n *\n * @returns Promise that resolves with the list of configured SIP hooks\n * @throws {SaynaConnectionError} If the request fails\n * @throws {SaynaServerError} If server returns an error (e.g., 500 if reading cache fails)\n *\n * @example\n * ```typescript\n * const response = await client.getSipHooks();\n * for (const hook of response.hooks) {\n * console.log(`Host: ${hook.host}, URL: ${hook.url}`);\n * }\n * ```\n */\n async getSipHooks(): Promise<SipHooksResponse> {\n return this.fetchFromSayna<SipHooksResponse>(\"sip/hooks\");\n }\n\n /**\n * Sets or updates SIP webhook hooks in the runtime cache.\n *\n * Hooks with matching hosts will be replaced; new hosts will be added.\n * The response contains the merged list of all hooks (existing + new).\n *\n * @param hooks - Array of SIP hook configurations to add or replace\n * @returns Promise that resolves with the merged list of all configured hooks\n * @throws {SaynaValidationError} If hooks array is empty or contains invalid entries\n * @throws {SaynaConnectionError} If the request fails\n * @throws {SaynaServerError} If server returns an error (e.g., 400 for duplicate hosts, 500 for cache errors)\n *\n * @example\n * ```typescript\n * const response = await client.setSipHooks([\n * { host: \"example.com\", url: \"https://webhook.example.com/events\" },\n * { host: \"another.com\", url: \"https://webhook.another.com/events\" }\n * ]);\n * console.log(\"Total hooks configured:\", response.hooks.length);\n * ```\n */\n async setSipHooks(hooks: SipHook[]): Promise<SipHooksResponse> {\n if (!Array.isArray(hooks)) {\n throw new SaynaValidationError(\"hooks must be an array\");\n }\n\n if (hooks.length === 0) {\n throw new SaynaValidationError(\"hooks array cannot be empty\");\n }\n\n for (const [i, hook] of hooks.entries()) {\n if (\n !hook.host ||\n typeof hook.host !== \"string\" ||\n hook.host.trim().length === 0\n ) {\n throw new SaynaValidationError(\n `hooks[${i}].host must be a non-empty string`\n );\n }\n if (\n !hook.url ||\n typeof hook.url !== \"string\" ||\n hook.url.trim().length === 0\n ) {\n throw new SaynaValidationError(\n `hooks[${i}].url must be a non-empty string`\n );\n }\n }\n\n return this.fetchFromSayna<SipHooksResponse>(\"sip/hooks\", {\n method: \"POST\",\n body: JSON.stringify({ hooks }),\n });\n }\n\n /**\n * Deletes SIP webhook hooks by host name from the runtime cache.\n *\n * If a deleted host exists in the original server configuration,\n * it will revert to its config value after deletion.\n *\n * @param hosts - Array of host names to remove (case-insensitive)\n * @returns Promise that resolves with the updated list of hooks after deletion\n * @throws {SaynaValidationError} If hosts array is empty or contains invalid entries\n * @throws {SaynaConnectionError} If the request fails\n * @throws {SaynaServerError} If server returns an error (e.g., 400 for empty hosts, 500 for cache errors)\n *\n * @example\n * ```typescript\n * const response = await client.deleteSipHooks([\"example.com\", \"another.com\"]);\n * console.log(\"Remaining hooks:\", response.hooks.length);\n * ```\n */\n async deleteSipHooks(hosts: string[]): Promise<SipHooksResponse> {\n if (!Array.isArray(hosts)) {\n throw new SaynaValidationError(\"hosts must be an array\");\n }\n\n if (hosts.length === 0) {\n throw new SaynaValidationError(\"hosts array cannot be empty\");\n }\n\n for (const [i, host] of hosts.entries()) {\n if (!host || typeof host !== \"string\" || host.trim().length === 0) {\n throw new SaynaValidationError(\n `hosts[${i}] must be a non-empty string`\n );\n }\n }\n\n return this.fetchFromSayna<SipHooksResponse>(\"sip/hooks\", {\n method: \"DELETE\",\n body: JSON.stringify({ hosts }),\n });\n }\n\n /**\n * Whether the client is ready to send/receive data.\n */\n get ready(): boolean {\n return this.isReady;\n }\n\n /**\n * Whether the client is connected to the WebSocket.\n */\n get connected(): boolean {\n return this.isConnected;\n }\n\n /**\n * LiveKit room name acknowledged by the server, if available.\n */\n get livekitRoomName(): string | undefined {\n return this._livekitRoomName;\n }\n\n /**\n * LiveKit WebSocket URL configured on the server, if available.\n */\n get livekitUrl(): string | undefined {\n return this._livekitUrl;\n }\n\n /**\n * Identity assigned to the agent participant when LiveKit is enabled, if available.\n */\n get saynaParticipantIdentity(): string | undefined {\n return this._saynaParticipantIdentity;\n }\n\n /**\n * Display name assigned to the agent participant when LiveKit is enabled, if available.\n */\n get saynaParticipantName(): string | undefined {\n return this._saynaParticipantName;\n }\n\n /**\n * Session identifier returned by the server.\n * This can be used to download recordings or correlate session data.\n * The value is available after the connection is ready.\n */\n get streamId(): string | undefined {\n return this._streamId;\n }\n}\n",
7
7
  "import { createHmac, timingSafeEqual } from \"crypto\";\nimport { SaynaValidationError } from \"./errors\";\nimport type { WebhookSIPOutput } from \"./types\";\n\n/**\n * Minimum required secret length in characters for security.\n * @internal\n */\nconst MIN_SECRET_LENGTH = 16;\n\n/**\n * Maximum allowed time difference in seconds for replay protection.\n * Webhooks with timestamps outside this window will be rejected.\n * @internal\n */\nconst TIMESTAMP_TOLERANCE_SECONDS = 300; // 5 minutes\n\n/**\n * Receives and verifies cryptographically signed webhooks from Sayna SIP service.\n *\n * This class handles the secure verification of webhook signatures using HMAC-SHA256,\n * validates timestamp freshness to prevent replay attacks, and parses the webhook\n * payload into a strongly-typed WebhookSIPOutput object.\n *\n * ## Security Features\n *\n * - **HMAC-SHA256 Signature Verification**: Ensures webhook authenticity\n * - **Constant-Time Comparison**: Prevents timing attack vulnerabilities\n * - **Replay Protection**: 5-minute timestamp window prevents replay attacks\n * - **Strict Validation**: Comprehensive checks on all required fields\n *\n * ## Usage\n *\n * ### Basic Example\n *\n * ```typescript\n * import { WebhookReceiver } from \"@sayna-ai/node-sdk\";\n *\n * // Initialize with secret (or uses SAYNA_WEBHOOK_SECRET env variable)\n * const receiver = new WebhookReceiver(\"your-secret-key-min-16-chars\");\n *\n * // In your Express route handler\n * app.post('/webhook', express.json({ verify: (req, res, buf) => {\n * req.rawBody = buf.toString('utf8');\n * }}), (req, res) => {\n * try {\n * const webhook = receiver.receive(req.headers, req.rawBody);\n *\n * console.log('Valid webhook received:');\n * console.log(' From:', webhook.from_phone_number);\n * console.log(' To:', webhook.to_phone_number);\n * console.log(' Room:', webhook.room.name);\n * console.log(' SIP Host:', webhook.sip_host);\n * console.log(' Participant:', webhook.participant.identity);\n *\n * res.status(200).json({ received: true });\n * } catch (error) {\n * console.error('Webhook verification failed:', error.message);\n * res.status(401).json({ error: 'Invalid signature' });\n * }\n * });\n * ```\n *\n * ### With Environment Variable\n *\n * ```typescript\n * // Set environment variable\n * process.env.SAYNA_WEBHOOK_SECRET = \"your-secret-key\";\n *\n * // Receiver automatically uses env variable\n * const receiver = new WebhookReceiver();\n * ```\n *\n * ### Fastify Example\n *\n * ```typescript\n * import Fastify from 'fastify';\n * import { WebhookReceiver } from \"@sayna-ai/node-sdk\";\n *\n * const fastify = Fastify();\n * const receiver = new WebhookReceiver();\n *\n * fastify.post('/webhook', {\n * config: {\n * rawBody: true\n * }\n * }, async (request, reply) => {\n * try {\n * const webhook = receiver.receive(\n * request.headers,\n * request.rawBody\n * );\n *\n * // Process webhook...\n *\n * return { received: true };\n * } catch (error) {\n * reply.code(401);\n * return { error: error.message };\n * }\n * });\n * ```\n *\n * ## Important Notes\n *\n * - **Raw Body Required**: You MUST pass the raw request body string, not the parsed JSON object.\n * The signature is computed over the exact bytes received, so any formatting changes will\n * cause verification to fail.\n *\n * - **Case-Insensitive Headers**: Header names are case-insensitive in HTTP. This class handles\n * both `X-Sayna-Signature` and `x-sayna-signature` correctly.\n *\n * - **Secret Security**: Never commit secrets to version control. Use environment variables\n * or a secret management system.\n *\n * @see WebhookSIPOutput\n */\nexport class WebhookReceiver {\n private readonly secret: string;\n\n /**\n * Creates a new webhook receiver with the specified signing secret.\n *\n * @param secret - HMAC signing secret (min 16 chars, 32+ recommended).\n * If not provided, uses SAYNA_WEBHOOK_SECRET environment variable.\n *\n * @throws {SaynaValidationError} If secret is missing or too short\n *\n * @example\n * ```typescript\n * // Explicit secret\n * const receiver = new WebhookReceiver(\"my-secret-key-at-least-16-chars\");\n *\n * // From environment variable\n * const receiver = new WebhookReceiver();\n * ```\n */\n constructor(secret?: string) {\n const effectiveSecret = secret ?? process.env.SAYNA_WEBHOOK_SECRET;\n\n if (!effectiveSecret) {\n throw new SaynaValidationError(\n \"Webhook secret is required. Provide it as a constructor parameter or set SAYNA_WEBHOOK_SECRET environment variable.\"\n );\n }\n\n const trimmedSecret = effectiveSecret.trim();\n\n if (trimmedSecret.length < MIN_SECRET_LENGTH) {\n throw new SaynaValidationError(\n `Webhook secret must be at least ${MIN_SECRET_LENGTH} characters long. ` +\n `Received ${trimmedSecret.length} characters. ` +\n `Generate a secure secret with: openssl rand -hex 32`\n );\n }\n\n this.secret = trimmedSecret;\n }\n\n /**\n * Verifies and parses an incoming SIP webhook from Sayna.\n *\n * This method performs the following security checks:\n * 1. Validates presence of required headers\n * 2. Verifies timestamp is within acceptable window (prevents replay attacks)\n * 3. Computes HMAC-SHA256 signature over canonical string\n * 4. Performs constant-time comparison to prevent timing attacks\n * 5. Parses and validates the webhook payload structure\n *\n * @param headers - HTTP request headers (case-insensitive)\n * @param body - Raw request body as string (not parsed JSON)\n *\n * @returns Parsed and validated webhook payload\n *\n * @throws {SaynaValidationError} If signature verification fails or payload is invalid\n *\n * @example\n * ```typescript\n * const receiver = new WebhookReceiver(\"your-secret\");\n *\n * // Express example\n * app.post('/webhook', express.json({ verify: (req, res, buf) => {\n * req.rawBody = buf.toString();\n * }}), (req, res) => {\n * const webhook = receiver.receive(req.headers, req.rawBody);\n * // webhook is now a validated WebhookSIPOutput object\n * });\n * ```\n */\n receive(\n headers: Record<string, string | string[] | undefined>,\n body: string\n ): WebhookSIPOutput {\n // Normalize headers to lowercase for case-insensitive lookup\n const normalizedHeaders = this.normalizeHeaders(headers);\n\n // Extract required headers\n const signature = this.getRequiredHeader(\n normalizedHeaders,\n \"x-sayna-signature\"\n );\n const timestamp = this.getRequiredHeader(\n normalizedHeaders,\n \"x-sayna-timestamp\"\n );\n const eventId = this.getRequiredHeader(\n normalizedHeaders,\n \"x-sayna-event-id\"\n );\n\n // Parse and validate signature format\n if (!signature.startsWith(\"v1=\")) {\n throw new SaynaValidationError(\n \"Invalid signature format. Expected 'v1=<hex>' but got: \" +\n signature.substring(0, 10) +\n \"...\"\n );\n }\n const signatureHex = signature.substring(3);\n\n // Validate signature is valid hex (64 chars for SHA256)\n if (!/^[0-9a-f]{64}$/i.test(signatureHex)) {\n throw new SaynaValidationError(\n \"Invalid signature: must be 64 hex characters (HMAC-SHA256)\"\n );\n }\n\n // Validate and check timestamp\n this.validateTimestamp(timestamp);\n\n // Build canonical string for signature verification\n const canonical = `v1:${timestamp}:${eventId}:${body}`;\n\n // Compute expected signature\n const hmac = createHmac(\"sha256\", this.secret);\n hmac.update(canonical, \"utf8\");\n const expectedSignature = hmac.digest(\"hex\");\n\n // Constant-time comparison to prevent timing attacks\n if (!this.constantTimeEqual(signatureHex, expectedSignature)) {\n throw new SaynaValidationError(\n \"Signature verification failed. The webhook may have been tampered with or the secret is incorrect.\"\n );\n }\n\n // Parse and validate the webhook payload\n return this.parseAndValidatePayload(body);\n }\n\n /**\n * Normalizes HTTP headers to lowercase for case-insensitive access.\n * Handles both single string values and arrays of strings.\n *\n * @internal\n */\n private normalizeHeaders(\n headers: Record<string, string | string[] | undefined>\n ): Record<string, string> {\n const normalized: Record<string, string> = {};\n\n for (const [key, value] of Object.entries(headers)) {\n if (value !== undefined) {\n // Handle array values (take first element)\n const stringValue = Array.isArray(value) ? value[0] : value;\n if (stringValue) {\n normalized[key.toLowerCase()] = stringValue;\n }\n }\n }\n\n return normalized;\n }\n\n /**\n * Retrieves a required header value or throws a validation error.\n *\n * @internal\n */\n private getRequiredHeader(\n headers: Record<string, string>,\n name: string\n ): string {\n const value = headers[name.toLowerCase()];\n\n if (!value) {\n throw new SaynaValidationError(`Missing required header: ${name}`);\n }\n\n return value;\n }\n\n /**\n * Validates the timestamp is within the acceptable window.\n *\n * @internal\n */\n private validateTimestamp(timestampStr: string): void {\n // Parse timestamp\n const timestamp = Number(timestampStr);\n\n if (isNaN(timestamp)) {\n throw new SaynaValidationError(\n `Invalid timestamp format: expected Unix seconds but got '${timestampStr}'`\n );\n }\n\n // Check if timestamp is within acceptable range\n const now = Math.floor(Date.now() / 1000);\n const diff = Math.abs(now - timestamp);\n\n if (diff > TIMESTAMP_TOLERANCE_SECONDS) {\n throw new SaynaValidationError(\n `Timestamp outside replay protection window. ` +\n `Difference: ${diff} seconds (max allowed: ${TIMESTAMP_TOLERANCE_SECONDS}). ` +\n `This webhook may be a replay attack or there may be significant clock skew.`\n );\n }\n }\n\n /**\n * Performs constant-time string comparison to prevent timing attacks.\n *\n * @internal\n */\n private constantTimeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) {\n return false;\n }\n\n const bufA = Buffer.from(a, \"utf8\");\n const bufB = Buffer.from(b, \"utf8\");\n\n return timingSafeEqual(bufA, bufB);\n }\n\n /**\n * Parses and validates the webhook payload structure.\n *\n * @internal\n */\n private parseAndValidatePayload(body: string): WebhookSIPOutput {\n let payload: unknown;\n\n // Parse JSON\n try {\n payload = JSON.parse(body);\n } catch (error) {\n throw new SaynaValidationError(\n `Invalid JSON payload: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n\n // Validate payload is an object\n if (!payload || typeof payload !== \"object\" || Array.isArray(payload)) {\n throw new SaynaValidationError(\"Webhook payload must be a JSON object\");\n }\n\n const data = payload as Record<string, unknown>;\n\n // Validate required fields\n this.validateParticipant(data.participant);\n this.validateRoom(data.room);\n this.validateStringField(data, \"from_phone_number\", \"from_phone_number\");\n this.validateStringField(data, \"to_phone_number\", \"to_phone_number\");\n this.validateStringField(data, \"room_prefix\", \"room_prefix\");\n this.validateStringField(data, \"sip_host\", \"sip_host\");\n\n // TypeScript type assertion is safe here because we've validated all fields\n // We use double assertion through unknown to satisfy strict type checking\n return data as unknown as WebhookSIPOutput;\n }\n\n /**\n * Validates the participant object structure.\n *\n * @internal\n */\n private validateParticipant(participant: unknown): void {\n if (\n !participant ||\n typeof participant !== \"object\" ||\n Array.isArray(participant)\n ) {\n throw new SaynaValidationError(\n \"Webhook payload missing required field 'participant' (must be an object)\"\n );\n }\n\n const p = participant as Record<string, unknown>;\n\n this.validateStringField(p, \"identity\", \"participant.identity\");\n this.validateStringField(p, \"sid\", \"participant.sid\");\n\n // name is optional, but if present must be a string\n if (p.name !== undefined && typeof p.name !== \"string\") {\n throw new SaynaValidationError(\n \"Field 'participant.name' must be a string if present\"\n );\n }\n }\n\n /**\n * Validates the room object structure.\n *\n * @internal\n */\n private validateRoom(room: unknown): void {\n if (!room || typeof room !== \"object\" || Array.isArray(room)) {\n throw new SaynaValidationError(\n \"Webhook payload missing required field 'room' (must be an object)\"\n );\n }\n\n const r = room as Record<string, unknown>;\n\n this.validateStringField(r, \"name\", \"room.name\");\n this.validateStringField(r, \"sid\", \"room.sid\");\n }\n\n /**\n * Validates a required string field.\n *\n * @internal\n */\n private validateStringField(\n obj: Record<string, unknown>,\n field: string,\n displayName: string\n ): void {\n const value = obj[field];\n\n if (typeof value !== \"string\" || value.length === 0) {\n throw new SaynaValidationError(\n `Webhook payload missing required field '${displayName}' (must be a non-empty string)`\n );\n }\n }\n}\n",
8
- "import { SaynaClient } from \"./sayna-client\";\nimport type { STTConfig, TTSConfig, LiveKitConfig } from \"./types\";\n\nexport * from \"./sayna-client\";\nexport * from \"./types\";\nexport * from \"./errors\";\nexport * from \"./webhook-receiver\";\n\n/**\n * Creates and connects a new SaynaClient instance.\n *\n * This is the recommended way to create a Sayna client. It handles both\n * instantiation and connection, returning a ready-to-use client.\n *\n * @param url - The Sayna server URL (e.g., \"https://api.sayna.ai\")\n * @param sttConfig - Speech-to-text configuration\n * @param ttsConfig - Text-to-speech configuration\n * @param livekitConfig - Optional LiveKit room configuration\n * @param withoutAudio - If true, disables audio streaming (default: false)\n * @param apiKey - Optional API key used to authorize HTTP and WebSocket calls (defaults to SAYNA_API_KEY env)\n *\n * @returns Promise that resolves to a connected SaynaClient\n *\n * @throws {SaynaValidationError} If parameters are invalid\n * @throws {SaynaConnectionError} If connection fails\n * @throws {SaynaServerError} If server returns an error during setup\n *\n * @example\n * ```typescript\n * import { saynaConnect } from \"@sayna/node-sdk\";\n *\n * const client = await saynaConnect(\n * \"https://api.sayna.ai\",\n * {\n * provider: \"deepgram\",\n * language: \"en-US\",\n * sample_rate: 16000,\n * channels: 1,\n * punctuation: true,\n * encoding: \"linear16\",\n * model: \"nova-2\"\n * },\n * {\n * provider: \"elevenlabs\",\n * voice_id: \"21m00Tcm4TlvDq8ikWAM\",\n * speaking_rate: 1.0,\n * audio_format: \"pcm\",\n * sample_rate: 16000,\n * connection_timeout: 5000,\n * request_timeout: 10000,\n * model: \"eleven_turbo_v2\",\n * pronunciations: []\n * }\n * );\n *\n * // Register event handlers\n * client.registerOnSttResult((result) => {\n * console.log(\"Transcription:\", result.transcript);\n * });\n *\n * // Send text to be spoken\n * await client.speak(\"Hello, world!\");\n *\n * // Clean up\n * await client.disconnect();\n * ```\n */\nexport async function saynaConnect(\n url: string,\n sttConfig: STTConfig,\n ttsConfig: TTSConfig,\n livekitConfig?: LiveKitConfig,\n withoutAudio: boolean = false,\n apiKey?: string\n): Promise<SaynaClient> {\n const client = new SaynaClient(\n url,\n sttConfig,\n ttsConfig,\n livekitConfig,\n withoutAudio,\n apiKey\n );\n await client.connect();\n return client;\n}\n"
8
+ "import { SaynaClient } from \"./sayna-client\";\nimport type { STTConfig, TTSConfig, LiveKitConfig } from \"./types\";\n\nexport * from \"./sayna-client\";\nexport * from \"./types\";\nexport * from \"./errors\";\nexport * from \"./webhook-receiver\";\n\n/**\n * Creates and connects a new SaynaClient instance.\n *\n * This is the recommended way to create a Sayna client. It handles both\n * instantiation and connection, returning a ready-to-use client.\n *\n * @param url - The Sayna server URL (e.g., \"https://api.sayna.ai\")\n * @param sttConfig - Speech-to-text configuration (required when withoutAudio=false)\n * @param ttsConfig - Text-to-speech configuration (required when withoutAudio=false)\n * @param livekitConfig - Optional LiveKit room configuration\n * @param withoutAudio - If true, disables audio streaming (default: false)\n * @param apiKey - Optional API key used to authorize HTTP and WebSocket calls (defaults to SAYNA_API_KEY env)\n *\n * @returns Promise that resolves to a connected SaynaClient\n *\n * @throws {SaynaValidationError} If parameters are invalid\n * @throws {SaynaConnectionError} If connection fails\n * @throws {SaynaServerError} If server returns an error during setup\n *\n * @example\n * ```typescript\n * import { saynaConnect } from \"@sayna/node-sdk\";\n *\n * const client = await saynaConnect(\n * \"https://api.sayna.ai\",\n * {\n * provider: \"deepgram\",\n * language: \"en-US\",\n * sample_rate: 16000,\n * channels: 1,\n * punctuation: true,\n * encoding: \"linear16\",\n * model: \"nova-2\"\n * },\n * {\n * provider: \"elevenlabs\",\n * voice_id: \"21m00Tcm4TlvDq8ikWAM\",\n * speaking_rate: 1.0,\n * audio_format: \"pcm\",\n * sample_rate: 16000,\n * connection_timeout: 5000,\n * request_timeout: 10000,\n * model: \"eleven_turbo_v2\",\n * pronunciations: []\n * }\n * );\n *\n * // Register event handlers\n * client.registerOnSttResult((result) => {\n * console.log(\"Transcription:\", result.transcript);\n * });\n *\n * // Send text to be spoken\n * await client.speak(\"Hello, world!\");\n *\n * // Clean up\n * await client.disconnect();\n * ```\n */\nexport async function saynaConnect(\n url: string,\n sttConfig?: STTConfig,\n ttsConfig?: TTSConfig,\n livekitConfig?: LiveKitConfig,\n withoutAudio: boolean = false,\n apiKey?: string\n): Promise<SaynaClient> {\n const client = new SaynaClient(\n url,\n sttConfig,\n ttsConfig,\n livekitConfig,\n withoutAudio,\n apiKey\n );\n await client.connect();\n return client;\n}\n"
9
9
  ],
10
- "mappings": "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",
11
- "debugId": "439FAA862268544264756E2164756E21",
10
+ "mappings": "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",
11
+ "debugId": "5692EE242C83976364756E2164756E21",
12
12
  "names": []
13
13
  }
@@ -1,4 +1,4 @@
1
- import type { STTConfig, TTSConfig, LiveKitConfig, STTResultMessage, ErrorMessage, SaynaMessage, Participant, VoicesResponse, HealthResponse, LiveKitTokenResponse, SipHook, SipHooksResponse } from "./types";
1
+ import type { STTConfig, TTSConfig, LiveKitConfig, STTResultMessage, ErrorMessage, SipTransferErrorMessage, SaynaMessage, Participant, VoicesResponse, HealthResponse, LiveKitTokenResponse, SipHook, SipHooksResponse } from "./types";
2
2
  /**
3
3
  * Event handler for speech-to-text results.
4
4
  */
@@ -23,6 +23,10 @@ export type ParticipantDisconnectedHandler = (participant: Participant) => void
23
23
  * Event handler for TTS playback completion.
24
24
  */
25
25
  export type TTSPlaybackCompleteHandler = (timestamp: number) => void | Promise<void>;
26
+ /**
27
+ * Event handler for SIP transfer specific errors.
28
+ */
29
+ export type SipTransferErrorHandler = (error: SipTransferErrorMessage) => void | Promise<void>;
26
30
  /**
27
31
  * Client for connecting to Sayna WebSocket server for real-time voice interactions.
28
32
  *
@@ -63,6 +67,7 @@ export declare class SaynaClient {
63
67
  private messageCallback?;
64
68
  private participantDisconnectedCallback?;
65
69
  private ttsPlaybackCompleteCallback?;
70
+ private sipTransferErrorCallback?;
66
71
  private readyPromiseResolve?;
67
72
  private readyPromiseReject?;
68
73
  /**
@@ -162,6 +167,12 @@ export declare class SaynaClient {
162
167
  * @param callback - Function to call when TTS playback is complete
163
168
  */
164
169
  registerOnTtsPlaybackComplete(callback: TTSPlaybackCompleteHandler): void;
170
+ /**
171
+ * Registers a callback for SIP transfer specific errors.
172
+ *
173
+ * @param callback - Function to call when a SIP transfer error message is received
174
+ */
175
+ registerOnSipTransferError(callback: SipTransferErrorHandler): void;
165
176
  /**
166
177
  * Sends text to be synthesized as speech.
167
178
  *
@@ -200,6 +211,15 @@ export declare class SaynaClient {
200
211
  * @throws {SaynaValidationError} If parameters are invalid
201
212
  */
202
213
  sendMessage(message: string, role: string, topic?: string, debug?: Record<string, unknown>): void;
214
+ /**
215
+ * Initiates a SIP transfer for the active LiveKit session.
216
+ *
217
+ * @param transferTo - Destination phone number or extension to transfer to
218
+ * @throws {SaynaNotConnectedError} If not connected
219
+ * @throws {SaynaNotReadyError} If connection is not ready
220
+ * @throws {SaynaValidationError} If transferTo is not a non-empty string
221
+ */
222
+ sipTransfer(transferTo: string): void;
203
223
  /**
204
224
  * Performs a health check on the Sayna server.
205
225
  *
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sayna-client.d.ts","sourceRoot":"","sources":["../src/sayna-client.ts"],"names":[],"mappings":"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"}
@@ -32,22 +32,43 @@ export interface Pronunciation {
32
32
  export interface TTSConfig {
33
33
  /** The TTS provider to use (e.g., "elevenlabs", "google") */
34
34
  provider: string;
35
- /** Voice identifier for the selected provider */
36
- voice_id: string;
37
- /** Speech rate multiplier (e.g., 1.0 for normal, 1.5 for faster) */
38
- speaking_rate: number;
39
- /** Audio format for TTS output (e.g., "mp3", "pcm") */
40
- audio_format: string;
41
- /** Audio sample rate in Hz (e.g., 16000, 44100) */
42
- sample_rate: number;
43
- /** Connection timeout in milliseconds */
44
- connection_timeout: number;
45
- /** Request timeout in milliseconds */
46
- request_timeout: number;
35
+ /**
36
+ * Voice identifier for the selected provider.
37
+ * Optional because some providers expose defaults or infer from the model.
38
+ */
39
+ voice_id?: string;
40
+ /**
41
+ * Speech rate multiplier (e.g., 1.0 for normal, 1.5 for faster).
42
+ * Optional to match spec defaults (server defaults to 1.0 when omitted).
43
+ */
44
+ speaking_rate?: number;
45
+ /**
46
+ * Audio format for TTS output (e.g., "mp3", "pcm").
47
+ * Optional; falls back to provider defaults when not provided.
48
+ */
49
+ audio_format?: string;
50
+ /**
51
+ * Audio sample rate in Hz (e.g., 16000, 44100).
52
+ * Optional; provider default is used when omitted.
53
+ */
54
+ sample_rate?: number;
55
+ /**
56
+ * Connection timeout in seconds.
57
+ * Optional because the server applies its own defaults when the field is omitted.
58
+ */
59
+ connection_timeout?: number;
60
+ /**
61
+ * Request timeout in seconds.
62
+ * Optional because the server applies its own defaults when the field is omitted.
63
+ */
64
+ request_timeout?: number;
47
65
  /** TTS model identifier to use */
48
66
  model: string;
49
- /** Custom pronunciation overrides */
50
- pronunciations: Pronunciation[];
67
+ /**
68
+ * Custom pronunciation overrides.
69
+ * Optional so minimal payloads from the spec are accepted; defaults to an empty list when absent.
70
+ */
71
+ pronunciations?: Pronunciation[];
51
72
  }
52
73
  /**
53
74
  * LiveKit room configuration for real-time communication.
@@ -55,13 +76,13 @@ export interface TTSConfig {
55
76
  export interface LiveKitConfig {
56
77
  /** LiveKit room name to join */
57
78
  room_name: string;
58
- /** Whether to enable session recording */
79
+ /** Whether to enable session recording (defaults to false) */
59
80
  enable_recording?: boolean;
60
81
  /** Identity assigned to the agent participant (defaults to "sayna-ai") */
61
82
  sayna_participant_identity?: string;
62
83
  /** Display name for the agent participant (defaults to "Sayna AI") */
63
84
  sayna_participant_name?: string;
64
- /** Optional list of participant identities to monitor; empty list means "all participants" */
85
+ /** Optional list of participant identities to monitor; defaults to empty array (all participants) */
65
86
  listen_participants?: string[];
66
87
  }
67
88
  /**
@@ -116,6 +137,15 @@ export interface SendMessageMessage {
116
137
  /** Optional debug metadata */
117
138
  debug?: Record<string, unknown>;
118
139
  }
140
+ /**
141
+ * Message to request a SIP call transfer for the active LiveKit session.
142
+ * LiveKit must be configured and a SIP participant must be active for this to succeed.
143
+ */
144
+ export interface SipTransferMessage {
145
+ type: "sip_transfer";
146
+ /** Destination phone number or extension to transfer to */
147
+ transfer_to: string;
148
+ }
119
149
  /**
120
150
  * Message received when the Sayna connection is ready.
121
151
  */
@@ -125,11 +155,11 @@ export interface ReadyMessage {
125
155
  stream_id?: string;
126
156
  /** LiveKit room name acknowledged by the server (present only when LiveKit is enabled) */
127
157
  livekit_room_name?: string;
128
- /** LiveKit WebSocket URL configured on the server */
129
- livekit_url: string;
130
- /** Identity assigned to the agent participant when LiveKit is enabled */
158
+ /** LiveKit WebSocket URL configured on the server (only present when LiveKit is enabled) */
159
+ livekit_url?: string;
160
+ /** Identity assigned to the agent participant when LiveKit is enabled (only present when LiveKit is enabled) */
131
161
  sayna_participant_identity?: string;
132
- /** Display name assigned to the agent participant when LiveKit is enabled */
162
+ /** Display name assigned to the agent participant when LiveKit is enabled (only present when LiveKit is enabled) */
133
163
  sayna_participant_name?: string;
134
164
  }
135
165
  /**
@@ -154,6 +184,14 @@ export interface ErrorMessage {
154
184
  /** Error description */
155
185
  message: string;
156
186
  }
187
+ /**
188
+ * SIP transfer specific error message from the Sayna server.
189
+ */
190
+ export interface SipTransferErrorMessage {
191
+ type: "sip_transfer_error";
192
+ /** Human-readable error description */
193
+ message: string;
194
+ }
157
195
  /**
158
196
  * Message data from a Sayna session participant.
159
197
  */
@@ -211,7 +249,7 @@ export interface TTSPlaybackCompleteMessage {
211
249
  /**
212
250
  * Union type of all possible messages received from the Sayna server.
213
251
  */
214
- export type OutgoingMessage = ReadyMessage | STTResultMessage | ErrorMessage | MessageMessage | ParticipantDisconnectedMessage | TTSPlaybackCompleteMessage;
252
+ export type OutgoingMessage = ReadyMessage | STTResultMessage | ErrorMessage | SipTransferErrorMessage | MessageMessage | ParticipantDisconnectedMessage | TTSPlaybackCompleteMessage;
215
253
  /**
216
254
  * Voice descriptor returned by the GET /voices endpoint.
217
255
  */
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhook-receiver.d.ts","sourceRoot":"","sources":["../src/webhook-receiver.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAehD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmGG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAEhC;;;;;;;;;;;;;;;;OAgBG;gBACS,MAAM,CAAC,EAAE,MAAM;IAsB3B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;IACH,OAAO,CACL,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,EACtD,IAAI,EAAE,MAAM,GACX,gBAAgB;IAyDnB;;;;;OAKG;IACH,OAAO,CAAC,gBAAgB;IAkBxB;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IAazB;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IAuBzB;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IAWzB;;;;OAIG;IACH,OAAO,CAAC,uBAAuB;IAgC/B;;;;OAIG;IACH,OAAO,CAAC,mBAAmB;IAwB3B;;;;OAIG;IACH,OAAO,CAAC,YAAY;IAapB;;;;OAIG;IACH,OAAO,CAAC,mBAAmB;CAa5B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sayna-ai/node-sdk",
3
- "version": "0.0.9",
3
+ "version": "0.0.11",
4
4
  "description": "Node.js SDK for Sayna.ai server-side WebSocket connections",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1 +0,0 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,UAAW,SAAQ,KAAK;gBACvB,OAAO,EAAE,MAAM;CAK5B;AAED;;GAEG;AACH,qBAAa,sBAAuB,SAAQ,UAAU;gBACxC,OAAO,GAAE,MAA2C;CAKjE;AAED;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,UAAU;gBAE9C,OAAO,GAAE,MAA0F;CAMtG;AAED;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,UAAU;IAClD,SAAyB,KAAK,CAAC,EAAE,OAAO,CAAC;gBAE7B,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;CAM7C;AAED;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,UAAU;gBACtC,OAAO,EAAE,MAAM;CAK5B;AAED;;GAEG;AACH,qBAAa,gBAAiB,SAAQ,UAAU;gBAClC,OAAO,EAAE,MAAM;CAK5B"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAEnE,cAAc,gBAAgB,CAAC;AAC/B,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,oBAAoB,CAAC;AAEnC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,SAAS,EACpB,SAAS,EAAE,SAAS,EACpB,aAAa,CAAC,EAAE,aAAa,EAC7B,YAAY,GAAE,OAAe,EAC7B,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,WAAW,CAAC,CAWtB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"sayna-client.d.ts","sourceRoot":"","sources":["../../src/sayna-client.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"webhook-receiver.d.ts","sourceRoot":"","sources":["../../src/webhook-receiver.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAehD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmGG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAEhC;;;;;;;;;;;;;;;;OAgBG;gBACS,MAAM,CAAC,EAAE,MAAM;IAsB3B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;IACH,OAAO,CACL,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,EACtD,IAAI,EAAE,MAAM,GACX,gBAAgB;IAyDnB;;;;;OAKG;IACH,OAAO,CAAC,gBAAgB;IAkBxB;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IAazB;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IAuBzB;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IAWzB;;;;OAIG;IACH,OAAO,CAAC,uBAAuB;IAgC/B;;;;OAIG;IACH,OAAO,CAAC,mBAAmB;IAwB3B;;;;OAIG;IACH,OAAO,CAAC,YAAY;IAapB;;;;OAIG;IACH,OAAO,CAAC,mBAAmB;CAa5B"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=errors.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"errors.test.d.ts","sourceRoot":"","sources":["../../tests/errors.test.ts"],"names":[],"mappings":""}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=sayna-client.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sayna-client.test.d.ts","sourceRoot":"","sources":["../../tests/sayna-client.test.ts"],"names":[],"mappings":""}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=types.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.test.d.ts","sourceRoot":"","sources":["../../tests/types.test.ts"],"names":[],"mappings":""}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=webhook-receiver.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"webhook-receiver.test.d.ts","sourceRoot":"","sources":["../../tests/webhook-receiver.test.ts"],"names":[],"mappings":""}
File without changes