WebContainerApp.tsx:35 Terminal instance is not available.
error @ intercept-console-error.js:56
writeToTerminal @ WebContainerApp.tsx:35
write @ WebContainerApp.tsx:120
"""
'use client'
import 'tailwindcss/tailwind.css';
import '@xterm/xterm/css/xterm.css';
import React, { useState, useEffect, useRef } from 'react';
import QueryInput from './QueryInput';
import useWebContainer from '../hooks/useWebContainer';
import { sendQuery } from '../utils/api';
import { mergeJson } from '../utils/mergeJson';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Terminal as XTerminal } from '@xterm/xterm';
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Terminal, Globe, Code2, RefreshCw, PlusCircle } from 'lucide-react';
import { Loader } from './Loader';
import StartTypingScreen from './StartTypingScreen';

const WebContainerApp: React.FC = () => {
  const [query, setQuery] = useState('');
  const [oldObj, setOldObj] = useState({});
  const [isInitialQuery, setIsInitialQuery] = useState(true);
  const [isProcessing, setIsProcessing] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [status, setStatus] = useState({ serverReady: false, loading: true });
  const [activeTab, setActiveTab] = useState('preview');

  const iframeRef = useRef<HTMLIFrameElement>(null);
  const { webContainerInstance, isInitialized, initializeWebContainer } = useWebContainer();
  const terminalRef = useRef<HTMLDivElement>(null);
  const terminalInstanceRef = useRef<XTerminal | null>(null);

  const writeToTerminal = (message: string, type: 'default' | 'error' | 'success' | 'info' = 'default') => {
    console.log(`writeToTerminal called with message: "${message}" and type: "${type}"`);
    if (!terminalInstanceRef.current) {
      console.error('Terminal instance is not available.');
      return;
    }
    const colors = {
      default: '\x1b[37m',
      error: '\x1b[31m',
      success: '\x1b[32m',
      info: '\x1b[34m'
    };
  
    const colorCode = colors[type] || colors.default;
    terminalInstanceRef.current.writeln(`${colorCode}${message}\x1b[0m`);
  };

  useEffect(() => {
    console.log('Attempting to initialize terminal...');
    if (terminalRef.current && !terminalInstanceRef.current) {
      const terminal = new XTerminal({
        convertEol: true,
        rows: 15,
        fontSize: 14,
        fontFamily: 'JetBrains Mono, monospace',
        theme: {
          background: '#1a1b26',
          foreground: '#a9b1d6',
          cursor: '#c0caf5',
          selectionForeground: '#33467c',
          black: '#32344a',
          blue: '#7aa2f7',
          cyan: '#449dab',
          green: '#9ece6a',
          magenta: '#ad8ee6',
          red: '#f7768e',
          white: '#787c99',
          yellow: '#e0af68'
        }
      });
      terminal.open(terminalRef.current);
      terminalInstanceRef.current = terminal;
      writeToTerminal('Terminal initialized successfully', 'info');
    }
  }, []);  
  
  useEffect(() => {
    initializeWebContainer();
    setStatus(prev => ({
      ...prev, 
      serverReady: true, 
      loading: false
    }));
  }, [initializeWebContainer]);

  useEffect(() => {
    if (isInitialized && Object.keys(oldObj).length > 0) {
      updateWebContainer(oldObj);
    }
  }, [isInitialized, oldObj]);

  const updateWebContainer = async (fileStructure: any) => {
    if (!webContainerInstance) {
      writeToTerminal('WebContainer not initialized', 'error');
      return;
    }
  
    try {
      writeToTerminal('Updating project files...', 'info');
      await webContainerInstance.mount(fileStructure);
      
      writeToTerminal('Installing dependencies...', 'info');
      const installProcess = await webContainerInstance.spawn('npm', ['install']);
      installProcess.output.pipeTo(new WritableStream({
        write(data) {
          writeToTerminal(data, 'info');
        }
      }));
      const installResult = await installProcess.exit;
  
      if (installResult !== 0) {
        throw new Error('Dependency installation failed');
      }
  
      writeToTerminal('Starting development server...', 'info');
      const devProcess = await webContainerInstance.spawn('npm', ['run', 'dev']);
      devProcess.output.pipeTo(new WritableStream({
        write(data) {
          writeToTerminal(data, 'info');
        }
      }));
  
      webContainerInstance.on('server-ready', (port, url) => {
        writeToTerminal(`Server ready at ${url}`, 'success');
        setStatus(prev => ({
          ...prev, 
          serverReady: true, 
          loading: false
        }));
        
        if (iframeRef.current) {
          iframeRef.current.src = url;
        }
      });
    } catch (error: any) {
      writeToTerminal(`WebContainer update failed: ${error.message}`, 'error');
      setError('Failed to update WebContainer: ' + error.message);
    }
  };

  const handleQuerySubmit = async () => {
    if (!query.trim() || isProcessing) return;

    setIsProcessing(true);
    setError(null);

    try {
      const response = await sendQuery(query, isInitialQuery ? undefined : oldObj);
      console.log("Full response from server:", response);

      if (!response) {
        throw new Error('No response received from server');
      }

      let mergedObj;

      if (isInitialQuery) {
        const initialFiles = response.initialFiles || {};
        const initialData = response.data || {};
        console.log("Initial Files:", initialFiles);
        console.log("Initial Data:", initialData);
        
        mergedObj = mergeJson(initialFiles, initialData);
        setOldObj(mergedObj);
        setIsInitialQuery(false);
      } else {
        const data = response.data || {};
        console.log("Old Object Before Merge:", oldObj);
        console.log("New Data:", data);

        mergedObj = mergeJson(oldObj, data);
        console.log("Merged Object:", mergedObj);
        setOldObj(mergedObj);
      }

      await updateWebContainer(mergedObj);
    } catch (err: any) {
      console.error('Query submission error:', err);
      setError(err.message || 'An error occurred while processing your query.');
    } finally {
      setIsProcessing(false);
      setStatus(prev => ({
        ...prev, 
        serverReady: true, 
      }));

      console.log("After setting - Old Object:", oldObj);
    }
  };

  const handleReset = async () => {
    setIsProcessing(true);
    setError(null);
    
    try {
      // Reset all state
      setQuery('');
      setOldObj({});
      setIsInitialQuery(true);
      setStatus({ serverReady: false, loading: true });
      
      // Clear terminal
      if (terminalInstanceRef.current) {
        terminalInstanceRef.current.clear();
      }
      
      // Reset iframe
      if (iframeRef.current) {
        iframeRef.current.src = 'about:blank';
      }
      
      // Re-initialize WebContainer
      await initializeWebContainer();
      
      writeToTerminal('Environment reset successfully', 'success');
    } catch (error: any) {
      setError('Failed to reset environment: ' + error.message);
      writeToTerminal('Failed to reset environment', 'error');
    } finally {
      setStatus(prev => ({
        ...prev, 
        serverReady: true, 
        loading: false
      }));
      setIsProcessing(false);
    }
  };



  return (
    <div className="min-h-screen bg-gradient-to-b from-gray-50 to-gray-100 p-6">
      <Card className="max-w-6xl mx-auto bg-white/80 backdrop-blur-sm shadow-xl border-gray-200">
        <CardHeader>
          <div className="flex items-center justify-between">
            <CardTitle className="text-2xl font-bold bg-gradient-to-r from-blue-600 to-indigo-600 bg-clip-text text-transparent">
              WebContainer Development Environment
            </CardTitle>
            <div className="flex items-center gap-2">
              {status.serverReady ? (
                <Button
                  variant="outline"
                  size="sm"
                  onClick={handleReset}
                  disabled={isProcessing}
                  className="flex items-center gap-2"
                >
                  <PlusCircle className="w-4 h-4" />
                  New
                </Button>
              ) : (
                <Badge variant="secondary" className="h-6">
                  Initializing
                </Badge>
              )}
              {isProcessing && <RefreshCw className="w-4 h-4 animate-spin text-blue-600" />}
            </div>
          </div>
        </CardHeader>
        <CardContent className="space-y-6">
          <QueryInput
            query={query}
            setQuery={setQuery}
            onSubmit={handleQuerySubmit}
            isProcessing={isProcessing}
            isInitialized={isInitialized}
          />

          {error && (
            <div className="bg-red-50 border-l-4 border-red-500 p-4 rounded-r">
              <div className="flex items-center">
                <div className="flex-shrink-0">
                  <svg className="h-5 w-5 text-red-500" viewBox="0 0 20 20" fill="currentColor">
                    <path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clipRule="evenodd" />
                  </svg>
                </div>
                <div className="ml-3">
                  <p className="text-sm text-red-700">{error}</p>
                </div>
              </div>
            </div>
          )}

          <Tabs value={activeTab} onValueChange={setActiveTab} className="w-full">
            <TabsList className="grid w-full grid-cols-2 mb-4">
              <TabsTrigger value="preview" className="flex items-center gap-2">
                <Globe className="w-4 h-4" />
                Preview
              </TabsTrigger>
              <TabsTrigger value="terminal" className="flex items-center gap-2">
                <Terminal className="w-4 h-4" />
                Terminal
              </TabsTrigger>
            </TabsList>

            <TabsContent value="preview" className="border rounded-lg overflow-hidden bg-white">
              <div className="h-[600px] relative">
                {(status.loading || isProcessing) && (
                  <div className="absolute inset-0 flex items-center justify-center bg-gray-50">
                    <Loader />
                  </div>
                )}
                { Object.keys(oldObj).length === 0   && (
                  <div className="absolute inset-0 flex items-center justify-center bg-gray-50">
                    <StartTypingScreen />
                  </div>
                )}
                <iframe
                  ref={iframeRef}
                  className="w-full h-full"
                  title="WebContainer Preview"
                />
              </div>
            </TabsContent>

            <TabsContent value="terminal">
              <div className="border rounded-lg overflow-hidden">
                <div className="bg-gray-900 px-4 py-2 flex items-center justify-between">
                  <div className="flex items-center gap-2">
                    <Code2 className="w-4 h-4 text-gray-400" />
                    <span className="text-sm text-gray-300">Terminal Output</span>
                  </div>
                </div>
                <div 
                  ref={terminalRef} 
                  className="w-full h-[400px] bg-[#1a1b26] p-4"
                />
              </div>
            </TabsContent>
          </Tabs>
        </CardContent>
      </Card>
    </div>
  );
};

export default WebContainerApp;
"""
please fix it perfectly