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 (
No content to preview
{processUnicodeContent(fileContent)}
{processedFilePath || 'Unknown file path'}
This file has been permanently removed
No source code to display
Source
{processedFilePath || 'Unknown file path'}