mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-17 00:40:14 +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) {
|
||||
try {
|
||||
const customConfig = await getCustomConfig();
|
||||
const sttExternal = !!customConfig.speech?.stt;
|
||||
const ttsExternal = !!customConfig.speech?.tts;
|
||||
let settings = {
|
||||
sttExternal,
|
||||
ttsExternal,
|
||||
};
|
||||
|
||||
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;
|
||||
let settings = {};
|
||||
const speechTab = customConfig.speech.speechTab;
|
||||
|
||||
if (ttsSchema.advancedMode !== undefined) {
|
||||
settings.advancedMode = ttsSchema.advancedMode;
|
||||
if (speechTab.advancedMode !== undefined) {
|
||||
settings.advancedMode = speechTab.advancedMode;
|
||||
}
|
||||
|
||||
if (ttsSchema.speechToText) {
|
||||
for (const key in ttsSchema.speechToText) {
|
||||
if (ttsSchema.speechToText[key] !== undefined) {
|
||||
settings[key] = ttsSchema.speechToText[key];
|
||||
if (speechTab.speechToText) {
|
||||
for (const key in speechTab.speechToText) {
|
||||
if (speechTab.speechToText[key] !== undefined) {
|
||||
settings[key] = speechTab.speechToText[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ttsSchema.textToSpeech) {
|
||||
for (const key in ttsSchema.textToSpeech) {
|
||||
if (ttsSchema.textToSpeech[key] !== undefined) {
|
||||
settings[key] = ttsSchema.textToSpeech[key];
|
||||
if (speechTab.textToSpeech) {
|
||||
for (const key in speechTab.textToSpeech) {
|
||||
if (speechTab.textToSpeech[key] !== undefined) {
|
||||
settings[key] = speechTab.textToSpeech[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res.status(200).send(settings);
|
||||
} 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 { Dropdown } from '~/components/ui';
|
||||
import { useLocalize } from '~/hooks';
|
||||
import store from '~/store';
|
||||
|
||||
export default function EngineSTTDropdown() {
|
||||
interface EngineSTTDropdownProps {
|
||||
external: boolean;
|
||||
}
|
||||
|
||||
const EngineSTTDropdown: React.FC<EngineSTTDropdownProps> = ({ external }) => {
|
||||
const localize = useLocalize();
|
||||
const [engineSTT, setEngineSTT] = useRecoilState<string>(store.engineSTT);
|
||||
const endpointOptions = [
|
||||
{ value: 'browser', display: localize('com_nav_browser') },
|
||||
{ value: 'external', display: localize('com_nav_external') },
|
||||
];
|
||||
|
||||
const endpointOptions = external
|
||||
? [
|
||||
{ value: 'browser', display: localize('com_nav_browser') },
|
||||
{ value: 'external', display: localize('com_nav_external') },
|
||||
]
|
||||
: [{ value: 'browser', display: localize('com_nav_browser') }];
|
||||
|
||||
const handleSelect = (value: string) => {
|
||||
setEngineSTT(value);
|
||||
|
|
@ -28,4 +36,6 @@ export default function EngineSTTDropdown() {
|
|||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default EngineSTTDropdown;
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ function Speech() {
|
|||
const { data } = useGetCustomConfigSpeechQuery();
|
||||
const isSmallScreen = useMediaQuery('(max-width: 767px)');
|
||||
|
||||
const [sttExternal, setSttExternal] = useState(false);
|
||||
const [ttsExternal, setTtsExternal] = useState(false);
|
||||
const [advancedMode, setAdvancedMode] = useRecoilState(store.advancedMode);
|
||||
const [autoTranscribeAudio, setAutoTranscribeAudio] = useRecoilState(store.autoTranscribeAudio);
|
||||
const [conversationMode, setConversationMode] = useRecoilState(store.conversationMode);
|
||||
|
|
@ -53,6 +55,8 @@ function Speech() {
|
|||
const updateSetting = useCallback(
|
||||
(key, newValue) => {
|
||||
const settings = {
|
||||
sttExternal: { value: sttExternal, setFunc: setSttExternal },
|
||||
ttsExternal: { value: ttsExternal, setFunc: setTtsExternal },
|
||||
conversationMode: { value: conversationMode, setFunc: setConversationMode },
|
||||
advancedMode: { value: advancedMode, setFunc: setAdvancedMode },
|
||||
speechToText: { value: speechToText, setFunc: setSpeechToText },
|
||||
|
|
@ -79,6 +83,8 @@ function Speech() {
|
|||
setting.setFunc(newValue);
|
||||
},
|
||||
[
|
||||
sttExternal,
|
||||
ttsExternal,
|
||||
conversationMode,
|
||||
advancedMode,
|
||||
speechToText,
|
||||
|
|
@ -95,6 +101,8 @@ function Speech() {
|
|||
languageTTS,
|
||||
automaticPlayback,
|
||||
playbackRate,
|
||||
setSttExternal,
|
||||
setTtsExternal,
|
||||
setConversationMode,
|
||||
setAdvancedMode,
|
||||
setSpeechToText,
|
||||
|
|
@ -123,6 +131,9 @@ function Speech() {
|
|||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [data]);
|
||||
|
||||
console.log(sttExternal);
|
||||
console.log(ttsExternal);
|
||||
|
||||
const contentRef = useRef(null);
|
||||
useOnClickOutside(contentRef, () => confirmClear && setConfirmClear(false), []);
|
||||
|
||||
|
|
@ -175,21 +186,21 @@ function Speech() {
|
|||
|
||||
<Tabs.Content value={'simple'}>
|
||||
<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 />
|
||||
</div>
|
||||
<div className="border-b last-of-type:border-b-0 dark:border-gray-700">
|
||||
<EngineSTTDropdown />
|
||||
<EngineSTTDropdown external={sttExternal} />
|
||||
</div>
|
||||
<div className="border-b last-of-type:border-b-0 dark:border-gray-700">
|
||||
<LanguageSTTDropdown />
|
||||
</div>
|
||||
<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 />
|
||||
</div>
|
||||
<div className="border-b last-of-type:border-b-0 dark:border-gray-700">
|
||||
<EngineTTSDropdown />
|
||||
<EngineTTSDropdown external={ttsExternal} />
|
||||
</div>
|
||||
<div className="border-b last-of-type:border-b-0 dark:border-gray-700">
|
||||
<VoiceDropdown />
|
||||
|
|
@ -199,15 +210,15 @@ function Speech() {
|
|||
|
||||
<Tabs.Content value={'advanced'}>
|
||||
<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 />
|
||||
</div>
|
||||
<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 />
|
||||
</div>
|
||||
<div className="border-b last-of-type:border-b-0 dark:border-gray-700">
|
||||
<EngineSTTDropdown />
|
||||
<EngineSTTDropdown external={sttExternal} />
|
||||
</div>
|
||||
<div className="border-b last-of-type:border-b-0 dark:border-gray-700">
|
||||
<LanguageSTTDropdown />
|
||||
|
|
@ -231,7 +242,7 @@ function Speech() {
|
|||
<AutomaticPlaybackSwitch />
|
||||
</div>
|
||||
<div className="border-b last-of-type:border-b-0 dark:border-gray-700">
|
||||
<EngineTTSDropdown />
|
||||
<EngineTTSDropdown external={ttsExternal} />
|
||||
</div>
|
||||
<div className="border-b last-of-type:border-b-0 dark:border-gray-700">
|
||||
<VoiceDropdown />
|
||||
|
|
|
|||
|
|
@ -1,15 +1,23 @@
|
|||
import React from 'react';
|
||||
import { useRecoilState } from 'recoil';
|
||||
import { Dropdown } from '~/components/ui';
|
||||
import { useLocalize } from '~/hooks';
|
||||
import store from '~/store';
|
||||
|
||||
export default function EngineTTSDropdown() {
|
||||
interface EngineTTSDropdownProps {
|
||||
external: boolean;
|
||||
}
|
||||
|
||||
const EngineTTSDropdown: React.FC<EngineTTSDropdownProps> = ({ external }) => {
|
||||
const localize = useLocalize();
|
||||
const [engineTTS, setEngineTTS] = useRecoilState<string>(store.engineTTS);
|
||||
const endpointOptions = [
|
||||
{ value: 'browser', display: localize('com_nav_browser') },
|
||||
{ value: 'external', display: localize('com_nav_external') },
|
||||
];
|
||||
|
||||
const endpointOptions = external
|
||||
? [
|
||||
{ value: 'browser', display: localize('com_nav_browser') },
|
||||
{ value: 'external', display: localize('com_nav_external') },
|
||||
]
|
||||
: [{ value: 'browser', display: localize('com_nav_browser') }];
|
||||
|
||||
const handleSelect = (value: string) => {
|
||||
setEngineTTS(value);
|
||||
|
|
@ -28,4 +36,6 @@ export default function EngineTTSDropdown() {
|
|||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default EngineTTSDropdown;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue