@dxos/plugin-transcription 0.9.0 → 0.9.1-staging.ee54ba693a

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 (324) hide show
  1. package/PLUGIN.mdl +25 -5
  2. package/dist/lib/neutral/{TranscriptionArticle-L6XANBH5.mjs → TranscriptionArticle-FEWCWG4A.mjs} +4 -7
  3. package/dist/lib/neutral/TranscriptionArticle-FEWCWG4A.mjs.map +7 -0
  4. package/dist/lib/neutral/TranscriptionPlugin.mjs +29 -6
  5. package/dist/lib/neutral/TranscriptionPlugin.mjs.map +4 -4
  6. package/dist/lib/neutral/TranscriptionPlugin.node.mjs +3 -3
  7. package/dist/lib/neutral/TranscriptionPlugin.node.mjs.map +3 -3
  8. package/dist/lib/neutral/app-graph-builder-GQRMI22E.mjs +48 -0
  9. package/dist/lib/neutral/app-graph-builder-GQRMI22E.mjs.map +7 -0
  10. package/dist/lib/neutral/capabilities/index.mjs +19 -5
  11. package/dist/lib/neutral/capabilities/index.mjs.map +3 -3
  12. package/dist/lib/neutral/chunk-5BVHY75B.mjs +54 -0
  13. package/dist/lib/neutral/chunk-5BVHY75B.mjs.map +7 -0
  14. package/dist/lib/neutral/chunk-HNXSU7HJ.mjs +8 -0
  15. package/dist/lib/neutral/{chunk-KXJZEYS7.mjs.map → chunk-HNXSU7HJ.mjs.map} +2 -2
  16. package/dist/lib/neutral/chunk-KOXLGGSL.mjs +30 -0
  17. package/dist/lib/neutral/chunk-KOXLGGSL.mjs.map +7 -0
  18. package/dist/lib/neutral/chunk-MDV7NBFJ.mjs +182 -0
  19. package/dist/lib/neutral/chunk-MDV7NBFJ.mjs.map +7 -0
  20. package/dist/lib/neutral/components/index.mjs +114 -258
  21. package/dist/lib/neutral/components/index.mjs.map +4 -4
  22. package/dist/lib/neutral/containers/index.mjs +1 -1
  23. package/dist/lib/neutral/{create-RVR7VC33.mjs → create-HNHGCKZ4.mjs} +2 -2
  24. package/dist/lib/neutral/enrich-message-DSJU4TXC.mjs +24 -0
  25. package/dist/lib/neutral/enrich-message-DSJU4TXC.mjs.map +7 -0
  26. package/dist/lib/neutral/entity-lookup-PCDW7NC4.mjs +25 -0
  27. package/dist/lib/neutral/entity-lookup-PCDW7NC4.mjs.map +7 -0
  28. package/dist/lib/neutral/hooks/index.mjs +93 -15
  29. package/dist/lib/neutral/hooks/index.mjs.map +4 -4
  30. package/dist/lib/neutral/index.mjs +8 -32
  31. package/dist/lib/neutral/markdown-extension-CCDXXY7E.mjs +16 -0
  32. package/dist/lib/neutral/markdown-extension-CCDXXY7E.mjs.map +7 -0
  33. package/dist/lib/neutral/meta.json +1 -1
  34. package/dist/lib/neutral/meta.mjs +1 -1
  35. package/dist/lib/neutral/{open-A5KXKRH4.mjs → open-SNMZXXYO.mjs} +4 -6
  36. package/dist/lib/neutral/open-SNMZXXYO.mjs.map +7 -0
  37. package/dist/lib/neutral/operations/index.mjs +1 -1
  38. package/dist/lib/neutral/pipeline-status-XMWMAUJY.mjs +17 -0
  39. package/dist/lib/neutral/pipeline-status-XMWMAUJY.mjs.map +7 -0
  40. package/dist/lib/neutral/plugin.mjs +2 -2
  41. package/dist/lib/neutral/recording-session-IADO7ATU.mjs +15 -0
  42. package/dist/lib/neutral/recording-session-IADO7ATU.mjs.map +7 -0
  43. package/dist/lib/neutral/settings-7KE4MABW.mjs +31 -0
  44. package/dist/lib/neutral/settings-7KE4MABW.mjs.map +7 -0
  45. package/dist/lib/neutral/skill-definition-DXNK324V.mjs +15 -0
  46. package/dist/lib/neutral/skill-definition-DXNK324V.mjs.map +7 -0
  47. package/dist/lib/neutral/skills/index.mjs +8 -0
  48. package/dist/lib/neutral/{summarize-5XPPMVTE.mjs → summarize-LBUZTOTH.mjs} +4 -4
  49. package/dist/lib/neutral/summarize-LBUZTOTH.mjs.map +7 -0
  50. package/dist/lib/neutral/{text-content-KBB37HSM.mjs → text-content-NOWR642C.mjs} +9 -9
  51. package/dist/lib/neutral/text-content-NOWR642C.mjs.map +7 -0
  52. package/dist/lib/neutral/transcriber-6XZHUUHK.mjs +174 -0
  53. package/dist/lib/neutral/transcriber-6XZHUUHK.mjs.map +7 -0
  54. package/dist/lib/neutral/transcription-driver-DN6ELQXZ.mjs +207 -0
  55. package/dist/lib/neutral/transcription-driver-DN6ELQXZ.mjs.map +7 -0
  56. package/dist/lib/neutral/translations.mjs +8 -1
  57. package/dist/lib/neutral/translations.mjs.map +3 -3
  58. package/dist/lib/neutral/types/index.mjs +3 -1
  59. package/dist/types/dx.config.d.ts +28 -0
  60. package/dist/types/dx.config.d.ts.map +1 -0
  61. package/dist/types/src/TranscriptionPlugin.d.ts.map +1 -1
  62. package/dist/types/src/capabilities/app-graph-builder.d.ts +5 -0
  63. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -0
  64. package/dist/types/src/capabilities/entity-lookup.d.ts +10 -0
  65. package/dist/types/src/capabilities/entity-lookup.d.ts.map +1 -0
  66. package/dist/types/src/capabilities/index.d.ts +11 -8
  67. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  68. package/dist/types/src/capabilities/markdown-extension.d.ts +5 -0
  69. package/dist/types/src/capabilities/markdown-extension.d.ts.map +1 -0
  70. package/dist/types/src/capabilities/pipeline-status.d.ts +9 -0
  71. package/dist/types/src/capabilities/pipeline-status.d.ts.map +1 -0
  72. package/dist/types/src/capabilities/react-surface.d.ts +2 -2
  73. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  74. package/dist/types/src/capabilities/recording-session.d.ts +5 -0
  75. package/dist/types/src/capabilities/recording-session.d.ts.map +1 -0
  76. package/dist/types/src/capabilities/settings.d.ts +5 -0
  77. package/dist/types/src/capabilities/settings.d.ts.map +1 -0
  78. package/dist/types/src/capabilities/skill-definition.d.ts +5 -0
  79. package/dist/types/src/capabilities/skill-definition.d.ts.map +1 -0
  80. package/dist/types/src/capabilities/text-content.d.ts +1 -4
  81. package/dist/types/src/capabilities/transcriber.d.ts +4 -3
  82. package/dist/types/src/capabilities/transcriber.d.ts.map +1 -1
  83. package/dist/types/src/capabilities/transcription-driver.d.ts +5 -0
  84. package/dist/types/src/capabilities/transcription-driver.d.ts.map +1 -0
  85. package/dist/types/src/components/Mic/Mic.d.ts +12 -0
  86. package/dist/types/src/components/Mic/Mic.d.ts.map +1 -0
  87. package/dist/types/src/components/{Oracle/Oracle.stories.d.ts → Mic/Mic.stories.d.ts} +9 -7
  88. package/dist/types/src/components/Mic/Mic.stories.d.ts.map +1 -0
  89. package/dist/types/src/components/Mic/index.d.ts +2 -0
  90. package/dist/types/src/components/Mic/index.d.ts.map +1 -0
  91. package/dist/types/src/components/index.d.ts +1 -2
  92. package/dist/types/src/components/index.d.ts.map +1 -1
  93. package/dist/types/src/containers/TranscriptionArticle/TranscriptionArticle.d.ts.map +1 -1
  94. package/dist/types/src/containers/TranscriptionArticle/TranscriptionArticle.stories.d.ts +7 -0
  95. package/dist/types/src/containers/TranscriptionArticle/TranscriptionArticle.stories.d.ts.map +1 -1
  96. package/dist/types/src/hooks/index.d.ts +0 -5
  97. package/dist/types/src/hooks/index.d.ts.map +1 -1
  98. package/dist/types/src/hooks/useTranscriptionRecording.d.ts.map +1 -1
  99. package/dist/types/src/index.d.ts +1 -3
  100. package/dist/types/src/index.d.ts.map +1 -1
  101. package/dist/types/src/meta.d.ts +32 -2
  102. package/dist/types/src/meta.d.ts.map +1 -1
  103. package/dist/types/src/normalization/message-normalizer.d.ts +2 -2
  104. package/dist/types/src/normalization/message-normalizer.d.ts.map +1 -1
  105. package/dist/types/src/normalization/normalization.d.ts +98 -733
  106. package/dist/types/src/normalization/normalization.d.ts.map +1 -1
  107. package/dist/types/src/operations/enrich-message.d.ts +9 -0
  108. package/dist/types/src/operations/enrich-message.d.ts.map +1 -0
  109. package/dist/types/src/operations/index.d.ts.map +1 -1
  110. package/dist/types/src/operations/open.d.ts.map +1 -1
  111. package/dist/types/src/operations/summarize.d.ts.map +1 -1
  112. package/dist/types/src/skills/index.d.ts +2 -0
  113. package/dist/types/src/skills/index.d.ts.map +1 -0
  114. package/dist/types/src/skills/transcription-skill.d.ts +4 -0
  115. package/dist/types/src/skills/transcription-skill.d.ts.map +1 -0
  116. package/dist/types/src/stories/Keyword.stories.d.ts +51 -0
  117. package/dist/types/src/stories/Keyword.stories.d.ts.map +1 -0
  118. package/dist/types/src/stories/Pipeline.stories.d.ts +60 -0
  119. package/dist/types/src/stories/Pipeline.stories.d.ts.map +1 -0
  120. package/dist/types/src/stories/Transcription.stories.d.ts +23 -0
  121. package/dist/types/src/stories/Transcription.stories.d.ts.map +1 -0
  122. package/dist/types/src/testing/decorators.d.ts +21 -0
  123. package/dist/types/src/testing/decorators.d.ts.map +1 -0
  124. package/dist/types/src/testing/index.d.ts +1 -0
  125. package/dist/types/src/testing/index.d.ts.map +1 -1
  126. package/dist/types/src/testing/testing.d.ts +3 -13
  127. package/dist/types/src/testing/testing.d.ts.map +1 -1
  128. package/dist/types/src/{transcriber/transcription-manager.d.ts → transcription-manager.d.ts} +6 -5
  129. package/dist/types/src/transcription-manager.d.ts.map +1 -0
  130. package/dist/types/src/translations.d.ts +7 -0
  131. package/dist/types/src/translations.d.ts.map +1 -1
  132. package/dist/types/src/types/Settings.d.ts +13 -0
  133. package/dist/types/src/types/Settings.d.ts.map +1 -0
  134. package/dist/types/src/types/TranscriptOperation.d.ts +114 -1564
  135. package/dist/types/src/types/TranscriptOperation.d.ts.map +1 -1
  136. package/dist/types/src/types/TranscriptionCapabilities.d.ts +52 -11
  137. package/dist/types/src/types/TranscriptionCapabilities.d.ts.map +1 -1
  138. package/dist/types/src/types/index.d.ts +1 -0
  139. package/dist/types/src/types/index.d.ts.map +1 -1
  140. package/dist/types/src/util/index.d.ts +0 -3
  141. package/dist/types/src/util/index.d.ts.map +1 -1
  142. package/dist/types/tsconfig.tsbuildinfo +1 -1
  143. package/dx.config.ts +42 -0
  144. package/package.json +69 -69
  145. package/src/TranscriptionPlugin.node.ts +2 -2
  146. package/src/TranscriptionPlugin.test.ts +2 -2
  147. package/src/TranscriptionPlugin.tsx +40 -3
  148. package/src/capabilities/app-graph-builder.tsx +49 -0
  149. package/src/capabilities/entity-lookup.ts +32 -0
  150. package/src/capabilities/index.ts +8 -7
  151. package/src/capabilities/markdown-extension.ts +17 -0
  152. package/src/capabilities/pipeline-status.ts +23 -0
  153. package/src/capabilities/recording-session.ts +17 -0
  154. package/src/capabilities/settings.ts +34 -0
  155. package/src/capabilities/skill-definition.ts +15 -0
  156. package/src/capabilities/text-content.ts +10 -7
  157. package/src/capabilities/transcriber.ts +5 -48
  158. package/src/capabilities/transcription-driver.tsx +263 -0
  159. package/src/components/Mic/Mic.stories.tsx +66 -0
  160. package/src/components/Mic/Mic.tsx +136 -0
  161. package/src/components/Mic/index.ts +5 -0
  162. package/src/components/index.ts +1 -2
  163. package/src/containers/TranscriptionArticle/TranscriptionArticle.stories.tsx +4 -0
  164. package/src/containers/TranscriptionArticle/TranscriptionArticle.tsx +5 -6
  165. package/src/hooks/index.ts +0 -5
  166. package/src/hooks/useTranscriptionRecording.ts +27 -9
  167. package/src/index.ts +1 -5
  168. package/src/meta.ts +2 -35
  169. package/src/normalization/message-normalizer.ts +3 -3
  170. package/src/normalization/normalization.ts +3 -0
  171. package/src/operations/enrich-message.ts +27 -0
  172. package/src/operations/index.ts +1 -0
  173. package/src/operations/open.ts +2 -2
  174. package/src/operations/summarize.ts +2 -2
  175. package/src/skills/index.ts +5 -0
  176. package/src/skills/transcription-skill.ts +29 -0
  177. package/src/stories/Keyword.stories.tsx +98 -0
  178. package/src/stories/Pipeline.stories.tsx +361 -0
  179. package/src/stories/Transcription.stories.tsx +178 -0
  180. package/src/testing/decorators.ts +78 -0
  181. package/src/testing/index.ts +1 -0
  182. package/src/testing/testing.ts +14 -134
  183. package/src/{transcriber/transcription-manager.ts → transcription-manager.ts} +13 -12
  184. package/src/translations.ts +9 -1
  185. package/src/types/Settings.ts +59 -0
  186. package/src/types/TranscriptOperation.ts +22 -4
  187. package/src/types/TranscriptionCapabilities.ts +61 -20
  188. package/src/types/index.ts +1 -0
  189. package/src/util/index.ts +0 -3
  190. package/dist/lib/neutral/TranscriptionArticle-L6XANBH5.mjs.map +0 -7
  191. package/dist/lib/neutral/blueprint-definition-DA4QFRYJ.mjs +0 -15
  192. package/dist/lib/neutral/blueprint-definition-DA4QFRYJ.mjs.map +0 -7
  193. package/dist/lib/neutral/blueprints/index.mjs +0 -8
  194. package/dist/lib/neutral/chunk-FHNI26QW.mjs +0 -45
  195. package/dist/lib/neutral/chunk-FHNI26QW.mjs.map +0 -7
  196. package/dist/lib/neutral/chunk-KAEXRX3Y.mjs +0 -35
  197. package/dist/lib/neutral/chunk-KAEXRX3Y.mjs.map +0 -7
  198. package/dist/lib/neutral/chunk-KMT3BMMQ.mjs +0 -124
  199. package/dist/lib/neutral/chunk-KMT3BMMQ.mjs.map +0 -7
  200. package/dist/lib/neutral/chunk-KXJZEYS7.mjs +0 -8
  201. package/dist/lib/neutral/chunk-MLRJWAQH.mjs +0 -179
  202. package/dist/lib/neutral/chunk-MLRJWAQH.mjs.map +0 -7
  203. package/dist/lib/neutral/chunk-TO77KAQK.mjs +0 -298
  204. package/dist/lib/neutral/chunk-TO77KAQK.mjs.map +0 -7
  205. package/dist/lib/neutral/chunk-TX3NQISZ.mjs +0 -435
  206. package/dist/lib/neutral/chunk-TX3NQISZ.mjs.map +0 -7
  207. package/dist/lib/neutral/chunk-ZR4BH4QQ.mjs +0 -30
  208. package/dist/lib/neutral/chunk-ZR4BH4QQ.mjs.map +0 -7
  209. package/dist/lib/neutral/open-A5KXKRH4.mjs.map +0 -7
  210. package/dist/lib/neutral/summarize-5XPPMVTE.mjs.map +0 -7
  211. package/dist/lib/neutral/text-content-KBB37HSM.mjs.map +0 -7
  212. package/dist/lib/neutral/transcriber-OGSF3XO5.mjs +0 -59
  213. package/dist/lib/neutral/transcriber-OGSF3XO5.mjs.map +0 -7
  214. package/dist/types/src/blueprints/index.d.ts +0 -2
  215. package/dist/types/src/blueprints/index.d.ts.map +0 -1
  216. package/dist/types/src/blueprints/transcription-blueprint.d.ts +0 -4
  217. package/dist/types/src/blueprints/transcription-blueprint.d.ts.map +0 -1
  218. package/dist/types/src/capabilities/blueprint-definition.d.ts +0 -6
  219. package/dist/types/src/capabilities/blueprint-definition.d.ts.map +0 -1
  220. package/dist/types/src/components/Oracle/Oracle.d.ts +0 -24
  221. package/dist/types/src/components/Oracle/Oracle.d.ts.map +0 -1
  222. package/dist/types/src/components/Oracle/Oracle.stories.d.ts.map +0 -1
  223. package/dist/types/src/components/Oracle/index.d.ts +0 -2
  224. package/dist/types/src/components/Oracle/index.d.ts.map +0 -1
  225. package/dist/types/src/components/Transcription/Transcription.d.ts +0 -11
  226. package/dist/types/src/components/Transcription/Transcription.d.ts.map +0 -1
  227. package/dist/types/src/components/Transcription/Transcription.stories.d.ts +0 -37
  228. package/dist/types/src/components/Transcription/Transcription.stories.d.ts.map +0 -1
  229. package/dist/types/src/components/Transcription/index.d.ts +0 -2
  230. package/dist/types/src/components/Transcription/index.d.ts.map +0 -1
  231. package/dist/types/src/components/Transcription/transcription-extension.d.ts +0 -15
  232. package/dist/types/src/components/Transcription/transcription-extension.d.ts.map +0 -1
  233. package/dist/types/src/enrichment/conversation.test.d.ts +0 -2
  234. package/dist/types/src/enrichment/conversation.test.d.ts.map +0 -1
  235. package/dist/types/src/enrichment/operations.d.ts +0 -200
  236. package/dist/types/src/enrichment/operations.d.ts.map +0 -1
  237. package/dist/types/src/enrichment/parser.d.ts +0 -26
  238. package/dist/types/src/enrichment/parser.d.ts.map +0 -1
  239. package/dist/types/src/enrichment/stream-simulator.d.ts +0 -38
  240. package/dist/types/src/enrichment/stream-simulator.d.ts.map +0 -1
  241. package/dist/types/src/hooks/useAudioFile.d.ts +0 -7
  242. package/dist/types/src/hooks/useAudioFile.d.ts.map +0 -1
  243. package/dist/types/src/hooks/useAudioTrack.d.ts +0 -5
  244. package/dist/types/src/hooks/useAudioTrack.d.ts.map +0 -1
  245. package/dist/types/src/hooks/useFeedModelAdapter.d.ts +0 -12
  246. package/dist/types/src/hooks/useFeedModelAdapter.d.ts.map +0 -1
  247. package/dist/types/src/hooks/useTranscriber.d.ts +0 -7
  248. package/dist/types/src/hooks/useTranscriber.d.ts.map +0 -1
  249. package/dist/types/src/hooks/useVoiceInput.d.ts +0 -11
  250. package/dist/types/src/hooks/useVoiceInput.d.ts.map +0 -1
  251. package/dist/types/src/model/index.d.ts +0 -2
  252. package/dist/types/src/model/index.d.ts.map +0 -1
  253. package/dist/types/src/model/model.d.ts +0 -68
  254. package/dist/types/src/model/model.d.ts.map +0 -1
  255. package/dist/types/src/model/model.test.d.ts +0 -2
  256. package/dist/types/src/model/model.test.d.ts.map +0 -1
  257. package/dist/types/src/stories/FileTranscription.stories.d.ts +0 -20
  258. package/dist/types/src/stories/FileTranscription.stories.d.ts.map +0 -1
  259. package/dist/types/src/stories/KeyWordRecognition.stories.d.ts +0 -14
  260. package/dist/types/src/stories/KeyWordRecognition.stories.d.ts.map +0 -1
  261. package/dist/types/src/stories/LiveTranscription.stories.d.ts +0 -20
  262. package/dist/types/src/stories/LiveTranscription.stories.d.ts.map +0 -1
  263. package/dist/types/src/stories/TranscriptionStory.d.ts +0 -21
  264. package/dist/types/src/stories/TranscriptionStory.d.ts.map +0 -1
  265. package/dist/types/src/stories/common.d.ts +0 -248
  266. package/dist/types/src/stories/common.d.ts.map +0 -1
  267. package/dist/types/src/transcriber/audio-recorder.d.ts +0 -47
  268. package/dist/types/src/transcriber/audio-recorder.d.ts.map +0 -1
  269. package/dist/types/src/transcriber/index.d.ts +0 -5
  270. package/dist/types/src/transcriber/index.d.ts.map +0 -1
  271. package/dist/types/src/transcriber/media-stream-recorder.d.ts +0 -30
  272. package/dist/types/src/transcriber/media-stream-recorder.d.ts.map +0 -1
  273. package/dist/types/src/transcriber/transcriber.browser.test.d.ts +0 -2
  274. package/dist/types/src/transcriber/transcriber.browser.test.d.ts.map +0 -1
  275. package/dist/types/src/transcriber/transcriber.d.ts +0 -105
  276. package/dist/types/src/transcriber/transcriber.d.ts.map +0 -1
  277. package/dist/types/src/transcriber/transcriber.test.d.ts +0 -2
  278. package/dist/types/src/transcriber/transcriber.test.d.ts.map +0 -1
  279. package/dist/types/src/transcriber/transcription-manager.d.ts.map +0 -1
  280. package/dist/types/src/util/array.d.ts +0 -2
  281. package/dist/types/src/util/array.d.ts.map +0 -1
  282. package/dist/types/src/util/monitor-audio-level.d.ts +0 -6
  283. package/dist/types/src/util/monitor-audio-level.d.ts.map +0 -1
  284. package/dist/types/src/util/render-byline.d.ts +0 -4
  285. package/dist/types/src/util/render-byline.d.ts.map +0 -1
  286. package/src/blueprints/index.ts +0 -5
  287. package/src/blueprints/transcription-blueprint.ts +0 -29
  288. package/src/capabilities/blueprint-definition.ts +0 -19
  289. package/src/components/Oracle/Oracle.stories.tsx +0 -147
  290. package/src/components/Oracle/Oracle.tsx +0 -142
  291. package/src/components/Oracle/index.ts +0 -5
  292. package/src/components/Transcription/Transcription.stories.tsx +0 -213
  293. package/src/components/Transcription/Transcription.tsx +0 -55
  294. package/src/components/Transcription/index.ts +0 -5
  295. package/src/components/Transcription/transcription-extension.ts +0 -203
  296. package/src/enrichment/conversation.test.ts +0 -162
  297. package/src/enrichment/conversation.txt +0 -23
  298. package/src/enrichment/operations.ts +0 -271
  299. package/src/enrichment/parser.ts +0 -101
  300. package/src/enrichment/stream-simulator.ts +0 -125
  301. package/src/hooks/useAudioFile.ts +0 -88
  302. package/src/hooks/useAudioTrack.ts +0 -35
  303. package/src/hooks/useFeedModelAdapter.ts +0 -46
  304. package/src/hooks/useTranscriber.ts +0 -47
  305. package/src/hooks/useVoiceInput.ts +0 -66
  306. package/src/model/index.ts +0 -5
  307. package/src/model/model.test.ts +0 -175
  308. package/src/model/model.ts +0 -229
  309. package/src/stories/FileTranscription.stories.tsx +0 -143
  310. package/src/stories/KeyWordRecognition.stories.tsx +0 -132
  311. package/src/stories/LiveTranscription.stories.tsx +0 -153
  312. package/src/stories/TranscriptionStory.tsx +0 -101
  313. package/src/stories/common.ts +0 -233
  314. package/src/transcriber/audio-recorder.ts +0 -56
  315. package/src/transcriber/index.ts +0 -8
  316. package/src/transcriber/media-stream-recorder.ts +0 -120
  317. package/src/transcriber/transcriber.browser.test.ts +0 -230
  318. package/src/transcriber/transcriber.test.ts +0 -104
  319. package/src/transcriber/transcriber.ts +0 -303
  320. package/src/util/array.ts +0 -14
  321. package/src/util/monitor-audio-level.ts +0 -58
  322. package/src/util/render-byline.ts +0 -33
  323. /package/dist/lib/neutral/{create-RVR7VC33.mjs.map → create-HNHGCKZ4.mjs.map} +0 -0
  324. /package/dist/lib/neutral/{blueprints → skills}/index.mjs.map +0 -0
