@dxos/plugin-transcription 0.8.4-main.67995b8 → 0.8.4-main.ae835ea

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 (172) hide show
  1. package/dist/lib/browser/TranscriptContainer-2GSL2XB5.mjs +11 -0
  2. package/dist/lib/browser/blueprint-definition-UAAJYVLZ.mjs +150 -0
  3. package/dist/lib/browser/blueprint-definition-UAAJYVLZ.mjs.map +7 -0
  4. package/dist/lib/browser/{chunk-U6QBOGTN.mjs → chunk-3MKZ2MNQ.mjs} +5 -5
  5. package/dist/lib/browser/chunk-3MKZ2MNQ.mjs.map +7 -0
  6. package/dist/lib/browser/{chunk-4FJIYH7T.mjs → chunk-535OJKFO.mjs} +2 -2
  7. package/dist/lib/browser/{chunk-5KPYIC3N.mjs → chunk-7DR6HZEF.mjs} +332 -363
  8. package/dist/lib/browser/chunk-7DR6HZEF.mjs.map +7 -0
  9. package/dist/lib/browser/chunk-VBUIO677.mjs +29 -0
  10. package/dist/lib/browser/chunk-VBUIO677.mjs.map +7 -0
  11. package/dist/lib/browser/chunk-W7WKZTM4.mjs +63 -0
  12. package/dist/lib/browser/chunk-W7WKZTM4.mjs.map +7 -0
  13. package/dist/lib/browser/{chunk-FFEPEPCU.mjs → chunk-WH36ENNE.mjs} +49 -78
  14. package/dist/lib/browser/chunk-WH36ENNE.mjs.map +7 -0
  15. package/dist/lib/browser/index.mjs +24 -19
  16. package/dist/lib/browser/index.mjs.map +3 -3
  17. package/dist/lib/browser/intent-resolver-ZTKTEAQX.mjs +25 -0
  18. package/dist/lib/browser/intent-resolver-ZTKTEAQX.mjs.map +7 -0
  19. package/dist/lib/browser/meta.json +1 -1
  20. package/dist/lib/browser/{react-surface-E5D5AE3F.mjs → react-surface-KA32A72I.mjs} +10 -10
  21. package/dist/lib/browser/react-surface-KA32A72I.mjs.map +7 -0
  22. package/dist/lib/browser/{transcriber-PXT4QBFY.mjs → transcriber-LWOLYQHC.mjs} +7 -7
  23. package/dist/lib/browser/transcriber-LWOLYQHC.mjs.map +7 -0
  24. package/dist/lib/browser/types/index.mjs +6 -8
  25. package/dist/lib/node-esm/{TranscriptContainer-VBAOM5DG.mjs → TranscriptContainer-GRLDCESB.mjs} +4 -4
  26. package/dist/lib/node-esm/blueprint-definition-Z3LTZ3ID.mjs +151 -0
  27. package/dist/lib/node-esm/blueprint-definition-Z3LTZ3ID.mjs.map +7 -0
  28. package/dist/lib/node-esm/{chunk-TJKAO7VR.mjs → chunk-K4AZOB5Y.mjs} +332 -363
  29. package/dist/lib/node-esm/chunk-K4AZOB5Y.mjs.map +7 -0
  30. package/dist/lib/node-esm/chunk-OLMSTF3M.mjs +64 -0
  31. package/dist/lib/node-esm/chunk-OLMSTF3M.mjs.map +7 -0
  32. package/dist/lib/node-esm/{chunk-Y2B4HWSS.mjs → chunk-Q6WD7L2J.mjs} +2 -2
  33. package/dist/lib/node-esm/{chunk-RHF2ALML.mjs → chunk-SWUVPFKR.mjs} +5 -5
  34. package/dist/lib/node-esm/chunk-SWUVPFKR.mjs.map +7 -0
  35. package/dist/lib/node-esm/{chunk-HT3W7LDP.mjs → chunk-YFN4FJFK.mjs} +49 -78
  36. package/dist/lib/node-esm/chunk-YFN4FJFK.mjs.map +7 -0
  37. package/dist/lib/node-esm/chunk-YVNQN2J6.mjs +30 -0
  38. package/dist/lib/node-esm/chunk-YVNQN2J6.mjs.map +7 -0
  39. package/dist/lib/node-esm/index.mjs +24 -19
  40. package/dist/lib/node-esm/index.mjs.map +3 -3
  41. package/dist/lib/node-esm/intent-resolver-55WH2GY6.mjs +26 -0
  42. package/dist/lib/node-esm/intent-resolver-55WH2GY6.mjs.map +7 -0
  43. package/dist/lib/node-esm/meta.json +1 -1
  44. package/dist/lib/node-esm/{react-surface-QRDJOHN5.mjs → react-surface-GU7LW2JO.mjs} +10 -10
  45. package/dist/lib/node-esm/react-surface-GU7LW2JO.mjs.map +7 -0
  46. package/dist/lib/node-esm/{transcriber-YUTEVANE.mjs → transcriber-UGB7ECX6.mjs} +7 -7
  47. package/dist/lib/node-esm/transcriber-UGB7ECX6.mjs.map +7 -0
  48. package/dist/lib/node-esm/types/index.mjs +6 -8
  49. package/dist/types/src/TranscriptionPlugin.d.ts +1 -1
  50. package/dist/types/src/TranscriptionPlugin.d.ts.map +1 -1
  51. package/dist/types/src/capabilities/blueprint-definition.d.ts +5 -0
  52. package/dist/types/src/capabilities/blueprint-definition.d.ts.map +1 -0
  53. package/dist/types/src/capabilities/capabilities.d.ts +1 -1
  54. package/dist/types/src/capabilities/capabilities.d.ts.map +1 -1
  55. package/dist/types/src/capabilities/index.d.ts +3 -2
  56. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  57. package/dist/types/src/capabilities/intent-resolver.d.ts +1 -1
  58. package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -1
  59. package/dist/types/src/capabilities/react-surface.d.ts +1 -1
  60. package/dist/types/src/capabilities/transcriber.d.ts +1 -1
  61. package/dist/types/src/capabilities/transcriber.d.ts.map +1 -1
  62. package/dist/types/src/components/Transcript/Transcript.d.ts +5 -5
  63. package/dist/types/src/components/Transcript/Transcript.d.ts.map +1 -1
  64. package/dist/types/src/components/Transcript/Transcript.stories.d.ts +31 -16
  65. package/dist/types/src/components/Transcript/Transcript.stories.d.ts.map +1 -1
  66. package/dist/types/src/components/Transcript/deprecated/OldTranscript.d.ts +3 -3
  67. package/dist/types/src/components/Transcript/deprecated/OldTranscript.d.ts.map +1 -1
  68. package/dist/types/src/components/Transcript/transcript-extension.d.ts +1 -5
  69. package/dist/types/src/components/Transcript/transcript-extension.d.ts.map +1 -1
  70. package/dist/types/src/components/TranscriptContainer.d.ts +2 -2
  71. package/dist/types/src/components/TranscriptContainer.d.ts.map +1 -1
  72. package/dist/types/src/components/stories/FileTranscription.stories.d.ts +5 -4
  73. package/dist/types/src/components/stories/FileTranscription.stories.d.ts.map +1 -1
  74. package/dist/types/src/components/stories/KeyWordRecognition.stories.d.ts +10 -6
  75. package/dist/types/src/components/stories/KeyWordRecognition.stories.d.ts.map +1 -1
  76. package/dist/types/src/components/stories/MicrophoneTranscription.stories.d.ts +7 -6
  77. package/dist/types/src/components/stories/MicrophoneTranscription.stories.d.ts.map +1 -1
  78. package/dist/types/src/components/stories/TranscriptionStory.d.ts +2 -1
  79. package/dist/types/src/components/stories/TranscriptionStory.d.ts.map +1 -1
  80. package/dist/types/src/functions/index.d.ts +3 -0
  81. package/dist/types/src/functions/index.d.ts.map +1 -0
  82. package/dist/types/src/functions/open.d.ts +7 -0
  83. package/dist/types/src/functions/open.d.ts.map +1 -0
  84. package/dist/types/src/functions/summarize.d.ts +11 -0
  85. package/dist/types/src/functions/summarize.d.ts.map +1 -0
  86. package/dist/types/src/hooks/useAudioFile.d.ts.map +1 -1
  87. package/dist/types/src/hooks/useVoiceInput.d.ts.map +1 -1
  88. package/dist/types/src/meta.d.ts +0 -1
  89. package/dist/types/src/meta.d.ts.map +1 -1
  90. package/dist/types/src/segments-normalization/normalization.d.ts +388 -328
  91. package/dist/types/src/segments-normalization/normalization.d.ts.map +1 -1
  92. package/dist/types/src/testing/testing.d.ts +2 -2
  93. package/dist/types/src/testing/testing.d.ts.map +1 -1
  94. package/dist/types/src/transcriber/media-stream-recorder.d.ts +1 -1
  95. package/dist/types/src/transcriber/media-stream-recorder.d.ts.map +1 -1
  96. package/dist/types/src/transcriber/transcriber.d.ts.map +1 -1
  97. package/dist/types/src/transcriber/transcription-manager.d.ts +3 -7
  98. package/dist/types/src/transcriber/transcription-manager.d.ts.map +1 -1
  99. package/dist/types/src/types/Transcript.d.ts +30 -0
  100. package/dist/types/src/types/Transcript.d.ts.map +1 -0
  101. package/dist/types/src/types/TranscriptAction.d.ts +23 -0
  102. package/dist/types/src/types/TranscriptAction.d.ts.map +1 -0
  103. package/dist/types/src/types/index.d.ts +2 -1
  104. package/dist/types/src/types/index.d.ts.map +1 -1
  105. package/dist/types/src/types/types.d.ts +0 -26
  106. package/dist/types/src/types/types.d.ts.map +1 -1
  107. package/dist/types/tsconfig.tsbuildinfo +1 -1
  108. package/package.json +65 -66
  109. package/src/TranscriptionPlugin.tsx +58 -53
  110. package/src/capabilities/blueprint-definition.ts +31 -0
  111. package/src/capabilities/capabilities.ts +6 -6
  112. package/src/capabilities/index.ts +1 -0
  113. package/src/capabilities/intent-resolver.ts +5 -11
  114. package/src/capabilities/react-surface.tsx +2 -2
  115. package/src/capabilities/transcriber.ts +3 -2
  116. package/src/components/Transcript/Transcript.stories.tsx +34 -31
  117. package/src/components/Transcript/Transcript.tsx +20 -27
  118. package/src/components/Transcript/deprecated/OldTranscript.tsx +9 -9
  119. package/src/components/Transcript/transcript-extension.ts +2 -39
  120. package/src/components/TranscriptContainer.tsx +7 -6
  121. package/src/components/stories/FileTranscription.stories.tsx +47 -36
  122. package/src/components/stories/KeyWordRecognition.stories.tsx +14 -10
  123. package/src/components/stories/MicrophoneTranscription.stories.tsx +40 -37
  124. package/src/components/stories/TranscriptionStory.tsx +10 -6
  125. package/src/functions/index.ts +6 -0
  126. package/src/functions/open.ts +39 -0
  127. package/src/functions/summarize.ts +103 -0
  128. package/src/hooks/useAudioFile.ts +49 -53
  129. package/src/hooks/useVoiceInput.ts +3 -2
  130. package/src/meta.ts +7 -4
  131. package/src/model/model.test.ts +1 -1
  132. package/src/segments-normalization/message-normalizer.ts +1 -1
  133. package/src/segments-normalization/normalization.test.ts +5 -5
  134. package/src/segments-normalization/normalization.ts +38 -37
  135. package/src/testing/testing.ts +7 -7
  136. package/src/transcriber/media-stream-recorder.ts +1 -1
  137. package/src/transcriber/transcriber.browser.test.ts +2 -1
  138. package/src/transcriber/transcriber.ts +2 -1
  139. package/src/transcriber/transcription-manager.ts +17 -38
  140. package/src/types/{schema.ts → Transcript.ts} +12 -9
  141. package/src/types/TranscriptAction.ts +24 -0
  142. package/src/types/index.ts +2 -1
  143. package/src/types/types.ts +0 -23
  144. package/dist/lib/browser/TranscriptContainer-6WCKCXQ6.mjs +0 -11
  145. package/dist/lib/browser/chunk-5KPYIC3N.mjs.map +0 -7
  146. package/dist/lib/browser/chunk-5WH45KBY.mjs +0 -19
  147. package/dist/lib/browser/chunk-5WH45KBY.mjs.map +0 -7
  148. package/dist/lib/browser/chunk-FFEPEPCU.mjs.map +0 -7
  149. package/dist/lib/browser/chunk-R7INNNUQ.mjs +0 -55
  150. package/dist/lib/browser/chunk-R7INNNUQ.mjs.map +0 -7
  151. package/dist/lib/browser/chunk-U6QBOGTN.mjs.map +0 -7
  152. package/dist/lib/browser/intent-resolver-3O33MMP5.mjs +0 -30
  153. package/dist/lib/browser/intent-resolver-3O33MMP5.mjs.map +0 -7
  154. package/dist/lib/browser/react-surface-E5D5AE3F.mjs.map +0 -7
  155. package/dist/lib/browser/transcriber-PXT4QBFY.mjs.map +0 -7
  156. package/dist/lib/node-esm/chunk-HT3W7LDP.mjs.map +0 -7
  157. package/dist/lib/node-esm/chunk-RHF2ALML.mjs.map +0 -7
  158. package/dist/lib/node-esm/chunk-TJKAO7VR.mjs.map +0 -7
  159. package/dist/lib/node-esm/chunk-U65ZWK3L.mjs +0 -56
  160. package/dist/lib/node-esm/chunk-U65ZWK3L.mjs.map +0 -7
  161. package/dist/lib/node-esm/chunk-XMUCZBP3.mjs +0 -21
  162. package/dist/lib/node-esm/chunk-XMUCZBP3.mjs.map +0 -7
  163. package/dist/lib/node-esm/intent-resolver-YMN5SXNC.mjs +0 -31
  164. package/dist/lib/node-esm/intent-resolver-YMN5SXNC.mjs.map +0 -7
  165. package/dist/lib/node-esm/react-surface-QRDJOHN5.mjs.map +0 -7
  166. package/dist/lib/node-esm/transcriber-YUTEVANE.mjs.map +0 -7
  167. package/dist/types/src/types/schema.d.ts +0 -41
  168. package/dist/types/src/types/schema.d.ts.map +0 -1
  169. /package/dist/lib/browser/{TranscriptContainer-6WCKCXQ6.mjs.map → TranscriptContainer-2GSL2XB5.mjs.map} +0 -0
  170. /package/dist/lib/browser/{chunk-4FJIYH7T.mjs.map → chunk-535OJKFO.mjs.map} +0 -0
  171. /package/dist/lib/node-esm/{TranscriptContainer-VBAOM5DG.mjs.map → TranscriptContainer-GRLDCESB.mjs.map} +0 -0
  172. /package/dist/lib/node-esm/{chunk-Y2B4HWSS.mjs.map → chunk-Q6WD7L2J.mjs.map} +0 -0
