From 2d602f687b6e52ade0b6bbe13e1b7e8cb51b87c2 Mon Sep 17 00:00:00 2001 From: chihlasm Date: Mon, 16 Mar 2026 00:47:52 -0400 Subject: [PATCH] feat: add FlowPilot prefill handoff from command palette to AssistantChatPage When navigated to /assistant with location.state.prefill, automatically creates a new chat and sends the prefill message without user interaction. Clears location state after handling to prevent re-trigger on back navigation. Co-Authored-By: Claude Opus 4.6 (1M context) --- frontend/src/pages/AssistantChatPage.tsx | 47 ++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/frontend/src/pages/AssistantChatPage.tsx b/frontend/src/pages/AssistantChatPage.tsx index ccdceba0..1eb51cfb 100644 --- a/frontend/src/pages/AssistantChatPage.tsx +++ b/frontend/src/pages/AssistantChatPage.tsx @@ -1,4 +1,5 @@ import { useState, useEffect, useRef, useCallback } from 'react' +import { useLocation, useNavigate } from 'react-router-dom' import { Sparkles, Send, Loader2, Flag } from 'lucide-react' import { PageMeta } from '@/components/common/PageMeta' import { assistantChatApi } from '@/api/assistantChat' @@ -14,6 +15,8 @@ interface MessageWithMeta extends ChatMessageType { } export default function AssistantChatPage() { + const location = useLocation() + const navigate = useNavigate() const [chats, setChats] = useState([]) const [activeChatId, setActiveChatId] = useState(null) const [messages, setMessages] = useState([]) @@ -22,12 +25,56 @@ export default function AssistantChatPage() { const [showConclude, setShowConclude] = useState(false) const messagesEndRef = useRef(null) const inputRef = useRef(null) + const prefillHandledRef = useRef(false) // Load chat list useEffect(() => { loadChats() }, []) + // Handle prefill from command palette handoff + useEffect(() => { + const prefill = (location.state as { prefill?: string } | null)?.prefill + if (!prefill || prefillHandledRef.current) return + prefillHandledRef.current = true + + // Clear the location state so back-navigation doesn't retrigger + navigate(location.pathname, { replace: true, state: {} }) + + const sendPrefill = async () => { + try { + const chat = await assistantChatApi.createChat() + setChats(prev => [ + { id: chat.id, title: chat.title, message_count: 0, pinned: false, created_at: chat.created_at, updated_at: chat.updated_at }, + ...prev, + ]) + setActiveChatId(chat.id) + setMessages([{ role: 'user', content: prefill }]) + setLoading(true) + + const response = await assistantChatApi.sendMessage(chat.id, prefill) + setMessages(prev => [ + ...prev, + { role: 'assistant', content: response.content, suggestedFlows: response.suggested_flows }, + ]) + setChats(prev => + prev.map(c => + c.id === chat.id + ? { ...c, message_count: 2, title: prefill.slice(0, 100), updated_at: new Date().toISOString() } + : c + ) + ) + } catch { + toast.error('Failed to start AI conversation') + } finally { + setLoading(false) + } + } + + sendPrefill() + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) + // Auto-scroll useEffect(() => { messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' })