diff --git a/ui/src/main.tsx b/ui/src/main.tsx index 49982f51..7e4229cf 100644 --- a/ui/src/main.tsx +++ b/ui/src/main.tsx @@ -14,6 +14,8 @@ import { SidebarProvider } from "./context/SidebarContext"; import { DialogProvider } from "./context/DialogContext"; import { ToastProvider } from "./context/ToastContext"; import { ThemeProvider } from "./context/ThemeContext"; +import { VoiceProvider } from "./context/VoiceContext"; +import { CommandPaletteProvider } from "./context/CommandPaletteContext"; import { TooltipProvider } from "@/components/ui/tooltip"; import { initPluginBridge } from "./plugins/bridge-init"; import { PluginLauncherProvider } from "./plugins/launchers"; @@ -41,29 +43,33 @@ createRoot(document.getElementById("root")!).render( - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ui/src/pages/PersonalAssistant.tsx b/ui/src/pages/PersonalAssistant.tsx index 42830b34..99cef509 100644 --- a/ui/src/pages/PersonalAssistant.tsx +++ b/ui/src/pages/PersonalAssistant.tsx @@ -43,6 +43,7 @@ export function PersonalAssistant() { const queryClient = useQueryClient(); const { pushToast } = useToast(); const { activeConversationId, setActiveConversationId } = useChatPanel(); + const voice = useVoice(); const companyId = selectedCompany?.id ?? null; const companyPrefix = useMemo( @@ -195,6 +196,21 @@ export function PersonalAssistant() { // eslint-disable-next-line react-hooks/exhaustive-deps }, [promote.state.kind]); + // Phase 14 — drain any voice transcripts captured from non-Assistant + // routes into the chat pipeline. Runs once per mount; if the queue is + // empty the effect is a no-op. + const voiceDrainedRef = useRef(false); + useEffect(() => { + if (voiceDrainedRef.current) return; + if (!companyId) return; + if (voice.queue.length === 0) return; + voiceDrainedRef.current = true; + const drained = voice.drainQueue(); + for (const text of drained) { + handleSend(text); + } + }, [companyId, voice, handleSend]); + const handlePromote = useCallback(() => { if (!selectedConvId || !canPromote) return; promote.startPrompting();