@dxos/plugin-transcription 0.8.3 → 0.8.4-main.c1de068

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 (124) hide show
  1. package/dist/lib/browser/TranscriptContainer-6WCKCXQ6.mjs +11 -0
  2. package/dist/lib/browser/{chunk-UDCCT32F.mjs → chunk-4FJIYH7T.mjs} +3 -3
  3. package/dist/lib/browser/{chunk-53AXUEIQ.mjs → chunk-5KPYIC3N.mjs} +34 -35
  4. package/dist/lib/browser/chunk-5KPYIC3N.mjs.map +7 -0
  5. package/dist/lib/browser/{chunk-GOF7MJNV.mjs → chunk-5WH45KBY.mjs} +2 -2
  6. package/dist/lib/browser/{chunk-IQ5ZRMHZ.mjs → chunk-FFEPEPCU.mjs} +12 -12
  7. package/dist/lib/browser/chunk-FFEPEPCU.mjs.map +7 -0
  8. package/dist/lib/browser/{chunk-OSISJM2F.mjs → chunk-R7INNNUQ.mjs} +4 -4
  9. package/dist/lib/browser/{chunk-W2KNYJD6.mjs → chunk-U6QBOGTN.mjs} +3 -3
  10. package/dist/lib/browser/{chunk-W2KNYJD6.mjs.map → chunk-U6QBOGTN.mjs.map} +1 -1
  11. package/dist/lib/browser/index.mjs +12 -12
  12. package/dist/lib/browser/index.mjs.map +3 -3
  13. package/dist/lib/browser/{intent-resolver-BGADCHVM.mjs → intent-resolver-3O33MMP5.mjs} +4 -4
  14. package/dist/lib/browser/meta.json +1 -1
  15. package/dist/lib/browser/{react-surface-HMJS5FSS.mjs → react-surface-E5D5AE3F.mjs} +7 -7
  16. package/dist/lib/browser/{transcriber-OYPLZFG5.mjs → transcriber-PXT4QBFY.mjs} +6 -6
  17. package/dist/lib/browser/types/index.mjs +2 -2
  18. package/dist/lib/node-esm/{TranscriptContainer-G75LDEO5.mjs → TranscriptContainer-VBAOM5DG.mjs} +4 -4
  19. package/dist/lib/node-esm/{chunk-PRL64SRU.mjs → chunk-HT3W7LDP.mjs} +12 -12
  20. package/dist/lib/node-esm/chunk-HT3W7LDP.mjs.map +7 -0
  21. package/dist/lib/node-esm/{chunk-MFJPEIVB.mjs → chunk-RHF2ALML.mjs} +3 -3
  22. package/dist/lib/node-esm/{chunk-MFJPEIVB.mjs.map → chunk-RHF2ALML.mjs.map} +1 -1
  23. package/dist/lib/node-esm/{chunk-56QHOX4A.mjs → chunk-TJKAO7VR.mjs} +34 -35
  24. package/dist/lib/node-esm/chunk-TJKAO7VR.mjs.map +7 -0
  25. package/dist/lib/node-esm/{chunk-FH75X4JC.mjs → chunk-U65ZWK3L.mjs} +4 -4
  26. package/dist/lib/node-esm/{chunk-TXMDLLBR.mjs → chunk-XMUCZBP3.mjs} +2 -2
  27. package/dist/lib/node-esm/{chunk-MFJO7EKD.mjs → chunk-Y2B4HWSS.mjs} +3 -3
  28. package/dist/lib/node-esm/index.mjs +12 -12
  29. package/dist/lib/node-esm/index.mjs.map +3 -3
  30. package/dist/lib/node-esm/{intent-resolver-5LVCYSJS.mjs → intent-resolver-YMN5SXNC.mjs} +4 -4
  31. package/dist/lib/node-esm/meta.json +1 -1
  32. package/dist/lib/node-esm/{react-surface-JGQSYGRR.mjs → react-surface-QRDJOHN5.mjs} +7 -7
  33. package/dist/lib/node-esm/{transcriber-TVG2MBBN.mjs → transcriber-YUTEVANE.mjs} +6 -6
  34. package/dist/lib/node-esm/types/index.mjs +2 -2
  35. package/dist/types/src/capabilities/capabilities.d.ts +2 -2
  36. package/dist/types/src/capabilities/capabilities.d.ts.map +1 -1
  37. package/dist/types/src/components/Transcript/Transcript.stories.d.ts +1 -1
  38. package/dist/types/src/components/Transcript/Transcript.stories.d.ts.map +1 -1
  39. package/dist/types/src/components/TranscriptContainer.d.ts +4 -3
  40. package/dist/types/src/components/TranscriptContainer.d.ts.map +1 -1
  41. package/dist/types/src/components/index.d.ts +1 -4
  42. package/dist/types/src/components/index.d.ts.map +1 -1
  43. package/dist/types/src/components/stories/FileTranscription.stories.d.ts +1 -1
  44. package/dist/types/src/components/stories/FileTranscription.stories.d.ts.map +1 -1
  45. package/dist/types/src/components/stories/KeyWordRecognition.stories.d.ts +1 -1
  46. package/dist/types/src/components/stories/KeyWordRecognition.stories.d.ts.map +1 -1
  47. package/dist/types/src/components/stories/MicrophoneTranscription.stories.d.ts +1 -1
  48. package/dist/types/src/components/stories/MicrophoneTranscription.stories.d.ts.map +1 -1
  49. package/dist/types/src/hooks/useTranscriber.d.ts +1 -1
  50. package/dist/types/src/segments-normalization/normalization.d.ts +150 -63
  51. package/dist/types/src/segments-normalization/normalization.d.ts.map +1 -1
  52. package/dist/types/src/testing/testing.d.ts +2 -2
  53. package/dist/types/src/testing/testing.d.ts.map +1 -1
  54. package/dist/types/src/transcriber/index.d.ts +1 -1
  55. package/dist/types/src/transcriber/index.d.ts.map +1 -1
  56. package/dist/types/src/transcriber/transcriber.d.ts +1 -1
  57. package/dist/types/src/transcriber/transcriber.d.ts.map +1 -1
  58. package/dist/types/src/translations.d.ts +11 -11
  59. package/dist/types/src/translations.d.ts.map +1 -1
  60. package/dist/types/tsconfig.tsbuildinfo +1 -1
  61. package/package.json +57 -57
  62. package/src/TranscriptionPlugin.tsx +1 -1
  63. package/src/capabilities/capabilities.ts +2 -2
  64. package/src/components/Transcript/Transcript.stories.tsx +2 -2
  65. package/src/components/Transcript/Transcript.tsx +2 -2
  66. package/src/components/Transcript/transcript-extension.ts +2 -2
  67. package/src/components/TranscriptContainer.tsx +8 -3
  68. package/src/components/stories/FileTranscription.stories.tsx +16 -13
  69. package/src/components/stories/KeyWordRecognition.stories.tsx +1 -1
  70. package/src/components/stories/MicrophoneTranscription.stories.tsx +11 -9
  71. package/src/hooks/useTranscriber.ts +5 -5
  72. package/src/model/model.test.ts +8 -8
  73. package/src/segments-normalization/normalization.test.ts +18 -20
  74. package/src/segments-normalization/normalization.ts +19 -10
  75. package/src/testing/testing.ts +10 -10
  76. package/src/transcriber/index.ts +1 -1
  77. package/src/transcriber/transcriber.browser.test.ts +2 -2
  78. package/src/transcriber/transcriber.ts +3 -6
  79. package/src/transcriber/transcription-manager.ts +3 -3
  80. package/src/translations.ts +6 -4
  81. package/dist/lib/browser/TranscriptContainer-H3AZQ4CQ.mjs +0 -11
  82. package/dist/lib/browser/chunk-53AXUEIQ.mjs.map +0 -7
  83. package/dist/lib/browser/chunk-IQ5ZRMHZ.mjs.map +0 -7
  84. package/dist/lib/node/TranscriptContainer-KIG3GMAB.cjs +0 -32
  85. package/dist/lib/node/TranscriptContainer-KIG3GMAB.cjs.map +0 -7
  86. package/dist/lib/node/chunk-3PYT3BDM.cjs +0 -40
  87. package/dist/lib/node/chunk-3PYT3BDM.cjs.map +0 -7
  88. package/dist/lib/node/chunk-6LW5RA3K.cjs +0 -75
  89. package/dist/lib/node/chunk-6LW5RA3K.cjs.map +0 -7
  90. package/dist/lib/node/chunk-AFUZI63A.cjs +0 -42
  91. package/dist/lib/node/chunk-AFUZI63A.cjs.map +0 -7
  92. package/dist/lib/node/chunk-CVUN3UO7.cjs +0 -778
  93. package/dist/lib/node/chunk-CVUN3UO7.cjs.map +0 -7
  94. package/dist/lib/node/chunk-FKDJNJ57.cjs +0 -35
  95. package/dist/lib/node/chunk-FKDJNJ57.cjs.map +0 -7
  96. package/dist/lib/node/chunk-ZFAUMZXE.cjs +0 -518
  97. package/dist/lib/node/chunk-ZFAUMZXE.cjs.map +0 -7
  98. package/dist/lib/node/index.cjs +0 -133
  99. package/dist/lib/node/index.cjs.map +0 -7
  100. package/dist/lib/node/intent-resolver-LL3TTI4H.cjs +0 -45
  101. package/dist/lib/node/intent-resolver-LL3TTI4H.cjs.map +0 -7
  102. package/dist/lib/node/meta.json +0 -1
  103. package/dist/lib/node/react-surface-N25TBBG4.cjs +0 -56
  104. package/dist/lib/node/react-surface-N25TBBG4.cjs.map +0 -7
  105. package/dist/lib/node/transcriber-6J4FVFSZ.cjs +0 -68
  106. package/dist/lib/node/transcriber-6J4FVFSZ.cjs.map +0 -7
  107. package/dist/lib/node/types/index.cjs +0 -36
  108. package/dist/lib/node/types/index.cjs.map +0 -7
  109. package/dist/lib/node-esm/chunk-56QHOX4A.mjs.map +0 -7
  110. package/dist/lib/node-esm/chunk-PRL64SRU.mjs.map +0 -7
  111. /package/dist/lib/browser/{TranscriptContainer-H3AZQ4CQ.mjs.map → TranscriptContainer-6WCKCXQ6.mjs.map} +0 -0
  112. /package/dist/lib/browser/{chunk-UDCCT32F.mjs.map → chunk-4FJIYH7T.mjs.map} +0 -0
  113. /package/dist/lib/browser/{chunk-GOF7MJNV.mjs.map → chunk-5WH45KBY.mjs.map} +0 -0
  114. /package/dist/lib/browser/{chunk-OSISJM2F.mjs.map → chunk-R7INNNUQ.mjs.map} +0 -0
  115. /package/dist/lib/browser/{intent-resolver-BGADCHVM.mjs.map → intent-resolver-3O33MMP5.mjs.map} +0 -0
  116. /package/dist/lib/browser/{react-surface-HMJS5FSS.mjs.map → react-surface-E5D5AE3F.mjs.map} +0 -0
  117. /package/dist/lib/browser/{transcriber-OYPLZFG5.mjs.map → transcriber-PXT4QBFY.mjs.map} +0 -0
  118. /package/dist/lib/node-esm/{TranscriptContainer-G75LDEO5.mjs.map → TranscriptContainer-VBAOM5DG.mjs.map} +0 -0
  119. /package/dist/lib/node-esm/{chunk-FH75X4JC.mjs.map → chunk-U65ZWK3L.mjs.map} +0 -0
  120. /package/dist/lib/node-esm/{chunk-TXMDLLBR.mjs.map → chunk-XMUCZBP3.mjs.map} +0 -0
  121. /package/dist/lib/node-esm/{chunk-MFJO7EKD.mjs.map → chunk-Y2B4HWSS.mjs.map} +0 -0
  122. /package/dist/lib/node-esm/{intent-resolver-5LVCYSJS.mjs.map → intent-resolver-YMN5SXNC.mjs.map} +0 -0
  123. /package/dist/lib/node-esm/{react-surface-JGQSYGRR.mjs.map → react-surface-QRDJOHN5.mjs.map} +0 -0
  124. /package/dist/lib/node-esm/{transcriber-TVG2MBBN.mjs.map → transcriber-YUTEVANE.mjs.map} +0 -0
