import { useEffect, useState } from "react"; import type { CapabilityGroup, ContainerCapabilities, Project, } from "../../../lib/types"; import { listContainerCapabilities } from "../../../lib/tauri-commands"; import Modal from "../../ui/Modal"; import Button from "../../ui/Button"; /** * Read-only inventory of what Claude Code can do inside this container. * Triple-C surfaces counts and launches the real editors in the terminal — * it does not rebuild `/agents`, `/hooks`, or `/plugins` as forms. */ const GROUPS: { key: keyof ContainerCapabilities; label: string }[] = [ { key: "skills", label: "Skills" }, { key: "agents", label: "Agents" }, { key: "commands", label: "Commands" }, { key: "hooks", label: "Hooks" }, { key: "plugins", label: "Plugins" }, { key: "mcp_servers", label: "MCP servers" }, ]; const SLASH_HINT: Partial> = { agents: "/agents", hooks: "/hooks", plugins: "/plugins", mcp_servers: "/mcp", }; interface Props { project: Project; onManageInTerminal: (command: string) => void; } export default function CapabilityTiles({ project, onManageInTerminal }: Props) { const [capabilities, setCapabilities] = useState(null); const [loading, setLoading] = useState(false); const [open, setOpen] = useState(null); const running = project.status === "running"; useEffect(() => { if (!running) { setCapabilities(null); return; } let cancelled = false; setLoading(true); listContainerCapabilities(project.id) .then((c) => { if (!cancelled) setCapabilities(c); }) // Introspection degrades to "nothing found" when the container is // unreachable — that is an empty state, not an error banner. .catch(() => { if (!cancelled) setCapabilities(null); }) .finally(() => { if (!cancelled) setLoading(false); }); return () => { cancelled = true; }; }, [project.id, running, project.container_id]); const openGroup: CapabilityGroup | null = open && capabilities ? capabilities[open] : null; const openLabel = GROUPS.find((g) => g.key === open)?.label ?? ""; return (

Capabilities

{!running ? (

Start the container to read its skills, agents, commands, hooks and plugins.

) : loading && !capabilities ? (

Reading container volume…

) : (
{GROUPS.map(({ key, label }) => { const count = capabilities?.[key].count ?? 0; return ( ); })}
)} {open && openGroup && ( setOpen(null)} widthClassName="w-[34rem]" footer={ <> } > {openGroup.items.length === 0 ? (

Nothing configured.

) : (
    {openGroup.items.map((item, i) => (
  • {item.name} {item.scope}
    {item.description && (

    {item.description}

    )}
  • ))}
)}
)}
); }