@dxos/plugin-transcription 0.7.5-main.b19bfc8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (172) hide show
  1. package/LICENSE +8 -0
  2. package/README.md +15 -0
  3. package/dist/lib/browser/TranscriptContainer-G7NUUBPJ.mjs +10 -0
  4. package/dist/lib/browser/TranscriptContainer-G7NUUBPJ.mjs.map +7 -0
  5. package/dist/lib/browser/app-graph-builder-ZSSJIFY7.mjs +7 -0
  6. package/dist/lib/browser/app-graph-builder-ZSSJIFY7.mjs.map +7 -0
  7. package/dist/lib/browser/chunk-7V6ZINS5.mjs +8 -0
  8. package/dist/lib/browser/chunk-7V6ZINS5.mjs.map +7 -0
  9. package/dist/lib/browser/chunk-D4ZMHRVK.mjs +241 -0
  10. package/dist/lib/browser/chunk-D4ZMHRVK.mjs.map +7 -0
  11. package/dist/lib/browser/chunk-QIHUPVQD.mjs +80 -0
  12. package/dist/lib/browser/chunk-QIHUPVQD.mjs.map +7 -0
  13. package/dist/lib/browser/chunk-ZMES3U2D.mjs +78 -0
  14. package/dist/lib/browser/chunk-ZMES3U2D.mjs.map +7 -0
  15. package/dist/lib/browser/index.mjs +652 -0
  16. package/dist/lib/browser/index.mjs.map +7 -0
  17. package/dist/lib/browser/intent-resolver-EAR2TFK2.mjs +32 -0
  18. package/dist/lib/browser/intent-resolver-EAR2TFK2.mjs.map +7 -0
  19. package/dist/lib/browser/meta.json +1 -0
  20. package/dist/lib/browser/react-surface-IXF7SETX.mjs +26 -0
  21. package/dist/lib/browser/react-surface-IXF7SETX.mjs.map +7 -0
  22. package/dist/lib/browser/types/index.mjs +17 -0
  23. package/dist/lib/browser/types/index.mjs.map +7 -0
  24. package/dist/lib/node/TranscriptContainer-IKMCPYQ2.cjs +31 -0
  25. package/dist/lib/node/TranscriptContainer-IKMCPYQ2.cjs.map +7 -0
  26. package/dist/lib/node/app-graph-builder-YFBX3OTP.cjs +26 -0
  27. package/dist/lib/node/app-graph-builder-YFBX3OTP.cjs.map +7 -0
  28. package/dist/lib/node/chunk-JBN3P6ZF.cjs +97 -0
  29. package/dist/lib/node/chunk-JBN3P6ZF.cjs.map +7 -0
  30. package/dist/lib/node/chunk-SQHF7N3B.cjs +40 -0
  31. package/dist/lib/node/chunk-SQHF7N3B.cjs.map +7 -0
  32. package/dist/lib/node/chunk-UIHEGU6Q.cjs +103 -0
  33. package/dist/lib/node/chunk-UIHEGU6Q.cjs.map +7 -0
  34. package/dist/lib/node/chunk-Y2GCR535.cjs +267 -0
  35. package/dist/lib/node/chunk-Y2GCR535.cjs.map +7 -0
  36. package/dist/lib/node/index.cjs +661 -0
  37. package/dist/lib/node/index.cjs.map +7 -0
  38. package/dist/lib/node/intent-resolver-3KJZGGUQ.cjs +44 -0
  39. package/dist/lib/node/intent-resolver-3KJZGGUQ.cjs.map +7 -0
  40. package/dist/lib/node/meta.json +1 -0
  41. package/dist/lib/node/react-surface-L4NQQWN4.cjs +49 -0
  42. package/dist/lib/node/react-surface-L4NQQWN4.cjs.map +7 -0
  43. package/dist/lib/node/types/index.cjs +39 -0
  44. package/dist/lib/node/types/index.cjs.map +7 -0
  45. package/dist/lib/node-esm/TranscriptContainer-HJTGGLU5.mjs +11 -0
  46. package/dist/lib/node-esm/TranscriptContainer-HJTGGLU5.mjs.map +7 -0
  47. package/dist/lib/node-esm/app-graph-builder-77GQG6UF.mjs +9 -0
  48. package/dist/lib/node-esm/app-graph-builder-77GQG6UF.mjs.map +7 -0
  49. package/dist/lib/node-esm/chunk-F4J7FV6Q.mjs +10 -0
  50. package/dist/lib/node-esm/chunk-F4J7FV6Q.mjs.map +7 -0
  51. package/dist/lib/node-esm/chunk-KEG3ME4O.mjs +82 -0
  52. package/dist/lib/node-esm/chunk-KEG3ME4O.mjs.map +7 -0
  53. package/dist/lib/node-esm/chunk-TNJUQCWM.mjs +242 -0
  54. package/dist/lib/node-esm/chunk-TNJUQCWM.mjs.map +7 -0
  55. package/dist/lib/node-esm/chunk-XYU6B73V.mjs +80 -0
  56. package/dist/lib/node-esm/chunk-XYU6B73V.mjs.map +7 -0
  57. package/dist/lib/node-esm/index.mjs +653 -0
  58. package/dist/lib/node-esm/index.mjs.map +7 -0
  59. package/dist/lib/node-esm/intent-resolver-UGLYRD4X.mjs +33 -0
  60. package/dist/lib/node-esm/intent-resolver-UGLYRD4X.mjs.map +7 -0
  61. package/dist/lib/node-esm/meta.json +1 -0
  62. package/dist/lib/node-esm/react-surface-TX4ULXGK.mjs +27 -0
  63. package/dist/lib/node-esm/react-surface-TX4ULXGK.mjs.map +7 -0
  64. package/dist/lib/node-esm/types/index.mjs +18 -0
  65. package/dist/lib/node-esm/types/index.mjs.map +7 -0
  66. package/dist/types/src/TranscriptionPlugin.d.ts +2 -0
  67. package/dist/types/src/TranscriptionPlugin.d.ts.map +1 -0
  68. package/dist/types/src/capabilities/app-graph-builder.d.ts +180 -0
  69. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -0
  70. package/dist/types/src/capabilities/capabilities.d.ts +4 -0
  71. package/dist/types/src/capabilities/capabilities.d.ts.map +1 -0
  72. package/dist/types/src/capabilities/index.d.ts +181 -0
  73. package/dist/types/src/capabilities/index.d.ts.map +1 -0
  74. package/dist/types/src/capabilities/intent-resolver.d.ts +4 -0
  75. package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -0
  76. package/dist/types/src/capabilities/react-surface.d.ts +4 -0
  77. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -0
  78. package/dist/types/src/components/Transcript/Transcript.d.ts +7 -0
  79. package/dist/types/src/components/Transcript/Transcript.d.ts.map +1 -0
  80. package/dist/types/src/components/Transcript/Transcript.stories.d.ts +9 -0
  81. package/dist/types/src/components/Transcript/Transcript.stories.d.ts.map +1 -0
  82. package/dist/types/src/components/Transcript/index.d.ts +2 -0
  83. package/dist/types/src/components/Transcript/index.d.ts.map +1 -0
  84. package/dist/types/src/components/TranscriptContainer.d.ts +7 -0
  85. package/dist/types/src/components/TranscriptContainer.d.ts.map +1 -0
  86. package/dist/types/src/components/index.d.ts +6 -0
  87. package/dist/types/src/components/index.d.ts.map +1 -0
  88. package/dist/types/src/components/transcription.stories.d.ts +14 -0
  89. package/dist/types/src/components/transcription.stories.d.ts.map +1 -0
  90. package/dist/types/src/hooks/index.d.ts +6 -0
  91. package/dist/types/src/hooks/index.d.ts.map +1 -0
  92. package/dist/types/src/hooks/useAudioFile.d.ts +7 -0
  93. package/dist/types/src/hooks/useAudioFile.d.ts.map +1 -0
  94. package/dist/types/src/hooks/useAudioTrack.d.ts +5 -0
  95. package/dist/types/src/hooks/useAudioTrack.d.ts.map +1 -0
  96. package/dist/types/src/hooks/useIsSpeaking.d.ts +2 -0
  97. package/dist/types/src/hooks/useIsSpeaking.d.ts.map +1 -0
  98. package/dist/types/src/hooks/useTranscriber.d.ts +10 -0
  99. package/dist/types/src/hooks/useTranscriber.d.ts.map +1 -0
  100. package/dist/types/src/hooks/useVoiceInput.d.ts +11 -0
  101. package/dist/types/src/hooks/useVoiceInput.d.ts.map +1 -0
  102. package/dist/types/src/index.d.ts +7 -0
  103. package/dist/types/src/index.d.ts.map +1 -0
  104. package/dist/types/src/meta.d.ts +11 -0
  105. package/dist/types/src/meta.d.ts.map +1 -0
  106. package/dist/types/src/sanity.test.d.ts +2 -0
  107. package/dist/types/src/sanity.test.d.ts.map +1 -0
  108. package/dist/types/src/transcriber/audio-recorder.d.ts +47 -0
  109. package/dist/types/src/transcriber/audio-recorder.d.ts.map +1 -0
  110. package/dist/types/src/transcriber/index.d.ts +4 -0
  111. package/dist/types/src/transcriber/index.d.ts.map +1 -0
  112. package/dist/types/src/transcriber/media-stream-recorder.d.ts +26 -0
  113. package/dist/types/src/transcriber/media-stream-recorder.d.ts.map +1 -0
  114. package/dist/types/src/transcriber/transcriber.d.ts +46 -0
  115. package/dist/types/src/transcriber/transcriber.d.ts.map +1 -0
  116. package/dist/types/src/transcriber/transcriber.test.d.ts +2 -0
  117. package/dist/types/src/transcriber/transcriber.test.d.ts.map +1 -0
  118. package/dist/types/src/translations.d.ts +40 -0
  119. package/dist/types/src/translations.d.ts.map +1 -0
  120. package/dist/types/src/types/index.d.ts +3 -0
  121. package/dist/types/src/types/index.d.ts.map +1 -0
  122. package/dist/types/src/types/schema.d.ts +63 -0
  123. package/dist/types/src/types/schema.d.ts.map +1 -0
  124. package/dist/types/src/types/types.d.ts +28 -0
  125. package/dist/types/src/types/types.d.ts.map +1 -0
  126. package/dist/types/src/util/array.d.ts +2 -0
  127. package/dist/types/src/util/array.d.ts.map +1 -0
  128. package/dist/types/src/util/get-time-str.d.ts +2 -0
  129. package/dist/types/src/util/get-time-str.d.ts.map +1 -0
  130. package/dist/types/src/util/index.d.ts +5 -0
  131. package/dist/types/src/util/index.d.ts.map +1 -0
  132. package/dist/types/src/util/monitor-audio-level.d.ts +6 -0
  133. package/dist/types/src/util/monitor-audio-level.d.ts.map +1 -0
  134. package/dist/types/src/util/random-queue-dxn.d.ts +3 -0
  135. package/dist/types/src/util/random-queue-dxn.d.ts.map +1 -0
  136. package/dist/types/tsconfig.tsbuildinfo +1 -0
  137. package/package.json +93 -0
  138. package/src/TranscriptionPlugin.tsx +57 -0
  139. package/src/capabilities/app-graph-builder.ts +7 -0
  140. package/src/capabilities/capabilities.ts +12 -0
  141. package/src/capabilities/index.ts +11 -0
  142. package/src/capabilities/intent-resolver.ts +24 -0
  143. package/src/capabilities/react-surface.tsx +21 -0
  144. package/src/components/Transcript/Transcript.stories.tsx +65 -0
  145. package/src/components/Transcript/Transcript.tsx +69 -0
  146. package/src/components/Transcript/index.ts +5 -0
  147. package/src/components/TranscriptContainer.tsx +167 -0
  148. package/src/components/index.ts +10 -0
  149. package/src/components/transcription.stories.tsx +198 -0
  150. package/src/hooks/index.ts +9 -0
  151. package/src/hooks/useAudioFile.ts +62 -0
  152. package/src/hooks/useAudioTrack.ts +35 -0
  153. package/src/hooks/useIsSpeaking.ts +77 -0
  154. package/src/hooks/useTranscriber.ts +62 -0
  155. package/src/hooks/useVoiceInput.ts +66 -0
  156. package/src/index.ts +11 -0
  157. package/src/meta.ts +17 -0
  158. package/src/sanity.test.ts +11 -0
  159. package/src/transcriber/audio-recorder.ts +56 -0
  160. package/src/transcriber/index.ts +7 -0
  161. package/src/transcriber/media-stream-recorder.ts +109 -0
  162. package/src/transcriber/transcriber.test.ts +230 -0
  163. package/src/transcriber/transcriber.ts +247 -0
  164. package/src/translations.ts +28 -0
  165. package/src/types/index.ts +6 -0
  166. package/src/types/schema.ts +60 -0
  167. package/src/types/types.ts +34 -0
  168. package/src/util/array.ts +14 -0
  169. package/src/util/get-time-str.ts +12 -0
  170. package/src/util/index.ts +8 -0
  171. package/src/util/monitor-audio-level.ts +58 -0
  172. package/src/util/random-queue-dxn.ts +9 -0