@@ -1,778 +0,0 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
11
- };
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
19
- };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
- var chunk_CVUN3UO7_exports = {};
30
- __export(chunk_CVUN3UO7_exports, {
31
- IntentResolver: () => IntentResolver,
32
- ReactSurface: () => ReactSurface,
33
- Transcriber: () => Transcriber,
34
- Transcript: () => Transcript,
35
- TranscriptContainer_default: () => TranscriptContainer_default,
36
- TranscriptionContainer: () => TranscriptionContainer,
37
- renderMarkdown: () => renderMarkdown,
38
- useAudioFile: () => useAudioFile,
39
- useAudioTrack: () => useAudioTrack,
40
- useQueueModelAdapter: () => useQueueModelAdapter,
41
- useTranscriber: () => useTranscriber,
42
- useVoiceInput: () => useVoiceInput
43
- });
44
- module.exports = __toCommonJS(chunk_CVUN3UO7_exports);
45
- var import_chunk_FKDJNJ57 = require("./chunk-FKDJNJ57.cjs");
46
- var import_tracking = require("@preact-signals/safe-react/tracking");
47
- var import_react = __toESM(require("react"));
48
- var import_echo = require("@dxos/client/echo");
49
- var import_echo2 = require("@dxos/react-client/echo");
50
- var import_react_ui_stack = require("@dxos/react-ui-stack");
51
- var import_tracking2 = require("@preact-signals/safe-react/tracking");
52
- var import_react2 = __toESM(require("react"));
53
- var import_react_ui = require("@dxos/react-ui");
54
- var import_react_ui_editor = require("@dxos/react-ui-editor");
55
- var import_react_ui_theme = require("@dxos/react-ui-theme");
56
- var import_util = require("@dxos/util");
57
- var import_state = require("@codemirror/state");
58
- var import_view = require("@codemirror/view");
59
- var import_format = require("date-fns/format");
60
- var import_intervalToDuration = require("date-fns/intervalToDuration");
61
- var import_async = require("@dxos/async");
62
- var import_state2 = require("@codemirror/state");
63
- var import_async2 = require("@dxos/async");
64
- var import_invariant = require("@dxos/invariant");
65
- var import_log = require("@dxos/log");
66
- var import_react3 = require("react");
67
- var import_async3 = require("@dxos/async");
68
- var import_context = require("@dxos/context");
69
- var import_log2 = require("@dxos/log");
70
- var import_react4 = require("react");
71
- var import_react5 = require("react");
72
- var import_react6 = require("react");
73
- var import_app_framework = require("@dxos/app-framework");
74
- var import_app_framework2 = require("@dxos/app-framework");
75
- var import_react7 = require("react");
76
- var import_async4 = require("@dxos/async");
77
- var import_context2 = require("@dxos/context");
78
- var import_log3 = require("@dxos/log");
79
- var import_react_ui_sfx = require("@dxos/react-ui-sfx");
80
- var __dxlog_file = "/home/runner/work/dxos/dxos/packages/plugins/plugin-transcription/src/model/model.ts";
81
- var DocumentAdapter = class {
82
- constructor(_view) {
83
- this._view = _view;
84
- }
85
- /** The document must always have at least one line. */
86
- lineCount() {
87
- return this._view.state.doc.lines - 1;
88
- }
89
- replaceLines(from, remove, insert) {
90
- (0, import_log.log)("replaceLines", {
91
- count: this._view.state.doc.lines,
92
- from,
93
- remove,
94
- insert
95
- }, {
96
- F: __dxlog_file,
97
- L: 39,
98
- S: this,
99
- C: (f, a) => f(...a)
100
- });
101
- const numLines = this._view.state.doc.lines;
102
- const posFrom = this._view.state.doc.line(from).from;
103
- const posTo = remove === 0 ? posFrom : this._view.state.doc.line(Math.min(numLines, from + remove)).from;
104
- let text = insert.join("\n");
105
- if (posTo === this._view.state.doc.length) {
106
- text += "\n";
107
- }
108
- this._view.dispatch({
109
- changes: {
110
- from: posFrom,
111
- to: posTo,
112
- insert: text
113
- }
114
- });
115
- }
116
- };
117
- var SerializationModel = class {
118
- constructor(_renderer, initialChunks = []) {
119
- this._renderer = _renderer;
120
- this._chunks = [];
121
- this._chunkLineCounts = /* @__PURE__ */ new Map();
122
- this._lineToChunk = /* @__PURE__ */ new Map();
123
- this._changes = [];
124
- this.update = new import_async2.Event();
125
- initialChunks.forEach((chunk) => {
126
- this.appendChunk(chunk);
127
- });
128
- }
129
- toJSON() {
130
- return {
131
- chunks: this._chunks.length,
132
- changes: this._changes.length
133
- };
134
- }
135
- get doc() {
136
- return import_state2.Text.of([
137
- ...this._chunks.flatMap((chunk, index) => this._renderer(chunk, index)),
138
- ""
139
- ]);
140
- }
141
- get chunks() {
142
- return this._chunks;
143
- }
144
- /**
145
- * Get the block ID at the given line number.
146
- */
147
- getChunkAtLine(line) {
148
- return this._lineToChunk.get(line);
149
- }
150
- reset() {
151
- this._chunks.length = 0;
152
- this._chunkLineCounts.clear();
153
- this._lineToChunk.clear();
154
- this.update.emit();
155
- return this;
156
- }
157
- appendChunk(chunk) {
158
- const index = this._chunks.length;
159
- this._chunks.push(chunk);
160
- this._changes.push({
161
- type: "append",
162
- index,
163
- chunk
164
- });
165
- this.update.emit();
166
- return this;
167
- }
168
- updateChunk(chunk) {
169
- const index = this._chunks.findIndex((c) => c.id === chunk.id);
170
- (0, import_invariant.invariant)(index !== -1, void 0, {
171
- F: __dxlog_file,
172
- L: 147,
173
- S: this,
174
- A: [
175
- "index !== -1",
176
- ""
177
- ]
178
- });
179
- this._chunks[index] = chunk;
180
- this._changes.push({
181
- type: "update",
182
- index,
183
- chunk
184
- });
185
- this.update.emit();
186
- return this;
187
- }
188
- deleteBlock(id) {
189
- const index = this._chunks.findIndex((c) => c.id === id);
190
- (0, import_invariant.invariant)(index !== -1, void 0, {
191
- F: __dxlog_file,
192
- L: 156,
193
- S: this,
194
- A: [
195
- "index !== -1",
196
- ""
197
- ]
198
- });
199
- this._chunks.splice(index, 1);
200
- this._changes.push({
201
- type: "delete",
202
- index,
203
- id
204
- });
205
- this.update.emit();
206
- return this;
207
- }
208
- /**
209
- * Syncs the tracked changes with the ChunkDocument.
210
- */
211
- sync(document2) {
212
- (0, import_log.log)("sync", {
213
- changes: this._changes
214
- }, {
215
- F: __dxlog_file,
216
- L: 167,
217
- S: this,
218
- C: (f, a) => f(...a)
219
- });
220
- for (const change of this._changes) {
221
- switch (change.type) {
222
- case "append": {
223
- const lines = this._renderer(change.chunk, change.index);
224
- const lastLine = document2.lineCount();
225
- document2.replaceLines(lastLine + 1, 0, lines);
226
- break;
227
- }
228
- case "update": {
229
- let lineStart = 1;
230
- for (let i = 0; i < change.index; i++) {
231
- lineStart += this._chunkLineCounts.get(this._chunks[i].id);
232
- }
233
- const previousLineCount = this._chunkLineCounts.get(change.chunk.id);
234
- const newLines = this._renderer(change.chunk, change.index);
235
- document2.replaceLines(lineStart, previousLineCount, newLines);
236
- break;
237
- }
238
- case "delete": {
239
- let lineStart = 1;
240
- for (let i = 0; i < change.index; i++) {
241
- lineStart += this._chunkLineCounts.get(this._chunks[i].id);
242
- }
243
- const previousLineCount = this._chunkLineCounts.get(change.id);
244
- document2.replaceLines(lineStart, previousLineCount, []);
245
- break;
246
- }
247
- }
248
- }
249
- this._lineToChunk.clear();
250
- let currentLine = 1;
251
- for (const [index, chunk] of this._chunks.entries()) {
252
- const lineCount = this._renderer(chunk, index).length;
253
- this._chunkLineCounts.set(chunk.id, lineCount);
254
- this._lineToChunk.set(currentLine, chunk);
255
- currentLine += lineCount;
256
- }
257
- const chunkIds = new Set(this._chunks.map((chunk) => chunk.id));
258
- for (const id of this._chunkLineCounts.keys()) {
259
- if (!chunkIds.has(id)) {
260
- this._chunkLineCounts.delete(id);
261
- }
262
- }
263
- this._changes.length = 0;
264
- return this;
265
- }
266
- };
267
- var transcript = ({ model, started, renderButton }) => {
268
- return [
269
- // Show timestamps in the gutter.
270
- (0, import_view.gutter)({
271
- class: "cm-timestamp-gutter",
272
- lineMarkerChange: (update) => update.docChanged || update.viewportChanged,
273
- markers: (view) => {
274
- const start = getStartTime(started, model.chunks[0]);
275
- const builder = new import_state.RangeSetBuilder();
276
- for (const { from, to } of view.visibleRanges) {
277
- let line = view.state.doc.lineAt(from);
278
- while (line.from <= to) {
279
- const block = model.getChunkAtLine(line.number)?.blocks[0];
280
- const timestamp = block?.type === "transcription" && block.started;
281
- if (timestamp) {
282
- builder.add(line.from, line.from, new TimestampMarker(line.number, new Date(timestamp), start));
283
- }
284
- if (line.to + 1 > view.state.doc.length) {
285
- break;
286
- }
287
- line = view.state.doc.lineAt(line.to + 1);
288
- }
289
- }
290
- return builder.finish();
291
- }
292
- }),
293
- // Listen for model updates.
294
- import_view.ViewPlugin.fromClass(class {
295
- constructor(view) {
296
- this._initialized = false;
297
- this._adapter = new DocumentAdapter(view);
298
- const scroller = view.scrollDOM;
299
- let isAutoScrolling = false;
300
- let hasScrolled = false;
301
- let timeout;
302
- const scrollToBottom = (smooth = false) => {
303
- scroller.style.scrollBehavior = smooth ? "smooth" : "";
304
- scroller.classList.add("cm-hide-scrollbar");
305
- isAutoScrolling = true;
306
- clearTimeout(timeout);
307
- timeout = setTimeout(() => {
308
- this._controls?.classList.add("opacity-0");
309
- scroller.classList.remove("cm-hide-scrollbar");
310
- isAutoScrolling = false;
311
- }, 500);
312
- view.dispatch({
313
- effects: import_view.EditorView.scrollIntoView(view.state.doc.length, {
314
- y: "end"
315
- })
316
- });
317
- };
318
- if (renderButton) {
319
- this._controls = document.createElement("div");
320
- this._controls.classList.add("cm-controls", "transition-opacity", "duration-300", "opacity-0");
321
- view.dom.appendChild(this._controls);
322
- renderButton(this._controls, {
323
- onClick: () => {
324
- scrollToBottom(false);
325
- }
326
- }, view);
327
- }
328
- this._cleanup = (0, import_async.combine)((0, import_async.addEventListener)(view.scrollDOM, "scroll", () => {
329
- if (!isAutoScrolling) {
330
- hasScrolled = true;
331
- this._controls?.classList.remove("opacity-0");
332
- }
333
- }), model.update.on(() => {
334
- const autoScroll = scroller.scrollHeight - scroller.scrollTop - scroller.clientHeight === 0 || !hasScrolled;
335
- model.sync(this._adapter);
336
- if (autoScroll) {
337
- scrollToBottom(true);
338
- }
339
- }));
340
- }
341
- update(update) {
342
- if (!this._initialized) {
343
- this._initialized = true;
344
- setTimeout(() => {
345
- model.sync(this._adapter);
346
- });
347
- }
348
- }
349
- destroy() {
350
- this._controls?.remove();
351
- this._cleanup();
352
- }
353
- }),
354
- import_view.EditorView.theme({
355
- ".cm-scroller": {
356
- overflowY: "scroll"
357
- },
358
- ".cm-hide-scrollbar": {
359
- scrollbarWidth: "none",
360
- "-ms-overflow-style": "none"
361
- },
362
- ".cm-hide-scrollbar::-webkit-scrollbar": {
363
- display: "none"
364
- },
365
- ".cm-controls": {
366
- position: "absolute",
367
- bottom: "0.5rem",
368
- right: "0.5rem",
369
- zIndex: 1e3
370
- },
371
- ".cm-line": {
372
- paddingRight: "1rem"
373
- },
374
- ".cm-timestamp-gutter": {
375
- width: "6rem",
376
- paddingRight: "1rem"
377
- },
378
- ".cm-timestamp-gutter > .cm-gutterElement > div": {
379
- display: "inline-flex",
380
- textAlign: "right",
381
- padding: "3px"
382
- }
383
- })
384
- ];
385
- };
386
- var TimestampMarker = class extends import_view.GutterMarker {
387
- constructor(_line, _timestamp, _started) {
388
- super(), this._line = _line, this._timestamp = _timestamp, this._started = _started;
389
- }
390
- eq(other) {
391
- return other._timestamp === this._timestamp;
392
- }
393
- toDOM(view) {
394
- const el = document.createElement("div");
395
- el.className = "text-sm text-subdued hover:bg-hoverSurface cursor-pointer";
396
- el.textContent = formatTimestamp(this._timestamp, this._started);
397
- el.onclick = () => {
398
- const pos = view.state.doc.line(this._line).from;
399
- view.dispatch({
400
- effects: import_view.EditorView.scrollIntoView(pos, {
401
- y: "start"
402
- })
403
- });
404
- };
405
- return el;
406
- }
407
- };
408
- var getStartTime = (started, message) => {
409
- if (started) {
410
- return started;
411
- }
412
- if (message?.blocks[0]?.type === "transcription" && message.blocks[0].started) {
413
- return new Date(message.blocks[0].started);
414
- }
415
- return void 0;
416
- };
417
- var formatTimestamp = (timestamp, relative) => {
418
- if (relative) {
419
- const pad = (n = 0) => String(n).padStart(2, "0");
420
- const { hours, minutes, seconds } = (0, import_intervalToDuration.intervalToDuration)({
421
- start: relative,
422
- end: timestamp
423
- });
424
- return `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;
425
- } else {
426
- return (0, import_format.format)(timestamp, "HH:mm:ss");
427
- }
428
- };
429
- var renderMarkdown = (identities) => (message, index, debug = false) => {
430
- if (message.sender.role === "assistant") {
431
- return [
432
- message.blocks.find((block) => block.type === "transcription")?.text ?? "",
433
- ""
434
- ];
435
- }
436
- const identity = identities.find((identity2) => identity2.did === message.sender.identityDid);
437
- const name = identity?.profile?.displayName ?? message.sender.contact?.target?.fullName ?? message.sender.name ?? message.sender.email ?? message.sender.identityDid;
438
- const blocks = message.blocks.filter((block) => block.type === "transcription");
439
- return [
440
- `###### ${name}` + (debug ? ` [${index}]:${message.id}` : ""),
441
- blocks.map((block) => block.text.trim()).join(" "),
442
- ""
443
- ];
444
- };
445
- var Transcript = ({ classNames, transcript: object, space, model, attendableId, ignoreAttention }) => {
446
- var _effect = (0, import_tracking2.useSignals)();
447
- try {
448
- const { themeMode } = (0, import_react_ui.useThemeContext)();
449
- const { parentRef } = (0, import_react_ui_editor.useTextEditor)(() => {
450
- return {
451
- extensions: [
452
- (0, import_react_ui_editor.createBasicExtensions)({
453
- readOnly: true,
454
- lineWrapping: true
455
- }),
456
- (0, import_react_ui_editor.createMarkdownExtensions)({
457
- themeMode
458
- }),
459
- (0, import_react_ui_editor.createThemeExtensions)({
460
- themeMode
461
- }),
462
- (0, import_react_ui_editor.decorateMarkdown)(),
463
- space && (0, import_react_ui_editor.preview)(),
464
- transcript({
465
- model,
466
- started: object?.started ? new Date(object.started) : void 0,
467
- renderButton: (0, import_react_ui_editor.createRenderer)(({ onClick }) => /* @__PURE__ */ import_react2.default.createElement(import_react_ui.IconButton, {
468
- icon: "ph--arrow-line-down--regular",
469
- iconOnly: true,
470
- label: "Scroll to bottom",
471
- onClick
472
- }))
473
- })
474
- ].filter(import_util.isNotFalsy)
475
- };
476
- }, [
477
- space,
478
- model
479
- ]);
480
- return /* @__PURE__ */ import_react2.default.createElement("div", {
481
- ref: parentRef,
482
- className: (0, import_react_ui_theme.mx)("flex grow overflow-hidden", import_react_ui_editor.editorWidth, classNames),
483
- "data-popover-collision-boundary": true
484
- });
485
- } finally {
486
- _effect.f();
487
- }
488
- };
489
- var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/plugins/plugin-transcription/src/hooks/useAudioFile.ts";
490
- var useAudioFile = (audioUrl, constraints) => {
491
- const [{ audio, stream, track }, setStream] = (0, import_react3.useState)({});
492
- (0, import_react3.useEffect)(() => {
493
- const ctx = new import_context.Context(void 0, {
494
- F: __dxlog_file2,
495
- L: 20
496
- });
497
- (0, import_async3.scheduleTask)(ctx, async () => {
498
- const response = await fetch(audioUrl);
499
- const blob = await response.blob();
500
- const objectUrl = URL.createObjectURL(blob);
501
- ctx.onDispose(() => {
502
- URL.revokeObjectURL(objectUrl);
503
- });
504
- const audio2 = new Audio();
505
- audio2.src = objectUrl;
506
- await new Promise((resolve, reject) => {
507
- audio2.addEventListener("error", (err) => {
508
- import_log2.log.error("error", {
509
- err
510
- }, {
511
- F: __dxlog_file2,
512
- L: 37,
513
- S: void 0,
514
- C: (f, a) => f(...a)
515
- });
516
- reject(err);
517
- }, {
518
- once: true
519
- });
520
- audio2.addEventListener("canplay", async () => {
521
- import_log2.log.info("starting...", void 0, {
522
- F: __dxlog_file2,
523
- L: 45,
524
- S: void 0,
525
- C: (f, a) => f(...a)
526
- });
527
- try {
528
- await audio2.play();
529
- resolve();
530
- } catch (playError) {
531
- import_log2.log.error("Play failed", {
532
- playError
533
- }, {
534
- F: __dxlog_file2,
535
- L: 51,
536
- S: void 0,
537
- C: (f, a) => f(...a)
538
- });
539
- resolve();
540
- }
541
- }, {
542
- once: true
543
- });
544
- audio2.load();
545
- });
546
- const audioCtx = new AudioContext();
547
- if (audioCtx.state === "suspended") {
548
- await audioCtx.resume();
549
- }
550
- const destination = audioCtx.createMediaStreamDestination();
551
- destination.channelCount = 1;
552
- const source = audioCtx.createMediaElementSource(audio2);
553
- source.connect(destination);
554
- const track2 = destination.stream.getAudioTracks()[0];
555
- if (constraints) {
556
- await track2.applyConstraints(constraints).catch((err) => import_log2.log.catch(err, void 0, {
557
- F: __dxlog_file2,
558
- L: 75,
559
- S: void 0,
560
- C: (f, a) => f(...a)
561
- }));
562
- }
563
- setStream({
564
- audio: audio2,
565
- stream: destination.stream,
566
- track: destination.stream.getAudioTracks()[0]
567
- });
568
- });
569
- return () => {
570
- void ctx.dispose();
571
- };
572
- }, [
573
- audioUrl
574
- ]);
575
- return {
576
- audio,
577
- stream,
578
- track
579
- };
580
- };
581
- var useAudioTrack = (active, constraints) => {
582
- const [track, setTrack] = (0, import_react4.useState)();
583
- (0, import_react4.useEffect)(() => {
584
- if (!active) {
585
- track?.stop();
586
- setTrack(void 0);
587
- return;
588
- }
589
- const initAudio = async () => {
590
- const audio = new Audio();
591
- audio.srcObject = await navigator.mediaDevices.getUserMedia({
592
- audio: constraints ?? true
593
- });
594
- const [track2] = audio.srcObject.getAudioTracks();
595
- if (track2) {
596
- setTrack(track2);
597
- }
598
- };
599
- if (active) {
600
- void initAudio();
601
- }
602
- }, [
603
- active
604
- ]);
605
- return track;
606
- };
607
- var useQueueModelAdapter = (renderer, queue, initialChunks = []) => {
608
- const model = (0, import_react5.useMemo)(() => new SerializationModel(renderer, initialChunks), [
609
- queue
610
- ]);
611
- const [loaded, setLoaded] = (0, import_react5.useState)(false);
612
- (0, import_react5.useEffect)(() => {
613
- if (!queue) {
614
- return;
615
- }
616
- const update = () => {
617
- for (const block of queue?.objects ?? []) {
618
- model.appendChunk(block);
619
- }
620
- setLoaded(true);
621
- };
622
- let i;
623
- if (queue.isLoading) {
624
- i = setInterval(() => {
625
- if (!queue?.isLoading) {
626
- clearInterval(i);
627
- update();
628
- }
629
- }, 1e3);
630
- } else {
631
- update();
632
- }
633
- return () => clearTimeout(i);
634
- }, [
635
- model,
636
- queue
637
- ]);
638
- (0, import_react5.useEffect)(() => {
639
- if (!loaded || !queue || model.chunks.length === queue.objects.length) {
640
- return;
641
- }
642
- const chunk = queue.objects.at(-1);
643
- if (chunk) {
644
- model.appendChunk(chunk);
645
- }
646
- }, [
647
- model,
648
- loaded,
649
- queue?.objects.length
650
- ]);
651
- return model;
652
- };
653
- var IntentResolver = (0, import_app_framework2.lazy)(() => import("./intent-resolver-LL3TTI4H.cjs"));
654
- var ReactSurface = (0, import_app_framework2.lazy)(() => import("./react-surface-N25TBBG4.cjs"));
655
- var Transcriber = (0, import_app_framework2.lazy)(() => import("./transcriber-6J4FVFSZ.cjs"));
656
- var useTranscriber = ({ audioStreamTrack, onSegments, transcriberConfig, recorderConfig }) => {
657
- const [getTranscriber] = (0, import_app_framework.useCapabilities)(import_chunk_FKDJNJ57.TranscriptionCapabilities.Transcriber);
658
- const transcriber = (0, import_react6.useMemo)(() => {
659
- if (!onSegments || !audioStreamTrack || !getTranscriber) {
660
- return void 0;
661
- }
662
- return getTranscriber({
663
- audioStreamTrack,
664
- onSegments,
665
- transcriberConfig,
666
- recorderConfig
667
- });
668
- }, [
669
- audioStreamTrack,
670
- onSegments,
671
- getTranscriber,
672
- transcriberConfig,
673
- recorderConfig
674
- ]);
675
- (0, import_react6.useEffect)(() => {
676
- return () => {
677
- void transcriber?.close();
678
- };
679
- }, [
680
- transcriber
681
- ]);
682
- return transcriber;
683
- };
684
- var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/plugins/plugin-transcription/src/hooks/useVoiceInput.ts";
685
- var useVoiceInput = ({ active, onUpdate }) => {
686
- const soundStart = (0, import_react_ui_sfx.useSoundEffect)("StartRecording");
687
- const soundStop = (0, import_react_ui_sfx.useSoundEffect)("StopRecording");
688
- const handleSegments = (0, import_react7.useCallback)(async (segments) => {
689
- const text = segments.map((str) => str.text.trim().replace(/[^\w\s]/g, "")).join(" ");
690
- onUpdate(text);
691
- }, []);
692
- const [recording, setRecording] = (0, import_react7.useState)(false);
693
- const track = useAudioTrack(active);
694
- const transcriber = useTranscriber({
695
- audioStreamTrack: track,
696
- onSegments: handleSegments
697
- });
698
- (0, import_react7.useEffect)(() => {
699
- const ctx = new import_context2.Context(void 0, {
700
- F: __dxlog_file3,
701
- L: 43
702
- });
703
- (0, import_async4.scheduleMicroTask)(ctx, async () => {
704
- if (active && transcriber) {
705
- await transcriber.open();
706
- import_log3.log.info("starting...", void 0, {
707
- F: __dxlog_file3,
708
- L: 47,
709
- S: void 0,
710
- C: (f, a) => f(...a)
711
- });
712
- setRecording(true);
713
- void soundStart.play();
714
- transcriber.startChunksRecording();
715
- } else if (!active && transcriber?.isOpen) {
716
- transcriber?.stopChunksRecording();
717
- await transcriber?.close();
718
- import_log3.log.info("stopped", void 0, {
719
- F: __dxlog_file3,
720
- L: 54,
721
- S: void 0,
722
- C: (f, a) => f(...a)
723
- });
724
- setRecording(false);
725
- void soundStop.play();
726
- }
727
- });
728
- return () => {
729
- void ctx.dispose();
730
- };
731
- }, [
732
- active,
733
- transcriber
734
- ]);
735
- return {
736
- recording
737
- };
738
- };
739
- var TranscriptionContainer = ({ role, transcript: transcript2 }) => {
740
- var _effect = (0, import_tracking.useSignals)();
741
- try {
742
- const attendableId = (0, import_echo.fullyQualifiedId)(transcript2);
743
- const space = (0, import_echo.getSpace)(transcript2);
744
- const members = (0, import_echo2.useMembers)(space?.key).map((member) => member.identity);
745
- const queue = (0, import_echo2.useQueue)(transcript2.queue.dxn, {
746
- pollInterval: 1e3
747
- });
748
- const model = useQueueModelAdapter(renderMarkdown(members), queue);
749
- return /* @__PURE__ */ import_react.default.createElement(import_react_ui_stack.StackItem.Content, {
750
- role,
751
- classNames: "container-max-width pli-2"
752
- }, /* @__PURE__ */ import_react.default.createElement(Transcript, {
753
- attendableId,
754
- space,
755
- model,
756
- transcript: transcript2
757
- }));
758
- } finally {
759
- _effect.f();
760
- }
761
- };
762
- var TranscriptContainer_default = TranscriptionContainer;
763
- // Annotate the CommonJS export names for ESM import in node:
764
- 0 && (module.exports = {
765
- IntentResolver,
766
- ReactSurface,
767
- Transcriber,
768
- Transcript,
769
- TranscriptContainer_default,
770
- TranscriptionContainer,
771
- renderMarkdown,
772
- useAudioFile,
773
- useAudioTrack,
774
- useQueueModelAdapter,
775
- useTranscriber,
776
- useVoiceInput
777
- });
778
- //# sourceMappingURL=chunk-CVUN3UO7.cjs.map