@corti/dictation-web 0.5.2-rc.1 → 0.5.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/bundle.js CHANGED
@@ -1048,8 +1048,21 @@ function usageEvent(detail) {
1048
1048
  detail
1049
1049
  });
1050
1050
  }
1051
+ function errorToMessage(error) {
1052
+ if (error instanceof Error) {
1053
+ return error.message;
1054
+ }
1055
+ if (typeof error === "object" && error !== null) {
1056
+ try {
1057
+ return JSON.stringify(error);
1058
+ } catch {
1059
+ return String(error);
1060
+ }
1061
+ }
1062
+ return String(error);
1063
+ }
1051
1064
  function errorEvent(error) {
1052
- const message = error instanceof Error && error.message ? error.message : JSON.stringify(error);
1065
+ const message = errorToMessage(error);
1053
1066
  return new CustomEvent("error", {
1054
1067
  bubbles: false,
1055
1068
  composed: true,
@@ -11701,6 +11714,7 @@ var _DictationController_doConnect;
11701
11714
  var _DictationController_connectProxy;
11702
11715
  var _DictationController_connectAuth;
11703
11716
  var _DictationController_setupWebSocketHandlers;
11717
+ var _DictationController_isSocketOpen;
11704
11718
  var _DictationController_drain;
11705
11719
  var DictationController = class {
11706
11720
  constructor(host) {
@@ -11718,7 +11732,7 @@ var DictationController = class {
11718
11732
  _DictationController_connectionGeneration.set(this, 0);
11719
11733
  _DictationController_isConnecting.set(this, false);
11720
11734
  this.mediaRecorderHandler = (data) => {
11721
- if (__classPrivateFieldGet4(this, _DictationController_socketReady, "f") && this.isConnectionOpen()) {
11735
+ if (__classPrivateFieldGet4(this, _DictationController_socketReady, "f") && __classPrivateFieldGet4(this, _DictationController_instances, "m", _DictationController_isSocketOpen).call(this)) {
11722
11736
  __classPrivateFieldGet4(this, _DictationController_webSocket, "f")?.send(data);
11723
11737
  __classPrivateFieldGet4(this, _DictationController_callbacks, "f")?.onNetworkActivity?.("sent", {
11724
11738
  size: data.size,
@@ -11746,7 +11760,7 @@ var DictationController = class {
11746
11760
  return __classPrivateFieldGet4(this, _DictationController_connectingPromise, "f");
11747
11761
  }
11748
11762
  async pause() {
11749
- if (__classPrivateFieldGet4(this, _DictationController_socketReady, "f") && this.isConnectionOpen()) {
11763
+ if (__classPrivateFieldGet4(this, _DictationController_socketReady, "f") && __classPrivateFieldGet4(this, _DictationController_instances, "m", _DictationController_isSocketOpen).call(this)) {
11750
11764
  __classPrivateFieldGet4(this, _DictationController_webSocket, "f")?.send(JSON.stringify({ type: "flush" }));
11751
11765
  __classPrivateFieldGet4(this, _DictationController_callbacks, "f")?.onNetworkActivity?.("sent", { type: "flush" });
11752
11766
  return;
@@ -11831,7 +11845,7 @@ var DictationController = class {
11831
11845
  __classPrivateFieldSet3(this, _DictationController_lastSocketUrl, void 0, "f");
11832
11846
  __classPrivateFieldSet3(this, _DictationController_lastSocketProxy, void 0, "f");
11833
11847
  if (__classPrivateFieldGet4(this, _DictationController_outboundQueue, "f").length > 0) {
11834
- this.host.dispatchEvent(errorEvent(`${__classPrivateFieldGet4(this, _DictationController_outboundQueue, "f").length} unsent audio message(s) were discarded because the configuration changed before the connection was closed`));
11848
+ this.host.dispatchEvent(errorEvent(`${__classPrivateFieldGet4(this, _DictationController_outboundQueue, "f").length} unsent message(s) were discarded because the configuration changed before the connection was closed`));
11835
11849
  }
11836
11850
  __classPrivateFieldSet3(this, _DictationController_outboundQueue, [], "f");
11837
11851
  }
@@ -11919,11 +11933,13 @@ _DictationController_cortiClient = /* @__PURE__ */ new WeakMap(), _DictationCont
11919
11933
  callbacks.onClose(event);
11920
11934
  }
11921
11935
  });
11936
+ }, _DictationController_isSocketOpen = function _DictationController_isSocketOpen2() {
11937
+ return __classPrivateFieldGet4(this, _DictationController_webSocket, "f") !== null && __classPrivateFieldGet4(this, _DictationController_webSocket, "f").readyState === WebSocket.OPEN;
11922
11938
  }, _DictationController_drain = function _DictationController_drain2() {
11923
- if (!__classPrivateFieldGet4(this, _DictationController_socketReady, "f") || !this.isConnectionOpen() || __classPrivateFieldGet4(this, _DictationController_outboundQueue, "f").length === 0) {
11939
+ if (!__classPrivateFieldGet4(this, _DictationController_socketReady, "f") || !__classPrivateFieldGet4(this, _DictationController_instances, "m", _DictationController_isSocketOpen).call(this) || __classPrivateFieldGet4(this, _DictationController_outboundQueue, "f").length === 0) {
11924
11940
  return;
11925
11941
  }
11926
- while (__classPrivateFieldGet4(this, _DictationController_outboundQueue, "f").length > 0 && this.isConnectionOpen()) {
11942
+ while (__classPrivateFieldGet4(this, _DictationController_outboundQueue, "f").length > 0 && __classPrivateFieldGet4(this, _DictationController_instances, "m", _DictationController_isSocketOpen).call(this)) {
11927
11943
  const item = __classPrivateFieldGet4(this, _DictationController_outboundQueue, "f").shift();
11928
11944
  if (item === void 0) {
11929
11945
  break;
@@ -9,7 +9,7 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
9
9
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
10
10
  return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
11
11
  };
12
- var _DictationController_instances, _DictationController_cortiClient, _DictationController_webSocket, _DictationController_closeTimeout, _DictationController_callbacks, _DictationController_lastDictationConfig, _DictationController_lastSocketUrl, _DictationController_lastSocketProxy, _DictationController_outboundQueue, _DictationController_socketReady, _DictationController_connectingPromise, _DictationController_connectionGeneration, _DictationController_isConnecting, _DictationController_configHasChanged, _DictationController_doConnect, _DictationController_connectProxy, _DictationController_connectAuth, _DictationController_setupWebSocketHandlers, _DictationController_drain;
12
+ var _DictationController_instances, _DictationController_cortiClient, _DictationController_webSocket, _DictationController_closeTimeout, _DictationController_callbacks, _DictationController_lastDictationConfig, _DictationController_lastSocketUrl, _DictationController_lastSocketProxy, _DictationController_outboundQueue, _DictationController_socketReady, _DictationController_connectingPromise, _DictationController_connectionGeneration, _DictationController_isConnecting, _DictationController_configHasChanged, _DictationController_doConnect, _DictationController_connectProxy, _DictationController_connectAuth, _DictationController_setupWebSocketHandlers, _DictationController_isSocketOpen, _DictationController_drain;
13
13
  import { CortiClient, CortiWebSocketProxyClient } from "@corti/sdk";
14
14
  import { DEFAULT_DICTATION_CONFIG } from "../constants.js";
15
15
  import { errorEvent } from "../utils/events.js";
@@ -29,7 +29,7 @@ export class DictationController {
29
29
  _DictationController_connectionGeneration.set(this, 0);
30
30
  _DictationController_isConnecting.set(this, false);
31
31
  this.mediaRecorderHandler = (data) => {
32
- if (__classPrivateFieldGet(this, _DictationController_socketReady, "f") && this.isConnectionOpen()) {
32
+ if (__classPrivateFieldGet(this, _DictationController_socketReady, "f") && __classPrivateFieldGet(this, _DictationController_instances, "m", _DictationController_isSocketOpen).call(this)) {
33
33
  __classPrivateFieldGet(this, _DictationController_webSocket, "f")?.send(data);
34
34
  __classPrivateFieldGet(this, _DictationController_callbacks, "f")?.onNetworkActivity?.("sent", {
35
35
  size: data.size,
@@ -63,7 +63,7 @@ export class DictationController {
63
63
  return __classPrivateFieldGet(this, _DictationController_connectingPromise, "f");
64
64
  }
65
65
  async pause() {
66
- if (__classPrivateFieldGet(this, _DictationController_socketReady, "f") && this.isConnectionOpen()) {
66
+ if (__classPrivateFieldGet(this, _DictationController_socketReady, "f") && __classPrivateFieldGet(this, _DictationController_instances, "m", _DictationController_isSocketOpen).call(this)) {
67
67
  __classPrivateFieldGet(this, _DictationController_webSocket, "f")?.send(JSON.stringify({ type: "flush" }));
68
68
  __classPrivateFieldGet(this, _DictationController_callbacks, "f")?.onNetworkActivity?.("sent", { type: "flush" });
69
69
  return;
@@ -158,7 +158,7 @@ export class DictationController {
158
158
  __classPrivateFieldSet(this, _DictationController_lastSocketUrl, undefined, "f");
159
159
  __classPrivateFieldSet(this, _DictationController_lastSocketProxy, undefined, "f");
160
160
  if (__classPrivateFieldGet(this, _DictationController_outboundQueue, "f").length > 0) {
161
- this.host.dispatchEvent(errorEvent(`${__classPrivateFieldGet(this, _DictationController_outboundQueue, "f").length} unsent audio message(s) were discarded because the configuration changed before the connection was closed`));
161
+ this.host.dispatchEvent(errorEvent(`${__classPrivateFieldGet(this, _DictationController_outboundQueue, "f").length} unsent message(s) were discarded because the configuration changed before the connection was closed`));
162
162
  }
163
163
  __classPrivateFieldSet(this, _DictationController_outboundQueue, [], "f");
164
164
  }
@@ -255,13 +255,15 @@ _DictationController_cortiClient = new WeakMap(), _DictationController_webSocket
255
255
  callbacks.onClose(event);
256
256
  }
257
257
  });
258
+ }, _DictationController_isSocketOpen = function _DictationController_isSocketOpen() {
259
+ return (__classPrivateFieldGet(this, _DictationController_webSocket, "f") !== null && __classPrivateFieldGet(this, _DictationController_webSocket, "f").readyState === WebSocket.OPEN);
258
260
  }, _DictationController_drain = function _DictationController_drain() {
259
261
  if (!__classPrivateFieldGet(this, _DictationController_socketReady, "f") ||
260
- !this.isConnectionOpen() ||
262
+ !__classPrivateFieldGet(this, _DictationController_instances, "m", _DictationController_isSocketOpen).call(this) ||
261
263
  __classPrivateFieldGet(this, _DictationController_outboundQueue, "f").length === 0) {
262
264
  return;
263
265
  }
264
- while (__classPrivateFieldGet(this, _DictationController_outboundQueue, "f").length > 0 && this.isConnectionOpen()) {
266
+ while (__classPrivateFieldGet(this, _DictationController_outboundQueue, "f").length > 0 && __classPrivateFieldGet(this, _DictationController_instances, "m", _DictationController_isSocketOpen).call(this)) {
265
267
  const item = __classPrivateFieldGet(this, _DictationController_outboundQueue, "f").shift();
266
268
  if (item === undefined) {
267
269
  break;
@@ -1 +1 @@
1
- {"version":3,"file":"dictation-controller.js","sourceRoot":"","sources":["../../src/controllers/dictation-controller.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Corti, CortiClient, CortiWebSocketProxyClient } from \"@corti/sdk\";\nimport type { ReactiveController, ReactiveControllerHost } from \"lit\";\nimport { DEFAULT_DICTATION_CONFIG } from \"../constants.js\";\nimport type { ProxyOptions } from \"../types.js\";\nimport { errorEvent } from \"../utils/events.js\";\n\ntype TranscribeSocket = Awaited<\n ReturnType<CortiClient[\"transcribe\"][\"connect\"]>\n>;\n\ninterface DictationControllerHost extends ReactiveControllerHost {\n dispatchEvent: (event: Event) => void;\n _accessToken?: string;\n _authConfig?: Corti.BearerOptions;\n _region?: string;\n _tenantName?: string;\n _socketUrl?: string;\n _socketProxy?: ProxyOptions;\n _dictationConfig?: Corti.TranscribeConfig;\n}\n\nexport type TranscribeMessage =\n | Corti.TranscribeConfigStatusMessage\n | Corti.TranscribeUsageMessage\n | Corti.TranscribeEndedMessage\n | Corti.TranscribeErrorMessage\n | Corti.TranscribeTranscriptMessage\n | Corti.TranscribeCommandMessage\n | Corti.TranscribeFlushedMessage;\n\ntype OutboundItem =\n | Blob\n | Corti.TranscribeFlushMessage\n | Corti.TranscribeEndMessage;\n\ninterface WebSocketCallbacks {\n onMessage?: (message: TranscribeMessage) => void;\n onError?: (error: Error) => void;\n onClose?: (event: unknown) => void;\n onNetworkActivity?: (direction: \"sent\" | \"received\", data: unknown) => void;\n}\n\nexport class DictationController implements ReactiveController {\n host: DictationControllerHost;\n\n #cortiClient: CortiClient | null = null;\n #webSocket: TranscribeSocket | null = null;\n #closeTimeout?: number;\n #callbacks?: WebSocketCallbacks;\n #lastDictationConfig: Corti.TranscribeConfig | null = null;\n #lastSocketUrl?: string;\n #lastSocketProxy?: ProxyOptions;\n #outboundQueue: OutboundItem[] = [];\n #socketReady = false;\n #connectingPromise: Promise<boolean | \"superseded\"> | null = null;\n #connectionGeneration = 0;\n #isConnecting = false;\n\n constructor(host: DictationControllerHost) {\n this.host = host;\n host.addController(this);\n }\n\n hostDisconnected(): void {\n this.cleanup();\n }\n\n #configHasChanged(): boolean {\n return (\n JSON.stringify(this.host._dictationConfig) !==\n JSON.stringify(this.#lastDictationConfig) ||\n this.host._socketUrl !== this.#lastSocketUrl ||\n JSON.stringify(this.host._socketProxy) !==\n JSON.stringify(this.#lastSocketProxy)\n );\n }\n\n async connect(\n dictationConfig: Corti.TranscribeConfig = DEFAULT_DICTATION_CONFIG,\n callbacks: WebSocketCallbacks = {},\n ): Promise<boolean | \"superseded\"> {\n // If a connection attempt is already in progress with the same config, reuse it\n // to avoid opening multiple sockets when connect() is called concurrently.\n if (this.#connectingPromise && !this.#configHasChanged()) {\n return this.#connectingPromise;\n }\n\n // #isConnecting must be set synchronously before #doConnect runs, because\n // #doConnect calls cleanup() which closes the old socket, firing its \"close\"\n // event synchronously. Handlers that check isConnecting() need to see true\n // at that point — before #connectingPromise is even assigned.\n this.#isConnecting = true;\n this.#connectingPromise = this.#doConnect(\n dictationConfig,\n callbacks,\n ).finally(() => {\n this.#isConnecting = false;\n this.#connectingPromise = null;\n });\n\n return this.#connectingPromise;\n }\n\n async #doConnect(\n dictationConfig: Corti.TranscribeConfig,\n callbacks: WebSocketCallbacks,\n ): Promise<boolean | \"superseded\"> {\n const newConnection = this.#configHasChanged() || !this.isConnectionOpen();\n\n if (newConnection) {\n this.cleanup();\n\n this.#lastDictationConfig = this.host._dictationConfig || null;\n this.#lastSocketUrl = this.host._socketUrl;\n this.#lastSocketProxy = this.host._socketProxy;\n\n const generation = this.#connectionGeneration;\n\n const socket =\n this.host._socketUrl || this.host._socketProxy\n ? await this.#connectProxy(dictationConfig)\n : await this.#connectAuth(dictationConfig);\n\n // If cleanup() was called while we were awaiting (e.g. config changed),\n // the generation counter will have advanced — discard this stale socket.\n if (this.#connectionGeneration !== generation) {\n socket.close();\n return \"superseded\";\n }\n\n this.#webSocket = socket;\n\n this.#callbacks?.onNetworkActivity?.(\"sent\", {\n configuration: dictationConfig,\n type: \"config\",\n });\n }\n\n this.#callbacks = callbacks;\n this.#setupWebSocketHandlers(callbacks);\n\n if (!newConnection && this.isConnectionOpen()) {\n this.#socketReady = true;\n this.#drain();\n }\n\n return newConnection;\n }\n\n async #connectProxy(\n dictationConfig: Corti.TranscribeConfig,\n ): Promise<TranscribeSocket> {\n const proxyOptions = this.host._socketProxy || {\n url: this.host._socketUrl || \"\",\n };\n\n if (!proxyOptions.url) {\n throw new Error(\"Proxy URL is required when using proxy client\");\n }\n\n return await CortiWebSocketProxyClient.transcribe.connect({\n configuration: dictationConfig,\n proxy: proxyOptions,\n });\n }\n\n async #connectAuth(\n dictationConfig: Corti.TranscribeConfig,\n ): Promise<TranscribeSocket> {\n if (!this.host._authConfig && !this.host._accessToken) {\n throw new Error(\n \"Auth configuration or access token is required to connect\",\n );\n }\n\n // Use authConfig if available, otherwise create one from accessToken\n const auth: Corti.BearerOptions = this.host._authConfig || {\n accessToken: this.host._accessToken || \"\",\n refreshAccessToken: () => ({\n accessToken: this.host._accessToken || \"\",\n }),\n };\n\n this.#cortiClient = new CortiClient({\n auth,\n environment: this.host._region,\n tenantName: this.host._tenantName,\n });\n\n return await this.#cortiClient.transcribe.connect({\n configuration: dictationConfig,\n });\n }\n\n #setupWebSocketHandlers(callbacks: WebSocketCallbacks): void {\n if (!this.#webSocket) {\n throw new Error(\"WebSocket not initialized\");\n }\n\n this.#webSocket.on(\"message\", (message: TranscribeMessage) => {\n if (message.type === \"CONFIG_ACCEPTED\") {\n this.#socketReady = true;\n this.#drain();\n }\n\n callbacks.onNetworkActivity?.(\"received\", message);\n\n if (callbacks.onMessage) {\n callbacks.onMessage(message);\n }\n });\n\n this.#webSocket.on(\"error\", (event: Error) => {\n this.#socketReady = false;\n if (callbacks.onError) {\n callbacks.onError(event);\n }\n });\n\n this.#webSocket.on(\"close\", (event: unknown) => {\n this.#socketReady = false;\n if (callbacks.onClose) {\n callbacks.onClose(event);\n }\n });\n }\n\n #drain(): void {\n if (\n !this.#socketReady ||\n !this.isConnectionOpen() ||\n this.#outboundQueue.length === 0\n ) {\n return;\n }\n\n while (this.#outboundQueue.length > 0 && this.isConnectionOpen()) {\n const item = this.#outboundQueue.shift();\n\n if (item === undefined) {\n break;\n }\n\n if (item instanceof Blob) {\n this.#webSocket!.send(item);\n this.#callbacks?.onNetworkActivity?.(\"sent\", {\n size: item.size,\n type: \"audio\",\n });\n continue;\n }\n\n this.#webSocket!.send(JSON.stringify(item));\n this.#callbacks?.onNetworkActivity?.(\"sent\", {\n type: item.type,\n });\n }\n }\n\n mediaRecorderHandler = (data: Blob): void => {\n if (this.#socketReady && this.isConnectionOpen()) {\n this.#webSocket?.send(data);\n this.#callbacks?.onNetworkActivity?.(\"sent\", {\n size: data.size,\n type: \"audio\",\n });\n return;\n }\n\n this.#outboundQueue.push(data);\n };\n\n async pause(): Promise<void> {\n if (this.#socketReady && this.isConnectionOpen()) {\n this.#webSocket?.send(JSON.stringify({ type: \"flush\" }));\n this.#callbacks?.onNetworkActivity?.(\"sent\", { type: \"flush\" });\n return;\n }\n\n this.#outboundQueue.push({ type: \"flush\" });\n }\n\n isConnectionOpen(): boolean {\n return (\n this.#webSocket !== null &&\n (this.#webSocket.readyState === WebSocket.OPEN ||\n this.#webSocket.readyState === WebSocket.CONNECTING)\n );\n }\n\n isConnecting(): boolean {\n return this.#isConnecting;\n }\n\n async waitForConnection(): Promise<void> {\n await this.#connectingPromise;\n }\n\n async closeConnection(onClose?: (event: unknown) => void): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n const oldSocket = this.#webSocket;\n this.#webSocket = null;\n\n if (\n !oldSocket ||\n (oldSocket.readyState !== WebSocket.OPEN &&\n oldSocket.readyState !== WebSocket.CONNECTING)\n ) {\n this.#socketReady = false;\n resolve();\n return;\n }\n\n oldSocket.on(\"close\", (event) => {\n if (this.#closeTimeout) {\n clearTimeout(this.#closeTimeout);\n this.#closeTimeout = undefined;\n }\n\n if (onClose) {\n onClose(event);\n }\n\n resolve();\n });\n\n const wasReady = this.#socketReady;\n this.#socketReady = false;\n\n oldSocket.on(\"message\", (message) => {\n this.#callbacks?.onNetworkActivity?.(\"received\", message);\n\n if (this.#callbacks?.onMessage) {\n this.#callbacks?.onMessage(message);\n }\n\n // closeConnection() may be called before CONFIG_ACCEPTED arrives (e.g.\n // openConnection() followed immediately by closeConnection()). We can't\n // use the outbound queue here because #webSocket is already null, so we\n // send \"end\" directly on oldSocket as soon as config is accepted.\n if (!wasReady && message.type === \"CONFIG_ACCEPTED\") {\n oldSocket.sendEnd({ type: \"end\" });\n this.#callbacks?.onNetworkActivity?.(\"sent\", { type: \"end\" });\n return;\n }\n\n if (message.type === \"ended\") {\n if (this.#closeTimeout) {\n clearTimeout(this.#closeTimeout);\n this.#closeTimeout = undefined;\n }\n\n resolve();\n return;\n }\n });\n\n if (wasReady) {\n oldSocket.sendEnd({ type: \"end\" });\n this.#callbacks?.onNetworkActivity?.(\"sent\", { type: \"end\" });\n }\n\n this.#closeTimeout = window.setTimeout(() => {\n reject(new Error(\"Connection close timeout\"));\n\n if (oldSocket?.readyState === WebSocket.OPEN) {\n oldSocket.close();\n }\n }, 10000);\n });\n }\n\n cleanup(): void {\n // Incrementing generation invalidates any in-flight #doConnect awaits,\n // causing them to discard their socket and return \"superseded\".\n this.#connectionGeneration++;\n this.#socketReady = false;\n\n if (this.#closeTimeout) {\n clearTimeout(this.#closeTimeout);\n this.#closeTimeout = undefined;\n }\n\n if (this.isConnectionOpen()) {\n this.#webSocket?.close();\n }\n\n this.#webSocket = null;\n this.#cortiClient = null;\n this.#lastDictationConfig = null;\n this.#lastSocketUrl = undefined;\n this.#lastSocketProxy = undefined;\n\n if (this.#outboundQueue.length > 0) {\n this.host.dispatchEvent(\n errorEvent(\n `${this.#outboundQueue.length} unsent audio message(s) were discarded because the configuration changed before the connection was closed`,\n ),\n );\n }\n\n this.#outboundQueue = [];\n }\n}\n"]}
1
+ {"version":3,"file":"dictation-controller.js","sourceRoot":"","sources":["../../src/controllers/dictation-controller.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,EAAc,WAAW,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAEhF,OAAO,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAE3D,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAsChD,MAAM,OAAO,mBAAmB;IAgB9B,YAAY,IAA6B;;QAbzC,2CAAmC,IAAI,EAAC;QACxC,yCAAsC,IAAI,EAAC;QAC3C,oDAAuB;QACvB,iDAAgC;QAChC,mDAAsD,IAAI,EAAC;QAC3D,qDAAwB;QACxB,uDAAgC;QAChC,6CAAiC,EAAE,EAAC;QACpC,2CAAe,KAAK,EAAC;QACrB,iDAA6D,IAAI,EAAC;QAClE,oDAAwB,CAAC,EAAC;QAC1B,4CAAgB,KAAK,EAAC;QAiNtB,yBAAoB,GAAG,CAAC,IAAU,EAAQ,EAAE;YAC1C,IAAI,uBAAA,IAAI,wCAAa,IAAI,uBAAA,IAAI,yEAAc,MAAlB,IAAI,CAAgB,EAAE,CAAC;gBAC9C,uBAAA,IAAI,sCAAW,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC5B,uBAAA,IAAI,sCAAW,EAAE,iBAAiB,EAAE,CAAC,MAAM,EAAE;oBAC3C,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,IAAI,EAAE,OAAO;iBACd,CAAC,CAAC;gBACH,OAAO;YACT,CAAC;YAED,uBAAA,IAAI,0CAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,CAAC,CAAC;QAzNA,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;IAED,gBAAgB;QACd,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAYD,KAAK,CAAC,OAAO,CACX,kBAA0C,wBAAwB,EAClE,YAAgC,EAAE;QAElC,gFAAgF;QAChF,2EAA2E;QAC3E,IAAI,uBAAA,IAAI,8CAAmB,IAAI,CAAC,uBAAA,IAAI,6EAAkB,MAAtB,IAAI,CAAoB,EAAE,CAAC;YACzD,OAAO,uBAAA,IAAI,8CAAmB,CAAC;QACjC,CAAC;QAED,0EAA0E;QAC1E,6EAA6E;QAC7E,2EAA2E;QAC3E,8DAA8D;QAC9D,uBAAA,IAAI,qCAAiB,IAAI,MAAA,CAAC;QAC1B,uBAAA,IAAI,0CAAsB,uBAAA,IAAI,sEAAW,MAAf,IAAI,EAC5B,eAAe,EACf,SAAS,CACV,CAAC,OAAO,CAAC,GAAG,EAAE;YACb,uBAAA,IAAI,qCAAiB,KAAK,MAAA,CAAC;YAC3B,uBAAA,IAAI,0CAAsB,IAAI,MAAA,CAAC;QACjC,CAAC,CAAC,MAAA,CAAC;QAEH,OAAO,uBAAA,IAAI,8CAAmB,CAAC;IACjC,CAAC;IAiLD,KAAK,CAAC,KAAK;QACT,IAAI,uBAAA,IAAI,wCAAa,IAAI,uBAAA,IAAI,yEAAc,MAAlB,IAAI,CAAgB,EAAE,CAAC;YAC9C,uBAAA,IAAI,sCAAW,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;YACzD,uBAAA,IAAI,sCAAW,EAAE,iBAAiB,EAAE,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;YAChE,OAAO;QACT,CAAC;QAED,uBAAA,IAAI,0CAAe,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,gBAAgB;QACd,OAAO,CACL,uBAAA,IAAI,sCAAW,KAAK,IAAI;YACxB,CAAC,uBAAA,IAAI,sCAAW,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI;gBAC5C,uBAAA,IAAI,sCAAW,CAAC,UAAU,KAAK,SAAS,CAAC,UAAU,CAAC,CACvD,CAAC;IACJ,CAAC;IAED,YAAY;QACV,OAAO,uBAAA,IAAI,yCAAc,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,iBAAiB;QACrB,MAAM,uBAAA,IAAI,8CAAmB,CAAC;IAChC,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,OAAkC;QACtD,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC1C,MAAM,SAAS,GAAG,uBAAA,IAAI,sCAAW,CAAC;YAClC,uBAAA,IAAI,kCAAc,IAAI,MAAA,CAAC;YAEvB,IACE,CAAC,SAAS;gBACV,CAAC,SAAS,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI;oBACtC,SAAS,CAAC,UAAU,KAAK,SAAS,CAAC,UAAU,CAAC,EAChD,CAAC;gBACD,uBAAA,IAAI,oCAAgB,KAAK,MAAA,CAAC;gBAC1B,OAAO,EAAE,CAAC;gBACV,OAAO;YACT,CAAC;YAED,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;gBAC9B,IAAI,uBAAA,IAAI,yCAAc,EAAE,CAAC;oBACvB,YAAY,CAAC,uBAAA,IAAI,yCAAc,CAAC,CAAC;oBACjC,uBAAA,IAAI,qCAAiB,SAAS,MAAA,CAAC;gBACjC,CAAC;gBAED,IAAI,OAAO,EAAE,CAAC;oBACZ,OAAO,CAAC,KAAK,CAAC,CAAC;gBACjB,CAAC;gBAED,OAAO,EAAE,CAAC;YACZ,CAAC,CAAC,CAAC;YAEH,MAAM,QAAQ,GAAG,uBAAA,IAAI,wCAAa,CAAC;YACnC,uBAAA,IAAI,oCAAgB,KAAK,MAAA,CAAC;YAE1B,SAAS,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE;gBAClC,uBAAA,IAAI,sCAAW,EAAE,iBAAiB,EAAE,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;gBAE1D,IAAI,uBAAA,IAAI,sCAAW,EAAE,SAAS,EAAE,CAAC;oBAC/B,uBAAA,IAAI,sCAAW,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;gBACtC,CAAC;gBAED,uEAAuE;gBACvE,wEAAwE;gBACxE,wEAAwE;gBACxE,kEAAkE;gBAClE,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC,IAAI,KAAK,iBAAiB,EAAE,CAAC;oBACpD,SAAS,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;oBACnC,uBAAA,IAAI,sCAAW,EAAE,iBAAiB,EAAE,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;oBAC9D,OAAO;gBACT,CAAC;gBAED,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;oBAC7B,IAAI,uBAAA,IAAI,yCAAc,EAAE,CAAC;wBACvB,YAAY,CAAC,uBAAA,IAAI,yCAAc,CAAC,CAAC;wBACjC,uBAAA,IAAI,qCAAiB,SAAS,MAAA,CAAC;oBACjC,CAAC;oBAED,OAAO,EAAE,CAAC;oBACV,OAAO;gBACT,CAAC;YACH,CAAC,CAAC,CAAC;YAEH,IAAI,QAAQ,EAAE,CAAC;gBACb,SAAS,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;gBACnC,uBAAA,IAAI,sCAAW,EAAE,iBAAiB,EAAE,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;YAChE,CAAC;YAED,uBAAA,IAAI,qCAAiB,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE;gBAC1C,MAAM,CAAC,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC,CAAC;gBAE9C,IAAI,SAAS,EAAE,UAAU,KAAK,SAAS,CAAC,IAAI,EAAE,CAAC;oBAC7C,SAAS,CAAC,KAAK,EAAE,CAAC;gBACpB,CAAC;YACH,CAAC,EAAE,KAAK,CAAC,MAAA,CAAC;QACZ,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO;;QACL,uEAAuE;QACvE,gEAAgE;QAChE,wEAAA,CAAA,iFAA0B,EAA1B,IAA4B,IAAA,CAAA,MAAA,CAAC;QAC7B,uBAAA,IAAI,oCAAgB,KAAK,MAAA,CAAC;QAE1B,IAAI,uBAAA,IAAI,yCAAc,EAAE,CAAC;YACvB,YAAY,CAAC,uBAAA,IAAI,yCAAc,CAAC,CAAC;YACjC,uBAAA,IAAI,qCAAiB,SAAS,MAAA,CAAC;QACjC,CAAC;QAED,IAAI,IAAI,CAAC,gBAAgB,EAAE,EAAE,CAAC;YAC5B,uBAAA,IAAI,sCAAW,EAAE,KAAK,EAAE,CAAC;QAC3B,CAAC;QAED,uBAAA,IAAI,kCAAc,IAAI,MAAA,CAAC;QACvB,uBAAA,IAAI,oCAAgB,IAAI,MAAA,CAAC;QACzB,uBAAA,IAAI,4CAAwB,IAAI,MAAA,CAAC;QACjC,uBAAA,IAAI,sCAAkB,SAAS,MAAA,CAAC;QAChC,uBAAA,IAAI,wCAAoB,SAAS,MAAA,CAAC;QAElC,IAAI,uBAAA,IAAI,0CAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnC,IAAI,CAAC,IAAI,CAAC,aAAa,CACrB,UAAU,CACR,GAAG,uBAAA,IAAI,0CAAe,CAAC,MAAM,sGAAsG,CACpI,CACF,CAAC;QACJ,CAAC;QAED,uBAAA,IAAI,sCAAkB,EAAE,MAAA,CAAC;IAC3B,CAAC;CACF;;IArVG,OAAO,CACL,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC;QACxC,IAAI,CAAC,SAAS,CAAC,uBAAA,IAAI,gDAAqB,CAAC;QAC3C,IAAI,CAAC,IAAI,CAAC,UAAU,KAAK,uBAAA,IAAI,0CAAe;QAC5C,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC;YACpC,IAAI,CAAC,SAAS,CAAC,uBAAA,IAAI,4CAAiB,CAAC,CACxC,CAAC;AACJ,CAAC,mCA4BD,KAAK,yCACH,eAAuC,EACvC,SAA6B;IAE7B,MAAM,aAAa,GAAG,uBAAA,IAAI,6EAAkB,MAAtB,IAAI,CAAoB,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;IAE3E,IAAI,aAAa,EAAE,CAAC;QAClB,IAAI,CAAC,OAAO,EAAE,CAAC;QAEf,uBAAA,IAAI,4CAAwB,IAAI,CAAC,IAAI,CAAC,gBAAgB,IAAI,IAAI,MAAA,CAAC;QAC/D,uBAAA,IAAI,sCAAkB,IAAI,CAAC,IAAI,CAAC,UAAU,MAAA,CAAC;QAC3C,uBAAA,IAAI,wCAAoB,IAAI,CAAC,IAAI,CAAC,YAAY,MAAA,CAAC;QAE/C,MAAM,UAAU,GAAG,uBAAA,IAAI,iDAAsB,CAAC;QAE9C,MAAM,MAAM,GACV,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,IAAI,CAAC,YAAY;YAC5C,CAAC,CAAC,MAAM,uBAAA,IAAI,yEAAc,MAAlB,IAAI,EAAe,eAAe,CAAC;YAC3C,CAAC,CAAC,MAAM,uBAAA,IAAI,wEAAa,MAAjB,IAAI,EAAc,eAAe,CAAC,CAAC;QAE/C,wEAAwE;QACxE,yEAAyE;QACzE,IAAI,uBAAA,IAAI,iDAAsB,KAAK,UAAU,EAAE,CAAC;YAC9C,MAAM,CAAC,KAAK,EAAE,CAAC;YACf,OAAO,YAAY,CAAC;QACtB,CAAC;QAED,uBAAA,IAAI,kCAAc,MAAM,MAAA,CAAC;QAEzB,uBAAA,IAAI,sCAAW,EAAE,iBAAiB,EAAE,CAAC,MAAM,EAAE;YAC3C,aAAa,EAAE,eAAe;YAC9B,IAAI,EAAE,QAAQ;SACf,CAAC,CAAC;IACL,CAAC;IAED,uBAAA,IAAI,kCAAc,SAAS,MAAA,CAAC;IAC5B,uBAAA,IAAI,mFAAwB,MAA5B,IAAI,EAAyB,SAAS,CAAC,CAAC;IAExC,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,gBAAgB,EAAE,EAAE,CAAC;QAC9C,uBAAA,IAAI,oCAAgB,IAAI,MAAA,CAAC;QACzB,uBAAA,IAAI,kEAAO,MAAX,IAAI,CAAS,CAAC;IAChB,CAAC;IAED,OAAO,aAAa,CAAC;AACvB,CAAC,sCAED,KAAK,4CACH,eAAuC;IAEvC,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI;QAC7C,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,EAAE;KAChC,CAAC;IAEF,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;IACnE,CAAC;IAED,OAAO,MAAM,yBAAyB,CAAC,UAAU,CAAC,OAAO,CAAC;QACxD,aAAa,EAAE,eAAe;QAC9B,KAAK,EAAE,YAAY;KACpB,CAAC,CAAC;AACL,CAAC,qCAED,KAAK,2CACH,eAAuC;IAEvC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;QACtD,MAAM,IAAI,KAAK,CACb,2DAA2D,CAC5D,CAAC;IACJ,CAAC;IAED,qEAAqE;IACrE,MAAM,IAAI,GAAwB,IAAI,CAAC,IAAI,CAAC,WAAW,IAAI;QACzD,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,EAAE;QACzC,kBAAkB,EAAE,GAAG,EAAE,CAAC,CAAC;YACzB,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,EAAE;SAC1C,CAAC;KACH,CAAC;IAEF,uBAAA,IAAI,oCAAgB,IAAI,WAAW,CAAC;QAClC,IAAI;QACJ,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO;QAC9B,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW;KAClC,CAAC,MAAA,CAAC;IAEH,OAAO,MAAM,uBAAA,IAAI,wCAAa,CAAC,UAAU,CAAC,OAAO,CAAC;QAChD,aAAa,EAAE,eAAe;KAC/B,CAAC,CAAC;AACL,CAAC,qGAEuB,SAA6B;IACnD,IAAI,CAAC,uBAAA,IAAI,sCAAW,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAC/C,CAAC;IAED,uBAAA,IAAI,sCAAW,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,OAA0B,EAAE,EAAE;QAC3D,IAAI,OAAO,CAAC,IAAI,KAAK,iBAAiB,EAAE,CAAC;YACvC,uBAAA,IAAI,oCAAgB,IAAI,MAAA,CAAC;YACzB,uBAAA,IAAI,kEAAO,MAAX,IAAI,CAAS,CAAC;QAChB,CAAC;QAED,SAAS,CAAC,iBAAiB,EAAE,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAEnD,IAAI,SAAS,CAAC,SAAS,EAAE,CAAC;YACxB,SAAS,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,uBAAA,IAAI,sCAAW,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAY,EAAE,EAAE;QAC3C,uBAAA,IAAI,oCAAgB,KAAK,MAAA,CAAC;QAC1B,IAAI,SAAS,CAAC,OAAO,EAAE,CAAC;YACtB,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,uBAAA,IAAI,sCAAW,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAc,EAAE,EAAE;QAC7C,uBAAA,IAAI,oCAAgB,KAAK,MAAA,CAAC;QAC1B,IAAI,SAAS,CAAC,OAAO,EAAE,CAAC;YACtB,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;IAGC,OAAO,CACL,uBAAA,IAAI,sCAAW,KAAK,IAAI,IAAI,uBAAA,IAAI,sCAAW,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI,CAC1E,CAAC;AACJ,CAAC;IAGC,IACE,CAAC,uBAAA,IAAI,wCAAa;QAClB,CAAC,uBAAA,IAAI,yEAAc,MAAlB,IAAI,CAAgB;QACrB,uBAAA,IAAI,0CAAe,CAAC,MAAM,KAAK,CAAC,EAChC,CAAC;QACD,OAAO;IACT,CAAC;IAED,OAAO,uBAAA,IAAI,0CAAe,CAAC,MAAM,GAAG,CAAC,IAAI,uBAAA,IAAI,yEAAc,MAAlB,IAAI,CAAgB,EAAE,CAAC;QAC9D,MAAM,IAAI,GAAG,uBAAA,IAAI,0CAAe,CAAC,KAAK,EAAE,CAAC;QAEzC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,MAAM;QACR,CAAC;QAED,IAAI,IAAI,YAAY,IAAI,EAAE,CAAC;YACzB,uBAAA,IAAI,sCAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC5B,uBAAA,IAAI,sCAAW,EAAE,iBAAiB,EAAE,CAAC,MAAM,EAAE;gBAC3C,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,IAAI,EAAE,OAAO;aACd,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QAED,uBAAA,IAAI,sCAAY,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;QAC5C,uBAAA,IAAI,sCAAW,EAAE,iBAAiB,EAAE,CAAC,MAAM,EAAE;YAC3C,IAAI,EAAE,IAAI,CAAC,IAAI;SAChB,CAAC,CAAC;IACL,CAAC;AACH,CAAC","sourcesContent":["import { type Corti, CortiClient, CortiWebSocketProxyClient } from \"@corti/sdk\";\nimport type { ReactiveController, ReactiveControllerHost } from \"lit\";\nimport { DEFAULT_DICTATION_CONFIG } from \"../constants.js\";\nimport type { ProxyOptions } from \"../types.js\";\nimport { errorEvent } from \"../utils/events.js\";\n\ntype TranscribeSocket = Awaited<\n ReturnType<CortiClient[\"transcribe\"][\"connect\"]>\n>;\n\ninterface DictationControllerHost extends ReactiveControllerHost {\n dispatchEvent: (event: Event) => void;\n _accessToken?: string;\n _authConfig?: Corti.BearerOptions;\n _region?: string;\n _tenantName?: string;\n _socketUrl?: string;\n _socketProxy?: ProxyOptions;\n _dictationConfig?: Corti.TranscribeConfig;\n}\n\nexport type TranscribeMessage =\n | Corti.TranscribeConfigStatusMessage\n | Corti.TranscribeUsageMessage\n | Corti.TranscribeEndedMessage\n | Corti.TranscribeErrorMessage\n | Corti.TranscribeTranscriptMessage\n | Corti.TranscribeCommandMessage\n | Corti.TranscribeFlushedMessage;\n\ntype OutboundItem =\n | Blob\n | Corti.TranscribeFlushMessage\n | Corti.TranscribeEndMessage;\n\ninterface WebSocketCallbacks {\n onMessage?: (message: TranscribeMessage) => void;\n onError?: (error: Error) => void;\n onClose?: (event: unknown) => void;\n onNetworkActivity?: (direction: \"sent\" | \"received\", data: unknown) => void;\n}\n\nexport class DictationController implements ReactiveController {\n host: DictationControllerHost;\n\n #cortiClient: CortiClient | null = null;\n #webSocket: TranscribeSocket | null = null;\n #closeTimeout?: number;\n #callbacks?: WebSocketCallbacks;\n #lastDictationConfig: Corti.TranscribeConfig | null = null;\n #lastSocketUrl?: string;\n #lastSocketProxy?: ProxyOptions;\n #outboundQueue: OutboundItem[] = [];\n #socketReady = false;\n #connectingPromise: Promise<boolean | \"superseded\"> | null = null;\n #connectionGeneration = 0;\n #isConnecting = false;\n\n constructor(host: DictationControllerHost) {\n this.host = host;\n host.addController(this);\n }\n\n hostDisconnected(): void {\n this.cleanup();\n }\n\n #configHasChanged(): boolean {\n return (\n JSON.stringify(this.host._dictationConfig) !==\n JSON.stringify(this.#lastDictationConfig) ||\n this.host._socketUrl !== this.#lastSocketUrl ||\n JSON.stringify(this.host._socketProxy) !==\n JSON.stringify(this.#lastSocketProxy)\n );\n }\n\n async connect(\n dictationConfig: Corti.TranscribeConfig = DEFAULT_DICTATION_CONFIG,\n callbacks: WebSocketCallbacks = {},\n ): Promise<boolean | \"superseded\"> {\n // If a connection attempt is already in progress with the same config, reuse it\n // to avoid opening multiple sockets when connect() is called concurrently.\n if (this.#connectingPromise && !this.#configHasChanged()) {\n return this.#connectingPromise;\n }\n\n // #isConnecting must be set synchronously before #doConnect runs, because\n // #doConnect calls cleanup() which closes the old socket, firing its \"close\"\n // event synchronously. Handlers that check isConnecting() need to see true\n // at that point — before #connectingPromise is even assigned.\n this.#isConnecting = true;\n this.#connectingPromise = this.#doConnect(\n dictationConfig,\n callbacks,\n ).finally(() => {\n this.#isConnecting = false;\n this.#connectingPromise = null;\n });\n\n return this.#connectingPromise;\n }\n\n async #doConnect(\n dictationConfig: Corti.TranscribeConfig,\n callbacks: WebSocketCallbacks,\n ): Promise<boolean | \"superseded\"> {\n const newConnection = this.#configHasChanged() || !this.isConnectionOpen();\n\n if (newConnection) {\n this.cleanup();\n\n this.#lastDictationConfig = this.host._dictationConfig || null;\n this.#lastSocketUrl = this.host._socketUrl;\n this.#lastSocketProxy = this.host._socketProxy;\n\n const generation = this.#connectionGeneration;\n\n const socket =\n this.host._socketUrl || this.host._socketProxy\n ? await this.#connectProxy(dictationConfig)\n : await this.#connectAuth(dictationConfig);\n\n // If cleanup() was called while we were awaiting (e.g. config changed),\n // the generation counter will have advanced — discard this stale socket.\n if (this.#connectionGeneration !== generation) {\n socket.close();\n return \"superseded\";\n }\n\n this.#webSocket = socket;\n\n this.#callbacks?.onNetworkActivity?.(\"sent\", {\n configuration: dictationConfig,\n type: \"config\",\n });\n }\n\n this.#callbacks = callbacks;\n this.#setupWebSocketHandlers(callbacks);\n\n if (!newConnection && this.isConnectionOpen()) {\n this.#socketReady = true;\n this.#drain();\n }\n\n return newConnection;\n }\n\n async #connectProxy(\n dictationConfig: Corti.TranscribeConfig,\n ): Promise<TranscribeSocket> {\n const proxyOptions = this.host._socketProxy || {\n url: this.host._socketUrl || \"\",\n };\n\n if (!proxyOptions.url) {\n throw new Error(\"Proxy URL is required when using proxy client\");\n }\n\n return await CortiWebSocketProxyClient.transcribe.connect({\n configuration: dictationConfig,\n proxy: proxyOptions,\n });\n }\n\n async #connectAuth(\n dictationConfig: Corti.TranscribeConfig,\n ): Promise<TranscribeSocket> {\n if (!this.host._authConfig && !this.host._accessToken) {\n throw new Error(\n \"Auth configuration or access token is required to connect\",\n );\n }\n\n // Use authConfig if available, otherwise create one from accessToken\n const auth: Corti.BearerOptions = this.host._authConfig || {\n accessToken: this.host._accessToken || \"\",\n refreshAccessToken: () => ({\n accessToken: this.host._accessToken || \"\",\n }),\n };\n\n this.#cortiClient = new CortiClient({\n auth,\n environment: this.host._region,\n tenantName: this.host._tenantName,\n });\n\n return await this.#cortiClient.transcribe.connect({\n configuration: dictationConfig,\n });\n }\n\n #setupWebSocketHandlers(callbacks: WebSocketCallbacks): void {\n if (!this.#webSocket) {\n throw new Error(\"WebSocket not initialized\");\n }\n\n this.#webSocket.on(\"message\", (message: TranscribeMessage) => {\n if (message.type === \"CONFIG_ACCEPTED\") {\n this.#socketReady = true;\n this.#drain();\n }\n\n callbacks.onNetworkActivity?.(\"received\", message);\n\n if (callbacks.onMessage) {\n callbacks.onMessage(message);\n }\n });\n\n this.#webSocket.on(\"error\", (event: Error) => {\n this.#socketReady = false;\n if (callbacks.onError) {\n callbacks.onError(event);\n }\n });\n\n this.#webSocket.on(\"close\", (event: unknown) => {\n this.#socketReady = false;\n if (callbacks.onClose) {\n callbacks.onClose(event);\n }\n });\n }\n\n #isSocketOpen(): boolean {\n return (\n this.#webSocket !== null && this.#webSocket.readyState === WebSocket.OPEN\n );\n }\n\n #drain(): void {\n if (\n !this.#socketReady ||\n !this.#isSocketOpen() ||\n this.#outboundQueue.length === 0\n ) {\n return;\n }\n\n while (this.#outboundQueue.length > 0 && this.#isSocketOpen()) {\n const item = this.#outboundQueue.shift();\n\n if (item === undefined) {\n break;\n }\n\n if (item instanceof Blob) {\n this.#webSocket!.send(item);\n this.#callbacks?.onNetworkActivity?.(\"sent\", {\n size: item.size,\n type: \"audio\",\n });\n continue;\n }\n\n this.#webSocket!.send(JSON.stringify(item));\n this.#callbacks?.onNetworkActivity?.(\"sent\", {\n type: item.type,\n });\n }\n }\n\n mediaRecorderHandler = (data: Blob): void => {\n if (this.#socketReady && this.#isSocketOpen()) {\n this.#webSocket?.send(data);\n this.#callbacks?.onNetworkActivity?.(\"sent\", {\n size: data.size,\n type: \"audio\",\n });\n return;\n }\n\n this.#outboundQueue.push(data);\n };\n\n async pause(): Promise<void> {\n if (this.#socketReady && this.#isSocketOpen()) {\n this.#webSocket?.send(JSON.stringify({ type: \"flush\" }));\n this.#callbacks?.onNetworkActivity?.(\"sent\", { type: \"flush\" });\n return;\n }\n\n this.#outboundQueue.push({ type: \"flush\" });\n }\n\n isConnectionOpen(): boolean {\n return (\n this.#webSocket !== null &&\n (this.#webSocket.readyState === WebSocket.OPEN ||\n this.#webSocket.readyState === WebSocket.CONNECTING)\n );\n }\n\n isConnecting(): boolean {\n return this.#isConnecting;\n }\n\n async waitForConnection(): Promise<void> {\n await this.#connectingPromise;\n }\n\n async closeConnection(onClose?: (event: unknown) => void): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n const oldSocket = this.#webSocket;\n this.#webSocket = null;\n\n if (\n !oldSocket ||\n (oldSocket.readyState !== WebSocket.OPEN &&\n oldSocket.readyState !== WebSocket.CONNECTING)\n ) {\n this.#socketReady = false;\n resolve();\n return;\n }\n\n oldSocket.on(\"close\", (event) => {\n if (this.#closeTimeout) {\n clearTimeout(this.#closeTimeout);\n this.#closeTimeout = undefined;\n }\n\n if (onClose) {\n onClose(event);\n }\n\n resolve();\n });\n\n const wasReady = this.#socketReady;\n this.#socketReady = false;\n\n oldSocket.on(\"message\", (message) => {\n this.#callbacks?.onNetworkActivity?.(\"received\", message);\n\n if (this.#callbacks?.onMessage) {\n this.#callbacks?.onMessage(message);\n }\n\n // closeConnection() may be called before CONFIG_ACCEPTED arrives (e.g.\n // openConnection() followed immediately by closeConnection()). We can't\n // use the outbound queue here because #webSocket is already null, so we\n // send \"end\" directly on oldSocket as soon as config is accepted.\n if (!wasReady && message.type === \"CONFIG_ACCEPTED\") {\n oldSocket.sendEnd({ type: \"end\" });\n this.#callbacks?.onNetworkActivity?.(\"sent\", { type: \"end\" });\n return;\n }\n\n if (message.type === \"ended\") {\n if (this.#closeTimeout) {\n clearTimeout(this.#closeTimeout);\n this.#closeTimeout = undefined;\n }\n\n resolve();\n return;\n }\n });\n\n if (wasReady) {\n oldSocket.sendEnd({ type: \"end\" });\n this.#callbacks?.onNetworkActivity?.(\"sent\", { type: \"end\" });\n }\n\n this.#closeTimeout = window.setTimeout(() => {\n reject(new Error(\"Connection close timeout\"));\n\n if (oldSocket?.readyState === WebSocket.OPEN) {\n oldSocket.close();\n }\n }, 10000);\n });\n }\n\n cleanup(): void {\n // Incrementing generation invalidates any in-flight #doConnect awaits,\n // causing them to discard their socket and return \"superseded\".\n this.#connectionGeneration++;\n this.#socketReady = false;\n\n if (this.#closeTimeout) {\n clearTimeout(this.#closeTimeout);\n this.#closeTimeout = undefined;\n }\n\n if (this.isConnectionOpen()) {\n this.#webSocket?.close();\n }\n\n this.#webSocket = null;\n this.#cortiClient = null;\n this.#lastDictationConfig = null;\n this.#lastSocketUrl = undefined;\n this.#lastSocketProxy = undefined;\n\n if (this.#outboundQueue.length > 0) {\n this.host.dispatchEvent(\n errorEvent(\n `${this.#outboundQueue.length} unsent message(s) were discarded because the configuration changed before the connection was closed`,\n ),\n );\n }\n\n this.#outboundQueue = [];\n }\n}\n"]}