import React from 'react'; import { Rocket, CheckCircle, AlertTriangle, ExternalLink, Globe, Folder, TerminalIcon, } from 'lucide-react'; import { ToolViewProps } from './types'; import { getToolTitle, normalizeContentToString } from './utils'; import { cn } from '@/lib/utils'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { ScrollArea } from "@/components/ui/scroll-area"; import { LoadingState } from './shared/LoadingState'; interface DeployResult { message?: string; output?: string; success?: boolean; url?: string; } function extractDeployData(assistantContent: any, toolContent: any): { name: string | null; directoryPath: string | null; deployResult: DeployResult | null; rawContent: string | null; } { let name: string | null = null; let directoryPath: string | null = null; let deployResult: DeployResult | null = null; let rawContent: string | null = null; // Try to extract from assistant content first const assistantStr = normalizeContentToString(assistantContent); if (assistantStr) { try { const parsed = JSON.parse(assistantStr); if (parsed.parameters) { name = parsed.parameters.name || null; directoryPath = parsed.parameters.directory_path || null; } } catch (e) { // Try regex extraction const nameMatch = assistantStr.match(/name["']\s*:\s*["']([^"']+)["']/); const dirMatch = assistantStr.match(/directory_path["']\s*:\s*["']([^"']+)["']/); if (nameMatch) name = nameMatch[1]; if (dirMatch) directoryPath = dirMatch[1]; } } // Extract deploy result from tool content const toolStr = normalizeContentToString(toolContent); if (toolStr) { rawContent = toolStr; try { const parsed = JSON.parse(toolStr); // Handle the nested tool_execution structure let resultData = null; if (parsed.tool_execution && parsed.tool_execution.result) { resultData = parsed.tool_execution.result; // Also extract arguments if not found in assistant content if (!name && parsed.tool_execution.arguments) { name = parsed.tool_execution.arguments.name || null; directoryPath = parsed.tool_execution.arguments.directory_path || null; } } else if (parsed.output) { // Fallback to old format resultData = parsed; } if (resultData) { deployResult = { message: resultData.output?.message || null, output: resultData.output?.output || null, success: resultData.success !== undefined ? resultData.success : true, }; // Try to extract deployment URL from output if (deployResult.output) { const urlMatch = deployResult.output.match(/https:\/\/[^\s]+\.pages\.dev[^\s]*/); if (urlMatch) { deployResult.url = urlMatch[0]; } } } } catch (e) { // If parsing fails, treat as raw content deployResult = { message: 'Deploy completed', output: toolStr, success: true, }; } } return { name, directoryPath, deployResult, rawContent }; } export function DeployToolView({ name = 'deploy', assistantContent, toolContent, assistantTimestamp, toolTimestamp, isSuccess = true, isStreaming = false, }: ToolViewProps) { const { name: projectName, directoryPath, deployResult, rawContent } = extractDeployData( assistantContent, toolContent ); const toolTitle = getToolTitle(name); const actualIsSuccess = deployResult?.success !== undefined ? deployResult.success : isSuccess; // Clean up terminal output for display const cleanOutput = React.useMemo(() => { if (!deployResult?.output) return []; let output = deployResult.output; // Remove ANSI escape codes output = output.replace(/\u001b\[[0-9;]*m/g, ''); // Replace escaped newlines with actual newlines output = output.replace(/\\n/g, '\n'); return output.split('\n').filter(line => line.trim().length > 0); }, [deployResult?.output]); return (
{toolTitle}
{!isStreaming && ( {actualIsSuccess ? ( ) : ( )} {actualIsSuccess ? 'Deploy successful' : 'Deploy failed'} )}
{isStreaming ? ( ) : (
{/* Success State */} {actualIsSuccess && deployResult ? (
{/* Deployment URL Card */} {deployResult.url && (
Website Deployed Live
{deployResult.url}
)} {/* Terminal Output */} {cleanOutput.length > 0 && (
Deployment Log
                                                    {cleanOutput.map((line, index) => (
                                                        
{line || ' '}
))}
)}
) : ( /* Failure State */

Deployment Failed

The deployment encountered an error. Check the logs below for details.

{/* Raw Error Output */} {rawContent && (
Error Details
                                                    {rawContent}
                                                
)}
)}
)}
); }