mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-18 17:30:16 +01:00
🌐 feat: disable external engine if not configured (#3313)
* feat: disable external engine if not configured * remove comment
This commit is contained in:
parent
237a0de8b6
commit
73dbf3eb20
4 changed files with 71 additions and 34 deletions
|
|
@ -15,37 +15,43 @@ const getCustomConfig = require('~/server/services/Config/getCustomConfig');
|
||||||
async function getCustomConfigSpeech(req, res) {
|
async function getCustomConfigSpeech(req, res) {
|
||||||
try {
|
try {
|
||||||
const customConfig = await getCustomConfig();
|
const customConfig = await getCustomConfig();
|
||||||
|
const sttExternal = !!customConfig.speech?.stt;
|
||||||
|
const ttsExternal = !!customConfig.speech?.tts;
|
||||||
|
let settings = {
|
||||||
|
sttExternal,
|
||||||
|
ttsExternal,
|
||||||
|
};
|
||||||
|
|
||||||
if (!customConfig || !customConfig.speech?.speechTab) {
|
if (!customConfig || !customConfig.speech?.speechTab) {
|
||||||
throw new Error('Configuration or speechTab schema is missing');
|
return res.status(200).send(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ttsSchema = customConfig.speech?.speechTab;
|
const speechTab = customConfig.speech.speechTab;
|
||||||
let settings = {};
|
|
||||||
|
|
||||||
if (ttsSchema.advancedMode !== undefined) {
|
if (speechTab.advancedMode !== undefined) {
|
||||||
settings.advancedMode = ttsSchema.advancedMode;
|
settings.advancedMode = speechTab.advancedMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ttsSchema.speechToText) {
|
if (speechTab.speechToText) {
|
||||||
for (const key in ttsSchema.speechToText) {
|
for (const key in speechTab.speechToText) {
|
||||||
if (ttsSchema.speechToText[key] !== undefined) {
|
if (speechTab.speechToText[key] !== undefined) {
|
||||||
settings[key] = ttsSchema.speechToText[key];
|
settings[key] = speechTab.speechToText[key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ttsSchema.textToSpeech) {
|
if (speechTab.textToSpeech) {
|
||||||
for (const key in ttsSchema.textToSpeech) {
|
for (const key in speechTab.textToSpeech) {
|
||||||
if (ttsSchema.textToSpeech[key] !== undefined) {
|
if (speechTab.textToSpeech[key] !== undefined) {
|
||||||
settings[key] = ttsSchema.textToSpeech[key];
|
settings[key] = speechTab.textToSpeech[key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.status(200).send(settings);
|
return res.status(200).send(settings);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(200).send();
|
console.error('Failed to get custom config speech settings:', error);
|
||||||
|
res.status(500).send('Internal Server Error');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,23 @@
|
||||||
|
import React from 'react';
|
||||||
import { useRecoilState } from 'recoil';
|
import { useRecoilState } from 'recoil';
|
||||||
import { Dropdown } from '~/components/ui';
|
import { Dropdown } from '~/components/ui';
|
||||||
import { useLocalize } from '~/hooks';
|
import { useLocalize } from '~/hooks';
|
||||||
import store from '~/store';
|
import store from '~/store';
|
||||||
|
|
||||||
export default function EngineSTTDropdown() {
|
interface EngineSTTDropdownProps {
|
||||||
|
external: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const EngineSTTDropdown: React.FC<EngineSTTDropdownProps> = ({ external }) => {
|
||||||
const localize = useLocalize();
|
const localize = useLocalize();
|
||||||
const [engineSTT, setEngineSTT] = useRecoilState<string>(store.engineSTT);
|
const [engineSTT, setEngineSTT] = useRecoilState<string>(store.engineSTT);
|
||||||
const endpointOptions = [
|
|
||||||
|
const endpointOptions = external
|
||||||
|
? [
|
||||||
{ value: 'browser', display: localize('com_nav_browser') },
|
{ value: 'browser', display: localize('com_nav_browser') },
|
||||||
{ value: 'external', display: localize('com_nav_external') },
|
{ value: 'external', display: localize('com_nav_external') },
|
||||||
];
|
]
|
||||||
|
: [{ value: 'browser', display: localize('com_nav_browser') }];
|
||||||
|
|
||||||
const handleSelect = (value: string) => {
|
const handleSelect = (value: string) => {
|
||||||
setEngineSTT(value);
|
setEngineSTT(value);
|
||||||
|
|
@ -28,4 +36,6 @@ export default function EngineSTTDropdown() {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export default EngineSTTDropdown;
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,8 @@ function Speech() {
|
||||||
const { data } = useGetCustomConfigSpeechQuery();
|
const { data } = useGetCustomConfigSpeechQuery();
|
||||||
const isSmallScreen = useMediaQuery('(max-width: 767px)');
|
const isSmallScreen = useMediaQuery('(max-width: 767px)');
|
||||||
|
|
||||||
|
const [sttExternal, setSttExternal] = useState(false);
|
||||||
|
const [ttsExternal, setTtsExternal] = useState(false);
|
||||||
const [advancedMode, setAdvancedMode] = useRecoilState(store.advancedMode);
|
const [advancedMode, setAdvancedMode] = useRecoilState(store.advancedMode);
|
||||||
const [autoTranscribeAudio, setAutoTranscribeAudio] = useRecoilState(store.autoTranscribeAudio);
|
const [autoTranscribeAudio, setAutoTranscribeAudio] = useRecoilState(store.autoTranscribeAudio);
|
||||||
const [conversationMode, setConversationMode] = useRecoilState(store.conversationMode);
|
const [conversationMode, setConversationMode] = useRecoilState(store.conversationMode);
|
||||||
|
|
@ -53,6 +55,8 @@ function Speech() {
|
||||||
const updateSetting = useCallback(
|
const updateSetting = useCallback(
|
||||||
(key, newValue) => {
|
(key, newValue) => {
|
||||||
const settings = {
|
const settings = {
|
||||||
|
sttExternal: { value: sttExternal, setFunc: setSttExternal },
|
||||||
|
ttsExternal: { value: ttsExternal, setFunc: setTtsExternal },
|
||||||
conversationMode: { value: conversationMode, setFunc: setConversationMode },
|
conversationMode: { value: conversationMode, setFunc: setConversationMode },
|
||||||
advancedMode: { value: advancedMode, setFunc: setAdvancedMode },
|
advancedMode: { value: advancedMode, setFunc: setAdvancedMode },
|
||||||
speechToText: { value: speechToText, setFunc: setSpeechToText },
|
speechToText: { value: speechToText, setFunc: setSpeechToText },
|
||||||
|
|
@ -79,6 +83,8 @@ function Speech() {
|
||||||
setting.setFunc(newValue);
|
setting.setFunc(newValue);
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
|
sttExternal,
|
||||||
|
ttsExternal,
|
||||||
conversationMode,
|
conversationMode,
|
||||||
advancedMode,
|
advancedMode,
|
||||||
speechToText,
|
speechToText,
|
||||||
|
|
@ -95,6 +101,8 @@ function Speech() {
|
||||||
languageTTS,
|
languageTTS,
|
||||||
automaticPlayback,
|
automaticPlayback,
|
||||||
playbackRate,
|
playbackRate,
|
||||||
|
setSttExternal,
|
||||||
|
setTtsExternal,
|
||||||
setConversationMode,
|
setConversationMode,
|
||||||
setAdvancedMode,
|
setAdvancedMode,
|
||||||
setSpeechToText,
|
setSpeechToText,
|
||||||
|
|
@ -123,6 +131,9 @@ function Speech() {
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [data]);
|
}, [data]);
|
||||||
|
|
||||||
|
console.log(sttExternal);
|
||||||
|
console.log(ttsExternal);
|
||||||
|
|
||||||
const contentRef = useRef(null);
|
const contentRef = useRef(null);
|
||||||
useOnClickOutside(contentRef, () => confirmClear && setConfirmClear(false), []);
|
useOnClickOutside(contentRef, () => confirmClear && setConfirmClear(false), []);
|
||||||
|
|
||||||
|
|
@ -175,21 +186,21 @@ function Speech() {
|
||||||
|
|
||||||
<Tabs.Content value={'simple'}>
|
<Tabs.Content value={'simple'}>
|
||||||
<div className="flex flex-col gap-3 text-sm text-black dark:text-gray-50">
|
<div className="flex flex-col gap-3 text-sm text-black dark:text-gray-50">
|
||||||
<div className="border-b pb-3 last-of-type:border-b-0 dark:border-gray-700">
|
<div className="border-b last-of-type:border-b-0 dark:border-gray-700">
|
||||||
<SpeechToTextSwitch />
|
<SpeechToTextSwitch />
|
||||||
</div>
|
</div>
|
||||||
<div className="border-b last-of-type:border-b-0 dark:border-gray-700">
|
<div className="border-b last-of-type:border-b-0 dark:border-gray-700">
|
||||||
<EngineSTTDropdown />
|
<EngineSTTDropdown external={sttExternal} />
|
||||||
</div>
|
</div>
|
||||||
<div className="border-b last-of-type:border-b-0 dark:border-gray-700">
|
<div className="border-b last-of-type:border-b-0 dark:border-gray-700">
|
||||||
<LanguageSTTDropdown />
|
<LanguageSTTDropdown />
|
||||||
</div>
|
</div>
|
||||||
<div className="h-px bg-black/20 bg-white/20" role="none" />
|
<div className="h-px bg-black/20 bg-white/20" role="none" />
|
||||||
<div className="border-b pb-3 last-of-type:border-b-0 dark:border-gray-700">
|
<div className="border-b last-of-type:border-b-0 dark:border-gray-700">
|
||||||
<TextToSpeechSwitch />
|
<TextToSpeechSwitch />
|
||||||
</div>
|
</div>
|
||||||
<div className="border-b last-of-type:border-b-0 dark:border-gray-700">
|
<div className="border-b last-of-type:border-b-0 dark:border-gray-700">
|
||||||
<EngineTTSDropdown />
|
<EngineTTSDropdown external={ttsExternal} />
|
||||||
</div>
|
</div>
|
||||||
<div className="border-b last-of-type:border-b-0 dark:border-gray-700">
|
<div className="border-b last-of-type:border-b-0 dark:border-gray-700">
|
||||||
<VoiceDropdown />
|
<VoiceDropdown />
|
||||||
|
|
@ -199,15 +210,15 @@ function Speech() {
|
||||||
|
|
||||||
<Tabs.Content value={'advanced'}>
|
<Tabs.Content value={'advanced'}>
|
||||||
<div className="flex flex-col gap-3 text-sm text-black dark:text-gray-50">
|
<div className="flex flex-col gap-3 text-sm text-black dark:text-gray-50">
|
||||||
<div className="border-b last-of-type:border-b-0 dark:border-gray-700">
|
<div className="border-b pb-3 last-of-type:border-b-0 dark:border-gray-700">
|
||||||
<ConversationModeSwitch />
|
<ConversationModeSwitch />
|
||||||
</div>
|
</div>
|
||||||
<div className="h-px bg-black/20 bg-white/20" role="none" />
|
<div className="h-px bg-black/20 bg-white/20" role="none" />
|
||||||
<div className="border-b pb-3 last-of-type:border-b-0 dark:border-gray-700">
|
<div className="border-b last-of-type:border-b-0 dark:border-gray-700">
|
||||||
<SpeechToTextSwitch />
|
<SpeechToTextSwitch />
|
||||||
</div>
|
</div>
|
||||||
<div className="border-b last-of-type:border-b-0 dark:border-gray-700">
|
<div className="border-b last-of-type:border-b-0 dark:border-gray-700">
|
||||||
<EngineSTTDropdown />
|
<EngineSTTDropdown external={sttExternal} />
|
||||||
</div>
|
</div>
|
||||||
<div className="border-b last-of-type:border-b-0 dark:border-gray-700">
|
<div className="border-b last-of-type:border-b-0 dark:border-gray-700">
|
||||||
<LanguageSTTDropdown />
|
<LanguageSTTDropdown />
|
||||||
|
|
@ -231,7 +242,7 @@ function Speech() {
|
||||||
<AutomaticPlaybackSwitch />
|
<AutomaticPlaybackSwitch />
|
||||||
</div>
|
</div>
|
||||||
<div className="border-b last-of-type:border-b-0 dark:border-gray-700">
|
<div className="border-b last-of-type:border-b-0 dark:border-gray-700">
|
||||||
<EngineTTSDropdown />
|
<EngineTTSDropdown external={ttsExternal} />
|
||||||
</div>
|
</div>
|
||||||
<div className="border-b last-of-type:border-b-0 dark:border-gray-700">
|
<div className="border-b last-of-type:border-b-0 dark:border-gray-700">
|
||||||
<VoiceDropdown />
|
<VoiceDropdown />
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,23 @@
|
||||||
|
import React from 'react';
|
||||||
import { useRecoilState } from 'recoil';
|
import { useRecoilState } from 'recoil';
|
||||||
import { Dropdown } from '~/components/ui';
|
import { Dropdown } from '~/components/ui';
|
||||||
import { useLocalize } from '~/hooks';
|
import { useLocalize } from '~/hooks';
|
||||||
import store from '~/store';
|
import store from '~/store';
|
||||||
|
|
||||||
export default function EngineTTSDropdown() {
|
interface EngineTTSDropdownProps {
|
||||||
|
external: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const EngineTTSDropdown: React.FC<EngineTTSDropdownProps> = ({ external }) => {
|
||||||
const localize = useLocalize();
|
const localize = useLocalize();
|
||||||
const [engineTTS, setEngineTTS] = useRecoilState<string>(store.engineTTS);
|
const [engineTTS, setEngineTTS] = useRecoilState<string>(store.engineTTS);
|
||||||
const endpointOptions = [
|
|
||||||
|
const endpointOptions = external
|
||||||
|
? [
|
||||||
{ value: 'browser', display: localize('com_nav_browser') },
|
{ value: 'browser', display: localize('com_nav_browser') },
|
||||||
{ value: 'external', display: localize('com_nav_external') },
|
{ value: 'external', display: localize('com_nav_external') },
|
||||||
];
|
]
|
||||||
|
: [{ value: 'browser', display: localize('com_nav_browser') }];
|
||||||
|
|
||||||
const handleSelect = (value: string) => {
|
const handleSelect = (value: string) => {
|
||||||
setEngineTTS(value);
|
setEngineTTS(value);
|
||||||
|
|
@ -28,4 +36,6 @@ export default function EngineTTSDropdown() {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export default EngineTTSDropdown;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue