| | import { useEffect, useMemo, useState } from 'react'; |
| | import type { Session, AuthChangeEvent } from '@supabase/supabase-js'; |
| | import { supabase } from './supabaseClient'; |
| | import { AuthPage } from './components/AuthPage'; |
| | import { Dashboard } from './pages/Dashboard'; |
| | import { DesignStudio } from './pages/DesignStudio'; |
| | import { HumanInLoopBuild } from './pages/HumanInLoopBuild'; |
| | import { Benchmarking } from './pages/Benchmarking'; |
| | import { Fabrication } from './pages/Fabrication'; |
| | import { Documentation } from './pages/Documentation'; |
| | import { api } from './api'; |
| | import './index.css'; |
| |
|
| | const AUTH_ENABLED = Boolean(import.meta.env.VITE_SUPABASE_URL); |
| |
|
| | const App = () => { |
| | const [session, setSession] = useState<Session | null>(null); |
| | const [authLoading, setAuthLoading] = useState(true); |
| | const [selectedPage, setSelectedPage] = useState('Design Studio'); |
| | const [designs, setDesigns] = useState<{ name: string, has_gds: boolean }[]>([]); |
| | const [selectedDesign, setSelectedDesign] = useState<string>(''); |
| | const [theme, setTheme] = useState<'light' | 'dark'>(() => { |
| | const saved = localStorage.getItem('agentic-theme'); |
| | return saved === 'dark' ? 'dark' : 'light'; |
| | }); |
| |
|
| | |
| | useEffect(() => { |
| | if (!AUTH_ENABLED) { |
| | setAuthLoading(false); |
| | return; |
| | } |
| | supabase.auth.getSession().then(({ data: { session: s } }: { data: { session: Session | null } }) => { |
| | setSession(s); |
| | setAuthLoading(false); |
| | }).catch(() => setAuthLoading(false)); |
| | const { data: { subscription } } = supabase.auth.onAuthStateChange((_event: AuthChangeEvent, s: Session | null) => { |
| | setSession(s); |
| | }); |
| | return () => subscription.unsubscribe(); |
| | }, []); |
| |
|
| | useEffect(() => { |
| | document.documentElement.setAttribute('data-theme', theme); |
| | localStorage.setItem('agentic-theme', theme); |
| | }, [theme]); |
| |
|
| | |
| | useEffect(() => { |
| | if (AUTH_ENABLED && !session) return; |
| | api.get('/designs') |
| | .then(res => { |
| | const data = res.data?.designs || []; |
| | setDesigns(data); |
| | if (data.length > 0) { |
| | const withGds = data.find((d: any) => d.has_gds); |
| | setSelectedDesign(withGds ? withGds.name : data[0].name); |
| | } |
| | }) |
| | .catch(err => console.error("Failed to fetch designs", err)); |
| | }, [session]); |
| |
|
| | const handleLogout = async () => { |
| | await supabase.auth.signOut(); |
| | setSession(null); |
| | setSelectedPage('Design Studio'); |
| | }; |
| |
|
| | const navItems = useMemo( |
| | () => [ |
| | { name: 'Home', icon: 'π ' }, |
| | { name: 'Design Studio', icon: 'β‘' }, |
| | { name: 'HITL Build', icon: 'π§βπ»' }, |
| | { name: 'Dashboard', icon: 'π' }, |
| | { name: 'Documentation', icon: 'π' }, |
| | { name: 'Benchmarking', icon: 'π' }, |
| | { name: 'Fabrication', icon: 'ποΈ' }, |
| | ], |
| | [] |
| | ); |
| |
|
| | |
| | if (authLoading) { |
| | return ( |
| | <div className="auth-loading"> |
| | <div className="auth-loading-spinner" /> |
| | <span>Loading AgentICβ¦</span> |
| | </div> |
| | ); |
| | } |
| |
|
| | if (AUTH_ENABLED && !session) { |
| | return <AuthPage onAuth={() => supabase.auth.getSession().then(({ data: { session: s } }: { data: { session: Session | null } }) => setSession(s))} />; |
| | } |
| |
|
| | return ( |
| | <div className="app-shell"> |
| | <aside className="app-sidebar"> |
| | <div className="app-brand"> |
| | <div className="app-brand-logo">A</div> |
| | <div> |
| | <div className="app-brand-title">AgentIC</div> |
| | <div className="app-brand-sub">Autonomous Silicon Studio</div> |
| | </div> |
| | </div> |
| | |
| | <div className="app-sidebar-group"> |
| | <div className="app-sidebar-label">Active Design</div> |
| | <select |
| | className="app-design-select" |
| | value={selectedDesign} |
| | onChange={(e) => setSelectedDesign(e.target.value)} |
| | > |
| | {designs.map((d) => ( |
| | <option key={d.name} value={d.name}> |
| | {d.name} {d.has_gds ? 'β’ GDS' : ''} |
| | </option> |
| | ))} |
| | </select> |
| | </div> |
| | |
| | <nav className="app-nav"> |
| | {navItems.map((item) => ( |
| | <button |
| | key={item.name} |
| | className={`app-nav-btn ${selectedPage === item.name ? 'active' : ''}`} |
| | onClick={() => setSelectedPage(item.name)} |
| | > |
| | <span>{item.icon}</span> |
| | <span>{item.name}</span> |
| | </button> |
| | ))} |
| | </nav> |
| | |
| | <div className="app-sidebar-footer"> |
| | {/* User info β only show when authenticated */} |
| | {session && ( |
| | <div className="app-user-info"> |
| | <div className="app-user-avatar"> |
| | {session.user.email?.[0]?.toUpperCase() || '?'} |
| | </div> |
| | <div className="app-user-details"> |
| | <div className="app-user-email">{session.user.email}</div> |
| | </div> |
| | </div> |
| | )} |
| | <button |
| | className="theme-toggle" |
| | onClick={() => setTheme((t) => (t === 'light' ? 'dark' : 'light'))} |
| | > |
| | {theme === 'light' ? 'π Dark' : 'βοΈ Light'} |
| | </button> |
| | {session && ( |
| | <button className="logout-btn" onClick={handleLogout}> |
| | β© Sign Out |
| | </button> |
| | )} |
| | <div className="app-version">AgentIC Β· 2026</div> |
| | </div> |
| | </aside> |
| | |
| | <main className="app-main"> |
| | <header className="app-topbar"> |
| | <h1>{selectedPage}</h1> |
| | <div className="app-topbar-meta">Multi-Agent Autonomous Silicon</div> |
| | </header> |
| | |
| | <section className="app-content"> |
| | {selectedPage === 'Home' && ( |
| | <div className="home-overview"> |
| | <div className="home-hero"> |
| | <div className="home-hero-badge">Text β Silicon</div> |
| | <h2 className="home-hero-title">Autonomous Chip Design Studio</h2> |
| | <p className="home-hero-desc"> |
| | From natural language to fabrication-ready GDSII β powered by multi-agent |
| | collaboration, intelligent specification analysis, self-healing loops, and |
| | a fully autonomous pipeline. |
| | </p> |
| | </div> |
| | |
| | <div className="home-card-grid"> |
| | <div className="home-kpi">{designs.length}<span>Designs</span></div> |
| | <div className="home-kpi">14<span>Pipeline Stages</span></div> |
| | <div className="home-kpi">5<span>Core Modules</span></div> |
| | <div className="home-kpi">AI<span>Agents</span></div> |
| | </div> |
| | |
| | <div className="home-section"> |
| | <h3 className="home-section-title">Multi-Agent Architecture</h3> |
| | <div className="home-agent-grid"> |
| | <div className="agent-card"> |
| | <div className="agent-icon">ποΈ</div> |
| | <div className="agent-name">Architect</div> |
| | <div className="agent-desc">Specification analysis and structured design decomposition</div> |
| | </div> |
| | <div className="agent-card"> |
| | <div className="agent-icon">π»</div> |
| | <div className="agent-name">RTL Designer + Reviewer</div> |
| | <div className="agent-desc">Multi-agent collaborative generation</div> |
| | </div> |
| | <div className="agent-card"> |
| | <div className="agent-icon">π§ͺ</div> |
| | <div className="agent-name">TB Designer</div> |
| | <div className="agent-desc">Automated testbench generation and validation</div> |
| | </div> |
| | <div className="agent-card"> |
| | <div className="agent-icon">π</div> |
| | <div className="agent-name">Error Analyst</div> |
| | <div className="agent-desc">Intelligent failure classification</div> |
| | </div> |
| | <div className="agent-card"> |
| | <div className="agent-icon">π</div> |
| | <div className="agent-name">Self-Healing Engine</div> |
| | <div className="agent-desc">Convergence-aware optimization and recovery</div> |
| | </div> |
| | <div className="agent-card"> |
| | <div className="agent-icon">π§ </div> |
| | <div className="agent-name">Deep Debugger</div> |
| | <div className="agent-desc">Causal failure analysis</div> |
| | </div> |
| | </div> |
| | </div> |
| | |
| | <div className="home-section"> |
| | <h3 className="home-section-title">Pipeline Flow</h3> |
| | <div className="pipeline-flow"> |
| | {[ |
| | { icon: 'π', label: 'SPEC', sub: 'Specification' }, |
| | { icon: 'π', label: 'VALIDATE', sub: 'Spec Validation' }, |
| | { icon: 'π²', label: 'EXPAND', sub: 'Hierarchy' }, |
| | { icon: 'βοΈ', label: 'FEASIBLE', sub: 'Feasibility' }, |
| | { icon: 'π', label: 'CDC', sub: 'Clock Domains' }, |
| | { icon: 'π', label: 'V-PLAN', sub: 'Verify Plan' }, |
| | { icon: 'π»', label: 'RTL', sub: 'Generation' }, |
| | { icon: 'π¨', label: 'FIX', sub: 'Code Quality' }, |
| | { icon: 'π§ͺ', label: 'VERIFY', sub: 'Simulation' }, |
| | { icon: 'π', label: 'FORMAL', sub: 'Formal' }, |
| | { icon: 'π', label: 'COV', sub: 'Coverage' }, |
| | { icon: 'πΊοΈ', label: 'FLOOR', sub: 'Floorplan' }, |
| | { icon: 'ποΈ', label: 'HARDEN', sub: 'Place+Route' }, |
| | { icon: 'β
', label: 'SIGNOFF', sub: 'Tape-out' }, |
| | ].map((s, i) => ( |
| | <div className="pipeline-stage" key={s.label}> |
| | <div className="pipeline-stage-icon">{s.icon}</div> |
| | <div className="pipeline-stage-label">{s.label}</div> |
| | <div className="pipeline-stage-sub">{s.sub}</div> |
| | {i < 13 && <div className="pipeline-arrow">β</div>} |
| | </div> |
| | ))} |
| | </div> |
| | </div> |
| | |
| | <div className="home-section"> |
| | <h3 className="home-section-title">Quick Start</h3> |
| | <div className="home-quickstart"> |
| | <div className="quickstart-step"> |
| | <div className="quickstart-num">1</div> |
| | <div>Go to <strong>Design Studio</strong> and describe any chip</div> |
| | </div> |
| | <div className="quickstart-step"> |
| | <div className="quickstart-num">2</div> |
| | <div>Watch AI agents autonomously build and verify your chip</div> |
| | </div> |
| | <div className="quickstart-step"> |
| | <div className="quickstart-num">3</div> |
| | <div>Check <strong>Dashboard</strong> for silicon metrics and signoff</div> |
| | </div> |
| | </div> |
| | <button className="btn-primary home-cta" onClick={() => setSelectedPage('Design Studio')}> |
| | Start New Build β |
| | </button> |
| | </div> |
| | </div> |
| | )} |
| | |
| | {selectedPage === 'Dashboard' && <Dashboard selectedDesign={selectedDesign} />} |
| | {selectedPage === 'Design Studio' && <DesignStudio />} |
| | {selectedPage === 'HITL Build' && <HumanInLoopBuild />} |
| | {selectedPage === 'Documentation' && <Documentation />} |
| | {selectedPage === 'Benchmarking' && <Benchmarking selectedDesign={selectedDesign} />} |
| | {selectedPage === 'Fabrication' && ( |
| | <Fabrication selectedDesign={selectedDesign} hasGds={designs.find((d) => d.name === selectedDesign)?.has_gds} /> |
| | )} |
| | </section> |
| | </main> |
| | </div> |
| | ); |
| | }; |
| |
|
| | export default App; |
| |
|