From 771c00830a98d1eb3d042ab3b1e093b8423ed3b3 Mon Sep 17 00:00:00 2001 From: hobokenchicken Date: Thu, 4 Jun 2026 15:34:37 -0400 Subject: [PATCH] feat(ui): display livePartial / transcript_delta in ChatBubble as 'Hearing:' indicator - REST STT now sends delta (full text) so UI lights up immediately with what was heard. - Works as 'live' for the final transcript (true partials would stream words if Realtime was available). - Per PLAN item 3. --- frontend/src/App.tsx | 3 ++- frontend/src/components/ChatBubble.tsx | 12 +++++++++++- frontend/src/hooks/useConversation.ts | 8 +++++++- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 8e702d4..69ee7ed 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -28,6 +28,7 @@ export default function App() { sendText, startRecording, stopRecording, + livePartial, } = useConversation(); const [currentSceneId, setCurrentSceneId] = useState('cozy-room'); @@ -143,7 +144,7 @@ export default function App() { {/* Column 3: Chat + Text Input */}
- + {/* Text input fallback */}
diff --git a/frontend/src/components/ChatBubble.tsx b/frontend/src/components/ChatBubble.tsx index 8189dfb..f768a8e 100644 --- a/frontend/src/components/ChatBubble.tsx +++ b/frontend/src/components/ChatBubble.tsx @@ -11,9 +11,10 @@ interface Props { messages: Message[]; isKiraSpeaking: boolean; userName?: string; + livePartial?: string; } -export default function ChatBubble({ messages, isKiraSpeaking }: Props) { +export default function ChatBubble({ messages, isKiraSpeaking, livePartial }: Props) { const bottomRef = useRef(null); useEffect(() => { @@ -27,6 +28,15 @@ export default function ChatBubble({ messages, isKiraSpeaking }: Props) { + {livePartial && ( +
+ 👂 + Hearing: + {livePartial} + ... +
+ )} +
{messages.length === 0 && (
diff --git a/frontend/src/hooks/useConversation.ts b/frontend/src/hooks/useConversation.ts index 5aa11ae..c161be9 100644 --- a/frontend/src/hooks/useConversation.ts +++ b/frontend/src/hooks/useConversation.ts @@ -39,6 +39,7 @@ export function useConversation() { }); const [loadingPrefs, setLoadingPrefs] = useState(true); const [micError, setMicError] = useState(null); + const [livePartial, setLivePartial] = useState(''); const wsRef = useRef(null); const audioRef = useRef(null); @@ -109,7 +110,11 @@ export function useConversation() { break; case 'transcript_delta': - // Streaming partial transcript — could show as typing indicator + if (msg.text) { + setLivePartial(msg.text); + // Clear after short delay so it doesn't stick (for REST full-text case) + setTimeout(() => setLivePartial(''), 1500); + } break; case 'speaking_start': @@ -282,6 +287,7 @@ export function useConversation() { preferences, loadingPrefs, micError, + livePartial, identify, setPreference, sendText,