import { useState, useEffect } from 'react' import { useSearchParams } from 'react-router-dom' import { Terminal } from 'lucide-react' import { cn } from '@/lib/utils' import { scriptBuilderApi } from '@/api' import { ScriptBuilderChat } from '@/components/script-builder/ScriptBuilderChat' import { ScriptBuilderInput } from '@/components/script-builder/ScriptBuilderInput' import { ScriptPreviewModal } from '@/components/script-builder/ScriptPreviewModal' import { SaveToLibraryDialog } from '@/components/script-builder/SaveToLibraryDialog' import type { ScriptBuilderSessionDetail, ScriptBuilderMessage } from '@/types' const LANGUAGES = [ { value: 'powershell', label: 'PowerShell' }, { value: 'bash', label: 'Bash' }, { value: 'python', label: 'Python' }, ] as const export default function ScriptBuilderPage() { const [searchParams] = useSearchParams() const [session, setSession] = useState(null) const [messages, setMessages] = useState([]) const [language, setLanguage] = useState('powershell') const [isLoading, setIsLoading] = useState(false) const [previewScript, setPreviewScript] = useState<{ script: string; filename: string | null } | null>(null) const [showSaveDialog, setShowSaveDialog] = useState(false) const [handoffProcessed, setHandoffProcessed] = useState(false) const hasMessages = messages.length > 0 // Handle FlowPilot handoff on mount useEffect(() => { if (handoffProcessed) return setHandoffProcessed(true) const contextRaw = sessionStorage.getItem('scriptBuilderContext') if (!contextRaw) return try { const context = JSON.parse(contextRaw) as { from_session?: string prompt?: string language?: string } sessionStorage.removeItem('scriptBuilderContext') if (context.language) { setLanguage(context.language) } if (context.prompt) { // Auto-send the prompt handleSend(context.prompt, context.language || 'powershell') } } catch { sessionStorage.removeItem('scriptBuilderContext') } // eslint-disable-next-line react-hooks/exhaustive-deps }, []) // Suppress unused searchParams warning — used to detect ?from=flowpilot context void searchParams const handleSend = async (content: string, langOverride?: string) => { const effectiveLanguage = langOverride || language // Optimistically add user message const userMessage: ScriptBuilderMessage = { role: 'user', content, created_at: new Date().toISOString(), } setMessages((prev) => [...prev, userMessage]) setIsLoading(true) try { // Create session if needed let currentSession = session if (!currentSession) { currentSession = await scriptBuilderApi.createSession(effectiveLanguage) setSession(currentSession) } // Send message const response = await scriptBuilderApi.sendMessage(currentSession.id, content) const assistantMessage: ScriptBuilderMessage = { role: 'assistant', content: response.content, script: response.script, script_filename: response.script_filename, line_count: response.line_count, created_at: response.timestamp, } setMessages((prev) => [...prev, assistantMessage]) } catch (err) { // Add error message const errorMessage: ScriptBuilderMessage = { role: 'assistant', content: `An error occurred: ${err instanceof Error ? err.message : 'Failed to generate response. Please try again.'}`, created_at: new Date().toISOString(), } setMessages((prev) => [...prev, errorMessage]) } finally { setIsLoading(false) } } const handleViewScript = (script: string, filename: string | null) => { setPreviewScript({ script, filename }) } const handleSaveScript = () => { setShowSaveDialog(true) } const handleSaved = () => { setShowSaveDialog(false) } // Derive default name from session title or filename const defaultSaveName = session?.title || session?.latest_script_filename || 'Untitled Script' return (
{/* Header with language selector */}

Script Builder

Describe what you need, AI generates the script

{/* Language pills */}
{LANGUAGES.map((lang) => ( ))}
{/* Chat area */} {/* Input */}
handleSend(content)} disabled={isLoading} />
{/* Preview modal */} {previewScript && ( setPreviewScript(null)} onSave={() => { setPreviewScript(null) setShowSaveDialog(true) }} /> )} {/* Save dialog */} {showSaveDialog && session && ( setShowSaveDialog(false)} onSaved={handleSaved} /> )}
) }