@dxos/plugin-transcription 0.8.2-main.36232bc → 0.8.2-main.5ca3450
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-2VFHUHLE.mjs → TranscriptContainer-3LU3XBEB.mjs} +2 -2
- package/dist/lib/browser/{app-graph-builder-TDP6PYV6.mjs → app-graph-builder-YXELPN6F.mjs} +19 -20
- package/dist/lib/browser/app-graph-builder-YXELPN6F.mjs.map +7 -0
- package/dist/lib/browser/{chunk-KSUYWWIU.mjs → chunk-GWY2Q2NE.mjs} +6 -6
- package/dist/lib/browser/chunk-GWY2Q2NE.mjs.map +7 -0
- package/dist/lib/browser/{chunk-NFVDICSJ.mjs → chunk-HNIKXVCG.mjs} +8 -7
- package/dist/lib/browser/chunk-HNIKXVCG.mjs.map +7 -0
- package/dist/lib/browser/{chunk-O6RY7FNK.mjs → chunk-HRDAILQX.mjs} +2 -2
- package/dist/lib/browser/{chunk-YRWBY6UK.mjs → chunk-TGOKX32G.mjs} +17 -15
- package/dist/lib/browser/chunk-TGOKX32G.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +6 -6
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/{intent-resolver-ZWKYRFE7.mjs → intent-resolver-BBB3DWV4.mjs} +2 -2
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/{react-surface-F32UNCKZ.mjs → react-surface-R277DACJ.mjs} +4 -4
- package/dist/lib/browser/{settings-6YAHKVKX.mjs → settings-I226DZ27.mjs} +2 -2
- package/dist/lib/browser/{transcriber-MSBS4VBI.mjs → transcriber-QRSS6X6S.mjs} +3 -3
- package/dist/lib/browser/types/index.mjs +1 -1
- package/dist/lib/node/{TranscriptContainer-E2D7PKO3.cjs → TranscriptContainer-DICOMZLM.cjs} +7 -7
- package/dist/lib/node/{TranscriptContainer-E2D7PKO3.cjs.map → TranscriptContainer-DICOMZLM.cjs.map} +2 -2
- package/dist/lib/node/{app-graph-builder-W4VDMVGV.cjs → app-graph-builder-I6LYVIYY.cjs} +28 -29
- package/dist/lib/node/app-graph-builder-I6LYVIYY.cjs.map +7 -0
- package/dist/lib/node/{chunk-IXU57SCA.cjs → chunk-34WFY7M7.cjs} +18 -16
- package/dist/lib/node/chunk-34WFY7M7.cjs.map +7 -0
- package/dist/lib/node/{chunk-NBC6V3M2.cjs → chunk-4JOJCZPJ.cjs} +11 -10
- package/dist/lib/node/chunk-4JOJCZPJ.cjs.map +7 -0
- package/dist/lib/node/{chunk-TJMZ26GS.cjs → chunk-K553L7CZ.cjs} +5 -5
- package/dist/lib/node/{chunk-7XIIUVN3.cjs → chunk-RK4BEN5E.cjs} +9 -9
- package/dist/lib/node/chunk-RK4BEN5E.cjs.map +7 -0
- package/dist/lib/node/index.cjs +27 -27
- package/dist/lib/node/index.cjs.map +3 -3
- package/dist/lib/node/{intent-resolver-RM4JOCDV.cjs → intent-resolver-7XY3WITN.cjs} +7 -7
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/{react-surface-YQHBGPOC.cjs → react-surface-HUSWAORU.cjs} +10 -10
- package/dist/lib/node/{settings-ZMB4XRWS.cjs → settings-NDMU3EWQ.cjs} +7 -7
- package/dist/lib/node/{transcriber-55OE4X6I.cjs → transcriber-UZJMG44C.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-5N3BSK2S.mjs → TranscriptContainer-K4E4P5T6.mjs} +2 -2
- package/dist/lib/node-esm/{app-graph-builder-DDDVKUHS.mjs → app-graph-builder-6FY2UQOH.mjs} +19 -20
- package/dist/lib/node-esm/app-graph-builder-6FY2UQOH.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-HZBSWUJH.mjs → chunk-3I7AC3D3.mjs} +2 -2
- package/dist/lib/node-esm/{chunk-4RMJO6QQ.mjs → chunk-6C34FO4C.mjs} +8 -7
- package/dist/lib/node-esm/chunk-6C34FO4C.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-UWF6LM27.mjs → chunk-CKANLRS4.mjs} +6 -6
- package/dist/lib/node-esm/chunk-CKANLRS4.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-OS2ITZUL.mjs → chunk-KUQ3ZTRX.mjs} +17 -15
- package/dist/lib/node-esm/chunk-KUQ3ZTRX.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +6 -6
- package/dist/lib/node-esm/index.mjs.map +3 -3
- package/dist/lib/node-esm/{intent-resolver-HDRFXMKP.mjs → intent-resolver-ACGAPLDZ.mjs} +2 -2
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/{react-surface-DRDNXTFZ.mjs → react-surface-G2OY4MWL.mjs} +4 -4
- package/dist/lib/node-esm/{settings-I35TVDUG.mjs → settings-O7X2UQQG.mjs} +2 -2
- package/dist/lib/node-esm/{transcriber-HH7EMCGH.mjs → transcriber-NVVFH7IF.mjs} +3 -3
- package/dist/lib/node-esm/types/index.mjs +1 -1
- package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
- 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/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 +10 -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 +51 -49
- package/src/TranscriptionPlugin.tsx +2 -2
- package/src/capabilities/app-graph-builder.ts +10 -10
- package/src/components/Transcript/Transcript.stories.tsx +5 -5
- package/src/components/Transcript/Transcript.tsx +10 -4
- 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 +14 -8
- package/src/entity-extraction/entity-extraction.test.ts +23 -4
- package/src/entity-extraction/entity-extraction.ts +11 -6
- package/src/model/model.test.ts +14 -10
- package/src/testing/testing.ts +34 -21
- 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 +12 -10
- package/dist/lib/browser/app-graph-builder-TDP6PYV6.mjs.map +0 -7
- package/dist/lib/browser/chunk-KSUYWWIU.mjs.map +0 -7
- package/dist/lib/browser/chunk-NFVDICSJ.mjs.map +0 -7
- package/dist/lib/browser/chunk-YRWBY6UK.mjs.map +0 -7
- package/dist/lib/node/app-graph-builder-W4VDMVGV.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-NBC6V3M2.cjs.map +0 -7
- package/dist/lib/node-esm/app-graph-builder-DDDVKUHS.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-4RMJO6QQ.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/browser/{TranscriptContainer-2VFHUHLE.mjs.map → TranscriptContainer-3LU3XBEB.mjs.map} +0 -0
- /package/dist/lib/browser/{chunk-O6RY7FNK.mjs.map → chunk-HRDAILQX.mjs.map} +0 -0
- /package/dist/lib/browser/{intent-resolver-ZWKYRFE7.mjs.map → intent-resolver-BBB3DWV4.mjs.map} +0 -0
- /package/dist/lib/browser/{react-surface-F32UNCKZ.mjs.map → react-surface-R277DACJ.mjs.map} +0 -0
- /package/dist/lib/browser/{settings-6YAHKVKX.mjs.map → settings-I226DZ27.mjs.map} +0 -0
- /package/dist/lib/browser/{transcriber-MSBS4VBI.mjs.map → transcriber-QRSS6X6S.mjs.map} +0 -0
- /package/dist/lib/node/{chunk-TJMZ26GS.cjs.map → chunk-K553L7CZ.cjs.map} +0 -0
- /package/dist/lib/node/{intent-resolver-RM4JOCDV.cjs.map → intent-resolver-7XY3WITN.cjs.map} +0 -0
- /package/dist/lib/node/{react-surface-YQHBGPOC.cjs.map → react-surface-HUSWAORU.cjs.map} +0 -0
- /package/dist/lib/node/{settings-ZMB4XRWS.cjs.map → settings-NDMU3EWQ.cjs.map} +0 -0
- /package/dist/lib/node/{transcriber-55OE4X6I.cjs.map → transcriber-UZJMG44C.cjs.map} +0 -0
- /package/dist/lib/node-esm/{TranscriptContainer-5N3BSK2S.mjs.map → TranscriptContainer-K4E4P5T6.mjs.map} +0 -0
- /package/dist/lib/node-esm/{chunk-HZBSWUJH.mjs.map → chunk-3I7AC3D3.mjs.map} +0 -0
- /package/dist/lib/node-esm/{intent-resolver-HDRFXMKP.mjs.map → intent-resolver-ACGAPLDZ.mjs.map} +0 -0
- /package/dist/lib/node-esm/{react-surface-DRDNXTFZ.mjs.map → react-surface-G2OY4MWL.mjs.map} +0 -0
- /package/dist/lib/node-esm/{settings-I35TVDUG.mjs.map → settings-O7X2UQQG.mjs.map} +0 -0
- /package/dist/lib/node-esm/{transcriber-HH7EMCGH.mjs.map → transcriber-NVVFH7IF.mjs.map} +0 -0
|
@@ -20,7 +20,7 @@ import { useMembers, useSpace } from '@dxos/react-client/echo';
|
|
|
20
20
|
import { IconButton, Toolbar } from '@dxos/react-ui';
|
|
21
21
|
import { SyntaxHighlighter } from '@dxos/react-ui-syntax-highlighter';
|
|
22
22
|
import { defaultTx } from '@dxos/react-ui-theme';
|
|
23
|
-
import {
|
|
23
|
+
import { DataType } from '@dxos/schema';
|
|
24
24
|
import { Testing } from '@dxos/schema/testing';
|
|
25
25
|
import { withLayout } from '@dxos/storybook-utils';
|
|
26
26
|
|
|
@@ -69,7 +69,7 @@ const TranscriptContainer: FC<
|
|
|
69
69
|
);
|
|
70
70
|
};
|
|
71
71
|
|
|
72
|
-
type StoryProps = { messages?:
|
|
72
|
+
type StoryProps = { messages?: DataType.Message[] } & Pick<TranscriptProps, 'ignoreAttention' | 'attendableId'>;
|
|
73
73
|
|
|
74
74
|
/**
|
|
75
75
|
* Basic story mutates array of messages.
|
|
@@ -78,11 +78,11 @@ const BasicStory = ({ messages: initialMessages = [], ...props }: StoryProps) =>
|
|
|
78
78
|
const [reset, setReset] = useState({});
|
|
79
79
|
const builder = useMemo(() => new MessageBuilder(), []);
|
|
80
80
|
const model = useMemo(
|
|
81
|
-
() => new SerializationModel<
|
|
81
|
+
() => new SerializationModel<DataType.Message>(renderMarkdown([]), initialMessages),
|
|
82
82
|
[initialMessages, reset],
|
|
83
83
|
);
|
|
84
84
|
const [running, setRunning] = useState(true);
|
|
85
|
-
const [currentMessage, setCurrentMessage] = useState<
|
|
85
|
+
const [currentMessage, setCurrentMessage] = useState<DataType.Message | null>(null);
|
|
86
86
|
useEffect(() => {
|
|
87
87
|
if (!running) {
|
|
88
88
|
return;
|
|
@@ -186,7 +186,7 @@ const meta: Meta<typeof QueueStory> = {
|
|
|
186
186
|
ThemePlugin({ tx: defaultTx }),
|
|
187
187
|
StorybookLayoutPlugin(),
|
|
188
188
|
ClientPlugin({
|
|
189
|
-
types: [TestItem, Testing.DocumentType,
|
|
189
|
+
types: [TestItem, Testing.DocumentType, DataType.Person, DataType.Organization],
|
|
190
190
|
onClientInitialized: async (_, client) => {
|
|
191
191
|
await client.halo.createIdentity();
|
|
192
192
|
},
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
useTextEditor,
|
|
19
19
|
} from '@dxos/react-ui-editor';
|
|
20
20
|
import { mx } from '@dxos/react-ui-theme';
|
|
21
|
-
import { type
|
|
21
|
+
import { type DataType } from '@dxos/schema';
|
|
22
22
|
import { isNotFalsy } from '@dxos/util';
|
|
23
23
|
|
|
24
24
|
import { transcript } from './transcript-extension';
|
|
@@ -27,7 +27,7 @@ import { type TranscriptType } from '../../types';
|
|
|
27
27
|
|
|
28
28
|
export const renderMarkdown =
|
|
29
29
|
(identities: Identity[]) =>
|
|
30
|
-
(message:
|
|
30
|
+
(message: DataType.Message, index: number, debug = false): string[] => {
|
|
31
31
|
if (message.sender.role === 'assistant') {
|
|
32
32
|
// Start/stop block.
|
|
33
33
|
return [message.blocks.find((block) => block.type === 'transcription')?.text ?? '', ''];
|
|
@@ -53,7 +53,7 @@ export const renderMarkdown =
|
|
|
53
53
|
export type TranscriptProps = ThemedClassName<{
|
|
54
54
|
transcript?: TranscriptType;
|
|
55
55
|
space?: Space;
|
|
56
|
-
model: SerializationModel<
|
|
56
|
+
model: SerializationModel<DataType.Message>;
|
|
57
57
|
// TODO(wittjosiah): Move to container.
|
|
58
58
|
attendableId?: string;
|
|
59
59
|
ignoreAttention?: boolean;
|
|
@@ -90,5 +90,11 @@ export const Transcript = ({
|
|
|
90
90
|
};
|
|
91
91
|
}, [space, model]);
|
|
92
92
|
|
|
93
|
-
return
|
|
93
|
+
return (
|
|
94
|
+
<div
|
|
95
|
+
ref={parentRef}
|
|
96
|
+
className={mx('flex grow overflow-hidden', editorWidth, classNames)}
|
|
97
|
+
data-popover-collision-boundary={true}
|
|
98
|
+
/>
|
|
99
|
+
);
|
|
94
100
|
};
|
|
@@ -3,11 +3,12 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { intervalToDuration } from 'date-fns/intervalToDuration';
|
|
6
|
+
import { Schema } from 'effect';
|
|
6
7
|
import { yieldOrContinue } from 'main-thread-scheduling';
|
|
7
8
|
import React, { type FC, useCallback, useEffect, useMemo, useRef, useState, type WheelEvent } from 'react';
|
|
8
9
|
import { type OnResizeCallback, useResizeDetector } from 'react-resize-detector';
|
|
9
10
|
|
|
10
|
-
import {
|
|
11
|
+
import { Type } from '@dxos/echo';
|
|
11
12
|
import { IconButton, type ThemedClassName, useTranslation } from '@dxos/react-ui';
|
|
12
13
|
import { useAttention } from '@dxos/react-ui-attention';
|
|
13
14
|
import {
|
|
@@ -25,25 +26,30 @@ import { TRANSCRIPTION_PLUGIN } from '../../../meta';
|
|
|
25
26
|
/**
|
|
26
27
|
* Transcription fragment.
|
|
27
28
|
*/
|
|
28
|
-
const TranscriptSegment =
|
|
29
|
+
const TranscriptSegment = Schema.Struct({
|
|
29
30
|
// TODO(burdon): TS from service is not Unix TS (x1000).
|
|
30
|
-
started:
|
|
31
|
-
text:
|
|
31
|
+
started: Schema.String,
|
|
32
|
+
text: Schema.String,
|
|
32
33
|
});
|
|
33
34
|
|
|
34
|
-
type TranscriptSegment =
|
|
35
|
+
type TranscriptSegment = Schema.Schema.Type<typeof TranscriptSegment>;
|
|
35
36
|
|
|
36
37
|
/**
|
|
37
38
|
* Transcription block (from single speaker).
|
|
38
39
|
*/
|
|
39
|
-
const TranscriptBlock =
|
|
40
|
-
id:
|
|
41
|
-
authorName:
|
|
42
|
-
authorHue:
|
|
43
|
-
segments:
|
|
44
|
-
}).pipe(
|
|
45
|
-
|
|
46
|
-
|
|
40
|
+
const TranscriptBlock = Schema.Struct({
|
|
41
|
+
id: Schema.String,
|
|
42
|
+
authorName: Schema.optional(Schema.String), // TODO(burdon): Replace with identityDid.
|
|
43
|
+
authorHue: Schema.optional(Schema.String), // TOOD(burdon): Remove.
|
|
44
|
+
segments: Schema.Array(TranscriptSegment),
|
|
45
|
+
}).pipe(
|
|
46
|
+
Type.def({
|
|
47
|
+
typename: 'dxos.org/type/TranscriptBlock',
|
|
48
|
+
version: '0.1.0',
|
|
49
|
+
}),
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
type TranscriptBlock = Schema.Schema.Type<typeof TranscriptBlock>;
|
|
47
53
|
|
|
48
54
|
// TODO(burdon): Actions (e.g., mark, summarize, translate, label, delete).
|
|
49
55
|
|
|
@@ -9,7 +9,7 @@ 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
|
|
12
|
+
import { type DataType } from '@dxos/schema';
|
|
13
13
|
|
|
14
14
|
import { DocumentAdapter, type SerializationModel } from '../../model';
|
|
15
15
|
|
|
@@ -17,7 +17,7 @@ import { DocumentAdapter, type SerializationModel } from '../../model';
|
|
|
17
17
|
* Data structure that maps Chunks queue to lines with transcript state.
|
|
18
18
|
*/
|
|
19
19
|
export type TranscriptOptions = {
|
|
20
|
-
model: SerializationModel<
|
|
20
|
+
model: SerializationModel<DataType.Message>;
|
|
21
21
|
started?: Date;
|
|
22
22
|
renderButton?: RenderCallback<{ onClick: () => void }>;
|
|
23
23
|
};
|
|
@@ -213,7 +213,7 @@ class TimestampMarker extends GutterMarker {
|
|
|
213
213
|
}
|
|
214
214
|
}
|
|
215
215
|
|
|
216
|
-
const getStartTime = (started?: Date, message?:
|
|
216
|
+
const getStartTime = (started?: Date, message?: DataType.Message): Date | undefined => {
|
|
217
217
|
if (started) {
|
|
218
218
|
return started;
|
|
219
219
|
}
|
|
@@ -7,7 +7,7 @@ import React, { type FC } from 'react';
|
|
|
7
7
|
import { fullyQualifiedId, getSpace } from '@dxos/client/echo';
|
|
8
8
|
import { useMembers, useQueue } from '@dxos/react-client/echo';
|
|
9
9
|
import { StackItem } from '@dxos/react-ui-stack';
|
|
10
|
-
import { type
|
|
10
|
+
import { type DataType } from '@dxos/schema';
|
|
11
11
|
|
|
12
12
|
import { Transcript, renderMarkdown } from './Transcript';
|
|
13
13
|
import { useQueueModelAdapter } from '../hooks';
|
|
@@ -17,7 +17,7 @@ export const TranscriptionContainer: FC<{ role: string; transcript: TranscriptTy
|
|
|
17
17
|
const attendableId = fullyQualifiedId(transcript);
|
|
18
18
|
const space = getSpace(transcript);
|
|
19
19
|
const members = useMembers(space?.key).map((member) => member.identity);
|
|
20
|
-
const queue = useQueue<
|
|
20
|
+
const queue = useQueue<DataType.Message>(transcript.queue.dxn, { pollInterval: 1_000 });
|
|
21
21
|
const model = useQueueModelAdapter(renderMarkdown(members), queue);
|
|
22
22
|
|
|
23
23
|
return (
|
|
@@ -33,7 +33,7 @@ import { createQueueDxn, useQueue, useSpace } from '@dxos/react-client/echo';
|
|
|
33
33
|
import { IconButton, Toolbar } from '@dxos/react-ui';
|
|
34
34
|
import { ScrollContainer } from '@dxos/react-ui-components';
|
|
35
35
|
import { defaultTx } from '@dxos/react-ui-theme';
|
|
36
|
-
import {
|
|
36
|
+
import { DataType } from '@dxos/schema';
|
|
37
37
|
import { seedTestData, Testing } from '@dxos/schema/testing';
|
|
38
38
|
import { withLayout, withTheme } from '@dxos/storybook-utils';
|
|
39
39
|
|
|
@@ -46,7 +46,7 @@ import { TestItem } from '../testing';
|
|
|
46
46
|
import { type TranscriberParams } from '../transcriber';
|
|
47
47
|
|
|
48
48
|
const TranscriptionStory: FC<{
|
|
49
|
-
model: SerializationModel<
|
|
49
|
+
model: SerializationModel<DataType.Message>;
|
|
50
50
|
running: boolean;
|
|
51
51
|
onRunningChange: Dispatch<SetStateAction<boolean>>;
|
|
52
52
|
}> = ({ model, running, onRunningChange }) => {
|
|
@@ -81,14 +81,14 @@ const Microphone = ({ entityExtraction }: { entityExtraction?: boolean }) => {
|
|
|
81
81
|
|
|
82
82
|
// Queue.
|
|
83
83
|
const queueDxn = useMemo(() => createQueueDxn(), []);
|
|
84
|
-
const queue = useMemo(() => new MemoryQueue<
|
|
84
|
+
const queue = useMemo(() => new MemoryQueue<DataType.Message>(queueDxn), [queueDxn]);
|
|
85
85
|
const model = useQueueModelAdapter(renderMarkdown([]), queue);
|
|
86
86
|
const space = useSpace();
|
|
87
87
|
|
|
88
88
|
// Transcriber.
|
|
89
89
|
const handleSegments = useCallback<TranscriberParams['onSegments']>(
|
|
90
90
|
async (blocks) => {
|
|
91
|
-
const message = create(
|
|
91
|
+
const message = create(DataType.Message, { sender: { name: 'You' }, created: new Date().toISOString(), blocks });
|
|
92
92
|
|
|
93
93
|
if (entityExtraction) {
|
|
94
94
|
if (!space) {
|
|
@@ -97,7 +97,13 @@ const Microphone = ({ entityExtraction }: { entityExtraction?: boolean }) => {
|
|
|
97
97
|
}
|
|
98
98
|
// TODO(dmaretskyi): Move to vector search index.
|
|
99
99
|
const { objects } = await space.db
|
|
100
|
-
.query(
|
|
100
|
+
.query(
|
|
101
|
+
Filter.or(
|
|
102
|
+
Filter.schema(DataType.Person),
|
|
103
|
+
Filter.schema(DataType.Organization),
|
|
104
|
+
Filter.schema(Testing.DocumentType),
|
|
105
|
+
),
|
|
106
|
+
)
|
|
101
107
|
.run();
|
|
102
108
|
|
|
103
109
|
log.info('context', { objects });
|
|
@@ -176,11 +182,11 @@ const AudioFile = ({ queueDxn, audioUrl }: { queueDxn: DXN; audioUrl: string; tr
|
|
|
176
182
|
}, [audio, running]);
|
|
177
183
|
|
|
178
184
|
// Transcriber.
|
|
179
|
-
const queue = useQueue<
|
|
185
|
+
const queue = useQueue<DataType.Message>(queueDxn, { pollInterval: 500 });
|
|
180
186
|
const model = useQueueModelAdapter(renderMarkdown([]), queue);
|
|
181
187
|
const handleSegments = useCallback<TranscriberParams['onSegments']>(
|
|
182
188
|
async (blocks) => {
|
|
183
|
-
const message = create(
|
|
189
|
+
const message = create(DataType.Message, { sender: { name: 'You' }, created: new Date().toISOString(), blocks });
|
|
184
190
|
void queue?.append([message]);
|
|
185
191
|
},
|
|
186
192
|
[queue],
|
|
@@ -224,7 +230,7 @@ const meta: Meta<typeof AudioFile> = {
|
|
|
224
230
|
ThemePlugin({ tx: defaultTx }),
|
|
225
231
|
StorybookLayoutPlugin(),
|
|
226
232
|
ClientPlugin({
|
|
227
|
-
types: [TestItem,
|
|
233
|
+
types: [TestItem, DataType.Person, DataType.Organization, Testing.DocumentType],
|
|
228
234
|
onClientInitialized: async (_, client) => {
|
|
229
235
|
await client.halo.createIdentity();
|
|
230
236
|
await client.spaces.waitUntilReady();
|
|
@@ -17,7 +17,7 @@ const aiService = new AIServiceEdgeClient({
|
|
|
17
17
|
});
|
|
18
18
|
|
|
19
19
|
describe.skip('EntityExtraction', { timeout: 180_000 }, () => {
|
|
20
|
-
test('should process a transcript block', async () => {
|
|
20
|
+
test.skip('should process a transcript block', async () => {
|
|
21
21
|
const { transcriptMessages, documents, contacts } = await createTestData();
|
|
22
22
|
|
|
23
23
|
log.info('context', { documents, contacts });
|
|
@@ -35,11 +35,11 @@ describe.skip('EntityExtraction', { timeout: 180_000 }, () => {
|
|
|
35
35
|
}
|
|
36
36
|
});
|
|
37
37
|
|
|
38
|
-
test.
|
|
39
|
-
const {
|
|
38
|
+
test.only('computational irreducibility', async () => {
|
|
39
|
+
const { transcriptWoflram, documents, contacts } = await createTestData();
|
|
40
40
|
|
|
41
41
|
log.info('context', { documents, contacts });
|
|
42
|
-
const message =
|
|
42
|
+
const message = transcriptWoflram[0];
|
|
43
43
|
log.info('input', message);
|
|
44
44
|
|
|
45
45
|
await Promise.all(
|
|
@@ -55,6 +55,25 @@ describe.skip('EntityExtraction', { timeout: 180_000 }, () => {
|
|
|
55
55
|
}),
|
|
56
56
|
);
|
|
57
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,
|
|
69
|
+
aiService,
|
|
70
|
+
context: {
|
|
71
|
+
objects: [...documents, ...Object.values(contacts), ...Object.values(organizations)],
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
log.info('output', enhancedMessage);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
58
77
|
});
|
|
59
78
|
|
|
60
79
|
describe('postprocessText', () => {
|
|
@@ -8,14 +8,15 @@ import { createTemplate, Message, structuredOutputParser } from '@dxos/artifact'
|
|
|
8
8
|
import type { AIServiceClient } from '@dxos/assistant';
|
|
9
9
|
import { MixedStreamParser } from '@dxos/assistant';
|
|
10
10
|
import { asyncTimeout } from '@dxos/async';
|
|
11
|
-
import { type BaseEchoObject, create } from '@dxos/echo-schema';
|
|
11
|
+
import { type BaseEchoObject, create, ObjectId } from '@dxos/echo-schema';
|
|
12
|
+
import { DXN } from '@dxos/keys';
|
|
12
13
|
import { log } from '@dxos/log';
|
|
13
|
-
import {
|
|
14
|
+
import { DataType } from '@dxos/schema';
|
|
14
15
|
|
|
15
16
|
import SYSTEM_PROMPT from './system-prompt.tpl?raw';
|
|
16
17
|
|
|
17
18
|
type ProcessTranscriptMessageParams = {
|
|
18
|
-
message:
|
|
19
|
+
message: DataType.Message;
|
|
19
20
|
aiService: AIServiceClient;
|
|
20
21
|
context: {
|
|
21
22
|
objects?: BaseEchoObject[];
|
|
@@ -37,7 +38,7 @@ type ProcessTranscriptMessageParams = {
|
|
|
37
38
|
};
|
|
38
39
|
|
|
39
40
|
type ProcessTranscriptMessageResult = {
|
|
40
|
-
message:
|
|
41
|
+
message: DataType.Message;
|
|
41
42
|
timeElapsed: number;
|
|
42
43
|
};
|
|
43
44
|
|
|
@@ -97,7 +98,7 @@ export const processTranscriptMessage = async (
|
|
|
97
98
|
log.info('entity extraction result', { refs: result.references });
|
|
98
99
|
|
|
99
100
|
return {
|
|
100
|
-
message: create(
|
|
101
|
+
message: create(DataType.Message, {
|
|
101
102
|
...params.message,
|
|
102
103
|
blocks: params.message.blocks.map((block, i) =>
|
|
103
104
|
block.type !== 'transcription'
|
|
@@ -136,9 +137,13 @@ export const processTranscriptMessage = async (
|
|
|
136
137
|
// TODO(dmaretskyi): Lookup and verifiy ids from provided context.
|
|
137
138
|
export const postprocessText = (text: string, quotes: ReferencedQuotes) => {
|
|
138
139
|
for (const quote of quotes.references) {
|
|
140
|
+
if (!ObjectId.isValid(quote.id)) {
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
|
|
139
144
|
// Use a case-insensitive regular expression to replace the quote
|
|
140
145
|
const regex = new RegExp(quote.quote.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'gi');
|
|
141
|
-
text = text.replace(regex, `[${quote.quote}][
|
|
146
|
+
text = text.replace(regex, `[${quote.quote}][${DXN.fromLocalObjectId(quote.id).toString()}]`);
|
|
142
147
|
}
|
|
143
148
|
return text;
|
|
144
149
|
};
|
package/src/model/model.test.ts
CHANGED
|
@@ -5,11 +5,15 @@
|
|
|
5
5
|
import { EditorView } from '@codemirror/view';
|
|
6
6
|
import { describe, test } from 'vitest';
|
|
7
7
|
|
|
8
|
-
import { type
|
|
8
|
+
import { type DataType } from '@dxos/schema';
|
|
9
9
|
|
|
10
10
|
import { SerializationModel, DocumentAdapter, type ChunkRenderer } from './model';
|
|
11
11
|
|
|
12
|
-
const blockToMarkdown: ChunkRenderer<
|
|
12
|
+
const blockToMarkdown: ChunkRenderer<DataType.Message> = (
|
|
13
|
+
message: DataType.Message,
|
|
14
|
+
index: number,
|
|
15
|
+
debug = true,
|
|
16
|
+
): string[] => {
|
|
13
17
|
return [
|
|
14
18
|
`###### ${message.sender.name}`,
|
|
15
19
|
...message.blocks.filter((block) => block.type === 'transcription').map((block) => block.text),
|
|
@@ -21,12 +25,12 @@ const createDate = () => new Date().toISOString();
|
|
|
21
25
|
|
|
22
26
|
describe('SerializationModel', () => {
|
|
23
27
|
test('basic', ({ expect }) => {
|
|
24
|
-
const model = new SerializationModel<
|
|
28
|
+
const model = new SerializationModel<DataType.Message>(blockToMarkdown);
|
|
25
29
|
expect(model.chunks.length).to.eq(0);
|
|
26
30
|
expect(model.doc.toString()).to.eq('');
|
|
27
31
|
|
|
28
32
|
// Create message.
|
|
29
|
-
const message:
|
|
33
|
+
const message: DataType.Message = {
|
|
30
34
|
id: '1',
|
|
31
35
|
created: createDate(),
|
|
32
36
|
sender: { name: 'Alice' },
|
|
@@ -57,14 +61,14 @@ describe('SerializationModel', () => {
|
|
|
57
61
|
|
|
58
62
|
test('sync - append', ({ expect }) => {
|
|
59
63
|
const view = new EditorView({ extensions: [], doc: '' });
|
|
60
|
-
const model = new SerializationModel<
|
|
64
|
+
const model = new SerializationModel<DataType.Message>(blockToMarkdown);
|
|
61
65
|
const adapter = new DocumentAdapter(view);
|
|
62
66
|
expect(adapter.lineCount()).to.eq(0);
|
|
63
67
|
expect(view.state.doc.toString()).to.eq('');
|
|
64
68
|
|
|
65
69
|
// Append message.
|
|
66
70
|
{
|
|
67
|
-
const message:
|
|
71
|
+
const message: DataType.Message = {
|
|
68
72
|
id: '1',
|
|
69
73
|
created: createDate(),
|
|
70
74
|
sender: { name: 'Alice' },
|
|
@@ -83,7 +87,7 @@ describe('SerializationModel', () => {
|
|
|
83
87
|
|
|
84
88
|
// Append message.
|
|
85
89
|
{
|
|
86
|
-
const message:
|
|
90
|
+
const message: DataType.Message = {
|
|
87
91
|
id: '2',
|
|
88
92
|
created: createDate(),
|
|
89
93
|
sender: { name: 'Bob' },
|
|
@@ -103,13 +107,13 @@ describe('SerializationModel', () => {
|
|
|
103
107
|
|
|
104
108
|
test('sync - append, update, delete', ({ expect }) => {
|
|
105
109
|
const view = new EditorView({ extensions: [], doc: '' });
|
|
106
|
-
const model = new SerializationModel<
|
|
110
|
+
const model = new SerializationModel<DataType.Message>(blockToMarkdown);
|
|
107
111
|
const adapter = new DocumentAdapter(view);
|
|
108
112
|
expect(adapter.lineCount()).to.eq(0);
|
|
109
113
|
|
|
110
114
|
// Append message.
|
|
111
115
|
{
|
|
112
|
-
const message:
|
|
116
|
+
const message: DataType.Message = {
|
|
113
117
|
id: '1',
|
|
114
118
|
created: createDate(),
|
|
115
119
|
sender: { name: 'Alice' },
|
|
@@ -142,7 +146,7 @@ describe('SerializationModel', () => {
|
|
|
142
146
|
|
|
143
147
|
// Append message.
|
|
144
148
|
{
|
|
145
|
-
const message:
|
|
149
|
+
const message: DataType.Message = {
|
|
146
150
|
id: '2',
|
|
147
151
|
created: createDate(),
|
|
148
152
|
sender: { name: 'Bob' },
|
package/src/testing/testing.ts
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import { Schema, SchemaAST } from 'effect';
|
|
5
6
|
import { useEffect, useMemo, useState } from 'react';
|
|
6
7
|
|
|
7
8
|
import { AIServiceEdgeClient } from '@dxos/assistant';
|
|
@@ -9,32 +10,38 @@ import { AI_SERVICE_ENDPOINT } from '@dxos/assistant/testing';
|
|
|
9
10
|
import { scheduleTaskInterval } from '@dxos/async';
|
|
10
11
|
import { createQueueDxn, Filter, type Queue } from '@dxos/client/echo';
|
|
11
12
|
import { Context } from '@dxos/context';
|
|
12
|
-
import {
|
|
13
|
+
import { Type } from '@dxos/echo';
|
|
14
|
+
import { create, ObjectId } from '@dxos/echo-schema';
|
|
13
15
|
import { IdentityDid } from '@dxos/keys';
|
|
14
16
|
import { log } from '@dxos/log';
|
|
15
17
|
import { faker } from '@dxos/random';
|
|
16
18
|
import { live, makeRef, useQueue, type Space } from '@dxos/react-client/echo';
|
|
17
|
-
import {
|
|
19
|
+
import { DataType } from '@dxos/schema';
|
|
18
20
|
import { Testing, seedTestData } from '@dxos/schema/testing';
|
|
19
21
|
|
|
20
22
|
import { processTranscriptMessage } from '../entity-extraction';
|
|
21
23
|
|
|
22
24
|
// TODO(burdon): Reconcile with plugin-markdown. Move to @dxos/schema/testing.
|
|
23
25
|
|
|
24
|
-
export const TestItem =
|
|
25
|
-
title:
|
|
26
|
-
[
|
|
27
|
-
[
|
|
26
|
+
export const TestItem = Schema.Struct({
|
|
27
|
+
title: Schema.String.annotations({
|
|
28
|
+
[SchemaAST.TitleAnnotationId]: 'Title',
|
|
29
|
+
[SchemaAST.DescriptionAnnotationId]: 'Product title',
|
|
28
30
|
}),
|
|
29
|
-
description:
|
|
30
|
-
[
|
|
31
|
-
[
|
|
31
|
+
description: Schema.String.annotations({
|
|
32
|
+
[SchemaAST.TitleAnnotationId]: 'Description',
|
|
33
|
+
[SchemaAST.DescriptionAnnotationId]: 'Product description',
|
|
32
34
|
}),
|
|
33
|
-
}).pipe(
|
|
35
|
+
}).pipe(
|
|
36
|
+
Type.def({
|
|
37
|
+
typename: 'dxos.org/type/Test',
|
|
38
|
+
version: '0.1.0',
|
|
39
|
+
}),
|
|
40
|
+
);
|
|
34
41
|
|
|
35
42
|
// TODO(wittjosiah): Make builder generic and reuse for all message types.
|
|
36
43
|
abstract class AbstractMessageBuilder {
|
|
37
|
-
abstract createMessage(numSegments?: number): Promise<
|
|
44
|
+
abstract createMessage(numSegments?: number): Promise<DataType.Message>;
|
|
38
45
|
}
|
|
39
46
|
|
|
40
47
|
/**
|
|
@@ -55,7 +62,7 @@ export class MessageBuilder extends AbstractMessageBuilder {
|
|
|
55
62
|
super();
|
|
56
63
|
}
|
|
57
64
|
|
|
58
|
-
override async createMessage(numSegments = 1): Promise<
|
|
65
|
+
override async createMessage(numSegments = 1): Promise<DataType.Message> {
|
|
59
66
|
return {
|
|
60
67
|
id: ObjectId.random().toString(),
|
|
61
68
|
created: this.next().toISOString(),
|
|
@@ -64,7 +71,7 @@ export class MessageBuilder extends AbstractMessageBuilder {
|
|
|
64
71
|
};
|
|
65
72
|
}
|
|
66
73
|
|
|
67
|
-
createBlock():
|
|
74
|
+
createBlock(): DataType.MessageBlock.Transcription {
|
|
68
75
|
let text = faker.lorem.paragraph();
|
|
69
76
|
if (this._space) {
|
|
70
77
|
const label = faker.commerce.productName();
|
|
@@ -96,7 +103,7 @@ class EntityExtractionMessageBuilder extends AbstractMessageBuilder {
|
|
|
96
103
|
|
|
97
104
|
space: Space | undefined;
|
|
98
105
|
currentMessage: number = 0;
|
|
99
|
-
transcriptMessages:
|
|
106
|
+
transcriptMessages: DataType.Message[] = [];
|
|
100
107
|
|
|
101
108
|
async connect(space: Space) {
|
|
102
109
|
this.space = space;
|
|
@@ -104,13 +111,19 @@ class EntityExtractionMessageBuilder extends AbstractMessageBuilder {
|
|
|
104
111
|
this.transcriptMessages = transcriptMessages;
|
|
105
112
|
}
|
|
106
113
|
|
|
107
|
-
override async createMessage(): Promise<
|
|
114
|
+
override async createMessage(): Promise<DataType.Message> {
|
|
108
115
|
if (!this.space) {
|
|
109
116
|
throw new Error('Space not connected');
|
|
110
117
|
}
|
|
111
118
|
|
|
112
119
|
const { objects } = await this.space.db
|
|
113
|
-
.query(
|
|
120
|
+
.query(
|
|
121
|
+
Filter.or(
|
|
122
|
+
Filter.schema(DataType.Person),
|
|
123
|
+
Filter.schema(DataType.Organization),
|
|
124
|
+
Filter.schema(Testing.DocumentType),
|
|
125
|
+
),
|
|
126
|
+
)
|
|
114
127
|
.run();
|
|
115
128
|
|
|
116
129
|
log.info('context', { objects });
|
|
@@ -135,7 +148,7 @@ type UseTestTranscriptionQueue = (
|
|
|
135
148
|
queueId?: ObjectId,
|
|
136
149
|
running?: boolean,
|
|
137
150
|
interval?: number,
|
|
138
|
-
) => Queue<
|
|
151
|
+
) => Queue<DataType.Message> | undefined;
|
|
139
152
|
|
|
140
153
|
/**
|
|
141
154
|
* Test transcriptionqueue.
|
|
@@ -147,7 +160,7 @@ export const useTestTranscriptionQueue: UseTestTranscriptionQueue = (
|
|
|
147
160
|
interval = 1_000,
|
|
148
161
|
) => {
|
|
149
162
|
const queueDxn = useMemo(() => (space ? createQueueDxn(space.id, queueId) : undefined), [space, queueId]);
|
|
150
|
-
const queue = useQueue<
|
|
163
|
+
const queue = useQueue<DataType.Message>(queueDxn);
|
|
151
164
|
const builder = useMemo(() => new MessageBuilder(space), [space]);
|
|
152
165
|
|
|
153
166
|
useEffect(() => {
|
|
@@ -157,7 +170,7 @@ export const useTestTranscriptionQueue: UseTestTranscriptionQueue = (
|
|
|
157
170
|
|
|
158
171
|
const i = setInterval(() => {
|
|
159
172
|
void builder.createMessage(Math.ceil(Math.random() * 3)).then((message) => {
|
|
160
|
-
queue.append([create(
|
|
173
|
+
queue.append([create(DataType.Message, message)]);
|
|
161
174
|
});
|
|
162
175
|
}, interval);
|
|
163
176
|
return () => clearInterval(i);
|
|
@@ -177,7 +190,7 @@ export const useTestTranscriptionQueueWithEntityExtraction: UseTestTranscription
|
|
|
177
190
|
interval = 1_000,
|
|
178
191
|
) => {
|
|
179
192
|
const queueDxn = useMemo(() => (space ? createQueueDxn(space.id, queueId) : undefined), [space, queueId]);
|
|
180
|
-
const queue = useQueue<
|
|
193
|
+
const queue = useQueue<DataType.Message>(queueDxn);
|
|
181
194
|
const [builder] = useState(() => new EntityExtractionMessageBuilder());
|
|
182
195
|
|
|
183
196
|
useEffect(() => {
|
|
@@ -194,7 +207,7 @@ export const useTestTranscriptionQueueWithEntityExtraction: UseTestTranscription
|
|
|
194
207
|
ctx,
|
|
195
208
|
async () => {
|
|
196
209
|
const message = await builder.createMessage();
|
|
197
|
-
queue.append([create(
|
|
210
|
+
queue.append([create(DataType.Message, message)]);
|
|
198
211
|
},
|
|
199
212
|
interval,
|
|
200
213
|
);
|
|
@@ -9,7 +9,7 @@ import { WaveFile } from 'wavefile';
|
|
|
9
9
|
|
|
10
10
|
import { Trigger } from '@dxos/async';
|
|
11
11
|
import { log } from '@dxos/log';
|
|
12
|
-
import { type
|
|
12
|
+
import { type DataType } from '@dxos/schema';
|
|
13
13
|
import { openAndClose } from '@dxos/test-utils';
|
|
14
14
|
import { trace, TRACE_PROCESSOR } from '@dxos/tracing';
|
|
15
15
|
|
|
@@ -93,7 +93,7 @@ describe.skip('Transcriber', () => {
|
|
|
93
93
|
});
|
|
94
94
|
|
|
95
95
|
test.skip('transcription of audio recording', { timeout: 10_000 }, async () => {
|
|
96
|
-
const trigger = new Trigger<
|
|
96
|
+
const trigger = new Trigger<DataType.MessageBlock.Transcription[]>({ autoReset: true });
|
|
97
97
|
const recorder = new MockAudioRecorder({
|
|
98
98
|
buffer: await readFile('test.wav'),
|
|
99
99
|
chunkDuration: 3_000,
|
|
@@ -127,7 +127,7 @@ describe.skip('Transcriber', () => {
|
|
|
127
127
|
});
|
|
128
128
|
|
|
129
129
|
test.skip('transcription of audio recording with overlapping chunks', { timeout: 20_000 }, async () => {
|
|
130
|
-
const trigger = new Trigger<
|
|
130
|
+
const trigger = new Trigger<DataType.MessageBlock.Transcription[]>({ autoReset: true });
|
|
131
131
|
const recorder = new MockAudioRecorder({
|
|
132
132
|
buffer: await readFile('test.wav'),
|
|
133
133
|
chunkDuration: 3_000,
|
|
@@ -7,7 +7,7 @@ import { WaveFile } from 'wavefile';
|
|
|
7
7
|
import { DeferredTask, Trigger } from '@dxos/async';
|
|
8
8
|
import { type Context, LifecycleState, Resource } from '@dxos/context';
|
|
9
9
|
import { log } from '@dxos/log';
|
|
10
|
-
import { type
|
|
10
|
+
import { type DataType } from '@dxos/schema';
|
|
11
11
|
import { trace } from '@dxos/tracing';
|
|
12
12
|
|
|
13
13
|
import { type AudioRecorder, type AudioChunk } from './audio-recorder';
|
|
@@ -65,7 +65,7 @@ export type TranscribeConfig = {
|
|
|
65
65
|
export type TranscriberParams = {
|
|
66
66
|
config: TranscribeConfig;
|
|
67
67
|
recorder: AudioRecorder;
|
|
68
|
-
onSegments: (segments:
|
|
68
|
+
onSegments: (segments: DataType.MessageBlock.Transcription[]) => Promise<void>;
|
|
69
69
|
};
|
|
70
70
|
|
|
71
71
|
/**
|
|
@@ -216,7 +216,10 @@ export class Transcriber extends Resource {
|
|
|
216
216
|
return segments;
|
|
217
217
|
}
|
|
218
218
|
|
|
219
|
-
private _alignSegments(
|
|
219
|
+
private _alignSegments(
|
|
220
|
+
segments: WhisperSegment[],
|
|
221
|
+
originalChunks: AudioChunk[],
|
|
222
|
+
): DataType.MessageBlock.Transcription[] {
|
|
220
223
|
// Absolute zero for all relative timestamps in the segments.
|
|
221
224
|
const zeroTimestamp = originalChunks.at(0)!.timestamp;
|
|
222
225
|
|