From a56fbd2704a065456e5756247035e0f838440c54 Mon Sep 17 00:00:00 2001 From: chihlasm Date: Fri, 6 Mar 2026 23:57:11 -0500 Subject: [PATCH] feat: add AI prompt dialog and wire into CreateFlowDropdown Replace navigation to /ai/chat with an inline AIPromptDialog modal that collects a single prompt, generates a flow via the editor AI API, imports it, and navigates to the editor with the AI panel open. Co-Authored-By: Claude Opus 4.6 --- .../components/common/CreateFlowDropdown.tsx | 56 ++++++++- .../components/editor-ai/AIPromptDialog.tsx | 111 ++++++++++++++++++ 2 files changed, 165 insertions(+), 2 deletions(-) create mode 100644 frontend/src/components/editor-ai/AIPromptDialog.tsx diff --git a/frontend/src/components/common/CreateFlowDropdown.tsx b/frontend/src/components/common/CreateFlowDropdown.tsx index 40ac7288..41438def 100644 --- a/frontend/src/components/common/CreateFlowDropdown.tsx +++ b/frontend/src/components/common/CreateFlowDropdown.tsx @@ -2,6 +2,11 @@ import { useState } from 'react' import { Link, useNavigate } from 'react-router-dom' import { Plus, ChevronDown, Sparkles, FolderTree, ListOrdered, Wrench } from 'lucide-react' import { cn } from '@/lib/utils' +import { editorAIApi } from '@/api/editorAI' +import { apiClient } from '@/api/client' +import { AIPromptDialog } from '@/components/editor-ai/AIPromptDialog' + +type AIFlowType = 'troubleshooting' | 'procedural' | 'maintenance' interface CreateFlowDropdownProps { aiEnabled: boolean @@ -16,8 +21,46 @@ export function CreateFlowDropdown({ label = 'Create Flow', }: CreateFlowDropdownProps) { const [showMenu, setShowMenu] = useState(false) + const [aiPromptOpen, setAiPromptOpen] = useState(false) + const [aiPromptFlowType, setAiPromptFlowType] = useState('troubleshooting') const navigate = useNavigate() + const handleAIGenerate = async (prompt: string) => { + // Start an AI session + const session = await editorAIApi.startSession( + aiPromptFlowType === 'maintenance' ? 'procedural' : aiPromptFlowType + ) + const sessionId = session.id + + // Send the user's prompt + await editorAIApi.sendMessage({ + sessionId, + content: prompt, + actionType: 'generate_full', + }) + + // Generate the full flow + await editorAIApi.generateFull(sessionId) + + // Import to create the tree + const { data: importResult } = await apiClient.post( + `/ai/chat/sessions/${sessionId}/import`, + {} + ) + const treeId = importResult.tree_id + + // Navigate to the editor + if (aiPromptFlowType === 'troubleshooting') { + navigate(`/trees/${treeId}/edit`, { + state: { aiPanelOpen: true, sessionId }, + }) + } else { + navigate(`/flows/${treeId}/edit`, { + state: { aiPanelOpen: true, sessionId }, + }) + } + } + return (
)} + + setAiPromptOpen(false)} + onGenerate={handleAIGenerate} + flowType={aiPromptFlowType} + /> ) } diff --git a/frontend/src/components/editor-ai/AIPromptDialog.tsx b/frontend/src/components/editor-ai/AIPromptDialog.tsx new file mode 100644 index 00000000..5878a754 --- /dev/null +++ b/frontend/src/components/editor-ai/AIPromptDialog.tsx @@ -0,0 +1,111 @@ +import { useState } from 'react' +import { Sparkles, Loader2, AlertCircle } from 'lucide-react' + +interface AIPromptDialogProps { + isOpen: boolean + onClose: () => void + onGenerate: (prompt: string) => Promise + flowType: 'troubleshooting' | 'procedural' | 'maintenance' +} + +const FLOW_TYPE_LABELS = { + troubleshooting: 'Troubleshooting Flow', + procedural: 'Project Flow', + maintenance: 'Maintenance Flow', +} + +export function AIPromptDialog({ + isOpen, + onClose, + onGenerate, + flowType, +}: AIPromptDialogProps) { + const [prompt, setPrompt] = useState('') + const [isGenerating, setIsGenerating] = useState(false) + const [error, setError] = useState(null) + + if (!isOpen) return null + + const handleGenerate = async () => { + if (!prompt.trim()) return + setIsGenerating(true) + setError(null) + try { + await onGenerate(prompt) + setPrompt('') + onClose() + } catch (e) { + setError(e instanceof Error ? e.message : 'Generation failed. Please try again.') + } finally { + setIsGenerating(false) + } + } + + return ( +
+ {/* Backdrop */} +
!isGenerating && onClose()} + /> + + {/* Dialog */} +
+
+ +

+ AI-Assisted {FLOW_TYPE_LABELS[flowType]} +

+
+ +

+ Describe what you want to build and AI will generate a starting structure for you. +

+ +