@dxos/plugin-transcription 0.8.2-main.f11618f → 0.8.2-main.fbd8ed0
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.
- package/dist/lib/browser/{TranscriptContainer-D3EH2SLO.mjs → TranscriptContainer-CXA4ZBHW.mjs} +2 -2
- package/dist/lib/browser/{app-graph-builder-7HN3M24G.mjs → app-graph-builder-REQZ5SC5.mjs} +37 -35
- package/dist/lib/browser/app-graph-builder-REQZ5SC5.mjs.map +7 -0
- package/dist/lib/browser/{chunk-KSUYWWIU.mjs → chunk-3TKXI6TQ.mjs} +6 -6
- package/dist/lib/browser/chunk-3TKXI6TQ.mjs.map +7 -0
- package/dist/lib/browser/{chunk-YRWBY6UK.mjs → chunk-JHWEZRWC.mjs} +19 -17
- package/dist/lib/browser/chunk-JHWEZRWC.mjs.map +7 -0
- package/dist/lib/browser/{chunk-BSZSM6KA.mjs → chunk-K2LS2QOM.mjs} +6 -6
- package/dist/lib/browser/chunk-K2LS2QOM.mjs.map +7 -0
- package/dist/lib/browser/{chunk-IWZ7C3OA.mjs → chunk-LCTMCTYY.mjs} +2 -2
- package/dist/lib/browser/index.mjs +7 -7
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/{intent-resolver-ZWKYRFE7.mjs → intent-resolver-DZ62CJPC.mjs} +3 -3
- package/dist/lib/browser/intent-resolver-DZ62CJPC.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/{react-surface-F7DBDGHS.mjs → react-surface-PUXZNAZL.mjs} +4 -4
- package/dist/lib/browser/{settings-6YAHKVKX.mjs → settings-JWDS4J3F.mjs} +2 -2
- package/dist/lib/browser/{transcriber-MSBS4VBI.mjs → transcriber-YWWIV6KP.mjs} +3 -3
- package/dist/lib/browser/types/index.mjs +1 -1
- package/dist/lib/node/{TranscriptContainer-WCBZMA5K.cjs → TranscriptContainer-SSJVLRM6.cjs} +7 -7
- package/dist/lib/node/{TranscriptContainer-WCBZMA5K.cjs.map → TranscriptContainer-SSJVLRM6.cjs.map} +2 -2
- package/dist/lib/node/{app-graph-builder-BVWYUGUO.cjs → app-graph-builder-OAPU4GDH.cjs} +50 -48
- package/dist/lib/node/app-graph-builder-OAPU4GDH.cjs.map +7 -0
- package/dist/lib/node/{chunk-IXU57SCA.cjs → chunk-EJWB53WK.cjs} +19 -17
- package/dist/lib/node/chunk-EJWB53WK.cjs.map +7 -0
- package/dist/lib/node/{chunk-JSCC2AQW.cjs → chunk-EVE3H46F.cjs} +9 -9
- package/dist/lib/node/chunk-EVE3H46F.cjs.map +7 -0
- package/dist/lib/node/{chunk-OCHTKDL7.cjs → chunk-L27AK6FQ.cjs} +5 -5
- package/dist/lib/node/{chunk-7XIIUVN3.cjs → chunk-WKZLGVEJ.cjs} +9 -9
- package/dist/lib/node/chunk-WKZLGVEJ.cjs.map +7 -0
- package/dist/lib/node/index.cjs +28 -28
- package/dist/lib/node/index.cjs.map +3 -3
- package/dist/lib/node/{intent-resolver-RM4JOCDV.cjs → intent-resolver-TRBKI24D.cjs} +9 -9
- package/dist/lib/node/intent-resolver-TRBKI24D.cjs.map +7 -0
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/{react-surface-7F37EYZA.cjs → react-surface-SZAMHCX7.cjs} +10 -10
- package/dist/lib/node/{settings-ZMB4XRWS.cjs → settings-AWWMOSCV.cjs} +7 -7
- package/dist/lib/node/{transcriber-55OE4X6I.cjs → transcriber-AFUXFHCR.cjs} +8 -8
- package/dist/lib/node/types/index.cjs +7 -7
- package/dist/lib/node/types/index.cjs.map +1 -1
- package/dist/lib/node-esm/{TranscriptContainer-GBPY6KKA.mjs → TranscriptContainer-M53LI2TX.mjs} +2 -2
- package/dist/lib/node-esm/{app-graph-builder-QK25O5K5.mjs → app-graph-builder-UBP6EOBR.mjs} +37 -35
- package/dist/lib/node-esm/app-graph-builder-UBP6EOBR.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-B2BD7S4X.mjs → chunk-4KC3E5T4.mjs} +6 -6
- package/dist/lib/node-esm/chunk-4KC3E5T4.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-DXJN2JWV.mjs → chunk-MHQP2PAF.mjs} +2 -2
- package/dist/lib/node-esm/{chunk-OS2ITZUL.mjs → chunk-QYG2FOXA.mjs} +19 -17
- package/dist/lib/node-esm/chunk-QYG2FOXA.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-UWF6LM27.mjs → chunk-V5IWBPYO.mjs} +6 -6
- package/dist/lib/node-esm/chunk-V5IWBPYO.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +7 -7
- package/dist/lib/node-esm/index.mjs.map +3 -3
- package/dist/lib/node-esm/{intent-resolver-HDRFXMKP.mjs → intent-resolver-HFVAL274.mjs} +3 -3
- package/dist/lib/node-esm/intent-resolver-HFVAL274.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/{react-surface-D3L6VBEV.mjs → react-surface-UEJELL7I.mjs} +4 -4
- package/dist/lib/node-esm/{settings-I35TVDUG.mjs → settings-QFNFGFJ5.mjs} +2 -2
- package/dist/lib/node-esm/{transcriber-HH7EMCGH.mjs → transcriber-7RJEFPDI.mjs} +3 -3
- package/dist/lib/node-esm/types/index.mjs +1 -1
- package/dist/types/src/capabilities/app-graph-builder.d.ts +2 -179
- package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
- package/dist/types/src/capabilities/index.d.ts +2 -178
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/intent-resolver.d.ts +2 -2
- package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -1
- package/dist/types/src/components/Transcript/Transcript.d.ts +3 -3
- package/dist/types/src/components/Transcript/Transcript.d.ts.map +1 -1
- package/dist/types/src/components/Transcript/Transcript.stories.d.ts +2 -2
- package/dist/types/src/components/Transcript/Transcript.stories.d.ts.map +1 -1
- package/dist/types/src/components/Transcript/deprecated/OldTranscript.d.ts +10 -10
- package/dist/types/src/components/Transcript/deprecated/OldTranscript.d.ts.map +1 -1
- package/dist/types/src/components/Transcript/transcript-extension.d.ts +2 -2
- package/dist/types/src/components/Transcript/transcript-extension.d.ts.map +1 -1
- package/dist/types/src/components/TranscriptionSettings/TranscriptionSettings.d.ts.map +1 -1
- package/dist/types/src/components/transcription.stories.d.ts.map +1 -1
- package/dist/types/src/entity-extraction/entity-extraction.d.ts +3 -3
- package/dist/types/src/entity-extraction/entity-extraction.d.ts.map +1 -1
- package/dist/types/src/hooks/useAudioFile.d.ts.map +1 -1
- package/dist/types/src/hooks/useAudioTrack.d.ts.map +1 -1
- package/dist/types/src/hooks/useQueueModelAdapter.d.ts.map +1 -1
- package/dist/types/src/hooks/useTranscriber.d.ts.map +1 -1
- package/dist/types/src/hooks/useVoiceInput.d.ts.map +1 -1
- package/dist/types/src/testing/testing.d.ts +11 -10
- package/dist/types/src/testing/testing.d.ts.map +1 -1
- package/dist/types/src/transcriber/transcriber.d.ts +2 -2
- package/dist/types/src/transcriber/transcriber.d.ts.map +1 -1
- package/dist/types/src/transcriber/transcription-manager.d.ts +2 -2
- package/dist/types/src/transcriber/transcription-manager.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +2 -20
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/schema.d.ts +26 -19
- package/dist/types/src/types/schema.d.ts.map +1 -1
- package/dist/types/src/types/types.d.ts +17 -10
- package/dist/types/src/types/types.d.ts.map +1 -1
- package/dist/types/src/util/array.d.ts.map +1 -1
- package/dist/types/src/util/get-time-str.d.ts.map +1 -1
- package/dist/types/src/util/monitor-audio-level.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +55 -49
- package/src/TranscriptionPlugin.tsx +3 -3
- package/src/capabilities/app-graph-builder.ts +145 -123
- package/src/capabilities/intent-resolver.ts +4 -3
- package/src/components/Transcript/Transcript.stories.tsx +6 -6
- package/src/components/Transcript/Transcript.tsx +3 -3
- package/src/components/Transcript/deprecated/OldTranscript.tsx +19 -13
- package/src/components/Transcript/transcript-extension.ts +3 -3
- package/src/components/TranscriptContainer.tsx +2 -2
- package/src/components/transcription.stories.tsx +17 -15
- package/src/entity-extraction/entity-extraction.ts +4 -4
- package/src/model/model.test.ts +14 -10
- package/src/testing/testing.ts +31 -23
- package/src/transcriber/transcriber.browser.test.ts +3 -3
- package/src/transcriber/transcriber.ts +6 -3
- package/src/transcriber/transcription-manager.ts +8 -8
- package/src/types/schema.ts +10 -8
- package/src/types/types.ts +14 -12
- package/dist/lib/browser/app-graph-builder-7HN3M24G.mjs.map +0 -7
- package/dist/lib/browser/chunk-BSZSM6KA.mjs.map +0 -7
- package/dist/lib/browser/chunk-KSUYWWIU.mjs.map +0 -7
- package/dist/lib/browser/chunk-YRWBY6UK.mjs.map +0 -7
- package/dist/lib/browser/intent-resolver-ZWKYRFE7.mjs.map +0 -7
- package/dist/lib/node/app-graph-builder-BVWYUGUO.cjs.map +0 -7
- package/dist/lib/node/chunk-7XIIUVN3.cjs.map +0 -7
- package/dist/lib/node/chunk-IXU57SCA.cjs.map +0 -7
- package/dist/lib/node/chunk-JSCC2AQW.cjs.map +0 -7
- package/dist/lib/node/intent-resolver-RM4JOCDV.cjs.map +0 -7
- package/dist/lib/node-esm/app-graph-builder-QK25O5K5.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-B2BD7S4X.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-OS2ITZUL.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-UWF6LM27.mjs.map +0 -7
- package/dist/lib/node-esm/intent-resolver-HDRFXMKP.mjs.map +0 -7
- /package/dist/lib/browser/{TranscriptContainer-D3EH2SLO.mjs.map → TranscriptContainer-CXA4ZBHW.mjs.map} +0 -0
- /package/dist/lib/browser/{chunk-IWZ7C3OA.mjs.map → chunk-LCTMCTYY.mjs.map} +0 -0
- /package/dist/lib/browser/{react-surface-F7DBDGHS.mjs.map → react-surface-PUXZNAZL.mjs.map} +0 -0
- /package/dist/lib/browser/{settings-6YAHKVKX.mjs.map → settings-JWDS4J3F.mjs.map} +0 -0
- /package/dist/lib/browser/{transcriber-MSBS4VBI.mjs.map → transcriber-YWWIV6KP.mjs.map} +0 -0
- /package/dist/lib/node/{chunk-OCHTKDL7.cjs.map → chunk-L27AK6FQ.cjs.map} +0 -0
- /package/dist/lib/node/{react-surface-7F37EYZA.cjs.map → react-surface-SZAMHCX7.cjs.map} +0 -0
- /package/dist/lib/node/{settings-ZMB4XRWS.cjs.map → settings-AWWMOSCV.cjs.map} +0 -0
- /package/dist/lib/node/{transcriber-55OE4X6I.cjs.map → transcriber-AFUXFHCR.cjs.map} +0 -0
- /package/dist/lib/node-esm/{TranscriptContainer-GBPY6KKA.mjs.map → TranscriptContainer-M53LI2TX.mjs.map} +0 -0
- /package/dist/lib/node-esm/{chunk-DXJN2JWV.mjs.map → chunk-MHQP2PAF.mjs.map} +0 -0
- /package/dist/lib/node-esm/{react-surface-D3L6VBEV.mjs.map → react-surface-UEJELL7I.mjs.map} +0 -0
- /package/dist/lib/node-esm/{settings-I35TVDUG.mjs.map → settings-QFNFGFJ5.mjs.map} +0 -0
- /package/dist/lib/node-esm/{transcriber-HH7EMCGH.mjs.map → transcriber-7RJEFPDI.mjs.map} +0 -0
package/dist/lib/browser/{TranscriptContainer-D3EH2SLO.mjs → TranscriptContainer-CXA4ZBHW.mjs}
RENAMED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
TranscriptContainer_default,
|
|
3
3
|
TranscriptionContainer
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-K2LS2QOM.mjs";
|
|
5
5
|
import "./chunk-LTIQFX4W.mjs";
|
|
6
6
|
import "./chunk-6ZR5MDK3.mjs";
|
|
7
7
|
export {
|
|
8
8
|
TranscriptionContainer,
|
|
9
9
|
TranscriptContainer_default as default
|
|
10
10
|
};
|
|
11
|
-
//# sourceMappingURL=TranscriptContainer-
|
|
11
|
+
//# sourceMappingURL=TranscriptContainer-CXA4ZBHW.mjs.map
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
TranscriptionManager
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-3TKXI6TQ.mjs";
|
|
4
4
|
import "./chunk-KLD7O5GJ.mjs";
|
|
5
5
|
import {
|
|
6
6
|
TranscriptType,
|
|
7
7
|
TranscriptionAction
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-JHWEZRWC.mjs";
|
|
9
9
|
import {
|
|
10
10
|
TranscriptionCapabilities
|
|
11
11
|
} from "./chunk-LTIQFX4W.mjs";
|
|
@@ -14,21 +14,23 @@ import {
|
|
|
14
14
|
} from "./chunk-6ZR5MDK3.mjs";
|
|
15
15
|
|
|
16
16
|
// packages/plugins/plugin-transcription/src/capabilities/app-graph-builder.ts
|
|
17
|
+
import { Rx } from "@effect-rx/rx-react";
|
|
18
|
+
import { Option, pipe } from "effect";
|
|
17
19
|
import { Capabilities, contributes, createIntent } from "@dxos/app-framework";
|
|
18
20
|
import { AIServiceEdgeClient } from "@dxos/assistant";
|
|
19
21
|
import { AI_SERVICE_ENDPOINT } from "@dxos/assistant/testing";
|
|
20
|
-
import { Filter, fullyQualifiedId, getSpace, makeRef } from "@dxos/client/echo";
|
|
22
|
+
import { Filter, fullyQualifiedId, getSpace, makeRef, Query } from "@dxos/client/echo";
|
|
21
23
|
import { getSchemaTypename, isInstanceOf } from "@dxos/echo-schema";
|
|
22
24
|
import { invariant } from "@dxos/invariant";
|
|
23
25
|
import { DXN as DXN2 } from "@dxos/keys";
|
|
24
26
|
import { log as log2 } from "@dxos/log";
|
|
25
27
|
import { ClientCapabilities } from "@dxos/plugin-client";
|
|
26
28
|
import { PLANK_COMPANION_TYPE, ATTENDABLE_PATH_SEPARATOR } from "@dxos/plugin-deck/types";
|
|
27
|
-
import { createExtension } from "@dxos/plugin-graph";
|
|
29
|
+
import { createExtension, rxFromSignal } from "@dxos/plugin-graph";
|
|
28
30
|
import { DocumentType } from "@dxos/plugin-markdown/types";
|
|
29
31
|
import { MeetingCapabilities } from "@dxos/plugin-meeting";
|
|
30
32
|
import { MeetingType } from "@dxos/plugin-meeting/types";
|
|
31
|
-
import {
|
|
33
|
+
import { DataType as DataType2 } from "@dxos/schema";
|
|
32
34
|
|
|
33
35
|
// packages/plugins/plugin-transcription/src/entity-extraction/entity-extraction.ts
|
|
34
36
|
import { Schema } from "effect";
|
|
@@ -38,7 +40,7 @@ import { asyncTimeout } from "@dxos/async";
|
|
|
38
40
|
import { create, ObjectId } from "@dxos/echo-schema";
|
|
39
41
|
import { DXN } from "@dxos/keys";
|
|
40
42
|
import { log } from "@dxos/log";
|
|
41
|
-
import {
|
|
43
|
+
import { DataType } from "@dxos/schema";
|
|
42
44
|
|
|
43
45
|
// raw-loader:./system-prompt.tpl?raw
|
|
44
46
|
var system_prompt_default = 'You are an AI assistant specialized in processing and enhancing transcripts with contextual information.\nYour task is to analyze a given transcript and extract references to the context objects.\n\nThe context and transcript are provided in the user message in `context` and `transcript` XML tags.\n\nHere are your instructions:\n\n1. Read the transcript and context information provided above.\n\n2. Process each segment of the transcript separately.\n\n3. For each segment:\n a. Analyze the content and identify relevant information from the context.\n b. Extract a number of references to the context objects that are mentioned in the segment.\n c. Output the references in the format `{ "quote": "earnings report", "id": "01JT0JP9AX0XKGZX4MV4B69VT6" }`.\n d. If there are no references, just output an empty array.\n\n4. Maintain the exact order and structure of the original transcript segments.\n\nOutput Format:\nThe final output should be a JSON array of references.\n\nExample output structure:\n```json\n{\n "references": [\n { "quote": "earnings report", "id": "01JT0JP9AX0XKGZX4MV4B69VT6" },\n { "quote": "John", "id": "01JT0VM0VN3ZKN7GDBM8CV9BA7" }\n ]\n}\n```\n\nRemember:\n- Only quote the text that is in the transcript.\n- Analyze each segment carefully before processing it.\n- Only reference objects that appear in the context and exactly by their id, If the object is not in the context, do not insert a reference. \n\nNow, process the transcript and context provided below according to these instructions.';
|
|
@@ -93,7 +95,7 @@ var processTranscriptMessage = async (params) => {
|
|
|
93
95
|
C: (f, a) => f(...a)
|
|
94
96
|
});
|
|
95
97
|
return {
|
|
96
|
-
message: create(
|
|
98
|
+
message: create(DataType.Message, {
|
|
97
99
|
...params.message,
|
|
98
100
|
blocks: params.message.blocks.map((block, i) => block.type !== "transcription" ? block : {
|
|
99
101
|
...block,
|
|
@@ -141,7 +143,7 @@ var postprocessText = (text, quotes) => {
|
|
|
141
143
|
// packages/plugins/plugin-transcription/src/capabilities/app-graph-builder.ts
|
|
142
144
|
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/plugins/plugin-transcription/src/capabilities/app-graph-builder.ts";
|
|
143
145
|
var getMeetingTranscript = async (context, meeting) => {
|
|
144
|
-
const { dispatchPromise: dispatch } = context.
|
|
146
|
+
const { dispatchPromise: dispatch } = context.getCapability(Capabilities.IntentDispatcher);
|
|
145
147
|
const typename = getSchemaTypename(TranscriptType);
|
|
146
148
|
const existing = await meeting.artifacts[typename]?.load();
|
|
147
149
|
if (existing instanceof TranscriptType) {
|
|
@@ -150,7 +152,7 @@ var getMeetingTranscript = async (context, meeting) => {
|
|
|
150
152
|
const space = getSpace(meeting);
|
|
151
153
|
invariant(space, void 0, {
|
|
152
154
|
F: __dxlog_file2,
|
|
153
|
-
L:
|
|
155
|
+
L: 49,
|
|
154
156
|
S: void 0,
|
|
155
157
|
A: [
|
|
156
158
|
"space",
|
|
@@ -166,10 +168,9 @@ var getMeetingTranscript = async (context, meeting) => {
|
|
|
166
168
|
var app_graph_builder_default = (context) => contributes(Capabilities.AppGraphBuilder, [
|
|
167
169
|
createExtension({
|
|
168
170
|
id: `${TRANSCRIPTION_PLUGIN}/meeting-transcript`,
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
const
|
|
172
|
-
const state = context.requestCapability(TranscriptionCapabilities.MeetingTranscriptionState);
|
|
171
|
+
actions: (node) => Rx.make((get) => pipe(get(node), Option.flatMap((node2) => isInstanceOf(MeetingType, node2.data) ? Option.some(node2.data) : Option.none()), Option.map((meeting) => {
|
|
172
|
+
const state = context.getCapability(TranscriptionCapabilities.MeetingTranscriptionState);
|
|
173
|
+
const enabled = get(rxFromSignal(() => state.enabled));
|
|
173
174
|
return [
|
|
174
175
|
{
|
|
175
176
|
id: `${fullyQualifiedId(meeting)}/action/start-stop-transcription`,
|
|
@@ -177,21 +178,21 @@ var app_graph_builder_default = (context) => contributes(Capabilities.AppGraphBu
|
|
|
177
178
|
const transcript = await getMeetingTranscript(context, meeting);
|
|
178
179
|
invariant(transcript, "Failed to create transcript", {
|
|
179
180
|
F: __dxlog_file2,
|
|
180
|
-
L:
|
|
181
|
+
L: 76,
|
|
181
182
|
S: void 0,
|
|
182
183
|
A: [
|
|
183
184
|
"transcript",
|
|
184
185
|
"'Failed to create transcript'"
|
|
185
186
|
]
|
|
186
187
|
});
|
|
187
|
-
const callManager = context.
|
|
188
|
+
const callManager = context.getCapability(MeetingCapabilities.CallManager);
|
|
188
189
|
callManager.setActivity(getSchemaTypename(TranscriptType), {
|
|
189
190
|
queueDxn: transcript.queue.dxn.toString(),
|
|
190
|
-
enabled: !
|
|
191
|
+
enabled: !enabled
|
|
191
192
|
});
|
|
192
193
|
},
|
|
193
194
|
properties: {
|
|
194
|
-
label:
|
|
195
|
+
label: enabled ? [
|
|
195
196
|
"stop transcription label",
|
|
196
197
|
{
|
|
197
198
|
ns: TRANSCRIPTION_PLUGIN
|
|
@@ -204,24 +205,25 @@ var app_graph_builder_default = (context) => contributes(Capabilities.AppGraphBu
|
|
|
204
205
|
],
|
|
205
206
|
icon: "ph--subtitles--regular",
|
|
206
207
|
disposition: "toolbar",
|
|
207
|
-
classNames:
|
|
208
|
+
classNames: enabled ? "bg-callAlert" : ""
|
|
208
209
|
}
|
|
209
210
|
}
|
|
210
211
|
];
|
|
211
|
-
},
|
|
212
|
-
connector: (
|
|
213
|
-
const
|
|
214
|
-
const
|
|
215
|
-
const
|
|
216
|
-
const settings =
|
|
212
|
+
}), Option.getOrElse(() => []))),
|
|
213
|
+
connector: (node) => Rx.make((get) => pipe(get(node), Option.flatMap((node2) => isInstanceOf(MeetingType, node2.data) ? Option.some(node2.data) : Option.none()), Option.map((meeting) => {
|
|
214
|
+
const client = context.getCapability(ClientCapabilities.Client);
|
|
215
|
+
const state = context.getCapability(TranscriptionCapabilities.MeetingTranscriptionState);
|
|
216
|
+
const settingsStore = get(context.capabilities(Capabilities.SettingsStore))[0];
|
|
217
|
+
const settings = get(rxFromSignal(() => settingsStore?.getStore(TRANSCRIPTION_PLUGIN).value));
|
|
217
218
|
const aiClient = new AIServiceEdgeClient({
|
|
219
|
+
// TODO(burdon): Get from config.
|
|
218
220
|
endpoint: AI_SERVICE_ENDPOINT.REMOTE
|
|
219
221
|
});
|
|
220
222
|
return [
|
|
221
223
|
{
|
|
222
224
|
id: `${fullyQualifiedId(meeting)}${ATTENDABLE_PATH_SEPARATOR}${getSchemaTypename(TranscriptType)}`,
|
|
223
225
|
type: PLANK_COMPANION_TYPE,
|
|
224
|
-
data: meeting.artifacts[getSchemaTypename(TranscriptType)]?.target,
|
|
226
|
+
data: get(rxFromSignal(() => meeting.artifacts[getSchemaTypename(TranscriptType)]?.target)),
|
|
225
227
|
properties: {
|
|
226
228
|
label: [
|
|
227
229
|
"transcript companion label",
|
|
@@ -241,7 +243,7 @@ var app_graph_builder_default = (context) => contributes(Capabilities.AppGraphBu
|
|
|
241
243
|
const identity = client.halo.identity.get();
|
|
242
244
|
invariant(identity, void 0, {
|
|
243
245
|
F: __dxlog_file2,
|
|
244
|
-
L:
|
|
246
|
+
L: 134,
|
|
245
247
|
S: void 0,
|
|
246
248
|
A: [
|
|
247
249
|
"identity",
|
|
@@ -251,7 +253,7 @@ var app_graph_builder_default = (context) => contributes(Capabilities.AppGraphBu
|
|
|
251
253
|
const space = getSpace(meeting2);
|
|
252
254
|
invariant(space, void 0, {
|
|
253
255
|
F: __dxlog_file2,
|
|
254
|
-
L:
|
|
256
|
+
L: 136,
|
|
255
257
|
S: void 0,
|
|
256
258
|
A: [
|
|
257
259
|
"space",
|
|
@@ -267,8 +269,8 @@ var app_graph_builder_default = (context) => contributes(Capabilities.AppGraphBu
|
|
|
267
269
|
// This will be replaced with a vector search index anyway, so its not a big deal.
|
|
268
270
|
contextTypes: [
|
|
269
271
|
DocumentType,
|
|
270
|
-
|
|
271
|
-
Organization
|
|
272
|
+
DataType2.Person,
|
|
273
|
+
DataType2.Organization
|
|
272
274
|
],
|
|
273
275
|
space
|
|
274
276
|
});
|
|
@@ -303,17 +305,17 @@ var app_graph_builder_default = (context) => contributes(Capabilities.AppGraphBu
|
|
|
303
305
|
}
|
|
304
306
|
}
|
|
305
307
|
];
|
|
306
|
-
}
|
|
308
|
+
}), Option.getOrElse(() => [])))
|
|
307
309
|
})
|
|
308
310
|
]);
|
|
309
311
|
var createEntityExtractionEnricher = ({ aiClient, contextTypes, space }) => {
|
|
310
312
|
return async (message) => {
|
|
311
|
-
const { objects } = await space.db.query(Filter.or(...contextTypes.map((s) => Filter.
|
|
313
|
+
const { objects } = await space.db.query(Query.select(Filter.or(...contextTypes.map((s) => Filter.type(s))))).run();
|
|
312
314
|
log2.info("context", {
|
|
313
315
|
objects
|
|
314
316
|
}, {
|
|
315
317
|
F: __dxlog_file2,
|
|
316
|
-
L:
|
|
318
|
+
L: 203,
|
|
317
319
|
S: void 0,
|
|
318
320
|
C: (f, a) => f(...a)
|
|
319
321
|
});
|
|
@@ -321,7 +323,7 @@ var createEntityExtractionEnricher = ({ aiClient, contextTypes, space }) => {
|
|
|
321
323
|
aiService: aiClient,
|
|
322
324
|
message,
|
|
323
325
|
context: {
|
|
324
|
-
objects: await Promise.all(objects.map(processContextObject))
|
|
326
|
+
objects: await Promise.all(objects.map((o) => processContextObject(o)))
|
|
325
327
|
},
|
|
326
328
|
options: {
|
|
327
329
|
timeout: ENTITY_EXTRACTOR_TIMEOUT,
|
|
@@ -332,7 +334,7 @@ var createEntityExtractionEnricher = ({ aiClient, contextTypes, space }) => {
|
|
|
332
334
|
timeElapsed
|
|
333
335
|
}, {
|
|
334
336
|
F: __dxlog_file2,
|
|
335
|
-
L:
|
|
337
|
+
L: 214,
|
|
336
338
|
S: void 0,
|
|
337
339
|
C: (f, a) => f(...a)
|
|
338
340
|
});
|
|
@@ -346,4 +348,4 @@ var ENTITY_EXTRACTOR_TIMEOUT = 25e3;
|
|
|
346
348
|
export {
|
|
347
349
|
app_graph_builder_default as default
|
|
348
350
|
};
|
|
349
|
-
//# sourceMappingURL=app-graph-builder-
|
|
351
|
+
//# sourceMappingURL=app-graph-builder-REQZ5SC5.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/capabilities/app-graph-builder.ts", "../../../src/entity-extraction/entity-extraction.ts", "raw-loader:./system-prompt.tpl?raw"],
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport { Rx } from '@effect-rx/rx-react';\nimport { Option, pipe, type Schema } from 'effect';\n\nimport { Capabilities, contributes, createIntent, type PluginContext } from '@dxos/app-framework';\nimport { AIServiceEdgeClient, type AIServiceClient } from '@dxos/assistant';\nimport { AI_SERVICE_ENDPOINT } from '@dxos/assistant/testing';\nimport { Filter, fullyQualifiedId, getSpace, makeRef, Query, type Space } from '@dxos/client/echo';\nimport { getSchemaTypename, isInstanceOf, type BaseEchoObject } from '@dxos/echo-schema';\nimport { invariant } from '@dxos/invariant';\nimport { DXN } from '@dxos/keys';\nimport { log } from '@dxos/log';\nimport { ClientCapabilities } from '@dxos/plugin-client';\nimport { PLANK_COMPANION_TYPE, ATTENDABLE_PATH_SEPARATOR } from '@dxos/plugin-deck/types';\nimport { createExtension, rxFromSignal } from '@dxos/plugin-graph';\nimport { DocumentType } from '@dxos/plugin-markdown/types';\nimport { MeetingCapabilities, type CallState, type MediaState } from '@dxos/plugin-meeting';\nimport { MeetingType, type MeetingCallProperties } from '@dxos/plugin-meeting/types';\nimport { type buf } from '@dxos/protocols/buf';\nimport { type TranscriptionPayloadSchema } from '@dxos/protocols/buf/dxos/edge/calls_pb';\nimport { DataType } from '@dxos/schema';\n\nimport { TranscriptionCapabilities } from './capabilities';\nimport { processTranscriptMessage } from '../entity-extraction';\nimport { TRANSCRIPTION_PLUGIN } from '../meta';\nimport { TranscriptionManager } from '../transcriber';\nimport { TranscriptionAction, type TranscriptionSettingsProps, TranscriptType } from '../types';\n\n// TODO(wittjosiah): Factor out.\n// TODO(wittjosiah): Can we stop using protobuf for this?\ntype TranscriptionPayload = buf.MessageInitShape<typeof TranscriptionPayloadSchema>;\n\nconst getMeetingTranscript = async (\n context: PluginContext,\n meeting: MeetingType,\n): Promise<TranscriptType | undefined> => {\n const { dispatchPromise: dispatch } = context.getCapability(Capabilities.IntentDispatcher);\n\n const typename = getSchemaTypename(TranscriptType)!;\n const existing = await meeting.artifacts[typename]?.load();\n if (existing instanceof TranscriptType) {\n return existing;\n }\n\n const space = getSpace(meeting);\n invariant(space);\n const { data } = await dispatch(createIntent(TranscriptionAction.Create, { spaceId: space.id }));\n meeting.artifacts[typename] = makeRef(data!.object);\n return data?.object;\n};\n\n// TODO(wittjosiah): Introduce a sound that plays when transcription is activated/deactivated.\nexport default (context: PluginContext) =>\n contributes(Capabilities.AppGraphBuilder, [\n createExtension({\n id: `${TRANSCRIPTION_PLUGIN}/meeting-transcript`,\n actions: (node) =>\n Rx.make((get) =>\n pipe(\n get(node),\n Option.flatMap((node) => (isInstanceOf(MeetingType, node.data) ? Option.some(node.data) : Option.none())),\n Option.map((meeting) => {\n const state = context.getCapability(TranscriptionCapabilities.MeetingTranscriptionState);\n const enabled = get(rxFromSignal(() => state.enabled));\n return [\n {\n id: `${fullyQualifiedId(meeting)}/action/start-stop-transcription`,\n data: async () => {\n // NOTE: We are not saving the state of the transcription manager here.\n // We expect the state to be updated through `onCallStateUpdated` once it is propagated through Swarm.\n // This is done to avoid race conditions and to not handle optimistic updates.\n const transcript = await getMeetingTranscript(context, meeting);\n invariant(transcript, 'Failed to create transcript');\n\n const callManager = context.getCapability(MeetingCapabilities.CallManager);\n callManager.setActivity(getSchemaTypename(TranscriptType)!, {\n queueDxn: transcript.queue.dxn.toString(),\n enabled: !enabled,\n });\n },\n properties: {\n label: enabled\n ? ['stop transcription label', { ns: TRANSCRIPTION_PLUGIN }]\n : ['start transcription label', { ns: TRANSCRIPTION_PLUGIN }],\n icon: 'ph--subtitles--regular',\n disposition: 'toolbar',\n classNames: enabled ? 'bg-callAlert' : '',\n },\n },\n ];\n }),\n Option.getOrElse(() => []),\n ),\n ),\n connector: (node) =>\n Rx.make((get) =>\n pipe(\n get(node),\n Option.flatMap((node) => (isInstanceOf(MeetingType, node.data) ? Option.some(node.data) : Option.none())),\n Option.map((meeting) => {\n const client = context.getCapability(ClientCapabilities.Client);\n const state = context.getCapability(TranscriptionCapabilities.MeetingTranscriptionState);\n const settingsStore = get(context.capabilities(Capabilities.SettingsStore))[0];\n const settings = get(\n rxFromSignal(() => settingsStore?.getStore<TranscriptionSettingsProps>(TRANSCRIPTION_PLUGIN)!.value),\n );\n\n // TODO(dmaretskyi): Request via capability.\n const aiClient: AIServiceClient | undefined = new AIServiceEdgeClient({\n // TODO(burdon): Get from config.\n endpoint: AI_SERVICE_ENDPOINT.REMOTE,\n });\n\n return [\n {\n id: `${fullyQualifiedId(meeting)}${ATTENDABLE_PATH_SEPARATOR}${getSchemaTypename(TranscriptType)}`,\n type: PLANK_COMPANION_TYPE,\n data: get(rxFromSignal(() => meeting.artifacts[getSchemaTypename(TranscriptType)!]?.target)),\n properties: {\n label: ['transcript companion label', { ns: TRANSCRIPTION_PLUGIN }],\n icon: 'ph--subtitles--regular',\n position: 'hoist',\n disposition: 'hidden',\n schema: TranscriptType,\n getIntent: ({ space }: { space: Space }) =>\n createIntent(TranscriptionAction.Create, { spaceId: space.id }),\n\n // TODO(burdon): Is this the right place to inisitalize the state? Change to a capability?\n onJoin: async ({ meeting }: { meeting?: MeetingType }) => {\n const identity = client.halo.identity.get();\n invariant(identity);\n const space = getSpace(meeting);\n invariant(space);\n\n let messageEnricher;\n if (aiClient && settings.entityExtraction) {\n messageEnricher = createEntityExtractionEnricher({\n aiClient,\n // TODO(dmaretskyi): Have those be discovered from the schema graph or contributed by capabilities?\n // This forced me to add a dependency on markdown plugin.\n // This will be replaced with a vector search index anyway, so its not a big deal.\n contextTypes: [DocumentType, DataType.Person, DataType.Organization],\n space,\n });\n }\n\n // TODO(burdon): The TranscriptionManager singleton is part of the state and should just be updated here.\n state.transcriptionManager = await new TranscriptionManager({\n edgeClient: client.edge,\n messageEnricher,\n })\n .setIdentityDid(identity.did)\n .open();\n },\n onLeave: async () => {\n await state.transcriptionManager?.close();\n state.transcriptionManager = undefined;\n state.enabled = false;\n },\n onCallStateUpdated: async (callState: CallState) => {\n const typename = getSchemaTypename(TranscriptType);\n const transcription = typename ? callState.activities?.[typename] : undefined;\n if (!transcription?.payload) {\n return;\n }\n\n const payload: TranscriptionPayload = transcription.payload;\n state.enabled = !!payload.enabled;\n if (payload.queueDxn) {\n // NOTE: Must set queue before enabling transcription.\n state.transcriptionManager?.setQueue(DXN.parse(payload.queueDxn));\n }\n await state.transcriptionManager?.setEnabled(payload.enabled);\n },\n onMediaStateUpdated: async ([mediaState, isSpeaking]: [MediaState, boolean]) => {\n void state.transcriptionManager?.setAudioTrack(mediaState.audioTrack);\n void state.transcriptionManager?.setRecording(isSpeaking);\n },\n } satisfies MeetingCallProperties,\n },\n ];\n }),\n Option.getOrElse(() => []),\n ),\n ),\n }),\n ]);\n\ntype EntityExtractionEnricherFactoryOptions = {\n aiClient: AIServiceClient;\n contextTypes: Schema.Schema.AnyNoContext[];\n space: Space;\n};\n\nconst createEntityExtractionEnricher = ({ aiClient, contextTypes, space }: EntityExtractionEnricherFactoryOptions) => {\n return async (message: DataType.Message) => {\n const { objects } = await space.db\n .query(Query.select(Filter.or(...contextTypes.map((s) => Filter.type(s as Schema.Schema<BaseEchoObject>)))))\n .run();\n log.info('context', { objects });\n\n const { message: enhancedMessage, timeElapsed } = await processTranscriptMessage({\n aiService: aiClient,\n message,\n context: {\n objects: await Promise.all(objects.map((o) => processContextObject(o))),\n },\n options: { timeout: ENTITY_EXTRACTOR_TIMEOUT, fallbackToRaw: true },\n });\n\n log.info('entity extraction time', { timeElapsed });\n return enhancedMessage;\n };\n};\n\n// TODO(dmaretskyi): Use Type.Any\nconst processContextObject = async (object: BaseEchoObject): Promise<any> => {\n // TODO(dmaretskyi): Documents need special processing is the content is behind a ref.\n // TODO(dmaretskyi): Think about a way to handle this serialization with a decorator.\n // if (isInstanceOf(DocumentType, object)) {\n // return {\n // ...object,\n // content: await object.content.load(),\n // };\n // }\n\n return object;\n};\n\nconst ENTITY_EXTRACTOR_TIMEOUT = 25_000;\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { Schema } from 'effect';\n\nimport { createTemplate, Message, structuredOutputParser } from '@dxos/artifact';\nimport type { AIServiceClient } from '@dxos/assistant';\nimport { MixedStreamParser } from '@dxos/assistant';\nimport { asyncTimeout } from '@dxos/async';\nimport { type BaseEchoObject, create, ObjectId } from '@dxos/echo-schema';\nimport { DXN } from '@dxos/keys';\nimport { log } from '@dxos/log';\nimport { DataType } from '@dxos/schema';\n\nimport SYSTEM_PROMPT from './system-prompt.tpl?raw';\n\ntype ProcessTranscriptMessageParams = {\n message: DataType.Message;\n aiService: AIServiceClient;\n context: {\n objects?: BaseEchoObject[];\n };\n\n options?: {\n /**\n * Timeout for the entity extraction.\n */\n timeout?: number;\n\n /**\n * Fallback to raw text if the entity extraction fails.\n * Otherwise the function will throw an error.\n * @default false\n */\n fallbackToRaw?: boolean;\n };\n};\n\ntype ProcessTranscriptMessageResult = {\n message: DataType.Message;\n timeElapsed: number;\n};\n\n/**\n * Process Handlebars template.\n */\nconst createSystemPrompt = (): string => {\n const template = createTemplate(SYSTEM_PROMPT);\n return template({});\n};\n\nconst ReferencedQuotes = Schema.Struct({\n references: Schema.Array(\n Schema.Struct({\n quote: Schema.String,\n id: Schema.String,\n }),\n ).annotations({\n description:\n 'The references to the context objects that are mentioned in the transcript. quote should match the original transcript text exactly, while id is the id of the context object.',\n }),\n});\ninterface ReferencedQuotes extends Schema.Schema.Type<typeof ReferencedQuotes> {}\n\n// TODO(dmaretskyi): Move context to a vector search index.\nexport const processTranscriptMessage = async (\n params: ProcessTranscriptMessageParams,\n): Promise<ProcessTranscriptMessageResult> => {\n try {\n const outputParser = structuredOutputParser(ReferencedQuotes);\n const runParser = async (): Promise<ProcessTranscriptMessageResult> => {\n const startTime = performance.now();\n const result = outputParser.getResult(\n await new MixedStreamParser().parse(\n await params.aiService.execStream({\n model: '@anthropic/claude-3-5-haiku-20241022',\n systemPrompt: createSystemPrompt(),\n history: [\n create(Message, {\n role: 'user',\n content: [\n {\n type: 'text',\n text: `<context>${JSON.stringify(params.context.objects)}</context>`,\n },\n {\n type: 'text',\n text: `<transcript>${JSON.stringify(params.message.blocks)}</transcript>`,\n },\n ],\n }),\n ],\n tools: [outputParser.tool],\n }),\n ),\n );\n log.info('entity extraction result', { refs: result.references });\n\n return {\n message: create(DataType.Message, {\n ...params.message,\n blocks: params.message.blocks.map((block, i) =>\n block.type !== 'transcription'\n ? block\n : {\n ...block,\n text: postprocessText(block.text, result),\n },\n ),\n }),\n timeElapsed: performance.now() - startTime,\n };\n };\n\n if (params.options?.timeout && params.options.timeout > 0) {\n return await asyncTimeout(runParser(), params.options.timeout);\n } else {\n return await runParser();\n }\n } catch (error) {\n if (params.options?.fallbackToRaw) {\n log.warn('failed to process transcript message, falling back to raw text', { error });\n return {\n message: params.message,\n timeElapsed: 0,\n };\n } else {\n throw error;\n }\n }\n};\n\n/**\n * Finds and replaces all quotes with DXNs references.\n */\n// TODO(dmaretskyi): Lookup and verifiy ids from provided context.\nexport const postprocessText = (text: string, quotes: ReferencedQuotes) => {\n for (const quote of quotes.references) {\n if (!ObjectId.isValid(quote.id)) {\n continue;\n }\n\n // Use a case-insensitive regular expression to replace the quote\n const regex = new RegExp(quote.quote.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'), 'gi');\n text = text.replace(regex, `[${quote.quote}][${DXN.fromLocalObjectId(quote.id).toString()}]`);\n }\n return text;\n};\n", "You are an AI assistant specialized in processing and enhancing transcripts with contextual information.\nYour task is to analyze a given transcript and extract references to the context objects.\n\nThe context and transcript are provided in the user message in `context` and `transcript` XML tags.\n\nHere are your instructions:\n\n1. Read the transcript and context information provided above.\n\n2. Process each segment of the transcript separately.\n\n3. For each segment:\n a. Analyze the content and identify relevant information from the context.\n b. Extract a number of references to the context objects that are mentioned in the segment.\n c. Output the references in the format `{ \"quote\": \"earnings report\", \"id\": \"01JT0JP9AX0XKGZX4MV4B69VT6\" }`.\n d. If there are no references, just output an empty array.\n\n4. Maintain the exact order and structure of the original transcript segments.\n\nOutput Format:\nThe final output should be a JSON array of references.\n\nExample output structure:\n```json\n{\n \"references\": [\n { \"quote\": \"earnings report\", \"id\": \"01JT0JP9AX0XKGZX4MV4B69VT6\" },\n { \"quote\": \"John\", \"id\": \"01JT0VM0VN3ZKN7GDBM8CV9BA7\" }\n ]\n}\n```\n\nRemember:\n- Only quote the text that is in the transcript.\n- Analyze each segment carefully before processing it.\n- Only reference objects that appear in the context and exactly by their id, If the object is not in the context, do not insert a reference. \n\nNow, process the transcript and context provided below according to these instructions."],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["Rx", "Option", "pipe", "Capabilities", "contributes", "createIntent", "AIServiceEdgeClient", "AI_SERVICE_ENDPOINT", "Filter", "fullyQualifiedId", "getSpace", "makeRef", "Query", "getSchemaTypename", "isInstanceOf", "invariant", "DXN", "log", "ClientCapabilities", "PLANK_COMPANION_TYPE", "ATTENDABLE_PATH_SEPARATOR", "createExtension", "rxFromSignal", "DocumentType", "MeetingCapabilities", "MeetingType", "DataType", "Schema", "createTemplate", "Message", "structuredOutputParser", "MixedStreamParser", "asyncTimeout", "create", "ObjectId", "DXN", "log", "DataType", "createSystemPrompt", "template", "createTemplate", "SYSTEM_PROMPT", "ReferencedQuotes", "Schema", "Struct", "references", "Array", "quote", "String", "id", "annotations", "description", "processTranscriptMessage", "params", "outputParser", "structuredOutputParser", "runParser", "startTime", "performance", "now", "result", "getResult", "MixedStreamParser", "parse", "aiService", "execStream", "model", "systemPrompt", "history", "create", "Message", "role", "content", "type", "text", "JSON", "stringify", "context", "objects", "message", "blocks", "tools", "tool", "log", "info", "refs", "DataType", "map", "block", "i", "postprocessText", "timeElapsed", "options", "timeout", "asyncTimeout", "error", "fallbackToRaw", "warn", "quotes", "ObjectId", "isValid", "regex", "RegExp", "replace", "DXN", "fromLocalObjectId", "toString", "getMeetingTranscript", "context", "meeting", "dispatchPromise", "dispatch", "getCapability", "Capabilities", "IntentDispatcher", "typename", "getSchemaTypename", "TranscriptType", "existing", "artifacts", "load", "space", "getSpace", "invariant", "data", "createIntent", "TranscriptionAction", "Create", "spaceId", "id", "makeRef", "object", "contributes", "AppGraphBuilder", "createExtension", "TRANSCRIPTION_PLUGIN", "actions", "node", "Rx", "make", "get", "pipe", "Option", "flatMap", "isInstanceOf", "MeetingType", "some", "none", "map", "state", "TranscriptionCapabilities", "MeetingTranscriptionState", "enabled", "rxFromSignal", "fullyQualifiedId", "transcript", "callManager", "MeetingCapabilities", "CallManager", "setActivity", "queueDxn", "queue", "dxn", "toString", "properties", "label", "ns", "icon", "disposition", "classNames", "getOrElse", "connector", "client", "ClientCapabilities", "Client", "settingsStore", "capabilities", "SettingsStore", "settings", "getStore", "value", "aiClient", "AIServiceEdgeClient", "endpoint", "AI_SERVICE_ENDPOINT", "REMOTE", "ATTENDABLE_PATH_SEPARATOR", "type", "PLANK_COMPANION_TYPE", "target", "position", "schema", "getIntent", "onJoin", "identity", "halo", "messageEnricher", "entityExtraction", "createEntityExtractionEnricher", "contextTypes", "DocumentType", "DataType", "Person", "Organization", "transcriptionManager", "TranscriptionManager", "edgeClient", "edge", "setIdentityDid", "did", "open", "onLeave", "close", "undefined", "onCallStateUpdated", "callState", "transcription", "activities", "payload", "setQueue", "DXN", "parse", "setEnabled", "onMediaStateUpdated", "mediaState", "isSpeaking", "setAudioTrack", "audioTrack", "setRecording", "message", "objects", "db", "query", "Query", "select", "Filter", "or", "s", "run", "log", "info", "enhancedMessage", "timeElapsed", "processTranscriptMessage", "aiService", "Promise", "all", "o", "processContextObject", "options", "timeout", "ENTITY_EXTRACTOR_TIMEOUT", "fallbackToRaw"]
|
|
7
|
+
}
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "./chunk-KLD7O5GJ.mjs";
|
|
4
4
|
import {
|
|
5
5
|
TRANSCRIPTION_URL
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-JHWEZRWC.mjs";
|
|
7
7
|
|
|
8
8
|
// packages/plugins/plugin-transcription/src/transcriber/media-stream-recorder.ts
|
|
9
9
|
import { MediaRecorder, register } from "extendable-media-recorder";
|
|
@@ -314,7 +314,7 @@ import { Resource as Resource2 } from "@dxos/context";
|
|
|
314
314
|
import { QueueImpl } from "@dxos/echo-db";
|
|
315
315
|
import { create } from "@dxos/echo-schema";
|
|
316
316
|
import { log as log3 } from "@dxos/log";
|
|
317
|
-
import {
|
|
317
|
+
import { DataType } from "@dxos/schema";
|
|
318
318
|
function _ts_decorate3(decorators, target, key, desc) {
|
|
319
319
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
320
320
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -397,7 +397,7 @@ var TranscriptionManager = class extends Resource2 {
|
|
|
397
397
|
await this._maybeReinitTranscriber();
|
|
398
398
|
if (this._enabled) {
|
|
399
399
|
await this._transcriber?.open();
|
|
400
|
-
const block = create(
|
|
400
|
+
const block = create(DataType.Message, {
|
|
401
401
|
created: (/* @__PURE__ */ new Date()).toISOString(),
|
|
402
402
|
blocks: [
|
|
403
403
|
{
|
|
@@ -415,7 +415,7 @@ var TranscriptionManager = class extends Resource2 {
|
|
|
415
415
|
]);
|
|
416
416
|
} else {
|
|
417
417
|
await this._transcriber?.close();
|
|
418
|
-
const block = create(
|
|
418
|
+
const block = create(DataType.Message, {
|
|
419
419
|
created: (/* @__PURE__ */ new Date()).toISOString(),
|
|
420
420
|
blocks: [
|
|
421
421
|
{
|
|
@@ -461,7 +461,7 @@ var TranscriptionManager = class extends Resource2 {
|
|
|
461
461
|
if (!this.isOpen || !this._queue) {
|
|
462
462
|
return;
|
|
463
463
|
}
|
|
464
|
-
let block = create(
|
|
464
|
+
let block = create(DataType.Message, {
|
|
465
465
|
created: (/* @__PURE__ */ new Date()).toISOString(),
|
|
466
466
|
blocks: segments,
|
|
467
467
|
sender: {
|
|
@@ -488,4 +488,4 @@ export {
|
|
|
488
488
|
Transcriber,
|
|
489
489
|
TranscriptionManager
|
|
490
490
|
};
|
|
491
|
-
//# sourceMappingURL=chunk-
|
|
491
|
+
//# sourceMappingURL=chunk-3TKXI6TQ.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/transcriber/media-stream-recorder.ts", "../../../src/transcriber/transcriber.ts", "../../../src/transcriber/transcription-manager.ts"],
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport { type IBlobEvent, type IMediaRecorder, MediaRecorder, register } from 'extendable-media-recorder';\nimport { WaveFile } from 'wavefile';\n\nimport { synchronized } from '@dxos/async';\nimport { invariant } from '@dxos/invariant';\nimport { log } from '@dxos/log';\nimport { trace } from '@dxos/tracing';\n\nimport { type WavConfig, type AudioChunk, type AudioRecorder } from './audio-recorder';\n\nlet initializingPromise: Promise<void> | undefined;\n\nconst initializeExtendableMediaRecorder = async () => {\n const { connect } = await import('extendable-media-recorder-wav-encoder');\n await register(await connect());\n};\n\n/**\n * Recorder that uses the MediaContext API and AudioNode API to record audio.\n *\n * It records MediaStream using https://www.npmjs.com/package/extendable-media-recorder.\n */\n@trace.resource()\nexport class MediaStreamRecorder implements AudioRecorder {\n private readonly _mediaStreamTrack: MediaStreamTrack;\n /**\n * Default MediaRecorder implementation do not support wav encoding.\n */\n private readonly _interval: number;\n private _mediaRecorder?: IMediaRecorder = undefined;\n private _header?: Uint8Array = undefined;\n private _onChunk?: (chunk: AudioChunk) => void;\n\n constructor({ mediaStreamTrack, interval }: { mediaStreamTrack: MediaStreamTrack; interval: number }) {\n this._mediaStreamTrack = mediaStreamTrack;\n this._interval = interval;\n }\n\n get wavConfig(): WavConfig {\n const settings = this._mediaStreamTrack.getSettings();\n return {\n channels: settings.channelCount ?? 1,\n sampleRate: settings.sampleRate ?? 16000,\n bitDepthCode: settings.sampleSize ? String(settings.sampleSize) : '16',\n };\n }\n\n get mediaStreamTrack() {\n return this._mediaStreamTrack;\n }\n\n setOnChunk(onChunk: (chunk: AudioChunk) => void): void {\n this._onChunk = onChunk;\n }\n\n async start() {\n await (initializingPromise ??= initializeExtendableMediaRecorder()).catch((err) =>\n log.info('initializeExtendableMediaRecorder', { err }),\n );\n\n if (!this._mediaRecorder) {\n const stream = new MediaStream([this._mediaStreamTrack]);\n this._mediaRecorder = new MediaRecorder(stream, { mimeType: 'audio/wav' });\n }\n\n if (this._mediaRecorder.state === 'recording') {\n return;\n }\n invariant(this._onChunk, 'MediaStreamRecorder: onChunk is not set');\n this._mediaRecorder.ondataavailable = (event) => this._ondataavailable(event);\n this._mediaRecorder.start(this._interval);\n }\n\n async stop() {\n if (this._mediaRecorder?.state !== 'recording') {\n return;\n }\n this._mediaRecorder.stop();\n }\n\n @synchronized\n private async _ondataavailable(event: IBlobEvent) {\n const blob = event.data;\n const uint8Array = new Uint8Array(await blob.arrayBuffer());\n\n // First chunk from the MediaRecorder has a header.\n const isHeader =\n uint8Array[0] === 0x52 && // R\n uint8Array[1] === 0x49 && // I\n uint8Array[2] === 0x46 && // F\n uint8Array[3] === 0x46; // F\n let wav: WaveFile;\n\n if (isHeader) {\n wav = new WaveFile(uint8Array);\n this._header = uint8Array.slice(0, 44);\n } else if (this._header) {\n wav = new WaveFile(new Uint8Array([...this._header, ...uint8Array]));\n } else {\n log.warn('MediaStreamRecorder: no header');\n return;\n }\n\n this._onChunk!({\n timestamp: Date.now(),\n data: wav.getSamples(),\n });\n }\n}\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { WaveFile } from 'wavefile';\n\nimport { DeferredTask, Trigger } from '@dxos/async';\nimport { type Context, LifecycleState, Resource } from '@dxos/context';\nimport { log } from '@dxos/log';\nimport { type DataType } from '@dxos/schema';\nimport { trace } from '@dxos/tracing';\n\nimport { type AudioRecorder, type AudioChunk } from './audio-recorder';\nimport { TRANSCRIPTION_URL } from '../types';\nimport { mergeFloat64Arrays } from '../util';\n\ntype WhisperWord = {\n word: string;\n\n /**\n * Time in seconds from the start of the audio.\n */\n start: number;\n\n /**\n * Time in seconds from the start of the audio.\n */\n end: number;\n};\n\ntype WhisperSegment = {\n text: string;\n\n /**\n * Time in seconds from the start of the audio.\n */\n start: number;\n\n /**\n * Time in seconds from the start of the audio.\n */\n end: number;\n\n /**\n * Probability of no speech in the segment.\n */\n no_speech_prob: number;\n\n words: WhisperWord[];\n};\n\nexport type TranscribeConfig = {\n /**\n * Number of chunks to transcribe automatically after.\n */\n transcribeAfterChunksAmount: number;\n\n /**\n * Number of chunks to save before the user starts speaking.\n * This is needed to catch the beginning of the user's speech.\n */\n prefixBufferChunksAmount: number;\n};\n\nexport type TranscriberParams = {\n config: TranscribeConfig;\n recorder: AudioRecorder;\n onSegments: (segments: DataType.MessageBlock.Transcription[]) => Promise<void>;\n};\n\n/**\n * Handles transcription of audio chunks.\n * If user is not speaking, the last `minChunksAmount` chunks are saved and transcribed.\n * If user is speaking, the chunks are added to the buffer until the user is done talking.\n */\nexport class Transcriber extends Resource {\n private _audioChunks: AudioChunk[] = [];\n private _lastUsedTimestamp = 0;\n\n private readonly _openTrigger = new Trigger({ autoReset: true });\n\n private readonly _config: TranscribeConfig;\n private readonly _recorder: AudioRecorder;\n private readonly _onSegments: TranscriberParams['onSegments'];\n\n private _recording = false;\n private _transcribeTask?: DeferredTask = undefined;\n\n constructor({ config, recorder, onSegments }: TranscriberParams) {\n super();\n this._config = config;\n this._recorder = recorder;\n this._onSegments = onSegments;\n }\n\n protected override async _open(ctx: Context) {\n log.info('opening');\n this._recorder.setOnChunk((chunk) => this._saveAudioChunk(chunk));\n await this._recorder.start();\n this._transcribeTask = new DeferredTask(ctx, async () => this._transcribe());\n this._openTrigger.wake();\n }\n\n protected override async _close() {\n log.info('closing');\n this._recording = false;\n this._transcribeTask = undefined;\n await this._recorder.stop();\n }\n\n startChunksRecording() {\n log.info('starting');\n if (this._lifecycleState !== LifecycleState.OPEN) {\n return;\n }\n\n this._recording = true;\n }\n\n stopChunksRecording() {\n if (this._lifecycleState !== LifecycleState.OPEN || !this._recording) {\n return;\n }\n\n this._recording = false;\n this._transcribeTask?.schedule();\n log.info('stopped');\n }\n\n private _saveAudioChunk(chunk: AudioChunk) {\n log('saving audio chunk', { chunk });\n this._audioChunks.push(chunk);\n\n // Clean the buffer if the user is not speaking and the transcription task is not scheduled.\n if (\n !this._recording &&\n (!this._transcribeTask || !this._transcribeTask.scheduled) &&\n this._audioChunks.length >= this._config.prefixBufferChunksAmount\n ) {\n this._audioChunks = this._dropOldChunks();\n } else if (this._audioChunks.length >= this._config.transcribeAfterChunksAmount && this._recording) {\n this._transcribeTask?.schedule();\n }\n }\n\n private async _transcribe() {\n log('transcribing', { chunks: this._audioChunks.length });\n const chunks = this._audioChunks;\n this._audioChunks = this._dropOldChunks();\n if (chunks.length === 0) {\n return;\n }\n\n const audio = await this._mergeAudioChunks(chunks);\n const segments = await this._fetchTranscription(audio);\n if (!Array.isArray(segments) || segments.length === 0) {\n return;\n }\n\n const alignedSegments = this._alignSegments(segments, chunks);\n if (alignedSegments.length > 0) {\n await this._onSegments(alignedSegments);\n }\n }\n\n private _dropOldChunks() {\n return this._config.prefixBufferChunksAmount > 0\n ? this._audioChunks.slice(-this._config.prefixBufferChunksAmount)\n : [];\n }\n\n @trace.span({ showInBrowserTimeline: true })\n private async _mergeAudioChunks(chunks: AudioChunk[]) {\n const file = new WaveFile();\n const wavConfig = this._recorder.wavConfig;\n\n file.fromScratch(\n wavConfig.channels,\n wavConfig.sampleRate,\n wavConfig.bitDepthCode,\n mergeFloat64Arrays(chunks.map(({ data }) => data)),\n );\n\n return file.toBase64();\n }\n\n @trace.span({ showInBrowserTimeline: true })\n private async _fetchTranscription(audio: string) {\n if (audio.length === 0) {\n this._audioChunks = [];\n throw new Error('No audio to send for transcribing');\n }\n\n const response = await fetch(`${TRANSCRIPTION_URL}/transcribe`, {\n method: 'POST',\n body: JSON.stringify({ audio }),\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok) {\n this._audioChunks = [];\n throw new Error(`Transcription failed: ${response.statusText}`);\n }\n\n const { segments } = (await response.json()) as {\n segments: WhisperSegment[];\n };\n\n log.info('transcription response', {\n segments: segments.length,\n string: segments.map((segments) => segments.text).join(' '),\n });\n\n return segments;\n }\n\n private _alignSegments(\n segments: WhisperSegment[],\n originalChunks: AudioChunk[],\n ): DataType.MessageBlock.Transcription[] {\n // Absolute zero for all relative timestamps in the segments.\n const zeroTimestamp = originalChunks.at(0)!.timestamp;\n\n const filteredSegments = segments\n // Use segments that end after the last used timestamp.\n // Segments could overlap, so we need to filter words that starts after the last used timestamp.\n .filter((segment) => zeroTimestamp + segment.end * 1_000 >= this._lastUsedTimestamp)\n // Use words that starts after the last used timestamp.\n .map((segment) => {\n const words = segment.words.filter((word) => zeroTimestamp + word.start * 1_000 >= this._lastUsedTimestamp);\n return {\n ...segment,\n words,\n text: words.map((word) => word.word).join(''),\n start: words.at(0)?.start ?? segment.end,\n };\n })\n .filter((segment) => segment.words.length > 0);\n\n if (filteredSegments.length === 0) {\n return [];\n }\n\n // Update last timestamp.\n this._lastUsedTimestamp = zeroTimestamp + filteredSegments.at(-1)!.end * 1_000;\n\n // Add absolute timestamp to each segment.\n return filteredSegments.map((segment) => ({\n type: 'transcription',\n started: new Date(zeroTimestamp + segment.start * 1_000).toISOString(),\n text: segment.text.trim(),\n }));\n }\n}\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { synchronized } from '@dxos/async';\nimport { Resource } from '@dxos/context';\nimport { QueueImpl, type Queue } from '@dxos/echo-db';\nimport { create } from '@dxos/echo-schema';\nimport { type DXN } from '@dxos/keys';\nimport { log } from '@dxos/log';\nimport { type EdgeHttpClient } from '@dxos/react-edge-client';\nimport { DataType } from '@dxos/schema';\n\nimport { MediaStreamRecorder } from './media-stream-recorder';\nimport { Transcriber } from './transcriber';\n\n/**\n * Length of the chunk in ms.\n */\nconst RECORD_INTERVAL = 200;\n\n/**\n * Number of chunks to save before the user starts speaking.\n */\nconst PREFIXED_CHUNKS_AMOUNT = 10;\n\n/**\n * Number of chunks to transcribe automatically after.\n * Combined should be mess than 25MB or whisper would fail.\n */\nconst TRANSCRIBE_AFTER_CHUNKS_AMOUNT = 50;\n\nexport type TranscriptMessageEnricher = (message: DataType.Message) => Promise<DataType.Message>;\n\nexport type TranscriptionManagerOptions = {\n edgeClient: EdgeHttpClient;\n\n /**\n * Enrich the message before it is written to the transcription queue.\n */\n messageEnricher?: TranscriptMessageEnricher;\n};\n\n/**\n * Manages transcription state for a meeting.\n */\nexport class TranscriptionManager extends Resource {\n private readonly _edgeClient: EdgeHttpClient;\n private readonly _messageEnricher?: TranscriptMessageEnricher;\n private _audioStreamTrack?: MediaStreamTrack = undefined;\n private _identityDid?: string = undefined;\n private _mediaRecorder?: MediaStreamRecorder = undefined;\n private _transcriber?: Transcriber = undefined;\n private _queue?: Queue<DataType.Message> = undefined;\n private _enabled = false;\n\n constructor(options: TranscriptionManagerOptions) {\n super();\n this._edgeClient = options.edgeClient;\n this._messageEnricher = options.messageEnricher;\n }\n\n protected override async _open() {\n await this._toggleTranscriber();\n }\n\n protected override async _close() {\n void this._transcriber?.close();\n }\n\n setQueue(queueDxn: DXN): TranscriptionManager {\n if (this._queue?.dxn.toString() !== queueDxn.toString()) {\n log.info('setQueue', { queueDxn: queueDxn.toString() });\n this._queue = new QueueImpl<DataType.Message>(this._edgeClient, queueDxn);\n }\n return this;\n }\n\n setIdentityDid(did: string): TranscriptionManager {\n if (this._identityDid !== did) {\n this._identityDid = did;\n }\n return this;\n }\n\n setRecording(recording?: boolean): TranscriptionManager {\n if (!this.isOpen || !this._enabled) {\n return this;\n }\n\n if (recording) {\n this._transcriber?.startChunksRecording();\n } else {\n this._transcriber?.stopChunksRecording();\n }\n return this;\n }\n\n /**\n * Enable or disable transcription.\n * @param enabled - Whether to enable transcription.\n */\n @synchronized\n async setEnabled(enabled?: boolean) {\n if (this._enabled === enabled) {\n return;\n }\n\n this._enabled = enabled ?? false;\n // TODO(burdon): Why is toggle called here?\n this.isOpen && (await this._toggleTranscriber());\n }\n\n @synchronized\n async setAudioTrack(track?: MediaStreamTrack) {\n if (this._audioStreamTrack === track) {\n return;\n }\n\n this._audioStreamTrack = track;\n this.isOpen && (await this._toggleTranscriber());\n }\n\n // TODO(burdon): Change this to setEnables (explicit), not toggle.\n private async _toggleTranscriber() {\n await this._maybeReinitTranscriber();\n\n // Open or close transcriber if transcription is enabled or disabled.\n if (this._enabled) {\n await this._transcriber?.open();\n // TODO(burdon): Started and stopped blocks appear twice.\n const block = create(DataType.Message, {\n created: new Date().toISOString(),\n blocks: [{ type: 'transcription', text: 'Started', started: new Date().toISOString() }],\n sender: { role: 'assistant' },\n });\n this._queue?.append([block]);\n } else {\n await this._transcriber?.close();\n const block = create(DataType.Message, {\n created: new Date().toISOString(),\n blocks: [{ type: 'transcription', text: 'Stopped', started: new Date().toISOString() }],\n sender: { role: 'assistant' },\n });\n this._queue?.append([block]);\n }\n }\n\n private async _maybeReinitTranscriber() {\n if (!this._audioStreamTrack || !this._enabled) {\n return;\n }\n\n // Reinitialize transcriber if queue or media stream track has changed.\n let needReinit = false;\n if (this._audioStreamTrack !== this._mediaRecorder?.mediaStreamTrack) {\n this._mediaRecorder = new MediaStreamRecorder({\n mediaStreamTrack: this._audioStreamTrack,\n interval: RECORD_INTERVAL,\n });\n needReinit = true;\n }\n if (needReinit) {\n await this._transcriber?.close();\n this._transcriber = new Transcriber({\n config: {\n transcribeAfterChunksAmount: TRANSCRIBE_AFTER_CHUNKS_AMOUNT,\n prefixBufferChunksAmount: PREFIXED_CHUNKS_AMOUNT,\n },\n recorder: this._mediaRecorder,\n onSegments: (segments) => this._onSegments(segments),\n });\n }\n }\n\n private async _onSegments(segments: DataType.MessageBlock.Transcription[]) {\n if (!this.isOpen || !this._queue) {\n return;\n }\n\n let block = create(DataType.Message, {\n created: new Date().toISOString(),\n blocks: segments,\n sender: { identityDid: this._identityDid },\n });\n\n if (this._messageEnricher) {\n block = await this._messageEnricher(block);\n }\n\n this._queue.append([block]);\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["MediaRecorder", "register", "WaveFile", "synchronized", "invariant", "log", "trace", "initializingPromise", "initializeExtendableMediaRecorder", "connect", "MediaStreamRecorder", "constructor", "mediaStreamTrack", "interval", "_mediaRecorder", "undefined", "_header", "_mediaStreamTrack", "_interval", "wavConfig", "settings", "getSettings", "channels", "channelCount", "sampleRate", "bitDepthCode", "sampleSize", "String", "setOnChunk", "onChunk", "_onChunk", "start", "catch", "err", "info", "stream", "MediaStream", "mimeType", "state", "ondataavailable", "event", "_ondataavailable", "stop", "blob", "data", "uint8Array", "Uint8Array", "arrayBuffer", "isHeader", "wav", "slice", "warn", "timestamp", "Date", "now", "getSamples", "resource", "WaveFile", "DeferredTask", "Trigger", "LifecycleState", "Resource", "log", "trace", "Transcriber", "Resource", "constructor", "config", "recorder", "onSegments", "_audioChunks", "_lastUsedTimestamp", "_openTrigger", "Trigger", "autoReset", "_recording", "_transcribeTask", "undefined", "_config", "_recorder", "_onSegments", "_open", "ctx", "log", "info", "setOnChunk", "chunk", "_saveAudioChunk", "start", "DeferredTask", "_transcribe", "wake", "_close", "stop", "startChunksRecording", "_lifecycleState", "LifecycleState", "OPEN", "stopChunksRecording", "schedule", "push", "scheduled", "length", "prefixBufferChunksAmount", "_dropOldChunks", "transcribeAfterChunksAmount", "chunks", "audio", "_mergeAudioChunks", "segments", "_fetchTranscription", "Array", "isArray", "alignedSegments", "_alignSegments", "slice", "file", "WaveFile", "wavConfig", "fromScratch", "channels", "sampleRate", "bitDepthCode", "mergeFloat64Arrays", "map", "data", "toBase64", "Error", "response", "fetch", "TRANSCRIPTION_URL", "method", "body", "JSON", "stringify", "headers", "ok", "statusText", "json", "string", "text", "join", "originalChunks", "zeroTimestamp", "at", "timestamp", "filteredSegments", "filter", "segment", "end", "words", "word", "type", "started", "Date", "toISOString", "trim", "trace", "span", "showInBrowserTimeline", "synchronized", "Resource", "QueueImpl", "create", "log", "DataType", "RECORD_INTERVAL", "PREFIXED_CHUNKS_AMOUNT", "TRANSCRIBE_AFTER_CHUNKS_AMOUNT", "TranscriptionManager", "Resource", "constructor", "options", "_audioStreamTrack", "undefined", "_identityDid", "_mediaRecorder", "_transcriber", "_queue", "_enabled", "_edgeClient", "edgeClient", "_messageEnricher", "messageEnricher", "_open", "_toggleTranscriber", "_close", "close", "setQueue", "queueDxn", "dxn", "toString", "log", "info", "QueueImpl", "setIdentityDid", "did", "setRecording", "recording", "isOpen", "startChunksRecording", "stopChunksRecording", "setEnabled", "enabled", "setAudioTrack", "track", "_maybeReinitTranscriber", "open", "block", "create", "DataType", "Message", "created", "Date", "toISOString", "blocks", "type", "text", "started", "sender", "role", "append", "needReinit", "mediaStreamTrack", "MediaStreamRecorder", "interval", "Transcriber", "config", "transcribeAfterChunksAmount", "prefixBufferChunksAmount", "recorder", "onSegments", "segments", "_onSegments", "identityDid", "synchronized"]
|
|
7
|
+
}
|
|
@@ -3,12 +3,13 @@ import {
|
|
|
3
3
|
} from "./chunk-6ZR5MDK3.mjs";
|
|
4
4
|
|
|
5
5
|
// packages/plugins/plugin-transcription/src/types/schema.ts
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
import { Schema } from "effect";
|
|
7
|
+
import { Expando, Ref, TypedObject } from "@dxos/echo-schema";
|
|
8
|
+
var TranscriptSchema = Schema.Struct({
|
|
9
|
+
name: Schema.String,
|
|
9
10
|
// TODO(burdon): Use Date or string?
|
|
10
|
-
started:
|
|
11
|
-
ended:
|
|
11
|
+
started: Schema.optional(Schema.String),
|
|
12
|
+
ended: Schema.optional(Schema.String),
|
|
12
13
|
/**
|
|
13
14
|
* Queue containing TranscriptBlock objects.
|
|
14
15
|
*/
|
|
@@ -20,23 +21,24 @@ var TranscriptType = class extends TypedObject({
|
|
|
20
21
|
version: "0.1.0"
|
|
21
22
|
})(TranscriptSchema.fields) {
|
|
22
23
|
};
|
|
23
|
-
var TranscriptHeader =
|
|
24
|
-
started:
|
|
24
|
+
var TranscriptHeader = Schema.Struct({
|
|
25
|
+
started: Schema.optional(Schema.String)
|
|
25
26
|
});
|
|
26
27
|
|
|
27
28
|
// packages/plugins/plugin-transcription/src/types/types.ts
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
29
|
+
import { Schema as Schema2 } from "effect";
|
|
30
|
+
import { isInstanceOf } from "@dxos/echo-schema";
|
|
31
|
+
import { isLiveObject, SpaceId } from "@dxos/react-client/echo";
|
|
30
32
|
var TRANSCRIPTION_URL = "https://calls-service.dxos.workers.dev";
|
|
31
33
|
var TranscriptionAction;
|
|
32
34
|
(function(TranscriptionAction2) {
|
|
33
35
|
const TRANSCRIPTION_ACTION = `${TRANSCRIPTION_PLUGIN}/action`;
|
|
34
|
-
class Create extends
|
|
35
|
-
input:
|
|
36
|
-
name:
|
|
37
|
-
spaceId:
|
|
36
|
+
class Create extends Schema2.TaggedClass()(`${TRANSCRIPTION_ACTION}/create`, {
|
|
37
|
+
input: Schema2.Struct({
|
|
38
|
+
name: Schema2.optional(Schema2.String),
|
|
39
|
+
spaceId: SpaceId
|
|
38
40
|
}),
|
|
39
|
-
output:
|
|
41
|
+
output: Schema2.Struct({
|
|
40
42
|
object: TranscriptType
|
|
41
43
|
})
|
|
42
44
|
}) {
|
|
@@ -46,8 +48,8 @@ var TranscriptionAction;
|
|
|
46
48
|
var isTranscript = (object) => {
|
|
47
49
|
return isLiveObject(object) && isInstanceOf(TranscriptType, object);
|
|
48
50
|
};
|
|
49
|
-
var TranscriptionSettingsSchema =
|
|
50
|
-
entityExtraction:
|
|
51
|
+
var TranscriptionSettingsSchema = Schema2.mutable(Schema2.Struct({
|
|
52
|
+
entityExtraction: Schema2.optional(Schema2.Boolean).pipe(Schema2.withConstructorDefault(() => true))
|
|
51
53
|
}));
|
|
52
54
|
|
|
53
55
|
export {
|
|
@@ -58,4 +60,4 @@ export {
|
|
|
58
60
|
isTranscript,
|
|
59
61
|
TranscriptionSettingsSchema
|
|
60
62
|
};
|
|
61
|
-
//# sourceMappingURL=chunk-
|
|
63
|
+
//# sourceMappingURL=chunk-JHWEZRWC.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/types/schema.ts", "../../../src/types/types.ts"],
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport { Schema } from 'effect';\n\nimport { Expando, Ref, TypedObject } from '@dxos/echo-schema';\n\n/**\n * Root transcript object created when the user starts a transcription.\n */\nexport const TranscriptSchema = Schema.Struct({\n name: Schema.String,\n\n // TODO(burdon): Use Date or string?\n started: Schema.optional(Schema.String),\n ended: Schema.optional(Schema.String),\n\n /**\n * Queue containing TranscriptBlock objects.\n */\n // TODO(wittjosiah): Should be a ref to a queue.\n queue: Ref(Expando),\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 = Schema.Struct({\n started: Schema.optional(Schema.String),\n});\n\nexport type TranscriptHeader = Schema.Schema.Type<typeof TranscriptHeader>;\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { Schema } from 'effect';\n\nimport { isInstanceOf } from '@dxos/echo-schema';\nimport { isLiveObject, SpaceId } from '@dxos/react-client/echo';\n\nimport { 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 Schema.TaggedClass<Create>()(`${TRANSCRIPTION_ACTION}/create`, {\n input: Schema.Struct({\n name: Schema.optional(Schema.String),\n spaceId: SpaceId,\n }),\n output: Schema.Struct({\n object: TranscriptType,\n }),\n }) {}\n}\n\nexport const isTranscript = (object: unknown): object is typeof TranscriptType => {\n return isLiveObject(object) && isInstanceOf(TranscriptType, object);\n};\n\n// TODO(burdon): Create with decode consistently: Schema.decodeSync(TranscriptionSettingsSchema)({}))\nexport const TranscriptionSettingsSchema = Schema.mutable(\n Schema.Struct({\n entityExtraction: Schema.optional(Schema.Boolean).pipe(Schema.withConstructorDefault(() => true)),\n }),\n);\n\nexport type TranscriptionSettingsProps = Schema.Schema.Type<typeof TranscriptionSettingsSchema>;\n"],
|
|
5
|
+
"mappings": ";;;;;AAIA,SAASA,cAAc;AAEvB,SAASC,SAASC,KAAKC,mBAAmB;AAKnC,IAAMC,mBAAmBC,OAAOC,OAAO;EAC5CC,MAAMF,OAAOG;;EAGbC,SAASJ,OAAOK,SAASL,OAAOG,MAAM;EACtCG,OAAON,OAAOK,SAASL,OAAOG,MAAM;;;;;EAMpCI,OAAOC,IAAIC,OAAAA;AACb,CAAA;AAEO,IAAMC,iBAAN,cAA6BC,YAAY;EAC9CC,UAAU;EACVC,SAAS;AACX,CAAA,EAAGd,iBAAiBe,MAAM,EAAA;AAAG;AAQ7B,IAAMC,mBAAmBf,OAAOC,OAAO;EACrCG,SAASJ,OAAOK,SAASL,OAAOG,MAAM;AACxC,CAAA;;;AClCA,SAASa,UAAAA,eAAc;AAEvB,SAASC,oBAAoB;AAC7B,SAASC,cAAcC,eAAe;AAW/B,IAAMC,oBAAoB;;UAEhBC,sBAAAA;AACf,QAAMC,uBAAuB,GAAGC,oBAAAA;EAEzB,MAAMC,eAAeC,QAAOC,YAAW,EAAW,GAAGJ,oBAAAA,WAA+B;IACzFK,OAAOF,QAAOG,OAAO;MACnBC,MAAMJ,QAAOK,SAASL,QAAOM,MAAM;MACnCC,SAASC;IACX,CAAA;IACAC,QAAQT,QAAOG,OAAO;MACpBO,QAAQC;IACV,CAAA;EACF,CAAA,EAAA;EAAI;uBARSZ,SAAAA;AASf,GAZiBH,wBAAAA,sBAAAA,CAAAA,EAAAA;AAcV,IAAMgB,eAAe,CAACF,WAAAA;AAC3B,SAAOG,aAAaH,MAAAA,KAAWI,aAAaH,gBAAgBD,MAAAA;AAC9D;AAGO,IAAMK,8BAA8Bf,QAAOgB,QAChDhB,QAAOG,OAAO;EACZc,kBAAkBjB,QAAOK,SAASL,QAAOkB,OAAO,EAAEC,KAAKnB,QAAOoB,uBAAuB,MAAM,IAAA,CAAA;AAC7F,CAAA,CAAA;",
|
|
6
|
+
"names": ["Schema", "Expando", "Ref", "TypedObject", "TranscriptSchema", "Schema", "Struct", "name", "String", "started", "optional", "ended", "queue", "Ref", "Expando", "TranscriptType", "TypedObject", "typename", "version", "fields", "TranscriptHeader", "Schema", "isInstanceOf", "isLiveObject", "SpaceId", "TRANSCRIPTION_URL", "TranscriptionAction", "TRANSCRIPTION_ACTION", "TRANSCRIPTION_PLUGIN", "Create", "Schema", "TaggedClass", "input", "Struct", "name", "optional", "String", "spaceId", "SpaceId", "output", "object", "TranscriptType", "isTranscript", "isLiveObject", "isInstanceOf", "TranscriptionSettingsSchema", "mutable", "entityExtraction", "Boolean", "pipe", "withConstructorDefault"]
|
|
7
|
+
}
|
|
@@ -582,12 +582,12 @@ import { useCapabilities } from "@dxos/app-framework";
|
|
|
582
582
|
|
|
583
583
|
// packages/plugins/plugin-transcription/src/capabilities/index.ts
|
|
584
584
|
import { lazy } from "@dxos/app-framework";
|
|
585
|
-
var AppGraphBuilder = lazy(() => import("./app-graph-builder-
|
|
586
|
-
var IntentResolver = lazy(() => import("./intent-resolver-
|
|
585
|
+
var AppGraphBuilder = lazy(() => import("./app-graph-builder-REQZ5SC5.mjs"));
|
|
586
|
+
var IntentResolver = lazy(() => import("./intent-resolver-DZ62CJPC.mjs"));
|
|
587
587
|
var MeetingTranscriptionState = lazy(() => import("./meeting-transcription-state-MNA2XROE.mjs"));
|
|
588
|
-
var ReactSurface = lazy(() => import("./react-surface-
|
|
589
|
-
var Transcriber = lazy(() => import("./transcriber-
|
|
590
|
-
var Settings = lazy(() => import("./settings-
|
|
588
|
+
var ReactSurface = lazy(() => import("./react-surface-PUXZNAZL.mjs"));
|
|
589
|
+
var Transcriber = lazy(() => import("./transcriber-YWWIV6KP.mjs"));
|
|
590
|
+
var Settings = lazy(() => import("./settings-JWDS4J3F.mjs"));
|
|
591
591
|
|
|
592
592
|
// packages/plugins/plugin-transcription/src/hooks/useTranscriber.ts
|
|
593
593
|
var useTranscriber = ({ audioStreamTrack, onSegments, config }) => {
|
|
@@ -717,4 +717,4 @@ export {
|
|
|
717
717
|
Transcriber,
|
|
718
718
|
Settings
|
|
719
719
|
};
|
|
720
|
-
//# sourceMappingURL=chunk-
|
|
720
|
+
//# sourceMappingURL=chunk-K2LS2QOM.mjs.map
|