@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,84 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import React__default from 'react';
3
+ import { StoreApi } from 'zustand/vanilla';
4
+ import { a as EphiaStoreState } from '../types-D5SXPSwR.js';
5
+ import { EphiaServerEvent } from 'ephia-protocol';
6
+ import { E as EphiaBinding } from '../EphiaBinding-BvRmlqqC.js';
7
+ import '../connection-state-Bk33YprE.js';
8
+ import '../Transport-zdeA4Pou.js';
9
+ import '../audio-state-kZ3KSvux.js';
10
+
11
+ type EphiaStore = StoreApi<EphiaStoreState>;
12
+
13
+ interface EphiaProviderConfig {
14
+ apiUrl?: string;
15
+ apiKey?: string;
16
+ bearerToken?: string;
17
+ clientType?: string;
18
+ language?: string;
19
+ medicalDomain?: string;
20
+ }
21
+ interface RegisterTargetOptions {
22
+ mode?: string;
23
+ element?: HTMLElement;
24
+ }
25
+ /**
26
+ * Public context value exposed by <EphiaProvider>.
27
+ *
28
+ * V2 rules:
29
+ * - no direct client access (getClient / clientRef removed)
30
+ * - no legacy registry (registryRef removed)
31
+ * - no voice-formatting config (handled backend-side)
32
+ *
33
+ * Consumers receive the reactive store and a target registration helper.
34
+ */
35
+ interface EphiaContextValue {
36
+ store: EphiaStore;
37
+ /**
38
+ * Registers a V2 EphiaBinding with the TargetManager.
39
+ * Returns a cleanup function that unregisters and detaches the binding.
40
+ */
41
+ registerTarget: (id: string, binding: EphiaBinding, opts?: RegisterTargetOptions) => () => void;
42
+ /**
43
+ * Réapplique un événement serveur (replay backend / événements manqués).
44
+ * Délègue au TranscriptApplier interne du provider.
45
+ */
46
+ applyServerEvent: (event: EphiaServerEvent) => void;
47
+ config: EphiaProviderConfig;
48
+ }
49
+
50
+ /**
51
+ * Crée un store Ephia vierge pour les tests ou le catalogue UI.
52
+ *
53
+ * Le store a le même shape que celui utilisé par <EphiaProvider>, mais il n'est
54
+ * connecté à aucun client audio. C'est utile pour monter des composants qui
55
+ * consomment useEphiaStatus / useEphiaConnection / useEphia en isolation.
56
+ */
57
+ declare function createEphiaTestStore(): EphiaStore;
58
+ interface EphiaTestProviderProps {
59
+ children: React__default.ReactNode;
60
+ /**
61
+ * Store injecté. Si absent, un store vierge est créé.
62
+ */
63
+ store?: EphiaStore;
64
+ }
65
+ /**
66
+ * Provider minimal pour les tests unitaires et le catalogue UI preview.
67
+ *
68
+ * Fournit un contexte Ephia avec un store Zustand réel mais déconnecté
69
+ * (status idle, connexion idle, etc.) afin que les composants utilisant
70
+ * useEphiaStatus / useEphiaConnection / useEphia / useEphiaPartial
71
+ * puissent être montés sans backend.
72
+ *
73
+ * @example
74
+ * ```tsx
75
+ * import { EphiaTestProvider } from "@ephia/dova-sdk/testing";
76
+ *
77
+ * <EphiaTestProvider>
78
+ * <MyComponent />
79
+ * </EphiaTestProvider>
80
+ * ```
81
+ */
82
+ declare function EphiaTestProvider({ children, store: injectedStore }: EphiaTestProviderProps): react_jsx_runtime.JSX.Element;
83
+
84
+ export { type EphiaContextValue, type EphiaProviderConfig, type EphiaStore, EphiaTestProvider, type EphiaTestProviderProps, createEphiaTestStore };
@@ -0,0 +1,36 @@
1
+ "use client";
2
+ import {
3
+ createEphiaStore
4
+ } from "../chunk-IDC7FHIZ.js";
5
+ import "../chunk-RFQRV7ML.js";
6
+ import "../chunk-EGIAN7FH.js";
7
+ import {
8
+ EphiaContext
9
+ } from "../chunk-K24GNU27.js";
10
+
11
+ // src/testing/index.tsx
12
+ import { useMemo } from "react";
13
+ import { jsx } from "react/jsx-runtime";
14
+ function createEphiaTestStore() {
15
+ return createEphiaStore();
16
+ }
17
+ function EphiaTestProvider({ children, store: injectedStore }) {
18
+ const store = useMemo(() => injectedStore ?? createEphiaTestStore(), [injectedStore]);
19
+ const value = useMemo(
20
+ () => ({
21
+ store,
22
+ registerTarget: () => () => {
23
+ },
24
+ applyServerEvent: () => {
25
+ },
26
+ config: {}
27
+ }),
28
+ [store]
29
+ );
30
+ return /* @__PURE__ */ jsx(EphiaContext.Provider, { value, children });
31
+ }
32
+ export {
33
+ EphiaTestProvider,
34
+ createEphiaTestStore
35
+ };
36
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/testing/index.tsx"],"sourcesContent":["\"use client\";\n\nimport React, { useMemo } from \"react\";\nimport { EphiaContext, type EphiaContextValue } from \"../react/provider/EphiaContext\";\nimport { createEphiaStore, type EphiaStore } from \"../react/store/create-ephia-store\";\n\nexport type { EphiaStore } from \"../react/store/create-ephia-store\";\nexport type { EphiaContextValue, EphiaProviderConfig } from \"../react/provider/EphiaContext\";\n\n/**\n * Crée un store Ephia vierge pour les tests ou le catalogue UI.\n *\n * Le store a le même shape que celui utilisé par <EphiaProvider>, mais il n'est\n * connecté à aucun client audio. C'est utile pour monter des composants qui\n * consomment useEphiaStatus / useEphiaConnection / useEphia en isolation.\n */\nexport function createEphiaTestStore(): EphiaStore {\n return createEphiaStore();\n}\n\nexport interface EphiaTestProviderProps {\n children: React.ReactNode;\n /**\n * Store injecté. Si absent, un store vierge est créé.\n */\n store?: EphiaStore;\n}\n\n/**\n * Provider minimal pour les tests unitaires et le catalogue UI preview.\n *\n * Fournit un contexte Ephia avec un store Zustand réel mais déconnecté\n * (status idle, connexion idle, etc.) afin que les composants utilisant\n * useEphiaStatus / useEphiaConnection / useEphia / useEphiaPartial\n * puissent être montés sans backend.\n *\n * @example\n * ```tsx\n * import { EphiaTestProvider } from \"@ephia/dova-sdk/testing\";\n *\n * <EphiaTestProvider>\n * <MyComponent />\n * </EphiaTestProvider>\n * ```\n */\nexport function EphiaTestProvider({ children, store: injectedStore }: EphiaTestProviderProps) {\n const store = useMemo(() => injectedStore ?? createEphiaTestStore(), [injectedStore]);\n\n const value = useMemo<EphiaContextValue>(\n () => ({\n store,\n registerTarget: () => () => {},\n applyServerEvent: () => {},\n config: {},\n }),\n [store],\n );\n\n return <EphiaContext.Provider value={value}>{children}</EphiaContext.Provider>;\n}\n"],"mappings":";;;;;;;;;;;AAEA,SAAgB,eAAe;AAwDtB;AA1CF,SAAS,uBAAmC;AACjD,SAAO,iBAAiB;AAC1B;AA2BO,SAAS,kBAAkB,EAAE,UAAU,OAAO,cAAc,GAA2B;AAC5F,QAAM,QAAQ,QAAQ,MAAM,iBAAiB,qBAAqB,GAAG,CAAC,aAAa,CAAC;AAEpF,QAAM,QAAQ;AAAA,IACZ,OAAO;AAAA,MACL;AAAA,MACA,gBAAgB,MAAM,MAAM;AAAA,MAAC;AAAA,MAC7B,kBAAkB,MAAM;AAAA,MAAC;AAAA,MACzB,QAAQ,CAAC;AAAA,IACX;AAAA,IACA,CAAC,KAAK;AAAA,EACR;AAEA,SAAO,oBAAC,aAAa,UAAb,EAAsB,OAAe,UAAS;AACxD;","names":[]}
@@ -0,0 +1,32 @@
1
+ import { E as EphiaConnectionState } from './connection-state-Bk33YprE.js';
2
+ import { a as EphiaAudioState } from './audio-state-kZ3KSvux.js';
3
+
4
+ type EphiaStatus = "idle" | "recording" | "processing" | "error";
5
+ interface EphiaPartial {
6
+ targetId: string | null;
7
+ text: string;
8
+ segmentId: string;
9
+ }
10
+ interface EphiaError {
11
+ code: string;
12
+ message: string;
13
+ }
14
+ interface EphiaStoreState {
15
+ status: EphiaStatus;
16
+ sessionId: string | null;
17
+ error: EphiaError | null;
18
+ activeTargetId: string | null;
19
+ partial: EphiaPartial | null;
20
+ connection: EphiaConnectionState;
21
+ audio: EphiaAudioState;
22
+ _setStatus: (status: EphiaStatus) => void;
23
+ _setSessionId: (sessionId: string | null) => void;
24
+ _setError: (error: EphiaError | null) => void;
25
+ _setActiveTarget: (id: string | null) => void;
26
+ _setPartial: (partial: EphiaPartial | null) => void;
27
+ _setConnection: (connection: EphiaConnectionState) => void;
28
+ _setAudio: (audio: EphiaAudioState) => void;
29
+ _reset: () => void;
30
+ }
31
+
32
+ export type { EphiaStatus as E, EphiaStoreState as a, EphiaError as b, EphiaPartial as c };
@@ -0,0 +1,30 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { CSSProperties } from 'react';
3
+ 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';
4
+ import '../types-D5SXPSwR.js';
5
+ import '../connection-state-Bk33YprE.js';
6
+ import '../Transport-zdeA4Pou.js';
7
+ import 'ephia-protocol';
8
+ import '../audio-state-kZ3KSvux.js';
9
+ import '../session-APaXR48R.js';
10
+
11
+ /** Source of truth: `src/ui/assets/ephia-logo.svg` (same as apps/ephia-website/public/ephia_logo.svg). */
12
+ declare const EPHIA_LOGO_VIEWBOX = "0 0 220 207";
13
+ declare const EPHIA_LOGO_ASPECT: number;
14
+ declare const EPHIA_BRAND_PURPLE = "#723ADE";
15
+ declare const EPHIA_BRAND_TEAL = "#00EBD0";
16
+ type EphiaLogoVariant = "color" | "mono";
17
+ interface EphiaLogoProps {
18
+ height?: number;
19
+ width?: number;
20
+ className?: string;
21
+ style?: CSSProperties;
22
+ variant?: EphiaLogoVariant;
23
+ /** Mono fill (custom brand colors). Ignored when variant is "color". */
24
+ fill?: string;
25
+ isRecording?: boolean;
26
+ }
27
+ declare function logoWidthFromHeight(heightPx: number): number;
28
+ declare function EphiaLogo({ height, width, className, style, variant, fill, isRecording, }: EphiaLogoProps): react_jsx_runtime.JSX.Element;
29
+
30
+ export { EPHIA_BRAND_PURPLE, EPHIA_BRAND_TEAL, EPHIA_LOGO_ASPECT, EPHIA_LOGO_VIEWBOX, EphiaLogo, type EphiaLogoProps, type EphiaLogoVariant, logoWidthFromHeight };
@@ -0,0 +1,34 @@
1
+ import {
2
+ Button,
3
+ EPHIA_BRAND_PURPLE,
4
+ EPHIA_BRAND_TEAL,
5
+ EPHIA_LOGO_ASPECT,
6
+ EPHIA_LOGO_VIEWBOX,
7
+ EphiaFloatingButton,
8
+ EphiaLogo,
9
+ Spinner,
10
+ logoWidthFromHeight
11
+ } from "../chunk-YWZUMUYE.js";
12
+ import "../chunk-ITJFN3VM.js";
13
+ import "../chunk-IDC7FHIZ.js";
14
+ import "../chunk-5IK5TLSK.js";
15
+ import "../chunk-RFQRV7ML.js";
16
+ import "../chunk-DIEWY3IT.js";
17
+ import "../chunk-PSYX674B.js";
18
+ import "../chunk-EGIAN7FH.js";
19
+ import "../chunk-LXMCRXXF.js";
20
+ import "../chunk-N7U5M3VZ.js";
21
+ import "../chunk-THNHRV2B.js";
22
+ import "../chunk-K24GNU27.js";
23
+ export {
24
+ Button,
25
+ EPHIA_BRAND_PURPLE,
26
+ EPHIA_BRAND_TEAL,
27
+ EPHIA_LOGO_ASPECT,
28
+ EPHIA_LOGO_VIEWBOX,
29
+ EphiaFloatingButton,
30
+ EphiaLogo,
31
+ Spinner,
32
+ logoWidthFromHeight
33
+ };
34
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,64 @@
1
+ import * as React from 'react';
2
+ import React__default from 'react';
3
+
4
+ type EphiaSpeechMikeHidStatus = "unsupported" | "driver_missing" | "idle" | "initializing" | "not_present" | "present_unauthorized" | "authorization_required" | "restoring" | "connected" | "disconnected" | "recovering" | "error";
5
+ type EphiaSpeechMikeAudioStatus = "idle" | "permission_required" | "resolving" | "ready" | "not_found" | "error";
6
+ interface EphiaSpeechMikeStatus {
7
+ hid: EphiaSpeechMikeHidStatus;
8
+ audio: EphiaSpeechMikeAudioStatus;
9
+ }
10
+ type EphiaSpeechMikeButton = "RECORD" | "PLAY" | "FORWARD" | "REWIND" | "F1" | "F1_A" | "F2" | "F2_B" | "F3" | "F3_C" | "F4" | "F4_D" | "INS" | "OVR" | "INS_OVR" | "EOL" | "EOL_PRIO" | string;
11
+ type EphiaSpeechMikeAction = "record.toggle" | "record.start" | "record.stop" | "play.toggle" | "seek.forward" | "seek.backward" | "audio.submit" | "audio.discard" | "agent.open" | "exam.new" | "resources.toggle" | "none";
12
+ type EphiaSpeechMikeLedIntent = "off" | "idle" | "recording" | "processing" | "audio_available" | "success" | "error" | "cancelled";
13
+ interface EphiaSpeechMikeDeviceInfo {
14
+ productName?: string;
15
+ manufacturerName?: string;
16
+ vendorId?: number;
17
+ productId?: number;
18
+ }
19
+ interface EphiaSpeechMikeError {
20
+ code: string;
21
+ message: string;
22
+ }
23
+ interface EphiaSpeechMikeState {
24
+ status: EphiaSpeechMikeStatus;
25
+ device: unknown | null;
26
+ deviceInfo: EphiaSpeechMikeDeviceInfo | null;
27
+ physicallyPresent: boolean;
28
+ audioInputDeviceId: string | null;
29
+ audioInputDeviceLabel: string | null;
30
+ pressedButtons: Set<string>;
31
+ lastButton: string | null;
32
+ lastAction: EphiaSpeechMikeAction | null;
33
+ error: EphiaSpeechMikeError | null;
34
+ }
35
+
36
+ type EphiaSpeechMikeProviderProps = {
37
+ children: React__default.ReactNode;
38
+ enabled?: boolean;
39
+ autoConnect?: boolean;
40
+ preferAudioInput?: boolean;
41
+ requestAudioPermissionOnInit?: boolean;
42
+ ledSync?: boolean;
43
+ initialLedIntent?: EphiaSpeechMikeLedIntent;
44
+ buttonMapping?: Partial<Record<string, EphiaSpeechMikeAction>>;
45
+ onAction?: (action: EphiaSpeechMikeAction) => void;
46
+ onError?: (error: EphiaSpeechMikeError) => void;
47
+ onStatusChange?: (state: EphiaSpeechMikeState) => void;
48
+ };
49
+ declare function EphiaSpeechMikeProvider({ children, enabled, autoConnect, preferAudioInput, requestAudioPermissionOnInit, ledSync, initialLedIntent, buttonMapping, onAction, onError, onStatusChange, }: EphiaSpeechMikeProviderProps): React__default.ReactElement;
50
+
51
+ type EphiaSpeechMikeContextValue = EphiaSpeechMikeState & {
52
+ isConnected: boolean;
53
+ isReady: boolean;
54
+ requestAuthorization: () => Promise<void>;
55
+ reconnect: () => Promise<void>;
56
+ setLedIntent: (intent: EphiaSpeechMikeLedIntent) => void;
57
+ setButtonMapping: (mapping: Partial<Record<string, EphiaSpeechMikeAction>>) => void;
58
+ };
59
+ declare const FALLBACK_EPHIA_SPEECHMIKE_STATE: EphiaSpeechMikeState;
60
+ declare const EphiaSpeechMikeContext: React.Context<EphiaSpeechMikeContextValue | null>;
61
+
62
+ declare function useEphiaSpeechMike(): EphiaSpeechMikeContextValue;
63
+
64
+ export { type EphiaSpeechMikeAction as E, FALLBACK_EPHIA_SPEECHMIKE_STATE as F, type EphiaSpeechMikeAudioStatus as a, type EphiaSpeechMikeButton as b, EphiaSpeechMikeContext as c, type EphiaSpeechMikeContextValue as d, type EphiaSpeechMikeDeviceInfo as e, type EphiaSpeechMikeError as f, type EphiaSpeechMikeHidStatus as g, type EphiaSpeechMikeLedIntent as h, EphiaSpeechMikeProvider as i, type EphiaSpeechMikeProviderProps as j, type EphiaSpeechMikeState as k, type EphiaSpeechMikeStatus as l, useEphiaSpeechMike as u };
package/package.json ADDED
@@ -0,0 +1,110 @@
1
+ {
2
+ "name": "@ephia/dova-sdk",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "sideEffects": [
6
+ "**/*.css"
7
+ ],
8
+ "description": "SDK Ephia — dictée audio headless + React + UI",
9
+ "publishConfig": {
10
+ "access": "public"
11
+ },
12
+ "exports": {
13
+ ".": {
14
+ "development": "./src/index.ts",
15
+ "types": "./dist/index.d.ts",
16
+ "import": "./dist/index.js"
17
+ },
18
+ "./shared": {
19
+ "development": "./src/shared/index.ts",
20
+ "types": "./dist/shared/index.d.ts",
21
+ "import": "./dist/shared/index.js"
22
+ },
23
+ "./react": {
24
+ "development": "./src/react/index.ts",
25
+ "types": "./dist/react/index.d.ts",
26
+ "import": "./dist/react/index.js"
27
+ },
28
+ "./speechmike": {
29
+ "development": "./src/devices/speechmike/index.ts",
30
+ "types": "./dist/devices/speechmike/index.d.ts",
31
+ "import": "./dist/devices/speechmike/index.js"
32
+ },
33
+ "./ui": {
34
+ "development": "./src/ui/index.ts",
35
+ "types": "./dist/ui/index.d.ts",
36
+ "import": "./dist/ui/index.js"
37
+ },
38
+ "./bindings": {
39
+ "development": "./src/core/bindings/index.ts",
40
+ "types": "./dist/core/bindings/index.d.ts",
41
+ "import": "./dist/core/bindings/index.js"
42
+ },
43
+ "./headless": {
44
+ "development": "./src/headless/index.ts",
45
+ "types": "./dist/headless/index.d.ts",
46
+ "import": "./dist/headless/index.js"
47
+ },
48
+ "./rich-editor": {
49
+ "development": "./src/rich-editor/index.ts",
50
+ "types": "./dist/rich-editor/index.d.ts",
51
+ "import": "./dist/rich-editor/index.js"
52
+ },
53
+ "./testing": {
54
+ "development": "./src/testing/index.tsx",
55
+ "types": "./dist/testing/index.d.ts",
56
+ "import": "./dist/testing/index.js"
57
+ },
58
+ "./style.css": "./src/style.css"
59
+ },
60
+ "files": [
61
+ "dist",
62
+ "src",
63
+ "src/ui/assets"
64
+ ],
65
+ "scripts": {
66
+ "build": "tsup && cat src/ui/theme.css src/react/ephia-react.css > dist/style.css",
67
+ "dev": "cat src/ui/theme.css src/react/ephia-react.css > dist/style.css && tsup --watch",
68
+ "build:css": "cat src/ui/theme.css src/react/ephia-react.css > dist/style.css",
69
+ "test": "vitest run",
70
+ "typecheck": "tsc --noEmit",
71
+ "clean": "rm -rf dist"
72
+ },
73
+ "dependencies": {
74
+ "@livekit/krisp-noise-filter": "^0.4.3",
75
+ "ephia-protocol": "workspace:*",
76
+ "livekit-client": "^2.0.0",
77
+ "zod": "^3.25.76",
78
+ "zustand": "^5.0.13"
79
+ },
80
+ "optionalDependencies": {
81
+ "dictation_support": "^1.0.5"
82
+ },
83
+ "peerDependencies": {
84
+ "@tiptap/core": ">=2.0.0",
85
+ "@tiptap/pm": ">=2.0.0",
86
+ "react": "^18.0.0 || ^19.0.0",
87
+ "react-dom": "^18.0.0 || ^19.0.0"
88
+ },
89
+ "peerDependenciesMeta": {
90
+ "@tiptap/core": {
91
+ "optional": true
92
+ },
93
+ "@tiptap/pm": {
94
+ "optional": true
95
+ }
96
+ },
97
+ "devDependencies": {
98
+ "@codemirror/state": "^6.5.2",
99
+ "@codemirror/view": "^6.36.5",
100
+ "@testing-library/dom": "^10.4.1",
101
+ "@testing-library/react": "^16.3.2",
102
+ "@tiptap/core": "^3.23.6",
103
+ "@tiptap/pm": "^3.23.6",
104
+ "@types/react": "^18.0.0",
105
+ "jsdom": "^24.0.0",
106
+ "tsup": "^8.5.0",
107
+ "typescript": "^5.4.0",
108
+ "vitest": "^2.0.0"
109
+ }
110
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Source AudioWorklet partagée pour la capture audio.
3
+ *
4
+ * Utilisée par VoiceLevelMeter et StartupAudioBuffer.
5
+ * Évite la duplication du blob URL et du processor name.
6
+ */
7
+
8
+ const AUDIO_WORKLET_SOURCE = `
9
+ class AudioCaptureProcessor extends AudioWorkletProcessor {
10
+ process(inputs) {
11
+ const input = inputs[0];
12
+ if (input.length > 0) {
13
+ this.port.postMessage(new Float32Array(input[0]));
14
+ }
15
+ return true;
16
+ }
17
+ }
18
+ registerProcessor('ephia-audio-capture', AudioCaptureProcessor);
19
+ `;
20
+
21
+ let sharedWorkletModuleUrl: string | null = null;
22
+
23
+ export function getAudioWorkletModuleUrl(): string {
24
+ if (!sharedWorkletModuleUrl) {
25
+ sharedWorkletModuleUrl = URL.createObjectURL(
26
+ new Blob([AUDIO_WORKLET_SOURCE], { type: "application/javascript" })
27
+ );
28
+ }
29
+ return sharedWorkletModuleUrl;
30
+ }
@@ -0,0 +1,3 @@
1
+ export { getAudioWorkletModuleUrl } from "./audio-worklet-source";
2
+ export { VoiceLevelMeter } from "./voice-level-meter";
3
+ export type { VoiceLevelSnapshot } from "./voice-level-meter";
@@ -0,0 +1,27 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { VoiceLevelMeter } from "./voice-level-meter";
3
+
4
+ describe("VoiceLevelMeter startup capture", () => {
5
+ it("resamples captured Float32 audio to PCM16 16 kHz on drain", () => {
6
+ const meter = new VoiceLevelMeter() as unknown as {
7
+ _actualSampleRate: number;
8
+ _captureEnabled: boolean;
9
+ _captureBuffers: Float32Array[];
10
+ _captureTotalSamples: number;
11
+ drainStartupCapture: () => ArrayBuffer | null;
12
+ };
13
+ const source = new Float32Array(48_000);
14
+ source.fill(0.5);
15
+ meter._actualSampleRate = 48_000;
16
+ meter._captureEnabled = true;
17
+ meter._captureBuffers = [source];
18
+ meter._captureTotalSamples = source.length;
19
+
20
+ const pcm = meter.drainStartupCapture();
21
+
22
+ expect(pcm).not.toBeNull();
23
+ const samples = new Int16Array(pcm!);
24
+ expect(samples.length).toBe(16_000);
25
+ expect(samples[0]).toBeGreaterThan(16_000);
26
+ });
27
+ });