@dxos/plugin-transcription 0.8.0 → 0.8.1-main.a06ad20

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 (74) 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/components/transcription.stories.d.ts +2 -1
  38. package/dist/types/src/components/transcription.stories.d.ts.map +1 -1
  39. package/dist/types/src/hooks/index.d.ts +0 -1
  40. package/dist/types/src/hooks/index.d.ts.map +1 -1
  41. package/dist/types/src/index.d.ts +1 -0
  42. package/dist/types/src/index.d.ts.map +1 -1
  43. package/dist/types/src/transcriber/media-stream-recorder.d.ts +1 -0
  44. package/dist/types/src/transcriber/media-stream-recorder.d.ts.map +1 -1
  45. package/dist/types/src/transcription-manager.d.ts +36 -0
  46. package/dist/types/src/transcription-manager.d.ts.map +1 -0
  47. package/package.json +37 -37
  48. package/src/components/TranscriptContainer.tsx +11 -15
  49. package/src/hooks/index.ts +0 -1
  50. package/src/index.ts +1 -0
  51. package/src/transcriber/media-stream-recorder.ts +4 -0
  52. package/src/transcription-manager.ts +173 -0
  53. package/dist/lib/browser/chunk-R4HHS6FA.mjs.map +0 -7
  54. package/dist/lib/browser/chunk-ZMES3U2D.mjs +0 -78
  55. package/dist/lib/browser/chunk-ZMES3U2D.mjs.map +0 -7
  56. package/dist/lib/node/chunk-JBN3P6ZF.cjs.map +0 -7
  57. package/dist/lib/node/chunk-YV74Z74I.cjs.map +0 -7
  58. package/dist/lib/node-esm/chunk-36EQXBWR.mjs.map +0 -7
  59. package/dist/lib/node-esm/chunk-XYU6B73V.mjs +0 -80
  60. package/dist/lib/node-esm/chunk-XYU6B73V.mjs.map +0 -7
  61. package/dist/types/src/hooks/useIsSpeaking.d.ts +0 -2
  62. package/dist/types/src/hooks/useIsSpeaking.d.ts.map +0 -1
  63. package/src/hooks/useIsSpeaking.ts +0 -77
  64. /package/dist/lib/browser/{TranscriptContainer-SX6PNFEC.mjs.map → TranscriptContainer-N4KQHMY4.mjs.map} +0 -0
  65. /package/dist/lib/browser/{chunk-AS364WZZ.mjs.map → chunk-BDVUIRBP.mjs.map} +0 -0
  66. /package/dist/lib/browser/{intent-resolver-EAR2TFK2.mjs.map → intent-resolver-RW6DEJC2.mjs.map} +0 -0
  67. /package/dist/lib/browser/{react-surface-FOEWLLTZ.mjs.map → react-surface-UPTZBHVB.mjs.map} +0 -0
  68. /package/dist/lib/node/{chunk-QWXLQPP5.cjs.map → chunk-I35KHI2G.cjs.map} +0 -0
  69. /package/dist/lib/node/{intent-resolver-3KJZGGUQ.cjs.map → intent-resolver-KLBZ25XJ.cjs.map} +0 -0
  70. /package/dist/lib/node/{react-surface-AGGGDOUC.cjs.map → react-surface-NCKXB7EQ.cjs.map} +0 -0
  71. /package/dist/lib/node-esm/{TranscriptContainer-DVBXQIQ4.mjs.map → TranscriptContainer-6IKRASR6.mjs.map} +0 -0
  72. /package/dist/lib/node-esm/{chunk-WEZGRUG6.mjs.map → chunk-2CPKXRN6.mjs.map} +0 -0
  73. /package/dist/lib/node-esm/{intent-resolver-UGLYRD4X.mjs.map → intent-resolver-4FMISUPW.mjs.map} +0 -0
  74. /package/dist/lib/node-esm/{react-surface-6AYPLJ2B.mjs.map → react-surface-2WJQ67LB.mjs.map} +0 -0
@@ -26,13 +26,13 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
26
26
  mod
