@dxos/plugin-transcription 0.7.5-staging.e6154f3 → 0.8.1-main.ae460ac

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 (72) hide show
  1. package/dist/lib/browser/{TranscriptContainer-SX6PNFEC.mjs → TranscriptContainer-N4KQHMY4.mjs} +2 -2
  2. package/dist/lib/browser/{chunk-AS364WZZ.mjs → chunk-BDVUIRBP.mjs} +2 -2
  3. package/dist/lib/browser/chunk-GHTRJTEB.mjs +35 -0
  4. package/dist/lib/browser/chunk-GHTRJTEB.mjs.map +7 -0
  5. package/dist/lib/browser/{chunk-R4HHS6FA.mjs → chunk-YX447BJ4.mjs} +16 -16
  6. package/dist/lib/browser/chunk-YX447BJ4.mjs.map +7 -0
  7. package/dist/lib/browser/index.mjs +180 -72
  8. package/dist/lib/browser/index.mjs.map +4 -4
  9. package/dist/lib/browser/{intent-resolver-EAR2TFK2.mjs → intent-resolver-RW6DEJC2.mjs} +2 -2
  10. package/dist/lib/browser/meta.json +1 -1
  11. package/dist/lib/browser/{react-surface-FOEWLLTZ.mjs → react-surface-UPTZBHVB.mjs} +3 -3
  12. package/dist/lib/node/{TranscriptContainer-HU763SN3.cjs → TranscriptContainer-4BWXOVML.cjs} +7 -7
  13. package/dist/lib/node/{TranscriptContainer-HU763SN3.cjs.map → TranscriptContainer-4BWXOVML.cjs.map} +2 -2
  14. package/dist/lib/node/{chunk-YV74Z74I.cjs → chunk-ANSWGFMS.cjs} +18 -18
  15. package/dist/lib/node/chunk-ANSWGFMS.cjs.map +7 -0
  16. package/dist/lib/node/{chunk-JBN3P6ZF.cjs → chunk-HDRXDMK2.cjs} +4 -46
  17. package/dist/lib/node/chunk-HDRXDMK2.cjs.map +7 -0
  18. package/dist/lib/node/{chunk-QWXLQPP5.cjs → chunk-I35KHI2G.cjs} +5 -5
  19. package/dist/lib/node/index.cjs +182 -74
  20. package/dist/lib/node/index.cjs.map +4 -4
  21. package/dist/lib/node/{intent-resolver-3KJZGGUQ.cjs → intent-resolver-KLBZ25XJ.cjs} +7 -7
  22. package/dist/lib/node/meta.json +1 -1
  23. package/dist/lib/node/{react-surface-AGGGDOUC.cjs → react-surface-NCKXB7EQ.cjs} +7 -7
  24. package/dist/lib/node-esm/{TranscriptContainer-DVBXQIQ4.mjs → TranscriptContainer-6IKRASR6.mjs} +2 -2
  25. package/dist/lib/node-esm/{chunk-WEZGRUG6.mjs → chunk-2CPKXRN6.mjs} +2 -2
  26. package/dist/lib/node-esm/chunk-LORUIVS4.mjs +37 -0
  27. package/dist/lib/node-esm/chunk-LORUIVS4.mjs.map +7 -0
  28. package/dist/lib/node-esm/{chunk-36EQXBWR.mjs → chunk-ZMK2QLW2.mjs} +16 -16
  29. package/dist/lib/node-esm/chunk-ZMK2QLW2.mjs.map +7 -0
  30. package/dist/lib/node-esm/index.mjs +180 -72
  31. package/dist/lib/node-esm/index.mjs.map +4 -4
  32. package/dist/lib/node-esm/{intent-resolver-UGLYRD4X.mjs → intent-resolver-4FMISUPW.mjs} +2 -2
  33. package/dist/lib/node-esm/meta.json +1 -1
  34. package/dist/lib/node-esm/{react-surface-6AYPLJ2B.mjs → react-surface-2WJQ67LB.mjs} +3 -3
  35. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
  36. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  37. package/dist/types/src/hooks/index.d.ts +0 -1
  38. package/dist/types/src/hooks/index.d.ts.map +1 -1
  39. package/dist/types/src/index.d.ts +1 -0
  40. package/dist/types/src/index.d.ts.map +1 -1
  41. package/dist/types/src/transcriber/media-stream-recorder.d.ts +1 -0
  42. package/dist/types/src/transcriber/media-stream-recorder.d.ts.map +1 -1
  43. package/dist/types/src/transcription-manager.d.ts +36 -0
  44. package/dist/types/src/transcription-manager.d.ts.map +1 -0
  45. package/package.json +36 -36
  46. package/src/components/TranscriptContainer.tsx +11 -15
  47. package/src/hooks/index.ts +0 -1
  48. package/src/index.ts +1 -0
  49. package/src/transcriber/media-stream-recorder.ts +4 -0
  50. package/src/transcription-manager.ts +173 -0
  51. package/dist/lib/browser/chunk-R4HHS6FA.mjs.map +0 -7
  52. package/dist/lib/browser/chunk-ZMES3U2D.mjs +0 -78
  53. package/dist/lib/browser/chunk-ZMES3U2D.mjs.map +0 -7
  54. package/dist/lib/node/chunk-JBN3P6ZF.cjs.map +0 -7
  55. package/dist/lib/node/chunk-YV74Z74I.cjs.map +0 -7
  56. package/dist/lib/node-esm/chunk-36EQXBWR.mjs.map +0 -7
  57. package/dist/lib/node-esm/chunk-XYU6B73V.mjs +0 -80
  58. package/dist/lib/node-esm/chunk-XYU6B73V.mjs.map +0 -7
  59. package/dist/types/src/hooks/useIsSpeaking.d.ts +0 -2
  60. package/dist/types/src/hooks/useIsSpeaking.d.ts.map +0 -1
  61. package/src/hooks/useIsSpeaking.ts +0 -77
  62. /package/dist/lib/browser/{TranscriptContainer-SX6PNFEC.mjs.map → TranscriptContainer-N4KQHMY4.mjs.map} +0 -0
  63. /package/dist/lib/browser/{chunk-AS364WZZ.mjs.map → chunk-BDVUIRBP.mjs.map} +0 -0
  64. /package/dist/lib/browser/{intent-resolver-EAR2TFK2.mjs.map → intent-resolver-RW6DEJC2.mjs.map} +0 -0
  65. /package/dist/lib/browser/{react-surface-FOEWLLTZ.mjs.map → react-surface-UPTZBHVB.mjs.map} +0 -0
  66. /package/dist/lib/node/{chunk-QWXLQPP5.cjs.map → chunk-I35KHI2G.cjs.map} +0 -0
  67. /package/dist/lib/node/{intent-resolver-3KJZGGUQ.cjs.map → intent-resolver-KLBZ25XJ.cjs.map} +0 -0
  68. /package/dist/lib/node/{react-surface-AGGGDOUC.cjs.map → react-surface-NCKXB7EQ.cjs.map} +0 -0
  69. /package/dist/lib/node-esm/{TranscriptContainer-DVBXQIQ4.mjs.map → TranscriptContainer-6IKRASR6.mjs.map} +0 -0
  70. /package/dist/lib/node-esm/{chunk-WEZGRUG6.mjs.map → chunk-2CPKXRN6.mjs.map} +0 -0
  71. /package/dist/lib/node-esm/{intent-resolver-UGLYRD4X.mjs.map → intent-resolver-4FMISUPW.mjs.map} +0 -0
  72. /package/dist/lib/node-esm/{react-surface-6AYPLJ2B.mjs.map → react-surface-2WJQ67LB.mjs.map} +0 -0
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  TranscriptContainer_default,
3
3
  TranscriptionContainer
4
- } from "./chunk-R4HHS6FA.mjs";
4
+ } from "./chunk-YX447BJ4.mjs";
5
5
  import "./chunk-QIHUPVQD.mjs";
6
6
  export {
7
7
  TranscriptionContainer,
8
8
  TranscriptContainer_default as default
9
9
  };
10
- //# sourceMappingURL=TranscriptContainer-SX6PNFEC.mjs.map
10
+ //# sourceMappingURL=TranscriptContainer-N4KQHMY4.mjs.map
@@ -1,8 +1,8 @@
1
1
  // packages/plugins/experimental/plugin-transcription/src/components/index.ts
2
2
  import { lazy } from "react";
3
- var TranscriptContainer = lazy(() => import("./TranscriptContainer-SX6PNFEC.mjs"));
3
+ var TranscriptContainer = lazy(() => import("./TranscriptContainer-N4KQHMY4.mjs"));
4
4
 
5
5
  export {
6
6
  TranscriptContainer
7
7
  };
8
- //# sourceMappingURL=chunk-AS364WZZ.mjs.map
8
+ //# sourceMappingURL=chunk-BDVUIRBP.mjs.map
@@ -0,0 +1,35 @@
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
+ export {
31
+ mergeFloat64Arrays,
32
+ getTimeStr,
33
+ randomQueueDxn
34
+ };
35
+ //# sourceMappingURL=chunk-GHTRJTEB.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"],
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"],
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;",
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"]
7
+ }
@@ -8,7 +8,7 @@ import { pipe } from "effect";
8
8
  import React2, { useCallback, useMemo, useState } from "react";