@@ -1,7 +1,7 @@
1
1
  import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
2
2
  import {
3
3
  TranscriptionCapabilities
4
- } from "./chunk-RHF2ALML.mjs";
4
+ } from "./chunk-SWUVPFKR.mjs";
5
5
 
6
6
  // src/components/TranscriptContainer.tsx
7
7
  import { useSignals as _useSignals2 } from "@preact-signals/safe-react/tracking";
@@ -10,28 +10,134 @@ 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
- // 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
+ try {
28
+ const response = await fetch(audioUrl);
29
+ const blob = await response.blob();
30
+ const objectUrl = URL.createObjectURL(blob);
31
+ ctx.onDispose(() => {
32
+ URL.revokeObjectURL(objectUrl);
33
+ });
34
+ const audio2 = new Audio();
35
+ audio2.src = objectUrl;
36
+ await new Promise((resolve, reject) => {
37
+ audio2.addEventListener("error", (err) => {
38
+ log.error("error", {
39
+ err
40
+ }, {
41
+ F: __dxlog_file,
42
+ L: 39,
43
+ S: void 0,
44
+ C: (f, a) => f(...a)
45
+ });
46
+ reject(err);
47
+ }, {
48
+ once: true
49
+ });
50
+ audio2.addEventListener("canplay", async () => {
51
+ resolve();
52
+ }, {
53
+ once: true
54
+ });
55
+ audio2.load();
56
+ });
57
+ const audioCtx = new AudioContext();
58
+ if (audioCtx.state === "suspended") {
59
+ await audioCtx.resume();
60
+ }
61
+ const destination = audioCtx.createMediaStreamDestination();
62
+ destination.channelCount = 1;
63
+ const source = audioCtx.createMediaElementSource(audio2);
64
+ source.connect(destination);
65
+ const track2 = destination.stream.getAudioTracks()[0];
66
+ if (constraints) {
67
+ await track2.applyConstraints(constraints).catch((err) => log.catch(err, void 0, {
68
+ F: __dxlog_file,
69
+ L: 68,
70
+ S: void 0,
71
+ C: (f, a) => f(...a)
72
+ }));
73
+ }
74
+ setStream({
75
+ audio: audio2,
76
+ stream: destination.stream,
77
+ track: destination.stream.getAudioTracks()[0]
78
+ });
79
+ } catch (err) {
80
+ log.catch(err, void 0, {
81
+ F: __dxlog_file,
82
+ L: 78,
83
+ S: void 0,
84
+ C: (f, a) => f(...a)
85
+ });
86
+ }
87
+ });
88
+ return () => {
89
+ void ctx.dispose();
90
+ };
91
+ }, [
92
+ audioUrl
93
+ ]);
94
+ return {
95
+ audio,
96
+ stream,
97
+ track
98
+ };
99
+ };
20
100
 
