@dxos/plugin-transcription 0.8.3 → 0.8.4-main.28f8d3d

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 (140) hide show
  1. package/dist/lib/browser/TranscriptContainer-FH7VAWYA.mjs +11 -0
  2. package/dist/lib/browser/{chunk-GOF7MJNV.mjs → chunk-5WH45KBY.mjs} +2 -2
  3. package/dist/lib/browser/{chunk-53AXUEIQ.mjs → chunk-BJWYA2BU.mjs} +332 -314
  4. package/dist/lib/browser/chunk-BJWYA2BU.mjs.map +7 -0
  5. package/dist/lib/browser/{chunk-IQ5ZRMHZ.mjs → chunk-KJIQQHJB.mjs} +45 -34
  6. package/dist/lib/browser/chunk-KJIQQHJB.mjs.map +7 -0
  7. package/dist/lib/browser/{chunk-OSISJM2F.mjs → chunk-KWOOVS5G.mjs} +4 -4
  8. package/dist/lib/browser/{chunk-OSISJM2F.mjs.map → chunk-KWOOVS5G.mjs.map} +2 -2
  9. package/dist/lib/browser/{chunk-W2KNYJD6.mjs → chunk-SREIAQSP.mjs} +3 -3
  10. package/dist/lib/browser/{chunk-W2KNYJD6.mjs.map → chunk-SREIAQSP.mjs.map} +1 -1
  11. package/dist/lib/browser/{chunk-UDCCT32F.mjs → chunk-UKUSJTQW.mjs} +3 -3
  12. package/dist/lib/browser/index.mjs +12 -12
  13. package/dist/lib/browser/index.mjs.map +3 -3
  14. package/dist/lib/browser/{intent-resolver-BGADCHVM.mjs → intent-resolver-AOVQ7JI4.mjs} +4 -4
  15. package/dist/lib/{node-esm/intent-resolver-5LVCYSJS.mjs.map → browser/intent-resolver-AOVQ7JI4.mjs.map} +2 -2
  16. package/dist/lib/browser/meta.json +1 -1
  17. package/dist/lib/browser/{react-surface-HMJS5FSS.mjs → react-surface-4MEJMKYQ.mjs} +7 -7
  18. package/dist/lib/browser/{transcriber-OYPLZFG5.mjs → transcriber-V77CN7XX.mjs} +6 -6
  19. package/dist/lib/browser/transcriber-V77CN7XX.mjs.map +7 -0
  20. package/dist/lib/browser/types/index.mjs +2 -2
  21. package/dist/lib/node-esm/{TranscriptContainer-G75LDEO5.mjs → TranscriptContainer-GEUOOYHX.mjs} +4 -4
  22. package/dist/lib/node-esm/{chunk-PRL64SRU.mjs → chunk-A33GNR44.mjs} +45 -34
  23. package/dist/lib/node-esm/chunk-A33GNR44.mjs.map +7 -0
  24. package/dist/lib/node-esm/{chunk-FH75X4JC.mjs → chunk-IKQMDRY6.mjs} +4 -4
  25. package/dist/lib/node-esm/{chunk-FH75X4JC.mjs.map → chunk-IKQMDRY6.mjs.map} +2 -2
  26. package/dist/lib/node-esm/{chunk-MFJO7EKD.mjs → chunk-PHP7MCAY.mjs} +3 -3
  27. package/dist/lib/node-esm/{chunk-MFJPEIVB.mjs → chunk-TM2ASOZA.mjs} +3 -3
  28. package/dist/lib/node-esm/{chunk-MFJPEIVB.mjs.map → chunk-TM2ASOZA.mjs.map} +1 -1
  29. package/dist/lib/node-esm/{chunk-TXMDLLBR.mjs → chunk-XMUCZBP3.mjs} +2 -2
  30. package/dist/lib/node-esm/{chunk-56QHOX4A.mjs → chunk-Y7PCJ34K.mjs} +332 -314
  31. package/dist/lib/node-esm/chunk-Y7PCJ34K.mjs.map +7 -0
  32. package/dist/lib/node-esm/index.mjs +12 -12
  33. package/dist/lib/node-esm/index.mjs.map +3 -3
  34. package/dist/lib/node-esm/{intent-resolver-5LVCYSJS.mjs → intent-resolver-P4XPIKQF.mjs} +4 -4
  35. package/dist/lib/{browser/intent-resolver-BGADCHVM.mjs.map → node-esm/intent-resolver-P4XPIKQF.mjs.map} +2 -2
  36. package/dist/lib/node-esm/meta.json +1 -1
  37. package/dist/lib/node-esm/{react-surface-JGQSYGRR.mjs → react-surface-EZUPNHUC.mjs} +7 -7
  38. package/dist/lib/node-esm/{transcriber-TVG2MBBN.mjs → transcriber-3SX3DNLV.mjs} +6 -6
  39. package/dist/lib/node-esm/transcriber-3SX3DNLV.mjs.map +7 -0
  40. package/dist/lib/node-esm/types/index.mjs +2 -2
  41. package/dist/types/src/capabilities/capabilities.d.ts +3 -3
  42. package/dist/types/src/capabilities/capabilities.d.ts.map +1 -1
  43. package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -1
  44. package/dist/types/src/capabilities/transcriber.d.ts.map +1 -1
  45. package/dist/types/src/components/Transcript/Transcript.d.ts.map +1 -1
  46. package/dist/types/src/components/Transcript/Transcript.stories.d.ts +1 -1
  47. package/dist/types/src/components/Transcript/Transcript.stories.d.ts.map +1 -1
  48. package/dist/types/src/components/TranscriptContainer.d.ts +4 -3
  49. package/dist/types/src/components/TranscriptContainer.d.ts.map +1 -1
  50. package/dist/types/src/components/index.d.ts +1 -4
  51. package/dist/types/src/components/index.d.ts.map +1 -1
  52. package/dist/types/src/components/stories/FileTranscription.stories.d.ts +1 -1
  53. package/dist/types/src/components/stories/FileTranscription.stories.d.ts.map +1 -1
  54. package/dist/types/src/components/stories/KeyWordRecognition.stories.d.ts +1 -1
  55. package/dist/types/src/components/stories/KeyWordRecognition.stories.d.ts.map +1 -1
  56. package/dist/types/src/components/stories/MicrophoneTranscription.stories.d.ts +1 -1
  57. package/dist/types/src/components/stories/MicrophoneTranscription.stories.d.ts.map +1 -1
  58. package/dist/types/src/hooks/useTranscriber.d.ts +1 -1
  59. package/dist/types/src/hooks/useVoiceInput.d.ts.map +1 -1
  60. package/dist/types/src/segments-normalization/normalization.d.ts +159 -66
  61. package/dist/types/src/segments-normalization/normalization.d.ts.map +1 -1
  62. package/dist/types/src/testing/testing.d.ts +1 -1
  63. package/dist/types/src/testing/testing.d.ts.map +1 -1
  64. package/dist/types/src/transcriber/index.d.ts +1 -1
  65. package/dist/types/src/transcriber/index.d.ts.map +1 -1
  66. package/dist/types/src/transcriber/media-stream-recorder.d.ts +1 -1
  67. package/dist/types/src/transcriber/media-stream-recorder.d.ts.map +1 -1
  68. package/dist/types/src/transcriber/transcriber.d.ts +1 -1
  69. package/dist/types/src/transcriber/transcriber.d.ts.map +1 -1
  70. package/dist/types/src/translations.d.ts +11 -11
  71. package/dist/types/src/translations.d.ts.map +1 -1
  72. package/dist/types/src/types/types.d.ts.map +1 -1
  73. package/dist/types/tsconfig.tsbuildinfo +1 -1
  74. package/package.json +59 -57
  75. package/src/TranscriptionPlugin.tsx +1 -1
  76. package/src/capabilities/capabilities.ts +5 -5
  77. package/src/capabilities/intent-resolver.ts +2 -2
  78. package/src/capabilities/transcriber.ts +3 -2
  79. package/src/components/Transcript/Transcript.stories.tsx +5 -4
  80. package/src/components/Transcript/Transcript.tsx +5 -4
  81. package/src/components/Transcript/deprecated/OldTranscript.tsx +2 -2
  82. package/src/components/Transcript/transcript-extension.ts +2 -2
  83. package/src/components/TranscriptContainer.tsx +10 -4
  84. package/src/components/stories/FileTranscription.stories.tsx +23 -19
  85. package/src/components/stories/KeyWordRecognition.stories.tsx +1 -1
  86. package/src/components/stories/MicrophoneTranscription.stories.tsx +18 -15
  87. package/src/hooks/useTranscriber.ts +5 -5
  88. package/src/hooks/useVoiceInput.ts +3 -2
  89. package/src/model/model.test.ts +9 -9
  90. package/src/segments-normalization/message-normalizer.ts +1 -1
  91. package/src/segments-normalization/normalization.test.ts +19 -21
  92. package/src/segments-normalization/normalization.ts +54 -44
  93. package/src/testing/testing.ts +11 -11
  94. package/src/transcriber/index.ts +1 -1
  95. package/src/transcriber/media-stream-recorder.ts +1 -1
  96. package/src/transcriber/transcriber.browser.test.ts +4 -3
  97. package/src/transcriber/transcriber.ts +5 -7
  98. package/src/transcriber/transcription-manager.ts +3 -3
  99. package/src/translations.ts +6 -4
  100. package/src/types/types.ts +2 -1
  101. package/dist/lib/browser/TranscriptContainer-H3AZQ4CQ.mjs +0 -11
  102. package/dist/lib/browser/chunk-53AXUEIQ.mjs.map +0 -7
  103. package/dist/lib/browser/chunk-IQ5ZRMHZ.mjs.map +0 -7
  104. package/dist/lib/browser/transcriber-OYPLZFG5.mjs.map +0 -7
  105. package/dist/lib/node/TranscriptContainer-KIG3GMAB.cjs +0 -32
  106. package/dist/lib/node/TranscriptContainer-KIG3GMAB.cjs.map +0 -7
  107. package/dist/lib/node/chunk-3PYT3BDM.cjs +0 -40
  108. package/dist/lib/node/chunk-3PYT3BDM.cjs.map +0 -7
  109. package/dist/lib/node/chunk-6LW5RA3K.cjs +0 -75
  110. package/dist/lib/node/chunk-6LW5RA3K.cjs.map +0 -7
  111. package/dist/lib/node/chunk-AFUZI63A.cjs +0 -42
  112. package/dist/lib/node/chunk-AFUZI63A.cjs.map +0 -7
  113. package/dist/lib/node/chunk-CVUN3UO7.cjs +0 -778
  114. package/dist/lib/node/chunk-CVUN3UO7.cjs.map +0 -7
  115. package/dist/lib/node/chunk-FKDJNJ57.cjs +0 -35
  116. package/dist/lib/node/chunk-FKDJNJ57.cjs.map +0 -7
  117. package/dist/lib/node/chunk-ZFAUMZXE.cjs +0 -518
  118. package/dist/lib/node/chunk-ZFAUMZXE.cjs.map +0 -7
  119. package/dist/lib/node/index.cjs +0 -133
  120. package/dist/lib/node/index.cjs.map +0 -7
  121. package/dist/lib/node/intent-resolver-LL3TTI4H.cjs +0 -45
  122. package/dist/lib/node/intent-resolver-LL3TTI4H.cjs.map +0 -7
  123. package/dist/lib/node/meta.json +0 -1
  124. package/dist/lib/node/react-surface-N25TBBG4.cjs +0 -56
  125. package/dist/lib/node/react-surface-N25TBBG4.cjs.map +0 -7
  126. package/dist/lib/node/transcriber-6J4FVFSZ.cjs +0 -68
  127. package/dist/lib/node/transcriber-6J4FVFSZ.cjs.map +0 -7
  128. package/dist/lib/node/types/index.cjs +0 -36
  129. package/dist/lib/node/types/index.cjs.map +0 -7
  130. package/dist/lib/node-esm/chunk-56QHOX4A.mjs.map +0 -7
  131. package/dist/lib/node-esm/chunk-PRL64SRU.mjs.map +0 -7
  132. package/dist/lib/node-esm/transcriber-TVG2MBBN.mjs.map +0 -7
  133. /package/dist/lib/browser/{TranscriptContainer-H3AZQ4CQ.mjs.map → TranscriptContainer-FH7VAWYA.mjs.map} +0 -0
  134. /package/dist/lib/browser/{chunk-GOF7MJNV.mjs.map → chunk-5WH45KBY.mjs.map} +0 -0
  135. /package/dist/lib/browser/{chunk-UDCCT32F.mjs.map → chunk-UKUSJTQW.mjs.map} +0 -0
  136. /package/dist/lib/browser/{react-surface-HMJS5FSS.mjs.map → react-surface-4MEJMKYQ.mjs.map} +0 -0
  137. /package/dist/lib/node-esm/{TranscriptContainer-G75LDEO5.mjs.map → TranscriptContainer-GEUOOYHX.mjs.map} +0 -0
  138. /package/dist/lib/node-esm/{chunk-MFJO7EKD.mjs.map → chunk-PHP7MCAY.mjs.map} +0 -0
  139. /package/dist/lib/node-esm/{chunk-TXMDLLBR.mjs.map → chunk-XMUCZBP3.mjs.map} +0 -0
  140. /package/dist/lib/node-esm/{react-surface-JGQSYGRR.mjs.map → react-surface-EZUPNHUC.mjs.map} +0 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/components/TranscriptContainer.tsx", "../../../src/hooks/useAudioFile.ts", "../../../src/hooks/useAudioTrack.ts", "../../../src/hooks/useQueueModelAdapter.ts", "../../../src/model/model.ts", "../../../src/hooks/useTranscriber.ts", "../../../src/capabilities/index.ts", "../../../src/hooks/useVoiceInput.ts", "../../../src/components/Transcript/Transcript.tsx", "../../../src/components/Transcript/transcript-extension.ts"],
