{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"agent-status","type":"registry:ui","title":"Agent Status","description":"Status for an AI agent working on its own — running, waiting on you, completed or failed, with what it did last.","author":"Scrim UI (https://scrimui.dev)","categories":["agents"],"docs":"https://scrimui.dev/components/agent-status","dependencies":[],"registryDependencies":[],"files":[{"path":"src/showcase/agent-status/agent-status.tsx","content":"\"use client\";\n\nimport * as React from \"react\";\n\n/* ------------------------------------------------------------------ */\n/* Types                                                               */\n/* ------------------------------------------------------------------ */\n\nexport type AgentState = \"running\" | \"waiting\" | \"completed\" | \"failed\";\n\nexport type AgentStatusProps = {\n  name: string;\n  status: AgentState;\n  action?: string;\n  progress?: number;\n  elapsed?: string;\n  icon?: React.ReactNode;\n  onStop?: () => void;\n  onRetry?: () => void;\n  className?: string;\n};\n\n/* ------------------------------------------------------------------ */\n/* Icons                                                               */\n/* ------------------------------------------------------------------ */\n\nfunction BotIcon(props: React.SVGProps<SVGSVGElement>) {\n  return (\n    <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" width=\"16\" height=\"16\" {...props}>\n      <rect width=\"18\" height=\"10\" x=\"3\" y=\"8\" rx=\"2\" />\n      <path d=\"M12 8V4a2 2 0 0 1 2-2h2\" />\n      <circle cx=\"9\" cy=\"13\" r=\"0.5\" fill=\"currentColor\" />\n      <circle cx=\"15\" cy=\"13\" r=\"0.5\" fill=\"currentColor\" />\n      <path d=\"M5 11v6M19 11v6M9 17h6\" />\n    </svg>\n  );\n}\n\nfunction CheckIcon(props: React.SVGProps<SVGSVGElement>) {\n  return (\n    <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" width=\"12\" height=\"12\" {...props}>\n      <path d=\"M20 6 9 17l-5-5\" />\n    </svg>\n  );\n}\n\nfunction XIcon(props: React.SVGProps<SVGSVGElement>) {\n  return (\n    <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" width=\"12\" height=\"12\" {...props}>\n      <path d=\"M18 6 6 18M6 6l12 12\" />\n    </svg>\n  );\n}\n\nfunction PauseIcon(props: React.SVGProps<SVGSVGElement>) {\n  return (\n    <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" width=\"11\" height=\"11\" {...props}>\n      <rect x=\"6\" y=\"5\" width=\"4\" height=\"14\" rx=\"1\" />\n      <rect x=\"14\" y=\"5\" width=\"4\" height=\"14\" rx=\"1\" />\n    </svg>\n  );\n}\n\nfunction StopIcon(props: React.SVGProps<SVGSVGElement>) {\n  return (\n    <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" width=\"10\" height=\"10\" {...props}>\n      <rect x=\"6\" y=\"6\" width=\"12\" height=\"12\" rx=\"2\" />\n    </svg>\n  );\n}\n\n/* ------------------------------------------------------------------ */\n/* Status pill + progress                                              */\n/* ------------------------------------------------------------------ */\n\nconst STATUS_STYLES: Record<AgentState, { pill: string; icon: React.ReactNode; label: string }> = {\n  running: {\n    pill: \"bg-blue-100 text-blue-700 dark:bg-blue-900/40 dark:text-blue-400\",\n    icon: (\n      <span className=\"h-2.5 w-2.5 animate-spin rounded-full border-[1.5px] border-current border-t-transparent\" />\n    ),\n    label: \"Running\",\n  },\n  waiting: {\n    pill: \"bg-amber-100 text-amber-700 dark:bg-amber-900/40 dark:text-amber-400\",\n    icon: <PauseIcon />,\n    label: \"Waiting\",\n  },\n  completed: {\n    pill: \"bg-emerald-100 text-emerald-700 dark:bg-emerald-900/40 dark:text-emerald-400\",\n    icon: <CheckIcon />,\n    label: \"Completed\",\n  },\n  failed: {\n    pill: \"bg-red-100 text-red-700 dark:bg-red-900/40 dark:text-red-400\",\n    icon: <XIcon />,\n    label: \"Failed\",\n  },\n};\n\n/* ------------------------------------------------------------------ */\n/* AgentStatus                                                         */\n/* ------------------------------------------------------------------ */\n\nexport function AgentStatus({\n  name,\n  status,\n  action,\n  progress,\n  elapsed,\n  icon,\n  onStop,\n  onRetry,\n  className = \"\",\n}: AgentStatusProps) {\n  const s = STATUS_STYLES[status];\n\n  return (\n    <div\n      className={`rounded-xl border border-zinc-200 bg-white p-3.5 transition-colors dark:border-zinc-800 dark:bg-zinc-900 ${\n        status === \"failed\"\n          ? \"border-red-200 dark:border-red-900/60\"\n          : status === \"running\"\n            ? \"border-zinc-300 dark:border-zinc-700\"\n            : \"\"\n      } ${className}`}\n    >\n      <div className=\"flex items-center gap-3\">\n        <span\n          className={`flex h-9 w-9 shrink-0 items-center justify-center rounded-lg ${\n            status === \"failed\"\n              ? \"bg-red-100 text-red-600 dark:bg-red-900/40 dark:text-red-400\"\n              : status === \"completed\"\n                ? \"bg-emerald-100 text-emerald-600 dark:bg-emerald-900/40 dark:text-emerald-400\"\n                : \"bg-zinc-100 text-zinc-600 dark:bg-zinc-800 dark:text-zinc-300\"\n          }`}\n        >\n          {icon ?? <BotIcon />}\n        </span>\n\n        <div className=\"min-w-0 flex-1\">\n          <div className=\"flex flex-wrap items-center gap-2\">\n            <span className=\"truncate text-sm font-medium text-zinc-900 dark:text-zinc-100\">\n              {name}\n            </span>\n            <span className={`inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[11px] ${s.pill}`}>\n              {s.icon}\n              {s.label}\n            </span>\n            {elapsed && <span className=\"text-xs tabular-nums text-zinc-500 dark:text-zinc-400\">{elapsed}</span>}\n          </div>\n          {action && (\n            <p className=\"mt-0.5 truncate text-[13px] text-zinc-500 dark:text-zinc-400\">{action}</p>\n          )}\n        </div>\n\n        {status === \"running\" && onStop && (\n          <button\n            type=\"button\"\n            onClick={onStop}\n            aria-label={`Stop ${name}`}\n            className=\"flex h-7 w-7 shrink-0 items-center justify-center rounded-lg border border-zinc-200 text-zinc-500 transition-colors hover:bg-zinc-100 hover:text-zinc-900 dark:border-zinc-700 dark:text-zinc-400 dark:hover:bg-zinc-800 dark:hover:text-zinc-100\"\n          >\n            <StopIcon />\n          </button>\n        )}\n        {status === \"failed\" && onRetry && (\n          <button\n            type=\"button\"\n            onClick={onRetry}\n            className=\"inline-flex h-7 shrink-0 items-center gap-1.5 rounded-lg border border-zinc-200 px-2.5 text-xs font-medium text-zinc-600 transition-colors hover:bg-zinc-100 hover:text-zinc-900 dark:border-zinc-700 dark:text-zinc-300 dark:hover:bg-zinc-800 dark:hover:text-zinc-100\"\n          >\n            <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" width=\"12\" height=\"12\">\n              <path d=\"M21 12a9 9 0 1 1-2.64-6.36L21 8\" />\n              <path d=\"M21 3v5h-5\" />\n            </svg>\n            Retry\n          </button>\n        )}\n      </div>\n\n      {/* Progress bar */}\n      {status === \"running\" && progress !== undefined && (\n        <div className=\"mt-3 h-1 overflow-hidden rounded-full bg-zinc-100 dark:bg-zinc-800\">\n          <div\n            className=\"h-full rounded-full bg-blue-500 transition-all duration-300\"\n            style={{ width: `${Math.min(100, Math.max(0, progress))}%` }}\n          />\n        </div>\n      )}\n    </div>\n  );\n}\n","type":"registry:ui","target":"components/ui/agent-status.tsx"}]}