@dxos/plugin-transcription 0.8.2-main.12df754 → 0.8.2-main.30e4dbb
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-4D4BHE7G.mjs → TranscriptContainer-3LU3XBEB.mjs} +3 -3
- package/dist/lib/browser/app-graph-builder-YXELPN6F.mjs +349 -0
- package/dist/lib/browser/app-graph-builder-YXELPN6F.mjs.map +7 -0
- package/dist/lib/browser/{chunk-DR3NBV6Q.mjs → chunk-GWY2Q2NE.mjs} +105 -78
- package/dist/lib/browser/chunk-GWY2Q2NE.mjs.map +7 -0
- package/dist/lib/browser/{chunk-RHHJZQPM.mjs → chunk-HNIKXVCG.mjs} +135 -117
- package/dist/lib/browser/chunk-HNIKXVCG.mjs.map +7 -0
- package/dist/lib/browser/chunk-HRDAILQX.mjs +27 -0
- package/dist/lib/browser/chunk-HRDAILQX.mjs.map +7 -0
- package/dist/lib/browser/{chunk-5BE6RTNC.mjs → chunk-LTIQFX4W.mjs} +1 -1
- package/dist/lib/browser/{chunk-5BE6RTNC.mjs.map → chunk-LTIQFX4W.mjs.map} +1 -1
- package/dist/lib/browser/{chunk-5Q3R53U3.mjs → chunk-TGOKX32G.mjs} +21 -31
- package/dist/lib/browser/chunk-TGOKX32G.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +29 -17
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/{intent-resolver-ZQQEH27F.mjs → intent-resolver-BBB3DWV4.mjs} +4 -4
- package/dist/lib/browser/{intent-resolver-ZQQEH27F.mjs.map → intent-resolver-BBB3DWV4.mjs.map} +2 -2
- package/dist/lib/browser/{meeting-transcription-state-5D52VTHU.mjs → meeting-transcription-state-MNA2XROE.mjs} +2 -2
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/{react-surface-HETJ5XY6.mjs → react-surface-R277DACJ.mjs} +18 -7
- package/dist/lib/browser/react-surface-R277DACJ.mjs.map +7 -0
- package/dist/lib/browser/settings-I226DZ27.mjs +24 -0
- package/dist/lib/browser/settings-I226DZ27.mjs.map +7 -0
- package/dist/lib/browser/{transcriber-SMRLU2KY.mjs → transcriber-QRSS6X6S.mjs} +4 -4
- package/dist/lib/browser/types/index.mjs +3 -3
- package/dist/lib/node/{TranscriptContainer-ZWP6UKY6.cjs → TranscriptContainer-DICOMZLM.cjs} +8 -8
- package/dist/lib/node/{TranscriptContainer-ZWP6UKY6.cjs.map → TranscriptContainer-DICOMZLM.cjs.map} +2 -2
- package/dist/lib/node/app-graph-builder-I6LYVIYY.cjs +350 -0
- package/dist/lib/node/app-graph-builder-I6LYVIYY.cjs.map +7 -0
- package/dist/lib/node/{chunk-3QEJ5EBO.cjs → chunk-34WFY7M7.cjs} +22 -32
- package/dist/lib/node/chunk-34WFY7M7.cjs.map +7 -0
- package/dist/lib/node/{chunk-KO6MKCED.cjs → chunk-4JOJCZPJ.cjs} +138 -119
- package/dist/lib/node/chunk-4JOJCZPJ.cjs.map +7 -0
- package/dist/lib/node/{chunk-HYGDHS6X.cjs → chunk-JUGOXWES.cjs} +4 -4
- package/dist/lib/node/{chunk-HYGDHS6X.cjs.map → chunk-JUGOXWES.cjs.map} +1 -1
- package/dist/lib/node/{chunk-WXG4Z2EZ.cjs → chunk-K553L7CZ.cjs} +23 -8
- package/dist/lib/node/chunk-K553L7CZ.cjs.map +7 -0
- package/dist/lib/node/{chunk-LA73IHCB.cjs → chunk-RK4BEN5E.cjs} +108 -80
- package/dist/lib/node/chunk-RK4BEN5E.cjs.map +7 -0
- package/dist/lib/node/index.cjs +46 -34
- package/dist/lib/node/index.cjs.map +3 -3
- package/dist/lib/node/{intent-resolver-VY3XWYAA.cjs → intent-resolver-7XY3WITN.cjs} +8 -8
- package/dist/lib/node/{intent-resolver-VY3XWYAA.cjs.map → intent-resolver-7XY3WITN.cjs.map} +2 -2
- package/dist/lib/node/{meeting-transcription-state-OYWCY5XE.cjs → meeting-transcription-state-5XLTMWPA.cjs} +6 -6
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/{react-surface-M2JQIIDY.cjs → react-surface-HUSWAORU.cjs} +20 -11
- package/dist/lib/node/react-surface-HUSWAORU.cjs.map +7 -0
- package/dist/lib/node/settings-NDMU3EWQ.cjs +38 -0
- package/dist/lib/node/settings-NDMU3EWQ.cjs.map +7 -0
- package/dist/lib/node/{transcriber-E6AAB4SU.cjs → transcriber-UZJMG44C.cjs} +10 -10
- package/dist/lib/node/types/index.cjs +8 -8
- package/dist/lib/node/types/index.cjs.map +1 -1
- package/dist/lib/node-esm/{TranscriptContainer-3HJ752CP.mjs → TranscriptContainer-K4E4P5T6.mjs} +3 -3
- package/dist/lib/node-esm/app-graph-builder-6FY2UQOH.mjs +350 -0
- package/dist/lib/node-esm/app-graph-builder-6FY2UQOH.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-3I7AC3D3.mjs +28 -0
- package/dist/lib/node-esm/chunk-3I7AC3D3.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-YXZOLOFT.mjs → chunk-5E2MR5XK.mjs} +1 -1
- package/dist/lib/node-esm/{chunk-YXZOLOFT.mjs.map → chunk-5E2MR5XK.mjs.map} +1 -1
- package/dist/lib/node-esm/{chunk-SDMGJZLN.mjs → chunk-6C34FO4C.mjs} +135 -117
- package/dist/lib/node-esm/chunk-6C34FO4C.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-K3R3YK3S.mjs → chunk-CKANLRS4.mjs} +105 -78
- package/dist/lib/node-esm/chunk-CKANLRS4.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-54HDN33F.mjs → chunk-KUQ3ZTRX.mjs} +21 -31
- package/dist/lib/node-esm/chunk-KUQ3ZTRX.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +29 -17
- package/dist/lib/node-esm/index.mjs.map +3 -3
- package/dist/lib/node-esm/{intent-resolver-FCTNJPWY.mjs → intent-resolver-ACGAPLDZ.mjs} +4 -4
- package/dist/lib/node-esm/{intent-resolver-FCTNJPWY.mjs.map → intent-resolver-ACGAPLDZ.mjs.map} +2 -2
- package/dist/lib/node-esm/{meeting-transcription-state-XMZJ45P4.mjs → meeting-transcription-state-3WOZ52BQ.mjs} +2 -2
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/{react-surface-PXFSIM6V.mjs → react-surface-G2OY4MWL.mjs} +18 -7
- package/dist/lib/node-esm/react-surface-G2OY4MWL.mjs.map +7 -0
- package/dist/lib/node-esm/settings-O7X2UQQG.mjs +25 -0
- package/dist/lib/node-esm/settings-O7X2UQQG.mjs.map +7 -0
- package/dist/lib/node-esm/{transcriber-REAGRCPY.mjs → transcriber-NVVFH7IF.mjs} +4 -4
- package/dist/lib/node-esm/types/index.mjs +3 -3
- package/dist/types/src/TranscriptionPlugin.d.ts.map +1 -1
- package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
- package/dist/types/src/capabilities/capabilities.d.ts +1 -1
- package/dist/types/src/capabilities/capabilities.d.ts.map +1 -1
- package/dist/types/src/capabilities/index.d.ts +1 -0
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
- package/dist/types/src/capabilities/settings.d.ts +4 -0
- package/dist/types/src/capabilities/settings.d.ts.map +1 -0
- package/dist/types/src/components/Transcript/Transcript.d.ts +6 -4
- package/dist/types/src/components/Transcript/Transcript.d.ts.map +1 -1
- package/dist/types/src/components/Transcript/Transcript.stories.d.ts +8 -4
- package/dist/types/src/components/Transcript/Transcript.stories.d.ts.map +1 -1
- package/dist/types/src/components/Transcript/deprecated/OldTranscript.d.ts +27 -0
- package/dist/types/src/components/Transcript/deprecated/OldTranscript.d.ts.map +1 -0
- package/dist/types/src/components/Transcript/transcript-extension.d.ts +4 -4
- package/dist/types/src/components/Transcript/transcript-extension.d.ts.map +1 -1
- package/dist/types/src/components/TranscriptContainer.d.ts.map +1 -1
- package/dist/types/src/components/TranscriptionSettings/TranscriptionSettings.d.ts +6 -0
- package/dist/types/src/components/TranscriptionSettings/TranscriptionSettings.d.ts.map +1 -0
- package/dist/types/src/components/TranscriptionSettings/index.d.ts +2 -0
- package/dist/types/src/components/TranscriptionSettings/index.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +1 -0
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/components/transcription.stories.d.ts +6 -3
- package/dist/types/src/components/transcription.stories.d.ts.map +1 -1
- package/dist/types/src/entity-extraction/entity-extraction.d.ts +33 -7
- 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 +2 -2
- 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/model/model.d.ts +23 -23
- package/dist/types/src/model/model.d.ts.map +1 -1
- package/dist/types/src/testing/index.d.ts +2 -0
- package/dist/types/src/testing/index.d.ts.map +1 -0
- package/dist/types/src/testing/testing.d.ts +40 -0
- package/dist/types/src/testing/testing.d.ts.map +1 -0
- 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 +17 -15
- package/dist/types/src/transcriber/transcription-manager.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +3 -18
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/schema.d.ts +26 -40
- package/dist/types/src/types/schema.d.ts.map +1 -1
- package/dist/types/src/types/types.d.ts +11 -7
- 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 +51 -46
- package/src/TranscriptionPlugin.tsx +29 -12
- package/src/capabilities/app-graph-builder.ts +99 -29
- package/src/capabilities/capabilities.ts +1 -1
- package/src/capabilities/index.ts +1 -0
- package/src/capabilities/intent-resolver.ts +2 -2
- package/src/capabilities/react-surface.tsx +12 -4
- package/src/capabilities/settings.ts +20 -0
- package/src/components/Transcript/Transcript.stories.tsx +72 -36
- package/src/components/Transcript/Transcript.tsx +37 -30
- package/src/components/Transcript/deprecated/{Transcript.tsx → OldTranscript.tsx} +30 -1
- package/src/components/Transcript/transcript-extension.ts +20 -17
- package/src/components/TranscriptContainer.tsx +6 -4
- package/src/components/TranscriptionSettings/TranscriptionSettings.tsx +26 -0
- package/src/components/TranscriptionSettings/index.ts +5 -0
- package/src/components/index.ts +1 -0
- package/src/components/transcription.stories.tsx +84 -34
- package/src/entity-extraction/entity-extraction.test.ts +75 -10
- package/src/entity-extraction/entity-extraction.ts +110 -55
- package/src/entity-extraction/system-prompt.tpl +38 -9
- package/src/hooks/useQueueModelAdapter.ts +44 -11
- package/src/model/model.test.ts +90 -44
- package/src/model/model.ts +59 -59
- package/src/testing/index.ts +5 -0
- package/src/testing/testing.ts +221 -0
- package/src/transcriber/transcriber.browser.test.ts +3 -3
- package/src/transcriber/transcriber.ts +19 -10
- package/src/transcriber/transcription-manager.ts +66 -57
- package/src/translations.ts +2 -0
- package/src/types/schema.ts +10 -31
- package/src/types/types.ts +17 -7
- package/dist/lib/browser/app-graph-builder-I4SSIQMW.mjs +0 -168
- package/dist/lib/browser/app-graph-builder-I4SSIQMW.mjs.map +0 -7
- package/dist/lib/browser/chunk-5Q3R53U3.mjs.map +0 -7
- package/dist/lib/browser/chunk-DR3NBV6Q.mjs.map +0 -7
- package/dist/lib/browser/chunk-GI5LZ4SV.mjs +0 -8
- package/dist/lib/browser/chunk-GI5LZ4SV.mjs.map +0 -7
- package/dist/lib/browser/chunk-RHHJZQPM.mjs.map +0 -7
- package/dist/lib/browser/react-surface-HETJ5XY6.mjs.map +0 -7
- package/dist/lib/node/app-graph-builder-WWC4WNTG.cjs +0 -177
- package/dist/lib/node/app-graph-builder-WWC4WNTG.cjs.map +0 -7
- package/dist/lib/node/chunk-3QEJ5EBO.cjs.map +0 -7
- package/dist/lib/node/chunk-KO6MKCED.cjs.map +0 -7
- package/dist/lib/node/chunk-LA73IHCB.cjs.map +0 -7
- package/dist/lib/node/chunk-WXG4Z2EZ.cjs.map +0 -7
- package/dist/lib/node/react-surface-M2JQIIDY.cjs.map +0 -7
- package/dist/lib/node-esm/app-graph-builder-PPJQAFSI.mjs +0 -169
- package/dist/lib/node-esm/app-graph-builder-PPJQAFSI.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-54HDN33F.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-K3R3YK3S.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-SDMGJZLN.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-XY22OP6H.mjs +0 -10
- package/dist/lib/node-esm/chunk-XY22OP6H.mjs.map +0 -7
- package/dist/lib/node-esm/react-surface-PXFSIM6V.mjs.map +0 -7
- package/dist/types/src/components/Transcript/deprecated/Transcript.d.ts +0 -13
- package/dist/types/src/components/Transcript/deprecated/Transcript.d.ts.map +0 -1
- package/dist/types/src/components/Transcript/testings.d.ts +0 -51
- package/dist/types/src/components/Transcript/testings.d.ts.map +0 -1
- package/dist/types/src/testing/test-data.d.ts +0 -73
- package/dist/types/src/testing/test-data.d.ts.map +0 -1
- package/src/components/Transcript/testings.ts +0 -182
- package/src/testing/test-data.ts +0 -314
- /package/dist/lib/browser/{TranscriptContainer-4D4BHE7G.mjs.map → TranscriptContainer-3LU3XBEB.mjs.map} +0 -0
- /package/dist/lib/browser/{meeting-transcription-state-5D52VTHU.mjs.map → meeting-transcription-state-MNA2XROE.mjs.map} +0 -0
- /package/dist/lib/browser/{transcriber-SMRLU2KY.mjs.map → transcriber-QRSS6X6S.mjs.map} +0 -0
- /package/dist/lib/node/{meeting-transcription-state-OYWCY5XE.cjs.map → meeting-transcription-state-5XLTMWPA.cjs.map} +0 -0
- /package/dist/lib/node/{transcriber-E6AAB4SU.cjs.map → transcriber-UZJMG44C.cjs.map} +0 -0
- /package/dist/lib/node-esm/{TranscriptContainer-3HJ752CP.mjs.map → TranscriptContainer-K4E4P5T6.mjs.map} +0 -0
- /package/dist/lib/node-esm/{meeting-transcription-state-XMZJ45P4.mjs.map → meeting-transcription-state-3WOZ52BQ.mjs.map} +0 -0
- /package/dist/lib/node-esm/{transcriber-REAGRCPY.mjs.map → transcriber-NVVFH7IF.mjs.map} +0 -0
|
@@ -9,15 +9,15 @@ import { intervalToDuration } from 'date-fns/intervalToDuration';
|
|
|
9
9
|
|
|
10
10
|
import { type CleanupFn, addEventListener, combine } from '@dxos/async';
|
|
11
11
|
import { type RenderCallback } from '@dxos/react-ui-editor';
|
|
12
|
+
import { type DataType } from '@dxos/schema';
|
|
12
13
|
|
|
13
|
-
import { DocumentAdapter, type
|
|
14
|
-
import { type TranscriptBlock } from '../../types';
|
|
14
|
+
import { DocumentAdapter, type SerializationModel } from '../../model';
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
|
-
* Data structure that maps
|
|
17
|
+
* Data structure that maps Chunks queue to lines with transcript state.
|
|
18
18
|
*/
|
|
19
19
|
export type TranscriptOptions = {
|
|
20
|
-
model:
|
|
20
|
+
model: SerializationModel<DataType.Message>;
|
|
21
21
|
started?: Date;
|
|
22
22
|
renderButton?: RenderCallback<{ onClick: () => void }>;
|
|
23
23
|
};
|
|
@@ -32,12 +32,13 @@ export const transcript = ({ model, started, renderButton }: TranscriptOptions):
|
|
|
32
32
|
class: 'cm-timestamp-gutter',
|
|
33
33
|
lineMarkerChange: (update) => update.docChanged || update.viewportChanged,
|
|
34
34
|
markers: (view) => {
|
|
35
|
-
const start = getStartTime(started, model.
|
|
35
|
+
const start = getStartTime(started, model.chunks[0]);
|
|
36
36
|
const builder = new RangeSetBuilder<GutterMarker>();
|
|
37
37
|
for (const { from, to } of view.visibleRanges) {
|
|
38
38
|
let line = view.state.doc.lineAt(from);
|
|
39
39
|
while (line.from <= to) {
|
|
40
|
-
const
|
|
40
|
+
const block = model.getChunkAtLine(line.number)?.blocks[0];
|
|
41
|
+
const timestamp = block?.type === 'transcription' && block.started;
|
|
41
42
|
if (timestamp) {
|
|
42
43
|
builder.add(line.from, line.from, new TimestampMarker(line.number, new Date(timestamp), start));
|
|
43
44
|
}
|
|
@@ -69,13 +70,15 @@ export const transcript = ({ model, started, renderButton }: TranscriptOptions):
|
|
|
69
70
|
let isAutoScrolling = false;
|
|
70
71
|
let hasScrolled = false;
|
|
71
72
|
|
|
72
|
-
|
|
73
|
-
|
|
73
|
+
let timeout: NodeJS.Timeout | undefined;
|
|
74
|
+
const scrollToBottom = (smooth = false) => {
|
|
75
|
+
scroller.style.scrollBehavior = smooth ? 'smooth' : '';
|
|
74
76
|
|
|
75
77
|
// Temporarily hide scrollbar to prevent flicker.
|
|
76
78
|
scroller.classList.add('cm-hide-scrollbar');
|
|
77
79
|
isAutoScrolling = true;
|
|
78
|
-
|
|
80
|
+
clearTimeout(timeout);
|
|
81
|
+
timeout = setTimeout(() => {
|
|
79
82
|
this._controls?.classList.add('opacity-0');
|
|
80
83
|
scroller.classList.remove('cm-hide-scrollbar');
|
|
81
84
|
isAutoScrolling = false;
|
|
@@ -96,7 +99,7 @@ export const transcript = ({ model, started, renderButton }: TranscriptOptions):
|
|
|
96
99
|
this._controls,
|
|
97
100
|
{
|
|
98
101
|
onClick: () => {
|
|
99
|
-
scrollToBottom();
|
|
102
|
+
scrollToBottom(false);
|
|
100
103
|
},
|
|
101
104
|
},
|
|
102
105
|
view,
|
|
@@ -122,7 +125,7 @@ export const transcript = ({ model, started, renderButton }: TranscriptOptions):
|
|
|
122
125
|
|
|
123
126
|
// Scroll.
|
|
124
127
|
if (autoScroll) {
|
|
125
|
-
scrollToBottom();
|
|
128
|
+
scrollToBottom(true);
|
|
126
129
|
}
|
|
127
130
|
}),
|
|
128
131
|
);
|
|
@@ -210,24 +213,24 @@ class TimestampMarker extends GutterMarker {
|
|
|
210
213
|
}
|
|
211
214
|
}
|
|
212
215
|
|
|
213
|
-
const getStartTime = (started?: Date,
|
|
216
|
+
const getStartTime = (started?: Date, message?: DataType.Message): Date | undefined => {
|
|
214
217
|
if (started) {
|
|
215
218
|
return started;
|
|
216
219
|
}
|
|
217
220
|
|
|
218
|
-
if (
|
|
219
|
-
return new Date(
|
|
221
|
+
if (message?.blocks[0]?.type === 'transcription' && message.blocks[0].started) {
|
|
222
|
+
return new Date(message.blocks[0].started);
|
|
220
223
|
}
|
|
221
224
|
|
|
222
225
|
return undefined;
|
|
223
226
|
};
|
|
224
227
|
|
|
225
228
|
const formatTimestamp = (timestamp: Date, relative?: Date) => {
|
|
226
|
-
if (
|
|
227
|
-
return format(timestamp, 'HH:mm:ss');
|
|
228
|
-
} else {
|
|
229
|
+
if (relative) {
|
|
229
230
|
const pad = (n = 0) => String(n).padStart(2, '0');
|
|
230
231
|
const { hours, minutes, seconds } = intervalToDuration({ start: relative, end: timestamp });
|
|
231
232
|
return `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;
|
|
233
|
+
} else {
|
|
234
|
+
return format(timestamp, 'HH:mm:ss');
|
|
232
235
|
}
|
|
233
236
|
};
|
|
@@ -5,18 +5,20 @@
|
|
|
5
5
|
import React, { type FC } from 'react';
|
|
6
6
|
|
|
7
7
|
import { fullyQualifiedId, getSpace } from '@dxos/client/echo';
|
|
8
|
-
import { useQueue } from '@dxos/react-client/echo';
|
|
8
|
+
import { useMembers, useQueue } from '@dxos/react-client/echo';
|
|
9
9
|
import { StackItem } from '@dxos/react-ui-stack';
|
|
10
|
+
import { type DataType } from '@dxos/schema';
|
|
10
11
|
|
|
11
12
|
import { Transcript, renderMarkdown } from './Transcript';
|
|
12
13
|
import { useQueueModelAdapter } from '../hooks';
|
|
13
|
-
import { type
|
|
14
|
+
import { type TranscriptType } from '../types';
|
|
14
15
|
|
|
15
16
|
export const TranscriptionContainer: FC<{ role: string; transcript: TranscriptType }> = ({ role, transcript }) => {
|
|
16
17
|
const attendableId = fullyQualifiedId(transcript);
|
|
17
18
|
const space = getSpace(transcript);
|
|
18
|
-
const
|
|
19
|
-
const
|
|
19
|
+
const members = useMembers(space?.key).map((member) => member.identity);
|
|
20
|
+
const queue = useQueue<DataType.Message>(transcript.queue.dxn, { pollInterval: 1_000 });
|
|
21
|
+
const model = useQueueModelAdapter(renderMarkdown(members), queue);
|
|
20
22
|
|
|
21
23
|
return (
|
|
22
24
|
<StackItem.Content role={role} classNames='container-max-width pli-2'>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2023 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React from 'react';
|
|
6
|
+
|
|
7
|
+
import { Input, useTranslation } from '@dxos/react-ui';
|
|
8
|
+
import { DeprecatedFormContainer, DeprecatedFormInput } from '@dxos/react-ui-form';
|
|
9
|
+
|
|
10
|
+
import { TRANSCRIPTION_PLUGIN } from '../../meta';
|
|
11
|
+
import { type TranscriptionSettingsProps } from '../../types';
|
|
12
|
+
|
|
13
|
+
export const TranscriptionSettings = ({ settings }: { settings: TranscriptionSettingsProps }) => {
|
|
14
|
+
const { t } = useTranslation(TRANSCRIPTION_PLUGIN);
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<DeprecatedFormContainer>
|
|
18
|
+
<DeprecatedFormInput label={t('settings entity extraction label')}>
|
|
19
|
+
<Input.Switch
|
|
20
|
+
checked={!!settings.entityExtraction}
|
|
21
|
+
onCheckedChange={(checked) => (settings.entityExtraction = checked)}
|
|
22
|
+
/>
|
|
23
|
+
</DeprecatedFormInput>
|
|
24
|
+
</DeprecatedFormContainer>
|
|
25
|
+
);
|
|
26
|
+
};
|
package/src/components/index.ts
CHANGED
|
@@ -18,32 +18,40 @@ import React, {
|
|
|
18
18
|
|
|
19
19
|
import { Events, IntentPlugin, SettingsPlugin } from '@dxos/app-framework';
|
|
20
20
|
import { withPluginManager } from '@dxos/app-framework/testing';
|
|
21
|
-
import {
|
|
21
|
+
import { AIServiceEdgeClient } from '@dxos/assistant';
|
|
22
|
+
import { AI_SERVICE_ENDPOINT } from '@dxos/assistant/testing';
|
|
23
|
+
import { Filter, MemoryQueue } from '@dxos/echo-db';
|
|
22
24
|
import { create } from '@dxos/echo-schema';
|
|
23
25
|
import { type DXN } from '@dxos/keys';
|
|
24
26
|
import { log } from '@dxos/log';
|
|
25
27
|
import { ClientPlugin } from '@dxos/plugin-client';
|
|
28
|
+
import { PreviewPlugin } from '@dxos/plugin-preview';
|
|
26
29
|
import { SpacePlugin } from '@dxos/plugin-space';
|
|
30
|
+
import { StorybookLayoutPlugin } from '@dxos/plugin-storybook-layout';
|
|
27
31
|
import { ThemePlugin } from '@dxos/plugin-theme';
|
|
28
|
-
import {
|
|
32
|
+
import { createQueueDxn, useQueue, useSpace } from '@dxos/react-client/echo';
|
|
29
33
|
import { IconButton, Toolbar } from '@dxos/react-ui';
|
|
30
34
|
import { ScrollContainer } from '@dxos/react-ui-components';
|
|
31
35
|
import { defaultTx } from '@dxos/react-ui-theme';
|
|
36
|
+
import { DataType } from '@dxos/schema';
|
|
37
|
+
import { seedTestData, Testing } from '@dxos/schema/testing';
|
|
32
38
|
import { withLayout, withTheme } from '@dxos/storybook-utils';
|
|
33
39
|
|
|
34
40
|
import { renderMarkdown, Transcript } from './Transcript';
|
|
35
|
-
import { TestItem } from './Transcript/testings';
|
|
36
41
|
import { TranscriptionPlugin } from '../TranscriptionPlugin';
|
|
42
|
+
import { processTranscriptMessage } from '../entity-extraction';
|
|
37
43
|
import { useAudioFile, useAudioTrack, useQueueModelAdapter, useTranscriber } from '../hooks';
|
|
38
|
-
import { type
|
|
44
|
+
import { type SerializationModel } from '../model';
|
|
45
|
+
import { TestItem } from '../testing';
|
|
39
46
|
import { type TranscriberParams } from '../transcriber';
|
|
40
|
-
import { TranscriptBlock } from '../types';
|
|
41
47
|
|
|
42
48
|
const TranscriptionStory: FC<{
|
|
43
|
-
model:
|
|
49
|
+
model: SerializationModel<DataType.Message>;
|
|
44
50
|
running: boolean;
|
|
45
51
|
onRunningChange: Dispatch<SetStateAction<boolean>>;
|
|
46
52
|
}> = ({ model, running, onRunningChange }) => {
|
|
53
|
+
const space = useSpace();
|
|
54
|
+
|
|
47
55
|
return (
|
|
48
56
|
<div className='flex flex-col w-[30rem]'>
|
|
49
57
|
<Toolbar.Root>
|
|
@@ -55,30 +63,67 @@ const TranscriptionStory: FC<{
|
|
|
55
63
|
/>
|
|
56
64
|
</Toolbar.Root>
|
|
57
65
|
<ScrollContainer>
|
|
58
|
-
<Transcript model={model} attendableId='story' />
|
|
66
|
+
<Transcript space={space} model={model} attendableId='story' />
|
|
59
67
|
</ScrollContainer>
|
|
60
68
|
</div>
|
|
61
69
|
);
|
|
62
70
|
};
|
|
63
71
|
|
|
64
|
-
const
|
|
72
|
+
const aiService = new AIServiceEdgeClient({
|
|
73
|
+
endpoint: AI_SERVICE_ENDPOINT.REMOTE,
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
const Microphone = ({ entityExtraction }: { entityExtraction?: boolean }) => {
|
|
65
77
|
const [running, setRunning] = useState(false);
|
|
66
78
|
|
|
67
79
|
// Audio.
|
|
68
80
|
const track = useAudioTrack(running);
|
|
69
81
|
|
|
70
82
|
// Queue.
|
|
71
|
-
const queueDxn = useMemo(() =>
|
|
72
|
-
const queue = useMemo(() => new MemoryQueue<
|
|
73
|
-
const model = useQueueModelAdapter(renderMarkdown, queue);
|
|
83
|
+
const queueDxn = useMemo(() => createQueueDxn(), []);
|
|
84
|
+
const queue = useMemo(() => new MemoryQueue<DataType.Message>(queueDxn), [queueDxn]);
|
|
85
|
+
const model = useQueueModelAdapter(renderMarkdown([]), queue);
|
|
86
|
+
const space = useSpace();
|
|
74
87
|
|
|
75
88
|
// Transcriber.
|
|
76
89
|
const handleSegments = useCallback<TranscriberParams['onSegments']>(
|
|
77
|
-
async (
|
|
78
|
-
const
|
|
79
|
-
|
|
90
|
+
async (blocks) => {
|
|
91
|
+
const message = create(DataType.Message, { sender: { name: 'You' }, created: new Date().toISOString(), blocks });
|
|
92
|
+
|
|
93
|
+
if (entityExtraction) {
|
|
94
|
+
if (!space) {
|
|
95
|
+
log.warn('no space');
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
// TODO(dmaretskyi): Move to vector search index.
|
|
99
|
+
const { objects } = await space.db
|
|
100
|
+
.query(
|
|
101
|
+
Filter.or(
|
|
102
|
+
Filter.schema(DataType.Person),
|
|
103
|
+
Filter.schema(DataType.Organization),
|
|
104
|
+
Filter.schema(Testing.DocumentType),
|
|
105
|
+
),
|
|
106
|
+
)
|
|
107
|
+
.run();
|
|
108
|
+
|
|
109
|
+
log.info('context', { objects });
|
|
110
|
+
|
|
111
|
+
const result = await processTranscriptMessage({
|
|
112
|
+
message,
|
|
113
|
+
aiService,
|
|
114
|
+
context: {
|
|
115
|
+
objects,
|
|
116
|
+
},
|
|
117
|
+
options: {
|
|
118
|
+
fallbackToRaw: true,
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
void queue.append([result.message]);
|
|
122
|
+
} else {
|
|
123
|
+
void queue.append([message]);
|
|
124
|
+
}
|
|
80
125
|
},
|
|
81
|
-
[queue],
|
|
126
|
+
[queue, space],
|
|
82
127
|
);
|
|
83
128
|
|
|
84
129
|
const config = useRef<TranscriberParams['config']>({
|
|
@@ -94,10 +139,8 @@ const Microphone = () => {
|
|
|
94
139
|
const [isOpen, setIsOpen] = useState(false);
|
|
95
140
|
useEffect(() => {
|
|
96
141
|
void transcriber?.open().then(() => setIsOpen(true));
|
|
97
|
-
log.info('transcriber open');
|
|
98
142
|
return () => {
|
|
99
143
|
void transcriber?.close().then(() => setIsOpen(false));
|
|
100
|
-
log.info('transcriber close');
|
|
101
144
|
};
|
|
102
145
|
}, [transcriber]);
|
|
103
146
|
|
|
@@ -105,10 +148,8 @@ const Microphone = () => {
|
|
|
105
148
|
useEffect(() => {
|
|
106
149
|
if (running && transcriber?.isOpen) {
|
|
107
150
|
transcriber?.startChunksRecording();
|
|
108
|
-
log.info('transcriber startChunksRecording');
|
|
109
151
|
} else if (!running) {
|
|
110
152
|
transcriber?.stopChunksRecording();
|
|
111
|
-
log.info('transcriber stopChunksRecording');
|
|
112
153
|
}
|
|
113
154
|
}, [transcriber, running, isOpen]);
|
|
114
155
|
|
|
@@ -141,12 +182,12 @@ const AudioFile = ({ queueDxn, audioUrl }: { queueDxn: DXN; audioUrl: string; tr
|
|
|
141
182
|
}, [audio, running]);
|
|
142
183
|
|
|
143
184
|
// Transcriber.
|
|
144
|
-
const queue = useQueue<
|
|
145
|
-
const model = useQueueModelAdapter(renderMarkdown, queue);
|
|
185
|
+
const queue = useQueue<DataType.Message>(queueDxn, { pollInterval: 500 });
|
|
186
|
+
const model = useQueueModelAdapter(renderMarkdown([]), queue);
|
|
146
187
|
const handleSegments = useCallback<TranscriberParams['onSegments']>(
|
|
147
|
-
async (
|
|
148
|
-
const
|
|
149
|
-
queue?.append([
|
|
188
|
+
async (blocks) => {
|
|
189
|
+
const message = create(DataType.Message, { sender: { name: 'You' }, created: new Date().toISOString(), blocks });
|
|
190
|
+
void queue?.append([message]);
|
|
150
191
|
},
|
|
151
192
|
[queue],
|
|
152
193
|
);
|
|
@@ -187,14 +228,19 @@ const meta: Meta<typeof AudioFile> = {
|
|
|
187
228
|
withPluginManager({
|
|
188
229
|
plugins: [
|
|
189
230
|
ThemePlugin({ tx: defaultTx }),
|
|
231
|
+
StorybookLayoutPlugin(),
|
|
190
232
|
ClientPlugin({
|
|
191
|
-
types: [TestItem],
|
|
233
|
+
types: [TestItem, DataType.Person, DataType.Organization, Testing.DocumentType],
|
|
192
234
|
onClientInitialized: async (_, client) => {
|
|
193
235
|
await client.halo.createIdentity();
|
|
236
|
+
await client.spaces.waitUntilReady();
|
|
237
|
+
await client.spaces.default.waitUntilReady();
|
|
238
|
+
await seedTestData(client.spaces.default);
|
|
194
239
|
},
|
|
195
240
|
}),
|
|
196
241
|
SpacePlugin(),
|
|
197
242
|
SettingsPlugin(),
|
|
243
|
+
PreviewPlugin(),
|
|
198
244
|
IntentPlugin(),
|
|
199
245
|
TranscriptionPlugin(),
|
|
200
246
|
],
|
|
@@ -218,26 +264,30 @@ const meta: Meta<typeof AudioFile> = {
|
|
|
218
264
|
// ],
|
|
219
265
|
}),
|
|
220
266
|
withTheme,
|
|
221
|
-
withLayout({
|
|
222
|
-
tooltips: true,
|
|
223
|
-
fullscreen: true,
|
|
224
|
-
classNames: 'justify-center',
|
|
225
|
-
}),
|
|
267
|
+
withLayout({ fullscreen: true, classNames: 'justify-center' }),
|
|
226
268
|
],
|
|
227
269
|
};
|
|
228
270
|
|
|
229
271
|
export default meta;
|
|
230
272
|
|
|
231
|
-
|
|
273
|
+
export const Default: StoryObj<typeof Microphone> = {
|
|
274
|
+
render: Microphone,
|
|
275
|
+
args: {
|
|
276
|
+
entityExtraction: false,
|
|
277
|
+
},
|
|
278
|
+
};
|
|
232
279
|
|
|
233
|
-
export const
|
|
280
|
+
export const EntityExtraction: StoryObj<typeof Microphone> = {
|
|
234
281
|
render: Microphone,
|
|
282
|
+
args: {
|
|
283
|
+
entityExtraction: true,
|
|
284
|
+
},
|
|
235
285
|
};
|
|
236
286
|
|
|
237
|
-
export const File:
|
|
287
|
+
export const File: StoryObj<typeof AudioFile> = {
|
|
238
288
|
render: AudioFile,
|
|
239
289
|
args: {
|
|
240
|
-
queueDxn:
|
|
290
|
+
queueDxn: createQueueDxn(),
|
|
241
291
|
// https://learnenglish.britishcouncil.org/general-english/audio-zone/living-london
|
|
242
292
|
transcriptUrl: 'https://dxos.network/audio-london.txt',
|
|
243
293
|
audioUrl: 'https://dxos.network/audio-london.m4a',
|
|
@@ -2,31 +2,96 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { describe, test } from 'vitest';
|
|
5
|
+
import { describe, test, expect } from 'vitest';
|
|
6
6
|
|
|
7
7
|
import { AIServiceEdgeClient } from '@dxos/assistant';
|
|
8
8
|
import { AI_SERVICE_ENDPOINT } from '@dxos/assistant/testing';
|
|
9
9
|
import { log } from '@dxos/log';
|
|
10
|
+
import { createTestData } from '@dxos/schema/testing';
|
|
11
|
+
import { range } from '@dxos/util';
|
|
10
12
|
|
|
11
|
-
import {
|
|
12
|
-
import * as TestData from '../testing/test-data';
|
|
13
|
+
import { processTranscriptMessage, postprocessText } from './entity-extraction';
|
|
13
14
|
|
|
14
15
|
const aiService = new AIServiceEdgeClient({
|
|
15
16
|
endpoint: AI_SERVICE_ENDPOINT.REMOTE,
|
|
16
17
|
});
|
|
17
18
|
|
|
18
19
|
describe.skip('EntityExtraction', { timeout: 180_000 }, () => {
|
|
19
|
-
test('should process a transcript block', async () => {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
test.skip('should process a transcript block', async () => {
|
|
21
|
+
const { transcriptMessages, documents, contacts } = await createTestData();
|
|
22
|
+
|
|
23
|
+
log.info('context', { documents, contacts });
|
|
24
|
+
|
|
25
|
+
for (const message of transcriptMessages) {
|
|
26
|
+
log.info('input', message);
|
|
27
|
+
const { message: enhancedMessage } = await processTranscriptMessage({
|
|
28
|
+
message,
|
|
29
|
+
aiService,
|
|
30
|
+
context: {
|
|
31
|
+
objects: [...documents, ...Object.values(contacts)],
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
log.info('output', enhancedMessage);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test.only('computational irreducibility', async () => {
|
|
39
|
+
const { transcriptWoflram, documents, contacts } = await createTestData();
|
|
40
|
+
|
|
41
|
+
log.info('context', { documents, contacts });
|
|
42
|
+
const message = transcriptWoflram[0];
|
|
43
|
+
log.info('input', message);
|
|
44
|
+
|
|
45
|
+
await Promise.all(
|
|
46
|
+
range(10).map(async () => {
|
|
47
|
+
const { message: enhancedMessage, timeElapsed } = await processTranscriptMessage({
|
|
48
|
+
message,
|
|
49
|
+
aiService,
|
|
50
|
+
context: {
|
|
51
|
+
objects: [...documents, ...Object.values(contacts)],
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
log.info('output', { message: enhancedMessage.blocks[0], timeElapsed });
|
|
55
|
+
}),
|
|
56
|
+
);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test('org and document linking', async () => {
|
|
60
|
+
const { transcriptJosiah, documents, contacts, organizations } = await createTestData();
|
|
61
|
+
|
|
62
|
+
log.info('context', { contacts, organizations, documents });
|
|
63
|
+
|
|
64
|
+
for (const message of transcriptJosiah) {
|
|
65
|
+
log.info('input', message);
|
|
66
|
+
|
|
67
|
+
const { message: enhancedMessage } = await processTranscriptMessage({
|
|
68
|
+
message,
|
|
24
69
|
aiService,
|
|
25
70
|
context: {
|
|
26
|
-
objects: [...
|
|
71
|
+
objects: [...documents, ...Object.values(contacts), ...Object.values(organizations)],
|
|
27
72
|
},
|
|
28
73
|
});
|
|
29
|
-
log.info('output',
|
|
74
|
+
log.info('output', enhancedMessage);
|
|
30
75
|
}
|
|
31
76
|
});
|
|
32
77
|
});
|
|
78
|
+
|
|
79
|
+
describe('postprocessText', () => {
|
|
80
|
+
test('should replace quotes with DXN references', () => {
|
|
81
|
+
const quotes = {
|
|
82
|
+
references: [{ quote: 'computational irreducibility', id: '01JTG9JW11XGWJZ32AW8ET93D1' }],
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
expect(postprocessText('This is a computational irreducibility test.', quotes)).toBe(
|
|
86
|
+
'This is a [computational irreducibility][dxn:echo:@:01JTG9JW11XGWJZ32AW8ET93D1] test.',
|
|
87
|
+
);
|
|
88
|
+
expect(
|
|
89
|
+
postprocessText(
|
|
90
|
+
"And what I'd like to talk today about is Steven Wolfram's concept of a computational irreducibility.",
|
|
91
|
+
quotes,
|
|
92
|
+
),
|
|
93
|
+
).toBe(
|
|
94
|
+
"And what I'd like to talk today about is Steven Wolfram's concept of a [computational irreducibility][dxn:echo:@:01JTG9JW11XGWJZ32AW8ET93D1].",
|
|
95
|
+
);
|
|
96
|
+
});
|
|
97
|
+
});
|