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