@@ -9,28 +9,12 @@ import { ClientCapabilities } from '@dxos/plugin-client';
9
9
 
10
10
  import { TranscriptionCapabilities } from '#types';
11
11
 
12
- import { MediaStreamRecorder, Transcriber, TranscriptionManager } from '../transcriber';
13
-
14
- // TODO(burdon): Move to config?
15
-
16
- /**
17
- * Length of the chunk in ms.
18
- */
19
- const RECORD_INTERVAL = 200;
20
-
21
- /**
22
- * Number of chunks to save before the user starts speaking.
23
- */
24
- const PREFIXED_CHUNKS_AMOUNT = 10;
12
+ import { TranscriptionManagerImpl } from '../transcription-manager';
25
13
 
26
14
  /**
27
- * Number of chunks to transcribe automatically after.
28
- * Combined should be mess than 25MB or whisper would fail.
29
- */
30
- const TRANSCRIBE_AFTER_CHUNKS_AMOUNT = 50;
31
-
32
- /**
33
- * Records audio while user is speaking and transcribes it after user is done speaking.
15
+ * Provides the higher-level transcription manager to the app-framework so other plugins can obtain it
16
+ * via DI. The low-level construction lives in `@dxos/react-ui-transcription`; this module is the
17
+ * provision seam.
34
18
  */
