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