@ephia/dova-sdk 1.0.0

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 (247) hide show
  1. package/README.md +89 -0
  2. package/dist/EphiaBinding-BvRmlqqC.d.ts +36 -0
  3. package/dist/EphiaFloatingButton-CxiF86VW.d.ts +65 -0
  4. package/dist/EphiaTextarea-B4_CAVUg.d.ts +183 -0
  5. package/dist/NativeBinding-ChG0GeSz.d.ts +53 -0
  6. package/dist/TargetBinding-BKGQwUMc.d.ts +89 -0
  7. package/dist/TiptapBinding-B-agfV2H.d.ts +45 -0
  8. package/dist/Transport-zdeA4Pou.d.ts +63 -0
  9. package/dist/audio-state-kZ3KSvux.d.ts +39 -0
  10. package/dist/chunk-35AJK2IO.js +1 -0
  11. package/dist/chunk-35AJK2IO.js.map +1 -0
  12. package/dist/chunk-3LXZODL4.js +886 -0
  13. package/dist/chunk-3LXZODL4.js.map +1 -0
  14. package/dist/chunk-5IK5TLSK.js +67 -0
  15. package/dist/chunk-5IK5TLSK.js.map +1 -0
  16. package/dist/chunk-7E43RY75.js +9 -0
  17. package/dist/chunk-7E43RY75.js.map +1 -0
  18. package/dist/chunk-A5UEXJ5R.js +183 -0
  19. package/dist/chunk-A5UEXJ5R.js.map +1 -0
  20. package/dist/chunk-AEE554FT.js +51 -0
  21. package/dist/chunk-AEE554FT.js.map +1 -0
  22. package/dist/chunk-DIEWY3IT.js +1332 -0
  23. package/dist/chunk-DIEWY3IT.js.map +1 -0
  24. package/dist/chunk-EGIAN7FH.js +18 -0
  25. package/dist/chunk-EGIAN7FH.js.map +1 -0
  26. package/dist/chunk-EMOEAPVU.js +486 -0
  27. package/dist/chunk-EMOEAPVU.js.map +1 -0
  28. package/dist/chunk-IDC7FHIZ.js +40 -0
  29. package/dist/chunk-IDC7FHIZ.js.map +1 -0
  30. package/dist/chunk-ITJFN3VM.js +601 -0
  31. package/dist/chunk-ITJFN3VM.js.map +1 -0
  32. package/dist/chunk-K24GNU27.js +22 -0
  33. package/dist/chunk-K24GNU27.js.map +1 -0
  34. package/dist/chunk-LXMCRXXF.js +778 -0
  35. package/dist/chunk-LXMCRXXF.js.map +1 -0
  36. package/dist/chunk-MJCEOOLW.js +122 -0
  37. package/dist/chunk-MJCEOOLW.js.map +1 -0
  38. package/dist/chunk-N7U5M3VZ.js +33 -0
  39. package/dist/chunk-N7U5M3VZ.js.map +1 -0
  40. package/dist/chunk-PSYX674B.js +27 -0
  41. package/dist/chunk-PSYX674B.js.map +1 -0
  42. package/dist/chunk-RFQRV7ML.js +33 -0
  43. package/dist/chunk-RFQRV7ML.js.map +1 -0
  44. package/dist/chunk-THNHRV2B.js +18 -0
  45. package/dist/chunk-THNHRV2B.js.map +1 -0
  46. package/dist/chunk-VSLGR64U.js +62 -0
  47. package/dist/chunk-VSLGR64U.js.map +1 -0
  48. package/dist/chunk-W2ZP674X.js +346 -0
  49. package/dist/chunk-W2ZP674X.js.map +1 -0
  50. package/dist/chunk-YWZUMUYE.js +695 -0
  51. package/dist/chunk-YWZUMUYE.js.map +1 -0
  52. package/dist/client-options-Uo6jXO8k.d.ts +64 -0
  53. package/dist/connection-state-Bk33YprE.d.ts +32 -0
  54. package/dist/core/bindings/index.d.ts +24 -0
  55. package/dist/core/bindings/index.js +1025 -0
  56. package/dist/core/bindings/index.js.map +1 -0
  57. package/dist/core/index.d.ts +383 -0
  58. package/dist/core/index.js +1284 -0
  59. package/dist/core/index.js.map +1 -0
  60. package/dist/createEphiaClient-BhdZ183V.d.ts +69 -0
  61. package/dist/devices/speechmike/index.d.ts +148 -0
  62. package/dist/devices/speechmike/index.js +40 -0
  63. package/dist/devices/speechmike/index.js.map +1 -0
  64. package/dist/headless/index.d.ts +10 -0
  65. package/dist/headless/index.js +25 -0
  66. package/dist/headless/index.js.map +1 -0
  67. package/dist/index.d.ts +18 -0
  68. package/dist/index.js +119 -0
  69. package/dist/index.js.map +1 -0
  70. package/dist/react/index.d.ts +38 -0
  71. package/dist/react/index.js +70 -0
  72. package/dist/react/index.js.map +1 -0
  73. package/dist/rich-editor/index.d.ts +46 -0
  74. package/dist/rich-editor/index.js +13 -0
  75. package/dist/rich-editor/index.js.map +1 -0
  76. package/dist/schema-B2ycPlNB.d.ts +87 -0
  77. package/dist/session-APaXR48R.d.ts +12 -0
  78. package/dist/shared/index.d.ts +16 -0
  79. package/dist/shared/index.js +30 -0
  80. package/dist/shared/index.js.map +1 -0
  81. package/dist/style.css +1093 -0
  82. package/dist/testing/index.d.ts +84 -0
  83. package/dist/testing/index.js +36 -0
  84. package/dist/testing/index.js.map +1 -0
  85. package/dist/types-D5SXPSwR.d.ts +32 -0
  86. package/dist/ui/index.d.ts +30 -0
  87. package/dist/ui/index.js +34 -0
  88. package/dist/ui/index.js.map +1 -0
  89. package/dist/useEphiaSpeechMike-CjD7DWnh.d.ts +64 -0
  90. package/package.json +110 -0
  91. package/src/core/audio/audio-worklet-source.ts +30 -0
  92. package/src/core/audio/index.ts +3 -0
  93. package/src/core/audio/voice-level-meter.test.ts +27 -0
  94. package/src/core/audio/voice-level-meter.ts +270 -0
  95. package/src/core/bindings/EphiaBinding.ts +41 -0
  96. package/src/core/bindings/SegmentBindingBridge.test.ts +422 -0
  97. package/src/core/bindings/SegmentBindingBridge.ts +377 -0
  98. package/src/core/bindings/TargetBinding.ts +142 -0
  99. package/src/core/bindings/adapters/NativeAdapter.test.ts +85 -0
  100. package/src/core/bindings/adapters/NativeAdapter.ts +216 -0
  101. package/src/core/bindings/adapters/ProseMirrorAdapter.ts +231 -0
  102. package/src/core/bindings/adapters/index.ts +2 -0
  103. package/src/core/bindings/binding-factory.ts +78 -0
  104. package/src/core/bindings/detect-editor-type.ts +87 -0
  105. package/src/core/bindings/index.ts +13 -0
  106. package/src/core/bindings/insertion-boundary.test.ts +38 -0
  107. package/src/core/bindings/insertion-boundary.ts +26 -0
  108. package/src/core/bindings/native/NativeBinding.test.ts +277 -0
  109. package/src/core/bindings/native/NativeBinding.ts +239 -0
  110. package/src/core/bindings/resolver.ts +18 -0
  111. package/src/core/bindings/targets/codemirror.binding.ts +293 -0
  112. package/src/core/bindings/targets/contenteditable.binding.ts +452 -0
  113. package/src/core/bindings/targets/index.ts +10 -0
  114. package/src/core/bindings/targets/monaco.binding.ts +315 -0
  115. package/src/core/bindings/targets/tiptap.binding.test.ts +417 -0
  116. package/src/core/bindings/targets/tiptap.binding.ts +1192 -0
  117. package/src/core/bindings/tiptap/TiptapBinding.test.ts +63 -0
  118. package/src/core/bindings/tiptap/TiptapBinding.ts +464 -0
  119. package/src/core/bindings/types.ts +41 -0
  120. package/src/core/client/EphiaAudioClient.ts +654 -0
  121. package/src/core/client/audio-capture.ts +263 -0
  122. package/src/core/client/client-options.ts +39 -0
  123. package/src/core/client/client-state.ts +18 -0
  124. package/src/core/client/constants.ts +23 -0
  125. package/src/core/client/session-api.ts +415 -0
  126. package/src/core/connection/connection-state.ts +78 -0
  127. package/src/core/connection/index.ts +6 -0
  128. package/src/core/index.ts +47 -0
  129. package/src/core/operations/textToDocumentOperations.test.ts +69 -0
  130. package/src/core/operations/textToDocumentOperations.ts +92 -0
  131. package/src/core/runtime/DictationRuntime.test.ts +578 -0
  132. package/src/core/runtime/DictationRuntime.ts +434 -0
  133. package/src/core/runtime/TranscriptApplier.test.ts +355 -0
  134. package/src/core/runtime/TranscriptApplier.ts +229 -0
  135. package/src/core/runtime/index.ts +18 -0
  136. package/src/core/session/index.ts +2 -0
  137. package/src/core/session/session-machine.test.ts +16 -0
  138. package/src/core/session/session-machine.ts +59 -0
  139. package/src/core/targets/EditorContextCollector.ts +71 -0
  140. package/src/core/targets/TargetManager.test.ts +194 -0
  141. package/src/core/targets/TargetManager.ts +194 -0
  142. package/src/core/targets/index.ts +10 -0
  143. package/src/core/text-processing/index.ts +11 -0
  144. package/src/core/text-processing/overlap.test.ts +35 -0
  145. package/src/core/text-processing/overlap.ts +101 -0
  146. package/src/core/text-processing/voice-formatting.normalizer.test.ts +132 -0
  147. package/src/core/text-processing/voice-formatting.normalizer.ts +284 -0
  148. package/src/core/transcript/client-transcript.reducer.ts +366 -0
  149. package/src/core/transcript/client-transcript.state.ts +25 -0
  150. package/src/core/transcript/index.ts +19 -0
  151. package/src/core/transcript/transcript.assembler.test.ts +205 -0
  152. package/src/core/transcript/transcript.assembler.ts +152 -0
  153. package/src/core/transcript/transcript.reducer.test.ts +199 -0
  154. package/src/core/transcript/transcript.reducer.ts +771 -0
  155. package/src/core/transcript/transcript.state.ts +123 -0
  156. package/src/core/transport/LiveKitTransport.publish.test.ts +226 -0
  157. package/src/core/transport/LiveKitTransport.ts +459 -0
  158. package/src/core/transport/MockTransport.ts +231 -0
  159. package/src/core/transport/Transport.ts +82 -0
  160. package/src/debug/sdk-debug-collector.ts +79 -0
  161. package/src/devices/index.ts +2 -0
  162. package/src/devices/speechmike/__tests__/EphiaSpeechMikeProvider.test.tsx +99 -0
  163. package/src/devices/speechmike/__tests__/speechmike-audio-resolver.test.ts +96 -0
  164. package/src/devices/speechmike/__tests__/speechmike-button-router.test.ts +66 -0
  165. package/src/devices/speechmike/__tests__/speechmike-device-manager.test.ts +201 -0
  166. package/src/devices/speechmike/__tests__/speechmike-led-controller.test.ts +68 -0
  167. package/src/devices/speechmike/browser.ts +80 -0
  168. package/src/devices/speechmike/constants.ts +74 -0
  169. package/src/devices/speechmike/dictation-support-loader.ts +81 -0
  170. package/src/devices/speechmike/index.ts +11 -0
  171. package/src/devices/speechmike/react/EphiaSpeechMikeContext.ts +34 -0
  172. package/src/devices/speechmike/react/EphiaSpeechMikeProvider.tsx +287 -0
  173. package/src/devices/speechmike/react/useEphiaSpeechMike.ts +26 -0
  174. package/src/devices/speechmike/speechmike-audio-resolver.ts +58 -0
  175. package/src/devices/speechmike/speechmike-button-router.ts +73 -0
  176. package/src/devices/speechmike/speechmike-device-manager.ts +461 -0
  177. package/src/devices/speechmike/speechmike-led-controller.ts +78 -0
  178. package/src/devices/speechmike/types.ts +96 -0
  179. package/src/dictation_support.d.ts +31 -0
  180. package/src/global.d.ts +10 -0
  181. package/src/headless/createEphiaClient.ts +220 -0
  182. package/src/headless/index.ts +18 -0
  183. package/src/index.ts +89 -0
  184. package/src/react/EphiaAuto.tsx +87 -0
  185. package/src/react/components/EphiaDictationButton.tsx +88 -0
  186. package/src/react/components/EphiaStatusBar.tsx +59 -0
  187. package/src/react/components/EphiaTextarea.tsx +295 -0
  188. package/src/react/ephia-react.css +318 -0
  189. package/src/react/hooks/targets/index.ts +3 -0
  190. package/src/react/hooks/targets/useEphiaCodemirror.ts +35 -0
  191. package/src/react/hooks/targets/useEphiaMonaco.ts +35 -0
  192. package/src/react/hooks/targets/useEphiaTiptap.ts +23 -0
  193. package/src/react/hooks/useEphia.lifecycle.test.tsx +389 -0
  194. package/src/react/hooks/useEphia.ts +367 -0
  195. package/src/react/hooks/useEphiaDiscardTarget.ts +53 -0
  196. package/src/react/hooks/useEphiaServerEvent.ts +33 -0
  197. package/src/react/hooks/useEphiaTarget.ts +47 -0
  198. package/src/react/hooks/useEphiaTranscript.ts +22 -0
  199. package/src/react/index.ts +58 -0
  200. package/src/react/provider/EphiaContext.ts +63 -0
  201. package/src/react/provider/EphiaInternalContext.ts +32 -0
  202. package/src/react/provider/EphiaProvider.tsx +373 -0
  203. package/src/react/registry/binding-factory.ts +7 -0
  204. package/src/react/registry/detect-editor-type.ts +2 -0
  205. package/src/react/registry/events.ts +37 -0
  206. package/src/react/registry/registries/CodeMirrorInstanceRegistry.ts +24 -0
  207. package/src/react/registry/registries/MonacoInstanceRegistry.ts +23 -0
  208. package/src/react/registry/registries/TargetRegistry.ts +327 -0
  209. package/src/react/registry/registries/TiptapInstanceRegistry.ts +43 -0
  210. package/src/react/registry/registries/index.ts +5 -0
  211. package/src/react/store/create-ephia-store.ts +36 -0
  212. package/src/react/store/types.ts +41 -0
  213. package/src/react/utils/flash-range.ts +24 -0
  214. package/src/react/utils/index.ts +1 -0
  215. package/src/rich-editor/adapters/tiptap.test.ts +86 -0
  216. package/src/rich-editor/adapters/tiptap.ts +23 -0
  217. package/src/rich-editor/index.ts +3 -0
  218. package/src/rich-editor/types.ts +24 -0
  219. package/src/rich-editor/use-ephia-rich-editor.test.tsx +202 -0
  220. package/src/rich-editor/use-ephia-rich-editor.ts +47 -0
  221. package/src/shared/config/endpoint.test.ts +45 -0
  222. package/src/shared/config/endpoint.ts +39 -0
  223. package/src/shared/config/schema.ts +32 -0
  224. package/src/shared/effective-text.ts +13 -0
  225. package/src/shared/errors/EphiaSdkError.ts +54 -0
  226. package/src/shared/errors/messages.ts +40 -0
  227. package/src/shared/index.ts +27 -0
  228. package/src/shared/state/audio-state.ts +45 -0
  229. package/src/shared/state/index.ts +2 -0
  230. package/src/shared/store/document-store.ts +32 -0
  231. package/src/shared/store/index.ts +2 -0
  232. package/src/shared/types/editors.ts +28 -0
  233. package/src/shared/types/session.ts +12 -0
  234. package/src/style.css +2 -0
  235. package/src/testing/index.tsx +60 -0
  236. package/src/ui/assets/ephia-logo.svg +4 -0
  237. package/src/ui/components/EphiaLogo.tsx +77 -0
  238. package/src/ui/index.ts +24 -0
  239. package/src/ui/primitives/Button.tsx +53 -0
  240. package/src/ui/primitives/Spinner.tsx +21 -0
  241. package/src/ui/primitives/index.ts +5 -0
  242. package/src/ui/recorder/EphiaFloatingButton.tsx +489 -0
  243. package/src/ui/recorder/MinimalProcessingBars.tsx +122 -0
  244. package/src/ui/recorder/StandardIntensityVisualizer.tsx +148 -0
  245. package/src/ui/recorder/appearance.ts +9 -0
  246. package/src/ui/recorder/index.ts +8 -0
  247. package/src/ui/theme.css +775 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/core/transport/MockTransport.ts","../../src/core/transcript/client-transcript.state.ts","../../src/core/transcript/transcript.assembler.ts","../../src/core/transcript/client-transcript.reducer.ts","../../src/core/transcript/transcript.state.ts","../../src/core/transcript/transcript.reducer.ts","../../src/core/targets/EditorContextCollector.ts"],"sourcesContent":["/**\n * Transport mock pour tests, storybook et sandbox sans backend.\n */\n\nimport type { EphiaAudioEvent, EphiaClientMessage, EphiaServerEvent } from \"ephia-protocol\";\nimport { PROTOCOL_VERSION, ephiaAudioEventSchema } from \"ephia-protocol\";\nimport { EphiaSdkError } from \"../../shared/errors/EphiaSdkError\";\nimport type {\n Transport,\n TransportConnectParams,\n TransportState,\n} from \"./Transport\";\n\nfunction uuid(): string {\n const c = globalThis.crypto;\n if (c?.randomUUID) return c.randomUUID();\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;\n}\n\ntype MockScriptStep = {\n type: string;\n delayMs: number;\n payload?: Record<string, unknown>;\n};\n\ntype MockTransportOptions = {\n script?: MockScriptStep[];\n autoEmitReady?: boolean;\n latencyMs?: number;\n};\n\nexport class MockTransport implements Transport {\n private _state: TransportState = {\n status: \"idle\",\n localAudioPublished: false,\n localAudioMuted: false,\n reconnectCount: 0,\n };\n\n private _eventCallbacks: Array<(event: EphiaAudioEvent) => void> = [];\n private _serverEventCallbacks: Array<(event: EphiaServerEvent) => void> = [];\n private _stateCallbacks: Array<(state: TransportState) => void> = [];\n private _errorCallbacks: Array<(error: EphiaSdkError) => void> = [];\n private _running = false;\n private _scriptTimer: ReturnType<typeof setTimeout> | null = null;\n private _options: MockTransportOptions;\n\n constructor(options: MockTransportOptions = {}) {\n this._options = options;\n }\n\n async connect(params: TransportConnectParams): Promise<void> {\n this._running = true;\n this._setState({ status: \"connecting\", roomName: params.roomName });\n\n await this._delay(this._options.latencyMs ?? 100);\n\n if (!this._running) return;\n\n this._setState({ status: \"connected\" });\n\n if (this._options.autoEmitReady !== false) {\n this._emit({\n protocolVersion: PROTOCOL_VERSION,\n eventId: \"00000000-0000-4000-8000-000000000001\",\n sessionId: \"mock-session\",\n type: \"session.ready\",\n seq: 0,\n timestampMs: Date.now(),\n payload: { roomName: params.roomName },\n });\n }\n\n this._runScript();\n }\n\n async disconnect(_reason?: string): Promise<void> {\n this._running = false;\n if (this._scriptTimer) {\n clearTimeout(this._scriptTimer);\n this._scriptTimer = null;\n }\n this._setState({ status: \"disconnected\" });\n }\n\n async publishAudio(_track: MediaStreamTrack): Promise<void> {\n this._setState({ localAudioPublished: true });\n }\n\n async unpublishAudio(): Promise<void> {\n this._setState({ localAudioPublished: false });\n }\n\n async sendMessage(message: EphiaClientMessage): Promise<void> {\n if (message.type === \"session.stop\") {\n this._emit({\n protocolVersion: PROTOCOL_VERSION,\n eventId: \"00000000-0000-4000-8000-000000000002\",\n sessionId: \"mock-session\",\n type: \"session.closed\",\n seq: 999,\n timestampMs: Date.now(),\n payload: { reason: \"user_stop\" },\n });\n }\n }\n\n onEvent(callback: (event: EphiaAudioEvent) => void): () => void {\n this._eventCallbacks.push(callback);\n return () => {\n this._eventCallbacks = this._eventCallbacks.filter((c) => c !== callback);\n };\n }\n\n onServerEvent(callback: (event: EphiaServerEvent) => void): () => void {\n this._serverEventCallbacks.push(callback);\n return () => {\n this._serverEventCallbacks = this._serverEventCallbacks.filter((c) => c !== callback);\n };\n }\n\n onTransportState(callback: (state: TransportState) => void): () => void {\n this._stateCallbacks.push(callback);\n return () => {\n this._stateCallbacks = this._stateCallbacks.filter((c) => c !== callback);\n };\n }\n\n onError(callback: (error: EphiaSdkError) => void): () => void {\n this._errorCallbacks.push(callback);\n return () => {\n this._errorCallbacks = this._errorCallbacks.filter((c) => c !== callback);\n };\n }\n\n getState(): TransportState {\n return { ...this._state };\n }\n\n async prepareConnection(_url: string, _token?: string): Promise<void> {\n // no-op in mock\n }\n\n async performRpc(method: string, payload: unknown, _timeout?: number): Promise<string> {\n if (method === \"ephia.session.sync\") {\n const lastSeq = Number((payload as { lastSeq?: number } | undefined)?.lastSeq ?? 0);\n return JSON.stringify({\n status: \"ok\",\n mode: \"replay\",\n fromSeq: lastSeq,\n toSeq: lastSeq,\n events: [],\n });\n }\n // Délègue vers sendMessage pour que les sous-classes de test (PauseAckTransport, etc.)\n // puissent continuer à intercepter via sendMessage sans modification.\n const msgType = method.replace(\"ephia.\", \"\") as EphiaClientMessage[\"type\"];\n await this.sendMessage({ type: msgType, payload: payload as any } as EphiaClientMessage);\n return JSON.stringify({ status: \"ok\" });\n }\n\n /** Émet manuellement un event legacy (utile pour les tests). */\n simulateEvent(event: EphiaAudioEvent): void {\n this._emit(event);\n }\n\n /** Émet manuellement un event serveur V2 (utile pour les tests de TranscriptApplier). */\n simulateServerEvent(event: EphiaServerEvent): void {\n this._serverEventCallbacks.forEach((cb) => cb(event));\n }\n\n /** Force manuellement un état transport (utile pour les tests). */\n simulateState(state: Partial<TransportState>): void {\n this._setState(state);\n }\n\n // ------------------------------------------------------------------\n // Internals\n // ------------------------------------------------------------------\n\n private _setState(partial: Partial<TransportState>): void {\n this._state = { ...this._state, ...partial };\n this._stateCallbacks.forEach((cb) => cb(this._state));\n }\n\n private _emit(event: EphiaAudioEvent): void {\n const parsed = ephiaAudioEventSchema.safeParse(event);\n if (!parsed.success) {\n console.warn(\n \"[MockTransport] invalid event schema (ignored):\",\n parsed.error.issues\n );\n return;\n }\n this._eventCallbacks.forEach((cb) => cb(parsed.data));\n }\n\n private async _delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n private _runScript(): void {\n const script = this._options.script ?? [];\n let index = 0;\n\n const runNext = () => {\n if (!this._running || index >= script.length) return;\n const step = script[index];\n index++;\n\n this._scriptTimer = setTimeout(() => {\n if (!this._running) return;\n\n const baseEvent: EphiaAudioEvent = {\n protocolVersion: PROTOCOL_VERSION,\n eventId: `00000000-0000-4000-8000-${String(index).padStart(12, \"0\")}`,\n sessionId: \"mock-session\",\n type: step.type as any,\n seq: index,\n timestampMs: Date.now(),\n payload: (step.payload ?? {}) as any,\n };\n\n this._emit(baseEvent);\n runNext();\n }, step.delayMs);\n };\n\n runNext();\n }\n}\n","export interface TranscriptSegment {\n segmentId: string;\n segmentSeq: number;\n partialText: string | null;\n finalText: string | null;\n committedText: string | null;\n isFinalized: boolean;\n isCommitted: boolean;\n revision: number;\n stable: boolean;\n source: string | null;\n mergedWith: string | string[] | null;\n}\n\nexport interface TranscriptState {\n segments: TranscriptSegment[];\n currentSegmentId: string | null;\n documentText: string;\n}\n\nexport const initialTranscriptState: TranscriptState = {\n segments: [],\n currentSegmentId: null,\n documentText: \"\",\n};\n","import type { LiveTranscriptChunk } from \"./transcript.state\";\n\nfunction trimBoundarySpaces(text: string): string {\n return text\n .replace(/\\r\\n/g, \"\\n\")\n .replace(/\\r/g, \"\\n\")\n .replace(/^[ \\t]+|[ \\t]+$/g, \"\");\n}\n\n/**\n * Joint deux morceaux de texte avec gestion intelligente des espaces et de la ponctuation.\n * Exported pour être réutilisé dans les autres reducers.\n */\nexport function joinWithSpacing(prev: string, next: string): string {\n if (!prev) return next;\n if (!next) return prev;\n const lastChar = prev.slice(-1);\n const firstChar = next.charAt(0);\n if (lastChar === \" \" && firstChar === \" \") return prev + next.trimStart();\n if (/\\s/.test(lastChar) || /\\s/.test(firstChar)) return prev + next;\n if (/[,.;:!?)\\]]/.test(firstChar)) return prev + next;\n return prev + \" \" + next;\n}\n\n/**\n * Assemble les chunks en texte cohérent.\n *\n * Règles :\n * - tri par segmentSeq\n * - pas de double espace\n * - espace après ponctuation si manquant\n * - ignorer les chunks error sans texte\n */\nexport function assembleTranscript(chunks: LiveTranscriptChunk[]): string {\n const sorted = [...chunks]\n .filter((c) => (c.status === \"done\" || c.finalizedText) && (c.text || c.finalizedText))\n .sort((a, b) => a.segmentSeq - b.segmentSeq);\n\n if (sorted.length === 0) return \"\";\n\n let result = \"\";\n for (let i = 0; i < sorted.length; i++) {\n const chunk = sorted[i];\n let text = trimBoundarySpaces(chunk.text || chunk.finalizedText || \"\");\n\n if (i === 0) {\n result = text;\n continue;\n }\n\n const prev = result;\n const lastChar = prev.slice(-1);\n const firstChar = text.charAt(0);\n\n // Règles d'espacement\n if (lastChar.match(/[.!?;,:\\)]/) && firstChar.match(/[a-zA-ZÀ-ÿ0-9]/)) {\n result = prev + \" \" + text;\n } else if (/\\s/.test(lastChar) && /\\s/.test(firstChar)) {\n result = prev + text.trimStart();\n } else if (\n !/\\s/.test(lastChar) &&\n !/\\s/.test(firstChar) &&\n firstChar.match(/[a-zA-ZÀ-ÿ0-9]/)\n ) {\n result = prev + \" \" + text;\n } else {\n result = prev + text;\n }\n }\n\n return result;\n}\n\n/**\n * Assemble les chunks commités en document texte.\n *\n * Règles :\n * - tri par segmentSeq\n * - utilise committedText ou text si disponible\n * - ignore les chunks fusionnés (mergedWith présent)\n */\nexport function assembleCommittedDocument(\n chunks: Record<string, LiveTranscriptChunk>,\n orderedSegmentIds: string[]\n): string {\n const sorted = [...orderedSegmentIds]\n .map((id) => chunks[id])\n .filter((c): c is LiveTranscriptChunk => !!c && c.status === \"done\")\n .filter((c) => !c.mergedWith || Array.isArray(c.mergedWith))\n .sort((a, b) => a.segmentSeq - b.segmentSeq);\n\n if (sorted.length === 0) return \"\";\n\n let result = \"\";\n for (let i = 0; i < sorted.length; i++) {\n const chunk = sorted[i];\n const text = trimBoundarySpaces(chunk.committedText ?? chunk.text ?? \"\");\n if (!text) continue;\n\n if (i === 0) {\n result = text;\n continue;\n }\n\n const prev = result;\n const lastChar = prev.slice(-1);\n const firstChar = text.charAt(0);\n\n if (lastChar.match(/[.!?;,:\\)]/) && firstChar.match(/[a-zA-ZÀ-ÿ0-9]/)) {\n result = prev + \" \" + text;\n } else if (/\\s/.test(lastChar) && /\\s/.test(firstChar)) {\n result = prev + text.trimStart();\n } else if (\n !/\\s/.test(lastChar) &&\n !/\\s/.test(firstChar) &&\n firstChar.match(/[a-zA-ZÀ-ÿ0-9]/)\n ) {\n result = prev + \" \" + text;\n } else {\n result = prev + text;\n }\n }\n\n return result;\n}\n\n/**\n * Construit le texte d'affichage complet :\n * finalText + previewText du chunk courant.\n */\nconst PUNCTUATION_NO_SPACE = new Set([\",\", \".\", \";\", \":\", \"!\", \"?\", \")\", \"]\", \"}\"]);\n\nexport function buildDisplayText(\n finalText: string,\n previewText: string,\n previewContinuesPreviousWord = false\n): string {\n if (!finalText && !previewText) return \"\";\n if (!finalText) return previewText;\n if (!previewText) return finalText;\n // trimEnd() supprimerait les \\n intentionnels (commandes \"à la ligne\")\n const prev = finalText.replace(/[ \\t]+$/, \"\");\n const next = previewText.trimStart();\n if (!next) return prev;\n if (previewContinuesPreviousWord) return prev + next;\n const firstChar = next[0];\n if (firstChar && PUNCTUATION_NO_SPACE.has(firstChar)) {\n return prev + next;\n }\n if (prev.endsWith(\"\\n\")) return prev + next;\n return prev + \" \" + next;\n}\n","import type {\n EphiaAudioEvent,\n TranscriptFinalEvent,\n TranscriptPreviewEvent,\n TranscriptPreviewStableEvent,\n TranscriptSegmentCommittedEvent,\n TranscriptSegmentReadyEvent,\n DocumentPatchEvent,\n} from \"ephia-protocol\";\nimport type { TranscriptState, TranscriptSegment } from \"./client-transcript.state\";\nimport { initialTranscriptState } from \"./client-transcript.state\";\nimport { joinWithSpacing } from \"./transcript.assembler\";\nimport { pickEffectiveText } from \"../../shared/effective-text\";\n\nexport function eventReducer(\n state: TranscriptState,\n event: EphiaAudioEvent\n): TranscriptState {\n switch (event.type) {\n case \"transcript.preview\":\n return handlePartial(state, event);\n case \"transcript.preview.stable\":\n return handleStable(state, event);\n case \"transcript.final\":\n return handleFinal(state, event);\n case \"transcript.segment.ready\":\n return handleChunkFinalized(state, event);\n case \"transcript.segment.committed\":\n return handleChunkCommitted(state, event);\n case \"session.context.reset\":\n return handleSessionContextReset(state, event);\n case \"document.patch\":\n return handleDocumentPatch(state, event);\n case \"segment.absorbed\": {\n const absorbedId = event.payload.segmentId;\n const absorbedInto = event.payload.absorbedInto;\n const newSegments = state.segments.map((s: TranscriptSegment) =>\n s.segmentId === absorbedId\n ? {\n ...s,\n isCommitted: true,\n committedText: null,\n partialText: null,\n finalText: null,\n mergedWith: absorbedInto,\n }\n : s\n );\n return { ...state, segments: newSegments };\n }\n default:\n return state;\n }\n}\n\nfunction handlePartial(\n state: TranscriptState,\n event: TranscriptPreviewEvent\n): TranscriptState {\n const existing = state.segments.find(\n (s: TranscriptSegment) => s.segmentId === event.payload.segmentId\n );\n\n if (existing) {\n if (existing.isCommitted) {\n return state;\n }\n // Fix 2.1 — bloquer seulement si texte identique ET révision identique\n if (\n event.payload.revision < existing.revision ||\n (event.payload.revision === existing.revision &&\n event.payload.text === existing.partialText)\n ) {\n return state;\n }\n return {\n ...state,\n segments: state.segments.map((s: TranscriptSegment) =>\n s.segmentId === event.payload.segmentId\n ? {\n ...s,\n partialText: event.payload.text,\n revision: event.payload.revision,\n stable: (event.payload as { stable?: boolean }).stable ?? false,\n }\n : s\n ),\n };\n }\n\n // Nouveau segment\n return {\n ...state,\n currentSegmentId: event.payload.segmentId,\n segments: [\n ...state.segments,\n {\n segmentId: event.payload.segmentId,\n segmentSeq: event.payload.segmentSeq,\n partialText: event.payload.text,\n finalText: null,\n committedText: null,\n isFinalized: false,\n isCommitted: false,\n revision: event.payload.revision,\n stable: (event.payload as { stable?: boolean }).stable ?? false,\n source: null,\n mergedWith: null,\n },\n ],\n };\n}\n\nfunction handleStable(\n state: TranscriptState,\n event: TranscriptPreviewStableEvent\n): TranscriptState {\n return {\n ...state,\n segments: state.segments.map((s: TranscriptSegment) =>\n s.segmentId === event.payload.segmentId\n ? { ...s, stable: true, partialText: event.payload.text }\n : s\n ),\n };\n}\n\nfunction handleFinal(\n state: TranscriptState,\n event: TranscriptFinalEvent\n): TranscriptState {\n const existing = state.segments.find(\n (s: TranscriptSegment) => s.segmentId === event.payload.segmentId\n );\n\n if (!existing) {\n return {\n ...state,\n segments: [\n ...state.segments,\n {\n segmentId: event.payload.segmentId,\n segmentSeq: event.payload.segmentSeq,\n partialText: null,\n finalText: event.payload.text,\n committedText: null,\n isFinalized: true,\n isCommitted: false,\n revision: 0,\n stable: true,\n source: null,\n mergedWith: null,\n },\n ],\n };\n }\n\n return {\n ...state,\n segments: state.segments.map((s: TranscriptSegment) =>\n s.segmentId === event.payload.segmentId\n ? {\n ...s,\n finalText: event.payload.text,\n isFinalized: true,\n partialText: null,\n }\n : s\n ),\n };\n}\n\nfunction handleChunkFinalized(\n state: TranscriptState,\n event: TranscriptSegmentReadyEvent\n): TranscriptState {\n const effectiveText = pickEffectiveText(event.payload);\n const existing = state.segments.find(\n (s: TranscriptSegment) => s.segmentId === event.payload.segmentId\n );\n\n if (!existing) {\n return {\n ...state,\n segments: [\n ...state.segments,\n {\n segmentId: event.payload.segmentId,\n segmentSeq: event.payload.segmentSeq,\n partialText: null,\n finalText: effectiveText,\n committedText: null,\n isFinalized: true,\n isCommitted: false,\n revision: 0,\n stable: true,\n source: event.payload.provider ?? null,\n mergedWith: null,\n },\n ],\n };\n }\n\n return {\n ...state,\n segments: state.segments.map((s: TranscriptSegment) =>\n s.segmentId === event.payload.segmentId\n ? {\n ...s,\n finalText: effectiveText,\n isFinalized: true,\n }\n : s\n ),\n };\n}\n\nfunction handleChunkCommitted(\n state: TranscriptState,\n event: TranscriptSegmentCommittedEvent\n): TranscriptState {\n const { segmentId, source, mergedWith } = event.payload;\n const text = pickEffectiveText(event.payload);\n const mergedIds: string[] = mergedWith\n ? Array.isArray(mergedWith)\n ? mergedWith\n : [mergedWith]\n : [];\n\n const existing = state.segments.find(\n (s: TranscriptSegment) => s.segmentId === segmentId\n );\n\n let newSegments = existing\n ? state.segments.map((s: TranscriptSegment) =>\n s.segmentId === segmentId\n ? {\n ...s,\n committedText: text,\n isCommitted: true,\n partialText: null,\n finalText: text,\n source: source ?? null,\n mergedWith: mergedIds.length > 0 ? mergedIds : null,\n }\n : s\n )\n : [\n ...state.segments,\n {\n segmentId,\n segmentSeq: event.payload.segmentSeq,\n partialText: null,\n finalText: text,\n committedText: text,\n isFinalized: true,\n isCommitted: true,\n revision: 0,\n stable: true,\n source: source ?? null,\n mergedWith: mergedIds.length > 0 ? mergedIds : null,\n },\n ];\n\n // Marquer les segments absorbés comme superseded\n for (const absorbedId of mergedIds) {\n newSegments = newSegments.map((s: TranscriptSegment) =>\n s.segmentId === absorbedId\n ? {\n ...s,\n isCommitted: true,\n committedText: null,\n partialText: null,\n finalText: null,\n mergedWith: segmentId,\n }\n : s\n );\n }\n\n // Reconstruire le document text\n const documentText = newSegments\n .filter(\n (s) =>\n s.isCommitted &&\n s.committedText &&\n (typeof s.mergedWith !== \"string\")\n )\n .map((s) => s.committedText as string)\n .reduce((acc, text) => joinWithSpacing(acc, text), \"\");\n\n return {\n ...state,\n segments: newSegments,\n documentText,\n };\n}\n\nfunction handleSessionContextReset(\n state: TranscriptState,\n event: { payload: { contextOnly?: boolean } }\n): TranscriptState {\n const contextOnly = event.payload.contextOnly ?? false;\n if (!contextOnly) {\n return { ...initialTranscriptState };\n }\n // Fix 2.3 — contextOnly=true : conserver uniquement les segments committés\n const committedSegments = state.segments.filter((s) => s.isCommitted);\n const documentText = committedSegments\n .filter(\n (s) =>\n s.committedText && (typeof s.mergedWith !== \"string\")\n )\n .map((s) => s.committedText as string)\n .reduce((acc, t) => joinWithSpacing(acc, t), \"\");\n return {\n ...state,\n segments: committedSegments,\n currentSegmentId: null,\n documentText,\n };\n}\n\nfunction handleDocumentPatch(\n state: TranscriptState,\n event: DocumentPatchEvent\n): TranscriptState {\n let segments = [...state.segments];\n\n for (const op of event.payload.ops) {\n switch (op.type) {\n case \"merge\": {\n const fromSeg = segments.find((s: TranscriptSegment) => s.segmentId === op.from);\n const toSeg = segments.find((s: TranscriptSegment) => s.segmentId === op.to);\n if (fromSeg && toSeg) {\n segments = segments.map((s) =>\n s.segmentId === op.to\n ? { ...s, committedText: op.text ?? null, mergedWith: op.from ?? null }\n : s\n );\n }\n break;\n }\n case \"replace\": {\n segments = segments.map((s: TranscriptSegment) =>\n s.segmentId === op.blockId\n ? { ...s, committedText: op.text ?? null }\n : s\n );\n break;\n }\n }\n }\n\n const documentText = segments\n .filter(\n (s) =>\n s.isCommitted &&\n s.committedText &&\n (typeof s.mergedWith !== \"string\")\n )\n .map((s) => s.committedText as string)\n .reduce((acc, text) => joinWithSpacing(acc, text), \"\");\n\n return { ...state, segments, documentText };\n}\n","import type { EphiaAudioEvent, TranscriptSafetyMeta, TranscriptLayoutMeta } from \"ephia-protocol\";\n\nexport type LiveTranscriptStatus =\n | \"idle\"\n | \"connecting\"\n | \"recording\"\n | \"finalizing\"\n | \"ended\"\n | \"error\";\n\nexport type LiveTranscriptChunkStatus =\n | \"opened\"\n | \"processing\"\n | \"preview\"\n | \"done\"\n | \"error\";\n\nexport type LiveTranscriptChunk = {\n segmentId: string;\n segmentSeq: number;\n status: LiveTranscriptChunkStatus;\n text: string;\n previewText?: string;\n previewContinuesPreviousWord?: boolean;\n stablePrefix?: string;\n previewDelta?: string;\n finalizedText?: string;\n committedText?: string;\n revision: number;\n startedAtMs?: number;\n audioClosedAtMs?: number;\n endedAtMs?: number;\n durationMs?: number;\n provider?: string;\n error?: string;\n uncertain?: boolean;\n reason?: string;\n reasonCodes?: string[];\n parseFallback?: boolean;\n source?: string;\n mergedWith?: string | string[];\n\n // P1 backend : métadonnées additives — text/committedText/status restent\n // la vérité affichable, ces champs ne servent qu'au debug/observabilité.\n effectiveSource?: string;\n correctionPending?: boolean;\n correctionAccepted?: boolean;\n correctionRejectedReason?: string | null;\n commandsApplied?: string[];\n normalizationsApplied?: string[];\n safety?: TranscriptSafetyMeta;\n layout?: TranscriptLayoutMeta;\n rawStt?: string;\n realtimeText?: string;\n hintSentToSmall?: string | null;\n fallbackText?: string | null;\n smallRawText?: string;\n correctionOutcome?: string;\n debug?: Record<string, unknown>;\n};\n\nexport type LiveTranscriptDiagnostics = {\n mode?: \"time\" | \"vad\";\n eventsCount: number;\n chunksCount: number;\n processingChunks: number;\n doneChunks: number;\n errorChunks: number;\n seqValid: boolean;\n lastProvider?: string;\n lastLatencyMs?: number;\n averageLatencyMs?: number;\n finalTextLength: number;\n previewActive: boolean;\n uncertainChunks?: number;\n parseFallbackChunks?: number;\n contextChars?: number;\n};\n\nexport type LiveTranscriptState = {\n sessionId: string | null;\n status: LiveTranscriptStatus;\n events: EphiaAudioEvent[];\n chunks: Record<string, LiveTranscriptChunk>;\n orderedSegmentIds: string[];\n finalText: string;\n previewText: string;\n displayText: string;\n documentText: string;\n lastEvent: EphiaAudioEvent | null;\n diagnostics: LiveTranscriptDiagnostics;\n error: { code: string; message: string } | null;\n spinnerTick: number;\n finalizedBeforeReset?: Record<string, true>;\n};\n\nexport const initialLiveTranscriptState: LiveTranscriptState = {\n sessionId: null,\n status: \"idle\",\n events: [],\n chunks: {},\n orderedSegmentIds: [],\n finalText: \"\",\n previewText: \"\",\n displayText: \"\",\n documentText: \"\",\n lastEvent: null,\n diagnostics: {\n eventsCount: 0,\n chunksCount: 0,\n processingChunks: 0,\n doneChunks: 0,\n errorChunks: 0,\n seqValid: true,\n finalTextLength: 0,\n previewActive: false,\n uncertainChunks: 0,\n parseFallbackChunks: 0,\n contextChars: 0,\n },\n error: null,\n spinnerTick: 0,\n};\n","import type { EphiaAudioEvent, DocumentPatchEvent } from \"ephia-protocol\";\nimport type { LiveTranscriptState, LiveTranscriptChunk, LiveTranscriptDiagnostics } from \"./transcript.state\";\nimport { initialLiveTranscriptState } from \"./transcript.state\";\nimport { assembleTranscript, buildDisplayText, assembleCommittedDocument, joinWithSpacing } from \"./transcript.assembler\";\nimport { pickEffectiveText } from \"../../shared/effective-text\";\n\nexport type LiveTranscriptAction =\n | { type: \"event\"; event: EphiaAudioEvent }\n | { type: \"reset\" }\n | { type: \"remove_segments\"; segmentIds: string[] }\n | { type: \"client_error\"; error: { code: string; message: string } }\n | { type: \"tick\" };\n\nexport function liveTranscriptReducer(\n state: LiveTranscriptState,\n action: LiveTranscriptAction\n): LiveTranscriptState {\n if (action.type === \"reset\") {\n return { ...initialLiveTranscriptState };\n }\n\n if (action.type === \"remove_segments\") {\n const removeSet = new Set(action.segmentIds);\n if (removeSet.size === 0) return state;\n const newChunks: Record<string, LiveTranscriptChunk> = {};\n for (const [id, chunk] of Object.entries(state.chunks)) {\n if (!removeSet.has(id)) {\n newChunks[id] = chunk;\n }\n }\n const orderedSegmentIds = state.orderedSegmentIds.filter(\n (id) => !removeSet.has(id)\n );\n const documentText = assembleCommittedDocument(newChunks, orderedSegmentIds);\n return {\n ...state,\n chunks: newChunks,\n orderedSegmentIds,\n documentText,\n diagnostics: computeDiagnostics(\n newChunks,\n orderedSegmentIds,\n state.diagnostics,\n state.finalText,\n state.previewText\n ),\n };\n }\n\n if (action.type === \"client_error\") {\n return {\n ...state,\n status: \"error\",\n error: action.error,\n };\n }\n\n if (action.type === \"tick\") {\n const hasProcessing = Object.values(state.chunks).some(\n (c) => c.status === \"opened\" || c.status === \"processing\"\n );\n if (!hasProcessing) return state;\n const nextTick = state.spinnerTick + 1;\n const previewText = buildPreviewText(state.chunks, state.orderedSegmentIds, nextTick);\n return {\n ...state,\n spinnerTick: nextTick,\n previewText,\n displayText: buildLiveDisplayText(state.chunks, state.orderedSegmentIds, state.finalText, previewText),\n diagnostics: computeDiagnostics(state.chunks, state.orderedSegmentIds, state.diagnostics, state.finalText, previewText),\n };\n }\n\n if (action.type !== \"event\") {\n return state;\n }\n\n const event = action.event;\n\n // Vérifier séquence monotone (strictement consécutive)\n // Après un session.sync réussi, les events redeviennent consécutifs :\n // on autorise la réparation automatique de seqValid.\n const lastSeq = state.lastEvent?.seq;\n const isFirstEvent = lastSeq === undefined;\n const isConsecutive = lastSeq !== undefined && event.seq === lastSeq + 1;\n const isRecoveredFromSync = !state.diagnostics.seqValid && isConsecutive;\n const seqValid =\n (state.diagnostics.seqValid || isRecoveredFromSync) &&\n (isFirstEvent || isConsecutive);\n\n const base: LiveTranscriptState = {\n ...state,\n events: [...state.events, event],\n lastEvent: event,\n diagnostics: {\n ...state.diagnostics,\n eventsCount: state.diagnostics.eventsCount + 1,\n seqValid,\n },\n };\n\n switch (event.type) {\n case \"session.started\":\n return {\n ...base,\n sessionId: event.sessionId,\n status: \"connecting\",\n };\n\n case \"session.ready\":\n return {\n ...base,\n status: \"recording\",\n };\n\n case \"session.paused\":\n return {\n ...base,\n status: \"ended\",\n diagnostics: {\n ...base.diagnostics,\n previewActive: false,\n },\n };\n\n case \"session.closed\":\n return {\n ...base,\n status: \"ended\",\n diagnostics: {\n ...base.diagnostics,\n previewActive: false,\n },\n };\n\n case \"session.error\":\n return {\n ...base,\n status: \"error\",\n error: {\n code: event.payload.code,\n message: event.payload.message,\n },\n };\n\n case \"session.context.reset\": {\n const contextOnly = (event as { payload: { contextOnly?: boolean } }).payload.contextOnly ?? false;\n if (!contextOnly) {\n const finalizedBeforeReset: Record<string, true> = {};\n for (const [id, chunk] of Object.entries(base.chunks)) {\n if (chunk.status === \"done\") finalizedBeforeReset[id] = true;\n }\n return { ...initialLiveTranscriptState, finalizedBeforeReset };\n }\n // contextOnly=true : conserver les chunks committés, vider les previews\n const newChunks: Record<string, LiveTranscriptChunk> = {};\n const newOrdered: string[] = [];\n for (const id of base.orderedSegmentIds) {\n const chunk = base.chunks[id];\n if (chunk && (chunk.committedText || chunk.status === \"done\")) {\n newChunks[id] = { ...chunk, previewText: undefined };\n newOrdered.push(id);\n }\n }\n const documentText = assembleCommittedDocument(newChunks, newOrdered);\n return {\n ...base,\n chunks: newChunks,\n orderedSegmentIds: newOrdered,\n documentText,\n previewText: \"\",\n displayText: documentText,\n diagnostics: computeDiagnostics(newChunks, newOrdered, base.diagnostics, base.finalText, \"\"),\n };\n }\n\n case \"transcript.segment.opened\": {\n const chunk: LiveTranscriptChunk = {\n segmentId: event.payload.segmentId,\n segmentSeq: event.payload.segmentSeq,\n status: \"opened\",\n text: \"\",\n revision: 0,\n startedAtMs: event.payload.startedAtMs,\n };\n const ordered = base.orderedSegmentIds.includes(event.payload.segmentId)\n ? base.orderedSegmentIds\n : [...base.orderedSegmentIds, event.payload.segmentId];\n const newChunks: Record<string, LiveTranscriptChunk> = { ...base.chunks, [event.payload.segmentId]: chunk };\n const previewText = buildPreviewText(newChunks, ordered, base.spinnerTick);\n return {\n ...base,\n chunks: newChunks,\n orderedSegmentIds: ordered,\n previewText,\n displayText: buildLiveDisplayText(newChunks, ordered, base.finalText, previewText),\n diagnostics: computeDiagnostics(newChunks, ordered, base.diagnostics, base.finalText, previewText),\n };\n }\n\n case \"transcript.segment.processing\": {\n const existing = base.chunks[event.payload.segmentId];\n if (!existing) return base;\n const newChunks: Record<string, LiveTranscriptChunk> = {\n ...base.chunks,\n [event.payload.segmentId]: {\n ...existing,\n status: \"processing\",\n durationMs: event.payload.durationMs,\n } as LiveTranscriptChunk,\n };\n const previewText = buildPreviewText(newChunks, base.orderedSegmentIds, base.spinnerTick);\n return {\n ...base,\n chunks: newChunks,\n previewText,\n displayText: buildLiveDisplayText(newChunks, base.orderedSegmentIds, base.finalText, previewText),\n diagnostics: computeDiagnostics(newChunks, base.orderedSegmentIds, base.diagnostics, base.finalText, previewText),\n };\n }\n\n case \"transcript.preview\": {\n const existing = base.chunks[event.payload.segmentId];\n const partialText = event.payload.text;\n if (!partialText) {\n return base;\n }\n if (existing) {\n // Ignorer si chunk déjà finalisé\n if (existing.status === \"done\") {\n return base;\n }\n // Ignorer si révision non croissante\n if (event.payload.revision <= existing.revision) {\n return base;\n }\n const newChunks: Record<string, LiveTranscriptChunk> = {\n ...base.chunks,\n [event.payload.segmentId]: {\n ...existing,\n status: \"preview\",\n previewText: partialText,\n previewContinuesPreviousWord: false,\n stablePrefix: event.payload.text,\n revision: event.payload.revision,\n } as LiveTranscriptChunk,\n };\n const previewText = buildPreviewText(newChunks, base.orderedSegmentIds, base.spinnerTick);\n return {\n ...base,\n chunks: newChunks,\n previewText,\n displayText: buildLiveDisplayText(newChunks, base.orderedSegmentIds, base.finalText, previewText),\n diagnostics: computeDiagnostics(newChunks, base.orderedSegmentIds, base.diagnostics, base.finalText, previewText),\n };\n }\n // Partial sans chunk connu (fallback)\n const chunk: LiveTranscriptChunk = {\n segmentId: event.payload.segmentId,\n segmentSeq: event.payload.segmentSeq,\n status: \"preview\",\n text: \"\",\n previewText: partialText,\n previewContinuesPreviousWord: false,\n stablePrefix: event.payload.text,\n revision: event.payload.revision,\n };\n const ordered = base.orderedSegmentIds.includes(event.payload.segmentId)\n ? base.orderedSegmentIds\n : [...base.orderedSegmentIds, event.payload.segmentId];\n const newChunks: Record<string, LiveTranscriptChunk> = { ...base.chunks, [event.payload.segmentId]: chunk };\n const previewText = buildPreviewText(newChunks, ordered, base.spinnerTick);\n return {\n ...base,\n chunks: newChunks,\n orderedSegmentIds: ordered,\n previewText,\n displayText: buildLiveDisplayText(newChunks, ordered, base.finalText, previewText),\n diagnostics: computeDiagnostics(newChunks, ordered, base.diagnostics, base.finalText, previewText),\n };\n }\n\n case \"segment.dropped\": {\n const newChunks: Record<string, LiveTranscriptChunk> = { ...base.chunks };\n delete newChunks[event.payload.segmentId];\n const orderedSegmentIds = base.orderedSegmentIds.filter(\n (id) => id !== event.payload.segmentId\n );\n const finalText = assembleTranscript(Object.values(newChunks));\n const documentText = assembleCommittedDocument(newChunks, orderedSegmentIds);\n const previewText = buildPreviewText(newChunks, orderedSegmentIds, base.spinnerTick);\n return {\n ...base,\n chunks: newChunks,\n orderedSegmentIds,\n finalText,\n documentText,\n previewText,\n displayText: buildLiveDisplayText(newChunks, orderedSegmentIds, finalText, previewText),\n diagnostics: computeDiagnostics(\n newChunks,\n orderedSegmentIds,\n base.diagnostics,\n finalText,\n previewText\n ),\n };\n }\n\n case \"segment.absorbed\": {\n if (base.finalizedBeforeReset?.[event.payload.segmentId]) return base;\n const absorbedId = event.payload.segmentId;\n const existing = base.chunks[absorbedId];\n if (!existing) return base;\n const newChunks: Record<string, LiveTranscriptChunk> = {\n ...base.chunks,\n [absorbedId]: {\n ...existing,\n status: \"done\",\n text: \"\",\n committedText: \"\",\n previewText: undefined,\n mergedWith: event.payload.absorbedInto,\n } as LiveTranscriptChunk,\n };\n const orderedSegmentIds = base.orderedSegmentIds.filter(id => id !== absorbedId);\n const documentText = assembleCommittedDocument(newChunks, orderedSegmentIds);\n const previewText = buildPreviewText(newChunks, orderedSegmentIds, base.spinnerTick);\n return {\n ...base,\n chunks: newChunks,\n orderedSegmentIds,\n documentText,\n previewText,\n displayText: buildLiveDisplayText(newChunks, orderedSegmentIds, base.finalText, previewText),\n diagnostics: computeDiagnostics(newChunks, orderedSegmentIds, base.diagnostics, base.finalText, previewText),\n };\n }\n\n case \"transcript.preview.stable\": {\n const existing = base.chunks[event.payload.segmentId];\n if (!existing) return base;\n const newChunks: Record<string, LiveTranscriptChunk> = {\n ...base.chunks,\n [event.payload.segmentId]: {\n ...existing,\n status: \"preview\",\n previewText: event.payload.text,\n previewContinuesPreviousWord: false,\n stablePrefix: event.payload.text,\n revision: event.payload.revision,\n } as LiveTranscriptChunk,\n };\n const previewText = buildPreviewText(newChunks, base.orderedSegmentIds, base.spinnerTick);\n return {\n ...base,\n chunks: newChunks,\n previewText,\n displayText: buildLiveDisplayText(newChunks, base.orderedSegmentIds, base.finalText, previewText),\n diagnostics: computeDiagnostics(newChunks, base.orderedSegmentIds, base.diagnostics, base.finalText, previewText),\n };\n }\n\n case \"transcript.final\": {\n const existing = base.chunks[event.payload.segmentId];\n let newChunks: Record<string, LiveTranscriptChunk>;\n let ordered = base.orderedSegmentIds;\n\n const meta = event.meta || {};\n const chunkUpdate: Partial<LiveTranscriptChunk> = {\n status: \"done\",\n text: event.payload.text,\n previewText: undefined,\n provider: event.payload.provider,\n uncertain: meta.uncertain as boolean | undefined,\n reason: meta.reason ? (meta.reason as string) : undefined,\n reasonCodes: meta.reasonCodes as string[] | undefined,\n parseFallback: meta.parseFallback as boolean | undefined,\n };\n\n if (!existing) {\n const chunk: LiveTranscriptChunk = {\n segmentId: event.payload.segmentId,\n segmentSeq: event.payload.segmentSeq,\n revision: 0,\n ...chunkUpdate,\n } as LiveTranscriptChunk;\n ordered = base.orderedSegmentIds.includes(event.payload.segmentId)\n ? base.orderedSegmentIds\n : [...base.orderedSegmentIds, event.payload.segmentId];\n newChunks = { ...base.chunks, [event.payload.segmentId]: chunk };\n } else {\n newChunks = {\n ...base.chunks,\n [event.payload.segmentId]: {\n ...existing,\n ...chunkUpdate,\n } as LiveTranscriptChunk,\n };\n }\n\n const finalText = assembleTranscript(Object.values(newChunks));\n const previewText = buildPreviewText(newChunks, ordered, base.spinnerTick);\n const latency = event.meta?.latencyMs as number | undefined;\n const contextChars = event.meta?.contextChars as number | undefined;\n const provider = event.payload.provider;\n\n return {\n ...base,\n chunks: newChunks,\n orderedSegmentIds: ordered,\n finalText,\n previewText,\n displayText: buildLiveDisplayText(newChunks, ordered, finalText, previewText),\n diagnostics: computeDiagnostics(newChunks, ordered, base.diagnostics, finalText, previewText, latency, contextChars, provider),\n };\n }\n\n case \"transcript.segment.ready\": {\n const existing = base.chunks[event.payload.segmentId];\n const effectiveText = pickEffectiveText(event.payload) || event.payload.text;\n const ordered = base.orderedSegmentIds.includes(event.payload.segmentId)\n ? base.orderedSegmentIds\n : [...base.orderedSegmentIds, event.payload.segmentId];\n const newChunks: Record<string, LiveTranscriptChunk> = {\n ...base.chunks,\n [event.payload.segmentId]: {\n ...(existing ?? {\n segmentId: event.payload.segmentId,\n segmentSeq: event.payload.segmentSeq,\n status: \"processing\",\n text: \"\",\n revision: 0,\n }),\n finalizedText: effectiveText,\n provider: event.payload.provider,\n previewText: undefined,\n } as LiveTranscriptChunk,\n };\n const previewText = buildPreviewText(newChunks, ordered, base.spinnerTick);\n return {\n ...base,\n chunks: newChunks,\n orderedSegmentIds: ordered,\n previewText,\n displayText: buildLiveDisplayText(newChunks, ordered, base.finalText, previewText),\n diagnostics: computeDiagnostics(newChunks, ordered, base.diagnostics, base.finalText, previewText),\n };\n }\n\n case \"transcript.segment.committed\": {\n if (base.finalizedBeforeReset?.[event.payload.segmentId]) return base;\n const existing = base.chunks[event.payload.segmentId];\n const effectiveText = pickEffectiveText(event.payload) || event.payload.text;\n const ordered = base.orderedSegmentIds.includes(event.payload.segmentId)\n ? base.orderedSegmentIds\n : [...base.orderedSegmentIds, event.payload.segmentId];\n const mergedIds: string[] = event.payload.mergedWith\n ? Array.isArray(event.payload.mergedWith)\n ? event.payload.mergedWith\n : [event.payload.mergedWith]\n : [];\n\n let newChunks: Record<string, LiveTranscriptChunk> = {\n ...base.chunks,\n [event.payload.segmentId]: {\n ...(existing ?? {\n segmentId: event.payload.segmentId,\n segmentSeq: event.payload.segmentSeq,\n revision: 0,\n }),\n status: \"done\",\n committedText: effectiveText,\n text: effectiveText,\n source: event.payload.source,\n mergedWith: mergedIds.length > 0 ? mergedIds : undefined,\n previewText: undefined,\n // P1 backend : additif, n'affecte ni le statut ni le texte affiché.\n effectiveSource: event.payload.effectiveSource,\n correctionPending: event.payload.correctionPending,\n correctionAccepted: event.payload.correctionAccepted,\n correctionRejectedReason: event.payload.correctionRejectedReason,\n commandsApplied: event.payload.commandsApplied,\n normalizationsApplied: event.payload.normalizationsApplied,\n safety: event.payload.safety,\n layout: event.payload.layout,\n rawStt: event.payload.rawStt,\n realtimeText: event.payload.realtimeText,\n hintSentToSmall: event.payload.hintSentToSmall,\n fallbackText: event.payload.fallbackText,\n smallRawText: event.payload.smallRawText,\n correctionOutcome: event.payload.correctionOutcome,\n debug: event.payload.debug,\n } as LiveTranscriptChunk,\n };\n\n // Purger les segments absorbés pour qu'ils ne polluent plus previewText\n for (const absorbedId of mergedIds) {\n const absorbed = newChunks[absorbedId];\n if (absorbed) {\n newChunks = {\n ...newChunks,\n [absorbedId]: {\n ...absorbed,\n status: \"done\",\n text: \"\",\n committedText: \"\",\n previewText: undefined,\n mergedWith: event.payload.segmentId,\n } as LiveTranscriptChunk,\n };\n }\n }\n const finalText = assembleTranscript(Object.values(newChunks));\n const documentText = assembleCommittedDocument(newChunks, ordered);\n const previewText = buildPreviewText(newChunks, ordered, base.spinnerTick);\n return {\n ...base,\n chunks: newChunks,\n orderedSegmentIds: ordered,\n finalText,\n documentText,\n previewText,\n displayText: buildLiveDisplayText(newChunks, ordered, finalText, previewText),\n diagnostics: computeDiagnostics(newChunks, ordered, base.diagnostics, finalText, previewText),\n };\n }\n\n case \"segment.opened\": {\n const id = event.payload.segmentId;\n if (base.chunks[id]) return base;\n const chunk: LiveTranscriptChunk = {\n segmentId: id,\n segmentSeq: event.payload.segmentSeq,\n status: \"opened\",\n text: \"\",\n revision: 0,\n startedAtMs: event.payload.startMs,\n };\n const ordered = [...base.orderedSegmentIds, id];\n const newChunks = { ...base.chunks, [id]: chunk };\n return {\n ...base,\n chunks: newChunks,\n orderedSegmentIds: ordered,\n diagnostics: computeDiagnostics(newChunks, ordered, base.diagnostics, base.finalText, base.previewText),\n };\n }\n\n case \"document.patch\": {\n let newChunks = { ...base.chunks };\n for (const op of (event as DocumentPatchEvent).payload.ops) {\n if (op.type === \"merge\" && op.to && newChunks[op.to]) {\n newChunks = {\n ...newChunks,\n [op.to]: {\n ...newChunks[op.to],\n committedText: op.text ?? newChunks[op.to].committedText,\n text: op.text ?? newChunks[op.to].text,\n mergedWith: op.from,\n } as LiveTranscriptChunk,\n };\n } else if (op.type === \"replace\" && op.blockId && newChunks[op.blockId]) {\n newChunks = {\n ...newChunks,\n [op.blockId]: {\n ...newChunks[op.blockId],\n committedText: op.text ?? newChunks[op.blockId].committedText,\n text: op.text ?? newChunks[op.blockId].text,\n } as LiveTranscriptChunk,\n };\n }\n }\n const documentText = assembleCommittedDocument(newChunks, base.orderedSegmentIds);\n return {\n ...base,\n chunks: newChunks,\n documentText,\n diagnostics: computeDiagnostics(newChunks, base.orderedSegmentIds, base.diagnostics, base.finalText, base.previewText),\n };\n }\n\n case \"transcript.segment.completed\": {\n const existing = base.chunks[event.payload.segmentId];\n if (!existing) return base;\n const newChunks: Record<string, LiveTranscriptChunk> = {\n ...base.chunks,\n [event.payload.segmentId]: {\n ...existing,\n status: existing.status === \"done\" || existing.status === \"preview\" ? existing.status : \"done\",\n durationMs: event.payload.durationMs,\n provider: event.payload.provider,\n } as LiveTranscriptChunk,\n };\n return {\n ...base,\n chunks: newChunks,\n diagnostics: computeDiagnostics(newChunks, base.orderedSegmentIds, base.diagnostics, base.finalText, base.previewText),\n };\n }\n\n case \"transcript.segment.error\": {\n const existing = base.chunks[event.payload.segmentId];\n const chunk: LiveTranscriptChunk = {\n ...(existing ?? {\n segmentId: event.payload.segmentId,\n segmentSeq: event.payload.segmentSeq,\n text: \"\",\n revision: 0,\n }),\n status: \"error\",\n error: `${event.payload.code}: ${event.payload.message}`,\n };\n const ordered = base.orderedSegmentIds.includes(event.payload.segmentId)\n ? base.orderedSegmentIds\n : [...base.orderedSegmentIds, event.payload.segmentId];\n const newChunks = { ...base.chunks, [event.payload.segmentId]: chunk };\n return {\n ...base,\n chunks: newChunks,\n orderedSegmentIds: ordered,\n diagnostics: computeDiagnostics(newChunks, ordered, base.diagnostics, base.finalText, base.previewText),\n };\n }\n\n case \"audio.vad.start\":\n return {\n ...base,\n diagnostics: { ...base.diagnostics, mode: \"vad\" },\n };\n\n case \"segment.audio.closed\": {\n const existing = base.chunks[event.payload.segmentId];\n if (!existing) return base;\n const newChunks: Record<string, LiveTranscriptChunk> = {\n ...base.chunks,\n [event.payload.segmentId]: {\n ...existing,\n audioClosedAtMs: event.payload.endMs,\n // Conserver le dernier preview jusqu'au committed — évite le flash vide\n // entre la fin audio VAD et la finalisation Voxtral.\n status: existing.status === \"preview\" ? \"processing\" : existing.status,\n } as LiveTranscriptChunk,\n };\n const previewText = buildPreviewText(newChunks, base.orderedSegmentIds, base.spinnerTick);\n return {\n ...base,\n chunks: newChunks,\n previewText,\n displayText: buildLiveDisplayText(newChunks, base.orderedSegmentIds, base.finalText, previewText),\n diagnostics: computeDiagnostics(newChunks, base.orderedSegmentIds, base.diagnostics, base.finalText, previewText),\n };\n }\n\n case \"audio.vad.end\":\n case \"session.pong\":\n default:\n return base;\n }\n}\n\nconst SPINNER_CHARS = [\"⠋\", \"⠙\", \"⠹\", \"⠸\", \"⠼\", \"⠴\", \"⠦\", \"⠧\", \"⠇\", \"⠏\"];\n\nfunction buildPreviewText(\n chunks: Record<string, LiveTranscriptChunk>,\n orderedSegmentIds: string[],\n spinnerTick: number = 0\n): string {\n const sorted = [...orderedSegmentIds]\n .map((id) => chunks[id])\n .filter((c): c is LiveTranscriptChunk => !!c)\n .sort((a, b) => a.segmentSeq - b.segmentSeq);\n let result = \"\";\n let hasPendingWithoutPreview = false;\n for (const chunk of sorted) {\n if (chunk.status === \"done\") continue;\n if ((chunk.status === \"preview\" || chunk.status === \"processing\" || chunk.status === \"opened\") && chunk.previewText) {\n result = joinWithSpacing(result, chunk.previewText);\n } else if (chunk.status === \"processing\" || chunk.status === \"opened\") {\n hasPendingWithoutPreview = true;\n }\n }\n if (hasPendingWithoutPreview && !result) {\n return SPINNER_CHARS[spinnerTick % SPINNER_CHARS.length];\n }\n return result;\n}\n\nfunction previewContinuesPreviousWord(\n chunks: Record<string, LiveTranscriptChunk>,\n orderedSegmentIds: string[]\n): boolean {\n const sorted = [...orderedSegmentIds]\n .map((id) => chunks[id])\n .filter((c): c is LiveTranscriptChunk => !!c)\n .sort((a, b) => a.segmentSeq - b.segmentSeq);\n const firstPreview = sorted.find(\n (chunk) =>\n chunk.status !== \"done\" &&\n !!chunk.previewText &&\n (chunk.status === \"preview\" ||\n chunk.status === \"processing\" ||\n chunk.status === \"opened\")\n );\n return !!firstPreview?.previewContinuesPreviousWord;\n}\n\nfunction buildLiveDisplayText(\n chunks: Record<string, LiveTranscriptChunk>,\n orderedSegmentIds: string[],\n finalText: string,\n previewText: string\n): string {\n return buildDisplayText(\n finalText,\n previewText,\n previewContinuesPreviousWord(chunks, orderedSegmentIds)\n );\n}\n\n\nfunction computeDiagnostics(\n chunks: Record<string, LiveTranscriptChunk>,\n orderedSegmentIds: string[],\n prevDiagnostics: LiveTranscriptDiagnostics,\n finalText: string,\n previewText: string,\n newLatencyMs?: number,\n newContextChars?: number,\n newProvider?: string,\n): LiveTranscriptDiagnostics {\n const all = Object.values(chunks);\n const processingChunks = all.filter((c) => c.status === \"opened\" || c.status === \"processing\").length;\n const doneChunks = all.filter((c) => c.status === \"done\").length;\n const errorChunks = all.filter((c) => c.status === \"error\").length;\n const previewActive = all.some((c) =>\n (c.status === \"preview\" || c.status === \"processing\" || c.status === \"opened\") && !!c.previewText\n );\n const uncertainChunks = all.filter((c) => c.uncertain).length;\n const parseFallbackChunks = all.filter((c) => c.parseFallback).length;\n\n // Moyenne glissante de latence\n let averageLatencyMs = prevDiagnostics.averageLatencyMs;\n let lastLatencyMs = prevDiagnostics.lastLatencyMs;\n if (newLatencyMs !== undefined) {\n lastLatencyMs = newLatencyMs;\n const prevAvg = prevDiagnostics.averageLatencyMs ?? 0;\n const count = doneChunks;\n if (count <= 1) {\n averageLatencyMs = newLatencyMs;\n } else {\n averageLatencyMs = Math.round((prevAvg * (count - 1) + newLatencyMs) / count);\n }\n }\n\n return {\n ...prevDiagnostics,\n chunksCount: orderedSegmentIds.length,\n processingChunks,\n doneChunks,\n errorChunks,\n averageLatencyMs,\n lastLatencyMs,\n lastProvider: newProvider ?? prevDiagnostics.lastProvider,\n finalTextLength: finalText.length,\n previewActive,\n uncertainChunks,\n parseFallbackChunks,\n contextChars: newContextChars ?? prevDiagnostics.contextChars ?? 0,\n };\n}\n","import type { EditorContext } from \"ephia-protocol\";\nimport type { TargetBinding } from \"../bindings/TargetBinding\";\n\nexport type EditorContextCollectorOptions = {\n maxContextChars?: number;\n};\n\nexport type EditorContextTarget = {\n id: string;\n binding: Pick<TargetBinding, \"getText\" | \"getSelection\" | \"getCursorOffset\"> | null;\n};\n\ntype SelectionSnapshot = {\n text: string;\n range: {\n start: number;\n end: number;\n };\n} | null;\n\nexport class EditorContextCollector {\n private readonly maxContextChars: number;\n\n constructor(options: EditorContextCollectorOptions = {}) {\n this.maxContextChars = options.maxContextChars ?? 600;\n }\n\n collect(target: EditorContextTarget): EditorContext {\n const text = target.binding?.getText?.() ?? \"\";\n const selection = target.binding?.getSelection?.() ?? null;\n const cursorOffset = this.resolveCursorOffset(target.binding, text, selection);\n const leftRaw = text.slice(0, cursorOffset);\n const rightRaw = text.slice(cursorOffset);\n\n return {\n targetId: target.id,\n documentEmpty: text.trim().length === 0,\n insertionMode: this.resolveInsertionMode(text, cursorOffset, selection),\n leftContext: leftRaw.slice(-this.maxContextChars),\n rightContext: rightRaw.slice(0, this.maxContextChars),\n selectedText: selection?.text || null,\n cursorOffset,\n };\n }\n\n private resolveCursorOffset(\n binding: EditorContextTarget[\"binding\"],\n text: string,\n selection: SelectionSnapshot\n ): number {\n if (selection?.range) return clamp(selection.range.start, 0, text.length);\n const cursor = binding?.getCursorOffset?.();\n if (typeof cursor === \"number\") return clamp(cursor, 0, text.length);\n return text.length;\n }\n\n private resolveInsertionMode(\n text: string,\n cursorOffset: number,\n selection: SelectionSnapshot\n ): EditorContext[\"insertionMode\"] {\n if (selection?.text) return \"replace_selection\";\n if (text.trim().length === 0) return \"document_start\";\n if (cursorOffset >= text.length) return \"append\";\n return \"middle_of_sentence\";\n }\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n"],"mappings":"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","names":["previewContinuesPreviousWord","text","newChunks","previewText"]}
