@speechos/core 0.2.4 → 0.2.6

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/index.d.cts CHANGED
@@ -12,5 +12,5 @@ export { livekit, Deferred } from "./livekit.js";
12
12
  export { websocket } from "./websocket.js";
13
13
  export { getBackend } from "./backend.js";
14
14
  export type { VoiceBackend } from "./backend.js";
15
- export type { SpeechOSCoreConfig, SpeechOSState, SpeechOSAction, SpeechOSEventMap, StateChangeCallback, UnsubscribeFn, RecordingState, LiveKitTokenResponse, ServerErrorMessage, ErrorSource, UserVocabularyData, CommandArgument, CommandDefinition, CommandResult, SessionSettings, VoiceSessionOptions, } from "./types.js";
15
+ export type { SpeechOSCoreConfig, SpeechOSState, SpeechOSAction, SpeechOSEventMap, StateChangeCallback, UnsubscribeFn, RecordingState, LiveKitTokenResponse, ServerErrorMessage, ErrorSource, UserVocabularyData, CommandArgument, CommandDefinition, CommandResult, SessionSettings, VoiceSessionOptions, WebSocketLike, WebSocketFactory, } from "./types.js";
16
16
  export declare const VERSION = "0.1.0";
package/dist/index.d.ts CHANGED
@@ -12,5 +12,5 @@ export { livekit, Deferred } from "./livekit.js";
12
12
  export { websocket } from "./websocket.js";
13
13
  export { getBackend } from "./backend.js";
14
14
  export type { VoiceBackend } from "./backend.js";
15
- export type { SpeechOSCoreConfig, SpeechOSState, SpeechOSAction, SpeechOSEventMap, StateChangeCallback, UnsubscribeFn, RecordingState, LiveKitTokenResponse, ServerErrorMessage, ErrorSource, UserVocabularyData, CommandArgument, CommandDefinition, CommandResult, SessionSettings, VoiceSessionOptions, } from "./types.js";
15
+ export type { SpeechOSCoreConfig, SpeechOSState, SpeechOSAction, SpeechOSEventMap, StateChangeCallback, UnsubscribeFn, RecordingState, LiveKitTokenResponse, ServerErrorMessage, ErrorSource, UserVocabularyData, CommandArgument, CommandDefinition, CommandResult, SessionSettings, VoiceSessionOptions, WebSocketLike, WebSocketFactory, } from "./types.js";
16
16
  export declare const VERSION = "0.1.0";
package/dist/index.js CHANGED
@@ -12,7 +12,8 @@ const defaultConfig = {
12
12
  apiKey: "",
13
13
  userId: "",
14
14
  host: DEFAULT_HOST,
15
- debug: false
15
+ debug: false,
16
+ webSocketFactory: void 0
16
17
  };
17
18
  /**
18
19
  * Validates and merges user config with defaults
@@ -25,7 +26,8 @@ function validateConfig(userConfig) {
25
26
  apiKey: userConfig.apiKey,
26
27
  userId: userConfig.userId ?? defaultConfig.userId,
27
28
  host: userConfig.host ?? defaultConfig.host,
28
- debug: userConfig.debug ?? defaultConfig.debug
29
+ debug: userConfig.debug ?? defaultConfig.debug,
30
+ webSocketFactory: userConfig.webSocketFactory ?? defaultConfig.webSocketFactory
29
31
  };
30
32
  }
31
33
  /**
@@ -1395,6 +1397,8 @@ const MESSAGE_TYPE_EDITED_TEXT = "edited_text";
1395
1397
  const MESSAGE_TYPE_EXECUTE_COMMAND = "execute_command";
1396
1398
  const MESSAGE_TYPE_COMMAND_RESULT = "command_result";
1397
1399
  const MESSAGE_TYPE_ERROR = "error";
1400
+ const WS_OPEN = 1;
1401
+ const WS_CLOSED = 3;
1398
1402
  /**
1399
1403
  * Response timeout in milliseconds.
1400
1404
  */
