@wix/legends-platform-sdk 1.3.0 → 1.5.0
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/README.md +3 -2
- package/dist/cjs/hooks/index.js +6 -0
- package/dist/cjs/hooks/index.js.map +1 -1
- package/dist/cjs/hooks/useConversation/livekit/constants.js +3 -1
- package/dist/cjs/hooks/useConversation/livekit/constants.js.map +1 -1
- package/dist/cjs/hooks/useConversation/livekit/useConversation.js +82 -35
- package/dist/cjs/hooks/useConversation/livekit/useConversation.js.map +1 -1
- package/dist/cjs/hooks/useCreateConversation/useCreateConversation.js +16 -8
- package/dist/cjs/hooks/useCreateConversation/useCreateConversation.js.map +1 -1
- package/dist/cjs/hooks/useSpeechActivityDetector/helpers.js +87 -0
- package/dist/cjs/hooks/useSpeechActivityDetector/helpers.js.map +1 -0
- package/dist/cjs/hooks/useSpeechActivityDetector/index.js +16 -0
- package/dist/cjs/hooks/useSpeechActivityDetector/index.js.map +1 -0
- package/dist/cjs/hooks/useSpeechActivityDetector/speechActivityProcessorSource.js +55 -0
- package/dist/cjs/hooks/useSpeechActivityDetector/speechActivityProcessorSource.js.map +1 -0
- package/dist/cjs/hooks/useSpeechActivityDetector/types.js +4 -0
- package/dist/cjs/hooks/useSpeechActivityDetector/types.js.map +1 -0
- package/dist/cjs/hooks/useSpeechActivityDetector/useSpeechActivityDetector.js +52 -0
- package/dist/cjs/hooks/useSpeechActivityDetector/useSpeechActivityDetector.js.map +1 -0
- package/dist/cjs/sdk.js +6 -0
- package/dist/cjs/sdk.js.map +1 -1
- package/dist/cjs/types/service.js.map +1 -1
- package/dist/esm/hooks/index.js +1 -0
- package/dist/esm/hooks/index.js.map +1 -1
- package/dist/esm/hooks/useConversation/livekit/constants.js +2 -0
- package/dist/esm/hooks/useConversation/livekit/constants.js.map +1 -1
- package/dist/esm/hooks/useConversation/livekit/useConversation.js +82 -35
- package/dist/esm/hooks/useConversation/livekit/useConversation.js.map +1 -1
- package/dist/esm/hooks/useCreateConversation/useCreateConversation.js +16 -8
- package/dist/esm/hooks/useCreateConversation/useCreateConversation.js.map +1 -1
- package/dist/esm/hooks/useSpeechActivityDetector/helpers.js +83 -0
- package/dist/esm/hooks/useSpeechActivityDetector/helpers.js.map +1 -0
- package/dist/esm/hooks/useSpeechActivityDetector/index.js +3 -0
- package/dist/esm/hooks/useSpeechActivityDetector/index.js.map +1 -0
- package/dist/esm/hooks/useSpeechActivityDetector/speechActivityProcessorSource.js +51 -0
- package/dist/esm/hooks/useSpeechActivityDetector/speechActivityProcessorSource.js.map +1 -0
- package/dist/esm/hooks/useSpeechActivityDetector/types.js +2 -0
- package/dist/esm/hooks/useSpeechActivityDetector/types.js.map +1 -0
- package/dist/esm/hooks/useSpeechActivityDetector/useSpeechActivityDetector.js +44 -0
- package/dist/esm/hooks/useSpeechActivityDetector/useSpeechActivityDetector.js.map +1 -0
- package/dist/esm/sdk.js +1 -0
- package/dist/esm/sdk.js.map +1 -1
- package/dist/esm/types/service.js.map +1 -1
- package/dist/types/hooks/index.d.ts +1 -0
- package/dist/types/hooks/index.d.ts.map +1 -1
- package/dist/types/hooks/useConversation/livekit/constants.d.ts +2 -0
- package/dist/types/hooks/useConversation/livekit/constants.d.ts.map +1 -1
- package/dist/types/hooks/useConversation/livekit/useConversation.d.ts.map +1 -1
- package/dist/types/hooks/useCreateConversation/useCreateConversation.d.ts +4 -0
- package/dist/types/hooks/useCreateConversation/useCreateConversation.d.ts.map +1 -1
- package/dist/types/hooks/useSpeechActivityDetector/helpers.d.ts +19 -0
- package/dist/types/hooks/useSpeechActivityDetector/helpers.d.ts.map +1 -0
- package/dist/types/hooks/useSpeechActivityDetector/index.d.ts +3 -0
- package/dist/types/hooks/useSpeechActivityDetector/index.d.ts.map +1 -0
- package/dist/types/hooks/useSpeechActivityDetector/speechActivityProcessorSource.d.ts +3 -0
- package/dist/types/hooks/useSpeechActivityDetector/speechActivityProcessorSource.d.ts.map +1 -0
- package/dist/types/hooks/useSpeechActivityDetector/types.d.ts +14 -0
- package/dist/types/hooks/useSpeechActivityDetector/types.d.ts.map +1 -0
- package/dist/types/hooks/useSpeechActivityDetector/useSpeechActivityDetector.d.ts +10 -0
- package/dist/types/hooks/useSpeechActivityDetector/useSpeechActivityDetector.d.ts.map +1 -0
- package/dist/types/sdk.d.ts +1 -0
- package/dist/types/sdk.d.ts.map +1 -1
- package/dist/types/types/service.d.ts +4 -0
- package/dist/types/types/service.d.ts.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.setupSpeechActivityDetector = setupSpeechActivityDetector;
|
|
5
|
+
var _speechActivityProcessorSource = require("./speechActivityProcessorSource");
|
|
6
|
+
const DEFAULT_THRESHOLD_RMS = 0.015;
|
|
7
|
+
const DEFAULT_HANGOVER_MS = 300;
|
|
8
|
+
const WORKLET_BLOCK_SIZE = 128;
|
|
9
|
+
/**
|
|
10
|
+
* Attaches an AudioWorkletNode-based RMS threshold+hangover detector to a
|
|
11
|
+
* LiveKit track's underlying MediaStreamTrack. Runs on the dedicated audio
|
|
12
|
+
* rendering thread — unlike requestAnimationFrame+AnalyserNode, it keeps
|
|
13
|
+
* running when the tab is backgrounded.
|
|
14
|
+
*/
|
|
15
|
+
function setupSpeechActivityDetector(track, options) {
|
|
16
|
+
if (!track) {
|
|
17
|
+
return {
|
|
18
|
+
cleanup: () => {}
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
let cancelled = false;
|
|
22
|
+
let audioContext = null;
|
|
23
|
+
let mediaStreamSource = null;
|
|
24
|
+
let node = null;
|
|
25
|
+
const thresholdRms = options.thresholdRms ?? DEFAULT_THRESHOLD_RMS;
|
|
26
|
+
const hangoverMs = options.hangoverMs ?? DEFAULT_HANGOVER_MS;
|
|
27
|
+
const setup = async () => {
|
|
28
|
+
const ctx = new AudioContext();
|
|
29
|
+
audioContext = ctx;
|
|
30
|
+
if (ctx.state === 'suspended') {
|
|
31
|
+
await ctx.resume();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Hangover is expressed in ms; convert to a block count using this
|
|
35
|
+
// context's actual sample rate (block size is fixed at 128 samples by
|
|
36
|
+
// the Web Audio spec, but wall-clock duration per block varies with
|
|
37
|
+
// sample rate across devices/browsers).
|
|
38
|
+
const hangoverBlocks = Math.max(1, Math.round(hangoverMs / 1000 * (ctx.sampleRate / WORKLET_BLOCK_SIZE)));
|
|
39
|
+
const blob = new Blob([_speechActivityProcessorSource.SPEECH_ACTIVITY_PROCESSOR_SOURCE], {
|
|
40
|
+
type: 'application/javascript'
|
|
41
|
+
});
|
|
42
|
+
const blobUrl = URL.createObjectURL(blob);
|
|
43
|
+
try {
|
|
44
|
+
await ctx.audioWorklet.addModule(blobUrl);
|
|
45
|
+
} finally {
|
|
46
|
+
URL.revokeObjectURL(blobUrl);
|
|
47
|
+
}
|
|
48
|
+
if (cancelled) {
|
|
49
|
+
await ctx.close();
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
mediaStreamSource = ctx.createMediaStreamSource(new MediaStream([track.mediaStreamTrack]));
|
|
53
|
+
node = new AudioWorkletNode(ctx, _speechActivityProcessorSource.SPEECH_ACTIVITY_PROCESSOR_NAME, {
|
|
54
|
+
processorOptions: {
|
|
55
|
+
thresholdRms,
|
|
56
|
+
hangoverBlocks
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
node.port.onmessage = event => {
|
|
60
|
+
var _event$data, _event$data2;
|
|
61
|
+
const timestampMs = performance.now();
|
|
62
|
+
if (((_event$data = event.data) == null ? void 0 : _event$data.type) === 'onset') {
|
|
63
|
+
options.onSpeechStart == null || options.onSpeechStart(timestampMs);
|
|
64
|
+
} else if (((_event$data2 = event.data) == null ? void 0 : _event$data2.type) === 'offset') {
|
|
65
|
+
options.onSpeechEnd == null || options.onSpeechEnd(timestampMs);
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
mediaStreamSource.connect(node);
|
|
69
|
+
};
|
|
70
|
+
setup().catch(error => {
|
|
71
|
+
// eslint-disable-next-line no-console
|
|
72
|
+
console.error('[useSpeechActivityDetector] failed to set up AudioWorklet', error);
|
|
73
|
+
});
|
|
74
|
+
return {
|
|
75
|
+
cleanup: () => {
|
|
76
|
+
var _mediaStreamSource, _audioContext;
|
|
77
|
+
cancelled = true;
|
|
78
|
+
if (node) {
|
|
79
|
+
node.port.onmessage = null;
|
|
80
|
+
node.disconnect();
|
|
81
|
+
}
|
|
82
|
+
(_mediaStreamSource = mediaStreamSource) == null || _mediaStreamSource.disconnect();
|
|
83
|
+
void ((_audioContext = audioContext) == null ? void 0 : _audioContext.close());
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_speechActivityProcessorSource","require","DEFAULT_THRESHOLD_RMS","DEFAULT_HANGOVER_MS","WORKLET_BLOCK_SIZE","setupSpeechActivityDetector","track","options","cleanup","cancelled","audioContext","mediaStreamSource","node","thresholdRms","hangoverMs","setup","ctx","AudioContext","state","resume","hangoverBlocks","Math","max","round","sampleRate","blob","Blob","SPEECH_ACTIVITY_PROCESSOR_SOURCE","type","blobUrl","URL","createObjectURL","audioWorklet","addModule","revokeObjectURL","close","createMediaStreamSource","MediaStream","mediaStreamTrack","AudioWorkletNode","SPEECH_ACTIVITY_PROCESSOR_NAME","processorOptions","port","onmessage","event","_event$data","_event$data2","timestampMs","performance","now","data","onSpeechStart","onSpeechEnd","connect","catch","error","console","_mediaStreamSource","_audioContext","disconnect"],"sources":["../../../../src/hooks/useSpeechActivityDetector/helpers.ts"],"sourcesContent":["import { Track } from 'livekit-client';\nimport {\n SPEECH_ACTIVITY_PROCESSOR_NAME,\n SPEECH_ACTIVITY_PROCESSOR_SOURCE,\n} from './speechActivityProcessorSource';\n\nconst DEFAULT_THRESHOLD_RMS = 0.015;\nconst DEFAULT_HANGOVER_MS = 300;\nconst WORKLET_BLOCK_SIZE = 128;\n\nexport type SetupSpeechActivityDetectorOptions = {\n thresholdRms?: number;\n hangoverMs?: number;\n minSpeechMs?: number;\n onSpeechStart?: (timestampMs: number) => void;\n onSpeechEnd?: (timestampMs: number) => void;\n onMisfire?: () => void;\n};\n\n/**\n * Attaches an AudioWorkletNode-based RMS threshold+hangover detector to a\n * LiveKit track's underlying MediaStreamTrack. Runs on the dedicated audio\n * rendering thread — unlike requestAnimationFrame+AnalyserNode, it keeps\n * running when the tab is backgrounded.\n */\nexport function setupSpeechActivityDetector(\n track: Track | undefined,\n options: SetupSpeechActivityDetectorOptions,\n): { cleanup: () => void } {\n if (!track) {\n return { cleanup: () => {} };\n }\n\n let cancelled = false;\n let audioContext: AudioContext | null = null;\n let mediaStreamSource: MediaStreamAudioSourceNode | null = null;\n let node: AudioWorkletNode | null = null;\n\n const thresholdRms = options.thresholdRms ?? DEFAULT_THRESHOLD_RMS;\n const hangoverMs = options.hangoverMs ?? DEFAULT_HANGOVER_MS;\n\n const setup = async () => {\n const ctx = new AudioContext();\n audioContext = ctx;\n if (ctx.state === 'suspended') {\n await ctx.resume();\n }\n\n // Hangover is expressed in ms; convert to a block count using this\n // context's actual sample rate (block size is fixed at 128 samples by\n // the Web Audio spec, but wall-clock duration per block varies with\n // sample rate across devices/browsers).\n const hangoverBlocks = Math.max(\n 1,\n Math.round((hangoverMs / 1000) * (ctx.sampleRate / WORKLET_BLOCK_SIZE)),\n );\n\n const blob = new Blob([SPEECH_ACTIVITY_PROCESSOR_SOURCE], {\n type: 'application/javascript',\n });\n const blobUrl = URL.createObjectURL(blob);\n try {\n await ctx.audioWorklet.addModule(blobUrl);\n } finally {\n URL.revokeObjectURL(blobUrl);\n }\n\n if (cancelled) {\n await ctx.close();\n return;\n }\n\n mediaStreamSource = ctx.createMediaStreamSource(\n new MediaStream([track.mediaStreamTrack]),\n );\n node = new AudioWorkletNode(ctx, SPEECH_ACTIVITY_PROCESSOR_NAME, {\n processorOptions: { thresholdRms, hangoverBlocks },\n });\n node.port.onmessage = (event: MessageEvent) => {\n const timestampMs = performance.now();\n if (event.data?.type === 'onset') {\n options.onSpeechStart?.(timestampMs);\n } else if (event.data?.type === 'offset') {\n options.onSpeechEnd?.(timestampMs);\n }\n };\n mediaStreamSource.connect(node);\n };\n\n setup().catch((error) => {\n // eslint-disable-next-line no-console\n console.error(\n '[useSpeechActivityDetector] failed to set up AudioWorklet',\n error,\n );\n });\n\n return {\n cleanup: () => {\n cancelled = true;\n if (node) {\n node.port.onmessage = null;\n node.disconnect();\n }\n mediaStreamSource?.disconnect();\n void audioContext?.close();\n },\n };\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
var _useSpeechActivityDetector = require("./useSpeechActivityDetector");
|
|
5
|
+
Object.keys(_useSpeechActivityDetector).forEach(function (key) {
|
|
6
|
+
if (key === "default" || key === "__esModule") return;
|
|
7
|
+
if (key in exports && exports[key] === _useSpeechActivityDetector[key]) return;
|
|
8
|
+
exports[key] = _useSpeechActivityDetector[key];
|
|
9
|
+
});
|
|
10
|
+
var _types = require("./types");
|
|
11
|
+
Object.keys(_types).forEach(function (key) {
|
|
12
|
+
if (key === "default" || key === "__esModule") return;
|
|
13
|
+
if (key in exports && exports[key] === _types[key]) return;
|
|
14
|
+
exports[key] = _types[key];
|
|
15
|
+
});
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_useSpeechActivityDetector","require","Object","keys","forEach","key","exports","_types"],"sources":["../../../../src/hooks/useSpeechActivityDetector/index.ts"],"sourcesContent":["export * from './useSpeechActivityDetector';\nexport * from './types';\n"],"mappings":";;;AAAA,IAAAA,0BAAA,GAAAC,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAH,0BAAA,EAAAI,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAL,0BAAA,CAAAK,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAL,0BAAA,CAAAK,GAAA;AAAA;AACA,IAAAE,MAAA,GAAAN,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAI,MAAA,EAAAH,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAE,MAAA,CAAAF,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAE,MAAA,CAAAF,GAAA;AAAA","ignoreList":[]}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.SPEECH_ACTIVITY_PROCESSOR_SOURCE = exports.SPEECH_ACTIVITY_PROCESSOR_NAME = void 0;
|
|
5
|
+
// AudioWorkletProcessor source, kept as a plain string and loaded via a Blob
|
|
6
|
+
// URL (see helpers.ts). AudioWorkletGlobalScope runs isolated code on the
|
|
7
|
+
// dedicated audio rendering thread — it is not throttled when the tab is
|
|
8
|
+
// backgrounded, unlike requestAnimationFrame-driven analysis. Threshold
|
|
9
|
+
// crossings are posted back to the main thread via `port.postMessage`.
|
|
10
|
+
const SPEECH_ACTIVITY_PROCESSOR_NAME = exports.SPEECH_ACTIVITY_PROCESSOR_NAME = 'speech-activity-processor';
|
|
11
|
+
const SPEECH_ACTIVITY_PROCESSOR_SOURCE = exports.SPEECH_ACTIVITY_PROCESSOR_SOURCE = `
|
|
12
|
+
class SpeechActivityProcessor extends AudioWorkletProcessor {
|
|
13
|
+
constructor(options) {
|
|
14
|
+
super();
|
|
15
|
+
const opts = (options && options.processorOptions) || {};
|
|
16
|
+
this.threshold = typeof opts.thresholdRms === 'number' ? opts.thresholdRms : 0.015;
|
|
17
|
+
this.hangoverBlocks = typeof opts.hangoverBlocks === 'number' ? opts.hangoverBlocks : 8;
|
|
18
|
+
this.speaking = false;
|
|
19
|
+
this.silentBlockCount = 0;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
process(inputs) {
|
|
23
|
+
const input = inputs[0];
|
|
24
|
+
const channel = input && input[0];
|
|
25
|
+
if (!channel || channel.length === 0) {
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
let sumSquares = 0;
|
|
30
|
+
for (let i = 0; i < channel.length; i++) {
|
|
31
|
+
sumSquares += channel[i] * channel[i];
|
|
32
|
+
}
|
|
33
|
+
const rms = Math.sqrt(sumSquares / channel.length);
|
|
34
|
+
const isLoud = rms > this.threshold;
|
|
35
|
+
|
|
36
|
+
if (isLoud) {
|
|
37
|
+
this.silentBlockCount = 0;
|
|
38
|
+
if (!this.speaking) {
|
|
39
|
+
this.speaking = true;
|
|
40
|
+
this.port.postMessage({ type: 'onset', rms: rms });
|
|
41
|
+
}
|
|
42
|
+
} else if (this.speaking) {
|
|
43
|
+
this.silentBlockCount += 1;
|
|
44
|
+
if (this.silentBlockCount >= this.hangoverBlocks) {
|
|
45
|
+
this.speaking = false;
|
|
46
|
+
this.port.postMessage({ type: 'offset', rms: rms });
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
registerProcessor('${SPEECH_ACTIVITY_PROCESSOR_NAME}', SpeechActivityProcessor);
|
|
54
|
+
`;
|
|
55
|
+
//# sourceMappingURL=speechActivityProcessorSource.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["SPEECH_ACTIVITY_PROCESSOR_NAME","exports","SPEECH_ACTIVITY_PROCESSOR_SOURCE"],"sources":["../../../../src/hooks/useSpeechActivityDetector/speechActivityProcessorSource.ts"],"sourcesContent":["// AudioWorkletProcessor source, kept as a plain string and loaded via a Blob\n// URL (see helpers.ts). AudioWorkletGlobalScope runs isolated code on the\n// dedicated audio rendering thread — it is not throttled when the tab is\n// backgrounded, unlike requestAnimationFrame-driven analysis. Threshold\n// crossings are posted back to the main thread via `port.postMessage`.\nexport const SPEECH_ACTIVITY_PROCESSOR_NAME = 'speech-activity-processor';\n\nexport const SPEECH_ACTIVITY_PROCESSOR_SOURCE = `\nclass SpeechActivityProcessor extends AudioWorkletProcessor {\n constructor(options) {\n super();\n const opts = (options && options.processorOptions) || {};\n this.threshold = typeof opts.thresholdRms === 'number' ? opts.thresholdRms : 0.015;\n this.hangoverBlocks = typeof opts.hangoverBlocks === 'number' ? opts.hangoverBlocks : 8;\n this.speaking = false;\n this.silentBlockCount = 0;\n }\n\n process(inputs) {\n const input = inputs[0];\n const channel = input && input[0];\n if (!channel || channel.length === 0) {\n return true;\n }\n\n let sumSquares = 0;\n for (let i = 0; i < channel.length; i++) {\n sumSquares += channel[i] * channel[i];\n }\n const rms = Math.sqrt(sumSquares / channel.length);\n const isLoud = rms > this.threshold;\n\n if (isLoud) {\n this.silentBlockCount = 0;\n if (!this.speaking) {\n this.speaking = true;\n this.port.postMessage({ type: 'onset', rms: rms });\n }\n } else if (this.speaking) {\n this.silentBlockCount += 1;\n if (this.silentBlockCount >= this.hangoverBlocks) {\n this.speaking = false;\n this.port.postMessage({ type: 'offset', rms: rms });\n }\n }\n return true;\n }\n}\n\nregisterProcessor('${SPEECH_ACTIVITY_PROCESSOR_NAME}', SpeechActivityProcessor);\n`;\n"],"mappings":";;;;AAAA;AACA;AACA;AACA;AACA;AACO,MAAMA,8BAA8B,GAAAC,OAAA,CAAAD,8BAAA,GAAG,2BAA2B;AAElE,MAAME,gCAAgC,GAAAD,OAAA,CAAAC,gCAAA,GAAG;AAChD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qBAAqBF,8BAA8B;AACnD,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sources":["../../../../src/hooks/useSpeechActivityDetector/types.ts"],"sourcesContent":["export type UseSpeechActivityDetectorOptions = {\n source: 'user' | 'agent';\n onSpeechStart?: (timestampMs: number) => void;\n onSpeechEnd?: (timestampMs: number) => void;\n /** Fired instead of onSpeechEnd when a segment was shorter than minSpeechMs. */\n onMisfire?: () => void;\n /** RMS threshold (0-1) above which a block counts as \"loud\". Default 0.015. */\n thresholdRms?: number;\n /** Consecutive silence duration before an \"offset\" fires. Default 300ms. */\n hangoverMs?: number;\n /** Minimum onset-to-offset duration to count as real speech, not a blip/echo. Default 0 (no filtering). */\n minSpeechMs?: number;\n};\n"],"mappings":"","ignoreList":[]}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.useSpeechActivityDetector = useSpeechActivityDetector;
|
|
5
|
+
var _react = require("react");
|
|
6
|
+
var _useParticipantTrack = require("../useParticipantTrack");
|
|
7
|
+
var _helpers = require("./helpers");
|
|
8
|
+
/**
|
|
9
|
+
* Acoustic speech onset/offset detector for a participant's microphone
|
|
10
|
+
* track, driven by AudioWorkletNode rather than LiveKit's speaking-state
|
|
11
|
+
* events. Useful when the caller needs a timestamp tied to the actual audio
|
|
12
|
+
* signal (e.g. perceived end-to-end latency measurement) rather than a
|
|
13
|
+
* VAD/turn-detection-derived event.
|
|
14
|
+
*/
|
|
15
|
+
function useSpeechActivityDetector(options) {
|
|
16
|
+
const {
|
|
17
|
+
source,
|
|
18
|
+
onSpeechStart,
|
|
19
|
+
onSpeechEnd,
|
|
20
|
+
thresholdRms,
|
|
21
|
+
hangoverMs
|
|
22
|
+
} = options;
|
|
23
|
+
const {
|
|
24
|
+
track
|
|
25
|
+
} = (0, _useParticipantTrack.useParticipantTrack)({
|
|
26
|
+
type: source,
|
|
27
|
+
source: _useParticipantTrack.Source.Microphone
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// Keep latest callbacks available to the effect without retriggering
|
|
31
|
+
// AudioContext/AudioWorkletNode setup on every render.
|
|
32
|
+
const callbacksRef = (0, _react.useRef)({
|
|
33
|
+
onSpeechStart,
|
|
34
|
+
onSpeechEnd
|
|
35
|
+
});
|
|
36
|
+
callbacksRef.current = {
|
|
37
|
+
onSpeechStart,
|
|
38
|
+
onSpeechEnd
|
|
39
|
+
};
|
|
40
|
+
(0, _react.useEffect)(() => {
|
|
41
|
+
const {
|
|
42
|
+
cleanup
|
|
43
|
+
} = (0, _helpers.setupSpeechActivityDetector)(track, {
|
|
44
|
+
thresholdRms,
|
|
45
|
+
hangoverMs,
|
|
46
|
+
onSpeechStart: timestampMs => callbacksRef.current.onSpeechStart == null ? void 0 : callbacksRef.current.onSpeechStart(timestampMs),
|
|
47
|
+
onSpeechEnd: timestampMs => callbacksRef.current.onSpeechEnd == null ? void 0 : callbacksRef.current.onSpeechEnd(timestampMs)
|
|
48
|
+
});
|
|
49
|
+
return cleanup;
|
|
50
|
+
}, [track == null ? void 0 : track.mediaStreamTrack, thresholdRms, hangoverMs]);
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=useSpeechActivityDetector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_react","require","_useParticipantTrack","_helpers","useSpeechActivityDetector","options","source","onSpeechStart","onSpeechEnd","thresholdRms","hangoverMs","track","useParticipantTrack","type","Source","Microphone","callbacksRef","useRef","current","useEffect","cleanup","setupSpeechActivityDetector","timestampMs","mediaStreamTrack"],"sources":["../../../../src/hooks/useSpeechActivityDetector/useSpeechActivityDetector.ts"],"sourcesContent":["import { useEffect, useRef } from 'react';\nimport { useParticipantTrack, Source } from '../useParticipantTrack';\nimport { setupSpeechActivityDetector } from './helpers';\nimport { type UseSpeechActivityDetectorOptions } from './types';\n\n/**\n * Acoustic speech onset/offset detector for a participant's microphone\n * track, driven by AudioWorkletNode rather than LiveKit's speaking-state\n * events. Useful when the caller needs a timestamp tied to the actual audio\n * signal (e.g. perceived end-to-end latency measurement) rather than a\n * VAD/turn-detection-derived event.\n */\nexport function useSpeechActivityDetector(\n options: UseSpeechActivityDetectorOptions,\n): void {\n const { source, onSpeechStart, onSpeechEnd, thresholdRms, hangoverMs } =\n options;\n const { track } = useParticipantTrack({\n type: source,\n source: Source.Microphone,\n });\n\n // Keep latest callbacks available to the effect without retriggering\n // AudioContext/AudioWorkletNode setup on every render.\n const callbacksRef = useRef({ onSpeechStart, onSpeechEnd });\n callbacksRef.current = { onSpeechStart, onSpeechEnd };\n\n useEffect(() => {\n const { cleanup } = setupSpeechActivityDetector(track, {\n thresholdRms,\n hangoverMs,\n onSpeechStart: (timestampMs) =>\n callbacksRef.current.onSpeechStart?.(timestampMs),\n onSpeechEnd: (timestampMs) =>\n callbacksRef.current.onSpeechEnd?.(timestampMs),\n });\n return cleanup;\n }, [track?.mediaStreamTrack, thresholdRms, hangoverMs]);\n}\n"],"mappings":";;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AACA,IAAAC,oBAAA,GAAAD,OAAA;AACA,IAAAE,QAAA,GAAAF,OAAA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAASG,yBAAyBA,CACvCC,OAAyC,EACnC;EACN,MAAM;IAAEC,MAAM;IAAEC,aAAa;IAAEC,WAAW;IAAEC,YAAY;IAAEC;EAAW,CAAC,GACpEL,OAAO;EACT,MAAM;IAAEM;EAAM,CAAC,GAAG,IAAAC,wCAAmB,EAAC;IACpCC,IAAI,EAAEP,MAAM;IACZA,MAAM,EAAEQ,2BAAM,CAACC;EACjB,CAAC,CAAC;;EAEF;EACA;EACA,MAAMC,YAAY,GAAG,IAAAC,aAAM,EAAC;IAAEV,aAAa;IAAEC;EAAY,CAAC,CAAC;EAC3DQ,YAAY,CAACE,OAAO,GAAG;IAAEX,aAAa;IAAEC;EAAY,CAAC;EAErD,IAAAW,gBAAS,EAAC,MAAM;IACd,MAAM;MAAEC;IAAQ,CAAC,GAAG,IAAAC,oCAA2B,EAACV,KAAK,EAAE;MACrDF,YAAY;MACZC,UAAU;MACVH,aAAa,EAAGe,WAAW,IACzBN,YAAY,CAACE,OAAO,CAACX,aAAa,oBAAlCS,YAAY,CAACE,OAAO,CAACX,aAAa,CAAGe,WAAW,CAAC;MACnDd,WAAW,EAAGc,WAAW,IACvBN,YAAY,CAACE,OAAO,CAACV,WAAW,oBAAhCQ,YAAY,CAACE,OAAO,CAACV,WAAW,CAAGc,WAAW;IAClD,CAAC,CAAC;IACF,OAAOF,OAAO;EAChB,CAAC,EAAE,CAACT,KAAK,oBAALA,KAAK,CAAEY,gBAAgB,EAAEd,YAAY,EAAEC,UAAU,CAAC,CAAC;AACzD","ignoreList":[]}
|
package/dist/cjs/sdk.js
CHANGED
|
@@ -139,6 +139,12 @@ Object.keys(_useParticipantTrack).forEach(function (key) {
|
|
|
139
139
|
if (key in exports && exports[key] === _useParticipantTrack[key]) return;
|
|
140
140
|
exports[key] = _useParticipantTrack[key];
|
|
141
141
|
});
|
|
142
|
+
var _useSpeechActivityDetector = require("./hooks/useSpeechActivityDetector");
|
|
143
|
+
Object.keys(_useSpeechActivityDetector).forEach(function (key) {
|
|
144
|
+
if (key === "default" || key === "__esModule") return;
|
|
145
|
+
if (key in exports && exports[key] === _useSpeechActivityDetector[key]) return;
|
|
146
|
+
exports[key] = _useSpeechActivityDetector[key];
|
|
147
|
+
});
|
|
142
148
|
var _types2 = require("./conversation/types");
|
|
143
149
|
Object.keys(_types2).forEach(function (key) {
|
|
144
150
|
if (key === "default" || key === "__esModule") return;
|
package/dist/cjs/sdk.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_types","require","Object","keys","forEach","key","exports","_LegendsPlatform","_LegendsPlatformQLess","_useTextChat","_useConversation","_useTranscriptions","_useConversationStatus","_useMicrophone","_useSpeaker","_useCamera","_useMediaRecorder","_useConversationTimer","_useAudioLevel","_useConversationEvents","_useUserActivity","_useAudio","_useScreenShare","_useConnectionState","_useActivityState","_usePictureInPicture","_useMediaPermissions","_useTools","_useParticipantTrack","_types2"],"sources":["../../src/sdk.ts"],"sourcesContent":["export * from './types';\nexport * from './components/LegendsPlatform';\nexport * from './components/LegendsPlatformQLess';\n\nexport * from './hooks/useTextChat';\nexport * from './hooks/useConversation';\nexport * from './hooks/useTranscriptions';\nexport * from './hooks/useConversationStatus';\nexport * from './hooks/useMicrophone';\nexport * from './hooks/useSpeaker';\nexport * from './hooks/useCamera';\nexport * from './hooks/useMediaRecorder';\nexport * from './hooks/useConversationTimer';\nexport * from './hooks/useAudioLevel';\nexport * from './hooks/useConversationEvents';\nexport * from './hooks/useUserActivity';\nexport * from './hooks/useAudio';\nexport * from './hooks/useScreenShare';\nexport * from './hooks/useConnectionState';\nexport * from './hooks/useActivityState';\nexport * from './hooks/usePictureInPicture';\nexport * from './hooks/useMediaPermissions';\nexport * from './hooks/useTools';\nexport * from './hooks/useParticipantTrack';\n\nexport * from './conversation/types';\n"],"mappings":";;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAH,MAAA,EAAAI,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAL,MAAA,CAAAK,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAL,MAAA,CAAAK,GAAA;AAAA;AACA,IAAAE,gBAAA,GAAAN,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAI,gBAAA,EAAAH,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAE,gBAAA,CAAAF,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAE,gBAAA,CAAAF,GAAA;AAAA;AACA,IAAAG,qBAAA,GAAAP,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAK,qBAAA,EAAAJ,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAG,qBAAA,CAAAH,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAG,qBAAA,CAAAH,GAAA;AAAA;AAEA,IAAAI,YAAA,GAAAR,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAM,YAAA,EAAAL,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAI,YAAA,CAAAJ,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAI,YAAA,CAAAJ,GAAA;AAAA;AACA,IAAAK,gBAAA,GAAAT,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAO,gBAAA,EAAAN,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAK,gBAAA,CAAAL,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAK,gBAAA,CAAAL,GAAA;AAAA;AACA,IAAAM,kBAAA,GAAAV,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAQ,kBAAA,EAAAP,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAM,kBAAA,CAAAN,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAM,kBAAA,CAAAN,GAAA;AAAA;AACA,IAAAO,sBAAA,GAAAX,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAS,sBAAA,EAAAR,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAO,sBAAA,CAAAP,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAO,sBAAA,CAAAP,GAAA;AAAA;AACA,IAAAQ,cAAA,GAAAZ,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAU,cAAA,EAAAT,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAQ,cAAA,CAAAR,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAQ,cAAA,CAAAR,GAAA;AAAA;AACA,IAAAS,WAAA,GAAAb,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAW,WAAA,EAAAV,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAS,WAAA,CAAAT,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAS,WAAA,CAAAT,GAAA;AAAA;AACA,IAAAU,UAAA,GAAAd,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAY,UAAA,EAAAX,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAU,UAAA,CAAAV,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAU,UAAA,CAAAV,GAAA;AAAA;AACA,IAAAW,iBAAA,GAAAf,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAa,iBAAA,EAAAZ,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAW,iBAAA,CAAAX,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAW,iBAAA,CAAAX,GAAA;AAAA;AACA,IAAAY,qBAAA,GAAAhB,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAc,qBAAA,EAAAb,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAY,qBAAA,CAAAZ,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAY,qBAAA,CAAAZ,GAAA;AAAA;AACA,IAAAa,cAAA,GAAAjB,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAe,cAAA,EAAAd,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAa,cAAA,CAAAb,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAa,cAAA,CAAAb,GAAA;AAAA;AACA,IAAAc,sBAAA,GAAAlB,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAgB,sBAAA,EAAAf,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAc,sBAAA,CAAAd,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAc,sBAAA,CAAAd,GAAA;AAAA;AACA,IAAAe,gBAAA,GAAAnB,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAiB,gBAAA,EAAAhB,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAe,gBAAA,CAAAf,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAe,gBAAA,CAAAf,GAAA;AAAA;AACA,IAAAgB,SAAA,GAAApB,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAkB,SAAA,EAAAjB,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAgB,SAAA,CAAAhB,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAgB,SAAA,CAAAhB,GAAA;AAAA;AACA,IAAAiB,eAAA,GAAArB,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAmB,eAAA,EAAAlB,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAiB,eAAA,CAAAjB,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAiB,eAAA,CAAAjB,GAAA;AAAA;AACA,IAAAkB,mBAAA,GAAAtB,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAoB,mBAAA,EAAAnB,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAkB,mBAAA,CAAAlB,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAkB,mBAAA,CAAAlB,GAAA;AAAA;AACA,IAAAmB,iBAAA,GAAAvB,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAqB,iBAAA,EAAApB,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAmB,iBAAA,CAAAnB,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAmB,iBAAA,CAAAnB,GAAA;AAAA;AACA,IAAAoB,oBAAA,GAAAxB,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAsB,oBAAA,EAAArB,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAoB,oBAAA,CAAApB,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAoB,oBAAA,CAAApB,GAAA;AAAA;AACA,IAAAqB,oBAAA,GAAAzB,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAuB,oBAAA,EAAAtB,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAqB,oBAAA,CAAArB,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAqB,oBAAA,CAAArB,GAAA;AAAA;AACA,IAAAsB,SAAA,GAAA1B,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAwB,SAAA,EAAAvB,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAsB,SAAA,CAAAtB,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAsB,SAAA,CAAAtB,GAAA;AAAA;AACA,IAAAuB,oBAAA,GAAA3B,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAyB,oBAAA,EAAAxB,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAuB,oBAAA,CAAAvB,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAuB,oBAAA,CAAAvB,GAAA;AAAA;
|
|
1
|
+
{"version":3,"names":["_types","require","Object","keys","forEach","key","exports","_LegendsPlatform","_LegendsPlatformQLess","_useTextChat","_useConversation","_useTranscriptions","_useConversationStatus","_useMicrophone","_useSpeaker","_useCamera","_useMediaRecorder","_useConversationTimer","_useAudioLevel","_useConversationEvents","_useUserActivity","_useAudio","_useScreenShare","_useConnectionState","_useActivityState","_usePictureInPicture","_useMediaPermissions","_useTools","_useParticipantTrack","_useSpeechActivityDetector","_types2"],"sources":["../../src/sdk.ts"],"sourcesContent":["export * from './types';\nexport * from './components/LegendsPlatform';\nexport * from './components/LegendsPlatformQLess';\n\nexport * from './hooks/useTextChat';\nexport * from './hooks/useConversation';\nexport * from './hooks/useTranscriptions';\nexport * from './hooks/useConversationStatus';\nexport * from './hooks/useMicrophone';\nexport * from './hooks/useSpeaker';\nexport * from './hooks/useCamera';\nexport * from './hooks/useMediaRecorder';\nexport * from './hooks/useConversationTimer';\nexport * from './hooks/useAudioLevel';\nexport * from './hooks/useConversationEvents';\nexport * from './hooks/useUserActivity';\nexport * from './hooks/useAudio';\nexport * from './hooks/useScreenShare';\nexport * from './hooks/useConnectionState';\nexport * from './hooks/useActivityState';\nexport * from './hooks/usePictureInPicture';\nexport * from './hooks/useMediaPermissions';\nexport * from './hooks/useTools';\nexport * from './hooks/useParticipantTrack';\nexport * from './hooks/useSpeechActivityDetector';\n\nexport * from './conversation/types';\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["../../../src/types/service.ts"],"sourcesContent":["export type FunctionCall = {\n functionCallId: string;\n name: string;\n arguments: string;\n};\n\nexport type FunctionCallResult = {\n functionCallId: string;\n result: string;\n error?: string;\n};\n\nexport type LimitationType = 'MINUTES' | 'SECONDS' | 'TOKENS';\n\nexport interface Limitation {\n type?: LimitationType;\n limit?: number;\n}\n\nexport interface ConversationResult {\n url: string;\n id: string;\n limit?: number;\n}\n\nexport interface CreateConversationParams {\n chatId: string;\n namespace: string;\n chatConfig?: object;\n}\n\nexport interface EndConversationParams {\n chatId: string;\n conversationId: string;\n namespace: string;\n}\n\nexport interface ChatMessageAttachment {\n fileName?: string;\n url?: string;\n mimeType?: string;\n textFileContent?: string;\n}\n\nexport interface SendMessageParams {\n chatId: string;\n namespace: string;\n message: string;\n functionCallResults?: FunctionCallResult[];\n chatConfig?: object;\n attachments?: ChatMessageAttachment[];\n}\n\nexport interface ChatMessage {\n id: string;\n content: string;\n role: 'user' | 'assistant';\n createdAt?: string;\n attachments?: ChatMessageAttachment[];\n}\n\nexport interface QueryMessagesParams {\n chatId: string;\n namespace: string;\n limit?: number;\n cursor?: string;\n}\n\nexport interface QueryMessagesResult {\n messages: ChatMessage[];\n nextCursor?: string;\n}\n\nexport interface IPersonaChatService {\n createVoiceConversation(\n params: CreateConversationParams,\n ): Promise<ConversationResult>;\n createInteractiveConversation(\n params: CreateConversationParams,\n ): Promise<ConversationResult>;\n endInteractiveConversation(params: EndConversationParams): Promise<void>;\n sendChatMessage(\n params: SendMessageParams,\n ): Promise<{ functionCalls?: FunctionCall[]; messages?: ChatMessage[] }>;\n queryChatMessages(params: QueryMessagesParams): Promise<QueryMessagesResult>;\n}\n"],"mappings":"","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":[],"sources":["../../../src/types/service.ts"],"sourcesContent":["export type FunctionCall = {\n functionCallId: string;\n name: string;\n arguments: string;\n};\n\nexport type FunctionCallResult = {\n functionCallId: string;\n result: string;\n error?: string;\n};\n\nexport type LimitationType = 'MINUTES' | 'SECONDS' | 'TOKENS';\n\nexport interface Limitation {\n type?: LimitationType;\n limit?: number;\n}\n\nexport interface ConversationResult {\n url: string;\n id: string;\n limit?: number;\n}\n\nexport interface CreateConversationParams {\n chatId: string;\n namespace: string;\n chatConfig?: object;\n /** Whether this is the visitor's first-ever conversation with the persona (drives the opening message). */\n firstConversation?: boolean;\n /** Title of the visitor's last meaningful conversation, for a returning-visitor greeting. */\n lastConversationTopic?: string;\n}\n\nexport interface EndConversationParams {\n chatId: string;\n conversationId: string;\n namespace: string;\n}\n\nexport interface ChatMessageAttachment {\n fileName?: string;\n url?: string;\n mimeType?: string;\n textFileContent?: string;\n}\n\nexport interface SendMessageParams {\n chatId: string;\n namespace: string;\n message: string;\n functionCallResults?: FunctionCallResult[];\n chatConfig?: object;\n attachments?: ChatMessageAttachment[];\n}\n\nexport interface ChatMessage {\n id: string;\n content: string;\n role: 'user' | 'assistant';\n createdAt?: string;\n attachments?: ChatMessageAttachment[];\n}\n\nexport interface QueryMessagesParams {\n chatId: string;\n namespace: string;\n limit?: number;\n cursor?: string;\n}\n\nexport interface QueryMessagesResult {\n messages: ChatMessage[];\n nextCursor?: string;\n}\n\nexport interface IPersonaChatService {\n createVoiceConversation(\n params: CreateConversationParams,\n ): Promise<ConversationResult>;\n createInteractiveConversation(\n params: CreateConversationParams,\n ): Promise<ConversationResult>;\n endInteractiveConversation(params: EndConversationParams): Promise<void>;\n sendChatMessage(\n params: SendMessageParams,\n ): Promise<{ functionCalls?: FunctionCall[]; messages?: ChatMessage[] }>;\n queryChatMessages(params: QueryMessagesParams): Promise<QueryMessagesResult>;\n}\n"],"mappings":"","ignoreList":[]}
|
package/dist/esm/hooks/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["../../../src/hooks/index.ts"],"sourcesContent":["export * from './useConversation';\nexport * from './useCreateConversation';\nexport * from './useConversationStatus';\nexport * from './useTextChat';\nexport * from './useConversationEvents';\nexport * from './useUserActivity';\nexport * from './useScreenShare';\nexport * from './usePictureInPicture';\nexport * from './useTools';\n"],"mappings":"AAAA,cAAc,mBAAmB;AACjC,cAAc,yBAAyB;AACvC,cAAc,yBAAyB;AACvC,cAAc,eAAe;AAC7B,cAAc,yBAAyB;AACvC,cAAc,mBAAmB;AACjC,cAAc,kBAAkB;AAChC,cAAc,uBAAuB;AACrC,cAAc,YAAY","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":[],"sources":["../../../src/hooks/index.ts"],"sourcesContent":["export * from './useConversation';\nexport * from './useCreateConversation';\nexport * from './useConversationStatus';\nexport * from './useTextChat';\nexport * from './useConversationEvents';\nexport * from './useUserActivity';\nexport * from './useScreenShare';\nexport * from './usePictureInPicture';\nexport * from './useTools';\nexport * from './useSpeechActivityDetector';\n"],"mappings":"AAAA,cAAc,mBAAmB;AACjC,cAAc,yBAAyB;AACvC,cAAc,yBAAyB;AACvC,cAAc,eAAe;AAC7B,cAAc,yBAAyB;AACvC,cAAc,mBAAmB;AACjC,cAAc,kBAAkB;AAChC,cAAc,uBAAuB;AACrC,cAAc,YAAY;AAC1B,cAAc,6BAA6B","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["SPEAKING_STATE_EVENT_MAP","STANDARD","speaking","listening","AGENT"],"sources":["../../../../../src/hooks/useConversation/livekit/constants.ts"],"sourcesContent":["import type { TurnDetectionData } from './types';\nimport type { ConversationEvent } from '../../useConversationEvents';\n\nexport const SPEAKING_STATE_EVENT_MAP: Record<\n TurnDetectionData['participantKind'],\n Record<TurnDetectionData['state'], ConversationEvent>\n> = {\n STANDARD: {\n speaking: 'userSpeakStart',\n listening: 'userSpeakStop',\n },\n AGENT: {\n speaking: 'agentSpeakStart',\n listening: 'agentSpeakStop',\n },\n};\n"],"mappings":"AAGA,OAAO,MAAMA,wBAGZ,GAAG;EACFC,QAAQ,EAAE;IACRC,QAAQ,EAAE,gBAAgB;IAC1BC,SAAS,EAAE;EACb,CAAC;EACDC,KAAK,EAAE;IACLF,QAAQ,EAAE,iBAAiB;IAC3BC,SAAS,EAAE;EACb;AACF,CAAC","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["SPEAKING_STATE_EVENT_MAP","STANDARD","speaking","listening","AGENT","ACOUSTIC_USER_THRESHOLD_RMS","ACOUSTIC_USER_HANGOVER_MS"],"sources":["../../../../../src/hooks/useConversation/livekit/constants.ts"],"sourcesContent":["import type { TurnDetectionData } from './types';\nimport type { ConversationEvent } from '../../useConversationEvents';\n\nexport const SPEAKING_STATE_EVENT_MAP: Record<\n TurnDetectionData['participantKind'],\n Record<TurnDetectionData['state'], ConversationEvent>\n> = {\n STANDARD: {\n speaking: 'userSpeakStart',\n listening: 'userSpeakStop',\n },\n AGENT: {\n speaking: 'agentSpeakStart',\n listening: 'agentSpeakStop',\n },\n};\n\nexport const ACOUSTIC_USER_THRESHOLD_RMS = 0.025;\nexport const ACOUSTIC_USER_HANGOVER_MS = 400;\n"],"mappings":"AAGA,OAAO,MAAMA,wBAGZ,GAAG;EACFC,QAAQ,EAAE;IACRC,QAAQ,EAAE,gBAAgB;IAC1BC,SAAS,EAAE;EACb,CAAC;EACDC,KAAK,EAAE;IACLF,QAAQ,EAAE,iBAAiB;IAC3BC,SAAS,EAAE;EACb;AACF,CAAC;AAED,OAAO,MAAME,2BAA2B,GAAG,KAAK;AAChD,OAAO,MAAMC,yBAAyB,GAAG,GAAG","ignoreList":[]}
|
|
@@ -7,9 +7,11 @@ import { useEnsureRoom, useMediaDeviceSelect } from '@livekit/components-react';
|
|
|
7
7
|
import { useAtom, useAtomValue, useSetAtom } from 'jotai';
|
|
8
8
|
import { state } from '../../../conversation';
|
|
9
9
|
import { useCreateConversation } from '../../useCreateConversation';
|
|
10
|
+
import { useSpeechActivityDetector } from '../../useSpeechActivityDetector';
|
|
10
11
|
import { useEmitConversationEvent } from '../../useConversationEvents/useEmitConversationEvent';
|
|
11
12
|
import { useToolCallingRuntime } from '../../useTools/runtime/useToolCallingRuntime';
|
|
12
13
|
import { checkIsTurnDetectionData, checkIsInactivityWarningData, checkIsInactivityTimeoutData, checkIsToolCallsData, createLivekitToolAdapter, decodeDataPayload, findJoinedAgentParticipant, mergeTranscriptions, publishConversationDataMessage, safeStringify, shouldHandleParticipantConnected } from './utils';
|
|
14
|
+
import { ACOUSTIC_USER_HANGOVER_MS, ACOUSTIC_USER_THRESHOLD_RMS } from './constants';
|
|
13
15
|
export function useConversation(_ref) {
|
|
14
16
|
var _conversation$data2;
|
|
15
17
|
let _ref$autoJoin = _ref.autoJoin,
|
|
@@ -68,8 +70,11 @@ export function useConversation(_ref) {
|
|
|
68
70
|
const setAgentActivityState = useSetAtom(state.agentActivityState);
|
|
69
71
|
const setUserActivityState = useSetAtom(state.userActivityState);
|
|
70
72
|
const emitEvent = useEmitConversationEvent();
|
|
71
|
-
const userStopRef = useRef(null);
|
|
72
73
|
const inactivityTimeoutRef = useRef(false);
|
|
74
|
+
const acousticPhaseRef = useRef('idle');
|
|
75
|
+
const acousticT0Ref = useRef(null);
|
|
76
|
+
const latestTurnMetadataRef = useRef({});
|
|
77
|
+
const isConnectedRef = useRef(false);
|
|
73
78
|
const timer = useTimer({
|
|
74
79
|
autoStart: false,
|
|
75
80
|
onExpire: handleExpire,
|
|
@@ -176,14 +181,11 @@ export function useConversation(_ref) {
|
|
|
176
181
|
switch (participantKind) {
|
|
177
182
|
case 'STANDARD':
|
|
178
183
|
if (eventState === 'listening') {
|
|
179
|
-
|
|
180
|
-
ts: performance.now(),
|
|
184
|
+
latestTurnMetadataRef.current = {
|
|
181
185
|
turnDetectionStrategy: data.turnDetectionStrategy,
|
|
182
186
|
sequence: data.sequence,
|
|
183
187
|
speechId: data.speechId
|
|
184
188
|
};
|
|
185
|
-
} else {
|
|
186
|
-
userStopRef.current = null;
|
|
187
189
|
}
|
|
188
190
|
emitEvent(eventState === 'speaking' ? 'userSpeakStart' : 'userSpeakStop', {
|
|
189
191
|
conversationId: conversationId
|
|
@@ -191,16 +193,11 @@ export function useConversation(_ref) {
|
|
|
191
193
|
setUserActivityState(eventState);
|
|
192
194
|
break;
|
|
193
195
|
case 'AGENT':
|
|
194
|
-
if (
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
turnDetectionStrategy: userStopRef.current.turnDetectionStrategy,
|
|
200
|
-
sequence: userStopRef.current.sequence,
|
|
201
|
-
speechId: data.speechId ?? userStopRef.current.speechId
|
|
202
|
-
});
|
|
203
|
-
userStopRef.current = null;
|
|
196
|
+
if (data.speechId) {
|
|
197
|
+
latestTurnMetadataRef.current = {
|
|
198
|
+
...latestTurnMetadataRef.current,
|
|
199
|
+
speechId: data.speechId
|
|
200
|
+
};
|
|
204
201
|
}
|
|
205
202
|
emitEvent(eventState === 'speaking' ? 'agentSpeakStart' : 'agentSpeakStop', {
|
|
206
203
|
conversationId: conversationId
|
|
@@ -209,18 +206,64 @@ export function useConversation(_ref) {
|
|
|
209
206
|
break;
|
|
210
207
|
}
|
|
211
208
|
}
|
|
212
|
-
function
|
|
209
|
+
function handleAcousticUserOnset() {
|
|
210
|
+
if (!isConnectedRef.current) {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
if (acousticPhaseRef.current === 'waitingForAgent') {
|
|
214
|
+
acousticPhaseRef.current = 'idle';
|
|
215
|
+
acousticT0Ref.current = null;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
function handleAcousticUserOffset(timestampMs) {
|
|
219
|
+
if (!isConnectedRef.current || acousticPhaseRef.current !== 'idle') {
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
acousticT0Ref.current = timestampMs - ACOUSTIC_USER_HANGOVER_MS;
|
|
223
|
+
acousticPhaseRef.current = 'waitingForAgent';
|
|
224
|
+
}
|
|
225
|
+
function handleAcousticAgentOnset(timestampMs) {
|
|
213
226
|
var _conversationRef$curr2;
|
|
214
|
-
|
|
227
|
+
if (!isConnectedRef.current || acousticPhaseRef.current !== 'waitingForAgent' || acousticT0Ref.current == null) {
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
const latencyMs = timestampMs - acousticT0Ref.current;
|
|
231
|
+
acousticT0Ref.current = null;
|
|
232
|
+
acousticPhaseRef.current = 'busy';
|
|
233
|
+
if (latencyMs < 0 || latencyMs > 15000) {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
emitEvent('responseLatency', {
|
|
215
237
|
conversationId: (_conversationRef$curr2 = conversationRef.current) == null ? void 0 : _conversationRef$curr2.id,
|
|
238
|
+
latencyMs,
|
|
239
|
+
turnDetectionStrategy: latestTurnMetadataRef.current.turnDetectionStrategy,
|
|
240
|
+
sequence: latestTurnMetadataRef.current.sequence,
|
|
241
|
+
speechId: latestTurnMetadataRef.current.speechId
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
useSpeechActivityDetector({
|
|
245
|
+
source: 'user',
|
|
246
|
+
onSpeechStart: handleAcousticUserOnset,
|
|
247
|
+
onSpeechEnd: handleAcousticUserOffset,
|
|
248
|
+
thresholdRms: ACOUSTIC_USER_THRESHOLD_RMS,
|
|
249
|
+
hangoverMs: ACOUSTIC_USER_HANGOVER_MS
|
|
250
|
+
});
|
|
251
|
+
useSpeechActivityDetector({
|
|
252
|
+
source: 'agent',
|
|
253
|
+
onSpeechStart: handleAcousticAgentOnset
|
|
254
|
+
});
|
|
255
|
+
function handleInactivityWarningEvent(data) {
|
|
256
|
+
var _conversationRef$curr3;
|
|
257
|
+
emitEvent('inactivityWarning', {
|
|
258
|
+
conversationId: (_conversationRef$curr3 = conversationRef.current) == null ? void 0 : _conversationRef$curr3.id,
|
|
216
259
|
gracePeriodSec: data.grace_period_sec
|
|
217
260
|
});
|
|
218
261
|
}
|
|
219
262
|
function handleInactivityTimeoutEvent(_data) {
|
|
220
|
-
var _conversationRef$
|
|
263
|
+
var _conversationRef$curr4;
|
|
221
264
|
inactivityTimeoutRef.current = true;
|
|
222
265
|
emitEvent('inactivityTimeout', {
|
|
223
|
-
conversationId: (_conversationRef$
|
|
266
|
+
conversationId: (_conversationRef$curr4 = conversationRef.current) == null ? void 0 : _conversationRef$curr4.id
|
|
224
267
|
});
|
|
225
268
|
}
|
|
226
269
|
async function handleToolCallsEvent(data) {
|
|
@@ -256,11 +299,12 @@ export function useConversation(_ref) {
|
|
|
256
299
|
}
|
|
257
300
|
}
|
|
258
301
|
function handleConnectedEvent() {
|
|
259
|
-
var _conversationRef$
|
|
302
|
+
var _conversationRef$curr5;
|
|
303
|
+
isConnectedRef.current = true;
|
|
260
304
|
setUserConnectionState('joined');
|
|
261
305
|
setAgentConnectionState('joining');
|
|
262
306
|
emitEvent('callStarted', {
|
|
263
|
-
conversationId: (_conversationRef$
|
|
307
|
+
conversationId: (_conversationRef$curr5 = conversationRef.current) == null ? void 0 : _conversationRef$curr5.id
|
|
264
308
|
});
|
|
265
309
|
}
|
|
266
310
|
async function handleEncryptionErrorEvent(error) {
|
|
@@ -268,7 +312,10 @@ export function useConversation(_ref) {
|
|
|
268
312
|
setConversationStatus('error');
|
|
269
313
|
}
|
|
270
314
|
function handleDisconnectedEvent(reason) {
|
|
271
|
-
|
|
315
|
+
isConnectedRef.current = false;
|
|
316
|
+
acousticPhaseRef.current = 'idle';
|
|
317
|
+
acousticT0Ref.current = null;
|
|
318
|
+
latestTurnMetadataRef.current = {};
|
|
272
319
|
setAgentActivityState('idle');
|
|
273
320
|
setAgentConnectionState('idle');
|
|
274
321
|
setUserActivityState('idle');
|
|
@@ -296,18 +343,18 @@ export function useConversation(_ref) {
|
|
|
296
343
|
}
|
|
297
344
|
}
|
|
298
345
|
function handleAgentJoin(participant) {
|
|
299
|
-
var _conversationRef$
|
|
346
|
+
var _conversationRef$curr6;
|
|
300
347
|
setAgentConnectionState('joined');
|
|
301
348
|
emitEvent('agentJoined', {
|
|
302
|
-
conversationId: (_conversationRef$
|
|
349
|
+
conversationId: (_conversationRef$curr6 = conversationRef.current) == null ? void 0 : _conversationRef$curr6.id,
|
|
303
350
|
participant
|
|
304
351
|
});
|
|
305
352
|
}
|
|
306
353
|
function handleParticipantDisconnectedEvent(participant) {
|
|
307
|
-
var _conversationRef$
|
|
354
|
+
var _conversationRef$curr7;
|
|
308
355
|
setAgentConnectionState('left');
|
|
309
356
|
emitEvent('agentLeft', {
|
|
310
|
-
conversationId: (_conversationRef$
|
|
357
|
+
conversationId: (_conversationRef$curr7 = conversationRef.current) == null ? void 0 : _conversationRef$curr7.id,
|
|
311
358
|
participant
|
|
312
359
|
});
|
|
313
360
|
}
|
|
@@ -316,13 +363,13 @@ export function useConversation(_ref) {
|
|
|
316
363
|
return;
|
|
317
364
|
}
|
|
318
365
|
try {
|
|
319
|
-
var _conversationRef$
|
|
366
|
+
var _conversationRef$curr8;
|
|
320
367
|
setUserConnectionState('leaving');
|
|
321
368
|
await (room == null ? void 0 : room.disconnect(true));
|
|
322
369
|
setConversationStatus('destroyed');
|
|
323
370
|
setJoinedAt(undefined);
|
|
324
371
|
emitEvent('callEnded', {
|
|
325
|
-
conversationId: (_conversationRef$
|
|
372
|
+
conversationId: (_conversationRef$curr8 = conversationRef.current) == null ? void 0 : _conversationRef$curr8.id
|
|
326
373
|
});
|
|
327
374
|
} catch (error) {
|
|
328
375
|
console.error('Failed to leave', error);
|
|
@@ -330,18 +377,18 @@ export function useConversation(_ref) {
|
|
|
330
377
|
}
|
|
331
378
|
}
|
|
332
379
|
async function handleExpire() {
|
|
333
|
-
var _conversationRef$
|
|
380
|
+
var _conversationRef$curr9, _conversationRef$curr0;
|
|
334
381
|
emitEvent('timeExceeded', {
|
|
335
|
-
conversationId: (_conversationRef$
|
|
336
|
-
limit: (_conversationRef$
|
|
382
|
+
conversationId: (_conversationRef$curr9 = conversationRef.current) == null ? void 0 : _conversationRef$curr9.id,
|
|
383
|
+
limit: (_conversationRef$curr0 = conversationRef.current) == null ? void 0 : _conversationRef$curr0.limit
|
|
337
384
|
});
|
|
338
385
|
await leave();
|
|
339
386
|
setConversationStatus('exceeded');
|
|
340
387
|
}
|
|
341
388
|
async function interrupt() {
|
|
342
|
-
var _conversationRef$
|
|
389
|
+
var _conversationRef$curr1;
|
|
343
390
|
emitEvent('interrupt', {
|
|
344
|
-
conversationId: (_conversationRef$
|
|
391
|
+
conversationId: (_conversationRef$curr1 = conversationRef.current) == null ? void 0 : _conversationRef$curr1.id
|
|
345
392
|
});
|
|
346
393
|
await publishConversationDataMessage(room, {}, 'interrupt');
|
|
347
394
|
}
|
|
@@ -351,7 +398,7 @@ export function useConversation(_ref) {
|
|
|
351
398
|
}, 'inactivity_dismiss');
|
|
352
399
|
}
|
|
353
400
|
async function send(message, attachments) {
|
|
354
|
-
var _conversationRef$
|
|
401
|
+
var _conversationRef$curr10;
|
|
355
402
|
if (attachments === void 0) {
|
|
356
403
|
attachments = [];
|
|
357
404
|
}
|
|
@@ -362,7 +409,7 @@ export function useConversation(_ref) {
|
|
|
362
409
|
}
|
|
363
410
|
}));
|
|
364
411
|
emitEvent('userSendMessage', {
|
|
365
|
-
conversationId: (_conversationRef$
|
|
412
|
+
conversationId: (_conversationRef$curr10 = conversationRef.current) == null ? void 0 : _conversationRef$curr10.id,
|
|
366
413
|
message
|
|
367
414
|
});
|
|
368
415
|
}
|