@azure/ai-voicelive 1.0.0-alpha.20260105.1 → 1.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/index.d.ts +1 -1
- package/dist/browser/index.js +1 -1
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/models/index.d.ts +1 -1
- package/dist/browser/models/index.js +1 -1
- package/dist/browser/models/index.js.map +1 -1
- package/dist/browser/models/models.d.ts +357 -25
- package/dist/browser/models/models.js +361 -56
- package/dist/browser/models/models.js.map +1 -1
- package/dist/browser/protocol/messageParser.d.ts +1 -1
- package/dist/browser/protocol/messageParser.js +19 -76
- package/dist/browser/protocol/messageParser.js.map +1 -1
- package/dist/browser/voiceLiveSession.d.ts +2 -2
- package/dist/browser/voiceLiveSession.js +11 -10
- package/dist/browser/voiceLiveSession.js.map +1 -1
- package/dist/browser/websocket/websocket-browser.mjs.map +1 -0
- package/dist/browser/websocket/{websocketBrowser.d.ts → websocket.d.ts} +8 -2
- package/dist/{react-native/websocket/websocketBrowser.js → browser/websocket/websocket.js} +43 -3
- package/dist/browser/websocket/websocketFactory.d.ts +0 -11
- package/dist/browser/websocket/websocketFactory.js +2 -66
- package/dist/browser/websocket/websocketFactory.js.map +1 -1
- package/dist/browser/websocket/websocketLike.d.ts +3 -0
- package/dist/browser/websocket/websocketLike.js.map +1 -1
- package/dist/commonjs/index.d.ts +1 -1
- package/dist/commonjs/index.js +6 -1
- package/dist/commonjs/index.js.map +1 -1
- package/dist/commonjs/models/index.d.ts +1 -1
- package/dist/commonjs/models/index.js +6 -1
- package/dist/commonjs/models/index.js.map +1 -1
- package/dist/commonjs/models/models.d.ts +357 -25
- package/dist/commonjs/models/models.js +386 -59
- package/dist/commonjs/models/models.js.map +1 -1
- package/dist/commonjs/protocol/messageParser.d.ts +1 -1
- package/dist/commonjs/protocol/messageParser.js +18 -75
- package/dist/commonjs/protocol/messageParser.js.map +1 -1
- package/dist/commonjs/voiceLiveSession.d.ts +2 -2
- package/dist/commonjs/voiceLiveSession.js +20 -19
- package/dist/commonjs/voiceLiveSession.js.map +1 -1
- package/dist/{esm/websocket/websocketNode.d.ts → commonjs/websocket/websocket.d.ts} +2 -2
- package/dist/commonjs/websocket/{websocketNode.js → websocket.js} +31 -6
- package/dist/commonjs/websocket/websocket.js.map +1 -0
- package/dist/commonjs/websocket/websocketFactory.d.ts +0 -11
- package/dist/commonjs/websocket/websocketFactory.js +2 -68
- package/dist/commonjs/websocket/websocketFactory.js.map +1 -1
- package/dist/commonjs/websocket/websocketLike.d.ts +3 -0
- package/dist/commonjs/websocket/websocketLike.js.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/models/index.d.ts +1 -1
- package/dist/esm/models/index.js +1 -1
- package/dist/esm/models/index.js.map +1 -1
- package/dist/esm/models/models.d.ts +357 -25
- package/dist/esm/models/models.js +361 -56
- package/dist/esm/models/models.js.map +1 -1
- package/dist/esm/protocol/messageParser.d.ts +1 -1
- package/dist/esm/protocol/messageParser.js +19 -76
- package/dist/esm/protocol/messageParser.js.map +1 -1
- package/dist/esm/voiceLiveSession.d.ts +2 -2
- package/dist/esm/voiceLiveSession.js +11 -10
- package/dist/esm/voiceLiveSession.js.map +1 -1
- package/dist/{react-native/websocket/websocketNode.d.ts → esm/websocket/websocket.d.ts} +2 -2
- package/dist/{browser/websocket/websocketNode.js → esm/websocket/websocket.js} +29 -4
- package/dist/esm/websocket/websocket.js.map +1 -0
- package/dist/esm/websocket/websocketFactory.d.ts +0 -11
- package/dist/esm/websocket/websocketFactory.js +2 -66
- package/dist/esm/websocket/websocketFactory.js.map +1 -1
- package/dist/esm/websocket/websocketLike.d.ts +3 -0
- package/dist/esm/websocket/websocketLike.js.map +1 -1
- package/dist/react-native/index.d.ts +1 -1
- package/dist/react-native/index.js +1 -1
- package/dist/react-native/index.js.map +1 -1
- package/dist/react-native/models/index.d.ts +1 -1
- package/dist/react-native/models/index.js +1 -1
- package/dist/react-native/models/index.js.map +1 -1
- package/dist/react-native/models/models.d.ts +357 -25
- package/dist/react-native/models/models.js +361 -56
- package/dist/react-native/models/models.js.map +1 -1
- package/dist/react-native/protocol/messageParser.d.ts +1 -1
- package/dist/react-native/protocol/messageParser.js +19 -76
- package/dist/react-native/protocol/messageParser.js.map +1 -1
- package/dist/react-native/voiceLiveSession.d.ts +2 -2
- package/dist/react-native/voiceLiveSession.js +11 -10
- package/dist/react-native/voiceLiveSession.js.map +1 -1
- package/dist/{commonjs/websocket/websocketNode.d.ts → react-native/websocket/websocket.d.ts} +2 -2
- package/dist/{esm/websocket/websocketNode.js → react-native/websocket/websocket.js} +29 -4
- package/dist/react-native/websocket/websocket.js.map +1 -0
- package/dist/react-native/websocket/websocketFactory.d.ts +0 -11
- package/dist/react-native/websocket/websocketFactory.js +2 -66
- package/dist/react-native/websocket/websocketFactory.js.map +1 -1
- package/dist/react-native/websocket/websocketLike.d.ts +3 -0
- package/dist/react-native/websocket/websocketLike.js.map +1 -1
- package/package.json +20 -7
- package/dist/browser/websocket/websocketBrowser.js +0 -175
- package/dist/browser/websocket/websocketBrowser.js.map +0 -1
- package/dist/browser/websocket/websocketNode.d.ts +0 -26
- package/dist/browser/websocket/websocketNode.js.map +0 -1
- package/dist/commonjs/websocket/websocketBrowser.d.ts +0 -26
- package/dist/commonjs/websocket/websocketBrowser.js +0 -179
- package/dist/commonjs/websocket/websocketBrowser.js.map +0 -1
- package/dist/commonjs/websocket/websocketNode.js.map +0 -1
- package/dist/esm/websocket/websocketBrowser.d.ts +0 -26
- package/dist/esm/websocket/websocketBrowser.js +0 -175
- package/dist/esm/websocket/websocketBrowser.js.map +0 -1
- package/dist/esm/websocket/websocketNode.js.map +0 -1
- package/dist/react-native/websocket/websocketBrowser.d.ts +0 -26
- package/dist/react-native/websocket/websocketBrowser.js.map +0 -1
- package/dist/react-native/websocket/websocketNode.js +0 -180
- package/dist/react-native/websocket/websocketNode.js.map +0 -1
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
// Copyright (c) Microsoft Corporation.
|
|
2
2
|
// Licensed under the MIT License.
|
|
3
|
-
import {
|
|
3
|
+
import { logger } from "../logger.js";
|
|
4
|
+
import { KnownServerEventType, } from "../models/index.js";
|
|
5
|
+
import { clientEventUnionSerializer, KnownClientEventType, serverEventUnionDeserializer, } from "../models/models.js";
|
|
4
6
|
/**
|
|
5
7
|
* Parses and serializes Voice Live protocol messages
|
|
6
8
|
*/
|
|
@@ -37,8 +39,20 @@ export class VoiceLiveMessageParser {
|
|
|
37
39
|
return null; // Unknown message format
|
|
38
40
|
}
|
|
39
41
|
catch (error) {
|
|
40
|
-
|
|
41
|
-
return
|
|
42
|
+
logger.error("Failed to parse incoming message:", error);
|
|
43
|
+
return {
|
|
44
|
+
type: "server",
|
|
45
|
+
event: {
|
|
46
|
+
type: KnownServerEventType.Error,
|
|
47
|
+
error: {
|
|
48
|
+
type: "error",
|
|
49
|
+
code: "MessageParsingError",
|
|
50
|
+
message: "Failed to parse incoming message data. " +
|
|
51
|
+
(error instanceof Error ? error.message : String(error)),
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
raw: data,
|
|
55
|
+
};
|
|
42
56
|
}
|
|
43
57
|
}
|
|
44
58
|
/**
|
|
@@ -66,85 +80,14 @@ export class VoiceLiveMessageParser {
|
|
|
66
80
|
*/
|
|
67
81
|
_isValidServerEventType(type) {
|
|
68
82
|
// Based on the comprehensive analysis in EXISTING_TYPES_ANALYSIS.md
|
|
69
|
-
|
|
70
|
-
// Error handling
|
|
71
|
-
"error",
|
|
72
|
-
// Session management
|
|
73
|
-
"session.created",
|
|
74
|
-
"session.updated",
|
|
75
|
-
"session.avatar.connecting",
|
|
76
|
-
// Audio buffer events
|
|
77
|
-
"input_audio_buffer.committed",
|
|
78
|
-
"input_audio_buffer.cleared",
|
|
79
|
-
"input_audio_buffer.speech_started",
|
|
80
|
-
"input_audio_buffer.speech_stopped",
|
|
81
|
-
// Conversation item events
|
|
82
|
-
"conversation.item.created",
|
|
83
|
-
"conversation.item.truncated",
|
|
84
|
-
"conversation.item.deleted",
|
|
85
|
-
"conversation.item.retrieved",
|
|
86
|
-
"conversation.item.input_audio_transcription.completed",
|
|
87
|
-
"conversation.item.input_audio_transcription.failed",
|
|
88
|
-
"conversation.item.input_audio_transcription.delta",
|
|
89
|
-
// Response lifecycle events
|
|
90
|
-
"response.created",
|
|
91
|
-
"response.done",
|
|
92
|
-
"response.output_item.added",
|
|
93
|
-
"response.output_item.done",
|
|
94
|
-
// Content streaming events
|
|
95
|
-
"response.content_part.added",
|
|
96
|
-
"response.content_part.done",
|
|
97
|
-
"response.text.delta",
|
|
98
|
-
"response.text.done",
|
|
99
|
-
// Audio streaming events
|
|
100
|
-
"response.audio_transcript.delta",
|
|
101
|
-
"response.audio_transcript.done",
|
|
102
|
-
"response.audio.delta",
|
|
103
|
-
"response.audio.done",
|
|
104
|
-
// Animation events
|
|
105
|
-
"response.animation.blendshape.delta",
|
|
106
|
-
"response.animation.blendshape.done",
|
|
107
|
-
"response.animation.viseme.delta",
|
|
108
|
-
"response.animation.viseme.done",
|
|
109
|
-
// Timestamp events
|
|
110
|
-
"response.audio.timestamp.delta",
|
|
111
|
-
"response.audio.timestamp.done",
|
|
112
|
-
// Function call events
|
|
113
|
-
"response.function_call_arguments.delta",
|
|
114
|
-
"response.function_call_arguments.done",
|
|
115
|
-
];
|
|
116
|
-
return validServerTypes.includes(type);
|
|
83
|
+
return Object.values(KnownServerEventType).includes(type);
|
|
117
84
|
}
|
|
118
85
|
/**
|
|
119
86
|
* Validates if the type string represents a valid client event type
|
|
120
87
|
*/
|
|
121
88
|
_isValidClientEventType(type) {
|
|
122
89
|
// Based on the comprehensive analysis in EXISTING_TYPES_ANALYSIS.md
|
|
123
|
-
|
|
124
|
-
// Session management
|
|
125
|
-
"session.update",
|
|
126
|
-
"session.avatar.connect",
|
|
127
|
-
// Turn-based audio
|
|
128
|
-
"input_audio_turn.start",
|
|
129
|
-
"input_audio_turn.append",
|
|
130
|
-
"input_audio_turn.end",
|
|
131
|
-
"input_audio_turn.cancel",
|
|
132
|
-
// Buffer-based audio
|
|
133
|
-
"input_audio_buffer.append",
|
|
134
|
-
"input_audio_buffer.commit",
|
|
135
|
-
"input_audio_buffer.clear",
|
|
136
|
-
// Audio control
|
|
137
|
-
"input_audio.clear",
|
|
138
|
-
// Conversation management
|
|
139
|
-
"conversation.item.create",
|
|
140
|
-
"conversation.item.truncate",
|
|
141
|
-
"conversation.item.delete",
|
|
142
|
-
"conversation.item.retrieve",
|
|
143
|
-
// Response management
|
|
144
|
-
"response.create",
|
|
145
|
-
"response.cancel",
|
|
146
|
-
];
|
|
147
|
-
return validClientTypes.includes(type);
|
|
90
|
+
return Object.values(KnownClientEventType).includes(type);
|
|
148
91
|
}
|
|
149
92
|
}
|
|
150
93
|
//# sourceMappingURL=messageParser.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messageParser.js","sourceRoot":"","sources":["../../../src/protocol/messageParser.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;
|
|
1
|
+
{"version":3,"file":"messageParser.js","sourceRoot":"","sources":["../../../src/protocol/messageParser.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAElC,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAGL,oBAAoB,GACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,0BAA0B,EAC1B,oBAAoB,EAGpB,4BAA4B,GAC7B,MAAM,qBAAqB,CAAC;AAc7B;;GAEG;AACH,MAAM,OAAO,sBAAsB;IACjC;;OAEG;IACH,oBAAoB,CAAC,IAA0B;QAC7C,IAAI,CAAC;YACH,IAAI,WAAmB,CAAC;YAExB,IAAI,IAAI,YAAY,WAAW,EAAE,CAAC;gBAChC,WAAW,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC/C,CAAC;iBAAM,CAAC;gBACN,WAAW,GAAG,IAAI,CAAC;YACrB,CAAC;YAED,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;YAE3C,0DAA0D;YAC1D,IAAI,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,EAAE,CAAC;gBACpC,OAAO;oBACL,IAAI,EAAE,QAAQ;oBACd,KAAK,EAAE,4BAA4B,CAAC,UAAU,CAAC;oBAC/C,GAAG,EAAE,IAAI;iBACV,CAAC;YACJ,CAAC;YAED,iFAAiF;YACjF,IAAI,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,EAAE,CAAC;gBACpC,OAAO;oBACL,IAAI,EAAE,QAAQ;oBACd,KAAK,EAAE,UAA8B;oBACrC,GAAG,EAAE,IAAI;iBACV,CAAC;YACJ,CAAC;YAED,OAAO,IAAI,CAAC,CAAC,yBAAyB;QACxC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,mCAAmC,EAAE,KAAK,CAAC,CAAC;YACzD,OAAO;gBACL,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE;oBACL,IAAI,EAAE,oBAAoB,CAAC,KAAK;oBAChC,KAAK,EAAE;wBACL,IAAI,EAAE,OAAO;wBACb,IAAI,EAAE,qBAAqB;wBAC3B,OAAO,EACL,yCAAyC;4BACzC,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;qBAChC;iBACT;gBACrB,GAAG,EAAE,IAAI;aACV,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;OAEG;IACH,wBAAwB,CAAC,KAAuB;QAC9C,OAAO,IAAI,CAAC,SAAS,CAAC,0BAA0B,CAAC,KAAK,CAAC,CAAC,CAAC;IAC3D,CAAC;IAED;;OAEG;IACK,cAAc,CAAC,IAAS;QAC9B,mDAAmD;QACnD,OAAO,IAAI,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1F,CAAC;IAED;;OAEG;IACK,cAAc,CAAC,IAAS;QAC9B,mDAAmD;QACnD,OAAO,IAAI,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1F,CAAC;IAED;;OAEG;IACK,uBAAuB,CAAC,IAAY;QAC1C,oEAAoE;QACpE,OAAO,MAAM,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC,QAAQ,CAAC,IAA4B,CAAC,CAAC;IACpF,CAAC;IAED;;OAEG;IACK,uBAAuB,CAAC,IAAY;QAC1C,oEAAoE;QACpE,OAAO,MAAM,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC,QAAQ,CAAC,IAA4B,CAAC,CAAC;IACpF,CAAC;CACF","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport { logger } from \"../logger.js\";\nimport {\n type ServerEventUnion,\n type ClientEventUnion,\n KnownServerEventType,\n} from \"../models/index.js\";\nimport {\n clientEventUnionSerializer,\n KnownClientEventType,\n type ServerEventError,\n type ServerEventErrorDetails,\n serverEventUnionDeserializer,\n} from \"../models/models.js\";\n\n/**\n * Parsed message containing event data and metadata\n */\nexport interface ParsedMessage {\n /** Type of event: client or server */\n type: \"client\" | \"server\";\n /** Parsed event data */\n event: ClientEventUnion | ServerEventUnion;\n /** Original raw data for debugging */\n raw: string | ArrayBuffer;\n}\n\n/**\n * Parses and serializes Voice Live protocol messages\n */\nexport class VoiceLiveMessageParser {\n /**\n * Parses incoming WebSocket message data into typed events\n */\n parseIncomingMessage(data: string | ArrayBuffer): ParsedMessage | null {\n try {\n let messageText: string;\n\n if (data instanceof ArrayBuffer) {\n messageText = new TextDecoder().decode(data);\n } else {\n messageText = data;\n }\n\n const parsedData = JSON.parse(messageText);\n\n // Validate and type the message based on the 'type' field\n if (this._isServerEvent(parsedData)) {\n return {\n type: \"server\",\n event: serverEventUnionDeserializer(parsedData),\n raw: data,\n };\n }\n\n // Handle unexpected client events (shouldn't normally receive these from server)\n if (this._isClientEvent(parsedData)) {\n return {\n type: \"client\",\n event: parsedData as ClientEventUnion,\n raw: data,\n };\n }\n\n return null; // Unknown message format\n } catch (error) {\n logger.error(\"Failed to parse incoming message:\", error);\n return {\n type: \"server\",\n event: {\n type: KnownServerEventType.Error,\n error: {\n type: \"error\",\n code: \"MessageParsingError\",\n message:\n \"Failed to parse incoming message data. \" +\n (error instanceof Error ? error.message : String(error)),\n } as ServerEventErrorDetails,\n } as ServerEventError,\n raw: data,\n };\n }\n }\n\n /**\n * Serializes outgoing client events for WebSocket transmission\n */\n serializeOutgoingMessage(event: ClientEventUnion): string {\n return JSON.stringify(clientEventUnionSerializer(event));\n }\n\n /**\n * Checks if the parsed data represents a server event\n */\n private _isServerEvent(data: any): boolean {\n // Check if data matches ServerEventUnion structure\n return data && typeof data.type === \"string\" && this._isValidServerEventType(data.type);\n }\n\n /**\n * Checks if the parsed data represents a client event\n */\n private _isClientEvent(data: any): boolean {\n // Check if data matches ClientEventUnion structure\n return data && typeof data.type === \"string\" && this._isValidClientEventType(data.type);\n }\n\n /**\n * Validates if the type string represents a valid server event type\n */\n private _isValidServerEventType(type: string): boolean {\n // Based on the comprehensive analysis in EXISTING_TYPES_ANALYSIS.md\n return Object.values(KnownServerEventType).includes(type as KnownServerEventType);\n }\n\n /**\n * Validates if the type string represents a valid client event type\n */\n private _isValidClientEventType(type: string): boolean {\n // Based on the comprehensive analysis in EXISTING_TYPES_ANALYSIS.md\n return Object.values(KnownClientEventType).includes(type as KnownClientEventType);\n }\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { KeyCredential, TokenCredential } from "@azure/core-auth";
|
|
2
2
|
import type { AbortSignalLike } from "@azure/abort-controller";
|
|
3
|
-
import type
|
|
3
|
+
import { type RequestSession, type ClientEventUnion, type ConversationRequestItem } from "./models/index.js";
|
|
4
4
|
import { ConnectionState } from "./websocket/connectionManager.js";
|
|
5
5
|
import type { VoiceLiveSessionHandlers, VoiceLiveSubscription } from "./handlers/sessionHandlers.js";
|
|
6
6
|
export interface VoiceLiveSessionOptions {
|
|
@@ -45,6 +45,7 @@ export declare class VoiceLiveSession {
|
|
|
45
45
|
private readonly _options;
|
|
46
46
|
private readonly _messageParser;
|
|
47
47
|
private readonly _model;
|
|
48
|
+
private readonly _apiVersion;
|
|
48
49
|
private _connectionManager?;
|
|
49
50
|
private _sessionId?;
|
|
50
51
|
private _activeTurnId?;
|
|
@@ -70,7 +71,6 @@ export declare class VoiceLiveSession {
|
|
|
70
71
|
disconnect(): Promise<void>;
|
|
71
72
|
/**
|
|
72
73
|
* Subscribe to VoiceLive session events using strongly-typed handlers.
|
|
73
|
-
* This follows the Azure SDK pattern used by EventHub, Service Bus, etc.
|
|
74
74
|
*
|
|
75
75
|
* @param handlers - Handler functions for different types of events
|
|
76
76
|
* @returns A subscription object that can be used to stop receiving events
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// Copyright (c) Microsoft Corporation.
|
|
2
2
|
// Licensed under the MIT License.
|
|
3
|
+
import { KnownClientEventType, KnownServerEventType, } from "./models/index.js";
|
|
3
4
|
import { ConnectionManager, ConnectionState } from "./websocket/connectionManager.js";
|
|
4
5
|
import { VoiceLiveWebSocketFactory } from "./websocket/websocketFactory.js";
|
|
5
6
|
import { VoiceLiveMessageParser } from "./protocol/messageParser.js";
|
|
@@ -19,6 +20,7 @@ export class VoiceLiveSession {
|
|
|
19
20
|
_options;
|
|
20
21
|
_messageParser;
|
|
21
22
|
_model;
|
|
23
|
+
_apiVersion;
|
|
22
24
|
_connectionManager;
|
|
23
25
|
_sessionId;
|
|
24
26
|
_activeTurnId;
|
|
@@ -40,6 +42,7 @@ export class VoiceLiveSession {
|
|
|
40
42
|
this._options = this._buildDefaultOptions(options);
|
|
41
43
|
this._messageParser = new VoiceLiveMessageParser();
|
|
42
44
|
this._model = model;
|
|
45
|
+
this._apiVersion = apiVersion;
|
|
43
46
|
// Initialize handler-based subscription management
|
|
44
47
|
this._subscriptionManager = new SubscriptionManager();
|
|
45
48
|
logger.info("VoiceLiveSession created", {
|
|
@@ -64,8 +67,7 @@ export class VoiceLiveSession {
|
|
|
64
67
|
model: this._model,
|
|
65
68
|
});
|
|
66
69
|
// Get WebSocket URL with authentication and model
|
|
67
|
-
const wsUrl = await this._credentialHandler.getWebSocketUrl(this._endpoint,
|
|
68
|
-
this._model);
|
|
70
|
+
const wsUrl = await this._credentialHandler.getWebSocketUrl(this._endpoint, this._apiVersion, this._model);
|
|
69
71
|
const authHeaders = await this._credentialHandler.getAuthHeaders();
|
|
70
72
|
// Create connection manager
|
|
71
73
|
const websocketFactory = new VoiceLiveWebSocketFactory();
|
|
@@ -117,7 +119,6 @@ export class VoiceLiveSession {
|
|
|
117
119
|
}
|
|
118
120
|
/**
|
|
119
121
|
* Subscribe to VoiceLive session events using strongly-typed handlers.
|
|
120
|
-
* This follows the Azure SDK pattern used by EventHub, Service Bus, etc.
|
|
121
122
|
*
|
|
122
123
|
* @param handlers - Handler functions for different types of events
|
|
123
124
|
* @returns A subscription object that can be used to stop receiving events
|
|
@@ -140,7 +141,7 @@ export class VoiceLiveSession {
|
|
|
140
141
|
async updateSession(session, options = {}) {
|
|
141
142
|
this._ensureConnected();
|
|
142
143
|
const updateEvent = {
|
|
143
|
-
type:
|
|
144
|
+
type: KnownClientEventType.SessionUpdate,
|
|
144
145
|
session: session,
|
|
145
146
|
eventId: this._generateEventId(),
|
|
146
147
|
};
|
|
@@ -155,7 +156,7 @@ export class VoiceLiveSession {
|
|
|
155
156
|
if (options.turnId) {
|
|
156
157
|
// Turn-based audio
|
|
157
158
|
const appendEvent = {
|
|
158
|
-
type:
|
|
159
|
+
type: KnownClientEventType.InputAudioTurnAppend,
|
|
159
160
|
audio: audioBase64,
|
|
160
161
|
turnId: options.turnId,
|
|
161
162
|
eventId: this._generateEventId(),
|
|
@@ -165,7 +166,7 @@ export class VoiceLiveSession {
|
|
|
165
166
|
else {
|
|
166
167
|
// Buffer-based audio (VAD mode)
|
|
167
168
|
const bufferEvent = {
|
|
168
|
-
type:
|
|
169
|
+
type: KnownClientEventType.InputAudioBufferAppend,
|
|
169
170
|
audio: audioBase64,
|
|
170
171
|
eventId: this._generateEventId(),
|
|
171
172
|
};
|
|
@@ -180,7 +181,7 @@ export class VoiceLiveSession {
|
|
|
180
181
|
const turnId = options.turnId || this._generateTurnId();
|
|
181
182
|
this._activeTurnId = turnId;
|
|
182
183
|
const startEvent = {
|
|
183
|
-
type:
|
|
184
|
+
type: KnownClientEventType.InputAudioTurnStart,
|
|
184
185
|
turnId: turnId,
|
|
185
186
|
eventId: this._generateEventId(),
|
|
186
187
|
};
|
|
@@ -197,7 +198,7 @@ export class VoiceLiveSession {
|
|
|
197
198
|
throw new VoiceLiveConnectionError("No active audio turn to end", "INVALID_STATE");
|
|
198
199
|
}
|
|
199
200
|
const endEvent = {
|
|
200
|
-
type:
|
|
201
|
+
type: KnownClientEventType.InputAudioTurnEnd,
|
|
201
202
|
turnId: targetTurnId,
|
|
202
203
|
eventId: this._generateEventId(),
|
|
203
204
|
};
|
|
@@ -212,7 +213,7 @@ export class VoiceLiveSession {
|
|
|
212
213
|
async addConversationItem(item, options = {}) {
|
|
213
214
|
this._ensureConnected();
|
|
214
215
|
const createEvent = {
|
|
215
|
-
type:
|
|
216
|
+
type: KnownClientEventType.ConversationItemCreate,
|
|
216
217
|
item: item,
|
|
217
218
|
eventId: this._generateEventId(),
|
|
218
219
|
};
|
|
@@ -348,7 +349,7 @@ export class VoiceLiveSession {
|
|
|
348
349
|
}
|
|
349
350
|
_handleServerEvent(event) {
|
|
350
351
|
// Extract session information from events
|
|
351
|
-
if (event.type ===
|
|
352
|
+
if (event.type === KnownServerEventType.SessionCreated && event.session?.id) {
|
|
352
353
|
this._sessionId = event.session.id;
|
|
353
354
|
logger.info("Session created", { sessionId: this._sessionId });
|
|
354
355
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"voiceLiveSession.js","sourceRoot":"","sources":["../../src/voiceLiveSession.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { KeyCredential, TokenCredential } from \"@azure/core-auth\";\nimport type { AbortSignalLike } from \"@azure/abort-controller\";\nimport type {\n RequestSession,\n ClientEventSessionUpdate,\n ClientEventUnion,\n ClientEventInputAudioBufferAppend,\n ClientEventInputAudioTurnStart,\n ClientEventInputAudioTurnAppend,\n ClientEventInputAudioTurnEnd,\n ConversationRequestItem,\n ClientEventConversationItemCreate,\n ServerEventUnion,\n} from \"./models/index.js\";\nimport { ConnectionManager, ConnectionState } from \"./websocket/connectionManager.js\";\nimport { VoiceLiveWebSocketFactory } from \"./websocket/websocketFactory.js\";\nimport { VoiceLiveMessageParser } from \"./protocol/messageParser.js\";\nimport { CredentialHandler } from \"./auth/credentialHandler.js\";\nimport { VoiceLiveConnectionError, classifyConnectionError } from \"./errors/index.js\";\nimport { logger } from \"./logger.js\";\nimport type {\n VoiceLiveSessionHandlers,\n VoiceLiveSubscription,\n ConnectionContext,\n SessionContext,\n ConnectedEventArgs,\n DisconnectedEventArgs,\n ErrorEventArgs,\n} from \"./handlers/sessionHandlers.js\";\nimport { SubscriptionManager } from \"./handlers/subscriptionManager.js\";\n\nexport interface VoiceLiveSessionOptions {\n /** Connection timeout in milliseconds */\n connectionTimeoutInMs?: number;\n /** Enable debug logging for development */\n enableDebugLogging?: boolean;\n}\n\nexport interface CreateSessionOptions extends VoiceLiveSessionOptions {}\n\nexport interface StartSessionOptions extends VoiceLiveSessionOptions {}\nexport interface ConnectOptions {\n /** Abort signal to cancel connection attempt */\n abortSignal?: AbortSignalLike;\n /** Override connection timeout for this operation */\n timeoutInMs?: number;\n}\n\nexport interface SendEventOptions {\n /** Abort signal to cancel send operation */\n abortSignal?: AbortSignalLike;\n /** Timeout for send operation */\n timeoutInMs?: number;\n}\n\nexport interface AudioStreamOptions extends SendEventOptions {\n /** Turn ID for turn-based audio (if not provided, uses buffer mode) */\n turnId?: string;\n}\n\nexport interface TurnOptions extends SendEventOptions {\n /** Custom turn ID (if not provided, one will be generated) */\n turnId?: string;\n}\n\n/**\n * Represents a WebSocket-based session for real-time voice communication with the Azure VoiceLive service.\n *\n * This class manages the connection, handles real-time communication, and provides access to all\n * interactive features including audio streaming, conversation management, and avatar control.\n */\nexport class VoiceLiveSession {\n private readonly _endpoint: string;\n private readonly _credentialHandler: CredentialHandler;\n private readonly _options: Required<VoiceLiveSessionOptions>;\n private readonly _messageParser: VoiceLiveMessageParser;\n private readonly _model: string;\n private _connectionManager?: ConnectionManager;\n private _sessionId?: string;\n private _activeTurnId?: string;\n private _disposed = false;\n\n // Handler-based subscription management\n private readonly _subscriptionManager: SubscriptionManager;\n\n /**\n * Creates an instance of VoiceLiveSession.\n *\n * @param endpoint - The Voice Live service endpoint URL\n * @param credential - Azure TokenCredential or KeyCredential for authentication\n * @param apiVersion - API version to use for the Voice Live service\n * @param model - The model name to use for the session\n * @param options - Optional configuration for the session\n */\n constructor(\n endpoint: string,\n credential: TokenCredential | KeyCredential,\n apiVersion: string,\n model: string,\n options: VoiceLiveSessionOptions = {},\n ) {\n this._endpoint = this._normalizeEndpoint(endpoint);\n this._credentialHandler = new CredentialHandler(credential);\n this._options = this._buildDefaultOptions(options);\n this._messageParser = new VoiceLiveMessageParser();\n this._model = model;\n\n // Initialize handler-based subscription management\n this._subscriptionManager = new SubscriptionManager();\n\n logger.info(\"VoiceLiveSession created\", {\n endpoint: this._endpoint,\n model: this._model,\n apiVersion: apiVersion,\n enableDebugLogging: this._options.enableDebugLogging,\n });\n }\n\n /**\n * Establishes connection to the Voice Live service with authentication.\n */\n async connect(options: ConnectOptions = {}): Promise<void> {\n this._ensureNotDisposed();\n\n if (this.isConnected) {\n logger.info(\"VoiceLiveSession already connected\");\n return;\n }\n\n try {\n logger.info(\"Connecting to Voice Live service\", {\n endpoint: this._endpoint,\n model: this._model,\n });\n\n // Get WebSocket URL with authentication and model\n const wsUrl = await this._credentialHandler.getWebSocketUrl(\n this._endpoint,\n \"2025-10-01\", // TODO: make this configurable through constructor\n this._model,\n );\n const authHeaders = await this._credentialHandler.getAuthHeaders();\n\n // Create connection manager\n const websocketFactory = new VoiceLiveWebSocketFactory();\n this._connectionManager = new ConnectionManager(\n () =>\n websocketFactory.create({\n headers: { ...authHeaders },\n connectionTimeoutInMs: this._options.connectionTimeoutInMs,\n compression: true,\n }),\n {\n endpoint: wsUrl,\n connectionTimeout: options.timeoutInMs || this._options.connectionTimeoutInMs,\n },\n );\n\n // Setup connection event handlers\n this._setupConnectionEventHandlers();\n\n // Connect with proper error handling\n await this._connectionManager.connect(options.abortSignal);\n\n logger.info(\"Successfully connected to Voice Live service\");\n } catch (error) {\n logger.error(\"Failed to connect to Voice Live service\", { error });\n\n // Use error classification\n if (error instanceof VoiceLiveConnectionError) {\n throw error;\n } else {\n throw classifyConnectionError(error);\n }\n }\n }\n\n /**\n * Disconnects from the Voice Live service and cleans up resources.\n */\n async disconnect(): Promise<void> {\n if (!this._connectionManager) {\n return;\n }\n\n logger.info(\"Disconnecting from Voice Live service\");\n\n try {\n await this._connectionManager.disconnect();\n } catch (error) {\n logger.error(\"Error during disconnect\", { error });\n } finally {\n this._connectionManager = undefined;\n this._sessionId = undefined;\n this._activeTurnId = undefined;\n logger.info(\"Disconnected from Voice Live service\");\n }\n }\n\n /**\n * Subscribe to VoiceLive session events using strongly-typed handlers.\n * This follows the Azure SDK pattern used by EventHub, Service Bus, etc.\n *\n * @param handlers - Handler functions for different types of events\n * @returns A subscription object that can be used to stop receiving events\n */\n subscribe(handlers: VoiceLiveSessionHandlers): VoiceLiveSubscription {\n this._ensureNotDisposed();\n\n logger.info(\"Creating VoiceLive session subscription\");\n return this._subscriptionManager.createSubscription(handlers);\n }\n\n /**\n * Sends a custom client event to the service.\n */\n async sendEvent(event: ClientEventUnion, options: SendEventOptions = {}): Promise<void> {\n this._ensureConnected();\n await this._sendEvent(event, options);\n }\n\n /**\n * Updates the session configuration with the service.\n */\n async updateSession(session: RequestSession, options: SendEventOptions = {}): Promise<void> {\n this._ensureConnected();\n\n const updateEvent: ClientEventSessionUpdate = {\n type: \"session.update\",\n session: session,\n eventId: this._generateEventId(),\n };\n\n await this._sendEvent(updateEvent, options);\n }\n\n /**\n * Sends audio data to the service using turn-based or buffer-based approach.\n */\n async sendAudio(\n audioData: ArrayBuffer | Uint8Array,\n options: AudioStreamOptions = {},\n ): Promise<void> {\n this._ensureConnected();\n\n const audioBase64 = this._arrayBufferToBase64(audioData);\n\n if (options.turnId) {\n // Turn-based audio\n const appendEvent: ClientEventInputAudioTurnAppend = {\n type: \"input_audio.turn.append\",\n audio: audioBase64,\n turnId: options.turnId,\n eventId: this._generateEventId(),\n };\n await this._sendEvent(appendEvent, options);\n } else {\n // Buffer-based audio (VAD mode)\n const bufferEvent: ClientEventInputAudioBufferAppend = {\n type: \"input_audio_buffer.append\",\n audio: audioBase64,\n eventId: this._generateEventId(),\n };\n await this._sendEvent(bufferEvent, options);\n }\n }\n\n /**\n * Starts a new audio turn for turn-based audio input.\n */\n async startAudioTurn(options: TurnOptions = {}): Promise<string> {\n this._ensureConnected();\n\n const turnId = options.turnId || this._generateTurnId();\n this._activeTurnId = turnId;\n\n const startEvent: ClientEventInputAudioTurnStart = {\n type: \"input_audio.turn.start\",\n turnId: turnId,\n eventId: this._generateEventId(),\n };\n\n await this._sendEvent(startEvent, options);\n return turnId;\n }\n\n /**\n * Ends the current audio turn.\n */\n async endAudioTurn(turnId?: string, options: SendEventOptions = {}): Promise<void> {\n this._ensureConnected();\n\n const targetTurnId = turnId || this._activeTurnId;\n if (!targetTurnId) {\n throw new VoiceLiveConnectionError(\"No active audio turn to end\", \"INVALID_STATE\");\n }\n\n const endEvent: ClientEventInputAudioTurnEnd = {\n type: \"input_audio.turn.end\",\n turnId: targetTurnId,\n eventId: this._generateEventId(),\n };\n\n await this._sendEvent(endEvent, options);\n\n if (targetTurnId === this._activeTurnId) {\n this._activeTurnId = undefined;\n }\n }\n\n /**\n * Adds a conversation item (message) to the conversation.\n */\n async addConversationItem(\n item: ConversationRequestItem,\n options: SendEventOptions = {},\n ): Promise<void> {\n this._ensureConnected();\n\n const createEvent: ClientEventConversationItemCreate = {\n type: \"conversation.item.create\",\n item: item,\n eventId: this._generateEventId(),\n };\n\n await this._sendEvent(createEvent, options);\n }\n\n /**\n * Indicates whether the session is currently connected to the Voice Live service.\n */\n get isConnected(): boolean {\n return this._connectionManager?.isConnected || false;\n }\n\n /**\n * Gets the current connection state of the session.\n */\n get connectionState(): ConnectionState {\n return this._connectionManager?.state || ConnectionState.Disconnected;\n }\n\n /**\n * Gets the current session ID.\n */\n get sessionId(): string | undefined {\n return this._sessionId;\n }\n\n /**\n * Gets the current active audio turn ID.\n */\n get activeTurnId(): string | undefined {\n return this._activeTurnId;\n }\n\n /**\n * Disposes the session and cleans up resources.\n */\n async dispose(): Promise<void> {\n if (this._disposed) {\n return;\n }\n\n logger.info(\"Disposing VoiceLiveSession\");\n\n try {\n // Close all subscriptions first\n await this._subscriptionManager.closeAll();\n\n // Then disconnect\n await this.disconnect();\n } catch (error) {\n logger.error(\"Error during session disposal\", { error });\n } finally {\n this._disposed = true;\n logger.info(\"VoiceLiveSession disposed\");\n }\n }\n\n // Private methods\n\n private _buildDefaultOptions(\n options: VoiceLiveSessionOptions,\n ): Required<VoiceLiveSessionOptions> {\n return {\n connectionTimeoutInMs: options.connectionTimeoutInMs || 30000,\n enableDebugLogging: options.enableDebugLogging ?? false,\n };\n }\n\n private _normalizeEndpoint(endpoint: string): string {\n // Ensure endpoint has proper protocol\n if (!endpoint.startsWith(\"http://\") && !endpoint.startsWith(\"https://\")) {\n endpoint = `https://${endpoint}`;\n }\n\n // Remove trailing slash\n return endpoint.replace(/\\/$/, \"\");\n }\n\n private _setupConnectionEventHandlers(): void {\n if (!this._connectionManager) return;\n\n this._connectionManager.updateEventHandlers({\n onStateChange: (state, previousState) => {\n logger.info(\"Connection state changed\", { state, previousState });\n\n // Handle connection state changes for handler-based subscriptions\n if (state === ConnectionState.Connected && previousState === ConnectionState.Connecting) {\n this._notifyConnectionEvent(\"connected\", {\n connectionId: `conn_${Date.now()}`,\n timestamp: new Date(),\n });\n } else if (\n state === ConnectionState.Disconnected &&\n previousState === ConnectionState.Connected\n ) {\n this._notifyConnectionEvent(\"disconnected\", {\n code: 1006, // Abnormal closure\n reason: \"Connection lost during session\",\n wasClean: false,\n timestamp: new Date(),\n });\n this._markSessionAsDead(\n \"Connection lost during session - session is permanently unusable\",\n );\n }\n },\n onMessage: (data) => {\n this._handleIncomingMessage(data);\n },\n onError: (error) => {\n logger.error(\"Connection error - marking session as dead\", { error });\n this._notifyConnectionEvent(\"error\", {\n error: error,\n context: \"WebSocket connection error\",\n recoverable: false,\n timestamp: new Date(),\n });\n this._markSessionAsDead(`Connection error: ${error.message}`);\n },\n });\n }\n\n private _markSessionAsDead(reason: string): void {\n if (this._disposed) return;\n\n logger.error(\"Session marked as permanently dead\", { reason });\n\n // Mark as disposed to prevent further use\n this._disposed = true;\n\n // Clean up connection manager\n this._connectionManager = undefined;\n this._sessionId = undefined;\n this._activeTurnId = undefined;\n }\n\n private _handleIncomingMessage(data: string | ArrayBuffer): void {\n try {\n logger.info(\"Message received\", {\n type: typeof data,\n size: typeof data === \"string\" ? data.length : data.byteLength,\n });\n\n // Parse and process the message\n const parsed = this._messageParser.parseIncomingMessage(data);\n if (parsed && parsed.type === \"server\") {\n // Handle server events\n this._handleServerEvent(parsed.event);\n }\n } catch (error) {\n logger.error(\"Error handling incoming message\", { error });\n }\n }\n\n private _handleServerEvent(event: any): void {\n // Extract session information from events\n if (event.type === \"session.created\" && event.session?.id) {\n this._sessionId = event.session.id;\n logger.info(\"Session created\", { sessionId: this._sessionId });\n }\n\n // Notify handler-based subscriptions\n this._notifyServerEvent(event);\n }\n\n private _notifyConnectionEvent(\n eventType: \"connected\" | \"disconnected\" | \"error\",\n args: ConnectedEventArgs | DisconnectedEventArgs | ErrorEventArgs,\n ): void {\n const context: ConnectionContext = {\n endpoint: this._endpoint,\n sessionId: this._sessionId,\n timestamp: new Date(),\n model: this._model,\n };\n\n // Fire and forget - don't await to avoid blocking\n this._subscriptionManager.processConnectionEvent(eventType, args, context).catch((error) => {\n logger.error(\"Error processing connection event in handlers\", { eventType, error });\n });\n }\n\n private _notifyServerEvent(event: ServerEventUnion): void {\n if (!this._sessionId) {\n // Can't notify server events without a session ID\n return;\n }\n\n const context: SessionContext = {\n endpoint: this._endpoint,\n sessionId: this._sessionId,\n timestamp: new Date(),\n model: this._model,\n conversationId: undefined, // Could extract from event if available\n };\n\n // Fire and forget - don't await to avoid blocking\n this._subscriptionManager.processServerEvent(event, context).catch((error) => {\n logger.error(\"Error processing server event in handlers\", { eventType: event.type, error });\n });\n }\n\n private async _sendEvent(event: ClientEventUnion, options: SendEventOptions): Promise<void> {\n if (!this._connectionManager?.isConnected) {\n throw new VoiceLiveConnectionError(\"Not connected to Voice Live service\", \"NOT_CONNECTED\");\n }\n\n try {\n const serialized = this._messageParser.serializeOutgoingMessage(event);\n await this._connectionManager.send(serialized, options.abortSignal);\n\n logger.info(\"Sent event\", { type: event.type, eventId: (event as any).eventId });\n } catch (error) {\n if (error instanceof VoiceLiveConnectionError) {\n throw error;\n }\n\n throw classifyConnectionError(error);\n }\n }\n\n private _ensureConnected(): void {\n this._ensureNotDisposed();\n if (!this.isConnected) {\n throw new VoiceLiveConnectionError(\n \"Must be connected to Voice Live service\",\n \"NOT_CONNECTED\",\n );\n }\n }\n\n private _ensureNotDisposed(): void {\n if (this._disposed) {\n throw new VoiceLiveConnectionError(\n \"Session is permanently dead and cannot be used. Create a new session to continue.\",\n \"SESSION_DEAD\",\n );\n }\n }\n\n private _generateEventId(): string {\n return `evt_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;\n }\n\n private _generateTurnId(): string {\n return `turn_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;\n }\n\n private _arrayBufferToBase64(buffer: ArrayBuffer | Uint8Array): string {\n const bytes = buffer instanceof ArrayBuffer ? new Uint8Array(buffer) : buffer;\n let binary = \"\";\n for (let i = 0; i < bytes.byteLength; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"voiceLiveSession.js","sourceRoot":"","sources":["../../src/voiceLiveSession.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { KeyCredential, TokenCredential } from \"@azure/core-auth\";\nimport type { AbortSignalLike } from \"@azure/abort-controller\";\nimport {\n type RequestSession,\n type ClientEventSessionUpdate,\n type ClientEventUnion,\n type ClientEventInputAudioBufferAppend,\n type ClientEventInputAudioTurnStart,\n type ClientEventInputAudioTurnAppend,\n type ClientEventInputAudioTurnEnd,\n type ConversationRequestItem,\n type ClientEventConversationItemCreate,\n type ServerEventUnion,\n KnownClientEventType,\n KnownServerEventType,\n} from \"./models/index.js\";\nimport { ConnectionManager, ConnectionState } from \"./websocket/connectionManager.js\";\nimport { VoiceLiveWebSocketFactory } from \"./websocket/websocketFactory.js\";\nimport { VoiceLiveMessageParser } from \"./protocol/messageParser.js\";\nimport { CredentialHandler } from \"./auth/credentialHandler.js\";\nimport { VoiceLiveConnectionError, classifyConnectionError } from \"./errors/index.js\";\nimport { logger } from \"./logger.js\";\nimport type {\n VoiceLiveSessionHandlers,\n VoiceLiveSubscription,\n ConnectionContext,\n SessionContext,\n ConnectedEventArgs,\n DisconnectedEventArgs,\n ErrorEventArgs,\n} from \"./handlers/sessionHandlers.js\";\nimport { SubscriptionManager } from \"./handlers/subscriptionManager.js\";\n\nexport interface VoiceLiveSessionOptions {\n /** Connection timeout in milliseconds */\n connectionTimeoutInMs?: number;\n /** Enable debug logging for development */\n enableDebugLogging?: boolean;\n}\n\nexport interface CreateSessionOptions extends VoiceLiveSessionOptions {}\n\nexport interface StartSessionOptions extends VoiceLiveSessionOptions {}\nexport interface ConnectOptions {\n /** Abort signal to cancel connection attempt */\n abortSignal?: AbortSignalLike;\n /** Override connection timeout for this operation */\n timeoutInMs?: number;\n}\n\nexport interface SendEventOptions {\n /** Abort signal to cancel send operation */\n abortSignal?: AbortSignalLike;\n /** Timeout for send operation */\n timeoutInMs?: number;\n}\n\nexport interface AudioStreamOptions extends SendEventOptions {\n /** Turn ID for turn-based audio (if not provided, uses buffer mode) */\n turnId?: string;\n}\n\nexport interface TurnOptions extends SendEventOptions {\n /** Custom turn ID (if not provided, one will be generated) */\n turnId?: string;\n}\n\n/**\n * Represents a WebSocket-based session for real-time voice communication with the Azure VoiceLive service.\n *\n * This class manages the connection, handles real-time communication, and provides access to all\n * interactive features including audio streaming, conversation management, and avatar control.\n */\nexport class VoiceLiveSession {\n private readonly _endpoint: string;\n private readonly _credentialHandler: CredentialHandler;\n private readonly _options: Required<VoiceLiveSessionOptions>;\n private readonly _messageParser: VoiceLiveMessageParser;\n private readonly _model: string;\n private readonly _apiVersion: string;\n private _connectionManager?: ConnectionManager;\n private _sessionId?: string;\n private _activeTurnId?: string;\n private _disposed = false;\n // Handler-based subscription management\n private readonly _subscriptionManager: SubscriptionManager;\n\n /**\n * Creates an instance of VoiceLiveSession.\n *\n * @param endpoint - The Voice Live service endpoint URL\n * @param credential - Azure TokenCredential or KeyCredential for authentication\n * @param apiVersion - API version to use for the Voice Live service\n * @param model - The model name to use for the session\n * @param options - Optional configuration for the session\n */\n constructor(\n endpoint: string,\n credential: TokenCredential | KeyCredential,\n apiVersion: string,\n model: string,\n options: VoiceLiveSessionOptions = {},\n ) {\n this._endpoint = this._normalizeEndpoint(endpoint);\n this._credentialHandler = new CredentialHandler(credential);\n this._options = this._buildDefaultOptions(options);\n this._messageParser = new VoiceLiveMessageParser();\n this._model = model;\n this._apiVersion = apiVersion;\n\n // Initialize handler-based subscription management\n this._subscriptionManager = new SubscriptionManager();\n\n logger.info(\"VoiceLiveSession created\", {\n endpoint: this._endpoint,\n model: this._model,\n apiVersion: apiVersion,\n enableDebugLogging: this._options.enableDebugLogging,\n });\n }\n\n /**\n * Establishes connection to the Voice Live service with authentication.\n */\n async connect(options: ConnectOptions = {}): Promise<void> {\n this._ensureNotDisposed();\n\n if (this.isConnected) {\n logger.info(\"VoiceLiveSession already connected\");\n return;\n }\n\n try {\n logger.info(\"Connecting to Voice Live service\", {\n endpoint: this._endpoint,\n model: this._model,\n });\n\n // Get WebSocket URL with authentication and model\n const wsUrl = await this._credentialHandler.getWebSocketUrl(\n this._endpoint,\n this._apiVersion,\n this._model,\n );\n const authHeaders = await this._credentialHandler.getAuthHeaders();\n\n // Create connection manager\n const websocketFactory = new VoiceLiveWebSocketFactory();\n this._connectionManager = new ConnectionManager(\n () =>\n websocketFactory.create({\n headers: { ...authHeaders },\n connectionTimeoutInMs: this._options.connectionTimeoutInMs,\n compression: true,\n }),\n {\n endpoint: wsUrl,\n connectionTimeout: options.timeoutInMs || this._options.connectionTimeoutInMs,\n },\n );\n\n // Setup connection event handlers\n this._setupConnectionEventHandlers();\n\n // Connect with proper error handling\n await this._connectionManager.connect(options.abortSignal);\n\n logger.info(\"Successfully connected to Voice Live service\");\n } catch (error) {\n logger.error(\"Failed to connect to Voice Live service\", { error });\n\n // Use error classification\n if (error instanceof VoiceLiveConnectionError) {\n throw error;\n } else {\n throw classifyConnectionError(error);\n }\n }\n }\n\n /**\n * Disconnects from the Voice Live service and cleans up resources.\n */\n async disconnect(): Promise<void> {\n if (!this._connectionManager) {\n return;\n }\n\n logger.info(\"Disconnecting from Voice Live service\");\n\n try {\n await this._connectionManager.disconnect();\n } catch (error) {\n logger.error(\"Error during disconnect\", { error });\n } finally {\n this._connectionManager = undefined;\n this._sessionId = undefined;\n this._activeTurnId = undefined;\n logger.info(\"Disconnected from Voice Live service\");\n }\n }\n\n /**\n * Subscribe to VoiceLive session events using strongly-typed handlers.\n *\n * @param handlers - Handler functions for different types of events\n * @returns A subscription object that can be used to stop receiving events\n */\n subscribe(handlers: VoiceLiveSessionHandlers): VoiceLiveSubscription {\n this._ensureNotDisposed();\n\n logger.info(\"Creating VoiceLive session subscription\");\n return this._subscriptionManager.createSubscription(handlers);\n }\n\n /**\n * Sends a custom client event to the service.\n */\n async sendEvent(event: ClientEventUnion, options: SendEventOptions = {}): Promise<void> {\n this._ensureConnected();\n await this._sendEvent(event, options);\n }\n\n /**\n * Updates the session configuration with the service.\n */\n async updateSession(session: RequestSession, options: SendEventOptions = {}): Promise<void> {\n this._ensureConnected();\n\n const updateEvent: ClientEventSessionUpdate = {\n type: KnownClientEventType.SessionUpdate,\n session: session,\n eventId: this._generateEventId(),\n };\n\n await this._sendEvent(updateEvent, options);\n }\n\n /**\n * Sends audio data to the service using turn-based or buffer-based approach.\n */\n async sendAudio(\n audioData: ArrayBuffer | Uint8Array,\n options: AudioStreamOptions = {},\n ): Promise<void> {\n this._ensureConnected();\n\n const audioBase64 = this._arrayBufferToBase64(audioData);\n\n if (options.turnId) {\n // Turn-based audio\n const appendEvent: ClientEventInputAudioTurnAppend = {\n type: KnownClientEventType.InputAudioTurnAppend,\n audio: audioBase64,\n turnId: options.turnId,\n eventId: this._generateEventId(),\n };\n await this._sendEvent(appendEvent, options);\n } else {\n // Buffer-based audio (VAD mode)\n const bufferEvent: ClientEventInputAudioBufferAppend = {\n type: KnownClientEventType.InputAudioBufferAppend,\n audio: audioBase64,\n eventId: this._generateEventId(),\n };\n await this._sendEvent(bufferEvent, options);\n }\n }\n\n /**\n * Starts a new audio turn for turn-based audio input.\n */\n async startAudioTurn(options: TurnOptions = {}): Promise<string> {\n this._ensureConnected();\n\n const turnId = options.turnId || this._generateTurnId();\n this._activeTurnId = turnId;\n\n const startEvent: ClientEventInputAudioTurnStart = {\n type: KnownClientEventType.InputAudioTurnStart,\n turnId: turnId,\n eventId: this._generateEventId(),\n };\n\n await this._sendEvent(startEvent, options);\n return turnId;\n }\n\n /**\n * Ends the current audio turn.\n */\n async endAudioTurn(turnId?: string, options: SendEventOptions = {}): Promise<void> {\n this._ensureConnected();\n\n const targetTurnId = turnId || this._activeTurnId;\n if (!targetTurnId) {\n throw new VoiceLiveConnectionError(\"No active audio turn to end\", \"INVALID_STATE\");\n }\n\n const endEvent: ClientEventInputAudioTurnEnd = {\n type: KnownClientEventType.InputAudioTurnEnd,\n turnId: targetTurnId,\n eventId: this._generateEventId(),\n };\n\n await this._sendEvent(endEvent, options);\n\n if (targetTurnId === this._activeTurnId) {\n this._activeTurnId = undefined;\n }\n }\n\n /**\n * Adds a conversation item (message) to the conversation.\n */\n async addConversationItem(\n item: ConversationRequestItem,\n options: SendEventOptions = {},\n ): Promise<void> {\n this._ensureConnected();\n\n const createEvent: ClientEventConversationItemCreate = {\n type: KnownClientEventType.ConversationItemCreate,\n item: item,\n eventId: this._generateEventId(),\n };\n\n await this._sendEvent(createEvent, options);\n }\n\n /**\n * Indicates whether the session is currently connected to the Voice Live service.\n */\n get isConnected(): boolean {\n return this._connectionManager?.isConnected || false;\n }\n\n /**\n * Gets the current connection state of the session.\n */\n get connectionState(): ConnectionState {\n return this._connectionManager?.state || ConnectionState.Disconnected;\n }\n\n /**\n * Gets the current session ID.\n */\n get sessionId(): string | undefined {\n return this._sessionId;\n }\n\n /**\n * Gets the current active audio turn ID.\n */\n get activeTurnId(): string | undefined {\n return this._activeTurnId;\n }\n\n /**\n * Disposes the session and cleans up resources.\n */\n async dispose(): Promise<void> {\n if (this._disposed) {\n return;\n }\n\n logger.info(\"Disposing VoiceLiveSession\");\n\n try {\n // Close all subscriptions first\n await this._subscriptionManager.closeAll();\n\n // Then disconnect\n await this.disconnect();\n } catch (error) {\n logger.error(\"Error during session disposal\", { error });\n } finally {\n this._disposed = true;\n logger.info(\"VoiceLiveSession disposed\");\n }\n }\n\n // Private methods\n\n private _buildDefaultOptions(\n options: VoiceLiveSessionOptions,\n ): Required<VoiceLiveSessionOptions> {\n return {\n connectionTimeoutInMs: options.connectionTimeoutInMs || 30000,\n enableDebugLogging: options.enableDebugLogging ?? false,\n };\n }\n\n private _normalizeEndpoint(endpoint: string): string {\n // Ensure endpoint has proper protocol\n if (!endpoint.startsWith(\"http://\") && !endpoint.startsWith(\"https://\")) {\n endpoint = `https://${endpoint}`;\n }\n\n // Remove trailing slash\n return endpoint.replace(/\\/$/, \"\");\n }\n\n private _setupConnectionEventHandlers(): void {\n if (!this._connectionManager) return;\n\n this._connectionManager.updateEventHandlers({\n onStateChange: (state, previousState) => {\n logger.info(\"Connection state changed\", { state, previousState });\n\n // Handle connection state changes for handler-based subscriptions\n if (state === ConnectionState.Connected && previousState === ConnectionState.Connecting) {\n this._notifyConnectionEvent(\"connected\", {\n connectionId: `conn_${Date.now()}`,\n timestamp: new Date(),\n });\n } else if (\n state === ConnectionState.Disconnected &&\n previousState === ConnectionState.Connected\n ) {\n this._notifyConnectionEvent(\"disconnected\", {\n code: 1006, // Abnormal closure\n reason: \"Connection lost during session\",\n wasClean: false,\n timestamp: new Date(),\n });\n this._markSessionAsDead(\n \"Connection lost during session - session is permanently unusable\",\n );\n }\n },\n onMessage: (data) => {\n this._handleIncomingMessage(data);\n },\n onError: (error) => {\n logger.error(\"Connection error - marking session as dead\", { error });\n this._notifyConnectionEvent(\"error\", {\n error: error,\n context: \"WebSocket connection error\",\n recoverable: false,\n timestamp: new Date(),\n });\n this._markSessionAsDead(`Connection error: ${error.message}`);\n },\n });\n }\n\n private _markSessionAsDead(reason: string): void {\n if (this._disposed) return;\n\n logger.error(\"Session marked as permanently dead\", { reason });\n\n // Mark as disposed to prevent further use\n this._disposed = true;\n\n // Clean up connection manager\n this._connectionManager = undefined;\n this._sessionId = undefined;\n this._activeTurnId = undefined;\n }\n\n private _handleIncomingMessage(data: string | ArrayBuffer): void {\n try {\n logger.info(\"Message received\", {\n type: typeof data,\n size: typeof data === \"string\" ? data.length : data.byteLength,\n });\n\n // Parse and process the message\n const parsed = this._messageParser.parseIncomingMessage(data);\n if (parsed && parsed.type === \"server\") {\n // Handle server events\n this._handleServerEvent(parsed.event);\n }\n } catch (error) {\n logger.error(\"Error handling incoming message\", { error });\n }\n }\n\n private _handleServerEvent(event: any): void {\n // Extract session information from events\n if (event.type === KnownServerEventType.SessionCreated && event.session?.id) {\n this._sessionId = event.session.id;\n logger.info(\"Session created\", { sessionId: this._sessionId });\n }\n\n // Notify handler-based subscriptions\n this._notifyServerEvent(event);\n }\n\n private _notifyConnectionEvent(\n eventType: \"connected\" | \"disconnected\" | \"error\",\n args: ConnectedEventArgs | DisconnectedEventArgs | ErrorEventArgs,\n ): void {\n const context: ConnectionContext = {\n endpoint: this._endpoint,\n sessionId: this._sessionId,\n timestamp: new Date(),\n model: this._model,\n };\n\n // Fire and forget - don't await to avoid blocking\n this._subscriptionManager.processConnectionEvent(eventType, args, context).catch((error) => {\n logger.error(\"Error processing connection event in handlers\", { eventType, error });\n });\n }\n\n private _notifyServerEvent(event: ServerEventUnion): void {\n if (!this._sessionId) {\n // Can't notify server events without a session ID\n return;\n }\n\n const context: SessionContext = {\n endpoint: this._endpoint,\n sessionId: this._sessionId,\n timestamp: new Date(),\n model: this._model,\n conversationId: undefined, // Could extract from event if available\n };\n\n // Fire and forget - don't await to avoid blocking\n this._subscriptionManager.processServerEvent(event, context).catch((error) => {\n logger.error(\"Error processing server event in handlers\", { eventType: event.type, error });\n });\n }\n\n private async _sendEvent(event: ClientEventUnion, options: SendEventOptions): Promise<void> {\n if (!this._connectionManager?.isConnected) {\n throw new VoiceLiveConnectionError(\"Not connected to Voice Live service\", \"NOT_CONNECTED\");\n }\n\n try {\n const serialized = this._messageParser.serializeOutgoingMessage(event);\n await this._connectionManager.send(serialized, options.abortSignal);\n\n logger.info(\"Sent event\", { type: event.type, eventId: (event as any).eventId });\n } catch (error) {\n if (error instanceof VoiceLiveConnectionError) {\n throw error;\n }\n\n throw classifyConnectionError(error);\n }\n }\n\n private _ensureConnected(): void {\n this._ensureNotDisposed();\n if (!this.isConnected) {\n throw new VoiceLiveConnectionError(\n \"Must be connected to Voice Live service\",\n \"NOT_CONNECTED\",\n );\n }\n }\n\n private _ensureNotDisposed(): void {\n if (this._disposed) {\n throw new VoiceLiveConnectionError(\n \"Session is permanently dead and cannot be used. Create a new session to continue.\",\n \"SESSION_DEAD\",\n );\n }\n }\n\n private _generateEventId(): string {\n return `evt_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;\n }\n\n private _generateTurnId(): string {\n return `turn_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;\n }\n\n private _arrayBufferToBase64(buffer: ArrayBuffer | Uint8Array): string {\n const bytes = buffer instanceof ArrayBuffer ? new Uint8Array(buffer) : buffer;\n let binary = \"\";\n for (let i = 0; i < bytes.byteLength; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"websocket-browser.mjs","sourceRoot":"","sources":["../../../src/websocket/websocket-browser.mts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAGlC,OAAO,EACL,cAAc,GAGf,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAE9F;;GAEG;AACH,MAAM,OAAO,kBAAkB;IACrB,GAAG,CAAa;IAChB,IAAI,CAAU;IACd,QAAQ,CAA0B;IAElC,OAAO,CAAc;IACrB,QAAQ,CAA0C;IAClD,UAAU,CAAwC;IAClD,QAAQ,CAA0B;IAE1C,YAAY,UAAmC,EAAE;QAC/C,IAAI,CAAC,QAAQ,GAAG;YACd,qBAAqB,EAAE,KAAK;YAC5B,cAAc,EAAE,IAAI,GAAG,IAAI,EAAE,MAAM;YACnC,GAAG,OAAO;SACX,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,GAAW,EAAE,SAAoB,EAAE,WAA6B;QAC5E,IAAI,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,MAAM,EAAE,CAAC;YACzD,MAAM,IAAI,wBAAwB,CAChC,8CAA8C,EAC9C,mBAAmB,CAAC,gBAAgB,CACrC,CAAC;QACJ,CAAC;QAED,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE;gBAChC,MAAM,CACJ,IAAI,wBAAwB,CAC1B,sCAAsC,IAAI,CAAC,QAAQ,CAAC,qBAAqB,IAAI,EAC7E,mBAAmB,CAAC,iBAAiB,CACtC,CACF,CAAC;YACJ,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,qBAAqB,CAAC,CAAC;YACxC,sBAAsB;YACtB,MAAM,YAAY,GAAG,GAAS,EAAE;gBAC9B,YAAY,CAAC,SAAS,CAAC,CAAC;gBACxB,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;oBACb,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;gBACnB,CAAC;gBACD,MAAM,CACJ,IAAI,wBAAwB,CAC1B,8BAA8B,EAC9B,mBAAmB,CAAC,kBAAkB,CACvC,CACF,CAAC;YACJ,CAAC,CAAC;YAEF,IAAI,WAAW,EAAE,CAAC;gBAChB,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC;oBACxB,YAAY,EAAE,CAAC;oBACf,OAAO;gBACT,CAAC;gBACD,WAAW,CAAC,gBAAgB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;YACtD,CAAC;YAED,IAAI,CAAC;gBACH,2EAA2E;gBAC3E,uDAAuD;gBACvD,MAAM,cAAc,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;gBAEzE,IAAI,CAAC,GAAG,GAAG,IAAI,SAAS,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;gBACpD,IAAI,CAAC,GAAG,CAAC,UAAU,GAAG,aAAa,CAAC;gBACpC,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC;gBAEhB,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC,MAAM,EAAE,GAAG,EAAE;oBACrC,YAAY,CAAC,SAAS,CAAC,CAAC;oBACxB,IAAI,WAAW,EAAE,CAAC;wBAChB,WAAW,CAAC,mBAAmB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;oBACzD,CAAC;oBACD,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;oBACjB,OAAO,EAAE,CAAC;gBACZ,CAAC,CAAC,CAAC;gBAEH,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,KAAiB,EAAE,EAAE;oBACvD,YAAY,CAAC,SAAS,CAAC,CAAC;oBACxB,IAAI,WAAW,EAAE,CAAC;wBAChB,WAAW,CAAC,mBAAmB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;oBACzD,CAAC;oBACD,IAAI,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;gBAC5C,CAAC,CAAC,CAAC;gBAEH,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC,SAAS,EAAE,CAAC,KAAmB,EAAE,EAAE;oBAC3D,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;wBACnC,IAAI,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;oBAChC,CAAC;yBAAM,IAAI,KAAK,CAAC,IAAI,YAAY,WAAW,EAAE,CAAC;wBAC7C,IAAI,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;oBAChC,CAAC;yBAAM,IAAI,KAAK,CAAC,IAAI,YAAY,IAAI,EAAE,CAAC;wBACtC,8BAA8B;wBAC9B,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;wBAChC,MAAM,CAAC,MAAM,GAAG,GAAG,EAAE;4BACnB,IAAI,MAAM,CAAC,MAAM,YAAY,WAAW,EAAE,CAAC;gCACzC,IAAI,CAAC,UAAU,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;4BACnC,CAAC;wBACH,CAAC,CAAC;wBACF,MAAM,CAAC,OAAO,GAAG,GAAG,EAAE;4BACpB,IAAI,CAAC,QAAQ,EAAE,CACb,IAAI,wBAAwB,CAC1B,0BAA0B,EAC1B,mBAAmB,CAAC,cAAc,EAClC,WAAW,CACZ,CACF,CAAC;wBACJ,CAAC,CAAC;wBACF,MAAM,CAAC,iBAAiB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;oBACvC,CAAC;gBACH,CAAC,CAAC,CAAC;gBAEH,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE;oBACtC,YAAY,CAAC,SAAS,CAAC,CAAC;oBACxB,IAAI,WAAW,EAAE,CAAC;wBAChB,WAAW,CAAC,mBAAmB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;oBACzD,CAAC;oBACD,MAAM,KAAK,GAAG,IAAI,wBAAwB,CACxC,6BAA6B,EAC7B,mBAAmB,CAAC,cAAc,EAClC,sBAAsB,EACtB,IAAI,CACL,CAAC;oBACF,IAAI,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,CAAC;oBACvB,MAAM,CAAC,KAAK,CAAC,CAAC;gBAChB,CAAC,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,YAAY,CAAC,SAAS,CAAC,CAAC;gBACxB,IAAI,WAAW,EAAE,CAAC;oBAChB,WAAW,CAAC,mBAAmB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;gBACzD,CAAC;gBACD,MAAM,CACJ,IAAI,wBAAwB,CAC1B,+BAA+B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,EACzF,mBAAmB,CAAC,gBAAgB,EACpC,oBAAoB,EACpB,KAAK,EACL,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAC1D,CACF,CAAC;YACJ,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,OAAe,IAAI,EAAE,MAAe;QACnD,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,MAAM,EAAE,CAAC;YAC1D,OAAO;QACT,CAAC;QAED,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC7B,MAAM,YAAY,GAAG,GAAS,EAAE;gBAC9B,OAAO,EAAE,CAAC;YACZ,CAAC,CAAC;YAEF,IAAI,IAAI,CAAC,GAAI,CAAC,UAAU,KAAK,SAAS,CAAC,OAAO,EAAE,CAAC;gBAC/C,IAAI,CAAC,GAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YACpE,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,GAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;gBAClE,IAAI,CAAC,GAAI,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAChC,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,IAA0B,EAAE,WAA6B;QAClE,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI,EAAE,CAAC;YACxD,MAAM,IAAI,wBAAwB,CAChC,4BAA4B,EAC5B,mBAAmB,CAAC,YAAY,CACjC,CAAC;QACJ,CAAC;QAED,IAAI,WAAW,EAAE,OAAO,EAAE,CAAC;YACzB,MAAM,IAAI,wBAAwB,CAChC,wBAAwB,EACxB,mBAAmB,CAAC,kBAAkB,CACvC,CAAC;QACJ,CAAC;QAED,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,MAAM,YAAY,GAAG,GAAS,EAAE;gBAC9B,MAAM,CACJ,IAAI,wBAAwB,CAC1B,wBAAwB,EACxB,mBAAmB,CAAC,kBAAkB,CACvC,CACF,CAAC;YACJ,CAAC,CAAC;YAEF,IAAI,WAAW,EAAE,CAAC;gBAChB,WAAW,CAAC,gBAAgB,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YACtE,CAAC;YAED,IAAI,CAAC;gBACH,IAAI,CAAC,GAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACrB,IAAI,WAAW,EAAE,CAAC;oBAChB,WAAW,CAAC,mBAAmB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;gBACzD,CAAC;gBACD,OAAO,EAAE,CAAC;YACZ,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,WAAW,EAAE,CAAC;oBAChB,WAAW,CAAC,mBAAmB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;gBACzD,CAAC;gBACD,MAAM,CACJ,IAAI,wBAAwB,CAC1B,qCAAqC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,EAC/F,mBAAmB,CAAC,cAAc,EAClC,cAAc,EACd,IAAI,EACJ,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAC1D,CACF,CAAC;YACJ,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,CAAC,OAAmB;QACxB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED,OAAO,CAAC,OAA+C;QACrD,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;IAC1B,CAAC;IAED,SAAS,CAAC,OAA6C;QACrD,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC;IAC5B,CAAC;IAED,OAAO,CAAC,OAA+B;QACrC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;IAC1B,CAAC;IAED,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,GAAG,EAAE,UAAU,KAAK,SAAS,CAAC,IAAI,CAAC;IACjD,CAAC;IAED,IAAI,UAAU;QACZ,IAAI,CAAC,IAAI,CAAC,GAAG;YAAE,OAAO,cAAc,CAAC,MAAM,CAAC;QAC5C,OAAO,IAAI,CAAC,GAAG,CAAC,UAA4B,CAAC;IAC/C,CAAC;IAED,IAAI,GAAG;QACL,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED;;;;OAIG;IACK,gBAAgB,CAAC,GAAW,EAAE,OAAgC;QACpE,IAAI,CAAC,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAClD,OAAO,GAAG,CAAC;QACb,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QAE5B,uEAAuE;QACvE,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YACnD,MAAM,QAAQ,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;YAEnC,IAAI,QAAQ,KAAK,eAAe,EAAE,CAAC;gBACjC,wDAAwD;gBACxD,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;YAClD,CAAC;iBAAM,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAClC,0CAA0C;gBAC1C,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;YAC5C,CAAC;iBAAM,IAAI,QAAQ,KAAK,wBAAwB,EAAE,CAAC;gBACjD,uCAAuC;gBACvC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,mBAAmB,EAAE,KAAK,CAAC,CAAC;YACtD,CAAC;iBAAM,IAAI,QAAQ,KAAK,YAAY,EAAE,CAAC;gBACrC,iDAAiD;gBACjD,SAAS;YACX,CAAC;iBAAM,CAAC;gBACN,kEAAkE;gBAClE,oDAAoD;gBACpD,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,QAAQ,EAAE,EAAE,KAAK,CAAC,CAAC;YAClD,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC,QAAQ,EAAE,CAAC;IAC3B,CAAC;CACF","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { AbortSignalLike } from \"@azure/abort-controller\";\nimport {\n WebSocketState,\n type VoiceLiveWebSocketLike,\n type WebSocketFactoryOptions,\n} from \"./websocketLike.js\";\nimport { VoiceLiveConnectionError, VoiceLiveErrorCodes } from \"../errors/connectionErrors.js\";\n\n/**\n * Browser WebSocket implementation using native WebSocket API\n */\nexport class VoiceLiveWebSocket implements VoiceLiveWebSocketLike {\n private _ws?: WebSocket;\n private _url?: string;\n private _options: WebSocketFactoryOptions;\n\n private _onOpen?: () => void;\n private _onClose?: (code: number, reason: string) => void;\n private _onMessage?: (data: string | ArrayBuffer) => void;\n private _onError?: (error: Error) => void;\n\n constructor(options: WebSocketFactoryOptions = {}) {\n this._options = {\n connectionTimeoutInMs: 30000,\n maxMessageSize: 1024 * 1024, // 1MB\n ...options,\n };\n }\n\n async connect(url: string, protocols?: string[], abortSignal?: AbortSignalLike): Promise<void> {\n if (this._ws && this._ws.readyState !== WebSocket.CLOSED) {\n throw new VoiceLiveConnectionError(\n \"WebSocket is already connected or connecting\",\n VoiceLiveErrorCodes.AlreadyConnected,\n );\n }\n\n return new Promise((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n reject(\n new VoiceLiveConnectionError(\n `WebSocket connection timeout after ${this._options.connectionTimeoutInMs}ms`,\n VoiceLiveErrorCodes.ConnectionTimeout,\n ),\n );\n }, this._options.connectionTimeoutInMs);\n // Handle abort signal\n const abortHandler = (): void => {\n clearTimeout(timeoutId);\n if (this._ws) {\n this._ws.close();\n }\n reject(\n new VoiceLiveConnectionError(\n \"WebSocket connection aborted\",\n VoiceLiveErrorCodes.OperationCancelled,\n ),\n );\n };\n\n if (abortSignal) {\n if (abortSignal.aborted) {\n abortHandler();\n return;\n }\n abortSignal.addEventListener(\"abort\", abortHandler);\n }\n\n try {\n // Browser WebSocket API doesn't support custom headers, so we need to pass\n // authentication and other headers as query parameters\n const urlWithHeaders = this._addHeadersToUrl(url, this._options.headers);\n\n this._ws = new WebSocket(urlWithHeaders, protocols);\n this._ws.binaryType = \"arraybuffer\";\n this._url = url;\n\n this._ws.addEventListener(\"open\", () => {\n clearTimeout(timeoutId);\n if (abortSignal) {\n abortSignal.removeEventListener(\"abort\", abortHandler);\n }\n this._onOpen?.();\n resolve();\n });\n\n this._ws.addEventListener(\"close\", (event: CloseEvent) => {\n clearTimeout(timeoutId);\n if (abortSignal) {\n abortSignal.removeEventListener(\"abort\", abortHandler);\n }\n this._onClose?.(event.code, event.reason);\n });\n\n this._ws.addEventListener(\"message\", (event: MessageEvent) => {\n if (typeof event.data === \"string\") {\n this._onMessage?.(event.data);\n } else if (event.data instanceof ArrayBuffer) {\n this._onMessage?.(event.data);\n } else if (event.data instanceof Blob) {\n // Convert Blob to ArrayBuffer\n const reader = new FileReader();\n reader.onload = () => {\n if (reader.result instanceof ArrayBuffer) {\n this._onMessage?.(reader.result);\n }\n };\n reader.onerror = () => {\n this._onError?.(\n new VoiceLiveConnectionError(\n \"Failed to read blob data\",\n VoiceLiveErrorCodes.WebSocketError,\n \"blob_read\",\n ),\n );\n };\n reader.readAsArrayBuffer(event.data);\n }\n });\n\n this._ws.addEventListener(\"error\", () => {\n clearTimeout(timeoutId);\n if (abortSignal) {\n abortSignal.removeEventListener(\"abort\", abortHandler);\n }\n const error = new VoiceLiveConnectionError(\n \"WebSocket connection failed\",\n VoiceLiveErrorCodes.WebSocketError,\n \"websocket_connection\",\n true,\n );\n this._onError?.(error);\n reject(error);\n });\n } catch (error) {\n clearTimeout(timeoutId);\n if (abortSignal) {\n abortSignal.removeEventListener(\"abort\", abortHandler);\n }\n reject(\n new VoiceLiveConnectionError(\n `Failed to create WebSocket: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n VoiceLiveErrorCodes.ConnectionFailed,\n \"websocket_creation\",\n false,\n error instanceof Error ? error : new Error(String(error)),\n ),\n );\n }\n });\n }\n\n async disconnect(code: number = 1000, reason?: string): Promise<void> {\n if (!this._ws || this._ws.readyState === WebSocket.CLOSED) {\n return;\n }\n\n return new Promise((resolve) => {\n const closeHandler = (): void => {\n resolve();\n };\n\n if (this._ws!.readyState === WebSocket.CLOSING) {\n this._ws!.addEventListener(\"close\", closeHandler, { once: true });\n } else {\n this._ws!.addEventListener(\"close\", closeHandler, { once: true });\n this._ws!.close(code, reason);\n }\n });\n }\n\n async send(data: string | ArrayBuffer, abortSignal?: AbortSignalLike): Promise<void> {\n if (!this._ws || this._ws.readyState !== WebSocket.OPEN) {\n throw new VoiceLiveConnectionError(\n \"WebSocket is not connected\",\n VoiceLiveErrorCodes.NotConnected,\n );\n }\n\n if (abortSignal?.aborted) {\n throw new VoiceLiveConnectionError(\n \"Send operation aborted\",\n VoiceLiveErrorCodes.OperationCancelled,\n );\n }\n\n return new Promise((resolve, reject) => {\n const abortHandler = (): void => {\n reject(\n new VoiceLiveConnectionError(\n \"Send operation aborted\",\n VoiceLiveErrorCodes.OperationCancelled,\n ),\n );\n };\n\n if (abortSignal) {\n abortSignal.addEventListener(\"abort\", abortHandler, { once: true });\n }\n\n try {\n this._ws!.send(data);\n if (abortSignal) {\n abortSignal.removeEventListener(\"abort\", abortHandler);\n }\n resolve();\n } catch (error) {\n if (abortSignal) {\n abortSignal.removeEventListener(\"abort\", abortHandler);\n }\n reject(\n new VoiceLiveConnectionError(\n `Failed to send WebSocket message: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n VoiceLiveErrorCodes.WebSocketError,\n \"message_send\",\n true,\n error instanceof Error ? error : new Error(String(error)),\n ),\n );\n }\n });\n }\n\n onOpen(handler: () => void): void {\n this._onOpen = handler;\n }\n\n onClose(handler: (code: number, reason: string) => void): void {\n this._onClose = handler;\n }\n\n onMessage(handler: (data: string | ArrayBuffer) => void): void {\n this._onMessage = handler;\n }\n\n onError(handler: (error: Error) => void): void {\n this._onError = handler;\n }\n\n get isConnected(): boolean {\n return this._ws?.readyState === WebSocket.OPEN;\n }\n\n get readyState(): WebSocketState {\n if (!this._ws) return WebSocketState.Closed;\n return this._ws.readyState as WebSocketState;\n }\n\n get url(): string | undefined {\n return this._url;\n }\n\n /**\n * Converts headers to query parameters for browser WebSocket connections.\n * Browser WebSocket API doesn't support custom headers, so authentication\n * and other headers need to be passed as query parameters.\n */\n private _addHeadersToUrl(url: string, headers?: Record<string, string>): string {\n if (!headers || Object.keys(headers).length === 0) {\n return url;\n }\n\n const urlObj = new URL(url);\n\n // Convert known authentication headers to appropriate query parameters\n for (const [key, value] of Object.entries(headers)) {\n const lowerKey = key.toLowerCase();\n\n if (lowerKey === \"authorization\") {\n // Convert Bearer token to authorization query parameter\n urlObj.searchParams.set(\"authorization\", value);\n } else if (lowerKey === \"api-key\") {\n // API key goes to api-key query parameter\n urlObj.searchParams.set(\"api-key\", value);\n } else if (lowerKey === \"x-ms-client-request-id\") {\n // Client request ID as query parameter\n urlObj.searchParams.set(\"client-request-id\", value);\n } else if (lowerKey === \"user-agent\") {\n // User-Agent cannot be set in WebSocket, skip it\n continue;\n } else {\n // For other headers, convert to query parameters with 'h-' prefix\n // to avoid conflicts with existing query parameters\n urlObj.searchParams.set(`h-${lowerKey}`, value);\n }\n }\n\n return urlObj.toString();\n }\n}\n"]}
|
|
@@ -3,7 +3,7 @@ import { WebSocketState, type VoiceLiveWebSocketLike, type WebSocketFactoryOptio
|
|
|
3
3
|
/**
|
|
4
4
|
* Browser WebSocket implementation using native WebSocket API
|
|
5
5
|
*/
|
|
6
|
-
export declare class
|
|
6
|
+
export declare class VoiceLiveWebSocket implements VoiceLiveWebSocketLike {
|
|
7
7
|
private _ws?;
|
|
8
8
|
private _url?;
|
|
9
9
|
private _options;
|
|
@@ -22,5 +22,11 @@ export declare class VoiceLiveWebSocketBrowser implements VoiceLiveWebSocketLike
|
|
|
22
22
|
get isConnected(): boolean;
|
|
23
23
|
get readyState(): WebSocketState;
|
|
24
24
|
get url(): string | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* Converts headers to query parameters for browser WebSocket connections.
|
|
27
|
+
* Browser WebSocket API doesn't support custom headers, so authentication
|
|
28
|
+
* and other headers need to be passed as query parameters.
|
|
29
|
+
*/
|
|
30
|
+
private _addHeadersToUrl;
|
|
25
31
|
}
|
|
26
|
-
//# sourceMappingURL=
|
|
32
|
+
//# sourceMappingURL=websocket-browser.d.mts.map
|
|
@@ -5,7 +5,7 @@ import { VoiceLiveConnectionError, VoiceLiveErrorCodes } from "../errors/connect
|
|
|
5
5
|
/**
|
|
6
6
|
* Browser WebSocket implementation using native WebSocket API
|
|
7
7
|
*/
|
|
8
|
-
export class
|
|
8
|
+
export class VoiceLiveWebSocket {
|
|
9
9
|
_ws;
|
|
10
10
|
_url;
|
|
11
11
|
_options;
|
|
@@ -44,7 +44,10 @@ export class VoiceLiveWebSocketBrowser {
|
|
|
44
44
|
abortSignal.addEventListener("abort", abortHandler);
|
|
45
45
|
}
|
|
46
46
|
try {
|
|
47
|
-
|
|
47
|
+
// Browser WebSocket API doesn't support custom headers, so we need to pass
|
|
48
|
+
// authentication and other headers as query parameters
|
|
49
|
+
const urlWithHeaders = this._addHeadersToUrl(url, this._options.headers);
|
|
50
|
+
this._ws = new WebSocket(urlWithHeaders, protocols);
|
|
48
51
|
this._ws.binaryType = "arraybuffer";
|
|
49
52
|
this._url = url;
|
|
50
53
|
this._ws.addEventListener("open", () => {
|
|
@@ -171,5 +174,42 @@ export class VoiceLiveWebSocketBrowser {
|
|
|
171
174
|
get url() {
|
|
172
175
|
return this._url;
|
|
173
176
|
}
|
|
177
|
+
/**
|
|
178
|
+
* Converts headers to query parameters for browser WebSocket connections.
|
|
179
|
+
* Browser WebSocket API doesn't support custom headers, so authentication
|
|
180
|
+
* and other headers need to be passed as query parameters.
|
|
181
|
+
*/
|
|
182
|
+
_addHeadersToUrl(url, headers) {
|
|
183
|
+
if (!headers || Object.keys(headers).length === 0) {
|
|
184
|
+
return url;
|
|
185
|
+
}
|
|
186
|
+
const urlObj = new URL(url);
|
|
187
|
+
// Convert known authentication headers to appropriate query parameters
|
|
188
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
189
|
+
const lowerKey = key.toLowerCase();
|
|
190
|
+
if (lowerKey === "authorization") {
|
|
191
|
+
// Convert Bearer token to authorization query parameter
|
|
192
|
+
urlObj.searchParams.set("authorization", value);
|
|
193
|
+
}
|
|
194
|
+
else if (lowerKey === "api-key") {
|
|
195
|
+
// API key goes to api-key query parameter
|
|
196
|
+
urlObj.searchParams.set("api-key", value);
|
|
197
|
+
}
|
|
198
|
+
else if (lowerKey === "x-ms-client-request-id") {
|
|
199
|
+
// Client request ID as query parameter
|
|
200
|
+
urlObj.searchParams.set("client-request-id", value);
|
|
201
|
+
}
|
|
202
|
+
else if (lowerKey === "user-agent") {
|
|
203
|
+
// User-Agent cannot be set in WebSocket, skip it
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
// For other headers, convert to query parameters with 'h-' prefix
|
|
208
|
+
// to avoid conflicts with existing query parameters
|
|
209
|
+
urlObj.searchParams.set(`h-${lowerKey}`, value);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return urlObj.toString();
|
|
213
|
+
}
|
|
174
214
|
}
|
|
175
|
-
//# sourceMappingURL=
|
|
215
|
+
//# sourceMappingURL=websocket-browser.mjs.map
|
|
@@ -4,18 +4,7 @@ import type { VoiceLiveWebSocketLike, VoiceLiveWebSocketFactoryLike, WebSocketFa
|
|
|
4
4
|
*/
|
|
5
5
|
export declare class VoiceLiveWebSocketFactory implements VoiceLiveWebSocketFactoryLike {
|
|
6
6
|
create(options?: WebSocketFactoryOptions): VoiceLiveWebSocketLike;
|
|
7
|
-
private _createBrowserWebSocket;
|
|
8
|
-
private _createNodeWebSocket;
|
|
9
|
-
private _detectPlatform;
|
|
10
7
|
}
|
|
11
|
-
/**
|
|
12
|
-
* Platform detection utility
|
|
13
|
-
*/
|
|
14
|
-
export declare function detectPlatform(): "browser" | "node" | "unknown";
|
|
15
|
-
/**
|
|
16
|
-
* Check if platform supports WebSocket
|
|
17
|
-
*/
|
|
18
|
-
export declare function isWebSocketSupported(): boolean;
|
|
19
8
|
/**
|
|
20
9
|
* Default factory instance
|
|
21
10
|
*/
|