@adonis-agora/agent
Version:
Governed, durable-backed AI agent (chat + tool-calling + governance) for AdonisJS — part of the Agora ecosystem.
92 lines • 3.32 kB
JavaScript
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
function getRecognitionCtor() {
if (typeof window === 'undefined')
return null;
const scope = window;
return scope.SpeechRecognition ?? scope.webkitSpeechRecognition ?? null;
}
/**
* Tiny wrapper around the Web Speech API. `start()` opens the mic and
* streams interim transcripts via `onInterimTranscript`; on a finalized
* chunk it fires `onFinalTranscript`. `isSupported` is false where the
* API is missing (e.g. Firefox) — callers should hide the mic button.
*/
export function useSpeechRecognition({ lang = 'en-US', onFinalTranscript, onInterimTranscript, }) {
const recognitionRef = useRef(null);
const [isListening, setIsListening] = useState(false);
const ctor = useMemo(() => getRecognitionCtor(), []);
const isSupported = ctor !== null;
// Keep latest callbacks in refs so we don't tear down the recognition
// object when they change identity each render.
const finalRef = useRef(onFinalTranscript);
const interimRef = useRef(onInterimTranscript);
finalRef.current = onFinalTranscript;
interimRef.current = onInterimTranscript;
useEffect(() => {
if (!ctor)
return;
const recognition = new ctor();
recognition.lang = lang;
recognition.continuous = false;
recognition.interimResults = true;
recognition.onresult = (event) => {
let interim = '';
for (let i = event.resultIndex; i < event.results.length; i++) {
const result = event.results[i];
if (!result)
continue;
const text = result[0]?.transcript ?? '';
if (result.isFinal) {
finalRef.current(text);
}
else {
interim += text;
}
}
if (interim && interimRef.current)
interimRef.current(interim);
};
recognition.onerror = (event) => {
if (event.error !== 'no-speech' && event.error !== 'aborted') {
console.warn('SpeechRecognition error', event.error);
}
setIsListening(false);
};
recognition.onend = () => setIsListening(false);
recognitionRef.current = recognition;
return () => {
try {
recognition.stop();
}
catch {
/* engine already stopped */
}
recognitionRef.current = null;
};
}, [ctor, lang]);
const start = useCallback(() => {
const recognition = recognitionRef.current;
if (!recognition)
return;
try {
recognition.start();
setIsListening(true);
}
catch (error) {
console.warn('SpeechRecognition start failed', error);
}
}, []);
const stop = useCallback(() => {
const recognition = recognitionRef.current;
if (!recognition)
return;
try {
recognition.stop();
}
catch {
/* already stopped */
}
}, []);
return { isSupported, isListening, start, stop };
}
//# sourceMappingURL=use-speech-recognition.js.map