21
- // 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";
101
+ // src/hooks/useAudioTrack.ts
102
+ import { useEffect as useEffect2, useState as useState2 } from "react";
103
+ var useAudioTrack = (active, constraints) => {
104
+ const [track, setTrack] = useState2();
105
+ useEffect2(() => {
106
+ if (!active) {
107
+ track?.stop();
108
+ setTrack(void 0);
109
+ return;
110
+ }
111
+ const initAudio = async () => {
112
+ const audio = new Audio();
113
+ audio.srcObject = await navigator.mediaDevices.getUserMedia({
114
+ audio: constraints ?? true
115
+ });
116
+ const [track2] = audio.srcObject.getAudioTracks();
117
+ if (track2) {
118
+ setTrack(track2);
119
+ }
120
+ };
121
+ if (active) {
122
+ void initAudio();
123
+ }
124
+ }, [
125
+ active
126
+ ]);
127
+ return track;
128
+ };
129
+
130
+ // src/hooks/useQueueModelAdapter.ts
131
+ import { useEffect as useEffect3, useMemo, useState as useState3 } from "react";
27
132
 
28
133
  // src/model/model.ts
29
134
  import { Text } from "@codemirror/state";
30
135
  import { Event } from "@dxos/async";
31
136
  import { invariant } from "@dxos/invariant";
32
- import { log } from "@dxos/log";
33
- var __dxlog_file = "/__w/dxos/dxos/packages/plugins/plugin-transcription/src/model/model.ts";
137
+ import { log as log2 } from "@dxos/log";
138
+ var __dxlog_file2 = "/__w/dxos/dxos/packages/plugins/plugin-transcription/src/model/model.ts";
34
139
  var DocumentAdapter = class {
140
+ _view;
35
141
  constructor(_view) {
36
142
  this._view = _view;
37
143
  }
@@ -40,13 +146,13 @@ var DocumentAdapter = class {
40
146
  return this._view.state.doc.lines - 1;
41
147
  }
42
148
  replaceLines(from, remove, insert) {
43
- log("replaceLines", {
149
+ log2("replaceLines", {
44
150
  count: this._view.state.doc.lines,
45
151
  from,
46
152
  remove,
47
153
  insert
48
154
  }, {
49
- F: __dxlog_file,
155
+ F: __dxlog_file2,
50
156
  L: 39,
51
157
  S: this,
52
158
  C: (f, a) => f(...a)
@@ -68,13 +174,19 @@ var DocumentAdapter = class {
68
174
  }
69
175
  };
70
176
  var SerializationModel = class {
177
+ _renderer;
178
+ /** Ordered set of chunks. */
179
+ _chunks = [];
180
+ /** Map of chunk IDs to their current line counts. */
181
+ _chunkLineCounts = /* @__PURE__ */ new Map();
182
+ /** Map of line numbers to chunk IDs. */
183
+ _lineToChunk = /* @__PURE__ */ new Map();
184
+ /** Track chunk changes since last sync. */
185
+ _changes = [];
186
+ /** Emits when the document is updated. */
187
+ update = new Event();
71
188
  constructor(_renderer, initialChunks = []) {
72
189
  this._renderer = _renderer;
73
- this._chunks = [];
74
- this._chunkLineCounts = /* @__PURE__ */ new Map();
75
- this._lineToChunk = /* @__PURE__ */ new Map();
76
- this._changes = [];
77
- this.update = new Event();
78
190
  initialChunks.forEach((chunk) => {
79
191
  this.appendChunk(chunk);
80
192
  });
@@ -121,7 +233,7 @@ var SerializationModel = class {
121
233
  updateChunk(chunk) {
122
234
  const index = this._chunks.findIndex((c) => c.id === chunk.id);
123
235
  invariant(index !== -1, void 0, {
124
- F: __dxlog_file,
236
+ F: __dxlog_file2,
125
237
  L: 147,
126
238
  S: this,
127
239
  A: [
@@ -141,7 +253,7 @@ var SerializationModel = class {
141
253
  deleteBlock(id) {
142
254
  const index = this._chunks.findIndex((c) => c.id === id);
143
255
  invariant(index !== -1, void 0, {
144
- F: __dxlog_file,
256
+ F: __dxlog_file2,
145
257
  L: 156,
146
258
  S: this,
147
259
  A: [
@@ -162,10 +274,10 @@ var SerializationModel = class {
162
274
  * Syncs the tracked changes with the ChunkDocument.
163
275
  */
164
276
  sync(document2) {
165
- log("sync", {
277
+ log2("sync", {
166
278
  changes: this._changes
167
279
  }, {
168
- F: __dxlog_file,
280
+ F: __dxlog_file2,
169
281
  L: 167,
170
282
  S: this,
171
283
  C: (f, a) => f(...a)
@@ -218,8 +330,172 @@ var SerializationModel = class {
218
330
  }
219
331
  };
220
332
 
333
+ // src/hooks/useQueueModelAdapter.ts
334
+ var useQueueModelAdapter = (renderer, queue, initialChunks = []) => {
335
+ const model = useMemo(() => new SerializationModel(renderer, initialChunks), [
336
+ queue
337
+ ]);
338
+ const [loaded, setLoaded] = useState3(false);
339
+ useEffect3(() => {
340
+ if (!queue) {
341
+ return;
342
+ }
343
+ const update = () => {
344
+ for (const block of queue?.objects ?? []) {
345
+ model.appendChunk(block);
346
+ }
347
+ setLoaded(true);
348
+ };
349
+ let i;
350
+ if (queue.isLoading) {
351
+ i = setInterval(() => {
352
+ if (!queue?.isLoading) {
353
+ clearInterval(i);
354
+ update();
355
+ }
356
+ }, 1e3);
357
+ } else {
358
+ update();
359
+ }
360
+ return () => clearTimeout(i);
361
+ }, [
362
+ model,
363
+ queue
364
+ ]);
365
+ useEffect3(() => {
366
+ if (!loaded || !queue || model.chunks.length === queue.objects.length) {
367
+ return;
368
+ }
369
+ const chunk = queue.objects.at(-1);
370
+ if (chunk) {
371
+ model.appendChunk(chunk);
372
+ }
373
+ }, [
374
+ model,
375
+ loaded,
376
+ queue?.objects.length
377
+ ]);
378
+ return model;
379
+ };
380
+
381
+ // src/hooks/useTranscriber.ts
382
+ import { useEffect as useEffect4, useMemo as useMemo2 } from "react";
383
+ import { useCapabilities } from "@dxos/app-framework";
384
+
385
+ // src/capabilities/index.ts
386
+ import { lazy } from "@dxos/app-framework";
387
+ var BlueprintDefinition = lazy(() => import("./blueprint-definition-Z3LTZ3ID.mjs"));
388
+ var IntentResolver = lazy(() => import("./intent-resolver-55WH2GY6.mjs"));
389
+ var ReactSurface = lazy(() => import("./react-surface-GU7LW2JO.mjs"));
390
+ var Transcriber = lazy(() => import("./transcriber-UGB7ECX6.mjs"));
391
+
392
+ // src/hooks/useTranscriber.ts
393
+ var useTranscriber = ({ audioStreamTrack, recorderConfig, transcriberConfig, onSegments }) => {
394
+ const [getTranscriber] = useCapabilities(TranscriptionCapabilities.Transcriber);
395
+ const transcriber = useMemo2(() => {
396
+ if (!getTranscriber || !audioStreamTrack || !onSegments) {
397
+ return void 0;
398
+ }
399
+ return getTranscriber({
400
+ audioStreamTrack,
401
+ recorderConfig,
402
+ transcriberConfig,
403
+ onSegments
404
+ });
405
+ }, [
406
+ getTranscriber,
407
+ audioStreamTrack,
408
+ recorderConfig,
409
+ transcriberConfig,
410
+ onSegments
411
+ ]);
412
+ useEffect4(() => {
413
+ return () => {
414
+ void transcriber?.close();
415
+ };
416
+ }, [
417
+ transcriber
418
+ ]);
419
+ return transcriber;
420
+ };
421
+
422
+ // src/hooks/useVoiceInput.ts
423
+ import { useCallback, useEffect as useEffect5, useState as useState4 } from "react";
424
+ import { scheduleMicroTask } from "@dxos/async";
425
+ import { Context as Context2 } from "@dxos/context";
426
+ import { log as log3 } from "@dxos/log";
427
+ import { useSoundEffect } from "@dxos/react-ui-sfx";
428
+ var __dxlog_file3 = "/__w/dxos/dxos/packages/plugins/plugin-transcription/src/hooks/useVoiceInput.ts";
429
+ var useVoiceInput = ({ active, onUpdate }) => {
430
+ const soundStart = useSoundEffect("StartRecording");
431
+ const soundStop = useSoundEffect("StopRecording");
432
+ const handleSegments = useCallback(async (segments) => {
433
+ const text = segments.map((str) => str.text.trim().replace(/[^\w\s]/g, "")).join(" ");
434
+ onUpdate(text);
435
+ }, []);
436
+ const [recording, setRecording] = useState4(false);
437
+ const track = useAudioTrack(active);
438
+ const transcriber = useTranscriber({
439
+ audioStreamTrack: track,
440
+ onSegments: handleSegments
441
+ });
442
+ useEffect5(() => {
443
+ const ctx = new Context2(void 0, {
444
+ F: __dxlog_file3,
445
+ L: 44
446
+ });
447
+ scheduleMicroTask(ctx, async () => {
448
+ if (active && transcriber) {
449
+ await transcriber.open();
450
+ log3.info("starting...", void 0, {
451
+ F: __dxlog_file3,
452
+ L: 48,
453
+ S: void 0,
454
+ C: (f, a) => f(...a)
455
+ });
456
+ setRecording(true);
457
+ void soundStart.play();
458
+ transcriber.startChunksRecording();
459
+ } else if (!active && transcriber?.isOpen) {
460
+ transcriber?.stopChunksRecording();
461
+ await transcriber?.close();
462
+ log3.info("stopped", void 0, {
463
+ F: __dxlog_file3,
464
+ L: 55,
465
+ S: void 0,
466
+ C: (f, a) => f(...a)
467
+ });
468
+ setRecording(false);
469
+ void soundStop.play();
470
+ }
471
+ });
472
+ return () => {
473
+ void ctx.dispose();
474
+ };
475
+ }, [
476
+ active,
477
+ transcriber
478
+ ]);
479
+ return {
480
+ recording
481
+ };
482
+ };
483
+
484
+ // src/components/Transcript/Transcript.tsx
485
+ import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
486
+ import React from "react";
487
+ import { useThemeContext } from "@dxos/react-ui";
488
+ import { autoScroll, createBasicExtensions, createMarkdownExtensions, createThemeExtensions, decorateMarkdown, preview, useTextEditor } from "@dxos/react-ui-editor";
489
+ import { mx } from "@dxos/react-ui-theme";
490
+ import { isTruthy } from "@dxos/util";
491
+
221
492
  // src/components/Transcript/transcript-extension.ts
222
- var transcript = ({ model, started, renderButton }) => {
493
+ import { RangeSetBuilder } from "@codemirror/state";
494
+ import { EditorView, GutterMarker, ViewPlugin, gutter } from "@codemirror/view";
495
+ import { format } from "date-fns/format";
496
+ import { intervalToDuration } from "date-fns/intervalToDuration";
497
+ import { addEventListener, combine } from "@dxos/async";
498
+ var transcript = ({ model, started }) => {
223
499
  return [
224
500
  // Show timestamps in the gutter.
225
501
  gutter({
@@ -247,8 +523,11 @@ var transcript = ({ model, started, renderButton }) => {
247
523
  }),
248
524
  // Listen for model updates.
249
525
  ViewPlugin.fromClass(class {
526
+ _controls;
527
+ _cleanup;
528
+ _adapter;
529
+ _initialized = false;
250
530
  constructor(view) {
251
- this._initialized = false;
252
531
  this._adapter = new DocumentAdapter(view);
253
532
  const scroller = view.scrollDOM;
254
533
  let isAutoScrolling = false;
@@ -270,30 +549,20 @@ var transcript = ({ model, started, renderButton }) => {
270
549
  })
271
550
  });
272
551
  };
273
- if (renderButton) {
274
- this._controls = document.createElement("div");
275
- this._controls.classList.add("cm-controls", "transition-opacity", "duration-300", "opacity-0");
276
- view.dom.appendChild(this._controls);
277
- renderButton(this._controls, {
278
- onClick: () => {
279
- scrollToBottom(false);
280
- }
281
- }, view);
282
- }
283
552
  this._cleanup = combine(addEventListener(view.scrollDOM, "scroll", () => {
284
553
  if (!isAutoScrolling) {
285
554
  hasScrolled = true;
286
555
  this._controls?.classList.remove("opacity-0");
287
556
  }
288
557
  }), model.update.on(() => {
289
- const autoScroll = scroller.scrollHeight - scroller.scrollTop - scroller.clientHeight === 0 || !hasScrolled;
558
+ const autoScroll2 = scroller.scrollHeight - scroller.scrollTop - scroller.clientHeight === 0 || !hasScrolled;
290
559
  model.sync(this._adapter);
291
- if (autoScroll) {
560
+ if (autoScroll2) {
292
561
  scrollToBottom(true);
293
562
  }
294
563
  }));
295
564
  }
296
- update(update) {
565
+ update(_update) {
297
566
  if (!this._initialized) {
298
567
  this._initialized = true;
299
568
  setTimeout(() => {
@@ -307,25 +576,6 @@ var transcript = ({ model, started, renderButton }) => {
307
576
  }
308
577
  }),
309
578
  EditorView.theme({
310
- ".cm-scroller": {
311
- overflowY: "scroll"
312
- },
313
- ".cm-hide-scrollbar": {
314
- scrollbarWidth: "none",
315
- "-ms-overflow-style": "none"
316
- },
317
- ".cm-hide-scrollbar::-webkit-scrollbar": {
318
- display: "none"
319
- },
320
- ".cm-controls": {
321
- position: "absolute",
322
- bottom: "0.5rem",
323
- right: "0.5rem",
324
- zIndex: 1e3
325
- },
326
- ".cm-line": {
327
- paddingRight: "1rem"
328
- },
329
579
  ".cm-timestamp-gutter": {
330
580
  width: "6rem",
331
581
  paddingRight: "1rem"
@@ -339,6 +589,9 @@ var transcript = ({ model, started, renderButton }) => {
339
589
  ];
340
590
  };
341
591
  var TimestampMarker = class extends GutterMarker {
592
+ _line;
593
+ _timestamp;
594
+ _started;
342
595
  constructor(_line, _timestamp, _started) {
343
596
  super(), this._line = _line, this._timestamp = _timestamp, this._started = _started;
344
597
  }
@@ -383,7 +636,7 @@ var formatTimestamp = (timestamp, relative) => {
383
636
  };
384
637
 
385
638
  // src/components/Transcript/Transcript.tsx
386
- var renderMarkdown = (identities) => (message, index, debug = false) => {
639
+ var renderByline = (identities) => (message, index, debug = false) => {
387
640
  if (message.sender.role === "assistant") {
388
641
  return [
389
642
  message.blocks.find((block) => block._tag === "transcript")?.text ?? "",
@@ -394,12 +647,13 @@ var renderMarkdown = (identities) => (message, index, debug = false) => {
394
647
  const name = identity?.profile?.displayName ?? message.sender.contact?.target?.fullName ?? message.sender.name ?? message.sender.email ?? message.sender.identityDid;
395
648
  const blocks = message.blocks.filter((block) => block._tag === "transcript");
396
649
  return [
650
+ // TODO(thure): Use an XML tag with the bits needed here.
397
651
  `###### ${name}` + (debug ? ` [${index}]:${message.id}` : ""),
398
652
  blocks.map((block) => block.text.trim()).join(" "),
399
653
  ""
400
654
  ];
401
655
  };
402
- var Transcript = ({ classNames, transcript: object, space, model, attendableId, ignoreAttention }) => {
656
+ var TranscriptView = ({ classNames, space, transcript: object, model }) => {
403
657
  var _effect = _useSignals();
404
658
  try {
405
659
  const { themeMode } = useThemeContext();
@@ -408,27 +662,21 @@ var Transcript = ({ classNames, transcript: object, space, model, attendableId,
408
662
  extensions: [
409
663
  createBasicExtensions({
410
664
  readOnly: true,
411
- lineWrapping: true
412
- }),
413
- createMarkdownExtensions({
414
- themeMode
665
+ lineWrapping: true,
666
+ search: true
415
667
  }),
668
+ createMarkdownExtensions(),
416
669
  createThemeExtensions({
417
670
  themeMode
418
671
  }),
419
672
  decorateMarkdown(),
420
- space && preview(),
673
+ preview(),
421
674
  transcript({
422
675
  model,
423
- started: object?.started ? new Date(object.started) : void 0,
424
- renderButton: createRenderer(({ onClick }) => /* @__PURE__ */ React.createElement(IconButton, {
425
- icon: "ph--arrow-line-down--regular",
426
- iconOnly: true,
427
- label: "Scroll to bottom",
428
- onClick
429
- }))
430
- })
431
- ].filter(isNotFalsy)
676
+ started: object?.started ? new Date(object.started) : void 0
677
+ }),
678
+ autoScroll()
679
+ ].filter(isTruthy)
432
680
  };
433
681
  }, [
434
682
  space,
@@ -436,7 +684,7 @@ var Transcript = ({ classNames, transcript: object, space, model, attendableId,
436
684
  ]);
437
685
  return /* @__PURE__ */ React.createElement("div", {
438
686
  ref: parentRef,
439
- className: mx("flex grow overflow-hidden", editorWidth, classNames),
687
+ className: mx("flex grow overflow-hidden container-max-width", classNames),
440
688
  "data-popover-collision-boundary": true
441
689
  });
442
690
  } finally {
@@ -444,284 +692,6 @@ var Transcript = ({ classNames, transcript: object, space, model, attendableId,
444
692
  }
445
693
  };
446
694
 
447
- // 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 = "/__w/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
- // 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
- // 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
- // src/hooks/useTranscriber.ts
624
- import { useEffect as useEffect4, useMemo as useMemo2 } from "react";
625
- import { useCapabilities } from "@dxos/app-framework";
626
-
627
- // src/capabilities/index.ts
628
- import { lazy } from "@dxos/app-framework";
629
- var IntentResolver = lazy(() => import("./intent-resolver-YMN5SXNC.mjs"));
630
- var ReactSurface = lazy(() => import("./react-surface-QRDJOHN5.mjs"));
631
- var Transcriber = lazy(() => import("./transcriber-YUTEVANE.mjs"));
632
-
633
- // src/hooks/useTranscriber.ts
634
- var useTranscriber = ({ audioStreamTrack, recorderConfig, transcriberConfig, onSegments }) => {
635
- const [getTranscriber] = useCapabilities(TranscriptionCapabilities.Transcriber);
636
- const transcriber = useMemo2(() => {
637
- if (!getTranscriber || !audioStreamTrack || !onSegments) {
638
- return void 0;
639
- }
640
- return getTranscriber({
641
- audioStreamTrack,
642
- recorderConfig,
643
- transcriberConfig,
644
- onSegments
645
- });
646
- }, [
647
- getTranscriber,
648
- audioStreamTrack,
649
- recorderConfig,
650
- transcriberConfig,
651
- onSegments
652
- ]);
653
- useEffect4(() => {
654
- return () => {
655
- void transcriber?.close();
656
- };
657
- }, [
658
- transcriber
659
- ]);
660
- return transcriber;
661
- };
662
-
663
- // 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 = "/__w/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
695
  // src/components/TranscriptContainer.tsx
726
696
  var TranscriptionContainer = ({ transcript: transcript2 }) => {
727
697
  var _effect = _useSignals2();
@@ -732,10 +702,8 @@ var TranscriptionContainer = ({ transcript: transcript2 }) => {
732
702
  const queue = useQueue(transcript2.queue.dxn, {
733
703
  pollInterval: 1e3
734
704
  });
735
- const model = useQueueModelAdapter(renderMarkdown(members), queue);
736
- return /* @__PURE__ */ React2.createElement(StackItem.Content, {
737
- classNames: "container-max-width pli-2"
738
- }, /* @__PURE__ */ React2.createElement(Transcript, {
705
+ const model = useQueueModelAdapter(renderByline(members), queue);
706
+ return /* @__PURE__ */ React2.createElement(StackItem.Content, null, /* @__PURE__ */ React2.createElement(TranscriptView, {
739
707
  attendableId,
740
708
  space,
741
709
  model,
@@ -748,8 +716,8 @@ var TranscriptionContainer = ({ transcript: transcript2 }) => {
748
716
  var TranscriptContainer_default = TranscriptionContainer;
749
717
 
750
718
  export {
751
- renderMarkdown,
752
- Transcript,
719
+ renderByline,
720
+ TranscriptView,
753
721
  useAudioFile,
754
722
  useAudioTrack,
755
723
  useQueueModelAdapter,
@@ -757,8 +725,9 @@ export {
757
725
  useVoiceInput,
758
726
  TranscriptionContainer,
759
727
  TranscriptContainer_default,
728
+ BlueprintDefinition,
760
729
  IntentResolver,
761
730
  ReactSurface,
762
731
  Transcriber
763
732
  };
764
- //# sourceMappingURL=chunk-TJKAO7VR.mjs.map
733
+ //# sourceMappingURL=chunk-K4AZOB5Y.mjs.map