4
+ "sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport React from 'react';\n\nimport { fullyQualifiedId, getSpace } from '@dxos/client/echo';\nimport { useMembers, useQueue } from '@dxos/react-client/echo';\nimport { StackItem } from '@dxos/react-ui-stack';\nimport { type DataType } from '@dxos/schema';\n\nimport { useQueueModelAdapter } from '../hooks';\nimport { type TranscriptType } from '../types';\n\nimport { Transcript, renderMarkdown } from './Transcript';\n\nexport type TranscriptionContainerProps = {\n role: string;\n transcript: TranscriptType;\n};\n\nexport const TranscriptionContainer = ({ transcript }: TranscriptionContainerProps) => {\n const attendableId = fullyQualifiedId(transcript);\n const space = getSpace(transcript);\n const members = useMembers(space?.key).map((member) => member.identity);\n const queue = useQueue<DataType.Message>(transcript.queue.dxn, { pollInterval: 1_000 });\n const model = useQueueModelAdapter(renderMarkdown(members), queue);\n\n return (\n <StackItem.Content classNames='container-max-width pli-2'>\n <Transcript attendableId={attendableId} space={space} model={model} transcript={transcript} />\n </StackItem.Content>\n );\n};\n\nexport default TranscriptionContainer;\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { useEffect, useState } from 'react';\n\nimport { scheduleTask } from '@dxos/async';\nimport { Context } from '@dxos/context';\nimport { log } from '@dxos/log';\n\nexport type UseAudioState = {\n audio?: HTMLAudioElement;\n stream?: MediaStream;\n track?: MediaStreamTrack;\n};\n\nexport const useAudioFile = (audioUrl: string, constraints?: MediaTrackConstraints): UseAudioState => {\n const [{ audio, stream, track }, setStream] = useState<UseAudioState>({});\n useEffect(() => {\n const ctx = new Context();\n\n scheduleTask(ctx, async () => {\n const response = await fetch(audioUrl);\n const blob = await response.blob();\n const objectUrl = URL.createObjectURL(blob);\n ctx.onDispose(() => {\n URL.revokeObjectURL(objectUrl);\n });\n\n const audio = new Audio();\n audio.src = objectUrl;\n\n await new Promise<void>((resolve, reject) => {\n audio.addEventListener(\n 'error',\n (err) => {\n log.error('error', { err });\n reject(err);\n },\n { once: true },\n );\n audio.addEventListener(\n 'canplay',\n async () => {\n log.info('starting...');\n try {\n // Try to play the audio\n await audio.play();\n resolve();\n } catch (playError) {\n log.error('Play failed', { playError });\n // Still resolve as the audio is ready, even if autoplay failed.\n resolve();\n }\n },\n { once: true },\n );\n audio.load();\n });\n\n const audioCtx = new AudioContext();\n\n // Resume AudioContext if it's suspended.\n if (audioCtx.state === 'suspended') {\n await audioCtx.resume();\n }\n\n const destination = audioCtx.createMediaStreamDestination();\n destination.channelCount = 1;\n\n const source = audioCtx.createMediaElementSource(audio);\n source.connect(destination);\n const track = destination.stream.getAudioTracks()[0];\n if (constraints) {\n await track.applyConstraints(constraints).catch((err) => log.catch(err));\n }\n\n // Also connect to speakers so audio is audible.\n setStream({\n audio,\n stream: destination.stream,\n track: destination.stream.getAudioTracks()[0],\n });\n });\n\n return () => {\n void ctx.dispose();\n };\n }, [audioUrl]);\n\n return { audio, stream, track };\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { useEffect, useState } from 'react';\n\n/**\n *\n */\n// TODO(burdon): Reconcile with react-ui-sfx and plugin-calls.\nexport const useAudioTrack = (active?: boolean, constraints?: MediaTrackConstraints): MediaStreamTrack | undefined => {\n const [track, setTrack] = useState<MediaStreamTrack>();\n useEffect(() => {\n if (!active) {\n track?.stop();\n setTrack(undefined);\n return;\n }\n\n const initAudio = async () => {\n const audio = new Audio();\n audio.srcObject = await navigator.mediaDevices.getUserMedia({ audio: constraints ?? true });\n const [track] = audio.srcObject.getAudioTracks();\n if (track) {\n setTrack(track);\n }\n };\n\n if (active) {\n void initAudio();\n }\n }, [active]);\n\n return track;\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { useEffect, useMemo, useState } from 'react';\n\nimport type { Obj } from '@dxos/echo';\nimport { type Queue } from '@dxos/react-client/echo';\n\nimport { type ChunkRenderer, SerializationModel } from '../model';\n\n/**\n * Model adapter for a queue.\n */\nexport const useQueueModelAdapter = <T extends Obj.Any>(\n renderer: ChunkRenderer<T>,\n queue: Queue<T> | undefined,\n initialChunks: T[] = [],\n): SerializationModel<T> => {\n const model = useMemo(() => new SerializationModel<T>(renderer, initialChunks), [queue]);\n const [loaded, setLoaded] = useState(false);\n\n // Set initial blocks.\n useEffect(() => {\n if (!queue) {\n return;\n }\n\n const update = () => {\n for (const block of queue?.objects ?? []) {\n model.appendChunk(block);\n }\n\n setLoaded(true);\n };\n\n // TODO(burdon): This is a hack to ensure the queue is loaded.\n let i: NodeJS.Timeout | undefined;\n if (queue.isLoading) {\n i = setInterval(() => {\n if (!queue?.isLoading) {\n clearInterval(i);\n update();\n }\n }, 1_000);\n } else {\n update();\n }\n\n return () => clearTimeout(i);\n }, [model, queue]);\n\n // TODO(burdon): Can we listen for queue events?\n useEffect(() => {\n if (!loaded || !queue || model.chunks.length === queue.objects.length) {\n return;\n }\n\n const chunk = queue.objects.at(-1);\n if (chunk) {\n model.appendChunk(chunk);\n }\n }, [model, loaded, queue?.objects.length]);\n\n return model;\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { Text } from '@codemirror/state';\nimport { type EditorView } from '@codemirror/view';\n\nimport { Event } from '@dxos/async';\nimport { invariant } from '@dxos/invariant';\nimport { log } from '@dxos/log';\n\nexport type Chunk = { id: string };\n\n/**\n * Covert block to a set of markdown lines.\n */\nexport type ChunkRenderer<T extends Chunk> = (chunk: T, index: number, debug?: boolean) => string[];\n\n/**\n * Abstract representation of the document model.\n */\nexport interface ChunkDocument {\n lineCount(): number;\n replaceLines(from: number, remove: number, insert: string[]): void;\n}\n\n/**\n * Codemirror document adapter.\n */\nexport class DocumentAdapter implements ChunkDocument {\n constructor(private readonly _view: EditorView) {}\n\n /** The document must always have at least one line. */\n lineCount(): number {\n return this._view.state.doc.lines - 1;\n }\n\n replaceLines(from: number, remove: number, insert: string[]): void {\n log('replaceLines', { count: this._view.state.doc.lines, from, remove, insert });\n\n const numLines = this._view.state.doc.lines;\n const posFrom = this._view.state.doc.line(from).from;\n const posTo = remove === 0 ? posFrom : this._view.state.doc.line(Math.min(numLines, from + remove)).from;\n\n // Don't remove the last line.\n let text = insert.join('\\n');\n if (posTo === this._view.state.doc.length) {\n text += '\\n';\n }\n\n this._view.dispatch({\n changes: { from: posFrom, to: posTo, insert: text },\n });\n }\n}\n\ntype ChunkChange<T extends Chunk> =\n | {\n type: 'append';\n index: number;\n chunk: T;\n }\n | {\n type: 'update';\n index: number;\n chunk: T;\n }\n | {\n type: 'delete';\n index: number;\n id: string;\n };\n\n/**\n * Each Chunk can be converted into a set of lines.\n * Chunks can be added, updated or deleted from the Queue.\n * A Document is an immutable projection that represents a flat list of lines corresponding to the Queue.\n *\n * Ideally we would implement a custom virtual Text model for the View, but this currently isn't possible in Codemirror.\n * Instead this model tracks changes and syncs them with the ChunkDocument.\n */\nexport class SerializationModel<T extends Chunk> {\n /** Ordered set of chunks. */\n private readonly _chunks: T[] = [];\n\n /** Map of chunk IDs to their current line counts. */\n private readonly _chunkLineCounts = new Map<string, number>();\n\n /** Map of line numbers to chunk IDs. */\n private readonly _lineToChunk = new Map<number, T>();\n\n /** Track chunk changes since last sync. */\n private readonly _changes: Array<ChunkChange<T>> = [];\n\n /** Emits when the document is updated. */\n public readonly update = new Event<void>();\n\n constructor(\n private readonly _renderer: ChunkRenderer<T>,\n initialChunks: T[] = [],\n ) {\n initialChunks.forEach((chunk) => {\n this.appendChunk(chunk);\n });\n }\n\n toJSON(): { chunks: number; changes: number } {\n return {\n chunks: this._chunks.length,\n changes: this._changes.length,\n };\n }\n\n get doc() {\n return Text.of([...this._chunks.flatMap((chunk, index) => this._renderer(chunk, index)), '']);\n }\n\n get chunks() {\n return this._chunks;\n }\n\n /**\n * Get the block ID at the given line number.\n */\n getChunkAtLine(line: number): T | undefined {\n return this._lineToChunk.get(line);\n }\n\n reset(): this {\n this._chunks.length = 0;\n this._chunkLineCounts.clear();\n this._lineToChunk.clear();\n this.update.emit();\n return this;\n }\n\n appendChunk(chunk: T): this {\n const index = this._chunks.length;\n this._chunks.push(chunk);\n this._changes.push({ type: 'append', index, chunk });\n this.update.emit();\n return this;\n }\n\n updateChunk(chunk: T): this {\n const index = this._chunks.findIndex((c) => c.id === chunk.id);\n invariant(index !== -1);\n this._chunks[index] = chunk;\n this._changes.push({ type: 'update', index, chunk });\n this.update.emit();\n return this;\n }\n\n deleteBlock(id: string): this {\n const index = this._chunks.findIndex((c) => c.id === id);\n invariant(index !== -1);\n this._chunks.splice(index, 1);\n this._changes.push({ type: 'delete', index, id });\n this.update.emit();\n return this;\n }\n\n /**\n * Syncs the tracked changes with the ChunkDocument.\n */\n sync(document: ChunkDocument): this {\n log('sync', { changes: this._changes });\n\n // Process each change in order.\n for (const change of this._changes) {\n switch (change.type) {\n case 'append': {\n // For appends, convert block to lines and add at the end.\n const lines = this._renderer(change.chunk, change.index);\n const lastLine = document.lineCount();\n document.replaceLines(lastLine + 1, 0, lines);\n break;\n }\n\n case 'update': {\n // For updates, find the block's line range and replace with new lines.\n let lineStart = 1;\n for (let i = 0; i < change.index; i++) {\n lineStart += this._chunkLineCounts.get(this._chunks[i].id)!;\n }\n const previousLineCount = this._chunkLineCounts.get(change.chunk.id)!;\n const newLines = this._renderer(change.chunk, change.index);\n document.replaceLines(lineStart, previousLineCount, newLines);\n break;\n }\n\n case 'delete': {\n // For deletes, find the block's line range and remove those lines.\n let lineStart = 1;\n for (let i = 0; i < change.index; i++) {\n lineStart += this._chunkLineCounts.get(this._chunks[i].id)!;\n }\n const previousLineCount = this._chunkLineCounts.get(change.id)!;\n document.replaceLines(lineStart, previousLineCount, []);\n break;\n }\n }\n }\n\n // Clear the line-to-block mapping.\n this._lineToChunk.clear();\n\n // Update all block line counts and line-to-block mapping after processing changes.\n let currentLine = 1;\n for (const [index, chunk] of this._chunks.entries()) {\n const lineCount = this._renderer(chunk, index).length;\n this._chunkLineCounts.set(chunk.id, lineCount);\n this._lineToChunk.set(currentLine, chunk);\n currentLine += lineCount;\n }\n\n // Clean up deleted blocks.\n const chunkIds = new Set(this._chunks.map((chunk) => chunk.id));\n for (const id of this._chunkLineCounts.keys()) {\n if (!chunkIds.has(id)) {\n this._chunkLineCounts.delete(id);\n }\n }\n\n // Clear changes after sync.\n this._changes.length = 0;\n return this;\n }\n}\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { useEffect, useMemo } from 'react';\n\nimport { useCapabilities } from '@dxos/app-framework';\n\nimport { TranscriptionCapabilities } from '../capabilities';\nimport { type Transcriber } from '../transcriber';\n\n/**\n * Records audio while user is speaking and transcribes it after user is done speaking.\n */\nexport const useTranscriber = ({\n audioStreamTrack,\n recorderConfig,\n transcriberConfig,\n onSegments,\n}: Partial<TranscriptionCapabilities.GetTranscriberProps>) => {\n const [getTranscriber] = useCapabilities(TranscriptionCapabilities.Transcriber);\n\n // Initialize audio transcription.\n const transcriber = useMemo<Transcriber | undefined>(() => {\n if (!getTranscriber || !audioStreamTrack || !onSegments) {\n return undefined;\n }\n\n return getTranscriber({ audioStreamTrack, recorderConfig, transcriberConfig, onSegments });\n }, [getTranscriber, audioStreamTrack, recorderConfig, transcriberConfig, onSegments]);\n\n useEffect(() => {\n return () => {\n void transcriber?.close();\n };\n }, [transcriber]);\n\n return transcriber;\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { lazy } from '@dxos/app-framework';\n\nexport const IntentResolver = lazy(() => import('./intent-resolver'));\nexport const ReactSurface = lazy(() => import('./react-surface'));\nexport const Transcriber = lazy(() => import('./transcriber'));\n\nexport * from './capabilities';\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { useCallback, useEffect, useState } from 'react';\n\nimport { scheduleMicroTask } from '@dxos/async';\nimport { Context } from '@dxos/context';\nimport { log } from '@dxos/log';\nimport { useSoundEffect } from '@dxos/react-ui-sfx';\n\nimport { type TranscriberParams } from '../transcriber';\n\nimport { useAudioTrack } from './useAudioTrack';\nimport { useTranscriber } from './useTranscriber';\n\nexport type UseVoiceInputProps = {\n active?: boolean;\n onUpdate: (text: string) => void;\n};\n\n/**\n * Hook for voice input.\n */\nexport const useVoiceInput = ({ active, onUpdate }: UseVoiceInputProps) => {\n const soundStart = useSoundEffect('StartRecording');\n const soundStop = useSoundEffect('StopRecording');\n\n const handleSegments = useCallback<TranscriberParams['onSegments']>(async (segments) => {\n const text = segments.map((str) => str.text.trim().replace(/[^\\w\\s]/g, '')).join(' ');\n onUpdate(text);\n }, []);\n\n // Audio/transcription.\n const [recording, setRecording] = useState(false);\n const track = useAudioTrack(active);\n const transcriber = useTranscriber({\n audioStreamTrack: track,\n onSegments: handleSegments,\n });\n\n // Start/stop transcription.\n useEffect(() => {\n const ctx = new Context();\n scheduleMicroTask(ctx, async () => {\n if (active && transcriber) {\n await transcriber.open();\n log.info('starting...');\n setRecording(true);\n void soundStart.play();\n transcriber.startChunksRecording();\n } else if (!active && transcriber?.isOpen) {\n transcriber?.stopChunksRecording();\n await transcriber?.close();\n log.info('stopped');\n setRecording(false);\n void soundStop.play();\n }\n });\n\n return () => {\n void ctx.dispose();\n };\n }, [active, transcriber]);\n\n return { recording };\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport React from 'react';\n\nimport { type Space } from '@dxos/react-client/echo';\nimport { type Identity } from '@dxos/react-client/halo';\nimport { IconButton, type ThemedClassName, useThemeContext } from '@dxos/react-ui';\nimport {\n createBasicExtensions,\n createMarkdownExtensions,\n createRenderer,\n createThemeExtensions,\n decorateMarkdown,\n editorWidth,\n preview,\n useTextEditor,\n} from '@dxos/react-ui-editor';\nimport { mx } from '@dxos/react-ui-theme';\nimport { type DataType } from '@dxos/schema';\nimport { isNotFalsy } from '@dxos/util';\n\nimport { type SerializationModel } from '../../model';\nimport { type TranscriptType } from '../../types';\n\nimport { transcript } from './transcript-extension';\n\nexport const renderMarkdown =\n (identities: Identity[]) =>\n (message: DataType.Message, index: number, debug = false): string[] => {\n if (message.sender.role === 'assistant') {\n // Start/stop block.\n return [message.blocks.find((block) => block._tag === 'transcript')?.text ?? '', ''];\n }\n\n // TODO(burdon): Use link/reference markup for users (with popover).\n // TODO(burdon): Color and avatar.\n const identity = identities.find((identity) => identity.did === message.sender.identityDid);\n const name =\n identity?.profile?.displayName ??\n message.sender.contact?.target?.fullName ??\n message.sender.name ??\n message.sender.email ??\n message.sender.identityDid;\n const blocks = message.blocks.filter((block) => block._tag === 'transcript');\n return [\n `###### ${name}` + (debug ? ` [${index}]:${message.id}` : ''),\n blocks.map((block) => block.text.trim()).join(' '),\n '',\n ];\n };\n\nexport type TranscriptProps = ThemedClassName<{\n transcript?: TranscriptType;\n space?: Space;\n model: SerializationModel<DataType.Message>;\n // TODO(wittjosiah): Move to container.\n attendableId?: string;\n ignoreAttention?: boolean;\n}>;\n\n/**\n * Transcript component implemented using the editor.\n */\nexport const Transcript = ({\n classNames,\n transcript: object,\n space,\n model,\n attendableId,\n ignoreAttention,\n}: TranscriptProps) => {\n const { themeMode } = useThemeContext();\n const { parentRef } = useTextEditor(() => {\n return {\n extensions: [\n createBasicExtensions({ readOnly: true, lineWrapping: true, search: true }),\n createMarkdownExtensions({ themeMode }),\n createThemeExtensions({ themeMode }),\n decorateMarkdown(),\n space && preview(),\n transcript({\n model,\n started: object?.started ? new Date(object.started) : undefined,\n renderButton: createRenderer(({ onClick }) => (\n <IconButton icon='ph--arrow-line-down--regular' iconOnly label='Scroll to bottom' onClick={onClick} />\n )),\n }),\n ].filter(isNotFalsy),\n };\n }, [space, model]);\n\n return (\n <div\n ref={parentRef}\n className={mx('flex grow overflow-hidden', editorWidth, classNames)}\n data-popover-collision-boundary={true}\n />\n );\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { type Extension, RangeSetBuilder } from '@codemirror/state';\nimport { EditorView, GutterMarker, ViewPlugin, type ViewUpdate, gutter } from '@codemirror/view';\nimport { format } from 'date-fns/format';\nimport { intervalToDuration } from 'date-fns/intervalToDuration';\n\nimport { type CleanupFn, addEventListener, combine } from '@dxos/async';\nimport { type RenderCallback } from '@dxos/react-ui-editor';\nimport { type DataType } from '@dxos/schema';\n\nimport { DocumentAdapter, type SerializationModel } from '../../model';\n\n/**\n * Data structure that maps Chunks queue to lines with transcript state.\n */\nexport type TranscriptOptions = {\n model: SerializationModel<DataType.Message>;\n started?: Date;\n renderButton?: RenderCallback<{ onClick: () => void }>;\n};\n\n/**\n * Scrolling transcript with timestamps.\n */\nexport const transcript = ({ model, started, renderButton }: TranscriptOptions): Extension => {\n return [\n // Show timestamps in the gutter.\n gutter({\n class: 'cm-timestamp-gutter',\n lineMarkerChange: (update) => update.docChanged || update.viewportChanged,\n markers: (view) => {\n const start = getStartTime(started, model.chunks[0]);\n const builder = new RangeSetBuilder<GutterMarker>();\n for (const { from, to } of view.visibleRanges) {\n let line = view.state.doc.lineAt(from);\n while (line.from <= to) {\n const block = model.getChunkAtLine(line.number)?.blocks[0];\n const timestamp = block?._tag === 'transcript' && block.started;\n if (timestamp) {\n builder.add(line.from, line.from, new TimestampMarker(line.number, new Date(timestamp), start));\n }\n\n if (line.to + 1 > view.state.doc.length) {\n break;\n }\n\n line = view.state.doc.lineAt(line.to + 1);\n }\n }\n\n return builder.finish();\n },\n }),\n\n // Listen for model updates.\n ViewPlugin.fromClass(\n class {\n private readonly _controls?: HTMLDivElement;\n private readonly _cleanup: CleanupFn;\n private readonly _adapter: DocumentAdapter;\n private _initialized = false;\n\n constructor(view: EditorView) {\n this._adapter = new DocumentAdapter(view);\n\n const scroller = view.scrollDOM;\n let isAutoScrolling = false;\n let hasScrolled = false;\n\n let timeout: NodeJS.Timeout | undefined;\n const scrollToBottom = (smooth = false) => {\n scroller.style.scrollBehavior = smooth ? 'smooth' : '';\n\n // Temporarily hide scrollbar to prevent flicker.\n scroller.classList.add('cm-hide-scrollbar');\n isAutoScrolling = true;\n clearTimeout(timeout);\n timeout = setTimeout(() => {\n this._controls?.classList.add('opacity-0');\n scroller.classList.remove('cm-hide-scrollbar');\n isAutoScrolling = false;\n }, 500);\n\n // Scroll to bottom.\n view.dispatch({\n effects: EditorView.scrollIntoView(view.state.doc.length, { y: 'end' }),\n });\n };\n\n // Scroll button.\n if (renderButton) {\n this._controls = document.createElement('div');\n this._controls.classList.add('cm-controls', 'transition-opacity', 'duration-300', 'opacity-0');\n view.dom.appendChild(this._controls);\n renderButton(\n this._controls,\n {\n onClick: () => {\n scrollToBottom(false);\n },\n },\n view,\n );\n }\n\n // Event listeners.\n this._cleanup = combine(\n addEventListener(view.scrollDOM, 'scroll', () => {\n if (!isAutoScrolling) {\n hasScrolled = true;\n this._controls?.classList.remove('opacity-0');\n }\n }),\n\n model.update.on(() => {\n // Check if clamped to bottom.\n const autoScroll =\n scroller.scrollHeight - scroller.scrollTop - scroller.clientHeight === 0 || !hasScrolled;\n\n // Sync.\n model.sync(this._adapter);\n\n // Scroll.\n if (autoScroll) {\n scrollToBottom(true);\n }\n }),\n );\n }\n\n update(update: ViewUpdate) {\n // Initial sync.\n if (!this._initialized) {\n this._initialized = true;\n setTimeout(() => {\n model.sync(this._adapter);\n });\n }\n }\n\n destroy() {\n this._controls?.remove();\n this._cleanup();\n }\n },\n ),\n\n EditorView.theme({\n '.cm-scroller': {\n overflowY: 'scroll',\n },\n '.cm-hide-scrollbar': {\n scrollbarWidth: 'none',\n '-ms-overflow-style': 'none',\n },\n '.cm-hide-scrollbar::-webkit-scrollbar': {\n display: 'none',\n },\n '.cm-controls': {\n position: 'absolute',\n bottom: '0.5rem',\n right: '0.5rem',\n zIndex: 1000,\n },\n '.cm-line': {\n paddingRight: '1rem',\n },\n '.cm-timestamp-gutter': {\n width: '6rem',\n paddingRight: '1rem',\n },\n '.cm-timestamp-gutter > .cm-gutterElement > div': {\n display: 'inline-flex',\n textAlign: 'right',\n padding: '3px',\n },\n }),\n ];\n};\n\n/**\n * Gutter marker that displays a timestamp.\n */\nclass TimestampMarker extends GutterMarker {\n constructor(\n readonly _line: number,\n readonly _timestamp: Date,\n readonly _started?: Date,\n ) {\n super();\n }\n\n override eq(other: this): boolean {\n return other._timestamp === this._timestamp;\n }\n\n override toDOM(view: EditorView): HTMLDivElement {\n const el = document.createElement('div');\n el.className = 'text-sm text-subdued hover:bg-hoverSurface cursor-pointer';\n el.textContent = formatTimestamp(this._timestamp, this._started);\n // TODO(burdon): Click to bookmark or copy hyperlink.\n el.onclick = () => {\n const pos = view.state.doc.line(this._line).from;\n view.dispatch({\n effects: EditorView.scrollIntoView(pos, { y: 'start' }),\n });\n };\n\n return el;\n }\n}\n\nconst getStartTime = (started?: Date, message?: DataType.Message): Date | undefined => {\n if (started) {\n return started;\n }\n\n if (message?.blocks[0]?._tag === 'transcript' && message.blocks[0].started) {\n return new Date(message.blocks[0].started);\n }\n\n return undefined;\n};\n\nconst formatTimestamp = (timestamp: Date, relative?: Date) => {\n if (relative) {\n const pad = (n = 0) => String(n).padStart(2, '0');\n const { hours, minutes, seconds } = intervalToDuration({ start: relative, end: timestamp });\n return `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;\n } else {\n return format(timestamp, 'HH:mm:ss');\n }\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["React", "fullyQualifiedId", "getSpace", "useMembers", "useQueue", "StackItem", "useEffect", "useState", "scheduleTask", "Context", "log", "useAudioFile", "audioUrl", "constraints", "audio", "stream", "track", "setStream", "ctx", "response", "fetch", "blob", "objectUrl", "URL", "createObjectURL", "onDispose", "revokeObjectURL", "Audio", "src", "Promise", "resolve", "reject", "addEventListener", "err", "error", "once", "info", "play", "playError", "load", "audioCtx", "AudioContext", "state", "resume", "destination", "createMediaStreamDestination", "channelCount", "source", "createMediaElementSource", "connect", "getAudioTracks", "applyConstraints", "catch", "dispose", "useEffect", "useState", "useAudioTrack", "active", "constraints", "track", "setTrack", "useState", "useEffect", "stop", "undefined", "initAudio", "audio", "Audio", "srcObject", "navigator", "mediaDevices", "getUserMedia", "getAudioTracks", "useEffect", "useMemo", "useState", "Text", "Event", "invariant", "log", "DocumentAdapter", "_view", "lineCount", "state", "doc", "lines", "replaceLines", "from", "remove", "insert", "count", "numLines", "posFrom", "line", "posTo", "Math", "min", "text", "join", "length", "dispatch", "changes", "to", "SerializationModel", "_chunks", "_chunkLineCounts", "_lineToChunk", "_changes", "update", "_renderer", "initialChunks", "Map", "forEach", "chunk", "appendChunk", "toJSON", "chunks", "of", "flatMap", "index", "getChunkAtLine", "get", "reset", "clear", "emit", "push", "type", "updateChunk", "findIndex", "c", "id", "deleteBlock", "splice", "sync", "document", "change", "lastLine", "lineStart", "i", "previousLineCount", "newLines", "currentLine", "entries", "set", "chunkIds", "Set", "map", "keys", "has", "delete", "useQueueModelAdapter", "renderer", "queue", "initialChunks", "model", "useMemo", "SerializationModel", "loaded", "setLoaded", "useState", "useEffect", "update", "block", "objects", "appendChunk", "i", "isLoading", "setInterval", "clearInterval", "clearTimeout", "chunks", "length", "chunk", "at", "useEffect", "useMemo", "useCapabilities", "lazy", "IntentResolver", "lazy", "ReactSurface", "Transcriber", "useTranscriber", "audioStreamTrack", "recorderConfig", "transcriberConfig", "onSegments", "getTranscriber", "useCapabilities", "TranscriptionCapabilities", "Transcriber", "transcriber", "useMemo", "undefined", "useEffect", "close", "useCallback", "useEffect", "useState", "scheduleMicroTask", "Context", "log", "useSoundEffect", "useVoiceInput", "active", "onUpdate", "soundStart", "useSoundEffect", "soundStop", "handleSegments", "useCallback", "segments", "text", "map", "str", "trim", "replace", "join", "recording", "setRecording", "useState", "track", "useAudioTrack", "transcriber", "useTranscriber", "audioStreamTrack", "onSegments", "useEffect", "ctx", "Context", "scheduleMicroTask", "open", "log", "info", "play", "startChunksRecording", "isOpen", "stopChunksRecording", "close", "dispose", "React", "IconButton", "useThemeContext", "createBasicExtensions", "createMarkdownExtensions", "createRenderer", "createThemeExtensions", "decorateMarkdown", "editorWidth", "preview", "useTextEditor", "mx", "isNotFalsy", "RangeSetBuilder", "EditorView", "GutterMarker", "ViewPlugin", "gutter", "format", "intervalToDuration", "addEventListener", "combine", "transcript", "model", "started", "renderButton", "gutter", "class", "lineMarkerChange", "update", "docChanged", "viewportChanged", "markers", "view", "start", "getStartTime", "chunks", "builder", "RangeSetBuilder", "from", "to", "visibleRanges", "line", "state", "doc", "lineAt", "block", "getChunkAtLine", "number", "blocks", "timestamp", "_tag", "add", "TimestampMarker", "Date", "length", "finish", "ViewPlugin", "fromClass", "_controls", "_cleanup", "_adapter", "_initialized", "DocumentAdapter", "scroller", "scrollDOM", "isAutoScrolling", "hasScrolled", "timeout", "scrollToBottom", "smooth", "style", "scrollBehavior", "classList", "clearTimeout", "setTimeout", "remove", "dispatch", "effects", "EditorView", "scrollIntoView", "y", "document", "createElement", "dom", "appendChild", "onClick", "combine", "addEventListener", "on", "autoScroll", "scrollHeight", "scrollTop", "clientHeight", "sync", "destroy", "theme", "overflowY", "scrollbarWidth", "display", "position", "bottom", "right", "zIndex", "paddingRight", "width", "textAlign", "padding", "GutterMarker", "_line", "_timestamp", "_started", "eq", "other", "toDOM", "el", "className", "textContent", "formatTimestamp", "onclick", "pos", "message", "undefined", "relative", "pad", "n", "String", "padStart", "hours", "minutes", "seconds", "intervalToDuration", "end", "format", "renderMarkdown", "identities", "message", "index", "debug", "sender", "role", "blocks", "find", "block", "_tag", "text", "identity", "did", "identityDid", "name", "profile", "displayName", "contact", "target", "fullName", "email", "filter", "id", "map", "trim", "join", "Transcript", "classNames", "transcript", "object", "space", "model", "attendableId", "ignoreAttention", "themeMode", "useThemeContext", "parentRef", "useTextEditor", "extensions", "createBasicExtensions", "readOnly", "lineWrapping", "search", "createMarkdownExtensions", "createThemeExtensions", "decorateMarkdown", "preview", "started", "Date", "undefined", "renderButton", "createRenderer", "onClick", "IconButton", "icon", "iconOnly", "label", "isNotFalsy", "div", "ref", "className", "mx", "editorWidth", "data-popover-collision-boundary", "TranscriptionContainer", "transcript", "attendableId", "fullyQualifiedId", "space", "getSpace", "members", "useMembers", "key", "map", "member", "identity", "queue", "useQueue", "dxn", "pollInterval", "model", "useQueueModelAdapter", "renderMarkdown", "React", "StackItem", "Content", "classNames", "Transcript"]
7
+ }
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  TRANSCRIPTION_URL
3
- } from "./chunk-OSISJM2F.mjs";
3
+ } from "./chunk-KWOOVS5G.mjs";
4
4
 