@@ -1513,7 +1517,10 @@ var WebSocketManager = class {
1513
1517
  state.setMicEnabled(true);
1514
1518
  const wsUrl = this.getWebSocketUrl();
1515
1519
  if (config.debug) console.log("[SpeechOS] Connecting to WebSocket:", wsUrl);
1516
- this.ws = new WebSocket(wsUrl);
1520
+ this.pendingAuth = new Deferred$1();
1521
+ this.pendingAuth.setTimeout(RESPONSE_TIMEOUT_MS, "Connection timed out", "connection_timeout", "connection");
1522
+ const factory = config.webSocketFactory ?? ((url) => new WebSocket(url));
1523
+ this.ws = factory(wsUrl);
1517
1524
  this.ws.onopen = () => {
1518
1525
  if (config.debug) console.log("[SpeechOS] WebSocket connected, authenticating...");
1519
1526
  this.authenticate();
@@ -1522,19 +1529,21 @@ var WebSocketManager = class {
1522
1529
  this.handleMessage(event.data);
1523
1530
  };
1524
1531
  this.ws.onerror = (event) => {
1525
- console.error("[SpeechOS] WebSocket error:", event);
1532
+ const isConnectionBlocked = this.ws?.readyState === WS_CLOSED;
1533
+ const errorCode = isConnectionBlocked ? "connection_blocked" : "websocket_error";
1534
+ const errorMessage = isConnectionBlocked ? "This site's CSP blocks the extension. Try embedded mode instead." : "WebSocket connection error";
1535
+ console.error("[SpeechOS] WebSocket error:", event, { isConnectionBlocked });
1526
1536
  events.emit("error", {
1527
- code: "websocket_error",
1528
- message: "WebSocket connection error",
1537
+ code: errorCode,
1538
+ message: errorMessage,
1529
1539
  source: "connection"
1530
1540
  });
1541
+ if (this.pendingAuth) this.pendingAuth.reject(new Error(errorMessage));
1531
1542
  };
1532
1543
  this.ws.onclose = (event) => {
1533
1544
  if (config.debug) console.log("[SpeechOS] WebSocket closed:", event.code, event.reason);
1534
1545
  state.setConnected(false);
1535
1546
  };
1536
- this.pendingAuth = new Deferred$1();
1537
- this.pendingAuth.setTimeout(RESPONSE_TIMEOUT_MS, "Connection timed out", "connection_timeout", "connection");
1538
1547
  await this.pendingAuth.promise;
1539
1548
  this.pendingAuth = null;
1540
1549
  if (this.audioCapture) this.audioCapture.setReady();
@@ -1583,7 +1592,7 @@ var WebSocketManager = class {
1583
1592
  * Actually send the audio chunk (async operation).
1584
1593
  */
1585
1594
  async doSendAudioChunk(chunk) {
1586
- if (this.ws && this.ws.readyState === WebSocket.OPEN) {
1595
+ if (this.ws && this.ws.readyState === WS_OPEN) {
1587
1596
  const arrayBuffer = await chunk.arrayBuffer();
1588
1597
  this.ws.send(arrayBuffer);
1589
1598
  }
@@ -1629,6 +1638,10 @@ var WebSocketManager = class {
1629
1638
  }
1630
1639
  handleIntermediateTranscription(message) {
1631
1640
  const config = getConfig();
1641
+ events.emit("transcription:interim", {
1642
+ transcript: message.transcript,
1643
+ isFinal: message.is_final
1644
+ });
1632
1645
  if (config.debug) console.log("[SpeechOS] Intermediate transcription:", message.transcript, "final:", message.is_final);
1633
1646
  }
1634
1647
  handleFinalTranscript(message) {
@@ -1765,7 +1778,7 @@ var WebSocketManager = class {
1765
1778
  * the transcript. Uses the same pattern as LiveKit's ReadableStream approach.
1766
1779
  */
1767
1780
  async waitForBufferDrain() {
1768
- if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return;
1781
+ if (!this.ws || this.ws.readyState !== WS_OPEN) return;
1769
1782
  const config = getConfig();
1770
1783
  const startTime = Date.now();
1771
1784
  while (this.ws.bufferedAmount > 0) {
@@ -1781,7 +1794,7 @@ var WebSocketManager = class {
1781
1794
  * Send a JSON message over the WebSocket.
1782
1795
  */
1783
1796
  sendMessage(message) {
1784
- if (this.ws && this.ws.readyState === WebSocket.OPEN) this.ws.send(JSON.stringify(message));
1797
+ if (this.ws && this.ws.readyState === WS_OPEN) this.ws.send(JSON.stringify(message));
1785
1798
  }
1786
1799
  /**
1787
1800
  * Disconnect from the WebSocket.
@@ -1823,7 +1836,7 @@ var WebSocketManager = class {
1823
1836
  * Check if connected to WebSocket.
1824
1837
  */
1825
1838
  isConnected() {
1826
- return this.ws !== null && this.ws.readyState === WebSocket.OPEN;
1839
+ return this.ws !== null && this.ws.readyState === WS_OPEN;
1827
1840
  }
1828
1841
  /**
1829
1842
  * Get the last input text from a command result.