import React, { useState } from 'react'; import { CheckCircle, AlertTriangle, ExternalLink, Loader2, Code, Eye, File, } from 'lucide-react'; import { extractFilePath, extractFileContent, extractStreamingFileContent, formatTimestamp, getToolTitle, normalizeContentToString, extractToolData, } from '../utils'; import { MarkdownRenderer, processUnicodeContent, } from '@/components/file-renderers/markdown-renderer'; import { CsvRenderer } from '@/components/file-renderers/csv-renderer'; import { cn } from '@/lib/utils'; import { useTheme } from 'next-themes'; import { CodeBlockCode } from '@/components/ui/code-block'; import { constructHtmlPreviewUrl } from '@/lib/utils/url'; import { Card, CardContent, CardHeader, CardTitle, } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { ScrollArea } from "@/components/ui/scroll-area"; import { getLanguageFromFileName, getOperationType, getOperationConfigs, getFileIcon, processFilePath, getFileName, getFileExtension, isFileType, hasLanguageHighlighting, splitContentIntoLines, type FileOperation, type OperationConfig, } from './_utils'; import { ToolViewProps } from '../types'; import { GenericToolView } from '../GenericToolView'; import { LoadingState } from '../shared/LoadingState'; export function FileOperationToolView({ assistantContent, toolContent, assistantTimestamp, toolTimestamp, isSuccess = true, isStreaming = false, name, project, }: ToolViewProps) { const { resolvedTheme } = useTheme(); const isDarkTheme = resolvedTheme === 'dark'; const operation = getOperationType(name, assistantContent); const configs = getOperationConfigs(); const config = configs[operation]; const Icon = config.icon; let filePath: string | null = null; let fileContent: string | null = null; const assistantToolData = extractToolData(assistantContent); const toolToolData = extractToolData(toolContent); if (assistantToolData.toolResult) { filePath = assistantToolData.filePath; fileContent = assistantToolData.fileContent; } else if (toolToolData.toolResult) { filePath = toolToolData.filePath; fileContent = toolToolData.fileContent; } if (!filePath) { filePath = extractFilePath(assistantContent); } if (!fileContent && operation !== 'delete') { fileContent = isStreaming ? extractStreamingFileContent( assistantContent, operation === 'create' ? 'create-file' : 'full-file-rewrite', ) || '' : extractFileContent( assistantContent, operation === 'create' ? 'create-file' : 'full-file-rewrite', ); } const toolTitle = getToolTitle(name || `file-${operation}`); const processedFilePath = processFilePath(filePath); const fileName = getFileName(processedFilePath); const fileExtension = getFileExtension(fileName); const isMarkdown = isFileType.markdown(fileExtension); const isHtml = isFileType.html(fileExtension); const isCsv = isFileType.csv(fileExtension); const language = getLanguageFromFileName(fileName); const hasHighlighting = hasLanguageHighlighting(language); const contentLines = splitContentIntoLines(fileContent); const htmlPreviewUrl = isHtml && project?.sandbox?.sandbox_url && processedFilePath ? constructHtmlPreviewUrl(project.sandbox.sandbox_url, processedFilePath) : undefined; const FileIcon = getFileIcon(fileName); if (!isStreaming && !processedFilePath && !fileContent) { return ( ); } const renderFilePreview = () => { if (!fileContent) { return (

No content to preview

); } if (isHtml && htmlPreviewUrl) { return (