5
- // packages/plugins/plugin-transcription/src/transcriber/media-stream-recorder.ts
5
+ // src/transcriber/media-stream-recorder.ts
6
6
  import { MediaRecorder, register } from "extendable-media-recorder";
7
7
  import { WaveFile } from "wavefile";
8
8
  import { synchronized } from "@dxos/async";
@@ -15,16 +15,22 @@ function _ts_decorate(decorators, target, key, desc) {
15
15
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
16
16
  return c > 3 && r && Object.defineProperty(target, key, r), r;
17
17
  }
18
- var __dxlog_file = "/home/runner/work/dxos/dxos/packages/plugins/plugin-transcription/src/transcriber/media-stream-recorder.ts";
18
+ var __dxlog_file = "/__w/dxos/dxos/packages/plugins/plugin-transcription/src/transcriber/media-stream-recorder.ts";
19
19
  var initializingPromise;
20
20
  var initializeExtendableMediaRecorder = async () => {
21
21
  const { connect } = await import("extendable-media-recorder-wav-encoder");
22
22
  await register(await connect());
23
23
  };
24
24
  var MediaStreamRecorder = class {
25
+ _mediaStreamTrack;
26
+ /**
27
+ * Default MediaRecorder implementation do not support wav encoding.
28
+ */
29
+ _config;
30
+ _mediaRecorder = void 0;
31
+ _header = void 0;
32
+ _onChunk;
25
33
  constructor({ mediaStreamTrack, config }) {
26
- this._mediaRecorder = void 0;
27
- this._header = void 0;
28
34
  this._mediaStreamTrack = mediaStreamTrack;
29
35
  this._config = config;
30
36
  }
@@ -118,14 +124,14 @@ MediaStreamRecorder = _ts_decorate([
118
124
  trace.resource()
119
125
  ], MediaStreamRecorder);
120
126
 
121
- // packages/plugins/plugin-transcription/src/transcriber/transcriber.ts
127
+ // src/transcriber/transcriber.ts
122
128
  import { WaveFile as WaveFile2 } from "wavefile";
123
129
  import { DeferredTask, Trigger } from "@dxos/async";
124
130
  import { LifecycleState, Resource } from "@dxos/context";
125
131
  import { log as log2 } from "@dxos/log";
126
132
  import { trace as trace2 } from "@dxos/tracing";
127
133
 
128
- // packages/plugins/plugin-transcription/src/util/array.ts
134
+ // src/util/array.ts
129
135
  var mergeFloat64Arrays = (arrays) => {
130
136
  const newArray = new Float64Array(arrays.reduce((acc, array) => array.length + acc, 0));
131
137
  let offset = 0;
@@ -136,24 +142,27 @@ var mergeFloat64Arrays = (arrays) => {
136
142
  return newArray;
137
143
  };
138
144
 
139
- // packages/plugins/plugin-transcription/src/transcriber/transcriber.ts
145
+ // src/transcriber/transcriber.ts
140
146
  function _ts_decorate2(decorators, target, key, desc) {
141
147
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
142
148
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
143
149
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
144
150
  return c > 3 && r && Object.defineProperty(target, key, r), r;
145
151
  }
146
- var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/plugins/plugin-transcription/src/transcriber/transcriber.ts";
152
+ var __dxlog_file2 = "/__w/dxos/dxos/packages/plugins/plugin-transcription/src/transcriber/transcriber.ts";
147
153
  var Transcriber = class extends Resource {
154
+ _audioChunks = [];
155
+ _lastUsedTimestamp = 0;
156
+ _openTrigger = new Trigger({
157
+ autoReset: true
158
+ });
159
+ _config;
160
+ _recorder;
161
+ _onSegments;
162
+ _recording = false;
163
+ _transcribeTask = void 0;
148
164
  constructor({ config, recorder, onSegments }) {
149
165
  super();
150
- this._audioChunks = [];
151
- this._lastUsedTimestamp = 0;
152
- this._openTrigger = new Trigger({
153
- autoReset: true
154
- });
155
- this._recording = false;
156
- this._transcribeTask = void 0;
157
166
  this._config = config;
158
167
  this._recorder = recorder;
159
168
  this._onSegments = onSegments;
@@ -161,7 +170,7 @@ var Transcriber = class extends Resource {
161
170
  async _open(ctx) {
162
171
  log2.info("opening", void 0, {
163
172
  F: __dxlog_file2,
164
- L: 101,
173
+ L: 102,
165
174
  S: this,
166
175
  C: (f, a) => f(...a)
167
176
  });
@@ -173,7 +182,7 @@ var Transcriber = class extends Resource {
173
182
  async _close() {
174
183
  log2.info("closing", void 0, {
175
184
  F: __dxlog_file2,
176
- L: 109,
185
+ L: 110,
177
186
  S: this,
178
187
  C: (f, a) => f(...a)
179
188
  });
@@ -184,7 +193,7 @@ var Transcriber = class extends Resource {
184
193
  startChunksRecording() {
185
194
  log2.info("starting", void 0, {
186
195
  F: __dxlog_file2,
187
- L: 116,
196
+ L: 117,
188
197
  S: this,
189
198
  C: (f, a) => f(...a)
190
199
  });
@@ -201,7 +210,7 @@ var Transcriber = class extends Resource {
201
210
  this._transcribeTask?.schedule();
202
211
  log2.info("stopped", void 0, {
203
212
  F: __dxlog_file2,
204
- L: 131,
213
+ L: 132,
205
214
  S: this,
206
215
  C: (f, a) => f(...a)
207
216
  });
@@ -211,7 +220,7 @@ var Transcriber = class extends Resource {
211
220
  chunk
212
221
  }, {
213
222
  F: __dxlog_file2,
214
- L: 135,
223
+ L: 136,
215
224
  S: this,
216
225
  C: (f, a) => f(...a)
217
226
  });
@@ -227,7 +236,7 @@ var Transcriber = class extends Resource {
227
236
  chunks: this._audioChunks.length
228
237
  }, {
229
238
  F: __dxlog_file2,
230
- L: 151,
239
+ L: 152,
231
240
  S: this,
232
241
  C: (f, a) => f(...a)
233
242
  });
@@ -279,7 +288,7 @@ var Transcriber = class extends Resource {
279
288
  string: segments.map((segments2) => segments2.text).join(" ")
280
289
  }, {
281
290
  F: __dxlog_file2,
282
- L: 215,
291
+ L: 216,
283
292
  S: this,
284
293
  C: (f, a) => f(...a)
285
294
  });
@@ -301,7 +310,7 @@ var Transcriber = class extends Resource {
301
310
  }
302
311
  this._lastUsedTimestamp = zeroTimestamp + filteredSegments.at(-1).end * 1e3;
303
312
  return filteredSegments.map((segment) => ({
304
- type: "transcription",
313
+ _tag: "transcript",
305
314
  started: new Date(zeroTimestamp + segment.start * 1e3).toISOString(),
306
315
  text: segment.text.trim()
307
316
  }));
@@ -318,7 +327,7 @@ _ts_decorate2([
318
327
  })
319
328
  ], Transcriber.prototype, "_fetchTranscription", null);
320
329
 
321
- // packages/plugins/plugin-transcription/src/transcriber/transcription-manager.ts
330
+ // src/transcriber/transcription-manager.ts
322
331
  import { signal } from "@preact/signals-core";
323
332
  import { synchronized as synchronized2 } from "@dxos/async";
324
333
  import { Resource as Resource2 } from "@dxos/context";
@@ -334,14 +343,16 @@ var RECORD_INTERVAL = 200;
334
343
  var PREFIXED_CHUNKS_AMOUNT = 10;
335
344
  var TRANSCRIBE_AFTER_CHUNKS_AMOUNT = 50;
336
345
  var TranscriptionManager = class extends Resource2 {
346
+ _edgeClient;
347
+ _messageEnricher;
348
+ _audioStreamTrack = void 0;
349
+ _identityDid = void 0;
350
+ _mediaRecorder = void 0;
351
+ _transcriber = void 0;
352
+ _queue = void 0;
353
+ _enabled = signal(false);
337
354
  constructor(options) {
338
355
  super();
339
- this._audioStreamTrack = void 0;
340
- this._identityDid = void 0;
341
- this._mediaRecorder = void 0;
342
- this._transcriber = void 0;
343
- this._queue = void 0;
344
- this._enabled = signal(false);
345
356
  this._edgeClient = options.edgeClient;
346
357
  this._messageEnricher = options.messageEnricher;
347
358
  }
@@ -403,7 +414,7 @@ var TranscriptionManager = class extends Resource2 {
403
414
  created: (/* @__PURE__ */ new Date()).toISOString(),
404
415
  blocks: [
405
416
  {
406
- type: "transcription",
417
+ _tag: "transcript",
407
418
  text: "Started",
408
419
  started: (/* @__PURE__ */ new Date()).toISOString()
409
420
  }
@@ -421,7 +432,7 @@ var TranscriptionManager = class extends Resource2 {
421
432
  created: (/* @__PURE__ */ new Date()).toISOString(),
422
433
  blocks: [
423
434
  {
424
- type: "transcription",
435
+ _tag: "transcript",
425
436
  text: "Stopped",
426
437
  started: (/* @__PURE__ */ new Date()).toISOString()
427
438
  }
@@ -492,4 +503,4 @@ export {
492
503
  Transcriber,
493
504
  TranscriptionManager
494
505
  };
495
- //# sourceMappingURL=chunk-IQ5ZRMHZ.mjs.map
506
+ //# sourceMappingURL=chunk-KJIQQHJB.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/transcriber/media-stream-recorder.ts", "../../../src/transcriber/transcriber.ts", "../../../src/util/array.ts", "../../../src/transcriber/transcription-manager.ts"],
4
+ "sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport { type IBlobEvent, type IMediaRecorder, MediaRecorder, register } from 'extendable-media-recorder';\nimport { WaveFile } from 'wavefile';\n\nimport { synchronized } from '@dxos/async';\nimport { invariant } from '@dxos/invariant';\nimport { log } from '@dxos/log';\nimport { trace } from '@dxos/tracing';\n\nimport { type AudioChunk, type AudioRecorder, type WavConfig } from './audio-recorder';\n\nlet initializingPromise: Promise<void> | undefined;\n\nconst initializeExtendableMediaRecorder = async () => {\n const { connect } = await import('extendable-media-recorder-wav-encoder');\n await register(await connect());\n};\n\nexport type MediaStreamRecorderParams = {\n mediaStreamTrack: MediaStreamTrack;\n config: {\n interval: number;\n };\n};\n\n/**\n * Recorder that uses the MediaContext API and AudioNode API to record audio.\n *\n * It records MediaStream using https://www.npmjs.com/package/extendable-media-recorder.\n */\n@trace.resource()\nexport class MediaStreamRecorder implements AudioRecorder {\n private readonly _mediaStreamTrack: MediaStreamTrack;\n /**\n * Default MediaRecorder implementation do not support wav encoding.\n */\n private readonly _config: MediaStreamRecorderParams['config'];\n private _mediaRecorder?: IMediaRecorder = undefined;\n private _header?: Uint8Array = undefined;\n private _onChunk?: (chunk: AudioChunk) => void;\n\n constructor({ mediaStreamTrack, config }: MediaStreamRecorderParams) {\n this._mediaStreamTrack = mediaStreamTrack;\n this._config = config;\n }\n\n get wavConfig(): WavConfig {\n const settings = this._mediaStreamTrack.getSettings();\n return {\n channels: settings.channelCount ?? 1,\n sampleRate: settings.sampleRate ?? 16000,\n bitDepthCode: settings.sampleSize ? String(settings.sampleSize) : '16',\n };\n }\n\n get mediaStreamTrack() {\n return this._mediaStreamTrack;\n }\n\n setOnChunk(onChunk: (chunk: AudioChunk) => void): void {\n this._onChunk = onChunk;\n }\n\n async start(): Promise<void> {\n await (initializingPromise ??= initializeExtendableMediaRecorder()).catch((err) =>\n log.info('initializeExtendableMediaRecorder', { err }),\n );\n\n if (!this._mediaRecorder) {\n const stream = new MediaStream([this._mediaStreamTrack]);\n this._mediaRecorder = new MediaRecorder(stream, { mimeType: 'audio/wav' });\n }\n\n if (this._mediaRecorder.state === 'recording') {\n return;\n }\n invariant(this._onChunk, 'MediaStreamRecorder: onChunk is not set');\n this._mediaRecorder.ondataavailable = (event) => this._ondataavailable(event);\n this._mediaRecorder.start(this._config.interval);\n }\n\n async stop(): Promise<void> {\n if (this._mediaRecorder?.state !== 'recording') {\n return;\n }\n this._mediaRecorder.stop();\n }\n\n @synchronized\n private async _ondataavailable(event: IBlobEvent): Promise<void> {\n const blob = event.data;\n const uint8Array = new Uint8Array(await blob.arrayBuffer());\n\n // First chunk from the MediaRecorder has a header.\n const isHeader =\n uint8Array[0] === 0x52 && // R\n uint8Array[1] === 0x49 && // I\n uint8Array[2] === 0x46 && // F\n uint8Array[3] === 0x46; // F\n let wav: WaveFile;\n\n if (isHeader) {\n wav = new WaveFile(uint8Array);\n this._header = uint8Array.slice(0, 44);\n } else if (this._header) {\n wav = new WaveFile(new Uint8Array([...this._header, ...uint8Array]));\n } else {\n log.warn('MediaStreamRecorder: no header');\n return;\n }\n\n this._onChunk!({\n timestamp: Date.now(),\n data: wav.getSamples(),\n });\n }\n}\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { WaveFile } from 'wavefile';\n\nimport { DeferredTask, Trigger } from '@dxos/async';\nimport { type Context, LifecycleState, Resource } from '@dxos/context';\nimport { log } from '@dxos/log';\nimport { type DataType } from '@dxos/schema';\nimport { trace } from '@dxos/tracing';\n\nimport { TRANSCRIPTION_URL } from '../types';\nimport { mergeFloat64Arrays } from '../util';\n\nimport { type AudioChunk, type AudioRecorder } from './audio-recorder';\n\ntype WhisperWord = {\n word: string;\n\n /**\n * Time in seconds from the start of the audio.\n */\n start: number;\n\n /**\n * Time in seconds from the start of the audio.\n */\n end: number;\n};\n\ntype WhisperSegment = {\n text: string;\n\n /**\n * Time in seconds from the start of the audio.\n */\n start: number;\n\n /**\n * Time in seconds from the start of the audio.\n */\n end: number;\n\n /**\n * Probability of no speech in the segment.\n */\n no_speech_prob: number;\n\n words: WhisperWord[];\n};\n\nexport type TranscribeConfig = {\n /**\n * Number of chunks to transcribe automatically after.\n */\n transcribeAfterChunksAmount: number;\n\n /**\n * Number of chunks to save before the user starts speaking.\n * This is needed to catch the beginning of the user's speech.\n */\n prefixBufferChunksAmount: number;\n};\n\nexport type TranscriberParams = {\n config: TranscribeConfig;\n recorder: AudioRecorder;\n /**\n * Callback to handle the transcribed segments, after all segment transformers are applied.\n * @param segments - The transcribed segments.\n */\n onSegments: (segments: DataType.MessageBlock.Transcript[]) => Promise<void>;\n};\n\n/**\n * Handles transcription of audio chunks.\n * If user is not speaking, the last `minChunksAmount` chunks are saved and transcribed.\n * If user is speaking, the chunks are added to the buffer until the user is done talking.\n */\nexport class Transcriber extends Resource {\n private _audioChunks: AudioChunk[] = [];\n private _lastUsedTimestamp = 0;\n\n private readonly _openTrigger = new Trigger({ autoReset: true });\n\n private readonly _config: TranscribeConfig;\n private readonly _recorder: AudioRecorder;\n private readonly _onSegments: TranscriberParams['onSegments'];\n\n private _recording = false;\n private _transcribeTask?: DeferredTask = undefined;\n\n constructor({ config, recorder, onSegments }: TranscriberParams) {\n super();\n this._config = config;\n this._recorder = recorder;\n this._onSegments = onSegments;\n }\n\n protected override async _open(ctx: Context): Promise<void> {\n log.info('opening');\n this._recorder.setOnChunk((chunk) => this._saveAudioChunk(chunk));\n await this._recorder.start();\n this._transcribeTask = new DeferredTask(ctx, async () => this._transcribe());\n this._openTrigger.wake();\n }\n\n protected override async _close(): Promise<void> {\n log.info('closing');\n this._recording = false;\n this._transcribeTask = undefined;\n await this._recorder.stop();\n }\n\n startChunksRecording(): void {\n log.info('starting');\n if (this._lifecycleState !== LifecycleState.OPEN) {\n return;\n }\n\n this._recording = true;\n }\n\n stopChunksRecording(): void {\n if (this._lifecycleState !== LifecycleState.OPEN || !this._recording) {\n return;\n }\n\n this._recording = false;\n this._transcribeTask?.schedule();\n log.info('stopped');\n }\n\n private _saveAudioChunk(chunk: AudioChunk): void {\n log('saving audio chunk', { chunk });\n this._audioChunks.push(chunk);\n\n // Clean the buffer if the user is not speaking and the transcription task is not scheduled.\n if (\n !this._recording &&\n (!this._transcribeTask || !this._transcribeTask.scheduled) &&\n this._audioChunks.length >= this._config.prefixBufferChunksAmount\n ) {\n this._audioChunks = this._dropOldChunks();\n } else if (this._audioChunks.length >= this._config.transcribeAfterChunksAmount && this._recording) {\n this._transcribeTask?.schedule();\n }\n }\n\n private async _transcribe(): Promise<void> {\n log('transcribing', { chunks: this._audioChunks.length });\n const chunks = this._audioChunks;\n this._audioChunks = this._dropOldChunks();\n if (chunks.length === 0) {\n return;\n }\n\n const audio = await this._mergeAudioChunks(chunks);\n const segments = await this._fetchTranscription(audio);\n if (!Array.isArray(segments) || segments.length === 0) {\n return;\n }\n\n const alignedSegments = this._alignSegments(segments, chunks);\n if (alignedSegments.length > 0) {\n await this._onSegments(alignedSegments);\n }\n }\n\n private _dropOldChunks(): AudioChunk[] {\n return this._config.prefixBufferChunksAmount > 0\n ? this._audioChunks.slice(-this._config.prefixBufferChunksAmount)\n : [];\n }\n\n @trace.span({ showInBrowserTimeline: true })\n private async _mergeAudioChunks(chunks: AudioChunk[]): Promise<string> {\n const file = new WaveFile();\n const wavConfig = this._recorder.wavConfig;\n\n file.fromScratch(\n wavConfig.channels,\n wavConfig.sampleRate,\n wavConfig.bitDepthCode,\n mergeFloat64Arrays(chunks.map(({ data }) => data)),\n );\n\n return file.toBase64();\n }\n\n @trace.span({ showInBrowserTimeline: true })\n private async _fetchTranscription(audio: string): Promise<WhisperSegment[]> {\n if (audio.length === 0) {\n this._audioChunks = [];\n throw new Error('No audio to send for transcribing');\n }\n\n const response = await fetch(`${TRANSCRIPTION_URL}/transcribe`, {\n method: 'POST',\n body: JSON.stringify({ audio }),\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok) {\n this._audioChunks = [];\n throw new Error(`Transcription failed: ${response.statusText}`);\n }\n\n const { segments } = (await response.json()) as {\n segments: WhisperSegment[];\n };\n\n log.info('transcription response', {\n segments: segments.length,\n string: segments.map((segments) => segments.text).join(' '),\n });\n\n return segments;\n }\n\n private _alignSegments(segments: WhisperSegment[], originalChunks: AudioChunk[]): DataType.MessageBlock.Transcript[] {\n // Absolute zero for all relative timestamps in the segments.\n const zeroTimestamp = originalChunks.at(0)!.timestamp;\n\n const filteredSegments = segments\n // Use segments that end after the last used timestamp.\n // Segments could overlap, so we need to filter words that starts after the last used timestamp.\n .filter((segment) => zeroTimestamp + segment.end * 1_000 >= this._lastUsedTimestamp)\n // Use words that starts after the last used timestamp.\n .map((segment) => {\n const words = segment.words.filter((word) => zeroTimestamp + word.start * 1_000 >= this._lastUsedTimestamp);\n return {\n ...segment,\n words,\n text: words.map((word) => word.word).join(''),\n start: words.at(0)?.start ?? segment.end,\n };\n })\n .filter((segment) => segment.words.length > 0);\n\n if (filteredSegments.length === 0) {\n return [];\n }\n\n // Update last timestamp.\n this._lastUsedTimestamp = zeroTimestamp + filteredSegments.at(-1)!.end * 1_000;\n\n // Add absolute timestamp to each segment.\n return filteredSegments.map((segment) => ({\n _tag: 'transcript',\n started: new Date(zeroTimestamp + segment.start * 1_000).toISOString(),\n text: segment.text.trim(),\n }));\n }\n}\n", "//\n// Copyright 2025 DXOS.org\n//\n\nexport const mergeFloat64Arrays = (arrays: Float64Array[]) => {\n const newArray = new Float64Array(arrays.reduce((acc, array) => array.length + acc, 0));\n let offset = 0;\n for (const array of arrays) {\n newArray.set(array, offset);\n offset += array.length;\n }\n\n return newArray;\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { signal } from '@preact/signals-core';\n\nimport { synchronized } from '@dxos/async';\nimport { Resource } from '@dxos/context';\nimport { Obj } from '@dxos/echo';\nimport { type Queue } from '@dxos/echo-db';\nimport { type EdgeHttpClient } from '@dxos/react-edge-client';\nimport { DataType } from '@dxos/schema';\n\nimport { MediaStreamRecorder } from './media-stream-recorder';\nimport { Transcriber } from './transcriber';\n\n/**\n * Length of the chunk in ms.\n */\nconst RECORD_INTERVAL = 200;\n\n/**\n * Number of chunks to save before the user starts speaking.\n */\nconst PREFIXED_CHUNKS_AMOUNT = 10;\n\n/**\n * Number of chunks to transcribe automatically after.\n * Combined should be mess than 25MB or whisper would fail.\n */\nconst TRANSCRIBE_AFTER_CHUNKS_AMOUNT = 50;\n\nexport type TranscriptMessageEnricher = (message: DataType.Message) => Promise<DataType.Message>;\n\nexport type TranscriptionManagerOptions = {\n edgeClient: EdgeHttpClient;\n\n /**\n * Enrich the message before it is written to the transcription queue.\n */\n messageEnricher?: TranscriptMessageEnricher;\n};\n\n/**\n * Manages transcription state for a meeting.\n */\nexport class TranscriptionManager extends Resource {\n private readonly _edgeClient: EdgeHttpClient;\n private readonly _messageEnricher?: TranscriptMessageEnricher;\n private _audioStreamTrack?: MediaStreamTrack = undefined;\n private _identityDid?: string = undefined;\n private _mediaRecorder?: MediaStreamRecorder = undefined;\n private _transcriber?: Transcriber = undefined;\n private _queue?: Queue<DataType.Message> = undefined;\n private _enabled = signal(false);\n\n constructor(options: TranscriptionManagerOptions) {\n super();\n this._edgeClient = options.edgeClient;\n this._messageEnricher = options.messageEnricher;\n }\n\n /** @reactive */\n get enabled() {\n return this._enabled.value;\n }\n\n setQueue(queue: Queue<DataType.Message>): this {\n this._queue = queue;\n return this;\n }\n\n setIdentityDid(did: string): this {\n if (this._identityDid !== did) {\n this._identityDid = did;\n }\n return this;\n }\n\n setRecording(recording?: boolean): this {\n if (!this.isOpen || !this._enabled.value) {\n return this;\n }\n\n if (recording) {\n this._transcriber?.startChunksRecording();\n } else {\n this._transcriber?.stopChunksRecording();\n }\n return this;\n }\n\n /**\n * Enable or disable transcription.\n * @param enabled - Whether to enable transcription.\n */\n @synchronized\n async setEnabled(enabled?: boolean): Promise<void> {\n if (this._enabled.value === enabled) {\n return;\n }\n\n this._enabled.value = enabled ?? false;\n // TODO(burdon): Why is toggle called here?\n this.isOpen && (await this._toggleTranscriber());\n }\n\n @synchronized\n async setAudioTrack(track?: MediaStreamTrack): Promise<void> {\n if (this._audioStreamTrack === track) {\n return;\n }\n\n this._audioStreamTrack = track;\n this.isOpen && (await this._toggleTranscriber());\n }\n\n protected override async _open(): Promise<void> {\n await this._toggleTranscriber();\n }\n\n protected override async _close(): Promise<void> {\n void this._transcriber?.close();\n }\n\n // TODO(burdon): Change this to setEnables (explicit), not toggle.\n private async _toggleTranscriber(): Promise<void> {\n await this._maybeReinitTranscriber();\n\n // Open or close transcriber if transcription is enabled or disabled.\n if (this._enabled.value) {\n await this._transcriber?.open();\n // TODO(burdon): Started and stopped blocks appear twice.\n const block = Obj.make(DataType.Message, {\n created: new Date().toISOString(),\n blocks: [{ _tag: 'transcript', text: 'Started', started: new Date().toISOString() }],\n sender: { role: 'assistant' },\n });\n await this._queue?.append([block]);\n } else {\n await this._transcriber?.close();\n const block = Obj.make(DataType.Message, {\n created: new Date().toISOString(),\n blocks: [{ _tag: 'transcript', text: 'Stopped', started: new Date().toISOString() }],\n sender: { role: 'assistant' },\n });\n await this._queue?.append([block]);\n }\n }\n\n private async _maybeReinitTranscriber(): Promise<void> {\n if (!this._audioStreamTrack || !this._enabled.value) {\n return;\n }\n\n // Reinitialize transcriber if queue or media stream track has changed.\n let needReinit = false;\n if (this._audioStreamTrack !== this._mediaRecorder?.mediaStreamTrack) {\n this._mediaRecorder = new MediaStreamRecorder({\n mediaStreamTrack: this._audioStreamTrack,\n config: { interval: RECORD_INTERVAL },\n });\n needReinit = true;\n }\n if (needReinit) {\n await this._transcriber?.close();\n this._transcriber = new Transcriber({\n config: {\n transcribeAfterChunksAmount: TRANSCRIBE_AFTER_CHUNKS_AMOUNT,\n prefixBufferChunksAmount: PREFIXED_CHUNKS_AMOUNT,\n },\n recorder: this._mediaRecorder,\n onSegments: (segments) => this._onSegments(segments),\n });\n }\n }\n\n private async _onSegments(segments: DataType.MessageBlock.Transcript[]): Promise<void> {\n if (!this.isOpen || !this._queue) {\n return;\n }\n\n let block = Obj.make(DataType.Message, {\n created: new Date().toISOString(),\n blocks: segments,\n sender: { identityDid: this._identityDid },\n });\n\n if (this._messageEnricher) {\n block = await this._messageEnricher(block);\n }\n\n await this._queue.append([block]);\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["MediaRecorder", "register", "WaveFile", "synchronized", "invariant", "log", "trace", "initializingPromise", "initializeExtendableMediaRecorder", "connect", "MediaStreamRecorder", "_mediaStreamTrack", "_config", "_mediaRecorder", "undefined", "_header", "_onChunk", "mediaStreamTrack", "config", "wavConfig", "settings", "getSettings", "channels", "channelCount", "sampleRate", "bitDepthCode", "sampleSize", "String", "setOnChunk", "onChunk", "start", "catch", "err", "info", "stream", "MediaStream", "mimeType", "state", "ondataavailable", "event", "_ondataavailable", "interval", "stop", "blob", "data", "uint8Array", "Uint8Array", "arrayBuffer", "isHeader", "wav", "slice", "warn", "timestamp", "Date", "now", "getSamples", "resource", "WaveFile", "DeferredTask", "Trigger", "LifecycleState", "Resource", "log", "trace", "mergeFloat64Arrays", "arrays", "newArray", "Float64Array", "reduce", "acc", "array", "length", "offset", "set", "Transcriber", "Resource", "_audioChunks", "_lastUsedTimestamp", "_openTrigger", "Trigger", "autoReset", "_config", "_recorder", "_onSegments", "_recording", "_transcribeTask", "undefined", "config", "recorder", "onSegments", "_open", "ctx", "log", "info", "setOnChunk", "chunk", "_saveAudioChunk", "start", "DeferredTask", "_transcribe", "wake", "_close", "stop", "startChunksRecording", "_lifecycleState", "LifecycleState", "OPEN", "stopChunksRecording", "schedule", "push", "scheduled", "length", "prefixBufferChunksAmount", "_dropOldChunks", "transcribeAfterChunksAmount", "chunks", "audio", "_mergeAudioChunks", "segments", "_fetchTranscription", "Array", "isArray", "alignedSegments", "_alignSegments", "slice", "file", "WaveFile", "wavConfig", "fromScratch", "channels", "sampleRate", "bitDepthCode", "mergeFloat64Arrays", "map", "data", "toBase64", "Error", "response", "fetch", "TRANSCRIPTION_URL", "method", "body", "JSON", "stringify", "headers", "ok", "statusText", "json", "string", "text", "join", "originalChunks", "zeroTimestamp", "at", "timestamp", "filteredSegments", "filter", "segment", "end", "words", "word", "_tag", "started", "Date", "toISOString", "trim", "span", "showInBrowserTimeline", "signal", "synchronized", "Resource", "Obj", "DataType", "RECORD_INTERVAL", "PREFIXED_CHUNKS_AMOUNT", "TRANSCRIBE_AFTER_CHUNKS_AMOUNT", "TranscriptionManager", "Resource", "_edgeClient", "_messageEnricher", "_audioStreamTrack", "undefined", "_identityDid", "_mediaRecorder", "_transcriber", "_queue", "_enabled", "signal", "options", "edgeClient", "messageEnricher", "enabled", "value", "setQueue", "queue", "setIdentityDid", "did", "setRecording", "recording", "isOpen", "startChunksRecording", "stopChunksRecording", "setEnabled", "_toggleTranscriber", "setAudioTrack", "track", "_open", "_close", "close", "_maybeReinitTranscriber", "open", "block", "Obj", "make", "DataType", "Message", "created", "Date", "toISOString", "blocks", "_tag", "text", "started", "sender", "role", "append", "needReinit", "mediaStreamTrack", "MediaStreamRecorder", "config", "interval", "Transcriber", "transcribeAfterChunksAmount", "prefixBufferChunksAmount", "recorder", "onSegments", "segments", "_onSegments", "identityDid"]
7
+ }
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  TRANSCRIPTION_PLUGIN
3
- } from "./chunk-GOF7MJNV.mjs";
3
+ } from "./chunk-5WH45KBY.mjs";
4
4
 
5
- // packages/plugins/plugin-transcription/src/types/schema.ts
5
+ // src/types/schema.ts
6
6
  import { Schema } from "effect";
7
7
  import { Queue } from "@dxos/client/echo";
8
8
  import { Type } from "@dxos/echo";
@@ -26,7 +26,7 @@ var TranscriptHeader = Schema.Struct({
26
26
  started: Schema.optional(Schema.String)
27
27
  });
28
28
 
29
- // packages/plugins/plugin-transcription/src/types/types.ts
29
+ // src/types/types.ts
30
30
  import { Schema as Schema2 } from "effect";
31
31
  import { SpaceId } from "@dxos/react-client/echo";
32
32
  var TRANSCRIPTION_URL = "https://calls-service.dxos.workers.dev";
@@ -52,4 +52,4 @@ export {
52
52
  TRANSCRIPTION_URL,
53
53
  TranscriptionAction
54
54
  };
55
- //# sourceMappingURL=chunk-OSISJM2F.mjs.map
55
+ //# sourceMappingURL=chunk-KWOOVS5G.mjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/types/schema.ts", "../../../src/types/types.ts"],
4
- "sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport { Schema } from 'effect';\n\nimport { Queue } from '@dxos/client/echo';\nimport { Type } from '@dxos/echo';\nimport { TypedObject } from '@dxos/echo-schema';\n\n/**\n * Root transcript object created when the user starts a transcription.\n */\nexport const TranscriptSchema = Schema.Struct({\n // TODO(wittjosiah): Remove?\n // TODO(burdon): Use Date or string?\n started: Schema.optional(Schema.String),\n ended: Schema.optional(Schema.String),\n\n /**\n * Queue containing TranscriptBlock objects.\n */\n queue: Type.Ref(Queue),\n});\n\nexport class TranscriptType extends TypedObject({\n typename: 'dxos.org/type/Transcript',\n version: '0.1.0',\n})(TranscriptSchema.fields) {}\n\n// TODO(burdon): Do these need to be kept in sync with EDGE?\n\n/**\n * First message in queue.\n * Contains metadata for the recording and transcript.\n */\nconst TranscriptHeader = Schema.Struct({\n started: Schema.optional(Schema.String),\n});\n\nexport type TranscriptHeader = Schema.Schema.Type<typeof TranscriptHeader>;\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { Schema } from 'effect';\n\nimport { SpaceId } from '@dxos/react-client/echo';\n\nimport { TranscriptType } from './schema';\nimport { TRANSCRIPTION_PLUGIN } from '../meta';\n\n// TODO(burdon): Move to separate proto.\n\n/**\n * Endpoint to the calls service.\n */\n// TODO(burdon): Reconfigure/move.\nexport const TRANSCRIPTION_URL = 'https://calls-service.dxos.workers.dev';\n\nexport namespace TranscriptionAction {\n const TRANSCRIPTION_ACTION = `${TRANSCRIPTION_PLUGIN}/action`;\n\n export class Create extends Schema.TaggedClass<Create>()(`${TRANSCRIPTION_ACTION}/create`, {\n input: Schema.Struct({\n name: Schema.optional(Schema.String),\n spaceId: SpaceId,\n }),\n output: Schema.Struct({\n object: TranscriptType,\n }),\n }) {}\n}\n"],
5
- "mappings": ";;;;;AAIA,SAASA,cAAc;AAEvB,SAASC,aAAa;AACtB,SAASC,YAAY;AACrB,SAASC,mBAAmB;AAKrB,IAAMC,mBAAmBC,OAAOC,OAAO;;;EAG5CC,SAASF,OAAOG,SAASH,OAAOI,MAAM;EACtCC,OAAOL,OAAOG,SAASH,OAAOI,MAAM;;;;EAKpCE,OAAOC,KAAKC,IAAIC,KAAAA;AAClB,CAAA;AAEO,IAAMC,iBAAN,cAA6BC,YAAY;EAC9CC,UAAU;EACVC,SAAS;AACX,CAAA,EAAGd,iBAAiBe,MAAM,EAAA;AAAG;AAQ7B,IAAMC,mBAAmBf,OAAOC,OAAO;EACrCC,SAASF,OAAOG,SAASH,OAAOI,MAAM;AACxC,CAAA;;;AClCA,SAASY,UAAAA,eAAc;AAEvB,SAASC,eAAe;AAWjB,IAAMC,oBAAoB;UAEhBC,sBAAAA;AACf,QAAMC,uBAAuB,GAAGC,oBAAAA;EAEzB,MAAMC,eAAeC,QAAOC,YAAW,EAAW,GAAGJ,oBAAAA,WAA+B;IACzFK,OAAOF,QAAOG,OAAO;MACnBC,MAAMJ,QAAOK,SAASL,QAAOM,MAAM;MACnCC,SAASC;IACX,CAAA;IACAC,QAAQT,QAAOG,OAAO;MACpBO,QAAQC;IACV,CAAA;EACF,CAAA,EAAA;EAAI;uBARSZ,SAAAA;AASf,GAZiBH,wBAAAA,sBAAAA,CAAAA,EAAAA;;",
4
+ "sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport { Schema } from 'effect';\n\nimport { Queue } from '@dxos/client/echo';\nimport { Type } from '@dxos/echo';\nimport { TypedObject } from '@dxos/echo-schema';\n\n/**\n * Root transcript object created when the user starts a transcription.\n */\nexport const TranscriptSchema = Schema.Struct({\n // TODO(wittjosiah): Remove?\n // TODO(burdon): Use Date or string?\n started: Schema.optional(Schema.String),\n ended: Schema.optional(Schema.String),\n\n /**\n * Queue containing TranscriptBlock objects.\n */\n queue: Type.Ref(Queue),\n});\n\nexport class TranscriptType extends TypedObject({\n typename: 'dxos.org/type/Transcript',\n version: '0.1.0',\n})(TranscriptSchema.fields) {}\n\n// TODO(burdon): Do these need to be kept in sync with EDGE?\n\n/**\n * First message in queue.\n * Contains metadata for the recording and transcript.\n */\nconst TranscriptHeader = Schema.Struct({\n started: Schema.optional(Schema.String),\n});\n\nexport type TranscriptHeader = Schema.Schema.Type<typeof TranscriptHeader>;\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { Schema } from 'effect';\n\nimport { SpaceId } from '@dxos/react-client/echo';\n\nimport { TRANSCRIPTION_PLUGIN } from '../meta';\n\nimport { TranscriptType } from './schema';\n\n// TODO(burdon): Move to separate proto.\n\n/**\n * Endpoint to the calls service.\n */\n// TODO(burdon): Reconfigure/move.\nexport const TRANSCRIPTION_URL = 'https://calls-service.dxos.workers.dev';\n\nexport namespace TranscriptionAction {\n const TRANSCRIPTION_ACTION = `${TRANSCRIPTION_PLUGIN}/action`;\n\n export class Create extends Schema.TaggedClass<Create>()(`${TRANSCRIPTION_ACTION}/create`, {\n input: Schema.Struct({\n name: Schema.optional(Schema.String),\n spaceId: SpaceId,\n }),\n output: Schema.Struct({\n object: TranscriptType,\n }),\n }) {}\n}\n"],
5
+ "mappings": ";;;;;AAIA,SAASA,cAAc;AAEvB,SAASC,aAAa;AACtB,SAASC,YAAY;AACrB,SAASC,mBAAmB;AAKrB,IAAMC,mBAAmBC,OAAOC,OAAO;;;EAG5CC,SAASF,OAAOG,SAASH,OAAOI,MAAM;EACtCC,OAAOL,OAAOG,SAASH,OAAOI,MAAM;;;;EAKpCE,OAAOC,KAAKC,IAAIC,KAAAA;AAClB,CAAA;AAEO,IAAMC,iBAAN,cAA6BC,YAAY;EAC9CC,UAAU;EACVC,SAAS;AACX,CAAA,EAAGd,iBAAiBe,MAAM,EAAA;AAAG;AAQ7B,IAAMC,mBAAmBf,OAAOC,OAAO;EACrCC,SAASF,OAAOG,SAASH,OAAOI,MAAM;AACxC,CAAA;;;AClCA,SAASY,UAAAA,eAAc;AAEvB,SAASC,eAAe;AAYjB,IAAMC,oBAAoB;UAEhBC,sBAAAA;AACf,QAAMC,uBAAuB,GAAGC,oBAAAA;EAEzB,MAAMC,eAAeC,QAAOC,YAAW,EAAW,GAAGJ,oBAAAA,WAA+B;IACzFK,OAAOF,QAAOG,OAAO;MACnBC,MAAMJ,QAAOK,SAASL,QAAOM,MAAM;MACnCC,SAASC;IACX,CAAA;IACAC,QAAQT,QAAOG,OAAO;MACpBO,QAAQC;IACV,CAAA;EACF,CAAA,EAAA;EAAI;uBARSZ,SAAAA;AASf,GAZiBH,wBAAAA,sBAAAA,CAAAA,EAAAA;;",
6
6
  "names": ["Schema", "Queue", "Type", "TypedObject", "TranscriptSchema", "Schema", "Struct", "started", "optional", "String", "ended", "queue", "Type", "Ref", "Queue", "TranscriptType", "TypedObject", "typename", "version", "fields", "TranscriptHeader", "Schema", "SpaceId", "TRANSCRIPTION_URL", "TranscriptionAction", "TRANSCRIPTION_ACTION", "TRANSCRIPTION_PLUGIN", "Create", "Schema", "TaggedClass", "input", "Struct", "name", "optional", "String", "spaceId", "SpaceId", "output", "object", "TranscriptType"]
7
7
  }
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  TRANSCRIPTION_PLUGIN
3
- } from "./chunk-GOF7MJNV.mjs";
3
+ } from "./chunk-5WH45KBY.mjs";
4
4
 
5
- // packages/plugins/plugin-transcription/src/capabilities/capabilities.ts
5
+ // src/capabilities/capabilities.ts
6
6
  import { defineCapability } from "@dxos/app-framework";
7
7
  (function(TranscriptionCapabilities2) {
8
8
  TranscriptionCapabilities2.Transcriber = defineCapability(`${TRANSCRIPTION_PLUGIN}/capability/transcriber`);
@@ -13,4 +13,4 @@ var TranscriptionCapabilities;
13
13
  export {
14
14
  TranscriptionCapabilities
15
15
  };
16
- //# sourceMappingURL=chunk-W2KNYJD6.mjs.map
16
+ //# sourceMappingURL=chunk-SREIAQSP.mjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/capabilities/capabilities.ts"],
4
- "sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport { defineCapability } from '@dxos/app-framework';\n\nimport { TRANSCRIPTION_PLUGIN } from '../meta';\nimport {\n type TranscriberParams,\n type Transcriber,\n type TranscriptionManager,\n type TranscriptMessageEnricher,\n type MediaStreamRecorderParams,\n} from '../transcriber';\n\nexport namespace TranscriptionCapabilities {\n export type GetTranscriberProps = {\n audioStreamTrack: MediaStreamTrack;\n onSegments: TranscriberParams['onSegments'];\n transcriberConfig?: Partial<TranscriberParams['config']>;\n recorderConfig?: Partial<MediaStreamRecorderParams['config']>;\n };\n export type GetTranscriber = (props: GetTranscriberProps) => Transcriber;\n export const Transcriber = defineCapability<GetTranscriber>(`${TRANSCRIPTION_PLUGIN}/capability/transcriber`);\n\n export type GetTranscriptionManagerProps = {\n messageEnricher?: TranscriptMessageEnricher;\n };\n export type GetTranscriptionManager = (props: GetTranscriptionManagerProps) => TranscriptionManager;\n export const TranscriptionManager = defineCapability<GetTranscriptionManager>(\n `${TRANSCRIPTION_PLUGIN}/capability/transcription-manager`,\n );\n}\n"],
4
+ "sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport { defineCapability } from '@dxos/app-framework';\n\nimport { TRANSCRIPTION_PLUGIN } from '../meta';\nimport {\n type MediaStreamRecorderParams,\n type Transcriber,\n type TranscriberParams,\n type TranscriptMessageEnricher,\n type TranscriptionManager,\n} from '../transcriber';\n\nexport namespace TranscriptionCapabilities {\n export type GetTranscriberProps = {\n audioStreamTrack: MediaStreamTrack;\n recorderConfig?: Partial<MediaStreamRecorderParams['config']>;\n transcriberConfig?: Partial<TranscriberParams['config']>;\n onSegments: TranscriberParams['onSegments'];\n };\n export type GetTranscriber = (props: GetTranscriberProps) => Transcriber;\n export const Transcriber = defineCapability<GetTranscriber>(`${TRANSCRIPTION_PLUGIN}/capability/transcriber`);\n\n export type GetTranscriptionManagerProps = {\n messageEnricher?: TranscriptMessageEnricher;\n };\n export type GetTranscriptionManager = (props: GetTranscriptionManagerProps) => TranscriptionManager;\n export const TranscriptionManager = defineCapability<GetTranscriptionManager>(\n `${TRANSCRIPTION_PLUGIN}/capability/transcription-manager`,\n );\n}\n"],
5
5
  "mappings": ";;;;;AAIA,SAASA,wBAAwB;UAWhBC,4BAAAA;6BAQFC,cAAcC,iBAAiC,GAAGC,oBAAAA,yBAA6C;6BAM/FC,uBAAuBF,iBAClC,GAAGC,oBAAAA,mCAAuD;AAE9D,GAjBiBH,8BAAAA,4BAAAA,CAAAA,EAAAA;;",
6
6
  "names": ["defineCapability", "TranscriptionCapabilities", "Transcriber", "defineCapability", "TRANSCRIPTION_PLUGIN", "TranscriptionManager"]
7
7
  }
@@ -1,8 +1,8 @@
1
- // packages/plugins/plugin-transcription/src/components/index.ts
1
+ // src/components/index.ts
2
2
  import { lazy } from "react";
3
- var TranscriptContainer = lazy(() => import("./TranscriptContainer-H3AZQ4CQ.mjs"));
3
+ var TranscriptContainer = lazy(() => import("./TranscriptContainer-FH7VAWYA.mjs"));
4
4
 
5
5
  export {
6
6
  TranscriptContainer
7
7
  };
8
- //# sourceMappingURL=chunk-UDCCT32F.mjs.map
8
+ //# sourceMappingURL=chunk-UKUSJTQW.mjs.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  TranscriptContainer
3
- } from "./chunk-UDCCT32F.mjs";
3
+ } from "./chunk-UKUSJTQW.mjs";
4
4
  import {
5
5
  IntentResolver,
6
6
  ReactSurface,
@@ -13,35 +13,35 @@ import {
13
13
  useQueueModelAdapter,
14
14
  useTranscriber,
15
15
  useVoiceInput
16
- } from "./chunk-53AXUEIQ.mjs";
16
+ } from "./chunk-BJWYA2BU.mjs";
17
17
  import {
18
18
  MediaStreamRecorder,
19
19
  Transcriber,
20
20
  TranscriptionManager
21
- } from "./chunk-IQ5ZRMHZ.mjs";
21
+ } from "./chunk-KJIQQHJB.mjs";
22
22
  import {
23
23
  TranscriptType
24
- } from "./chunk-OSISJM2F.mjs";
24
+ } from "./chunk-KWOOVS5G.mjs";
25
25
  import {
26
26
  TranscriptionCapabilities
27
- } from "./chunk-W2KNYJD6.mjs";
27
+ } from "./chunk-SREIAQSP.mjs";
28
28
  import {
29
29
  TRANSCRIPTION_PLUGIN,
30
30
  meta
31
- } from "./chunk-GOF7MJNV.mjs";
31
+ } from "./chunk-5WH45KBY.mjs";
32
32
 
