2025-12-13 12:35:03 +08:00
|
|
|
/**
|
|
|
|
|
* Sidebar Component
|
|
|
|
|
* Cyberpunk Terminal Aesthetic
|
|
|
|
|
*/
|
|
|
|
|
|
2025-11-27 18:01:57 +08:00
|
|
|
import { useState } from "react";
|
|
|
|
|
import { Link, useLocation } from "react-router-dom";
|
|
|
|
|
import { Button } from "@/components/ui/button";
|
|
|
|
|
import {
|
|
|
|
|
Menu,
|
|
|
|
|
X,
|
|
|
|
|
LayoutDashboard,
|
|
|
|
|
FolderGit2,
|
|
|
|
|
Zap,
|
|
|
|
|
ListTodo,
|
|
|
|
|
Settings,
|
|
|
|
|
Trash2,
|
|
|
|
|
ChevronLeft,
|
|
|
|
|
ChevronRight,
|
2025-11-28 01:06:01 +08:00
|
|
|
Github,
|
2025-12-09 21:42:00 +08:00
|
|
|
UserCircle,
|
|
|
|
|
Shield,
|
feat(agent): implement comprehensive agent architecture with knowledge base and persistence layer
- Add database migrations for agent checkpoints and tree node tracking
- Implement core agent execution framework with executor, state management, and message handling
- Create knowledge base system with framework-specific modules (Django, FastAPI, Flask, Express, React, Supabase)
- Add vulnerability knowledge modules covering authentication, cryptography, injection, XSS, XXE, SSRF, path traversal, deserialization, and race conditions
- Introduce new agent tools: thinking tool, reporting tool, and agent-specific utilities
- Implement LLM memory compression and prompt caching for improved performance
- Add agent registry and persistence layer for checkpoint management
- Refactor agent implementations (analysis, recon, verification, orchestrator) with enhanced capabilities
- Remove legacy agent implementations (analysis_v2, react_agent)
- Update API endpoints for agent task creation and project management
- Add frontend components for agent task creation and enhanced audit UI
- Consolidate agent service architecture with improved separation of concerns
- This refactoring provides a scalable foundation for multi-agent collaboration with knowledge-driven decision making and state persistence
2025-12-12 15:27:12 +08:00
|
|
|
MessageSquare,
|
2025-12-13 12:35:03 +08:00
|
|
|
Bot,
|
|
|
|
|
Terminal
|
2025-11-27 18:01:57 +08:00
|
|
|
} from "lucide-react";
|
|
|
|
|
import routes from "@/app/routes";
|
2025-11-28 16:16:29 +08:00
|
|
|
import { version } from "../../../package.json";
|
2025-11-27 18:01:57 +08:00
|
|
|
|
|
|
|
|
// Icon mapping for routes
|
|
|
|
|
const routeIcons: Record<string, React.ReactNode> = {
|
2025-12-13 12:35:03 +08:00
|
|
|
"/": <Bot className="w-5 h-5" />,
|
|
|
|
|
"/dashboard": <LayoutDashboard className="w-5 h-5" />,
|
2025-11-27 18:01:57 +08:00
|
|
|
"/projects": <FolderGit2 className="w-5 h-5" />,
|
|
|
|
|
"/instant-analysis": <Zap className="w-5 h-5" />,
|
|
|
|
|
"/audit-tasks": <ListTodo className="w-5 h-5" />,
|
2025-12-09 21:42:00 +08:00
|
|
|
"/audit-rules": <Shield className="w-5 h-5" />,
|
|
|
|
|
"/prompts": <MessageSquare className="w-5 h-5" />,
|
2025-11-27 18:01:57 +08:00
|
|
|
"/admin": <Settings className="w-5 h-5" />,
|
|
|
|
|
"/recycle-bin": <Trash2 className="w-5 h-5" />,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
interface SidebarProps {
|
|
|
|
|
collapsed: boolean;
|
|
|
|
|
setCollapsed: (collapsed: boolean) => void;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default function Sidebar({ collapsed, setCollapsed }: SidebarProps) {
|
|
|
|
|
const location = useLocation();
|
|
|
|
|
const [mobileOpen, setMobileOpen] = useState(false);
|
|
|
|
|
|
|
|
|
|
const visibleRoutes = routes.filter(route => route.visible !== false);
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
{/* Mobile Menu Button */}
|
|
|
|
|
<Button
|
|
|
|
|
variant="ghost"
|
|
|
|
|
size="sm"
|
2025-12-13 12:35:03 +08:00
|
|
|
className="fixed top-4 left-4 z-50 md:hidden bg-[#0c0c12] border border-gray-800 text-gray-300 hover:bg-gray-800 hover:text-white"
|
2025-11-27 18:01:57 +08:00
|
|
|
onClick={() => setMobileOpen(!mobileOpen)}
|
|
|
|
|
>
|
|
|
|
|
{mobileOpen ? <X className="w-5 h-5" /> : <Menu className="w-5 h-5" />}
|
|
|
|
|
</Button>
|
|
|
|
|
|
|
|
|
|
{/* Overlay for mobile */}
|
|
|
|
|
{mobileOpen && (
|
|
|
|
|
<div
|
2025-12-13 12:35:03 +08:00
|
|
|
className="fixed inset-0 bg-black/70 backdrop-blur-sm z-40 md:hidden"
|
2025-11-27 18:01:57 +08:00
|
|
|
onClick={() => setMobileOpen(false)}
|
|
|
|
|
/>
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
{/* Sidebar */}
|
|
|
|
|
<aside
|
|
|
|
|
className={`
|
2025-12-13 12:35:03 +08:00
|
|
|
fixed top-0 left-0 h-screen
|
|
|
|
|
bg-[#0a0a0f] border-r border-gray-800/60
|
|
|
|
|
z-40 transition-all duration-300 ease-in-out
|
|
|
|
|
${collapsed ? "w-20" : "w-64"}
|
|
|
|
|
${mobileOpen ? "translate-x-0" : "-translate-x-full md:translate-x-0"}
|
|
|
|
|
`}
|
2025-11-27 18:01:57 +08:00
|
|
|
>
|
2025-11-27 21:33:51 +08:00
|
|
|
<div className="flex flex-col h-full relative">
|
2025-12-13 12:35:03 +08:00
|
|
|
{/* Subtle grid background */}
|
|
|
|
|
<div
|
|
|
|
|
className="absolute inset-0 opacity-30 pointer-events-none"
|
|
|
|
|
style={{
|
|
|
|
|
backgroundImage: `
|
|
|
|
|
linear-gradient(rgba(255,107,44,0.03) 1px, transparent 1px),
|
|
|
|
|
linear-gradient(90deg, rgba(255,107,44,0.03) 1px, transparent 1px)
|
|
|
|
|
`,
|
|
|
|
|
backgroundSize: '24px 24px',
|
|
|
|
|
}}
|
|
|
|
|
/>
|
2025-11-27 21:33:51 +08:00
|
|
|
|
2025-11-27 18:01:57 +08:00
|
|
|
{/* Logo Section */}
|
2025-12-13 12:35:03 +08:00
|
|
|
<div className={`
|
|
|
|
|
relative flex items-center h-[72px]
|
|
|
|
|
border-b border-gray-800/60 bg-[#0c0c12]
|
|
|
|
|
${collapsed ? 'px-3 justify-center' : 'px-4 pr-6'}
|
|
|
|
|
`}>
|
2025-11-27 18:01:57 +08:00
|
|
|
<Link
|
|
|
|
|
to="/"
|
2025-12-13 12:35:03 +08:00
|
|
|
className={`
|
|
|
|
|
flex items-center gap-3 group transition-all duration-300
|
|
|
|
|
${collapsed ? 'justify-center' : 'flex-1 min-w-0'}
|
|
|
|
|
`}
|
2025-11-27 18:01:57 +08:00
|
|
|
onClick={() => setMobileOpen(false)}
|
|
|
|
|
>
|
2025-12-13 12:35:03 +08:00
|
|
|
{/* Logo Icon */}
|
|
|
|
|
<div className="relative flex-shrink-0">
|
|
|
|
|
<div className="w-10 h-10 bg-[#0a0a0f] border border-primary/30 rounded-lg flex items-center justify-center overflow-hidden group-hover:border-primary/60 transition-colors">
|
|
|
|
|
<img
|
|
|
|
|
src="/logo_deepaudit.png"
|
|
|
|
|
alt="DeepAudit"
|
|
|
|
|
className="w-7 h-7 object-contain"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
{/* Glow effect */}
|
|
|
|
|
<div className="absolute inset-0 bg-primary/20 rounded-lg blur-xl opacity-0 group-hover:opacity-100 transition-opacity" />
|
2025-11-27 18:01:57 +08:00
|
|
|
</div>
|
2025-12-13 12:35:03 +08:00
|
|
|
|
|
|
|
|
{/* Logo Text */}
|
|
|
|
|
<div className={`
|
|
|
|
|
transition-all duration-300
|
|
|
|
|
${collapsed ? 'w-0 opacity-0 overflow-hidden' : 'flex-1 min-w-0 opacity-100'}
|
|
|
|
|
`}>
|
|
|
|
|
<div
|
|
|
|
|
className="text-xl font-bold tracking-wider font-mono"
|
|
|
|
|
style={{ textShadow: '0 0 20px rgba(255,107,44,0.3)' }}
|
|
|
|
|
>
|
|
|
|
|
<span className="text-primary">DEEP</span>
|
|
|
|
|
<span className="text-white">AUDIT</span>
|
|
|
|
|
</div>
|
2025-11-27 18:01:57 +08:00
|
|
|
</div>
|
|
|
|
|
</Link>
|
|
|
|
|
|
2025-12-13 12:35:03 +08:00
|
|
|
{/* Collapse button */}
|
2025-11-27 21:33:51 +08:00
|
|
|
<button
|
2025-12-13 12:35:03 +08:00
|
|
|
className={`
|
|
|
|
|
hidden md:flex absolute -right-3 top-1/2 -translate-y-1/2
|
|
|
|
|
w-6 h-6 bg-[#0c0c12] border border-gray-700 rounded
|
|
|
|
|
items-center justify-center text-gray-500
|
|
|
|
|
hover:bg-primary hover:border-primary hover:text-white
|
|
|
|
|
transition-all duration-200
|
|
|
|
|
`}
|
2025-11-27 18:01:57 +08:00
|
|
|
onClick={() => setCollapsed(!collapsed)}
|
2025-11-27 22:34:23 +08:00
|
|
|
style={{ zIndex: 100 }}
|
2025-11-27 18:01:57 +08:00
|
|
|
>
|
|
|
|
|
{collapsed ? (
|
|
|
|
|
<ChevronRight className="w-3 h-3" />
|
|
|
|
|
) : (
|
|
|
|
|
<ChevronLeft className="w-3 h-3" />
|
|
|
|
|
)}
|
2025-11-27 21:33:51 +08:00
|
|
|
</button>
|
2025-11-27 18:01:57 +08:00
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* Navigation */}
|
2025-12-13 12:35:03 +08:00
|
|
|
<nav className="flex-1 overflow-y-auto py-4 px-3 custom-scrollbar">
|
|
|
|
|
<div className="space-y-1">
|
2025-11-27 18:01:57 +08:00
|
|
|
{visibleRoutes.map((route) => {
|
|
|
|
|
const isActive = location.pathname === route.path;
|
|
|
|
|
return (
|
|
|
|
|
<Link
|
|
|
|
|
key={route.path}
|
|
|
|
|
to={route.path}
|
|
|
|
|
className={`
|
2025-12-13 12:35:03 +08:00
|
|
|
flex items-center gap-3 px-3 py-2.5
|
|
|
|
|
transition-all duration-200 group relative rounded-lg
|
|
|
|
|
${isActive
|
|
|
|
|
? "bg-primary/15 text-primary border border-primary/30"
|
|
|
|
|
: "text-gray-400 hover:text-gray-200 hover:bg-gray-800/50 border border-transparent"
|
2025-11-27 18:01:57 +08:00
|
|
|
}
|
2025-12-13 12:35:03 +08:00
|
|
|
`}
|
2025-11-27 18:01:57 +08:00
|
|
|
onClick={() => setMobileOpen(false)}
|
|
|
|
|
title={collapsed ? route.name : undefined}
|
|
|
|
|
>
|
2025-12-13 12:35:03 +08:00
|
|
|
{/* Active indicator */}
|
|
|
|
|
{isActive && (
|
|
|
|
|
<div className="absolute left-0 top-1/2 -translate-y-1/2 w-1 h-6 bg-primary rounded-r" />
|
|
|
|
|
)}
|
|
|
|
|
|
2025-11-27 18:01:57 +08:00
|
|
|
{/* Icon */}
|
|
|
|
|
<span className={`
|
2025-12-13 12:35:03 +08:00
|
|
|
flex-shrink-0 transition-colors duration-200
|
|
|
|
|
${isActive ? "text-primary" : "text-gray-500 group-hover:text-gray-300"}
|
|
|
|
|
`}>
|
2025-11-27 18:01:57 +08:00
|
|
|
{routeIcons[route.path] || <LayoutDashboard className="w-5 h-5" />}
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
|
|
{/* Label */}
|
|
|
|
|
{!collapsed && (
|
2025-12-13 12:35:03 +08:00
|
|
|
<span className={`
|
|
|
|
|
font-mono text-sm tracking-wide
|
|
|
|
|
${isActive ? 'font-semibold' : 'font-medium'}
|
|
|
|
|
`}>
|
2025-11-27 18:01:57 +08:00
|
|
|
{route.name}
|
|
|
|
|
</span>
|
|
|
|
|
)}
|
|
|
|
|
|
2025-12-13 12:35:03 +08:00
|
|
|
{/* Hover arrow */}
|
2025-11-27 21:33:51 +08:00
|
|
|
{!isActive && !collapsed && (
|
2025-12-13 12:35:03 +08:00
|
|
|
<span className="absolute right-3 opacity-0 group-hover:opacity-100 text-xs text-primary transition-opacity">
|
|
|
|
|
→
|
2025-11-27 21:33:51 +08:00
|
|
|
</span>
|
2025-11-27 18:01:57 +08:00
|
|
|
)}
|
|
|
|
|
</Link>
|
|
|
|
|
);
|
|
|
|
|
})}
|
|
|
|
|
</div>
|
|
|
|
|
</nav>
|
|
|
|
|
|
2025-12-13 12:35:03 +08:00
|
|
|
{/* Footer */}
|
|
|
|
|
<div className="p-3 border-t border-gray-800/60 bg-[#0c0c12] space-y-1">
|
2025-11-28 01:06:01 +08:00
|
|
|
{/* Account Link */}
|
|
|
|
|
<Link
|
|
|
|
|
to="/account"
|
|
|
|
|
className={`
|
2025-12-13 12:35:03 +08:00
|
|
|
flex items-center gap-3 px-3 py-2.5 rounded-lg
|
|
|
|
|
transition-all duration-200 group
|
|
|
|
|
${location.pathname === '/account'
|
|
|
|
|
? "bg-primary/15 text-primary border border-primary/30"
|
|
|
|
|
: "text-gray-400 hover:text-gray-200 hover:bg-gray-800/50 border border-transparent"
|
2025-11-28 01:06:01 +08:00
|
|
|
}
|
2025-12-13 12:35:03 +08:00
|
|
|
`}
|
2025-11-28 01:06:01 +08:00
|
|
|
onClick={() => setMobileOpen(false)}
|
|
|
|
|
title={collapsed ? "账号管理" : undefined}
|
|
|
|
|
>
|
2025-12-13 12:35:03 +08:00
|
|
|
<UserCircle className={`w-5 h-5 flex-shrink-0 ${
|
|
|
|
|
location.pathname === '/account' ? 'text-primary' : 'text-gray-500 group-hover:text-gray-300'
|
|
|
|
|
}`} />
|
2025-11-28 01:06:01 +08:00
|
|
|
{!collapsed && (
|
2025-12-13 12:35:03 +08:00
|
|
|
<span className="font-mono text-sm">账号管理</span>
|
2025-11-28 01:06:01 +08:00
|
|
|
)}
|
|
|
|
|
</Link>
|
|
|
|
|
|
|
|
|
|
{/* GitHub Link */}
|
2025-11-27 18:01:57 +08:00
|
|
|
<a
|
2025-12-08 21:35:09 +08:00
|
|
|
href="https://github.com/lintsinghua/DeepAudit"
|
2025-11-27 18:01:57 +08:00
|
|
|
target="_blank"
|
|
|
|
|
rel="noopener noreferrer"
|
|
|
|
|
className={`
|
2025-12-13 12:35:03 +08:00
|
|
|
flex items-center gap-3 px-3 py-2.5 rounded-lg
|
|
|
|
|
text-gray-400 hover:text-gray-200 hover:bg-gray-800/50
|
|
|
|
|
transition-all duration-200 group border border-transparent
|
|
|
|
|
`}
|
|
|
|
|
title={collapsed ? "GitHub" : undefined}
|
2025-11-27 18:01:57 +08:00
|
|
|
>
|
2025-12-13 12:35:03 +08:00
|
|
|
<Github className="w-5 h-5 flex-shrink-0 text-gray-500 group-hover:text-gray-300" />
|
2025-11-27 18:01:57 +08:00
|
|
|
{!collapsed && (
|
|
|
|
|
<div className="flex flex-col">
|
2025-12-13 12:35:03 +08:00
|
|
|
<span className="font-mono text-sm">GitHub</span>
|
|
|
|
|
<span className="text-[10px] text-gray-600 font-mono">v{version}</span>
|
2025-11-27 18:01:57 +08:00
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</a>
|
2025-12-13 12:35:03 +08:00
|
|
|
|
|
|
|
|
{/* System Status */}
|
|
|
|
|
{!collapsed && (
|
|
|
|
|
<div className="mt-3 pt-3 border-t border-gray-800/50">
|
|
|
|
|
<div className="flex items-center gap-2 px-3 py-2">
|
|
|
|
|
<div className="w-2 h-2 rounded-full bg-emerald-400 animate-pulse"
|
|
|
|
|
style={{ boxShadow: '0 0 8px rgba(52, 211, 153, 0.5)' }} />
|
|
|
|
|
<span className="text-[10px] text-gray-600 font-mono uppercase tracking-wider">
|
|
|
|
|
System Online
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
2025-11-27 18:01:57 +08:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</aside>
|
|
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
}
|