@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
@@ -1,203 +0,0 @@
1
- //
2
- // Copyright 2025 DXOS.org
3
- //
4
-
5
- import { type Extension, RangeSetBuilder } from '@codemirror/state';
6
- import { EditorView, GutterMarker, ViewPlugin, type ViewUpdate, gutter } from '@codemirror/view';
7
- import { format } from 'date-fns/format';
8
- import { intervalToDuration } from 'date-fns/intervalToDuration';
9
-
10
- import { type CleanupFn, addEventListener, combine } from '@dxos/async';
11
- import { type Message } from '@dxos/types';
12
-
13
- import { DocumentAdapter, type SerializationModel } from '../../model';
14
-
15
- /**
16
- * Data structure that maps Chunks queue to lines with transcript state.
17
- */
18
- export type TranscriptionOptions = {
19
- model: SerializationModel<Message.Message>;
20
- started?: Date;
21
- };
22
-
23
- /**
24
- * Scrolling transcript with timestamps.
25
- */
26
- export const transcription = ({ model, started }: TranscriptionOptions): Extension => {
27
- return [
28
- // Show timestamps in the gutter.
29
- gutter({
30
- class: 'cm-timestamp-gutter',
31
- lineMarkerChange: (update) => update.docChanged || update.viewportChanged,
32
- markers: (view) => {
33
- const start = getStartTime(started, model.chunks[0]);
34
- const builder = new RangeSetBuilder<GutterMarker>();
35
- for (const { from, to } of view.visibleRanges) {
36
- let line = view.state.doc.lineAt(from);
37
- while (line.from <= to) {
38
- const block = model.getChunkAtLine(line.number)?.blocks[0];
39
- const timestamp = block?._tag === 'transcript' && block.started;
40
- if (timestamp) {
41
- builder.add(line.from, line.from, new TimestampMarker(line.number, new Date(timestamp), start));
42
- }
43
-
44
- if (line.to + 1 > view.state.doc.length) {
45
- break;
46
- }
47
-
48
- line = view.state.doc.lineAt(line.to + 1);
49
- }
50
- }
51
-
52
- return builder.finish();
53
- },
54
- }),
55
-
56
- // Listen for model updates.
57
- ViewPlugin.fromClass(
58
- class {
59
- private readonly _controls?: HTMLDivElement;
60
- private readonly _cleanup: CleanupFn;
61
- private readonly _adapter: DocumentAdapter;
62
- private _initialized = false;
63
-
64
- constructor(view: EditorView) {
65
- this._adapter = new DocumentAdapter(view);
66
-
67
- const scroller = view.scrollDOM;
68
- let isAutoScrolling = false;
69
- let hasScrolled = false;
70
-
71
- let timeout: NodeJS.Timeout | undefined;
72
- const scrollToBottom = (smooth = false) => {
73
- scroller.style.scrollBehavior = smooth ? 'smooth' : '';
74
-
75
- // Temporarily hide scrollbar to prevent flicker.
76
- scroller.classList.add('cm-hide-scrollbar');
77
- isAutoScrolling = true;
78
- clearTimeout(timeout);
79
- timeout = setTimeout(() => {
80
- this._controls?.classList.add('opacity-0');
81
- scroller.classList.remove('cm-hide-scrollbar');
82
- isAutoScrolling = false;
83
- }, 500);
84
-
85
- // Scroll to bottom.
86
- view.dispatch({
87
- effects: EditorView.scrollIntoView(view.state.doc.length, { y: 'end' }),
88
- });
89
- };
90
-
91
- // Event listeners.
92
- this._cleanup = combine(
93
- addEventListener(view.scrollDOM, 'scroll', () => {
94
- if (!isAutoScrolling) {
95
- hasScrolled = true;
96
- this._controls?.classList.remove('opacity-0');
97
- }
98
- }),
99
-
100
- model.update.on(() => {
101
- // Check if clamped to bottom.
102
- const autoScroll =
103
- scroller.scrollHeight - scroller.scrollTop - scroller.clientHeight === 0 || !hasScrolled;
104
-
105
- // Sync.
106
- model.sync(this._adapter);
107
-
108
- // Scroll.
109
- if (autoScroll) {
110
- scrollToBottom(true);
111
- }
112
- }),
113
- );
114
- }
115
-
116
- update(_update: ViewUpdate) {
117
- // Initial sync.
118
- if (!this._initialized) {
119
- this._initialized = true;
120
- setTimeout(() => {
121
- model.sync(this._adapter);
122
- });
123
- }
124
- }
125
-
126
- destroy() {
127
- this._controls?.remove();
128
- this._cleanup();
129
- }
130
- },
131
- ),
132
-
133
- EditorView.theme({
134
- '.cm-gutters': {
135
- backgroundColor: 'var(--color-base-surface)',
136
- },
137
- '.cm-timestamp-gutter': {
138
- width: '6rem',
139
- paddingLeft: '0.5rem',
140
- paddingRight: '1rem',
141
- },
142
- '.cm-timestamp-gutter > .cm-gutterElement > div': {
143
- display: 'inline-flex',
144
- textAlign: 'right',
145
- padding: '3px',
146
- },
147
- }),
148
- ];
149
- };
150
-
151
- /**
152
- * Gutter marker that displays a timestamp.
153
- */
154
- class TimestampMarker extends GutterMarker {
155
- constructor(
156
- readonly _line: number,
157
- readonly _timestamp: Date,
158
- readonly _started?: Date,
159
- ) {
160
- super();
161
- }
162
-
163
- override eq(other: this) {
164
- return this._timestamp === other._timestamp;
165
- }
166
-
167
- override toDOM(view: EditorView) {
168
- const el = document.createElement('div');
169
- el.className = 'text-sm text-subdued hover:bg-hover-surface cursor-pointer';
170
- el.textContent = formatTimestamp(this._timestamp, this._started);
171
- // TODO(burdon): Click to bookmark or copy hyperlink.
172
- el.onclick = () => {
173
- const pos = view.state.doc.line(this._line).from;
174
- view.dispatch({
175
- effects: EditorView.scrollIntoView(pos, { y: 'start' }),
176
- });
177
- };
178
-
179
- return el;
180
- }
181
- }
182
-
183
- const getStartTime = (started?: Date, message?: Message.Message): Date | undefined => {
184
- if (started) {
185
- return started;
186
- }
187
-
188
- if (message?.blocks[0]?._tag === 'transcript' && message.blocks[0].started) {
189
- return new Date(message.blocks[0].started);
190
- }
191
-
192
- return undefined;
193
- };
194
-
195
- const formatTimestamp = (timestamp: Date, relative?: Date) => {
196
- if (relative) {
197
- const pad = (n = 0) => String(n).padStart(2, '0');
198
- const { hours, minutes, seconds } = intervalToDuration({ start: relative, end: timestamp });
199
- return `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;
200
- } else {
201
- return format(timestamp, 'HH:mm:ss');
202
- }
203
- };
@@ -1,162 +0,0 @@
1
- //
2
- // Copyright 2024 DXOS.org
3
- //
4
-
5
- // Headless test that simulates a two-speaker conversation as a pair of Whisper streams and
6
- // drives them through the (currently stubbed) Pass A enrichment and Pass B summarization
7
- // operations. The handlers are deterministic placeholders — they don't call an LLM — so the
8
- // test runs offline; switching to the real LLM-backed handlers later doesn't change the
9
- // harness, just the assertions.
10
- //
11
- // What this verifies today:
12
- // - Conversation fixture parses to entities + speaker-tagged utterances.
13
- // - Stream simulator emits per-batch transcript blocks in chronological order.
14
- // - Pass A's sliding-window enrichment links seeded ECHO entities by name and surfaces
15
- // remaining capitalised tokens as candidates.
16
- // - Pass B accumulates a per-speaker summary and resolves "I" → speaker display name.
17
-
18
- import { describe, it } from '@effect/vitest';
19
- import * as Effect from 'effect/Effect';
20
- import * as fs from 'node:fs';
21
- import * as path from 'node:path';
22
- import * as url from 'node:url';
23
-
24
- import { Blueprint, Operation, OperationHandlerSet } from '@dxos/compute';
25
- import { Database, Feed, Obj, Type } from '@dxos/echo';
26
- import { TestHelpers } from '@dxos/effect/testing';
27
- import { AssistantTestLayer } from '@dxos/functions-runtime/testing';
28
- import { EntityId } from '@dxos/keys';
29
- import { Organization, Person } from '@dxos/types';
30
-
31
- import { EnrichTranscript, EnrichmentHandlers, SummarizeConversation } from './operations';
32
- import { parseConversation } from './parser';
33
- import { simulateStream } from './stream-simulator';
34
-
35
- EntityId.dangerouslyDisableRandomness();
36
-
37
- const TestLayer = AssistantTestLayer({
38
- operationHandlers: OperationHandlerSet.make(...EnrichmentHandlers),
39
- types: [Person.Person, Organization.Organization, Blueprint.Blueprint, Feed.Feed],
40
- disableLlmMemoization: true,
41
- });
42
-
43
- describe('Transcript enrichment — conversation simulation', () => {
44
- it.scoped(
45
- 'streams a two-speaker conversation through Pass A and Pass B (stub handlers)',
46
- Effect.fnUntraced(
47
- function* ({ expect }) {
48
- // 1. Load and parse the fixture.
49
- const fixturePath = path.join(path.dirname(url.fileURLToPath(import.meta.url)), 'conversation.txt');
50
- const conversation = parseConversation(fs.readFileSync(fixturePath, 'utf8'));
51
- expect(conversation.speakers).toEqual(['A', 'B']);
52
- expect(conversation.utterances.length).toBeGreaterThan(0);
53
- expect(conversation.entities.length).toBeGreaterThan(0);
54
-
55
- // 2. Seed the ECHO space with the fixture's entities. Map fixture types → schema types.
56
- const seeded: { id: string; typename: string; name: string }[] = [];
57
- for (const entity of conversation.entities) {
58
- if (entity.kind === 'Person') {
59
- const fullName = entity.fields.fullName ?? entity.fields.name;
60
- if (!fullName) {
61
- continue;
62
- }
63
- const person = yield* Database.add(Obj.make(Person.Person, { fullName }));
64
- seeded.push({ id: person.id, typename: Type.getTypename(Person.Person), name: fullName });
65
- } else if (entity.kind === 'Organization') {
66
- const name = entity.fields.name;
67
- if (!name) {
68
- continue;
69
- }
70
- const org = yield* Database.add(Obj.make(Organization.Organization, { name }));
71
- seeded.push({ id: org.id, typename: Type.getTypename(Organization.Organization), name });
72
- }
73
- }
74
- yield* Database.flush();
75
- expect(seeded.map((s) => s.name)).toContain('Chad');
76
- expect(seeded.map((s) => s.name)).toContain('Blue Yard');
77
-
78
- // 3. Generate the per-batch Whisper schedule. Batch by speaker so each batch maps to
79
- // a single Pass-A invocation, mimicking what the live `useTranscriptEnrichment`
80
- // hook will receive from the transcriber.
81
- const batches = simulateStream(conversation, { wordsPerSecond: 2.5, gapSeconds: 0.5 });
82
- expect(batches.length).toBe(conversation.utterances.length);
83
- expect(batches[0].offsetMs).toBe(0);
84
- expect(batches.every((b) => b.blocks.length > 0)).toBe(true);
85
-
86
- // 4. Run Pass A over each batch — sliding window of the last 4 blocks across speakers.
87
- const slidingWindow: { speaker: string; text: string; started: string }[] = [];
88
- const enrichments: {
89
- speaker: string;
90
- corrected: string;
91
- referenceIds: string[];
92
- candidates: { text: string }[];
93
- }[] = [];
94
- for (const batch of batches) {
95
- for (const block of batch.blocks) {
96
- slidingWindow.push({ speaker: batch.speaker, text: block.text, started: block.started });
97
- if (slidingWindow.length > 4) {
98
- slidingWindow.shift();
99
- }
100
- }
101
- const result = yield* Operation.invoke(EnrichTranscript, {
102
- window: slidingWindow,
103
- knownEntities: seeded,
104
- });
105
- // The new batch's entries are the *last* `batch.blocks.length` items in the window.
106
- const newEntries = result.blocks.slice(-batch.blocks.length);
107
- for (const block of newEntries) {
108
- const windowEntry = slidingWindow[block.index];
109
- enrichments.push({
110
- speaker: windowEntry.speaker,
111
- corrected: block.corrected,
112
- referenceIds: [...block.referenceIds],
113
- candidates: block.candidates.map((c) => ({ text: c.text })),
114
- });
115
- }
116
- }
117
-
118
- // 4a. Every block got a terminal-punctuated `corrected` value.
119
- for (const e of enrichments) {
120
- expect(e.corrected).toMatch(/[.!?]$/);
121
- }
122
-
123
- // 4b. The block containing "Chad" links to the seeded Person.
124
- const chadId = seeded.find((s) => s.name === 'Chad')!.id;
125
- const chadMention = enrichments.find((e) => /\bChad\b/.test(e.corrected));
126
- expect(chadMention).toBeDefined();
127
- expect(chadMention!.referenceIds).toContain(chadId);
128
-
129
- // 4c. Place names surface as candidates (not in our seed).
130
- const allCandidates = enrichments.flatMap((e) => e.candidates.map((c) => c.text));
131
- expect(allCandidates).toContain('Munich');
132
- expect(allCandidates).toContain('Los Angeles');
133
-
134
- // 5. Run Pass B once at the end of the conversation (the real pipeline would fire it
135
- // after silence + interval; here we trigger it manually after the last batch).
136
- const speakerNames = { A: 'Speaker A', B: 'Speaker B' };
137
- const summary = yield* Operation.invoke(SummarizeConversation, {
138
- previousSummary: '',
139
- newUtterances: enrichments.map((e) => ({ speaker: e.speaker, text: e.corrected })),
140
- speakerNames,
141
- recentReferences: seeded.map((s) => ({ id: s.id, name: s.name })),
142
- });
143
-
144
- // 5a. Summary is non-empty and mentions both speakers.
145
- expect(summary.summary.length).toBeGreaterThan(0);
146
- expect(summary.summary).toContain('Speaker A');
147
- expect(summary.summary).toContain('Speaker B');
148
-
149
- // 5b. Resolved referents: every utterance that contains "I" picks up the speaker's name.
150
- const iUtterances = enrichments.filter((e) => /\bI\b/.test(e.corrected));
151
- expect(summary.resolvedReferents.length).toBe(iUtterances.length);
152
- for (const referent of summary.resolvedReferents) {
153
- expect(referent.surface).toBe('I');
154
- expect([speakerNames.A, speakerNames.B]).toContain(referent.referent);
155
- }
156
- },
157
- Effect.provide(TestLayer),
158
- TestHelpers.provideTestContext,
159
- ),
160
- { timeout: 30_000 },
161
- );
162
- });
@@ -1,23 +0,0 @@
1
- # Conversation fixture for transcription enrichment tests.
2
- # Format:
3
- # `Entities:` block — declares ECHO objects to seed into the test space.
4
- # Each entry is `<Type>:` followed by indented `<field>: <value>` lines.
5
- # `Conversation:` block — one utterance per line, `<speaker>: <text>`.
6
- # Speakers map to distinct virtual Whisper streams in the simulator.
7
- # Lines starting with `#` are comments and are ignored by the parser.
8
-
9
- Entities:
10
- Person:
11
- fullName: Chad
12
- employer: Blue Yard
13
- Organization:
14
- name: Blue Yard
15
-
16
- Conversation:
17
- A: I think I'm going to go.
18
- B: Are you meeting with them?
19
- A: Yes I think so.
20
- B: But I thought they were in Munich?
21
- A: They are, but the offsite is in Los Angeles.
22
- B: Is Chad going to be there?
23
- A: Yes, the whole team. It's their annual offsite.
@@ -1,271 +0,0 @@
1
- //
2
- // Copyright 2024 DXOS.org
3
- //
4
-
5
- // Operation definitions for the transcript enrichment pipeline (see ENRICHMENT.md).
6
- //
7
- // **Stub status.** The handlers below return deterministic dummy values rather than calling
8
- // an LLM; they exist so the end-to-end test harness (`conversation.test.ts`) can exercise
9
- // the schemas, the operation wiring, and the streaming/orchestration code paths without
10
- // requiring an Anthropic key on first run. The real handlers will replace these stubs in
11
- // a follow-up PR (calling `LanguageModel.generateObject(...)`) while keeping the same
12
- // inputs / outputs.
13
-
14
- import * as Effect from 'effect/Effect';
15
- import * as Schema from 'effect/Schema';
16
-
17
- import { Operation } from '@dxos/compute';
18
- import { DXN } from '@dxos/keys';
19
-
20
- import { meta } from '#meta';
21
-
22
- const NAMESPACE = `${meta.id}.enrichment`;
23
-
24
- //
25
- // Shared sub-schemas.
26
- //
27
-
28
- /** A noun / proper noun surfaced for follow-up actions (create object, research, link…). */
29
- export const CandidateMention = Schema.Struct({
30
- text: Schema.String.annotations({ description: 'Surface form as it appears in the transcript.' }),
31
- kind: Schema.Literal('noun', 'proper-noun').annotations({
32
- description: 'Whether this is a common noun (e.g. "team") or a proper noun (e.g. "Munich").',
33
- }),
34
- start: Schema.Number.annotations({ description: 'Character offset within the corrected text.' }),
35
- end: Schema.Number.annotations({ description: 'Character offset within the corrected text.' }),
36
- suggested: Schema.optional(
37
- Schema.Struct({
38
- typename: Schema.String.annotations({
39
- description: 'Optional hint for the ECHO type the user might create (e.g. "org.dxos.type.organization").',
40
- }),
41
- }),
42
- ),
43
- });
44
-
45
- /** Per-block enrichment output produced by Pass A. */
46
- export const EnrichmentBlock = Schema.Struct({
47
- /** Index into the input window; lets the caller match enrichment to the originating block. */
48
- index: Schema.Number,
49
- /** Corrected text — punctuation, capitalization, words split across batch boundaries reassembled. */
50
- corrected: Schema.String,
51
- /**
52
- * IDs of ECHO objects the LLM is confident the block mentions. Strings rather than `Ref<T>`
53
- * to keep the schema serialisable; the consumer resolves them via `Database.resolve(...)`.
54
- */
55
- referenceIds: Schema.Array(Schema.String),
56
- /** Candidate nouns / proper nouns not already covered by `referenceIds`. */
57
- candidates: Schema.Array(CandidateMention),
58
- });
59
-
60
- //
61
- // Pass A — enrichment (per Whisper batch / sliding window).
62
- //
63
-
64
- export const EnrichmentInput = Schema.Struct({
65
- /** Sliding-window blocks. Each carries the speaker that produced it. */
66
- window: Schema.Array(
67
- Schema.Struct({
68
- speaker: Schema.String,
69
- text: Schema.String,
70
- started: Schema.String,
71
- }),
72
- ),
73
- /** ECHO objects available in the space that the LLM may pick from when linking references. */
74
- knownEntities: Schema.optional(
75
- Schema.Array(
76
- Schema.Struct({
77
- id: Schema.String,
78
- typename: Schema.String,
79
- name: Schema.String,
80
- }),
81
- ),
82
- ),
83
- });
84
- export type EnrichmentInputType = Schema.Schema.Type<typeof EnrichmentInput>;
85
-
86
- export const EnrichmentOutput = Schema.Struct({
87
- blocks: Schema.Array(EnrichmentBlock),
88
- });
89
- export type EnrichmentOutputType = Schema.Schema.Type<typeof EnrichmentOutput>;
90
-
91
- export const EnrichTranscript = Operation.make({
92
- meta: {
93
- key: DXN.make(`${NAMESPACE}.enrich`),
94
- name: 'Enrich Transcript',
95
- description: 'Correct Whisper output and surface entity references and candidates over a sliding window.',
96
- icon: 'ph--microphone--regular',
97
- },
98
- input: EnrichmentInput,
99
- output: EnrichmentOutput,
100
- });
101
-
102
- /**
103
- * Deterministic stub: echoes the input text as `corrected`, links every block whose text contains
104
- * a `knownEntities[i].name` substring to that entity's id, and surfaces every capitalised word
105
- * not already linked as a `proper-noun` candidate. Sentence-end punctuation is added if missing.
106
- */
107
- const enrichHandler: Operation.WithHandler<typeof EnrichTranscript> = EnrichTranscript.pipe(
108
- Operation.withHandler(
109
- Effect.fnUntraced(function* ({ window, knownEntities }) {
110
- const known = knownEntities ?? [];
111
- const blocks = window.map((entry, index) => {
112
- const corrected = ensureTerminalPunctuation(entry.text);
113
- const referenceIds: string[] = [];
114
- const covered: Array<{ start: number; end: number }> = [];
115
- for (const entity of known) {
116
- const haystack = corrected.toLowerCase();
117
- const needle = entity.name.toLowerCase();
118
- const idx = haystack.indexOf(needle);
119
- if (idx >= 0) {
120
- referenceIds.push(entity.id);
121
- covered.push({ start: idx, end: idx + entity.name.length });
122
- }
123
- }
124
-
125
- const candidates = [...findCapitalisedWords(corrected)].filter(
126
- ({ start, end }) => !covered.some((c) => c.start <= start && end <= c.end),
127
- );
128
-
129
- return { index, corrected, referenceIds, candidates };
130
- });
131
- return { blocks };
132
- }),
133
- ),
134
- );
135
-
136
- //
137
- // Pass B — summary (end-of-utterance + periodic).
138
- //
139
-
140
- export const SummaryInput = Schema.Struct({
141
- /** The cumulative summary as of the last invocation (empty string on first call). */
142
- previousSummary: Schema.String,
143
- /** New corrected utterances appended since the previous summary. */
144
- newUtterances: Schema.Array(
145
- Schema.Struct({
146
- speaker: Schema.String,
147
- text: Schema.String,
148
- }),
149
- ),
150
- /** Map of speaker label → human-readable display name. Drives "I" resolution. */
151
- speakerNames: Schema.optional(Schema.Record({ key: Schema.String, value: Schema.String })),
152
- /** IDs and surface forms of references emitted by recent Pass A invocations. */
153
- recentReferences: Schema.optional(
154
- Schema.Array(
155
- Schema.Struct({
156
- id: Schema.String,
157
- name: Schema.String,
158
- }),
159
- ),
160
- ),
161
- });
162
- export type SummaryInputType = Schema.Schema.Type<typeof SummaryInput>;
163
-
164
- export const ResolvedReferent = Schema.Struct({
165
- surface: Schema.String.annotations({ description: 'The deictic / anaphoric form, e.g. "I", "there".' }),
166
- referent: Schema.String.annotations({ description: 'Canonical name or description the surface resolves to.' }),
167
- refId: Schema.optional(Schema.String).annotations({
168
- description: 'ECHO object id when the referent maps to a known entity.',
169
- }),
170
- });
171
-
172
- export const SummaryOutput = Schema.Struct({
173
- summary: Schema.String,
174
- resolvedReferents: Schema.Array(ResolvedReferent),
175
- });
176
- export type SummaryOutputType = Schema.Schema.Type<typeof SummaryOutput>;
177
-
178
- export const SummarizeConversation = Operation.make({
179
- meta: {
180
- key: DXN.make(`${NAMESPACE}.summarize`),
181
- name: 'Summarize Conversation',
182
- description: 'Maintain a cumulative summary with referent resolution over a transcript stream.',
183
- icon: 'ph--text-align-left--regular',
184
- },
185
- input: SummaryInput,
186
- output: SummaryOutput,
187
- });
188
-
189
- /**
190
- * Deterministic stub: appends each new utterance to the previous summary on its own line,
191
- * prefixed with the speaker's display name (resolving the speaker label via `speakerNames`).
192
- * If any utterance contains "I" as a standalone word, emits a `resolvedReferents` entry binding
193
- * it to the speaker's display name — this is the minimal demonstration of the Pass-C contract.
194
- */
195
- const summarizeHandler: Operation.WithHandler<typeof SummarizeConversation> = SummarizeConversation.pipe(
196
- Operation.withHandler(
197
- Effect.fnUntraced(function* ({ previousSummary, newUtterances, speakerNames, recentReferences }) {
198
- const names = speakerNames ?? {};
199
- const lines = newUtterances.map((u) => `${names[u.speaker] ?? u.speaker}: ${u.text}`);
200
- const summary = [previousSummary.trim(), ...lines].filter(Boolean).join('\n');
201
-
202
- const resolvedReferents = newUtterances
203
- .filter((u) => /\bI\b/.test(u.text))
204
- .map((u) => {
205
- const displayName = names[u.speaker] ?? u.speaker;
206
- const ref = (recentReferences ?? []).find((r) => r.name === displayName);
207
- return { surface: 'I', referent: displayName, refId: ref?.id };
208
- });
209
-
210
- return { summary, resolvedReferents };
211
- }),
212
- ),
213
- );
214
-
215
- //
216
- // Exports.
217
- //
218
-
219
- export const EnrichmentHandlers = [enrichHandler, summarizeHandler];
220
-
221
- //
222
- // Helpers.
223
- //
224
-
225
- const ensureTerminalPunctuation = (text: string): string => {
226
- const trimmed = text.trim();
227
- if (trimmed.length === 0) {
228
- return trimmed;
229
- }
230
- return /[.!?]$/.test(trimmed) ? trimmed : `${trimmed}.`;
231
- };
232
-
233
- function* findCapitalisedWords(
234
- text: string,
235
- ): Generator<{ text: string; kind: 'proper-noun'; start: number; end: number }> {
236
- const re = /\b[A-Z][a-zA-Z]+(?:\s+[A-Z][a-zA-Z]+)*\b/g;
237
- let match: RegExpExecArray | null;
238
- while ((match = re.exec(text)) !== null) {
239
- // Skip pure sentence-initial single words ("Yes", "I", "But", "They") to keep candidates focused on
240
- // proper nouns. Heuristic for the stub: drop common stop-words.
241
- const word = match[0];
242
- if (STOP_WORDS.has(word)) {
243
- continue;
244
- }
245
- yield { text: word, kind: 'proper-noun', start: match.index, end: match.index + word.length };
246
- }
247
- }
248
-
249
- const STOP_WORDS = new Set([
250
- 'I',
251
- 'Yes',
252
- 'No',
253
- 'But',
254
- 'And',
255
- 'Or',
256
- 'So',
257
- 'They',
258
- 'We',
259
- 'He',
260
- 'She',
261
- 'It',
262
- 'The',
263
- 'A',
264
- 'An',
265
- 'Is',
266
- 'Are',
267
- 'Was',
268
- 'Were',
269
- 'Be',
270
- 'Been',
271
- ]);