@dxos/plugin-transcription 0.8.4-main.ae835ea → 0.8.4-main.bc2380dfbc
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.
- package/LICENSE +102 -5
- package/README.md +1 -1
- package/dist/lib/neutral/TranscriptionArticle-L6XANBH5.mjs +54 -0
- package/dist/lib/neutral/TranscriptionArticle-L6XANBH5.mjs.map +7 -0
- package/dist/lib/neutral/TranscriptionPlugin.mjs +34 -0
- package/dist/lib/neutral/TranscriptionPlugin.mjs.map +7 -0
- package/dist/lib/neutral/TranscriptionPlugin.node.mjs +25 -0
- package/dist/lib/neutral/TranscriptionPlugin.node.mjs.map +7 -0
- package/dist/lib/neutral/TranscriptionPlugin.workerd.mjs +21 -0
- package/dist/lib/neutral/TranscriptionPlugin.workerd.mjs.map +7 -0
- package/dist/lib/neutral/blueprint-definition-HOXDG5QP.mjs +15 -0
- package/dist/lib/neutral/blueprint-definition-HOXDG5QP.mjs.map +7 -0
- package/dist/lib/neutral/blueprints/index.mjs +8 -0
- package/dist/lib/neutral/capabilities/index.mjs +17 -0
- package/dist/lib/neutral/capabilities/index.mjs.map +7 -0
- package/dist/lib/neutral/chunk-2O3ONPRZ.mjs +298 -0
- package/dist/lib/neutral/chunk-2O3ONPRZ.mjs.map +7 -0
- package/dist/lib/neutral/chunk-5FXU36PN.mjs +120 -0
- package/dist/lib/neutral/chunk-5FXU36PN.mjs.map +7 -0
- package/dist/lib/{browser/chunk-VBUIO677.mjs → neutral/chunk-GL4RS533.mjs} +2 -9
- package/dist/lib/neutral/chunk-GL4RS533.mjs.map +7 -0
- package/dist/lib/{browser/chunk-WH36ENNE.mjs → neutral/chunk-ILSA3DU7.mjs} +102 -133
- package/dist/lib/neutral/chunk-ILSA3DU7.mjs.map +7 -0
- package/dist/lib/neutral/chunk-J5LGTIGS.mjs +10 -0
- package/dist/lib/neutral/chunk-KAEXRX3Y.mjs +35 -0
- package/dist/lib/neutral/chunk-KAEXRX3Y.mjs.map +7 -0
- package/dist/lib/neutral/chunk-MLRJWAQH.mjs +179 -0
- package/dist/lib/neutral/chunk-MLRJWAQH.mjs.map +7 -0
- package/dist/lib/neutral/chunk-Y5EQAFFR.mjs +8 -0
- package/dist/lib/neutral/chunk-Y5EQAFFR.mjs.map +7 -0
- package/dist/lib/neutral/chunk-ZR4BH4QQ.mjs +30 -0
- package/dist/lib/neutral/chunk-ZR4BH4QQ.mjs.map +7 -0
- package/dist/lib/neutral/components/index.mjs +272 -0
- package/dist/lib/neutral/components/index.mjs.map +7 -0
- package/dist/lib/neutral/containers/index.mjs +9 -0
- package/dist/lib/neutral/containers/index.mjs.map +7 -0
- package/dist/lib/neutral/create-RRWRIUSR.mjs +21 -0
- package/dist/lib/neutral/create-RRWRIUSR.mjs.map +7 -0
- package/dist/lib/neutral/hooks/index.mjs +19 -0
- package/dist/lib/neutral/index.mjs +44 -0
- package/dist/lib/neutral/meta.json +1 -0
- package/dist/lib/neutral/meta.mjs +8 -0
- package/dist/lib/neutral/meta.mjs.map +7 -0
- package/dist/lib/neutral/open-CVMX5KXZ.mjs +27 -0
- package/dist/lib/neutral/open-CVMX5KXZ.mjs.map +7 -0
- package/dist/lib/neutral/operation-handler-NXMOAXFP.mjs +13 -0
- package/dist/lib/neutral/operation-handler-NXMOAXFP.mjs.map +7 -0
- package/dist/lib/neutral/operations/index.mjs +8 -0
- package/dist/lib/neutral/operations/index.mjs.map +7 -0
- package/dist/lib/neutral/plugin.mjs +16 -0
- package/dist/lib/neutral/plugin.mjs.map +7 -0
- package/dist/lib/neutral/react-surface-YMZRO242.mjs +26 -0
- package/dist/lib/neutral/react-surface-YMZRO242.mjs.map +7 -0
- package/dist/lib/neutral/summarize-LA7TRW7A.mjs +78 -0
- package/dist/lib/neutral/summarize-LA7TRW7A.mjs.map +7 -0
- package/dist/lib/neutral/text-content-F4ASMITB.mjs +30 -0
- package/dist/lib/neutral/text-content-F4ASMITB.mjs.map +7 -0
- package/dist/lib/{node-esm/transcriber-UGB7ECX6.mjs → neutral/transcriber-ABHATBVH.mjs} +20 -18
- package/dist/lib/neutral/transcriber-ABHATBVH.mjs.map +7 -0
- package/dist/lib/neutral/translations.mjs +24 -0
- package/dist/lib/neutral/translations.mjs.map +7 -0
- package/dist/lib/neutral/types/index.mjs +10 -0
- package/dist/lib/neutral/types/index.mjs.map +7 -0
- package/dist/types/src/TranscriptionPlugin.d.ts +3 -1
- package/dist/types/src/TranscriptionPlugin.d.ts.map +1 -1
- package/dist/types/src/TranscriptionPlugin.node.d.ts +4 -0
- package/dist/types/src/TranscriptionPlugin.node.d.ts.map +1 -0
- package/dist/types/src/TranscriptionPlugin.test.d.ts +2 -0
- package/dist/types/src/TranscriptionPlugin.test.d.ts.map +1 -0
- package/dist/types/src/TranscriptionPlugin.workerd.d.ts +4 -0
- package/dist/types/src/TranscriptionPlugin.workerd.d.ts.map +1 -0
- package/dist/types/src/blueprints/index.d.ts +2 -0
- package/dist/types/src/blueprints/index.d.ts.map +1 -0
- package/dist/types/src/blueprints/transcription-blueprint.d.ts +4 -0
- package/dist/types/src/blueprints/transcription-blueprint.d.ts.map +1 -0
- package/dist/types/src/capabilities/blueprint-definition.d.ts +5 -4
- package/dist/types/src/capabilities/blueprint-definition.d.ts.map +1 -1
- package/dist/types/src/capabilities/index.d.ts +10 -5
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/operation-handler.d.ts +6 -0
- package/dist/types/src/capabilities/operation-handler.d.ts.map +1 -0
- package/dist/types/src/capabilities/react-surface.d.ts +3 -2
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
- package/dist/types/src/capabilities/text-content.d.ts +8 -0
- package/dist/types/src/capabilities/text-content.d.ts.map +1 -0
- package/dist/types/src/capabilities/transcriber.d.ts +4 -3
- package/dist/types/src/capabilities/transcriber.d.ts.map +1 -1
- package/dist/types/src/components/Oracle/Oracle.d.ts +24 -0
- package/dist/types/src/components/Oracle/Oracle.d.ts.map +1 -0
- package/dist/types/src/components/Oracle/Oracle.stories.d.ts +32 -0
- package/dist/types/src/components/Oracle/Oracle.stories.d.ts.map +1 -0
- package/dist/types/src/components/Oracle/index.d.ts +2 -0
- package/dist/types/src/components/Oracle/index.d.ts.map +1 -0
- package/dist/types/src/components/Transcription/Transcription.d.ts +13 -0
- package/dist/types/src/components/Transcription/Transcription.d.ts.map +1 -0
- package/dist/types/src/components/Transcription/Transcription.stories.d.ts +37 -0
- package/dist/types/src/components/Transcription/Transcription.stories.d.ts.map +1 -0
- package/dist/types/src/components/Transcription/index.d.ts +2 -0
- package/dist/types/src/components/Transcription/index.d.ts.map +1 -0
- package/dist/types/src/components/Transcription/transcription-extension.d.ts +15 -0
- package/dist/types/src/components/Transcription/transcription-extension.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +2 -3
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/containers/TranscriptionArticle/TranscriptionArticle.d.ts +6 -0
- package/dist/types/src/containers/TranscriptionArticle/TranscriptionArticle.d.ts.map +1 -0
- package/dist/types/src/containers/TranscriptionArticle/TranscriptionArticle.stories.d.ts +28 -0
- package/dist/types/src/containers/TranscriptionArticle/TranscriptionArticle.stories.d.ts.map +1 -0
- package/dist/types/src/containers/TranscriptionArticle/index.d.ts +2 -0
- package/dist/types/src/containers/TranscriptionArticle/index.d.ts.map +1 -0
- package/dist/types/src/containers/index.d.ts +3 -0
- package/dist/types/src/containers/index.d.ts.map +1 -0
- package/dist/types/src/enrichment/conversation.test.d.ts +2 -0
- package/dist/types/src/enrichment/conversation.test.d.ts.map +1 -0
- package/dist/types/src/enrichment/operations.d.ts +200 -0
- package/dist/types/src/enrichment/operations.d.ts.map +1 -0
- package/dist/types/src/enrichment/parser.d.ts +26 -0
- package/dist/types/src/enrichment/parser.d.ts.map +1 -0
- package/dist/types/src/enrichment/stream-simulator.d.ts +38 -0
- package/dist/types/src/enrichment/stream-simulator.d.ts.map +1 -0
- package/dist/types/src/hooks/index.d.ts +2 -1
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useAudioFile.d.ts.map +1 -1
- package/dist/types/src/hooks/useAudioTrack.d.ts.map +1 -1
- package/dist/types/src/hooks/useFeedModelAdapter.d.ts +12 -0
- package/dist/types/src/hooks/useFeedModelAdapter.d.ts.map +1 -0
- package/dist/types/src/hooks/useTranscriber.d.ts +2 -2
- package/dist/types/src/hooks/useTranscriber.d.ts.map +1 -1
- package/dist/types/src/hooks/useTranscriptionRecording.d.ts +12 -0
- package/dist/types/src/hooks/useTranscriptionRecording.d.ts.map +1 -0
- package/dist/types/src/hooks/useVoiceInput.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +2 -3
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/meta.d.ts +2 -2
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/model/model.d.ts +2 -2
- package/dist/types/src/model/model.d.ts.map +1 -1
- package/dist/types/src/{segments-normalization → normalization}/index.d.ts +1 -1
- package/dist/types/src/normalization/index.d.ts.map +1 -0
- package/dist/types/src/{segments-normalization → normalization}/message-normalizer.d.ts +9 -7
- package/dist/types/src/normalization/message-normalizer.d.ts.map +1 -0
- package/dist/types/src/normalization/normalization.d.ts +543 -0
- package/dist/types/src/normalization/normalization.d.ts.map +1 -0
- package/dist/types/src/normalization/normalization.test.d.ts.map +1 -0
- package/dist/types/src/normalization/utils.d.ts +3 -0
- package/dist/types/src/normalization/utils.d.ts.map +1 -0
- package/dist/types/src/operations/create.d.ts +5 -0
- package/dist/types/src/operations/create.d.ts.map +1 -0
- package/dist/types/src/operations/index.d.ts +3 -0
- package/dist/types/src/operations/index.d.ts.map +1 -0
- package/dist/types/src/operations/open.d.ts +5 -0
- package/dist/types/src/operations/open.d.ts.map +1 -0
- package/dist/types/src/operations/summarize.d.ts +8 -0
- package/dist/types/src/operations/summarize.d.ts.map +1 -0
- package/dist/types/src/plugin.d.ts +4 -0
- package/dist/types/src/plugin.d.ts.map +1 -0
- package/dist/types/src/stories/FileTranscription.stories.d.ts +20 -0
- package/dist/types/src/stories/FileTranscription.stories.d.ts.map +1 -0
- package/dist/types/src/{components/stories → stories}/KeyWordRecognition.stories.d.ts +2 -2
- package/dist/types/src/stories/KeyWordRecognition.stories.d.ts.map +1 -0
- package/dist/types/src/{components/stories/MicrophoneTranscription.stories.d.ts → stories/LiveTranscription.stories.d.ts} +7 -7
- package/dist/types/src/stories/LiveTranscription.stories.d.ts.map +1 -0
- package/dist/types/src/stories/TranscriptionStory.d.ts +21 -0
- package/dist/types/src/stories/TranscriptionStory.d.ts.map +1 -0
- package/dist/types/src/stories/common.d.ts +46 -0
- package/dist/types/src/stories/common.d.ts.map +1 -0
- package/dist/types/src/testing/testing.d.ts +13 -14
- package/dist/types/src/testing/testing.d.ts.map +1 -1
- package/dist/types/src/transcriber/index.d.ts +1 -1
- package/dist/types/src/transcriber/index.d.ts.map +1 -1
- package/dist/types/src/transcriber/media-stream-recorder.d.ts +2 -2
- package/dist/types/src/transcriber/media-stream-recorder.d.ts.map +1 -1
- package/dist/types/src/transcriber/transcriber.d.ts +61 -6
- package/dist/types/src/transcriber/transcriber.d.ts.map +1 -1
- package/dist/types/src/transcriber/transcriber.test.d.ts +2 -0
- package/dist/types/src/transcriber/transcriber.test.d.ts.map +1 -0
- package/dist/types/src/transcriber/transcription-manager.d.ts +14 -9
- package/dist/types/src/transcriber/transcription-manager.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +9 -8
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/TranscriptOperation.d.ts +917 -0
- package/dist/types/src/types/TranscriptOperation.d.ts.map +1 -0
- package/dist/types/src/types/TranscriptionCapabilities.d.ts +17 -0
- package/dist/types/src/types/TranscriptionCapabilities.d.ts.map +1 -0
- package/dist/types/src/types/index.d.ts +2 -3
- package/dist/types/src/types/index.d.ts.map +1 -1
- package/dist/types/src/util/array.d.ts.map +1 -1
- package/dist/types/src/util/get-time-str.d.ts.map +1 -1
- package/dist/types/src/util/index.d.ts +1 -0
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/src/util/monitor-audio-level.d.ts.map +1 -1
- package/dist/types/src/util/render-byline.d.ts +4 -0
- package/dist/types/src/util/render-byline.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +157 -82
- package/src/TranscriptionPlugin.node.ts +20 -0
- package/src/TranscriptionPlugin.test.ts +31 -0
- package/src/TranscriptionPlugin.tsx +20 -64
- package/src/TranscriptionPlugin.workerd.ts +18 -0
- package/src/blueprints/index.ts +5 -0
- package/src/blueprints/transcription-blueprint.ts +29 -0
- package/src/capabilities/blueprint-definition.ts +12 -24
- package/src/capabilities/index.ts +11 -7
- package/src/capabilities/operation-handler.ts +16 -0
- package/src/capabilities/react-surface.tsx +23 -14
- package/src/capabilities/text-content.ts +33 -0
- package/src/capabilities/transcriber.ts +53 -42
- package/src/components/Oracle/Oracle.stories.tsx +147 -0
- package/src/components/Oracle/Oracle.tsx +141 -0
- package/src/components/Oracle/index.ts +5 -0
- package/src/components/Transcription/Transcription.stories.tsx +213 -0
- package/src/components/Transcription/Transcription.tsx +58 -0
- package/src/components/{Transcript → Transcription}/index.ts +1 -1
- package/src/components/{Transcript/transcript-extension.ts → Transcription/transcription-extension.ts} +13 -9
- package/src/components/index.ts +2 -6
- package/src/containers/TranscriptionArticle/TranscriptionArticle.stories.tsx +61 -0
- package/src/containers/TranscriptionArticle/TranscriptionArticle.tsx +62 -0
- package/src/containers/TranscriptionArticle/index.ts +5 -0
- package/src/containers/index.ts +7 -0
- package/src/enrichment/conversation.test.ts +162 -0
- package/src/enrichment/conversation.txt +23 -0
- package/src/enrichment/operations.ts +268 -0
- package/src/enrichment/parser.ts +101 -0
- package/src/enrichment/stream-simulator.ts +125 -0
- package/src/hooks/index.ts +2 -1
- package/src/hooks/useFeedModelAdapter.ts +46 -0
- package/src/hooks/useTranscriber.ts +12 -4
- package/src/hooks/useTranscriptionRecording.ts +87 -0
- package/src/hooks/useVoiceInput.ts +2 -3
- package/src/index.ts +4 -5
- package/src/meta.ts +3 -3
- package/src/model/model.test.ts +20 -14
- package/src/model/model.ts +3 -3
- package/src/{segments-normalization → normalization}/message-normalizer.ts +37 -24
- package/src/{segments-normalization → normalization}/normalization.test.ts +8 -47
- package/src/normalization/normalization.ts +76 -0
- package/src/{segments-normalization → normalization}/utils.ts +2 -2
- package/src/operations/create.ts +24 -0
- package/src/operations/index.ts +11 -0
- package/src/operations/open.ts +28 -0
- package/src/operations/summarize.ts +101 -0
- package/src/plugin.ts +11 -0
- package/src/stories/FileTranscription.stories.tsx +143 -0
- package/src/{components/stories → stories}/KeyWordRecognition.stories.tsx +40 -40
- package/src/stories/LiveTranscription.stories.tsx +153 -0
- package/src/stories/TranscriptionStory.tsx +101 -0
- package/src/stories/common.ts +233 -0
- package/src/testing/testing.ts +49 -56
- package/src/transcriber/index.ts +1 -1
- package/src/transcriber/media-stream-recorder.ts +3 -3
- package/src/transcriber/transcriber.browser.test.ts +4 -5
- package/src/transcriber/transcriber.test.ts +104 -0
- package/src/transcriber/transcriber.ts +105 -60
- package/src/transcriber/transcription-manager.ts +33 -22
- package/src/translations.ts +10 -7
- package/src/types/TranscriptOperation.ts +103 -0
- package/src/types/TranscriptionCapabilities.ts +39 -0
- package/src/types/index.ts +2 -3
- package/src/util/index.ts +1 -0
- package/src/util/render-byline.ts +33 -0
- package/dist/lib/browser/TranscriptContainer-2GSL2XB5.mjs +0 -11
- package/dist/lib/browser/blueprint-definition-UAAJYVLZ.mjs +0 -150
- package/dist/lib/browser/blueprint-definition-UAAJYVLZ.mjs.map +0 -7
- package/dist/lib/browser/chunk-3MKZ2MNQ.mjs +0 -16
- package/dist/lib/browser/chunk-3MKZ2MNQ.mjs.map +0 -7
- package/dist/lib/browser/chunk-535OJKFO.mjs +0 -8
- package/dist/lib/browser/chunk-535OJKFO.mjs.map +0 -7
- package/dist/lib/browser/chunk-7DR6HZEF.mjs +0 -732
- package/dist/lib/browser/chunk-7DR6HZEF.mjs.map +0 -7
- package/dist/lib/browser/chunk-VBUIO677.mjs.map +0 -7
- package/dist/lib/browser/chunk-W7WKZTM4.mjs +0 -63
- package/dist/lib/browser/chunk-W7WKZTM4.mjs.map +0 -7
- package/dist/lib/browser/chunk-WH36ENNE.mjs.map +0 -7
- package/dist/lib/browser/index.mjs +0 -130
- package/dist/lib/browser/index.mjs.map +0 -7
- package/dist/lib/browser/intent-resolver-ZTKTEAQX.mjs +0 -25
- package/dist/lib/browser/intent-resolver-ZTKTEAQX.mjs.map +0 -7
- package/dist/lib/browser/meta.json +0 -1
- package/dist/lib/browser/react-surface-KA32A72I.mjs +0 -34
- package/dist/lib/browser/react-surface-KA32A72I.mjs.map +0 -7
- package/dist/lib/browser/transcriber-LWOLYQHC.mjs +0 -56
- package/dist/lib/browser/transcriber-LWOLYQHC.mjs.map +0 -7
- package/dist/lib/browser/types/index.mjs +0 -12
- package/dist/lib/node-esm/TranscriptContainer-GRLDCESB.mjs +0 -12
- package/dist/lib/node-esm/blueprint-definition-Z3LTZ3ID.mjs +0 -151
- package/dist/lib/node-esm/blueprint-definition-Z3LTZ3ID.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-K4AZOB5Y.mjs +0 -733
- package/dist/lib/node-esm/chunk-K4AZOB5Y.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-OLMSTF3M.mjs +0 -64
- package/dist/lib/node-esm/chunk-OLMSTF3M.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-Q6WD7L2J.mjs +0 -10
- package/dist/lib/node-esm/chunk-Q6WD7L2J.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-SWUVPFKR.mjs +0 -17
- package/dist/lib/node-esm/chunk-SWUVPFKR.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-YFN4FJFK.mjs +0 -467
- package/dist/lib/node-esm/chunk-YFN4FJFK.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-YVNQN2J6.mjs +0 -30
- package/dist/lib/node-esm/chunk-YVNQN2J6.mjs.map +0 -7
- package/dist/lib/node-esm/index.mjs +0 -131
- package/dist/lib/node-esm/index.mjs.map +0 -7
- package/dist/lib/node-esm/intent-resolver-55WH2GY6.mjs +0 -26
- package/dist/lib/node-esm/intent-resolver-55WH2GY6.mjs.map +0 -7
- package/dist/lib/node-esm/meta.json +0 -1
- package/dist/lib/node-esm/react-surface-GU7LW2JO.mjs +0 -35
- package/dist/lib/node-esm/react-surface-GU7LW2JO.mjs.map +0 -7
- package/dist/lib/node-esm/transcriber-UGB7ECX6.mjs.map +0 -7
- package/dist/lib/node-esm/types/index.mjs +0 -13
- package/dist/types/src/capabilities/capabilities.d.ts +0 -17
- package/dist/types/src/capabilities/capabilities.d.ts.map +0 -1
- package/dist/types/src/capabilities/intent-resolver.d.ts +0 -4
- package/dist/types/src/capabilities/intent-resolver.d.ts.map +0 -1
- package/dist/types/src/components/Transcript/Transcript.d.ts +0 -20
- package/dist/types/src/components/Transcript/Transcript.d.ts.map +0 -1
- package/dist/types/src/components/Transcript/Transcript.stories.d.ts +0 -39
- package/dist/types/src/components/Transcript/Transcript.stories.d.ts.map +0 -1
- package/dist/types/src/components/Transcript/deprecated/OldTranscript.d.ts +0 -28
- package/dist/types/src/components/Transcript/deprecated/OldTranscript.d.ts.map +0 -1
- package/dist/types/src/components/Transcript/index.d.ts +0 -2
- package/dist/types/src/components/Transcript/index.d.ts.map +0 -1
- package/dist/types/src/components/Transcript/transcript-extension.d.ts +0 -15
- package/dist/types/src/components/Transcript/transcript-extension.d.ts.map +0 -1
- package/dist/types/src/components/TranscriptContainer.d.ts +0 -9
- package/dist/types/src/components/TranscriptContainer.d.ts.map +0 -1
- package/dist/types/src/components/stories/FileTranscription.stories.d.ts +0 -18
- package/dist/types/src/components/stories/FileTranscription.stories.d.ts.map +0 -1
- package/dist/types/src/components/stories/KeyWordRecognition.stories.d.ts.map +0 -1
- package/dist/types/src/components/stories/MicrophoneTranscription.stories.d.ts.map +0 -1
- package/dist/types/src/components/stories/TranscriptionStory.d.ts +0 -12
- package/dist/types/src/components/stories/TranscriptionStory.d.ts.map +0 -1
- package/dist/types/src/components/stories/useIsSpeaking.d.ts +0 -3
- package/dist/types/src/components/stories/useIsSpeaking.d.ts.map +0 -1
- package/dist/types/src/functions/index.d.ts +0 -3
- package/dist/types/src/functions/index.d.ts.map +0 -1
- package/dist/types/src/functions/open.d.ts +0 -7
- package/dist/types/src/functions/open.d.ts.map +0 -1
- package/dist/types/src/functions/summarize.d.ts +0 -11
- package/dist/types/src/functions/summarize.d.ts.map +0 -1
- package/dist/types/src/hooks/useQueueModelAdapter.d.ts +0 -8
- package/dist/types/src/hooks/useQueueModelAdapter.d.ts.map +0 -1
- package/dist/types/src/segments-normalization/index.d.ts.map +0 -1
- package/dist/types/src/segments-normalization/message-normalizer.d.ts.map +0 -1
- package/dist/types/src/segments-normalization/normalization.d.ts +0 -476
- package/dist/types/src/segments-normalization/normalization.d.ts.map +0 -1
- package/dist/types/src/segments-normalization/normalization.test.d.ts.map +0 -1
- package/dist/types/src/segments-normalization/utils.d.ts +0 -3
- package/dist/types/src/segments-normalization/utils.d.ts.map +0 -1
- package/dist/types/src/types/Transcript.d.ts +0 -30
- package/dist/types/src/types/Transcript.d.ts.map +0 -1
- package/dist/types/src/types/TranscriptAction.d.ts +0 -23
- package/dist/types/src/types/TranscriptAction.d.ts.map +0 -1
- package/dist/types/src/types/types.d.ts +0 -5
- package/dist/types/src/types/types.d.ts.map +0 -1
- package/src/capabilities/capabilities.ts +0 -33
- package/src/capabilities/intent-resolver.ts +0 -18
- package/src/components/Transcript/Transcript.stories.tsx +0 -245
- package/src/components/Transcript/Transcript.tsx +0 -93
- package/src/components/Transcript/deprecated/OldTranscript.tsx +0 -260
- package/src/components/TranscriptContainer.tsx +0 -36
- package/src/components/stories/FileTranscription.stories.tsx +0 -256
- package/src/components/stories/MicrophoneTranscription.stories.tsx +0 -285
- package/src/components/stories/TranscriptionStory.tsx +0 -45
- package/src/components/stories/useIsSpeaking.tsx +0 -40
- package/src/functions/index.ts +0 -6
- package/src/functions/open.ts +0 -39
- package/src/functions/summarize.ts +0 -103
- package/src/hooks/useQueueModelAdapter.ts +0 -66
- package/src/segments-normalization/normalization.ts +0 -115
- package/src/types/Transcript.ts +0 -44
- package/src/types/TranscriptAction.ts +0 -24
- package/src/types/types.ts +0 -9
- package/dist/lib/{browser/types → neutral/blueprints}/index.mjs.map +0 -0
- package/dist/lib/{browser/TranscriptContainer-2GSL2XB5.mjs.map → neutral/chunk-J5LGTIGS.mjs.map} +0 -0
- package/dist/lib/{node-esm/types → neutral/hooks}/index.mjs.map +0 -0
- package/dist/lib/{node-esm/TranscriptContainer-GRLDCESB.mjs.map → neutral/index.mjs.map} +0 -0
- package/dist/types/src/{segments-normalization → normalization}/normalization.test.d.ts +0 -0
- package/src/{segments-normalization → normalization}/index.ts +1 -1
|
@@ -6,24 +6,23 @@ import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
|
6
6
|
import React, { useEffect, useMemo, useState } from 'react';
|
|
7
7
|
|
|
8
8
|
import { log } from '@dxos/log';
|
|
9
|
-
import { Toolbar } from '@dxos/react-ui';
|
|
9
|
+
import { Panel, Toolbar } from '@dxos/react-ui';
|
|
10
10
|
import { withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
11
|
-
import { mx } from '@dxos/
|
|
11
|
+
import { mx } from '@dxos/ui-theme';
|
|
12
12
|
|
|
13
13
|
type Word = {
|
|
14
14
|
text: string;
|
|
15
15
|
matched: boolean;
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
-
type
|
|
18
|
+
type DefaultStoryProps = {
|
|
19
19
|
keywords: string[];
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
-
const DefaultStory = ({ keywords }:
|
|
22
|
+
const DefaultStory = ({ keywords }: DefaultStoryProps) => {
|
|
23
23
|
const [running, setRunning] = useState(false);
|
|
24
24
|
const [matchingWords, setMatchingWords] = useState<Word[]>(keywords.map((word) => ({ text: word, matched: false })));
|
|
25
25
|
|
|
26
|
-
const [transcript, setTranscript] = useState('');
|
|
27
26
|
const recognition = useMemo(() => {
|
|
28
27
|
// TODO(mykola): Fix types
|
|
29
28
|
const SpeechRecognition = (window as any).SpeechRecognition || (window as any).webkitSpeechRecognition;
|
|
@@ -38,16 +37,16 @@ const DefaultStory = ({ keywords }: StoryProps) => {
|
|
|
38
37
|
recognition.interimResults = true;
|
|
39
38
|
recognition.lang = 'en-US';
|
|
40
39
|
recognition.maxAlternatives = 1;
|
|
41
|
-
// Add this line to enable punctuation
|
|
40
|
+
// Add this line to enable punctuation.
|
|
42
41
|
recognition.grammars = new SpeechGrammarList();
|
|
43
42
|
|
|
44
|
-
// TODO(mykola): Fix types
|
|
43
|
+
// TODO(mykola): Fix types.
|
|
45
44
|
recognition.onresult = (event: any) => {
|
|
46
45
|
log.info('recognition result', { event });
|
|
47
46
|
const current = event.resultIndex;
|
|
48
47
|
const transcript = event.results[current][0].transcript;
|
|
49
48
|
|
|
50
|
-
// Remove punctuation and normalize whitespace for comparison
|
|
49
|
+
// Remove punctuation and normalize whitespace for comparison.
|
|
51
50
|
const normalizeText = (text: string) =>
|
|
52
51
|
text
|
|
53
52
|
.toLowerCase()
|
|
@@ -57,7 +56,7 @@ const DefaultStory = ({ keywords }: StoryProps) => {
|
|
|
57
56
|
|
|
58
57
|
const normalizedTranscript = normalizeText(transcript);
|
|
59
58
|
|
|
60
|
-
// Check each keyword and update matching words
|
|
59
|
+
// Check each keyword and update matching words.
|
|
61
60
|
const updatedWords = matchingWords.map((word) => {
|
|
62
61
|
const normalizedKeyword = normalizeText(word.text);
|
|
63
62
|
const matched = normalizedTranscript.includes(normalizedKeyword);
|
|
@@ -65,10 +64,9 @@ const DefaultStory = ({ keywords }: StoryProps) => {
|
|
|
65
64
|
});
|
|
66
65
|
|
|
67
66
|
setMatchingWords(updatedWords);
|
|
68
|
-
setTranscript(transcript);
|
|
69
67
|
};
|
|
70
68
|
|
|
71
|
-
// TODO(mykola): Fix types
|
|
69
|
+
// TODO(mykola): Fix types.
|
|
72
70
|
recognition.onerror = (event: any) => {
|
|
73
71
|
log.error('Speech recognition error:', { error: event.error });
|
|
74
72
|
setRunning(false);
|
|
@@ -86,39 +84,41 @@ const DefaultStory = ({ keywords }: StoryProps) => {
|
|
|
86
84
|
}, [running, recognition]);
|
|
87
85
|
|
|
88
86
|
return (
|
|
89
|
-
<
|
|
90
|
-
<Toolbar
|
|
91
|
-
<Toolbar.
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
87
|
+
<Panel.Root>
|
|
88
|
+
<Panel.Toolbar asChild>
|
|
89
|
+
<Toolbar.Root>
|
|
90
|
+
<Toolbar.IconButton
|
|
91
|
+
iconOnly
|
|
92
|
+
icon={running ? 'ph--pause--regular' : 'ph--play--regular'}
|
|
93
|
+
label={running ? 'Pause' : 'Play'}
|
|
94
|
+
onClick={() => setRunning((running) => !running)}
|
|
95
|
+
/>
|
|
96
|
+
</Toolbar.Root>
|
|
97
|
+
</Panel.Toolbar>
|
|
98
|
+
|
|
99
|
+
<Panel.Content>
|
|
100
|
+
<div className='p-2 grid grid-cols-[repeat(auto-fill,minmax(6rem,1fr))] gap-2'>
|
|
101
|
+
{matchingWords.map((word, index) => (
|
|
102
|
+
<span
|
|
103
|
+
key={index}
|
|
104
|
+
className={mx(
|
|
105
|
+
'grid place-items-center p-2 aspect-square rounded-sm border border-separator',
|
|
106
|
+
word.matched && 'border-red-300',
|
|
107
|
+
)}
|
|
108
|
+
>
|
|
109
|
+
{word.text}
|
|
110
|
+
</span>
|
|
111
|
+
))}
|
|
112
|
+
</div>
|
|
113
|
+
</Panel.Content>
|
|
114
|
+
</Panel.Root>
|
|
115
115
|
);
|
|
116
116
|
};
|
|
117
117
|
|
|
118
118
|
const meta = {
|
|
119
|
-
title: 'plugins/plugin-transcription/KeyWordDetection',
|
|
119
|
+
title: 'plugins/plugin-transcription/stories/KeyWordDetection',
|
|
120
120
|
render: DefaultStory,
|
|
121
|
-
decorators: [withTheme, withLayout({
|
|
121
|
+
decorators: [withTheme(), withLayout({ layout: 'column' })],
|
|
122
122
|
} satisfies Meta<typeof DefaultStory>;
|
|
123
123
|
|
|
124
124
|
export default meta;
|
|
@@ -127,6 +127,6 @@ type Story = StoryObj<typeof meta>;
|
|
|
127
127
|
|
|
128
128
|
export const SpeechRecognitionAPI: Story = {
|
|
129
129
|
args: {
|
|
130
|
-
keywords: ['kai', 'computer', 'hello'],
|
|
130
|
+
keywords: ['kai', 'computer', 'hello', 'dxos'],
|
|
131
131
|
},
|
|
132
132
|
};
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
6
|
+
import React, { useCallback, useMemo, useState } from 'react';
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
type ExtractionFunction,
|
|
10
|
+
extractionAnthropicFunction,
|
|
11
|
+
extractionNerFunction,
|
|
12
|
+
getNer,
|
|
13
|
+
processTranscriptMessage,
|
|
14
|
+
} from '@dxos/assistant/extraction';
|
|
15
|
+
import { Filter, type Obj } from '@dxos/echo';
|
|
16
|
+
import { invariant } from '@dxos/invariant';
|
|
17
|
+
import { useSpaces } from '@dxos/react-client/echo';
|
|
18
|
+
import { Message, Organization, Person } from '@dxos/types';
|
|
19
|
+
|
|
20
|
+
import { useAudioTrack } from '#hooks';
|
|
21
|
+
|
|
22
|
+
import { type MediaStreamRecorderProps, type TranscriberProps } from '../transcriber';
|
|
23
|
+
import { useIsSpeaking, createStoryDecorators, useStoryMessageModel, useStoryTranscriber } from './common';
|
|
24
|
+
import { TranscriptionStory } from './TranscriptionStory';
|
|
25
|
+
|
|
26
|
+
const DEFAULT_TRANSCRIBER_CONFIG = {
|
|
27
|
+
transcribeAfterChunksAmount: 50,
|
|
28
|
+
prefixBufferChunksAmount: 10,
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const DEFAULT_RECORDER_CONFIG = {
|
|
32
|
+
interval: 200,
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
type DefaultStoryProps = {
|
|
36
|
+
detectSpeaking?: boolean;
|
|
37
|
+
transcriberConfig?: TranscriberProps['config'];
|
|
38
|
+
recorderConfig?: MediaStreamRecorderProps['config'];
|
|
39
|
+
audioConstraints?: MediaTrackConstraints;
|
|
40
|
+
entityExtraction?: 'ner' | 'llm';
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const DefaultStory = ({
|
|
44
|
+
detectSpeaking,
|
|
45
|
+
entityExtraction,
|
|
46
|
+
transcriberConfig = DEFAULT_TRANSCRIBER_CONFIG,
|
|
47
|
+
recorderConfig = DEFAULT_RECORDER_CONFIG,
|
|
48
|
+
audioConstraints,
|
|
49
|
+
}: DefaultStoryProps) => {
|
|
50
|
+
const [running, setRunning] = useState(false);
|
|
51
|
+
const track = useAudioTrack(running, audioConstraints);
|
|
52
|
+
const isSpeaking = detectSpeaking ? useIsSpeaking(track) : true;
|
|
53
|
+
const { model, appendMessage } = useStoryMessageModel();
|
|
54
|
+
const [space] = useSpaces();
|
|
55
|
+
|
|
56
|
+
// Resolve the entity-extraction function + nearby objects once per `entityExtraction` toggle.
|
|
57
|
+
const { extractionFunction, objects } = useMemo(() => {
|
|
58
|
+
if (!space || !entityExtraction) {
|
|
59
|
+
return {};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
let extractionFunction: ExtractionFunction | undefined;
|
|
63
|
+
let objects: Promise<Obj.Unknown[]> | undefined;
|
|
64
|
+
if (entityExtraction === 'ner') {
|
|
65
|
+
void getNer(); // Init model loading. Takes time.
|
|
66
|
+
extractionFunction = extractionNerFunction;
|
|
67
|
+
} else if (entityExtraction === 'llm') {
|
|
68
|
+
extractionFunction = extractionAnthropicFunction;
|
|
69
|
+
objects = space.db.query(Filter.or(Filter.type(Person.Person), Filter.type(Organization.Organization))).run();
|
|
70
|
+
}
|
|
71
|
+
return { extractionFunction, objects };
|
|
72
|
+
}, [entityExtraction, space]);
|
|
73
|
+
|
|
74
|
+
// Build a Message from each transcribed batch; optionally enrich via entity extraction.
|
|
75
|
+
const handleSegments = useCallback<TranscriberProps['onSegments']>(
|
|
76
|
+
async (blocks) => {
|
|
77
|
+
const message = Message.make({
|
|
78
|
+
sender: { name: 'You' },
|
|
79
|
+
created: new Date().toISOString(),
|
|
80
|
+
blocks,
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
if (entityExtraction && space) {
|
|
84
|
+
invariant(extractionFunction, 'extractionFunction is required');
|
|
85
|
+
const result = await processTranscriptMessage({
|
|
86
|
+
function: extractionFunction,
|
|
87
|
+
input: { message, objects: await objects },
|
|
88
|
+
options: { fallbackToRaw: true, timeout: 30_000 },
|
|
89
|
+
});
|
|
90
|
+
appendMessage(result.message);
|
|
91
|
+
} else {
|
|
92
|
+
appendMessage(message);
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
[appendMessage, space, entityExtraction, extractionFunction, objects],
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
useStoryTranscriber({
|
|
99
|
+
audioStreamTrack: track,
|
|
100
|
+
running,
|
|
101
|
+
isSpeaking,
|
|
102
|
+
transcriberConfig,
|
|
103
|
+
recorderConfig,
|
|
104
|
+
onSegments: handleSegments,
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
return <TranscriptionStory model={model} running={running} onRunningChange={setRunning} />;
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const meta = {
|
|
111
|
+
title: 'plugins/plugin-transcription/stories/LiveTranscription',
|
|
112
|
+
render: DefaultStory,
|
|
113
|
+
decorators: createStoryDecorators({ enableVectorIndex: true }),
|
|
114
|
+
} satisfies Meta<typeof DefaultStory>;
|
|
115
|
+
|
|
116
|
+
export default meta;
|
|
117
|
+
|
|
118
|
+
type Story = StoryObj<typeof meta>;
|
|
119
|
+
|
|
120
|
+
export const Default: Story = {
|
|
121
|
+
args: {
|
|
122
|
+
detectSpeaking: false,
|
|
123
|
+
audioConstraints: {
|
|
124
|
+
echoCancellation: false,
|
|
125
|
+
noiseSuppression: false,
|
|
126
|
+
autoGainControl: false,
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
export const SpeechDetection: Story = {
|
|
132
|
+
args: {
|
|
133
|
+
detectSpeaking: true,
|
|
134
|
+
audioConstraints: {
|
|
135
|
+
echoCancellation: true,
|
|
136
|
+
noiseSuppression: true,
|
|
137
|
+
autoGainControl: true,
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
// TODO(mykola): Fix hugging face quota issues.
|
|
143
|
+
// export const EntityExtraction: Story = {
|
|
144
|
+
// args: {
|
|
145
|
+
// detectSpeaking: true,
|
|
146
|
+
// entityExtraction: 'ner',
|
|
147
|
+
// audioConstraints: {
|
|
148
|
+
// echoCancellation: true,
|
|
149
|
+
// noiseSuppression: true,
|
|
150
|
+
// autoGainControl: true,
|
|
151
|
+
// },
|
|
152
|
+
// },
|
|
153
|
+
// };
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React, {
|
|
6
|
+
type ChangeEvent,
|
|
7
|
+
type Dispatch,
|
|
8
|
+
type RefObject,
|
|
9
|
+
type SetStateAction,
|
|
10
|
+
useCallback,
|
|
11
|
+
useRef,
|
|
12
|
+
} from 'react';
|
|
13
|
+
|
|
14
|
+
import { IconButton, ScrollContainer, Toolbar } from '@dxos/react-ui';
|
|
15
|
+
import { type Message } from '@dxos/types';
|
|
16
|
+
|
|
17
|
+
import { Transcription } from '../components';
|
|
18
|
+
import { type SerializationModel } from '../model';
|
|
19
|
+
|
|
20
|
+
export type TranscriptionStoryProps = {
|
|
21
|
+
audioRef?: RefObject<HTMLAudioElement | null>;
|
|
22
|
+
model: SerializationModel<Message.Message>;
|
|
23
|
+
running: boolean;
|
|
24
|
+
disabled?: boolean;
|
|
25
|
+
uploadAccept?: string;
|
|
26
|
+
onRunningChange: Dispatch<SetStateAction<boolean>>;
|
|
27
|
+
onUpload?: (file: File) => void;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Story wrapper that renders a transcript with playback controls, an optional audio file
|
|
32
|
+
* upload affordance, and a toolbar slot for additional controls.
|
|
33
|
+
*
|
|
34
|
+
* @param onUpload - Callback fired when the user picks a local audio file via the upload button.
|
|
35
|
+
* @param uploadAccept - HTML `accept` filter for the hidden file input. Defaults to `audio/*`.
|
|
36
|
+
*/
|
|
37
|
+
export const TranscriptionStory = ({
|
|
38
|
+
audioRef,
|
|
39
|
+
model,
|
|
40
|
+
running,
|
|
41
|
+
disabled,
|
|
42
|
+
uploadAccept = 'audio/*',
|
|
43
|
+
onRunningChange,
|
|
44
|
+
onUpload,
|
|
45
|
+
}: TranscriptionStoryProps) => {
|
|
46
|
+
const fileInputRef = useRef<HTMLInputElement>(null);
|
|
47
|
+
|
|
48
|
+
const handleFileChange = useCallback(
|
|
49
|
+
(event: ChangeEvent<HTMLInputElement>) => {
|
|
50
|
+
const file = event.target.files?.[0];
|
|
51
|
+
if (file && onUpload) {
|
|
52
|
+
onUpload(file);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Reset so the same file can be re-selected.
|
|
56
|
+
event.target.value = '';
|
|
57
|
+
},
|
|
58
|
+
[onUpload],
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<>
|
|
63
|
+
{audioRef && <audio ref={audioRef} autoPlay />}
|
|
64
|
+
<Toolbar.Root>
|
|
65
|
+
<IconButton
|
|
66
|
+
iconOnly
|
|
67
|
+
disabled={disabled}
|
|
68
|
+
icon={running ? 'ph--pause--regular' : 'ph--play--regular'}
|
|
69
|
+
label={running ? 'Pause' : 'Play'}
|
|
70
|
+
onClick={() => onRunningChange((running) => !running)}
|
|
71
|
+
/>
|
|
72
|
+
{onUpload && (
|
|
73
|
+
<>
|
|
74
|
+
<input
|
|
75
|
+
ref={fileInputRef}
|
|
76
|
+
type='file'
|
|
77
|
+
accept={uploadAccept}
|
|
78
|
+
disabled={disabled}
|
|
79
|
+
className='hidden'
|
|
80
|
+
onChange={handleFileChange}
|
|
81
|
+
/>
|
|
82
|
+
<IconButton
|
|
83
|
+
iconOnly
|
|
84
|
+
disabled={disabled}
|
|
85
|
+
icon='ph--upload--regular'
|
|
86
|
+
label='Upload audio'
|
|
87
|
+
onClick={() => fileInputRef.current?.click()}
|
|
88
|
+
/>
|
|
89
|
+
</>
|
|
90
|
+
)}
|
|
91
|
+
</Toolbar.Root>
|
|
92
|
+
<ScrollContainer.Root pin>
|
|
93
|
+
<ScrollContainer.Content>
|
|
94
|
+
<ScrollContainer.Viewport>
|
|
95
|
+
<Transcription model={model} />
|
|
96
|
+
</ScrollContainer.Viewport>
|
|
97
|
+
</ScrollContainer.Content>
|
|
98
|
+
</ScrollContainer.Root>
|
|
99
|
+
</>
|
|
100
|
+
);
|
|
101
|
+
};
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
// Helpers shared between LiveTranscription / FileTranscription stories.
|
|
6
|
+
// Each "live" story differs only in its *audio source* (mic vs file); everything else —
|
|
7
|
+
// the local in-memory message buffer, the transcriber lifecycle, and the plugin-manager
|
|
8
|
+
// decorator stack — is identical and lives here.
|
|
9
|
+
|
|
10
|
+
import { type Decorator } from '@storybook/react-vite';
|
|
11
|
+
import * as Effect from 'effect/Effect';
|
|
12
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
13
|
+
|
|
14
|
+
import { withPluginManager } from '@dxos/app-framework/testing';
|
|
15
|
+
import { AppActivationEvents } from '@dxos/app-toolkit';
|
|
16
|
+
import { scheduleTask } from '@dxos/async';
|
|
17
|
+
import { Context } from '@dxos/context';
|
|
18
|
+
import { Obj } from '@dxos/echo';
|
|
19
|
+
import { SpeakingMonitor } from '@dxos/plugin-calls';
|
|
20
|
+
import { ClientPlugin, initializeIdentity } from '@dxos/plugin-client/testing';
|
|
21
|
+
import { PreviewPlugin } from '@dxos/plugin-preview/testing';
|
|
22
|
+
import { StorybookPlugin, corePlugins } from '@dxos/plugin-testing';
|
|
23
|
+
import { IndexKind } from '@dxos/react-client/echo';
|
|
24
|
+
import { withLayout } from '@dxos/react-ui/testing';
|
|
25
|
+
import { Message, Organization, Person } from '@dxos/types';
|
|
26
|
+
import { seedTestData } from '@dxos/types/testing';
|
|
27
|
+
|
|
28
|
+
import { useFeedModelAdapter, useTranscriber } from '#hooks';
|
|
29
|
+
import { TestItem } from '#testing';
|
|
30
|
+
import { type TranscriptionCapabilities } from '#types';
|
|
31
|
+
|
|
32
|
+
import { type Transcriber, type TranscriberProps } from '../transcriber';
|
|
33
|
+
import { TranscriptionPlugin } from '../TranscriptionPlugin';
|
|
34
|
+
import { renderByline } from '../util';
|
|
35
|
+
|
|
36
|
+
export const useIsSpeaking = (track?: MediaStreamTrack) => {
|
|
37
|
+
const [isSpeaking, setIsSpeaking] = useState(false);
|
|
38
|
+
const speakingMonitor = useMemo(() => {
|
|
39
|
+
if (!track) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return new SpeakingMonitor(track);
|
|
44
|
+
}, [track]);
|
|
45
|
+
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
if (!speakingMonitor) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const ctx = new Context();
|
|
52
|
+
scheduleTask(ctx, async () => {
|
|
53
|
+
speakingMonitor.speakingChanged.on(ctx, () => setIsSpeaking(speakingMonitor.isSpeaking));
|
|
54
|
+
await speakingMonitor.open();
|
|
55
|
+
ctx.onDispose(() => speakingMonitor.close());
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
return () => {
|
|
59
|
+
void ctx.dispose();
|
|
60
|
+
};
|
|
61
|
+
}, [speakingMonitor]);
|
|
62
|
+
|
|
63
|
+
return isSpeaking;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
//
|
|
67
|
+
// Message model.
|
|
68
|
+
//
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* In-memory message buffer + model adapter for storybook use (production wires up a real
|
|
72
|
+
* space-backed `Feed`). Returns the renderable `model` plus an `appendMessage` callback.
|
|
73
|
+
*/
|
|
74
|
+
export const useStoryMessageModel = () => {
|
|
75
|
+
const [messages, setMessages] = useState<Message.Message[]>([]);
|
|
76
|
+
const appendMessage = useCallback((message: Message.Message) => setMessages((prev) => [...prev, message]), []);
|
|
77
|
+
const model = useFeedModelAdapter(renderByline([]), messages);
|
|
78
|
+
return { model, appendMessage };
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Wraps blocks in a `Message.Message` with the given sender and appends it to the local buffer.
|
|
83
|
+
* Provided as a convenience for stories that don't need entity-extraction or custom enrichment.
|
|
84
|
+
*/
|
|
85
|
+
export const useStoryAppendSegments = (
|
|
86
|
+
appendMessage: (message: Message.Message) => void,
|
|
87
|
+
sender: Message.Message['sender'] = {},
|
|
88
|
+
): TranscriberProps['onSegments'] =>
|
|
89
|
+
useCallback<TranscriberProps['onSegments']>(
|
|
90
|
+
async (blocks) => {
|
|
91
|
+
appendMessage(
|
|
92
|
+
Obj.make(Message.Message, {
|
|
93
|
+
created: new Date().toISOString(),
|
|
94
|
+
sender,
|
|
95
|
+
blocks,
|
|
96
|
+
}),
|
|
97
|
+
);
|
|
98
|
+
},
|
|
99
|
+
[appendMessage, sender],
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
//
|
|
103
|
+
// Transcriber lifecycle.
|
|
104
|
+
//
|
|
105
|
+
|
|
106
|
+
export type UseStoryTranscriberOptions = Pick<
|
|
107
|
+
TranscriptionCapabilities.GetTranscriberProps,
|
|
108
|
+
'transcriberConfig' | 'recorderConfig' | 'onSegments'
|
|
109
|
+
> & {
|
|
110
|
+
audioStreamTrack?: MediaStreamTrack;
|
|
111
|
+
/** Whether the user has the toolbar toggle on. */
|
|
112
|
+
running: boolean;
|
|
113
|
+
/** Voice-activity flag — chunks recording only fires while `true`. */
|
|
114
|
+
isSpeaking: boolean;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Drives the transcriber's open/close + chunk-recording lifecycle off `running`,
|
|
119
|
+
* the open flag, and an `isSpeaking` voice-activity gate. Returns the transcriber instance
|
|
120
|
+
* (`undefined` until the capability resolves and an audio track is available).
|
|
121
|
+
*/
|
|
122
|
+
export const useStoryTranscriber = ({
|
|
123
|
+
audioStreamTrack,
|
|
124
|
+
running,
|
|
125
|
+
isSpeaking,
|
|
126
|
+
transcriberConfig,
|
|
127
|
+
recorderConfig,
|
|
128
|
+
onSegments,
|
|
129
|
+
}: UseStoryTranscriberOptions): Transcriber | undefined => {
|
|
130
|
+
const transcriber = useTranscriber({
|
|
131
|
+
audioStreamTrack,
|
|
132
|
+
onSegments,
|
|
133
|
+
transcriberConfig,
|
|
134
|
+
recorderConfig,
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
// Open the transcriber when it becomes available; close on teardown.
|
|
138
|
+
// `tokenRef` is a per-effect identity so a late `close()` completion from a stale
|
|
139
|
+
// transcriber instance can't clobber `isOpen` after a newer instance has opened.
|
|
140
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
141
|
+
const tokenRef = useRef<symbol | null>(null);
|
|
142
|
+
useEffect(() => {
|
|
143
|
+
if (!transcriber) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
const token = Symbol();
|
|
147
|
+
tokenRef.current = token;
|
|
148
|
+
void transcriber.open().then(
|
|
149
|
+
() => tokenRef.current === token && setIsOpen(true),
|
|
150
|
+
() => tokenRef.current === token && setIsOpen(false),
|
|
151
|
+
);
|
|
152
|
+
return () => {
|
|
153
|
+
void transcriber.close().then(() => {
|
|
154
|
+
if (tokenRef.current === token) {
|
|
155
|
+
setIsOpen(false);
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
};
|
|
159
|
+
}, [transcriber]);
|
|
160
|
+
|
|
161
|
+
// Start/stop chunk recording based on running + open + isSpeaking.
|
|
162
|
+
useEffect(() => {
|
|
163
|
+
if (!transcriber || !isOpen) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
if (running && isSpeaking) {
|
|
167
|
+
transcriber.startChunksRecording();
|
|
168
|
+
} else {
|
|
169
|
+
transcriber.stopChunksRecording();
|
|
170
|
+
}
|
|
171
|
+
}, [transcriber, isOpen, running, isSpeaking]);
|
|
172
|
+
|
|
173
|
+
return transcriber;
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
//
|
|
177
|
+
// Plugin manager decorator.
|
|
178
|
+
//
|
|
179
|
+
|
|
180
|
+
export type StoryDecoratorsOptions = {
|
|
181
|
+
/**
|
|
182
|
+
* Enable schema/graph/vector indexes after the client boots; needed for entity-extraction
|
|
183
|
+
* queries over seeded `Person` / `Organization` objects.
|
|
184
|
+
* @default false
|
|
185
|
+
*/
|
|
186
|
+
enableVectorIndex?: boolean;
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Standard plugin-manager decorator for transcription stories: core plugins,
|
|
191
|
+
* `ClientPlugin` with `Person`/`Organization`/`TestItem` schemas + seeded test data, plus
|
|
192
|
+
* the `PreviewPlugin` and `TranscriptionPlugin`. Toggle `enableVectorIndex` for entity-extraction.
|
|
193
|
+
*/
|
|
194
|
+
export const createStoryDecorators = ({ enableVectorIndex = false }: StoryDecoratorsOptions = {}): Decorator[] => [
|
|
195
|
+
withLayout({ layout: 'column' }),
|
|
196
|
+
withPluginManager({
|
|
197
|
+
plugins: [
|
|
198
|
+
...corePlugins(),
|
|
199
|
+
StorybookPlugin({}),
|
|
200
|
+
ClientPlugin({
|
|
201
|
+
types: [TestItem, Person.Person, Organization.Organization],
|
|
202
|
+
onClientInitialized: ({ client }) =>
|
|
203
|
+
Effect.gen(function* () {
|
|
204
|
+
const { personalSpace } = yield* initializeIdentity(client);
|
|
205
|
+
if (enableVectorIndex) {
|
|
206
|
+
yield* enableQueryIndexes(client.services.services);
|
|
207
|
+
}
|
|
208
|
+
yield* Effect.promise(() => seedTestData(personalSpace));
|
|
209
|
+
}),
|
|
210
|
+
}),
|
|
211
|
+
PreviewPlugin(),
|
|
212
|
+
TranscriptionPlugin(),
|
|
213
|
+
],
|
|
214
|
+
fireEvents: [AppActivationEvents.SetupAppGraph],
|
|
215
|
+
}),
|
|
216
|
+
];
|
|
217
|
+
|
|
218
|
+
// TODO(mykola): Make API easier to use.
|
|
219
|
+
// TODO(mykola): Delete after enabling vector indexing by default.
|
|
220
|
+
const enableQueryIndexes = (services: { QueryService?: any }) =>
|
|
221
|
+
Effect.gen(function* () {
|
|
222
|
+
yield* Effect.promise(() =>
|
|
223
|
+
services.QueryService!.setConfig({
|
|
224
|
+
enabled: true,
|
|
225
|
+
indexes: [
|
|
226
|
+
{ kind: IndexKind.Kind.SCHEMA_MATCH },
|
|
227
|
+
{ kind: IndexKind.Kind.GRAPH },
|
|
228
|
+
{ kind: IndexKind.Kind.VECTOR },
|
|
229
|
+
],
|
|
230
|
+
}),
|
|
231
|
+
);
|
|
232
|
+
yield* Effect.promise(() => services.QueryService!.reindex());
|
|
233
|
+
});
|