@glassly/engine 0.3.2-beta.572 → 0.3.2-beta.597

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.
Files changed (146) hide show
  1. package/README.md +1 -1
  2. package/build/engine.d.ts +15 -1
  3. package/build/engine.d.ts.map +1 -1
  4. package/build/engine.js +7 -3
  5. package/build/engine.js.map +1 -1
  6. package/build/facades/dev.d.ts +2 -2
  7. package/build/facades/dev.d.ts.map +1 -1
  8. package/build/facades/dev.js +2 -2
  9. package/build/facades/dev.js.map +1 -1
  10. package/build/facades/glasses.d.ts +20 -0
  11. package/build/facades/glasses.d.ts.map +1 -1
  12. package/build/facades/glasses.js +21 -0
  13. package/build/facades/glasses.js.map +1 -1
  14. package/build/facades/pairing.js +1 -1
  15. package/build/facades/pairing.js.map +1 -1
  16. package/build/facades/reports.js +2 -2
  17. package/build/facades/reports.js.map +1 -1
  18. package/build/facades/session.d.ts +1 -1
  19. package/build/facades/session.js +2 -2
  20. package/build/facades/session.js.map +1 -1
  21. package/build/generated/releaseMetadata.js +3 -3
  22. package/build/generated/releaseMetadata.js.map +1 -1
  23. package/build/index.d.ts +3 -1
  24. package/build/index.d.ts.map +1 -1
  25. package/build/index.js +3 -1
  26. package/build/index.js.map +1 -1
  27. package/build/runtime/bootstrap.d.ts +2 -2
  28. package/build/runtime/bootstrap.d.ts.map +1 -1
  29. package/build/runtime/bootstrap.js.map +1 -1
  30. package/build/services/CloudAudioSubscriptionSync.d.ts +2 -2
  31. package/build/services/CloudAudioSubscriptionSync.js +2 -2
  32. package/build/services/CloudAudioSubscriptionSync.js.map +1 -1
  33. package/build/services/CloudClientService.d.ts +2 -2
  34. package/build/services/CloudClientService.d.ts.map +1 -1
  35. package/build/services/CloudClientService.js +4 -4
  36. package/build/services/CloudClientService.js.map +1 -1
  37. package/build/services/CloudTranscriptE2EMetrics.d.ts +2 -2
  38. package/build/services/CloudTranscriptE2EMetrics.d.ts.map +1 -1
  39. package/build/services/CloudTranscriptE2EMetrics.js +3 -3
  40. package/build/services/CloudTranscriptE2EMetrics.js.map +1 -1
  41. package/build/services/DeviceEventRouter.d.ts.map +1 -1
  42. package/build/services/DeviceEventRouter.js +5 -0
  43. package/build/services/DeviceEventRouter.js.map +1 -1
  44. package/build/services/GestureDotsService.d.ts +9 -9
  45. package/build/services/GestureDotsService.d.ts.map +1 -1
  46. package/build/services/GestureDotsService.js +75 -50
  47. package/build/services/GestureDotsService.js.map +1 -1
  48. package/build/services/GlassesTouchInput.d.ts +1 -1
  49. package/build/services/GlassesTouchInput.d.ts.map +1 -1
  50. package/build/services/GlassesTouchInput.js +7 -4
  51. package/build/services/GlassesTouchInput.js.map +1 -1
  52. package/build/services/LocalMiniappRuntime.d.ts +1 -1
  53. package/build/services/LocalMiniappRuntime.d.ts.map +1 -1
  54. package/build/services/LocalMiniappRuntime.js +26 -7
  55. package/build/services/LocalMiniappRuntime.js.map +1 -1
  56. package/build/services/LocalSttFallbackCoordinator.d.ts +5 -2
  57. package/build/services/LocalSttFallbackCoordinator.d.ts.map +1 -1
  58. package/build/services/LocalSttFallbackCoordinator.js +7 -3
  59. package/build/services/LocalSttFallbackCoordinator.js.map +1 -1
  60. package/build/services/PhonePhotoCoordinator.d.ts +1 -1
  61. package/build/services/PhonePhotoCoordinator.js +4 -4
  62. package/build/services/PhonePhotoCoordinator.js.map +1 -1
  63. package/build/services/PhoneStreamCoordinator.d.ts +1 -1
  64. package/build/services/PhoneStreamCoordinator.js +1 -1
  65. package/build/services/PhoneStreamCoordinator.js.map +1 -1
  66. package/build/services/SupportProfileSync.d.ts +1 -1
  67. package/build/services/SupportProfileSync.js +2 -2
  68. package/build/services/SupportProfileSync.js.map +1 -1
  69. package/build/services/TranscriptionRouting.d.ts +6 -1
  70. package/build/services/TranscriptionRouting.d.ts.map +1 -1
  71. package/build/services/TranscriptionRouting.js +7 -3
  72. package/build/services/TranscriptionRouting.js.map +1 -1
  73. package/build/services/cloudStreamApi.d.ts +2 -2
  74. package/build/services/cloudStreamApi.js +2 -2
  75. package/build/services/cloudStreamApi.js.map +1 -1
  76. package/build/services/gestureDotGlyphs.d.ts +1 -1
  77. package/build/services/gestureDotGlyphs.d.ts.map +1 -1
  78. package/build/services/gestureDotGlyphs.js +5 -0
  79. package/build/services/gestureDotGlyphs.js.map +1 -1
  80. package/build/services/neuralBand/MetaAuth.d.ts +31 -0
  81. package/build/services/neuralBand/MetaAuth.d.ts.map +1 -0
  82. package/build/services/neuralBand/MetaAuth.js +161 -0
  83. package/build/services/neuralBand/MetaAuth.js.map +1 -0
  84. package/build/services/neuralBand/NeuralBandInput.d.ts +50 -0
  85. package/build/services/neuralBand/NeuralBandInput.d.ts.map +1 -0
  86. package/build/services/neuralBand/NeuralBandInput.js +114 -0
  87. package/build/services/neuralBand/NeuralBandInput.js.map +1 -0
  88. package/build/services/neuralBand/NeuralBandSettingsSync.d.ts +3 -0
  89. package/build/services/neuralBand/NeuralBandSettingsSync.d.ts.map +1 -0
  90. package/build/services/neuralBand/NeuralBandSettingsSync.js +52 -0
  91. package/build/services/neuralBand/NeuralBandSettingsSync.js.map +1 -0
  92. package/build/services/neuralBand/sha256.d.ts +7 -0
  93. package/build/services/neuralBand/sha256.d.ts.map +1 -0
  94. package/build/services/neuralBand/sha256.js +68 -0
  95. package/build/services/neuralBand/sha256.js.map +1 -0
  96. package/build/services/soniox/SonioxRealtimeClient.d.ts +2 -2
  97. package/build/services/soniox/SonioxRealtimeClient.js +2 -2
  98. package/build/services/soniox/SonioxRealtimeClient.js.map +1 -1
  99. package/build/services/soniox/SonioxTokenAssembler.d.ts +1 -1
  100. package/build/services/soniox/SonioxTokenAssembler.js +1 -1
  101. package/build/services/soniox/SonioxTokenAssembler.js.map +1 -1
  102. package/build/stores/cloudClientStatus.js +1 -1
  103. package/build/stores/cloudClientStatus.js.map +1 -1
  104. package/build/stores/settings.d.ts.map +1 -1
  105. package/build/stores/settings.js +25 -7
  106. package/build/stores/settings.js.map +1 -1
  107. package/build/types/enums.d.ts +2 -1
  108. package/build/types/enums.d.ts.map +1 -1
  109. package/build/types/enums.js +1 -0
  110. package/build/types/enums.js.map +1 -1
  111. package/build/utils/cloudClient/cloudSecureStore.js +2 -2
  112. package/build/utils/cloudClient/cloudSecureStore.js.map +1 -1
  113. package/package.json +7 -7
  114. package/src/engine.ts +7 -3
  115. package/src/facades/dev.ts +2 -2
  116. package/src/facades/glasses.ts +27 -0
  117. package/src/facades/pairing.ts +1 -1
  118. package/src/facades/reports.ts +2 -2
  119. package/src/facades/session.ts +2 -2
  120. package/src/generated/releaseMetadata.ts +3 -3
  121. package/src/index.ts +15 -1
  122. package/src/runtime/bootstrap.ts +2 -2
  123. package/src/services/CloudAudioSubscriptionSync.ts +2 -2
  124. package/src/services/CloudClientService.ts +4 -4
  125. package/src/services/CloudTranscriptE2EMetrics.ts +3 -3
  126. package/src/services/DeviceEventRouter.ts +5 -0
  127. package/src/services/GestureDotsService.ts +72 -49
  128. package/src/services/GlassesTouchInput.ts +13 -5
  129. package/src/services/LocalMiniappRuntime.ts +46 -24
  130. package/src/services/LocalSttFallbackCoordinator.ts +18 -4
  131. package/src/services/PhonePhotoCoordinator.ts +4 -4
  132. package/src/services/PhoneStreamCoordinator.ts +1 -1
  133. package/src/services/SupportProfileSync.ts +2 -2
  134. package/src/services/TranscriptionRouting.ts +12 -4
  135. package/src/services/cloudStreamApi.ts +3 -3
  136. package/src/services/gestureDotGlyphs.ts +6 -1
  137. package/src/services/neuralBand/MetaAuth.ts +192 -0
  138. package/src/services/neuralBand/NeuralBandInput.ts +148 -0
  139. package/src/services/neuralBand/NeuralBandSettingsSync.ts +63 -0
  140. package/src/services/neuralBand/sha256.ts +70 -0
  141. package/src/services/soniox/SonioxRealtimeClient.ts +2 -2
  142. package/src/services/soniox/SonioxTokenAssembler.ts +1 -1
  143. package/src/stores/cloudClientStatus.ts +1 -1
  144. package/src/stores/settings.ts +25 -7
  145. package/src/types/enums.ts +1 -0
  146. package/src/utils/cloudClient/cloudSecureStore.ts +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"SonioxRealtimeClient.js","sourceRoot":"","sources":["../../../src/services/soniox/SonioxRealtimeClient.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * SonioxRealtimeClient\n *\n * Minimal React Native WebSocket client for Soniox realtime STT\n * (wss://stt-rt.soniox.com/transcribe-websocket). Used by SonioxDirectService\n * when the user supplies their own Soniox API key: audio streams from the\n * phone straight to Soniox, bypassing the Glassly cloud.\n *\n * Deliberately hand-rolled rather than depending on `@soniox/node` (node HTTP\n * machinery) or `@soniox/web` (MediaStream capture): the wire protocol is one\n * JSON config message, then binary PCM frames up / JSON token results down.\n * Protocol shape mirrors the vendored SDK's buildConfigMessage /\n * parseResultMessage (cloud-v2 runtime's provider is the reference\n * implementation: cloud-v2/packages/runtime/src/services/audio/providers/soniox.ts).\n */\n\nimport {BgTimer} from \"../../utils/timers\"\n\nexport const SONIOX_STT_WS_URL = \"wss://stt-rt.soniox.com/transcribe-websocket\"\nexport const SONIOX_MODEL = \"stt-rt-v4\"\n/** REST endpoint used only for cheap key validation (Save & Test). */\nexport const SONIOX_MODELS_URL = \"https://api.soniox.com/v1/models\"\n\nconst CONNECT_TIMEOUT_MS = 20_000\nconst KEEPALIVE_INTERVAL_MS = 5_000\n\nexport interface SonioxToken {\n text: string\n start_ms?: number\n end_ms?: number\n confidence?: number\n is_final: boolean\n speaker?: string\n language?: string\n translation_status?: \"none\" | \"original\" | \"translation\"\n source_language?: string\n}\n\nexport interface SonioxResult {\n tokens: SonioxToken[]\n finished?: boolean\n}\n\nexport class SonioxClientError extends Error {\n readonly code: number | string | undefined\n /**\n * Billing/auth failures (bad key, quota exhausted) are not healed by\n * reconnecting — Soniox accepts the socket then rejects the session.\n * Mirrors the cloud provider's isNonTransientProviderError: 401/402/403\n * plus the quota codes (the raw wire uses 429 for quota).\n */\n readonly nonTransient: boolean\n\n constructor(message: string, code?: number | string) {\n super(message)\n this.name = \"SonioxClientError\"\n this.code = code\n this.nonTransient = code === 401 || code === 402 || code === 403 || code === 429 || code === \"quota_exceeded\"\n }\n}\n\nexport interface SonioxSessionOptions {\n apiKey: string\n /** Subscription language (\"auto\", \"en-US\", ...). Hints are derived from it. */\n language?: string\n /** Detection hints for auto-mode subscriptions (already bare or BCP-47; normalized here). */\n languageHints?: string[]\n /** When set, configure Soniox one-way translation to this target (BCP-47 ok; normalized). */\n targetLanguage?: string\n onOpen?: () => void\n onResult: (result: SonioxResult) => void\n onEndpoint: () => void\n onFinalized: () => void\n onError: (err: SonioxClientError) => void\n onClose?: () => void\n /** Test seam: WebSocket constructor override. */\n webSocketFactory?: (url: string) => WebSocket\n}\n\n/**\n * Build Soniox `language_hints`. A specific language is its own hint (region\n * stripped: \"en-US\" -> \"en\"). For \"auto\" the miniapp's detection hints are\n * reduced to bare codes and deduped. Passing a BCP-47 tag or unknown code\n * makes Soniox reject the session (\"Invalid language hint\"), so everything is\n * normalized here. Port of the cloud provider's sonioxLanguageHints.\n */\nexport function sonioxLanguageHints(language: string | undefined, hints: string[] | undefined): string[] | undefined {\n const toBareCode = (code: string) => code.split(\"-\")[0].toLowerCase()\n if (language && language !== \"auto\") {\n return [toBareCode(language)]\n }\n if (!hints || hints.length === 0) return undefined\n const bare = [...new Set(hints.map(toBareCode).filter(Boolean))]\n return bare.length > 0 ? bare : undefined\n}\n\n/**\n * Soniox one-way translation target takes a bare ISO 639-1 code — a BCP-47\n * tag (\"es-ES\") kills the session. Subscription keys keep the full tag; only\n * the wire config is reduced. Port of the cloud provider's sonioxTranslationTarget.\n */\nexport function sonioxTranslationTarget(target: string): string {\n return target.split(\"-\")[0].toLowerCase()\n}\n\n/** The first (and only) config message sent after the socket opens. */\nexport function buildSonioxConfigMessage(opts: {\n apiKey: string\n language?: string\n languageHints?: string[]\n targetLanguage?: string\n}): Record<string, unknown> {\n return {\n api_key: opts.apiKey,\n model: SONIOX_MODEL,\n audio_format: \"pcm_s16le\",\n sample_rate: 16_000,\n num_channels: 1,\n enable_language_identification: true,\n enable_endpoint_detection: true,\n enable_speaker_diarization: true,\n max_endpoint_delay_ms: 2_000,\n language_hints: sonioxLanguageHints(opts.language, opts.languageHints),\n context: {\n terms: [\"Glassly\", \"Hey Glassly\"],\n text: \"Glassly, Hey Glassly (an AI assistant)\",\n },\n translation: opts.targetLanguage\n ? {type: \"one_way\", target_language: sonioxTranslationTarget(opts.targetLanguage)}\n : undefined,\n }\n}\n\n/**\n * One realtime session: connect, stream audio, receive tokens. A dead session\n * is not reusable — SonioxDirectService replaces it on reconnect.\n */\nexport class SonioxRealtimeClient {\n private readonly opts: SonioxSessionOptions\n private ws: WebSocket | null = null\n private opened = false\n private closed = false\n private connectTimer: number | null = null\n private keepaliveTimer: number | null = null\n private lastAudioSentAt = 0\n\n constructor(opts: SonioxSessionOptions) {\n this.opts = opts\n }\n\n isOpen(): boolean {\n return this.opened && !this.closed\n }\n\n connect(): void {\n if (this.ws) return\n const factory = this.opts.webSocketFactory ?? ((url: string) => new WebSocket(url))\n let ws: WebSocket\n try {\n ws = factory(SONIOX_STT_WS_URL)\n } catch (err) {\n this.opts.onError(new SonioxClientError(`websocket construction failed: ${(err as Error)?.message ?? err}`))\n return\n }\n this.ws = ws\n ws.binaryType = \"arraybuffer\"\n\n this.connectTimer = BgTimer.setTimeout(() => {\n this.connectTimer = null\n if (!this.opened && !this.closed) {\n this.opts.onError(new SonioxClientError(\"connect timeout\", 503))\n this.close()\n }\n }, CONNECT_TIMEOUT_MS)\n\n ws.onopen = () => {\n if (this.closed) return\n this.clearConnectTimer()\n this.opened = true\n const config = buildSonioxConfigMessage({\n apiKey: this.opts.apiKey,\n language: this.opts.language,\n languageHints: this.opts.languageHints,\n targetLanguage: this.opts.targetLanguage,\n })\n try {\n ws.send(JSON.stringify(config))\n } catch (err) {\n this.opts.onError(new SonioxClientError(`config send failed: ${(err as Error)?.message ?? err}`))\n this.close()\n return\n }\n this.startKeepalive()\n this.opts.onOpen?.()\n }\n\n ws.onmessage = (event) => {\n if (this.closed || typeof event.data !== \"string\") return\n this.handleMessage(event.data)\n }\n\n ws.onerror = () => {\n if (this.closed) return\n // RN's error event carries no useful detail; the close event follows.\n this.opts.onError(new SonioxClientError(\"websocket error\", 503))\n }\n\n ws.onclose = () => {\n const wasClosed = this.closed\n this.teardown()\n if (!wasClosed) this.opts.onClose?.()\n }\n }\n\n /** Binary PCM (s16le 16kHz mono) frame. Dropped when the socket isn't open. */\n sendAudio(pcm: ArrayBuffer): void {\n if (!this.isOpen() || !this.ws) return\n this.lastAudioSentAt = Date.now()\n try {\n this.ws.send(pcm)\n } catch (err) {\n this.opts.onError(new SonioxClientError(`audio send failed: ${(err as Error)?.message ?? err}`))\n }\n }\n\n finalize(): void {\n this.sendControl({type: \"finalize\"})\n }\n\n close(): void {\n if (this.closed) {\n return\n }\n this.closed = true\n this.clearConnectTimer()\n this.stopKeepalive()\n const ws = this.ws\n this.ws = null\n this.opened = false\n if (ws) {\n try {\n ws.close()\n } catch {\n /* best-effort */\n }\n }\n }\n\n private handleMessage(data: string): void {\n let raw: Record<string, unknown>\n try {\n raw = JSON.parse(data) as Record<string, unknown>\n } catch {\n return\n }\n if (\"error_code\" in raw || \"error_message\" in raw) {\n const code = raw.error_code as number | string | undefined\n const message = typeof raw.error_message === \"string\" ? raw.error_message : \"soniox error\"\n this.opts.onError(new SonioxClientError(message, code))\n return\n }\n\n const allTokens = Array.isArray(raw.tokens) ? (raw.tokens as SonioxToken[]) : []\n let sawEndpoint = false\n let sawFinalized = false\n const tokens: SonioxToken[] = []\n for (const t of allTokens) {\n if (typeof t?.text !== \"string\") continue\n if (t.text === \"<end>\") {\n sawEndpoint = true\n } else if (t.text === \"<fin>\") {\n sawFinalized = true\n } else {\n tokens.push(t)\n }\n }\n\n if (tokens.length > 0) {\n this.opts.onResult({tokens, finished: raw.finished === true})\n }\n // Order matters: tokens in the same message belong to the utterance the\n // endpoint closes, so deliver them before the boundary signal.\n if (sawEndpoint) this.opts.onEndpoint()\n if (sawFinalized) this.opts.onFinalized()\n }\n\n private sendControl(msg: {type: string}): void {\n if (!this.isOpen() || !this.ws) return\n try {\n this.ws.send(JSON.stringify(msg))\n } catch {\n /* best-effort */\n }\n }\n\n private startKeepalive(): void {\n this.stopKeepalive()\n this.keepaliveTimer = BgTimer.setInterval(() => {\n // Only needed when no audio has been sent recently — Soniox times out\n // idle sessions. Continuous audio makes this a safety net.\n if (Date.now() - this.lastAudioSentAt >= KEEPALIVE_INTERVAL_MS) {\n this.sendControl({type: \"keepalive\"})\n }\n }, KEEPALIVE_INTERVAL_MS)\n }\n\n private stopKeepalive(): void {\n if (this.keepaliveTimer !== null) {\n BgTimer.clearInterval(this.keepaliveTimer)\n this.keepaliveTimer = null\n }\n }\n\n private clearConnectTimer(): void {\n if (this.connectTimer !== null) {\n BgTimer.clearTimeout(this.connectTimer)\n this.connectTimer = null\n }\n }\n\n private teardown(): void {\n this.closed = true\n this.opened = false\n this.clearConnectTimer()\n this.stopKeepalive()\n this.ws = null\n }\n}\n\n/**\n * Cheap key validation for the Keys screen: GET /v1/models with the key as a\n * Bearer token. 401/403 → invalid key; network failure → indeterminate (the\n * caller may offer \"save anyway\").\n */\nexport async function validateSonioxApiKey(\n apiKey: string,\n): Promise<{ok: true} | {ok: false; reason: \"invalid_key\" | \"network\"}> {\n try {\n const res = await fetch(SONIOX_MODELS_URL, {\n method: \"GET\",\n headers: {Authorization: `Bearer ${apiKey}`},\n })\n if (res.ok) return {ok: true}\n if (res.status === 401 || res.status === 403) return {ok: false, reason: \"invalid_key\"}\n return {ok: false, reason: \"network\"}\n } catch {\n return {ok: false, reason: \"network\"}\n }\n}\n"]}
