feat: Add FastGPT interactive voice toggle to DebugDrawer and state management
This commit is contained in:
@@ -2534,6 +2534,8 @@ export const DebugDrawer: React.FC<{
|
|||||||
const setNsEnabled = useDebugPrefsStore((state) => state.setNsEnabled);
|
const setNsEnabled = useDebugPrefsStore((state) => state.setNsEnabled);
|
||||||
const agcEnabled = useDebugPrefsStore((state) => state.agcEnabled);
|
const agcEnabled = useDebugPrefsStore((state) => state.agcEnabled);
|
||||||
const setAgcEnabled = useDebugPrefsStore((state) => state.setAgcEnabled);
|
const setAgcEnabled = useDebugPrefsStore((state) => state.setAgcEnabled);
|
||||||
|
const fastgptInteractiveVoiceEnabled = useDebugPrefsStore((state) => state.fastgptInteractiveVoiceEnabled);
|
||||||
|
const setFastgptInteractiveVoiceEnabled = useDebugPrefsStore((state) => state.setFastgptInteractiveVoiceEnabled);
|
||||||
const clientToolEnabledMap = useDebugPrefsStore((state) => state.clientToolEnabledMap);
|
const clientToolEnabledMap = useDebugPrefsStore((state) => state.clientToolEnabledMap);
|
||||||
const setClientToolEnabled = useDebugPrefsStore((state) => state.setClientToolEnabled);
|
const setClientToolEnabled = useDebugPrefsStore((state) => state.setClientToolEnabled);
|
||||||
const hydrateClientToolDefaults = useDebugPrefsStore((state) => state.hydrateClientToolDefaults);
|
const hydrateClientToolDefaults = useDebugPrefsStore((state) => state.hydrateClientToolDefaults);
|
||||||
@@ -2752,6 +2754,12 @@ export const DebugDrawer: React.FC<{
|
|||||||
fastgptInteractiveDialogRef.current = fastgptInteractiveDialog;
|
fastgptInteractiveDialogRef.current = fastgptInteractiveDialog;
|
||||||
}, [fastgptInteractiveDialog]);
|
}, [fastgptInteractiveDialog]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!fastgptInteractiveVoiceEnabled && fastgptInteractiveDialog.open) {
|
||||||
|
stopPromptVoicePlayback();
|
||||||
|
}
|
||||||
|
}, [fastgptInteractiveVoiceEnabled, fastgptInteractiveDialog.open]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
dynamicVariableSeqRef.current = 0;
|
dynamicVariableSeqRef.current = 0;
|
||||||
setDynamicVariables([]);
|
setDynamicVariables([]);
|
||||||
@@ -3088,7 +3096,7 @@ export const DebugDrawer: React.FC<{
|
|||||||
submitLabel: item.payload.submitLabel,
|
submitLabel: item.payload.submitLabel,
|
||||||
cancelLabel: item.payload.cancelLabel,
|
cancelLabel: item.payload.cancelLabel,
|
||||||
});
|
});
|
||||||
if (nextVoiceText) {
|
if (nextVoiceText && fastgptInteractiveVoiceEnabled) {
|
||||||
void playPromptVoice(nextVoiceText);
|
void playPromptVoice(nextVoiceText);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -3163,6 +3171,10 @@ export const DebugDrawer: React.FC<{
|
|||||||
const fieldValues = snapshot.fieldValues;
|
const fieldValues = snapshot.fieldValues;
|
||||||
const interactionType = snapshot.interactionType;
|
const interactionType = snapshot.interactionType;
|
||||||
stopPromptVoicePlayback();
|
stopPromptVoicePlayback();
|
||||||
|
// Stop only local playback so the resumed FastGPT response can take over
|
||||||
|
// without cancelling the active server-side turn.
|
||||||
|
stopPlaybackImmediately();
|
||||||
|
setAgentState('waiting');
|
||||||
setFastgptInteractiveDialog({
|
setFastgptInteractiveDialog({
|
||||||
open: false,
|
open: false,
|
||||||
interactionType: 'userSelect',
|
interactionType: 'userSelect',
|
||||||
@@ -4605,6 +4617,23 @@ export const DebugDrawer: React.FC<{
|
|||||||
Auto Gain Control (AGC)
|
Auto Gain Control (AGC)
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="rounded-md border border-white/10 bg-black/20 p-2 space-y-2">
|
||||||
|
<p className="text-[10px] uppercase tracking-widest text-muted-foreground">Prompt Voice</p>
|
||||||
|
<div className="flex items-center justify-between gap-3 rounded-md border border-white/10 bg-black/20 px-2 py-1.5">
|
||||||
|
<div className="min-w-0">
|
||||||
|
<div className="text-[11px] font-mono text-foreground truncate">FastGPT Interactive</div>
|
||||||
|
<div className="text-[10px] text-muted-foreground">
|
||||||
|
Play the interactive description or prompt voice when the popup opens.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Switch
|
||||||
|
checked={fastgptInteractiveVoiceEnabled}
|
||||||
|
onCheckedChange={setFastgptInteractiveVoiceEnabled}
|
||||||
|
title={fastgptInteractiveVoiceEnabled ? 'Click to mute FastGPT interactive prompt voice' : 'Click to enable FastGPT interactive prompt voice'}
|
||||||
|
aria-label={`FastGPT interactive prompt voice ${fastgptInteractiveVoiceEnabled ? 'enabled' : 'disabled'}`}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div className="rounded-md border border-white/10 bg-black/20 p-2 space-y-2">
|
<div className="rounded-md border border-white/10 bg-black/20 p-2 space-y-2">
|
||||||
<p className="text-[10px] uppercase tracking-widest text-muted-foreground">Client Tools</p>
|
<p className="text-[10px] uppercase tracking-widest text-muted-foreground">Client Tools</p>
|
||||||
<p className="text-[11px] text-muted-foreground">滑块控制调试会话内客户端工具是否启用。</p>
|
<p className="text-[11px] text-muted-foreground">滑块控制调试会话内客户端工具是否启用。</p>
|
||||||
@@ -5086,7 +5115,7 @@ export const DebugDrawer: React.FC<{
|
|||||||
)}
|
)}
|
||||||
{fastgptInteractiveDialog.open && (
|
{fastgptInteractiveDialog.open && (
|
||||||
<div className="absolute inset-0 z-40 flex items-center justify-center bg-black/55 backdrop-blur-[1px]">
|
<div className="absolute inset-0 z-40 flex items-center justify-center bg-black/55 backdrop-blur-[1px]">
|
||||||
<div className="relative w-[92%] max-w-lg rounded-xl border border-white/15 bg-card/95 p-4 shadow-2xl animate-in zoom-in-95 duration-200">
|
<div className="relative flex max-h-[82vh] w-[92%] max-w-lg flex-col rounded-xl border border-white/15 bg-card/95 p-4 shadow-2xl animate-in zoom-in-95 duration-200">
|
||||||
{!fastgptInteractiveDialog.required && (
|
{!fastgptInteractiveDialog.required && (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -5122,6 +5151,7 @@ export const DebugDrawer: React.FC<{
|
|||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
<div className="min-h-0 overflow-y-auto pr-1 custom-scrollbar">
|
||||||
{fastgptInteractiveDialog.interactionType === 'userSelect' ? (
|
{fastgptInteractiveDialog.interactionType === 'userSelect' ? (
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
{fastgptInteractiveDialog.options.map((option) => {
|
{fastgptInteractiveDialog.options.map((option) => {
|
||||||
@@ -5202,6 +5232,7 @@ export const DebugDrawer: React.FC<{
|
|||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
</div>
|
||||||
<div className="mt-4 flex items-center justify-end gap-2">
|
<div className="mt-4 flex items-center justify-end gap-2">
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
|
|||||||
@@ -6,11 +6,13 @@ type DebugPrefsState = {
|
|||||||
aecEnabled: boolean;
|
aecEnabled: boolean;
|
||||||
nsEnabled: boolean;
|
nsEnabled: boolean;
|
||||||
agcEnabled: boolean;
|
agcEnabled: boolean;
|
||||||
|
fastgptInteractiveVoiceEnabled: boolean;
|
||||||
clientToolEnabledMap: Record<string, boolean>;
|
clientToolEnabledMap: Record<string, boolean>;
|
||||||
setWsUrl: (value: string) => void;
|
setWsUrl: (value: string) => void;
|
||||||
setAecEnabled: (value: boolean) => void;
|
setAecEnabled: (value: boolean) => void;
|
||||||
setNsEnabled: (value: boolean) => void;
|
setNsEnabled: (value: boolean) => void;
|
||||||
setAgcEnabled: (value: boolean) => void;
|
setAgcEnabled: (value: boolean) => void;
|
||||||
|
setFastgptInteractiveVoiceEnabled: (value: boolean) => void;
|
||||||
setClientToolEnabled: (toolId: string, enabled: boolean) => void;
|
setClientToolEnabled: (toolId: string, enabled: boolean) => void;
|
||||||
hydrateClientToolDefaults: (toolIds: string[]) => void;
|
hydrateClientToolDefaults: (toolIds: string[]) => void;
|
||||||
};
|
};
|
||||||
@@ -30,11 +32,13 @@ export const useDebugPrefsStore = create<DebugPrefsState>()(
|
|||||||
aecEnabled: true,
|
aecEnabled: true,
|
||||||
nsEnabled: true,
|
nsEnabled: true,
|
||||||
agcEnabled: true,
|
agcEnabled: true,
|
||||||
|
fastgptInteractiveVoiceEnabled: true,
|
||||||
clientToolEnabledMap: {},
|
clientToolEnabledMap: {},
|
||||||
setWsUrl: (value) => set({ wsUrl: value }),
|
setWsUrl: (value) => set({ wsUrl: value }),
|
||||||
setAecEnabled: (value) => set({ aecEnabled: value }),
|
setAecEnabled: (value) => set({ aecEnabled: value }),
|
||||||
setNsEnabled: (value) => set({ nsEnabled: value }),
|
setNsEnabled: (value) => set({ nsEnabled: value }),
|
||||||
setAgcEnabled: (value) => set({ agcEnabled: value }),
|
setAgcEnabled: (value) => set({ agcEnabled: value }),
|
||||||
|
setFastgptInteractiveVoiceEnabled: (value) => set({ fastgptInteractiveVoiceEnabled: value }),
|
||||||
setClientToolEnabled: (toolId, enabled) =>
|
setClientToolEnabled: (toolId, enabled) =>
|
||||||
set((state) => ({
|
set((state) => ({
|
||||||
clientToolEnabledMap: {
|
clientToolEnabledMap: {
|
||||||
|
|||||||
Reference in New Issue
Block a user