27
27
  ));
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
- var chunk_YV74Z74I_exports = {};
30
- __export(chunk_YV74Z74I_exports, {
29
+ var chunk_ANSWGFMS_exports = {};
30
+ __export(chunk_ANSWGFMS_exports, {
31
31
  Transcript: () => Transcript,
32
32
  TranscriptContainer_default: () => TranscriptContainer_default,
33
33
  TranscriptionContainer: () => TranscriptionContainer
34
34
  });
35
- module.exports = __toCommonJS(chunk_YV74Z74I_exports);
35
+ module.exports = __toCommonJS(chunk_ANSWGFMS_exports);
36
36
  var import_chunk_UIHEGU6Q = require("./chunk-UIHEGU6Q.cjs");
37
37
  var import_effect = require("effect");
38
38
  var import_react = __toESM(require("react"));
@@ -107,7 +107,7 @@ var __dxlog_file = "/home/runner/work/dxos/dxos/packages/plugins/experimental/pl
107
107
  var TranscriptionContainer = ({ transcript }) => {
108
108
  const { t } = (0, import_react_ui.useTranslation)(import_chunk_UIHEGU6Q.TRANSCRIPTION_PLUGIN);
109
109
  const edge = (0, import_react_edge_client.useEdgeClient)();
110
- const aiService = useAiServiceClient();
110
+ const ai = useAiServiceClient();
111
111
  const { dispatchPromise: dispatch } = (0, import_app_framework.useIntentDispatcher)();
112
112
  const queue = (0, import_react_edge_client.useQueue)(edge, transcript.queue ? import_keys.DXN.parse(transcript.queue) : void 0, {
113
113
  pollInterval: 1e3
@@ -116,7 +116,7 @@ var TranscriptionContainer = ({ transcript }) => {
116
116
  const handleSummarize = (0, import_react.useCallback)(async () => {
117
117
  setIsSummarizing(true);
118
118
  try {
119
- const document = await summarizeTranscript(edge, aiService, transcript);
119
+ const document = await summarizeTranscript(edge, ai, transcript);
120
120
  const space = (0, import_echo.getSpace)(transcript);
121
121
  const target = space?.properties[import_types2.CollectionType.typename]?.target;
122
122
  await dispatch((0, import_effect.pipe)((0, import_app_framework.createIntent)(import_types2.SpaceAction.AddObject, {
@@ -150,17 +150,17 @@ var TranscriptionContainer = ({ transcript }) => {
150
150
  })));
151
151
  };
152
152
  var TranscriptContainer_default = TranscriptionContainer;
153
- var summarizeTranscript = async (edgeClient, aiService, transcript) => {
153
+ var summarizeTranscript = async (edge, ai, transcript) => {
154
154
  (0, import_invariant.invariant)(transcript.queue, "No queue found for transcript", {
155
155
  F: __dxlog_file,
156
- L: 90,
156
+ L: 86,
157
157
  S: void 0,
158
158
  A: [
159
159
  "transcript.queue",
160
160
  "'No queue found for transcript'"
161
161
  ]
162
162
  });
163
- const queue = new import_echo_db.QueueImpl(edgeClient, import_keys.DXN.parse(transcript.queue));
163
+ const queue = new import_echo_db.QueueImpl(edge, import_keys.DXN.parse(transcript.queue));
164
164
  await queue.refresh();
165
165
  const content = queue.items.filter((block) => (0, import_echo_schema.isInstanceOf)(import_chunk_UIHEGU6Q.TranscriptBlock, block)).map((block) => `${block.author}: ${block.segments.map((segment) => segment.text).join("\n")}`).join("\n\n");
166
166
  const parser = new import_assistant.MixedStreamParser();
@@ -168,11 +168,11 @@ var summarizeTranscript = async (edgeClient, aiService, transcript) => {
168
168
  blockCount: queue.items.length
169
169
  }, {
170
170
  F: __dxlog_file,
171
- L: 101,
171
+ L: 97,
172
172
  S: void 0,
173
173
  C: (f, a) => f(...a)
174
174
  });
175
- const output = await parser.parse(await aiService.exec({
175
+ const output = await parser.parse(await ai.exec({
176
176
  model: import_assistant.DEFAULT_LLM_MODEL,
177
177
  systemPrompt: SUMMARIZE_PROMPT,
178
178
  history: [
@@ -191,13 +191,13 @@ var summarizeTranscript = async (edgeClient, aiService, transcript) => {
191
191
  output
192
192
  }, {
193
193
  F: __dxlog_file,
194
- L: 110,
194
+ L: 106,
195
195
  S: void 0,
196
196
  C: (f, a) => f(...a)
197
197
  });
198
198
  (0, import_invariant.invariant)(output[0].content[0].type === "text", "Expected text content", {
199
199
  F: __dxlog_file,
200
- L: 111,
200
+ L: 107,
201
201
  S: void 0,
202
202
  A: [
203
203
  "output[0].content[0].type === 'text'",
@@ -237,10 +237,10 @@ var SUMMARIZE_PROMPT = `
237
237
  # Tasks
238
238
  At the end of the summary include tasks.
239
239
  Extract only the tasks that are:
240
- - Directly actionable
241
- - Clearly assigned to a person or team (or can easily be inferred)
242
- - Strongly implied by the conversation and/or user note (no speculative tasks)
243
- - Specific enough that someone reading them would know exactly what to do next
240
+ - Directly actionable.
241
+ - Clearly assigned to a person or team (or can easily be inferred).
242
+ - Strongly implied by the conversation and/or user note (no speculative tasks).
243
+ - Specific enough that someone reading them would know exactly what to do next.
244
244
 
245
245
  Format all tasks as markdown checkboxes using the syntax:
246
246
  - [ ] Task description
@@ -252,7 +252,7 @@ var SUMMARIZE_PROMPT = `
252
252
  var useAiServiceClient = () => {
253
253
  const config = (0, import_react_client.useConfig)();
254
254
  const endpoint = config.values.runtime?.services?.ai?.server ?? "http://localhost:8788";
255
- return (0, import_react.useMemo)(() => new import_assistant.AIServiceClientImpl({
255
+ return (0, import_react.useMemo)(() => new import_assistant.AIServiceEdgeClient({
256
256
  endpoint
257
257
  }), [
258
258
  endpoint
@@ -264,4 +264,4 @@ var useAiServiceClient = () => {
264
264
  TranscriptContainer_default,
265
265
  TranscriptionContainer
266
266
  });
267
- //# sourceMappingURL=chunk-YV74Z74I.cjs.map
267
+ //# sourceMappingURL=chunk-ANSWGFMS.cjs.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": ["import_types", "import_react", "import_react_ui", "Transcript", "blocks", "t", "useTranslation", "TRANSCRIPTION_PLUGIN", "hoverButton", "React", "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", "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", "StackItem", "Content", "toolbar", "Heading", "Toolbar", "Root", "onClick", "ScrollContainer", "items", "invariant", "QueueImpl", "refresh", "content", "filter", "isInstanceOf", "TranscriptBlock", "join", "parser", "MixedStreamParser", "log", "info", "blockCount", "length", "output", "exec", "model", "DEFAULT_LLM_MODEL", "systemPrompt", "SUMMARIZE_PROMPT", "history", "createStatic", "Message", "type", "summary", "name", "Date", "toLocaleString", "year", "month", "day", "hour", "minute", "create", "DocumentType", "makeRef", "TextType", "threads", "config", "useConfig", "endpoint", "values", "runtime", "services", "server", "useMemo", "AIServiceEdgeClient"]
7
+ }
@@ -16,14 +16,13 @@ var __copyProps = (to, from, except, desc) => {
16
16
  return to;
17
17
  };
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
- var chunk_JBN3P6ZF_exports = {};
20
- __export(chunk_JBN3P6ZF_exports, {
19
+ var chunk_HDRXDMK2_exports = {};
20
+ __export(chunk_HDRXDMK2_exports, {
21
21
  getTimeStr: () => getTimeStr,
22
22
  mergeFloat64Arrays: () => mergeFloat64Arrays,
23
- monitorAudioLevel: () => monitorAudioLevel,
24
23
  randomQueueDxn: () => randomQueueDxn
25
24
  });
26
- module.exports = __toCommonJS(chunk_JBN3P6ZF_exports);
25
+ module.exports = __toCommonJS(chunk_HDRXDMK2_exports);
27
26
  var import_echo_schema = require("@dxos/echo-schema");
28
27
  var import_keys = require("@dxos/keys");
29
28
  var getTimeStr = (timestamp) => new Date(timestamp ?? Date.now()).toLocaleTimeString("en-US", {
@@ -47,51 +46,10 @@ var mergeFloat64Arrays = (arrays) => {
47
46
  }
48
47
  return newArray;
49
48
  };
50
- var monitorAudioLevel = ({ mediaStreamTrack, onMeasure, intervalMs = 1e3 / 10 }) => {
51
- let timeout = -1;
52
- let interval = -1;
53
- const audioContext = new AudioContext();
54
- const stream = new MediaStream();
55
- stream.addTrack(mediaStreamTrack);
56
- const mediaStreamAudioSourceNode = audioContext.createMediaStreamSource(stream);
57
- const analyserNode = audioContext.createAnalyser();
58
- mediaStreamAudioSourceNode.connect(analyserNode);
59
- analyserNode.fftSize = 32;
60
- const pcmData = new Float32Array(analyserNode.fftSize);
61
- let peak = 0;
62
- interval = window.setInterval(() => {
63
- onMeasure(peak);
64
- peak = 0;
65
- }, intervalMs);
66
- const tick = () => {
67
- timeout = window.setTimeout(() => {
68
- analyserNode.getFloatTimeDomainData(pcmData);
69
- let sumSquares = 0;
70
- for (const amplitude of pcmData) {
71
- sumSquares += amplitude * amplitude;
72
- }
73
- const current = Math.sqrt(sumSquares / pcmData.length);
74
- if (current > peak) {
75
- peak = current;
76
- }
77
- tick();
78
- }, intervalMs);
79
- };
80
- tick();
81
- return () => {
82
- mediaStreamAudioSourceNode.disconnect();
83
- analyserNode.disconnect();
84
- void audioContext.close();
85
- clearInterval(interval);
86
- clearTimeout(timeout);
87
- stream.removeTrack(mediaStreamTrack);
88
- };
89
- };
90
49
  // Annotate the CommonJS export names for ESM import in node:
91
50
  0 && (module.exports = {
92
51
  getTimeStr,
93
52
  mergeFloat64Arrays,
94
- monitorAudioLevel,
95
53
  randomQueueDxn
96
54
  });
97
- //# sourceMappingURL=chunk-JBN3P6ZF.cjs.map
55
+ //# sourceMappingURL=chunk-HDRXDMK2.cjs.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": ";;;;;;;;;;;;;;;;;;;;;;;;;ACIA,yBAAyB;AACzB,kBAAgD;ADDzC,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;ACJK,IAAMC,iBAAiB,MAC5B,IAAIC,gBAAIA,gBAAIC,KAAKC,OAAO;EAACC,8BAAkBC;EAAMC,oBAAQC,OAAM;EAAIC,4BAASD,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", "randomQueueDxn", "DXN", "kind", "QUEUE", "QueueSubspaceTags", "DATA", "SpaceId", "random", "ObjectId", "mergeFloat64Arrays", "arrays", "newArray", "Float64Array", "reduce", "acc", "array", "length", "offset", "set"]
7
+ }
@@ -26,15 +26,15 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
26
26
  mod
27
27
  ));
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
- var chunk_QWXLQPP5_exports = {};
30
- __export(chunk_QWXLQPP5_exports, {
29
+ var chunk_I35KHI2G_exports = {};
30
+ __export(chunk_I35KHI2G_exports, {
31
31
  TranscriptContainer: () => TranscriptContainer
32
32
  });
33
- module.exports = __toCommonJS(chunk_QWXLQPP5_exports);
33
+ module.exports = __toCommonJS(chunk_I35KHI2G_exports);
34
34
  var import_react = require("react");
35
- var TranscriptContainer = (0, import_react.lazy)(() => import("./TranscriptContainer-HU763SN3.cjs"));
35
+ var TranscriptContainer = (0, import_react.lazy)(() => import("./TranscriptContainer-4BWXOVML.cjs"));
36
36
  // Annotate the CommonJS export names for ESM import in node:
37
37
  0 && (module.exports = {
38
38
  TranscriptContainer
39
39
  });
40
- //# sourceMappingURL=chunk-QWXLQPP5.cjs.map
40
+ //# sourceMappingURL=chunk-I35KHI2G.cjs.map
@@ -34,22 +34,22 @@ __export(node_exports, {
34
34
  ReactSurface: () => ReactSurface,
35
35
  TRANSCRIPTION_PLUGIN: () => import_chunk_UIHEGU6Q.TRANSCRIPTION_PLUGIN,
36
36
  Transcriber: () => Transcriber,
37
- Transcript: () => import_chunk_YV74Z74I.Transcript,
38
- TranscriptContainer: () => import_chunk_QWXLQPP5.TranscriptContainer,
37
+ Transcript: () => import_chunk_ANSWGFMS.Transcript,
38
+ TranscriptContainer: () => import_chunk_I35KHI2G.TranscriptContainer,
39
39
  TranscriptionCapabilities: () => TranscriptionCapabilities,
40
- TranscriptionContainer: () => import_chunk_YV74Z74I.TranscriptionContainer,
40
+ TranscriptionContainer: () => import_chunk_ANSWGFMS.TranscriptionContainer,
41
+ TranscriptionManager: () => TranscriptionManager,
41
42
  TranscriptionPlugin: () => TranscriptionPlugin,
42
43
  meta: () => import_chunk_UIHEGU6Q.meta,
43
44
  useAudioFile: () => useAudioFile,
44
45
  useAudioTrack: () => useAudioTrack,
45
- useIsSpeaking: () => useIsSpeaking,
46
46
  useTranscriber: () => useTranscriber,
47
47
  useVoiceInput: () => useVoiceInput
48
48
  });
49
49
  module.exports = __toCommonJS(node_exports);
50
- var import_chunk_JBN3P6ZF = require("./chunk-JBN3P6ZF.cjs");
51
- var import_chunk_QWXLQPP5 = require("./chunk-QWXLQPP5.cjs");
52
- var import_chunk_YV74Z74I = require("./chunk-YV74Z74I.cjs");
50
+ var import_chunk_HDRXDMK2 = require("./chunk-HDRXDMK2.cjs");
51
+ var import_chunk_I35KHI2G = require("./chunk-I35KHI2G.cjs");
52
+ var import_chunk_ANSWGFMS = require("./chunk-ANSWGFMS.cjs");
53
53
  var import_chunk_UIHEGU6Q = require("./chunk-UIHEGU6Q.cjs");
54
54
  var import_app_framework = require("@dxos/app-framework");
55
55
  var import_app_framework2 = require("@dxos/app-framework");
@@ -57,7 +57,6 @@ var import_react = require("react");
57
57
  var import_log = require("@dxos/log");
58
58
  var import_react2 = require("react");
59
59
  var import_react3 = require("react");
60
- var import_react4 = require("react");
61
60
  var import_extendable_media_recorder = require("extendable-media-recorder");
62
61
  var import_wavefile = require("wavefile");
63
62
  var import_async = require("@dxos/async");
@@ -69,11 +68,17 @@ var import_async2 = require("@dxos/async");
69
68
  var import_context = require("@dxos/context");
70
69
  var import_log3 = require("@dxos/log");
71
70
  var import_tracing2 = require("@dxos/tracing");
72
- var import_react5 = require("react");
71
+ var import_react4 = require("react");
73
72
  var import_async3 = require("@dxos/async");
74
73
  var import_context2 = require("@dxos/context");
75
74
  var import_log4 = require("@dxos/log");
76
75
  var import_react_ui_sfx = require("@dxos/react-ui-sfx");
76
+ var import_async4 = require("@dxos/async");
77
+ var import_context3 = require("@dxos/context");
78
+ var import_echo_db = require("@dxos/echo-db");
79
+ var import_echo_schema = require("@dxos/echo-schema");
80
+ var import_invariant2 = require("@dxos/invariant");
81
+ var import_keys = require("@dxos/keys");
77
82
  var import_app_framework3 = require("@dxos/app-framework");
78
83
  var import_plugin_client = require("@dxos/plugin-client");
79
84
  var TranscriptionCapabilities;
@@ -81,8 +86,8 @@ var TranscriptionCapabilities;
81
86
  TranscriptionCapabilities2.Transcription = (0, import_app_framework2.defineCapability)(`${import_chunk_UIHEGU6Q.TRANSCRIPTION_PLUGIN}/capability/transcription`);
82
87
  })(TranscriptionCapabilities || (TranscriptionCapabilities = {}));
83
88
  var AppGraphBuilder = (0, import_app_framework.lazy)(() => import("./app-graph-builder-YFBX3OTP.cjs"));
84
- var IntentResolver = (0, import_app_framework.lazy)(() => import("./intent-resolver-3KJZGGUQ.cjs"));
85
- var ReactSurface = (0, import_app_framework.lazy)(() => import("./react-surface-AGGGDOUC.cjs"));
89
+ var IntentResolver = (0, import_app_framework.lazy)(() => import("./intent-resolver-KLBZ25XJ.cjs"));
90
+ var ReactSurface = (0, import_app_framework.lazy)(() => import("./react-surface-NCKXB7EQ.cjs"));
86
91
  var __dxlog_file = "/home/runner/work/dxos/dxos/packages/plugins/experimental/plugin-transcription/src/hooks/useAudioFile.ts";
87
92
  var useAudioFile = (audioUrl) => {
88
93
  const [{ audio, stream, track }, setStream] = (0, import_react.useState)({});
@@ -166,59 +171,6 @@ var useAudioTrack = (active) => {
166
171
  ]);
167
172
  return track;
168
173
  };
169
- var useIsSpeaking = (mediaStreamTrack) => {
170
- const [isSpeaking, setIsSpeaking] = (0, import_react3.useState)(false);
171
- const isSpeakingRef = (0, import_react3.useRef)(isSpeaking);
172
- (0, import_react3.useEffect)(() => {
173
- if (!mediaStreamTrack) {
174
- setIsSpeaking(false);
175
- return;
176
- }
177
- isSpeakingRef.current = isSpeaking;
178
- const interval = window.setInterval(() => {
179
- if (isSpeaking === isSpeakingRef.current) {
180
- return;
181
- }
182
- setIsSpeaking(isSpeakingRef.current);
183
- }, 50);
184
- return () => {
185
- clearInterval(interval);
186
- };
187
- }, [
188
- isSpeaking,
189
- isSpeakingRef,
190
- mediaStreamTrack
191
- ]);
192
- (0, import_react3.useEffect)(() => {
193
- if (!mediaStreamTrack) {
194
- return;
195
- }
196
- let timeout = -1;
197
- const cleanup = (0, import_chunk_JBN3P6ZF.monitorAudioLevel)({
198
- mediaStreamTrack,
199
- onMeasure: (vol) => {
200
- const audioLevelAboveThreshold = vol > (isSpeakingRef.current ? 0.02 : 0.05);
201
- if (audioLevelAboveThreshold) {
202
- clearTimeout(timeout);
203
- timeout = -1;
204
- isSpeakingRef.current = true;
205
- } else if (timeout === -1) {
206
- timeout = window.setTimeout(() => {
207
- isSpeakingRef.current = false;
208
- timeout = -1;
209
- }, 1e3);
210
- }
211
- }
212
- });
213
- return () => {
214
- cleanup();
215
- };
216
- }, [
217
- isSpeaking,
218
- mediaStreamTrack
219
- ]);
220
- return isSpeaking;
221
- };
222
174
  function _ts_decorate(decorators, target, key, desc) {
223
175
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
224
176
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -246,6 +198,9 @@ var MediaStreamRecorder = class {
246
198
  bitDepthCode: settings.sampleSize ? String(settings.sampleSize) : "16"
247
199
  };
248
200
  }
201
+ get mediaStreamTrack() {
202
+ return this._mediaStreamTrack;
203
+ }
249
204
  setOnChunk(onChunk) {
250
205
  this._onChunk = onChunk;
251
206
  }
@@ -254,7 +209,7 @@ var MediaStreamRecorder = class {
254
209
  err
255
210
  }, {
256
211
  F: __dxlog_file2,
257
- L: 58,
212
+ L: 62,
258
213
  S: this,
259
214
  C: (f, a) => f(...a)
260
215
  }));
@@ -271,7 +226,7 @@ var MediaStreamRecorder = class {
271
226
  }
272
227
  (0, import_invariant.invariant)(this._onChunk, "MediaStreamRecorder: onChunk is not set", {
273
228
  F: __dxlog_file2,
274
- L: 69,
229
+ L: 73,
275
230
  S: this,
276
231
  A: [
277
232
  "this._onChunk",
@@ -306,7 +261,7 @@ var MediaStreamRecorder = class {
306
261
  } else {
307
262
  import_log2.log.warn("MediaStreamRecorder: no header", void 0, {
308
263
  F: __dxlog_file2,
309
- L: 100,
264
+ L: 104,
310
265
  S: this,
311
266
  C: (f, a) => f(...a)
312
267
  });
@@ -415,7 +370,7 @@ var Transcriber = class extends import_context.Resource {
415
370
  async _mergeAudioChunks(chunks) {
416
371
  const file = new import_wavefile2.WaveFile();
417
372
  const wavConfig = this._recorder.wavConfig;
418
- file.fromScratch(wavConfig.channels, wavConfig.sampleRate, wavConfig.bitDepthCode, (0, import_chunk_JBN3P6ZF.mergeFloat64Arrays)(chunks.map(({ data }) => data)));
373
+ file.fromScratch(wavConfig.channels, wavConfig.sampleRate, wavConfig.bitDepthCode, (0, import_chunk_HDRXDMK2.mergeFloat64Arrays)(chunks.map(({ data }) => data)));
419
374
  return file.toBase64();
420
375
  }
421
376
  async _fetchTranscription(audio) {
@@ -483,7 +438,7 @@ var RECORD_INTERVAL = 200;
483
438
  var PREFIXED_CHUNKS_AMOUNT = 10;
484
439
  var TRANSCRIBE_AFTER_CHUNKS_AMOUNT = 50;
485
440
  var useTranscriber = ({ audioStreamTrack, onSegments }) => {
486
- const transcriber = (0, import_react4.useMemo)(() => {
441
+ const transcriber = (0, import_react3.useMemo)(() => {
487
442
  if (!onSegments || !audioStreamTrack) {
488
443
  return void 0;
489
444
  }
@@ -502,7 +457,7 @@ var useTranscriber = ({ audioStreamTrack, onSegments }) => {
502
457
  audioStreamTrack,
503
458
  onSegments
504
459
  ]);
505
- (0, import_react4.useEffect)(() => {
460
+ (0, import_react3.useEffect)(() => {
506
461
  return () => {
507
462
  void transcriber?.close();
508
463
  };
@@ -515,17 +470,17 @@ var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/plugins/experimental/p
515
470
  var useVoiceInput = ({ active, onUpdate }) => {
516
471
  const soundStart = (0, import_react_ui_sfx.useSoundEffect)("StartRecording");
517
472
  const soundStop = (0, import_react_ui_sfx.useSoundEffect)("StopRecording");
518
- const handleSegments = (0, import_react5.useCallback)(async (segments) => {
473
+ const handleSegments = (0, import_react4.useCallback)(async (segments) => {
519
474
  const text = segments.map((str) => str.text.trim().replace(/[^\w\s]/g, "")).join(" ");
520
475
  onUpdate(text);
521
476
  }, []);
522
- const [recording, setRecording] = (0, import_react5.useState)(false);
477
+ const [recording, setRecording] = (0, import_react4.useState)(false);
523
478
  const track = useAudioTrack(active);
524
479
  const transcriber = useTranscriber({
525
480
  audioStreamTrack: track,
526
481
  onSegments: handleSegments
527
482
  });
528
- (0, import_react5.useEffect)(() => {
483
+ (0, import_react4.useEffect)(() => {
529
484
  const ctx = new import_context2.Context(void 0, {
530
485
  F: __dxlog_file4,
531
486
  L: 43
@@ -566,6 +521,159 @@ var useVoiceInput = ({ active, onUpdate }) => {
566
521
  recording
567
522
  };
568
523
  };
524
+ function _ts_decorate3(decorators, target, key, desc) {
525
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
526
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
527
+ 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;
528
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
529
+ }
530
+ var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/plugins/experimental/plugin-transcription/src/transcription-manager.ts";
531
+ var RECORD_INTERVAL2 = 200;
532
+ var PREFIXED_CHUNKS_AMOUNT2 = 10;
533
+ var TRANSCRIBE_AFTER_CHUNKS_AMOUNT2 = 50;
534
+ var TranscriptionManager = class extends import_context3.Resource {
535
+ constructor(edgeClient) {
536
+ super();
537
+ this._audioStreamTrack = void 0;
538
+ this._name = void 0;
539
+ this._mediaRecorder = void 0;
540
+ this._transcriber = void 0;
541
+ this._enabled = false;
542
+ this._queue = void 0;
543
+ this._edgeClient = edgeClient;
544
+ }
545
+ async _open() {
546
+ await this._toggleTranscriber();
547
+ }
548
+ async _close() {
549
+ void this._transcriber?.close();
550
+ }
551
+ setRecording(recording) {
552
+ if (!this.isOpen || !this._enabled) {
553
+ return;
554
+ }
555
+ if (recording) {
556
+ this._transcriber?.startChunksRecording();
557
+ } else {
558
+ this._transcriber?.stopChunksRecording();
559
+ }
560
+ }
561
+ /**
562
+ * Enable or disable transcription.
563
+ * @param enabled - Whether to enable transcription.
564
+ */
565
+ async setEnabled(enabled) {
566
+ if (this._enabled === enabled) {
567
+ return;
568
+ }
569
+ this._enabled = enabled ?? false;
570
+ this.isOpen && await this._toggleTranscriber();
571
+ }
572
+ async setAudioTrack(track) {
573
+ if (this._audioStreamTrack === track) {
574
+ return;
575
+ }
576
+ this._audioStreamTrack = track;
577
+ this.isOpen && await this._toggleTranscriber();
578
+ }
579
+ /**
580
+ * Set the queue to save the transcription to.
581
+ * @param queue - The queue to save the transcription to or the DXN of the queue.
582
+ */
583
+ setQueue(queue) {
584
+ switch (typeof queue) {
585
+ case "string":
586
+ if (this._queue?.dxn.toString() === queue) {
587
+ return;
588
+ }
589
+ this._queue = new import_echo_db.QueueImpl(this._edgeClient, import_keys.DXN.parse(queue));
590
+ break;
591
+ case "object":
592
+ if (this._queue === queue) {
593
+ return;
594
+ }
595
+ (0, import_invariant2.invariant)(queue instanceof import_echo_db.QueueImpl, void 0, {
596
+ F: __dxlog_file5,
597
+ L: 110,
598
+ S: this,
599
+ A: [
600
+ "queue instanceof QueueImpl",
601
+ ""
602
+ ]
603
+ });
604
+ this._queue = queue;
605
+ break;
606
+ case "undefined":
607
+ this._queue = void 0;
608
+ break;
609
+ }
610
+ }
611
+ setName(name) {
612
+ if (this._name === name) {
613
+ return;
614
+ }
615
+ this._name = name;
616
+ }
617
+ async _toggleTranscriber() {
618
+ await this._maybeReinitTranscriber();
619
+ if (this._enabled) {
620
+ await this._transcriber?.open();
621
+ } else {
622
+ await this._transcriber?.close();
623
+ }
624
+ }
625
+ async _maybeReinitTranscriber() {
626
+ if (!this._audioStreamTrack || !this._enabled) {
627
+ return;
628
+ }
629
+ let needReinit = false;
630
+ if (this._audioStreamTrack !== this._mediaRecorder?.mediaStreamTrack) {
631
+ this._mediaRecorder = new MediaStreamRecorder({
632
+ mediaStreamTrack: this._audioStreamTrack,
633
+ interval: RECORD_INTERVAL2
634
+ });
635
+ needReinit = true;
636
+ }
637
+ if (needReinit) {
638
+ await this._transcriber?.close();
639
+ this._transcriber = new Transcriber({
640
+ config: {
641
+ transcribeAfterChunksAmount: TRANSCRIBE_AFTER_CHUNKS_AMOUNT2,
642
+ prefixBufferChunksAmount: PREFIXED_CHUNKS_AMOUNT2
643
+ },
644
+ recorder: this._mediaRecorder,
645
+ onSegments: (segments) => this._onSegments(segments)
646
+ });
647
+ }
648
+ }
649
+ async _onSegments(segments) {
650
+ if (!this.isOpen || !this._queue) {
651
+ return;
652
+ }
653
+ const block = (0, import_echo_schema.createStatic)(import_chunk_UIHEGU6Q.TranscriptBlock, {
654
+ author: this._name,
655
+ segments
656
+ });
657
+ this._queue.append([
658
+ block
659
+ ]);
660
+ }
661
+ };
662
+ _ts_decorate3([
663
+ import_async4.synchronized
664
+ ], TranscriptionManager.prototype, "setRecording", null);
665
+ _ts_decorate3([
666
+ import_async4.synchronized
667
+ ], TranscriptionManager.prototype, "setEnabled", null);
668
+ _ts_decorate3([
669
+ import_async4.synchronized
670
+ ], TranscriptionManager.prototype, "setAudioTrack", null);
671
+ _ts_decorate3([
672
+ import_async4.synchronized
673
+ ], TranscriptionManager.prototype, "setQueue", null);
674
+ _ts_decorate3([
675
+ import_async4.synchronized
676
+ ], TranscriptionManager.prototype, "setName", null);
569
677
  var translations_default = [
570
678
  {
571
679
  "en-US": {
@@ -650,11 +758,11 @@ var TranscriptionPlugin = () => (0, import_app_framework3.definePlugin)(import_c
650
758
  TranscriptContainer,
651
759
  TranscriptionCapabilities,
652
760
  TranscriptionContainer,
761
+ TranscriptionManager,
653
762
  TranscriptionPlugin,
654
763
  meta,
655
764
  useAudioFile,
656
765
  useAudioTrack,
657
- useIsSpeaking,
658
766
  useTranscriber,
659
767
  useVoiceInput
660
768
  });