1
+ {"version":3,"file":"SonioxRealtimeClient.js","sourceRoot":"","sources":["../../../src/services/soniox/SonioxRealtimeClient.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * SonioxRealtimeClient\n *\n * Minimal React Native WebSocket client for Soniox realtime STT\n * (wss://stt-rt.soniox.com/transcribe-websocket). Used by SonioxDirectService\n * when the user supplies their own Soniox API key: audio streams from the\n * phone straight to Soniox, bypassing the Glassly cloud.\n *\n * Deliberately hand-rolled rather than depending on `@soniox/node` (node HTTP\n * machinery) or `@soniox/web` (MediaStream capture): the wire protocol is one\n * JSON config message, then binary PCM frames up / JSON token results down.\n * Protocol shape mirrors the vendored SDK's buildConfigMessage /\n * parseResultMessage (cloud runtime's provider is the reference\n * implementation: cloud/packages/runtime/src/services/audio/providers/soniox.ts).\n */\n\nimport {BgTimer} from \"../../utils/timers\"\n\nexport const SONIOX_STT_WS_URL = \"wss://stt-rt.soniox.com/transcribe-websocket\"\nexport const SONIOX_MODEL = \"stt-rt-v4\"\n/** REST endpoint used only for cheap key validation (Save & Test). */\nexport const SONIOX_MODELS_URL = \"https://api.soniox.com/v1/models\"\n\nconst CONNECT_TIMEOUT_MS = 20_000\nconst KEEPALIVE_INTERVAL_MS = 5_000\n\nexport interface SonioxToken {\n text: string\n start_ms?: number\n end_ms?: number\n confidence?: number\n is_final: boolean\n speaker?: string\n language?: string\n translation_status?: \"none\" | \"original\" | \"translation\"\n source_language?: string\n}\n\nexport interface SonioxResult {\n tokens: SonioxToken[]\n finished?: boolean\n}\n\nexport class SonioxClientError extends Error {\n readonly code: number | string | undefined\n /**\n * Billing/auth failures (bad key, quota exhausted) are not healed by\n * reconnecting — Soniox accepts the socket then rejects the session.\n * Mirrors the cloud provider's isNonTransientProviderError: 401/402/403\n * plus the quota codes (the raw wire uses 429 for quota).\n */\n readonly nonTransient: boolean\n\n constructor(message: string, code?: number | string) {\n super(message)\n this.name = \"SonioxClientError\"\n this.code = code\n this.nonTransient = code === 401 || code === 402 || code === 403 || code === 429 || code === \"quota_exceeded\"\n }\n}\n\nexport interface SonioxSessionOptions {\n apiKey: string\n /** Subscription language (\"auto\", \"en-US\", ...). Hints are derived from it. */\n language?: string\n /** Detection hints for auto-mode subscriptions (already bare or BCP-47; normalized here). */\n languageHints?: string[]\n /** When set, configure Soniox one-way translation to this target (BCP-47 ok; normalized). */\n targetLanguage?: string\n onOpen?: () => void\n onResult: (result: SonioxResult) => void\n onEndpoint: () => void\n onFinalized: () => void\n onError: (err: SonioxClientError) => void\n onClose?: () => void\n /** Test seam: WebSocket constructor override. */\n webSocketFactory?: (url: string) => WebSocket\n}\n\n/**\n * Build Soniox `language_hints`. A specific language is its own hint (region\n * stripped: \"en-US\" -> \"en\"). For \"auto\" the miniapp's detection hints are\n * reduced to bare codes and deduped. Passing a BCP-47 tag or unknown code\n * makes Soniox reject the session (\"Invalid language hint\"), so everything is\n * normalized here. Port of the cloud provider's sonioxLanguageHints.\n */\nexport function sonioxLanguageHints(language: string | undefined, hints: string[] | undefined): string[] | undefined {\n const toBareCode = (code: string) => code.split(\"-\")[0].toLowerCase()\n if (language && language !== \"auto\") {\n return [toBareCode(language)]\n }\n if (!hints || hints.length === 0) return undefined\n const bare = [...new Set(hints.map(toBareCode).filter(Boolean))]\n return bare.length > 0 ? bare : undefined\n}\n\n/**\n * Soniox one-way translation target takes a bare ISO 639-1 code — a BCP-47\n * tag (\"es-ES\") kills the session. Subscription keys keep the full tag; only\n * the wire config is reduced. Port of the cloud provider's sonioxTranslationTarget.\n */\nexport function sonioxTranslationTarget(target: string): string {\n return target.split(\"-\")[0].toLowerCase()\n}\n\n/** The first (and only) config message sent after the socket opens. */\nexport function buildSonioxConfigMessage(opts: {\n apiKey: string\n language?: string\n languageHints?: string[]\n targetLanguage?: string\n}): Record<string, unknown> {\n return {\n api_key: opts.apiKey,\n model: SONIOX_MODEL,\n audio_format: \"pcm_s16le\",\n sample_rate: 16_000,\n num_channels: 1,\n enable_language_identification: true,\n enable_endpoint_detection: true,\n enable_speaker_diarization: true,\n max_endpoint_delay_ms: 2_000,\n language_hints: sonioxLanguageHints(opts.language, opts.languageHints),\n context: {\n terms: [\"Glassly\", \"Hey Glassly\"],\n text: \"Glassly, Hey Glassly (an AI assistant)\",\n },\n translation: opts.targetLanguage\n ? {type: \"one_way\", target_language: sonioxTranslationTarget(opts.targetLanguage)}\n : undefined,\n }\n}\n\n/**\n * One realtime session: connect, stream audio, receive tokens. A dead session\n * is not reusable — SonioxDirectService replaces it on reconnect.\n */\nexport class SonioxRealtimeClient {\n private readonly opts: SonioxSessionOptions\n private ws: WebSocket | null = null\n private opened = false\n private closed = false\n private connectTimer: number | null = null\n private keepaliveTimer: number | null = null\n private lastAudioSentAt = 0\n\n constructor(opts: SonioxSessionOptions) {\n this.opts = opts\n }\n\n isOpen(): boolean {\n return this.opened && !this.closed\n }\n\n connect(): void {\n if (this.ws) return\n const factory = this.opts.webSocketFactory ?? ((url: string) => new WebSocket(url))\n let ws: WebSocket\n try {\n ws = factory(SONIOX_STT_WS_URL)\n } catch (err) {\n this.opts.onError(new SonioxClientError(`websocket construction failed: ${(err as Error)?.message ?? err}`))\n return\n }\n this.ws = ws\n ws.binaryType = \"arraybuffer\"\n\n this.connectTimer = BgTimer.setTimeout(() => {\n this.connectTimer = null\n if (!this.opened && !this.closed) {\n this.opts.onError(new SonioxClientError(\"connect timeout\", 503))\n this.close()\n }\n }, CONNECT_TIMEOUT_MS)\n\n ws.onopen = () => {\n if (this.closed) return\n this.clearConnectTimer()\n this.opened = true\n const config = buildSonioxConfigMessage({\n apiKey: this.opts.apiKey,\n language: this.opts.language,\n languageHints: this.opts.languageHints,\n targetLanguage: this.opts.targetLanguage,\n })\n try {\n ws.send(JSON.stringify(config))\n } catch (err) {\n this.opts.onError(new SonioxClientError(`config send failed: ${(err as Error)?.message ?? err}`))\n this.close()\n return\n }\n this.startKeepalive()\n this.opts.onOpen?.()\n }\n\n ws.onmessage = (event) => {\n if (this.closed || typeof event.data !== \"string\") return\n this.handleMessage(event.data)\n }\n\n ws.onerror = () => {\n if (this.closed) return\n // RN's error event carries no useful detail; the close event follows.\n this.opts.onError(new SonioxClientError(\"websocket error\", 503))\n }\n\n ws.onclose = () => {\n const wasClosed = this.closed\n this.teardown()\n if (!wasClosed) this.opts.onClose?.()\n }\n }\n\n /** Binary PCM (s16le 16kHz mono) frame. Dropped when the socket isn't open. */\n sendAudio(pcm: ArrayBuffer): void {\n if (!this.isOpen() || !this.ws) return\n this.lastAudioSentAt = Date.now()\n try {\n this.ws.send(pcm)\n } catch (err) {\n this.opts.onError(new SonioxClientError(`audio send failed: ${(err as Error)?.message ?? err}`))\n }\n }\n\n finalize(): void {\n this.sendControl({type: \"finalize\"})\n }\n\n close(): void {\n if (this.closed) {\n return\n }\n this.closed = true\n this.clearConnectTimer()\n this.stopKeepalive()\n const ws = this.ws\n this.ws = null\n this.opened = false\n if (ws) {\n try {\n ws.close()\n } catch {\n /* best-effort */\n }\n }\n }\n\n private handleMessage(data: string): void {\n let raw: Record<string, unknown>\n try {\n raw = JSON.parse(data) as Record<string, unknown>\n } catch {\n return\n }\n if (\"error_code\" in raw || \"error_message\" in raw) {\n const code = raw.error_code as number | string | undefined\n const message = typeof raw.error_message === \"string\" ? raw.error_message : \"soniox error\"\n this.opts.onError(new SonioxClientError(message, code))\n return\n }\n\n const allTokens = Array.isArray(raw.tokens) ? (raw.tokens as SonioxToken[]) : []\n let sawEndpoint = false\n let sawFinalized = false\n const tokens: SonioxToken[] = []\n for (const t of allTokens) {\n if (typeof t?.text !== \"string\") continue\n if (t.text === \"<end>\") {\n sawEndpoint = true\n } else if (t.text === \"<fin>\") {\n sawFinalized = true\n } else {\n tokens.push(t)\n }\n }\n\n if (tokens.length > 0) {\n this.opts.onResult({tokens, finished: raw.finished === true})\n }\n // Order matters: tokens in the same message belong to the utterance the\n // endpoint closes, so deliver them before the boundary signal.\n if (sawEndpoint) this.opts.onEndpoint()\n if (sawFinalized) this.opts.onFinalized()\n }\n\n private sendControl(msg: {type: string}): void {\n if (!this.isOpen() || !this.ws) return\n try {\n this.ws.send(JSON.stringify(msg))\n } catch {\n /* best-effort */\n }\n }\n\n private startKeepalive(): void {\n this.stopKeepalive()\n this.keepaliveTimer = BgTimer.setInterval(() => {\n // Only needed when no audio has been sent recently — Soniox times out\n // idle sessions. Continuous audio makes this a safety net.\n if (Date.now() - this.lastAudioSentAt >= KEEPALIVE_INTERVAL_MS) {\n this.sendControl({type: \"keepalive\"})\n }\n }, KEEPALIVE_INTERVAL_MS)\n }\n\n private stopKeepalive(): void {\n if (this.keepaliveTimer !== null) {\n BgTimer.clearInterval(this.keepaliveTimer)\n this.keepaliveTimer = null\n }\n }\n\n private clearConnectTimer(): void {\n if (this.connectTimer !== null) {\n BgTimer.clearTimeout(this.connectTimer)\n this.connectTimer = null\n }\n }\n\n private teardown(): void {\n this.closed = true\n this.opened = false\n this.clearConnectTimer()\n this.stopKeepalive()\n this.ws = null\n }\n}\n\n/**\n * Cheap key validation for the Keys screen: GET /v1/models with the key as a\n * Bearer token. 401/403 → invalid key; network failure → indeterminate (the\n * caller may offer \"save anyway\").\n */\nexport async function validateSonioxApiKey(\n apiKey: string,\n): Promise<{ok: true} | {ok: false; reason: \"invalid_key\" | \"network\"}> {\n try {\n const res = await fetch(SONIOX_MODELS_URL, {\n method: \"GET\",\n headers: {Authorization: `Bearer ${apiKey}`},\n })\n if (res.ok) return {ok: true}\n if (res.status === 401 || res.status === 403) return {ok: false, reason: \"invalid_key\"}\n return {ok: false, reason: \"network\"}\n } catch {\n return {ok: false, reason: \"network\"}\n }\n}\n"]}
@@ -2,7 +2,7 @@
2
2
  * SonioxTokenAssembler
