@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
@@ -1,37 +1,153 @@
1
1
  import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
2
2
  import {
3
3
  TranscriptionCapabilities
4
- } from "./chunk-MFJPEIVB.mjs";
4
+ } from "./chunk-TM2ASOZA.mjs";
5
5
 
6
- // packages/plugins/plugin-transcription/src/components/TranscriptContainer.tsx
6
+ // src/components/TranscriptContainer.tsx
7
7
  import { useSignals as _useSignals2 } from "@preact-signals/safe-react/tracking";
8
8
  import React2 from "react";
9
9
  import { fullyQualifiedId, getSpace } from "@dxos/client/echo";
10
10
  import { useMembers, useQueue } from "@dxos/react-client/echo";
11
11
  import { StackItem } from "@dxos/react-ui-stack";
12
12
 
13
- // packages/plugins/plugin-transcription/src/components/Transcript/Transcript.tsx
14
- import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
15
- import React from "react";
16
- import { IconButton, useThemeContext } from "@dxos/react-ui";
17
- import { createBasicExtensions, createMarkdownExtensions, createRenderer, createThemeExtensions, decorateMarkdown, editorWidth, preview, useTextEditor } from "@dxos/react-ui-editor";
18
- import { mx } from "@dxos/react-ui-theme";
19
- import { isNotFalsy } from "@dxos/util";
13
+ // src/hooks/useAudioFile.ts
14
+ import { useEffect, useState } from "react";
15
+ import { scheduleTask } from "@dxos/async";
16
+ import { Context } from "@dxos/context";
17
+ import { log } from "@dxos/log";
18
+ var __dxlog_file = "/__w/dxos/dxos/packages/plugins/plugin-transcription/src/hooks/useAudioFile.ts";
19
+ var useAudioFile = (audioUrl, constraints) => {
20
+ const [{ audio, stream, track }, setStream] = useState({});
21
+ useEffect(() => {
22
+ const ctx = new Context(void 0, {
23
+ F: __dxlog_file,
24
+ L: 20
25
+ });
26
+ scheduleTask(ctx, async () => {
27
+ const response = await fetch(audioUrl);
28
+ const blob = await response.blob();
29
+ const objectUrl = URL.createObjectURL(blob);
30
+ ctx.onDispose(() => {
31
+ URL.revokeObjectURL(objectUrl);
32
+ });
33
+ const audio2 = new Audio();
34
+ audio2.src = objectUrl;
35
+ await new Promise((resolve, reject) => {
36
+ audio2.addEventListener("error", (err) => {
37
+ log.error("error", {
38
+ err
39
+ }, {
40
+ F: __dxlog_file,
41
+ L: 37,
42
+ S: void 0,
43
+ C: (f, a) => f(...a)
44
+ });
45
+ reject(err);
46
+ }, {
47
+ once: true
48
+ });
49
+ audio2.addEventListener("canplay", async () => {
50
+ log.info("starting...", void 0, {
51
+ F: __dxlog_file,
52
+ L: 45,
53
+ S: void 0,
54
+ C: (f, a) => f(...a)
55
+ });
56
+ try {
57
+ await audio2.play();
58
+ resolve();
59
+ } catch (playError) {
60
+ log.error("Play failed", {
61
+ playError
62
+ }, {
63
+ F: __dxlog_file,
64
+ L: 51,
65
+ S: void 0,
66
+ C: (f, a) => f(...a)
67
+ });
68
+ resolve();
69
+ }
70
+ }, {
71
+ once: true
72
+ });
73
+ audio2.load();
74
+ });
75
+ const audioCtx = new AudioContext();
76
+ if (audioCtx.state === "suspended") {
77
+ await audioCtx.resume();
78
+ }
79
+ const destination = audioCtx.createMediaStreamDestination();
80
+ destination.channelCount = 1;
81
+ const source = audioCtx.createMediaElementSource(audio2);
82
+ source.connect(destination);
83
+ const track2 = destination.stream.getAudioTracks()[0];
84
+ if (constraints) {
85
+ await track2.applyConstraints(constraints).catch((err) => log.catch(err, void 0, {
86
+ F: __dxlog_file,
87
+ L: 75,
88
+ S: void 0,
89
+ C: (f, a) => f(...a)
90
+ }));
91
+ }
92
+ setStream({
93
+ audio: audio2,
94
+ stream: destination.stream,
95
+ track: destination.stream.getAudioTracks()[0]
96
+ });
97
+ });
98
+ return () => {
99
+ void ctx.dispose();
100
+ };
101
+ }, [
102
+ audioUrl
103
+ ]);
104
+ return {
105
+ audio,
106
+ stream,
107
+ track
108
+ };
109
+ };
20
110
 
