@dxos/plugin-transcription 0.8.3 → 0.8.4-main.1da679c

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