@unctad-ai/voice-agent-core 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/config/defaults.d.ts +128 -0
  2. package/dist/config/defaults.d.ts.map +1 -0
  3. package/dist/config/defaults.js +169 -0
  4. package/dist/config/defaults.js.map +1 -0
  5. package/dist/contexts/SiteConfigContext.d.ts +7 -0
  6. package/dist/contexts/SiteConfigContext.d.ts.map +1 -0
  7. package/dist/contexts/SiteConfigContext.js +14 -0
  8. package/dist/contexts/SiteConfigContext.js.map +1 -0
  9. package/dist/hooks/useAudioPlayback.d.ts +18 -0
  10. package/dist/hooks/useAudioPlayback.d.ts.map +1 -0
  11. package/dist/hooks/useAudioPlayback.js +482 -0
  12. package/dist/hooks/useAudioPlayback.js.map +1 -0
  13. package/dist/hooks/useTenVAD.d.ts +42 -0
  14. package/dist/hooks/useTenVAD.d.ts.map +1 -0
  15. package/dist/hooks/useTenVAD.js +318 -0
  16. package/dist/hooks/useTenVAD.js.map +1 -0
  17. package/dist/hooks/useVoiceAgent.d.ts +50 -0
  18. package/dist/hooks/useVoiceAgent.d.ts.map +1 -0
  19. package/dist/hooks/useVoiceAgent.js +1005 -0
  20. package/dist/hooks/useVoiceAgent.js.map +1 -0
  21. package/dist/index.d.ts +14 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.js +10 -0
  24. package/dist/index.js.map +1 -0
  25. package/dist/services/voiceApi.d.ts +22 -0
  26. package/dist/services/voiceApi.d.ts.map +1 -0
  27. package/dist/services/voiceApi.js +93 -0
  28. package/dist/services/voiceApi.js.map +1 -0
  29. package/dist/types/config.d.ts +53 -0
  30. package/dist/types/config.d.ts.map +1 -0
  31. package/dist/types/config.js +2 -0
  32. package/dist/types/config.js.map +1 -0
  33. package/dist/types/errors.d.ts +2 -0
  34. package/dist/types/errors.d.ts.map +1 -0
  35. package/dist/types/errors.js +2 -0
  36. package/dist/types/errors.js.map +1 -0
  37. package/dist/types/index.d.ts +5 -0
  38. package/dist/types/index.d.ts.map +1 -0
  39. package/dist/types/index.js +5 -0
  40. package/dist/types/index.js.map +1 -0
  41. package/dist/types/settings.d.ts +26 -0
  42. package/dist/types/settings.d.ts.map +1 -0
  43. package/dist/types/settings.js +2 -0
  44. package/dist/types/settings.js.map +1 -0
  45. package/dist/types/voice.d.ts +20 -0
  46. package/dist/types/voice.d.ts.map +1 -0
  47. package/dist/types/voice.js +11 -0
  48. package/dist/types/voice.js.map +1 -0
  49. package/dist/utils/audioUtils.d.ts +2 -0
  50. package/dist/utils/audioUtils.d.ts.map +1 -0
  51. package/dist/utils/audioUtils.js +30 -0
  52. package/dist/utils/audioUtils.js.map +1 -0
  53. package/dist/utils/wavParser.d.ts +27 -0
  54. package/dist/utils/wavParser.d.ts.map +1 -0
  55. package/dist/utils/wavParser.js +75 -0
  56. package/dist/utils/wavParser.js.map +1 -0
  57. package/package.json +47 -0