package/LICENSE ADDED
@@ -0,0 +1,8 @@
1
+ MIT License
2
+ Copyright (c) 2022 DXOS
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5
+
6
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7
+
8
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,15 @@
1
+ # @dxos/plugin-transcription
2
+
3
+ Transcription functionality
4
+
5
+ ## DXOS Resources
6
+
7
+ - [Website](https://dxos.org)
8
+ - [Developer Documentation](https://docs.dxos.org)
9
+ - Talk to us on [Discord](https://dxos.org/discord)
10
+
11
+ ## Contributions
12
+
13
+ Your ideas, issues, and code are most welcome. Please take a look at our [community code of conduct](https://github.com/dxos/dxos/blob/main/CODE_OF_CONDUCT.md), the [issue guide](https://github.com/dxos/dxos/blob/main/CONTRIBUTING.md#submitting-issues), and the [PR contribution guide](https://github.com/dxos/dxos/blob/main/CONTRIBUTING.md#submitting-prs).
14
+
15
+ License: [MIT](./LICENSE) Copyright 2023 © DXOS
@@ -0,0 +1,10 @@
1
+ import {
2
+ TranscriptContainer_default,
3
+ TranscriptionContainer
4
+ } from "./chunk-D4ZMHRVK.mjs";
5
+ import "./chunk-QIHUPVQD.mjs";
6
+ export {
7
+ TranscriptionContainer,
8
+ TranscriptContainer_default as default
9
+ };
10
+ //# sourceMappingURL=TranscriptContainer-G7NUUBPJ.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": [],
4
+ "sourcesContent": [],
5
+ "mappings": "",
6
+ "names": []
7
+ }
@@ -0,0 +1,7 @@
1
+ // packages/plugins/experimental/plugin-transcription/src/capabilities/app-graph-builder.ts
2
+ import { Capabilities, contributes } from "@dxos/app-framework";
3
+ var app_graph_builder_default = (context) => contributes(Capabilities.AppGraphBuilder, []);
4
+ export {
5
+ app_graph_builder_default as default
6
+ };
7
+ //# sourceMappingURL=app-graph-builder-ZSSJIFY7.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/capabilities/app-graph-builder.ts"],
4
+ "sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport { Capabilities, contributes, type PluginsContext } from '@dxos/app-framework';\n\nexport default (context: PluginsContext) => contributes(Capabilities.AppGraphBuilder, []);\n"],
5
+ "mappings": ";AAIA,SAASA,cAAcC,mBAAwC;AAE/D,IAAA,4BAAe,CAACC,YAA4BC,YAAYC,aAAaC,iBAAiB,CAAA,CAAE;",
6
+ "names": ["Capabilities", "contributes", "context", "contributes", "Capabilities", "AppGraphBuilder"]
7
+ }
@@ -0,0 +1,8 @@
1
+ // packages/plugins/experimental/plugin-transcription/src/components/index.ts
2
+ import { lazy } from "react";
3
+ var TranscriptContainer = lazy(() => import("./TranscriptContainer-G7NUUBPJ.mjs"));
4
+
5
+ export {
6
+ TranscriptContainer
7
+ };
8
+ //# sourceMappingURL=chunk-7V6ZINS5.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/components/index.ts"],
4
+ "sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport { lazy } from 'react';\n\nexport * from './Transcript';\nexport * from './TranscriptContainer';\n\nexport const TranscriptContainer = lazy(() => import('./TranscriptContainer'));\n"],
5
+ "mappings": ";AAIA,SAASA,YAAY;AAKd,IAAMC,sBAAsBC,KAAK,MAAM,OAAO,oCAAA,CAAA;",
6
+ "names": ["lazy", "TranscriptContainer", "lazy"]
7
+ }
@@ -0,0 +1,241 @@
1
+ import {
2
+ TRANSCRIPTION_PLUGIN,
3
+ TranscriptBlock
4
+ } from "./chunk-QIHUPVQD.mjs";
5
+
6
+ // packages/plugins/experimental/plugin-transcription/src/components/TranscriptContainer.tsx
7
+ import { pipe } from "effect";
8
+ import React2, { useCallback, useMemo, useState } from "react";
9
+ import { chain, createIntent, LayoutAction, useIntentDispatcher } from "@dxos/app-framework";
10
+ import { Message } from "@dxos/artifact";
11
+ import { AIServiceClientImpl, DEFAULT_LLM_MODEL, MixedStreamParser } from "@dxos/assistant";
12
+ import { create, getSpace, makeRef } from "@dxos/client/echo";
13
+ import { QueueImpl } from "@dxos/echo-db";
14
+ import { createStatic, isInstanceOf } from "@dxos/echo-schema";
15
+ import { invariant } from "@dxos/invariant";
16
+ import { DXN } from "@dxos/keys";
17
+ import { log } from "@dxos/log";
18
+ import { DocumentType } from "@dxos/plugin-markdown/types";
19
+ import { CollectionType, SpaceAction } from "@dxos/plugin-space/types";
20
+ import { useConfig } from "@dxos/react-client";
21
+ import { useEdgeClient, useQueue } from "@dxos/react-edge-client";
22
+ import { IconButton as IconButton2, Toolbar, useTranslation as useTranslation2 } from "@dxos/react-ui";
23
+ import { ScrollContainer } from "@dxos/react-ui-components";
24
+ import { StackItem } from "@dxos/react-ui-stack";
25
+ import { TextType } from "@dxos/schema";
26
+
27
+ // packages/plugins/experimental/plugin-transcription/src/components/Transcript/Transcript.tsx
28
+ import { formatDistanceToNow } from "date-fns/formatDistanceToNow";
29
+ import React from "react";
30
+ import { Icon, IconButton, useTranslation } from "@dxos/react-ui";
31
+ var Transcript = ({ blocks }) => {
32
+ const { t } = useTranslation(TRANSCRIPTION_PLUGIN);
33
+ const hoverButton = "p-1 min-bs-1 transition-opacity duration-250 opacity-10 group-hover:opacity-100";
34
+ return /* @__PURE__ */ React.createElement("div", {
35
+ role: "list",
36
+ className: "flex flex-col grow gap-2 m-1"
37
+ }, blocks?.map((block) => /* @__PURE__ */ React.createElement("div", {
38
+ role: "listitem",
39
+ key: block.id,
40
+ className: "flex flex-col py-1 border border-transparent hover:border-separator rounded"
41
+ }, /* @__PURE__ */ React.createElement("div", {
42
+ className: "group flex items-center px-2"
43
+ }, /* @__PURE__ */ React.createElement(Icon, {
44
+ icon: "ph--user--regular"
45
+ }), /* @__PURE__ */ React.createElement("div", {
46
+ className: "px-2 text-sm text-subdued"
47
+ }, block.author), /* @__PURE__ */ React.createElement("div", {
48
+ className: "grow"
49
+ }), /* @__PURE__ */ React.createElement(IconButton, {
50
+ disabled: true,
51
+ icon: "ph--x--regular",
52
+ label: t("delete button"),
53
+ iconOnly: true,
54
+ size: 4,
55
+ classNames: hoverButton
56
+ })), block.segments.map((segment, i) => /* @__PURE__ */ React.createElement("div", {
57
+ key: i,
58
+ className: "group flex flex-col"
59
+ }, /* @__PURE__ */ React.createElement("div", {
60
+ className: "px-2"
61
+ }, segment.text), /* @__PURE__ */ React.createElement("div", {
62
+ className: "flex gap-1 items-center justify-between px-2"
63
+ }, /* @__PURE__ */ React.createElement("div", {
64
+ className: "grow"
65
+ }), /* @__PURE__ */ React.createElement("div", {
66
+ className: "truncate text-xs text-subdued"
67
+ }, formatDistanceToNow(segment.started, {
68
+ addSuffix: true
69
+ })), /* @__PURE__ */ React.createElement(IconButton, {
70
+ disabled: true,
71
+ icon: "ph--bookmark-simple--regular",
72
+ label: t("bookmark button"),
73
+ iconOnly: true,
74
+ size: 4,
75
+ classNames: hoverButton
76
+ })))))));
77
+ };
78
+
79
+ // packages/plugins/experimental/plugin-transcription/src/components/TranscriptContainer.tsx
80
+ var __dxlog_file = "/home/runner/work/dxos/dxos/packages/plugins/experimental/plugin-transcription/src/components/TranscriptContainer.tsx";
81
+ var TranscriptionContainer = ({ transcript }) => {
82
+ const { t } = useTranslation2(TRANSCRIPTION_PLUGIN);
83
+ const edge = useEdgeClient();
84
+ const aiService = useAiServiceClient();
85
+ const { dispatchPromise: dispatch } = useIntentDispatcher();
86
+ const queue = useQueue(edge, transcript.queue ? DXN.parse(transcript.queue) : void 0, {
87
+ pollInterval: 1e3
88
+ });
89
+ const [isSummarizing, setIsSummarizing] = useState(false);
90
+ const handleSummarize = useCallback(async () => {
91
+ setIsSummarizing(true);
92
+ try {
93
+ const document = await summarizeTranscript(edge, aiService, transcript);
94
+ const space = getSpace(transcript);
95
+ const target = space?.properties[CollectionType.typename]?.target;
96
+ await dispatch(pipe(createIntent(SpaceAction.AddObject, {
97
+ object: document,
98
+ target
99
+ }), chain(LayoutAction.Open, {
100
+ part: "main"
101
+ })));
102
+ } finally {
103
+ setIsSummarizing(false);
104
+ }
105
+ }, [
106
+ transcript,
107
+ edge
108
+ ]);
109
+ return /* @__PURE__ */ React2.createElement(StackItem.Content, {
110
+ toolbar: true
111
+ }, /* @__PURE__ */ React2.createElement(StackItem.Heading, null, /* @__PURE__ */ React2.createElement(Toolbar.Root, {
112
+ classNames: "flex gap-2"
113
+ }, /* @__PURE__ */ React2.createElement(IconButton2, {
114
+ icon: "ph--subtitles--regular",
115
+ iconOnly: true,
116
+ size: 5,
117
+ disabled: isSummarizing,
118
+ onClick: handleSummarize,
119
+ label: t("summary button")
120
+ }), isSummarizing && /* @__PURE__ */ React2.createElement("div", {
121
+ className: "text-sm"
122
+ }, t("summarizing label")))), /* @__PURE__ */ React2.createElement(ScrollContainer, null, /* @__PURE__ */ React2.createElement(Transcript, {
123
+ blocks: queue?.items
124
+ })));
125
+ };
126
+ var TranscriptContainer_default = TranscriptionContainer;
127
+ var summarizeTranscript = async (edgeClient, aiService, transcript) => {
128
+ invariant(transcript.queue, "No queue found for transcript", {
129
+ F: __dxlog_file,
130
+ L: 90,
131
+ S: void 0,
132
+ A: [
133
+ "transcript.queue",
134
+ "'No queue found for transcript'"
135
+ ]
136
+ });
137
+ const queue = new QueueImpl(edgeClient, DXN.parse(transcript.queue));
138
+ await queue.refresh();
139
+ const content = queue.items.filter((block) => isInstanceOf(TranscriptBlock, block)).map((block) => `${block.author}: ${block.segments.map((segment) => segment.text).join("\n")}`).join("\n\n");
140
+ const parser = new MixedStreamParser();
141
+ log.info("summarizing transcript", {
142
+ blockCount: queue.items.length
143
+ }, {
144
+ F: __dxlog_file,
145
+ L: 101,
146
+ S: void 0,
147
+ C: (f, a) => f(...a)
148
+ });
149
+ const output = await parser.parse(await aiService.generate({
150
+ model: DEFAULT_LLM_MODEL,
151
+ systemPrompt: SUMMARIZE_PROMPT,
152
+ history: [
153
+ createStatic(Message, {
154
+ role: "user",
155
+ content: [
156
+ {
157
+ type: "text",
158
+ text: content
159
+ }
160
+ ]
161
+ })
162
+ ]
163
+ }));
164
+ log.info("transcript summary", {
165
+ output
166
+ }, {
167
+ F: __dxlog_file,
168
+ L: 110,
169
+ S: void 0,
170
+ C: (f, a) => f(...a)
171
+ });
172
+ invariant(output[0].content[0].type === "text", "Expected text content", {
173
+ F: __dxlog_file,
174
+ L: 111,
175
+ S: void 0,
176
+ A: [
177
+ "output[0].content[0].type === 'text'",
178
+ "'Expected text content'"
179
+ ]
180
+ });
181
+ const summary = output[0].content[0].text;
182
+ const name = `Summary ${(transcript.started ?? /* @__PURE__ */ new Date()).toLocaleString("en-US", {
183
+ year: "numeric",
184
+ month: "long",
185
+ day: "numeric",
186
+ hour: "2-digit",
187
+ minute: "2-digit"
188
+ })}`;
189
+ return create(DocumentType, {
190
+ name,
191
+ content: makeRef(create(TextType, {
192
+ content: summary
193
+ })),
194
+ threads: []
195
+ });
196
+ };
197
+ var SUMMARIZE_PROMPT = `
198
+ # Goal
199
+ Create a markdown summary of the transcript provided.
200
+
201
+ # Formatting
202
+ - Format the summary as a markdown document without extra comments like "Here is the summary of the transcript:".
203
+ - Use markdown formatting for headings and bullet points.
204
+ - Format the summary as a list of key points and takeaways.
205
+ - All names of people should be in bold.
206
+
207
+ # Note Taking
208
+ - Correlate items in the summary with the person of origin to build a coherent narrative.
209
+ - Include short quotes verbatim where appropriate. Especially when concerned with design decisions and problem descriptions.
210
+
211
+ # Tasks
212
+ At the end of the summary include tasks.
213
+ Extract only the tasks that are:
214
+ - Directly actionable
215
+ - Clearly assigned to a person or team (or can easily be inferred)
216
+ - Strongly implied by the conversation and/or user note (no speculative tasks)
217
+ - Specific enough that someone reading them would know exactly what to do next
218
+
219
+ Format all tasks as markdown checkboxes using the syntax:
220
+ - [ ] Task description
221
+
222
+ Additional information can be included (indented).
223
+
224
+ If no actionable tasks are found, omit this tasks section.
225
+ `;
226
+ var useAiServiceClient = () => {
227
+ const config = useConfig();
228
+ const endpoint = config.values.runtime?.services?.ai?.server ?? "http://localhost:8788";
229
+ return useMemo(() => new AIServiceClientImpl({
230
+ endpoint
231
+ }), [
232
+ endpoint
233
+ ]);
234
+ };
235
+
236
+ export {
237
+ Transcript,
238
+ TranscriptionContainer,
239
+ TranscriptContainer_default
240
+ };
241
+ //# sourceMappingURL=chunk-D4ZMHRVK.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/components/TranscriptContainer.tsx", "../../../src/components/Transcript/Transcript.tsx"],
4
+ "sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport { pipe } from 'effect';\nimport React, { useCallback, useMemo, useState, type FC } from 'react';\n\nimport { chain, createIntent, LayoutAction, useIntentDispatcher } from '@dxos/app-framework';\nimport { Message } from '@dxos/artifact';\nimport { AIServiceClientImpl, DEFAULT_LLM_MODEL, MixedStreamParser, type AIServiceClient } from '@dxos/assistant';\nimport { create, getSpace, makeRef } from '@dxos/client/echo';\nimport { QueueImpl } from '@dxos/echo-db';\nimport { createStatic, isInstanceOf } from '@dxos/echo-schema';\nimport { invariant } from '@dxos/invariant';\nimport { DXN } from '@dxos/keys';\nimport { log } from '@dxos/log';\nimport { DocumentType } from '@dxos/plugin-markdown/types';\nimport { CollectionType, SpaceAction } from '@dxos/plugin-space/types';\nimport { useConfig } from '@dxos/react-client';\nimport { useEdgeClient, useQueue, type EdgeHttpClient } from '@dxos/react-edge-client';\nimport { IconButton, Toolbar, useTranslation } from '@dxos/react-ui';\nimport { ScrollContainer } from '@dxos/react-ui-components';\nimport { StackItem } from '@dxos/react-ui-stack';\nimport { TextType } from '@dxos/schema';\n\nimport { Transcript } from './Transcript';\nimport { TRANSCRIPTION_PLUGIN } from '../meta';\nimport { TranscriptBlock, type TranscriptType } from '../types';\n\nexport const TranscriptionContainer: FC<{ transcript: TranscriptType }> = ({ transcript }) => {\n const { t } = useTranslation(TRANSCRIPTION_PLUGIN);\n const edge = useEdgeClient();\n const aiService = useAiServiceClient();\n const { dispatchPromise: dispatch } = useIntentDispatcher();\n\n const queue = useQueue<TranscriptBlock>(edge, transcript.queue ? DXN.parse(transcript.queue) : undefined, {\n pollInterval: 1_000,\n });\n\n // TODO(dmaretskyi): Pending state and errors should be handled by the framework!!!\n const [isSummarizing, setIsSummarizing] = useState(false);\n const handleSummarize = useCallback(async () => {\n setIsSummarizing(true);\n try {\n const document = await summarizeTranscript(edge, aiService, transcript);\n const space = getSpace(transcript);\n const target = space?.properties[CollectionType.typename]?.target;\n await dispatch(\n pipe(\n createIntent(SpaceAction.AddObject, { object: document, target }),\n chain(LayoutAction.Open, { part: 'main' }),\n ),\n );\n } finally {\n setIsSummarizing(false);\n }\n }, [transcript, edge]);\n\n // TODO(dmaretskyi): Move action to menu.\n return (\n <StackItem.Content toolbar={true}>\n <StackItem.Heading>\n <Toolbar.Root classNames='flex gap-2'>\n <IconButton\n icon='ph--subtitles--regular'\n iconOnly\n size={5}\n disabled={isSummarizing}\n onClick={handleSummarize}\n label={t('summary button')}\n />\n {isSummarizing && <div className='text-sm'>{t('summarizing label')}</div>}\n </Toolbar.Root>\n </StackItem.Heading>\n <ScrollContainer>\n <Transcript blocks={queue?.items} />\n </ScrollContainer>\n </StackItem.Content>\n );\n};\n\nexport default TranscriptionContainer;\n\n// TODO(dmaretskyi): Extract to the new file once transcript refactoring has settled.\nconst summarizeTranscript = async (\n edgeClient: EdgeHttpClient,\n aiService: AIServiceClient,\n transcript: TranscriptType,\n) => {\n invariant(transcript.queue, 'No queue found for transcript');\n\n const queue = new QueueImpl(edgeClient, DXN.parse(transcript.queue));\n await queue.refresh();\n const content = queue.items\n .filter((block) => isInstanceOf(TranscriptBlock, block))\n .map((block) => `${block.author}: ${block.segments.map((segment) => segment.text).join('\\n')}`)\n .join('\\n\\n');\n\n const parser = new MixedStreamParser();\n\n log.info('summarizing transcript', { blockCount: queue.items.length });\n const output = await parser.parse(\n await aiService.generate({\n model: DEFAULT_LLM_MODEL,\n systemPrompt: SUMMARIZE_PROMPT,\n history: [createStatic(Message, { role: 'user', content: [{ type: 'text', text: content }] })],\n }),\n );\n\n log.info('transcript summary', { output });\n invariant(output[0].content[0].type === 'text', 'Expected text content');\n const summary = output[0].content[0].text;\n\n // TODO(dmaretskyi): .started is missing.\n const name = `Summary ${(transcript.started ?? new Date()).toLocaleString('en-US', {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n })}`;\n\n return create(DocumentType, {\n name,\n content: makeRef(create(TextType, { content: summary })),\n threads: [],\n });\n};\n\n// TODO(dmaretskyi): Add example to set consistent structure for the summary.\nconst SUMMARIZE_PROMPT = `\n # Goal\n Create a markdown summary of the transcript provided.\n\n # Formatting\n - Format the summary as a markdown document without extra comments like \"Here is the summary of the transcript:\".\n - Use markdown formatting for headings and bullet points.\n - Format the summary as a list of key points and takeaways.\n - All names of people should be in bold.\n\n # Note Taking\n - Correlate items in the summary with the person of origin to build a coherent narrative.\n - Include short quotes verbatim where appropriate. Especially when concerned with design decisions and problem descriptions.\n\n # Tasks\n At the end of the summary include tasks.\n Extract only the tasks that are:\n - Directly actionable\n - Clearly assigned to a person or team (or can easily be inferred)\n - Strongly implied by the conversation and/or user note (no speculative tasks)\n - Specific enough that someone reading them would know exactly what to do next\n\n Format all tasks as markdown checkboxes using the syntax:\n - [ ] Task description\n\n Additional information can be included (indented).\n\n If no actionable tasks are found, omit this tasks section.\n`;\n\n// TODO(dmaretskyi): Extract?\n// Also this conflicts with plugin automation providing the ai client via a capability. Need to reconcile.\nconst useAiServiceClient = (): AIServiceClient => {\n const config = useConfig();\n const endpoint = config.values.runtime?.services?.ai?.server ?? 'http://localhost:8788';\n return useMemo(() => new AIServiceClientImpl({ endpoint }), [endpoint]);\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { formatDistanceToNow } from 'date-fns/formatDistanceToNow';\nimport React, { type FC } from 'react';\n\nimport { Icon, IconButton, useTranslation } from '@dxos/react-ui';\n\nimport { TRANSCRIPTION_PLUGIN } from '../../meta';\nimport { type TranscriptBlock } from '../../types';\n\n// TODO(burdon): react-ui-list.\n// TODO(burdon): Actions (e.g., mark, summarize, translate, label, delete).\n\nexport type TranscriptProps = {\n blocks?: TranscriptBlock[];\n};\n\nexport const Transcript: FC<TranscriptProps> = ({ blocks }) => {\n const { t } = useTranslation(TRANSCRIPTION_PLUGIN);\n const hoverButton = 'p-1 min-bs-1 transition-opacity duration-250 opacity-10 group-hover:opacity-100';\n\n return (\n <div role='list' className='flex flex-col grow gap-2 m-1'>\n {blocks?.map((block) => (\n <div\n role='listitem'\n key={block.id}\n className='flex flex-col py-1 border border-transparent hover:border-separator rounded'\n >\n <div className='group flex items-center px-2'>\n <Icon icon='ph--user--regular' />\n <div className='px-2 text-sm text-subdued'>{block.author}</div>\n <div className='grow' />\n <IconButton\n disabled\n icon='ph--x--regular'\n label={t('delete button')}\n iconOnly\n size={4}\n classNames={hoverButton}\n />\n </div>\n\n {block.segments.map((segment, i) => (\n <div key={i} className='group flex flex-col'>\n <div className='px-2'>{segment.text}</div>\n <div className='flex gap-1 items-center justify-between px-2'>\n <div className='grow' />\n <div className='truncate text-xs text-subdued'>\n {formatDistanceToNow(segment.started, { addSuffix: true })}\n </div>\n <IconButton\n disabled\n icon='ph--bookmark-simple--regular'\n label={t('bookmark button')}\n iconOnly\n size={4}\n classNames={hoverButton}\n />\n </div>\n </div>\n ))}\n </div>\n ))}\n </div>\n );\n};\n"],
5
+ "mappings": ";;;;;;AAIA,SAASA,YAAY;AACrB,OAAOC,UAASC,aAAaC,SAASC,gBAAyB;AAE/D,SAASC,OAAOC,cAAcC,cAAcC,2BAA2B;AACvE,SAASC,eAAe;AACxB,SAASC,qBAAqBC,mBAAmBC,yBAA+C;AAChG,SAASC,QAAQC,UAAUC,eAAe;AAC1C,SAASC,iBAAiB;AAC1B,SAASC,cAAcC,oBAAoB;AAC3C,SAASC,iBAAiB;AAC1B,SAASC,WAAW;AACpB,SAASC,WAAW;AACpB,SAASC,oBAAoB;AAC7B,SAASC,gBAAgBC,mBAAmB;AAC5C,SAASC,iBAAiB;AAC1B,SAASC,eAAeC,gBAAqC;AAC7D,SAASC,cAAAA,aAAYC,SAASC,kBAAAA,uBAAsB;AACpD,SAASC,uBAAuB;AAChC,SAASC,iBAAiB;AAC1B,SAASC,gBAAgB;;;ACnBzB,SAASC,2BAA2B;AACpC,OAAOC,WAAwB;AAE/B,SAASC,MAAMC,YAAYC,sBAAsB;AAY1C,IAAMC,aAAkC,CAAC,EAAEC,OAAM,MAAE;AACxD,QAAM,EAAEC,EAAC,IAAKC,eAAeC,oBAAAA;AAC7B,QAAMC,cAAc;AAEpB,SACE,sBAAA,cAACC,OAAAA;IAAIC,MAAK;IAAOC,WAAU;KACxBP,QAAQQ,IAAI,CAACC,UACZ,sBAAA,cAACJ,OAAAA;IACCC,MAAK;IACLI,KAAKD,MAAME;IACXJ,WAAU;KAEV,sBAAA,cAACF,OAAAA;IAAIE,WAAU;KACb,sBAAA,cAACK,MAAAA;IAAKC,MAAK;MACX,sBAAA,cAACR,OAAAA;IAAIE,WAAU;KAA6BE,MAAMK,MAAM,GACxD,sBAAA,cAACT,OAAAA;IAAIE,WAAU;MACf,sBAAA,cAACQ,YAAAA;IACCC,UAAAA;IACAH,MAAK;IACLI,OAAOhB,EAAE,eAAA;IACTiB,UAAAA;IACAC,MAAM;IACNC,YAAYhB;OAIfK,MAAMY,SAASb,IAAI,CAACc,SAASC,MAC5B,sBAAA,cAAClB,OAAAA;IAAIK,KAAKa;IAAGhB,WAAU;KACrB,sBAAA,cAACF,OAAAA;IAAIE,WAAU;KAAQe,QAAQE,IAAI,GACnC,sBAAA,cAACnB,OAAAA;IAAIE,WAAU;KACb,sBAAA,cAACF,OAAAA;IAAIE,WAAU;MACf,sBAAA,cAACF,OAAAA;IAAIE,WAAU;KACZkB,oBAAoBH,QAAQI,SAAS;IAAEC,WAAW;EAAK,CAAA,CAAA,GAE1D,sBAAA,cAACZ,YAAAA;IACCC,UAAAA;IACAH,MAAK;IACLI,OAAOhB,EAAE,iBAAA;IACTiB,UAAAA;IACAC,MAAM;IACNC,YAAYhB;;AAS9B;;;;ADvCO,IAAMwB,yBAA6D,CAAC,EAAEC,WAAU,MAAE;AACvF,QAAM,EAAEC,EAAC,IAAKC,gBAAeC,oBAAAA;AAC7B,QAAMC,OAAOC,cAAAA;AACb,QAAMC,YAAYC,mBAAAA;AAClB,QAAM,EAAEC,iBAAiBC,SAAQ,IAAKC,oBAAAA;AAEtC,QAAMC,QAAQC,SAA0BR,MAAMJ,WAAWW,QAAQE,IAAIC,MAAMd,WAAWW,KAAK,IAAII,QAAW;IACxGC,cAAc;EAChB,CAAA;AAGA,QAAM,CAACC,eAAeC,gBAAAA,IAAoBC,SAAS,KAAA;AACnD,QAAMC,kBAAkBC,YAAY,YAAA;AAClCH,qBAAiB,IAAA;AACjB,QAAI;AACF,YAAMI,WAAW,MAAMC,oBAAoBnB,MAAME,WAAWN,UAAAA;AAC5D,YAAMwB,QAAQC,SAASzB,UAAAA;AACvB,YAAM0B,SAASF,OAAOG,WAAWC,eAAeC,QAAQ,GAAGH;AAC3D,YAAMjB,SACJqB,KACEC,aAAaC,YAAYC,WAAW;QAAEC,QAAQZ;QAAUI;MAAO,CAAA,GAC/DS,MAAMC,aAAaC,MAAM;QAAEC,MAAM;MAAO,CAAA,CAAA,CAAA;IAG9C,UAAA;AACEpB,uBAAiB,KAAA;IACnB;EACF,GAAG;IAAClB;IAAYI;GAAK;AAGrB,SACE,gBAAAmC,OAAA,cAACC,UAAUC,SAAO;IAACC,SAAS;KAC1B,gBAAAH,OAAA,cAACC,UAAUG,SAAO,MAChB,gBAAAJ,OAAA,cAACK,QAAQC,MAAI;IAACC,YAAW;KACvB,gBAAAP,OAAA,cAACQ,aAAAA;IACCC,MAAK;IACLC,UAAAA;IACAC,MAAM;IACNC,UAAUlC;IACVmC,SAAShC;IACTiC,OAAOpD,EAAE,gBAAA;MAEVgB,iBAAiB,gBAAAsB,OAAA,cAACe,OAAAA;IAAIC,WAAU;KAAWtD,EAAE,mBAAA,CAAA,CAAA,CAAA,GAGlD,gBAAAsC,OAAA,cAACiB,iBAAAA,MACC,gBAAAjB,OAAA,cAACkB,YAAAA;IAAWC,QAAQ/C,OAAOgD;;AAInC;AAEA,IAAA,8BAAe5D;AAGf,IAAMwB,sBAAsB,OAC1BqC,YACAtD,WACAN,eAAAA;AAEA6D,YAAU7D,WAAWW,OAAO,iCAAA;;;;;;;;;AAE5B,QAAMA,QAAQ,IAAImD,UAAUF,YAAY/C,IAAIC,MAAMd,WAAWW,KAAK,CAAA;AAClE,QAAMA,MAAMoD,QAAO;AACnB,QAAMC,UAAUrD,MAAMgD,MACnBM,OAAO,CAACC,UAAUC,aAAaC,iBAAiBF,KAAAA,CAAAA,EAChDG,IAAI,CAACH,UAAU,GAAGA,MAAMI,MAAM,KAAKJ,MAAMK,SAASF,IAAI,CAACG,YAAYA,QAAQC,IAAI,EAAEC,KAAK,IAAA,CAAA,EAAO,EAC7FA,KAAK,MAAA;AAER,QAAMC,SAAS,IAAIC,kBAAAA;AAEnBC,MAAIC,KAAK,0BAA0B;IAAEC,YAAYpE,MAAMgD,MAAMqB;EAAO,GAAA;;;;;;AACpE,QAAMC,SAAS,MAAMN,OAAO7D,MAC1B,MAAMR,UAAU4E,SAAS;IACvBC,OAAOC;IACPC,cAAcC;IACdC,SAAS;MAACC,aAAaC,SAAS;QAAEC,MAAM;QAAQ1B,SAAS;UAAC;YAAE2B,MAAM;YAAQlB,MAAMT;UAAQ;;MAAG,CAAA;;EAC7F,CAAA,CAAA;AAGFa,MAAIC,KAAK,sBAAsB;IAAEG;EAAO,GAAA;;;;;;AACxCpB,YAAUoB,OAAO,CAAA,EAAGjB,QAAQ,CAAA,EAAG2B,SAAS,QAAQ,yBAAA;;;;;;;;;AAChD,QAAMC,UAAUX,OAAO,CAAA,EAAGjB,QAAQ,CAAA,EAAGS;AAGrC,QAAMoB,OAAO,YAAY7F,WAAW8F,WAAW,oBAAIC,KAAAA,GAAQC,eAAe,SAAS;IACjFC,MAAM;IACNC,OAAO;IACPC,KAAK;IACLC,MAAM;IACNC,QAAQ;EACV,CAAA,CAAA;AAEA,SAAOC,OAAOC,cAAc;IAC1BV;IACA7B,SAASwC,QAAQF,OAAOG,UAAU;MAAEzC,SAAS4B;IAAQ,CAAA,CAAA;IACrDc,SAAS,CAAA;EACX,CAAA;AACF;AAGA,IAAMpB,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCzB,IAAM/E,qBAAqB,MAAA;AACzB,QAAMoG,SAASC,UAAAA;AACf,QAAMC,WAAWF,OAAOG,OAAOC,SAASC,UAAUC,IAAIC,UAAU;AAChE,SAAOC,QAAQ,MAAM,IAAIC,oBAAoB;IAAEP;EAAS,CAAA,GAAI;IAACA;GAAS;AACxE;",
6
+ "names": ["pipe", "React", "useCallback", "useMemo", "useState", "chain", "createIntent", "LayoutAction", "useIntentDispatcher", "Message", "AIServiceClientImpl", "DEFAULT_LLM_MODEL", "MixedStreamParser", "create", "getSpace", "makeRef", "QueueImpl", "createStatic", "isInstanceOf", "invariant", "DXN", "log", "DocumentType", "CollectionType", "SpaceAction", "useConfig", "useEdgeClient", "useQueue", "IconButton", "Toolbar", "useTranslation", "ScrollContainer", "StackItem", "TextType", "formatDistanceToNow", "React", "Icon", "IconButton", "useTranslation", "Transcript", "blocks", "t", "useTranslation", "TRANSCRIPTION_PLUGIN", "hoverButton", "div", "role", "className", "map", "block", "key", "id", "Icon", "icon", "author", "IconButton", "disabled", "label", "iconOnly", "size", "classNames", "segments", "segment", "i", "text", "formatDistanceToNow", "started", "addSuffix", "TranscriptionContainer", "transcript", "t", "useTranslation", "TRANSCRIPTION_PLUGIN", "edge", "useEdgeClient", "aiService", "useAiServiceClient", "dispatchPromise", "dispatch", "useIntentDispatcher", "queue", "useQueue", "DXN", "parse", "undefined", "pollInterval", "isSummarizing", "setIsSummarizing", "useState", "handleSummarize", "useCallback", "document", "summarizeTranscript", "space", "getSpace", "target", "properties", "CollectionType", "typename", "pipe", "createIntent", "SpaceAction", "AddObject", "object", "chain", "LayoutAction", "Open", "part", "React", "StackItem", "Content", "toolbar", "Heading", "Toolbar", "Root", "classNames", "IconButton", "icon", "iconOnly", "size", "disabled", "onClick", "label", "div", "className", "ScrollContainer", "Transcript", "blocks", "items", "edgeClient", "invariant", "QueueImpl", "refresh", "content", "filter", "block", "isInstanceOf", "TranscriptBlock", "map", "author", "segments", "segment", "text", "join", "parser", "MixedStreamParser", "log", "info", "blockCount", "length", "output", "generate", "model", "DEFAULT_LLM_MODEL", "systemPrompt", "SUMMARIZE_PROMPT", "history", "createStatic", "Message", "role", "type", "summary", "name", "started", "Date", "toLocaleString", "year", "month", "day", "hour", "minute", "create", "DocumentType", "makeRef", "TextType", "threads", "config", "useConfig", "endpoint", "values", "runtime", "services", "ai", "server", "useMemo", "AIServiceClientImpl"]
7
+ }
@@ -0,0 +1,80 @@
1
+ // packages/plugins/experimental/plugin-transcription/src/types/schema.ts
2
+ import { EchoObject, ObjectId, S, TypedObject } from "@dxos/echo-schema";
3
+ var TranscriptSchema = S.Struct({
4
+ name: S.String,
5
+ // TODO(burdon): Use string for dates?
6
+ started: S.optional(S.Date),
7
+ ended: S.optional(S.Date),
8
+ /**
9
+ * Queue containing TranscriptBlock objects.
10
+ */
11
+ queue: S.optional(S.String)
12
+ });
13
+ var TranscriptType = class extends TypedObject({
14
+ typename: "dxos.org/type/Transcript",
15
+ version: "0.1.0"
16
+ })(TranscriptSchema.fields) {
17
+ };
18
+ var TranscriptHeader = S.Struct({
19
+ started: S.optional(S.Date)
20
+ });
21
+ var TranscriptSegment = S.Struct({
22
+ // TODO(burdon): TS from service is not Unix TS (x1000).
23
+ started: S.Date,
24
+ text: S.String
25
+ });
26
+ var TranscriptBlock = S.Struct({
27
+ id: ObjectId,
28
+ author: S.optional(S.String),
29
+ segments: S.Array(TranscriptSegment)
30
+ }).pipe(EchoObject("dxos.org/type/TranscriptBlock", "0.1.0"));
31
+
32
+ // packages/plugins/experimental/plugin-transcription/src/types/types.ts
33
+ import { S as S2, isInstanceOf } from "@dxos/echo-schema";
34
+ import { isReactiveObject } from "@dxos/react-client/echo";
35
+
36
+ // packages/plugins/experimental/plugin-transcription/src/meta.ts
37
+ var TRANSCRIPTION_PLUGIN = "dxos.org/plugin/transcription";
38
+ var meta = {
39
+ id: TRANSCRIPTION_PLUGIN,
40
+ name: "Transcription",
41
+ description: "Voice transcription.",
42
+ icon: "ph--microphone--regular",
43
+ source: "https://github.com/dxos/dxos/tree/main/packages/plugins/experimental/plugin-transcription",
44
+ tags: [
45
+ "experimental"
46
+ ],
47
+ screenshots: []
48
+ };
49
+
50
+ // packages/plugins/experimental/plugin-transcription/src/types/types.ts
51
+ var TRANSCRIPTION_URL = "https://calls-service.dxos.workers.dev";
52
+ var TranscriptionAction;
53
+ (function(TranscriptionAction2) {
54
+ const TRANSCRIPTION_ACTION = `${TRANSCRIPTION_PLUGIN}/action`;
55
+ class Create extends S2.TaggedClass()(`${TRANSCRIPTION_ACTION}/create`, {
56
+ input: S2.Struct({
57
+ name: S2.optional(S2.String)
58
+ }),
59
+ output: S2.Struct({
60
+ object: TranscriptSchema
61
+ })
62
+ }) {
63
+ }
64
+ TranscriptionAction2.Create = Create;
65
+ })(TranscriptionAction || (TranscriptionAction = {}));
66
+ var isTranscript = (object) => {
67
+ return isReactiveObject(object) && isInstanceOf(TranscriptType, object);
68
+ };
69
+
70
+ export {
71
+ TRANSCRIPTION_PLUGIN,
72
+ meta,
73
+ TranscriptSchema,
74
+ TranscriptType,
75
+ TranscriptBlock,
76
+ TRANSCRIPTION_URL,
77
+ TranscriptionAction,
78
+ isTranscript
79
+ };
80
+ //# sourceMappingURL=chunk-QIHUPVQD.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/types/schema.ts", "../../../src/types/types.ts", "../../../src/meta.ts"],
4
+ "sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport { EchoObject, ObjectId, S, TypedObject } from '@dxos/echo-schema';\n\n/**\n * Root transcript object created when the user starts a transcription.\n */\nexport const TranscriptSchema = S.Struct({\n name: S.String,\n\n // TODO(burdon): Use string for dates?\n started: S.optional(S.Date),\n ended: S.optional(S.Date),\n\n /**\n * Queue containing TranscriptBlock objects.\n */\n queue: S.optional(S.String),\n});\n\nexport class TranscriptType extends TypedObject({\n typename: 'dxos.org/type/Transcript',\n version: '0.1.0',\n})(TranscriptSchema.fields) {}\n\n// TODO(burdon): Do these need to be kept in sync with EDGE?\n\n/**\n * First message in queue.\n * Contains metadata for the recording and transcript.\n */\nconst TranscriptHeader = S.Struct({\n started: S.optional(S.Date),\n});\n\nexport type TranscriptHeader = S.Schema.Type<typeof TranscriptHeader>;\n\n/**\n * Transcription fragment.\n */\nconst TranscriptSegment = S.Struct({\n // TODO(burdon): TS from service is not Unix TS (x1000).\n started: S.Date,\n text: S.String,\n});\n\nexport type TranscriptSegment = S.Schema.Type<typeof TranscriptSegment>;\n\n/**\n * Transcription block (from single speaker).\n */\nexport const TranscriptBlock = S.Struct({\n id: ObjectId,\n author: S.optional(S.String), // TODO(burdon): DID?\n segments: S.Array(TranscriptSegment),\n}).pipe(EchoObject('dxos.org/type/TranscriptBlock', '0.1.0'));\n\nexport type TranscriptBlock = S.Schema.Type<typeof TranscriptBlock>;\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { S, isInstanceOf } from '@dxos/echo-schema';\nimport { isReactiveObject } from '@dxos/react-client/echo';\n\nimport { TranscriptSchema, TranscriptType } from './schema';\nimport { TRANSCRIPTION_PLUGIN } from '../meta';\n\n// TODO(burdon): Move to separate proto.\n\n/**\n * Endpoint to the calls service.\n */\n// TODO(burdon): Reconfigure/move.\nexport const TRANSCRIPTION_URL = 'https://calls-service.dxos.workers.dev';\n\nexport namespace TranscriptionAction {\n const TRANSCRIPTION_ACTION = `${TRANSCRIPTION_PLUGIN}/action`;\n\n export class Create extends S.TaggedClass<Create>()(`${TRANSCRIPTION_ACTION}/create`, {\n input: S.Struct({\n name: S.optional(S.String),\n }),\n output: S.Struct({\n object: TranscriptSchema,\n }),\n }) {}\n}\n\nexport const isTranscript = (object: unknown): object is typeof TranscriptType => {\n return isReactiveObject(object) && isInstanceOf(TranscriptType, object);\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { type PluginMeta } from '@dxos/app-framework';\n\nexport const TRANSCRIPTION_PLUGIN = 'dxos.org/plugin/transcription';\n\nexport const meta = {\n id: TRANSCRIPTION_PLUGIN,\n name: 'Transcription',\n description: 'Voice transcription.',\n icon: 'ph--microphone--regular',\n source: 'https://github.com/dxos/dxos/tree/main/packages/plugins/experimental/plugin-transcription',\n tags: ['experimental'],\n screenshots: [],\n} satisfies PluginMeta;\n"],
5
+ "mappings": ";AAIA,SAASA,YAAYC,UAAUC,GAAGC,mBAAmB;AAK9C,IAAMC,mBAAmBC,EAAEC,OAAO;EACvCC,MAAMF,EAAEG;;EAGRC,SAASJ,EAAEK,SAASL,EAAEM,IAAI;EAC1BC,OAAOP,EAAEK,SAASL,EAAEM,IAAI;;;;EAKxBE,OAAOR,EAAEK,SAASL,EAAEG,MAAM;AAC5B,CAAA;AAEO,IAAMM,iBAAN,cAA6BC,YAAY;EAC9CC,UAAU;EACVC,SAAS;AACX,CAAA,EAAGb,iBAAiBc,MAAM,EAAA;AAAG;AAQ7B,IAAMC,mBAAmBd,EAAEC,OAAO;EAChCG,SAASJ,EAAEK,SAASL,EAAEM,IAAI;AAC5B,CAAA;AAOA,IAAMS,oBAAoBf,EAAEC,OAAO;;EAEjCG,SAASJ,EAAEM;EACXU,MAAMhB,EAAEG;AACV,CAAA;AAOO,IAAMc,kBAAkBjB,EAAEC,OAAO;EACtCiB,IAAIC;EACJC,QAAQpB,EAAEK,SAASL,EAAEG,MAAM;EAC3BkB,UAAUrB,EAAEsB,MAAMP,iBAAAA;AACpB,CAAA,EAAGQ,KAAKC,WAAW,iCAAiC,OAAA,CAAA;;;ACrDpD,SAASC,KAAAA,IAAGC,oBAAoB;AAChC,SAASC,wBAAwB;;;ACC1B,IAAMC,uBAAuB;AAE7B,IAAMC,OAAO;EAClBC,IAAIF;EACJG,MAAM;EACNC,aAAa;EACbC,MAAM;EACNC,QAAQ;EACRC,MAAM;IAAC;;EACPC,aAAa,CAAA;AACf;;;ADAO,IAAMC,oBAAoB;;UAEhBC,sBAAAA;AACf,QAAMC,uBAAuB,GAAGC,oBAAAA;EAEzB,MAAMC,eAAeC,GAAEC,YAAW,EAAW,GAAGJ,oBAAAA,WAA+B;IACpFK,OAAOF,GAAEG,OAAO;MACdC,MAAMJ,GAAEK,SAASL,GAAEM,MAAM;IAC3B,CAAA;IACAC,QAAQP,GAAEG,OAAO;MACfK,QAAQC;IACV,CAAA;EACF,CAAA,EAAA;EAAI;uBAPSV,SAAAA;AAQf,GAXiBH,wBAAAA,sBAAAA,CAAAA,EAAAA;AAaV,IAAMc,eAAe,CAACF,WAAAA;AAC3B,SAAOG,iBAAiBH,MAAAA,KAAWI,aAAaC,gBAAgBL,MAAAA;AAClE;",
6
+ "names": ["EchoObject", "ObjectId", "S", "TypedObject", "TranscriptSchema", "S", "Struct", "name", "String", "started", "optional", "Date", "ended", "queue", "TranscriptType", "TypedObject", "typename", "version", "fields", "TranscriptHeader", "TranscriptSegment", "text", "TranscriptBlock", "id", "ObjectId", "author", "segments", "Array", "pipe", "EchoObject", "S", "isInstanceOf", "isReactiveObject", "TRANSCRIPTION_PLUGIN", "meta", "id", "name", "description", "icon", "source", "tags", "screenshots", "TRANSCRIPTION_URL", "TranscriptionAction", "TRANSCRIPTION_ACTION", "TRANSCRIPTION_PLUGIN", "Create", "S", "TaggedClass", "input", "Struct", "name", "optional", "String", "output", "object", "TranscriptSchema", "isTranscript", "isReactiveObject", "isInstanceOf", "TranscriptType"]
7
+ }
@@ -0,0 +1,78 @@
1
+ // packages/plugins/experimental/plugin-transcription/src/util/get-time-str.ts
2
+ var getTimeStr = (timestamp) => new Date(timestamp ?? Date.now()).toLocaleTimeString("en-US", {
3
+ timeZone: "UTC",
4
+ hour12: true,
5
+ hour: "numeric",
6
+ minute: "2-digit",
7
+ second: "2-digit"
8
+ });
9
+
10
+ // packages/plugins/experimental/plugin-transcription/src/util/random-queue-dxn.ts
11
+ import { ObjectId } from "@dxos/echo-schema";
12
+ import { DXN, QueueSubspaceTags, SpaceId } from "@dxos/keys";
13
+ var randomQueueDxn = () => new DXN(DXN.kind.QUEUE, [
14
+ QueueSubspaceTags.DATA,
15
+ SpaceId.random(),
16
+ ObjectId.random()
17
+ ]);
18
+
19
+ // packages/plugins/experimental/plugin-transcription/src/util/array.ts
20
+ var mergeFloat64Arrays = (arrays) => {
21
+ const newArray = new Float64Array(arrays.reduce((acc, array) => array.length + acc, 0));
22
+ let offset = 0;
23
+ for (const array of arrays) {
24
+ newArray.set(array, offset);
25
+ offset += array.length;
26
+ }
27
+ return newArray;
28
+ };
29
+
30
+ // packages/plugins/experimental/plugin-transcription/src/util/monitor-audio-level.ts
31
+ var monitorAudioLevel = ({ mediaStreamTrack, onMeasure, intervalMs = 1e3 / 10 }) => {
32
+ let timeout = -1;
33
+ let interval = -1;
34
+ const audioContext = new AudioContext();
35
+ const stream = new MediaStream();
36
+ stream.addTrack(mediaStreamTrack);
37
+ const mediaStreamAudioSourceNode = audioContext.createMediaStreamSource(stream);
38
+ const analyserNode = audioContext.createAnalyser();
39
+ mediaStreamAudioSourceNode.connect(analyserNode);
40
+ analyserNode.fftSize = 32;
41
+ const pcmData = new Float32Array(analyserNode.fftSize);
42
+ let peak = 0;
43
+ interval = window.setInterval(() => {
44
+ onMeasure(peak);
45
+ peak = 0;
46
+ }, intervalMs);
47
+ const tick = () => {
48
+ timeout = window.setTimeout(() => {
49
+ analyserNode.getFloatTimeDomainData(pcmData);
50
+ let sumSquares = 0;
51
+ for (const amplitude of pcmData) {
52
+ sumSquares += amplitude * amplitude;
53
+ }
54
+ const current = Math.sqrt(sumSquares / pcmData.length);
55
+ if (current > peak) {
56
+ peak = current;
57
+ }
58
+ tick();
59
+ }, intervalMs);
60
+ };
61
+ tick();
62
+ return () => {
63
+ mediaStreamAudioSourceNode.disconnect();
64
+ analyserNode.disconnect();
65
+ void audioContext.close();
66
+ clearInterval(interval);
67
+ clearTimeout(timeout);
68
+ stream.removeTrack(mediaStreamTrack);
69
+ };
70
+ };
71
+
72
+ export {
73
+ mergeFloat64Arrays,
74
+ getTimeStr,
75
+ monitorAudioLevel,
76
+ randomQueueDxn
77
+ };
78
+ //# sourceMappingURL=chunk-ZMES3U2D.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/util/get-time-str.ts", "../../../src/util/random-queue-dxn.ts", "../../../src/util/array.ts", "../../../src/util/monitor-audio-level.ts"],
4
+ "sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nexport const getTimeStr = (timestamp?: number) =>\n new Date(timestamp ?? Date.now()).toLocaleTimeString('en-US', {\n timeZone: 'UTC',\n hour12: true,\n hour: 'numeric',\n minute: '2-digit',\n second: '2-digit',\n });\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { ObjectId } from '@dxos/echo-schema';\nimport { DXN, QueueSubspaceTags, SpaceId } from '@dxos/keys';\n\nexport const randomQueueDxn = () =>\n new DXN(DXN.kind.QUEUE, [QueueSubspaceTags.DATA, SpaceId.random(), ObjectId.random()]);\n", "//\n// Copyright 2025 DXOS.org\n//\n\nexport const mergeFloat64Arrays = (arrays: Float64Array[]) => {\n const newArray = new Float64Array(arrays.reduce((acc, array) => array.length + acc, 0));\n let offset = 0;\n for (const array of arrays) {\n newArray.set(array, offset);\n offset += array.length;\n }\n\n return newArray;\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nexport const monitorAudioLevel = ({\n mediaStreamTrack,\n onMeasure,\n intervalMs = 1000 / 10, // 12 fps.\n}: {\n mediaStreamTrack: MediaStreamTrack;\n onMeasure: (value: number) => void;\n intervalMs?: number;\n}) => {\n let timeout = -1;\n let interval = -1;\n const audioContext = new AudioContext();\n const stream = new MediaStream();\n stream.addTrack(mediaStreamTrack);\n const mediaStreamAudioSourceNode = audioContext.createMediaStreamSource(stream);\n const analyserNode = audioContext.createAnalyser();\n mediaStreamAudioSourceNode.connect(analyserNode);\n // Since we just need a rough approximation and will be measuring\n // frequently, we want to drop this down from the default of 2048.\n analyserNode.fftSize = 32;\n\n const pcmData = new Float32Array(analyserNode.fftSize);\n let peak = 0;\n\n interval = window.setInterval(() => {\n onMeasure(peak);\n peak = 0;\n }, intervalMs);\n\n const tick = () => {\n timeout = window.setTimeout(() => {\n analyserNode.getFloatTimeDomainData(pcmData);\n let sumSquares = 0.0;\n for (const amplitude of pcmData) {\n sumSquares += amplitude * amplitude;\n }\n const current = Math.sqrt(sumSquares / pcmData.length);\n if (current > peak) {\n peak = current;\n }\n tick();\n }, intervalMs);\n };\n tick();\n\n return () => {\n mediaStreamAudioSourceNode.disconnect();\n analyserNode.disconnect();\n void audioContext.close();\n clearInterval(interval);\n clearTimeout(timeout);\n stream.removeTrack(mediaStreamTrack);\n };\n};\n"],
5
+ "mappings": ";AAIO,IAAMA,aAAa,CAACC,cACzB,IAAIC,KAAKD,aAAaC,KAAKC,IAAG,CAAA,EAAIC,mBAAmB,SAAS;EAC5DC,UAAU;EACVC,QAAQ;EACRC,MAAM;EACNC,QAAQ;EACRC,QAAQ;AACV,CAAA;;;ACPF,SAASC,gBAAgB;AACzB,SAASC,KAAKC,mBAAmBC,eAAe;AAEzC,IAAMC,iBAAiB,MAC5B,IAAIC,IAAIA,IAAIC,KAAKC,OAAO;EAACC,kBAAkBC;EAAMC,QAAQC,OAAM;EAAIC,SAASD,OAAM;CAAG;;;ACJhF,IAAME,qBAAqB,CAACC,WAAAA;AACjC,QAAMC,WAAW,IAAIC,aAAaF,OAAOG,OAAO,CAACC,KAAKC,UAAUA,MAAMC,SAASF,KAAK,CAAA,CAAA;AACpF,MAAIG,SAAS;AACb,aAAWF,SAASL,QAAQ;AAC1BC,aAASO,IAAIH,OAAOE,MAAAA;AACpBA,cAAUF,MAAMC;EAClB;AAEA,SAAOL;AACT;;;ACTO,IAAMQ,oBAAoB,CAAC,EAChCC,kBACAC,WACAC,aAAa,MAAO,GAAE,MAKvB;AACC,MAAIC,UAAU;AACd,MAAIC,WAAW;AACf,QAAMC,eAAe,IAAIC,aAAAA;AACzB,QAAMC,SAAS,IAAIC,YAAAA;AACnBD,SAAOE,SAAST,gBAAAA;AAChB,QAAMU,6BAA6BL,aAAaM,wBAAwBJ,MAAAA;AACxE,QAAMK,eAAeP,aAAaQ,eAAc;AAChDH,6BAA2BI,QAAQF,YAAAA;AAGnCA,eAAaG,UAAU;AAEvB,QAAMC,UAAU,IAAIC,aAAaL,aAAaG,OAAO;AACrD,MAAIG,OAAO;AAEXd,aAAWe,OAAOC,YAAY,MAAA;AAC5BnB,cAAUiB,IAAAA;AACVA,WAAO;EACT,GAAGhB,UAAAA;AAEH,QAAMmB,OAAO,MAAA;AACXlB,cAAUgB,OAAOG,WAAW,MAAA;AAC1BV,mBAAaW,uBAAuBP,OAAAA;AACpC,UAAIQ,aAAa;AACjB,iBAAWC,aAAaT,SAAS;AAC/BQ,sBAAcC,YAAYA;MAC5B;AACA,YAAMC,UAAUC,KAAKC,KAAKJ,aAAaR,QAAQa,MAAM;AACrD,UAAIH,UAAUR,MAAM;AAClBA,eAAOQ;MACT;AACAL,WAAAA;IACF,GAAGnB,UAAAA;EACL;AACAmB,OAAAA;AAEA,SAAO,MAAA;AACLX,+BAA2BoB,WAAU;AACrClB,iBAAakB,WAAU;AACvB,SAAKzB,aAAa0B,MAAK;AACvBC,kBAAc5B,QAAAA;AACd6B,iBAAa9B,OAAAA;AACbI,WAAO2B,YAAYlC,gBAAAA;EACrB;AACF;",
6
+ "names": ["getTimeStr", "timestamp", "Date", "now", "toLocaleTimeString", "timeZone", "hour12", "hour", "minute", "second", "ObjectId", "DXN", "QueueSubspaceTags", "SpaceId", "randomQueueDxn", "DXN", "kind", "QUEUE", "QueueSubspaceTags", "DATA", "SpaceId", "random", "ObjectId", "mergeFloat64Arrays", "arrays", "newArray", "Float64Array", "reduce", "acc", "array", "length", "offset", "set", "monitorAudioLevel", "mediaStreamTrack", "onMeasure", "intervalMs", "timeout", "interval", "audioContext", "AudioContext", "stream", "MediaStream", "addTrack", "mediaStreamAudioSourceNode", "createMediaStreamSource", "analyserNode", "createAnalyser", "connect", "fftSize", "pcmData", "Float32Array", "peak", "window", "setInterval", "tick", "setTimeout", "getFloatTimeDomainData", "sumSquares", "amplitude", "current", "Math", "sqrt", "length", "disconnect", "close", "clearInterval", "clearTimeout", "removeTrack"]
7
+ }