33
- // packages/plugins/plugin-transcription/src/TranscriptionPlugin.tsx
33
+ // src/TranscriptionPlugin.tsx
34
34
  import { Capabilities, Events, contributes, defineModule, definePlugin } from "@dxos/app-framework";
35
35
  import { Obj } from "@dxos/echo";
36
36
  import { ClientCapabilities, ClientEvents } from "@dxos/plugin-client";
37
37
  import { getSpace } from "@dxos/react-client/echo";
38
38
  import { DataType } from "@dxos/schema";
39
39
 
40
- // packages/plugins/plugin-transcription/src/translations.ts
41
- var translations_default = [
40
+ // src/translations.ts
41
+ var translations = [
42
42
  {
43
43
  "en-US": {
44
- [TRANSCRIPTION_PLUGIN]: {
44
+ [meta.id]: {
45
45
  "plugin name": "Transcription",
46
46
  "transcript companion label": "Transcript",
47
47
  "delete button": "Delete",
@@ -53,12 +53,12 @@ var translations_default = [
53
53
  }
54
54
  ];
55
55
 
56
- // packages/plugins/plugin-transcription/src/TranscriptionPlugin.tsx
56
+ // src/TranscriptionPlugin.tsx
57
57
  var TranscriptionPlugin = () => definePlugin(meta, [
58
58
  defineModule({
59
59
  id: `${meta.id}/module/translations`,
60
60
  activatesOn: Events.SetupTranslations,
61
- activate: () => contributes(Capabilities.Translations, translations_default)
61
+ activate: () => contributes(Capabilities.Translations, translations)
62
62
  }),
63
63
  defineModule({
64
64
  id: `${meta.id}/module/metadata`,