21
- // packages/plugins/plugin-transcription/src/components/Transcript/transcript-extension.ts
22
- import { RangeSetBuilder } from "@codemirror/state";
23
- import { EditorView, GutterMarker, ViewPlugin, gutter } from "@codemirror/view";
24
- import { format } from "date-fns/format";
25
- import { intervalToDuration } from "date-fns/intervalToDuration";
26
- import { addEventListener, combine } from "@dxos/async";
111
+ // src/hooks/useAudioTrack.ts
112
+ import { useEffect as useEffect2, useState as useState2 } from "react";
113
+ var useAudioTrack = (active, constraints) => {
114
+ const [track, setTrack] = useState2();
115
+ useEffect2(() => {
116
+ if (!active) {
117
+ track?.stop();
118
+ setTrack(void 0);
119
+ return;
120
+ }
121
+ const initAudio = async () => {
122
+ const audio = new Audio();
123
+ audio.srcObject = await navigator.mediaDevices.getUserMedia({
124
+ audio: constraints ?? true
125
+ });
126
+ const [track2] = audio.srcObject.getAudioTracks();
127
+ if (track2) {
128
+ setTrack(track2);
129
+ }
130
+ };
131
+ if (active) {
132
+ void initAudio();
133
+ }
134
+ }, [
135
+ active
136
+ ]);
137
+ return track;
138
+ };
139
+
140
+ // src/hooks/useQueueModelAdapter.ts
141
+ import { useEffect as useEffect3, useMemo, useState as useState3 } from "react";
27
142
 
28
- // packages/plugins/plugin-transcription/src/model/model.ts
143
+ // src/model/model.ts
29
144
  import { Text } from "@codemirror/state";
30
145
  import { Event } from "@dxos/async";
31
146
  import { invariant } from "@dxos/invariant";
