Files
app/frontend/src/components/Sidebar/AppSidebar.tsx
T
stroblmeandClaude Fable 5 f300c43f3a Run python nodes out of process, with modules of their own
User code no longer execs in the engine. A pool of persistent worker
subprocesses speaks one JSON object per line; the controller installs a
proxy as the node's function, so every execution path funnels through it
and the pipeline is untouched. A crash costs one subprocess, a per-node
timeout is a kill, and cancelling from the canvas is that same kill.

The workers run a venv of the user's own on the data volume, filled from
a pip manifest versioned beside the flows. Applying it retires the
workers and rebuilds, so a package lands without restarting the engine.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017MeiWk3Yq12n2pTvnQWYvt
2026-08-16 21:43:36 +02:00

79 lines
2.6 KiB
TypeScript

import {
Bell,
Home,
KeyRound,
LayoutDashboard,
LogOut,
Package,
Settings,
Users,
Workflow,
} from "lucide-react"
import { Logo } from "@/components/Common/Logo"
import {
Sidebar,
SidebarContent,
SidebarFooter,
SidebarHeader,
SidebarTrigger,
} from "@/components/ui/sidebar"
import useAuth from "@/hooks/useAuth"
import { type Item, Main } from "./Main"
const baseItems: Item[] = [
// "Home" rather than "Dashboard": dashboards are their own thing now.
{ icon: Home, title: "Home", path: "/" },
{ icon: Workflow, title: "Flows", path: "/flows" },
{ icon: LayoutDashboard, title: "Dashboards", path: "/dashboards" },
// Both are engine-wide operator settings rather than personal ones, so they
// sit here and not among the per-user tabs under Settings.
{ icon: KeyRound, title: "Secrets", path: "/secrets" },
{ icon: Package, title: "Modules", path: "/modules" },
{ icon: Bell, title: "Alerts", path: "/alerts" },
]
export function AppSidebar() {
const { user: currentUser, logout } = useAuth()
const items = currentUser?.is_superuser
? [...baseItems, { icon: Users, title: "Admin", path: "/admin" }]
: baseItems
const footerItems: Item[] = [
{ icon: Settings, title: "Settings", path: "/settings" },
{ icon: LogOut, title: "Log Out", onClick: logout },
]
return (
// Floating frosted chrome over whatever surface the shell paints; see the
// root DESIGN-GUIDELINES.md → Shells and → Overlay surfaces & content chips.
<Sidebar
collapsible="icon"
variant="floating"
className="[&>[data-sidebar=sidebar]]:bg-card/80 [&>[data-sidebar=sidebar]]:backdrop-blur-md [&>[data-sidebar=sidebar]]:shadow-e2"
>
<SidebarHeader className="px-4 py-6 group-data-[collapsible=icon]:px-0 group-data-[collapsible=icon]:items-center">
<div className="flex w-full items-center justify-between gap-2 group-data-[collapsible=icon]:justify-center">
{/* Collapsed, the rail has room for one thing, and that is the way
back out. */}
<span className="group-data-[collapsible=icon]:hidden">
<Logo variant="responsive" />
</span>
{/* On a phone the sidebar is a sheet with its own way in and out. */}
<SidebarTrigger className="hidden shrink-0 text-muted-foreground md:inline-flex" />
</div>
</SidebarHeader>
<SidebarContent>
<Main items={items} />
</SidebarContent>
{/* Main already pads horizontally; the footer only adds the bottom gap. */}
<SidebarFooter className="px-0">
<Main items={footerItems} />
</SidebarFooter>
</Sidebar>
)
}
export default AppSidebar