@@ -0,0 +1,318 @@
1
+ /**
2
+ * useTenVAD — React hook wrapping TEN VAD (WebAssembly) for browser voice
3
+ * activity detection. Drop-in replacement for `useMicVAD` from
4
+ * `@ricky0123/vad-react` with the same callback/state contract.
5
+ *
6
+ * Architecture:
7
+ * AudioContext (16 kHz) → AudioWorkletNode (ten-vad-processor.js)
8
+ * → postMessage Float32 chunks → main-thread WASM inference
9
+ * → speech segmentation state machine → callbacks
10
+ */
11
+ import { useCallback, useEffect, useRef, useState } from 'react';
12
+ // ---------------------------------------------------------------------------
13
+ // Helpers
14
+ // ---------------------------------------------------------------------------
15
+ /** Convert Float32 [-1,1] to Int16 for TEN VAD */
16
+ function float32ToInt16(f32) {
17
+ const i16 = new Int16Array(f32.length);
18
+ for (let i = 0; i < f32.length; i++) {
19
+ const s = Math.max(-1, Math.min(1, f32[i]));
20
+ i16[i] = s < 0 ? s * 0x8000 : s * 0x7fff;
21
+ }
22
+ return i16;
23
+ }
24
+ // ---------------------------------------------------------------------------
25
+ // Hook
26
+ // ---------------------------------------------------------------------------
27
+ export function useTenVAD(options = {}) {
28
+ const { startOnLoad = false, hopSize = 256, threshold = 0.5, positiveSpeechThreshold = 0.6, negativeSpeechThreshold = 0.35, redemptionMs = 600, minSpeechMs = 500, preSpeechPadMs = 400, onSpeechStart, onSpeechEnd, onVADMisfire, onFrameProcessed, } = options;
29
+ const [loading, setLoading] = useState(true);
30
+ const [errored, setErrored] = useState(false);
31
+ // Stable refs for callbacks so we never re-create the worklet listener
32
+ const cbRef = useRef({ onSpeechStart, onSpeechEnd, onVADMisfire, onFrameProcessed });
33
+ useEffect(() => {
34
+ cbRef.current = { onSpeechStart, onSpeechEnd, onVADMisfire, onFrameProcessed };
35
+ });
36
+ // WASM module + handle
37
+ const moduleRef = useRef(null);
38
+ const vadHandleRef = useRef(0);
39
+ // Audio graph
40
+ const audioCtxRef = useRef(null);
41
+ const workletNodeRef = useRef(null);
42
+ const streamRef = useRef(null);
43
+ // Speech segmentation state
44
+ const segStateRef = useRef('idle');
45
+ const speechFramesRef = useRef(0);
46
+ const redemptionFramesRef = useRef(0);
47
+ const audioChunksRef = useRef([]);
48
+ const preSpeechBufferRef = useRef([]);
49
+ // Compute frame counts from ms
50
+ const frameDurationMs = (hopSize / 16000) * 1000; // e.g. 256/16000*1000 = 16 ms
51
+ const redemptionFrames = Math.ceil(redemptionMs / frameDurationMs);
52
+ const minSpeechFrames = Math.ceil(minSpeechMs / frameDurationMs);
53
+ const preSpeechFrames = Math.ceil(preSpeechPadMs / frameDurationMs);
54
+ // Active flag to prevent work after unmount
55
+ const activeRef = useRef(false);
56
+ // -----------------------------------------------------------------------
57
+ // WASM memory helpers (allocated once per module lifetime)
58
+ // -----------------------------------------------------------------------
59
+ const ptrsRef = useRef(null);
60
+ const allocPtrs = useCallback((mod) => {
61
+ if (ptrsRef.current)
62
+ return ptrsRef.current;
63
+ const audioPtr = mod._malloc(hopSize * 2); // Int16 = 2 bytes/sample
64
+ const probPtr = mod._malloc(4); // float
65
+ const flagPtr = mod._malloc(4); // int32
66
+ ptrsRef.current = { audioPtr, probPtr, flagPtr };
67
+ return ptrsRef.current;
68
+ }, [hopSize]);
69
+ const freePtrs = useCallback((mod) => {
70
+ if (!ptrsRef.current)
71
+ return;
72
+ mod._free(ptrsRef.current.audioPtr);
73
+ mod._free(ptrsRef.current.probPtr);
74
+ mod._free(ptrsRef.current.flagPtr);
75
+ ptrsRef.current = null;
76
+ }, []);
77
+ // -----------------------------------------------------------------------
78
+ // Process a single frame from the AudioWorklet
79
+ // -----------------------------------------------------------------------
80
+ const processFrame = useCallback((samples) => {
81
+ const mod = moduleRef.current;
82
+ if (!mod || !vadHandleRef.current)
83
+ return;
84
+ const ptrs = allocPtrs(mod);
85
+ const i16 = float32ToInt16(samples);
86
+ // Copy Int16 samples into WASM heap
87
+ mod.HEAP16.set(i16, ptrs.audioPtr >> 1);
88
+ const ret = mod._ten_vad_process(vadHandleRef.current, ptrs.audioPtr, hopSize, ptrs.probPtr, ptrs.flagPtr);
89
+ if (ret !== 0)
90
+ return;
91
+ const probability = mod.HEAPF32[ptrs.probPtr >> 2];
92
+ // Compute frame RMS for barge-in energy gating
93
+ let sumSq = 0;
94
+ for (let j = 0; j < samples.length; j++)
95
+ sumSq += samples[j] * samples[j];
96
+ const rms = Math.sqrt(sumSq / samples.length);
97
+ cbRef.current.onFrameProcessed?.({ isSpeech: probability, rms });
98
+ // ---- Speech segmentation state machine ----
99
+ const seg = segStateRef.current;
100
+ if (seg === 'idle') {
101
+ // Maintain rolling pre-speech buffer
102
+ preSpeechBufferRef.current.push(samples);
103
+ if (preSpeechBufferRef.current.length > preSpeechFrames) {
104
+ preSpeechBufferRef.current.shift();
105
+ }
106
+ if (probability >= positiveSpeechThreshold) {
107
+ segStateRef.current = 'speaking';
108
+ speechFramesRef.current = 1;
109
+ redemptionFramesRef.current = 0;
110
+ // Start audio accumulation with pre-speech pad
111
+ audioChunksRef.current = [...preSpeechBufferRef.current, samples];
112
+ preSpeechBufferRef.current = [];
113
+ cbRef.current.onSpeechStart?.();
114
+ }
115
+ }
116
+ else if (seg === 'speaking') {
117
+ speechFramesRef.current++;
118
+ audioChunksRef.current.push(samples);
119
+ if (probability < negativeSpeechThreshold) {
120
+ segStateRef.current = 'redemption';
121
+ redemptionFramesRef.current = 1;
122
+ }
123
+ }
124
+ else if (seg === 'redemption') {
125
+ speechFramesRef.current++;
126
+ redemptionFramesRef.current++;
127
+ audioChunksRef.current.push(samples);
128
+ if (probability >= positiveSpeechThreshold) {
129
+ // Speech resumed — go back
130
+ segStateRef.current = 'speaking';
131
+ redemptionFramesRef.current = 0;
132
+ }
133
+ else if (redemptionFramesRef.current >= redemptionFrames) {
134
+ // Speech truly ended
135
+ segStateRef.current = 'idle';
136
+ if (speechFramesRef.current >= minSpeechFrames) {
137
+ // Concatenate all chunks into one Float32Array
138
+ const totalLen = audioChunksRef.current.reduce((s, c) => s + c.length, 0);
139
+ const merged = new Float32Array(totalLen);
140
+ let offset = 0;
141
+ for (const chunk of audioChunksRef.current) {
142
+ merged.set(chunk, offset);
143
+ offset += chunk.length;
144
+ }
145
+ cbRef.current.onSpeechEnd?.(merged);
146
+ }
147
+ else {
148
+ cbRef.current.onVADMisfire?.();
149
+ }
150
+ audioChunksRef.current = [];
151
+ speechFramesRef.current = 0;
152
+ redemptionFramesRef.current = 0;
153
+ }
154
+ }
155
+ }, [
156
+ hopSize,
157
+ allocPtrs,
158
+ positiveSpeechThreshold,
159
+ negativeSpeechThreshold,
160
+ redemptionFrames,
161
+ minSpeechFrames,
162
+ preSpeechFrames,
163
+ ]);
164
+ // -----------------------------------------------------------------------
165
+ // Stable ref for processFrame so worklet listener never goes stale
166
+ // -----------------------------------------------------------------------
167
+ const processFrameRef = useRef(processFrame);
168
+ useEffect(() => {
169
+ processFrameRef.current = processFrame;
170
+ });
171
+ // -----------------------------------------------------------------------
172
+ // Load WASM module once
173
+ // -----------------------------------------------------------------------
174
+ useEffect(() => {
175
+ let cancelled = false;
176
+ (async () => {
177
+ try {
178
+ // Dynamic import of the Emscripten glue — Vite bundles it as ESM
179
+ // Vite alias 'ten-vad-glue' → node_modules/@gooney-001/ten-vad-lib/ten_vad.js
180
+ const { default: createVADModule } = await import(
181
+ /* @vite-ignore */
182
+ 'ten-vad-glue');
183
+ const mod = await createVADModule({
184
+ locateFile: (filename) => {
185
+ if (filename.endsWith('.wasm'))
186
+ return '/ten_vad.wasm';
187
+ return filename;
188
+ },
189
+ });
190
+ if (cancelled)
191
+ return;
192
+ // Create VAD handle
193
+ const handlePtr = mod._malloc(4);
194
+ const ret = mod._ten_vad_create(handlePtr, hopSize, threshold);
195
+ if (ret !== 0) {
196
+ mod._free(handlePtr);
197
+ throw new Error('ten_vad_create failed');
198
+ }
199
+ const handle = mod.HEAP32[handlePtr >> 2];
200
+ mod._free(handlePtr);
201
+ moduleRef.current = mod;
202
+ vadHandleRef.current = handle;
203
+ setLoading(false);
204
+ }
205
+ catch (err) {
206
+ if (!cancelled) {
207
+ console.error('[useTenVAD] Failed to load WASM module:', err);
208
+ setErrored(err instanceof Error ? err : { message: String(err) });
209
+ setLoading(false);
210
+ }
211
+ }
212
+ })();
213
+ return () => {
214
+ cancelled = true;
215
+ };
216
+ }, [hopSize, threshold]);
217
+ // -----------------------------------------------------------------------
218
+ // start / pause
219
+ // -----------------------------------------------------------------------
220
+ const start = useCallback(async () => {
221
+ if (activeRef.current)
222
+ return;
223
+ activeRef.current = true;
224
+ try {
225
+ const stream = await navigator.mediaDevices.getUserMedia({
226
+ audio: {
227
+ sampleRate: 16000,
228
+ channelCount: 1,
229
+ echoCancellation: true,
230
+ noiseSuppression: true,
231
+ },
232
+ });
233
+ streamRef.current = stream;
234
+ // Create AudioContext at 16 kHz
235
+ const ctx = new AudioContext({ sampleRate: 16000 });
236
+ audioCtxRef.current = ctx;
237
+ // Load the AudioWorklet processor via blob URL to bypass stale HTTP cache
238
+ const workletRes = await fetch('/ten-vad-processor.js', { cache: 'no-store' });
239
+ const workletBlob = new Blob([await workletRes.text()], { type: 'application/javascript' });
240
+ const workletUrl = URL.createObjectURL(workletBlob);
241
+ await ctx.audioWorklet.addModule(workletUrl);
242
+ URL.revokeObjectURL(workletUrl);
243
+ const source = ctx.createMediaStreamSource(stream);
244
+ const worklet = new AudioWorkletNode(ctx, 'ten-vad-processor', {
245
+ processorOptions: { hopSize },
246
+ });
247
+ worklet.port.onmessage = (e) => {
248
+ if (e.data?.type === 'audio') {
249
+ processFrameRef.current(e.data.samples);
250
+ }
251
+ };
252
+ source.connect(worklet);
253
+ // Don't connect to destination — we don't want to hear the mic
254
+ workletNodeRef.current = worklet;
255
+ }
256
+ catch (err) {
257
+ activeRef.current = false;
258
+ console.error('[useTenVAD] start failed:', err);
259
+ setErrored(err instanceof Error ? err : { message: String(err) });
260
+ }
261
+ }, [hopSize]);
262
+ const pause = useCallback(() => {
263
+ activeRef.current = false;
264
+ // Tell worklet to stop
265
+ workletNodeRef.current?.port.postMessage({ type: 'stop' });
266
+ workletNodeRef.current?.disconnect();
267
+ workletNodeRef.current = null;
268
+ // Stop mic
269
+ streamRef.current?.getTracks().forEach((t) => t.stop());
270
+ streamRef.current = null;
271
+ // Close audio context
272
+ audioCtxRef.current?.close();
273
+ audioCtxRef.current = null;
274
+ // Reset segmentation state
275
+ segStateRef.current = 'idle';
276
+ speechFramesRef.current = 0;
277
+ redemptionFramesRef.current = 0;
278
+ audioChunksRef.current = [];
279
+ preSpeechBufferRef.current = [];
280
+ }, []);
281
+ // -----------------------------------------------------------------------
282
+ // Auto-start if requested
283
+ // -----------------------------------------------------------------------
284
+ useEffect(() => {
285
+ if (startOnLoad && !loading && !errored) {
286
+ start();
287
+ }
288
+ }, [startOnLoad, loading, errored, start]);
289
+ // -----------------------------------------------------------------------
290
+ // Cleanup on unmount
291
+ // -----------------------------------------------------------------------
292
+ useEffect(() => {
293
+ return () => {
294
+ activeRef.current = false;
295
+ workletNodeRef.current?.port.postMessage({ type: 'stop' });
296
+ workletNodeRef.current?.disconnect();
297
+ workletNodeRef.current = null;
298
+ streamRef.current?.getTracks().forEach((t) => t.stop());
299
+ streamRef.current = null;
300
+ audioCtxRef.current?.close();
301
+ audioCtxRef.current = null;
302
+ // Destroy WASM handle
303
+ const mod = moduleRef.current;
304
+ if (mod && vadHandleRef.current) {
305
+ const handlePtr = mod._malloc(4);
306
+ mod.HEAP32[handlePtr >> 2] = vadHandleRef.current;
307
+ mod._ten_vad_destroy(handlePtr);
308
+ mod._free(handlePtr);
309
+ vadHandleRef.current = 0;
310
+ }
311
+ if (mod) {
312
+ freePtrs(mod);
313
+ }
314
+ };
315
+ }, [freePtrs]);
316
+ return { loading, errored, start, pause };
317
+ }
318
+ //# sourceMappingURL=useTenVAD.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTenVAD.js","sourceRoot":"","sources":["../../src/hooks/useTenVAD.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ import type { VoiceState, VoiceMessage } from '../types/voice';
2
+ import type { VoiceErrorType } from '../types/errors';
3
+ import type { VoiceSettings } from '../types/settings';
4
+ export interface PipelineTimings {
5
+ pipeline: 'voice' | 'text';
6
+ speechDurationMs?: number;
7
+ wavSizeBytes?: number;
8
+ wavEncodeMs?: number;
9
+ sttMs?: number;
10
+ sttRetries?: number;
11
+ llmSendMs?: number;
12
+ llmWaitMs?: number;
13
+ llmTotalMs?: number;
14
+ ttsMs?: number;
15
+ ttsFirstChunkMs?: number;
16
+ ttsTotalMs?: number;
17
+ playbackMs?: number;
18
+ totalMs: number;
19
+ timestamp: number;
20
+ }
21
+ export interface UseVoiceAgentOptions {
22
+ bargeInEnabled?: boolean;
23
+ /** Voice settings — injected from host app's VoiceSettingsContext */
24
+ settings: VoiceSettings;
25
+ /** Ref tracking current volume (updated by settings provider) */
26
+ volumeRef: React.RefObject<number>;
27
+ /** Ref tracking current playback speed (updated by settings provider) */
28
+ speedRef: React.RefObject<number>;
29
+ }
30
+ export declare function useVoiceAgent({ bargeInEnabled, settings, volumeRef, speedRef, }: UseVoiceAgentOptions): {
31
+ state: VoiceState;
32
+ start: () => void;
33
+ stop: (force?: boolean) => void;
34
+ loading: boolean;
35
+ error: false | object;
36
+ voiceError: VoiceErrorType;
37
+ dismissError: () => void;
38
+ messages: VoiceMessage[];
39
+ currentTranscript: string;
40
+ isLLMLoading: boolean;
41
+ getAmplitude: () => number;
42
+ initContext: () => void;
43
+ applyVolume: (v: number) => void;
44
+ analyser: AnalyserNode | null;
45
+ sendTextMessage: (text: string) => Promise<void>;
46
+ lastTimings: PipelineTimings | null;
47
+ sessionEnded: boolean;
48
+ settings: VoiceSettings;
49
+ };
50
+ //# sourceMappingURL=useVoiceAgent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useVoiceAgent.d.ts","sourceRoot":"","sources":["../../src/hooks/useVoiceAgent.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAoLvD,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,OAAO,GAAG,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AA0BD,MAAM,WAAW,oBAAoB;IACnC,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,qEAAqE;IACrE,QAAQ,EAAE,aAAa,CAAC;IACxB,iEAAiE;IACjE,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IACnC,yEAAyE;IACzE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;CACnC;AAcD,wBAAgB,aAAa,CAAC,EAC5B,cAAqB,EACrB,QAAQ,EACR,SAAS,EACT,QAAQ,GACT,EAAE,oBAAoB;;;mBAoyBV,OAAO;;;;;;;;;;;;4BA6BH,MAAM;;;;EAmEtB"}