35
19
  export default Capability.makeModule(
36
20
  Effect.fnUntraced(function* () {
@@ -38,37 +22,11 @@ export default Capability.makeModule(
38
22
  const capabilities = yield* Capability.Service;
39
23
  const registry = yield* Capability.get(Capabilities.AtomRegistry);
40
24
 
41
- const transcriberProvider: TranscriptionCapabilities.TranscriberProvider = ({
42
- audioStreamTrack,
43
- onSegments,
44
- transcriberConfig,
45
- recorderConfig,
46
- transcribe,
47
- }) => {
48
- // Initialize audio transcription.
49
- return new Transcriber({
50
- config: {
51
- transcribeAfterChunksAmount: TRANSCRIBE_AFTER_CHUNKS_AMOUNT,
52
- prefixBufferChunksAmount: PREFIXED_CHUNKS_AMOUNT,
53
- ...transcriberConfig,
54
- },
55
- recorder: new MediaStreamRecorder({
56
- mediaStreamTrack: audioStreamTrack,
57
- config: {
58
- interval: RECORD_INTERVAL,
59
- ...recorderConfig,
60
- },
61
- }),
62
- onSegments,
63
- transcribe,
64
- });
65
- };
66
-
67
25
  const transcriptionManagerProvider: TranscriptionCapabilities.TranscriptionManagerProvider = ({
68
26
  messageEnricher,
69
27
  }) => {
70
28
  const client = capabilities.get(ClientCapabilities.Client);
71
- const transcriptionManager = new TranscriptionManager({
29
+ const transcriptionManager = new TranscriptionManagerImpl({
72
30
  edgeClient: client.edge.http,
73
31
  messageEnricher,
74
32
  registry,
@@ -83,7 +41,6 @@ export default Capability.makeModule(
83
41
  };
84
42
 
85
43
  return [
86
- Capability.contributes(TranscriptionCapabilities.TranscriberProvider, transcriberProvider),
87
44
  Capability.contributes(TranscriptionCapabilities.TranscriptionManagerProvider, transcriptionManagerProvider),
88
45
  ];
89
46
  }),
@@ -0,0 +1,263 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import * as Effect from 'effect/Effect';
6
+ import React, { Fragment, useCallback, useEffect, useMemo, useRef, useState } from 'react';
7
+
8
+ import { Capabilities, Capability } from '@dxos/app-framework';
9
+ import { useAtomCapability, useAtomCapabilityState, useCapabilities } from '@dxos/app-framework/ui';
10
+ import { log } from '@dxos/log';
11
+ import { MarkdownCapabilities } from '@dxos/plugin-markdown/types';
12
+ import { useAudioTrack, useTranscriber } from '@dxos/react-ui-transcription';
13
+ import { linkEntities } from '@dxos/transcription-pipeline';
14
+ import { type ContentBlock } from '@dxos/types';
15
+ import { PendingTextStreamer, cancelPendingText, editorPendingTextSink, pendingTextState } from '@dxos/ui-editor';
16
+
17
+ import { meta } from '#meta';
18
+ import { TranscriptionCapabilities } from '#types';
19
+
20
+ // Recorder chunk interval; the transcriber's chunk threshold is derived from the buffering setting.
21
+ const RECORDER_INTERVAL_MS = 200;
22
+
23
+ /**
24
+ * Headless controller driving live transcription into a Markdown editor. Reads the active recording
25
+ * session, captures audio while recording, and dispatches the transcribed text into the target
26
+ * editor as pending-text effects. The user confirms or discards the pending text via the editor's
27
+ * inline affordances. Mounted once, app-wide, via `Capabilities.ReactContext`.
28
+ */
29
+ const TranscriptionDriver = () => {
30
+ const [session, setSession] = useAtomCapabilityState(TranscriptionCapabilities.RecordingSession);
31
+ // `useCapabilities` (not `useCapability`) so the driver does not throw when plugin-markdown is absent.
32
+ const [editorViews] = useCapabilities(MarkdownCapabilities.EditorViews);
33
+ // Injected entity resolver (full-text/vector/…); the driver stays decoupled from the database.
34
+ const [lookup] = useCapabilities(TranscriptionCapabilities.EntityLookup);
35
+ const settings = useAtomCapability(TranscriptionCapabilities.Settings);
36
+
37
+ const [, setStatus] = useAtomCapabilityState(TranscriptionCapabilities.PipelineStatus);
38
+
39
+ const recording = session?.recording ?? false;
40
+ const liveSessionId = session?.id;
41
+
42
+ // Only this driver's editor-backed sessions are captured here: if no editor view is registered for
43
+ // the session there is nowhere to stream transcription, so the driver stays idle and leaves the
44
+ // mic to whoever owns that session (e.g. a non-editor consumer running its own transcriber).
45
+ const hasEditorForSession = !!(liveSessionId && editorViews?.get(liveSessionId));
46
+
47
+ // Lifecycle phase. Driven from `recording` via an effect (not derived synchronously) so that when
48
+ // the mic switches off the phase is still 'recording' for that commit — nothing tears down until
49
+ // the drain finishes and sets 'idle'. This lets the final transcription + enrichment complete.
50
+ const [phase, setPhase] = useState<'idle' | 'recording' | 'draining'>('idle');
51
+ const active = phase !== 'idle';
52
+
53
+ // The toolbar clears the RecordingSession on stop, but the driver must keep targeting the same
54
+ // editor through the drain — capture the session id for the lifetime of the active phase (the
55
+ // editor stays open). Cleared once the phase returns to idle.
56
+ const [sessionId, setSessionId] = useState<string>();
57
+ useEffect(() => {
58
+ if (recording && liveSessionId && hasEditorForSession) {
59
+ setSessionId(liveSessionId);
60
+ }
61
+ }, [recording, liveSessionId, hasEditorForSession]);
62
+
63
+ useEffect(() => {
64
+ setPhase((current) =>
65
+ recording && hasEditorForSession ? 'recording' : current === 'recording' ? 'draining' : current,
66
+ );
67
+ }, [recording, hasEditorForSession]);
68
+
69
+ useEffect(() => {
70
+ if (phase === 'idle') {
71
+ setSessionId(undefined);
72
+ }
73
+ }, [phase]);
74
+
75
+ // Publish the phase so the toolbar / testbench can reflect mic + pipeline state in real time.
76
+ useEffect(() => {
77
+ setStatus(() => ({ phase }));
78
+ }, [phase, setStatus]);
79
+
80
+ // `ideal` (not `exact`) so an unavailable device falls back to the default rather than failing.
81
+ const audioConstraints = useMemo<MediaTrackConstraints | undefined>(
82
+ () => (settings?.audioDeviceId ? { deviceId: { ideal: settings.audioDeviceId } } : undefined),
83
+ [settings?.audioDeviceId],
84
+ );
85
+
86
+ // Keep the track (and thus the transcriber) alive across the whole active session — including the
87
+ // drain — so the transcriber can flush its buffered audio before teardown. Released at idle. The
88
+ // mic indicator therefore lingers for the brief drain after stop.
89
+ const track = useAudioTrack(active, audioConstraints);
90
+
91
+ // Refs so `handleSegments` stays stable (changing it would recreate the transcriber).
92
+ const sessionIdRef = useRef(sessionId);
93
+ sessionIdRef.current = sessionId;
94
+ const editorViewsRef = useRef(editorViews);
95
+ editorViewsRef.current = editorViews;
96
+
97
+ // The user cancelled (✕) if the pending decoration was cleared mid-session; guards against
98
+ // resurrecting it with late transcription / post-process writes during the drain.
99
+ const isCancelled = useCallback(() => {
100
+ const id = sessionIdRef.current;
101
+ const view = id ? editorViewsRef.current?.get(id)?.view : undefined;
102
+ return view ? view.state.field(pendingTextState, false) == null : false;
103
+ }, []);
104
+
105
+ // Streams transcribed text into the editor's pending-text block (buffering + word-by-word reveal).
106
+ // Kept alive across the whole session (incl. drain); disposed only when the phase returns to idle.
107
+ const streamerRef = useRef<PendingTextStreamer | null>(null);
108
+
109
+ useEffect(() => {
110
+ if (!active || !editorViews || !sessionId) {
111
+ return;
112
+ }
113
+ const entry = editorViews.get(sessionId);
114
+ if (!entry) {
115
+ return;
116
+ }
117
+
118
+ // Clicking the toolbar blurs the editor and hides the caret, so anchor + placeholder give
119
+ // immediate feedback while the first transcription is buffered.
120
+ // When entity extraction is enabled and a lookup is available, rewrite settled text with inline
121
+ // `[noun](echo:/<id>)` links — decorated as dx-anchors by the markdown editor's preview extension.
122
+ const entityExtraction = settings?.entityExtraction !== false;
123
+ const streamer = new PendingTextStreamer(editorPendingTextSink(entry.view), {
124
+ mode: settings?.streamMode ?? 'word',
125
+ wordIntervalMs: settings?.wordIntervalMs ?? 80,
126
+ postProcess: entityExtraction && lookup ? (text) => linkEntities(text, lookup) : undefined,
127
+ });
128
+ streamer.start({ anchor: entry.view.state.selection.main.head, placeholder: 'Recording…' });
129
+ streamerRef.current = streamer;
130
+
131
+ return () => {
132
+ streamer.dispose();
133
+ streamerRef.current = null;
134
+ // On teardown, drop the placeholder if nothing was transcribed; otherwise leave it for review.
135
+ const current = editorViews.get(sessionId);
136
+ const pending = current?.view.state.field(pendingTextState, false);
137
+ if (current && pending && pending.final.length === 0) {
138
+ current.view.dispatch({ effects: cancelPendingText.of() });
139
+ }
140
+ };
141
+ }, [
142
+ active,
143
+ sessionId,
144
+ editorViews,
145
+ lookup,
146
+ settings?.streamMode,
147
+ settings?.wordIntervalMs,
148
+ settings?.entityExtraction,
149
+ ]);
150
+
151
+ const handleSegments = useCallback(
152
+ async (segments: ContentBlock.Transcript[]) => {
153
+ const text = segments
154
+ .map((segment) => segment.text)
155
+ .join(' ')
156
+ .trim();
157
+ if (text.length > 0 && !isCancelled()) {
158
+ streamerRef.current?.push(text);
159
+ }
160
+ },
161
+ [isCancelled],
162
+ );
163
+
164
+ // Derive the transcriber's chunk threshold from the configured initial buffering time.
165
+ const transcriberConfig = useMemo(
166
+ () => ({
167
+ transcribeAfterChunksAmount: Math.max(
168
+ 1,
169
+ Math.round((settings?.transcribeAfterMs ?? 4000) / RECORDER_INTERVAL_MS),
170
+ ),
171
+ }),
172
+ [settings?.transcribeAfterMs],
173
+ );
174
+
175
+ // Stable identity: a fresh object would change useTranscriber's memo deps every render, recreating
176
+ // (and reopening) the transcriber and discarding its buffered audio.
177
+ const recorderConfig = useMemo(() => ({ interval: RECORDER_INTERVAL_MS }), []);
178
+ const transcriber = useTranscriber({
179
+ audioStreamTrack: track,
180
+ onSegments: handleSegments,
181
+ transcriberConfig,
182
+ recorderConfig,
183
+ });
184
+ const transcriberRef = useRef(transcriber);
185
+ transcriberRef.current = transcriber;
186
+
187
+ useEffect(() => {
188
+ if (!transcriber) {
189
+ return;
190
+ }
191
+ let cancelled = false;
192
+ // Clear the session if `open()` rejects (e.g. mic permission denied) so the toolbar does not
193
+ // report "stop" forever while nothing is captured.
194
+ void transcriber.open().then(
195
+ () => {
196
+ if (!cancelled && phase === 'recording') {
197
+ transcriber.startChunksRecording();
198
+ }
199
+ },
200
+ (err) => {
201
+ if (!cancelled) {
202
+ log.catch(err);
203
+ setSession(() => null);
204
+ }
205
+ },
206
+ );
207
+ return () => {
208
+ cancelled = true;
209
+ };
210
+ }, [transcriber, phase, setSession]);
211
+
212
+ // Drain on stop: flush buffered audio (final transcription) and the streamer's post-process
213
+ // (entity linking) before tearing down — so the tail of speech and its enrichment are not lost.
214
+ useEffect(() => {
215
+ if (phase !== 'draining') {
216
+ return;
217
+ }
218
+ let cancelled = false;
219
+ // Hard-abort the in-flight transcription request if the user cancels (✕) during the drain.
220
+ const abortTimer = setInterval(() => {
221
+ if (isCancelled()) {
222
+ transcriberRef.current?.abort();
223
+ }
224
+ }, 150);
225
+ void (async () => {
226
+ try {
227
+ // Flush buffered audio (final transcription) then settle the streamer's post-process, unless
228
+ // the user cancelled (✕) — in which case skip the writes so the decoration stays cleared.
229
+ await transcriberRef.current?.flush();
230
+ if (!isCancelled()) {
231
+ await streamerRef.current?.flush();
232
+ }
233
+ } catch (err) {
234
+ log.catch(err);
235
+ } finally {
236
+ clearInterval(abortTimer);
237
+ if (!cancelled) {
238
+ setPhase((current) => (current === 'draining' ? 'idle' : current));
239
+ }
240
+ }
241
+ })();
242
+ return () => {
243
+ cancelled = true;
244
+ clearInterval(abortTimer);
245
+ };
246
+ }, [phase, isCancelled]);
247
+
248
+ return null;
249
+ };
250
+
251
+ export default Capability.makeModule(
252
+ Effect.fnUntraced(function* () {
253
+ return Capability.contributes(Capabilities.ReactContext, {
254
+ id: meta.profile.key,
255
+ context: ({ children }) => (
256
+ <Fragment>
257
+ {children}
258
+ <TranscriptionDriver />
259
+ </Fragment>
260
+ ),
261
+ });
262
+ }),
263
+ );
@@ -0,0 +1,66 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
6
+ import React, { useState } from 'react';
7
+
8
+ import { MicButton, Toolbar } from '@dxos/react-ui';
9
+ import { type AudioInputDevice, MicSettings, type RecordMode } from '@dxos/react-ui-transcription';
10
+ import { withLayout, withTheme } from '@dxos/react-ui/testing';
11
+
12
+ import { meta as pluginMeta } from '#meta';
13
+ import { translations } from '#translations';
14
+
15
+ const DEVICES: AudioInputDevice[] = [
16
+ { deviceId: 'default', label: 'Default — MacBook Pro Microphone' },
17
+ { deviceId: 'usb-1', label: 'USB Audio Interface' },
18
+ { deviceId: 'bt-1', label: 'AirPods Pro' },
19
+ ];
20
+
21
+ // Drives the presentational pieces from local state so the dropdown, mode switch, and
22
+ // press-and-hold can be exercised without capabilities.
23
+ const DefaultStory = () => {
24
+ const [recording, setRecording] = useState(false);
25
+ const [recordMode, setRecordMode] = useState<RecordMode>('toggle');
26
+ const [entityExtraction, setEntityExtraction] = useState(true);
27
+ const [selectedDeviceId, setSelectedDeviceId] = useState('');
28
+
29
+ return (
30
+ <Toolbar.Root>
31
+ <MicButton
32
+ iconOnly
33
+ variant='ghost'
34
+ label={recording ? 'Stop recording' : recordMode === 'hold' ? 'Hold to record' : 'Start recording'}
35
+ recording={recording}
36
+ mode={recordMode}
37
+ onToggle={() => setRecording((value) => !value)}
38
+ onPressStart={() => setRecording(true)}
39
+ onPressEnd={() => setRecording(false)}
40
+ />
41
+ <MicSettings
42
+ translationNs={pluginMeta.profile.key}
43
+ recordMode={recordMode}
44
+ entityExtraction={entityExtraction}
45
+ devices={DEVICES}
46
+ selectedDeviceId={selectedDeviceId}
47
+ onRecordModeChange={setRecordMode}
48
+ onEntityExtractionChange={setEntityExtraction}
49
+ onSelectDevice={setSelectedDeviceId}
50
+ />
51
+ </Toolbar.Root>
52
+ );
53
+ };
54
+
55
+ const meta = {
56
+ title: 'plugins/plugin-transcription/components/Mic',
57
+ render: DefaultStory,
58
+ decorators: [withTheme(), withLayout({ layout: 'centered' })],
59
+ parameters: { translations },
60
+ } satisfies Meta<typeof DefaultStory>;
61
+
62
+ export default meta;
63
+
64
+ type Story = StoryObj<typeof meta>;
65
+
66
+ export const Default: Story = {};
@@ -0,0 +1,136 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import React, { useCallback, useEffect, useRef, useState } from 'react';
6
+
7
+ import { useAtomCapabilityState } from '@dxos/app-framework/ui';
8
+ import { MicButton, useTranslation } from '@dxos/react-ui';
9
+ import { useSoundEffect } from '@dxos/react-ui-audio';
10
+ import { type AudioInputDevice, MicSettings } from '@dxos/react-ui-transcription';
11
+
12
+ import { meta } from '#meta';
13
+ import { type Settings, TranscriptionCapabilities } from '#types';
14
+
15
+ export type MicProps = {
16
+ /** Attendable id of the target editor; keys the recording session. */
17
+ docId: string;
18
+ };
19
+
20
+ /**
21
+ * Connects the {@link MicButton} and {@link MicSettings} to the recording session and settings
22
+ * capabilities, and enumerates available audio inputs. Mounted from the toolbar's custom action, so
23
+ * capability hooks resolve.
24
+ */
25
+ export const Mic = ({ docId }: MicProps) => {
26
+ const { t } = useTranslation(meta.profile.key);
27
+ const [session, setSession] = useAtomCapabilityState(TranscriptionCapabilities.RecordingSession);
28
+ const [settings, setSettings] = useAtomCapabilityState(TranscriptionCapabilities.Settings);
29
+
30
+ const recording = !!session?.recording && session.id === docId;
31
+
32
+ // Play start/stop cues as this session's recording flag flips (skip the initial mount).
33
+ const soundStart = useSoundEffect('StartRecording');
34
+ const soundStop = useSoundEffect('StopRecording');
35
+ const wasRecording = useRef(recording);
36
+ useEffect(() => {
37
+ if (wasRecording.current === recording) {
38
+ return;
39
+ }
40
+ wasRecording.current = recording;
41
+ void (recording ? soundStart : soundStop).play();
42
+ }, [recording, soundStart, soundStop]);
43
+
44
+ const recordMode: Settings.RecordMode = settings?.recordMode ?? 'toggle';
45
+ const entityExtraction = settings?.entityExtraction !== false;
46
+ const selectedDeviceId = settings?.audioDeviceId ?? '';
47
+
48
+ const [devices, setDevices] = useState<AudioInputDevice[]>([]);
49
+ useEffect(() => {
50
+ if (!navigator.mediaDevices?.enumerateDevices) {
51
+ return;
52
+ }
53
+ let cancelled = false;
54
+ const refresh = async () => {
55
+ const all = await navigator.mediaDevices.enumerateDevices();
56
+ if (cancelled) {
57
+ return;
58
+ }
59
+ // Labels are blank until microphone permission is granted; fall back to an ordinal name.
60
+ setDevices(
61
+ all
62
+ .filter((device) => device.kind === 'audioinput' && device.deviceId)
63
+ .map((device, index) => ({
64
+ deviceId: device.deviceId,
65
+ label: device.label || `Microphone ${index + 1}`,
66
+ })),
67
+ );
68
+ };
69
+ void refresh();
70
+ navigator.mediaDevices.addEventListener('devicechange', refresh);
71
+ return () => {
72
+ cancelled = true;
73
+ navigator.mediaDevices.removeEventListener('devicechange', refresh);
74
+ };
75
+ }, []);
76
+
77
+ const handleToggle = useCallback(() => {
78
+ setSession((current) => (current?.recording && current.id === docId ? null : { id: docId, recording: true }));
79
+ }, [setSession, docId]);
80
+
81
+ const handlePressStart = useCallback(() => {
82
+ setSession(() => ({ id: docId, recording: true }));
83
+ }, [setSession, docId]);
84
+
85
+ const handlePressEnd = useCallback(() => {
86
+ // Only stop our own session; a stray release must not clear another editor's recording.
87
+ setSession((current) => (current?.id === docId ? null : current));
88
+ }, [setSession, docId]);
89
+
90
+ const handleRecordModeChange = useCallback(
91
+ (mode: Settings.RecordMode) => setSettings((current) => ({ ...current, recordMode: mode })),
92
+ [setSettings],
93
+ );
94
+
95
+ const handleEntityExtractionChange = useCallback(
96
+ (value: boolean) => setSettings((current) => ({ ...current, entityExtraction: value })),
97
+ [setSettings],
98
+ );
99
+
100
+ const handleSelectDevice = useCallback(
101
+ (deviceId: string) => setSettings((current) => ({ ...current, audioDeviceId: deviceId || undefined })),
102
+ [setSettings],
103
+ );
104
+
105
+ const recordLabel = recording
106
+ ? t('stop-recording.label')
107
+ : recordMode === 'hold'
108
+ ? t('hold-to-record.label')
109
+ : t('start-recording.label');
110
+
111
+ return (
112
+ <div className='flex items-center'>
113
+ <MicButton
114
+ iconOnly
115
+ variant='ghost'
116
+ label={recordLabel}
117
+ recording={recording}
118
+ mode={recordMode}
119
+ onToggle={handleToggle}
120
+ onPressStart={handlePressStart}
121
+ onPressEnd={handlePressEnd}
122
+ data-testid='transcription.record'
123
+ />
124
+ <MicSettings
125
+ translationNs={meta.profile.key}
126
+ recordMode={recordMode}
127
+ entityExtraction={entityExtraction}
128
+ devices={devices}
129
+ selectedDeviceId={selectedDeviceId}
130
+ onRecordModeChange={handleRecordModeChange}
131
+ onEntityExtractionChange={handleEntityExtractionChange}
132
+ onSelectDevice={handleSelectDevice}
133
+ />
134
+ </div>
135
+ );
136
+ };
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ export * from './Mic';
@@ -2,5 +2,4 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- export * from './Oracle';
6
- export * from './Transcription';
5
+ export * from './Mic';
@@ -7,6 +7,7 @@ import * as Effect from 'effect/Effect';
7
7
  import React from 'react';
8
8
 
9
9
  import { withPluginManager } from '@dxos/app-framework/testing';
10
+ import { AppActivationEvents } from '@dxos/app-toolkit';
10
11
  import { Feed, Query, Ref } from '@dxos/echo';
11
12
  import { ClientPlugin, initializeIdentity } from '@dxos/plugin-client/testing';
12
13
  import { corePlugins } from '@dxos/plugin-testing';
@@ -36,6 +37,9 @@ const meta = {
36
37
  decorators: [
37
38
  withLayout({ layout: 'column' }),
38
39
  withPluginManager({
40
+ // The app-wide TranscriptionDriver (ReactContext) reads the recording-session/settings
41
+ // capabilities, which activate on SetupSettings — fire it so the driver does not throw.
42
+ setupEvents: [AppActivationEvents.SetupSettings],
39
43
  plugins: [
40
44
  ...corePlugins(),
41
45
  ClientPlugin({
@@ -9,14 +9,12 @@ import { Filter, Obj, Query } from '@dxos/echo';
9
9
  import { useMembers, useQuery } from '@dxos/react-client/echo';
10
10
  import { Panel } from '@dxos/react-ui';
11
11
  import { Menu, MenuBuilder, useMenuBuilder } from '@dxos/react-ui-menu';
12
+ import { Transcription, renderByline, useFeedModelAdapter } from '@dxos/react-ui-transcription';
12
13
  import { Message, type Transcript } from '@dxos/types';
13
14
 
14
- import { Transcription } from '#components';
15
- import { useFeedModelAdapter, useTranscriptionRecording } from '#hooks';
15
+ import { useTranscriptionRecording } from '#hooks';
16
16
  import { meta } from '#meta';
17
17
 
18
- import { renderByline } from '../../util';
19
-
20
18
  export type TranscriptionArticleProps = AppSurface.ObjectArticleProps<Transcript.Transcript>;
21
19
 
22
20
  export const TranscriptionArticle = ({ role, subject: transcript, attendableId }: TranscriptionArticleProps) => {
@@ -28,15 +26,16 @@ export const TranscriptionArticle = ({ role, subject: transcript, attendableId }
28
26
  feed ? Query.select(Filter.type(Message.Message)).from(feed) : Query.select(Filter.nothing()),
29
27
  );
30
28
  const model = useFeedModelAdapter(renderByline(members), messages);
31
- const { recording, toggleRecording } = useTranscriptionRecording(transcript);
32
29
 
30
+ // TODO(burdon): Remove if not mutable. E.g., finalized transcript.
31
+ const { recording, toggleRecording } = useTranscriptionRecording(transcript);
33
32
  const menuActions = useMenuBuilder(
34
33
  () =>
35
34
  MenuBuilder.make()
36
35
  .action(
37
36
  'toggle-recording',
38
37
  {
39
- label: [recording ? 'stop-recording.label' : 'start-recording.label', { ns: meta.id }],
38
+ label: [recording ? 'stop-recording.label' : 'start-recording.label', { ns: meta.profile.key }],
40
39
  icon: recording ? 'ph--stop-circle--regular' : 'ph--microphone--regular',
41
40
  disposition: 'toolbar',
42
41
  testId: 'transcription.toggle-recording',
@@ -2,9 +2,4 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- export * from './useAudioFile';
6
- export * from './useAudioTrack';
7
- export * from './useFeedModelAdapter';
8
- export * from './useTranscriber';
9
5
  export * from './useTranscriptionRecording';
10
- export * from './useVoiceInput';