import { redirect } from "next/navigation"; import { z } from "zod"; import { LeftRail } from "@/components/shell/LeftRail"; import { StatusBar } from "@/components/shell/StatusBar"; import { TopBar } from "@/components/shell/TopBar"; import { ApiAuthError, apiFetch } from "@/lib/api/http"; import { fetchClaws, fetchCredits, fetchMe } from "@/lib/api/team"; import { fetchCompanies, fetchOrgs, fetchStats, fetchTeams, type GroupSummary, type StructureStats, } from "@/lib/api/structure"; import type { Agent, Credits, User } from "@/lib/api/schemas"; // Every workspace page shares the persistent shell (top bar + structure rail + // context column + status bar). The layout server-fetches the chrome data once. export default async function WorkspaceLayout({ children, }: Readonly<{ children: React.ReactNode }>) { let user: User; let roster: Agent[]; let credits: Credits; let orgs: GroupSummary[]; let companies: GroupSummary[]; let teams: GroupSummary[]; let stats: StructureStats | null; let doors: number; try { // Non-critical chrome — never let one failed fetch break the shell. const opt = (p: Promise, fallback: T) => p.catch(() => fallback); const groups = (p: Promise) => p.catch(() => [] as T[]); [user, roster, credits, orgs, companies, teams, stats, doors] = await Promise.all([ fetchMe(), fetchClaws(), fetchCredits(), groups(fetchOrgs()), groups(fetchCompanies()), groups(fetchTeams()), opt(fetchStats(), null), opt( apiFetch(z.array(z.unknown()), "/api/approvals").then((a) => a.length), 0, ), ]); } catch (error) { if (error instanceof ApiAuthError) { redirect("/login"); } throw error; } return (
{children}
); }