3
3
  *
4
4
  * Pure port of the cloud Soniox provider's utterance assembly
5
- * (cloud-v2/packages/runtime/src/services/audio/providers/soniox.ts). Soniox
5
+ * (cloud/packages/runtime/src/services/audio/providers/soniox.ts). Soniox
6
6
  * emits a rolling token window that is re-finalized/compacted across results;
7
7
  * this class turns that stream into stable interim/final utterances:
8
8
  *
@@ -2,7 +2,7 @@
2
2
  * SonioxTokenAssembler
3
3
  *
4
4
  * Pure port of the cloud Soniox provider's utterance assembly
5
- * (cloud-v2/packages/runtime/src/services/audio/providers/soniox.ts). Soniox
5
+ * (cloud/packages/runtime/src/services/audio/providers/soniox.ts). Soniox
6
6
  * emits a rolling token window that is re-finalized/compacted across results;
7
7
  * this class turns that stream into stable interim/final utterances:
8
8
  *
@@ -1 +1 @@
1
- {"version":3,"file":"SonioxTokenAssembler.js","sourceRoot":"","sources":["../../../src/services/soniox/SonioxTokenAssembler.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * SonioxTokenAssembler\n *\n * Pure port of the cloud Soniox provider's utterance assembly\n * (cloud-v2/packages/runtime/src/services/audio/providers/soniox.ts). Soniox\n * emits a rolling token window that is re-finalized/compacted across results;\n * this class turns that stream into stable interim/final utterances:\n *\n * - finalized text accumulates into a stable prefix so interims never shrink\n * - a single FINAL per utterance, committed at the endpoint boundary\n * - the endpoint is a soft signal: the candidate final is held briefly\n * (debounce) and merged back if the next rolling window overlaps\n * - speaker/language are tracked per token but never split an utterance\n * (Soniox re-diarizes its window; per-token labels flicker)\n * - translation sessions split the window: translation-status tokens are the\n * emitted text, original-status tokens ride along as `originalText`, and\n * untagged tokens are Soniox's same-language passthrough\n *\n * Timers are injected for testability; production uses BgTimer so the debounce\n * survives app backgrounding.\n */\n\nimport {BgTimer} from \"../../utils/timers\"\nimport type {SonioxResult} from \"./SonioxRealtimeClient\"\n\nconst MIN_ENDPOINT_OVERLAP_CHARS = 3\nconst MIN_REGRESSION_DROP_CHARS = 12\nconst MIN_REGRESSION_PREFIX_CHARS = 12\nconst DEFAULT_ENDPOINT_DEBOUNCE_MS = 500\n\nexport interface AssembledTranscript {\n text: string\n isFinal: boolean\n utteranceId?: string\n speakerId?: string\n language?: string\n originalText?: string\n sourceLanguage?: string\n startMs?: number\n endMs?: number\n}\n\nexport interface SonioxTokenAssemblerOptions {\n /** Stable id used in minted utterance ids (readable per subscription). */\n scope: string\n /** True for translation sessions: split original/translation token halves. */\n isTranslation: boolean\n /** Subscription language, used when a token carries no detected language. */\n fallbackLanguage?: string\n onTranscript: (t: AssembledTranscript) => void\n endpointDebounceMs?: number\n /** Test seams; default to background-safe timers. */\n setTimeoutFn?: (cb: () => void, ms: number) => number\n clearTimeoutFn?: (id: number) => void\n}\n\nexport class SonioxTokenAssembler {\n private readonly opts: SonioxTokenAssemblerOptions\n private readonly endpointDebounceMs: number\n private readonly setTimeoutFn: (cb: () => void, ms: number) => number\n private readonly clearTimeoutFn: (id: number) => void\n\n // === Per-utterance state ===\n private stablePrefix = \"\"\n private prevFinalLen = 0\n private lastSentInterim = \"\"\n\n // Translation subs only: parallel accumulator for original-language tokens.\n private originalStablePrefix = \"\"\n private originalPrevFinalLen = 0\n private lastOriginalText = \"\"\n private currentSourceLanguage: string | undefined = undefined\n\n private currentUtteranceId: string | null = null\n private currentSpeakerId: string | undefined = undefined\n private currentLanguage: string | undefined = undefined\n\n // Deferred final (endpoint debounce).\n private pendingFinalText = \"\"\n private pendingFinalUtteranceId: string | null = null\n private pendingFinalSpeakerId: string | undefined = undefined\n private pendingFinalLanguage: string | undefined = undefined\n private pendingFinalOriginalText = \"\"\n private pendingFinalSourceLanguage: string | undefined = undefined\n private pendingFinalStartMs: number | undefined = undefined\n private pendingFinalEndMs: number | undefined = undefined\n private pendingFinalTimer: number | null = null\n\n // Id minting: an instance nonce prevents collisions across service restarts.\n private utteranceSeq = 0\n private readonly instanceId = Math.random().toString(36).slice(2, 10)\n\n constructor(opts: SonioxTokenAssemblerOptions) {\n this.opts = opts\n this.endpointDebounceMs = opts.endpointDebounceMs ?? DEFAULT_ENDPOINT_DEBOUNCE_MS\n this.setTimeoutFn = opts.setTimeoutFn ?? ((cb, ms) => BgTimer.setTimeout(cb, ms))\n this.clearTimeoutFn = opts.clearTimeoutFn ?? ((id) => BgTimer.clearTimeout(id))\n }\n\n private mintUtteranceId(): string {\n this.utteranceSeq += 1\n return `utt_${this.opts.scope}_${this.instanceId}_${this.utteranceSeq}`\n }\n\n private startNewUtterance(speakerId?: string, language?: string): void {\n this.currentUtteranceId = this.mintUtteranceId()\n this.currentSpeakerId = speakerId\n this.currentLanguage = language\n this.stablePrefix = \"\"\n this.prevFinalLen = 0\n this.lastSentInterim = \"\"\n this.originalStablePrefix = \"\"\n this.originalPrevFinalLen = 0\n this.lastOriginalText = \"\"\n this.currentSourceLanguage = undefined\n }\n\n private resetActiveUtterance(): void {\n this.stablePrefix = \"\"\n this.prevFinalLen = 0\n this.lastSentInterim = \"\"\n this.originalStablePrefix = \"\"\n this.originalPrevFinalLen = 0\n this.lastOriginalText = \"\"\n this.currentSourceLanguage = undefined\n this.currentUtteranceId = null\n this.currentSpeakerId = undefined\n this.currentLanguage = undefined\n }\n\n private clearPendingFinal(): void {\n if (this.pendingFinalTimer !== null) {\n this.clearTimeoutFn(this.pendingFinalTimer)\n this.pendingFinalTimer = null\n }\n this.pendingFinalText = \"\"\n this.pendingFinalUtteranceId = null\n this.pendingFinalSpeakerId = undefined\n this.pendingFinalLanguage = undefined\n this.pendingFinalOriginalText = \"\"\n this.pendingFinalSourceLanguage = undefined\n this.pendingFinalStartMs = undefined\n this.pendingFinalEndMs = undefined\n }\n\n private tryMergeOverlap(a: string, b: string): string | null {\n const left = a.trim()\n const right = b.trim()\n if (!left || !right) return null\n if (left === right || left.startsWith(right)) return left\n if (right.startsWith(left)) return left + right.slice(left.length)\n\n const maxOverlap = Math.min(left.length, right.length)\n for (let len = maxOverlap; len >= MIN_ENDPOINT_OVERLAP_CHARS; len -= 1) {\n if (left.endsWith(right.slice(0, len))) {\n return left + right.slice(len)\n }\n }\n return null\n }\n\n private isLikelyWindowRegression(next: string, previous: string): boolean {\n const normalizedNext = next.trim()\n const normalizedPrevious = previous.trim()\n if (!normalizedNext || !normalizedPrevious) return false\n const drop = normalizedPrevious.length - normalizedNext.length\n if (drop < MIN_REGRESSION_DROP_CHARS) return false\n\n let sharedPrefix = 0\n const maxPrefix = Math.min(normalizedNext.length, normalizedPrevious.length)\n while (sharedPrefix < maxPrefix && normalizedNext[sharedPrefix] === normalizedPrevious[sharedPrefix]) {\n sharedPrefix += 1\n }\n\n return sharedPrefix >= Math.min(MIN_REGRESSION_PREFIX_CHARS, normalizedNext.length)\n }\n\n private emitFinalEvent(event: {\n text: string\n utteranceId?: string\n speakerId?: string\n language?: string\n originalText?: string\n sourceLanguage?: string\n startMs?: number\n endMs?: number\n }): void {\n this.opts.onTranscript({\n text: event.text,\n isFinal: true,\n utteranceId: event.utteranceId,\n speakerId: event.speakerId,\n language: event.language,\n originalText: event.originalText || undefined,\n sourceLanguage: event.sourceLanguage,\n startMs: event.startMs,\n endMs: event.endMs,\n })\n }\n\n private commitPendingFinal(): void {\n if (!this.pendingFinalText) {\n this.clearPendingFinal()\n return\n }\n\n const committedText = this.pendingFinalText\n const committedUtteranceId = this.pendingFinalUtteranceId\n this.emitFinalEvent({\n text: committedText,\n utteranceId: committedUtteranceId ?? undefined,\n speakerId: this.pendingFinalSpeakerId,\n language: this.pendingFinalLanguage,\n originalText: this.pendingFinalOriginalText,\n sourceLanguage: this.pendingFinalSourceLanguage,\n startMs: this.pendingFinalStartMs,\n endMs: this.pendingFinalEndMs,\n })\n if (\n committedUtteranceId &&\n this.currentUtteranceId === committedUtteranceId &&\n this.lastSentInterim.trim() === committedText\n ) {\n this.resetActiveUtterance()\n }\n this.clearPendingFinal()\n }\n\n private schedulePendingFinalCommit(): void {\n if (this.pendingFinalTimer !== null) this.clearTimeoutFn(this.pendingFinalTimer)\n this.pendingFinalTimer = this.setTimeoutFn(() => {\n this.commitPendingFinal()\n }, this.endpointDebounceMs)\n }\n\n private setPendingFinalFromActive(text: string): void {\n this.pendingFinalText = text\n this.pendingFinalUtteranceId = this.currentUtteranceId\n this.pendingFinalSpeakerId = this.currentSpeakerId\n this.pendingFinalLanguage = this.currentLanguage\n this.pendingFinalOriginalText = this.lastOriginalText\n this.pendingFinalSourceLanguage = this.currentSourceLanguage\n }\n\n /**\n * Commit the current utterance as a single FINAL and reset. Called only at a\n * real boundary: endpoint (via the debounce path), finalize ack, or close.\n */\n private emitFinal(startMs?: number, endMs?: number): void {\n const text = this.lastSentInterim.trim()\n if (!text) {\n this.resetActiveUtterance()\n return\n }\n this.emitFinalEvent({\n text,\n utteranceId: this.currentUtteranceId ?? undefined,\n speakerId: this.currentSpeakerId,\n language: this.currentLanguage,\n originalText: this.lastOriginalText || undefined,\n sourceLanguage: this.currentSourceLanguage,\n startMs,\n endMs,\n })\n this.resetActiveUtterance()\n }\n\n handleResult(result: SonioxResult): void {\n const allTokens = result.tokens ?? []\n\n // Translation sessions: translation-status tokens are the emitted text;\n // original-status tokens feed the parallel originalText accumulator.\n // Untagged tokens are Soniox's SAME-LANGUAGE PASSTHROUGH (spoken language\n // already equals the target): keep them as emitted text so target-language\n // speech surfaces instead of silently vanishing.\n const tokens = this.opts.isTranslation ? allTokens.filter((t) => t.translation_status !== \"original\") : allTokens\n const originalTokens = this.opts.isTranslation ? allTokens.filter((t) => t.translation_status === \"original\") : []\n\n let interimText = \"\"\n let language: string | undefined\n let startMs: number | undefined\n let endMs: number | undefined\n let currentFinalText = \"\"\n\n for (const t of tokens) {\n // First token of the stream (or first after a commit): open an\n // utterance. Deliberately no split on per-token speaker change — Soniox\n // re-diarizes its rolling window, so speaker labels flicker within one\n // real utterance; the single FINAL comes from the endpoint boundary.\n if (!this.currentUtteranceId) {\n this.startNewUtterance(t.speaker, t.language ?? this.opts.fallbackLanguage)\n }\n\n if (t.speaker) this.currentSpeakerId = t.speaker\n if (t.language) {\n language = t.language\n this.currentLanguage = t.language\n // Untagged tokens on a translation session are the same-language\n // passthrough: their language IS the detected source.\n if (this.opts.isTranslation && t.translation_status == null) {\n this.currentSourceLanguage = t.language\n }\n }\n\n if (t.is_final) {\n currentFinalText += t.text\n if (t.start_ms != null && startMs == null) startMs = t.start_ms\n if (t.end_ms != null) endMs = t.end_ms\n } else {\n interimText += t.text\n }\n }\n\n if (originalTokens.length > 0) {\n let originalInterim = \"\"\n let originalFinal = \"\"\n for (const t of originalTokens) {\n if (!this.currentUtteranceId) {\n this.startNewUtterance(t.speaker, undefined)\n }\n if (t.language) this.currentSourceLanguage = t.language\n if (t.is_final) originalFinal += t.text\n else originalInterim += t.text\n }\n if (originalFinal.length > this.originalPrevFinalLen) {\n this.originalStablePrefix += originalFinal.slice(this.originalPrevFinalLen)\n }\n this.originalPrevFinalLen = originalFinal.length\n const originalComposite = this.originalStablePrefix + originalInterim\n if (originalComposite.length > 0) this.lastOriginalText = originalComposite\n }\n\n // Accumulate finalized text: on window growth append the delta; on shrink\n // (compaction) keep stablePrefix and reset the tracker.\n if (currentFinalText.length > this.prevFinalLen) {\n this.stablePrefix += currentFinalText.slice(this.prevFinalLen)\n }\n this.prevFinalLen = currentFinalText.length\n\n const compositeText = (this.stablePrefix + interimText).trim()\n if (compositeText.length === 0) return\n\n if (this.pendingFinalText && this.pendingFinalTimer !== null) {\n const pendingBefore = this.pendingFinalText\n const merged = this.tryMergeOverlap(this.pendingFinalText, compositeText)\n if (merged !== null) {\n this.currentUtteranceId = this.pendingFinalUtteranceId ?? this.currentUtteranceId\n if (this.currentSpeakerId) this.pendingFinalSpeakerId = this.currentSpeakerId\n else this.currentSpeakerId = this.pendingFinalSpeakerId\n if (this.currentLanguage) this.pendingFinalLanguage = this.currentLanguage\n else this.currentLanguage = this.pendingFinalLanguage\n if (this.lastOriginalText) {\n this.pendingFinalOriginalText =\n this.tryMergeOverlap(this.pendingFinalOriginalText, this.lastOriginalText) ?? this.lastOriginalText\n }\n if (this.currentSourceLanguage) {\n this.pendingFinalSourceLanguage = this.currentSourceLanguage\n }\n\n this.pendingFinalText = merged\n this.lastSentInterim = merged\n\n if (merged !== pendingBefore) {\n this.opts.onTranscript({\n text: merged,\n isFinal: false,\n utteranceId: this.currentUtteranceId ?? undefined,\n speakerId: this.currentSpeakerId,\n language,\n originalText: this.pendingFinalOriginalText || undefined,\n sourceLanguage: this.pendingFinalSourceLanguage,\n startMs,\n endMs,\n })\n this.schedulePendingFinalCommit()\n }\n return\n }\n\n this.commitPendingFinal()\n }\n\n // Emit an INTERIM only; the single final comes at the utterance boundary.\n if (this.isLikelyWindowRegression(compositeText, this.lastSentInterim)) {\n return\n }\n\n if (compositeText !== this.lastSentInterim) {\n this.opts.onTranscript({\n text: compositeText,\n isFinal: false,\n utteranceId: this.currentUtteranceId ?? undefined,\n speakerId: this.currentSpeakerId,\n language,\n originalText: this.lastOriginalText || undefined,\n sourceLanguage: this.currentSourceLanguage,\n startMs,\n endMs,\n })\n this.lastSentInterim = compositeText\n }\n }\n\n handleEndpoint(): void {\n // Soft boundary: defer the FINAL briefly; if Soniox's next rolling window\n // overlaps, it merges back into this utterance.\n const candidate = this.lastSentInterim.trim()\n if (candidate) {\n if (this.pendingFinalText && this.pendingFinalTimer !== null) {\n const merged = this.tryMergeOverlap(this.pendingFinalText, candidate)\n if (merged !== null) {\n this.pendingFinalText = merged\n if (this.currentSpeakerId) this.pendingFinalSpeakerId = this.currentSpeakerId\n if (this.currentLanguage) this.pendingFinalLanguage = this.currentLanguage\n if (this.lastOriginalText) {\n this.pendingFinalOriginalText =\n this.tryMergeOverlap(this.pendingFinalOriginalText, this.lastOriginalText) ?? this.lastOriginalText\n }\n if (this.currentSourceLanguage) {\n this.pendingFinalSourceLanguage = this.currentSourceLanguage\n }\n } else {\n this.commitPendingFinal()\n this.setPendingFinalFromActive(candidate)\n }\n } else {\n this.setPendingFinalFromActive(candidate)\n }\n this.schedulePendingFinalCommit()\n }\n this.resetActiveUtterance()\n }\n\n /** Finalize ack (`<fin>`): trusted \"speech segment ended\" signal. */\n handleFinalized(): void {\n this.commitPendingFinal()\n this.emitFinal()\n }\n\n /** Flush any in-flight utterance as a final (session close/teardown). */\n flush(): void {\n this.commitPendingFinal()\n this.emitFinal()\n }\n\n /** Drop all state without emitting (e.g. audio-gap resume). */\n discard(): void {\n this.clearPendingFinal()\n this.resetActiveUtterance()\n }\n}\n"]}
1
+ {"version":3,"file":"SonioxTokenAssembler.js","sourceRoot":"","sources":["../../../src/services/soniox/SonioxTokenAssembler.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * SonioxTokenAssembler\n *\n * Pure port of the cloud Soniox provider's utterance assembly\n * (cloud/packages/runtime/src/services/audio/providers/soniox.ts). Soniox\n * emits a rolling token window that is re-finalized/compacted across results;\n * this class turns that stream into stable interim/final utterances:\n *\n * - finalized text accumulates into a stable prefix so interims never shrink\n * - a single FINAL per utterance, committed at the endpoint boundary\n * - the endpoint is a soft signal: the candidate final is held briefly\n * (debounce) and merged back if the next rolling window overlaps\n * - speaker/language are tracked per token but never split an utterance\n * (Soniox re-diarizes its window; per-token labels flicker)\n * - translation sessions split the window: translation-status tokens are the\n * emitted text, original-status tokens ride along as `originalText`, and\n * untagged tokens are Soniox's same-language passthrough\n *\n * Timers are injected for testability; production uses BgTimer so the debounce\n * survives app backgrounding.\n */\n\nimport {BgTimer} from \"../../utils/timers\"\nimport type {SonioxResult} from \"./SonioxRealtimeClient\"\n\nconst MIN_ENDPOINT_OVERLAP_CHARS = 3\nconst MIN_REGRESSION_DROP_CHARS = 12\nconst MIN_REGRESSION_PREFIX_CHARS = 12\nconst DEFAULT_ENDPOINT_DEBOUNCE_MS = 500\n\nexport interface AssembledTranscript {\n text: string\n isFinal: boolean\n utteranceId?: string\n speakerId?: string\n language?: string\n originalText?: string\n sourceLanguage?: string\n startMs?: number\n endMs?: number\n}\n\nexport interface SonioxTokenAssemblerOptions {\n /** Stable id used in minted utterance ids (readable per subscription). */\n scope: string\n /** True for translation sessions: split original/translation token halves. */\n isTranslation: boolean\n /** Subscription language, used when a token carries no detected language. */\n fallbackLanguage?: string\n onTranscript: (t: AssembledTranscript) => void\n endpointDebounceMs?: number\n /** Test seams; default to background-safe timers. */\n setTimeoutFn?: (cb: () => void, ms: number) => number\n clearTimeoutFn?: (id: number) => void\n}\n\nexport class SonioxTokenAssembler {\n private readonly opts: SonioxTokenAssemblerOptions\n private readonly endpointDebounceMs: number\n private readonly setTimeoutFn: (cb: () => void, ms: number) => number\n private readonly clearTimeoutFn: (id: number) => void\n\n // === Per-utterance state ===\n private stablePrefix = \"\"\n private prevFinalLen = 0\n private lastSentInterim = \"\"\n\n // Translation subs only: parallel accumulator for original-language tokens.\n private originalStablePrefix = \"\"\n private originalPrevFinalLen = 0\n private lastOriginalText = \"\"\n private currentSourceLanguage: string | undefined = undefined\n\n private currentUtteranceId: string | null = null\n private currentSpeakerId: string | undefined = undefined\n private currentLanguage: string | undefined = undefined\n\n // Deferred final (endpoint debounce).\n private pendingFinalText = \"\"\n private pendingFinalUtteranceId: string | null = null\n private pendingFinalSpeakerId: string | undefined = undefined\n private pendingFinalLanguage: string | undefined = undefined\n private pendingFinalOriginalText = \"\"\n private pendingFinalSourceLanguage: string | undefined = undefined\n private pendingFinalStartMs: number | undefined = undefined\n private pendingFinalEndMs: number | undefined = undefined\n private pendingFinalTimer: number | null = null\n\n // Id minting: an instance nonce prevents collisions across service restarts.\n private utteranceSeq = 0\n private readonly instanceId = Math.random().toString(36).slice(2, 10)\n\n constructor(opts: SonioxTokenAssemblerOptions) {\n this.opts = opts\n this.endpointDebounceMs = opts.endpointDebounceMs ?? DEFAULT_ENDPOINT_DEBOUNCE_MS\n this.setTimeoutFn = opts.setTimeoutFn ?? ((cb, ms) => BgTimer.setTimeout(cb, ms))\n this.clearTimeoutFn = opts.clearTimeoutFn ?? ((id) => BgTimer.clearTimeout(id))\n }\n\n private mintUtteranceId(): string {\n this.utteranceSeq += 1\n return `utt_${this.opts.scope}_${this.instanceId}_${this.utteranceSeq}`\n }\n\n private startNewUtterance(speakerId?: string, language?: string): void {\n this.currentUtteranceId = this.mintUtteranceId()\n this.currentSpeakerId = speakerId\n this.currentLanguage = language\n this.stablePrefix = \"\"\n this.prevFinalLen = 0\n this.lastSentInterim = \"\"\n this.originalStablePrefix = \"\"\n this.originalPrevFinalLen = 0\n this.lastOriginalText = \"\"\n this.currentSourceLanguage = undefined\n }\n\n private resetActiveUtterance(): void {\n this.stablePrefix = \"\"\n this.prevFinalLen = 0\n this.lastSentInterim = \"\"\n this.originalStablePrefix = \"\"\n this.originalPrevFinalLen = 0\n this.lastOriginalText = \"\"\n this.currentSourceLanguage = undefined\n this.currentUtteranceId = null\n this.currentSpeakerId = undefined\n this.currentLanguage = undefined\n }\n\n private clearPendingFinal(): void {\n if (this.pendingFinalTimer !== null) {\n this.clearTimeoutFn(this.pendingFinalTimer)\n this.pendingFinalTimer = null\n }\n this.pendingFinalText = \"\"\n this.pendingFinalUtteranceId = null\n this.pendingFinalSpeakerId = undefined\n this.pendingFinalLanguage = undefined\n this.pendingFinalOriginalText = \"\"\n this.pendingFinalSourceLanguage = undefined\n this.pendingFinalStartMs = undefined\n this.pendingFinalEndMs = undefined\n }\n\n private tryMergeOverlap(a: string, b: string): string | null {\n const left = a.trim()\n const right = b.trim()\n if (!left || !right) return null\n if (left === right || left.startsWith(right)) return left\n if (right.startsWith(left)) return left + right.slice(left.length)\n\n const maxOverlap = Math.min(left.length, right.length)\n for (let len = maxOverlap; len >= MIN_ENDPOINT_OVERLAP_CHARS; len -= 1) {\n if (left.endsWith(right.slice(0, len))) {\n return left + right.slice(len)\n }\n }\n return null\n }\n\n private isLikelyWindowRegression(next: string, previous: string): boolean {\n const normalizedNext = next.trim()\n const normalizedPrevious = previous.trim()\n if (!normalizedNext || !normalizedPrevious) return false\n const drop = normalizedPrevious.length - normalizedNext.length\n if (drop < MIN_REGRESSION_DROP_CHARS) return false\n\n let sharedPrefix = 0\n const maxPrefix = Math.min(normalizedNext.length, normalizedPrevious.length)\n while (sharedPrefix < maxPrefix && normalizedNext[sharedPrefix] === normalizedPrevious[sharedPrefix]) {\n sharedPrefix += 1\n }\n\n return sharedPrefix >= Math.min(MIN_REGRESSION_PREFIX_CHARS, normalizedNext.length)\n }\n\n private emitFinalEvent(event: {\n text: string\n utteranceId?: string\n speakerId?: string\n language?: string\n originalText?: string\n sourceLanguage?: string\n startMs?: number\n endMs?: number\n }): void {\n this.opts.onTranscript({\n text: event.text,\n isFinal: true,\n utteranceId: event.utteranceId,\n speakerId: event.speakerId,\n language: event.language,\n originalText: event.originalText || undefined,\n sourceLanguage: event.sourceLanguage,\n startMs: event.startMs,\n endMs: event.endMs,\n })\n }\n\n private commitPendingFinal(): void {\n if (!this.pendingFinalText) {\n this.clearPendingFinal()\n return\n }\n\n const committedText = this.pendingFinalText\n const committedUtteranceId = this.pendingFinalUtteranceId\n this.emitFinalEvent({\n text: committedText,\n utteranceId: committedUtteranceId ?? undefined,\n speakerId: this.pendingFinalSpeakerId,\n language: this.pendingFinalLanguage,\n originalText: this.pendingFinalOriginalText,\n sourceLanguage: this.pendingFinalSourceLanguage,\n startMs: this.pendingFinalStartMs,\n endMs: this.pendingFinalEndMs,\n })\n if (\n committedUtteranceId &&\n this.currentUtteranceId === committedUtteranceId &&\n this.lastSentInterim.trim() === committedText\n ) {\n this.resetActiveUtterance()\n }\n this.clearPendingFinal()\n }\n\n private schedulePendingFinalCommit(): void {\n if (this.pendingFinalTimer !== null) this.clearTimeoutFn(this.pendingFinalTimer)\n this.pendingFinalTimer = this.setTimeoutFn(() => {\n this.commitPendingFinal()\n }, this.endpointDebounceMs)\n }\n\n private setPendingFinalFromActive(text: string): void {\n this.pendingFinalText = text\n this.pendingFinalUtteranceId = this.currentUtteranceId\n this.pendingFinalSpeakerId = this.currentSpeakerId\n this.pendingFinalLanguage = this.currentLanguage\n this.pendingFinalOriginalText = this.lastOriginalText\n this.pendingFinalSourceLanguage = this.currentSourceLanguage\n }\n\n /**\n * Commit the current utterance as a single FINAL and reset. Called only at a\n * real boundary: endpoint (via the debounce path), finalize ack, or close.\n */\n private emitFinal(startMs?: number, endMs?: number): void {\n const text = this.lastSentInterim.trim()\n if (!text) {\n this.resetActiveUtterance()\n return\n }\n this.emitFinalEvent({\n text,\n utteranceId: this.currentUtteranceId ?? undefined,\n speakerId: this.currentSpeakerId,\n language: this.currentLanguage,\n originalText: this.lastOriginalText || undefined,\n sourceLanguage: this.currentSourceLanguage,\n startMs,\n endMs,\n })\n this.resetActiveUtterance()\n }\n\n handleResult(result: SonioxResult): void {\n const allTokens = result.tokens ?? []\n\n // Translation sessions: translation-status tokens are the emitted text;\n // original-status tokens feed the parallel originalText accumulator.\n // Untagged tokens are Soniox's SAME-LANGUAGE PASSTHROUGH (spoken language\n // already equals the target): keep them as emitted text so target-language\n // speech surfaces instead of silently vanishing.\n const tokens = this.opts.isTranslation ? allTokens.filter((t) => t.translation_status !== \"original\") : allTokens\n const originalTokens = this.opts.isTranslation ? allTokens.filter((t) => t.translation_status === \"original\") : []\n\n let interimText = \"\"\n let language: string | undefined\n let startMs: number | undefined\n let endMs: number | undefined\n let currentFinalText = \"\"\n\n for (const t of tokens) {\n // First token of the stream (or first after a commit): open an\n // utterance. Deliberately no split on per-token speaker change — Soniox\n // re-diarizes its rolling window, so speaker labels flicker within one\n // real utterance; the single FINAL comes from the endpoint boundary.\n if (!this.currentUtteranceId) {\n this.startNewUtterance(t.speaker, t.language ?? this.opts.fallbackLanguage)\n }\n\n if (t.speaker) this.currentSpeakerId = t.speaker\n if (t.language) {\n language = t.language\n this.currentLanguage = t.language\n // Untagged tokens on a translation session are the same-language\n // passthrough: their language IS the detected source.\n if (this.opts.isTranslation && t.translation_status == null) {\n this.currentSourceLanguage = t.language\n }\n }\n\n if (t.is_final) {\n currentFinalText += t.text\n if (t.start_ms != null && startMs == null) startMs = t.start_ms\n if (t.end_ms != null) endMs = t.end_ms\n } else {\n interimText += t.text\n }\n }\n\n if (originalTokens.length > 0) {\n let originalInterim = \"\"\n let originalFinal = \"\"\n for (const t of originalTokens) {\n if (!this.currentUtteranceId) {\n this.startNewUtterance(t.speaker, undefined)\n }\n if (t.language) this.currentSourceLanguage = t.language\n if (t.is_final) originalFinal += t.text\n else originalInterim += t.text\n }\n if (originalFinal.length > this.originalPrevFinalLen) {\n this.originalStablePrefix += originalFinal.slice(this.originalPrevFinalLen)\n }\n this.originalPrevFinalLen = originalFinal.length\n const originalComposite = this.originalStablePrefix + originalInterim\n if (originalComposite.length > 0) this.lastOriginalText = originalComposite\n }\n\n // Accumulate finalized text: on window growth append the delta; on shrink\n // (compaction) keep stablePrefix and reset the tracker.\n if (currentFinalText.length > this.prevFinalLen) {\n this.stablePrefix += currentFinalText.slice(this.prevFinalLen)\n }\n this.prevFinalLen = currentFinalText.length\n\n const compositeText = (this.stablePrefix + interimText).trim()\n if (compositeText.length === 0) return\n\n if (this.pendingFinalText && this.pendingFinalTimer !== null) {\n const pendingBefore = this.pendingFinalText\n const merged = this.tryMergeOverlap(this.pendingFinalText, compositeText)\n if (merged !== null) {\n this.currentUtteranceId = this.pendingFinalUtteranceId ?? this.currentUtteranceId\n if (this.currentSpeakerId) this.pendingFinalSpeakerId = this.currentSpeakerId\n else this.currentSpeakerId = this.pendingFinalSpeakerId\n if (this.currentLanguage) this.pendingFinalLanguage = this.currentLanguage\n else this.currentLanguage = this.pendingFinalLanguage\n if (this.lastOriginalText) {\n this.pendingFinalOriginalText =\n this.tryMergeOverlap(this.pendingFinalOriginalText, this.lastOriginalText) ?? this.lastOriginalText\n }\n if (this.currentSourceLanguage) {\n this.pendingFinalSourceLanguage = this.currentSourceLanguage\n }\n\n this.pendingFinalText = merged\n this.lastSentInterim = merged\n\n if (merged !== pendingBefore) {\n this.opts.onTranscript({\n text: merged,\n isFinal: false,\n utteranceId: this.currentUtteranceId ?? undefined,\n speakerId: this.currentSpeakerId,\n language,\n originalText: this.pendingFinalOriginalText || undefined,\n sourceLanguage: this.pendingFinalSourceLanguage,\n startMs,\n endMs,\n })\n this.schedulePendingFinalCommit()\n }\n return\n }\n\n this.commitPendingFinal()\n }\n\n // Emit an INTERIM only; the single final comes at the utterance boundary.\n if (this.isLikelyWindowRegression(compositeText, this.lastSentInterim)) {\n return\n }\n\n if (compositeText !== this.lastSentInterim) {\n this.opts.onTranscript({\n text: compositeText,\n isFinal: false,\n utteranceId: this.currentUtteranceId ?? undefined,\n speakerId: this.currentSpeakerId,\n language,\n originalText: this.lastOriginalText || undefined,\n sourceLanguage: this.currentSourceLanguage,\n startMs,\n endMs,\n })\n this.lastSentInterim = compositeText\n }\n }\n\n handleEndpoint(): void {\n // Soft boundary: defer the FINAL briefly; if Soniox's next rolling window\n // overlaps, it merges back into this utterance.\n const candidate = this.lastSentInterim.trim()\n if (candidate) {\n if (this.pendingFinalText && this.pendingFinalTimer !== null) {\n const merged = this.tryMergeOverlap(this.pendingFinalText, candidate)\n if (merged !== null) {\n this.pendingFinalText = merged\n if (this.currentSpeakerId) this.pendingFinalSpeakerId = this.currentSpeakerId\n if (this.currentLanguage) this.pendingFinalLanguage = this.currentLanguage\n if (this.lastOriginalText) {\n this.pendingFinalOriginalText =\n this.tryMergeOverlap(this.pendingFinalOriginalText, this.lastOriginalText) ?? this.lastOriginalText\n }\n if (this.currentSourceLanguage) {\n this.pendingFinalSourceLanguage = this.currentSourceLanguage\n }\n } else {\n this.commitPendingFinal()\n this.setPendingFinalFromActive(candidate)\n }\n } else {\n this.setPendingFinalFromActive(candidate)\n }\n this.schedulePendingFinalCommit()\n }\n this.resetActiveUtterance()\n }\n\n /** Finalize ack (`<fin>`): trusted \"speech segment ended\" signal. */\n handleFinalized(): void {\n this.commitPendingFinal()\n this.emitFinal()\n }\n\n /** Flush any in-flight utterance as a final (session close/teardown). */\n flush(): void {\n this.commitPendingFinal()\n this.emitFinal()\n }\n\n /** Drop all state without emitting (e.g. audio-gap resume). */\n discard(): void {\n this.clearPendingFinal()\n this.resetActiveUtterance()\n }\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Cloud-client runtime status store — moved into engine so engine owns the
3
- * cloud-v2 runtime status (connection status + audio transport). Re-exported
3
+ * cloud runtime status (connection status + audio transport). Re-exported
4
4
  * through the host's `@/stores/cloudClientStatus` shim so the app keeps its
5
5
  * imports, and surfaced as `engine.stores.cloudClientStatus`.
6
6
  */
@@ -1 +1 @@
1
- {"version":3,"file":"cloudClientStatus.js","sourceRoot":"","sources":["../../src/stores/cloudClientStatus.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAC,MAAM,EAAC,MAAM,SAAS,CAAA;AAI9B,MAAM,eAAe,GAAoB;IACvC,MAAM,EAAE,cAAc;IACtB,cAAc,EAAE,MAAM;CACvB,CAAA;AAQD,MAAM,CAAC,MAAM,yBAAyB,GAAG,MAAM,CAAyB,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAChF,GAAG,eAAe;IAClB,aAAa,EAAE,IAAI;IACnB,WAAW,EAAE,CAAC,QAAQ,EAAE,EAAE,CACxB,GAAG,CAAC;QACF,GAAG,QAAQ;QACX,aAAa,EAAE,IAAI,IAAI,EAAE;KAC1B,CAAC;IACJ,KAAK,EAAE,GAAG,EAAE,CACV,GAAG,CAAC;QACF,GAAG,eAAe;QAClB,aAAa,EAAE,IAAI;KACpB,CAAC;CACL,CAAC,CAAC,CAAA","sourcesContent":["/**\n * Cloud-client runtime status store — moved into engine so engine owns the\n * cloud-v2 runtime status (connection status + audio transport). Re-exported\n * through the host's `@/stores/cloudClientStatus` shim so the app keeps its\n * imports, and surfaced as `engine.stores.cloudClientStatus`.\n */\nimport {create} from \"zustand\"\n\nimport type {RuntimeAudioTransport, RuntimeSnapshot, RuntimeStatus} from \"@glassly/cloud-client/react-native\"\n\nconst initialSnapshot: RuntimeSnapshot = {\n status: \"disconnected\",\n audioTransport: \"none\",\n}\n\nexport interface CloudClientStatusState extends RuntimeSnapshot {\n lastChangedAt: Date | null\n setSnapshot: (snapshot: RuntimeSnapshot) => void\n reset: () => void\n}\n\nexport const useCloudClientStatusStore = create<CloudClientStatusState>((set) => ({\n ...initialSnapshot,\n lastChangedAt: null,\n setSnapshot: (snapshot) =>\n set({\n ...snapshot,\n lastChangedAt: new Date(),\n }),\n reset: () =>\n set({\n ...initialSnapshot,\n lastChangedAt: null,\n }),\n}))\n\nexport type {RuntimeAudioTransport, RuntimeSnapshot, RuntimeStatus}\n"]}
1
+ {"version":3,"file":"cloudClientStatus.js","sourceRoot":"","sources":["../../src/stores/cloudClientStatus.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAC,MAAM,EAAC,MAAM,SAAS,CAAA;AAI9B,MAAM,eAAe,GAAoB;IACvC,MAAM,EAAE,cAAc;IACtB,cAAc,EAAE,MAAM;CACvB,CAAA;AAQD,MAAM,CAAC,MAAM,yBAAyB,GAAG,MAAM,CAAyB,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAChF,GAAG,eAAe;IAClB,aAAa,EAAE,IAAI;IACnB,WAAW,EAAE,CAAC,QAAQ,EAAE,EAAE,CACxB,GAAG,CAAC;QACF,GAAG,QAAQ;QACX,aAAa,EAAE,IAAI,IAAI,EAAE;KAC1B,CAAC;IACJ,KAAK,EAAE,GAAG,EAAE,CACV,GAAG,CAAC;QACF,GAAG,eAAe;QAClB,aAAa,EAAE,IAAI;KACpB,CAAC;CACL,CAAC,CAAC,CAAA","sourcesContent":["/**\n * Cloud-client runtime status store — moved into engine so engine owns the\n * cloud runtime status (connection status + audio transport). Re-exported\n * through the host's `@/stores/cloudClientStatus` shim so the app keeps its\n * imports, and surfaced as `engine.stores.cloudClientStatus`.\n */\nimport {create} from \"zustand\"\n\nimport type {RuntimeAudioTransport, RuntimeSnapshot, RuntimeStatus} from \"@glassly/cloud-client/react-native\"\n\nconst initialSnapshot: RuntimeSnapshot = {\n status: \"disconnected\",\n audioTransport: \"none\",\n}\n\nexport interface CloudClientStatusState extends RuntimeSnapshot {\n lastChangedAt: Date | null\n setSnapshot: (snapshot: RuntimeSnapshot) => void\n reset: () => void\n}\n\nexport const useCloudClientStatusStore = create<CloudClientStatusState>((set) => ({\n ...initialSnapshot,\n lastChangedAt: null,\n setSnapshot: (snapshot) =>\n set({\n ...snapshot,\n lastChangedAt: new Date(),\n }),\n reset: () =>\n set({\n ...initialSnapshot,\n lastChangedAt: null,\n }),\n}))\n\nexport type {RuntimeAudioTransport, RuntimeSnapshot, RuntimeStatus}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../src/stores/settings.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,WAAW,EAAwB,MAAM,aAAa,CAAA;AAQ9D,OAAO,EAAC,wBAAwB,EAAE,gCAAgC,EAAC,MAAM,wBAAwB,CAAA;AAEjG,MAAM,WAAW,OAAO;IACtB,GAAG,EAAE,MAAM,CAAA;IACX,YAAY,EAAE,MAAM,GAAG,CAAA;IACvB,QAAQ,EAAE,OAAO,CAAA;IACjB,YAAY,EAAE,OAAO,CAAA;IAGrB,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAA;IAEjC,QAAQ,CAAC,EAAE,MAAM,GAAG,CAAA;IAEpB,OAAO,EAAE,OAAO,CAAA;IAQhB,mBAAmB,CAAC,EAAE,IAAI,CAAA;IAC1B;;;;;;;;;;;;;;;OAeG;IACH,qBAAqB,CAAC,EAAE,IAAI,CAAA;CAC7B;AAKD,eAAO,MAAM,uBAAuB,IAAI,CAAA;AAExC,eAAO,MAAM,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAigCnC,CAAA;AAEV,eAAO,MAAM,eAAe,EAAE,MAAM,EAAuD,CAAA;AAI3F,eAAO,MAAM,sBAAsB,EAAE,MAAM,EAqD1C,CAAA;AAeD,eAAO,MAAM,qBAAqB,EAAE,MAAM,EAEV,CAAA;AAIhC,MAAM,WAAW,aAAa;IAE5B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAE7B,aAAa,EAAE,OAAO,CAAA;IAEtB,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,YAAY,CAAC,EAAE,OAAO,KAAK,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IACzF,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IAC3E,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,GAAG,CAAA;IAEhC,eAAe,EAAE,MAAM,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IAE/C,oBAAoB,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC/C,uBAAuB,EAAE,MAAM,IAAI,CAAA;CACpC;AAoBD,eAAO,MAAM,gBAAgB;;;;;;;;EA+U5B,CAAA;AAED,eAAO,MAAM,UAAU,GAAI,CAAC,GAAG,GAAG,EAAE,KAAK,MAAM,KAAG,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAI3F,CAAA"}
1
+ {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../src/stores/settings.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,WAAW,EAAwB,MAAM,aAAa,CAAA;AAQ9D,OAAO,EAAC,wBAAwB,EAAE,gCAAgC,EAAC,MAAM,wBAAwB,CAAA;AAEjG,MAAM,WAAW,OAAO;IACtB,GAAG,EAAE,MAAM,CAAA;IACX,YAAY,EAAE,MAAM,GAAG,CAAA;IACvB,QAAQ,EAAE,OAAO,CAAA;IACjB,YAAY,EAAE,OAAO,CAAA;IAGrB,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAA;IAEjC,QAAQ,CAAC,EAAE,MAAM,GAAG,CAAA;IAEpB,OAAO,EAAE,OAAO,CAAA;IAQhB,mBAAmB,CAAC,EAAE,IAAI,CAAA;IAC1B;;;;;;;;;;;;;;;OAeG;IACH,qBAAqB,CAAC,EAAE,IAAI,CAAA;CAC7B;AAKD,eAAO,MAAM,uBAAuB,IAAI,CAAA;AAExC,eAAO,MAAM,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAmhCnC,CAAA;AAEV,eAAO,MAAM,eAAe,EAAE,MAAM,EAAuD,CAAA;AAI3F,eAAO,MAAM,sBAAsB,EAAE,MAAM,EAqD1C,CAAA;AAeD,eAAO,MAAM,qBAAqB,EAAE,MAAM,EAEV,CAAA;AAIhC,MAAM,WAAW,aAAa;IAE5B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAE7B,aAAa,EAAE,OAAO,CAAA;IAEtB,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,YAAY,CAAC,EAAE,OAAO,KAAK,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IACzF,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IAC3E,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,GAAG,CAAA;IAEhC,eAAe,EAAE,MAAM,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IAE/C,oBAAoB,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC/C,uBAAuB,EAAE,MAAM,IAAI,CAAA;CACpC;AAoBD,eAAO,MAAM,gBAAgB;;;;;;;;EA+U5B,CAAA;AAED,eAAO,MAAM,UAAU,GAAI,CAAC,GAAG,GAAG,EAAE,KAAK,MAAM,KAAG,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAI3F,CAAA"}
@@ -219,7 +219,7 @@ export const SETTINGS = {
219
219
  saveOnServer: false,
220
220
  persist: true,
221
221
  },
222
- // Cloud V2 endpoint OVERRIDES. Empty = no override; cloudClient's resolveUrl
222
+ // Cloud endpoint OVERRIDES. Empty = no override; cloudClient's resolveUrl
223
223
  // owns the full precedence (override -> env -> Metro-derived dev default).
224
224
  // The value may be an explicit URL or the METRO_AUTO sentinel ("my dev
225
225
  // laptop", resolved live from Metro so it survives network changes). Never
@@ -241,7 +241,7 @@ export const SETTINGS = {
241
241
  persist: true,
242
242
  resetOnBuildEnvChange: true,
243
243
  },
244
- // Bookmarked Cloud V2 endpoint pairs. Each entry is {label, coreUrl,
244
+ // Bookmarked Cloud endpoint pairs. Each entry is {label, coreUrl,
245
245
  // runtimeUrl} — core + runtime are saved together because they are always
246
246
  // applied as a matched set (presets fill both; Save & Test verifies both).
247
247
  saved_cloud_url_pairs: {
@@ -368,7 +368,7 @@ export const SETTINGS = {
368
368
  persist: true,
369
369
  },
370
370
  location_tier: { key: "location_tier", defaultValue: () => "", writable: true, saveOnServer: true, persist: true },
371
- // Volatile bearer synced to Bluetooth for glasses-side Cloud V2 calls. The
371
+ // Volatile bearer synced to Bluetooth for glasses-side Cloud calls. The
372
372
  // key name is kept for BLE compatibility, but the value must never be loaded
373
373
  // from or saved to the legacy Cloud V1 settings store.
374
374
  core_token: { key: "core_token", defaultValue: () => "", writable: true, saveOnServer: false, persist: false },
@@ -700,10 +700,10 @@ export const SETTINGS = {
700
700
  },
701
701
  // Debug: route the R1 ring through the glasses (advStart + RING_CONNECT_INFO,
702
702
  // events forwarded by the CFW) instead of the phone link. OFF by default:
703
- // the ring sends its touch reports to the glasses whenever it holds glasses
704
- // targets, so the phone link only carries telemetry until those are erased.
705
- // Synced to the Bluetooth SDK, which re-routes a connected ring on change.
706
- // Device-local debug knob, so not saved on the server.
703
+ // the ring is a direct phone link whether or not a G2 is paired, which is
704
+ // how the Faceclaw reference client runs it. Synced to the Bluetooth SDK,
705
+ // which re-routes a connected ring on change. Device-local debug knob, so
706
+ // not saved on the server.
707
707
  ring_via_glasses: {
708
708
  key: "ring_via_glasses",
709
709
  defaultValue: () => false,
@@ -711,6 +711,24 @@ export const SETTINGS = {
711
711
  saveOnServer: false,
712
712
  persist: true,
713
713
  },
714
+ // Meta Neural Band: the air mouse streams the band's orientation at 128 Hz, so it
715
+ // stays off unless asked for. The band side is pushed when the band connects.
716
+ neural_band_air_mouse: {
717
+ key: "neural_band_air_mouse",
718
+ defaultValue: () => false,
719
+ writable: true,
720
+ saveOnServer: false,
721
+ persist: true,
722
+ },
723
+ // Which wrist wears the band: flips the air mouse's forearm axis and is written
724
+ // to the band's own hand setting on connect.
725
+ neural_band_hand: {
726
+ key: "neural_band_hand",
727
+ defaultValue: () => "right",
728
+ writable: true,
729
+ saveOnServer: false,
730
+ persist: true,
731
+ },
714
732
  // Maximum rate at which display updates leave the phone for the glasses.
715
733
  // The Bluetooth SDK paces every scene frame and legacy layout to this,
716
734
  // coalescing faster updates last-wins; clears bypass it. No effect on G2