"use client"; import React, { useState, useEffect, useRef, memo } from "react"; import { MessageSquare, Send, Code2, Palette, Search, Trash2, Copy, Monitor, StopCircle, X, Zap, Ghost, Wand2, LayoutPanelLeft, Play, Orbit, Plus, Key } from "lucide-react"; import ReactMarkdown from "react-markdown"; import remarkGfm from "remark-gfm"; import rehypeHighlight from "rehype-highlight"; import { Download, Github } from "lucide-react"; import { downloadArtifactAsZip, pushToGithub } from "@/lib/artifact-utils"; import { cn } from "@/lib/utils"; import { AIAssistMessage } from "@/types"; import { Button } from "@/components/ui/button"; import { Card } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Input } from "@/components/ui/input"; import useStore from "@/lib/store"; import { translations } from "@/lib/i18n/translations"; import modelAdapter from "@/lib/services/adapter-instance"; // --- Types --- interface PreviewData { type: string; data: string; language?: string; isStreaming?: boolean; } // --- Specialized Components --- /** * A ultra-stable iframe wrapper that avoids hydration issues * and provides a WOW visual experience. */ // Error Boundary for Canvas crashes class CanvasErrorBoundary extends React.Component<{ children: React.ReactNode }, { hasError: boolean, error: string | null }> { constructor(props: { children: React.ReactNode }) { super(props); this.state = { hasError: false, error: null }; } static getDerivedStateFromError(error: Error) { return { hasError: true, error: error.message }; } render() { if (this.state.hasError) { return (
{this.state.error}
{renderError}
{t.agentLabel} {t.agents[currentAgent as keyof typeof t.agents] || currentAgent}
Sign in with Qwen to use AI Assist with this provider
{qwenAuthError && ({qwenAuthError}
)}{t.studioDesc}
{children}
{children}
);
},
}}
>
{parseStreamingContent(msg.content, msg.agent || "general").chatDisplay || (msg.role === "assistant" ? "..." : "")}
{t.architecture}
{aiPlan.architecture}
{t.techStack}
{t.files}
{t.filesPlanned(aiPlan.files?.length || 0)}
{currentPreviewData?.data}
{t.githubAuth}
Requires 'repo' scope. Get one at github.com/settings/tokens