@@ -0,0 +1,69 @@
1
+ import { EphiaServerEvent, EditorContext, ResetReason } from 'ephia-protocol';
2
+ import { T as Transport } from './Transport-zdeA4Pou.js';
3
+ import { a as EphiaStartOptions, E as EphiaStartResult } from './client-options-Uo6jXO8k.js';
4
+ import { E as EphiaBinding } from './EphiaBinding-BvRmlqqC.js';
5
+
6
+ type EphiaHeadlessTarget = {
7
+ id: string;
8
+ binding: EphiaBinding;
9
+ mode?: string;
10
+ };
11
+ type EphiaHeadlessOptions = {
12
+ apiUrl?: string;
13
+ apiKey?: string;
14
+ bearerToken?: string;
15
+ clientType?: string;
16
+ language?: string;
17
+ /** Pre-registered targets. Additional targets can be registered via registerTarget(). */
18
+ targets?: EphiaHeadlessTarget[];
19
+ /** Single target shorthand; equivalent to targets: [{ id: "default", binding }]. */
20
+ binding?: EphiaBinding;
21
+ /** Transport override for testing. */
22
+ transport?: Transport;
23
+ };
24
+ type EphiaHeadlessClient = {
25
+ /**
26
+ * Subscribe to a typed V2 server event. Returns an unsubscriber.
27
+ *
28
+ * @example
29
+ * const unsub = client.on("segment.operation", (event) => { ... });
30
+ * // later:
31
+ * unsub();
32
+ */
33
+ on<T extends EphiaServerEvent["type"]>(type: T, handler: (event: Extract<EphiaServerEvent, {
34
+ type: T;
35
+ }>) => void): () => void;
36
+ start(targetId?: string, options?: EphiaStartOptions): Promise<EphiaStartResult>;
37
+ start(options?: EphiaStartOptions): Promise<EphiaStartResult>;
38
+ stop(): Promise<void>;
39
+ pause(): Promise<void>;
40
+ resume(options?: EphiaStartOptions): Promise<void>;
41
+ endSession(): Promise<void>;
42
+ warmupMic(): Promise<void>;
43
+ /**
44
+ * Registers a new target binding. Returns an unsubscriber.
45
+ */
46
+ registerTarget(target: EphiaHeadlessTarget): () => void;
47
+ /**
48
+ * Notifies the backend that a specific target is now active.
49
+ * Sends session.target.changed + editor_context.update.
50
+ */
51
+ setActiveTarget(targetId: string): Promise<void>;
52
+ /**
53
+ * Sends a manual editor context snapshot to the backend.
54
+ * Use when the backend needs cursor/text state without a target switch.
55
+ */
56
+ sendEditorContext(context: EditorContext): Promise<void>;
57
+ /**
58
+ * Resets the dictation context for a specific target (clears pending segments).
59
+ */
60
+ resetTarget(targetId: string, reason?: ResetReason): Promise<void>;
61
+ /**
62
+ * Resets the global session context (all targets).
63
+ */
64
+ resetSession(reason?: ResetReason): Promise<void>;
65
+ dispose(): Promise<void>;
66
+ };
67
+ declare function createEphiaClient(options: EphiaHeadlessOptions): EphiaHeadlessClient;
68
+
69
+ export { type EphiaHeadlessClient as E, type EphiaHeadlessOptions as a, type EphiaHeadlessTarget as b, createEphiaClient as c };
@@ -0,0 +1,148 @@
1
+ import { E as EphiaSpeechMikeAction, h as EphiaSpeechMikeLedIntent, g as EphiaSpeechMikeHidStatus, e as EphiaSpeechMikeDeviceInfo, f as EphiaSpeechMikeError } from '../../useEphiaSpeechMike-CjD7DWnh.js';
2
+ export { a as EphiaSpeechMikeAudioStatus, b as EphiaSpeechMikeButton, c as EphiaSpeechMikeContext, d as EphiaSpeechMikeContextValue, i as EphiaSpeechMikeProvider, j as EphiaSpeechMikeProviderProps, k as EphiaSpeechMikeState, l as EphiaSpeechMikeStatus, F as FALLBACK_EPHIA_SPEECHMIKE_STATE, u as useEphiaSpeechMike } from '../../useEphiaSpeechMike-CjD7DWnh.js';
3
+ import 'react';
4
+
5
+ declare const SPEECHMIKE_VENDOR_IDS: {
6
+ readonly PHILIPS: 2321;
7
+ };
8
+ declare const SPEECHMIKE_CONFIG: {
9
+ readonly BUTTON_DEBOUNCE_MS: 150;
10
+ readonly WATCHDOG_INTERVAL_MS: 10000;
11
+ readonly DEVICE_OPERATION_TIMEOUT_MS: 2000;
12
+ readonly REQUEST_DEVICE_TIMEOUT_MS: 15000;
13
+ readonly LED_OPERATION_TIMEOUT_MS: 500;
14
+ };
15
+ declare const LED_MODE: {
16
+ readonly OFF: 0;
17
+ readonly ON: 1;
18
+ readonly ON_BRIGHT: 3;
19
+ };
20
+ declare const DEFAULT_BUTTON_MAPPING: Record<string, EphiaSpeechMikeAction>;
21
+ declare const DEFAULT_LED_INTENTS: Record<EphiaSpeechMikeLedIntent, Record<number, number>>;
22
+
23
+ type DictationDevice = unknown;
24
+ type DictationButtonCallback = (device: DictationDevice, bitMask: number) => void;
25
+ type DictationDeviceCallback = (device: DictationDevice) => void;
26
+ type DictationMotionCallback = (device: DictationDevice, motion: number) => void;
27
+ type DictationDeviceManagerLike = {
28
+ init?: () => Promise<void>;
29
+ requestDevice: () => Promise<DictationDevice[]>;
30
+ getDeviceInfo?: (device: DictationDevice) => Promise<unknown>;
31
+ getDevices?: () => DictationDevice[];
32
+ addButtonEventListener?: (cb: DictationButtonCallback) => void;
33
+ removeButtonEventListener?: (cb: DictationButtonCallback) => void;
34
+ addDeviceConnectedEventListener?: (cb: DictationDeviceCallback) => void;
35
+ removeDeviceConnectedEventListener?: (cb: DictationDeviceCallback) => void;
36
+ addDeviceDisconnectedEventListener?: (cb: DictationDeviceCallback) => void;
37
+ removeDeviceDisconnectedEventListener?: (cb: DictationDeviceCallback) => void;
38
+ addMotionEventListener?: (cb: DictationMotionCallback) => void;
39
+ removeMotionEventListener?: (cb: DictationMotionCallback) => void;
40
+ disconnect?: () => void;
41
+ };
42
+ type DictationSupportEnum = Record<number, string> & Record<string, number>;
43
+ type DictationSupportRuntime = {
44
+ DictationDeviceManager: new () => DictationDeviceManagerLike;
45
+ ButtonEvent: DictationSupportEnum;
46
+ MotionEvent?: DictationSupportEnum;
47
+ };
48
+ declare function resetDictationSupportLoaderForTests(): void;
49
+ declare function loadDictationSupport(): Promise<DictationSupportRuntime>;
50
+
51
+ type SpeechMikeAudioMatch = {
52
+ deviceId: string;
53
+ label: string;
54
+ score: number;
55
+ raw: MediaDeviceInfo;
56
+ };
57
+ declare function scoreSpeechMikeAudioDevice(device: MediaDeviceInfo): number;
58
+ declare function listAudioInputDevices(): Promise<MediaDeviceInfo[]>;
59
+ declare function resolveSpeechMikeAudioInput(options?: {
60
+ requestPermission?: boolean;
61
+ }): Promise<SpeechMikeAudioMatch | null>;
62
+
63
+ type ButtonRouterEvent = {
64
+ buttons: Set<string>;
65
+ actions: EphiaSpeechMikeAction[];
66
+ rawBitMask: number;
67
+ };
68
+ declare class SpeechMikeButtonRouter {
69
+ private readonly buttonEnum;
70
+ private readonly debounceMs;
71
+ private lastEventTime;
72
+ private readonly processedEvents;
73
+ private mapping;
74
+ constructor(buttonEnum: DictationSupportEnum, mapping?: Partial<Record<string, EphiaSpeechMikeAction>>, debounceMs?: 150);
75
+ setMapping(mapping: Partial<Record<string, EphiaSpeechMikeAction>>): void;
76
+ parse(bitMask: number): ButtonRouterEvent | null;
77
+ }
78
+
79
+ declare class SpeechMikeLedController {
80
+ private readonly getDevice;
81
+ private queue;
82
+ constructor(getDevice: () => unknown | null);
83
+ setIntent(intent: EphiaSpeechMikeLedIntent): void;
84
+ setBatchQueued(states: Record<number, number>): void;
85
+ setBatch(states: Record<number, number>): Promise<void>;
86
+ setLed(index: number, mode: number): Promise<boolean>;
87
+ clear(): void;
88
+ private getLedDevice;
89
+ }
90
+
91
+ type SpeechMikeDeviceManagerEvents = {
92
+ status: (status: EphiaSpeechMikeHidStatus) => void;
93
+ device: (device: unknown | null) => void;
94
+ deviceInfo: (info: EphiaSpeechMikeDeviceInfo | null) => void;
95
+ presence: (present: boolean) => void;
96
+ button: (event: ButtonRouterEvent) => void;
97
+ error: (error: EphiaSpeechMikeError) => void;
98
+ };
99
+ type SpeechMikeDeviceManagerOptions = {
100
+ buttonMapping?: Partial<Record<string, EphiaSpeechMikeAction>>;
101
+ loadRuntime?: () => Promise<DictationSupportRuntime>;
102
+ };
103
+ declare class SpeechMikeDeviceManager {
104
+ private readonly listeners;
105
+ private readonly loadRuntime;
106
+ private readonly initialButtonMapping;
107
+ private manager;
108
+ private router;
109
+ private currentDevice;
110
+ private currentDeviceInfo;
111
+ private status;
112
+ private physicallyPresent;
113
+ private initialized;
114
+ private disposed;
115
+ private reconnectLock;
116
+ private watchdogInterval;
117
+ private readonly onButtonEvent;
118
+ private readonly onDeviceConnected;
119
+ private readonly onDeviceDisconnected;
120
+ private readonly onMotionEvent;
121
+ private readonly onHidConnect;
122
+ private readonly onHidDisconnect;
123
+ constructor(options?: SpeechMikeDeviceManagerOptions);
124
+ initialize(): Promise<void>;
125
+ requestAuthorization(): Promise<void>;
126
+ reconnect(): Promise<void>;
127
+ dispose(): void;
128
+ getCurrentDevice(): unknown | null;
129
+ getStatus(): EphiaSpeechMikeHidStatus;
130
+ getPhysicallyPresent(): boolean;
131
+ getDeviceInfo(): EphiaSpeechMikeDeviceInfo | null;
132
+ setButtonMapping(mapping: Partial<Record<string, EphiaSpeechMikeAction>>): void;
133
+ on<K extends keyof SpeechMikeDeviceManagerEvents>(event: K, cb: SpeechMikeDeviceManagerEvents[K]): () => void;
134
+ private attachDevice;
135
+ private detachDevice;
136
+ private handleHidConnect;
137
+ private handleHidDisconnect;
138
+ private startWatchdog;
139
+ private watchdogTick;
140
+ private detectPhysicalPresence;
141
+ private resolveDeviceInfo;
142
+ private getManagerDevices;
143
+ private setStatus;
144
+ private setPhysicallyPresent;
145
+ private emit;
146
+ }
147
+
148
+ export { type ButtonRouterEvent, DEFAULT_BUTTON_MAPPING, DEFAULT_LED_INTENTS, type DictationButtonCallback, type DictationDevice, type DictationDeviceCallback, type DictationDeviceManagerLike, type DictationMotionCallback, type DictationSupportEnum, type DictationSupportRuntime, EphiaSpeechMikeAction, EphiaSpeechMikeDeviceInfo, EphiaSpeechMikeError, EphiaSpeechMikeHidStatus, EphiaSpeechMikeLedIntent, LED_MODE, SPEECHMIKE_CONFIG, SPEECHMIKE_VENDOR_IDS, type SpeechMikeAudioMatch, SpeechMikeButtonRouter, SpeechMikeDeviceManager, type SpeechMikeDeviceManagerEvents, type SpeechMikeDeviceManagerOptions, SpeechMikeLedController, listAudioInputDevices, loadDictationSupport, resetDictationSupportLoaderForTests, resolveSpeechMikeAudioInput, scoreSpeechMikeAudioDevice };
@@ -0,0 +1,40 @@
1
+ import {
2
+ DEFAULT_BUTTON_MAPPING,
3
+ DEFAULT_LED_INTENTS,
4
+ EphiaSpeechMikeContext,
5
+ EphiaSpeechMikeProvider,
6
+ FALLBACK_EPHIA_SPEECHMIKE_STATE,
7
+ LED_MODE,
8
+ SPEECHMIKE_CONFIG,
9
+ SPEECHMIKE_VENDOR_IDS,
10
+ SpeechMikeButtonRouter,
11
+ SpeechMikeDeviceManager,
12
+ SpeechMikeLedController,
13
+ listAudioInputDevices,
14
+ loadDictationSupport,
15
+ resetDictationSupportLoaderForTests,
16
+ resolveSpeechMikeAudioInput,
17
+ scoreSpeechMikeAudioDevice,
18
+ useEphiaSpeechMike
19
+ } from "../../chunk-3LXZODL4.js";
20
+ import "../../chunk-THNHRV2B.js";
21
+ export {
22
+ DEFAULT_BUTTON_MAPPING,
23
+ DEFAULT_LED_INTENTS,
24
+ EphiaSpeechMikeContext,
25
+ EphiaSpeechMikeProvider,
26
+ FALLBACK_EPHIA_SPEECHMIKE_STATE,
27
+ LED_MODE,
28
+ SPEECHMIKE_CONFIG,
29
+ SPEECHMIKE_VENDOR_IDS,
30
+ SpeechMikeButtonRouter,
31
+ SpeechMikeDeviceManager,
32
+ SpeechMikeLedController,
33
+ listAudioInputDevices,
34
+ loadDictationSupport,
35
+ resetDictationSupportLoaderForTests,
36
+ resolveSpeechMikeAudioInput,
37
+ scoreSpeechMikeAudioDevice,
38
+ useEphiaSpeechMike
39
+ };
40
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,10 @@
1
+ export { E as EphiaHeadlessClient, a as EphiaHeadlessOptions, b as EphiaHeadlessTarget, c as createEphiaClient } from '../createEphiaClient-BhdZ183V.js';
2
+ export { E as EphiaBinding, P as PreviewSegmentInput, U as UpsertSegmentInput } from '../EphiaBinding-BvRmlqqC.js';
3
+ export { N as NativeBinding } from '../NativeBinding-ChG0GeSz.js';
4
+ export { E as EphiaV2CommittedMark, a as EphiaV2PreviewMark, T as TiptapBinding } from '../TiptapBinding-B-agfV2H.js';
5
+ export { EditorContext, EphiaServerEvent, ResetReason } from 'ephia-protocol';
6
+ import '../Transport-zdeA4Pou.js';
7
+ import '../audio-state-kZ3KSvux.js';
8
+ import '../client-options-Uo6jXO8k.js';
9
+ import '../session-APaXR48R.js';
10
+ import '@tiptap/core';
@@ -0,0 +1,25 @@
1
+ import {
2
+ createEphiaClient
3
+ } from "../chunk-MJCEOOLW.js";
4
+ import {
5
+ NativeBinding
6
+ } from "../chunk-A5UEXJ5R.js";
7
+ import "../chunk-DIEWY3IT.js";
8
+ import "../chunk-PSYX674B.js";
9
+ import "../chunk-EGIAN7FH.js";
10
+ import "../chunk-LXMCRXXF.js";
11
+ import "../chunk-N7U5M3VZ.js";
12
+ import {
13
+ EphiaV2CommittedMark,
14
+ EphiaV2PreviewMark,
15
+ TiptapBinding
16
+ } from "../chunk-W2ZP674X.js";
17
+ import "../chunk-VSLGR64U.js";
18
+ export {
19
+ EphiaV2CommittedMark,
20
+ EphiaV2PreviewMark,
21
+ NativeBinding,
22
+ TiptapBinding,
23
+ createEphiaClient
24
+ };
25
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,18 @@
1
+ export { E as EphiaAuto, a as EphiaDictationButton, b as EphiaProvider, c as EphiaProviderProps, d as EphiaStatusBar, e as EphiaTextarea, U as UseEphiaReturn, u as useEphia, f as useEphiaAudioLevel, g as useEphiaConnection, h as useEphiaError, i as useEphiaNativeTarget, j as useEphiaPartial, k as useEphiaSpeaking, l as useEphiaStatus, m as useEphiaTarget, n as useEphiaTiptap, o as useOptionalEphiaConnection, p as useOptionalEphiaStatus } from './EphiaTextarea-B4_CAVUg.js';
2
+ export { E as EphiaStartResult } from './client-options-Uo6jXO8k.js';
3
+ export { E as EphiaSpeechMikeAction, a as EphiaSpeechMikeAudioStatus, b as EphiaSpeechMikeButton, c as EphiaSpeechMikeContext, d as EphiaSpeechMikeContextValue, e as EphiaSpeechMikeDeviceInfo, f as EphiaSpeechMikeError, g as EphiaSpeechMikeHidStatus, h as EphiaSpeechMikeLedIntent, i as EphiaSpeechMikeProvider, j as EphiaSpeechMikeProviderProps, k as EphiaSpeechMikeState, l as EphiaSpeechMikeStatus, F as FALLBACK_EPHIA_SPEECHMIKE_STATE, u as useEphiaSpeechMike } from './useEphiaSpeechMike-CjD7DWnh.js';
4
+ export { ButtonRouterEvent, DEFAULT_BUTTON_MAPPING, DEFAULT_LED_INTENTS, DictationButtonCallback, DictationDevice, DictationDeviceCallback, DictationDeviceManagerLike, DictationMotionCallback, DictationSupportEnum, DictationSupportRuntime, LED_MODE, SPEECHMIKE_CONFIG, SPEECHMIKE_VENDOR_IDS, SpeechMikeAudioMatch, SpeechMikeButtonRouter, SpeechMikeDeviceManager, SpeechMikeDeviceManagerEvents, SpeechMikeDeviceManagerOptions, SpeechMikeLedController, listAudioInputDevices, loadDictationSupport, resetDictationSupportLoaderForTests, resolveSpeechMikeAudioInput, scoreSpeechMikeAudioDevice } from './devices/speechmike/index.js';
5
+ export { E as EphiaStatus } from './types-D5SXPSwR.js';
6
+ export { E as EphiaHeadlessClient, a as EphiaHeadlessOptions, b as EphiaHeadlessTarget, c as createEphiaClient } from './createEphiaClient-BhdZ183V.js';
7
+ export { B as Button, a as ButtonProps, E as EphiaFloatingButton, b as EphiaFloatingButtonBorderRadius, c as EphiaFloatingButtonPosition, d as EphiaFloatingButtonProps, e as EphiaFloatingButtonSize, f as EphiaFloatingButtonTheme, S as Spinner, g as SpinnerProps } from './EphiaFloatingButton-CxiF86VW.js';
8
+ export { E as EphiaAudioPermission, a as EphiaAudioState, b as EphiaSdkError, c as EphiaSdkErrorCode, i as initialAudioState } from './audio-state-kZ3KSvux.js';
9
+ export { D as DEFAULT_EPHIA_SDK_API_URL, E as EphiaClientConfig, a as EphiaLang, b as EphiaSessionOptionsConfig, g as getMessage, r as resolveEphiaSdkApiUrl } from './schema-B2ycPlNB.js';
10
+ export { E as EphiaSessionOptions, M as Mode } from './session-APaXR48R.js';
11
+ import 'react/jsx-runtime';
12
+ import 'react';
13
+ import './connection-state-Bk33YprE.js';
14
+ import './Transport-zdeA4Pou.js';
15
+ import 'ephia-protocol';
16
+ import '@tiptap/core';
17
+ import './EphiaBinding-BvRmlqqC.js';
18
+ import 'zod';
package/dist/index.js ADDED
@@ -0,0 +1,119 @@
1
+ import "./chunk-35AJK2IO.js";
2
+ import "./chunk-7E43RY75.js";
3
+ import {
4
+ EphiaAuto,
5
+ EphiaDictationButton,
6
+ EphiaStatusBar,
7
+ EphiaTextarea,
8
+ useEphiaNativeTarget,
9
+ useEphiaTarget,
10
+ useEphiaTiptap
11
+ } from "./chunk-EMOEAPVU.js";
12
+ import {
13
+ DEFAULT_BUTTON_MAPPING,
14
+ DEFAULT_LED_INTENTS,
15
+ EphiaSpeechMikeContext,
16
+ EphiaSpeechMikeProvider,
17
+ FALLBACK_EPHIA_SPEECHMIKE_STATE,
18
+ LED_MODE,
19
+ SPEECHMIKE_CONFIG,
20
+ SPEECHMIKE_VENDOR_IDS,
21
+ SpeechMikeButtonRouter,
22
+ SpeechMikeDeviceManager,
23
+ SpeechMikeLedController,
24
+ listAudioInputDevices,
25
+ loadDictationSupport,
26
+ resetDictationSupportLoaderForTests,
27
+ resolveSpeechMikeAudioInput,
28
+ scoreSpeechMikeAudioDevice,
29
+ useEphiaSpeechMike
30
+ } from "./chunk-3LXZODL4.js";
31
+ import {
32
+ Button,
33
+ EphiaFloatingButton,
34
+ Spinner
35
+ } from "./chunk-YWZUMUYE.js";
36
+ import {
37
+ EphiaProvider,
38
+ useEphia,
39
+ useEphiaAudioLevel,
40
+ useEphiaConnection,
41
+ useEphiaError,
42
+ useEphiaPartial,
43
+ useEphiaSpeaking,
44
+ useEphiaStatus,
45
+ useOptionalEphiaConnection,
46
+ useOptionalEphiaStatus
47
+ } from "./chunk-ITJFN3VM.js";
48
+ import "./chunk-IDC7FHIZ.js";
49
+ import {
50
+ getMessage
51
+ } from "./chunk-5IK5TLSK.js";
52
+ import "./chunk-RFQRV7ML.js";
53
+ import {
54
+ createEphiaClient
55
+ } from "./chunk-MJCEOOLW.js";
56
+ import "./chunk-A5UEXJ5R.js";
57
+ import "./chunk-DIEWY3IT.js";
58
+ import {
59
+ DEFAULT_EPHIA_SDK_API_URL,
60
+ resolveEphiaSdkApiUrl
61
+ } from "./chunk-PSYX674B.js";
62
+ import {
63
+ initialAudioState
64
+ } from "./chunk-EGIAN7FH.js";
65
+ import "./chunk-LXMCRXXF.js";
66
+ import {
67
+ EphiaSdkError
68
+ } from "./chunk-N7U5M3VZ.js";
69
+ import "./chunk-AEE554FT.js";
70
+ import "./chunk-THNHRV2B.js";
71
+ import "./chunk-K24GNU27.js";
72
+ import "./chunk-W2ZP674X.js";
73
+ import "./chunk-VSLGR64U.js";
74
+ export {
75
+ Button,
76
+ DEFAULT_BUTTON_MAPPING,
77
+ DEFAULT_EPHIA_SDK_API_URL,
78
+ DEFAULT_LED_INTENTS,
79
+ EphiaAuto,
80
+ EphiaDictationButton,
81
+ EphiaFloatingButton,
82
+ EphiaProvider,
83
+ EphiaSdkError,
84
+ EphiaSpeechMikeContext,
85
+ EphiaSpeechMikeProvider,
86
+ EphiaStatusBar,
87
+ EphiaTextarea,
88
+ FALLBACK_EPHIA_SPEECHMIKE_STATE,
89
+ LED_MODE,
90
+ SPEECHMIKE_CONFIG,
91
+ SPEECHMIKE_VENDOR_IDS,
92
+ SpeechMikeButtonRouter,
93
+ SpeechMikeDeviceManager,
94
+ SpeechMikeLedController,
95
+ Spinner,
96
+ createEphiaClient,
97
+ getMessage,
98
+ initialAudioState,
99
+ listAudioInputDevices,
100
+ loadDictationSupport,
101
+ resetDictationSupportLoaderForTests,
102
+ resolveEphiaSdkApiUrl,
103
+ resolveSpeechMikeAudioInput,
104
+ scoreSpeechMikeAudioDevice,
105
+ useEphia,
106
+ useEphiaAudioLevel,
107
+ useEphiaConnection,
108
+ useEphiaError,
109
+ useEphiaNativeTarget,
110
+ useEphiaPartial,
111
+ useEphiaSpeaking,
112
+ useEphiaSpeechMike,
113
+ useEphiaStatus,
114
+ useEphiaTarget,
115
+ useEphiaTiptap,
116
+ useOptionalEphiaConnection,
117
+ useOptionalEphiaStatus
118
+ };
119
+ //# sourceMappingURL=index.js.map