9
9
  import { chain, createIntent, LayoutAction, useIntentDispatcher } from "@dxos/app-framework";
10
10
  import { Message } from "@dxos/artifact";
11
- import { AIServiceClientImpl, DEFAULT_LLM_MODEL, MixedStreamParser } from "@dxos/assistant";
11
+ import { AIServiceEdgeClient, DEFAULT_LLM_MODEL, MixedStreamParser } from "@dxos/assistant";
12
12
  import { create, getSpace, makeRef } from "@dxos/client/echo";
13
13
  import { QueueImpl } from "@dxos/echo-db";
14
14
  import { createStatic, isInstanceOf } from "@dxos/echo-schema";
@@ -81,7 +81,7 @@ var __dxlog_file = "/home/runner/work/dxos/dxos/packages/plugins/experimental/pl
81
81
  var TranscriptionContainer = ({ transcript }) => {
82
82
  const { t } = useTranslation2(TRANSCRIPTION_PLUGIN);
83
83
  const edge = useEdgeClient();
84
- const aiService = useAiServiceClient();
84
+ const ai = useAiServiceClient();
85
85
  const { dispatchPromise: dispatch } = useIntentDispatcher();
86
86
  const queue = useQueue(edge, transcript.queue ? DXN.parse(transcript.queue) : void 0, {
87
87
  pollInterval: 1e3
@@ -90,7 +90,7 @@ var TranscriptionContainer = ({ transcript }) => {
90
90
  const handleSummarize = useCallback(async () => {
91
91
  setIsSummarizing(true);
92
92
  try {
93
- const document = await summarizeTranscript(edge, aiService, transcript);
93
+ const document = await summarizeTranscript(edge, ai, transcript);
94
94
  const space = getSpace(transcript);
95
95
  const target = space?.properties[CollectionType.typename]?.target;
96
96
  await dispatch(pipe(createIntent(SpaceAction.AddObject, {
@@ -124,17 +124,17 @@ var TranscriptionContainer = ({ transcript }) => {
124
124
  })));
125
125
  };
126
126
  var TranscriptContainer_default = TranscriptionContainer;
127
- var summarizeTranscript = async (edgeClient, aiService, transcript) => {
127
+ var summarizeTranscript = async (edge, ai, transcript) => {
128
128
  invariant(transcript.queue, "No queue found for transcript", {
129
129
  F: __dxlog_file,
130
- L: 90,
130
+ L: 86,
131
131
  S: void 0,
132
132
  A: [
133
133
  "transcript.queue",
134
134
  "'No queue found for transcript'"
135
135
  ]
136
136
  });
137
- const queue = new QueueImpl(edgeClient, DXN.parse(transcript.queue));
137
+ const queue = new QueueImpl(edge, DXN.parse(transcript.queue));
138
138
  await queue.refresh();
139
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
140
  const parser = new MixedStreamParser();
@@ -142,11 +142,11 @@ var summarizeTranscript = async (edgeClient, aiService, transcript) => {
142
142
  blockCount: queue.items.length
143
143
  }, {
144
144
  F: __dxlog_file,
145
- L: 101,
145
+ L: 97,
146
146
  S: void 0,
147
147
  C: (f, a) => f(...a)
148
148
  });
149
- const output = await parser.parse(await aiService.exec({
149
+ const output = await parser.parse(await ai.exec({
150
150
  model: DEFAULT_LLM_MODEL,
151
151
  systemPrompt: SUMMARIZE_PROMPT,
152
152
  history: [
@@ -165,13 +165,13 @@ var summarizeTranscript = async (edgeClient, aiService, transcript) => {
165
165
  output
166
166
  }, {
167
167
  F: __dxlog_file,
168
- L: 110,
168
+ L: 106,
169
169
  S: void 0,
170
170
  C: (f, a) => f(...a)
171
171
  });
172
172
  invariant(output[0].content[0].type === "text", "Expected text content", {
173
173
  F: __dxlog_file,
174
- L: 111,
174
+ L: 107,
175
175
  S: void 0,
176
176
  A: [
177
177
  "output[0].content[0].type === 'text'",
@@ -211,10 +211,10 @@ var SUMMARIZE_PROMPT = `
211
211
  # Tasks
212
212
  At the end of the summary include tasks.
213
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
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
218
 
219
219
  Format all tasks as markdown checkboxes using the syntax:
220
220
  - [ ] Task description
@@ -226,7 +226,7 @@ var SUMMARIZE_PROMPT = `
226
226
  var useAiServiceClient = () => {
227
227
  const config = useConfig();
228
228
  const endpoint = config.values.runtime?.services?.ai?.server ?? "http://localhost:8788";
229
- return useMemo(() => new AIServiceClientImpl({
229
+ return useMemo(() => new AIServiceEdgeClient({
230
230
  endpoint
231
231
  }), [
232
232
  endpoint
@@ -238,4 +238,4 @@ export {
238
238
  TranscriptionContainer,
239
239
  TranscriptContainer_default
240
240
  };
241
- //# sourceMappingURL=chunk-R4HHS6FA.mjs.map
241
+ //# sourceMappingURL=chunk-YX447BJ4.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 { AIServiceEdgeClient, 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 ai = 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, ai, 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 (edge: EdgeHttpClient, ai: AIServiceClient, transcript: TranscriptType) => {\n invariant(transcript.queue, 'No queue found for transcript');\n\n const queue = new QueueImpl(edge, 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 ai.exec({\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'; // TOOD(burdon): Standardize consts.\n return useMemo(() => new AIServiceEdgeClient({ 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": "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",
6
+ "names": ["pipe", "React", "useCallback", "useMemo", "useState", "chain", "createIntent", "LayoutAction", "useIntentDispatcher", "Message", "AIServiceEdgeClient", "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", "ai", "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", "invariant", "QueueImpl", "refresh", "content", "filter", "block", "isInstanceOf", "TranscriptBlock", "map", "author", "segments", "segment", "text", "join", "parser", "MixedStreamParser", "log", "info", "blockCount", "length", "output", "exec", "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", "server", "useMemo", "AIServiceEdgeClient"]
7
+ }
@@ -1,17 +1,17 @@
1
1
  import {
2
- mergeFloat64Arrays,
3
- monitorAudioLevel
4
- } from "./chunk-ZMES3U2D.mjs";
2
+ mergeFloat64Arrays
3
+ } from "./chunk-GHTRJTEB.mjs";
5
4
  import {
6
5
  TranscriptContainer
7
- } from "./chunk-AS364WZZ.mjs";
6
+ } from "./chunk-BDVUIRBP.mjs";
8
7
  import {
9
8
  Transcript,
10
9
  TranscriptionContainer
11
- } from "./chunk-R4HHS6FA.mjs";
10
+ } from "./chunk-YX447BJ4.mjs";
12
11
  import {
13
12
  TRANSCRIPTION_PLUGIN,
14
13
  TRANSCRIPTION_URL,
14
+ TranscriptBlock,
15
15
  TranscriptType,
16
16
  meta
17
17
  } from "./chunk-QIHUPVQD.mjs";
@@ -28,8 +28,8 @@ var TranscriptionCapabilities;
28
28
 
29
29
  // packages/plugins/experimental/plugin-transcription/src/capabilities/index.ts
30
30
  var AppGraphBuilder = lazy(() => import("./app-graph-builder-ZSSJIFY7.mjs"));
31
- var IntentResolver = lazy(() => import("./intent-resolver-EAR2TFK2.mjs"));
32
- var ReactSurface = lazy(() => import("./react-surface-FOEWLLTZ.mjs"));
31
+ var IntentResolver = lazy(() => import("./intent-resolver-RW6DEJC2.mjs"));
32
+ var ReactSurface = lazy(() => import("./react-surface-UPTZBHVB.mjs"));
33
33
 
34
34
  // packages/plugins/experimental/plugin-transcription/src/hooks/useAudioFile.ts
35
35
  import { useEffect, useState } from "react";
@@ -121,64 +121,8 @@ var useAudioTrack = (active) => {
121
121
  return track;
122
122
  };
123
123
 
124
- // packages/plugins/experimental/plugin-transcription/src/hooks/useIsSpeaking.ts
125
- import { useEffect as useEffect3, useRef, useState as useState3 } from "react";
126
- var useIsSpeaking = (mediaStreamTrack) => {
127
- const [isSpeaking, setIsSpeaking] = useState3(false);
128
- const isSpeakingRef = useRef(isSpeaking);
129
- useEffect3(() => {
130
- if (!mediaStreamTrack) {
131
- setIsSpeaking(false);
132
- return;
133
- }
134
- isSpeakingRef.current = isSpeaking;
135
- const interval = window.setInterval(() => {
136
- if (isSpeaking === isSpeakingRef.current) {
137
- return;
138
- }
139
- setIsSpeaking(isSpeakingRef.current);
140
- }, 50);
141
- return () => {
142
- clearInterval(interval);
143
- };
144
- }, [
145
- isSpeaking,
146
- isSpeakingRef,
147
- mediaStreamTrack
148
- ]);
149
- useEffect3(() => {
150
- if (!mediaStreamTrack) {
151
- return;
152
- }
153
- let timeout = -1;
154
- const cleanup = monitorAudioLevel({
155
- mediaStreamTrack,
156
- onMeasure: (vol) => {
157
- const audioLevelAboveThreshold = vol > (isSpeakingRef.current ? 0.02 : 0.05);
158
- if (audioLevelAboveThreshold) {
159
- clearTimeout(timeout);
160
- timeout = -1;
161
- isSpeakingRef.current = true;
162
- } else if (timeout === -1) {
163
- timeout = window.setTimeout(() => {
164
- isSpeakingRef.current = false;
165
- timeout = -1;
166
- }, 1e3);
167
- }
168
- }
169
- });
170
- return () => {
171
- cleanup();
172
- };
173
- }, [
174
- isSpeaking,
175
- mediaStreamTrack
176
- ]);
177
- return isSpeaking;
178
- };
179
-
180
124
  // packages/plugins/experimental/plugin-transcription/src/hooks/useTranscriber.ts
181
- import { useEffect as useEffect4, useMemo } from "react";
125
+ import { useEffect as useEffect3, useMemo } from "react";
182
126
 
183
127
  // packages/plugins/experimental/plugin-transcription/src/transcriber/media-stream-recorder.ts
184
128
  import { MediaRecorder, register } from "extendable-media-recorder";
@@ -214,6 +158,9 @@ var MediaStreamRecorder = class {
214
158
  bitDepthCode: settings.sampleSize ? String(settings.sampleSize) : "16"
215
159
  };
216
160
  }
161
+ get mediaStreamTrack() {
162
+ return this._mediaStreamTrack;
163
+ }
217
164
  setOnChunk(onChunk) {
218
165
  this._onChunk = onChunk;
219
166
  }
@@ -222,7 +169,7 @@ var MediaStreamRecorder = class {
222
169
  err
223
170
  }, {
224
171
  F: __dxlog_file2,
225
- L: 58,
172
+ L: 62,
226
173
  S: this,
227
174
  C: (f, a) => f(...a)
228
175
  }));
@@ -239,7 +186,7 @@ var MediaStreamRecorder = class {
239
186
  }
240
187
  invariant(this._onChunk, "MediaStreamRecorder: onChunk is not set", {
241
188
  F: __dxlog_file2,
242
- L: 69,
189
+ L: 73,
243
190
  S: this,
244
191
  A: [
245
192
  "this._onChunk",
@@ -274,7 +221,7 @@ var MediaStreamRecorder = class {
274
221
  } else {
275
222
  log2.warn("MediaStreamRecorder: no header", void 0, {
276
223
  F: __dxlog_file2,
277
- L: 100,
224
+ L: 104,
278
225
  S: this,
279
226
  C: (f, a) => f(...a)
280
227
  });
@@ -479,7 +426,7 @@ var useTranscriber = ({ audioStreamTrack, onSegments }) => {
479
426
  audioStreamTrack,
480
427
  onSegments
481
428
  ]);
482
- useEffect4(() => {
429
+ useEffect3(() => {
483
430
  return () => {
484
431
  void transcriber?.close();
485
432
  };
@@ -490,7 +437,7 @@ var useTranscriber = ({ audioStreamTrack, onSegments }) => {
490
437
  };
491
438
 
492
439
  // packages/plugins/experimental/plugin-transcription/src/hooks/useVoiceInput.ts
493
- import { useState as useState4, useEffect as useEffect5, useCallback } from "react";
440
+ import { useState as useState3, useEffect as useEffect4, useCallback } from "react";
494
441
  import { scheduleMicroTask } from "@dxos/async";
495
442
  import { Context } from "@dxos/context";
496
443
  import { log as log4 } from "@dxos/log";
@@ -503,13 +450,13 @@ var useVoiceInput = ({ active, onUpdate }) => {
503
450
  const text = segments.map((str) => str.text.trim().replace(/[^\w\s]/g, "")).join(" ");
504
451
  onUpdate(text);
505
452
  }, []);
506
- const [recording, setRecording] = useState4(false);
453
+ const [recording, setRecording] = useState3(false);
507
454
  const track = useAudioTrack(active);
508
455
  const transcriber = useTranscriber({
509
456
  audioStreamTrack: track,
510
457
  onSegments: handleSegments
511
458
  });
512
- useEffect5(() => {
459
+ useEffect4(() => {
513
460
  const ctx = new Context(void 0, {
514
461
  F: __dxlog_file4,
515
462
  L: 43
@@ -551,6 +498,167 @@ var useVoiceInput = ({ active, onUpdate }) => {
551
498
  };
552
499
  };
553
500
 
501
+ // packages/plugins/experimental/plugin-transcription/src/transcription-manager.ts
502
+ import { synchronized as synchronized2 } from "@dxos/async";
503
+ import { Resource as Resource2 } from "@dxos/context";
504
+ import { QueueImpl } from "@dxos/echo-db";
505
+ import { createStatic } from "@dxos/echo-schema";
506
+ import { invariant as invariant2 } from "@dxos/invariant";
507
+ import { DXN } from "@dxos/keys";
508
+ function _ts_decorate3(decorators, target, key, desc) {
509
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
510
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
511
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
512
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
513
+ }
514
+ var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/plugins/experimental/plugin-transcription/src/transcription-manager.ts";
515
+ var RECORD_INTERVAL2 = 200;
516
+ var PREFIXED_CHUNKS_AMOUNT2 = 10;
517
+ var TRANSCRIBE_AFTER_CHUNKS_AMOUNT2 = 50;
518
+ var TranscriptionManager = class extends Resource2 {
519
+ constructor(edgeClient) {
520
+ super();
521
+ this._audioStreamTrack = void 0;
522
+ this._name = void 0;
523
+ this._mediaRecorder = void 0;
524
+ this._transcriber = void 0;
525
+ this._enabled = false;
526
+ this._queue = void 0;
527
+ this._edgeClient = edgeClient;
528
+ }
529
+ async _open() {
530
+ await this._toggleTranscriber();
531
+ }
532
+ async _close() {
533
+ void this._transcriber?.close();
534
+ }
535
+ setRecording(recording) {
536
+ if (!this.isOpen || !this._enabled) {
537
+ return;
538
+ }
539
+ if (recording) {
540
+ this._transcriber?.startChunksRecording();
541
+ } else {
542
+ this._transcriber?.stopChunksRecording();
543
+ }
544
+ }
545
+ /**
546
+ * Enable or disable transcription.
547
+ * @param enabled - Whether to enable transcription.
548
+ */
549
+ async setEnabled(enabled) {
550
+ if (this._enabled === enabled) {
551
+ return;
552
+ }
553
+ this._enabled = enabled ?? false;
554
+ this.isOpen && await this._toggleTranscriber();
555
+ }
556
+ async setAudioTrack(track) {
557
+ if (this._audioStreamTrack === track) {
558
+ return;
559
+ }
560
+ this._audioStreamTrack = track;
561
+ this.isOpen && await this._toggleTranscriber();
562
+ }
563
+ /**
564
+ * Set the queue to save the transcription to.
565
+ * @param queue - The queue to save the transcription to or the DXN of the queue.
566
+ */
567
+ setQueue(queue) {
568
+ switch (typeof queue) {
569
+ case "string":
570
+ if (this._queue?.dxn.toString() === queue) {
571
+ return;
572
+ }
573
+ this._queue = new QueueImpl(this._edgeClient, DXN.parse(queue));
574
+ break;
575
+ case "object":
576
+ if (this._queue === queue) {
577
+ return;
578
+ }
579
+ invariant2(queue instanceof QueueImpl, void 0, {
580
+ F: __dxlog_file5,
581
+ L: 110,
582
+ S: this,
583
+ A: [
584
+ "queue instanceof QueueImpl",
585
+ ""
586
+ ]
587
+ });
588
+ this._queue = queue;
589
+ break;
590
+ case "undefined":
591
+ this._queue = void 0;
592
+ break;
593
+ }
594
+ }
595
+ setName(name) {
596
+ if (this._name === name) {
597
+ return;
598
+ }
599
+ this._name = name;
600
+ }
601
+ async _toggleTranscriber() {
602
+ await this._maybeReinitTranscriber();
603
+ if (this._enabled) {
604
+ await this._transcriber?.open();
605
+ } else {
606
+ await this._transcriber?.close();
607
+ }
608
+ }
609
+ async _maybeReinitTranscriber() {
610
+ if (!this._audioStreamTrack || !this._enabled) {
611
+ return;
612
+ }
613
+ let needReinit = false;
614
+ if (this._audioStreamTrack !== this._mediaRecorder?.mediaStreamTrack) {
615
+ this._mediaRecorder = new MediaStreamRecorder({
616
+ mediaStreamTrack: this._audioStreamTrack,
617
+ interval: RECORD_INTERVAL2
618
+ });
619
+ needReinit = true;
620
+ }
621
+ if (needReinit) {
622
+ await this._transcriber?.close();
623
+ this._transcriber = new Transcriber({
624
+ config: {
625
+ transcribeAfterChunksAmount: TRANSCRIBE_AFTER_CHUNKS_AMOUNT2,
626
+ prefixBufferChunksAmount: PREFIXED_CHUNKS_AMOUNT2
627
+ },
628
+ recorder: this._mediaRecorder,
629
+ onSegments: (segments) => this._onSegments(segments)
630
+ });
631
+ }
632
+ }
633
+ async _onSegments(segments) {
634
+ if (!this.isOpen || !this._queue) {
635
+ return;
636
+ }
637
+ const block = createStatic(TranscriptBlock, {
638
+ author: this._name,
639
+ segments
640
+ });
641
+ this._queue.append([
642
+ block
643
+ ]);
644
+ }
645
+ };
646
+ _ts_decorate3([
647
+ synchronized2
648
+ ], TranscriptionManager.prototype, "setRecording", null);
649
+ _ts_decorate3([
650
+ synchronized2
651
+ ], TranscriptionManager.prototype, "setEnabled", null);
652
+ _ts_decorate3([
653
+ synchronized2
654
+ ], TranscriptionManager.prototype, "setAudioTrack", null);
655
+ _ts_decorate3([
656
+ synchronized2
657
+ ], TranscriptionManager.prototype, "setQueue", null);
658
+ _ts_decorate3([
659
+ synchronized2
660
+ ], TranscriptionManager.prototype, "setName", null);
661
+
554
662
  // packages/plugins/experimental/plugin-transcription/src/TranscriptionPlugin.tsx
555
663
  import { Capabilities, Events, contributes, defineModule, definePlugin } from "@dxos/app-framework";
556
664
  import { ClientCapabilities, ClientEvents } from "@dxos/plugin-client";
@@ -641,11 +749,11 @@ export {
641
749
  TranscriptContainer,
642
750
  TranscriptionCapabilities,
643
751
  TranscriptionContainer,
752
+ TranscriptionManager,
644
753
  TranscriptionPlugin,
645
754
  meta,
646
755
  useAudioFile,
647
756
  useAudioTrack,
648
- useIsSpeaking,
649
757
  useTranscriber,
650
758
  useVoiceInput
651
759
  };