From d841c59f459c626955b9fa8930955b57593078bf Mon Sep 17 00:00:00 2001 From: Xin Wang Date: Mon, 9 Feb 2026 10:21:31 +0800 Subject: [PATCH] Improve text debug flow --- web/pages/Assistants.tsx | 111 +++++++++++++++++++++++++++------------ 1 file changed, 76 insertions(+), 35 deletions(-) diff --git a/web/pages/Assistants.tsx b/web/pages/Assistants.tsx index 3d697f2..f5d54fa 100644 --- a/web/pages/Assistants.tsx +++ b/web/pages/Assistants.tsx @@ -1041,6 +1041,7 @@ export const DebugDrawer: React.FC<{ const [inputText, setInputText] = useState(''); const [isLoading, setIsLoading] = useState(false); const [callStatus, setCallStatus] = useState<'idle' | 'calling' | 'active'>('idle'); + const [textSessionStarted, setTextSessionStarted] = useState(false); const [wsStatus, setWsStatus] = useState<'disconnected' | 'connecting' | 'ready' | 'error'>('disconnected'); const [wsError, setWsError] = useState(''); const [resolvedConfigOpen, setResolvedConfigOpen] = useState(false); @@ -1074,7 +1075,8 @@ export const DebugDrawer: React.FC<{ useEffect(() => { if (isOpen) { if (mode === 'text') { - setMessages([{ role: 'model', text: assistant.opener || "Hello!" }]); + setMessages([]); + setTextSessionStarted(false); } else { setMessages([]); setCallStatus('idle'); @@ -1240,6 +1242,21 @@ export const DebugDrawer: React.FC<{ } }; + const handleTextLaunch = async () => { + try { + setWsError(''); + if (textTtsEnabled) await ensureAudioContext(); + await ensureWsSession(); + setTextSessionStarted(true); + setMessages((prev) => (prev.length > 0 ? prev : [{ role: 'model', text: assistant.opener || 'Hello!' }])); + } catch (e) { + console.error(e); + setWsStatus('error'); + setWsError((e as Error)?.message || 'Failed to connect'); + setTextSessionStarted(false); + } + }; + const buildLocalResolvedRuntime = () => { const warnings: string[] = []; const services: Record = {}; @@ -1371,6 +1388,7 @@ export const DebugDrawer: React.FC<{ pendingResolveRef.current = null; pendingRejectRef.current = null; assistantDraftIndexRef.current = null; + setTextSessionStarted(false); clearPlaybackQueue(); if (isOpen) setWsStatus('disconnected'); }; @@ -1520,6 +1538,7 @@ export const DebugDrawer: React.FC<{ ws.onclose = () => { wsReadyRef.current = false; + setTextSessionStarted(false); clearPlaybackQueue(); if (wsStatus !== 'error') setWsStatus('disconnected'); }; @@ -1586,15 +1605,48 @@ export const DebugDrawer: React.FC<{ ))} +
+ + {resolvedConfigOpen && ( +
+              {resolvedConfigView || 'Connect to load resolved config...'}
+            
+ )} +
+
{mode === 'text' ? ( -
-
+ textSessionStarted ? ( +
+
+ + WS: {wsStatus} + + + {wsError && {wsError}} +
+ +
+ ) : ( +
+
+ setWsUrl(e.target.value)} placeholder="ws://localhost:8000/ws" /> -
- - WS: {wsStatus} - +
+ WS: {wsStatus} - - {wsError && {wsError}}
-
- - {resolvedConfigOpen && ( -
-                        {resolvedConfigView || 'Connect to load resolved config...'}
-                      
- )} -
- -
+ +
+ ) ) : callStatus === 'idle' ? (
@@ -1696,12 +1735,14 @@ export const DebugDrawer: React.FC<{ )}
-
-
- setInputText(e.target.value)} placeholder={mode === 'text' ? "输入消息..." : "输入文本模拟交互..."} onKeyDown={e => e.key === 'Enter' && handleSend()} disabled={isLoading || (mode !== 'text' && callStatus !== 'active')} className="flex-1" /> - -
-
+ {(mode !== 'text' || textSessionStarted) && ( +
+
+ setInputText(e.target.value)} placeholder={mode === 'text' ? "输入消息..." : "输入文本模拟交互..."} onKeyDown={e => e.key === 'Enter' && handleSend()} disabled={isLoading || (mode === 'text' ? !textSessionStarted : callStatus !== 'active')} className="flex-1" /> + +
+
+ )}
);