32
- import { log } from "@dxos/log";
33
- var __dxlog_file = "/home/runner/work/dxos/dxos/packages/plugins/plugin-transcription/src/model/model.ts";
147
+ import { log as log2 } from "@dxos/log";
148
+ var __dxlog_file2 = "/__w/dxos/dxos/packages/plugins/plugin-transcription/src/model/model.ts";
34
149
  var DocumentAdapter = class {
150
+ _view;
35
151
  constructor(_view) {
36
152
  this._view = _view;
37
153
  }
@@ -40,13 +156,13 @@ var DocumentAdapter = class {
40
156
  return this._view.state.doc.lines - 1;
41
157
  }
42
158
  replaceLines(from, remove, insert) {
43
- log("replaceLines", {
159
+ log2("replaceLines", {
44
160
  count: this._view.state.doc.lines,
45
161
  from,
46
162
  remove,
47
163
  insert
48
164
  }, {
49
- F: __dxlog_file,
165
+ F: __dxlog_file2,
50
166
  L: 39,
51
167
  S: this,
52
168
  C: (f, a) => f(...a)
@@ -68,6 +184,17 @@ var DocumentAdapter = class {
68
184
  }
69
185
  };
70
186
  var SerializationModel = class {
187
+ _renderer;
188
+ /** Ordered set of chunks. */
189
+ _chunks;
190
+ /** Map of chunk IDs to their current line counts. */
191
+ _chunkLineCounts;
192
+ /** Map of line numbers to chunk IDs. */
193
+ _lineToChunk;
194
+ /** Track chunk changes since last sync. */
195
+ _changes;
196
+ /** Emits when the document is updated. */
197
+ update;
71
198
  constructor(_renderer, initialChunks = []) {
72
199
  this._renderer = _renderer;
73
200
  this._chunks = [];
@@ -121,7 +248,7 @@ var SerializationModel = class {
121
248
  updateChunk(chunk) {
122
249
  const index = this._chunks.findIndex((c) => c.id === chunk.id);
123
250
  invariant(index !== -1, void 0, {
124
- F: __dxlog_file,
251
+ F: __dxlog_file2,
125
252
  L: 147,
126
253
  S: this,
127
254
  A: [
@@ -141,7 +268,7 @@ var SerializationModel = class {
141
268
  deleteBlock(id) {
142
269
  const index = this._chunks.findIndex((c) => c.id === id);
143
270
  invariant(index !== -1, void 0, {
144
- F: __dxlog_file,
271
+ F: __dxlog_file2,
145
272
  L: 156,
146
273
  S: this,
147
274
  A: [
@@ -162,10 +289,10 @@ var SerializationModel = class {
162
289
  * Syncs the tracked changes with the ChunkDocument.
163
290
  */
164
291
  sync(document2) {
165
- log("sync", {
292
+ log2("sync", {
166
293
  changes: this._changes
167
294
  }, {
168
- F: __dxlog_file,
295
+ F: __dxlog_file2,
169
296
  L: 167,
170
297
  S: this,
171
298
  C: (f, a) => f(...a)
@@ -218,7 +345,170 @@ var SerializationModel = class {
218
345
  }
219
346
  };
220
347
 
221
- // packages/plugins/plugin-transcription/src/components/Transcript/transcript-extension.ts
348
+ // src/hooks/useQueueModelAdapter.ts
349
+ var useQueueModelAdapter = (renderer, queue, initialChunks = []) => {
350
+ const model = useMemo(() => new SerializationModel(renderer, initialChunks), [
351
+ queue
352
+ ]);
353
+ const [loaded, setLoaded] = useState3(false);
354
+ useEffect3(() => {
355
+ if (!queue) {
356
+ return;
357
+ }
358
+ const update = () => {
359
+ for (const block of queue?.objects ?? []) {
360
+ model.appendChunk(block);
361
+ }
362
+ setLoaded(true);
363
+ };
364
+ let i;
365
+ if (queue.isLoading) {
366
+ i = setInterval(() => {
367
+ if (!queue?.isLoading) {
368
+ clearInterval(i);
369
+ update();
370
+ }
371
+ }, 1e3);
372
+ } else {
373
+ update();
374
+ }
375
+ return () => clearTimeout(i);
376
+ }, [
377
+ model,
378
+ queue
379
+ ]);
380
+ useEffect3(() => {
381
+ if (!loaded || !queue || model.chunks.length === queue.objects.length) {
382
+ return;
383
+ }
384
+ const chunk = queue.objects.at(-1);
385
+ if (chunk) {
386
+ model.appendChunk(chunk);
387
+ }
388
+ }, [
389
+ model,
390
+ loaded,
391
+ queue?.objects.length
392
+ ]);
393
+ return model;
394
+ };
395
+
396
+ // src/hooks/useTranscriber.ts
397
+ import { useEffect as useEffect4, useMemo as useMemo2 } from "react";
398
+ import { useCapabilities } from "@dxos/app-framework";
399
+
400
+ // src/capabilities/index.ts
401
+ import { lazy } from "@dxos/app-framework";
402
+ var IntentResolver = lazy(() => import("./intent-resolver-P4XPIKQF.mjs"));
403
+ var ReactSurface = lazy(() => import("./react-surface-EZUPNHUC.mjs"));
404
+ var Transcriber = lazy(() => import("./transcriber-3SX3DNLV.mjs"));
405
+
406
+ // src/hooks/useTranscriber.ts
407
+ var useTranscriber = ({ audioStreamTrack, recorderConfig, transcriberConfig, onSegments }) => {
408
+ const [getTranscriber] = useCapabilities(TranscriptionCapabilities.Transcriber);
409
+ const transcriber = useMemo2(() => {
410
+ if (!getTranscriber || !audioStreamTrack || !onSegments) {
411
+ return void 0;
412
+ }
413
+ return getTranscriber({
414
+ audioStreamTrack,
415
+ recorderConfig,
416
+ transcriberConfig,
417
+ onSegments
418
+ });
419
+ }, [
420
+ getTranscriber,
421
+ audioStreamTrack,
422
+ recorderConfig,
423
+ transcriberConfig,
424
+ onSegments
425
+ ]);
426
+ useEffect4(() => {
427
+ return () => {
428
+ void transcriber?.close();
429
+ };
430
+ }, [
431
+ transcriber
432
+ ]);
433
+ return transcriber;
434
+ };
435
+
436
+ // src/hooks/useVoiceInput.ts
437
+ import { useCallback, useEffect as useEffect5, useState as useState4 } from "react";
438
+ import { scheduleMicroTask } from "@dxos/async";
439
+ import { Context as Context2 } from "@dxos/context";
440
+ import { log as log3 } from "@dxos/log";
441
+ import { useSoundEffect } from "@dxos/react-ui-sfx";
442
+ var __dxlog_file3 = "/__w/dxos/dxos/packages/plugins/plugin-transcription/src/hooks/useVoiceInput.ts";
443
+ var useVoiceInput = ({ active, onUpdate }) => {
444
+ const soundStart = useSoundEffect("StartRecording");
445
+ const soundStop = useSoundEffect("StopRecording");
446
+ const handleSegments = useCallback(async (segments) => {
447
+ const text = segments.map((str) => str.text.trim().replace(/[^\w\s]/g, "")).join(" ");
448
+ onUpdate(text);
449
+ }, []);
450
+ const [recording, setRecording] = useState4(false);
451
+ const track = useAudioTrack(active);
452
+ const transcriber = useTranscriber({
453
+ audioStreamTrack: track,
454
+ onSegments: handleSegments
455
+ });
456
+ useEffect5(() => {
457
+ const ctx = new Context2(void 0, {
458
+ F: __dxlog_file3,
459
+ L: 44
460
+ });
461
+ scheduleMicroTask(ctx, async () => {
462
+ if (active && transcriber) {
463
+ await transcriber.open();
464
+ log3.info("starting...", void 0, {
465
+ F: __dxlog_file3,
466
+ L: 48,
467
+ S: void 0,
468
+ C: (f, a) => f(...a)
469
+ });
470
+ setRecording(true);
471
+ void soundStart.play();
472
+ transcriber.startChunksRecording();
473
+ } else if (!active && transcriber?.isOpen) {
474
+ transcriber?.stopChunksRecording();
475
+ await transcriber?.close();
476
+ log3.info("stopped", void 0, {
477
+ F: __dxlog_file3,
478
+ L: 55,
479
+ S: void 0,
480
+ C: (f, a) => f(...a)
481
+ });
482
+ setRecording(false);
483
+ void soundStop.play();
484
+ }
485
+ });
486
+ return () => {
487
+ void ctx.dispose();
488
+ };
489
+ }, [
490
+ active,
491
+ transcriber
492
+ ]);
493
+ return {
494
+ recording
495
+ };
496
+ };
497
+
498
+ // src/components/Transcript/Transcript.tsx
499
+ import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
500
+ import React from "react";
501
+ import { IconButton, useThemeContext } from "@dxos/react-ui";
502
+ import { createBasicExtensions, createMarkdownExtensions, createRenderer, createThemeExtensions, decorateMarkdown, editorWidth, preview, useTextEditor } from "@dxos/react-ui-editor";
503
+ import { mx } from "@dxos/react-ui-theme";
504
+ import { isNotFalsy } from "@dxos/util";
505
+
506
+ // src/components/Transcript/transcript-extension.ts
507
+ import { RangeSetBuilder } from "@codemirror/state";
508
+ import { EditorView, GutterMarker, ViewPlugin, gutter } from "@codemirror/view";
509
+ import { format } from "date-fns/format";
510
+ import { intervalToDuration } from "date-fns/intervalToDuration";
511
+ import { addEventListener, combine } from "@dxos/async";
222
512
  var transcript = ({ model, started, renderButton }) => {
223
513
  return [
224
514
  // Show timestamps in the gutter.
@@ -232,7 +522,7 @@ var transcript = ({ model, started, renderButton }) => {
232
522
  let line = view.state.doc.lineAt(from);
233
523
  while (line.from <= to) {
234
524
  const block = model.getChunkAtLine(line.number)?.blocks[0];
235
- const timestamp = block?.type === "transcription" && block.started;
525
+ const timestamp = block?._tag === "transcript" && block.started;
236
526
  if (timestamp) {
237
527
  builder.add(line.from, line.from, new TimestampMarker(line.number, new Date(timestamp), start));
238
528
  }
@@ -247,8 +537,11 @@ var transcript = ({ model, started, renderButton }) => {
247
537
  }),
248
538
  // Listen for model updates.
249
539
  ViewPlugin.fromClass(class {
540
+ _controls;
541
+ _cleanup;
542
+ _adapter;
543
+ _initialized = false;
250
544
  constructor(view) {
251
- this._initialized = false;
252
545
  this._adapter = new DocumentAdapter(view);
253
546
  const scroller = view.scrollDOM;
254
547
  let isAutoScrolling = false;
@@ -339,6 +632,9 @@ var transcript = ({ model, started, renderButton }) => {
339
632
  ];
340
633
  };
341
634
  var TimestampMarker = class extends GutterMarker {
635
+ _line;
636
+ _timestamp;
637
+ _started;
342
638
  constructor(_line, _timestamp, _started) {
343
639
  super(), this._line = _line, this._timestamp = _timestamp, this._started = _started;
344
640
  }
@@ -364,7 +660,7 @@ var getStartTime = (started, message) => {
364
660
  if (started) {
365
661
  return started;
366
662
  }
367
- if (message?.blocks[0]?.type === "transcription" && message.blocks[0].started) {
663
+ if (message?.blocks[0]?._tag === "transcript" && message.blocks[0].started) {
368
664
  return new Date(message.blocks[0].started);
369
665
  }
370
666
  return void 0;
@@ -382,17 +678,17 @@ var formatTimestamp = (timestamp, relative) => {
382
678
  }
383
679
  };
384
680
 
385
- // packages/plugins/plugin-transcription/src/components/Transcript/Transcript.tsx
681
+ // src/components/Transcript/Transcript.tsx
386
682
  var renderMarkdown = (identities) => (message, index, debug = false) => {
387
683
  if (message.sender.role === "assistant") {
388
684
  return [
389
- message.blocks.find((block) => block.type === "transcription")?.text ?? "",
685
+ message.blocks.find((block) => block._tag === "transcript")?.text ?? "",
390
686
  ""
391
687
  ];
392
688
  }
393
689
  const identity = identities.find((identity2) => identity2.did === message.sender.identityDid);
394
690
  const name = identity?.profile?.displayName ?? message.sender.contact?.target?.fullName ?? message.sender.name ?? message.sender.email ?? message.sender.identityDid;
395
- const blocks = message.blocks.filter((block) => block.type === "transcription");
691
+ const blocks = message.blocks.filter((block) => block._tag === "transcript");
396
692
  return [
397
693
  `###### ${name}` + (debug ? ` [${index}]:${message.id}` : ""),
398
694
  blocks.map((block) => block.text.trim()).join(" "),
@@ -408,7 +704,8 @@ var Transcript = ({ classNames, transcript: object, space, model, attendableId,
408
704
  extensions: [
409
705
  createBasicExtensions({
410
706
  readOnly: true,
411
- lineWrapping: true
707
+ lineWrapping: true,
708
+ search: true
412
709
  }),
413
710
  createMarkdownExtensions({
414
711
  themeMode
@@ -444,286 +741,8 @@ var Transcript = ({ classNames, transcript: object, space, model, attendableId,
444
741
  }
445
742
  };
446
743
 
447
- // packages/plugins/plugin-transcription/src/hooks/useAudioFile.ts
448
- import { useEffect, useState } from "react";
449
- import { scheduleTask } from "@dxos/async";
450
- import { Context } from "@dxos/context";
451
- import { log as log2 } from "@dxos/log";
452
- var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/plugins/plugin-transcription/src/hooks/useAudioFile.ts";
453
- var useAudioFile = (audioUrl, constraints) => {
454
- const [{ audio, stream, track }, setStream] = useState({});
455
- useEffect(() => {
456
- const ctx = new Context(void 0, {
457
- F: __dxlog_file2,
458
- L: 20
459
- });
460
- scheduleTask(ctx, async () => {
461
- const response = await fetch(audioUrl);
462
- const blob = await response.blob();
463
- const objectUrl = URL.createObjectURL(blob);
464
- ctx.onDispose(() => {
465
- URL.revokeObjectURL(objectUrl);
466
- });
467
- const audio2 = new Audio();
468
- audio2.src = objectUrl;
469
- await new Promise((resolve, reject) => {
470
- audio2.addEventListener("error", (err) => {
471
- log2.error("error", {
472
- err
473
- }, {
474
- F: __dxlog_file2,
475
- L: 37,
476
- S: void 0,
477
- C: (f, a) => f(...a)
478
- });
479
- reject(err);
480
- }, {
481
- once: true
482
- });
483
- audio2.addEventListener("canplay", async () => {
484
- log2.info("starting...", void 0, {
485
- F: __dxlog_file2,
486
- L: 45,
487
- S: void 0,
488
- C: (f, a) => f(...a)
489
- });
490
- try {
491
- await audio2.play();
492
- resolve();
493
- } catch (playError) {
494
- log2.error("Play failed", {
495
- playError
496
- }, {
497
- F: __dxlog_file2,
498
- L: 51,
499
- S: void 0,
500
- C: (f, a) => f(...a)
501
- });
502
- resolve();
503
- }
504
- }, {
505
- once: true
506
- });
507
- audio2.load();
508
- });
509
- const audioCtx = new AudioContext();
510
- if (audioCtx.state === "suspended") {
511
- await audioCtx.resume();
512
- }
513
- const destination = audioCtx.createMediaStreamDestination();
514
- destination.channelCount = 1;
515
- const source = audioCtx.createMediaElementSource(audio2);
516
- source.connect(destination);
517
- const track2 = destination.stream.getAudioTracks()[0];
518
- if (constraints) {
519
- await track2.applyConstraints(constraints).catch((err) => log2.catch(err, void 0, {
520
- F: __dxlog_file2,
521
- L: 75,
522
- S: void 0,
523
- C: (f, a) => f(...a)
524
- }));
525
- }
526
- setStream({
527
- audio: audio2,
528
- stream: destination.stream,
529
- track: destination.stream.getAudioTracks()[0]
530
- });
531
- });
532
- return () => {
533
- void ctx.dispose();
534
- };
535
- }, [
536
- audioUrl
537
- ]);
538
- return {
539
- audio,
540
- stream,
541
- track
542
- };
543
- };
544
-
545
- // packages/plugins/plugin-transcription/src/hooks/useAudioTrack.ts
546
- import { useEffect as useEffect2, useState as useState2 } from "react";
547
- var useAudioTrack = (active, constraints) => {
548
- const [track, setTrack] = useState2();
549
- useEffect2(() => {
550
- if (!active) {
551
- track?.stop();
552
- setTrack(void 0);
553
- return;
554
- }
555
- const initAudio = async () => {
556
- const audio = new Audio();
557
- audio.srcObject = await navigator.mediaDevices.getUserMedia({
558
- audio: constraints ?? true
559
- });
560
- const [track2] = audio.srcObject.getAudioTracks();
561
- if (track2) {
562
- setTrack(track2);
563
- }
564
- };
565
- if (active) {
566
- void initAudio();
567
- }
568
- }, [
569
- active
570
- ]);
571
- return track;
572
- };
573
-
574
- // packages/plugins/plugin-transcription/src/hooks/useQueueModelAdapter.ts
575
- import { useEffect as useEffect3, useMemo, useState as useState3 } from "react";
576
- var useQueueModelAdapter = (renderer, queue, initialChunks = []) => {
577
- const model = useMemo(() => new SerializationModel(renderer, initialChunks), [
578
- queue
579
- ]);
580
- const [loaded, setLoaded] = useState3(false);
581
- useEffect3(() => {
582
- if (!queue) {
583
- return;
584
- }
585
- const update = () => {
586
- for (const block of queue?.objects ?? []) {
587
- model.appendChunk(block);
588
- }
589
- setLoaded(true);
590
- };
591
- let i;
592
- if (queue.isLoading) {
593
- i = setInterval(() => {
594
- if (!queue?.isLoading) {
595
- clearInterval(i);
596
- update();
597
- }
598
- }, 1e3);
599
- } else {
600
- update();
601
- }
602
- return () => clearTimeout(i);
603
- }, [
604
- model,
605
- queue
606
- ]);
607
- useEffect3(() => {
608
- if (!loaded || !queue || model.chunks.length === queue.objects.length) {
609
- return;
610
- }
611
- const chunk = queue.objects.at(-1);
612
- if (chunk) {
613
- model.appendChunk(chunk);
614
- }
615
- }, [
616
- model,
617
- loaded,
618
- queue?.objects.length
619
- ]);
620
- return model;
621
- };
622
-
623
- // packages/plugins/plugin-transcription/src/hooks/useTranscriber.ts
624
- import { useEffect as useEffect4, useMemo as useMemo2 } from "react";
625
- import { useCapabilities } from "@dxos/app-framework";
626
-
627
- // packages/plugins/plugin-transcription/src/capabilities/index.ts
628
- import { lazy } from "@dxos/app-framework";
629
- var IntentResolver = lazy(() => import("./intent-resolver-5LVCYSJS.mjs"));
630
- var ReactSurface = lazy(() => import("./react-surface-JGQSYGRR.mjs"));
631
- var Transcriber = lazy(() => import("./transcriber-TVG2MBBN.mjs"));
632
-
633
- // packages/plugins/plugin-transcription/src/hooks/useTranscriber.ts
634
- var useTranscriber = ({ audioStreamTrack, onSegments, transcriberConfig, recorderConfig }) => {
635
- const [getTranscriber] = useCapabilities(TranscriptionCapabilities.Transcriber);
636
- const transcriber = useMemo2(() => {
637
- if (!onSegments || !audioStreamTrack || !getTranscriber) {
638
- return void 0;
639
- }
640
- return getTranscriber({
641
- audioStreamTrack,
642
- onSegments,
643
- transcriberConfig,
644
- recorderConfig
645
- });
646
- }, [
647
- audioStreamTrack,
648
- onSegments,
649
- getTranscriber,
650
- transcriberConfig,
651
- recorderConfig
652
- ]);
653
- useEffect4(() => {
654
- return () => {
655
- void transcriber?.close();
656
- };
657
- }, [
658
- transcriber
659
- ]);
660
- return transcriber;
661
- };
662
-
663
- // packages/plugins/plugin-transcription/src/hooks/useVoiceInput.ts
664
- import { useState as useState4, useEffect as useEffect5, useCallback } from "react";
665
- import { scheduleMicroTask } from "@dxos/async";
666
- import { Context as Context2 } from "@dxos/context";
667
- import { log as log3 } from "@dxos/log";
668
- import { useSoundEffect } from "@dxos/react-ui-sfx";
669
- var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/plugins/plugin-transcription/src/hooks/useVoiceInput.ts";
670
- var useVoiceInput = ({ active, onUpdate }) => {
671
- const soundStart = useSoundEffect("StartRecording");
672
- const soundStop = useSoundEffect("StopRecording");
673
- const handleSegments = useCallback(async (segments) => {
674
- const text = segments.map((str) => str.text.trim().replace(/[^\w\s]/g, "")).join(" ");
675
- onUpdate(text);
676
- }, []);
677
- const [recording, setRecording] = useState4(false);
678
- const track = useAudioTrack(active);
679
- const transcriber = useTranscriber({
680
- audioStreamTrack: track,
681
- onSegments: handleSegments
682
- });
683
- useEffect5(() => {
684
- const ctx = new Context2(void 0, {
685
- F: __dxlog_file3,
686
- L: 43
687
- });
688
- scheduleMicroTask(ctx, async () => {
689
- if (active && transcriber) {
690
- await transcriber.open();
691
- log3.info("starting...", void 0, {
692
- F: __dxlog_file3,
693
- L: 47,
694
- S: void 0,
695
- C: (f, a) => f(...a)
696
- });
697
- setRecording(true);
698
- void soundStart.play();
699
- transcriber.startChunksRecording();
700
- } else if (!active && transcriber?.isOpen) {
701
- transcriber?.stopChunksRecording();
702
- await transcriber?.close();
703
- log3.info("stopped", void 0, {
704
- F: __dxlog_file3,
705
- L: 54,
706
- S: void 0,
707
- C: (f, a) => f(...a)
708
- });
709
- setRecording(false);
710
- void soundStop.play();
711
- }
712
- });
713
- return () => {
714
- void ctx.dispose();
715
- };
716
- }, [
717
- active,
718
- transcriber
719
- ]);
720
- return {
721
- recording
722
- };
723
- };
724
-
725
- // packages/plugins/plugin-transcription/src/components/TranscriptContainer.tsx
726
- var TranscriptionContainer = ({ role, transcript: transcript2 }) => {
744
+ // src/components/TranscriptContainer.tsx
745
+ var TranscriptionContainer = ({ transcript: transcript2 }) => {
727
746
  var _effect = _useSignals2();
728
747
  try {
729
748
  const attendableId = fullyQualifiedId(transcript2);
@@ -734,7 +753,6 @@ var TranscriptionContainer = ({ role, transcript: transcript2 }) => {
734
753
  });
735
754
  const model = useQueueModelAdapter(renderMarkdown(members), queue);
736
755
  return /* @__PURE__ */ React2.createElement(StackItem.Content, {
737
- role,
738
756
  classNames: "container-max-width pli-2"
739
757
  }, /* @__PURE__ */ React2.createElement(Transcript, {
740
758
  attendableId,
@@ -762,4 +780,4 @@ export {
762
780
  ReactSurface,
763
781
  Transcriber
764
782
  };
765
- //# sourceMappingURL=chunk-56QHOX4A.mjs.map
783
+ //# sourceMappingURL=chunk-Y7PCJ34K.mjs.map