{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "ai-agent-orchestrator",
  "title": "Ai Agent Orchestrator",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-angular/blocks/ai-agent-orchestrator/ai-agent-orchestrator.component.ts",
      "content": "// Edit this file to change the pipeline (`initialNodes`), the copy or the controls.\n// The pipeline is sample data: wire `stepForward`, `retryStep`, `rerunPipeline` and\n// `cancelWorkflow` to your agent runtime.\nimport {\n  Component,\n  DestroyRef,\n  Input,\n  afterNextRender,\n  computed,\n  inject,\n  signal,\n  ChangeDetectionStrategy,\n} from '@angular/core'\nimport {\n  Activity,\n  Bot,\n  Check,\n  CheckCircle2,\n  ChevronDown,\n  ChevronRight,\n  Clock,\n  Code2,\n  Compass,\n  Copy,\n  FastForward,\n  FileCode2,\n  FileText,\n  Globe,\n  Layers,\n  LucideAngularModule,\n  Pause,\n  Play,\n  RefreshCw,\n  RotateCcw,\n  Search,\n  ShieldCheck,\n  Sparkles,\n  Terminal,\n  X,\n  type LucideIconData,\n} from 'lucide-angular'\nimport { cn } from '@/lib/utils'\nimport { UiBadgeComponent } from '@/ui/badge/badge.component'\nimport { UiButtonComponent } from '@/ui/button/button.component'\nimport {\n  UiCardComponent,\n  UiCardContentComponent,\n  UiCardDescriptionComponent,\n  UiCardHeaderComponent,\n  UiCardTitleComponent,\n} from '@/ui/card/card.component'\nimport { UiProgressComponent } from '@/ui/progress/progress.component'\n\ntype AgentId = 'planner' | 'researcher' | 'engineer' | 'reviewer'\ntype NodeStatus = 'completed' | 'running' | 'queued'\n\ninterface ThoughtStep {\n  id: string\n  title: string\n  duration: string\n  status: 'completed' | 'running' | 'queued'\n  detail: string\n}\n\ninterface ToolInvocation {\n  name: string\n  count: number\n  icon: string\n}\n\ninterface AgentNode {\n  id: AgentId\n  stepNumber: number\n  name: string\n  role: string\n  iconName: string\n  model: string\n  status: NodeStatus\n  duration: string\n  task: string\n  tokens: string\n  speed: string\n  progress: number\n  tools: ToolInvocation[]\n  thoughts: ThoughtStep[]\n  artifactFileName: string\n  artifactSize: string\n  artifactCode: string\n}\n\nconst initialCodeSnippet = `import * as React from 'react'\nimport { useAgentGraph } from '@/hooks/useAgentGraph'\n\nexport interface AgentWorkflowConfig {\n  pipelineId: string\n  name: string\n  autonomousMode: boolean\n  maxRetries: number\n  timeoutMs: number\n}\n\nexport interface ExecutionArtifact {\n  fileName: string\n  language: string\n  content: string\n  checksum: string\n}\n\nexport async function dispatchAgentWorkflow(\n  config: AgentWorkflowConfig\n): Promise<ExecutionArtifact[]> {\n  const orchestrator = new MultiAgentEngine({\n    model: 'claude-3-5-sonnet',\n    telemetry: true,\n  })\n\n  // Stream reasoning thoughts and token outputs\n  const stream = await orchestrator.executePipeline(config.pipelineId)\n  return stream.collectArtifacts()\n}`\n\nconst initialNodes: AgentNode[] = [\n  {\n    id: 'planner',\n    stepNumber: 1,\n    name: 'Planner Agent',\n    role: 'Task Decomposition & Schema',\n    iconName: 'Compass',\n    model: 'Claude 3.5',\n    status: 'completed',\n    duration: '12s',\n    task: 'Deconstruct task into 4 sub-goals',\n    tokens: '842 tokens',\n    speed: '52 tok/s',\n    progress: 100,\n    tools: [\n      { name: 'spec_parse', count: 1, icon: 'Terminal' },\n      { name: 'context_index', count: 4, icon: 'FileText' },\n    ],\n    thoughts: [\n      {\n        id: 'p1',\n        title: 'Analyze project manifest and user constraints',\n        duration: '3.2s',\n        status: 'completed',\n        detail:\n          'Identified dual-framework registry requirement (Vue SFC + React TSX) with Tailwind v4 OKLCH token mapping.',\n      },\n      {\n        id: 'p2',\n        title: 'Partition workflow into 4 autonomous agent stages',\n        duration: '8.8s',\n        status: 'completed',\n        detail: 'Created topological execution graph: Planner -> Researcher -> Code Engineer -> Reviewer & QA.',\n      },\n    ],\n    artifactFileName: 'pipeline-manifest.json',\n    artifactSize: '1.1 kB',\n    artifactCode: `{\\n  \"pipeline\": \"autonomous-research-codegen\",\\n  \"stages\": 4,\\n  \"target\": \"UIPKGE Block Registry\",\\n  \"strictMode\": true\\n}`,\n  },\n  {\n    id: 'researcher',\n    stepNumber: 2,\n    name: 'Research Agent',\n    role: 'Documentation & API Contracts',\n    iconName: 'Search',\n    model: 'GPT-4o',\n    status: 'completed',\n    duration: '45s',\n    task: 'Query documentation and verify API contracts',\n    tokens: '1,420 tokens',\n    speed: '64 tok/s',\n    progress: 100,\n    tools: [\n      { name: 'web_search', count: 2, icon: 'Globe' },\n      { name: 'doc_scrape', count: 6, icon: 'FileText' },\n    ],\n    thoughts: [\n      {\n        id: 'r1',\n        title: 'Verify Reka UI and Radix UI primitive specifications',\n        duration: '18s',\n        status: 'completed',\n        detail: 'Confirmed Radix Progress and Reka Progress Root/Indicator element bindings for zero-drift parity.',\n      },\n      {\n        id: 'r2',\n        title: 'Check Lucide icon availability in Vue and React packages',\n        duration: '27s',\n        status: 'completed',\n        detail:\n          'Validated Compass, Search, Code2, ShieldCheck, FastForward, RotateCcw, RefreshCw icons across registries.',\n      },\n    ],\n    artifactFileName: 'api-contracts.d.ts',\n    artifactSize: '1.8 kB',\n    artifactCode: `export interface NodeContract {\\n  id: string\\n  status: 'completed' | 'running' | 'queued'\\n  duration: string\\n}`,\n  },\n  {\n    id: 'engineer',\n    stepNumber: 3,\n    name: 'Code Engineer Agent',\n    role: 'Component Synthesis & Tests',\n    iconName: 'Code2',\n    model: 'Claude 3.5',\n    status: 'running',\n    duration: '1m 17s',\n    task: 'Generate component architecture & unit tests',\n    tokens: '2,840 tokens',\n    speed: '48 tok/s',\n    progress: 68,\n    tools: [\n      { name: 'web_search', count: 2, icon: 'Globe' },\n      { name: 'file_read', count: 8, icon: 'FileText' },\n      { name: 'ast_parse', count: 1, icon: 'Terminal' },\n      { name: 'typecheck', count: 1, icon: 'ShieldCheck' },\n    ],\n    thoughts: [\n      {\n        id: 't1',\n        title: 'Parse upstream specifications from Planner & Research Agent',\n        duration: '14ms',\n        status: 'completed',\n        detail:\n          'Loaded 4 sub-goal definitions. Validated schema definitions for Reka UI and Radix UI primitive bindings.',\n      },\n      {\n        id: 't2',\n        title: 'Synthesize component state machine & reactive bindings',\n        duration: '420ms',\n        status: 'completed',\n        detail:\n          'Constructed state flow machine for pipeline progression. Hooked up active execution timers and streaming buffers.',\n      },\n      {\n        id: 't3',\n        title: 'Construct test matrix with boundary coverage',\n        duration: '850ms',\n        status: 'completed',\n        detail:\n          'Generated unit test cases covering step navigation, retry triggers, state pausing, and copy payload verification.',\n      },\n      {\n        id: 't4',\n        title: 'Stream production TypeScript & TSX definitions',\n        duration: '1m 17s',\n        status: 'running',\n        detail:\n          'Writing template layout with responsive CSS grid, glowing node state markers, tool invocation badge metrics, and dark-mode safe styling.',\n      },\n    ],\n    artifactFileName: 'AiAgentOrchestrator.tsx',\n    artifactSize: '2.4 kB',\n    artifactCode: initialCodeSnippet,\n  },\n  {\n    id: 'reviewer',\n    stepNumber: 4,\n    name: 'Reviewer & QA Agent',\n    role: 'Typecheck & Token Audit',\n    iconName: 'ShieldCheck',\n    model: 'Claude 3.5',\n    status: 'queued',\n    duration: '0s',\n    task: 'Validate TypeScript types and token standards',\n    tokens: '0 tokens',\n    speed: '0 tok/s',\n    progress: 0,\n    tools: [\n      { name: 'typecheck', count: 1, icon: 'ShieldCheck' },\n      { name: 'token_audit', count: 1, icon: 'Terminal' },\n    ],\n    thoughts: [\n      {\n        id: 'q1',\n        title: 'Perform static type-safety and interface contract validation',\n        duration: '0s',\n        status: 'queued',\n        detail:\n          'Awaiting Code Engineer stream completion to run full TypeScript compiler validation without any types.',\n      },\n      {\n        id: 'q2',\n        title: 'Verify minimum 12px font scale and OKLCH color token conformance',\n        duration: '0s',\n        status: 'queued',\n        detail: 'Scanning AST for forbidden sub-12px micro-classes and hardcoded hex color values.',\n      },\n    ],\n    artifactFileName: 'qa-audit-report.md',\n    artifactSize: '0.9 kB',\n    artifactCode: `# QA Verification Gate\\n- [ ] TypeScript parity check\\n- [ ] Design token conformance\\n- [ ] Accessibility keyboard focus`,\n  },\n]\n\nconst NODE_BASE =\n  'group focus-visible:ring-ring relative flex w-full cursor-pointer flex-col justify-between rounded-xl border p-4 text-left transition-[border-color,box-shadow] duration-200 focus-visible:ring-2 focus-visible:ring-offset-1 focus-visible:outline-none'\n\n/** Per-node class variations, exactly as the React block writes them for each of its four node buttons. */\nconst NODE_STYLES: Record<\n  AgentId,\n  { selected: string; idle: string; running: string; queued: string; iconRunning: string; iconQueued: string }\n> = {\n  planner: {\n    selected: 'border-primary ring-primary/30 shadow-xs ring-2',\n    idle: 'border-border hover:border-muted-foreground/40',\n    running: 'border-primary/60 bg-primary/[0.03]',\n    queued: 'bg-muted/20 opacity-75',\n    iconRunning: 'border-primary/30 bg-primary/10 text-primary',\n    iconQueued: 'border-border bg-muted text-muted-foreground',\n  },\n  researcher: {\n    selected: 'border-primary ring-primary/30 shadow-xs ring-2',\n    idle: 'border-border hover:border-muted-foreground/40',\n    running: 'border-primary/60 bg-primary/[0.03]',\n    queued: 'bg-muted/20 opacity-75',\n    iconRunning: 'border-primary/30 bg-primary/10 text-primary',\n    iconQueued: 'border-border bg-muted text-muted-foreground',\n  },\n  engineer: {\n    selected: 'border-primary ring-primary/40 shadow-xs ring-2',\n    idle: 'border-border hover:border-muted-foreground/40',\n    running: 'border-primary/60 bg-primary/[0.04]',\n    queued: 'bg-muted/20 opacity-75',\n    iconRunning: 'border-primary/40 bg-primary/15 text-primary',\n    iconQueued: 'border-border bg-muted text-muted-foreground',\n  },\n  reviewer: {\n    selected: 'border-primary ring-primary/30 shadow-xs ring-2',\n    idle: 'border-border/80 hover:border-muted-foreground/40',\n    running: 'border-primary/60 bg-primary/[0.03]',\n    queued: 'bg-muted/15 border-dashed',\n    iconRunning: 'border-primary/30 bg-primary/10 text-primary',\n    iconQueued: 'border-border bg-muted/60 text-muted-foreground',\n  },\n}\n\nconst AGENT_ICONS: Record<AgentId, LucideIconData> = {\n  planner: Compass,\n  researcher: Search,\n  engineer: Code2,\n  reviewer: ShieldCheck,\n}\n\n/**\n * AiAgentOrchestrator -- the React block, 1:1: a multi-agent pipeline dashboard with a run\n * header (status, live timer, pause / cancel), a four-node execution graph, and a detail\n * panel for the selected node (progress, telemetry, thought stream, tool invocations, the\n * generated artifact) plus pipeline controls (step forward, retry, re-run, pause).\n *\n * Icon notes (lucide-angular wraps each <svg> in a <lucide-icon> host, so the Badge's\n * `[&>svg]:size-3` and the Button's `has-[>svg]:px-*` never see it): icons inside badges are\n * written at the size-3 React renders them at, and icon buttons carry the `px-*` React's\n * `has-[>svg]` resolves to. Icons with a margin use `[class]` so the margin lands on the svg only.\n */\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-ai-agent-orchestrator, [ui-ai-agent-orchestrator]',\n  standalone: true,\n  host: {\n    '[attr.data-slot]': '\"ai-agent-orchestrator\"',\n    '[class]': 'hostClass',\n  },\n  imports: [\n    LucideAngularModule,\n    UiBadgeComponent,\n    UiButtonComponent,\n    UiCardComponent,\n    UiCardContentComponent,\n    UiCardDescriptionComponent,\n    UiCardHeaderComponent,\n    UiCardTitleComponent,\n    UiProgressComponent,\n  ],\n  template: `\n    <!-- Top Header Bar -->\n    <div ui-card class=\"border-border bg-card shadow-xs\">\n      <div ui-card-content class=\"flex flex-col gap-4 p-5 sm:flex-row sm:items-center sm:justify-between\">\n        <div class=\"flex items-start gap-3.5 sm:items-center\">\n          <div\n            class=\"bg-primary/10 text-primary border-primary/20 flex size-11 shrink-0 items-center justify-center rounded-xl border\"\n          >\n            <lucide-icon [img]=\"Bot\" class=\"size-5\" />\n          </div>\n          <div class=\"space-y-1\">\n            <div class=\"flex flex-wrap items-center gap-2\">\n              <h2 class=\"text-foreground text-lg font-semibold tracking-tight sm:text-xl\">\n                Autonomous Research &amp; Code Generation Squad\n              </h2>\n            </div>\n            <div class=\"text-muted-foreground flex flex-wrap items-center gap-2 text-xs\">\n              <span class=\"font-mono\">Pipeline ID: pipe-892f4c</span>\n              <span>•</span>\n              <span>4 Agents Orchestrated</span>\n              <span>•</span>\n              <span>Target: UIPKGE Registry Block</span>\n            </div>\n          </div>\n        </div>\n\n        <div class=\"flex flex-wrap items-center gap-2.5\">\n          <!-- Status Badge -->\n          @if (!isPaused() && activeStepIndex() < 4) {\n            <span ui-badge variant=\"outline\" class=\"border-primary/40 bg-primary/10 text-primary shadow-xs\">\n              <span class=\"relative mr-1.5 flex size-2\">\n                <span class=\"bg-primary absolute inline-flex h-full w-full rounded-full opacity-75\"></span>\n                <span class=\"bg-primary relative inline-flex size-2 rounded-full\"></span>\n              </span>\n              Running • Step {{ stepLabel() }} of 4\n            </span>\n          } @else if (isPaused()) {\n            <span ui-badge variant=\"warning\" class=\"shadow-xs\">\n              <lucide-icon [img]=\"Pause\" [class]=\"'mr-1 size-3'\" />\n              Paused • Step {{ stepLabel() }} of 4\n            </span>\n          } @else {\n            <span ui-badge variant=\"success\" class=\"shadow-xs\">\n              <lucide-icon [img]=\"CheckCircle2\" [class]=\"'mr-1 size-3'\" />\n              Completed • 4 of 4 Steps\n            </span>\n          }\n\n          <!-- Timer -->\n          <div\n            class=\"border-border bg-muted/40 text-foreground flex items-center gap-1.5 rounded-md border px-2.5 py-1 font-mono text-xs font-medium\"\n          >\n            <lucide-icon [img]=\"Clock\" class=\"text-muted-foreground size-3.5\" />\n            <span>{{ formattedTime() }}</span>\n          </div>\n\n          <!-- Controls -->\n          <button ui-button variant=\"outline\" size=\"sm\" class=\"h-8 gap-1.5 px-2.5 text-xs\" (click)=\"togglePause()\">\n            <lucide-icon [img]=\"isPaused() ? Play : Pause\" class=\"size-3.5\" />\n            <span>{{ isPaused() ? 'Resume Workflow' : 'Pause Workflow' }}</span>\n          </button>\n\n          <button\n            ui-button\n            variant=\"ghost\"\n            size=\"sm\"\n            class=\"text-muted-foreground hover:text-foreground h-8 gap-1 px-2.5 text-xs\"\n            (click)=\"cancelWorkflow()\"\n          >\n            <lucide-icon [img]=\"X\" class=\"size-3.5\" />\n            <span>Cancel</span>\n          </button>\n        </div>\n      </div>\n    </div>\n\n    <!-- Agent Flow Pipeline Nodes (Horizontal Connected Flow) -->\n    <div ui-card class=\"border-border bg-card shadow-xs\">\n      <div ui-card-header class=\"pb-3\">\n        <div class=\"flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between\">\n          <div>\n            <h3 ui-card-title class=\"text-base font-semibold\">Agent Execution Graph</h3>\n            <p ui-card-description class=\"text-xs\">\n              Real-time multi-agent execution pipeline. Select any node to inspect telemetry.\n            </p>\n          </div>\n          <div class=\"flex flex-wrap items-center gap-2\">\n            <span class=\"text-muted-foreground text-xs font-medium\">Pipeline Progress</span>\n            <div class=\"bg-muted h-2 w-28 overflow-hidden rounded-full\">\n              <div\n                class=\"bg-primary h-full transition-[width] duration-500 ease-out\"\n                [style.width.%]=\"overallProgress()\"\n              ></div>\n            </div>\n            <span class=\"font-mono text-xs font-semibold\">{{ overallProgress() }}%</span>\n          </div>\n        </div>\n      </div>\n\n      <div ui-card-content class=\"p-6 pt-2\">\n        <div class=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n          <!-- Node 1: Planner Agent -->\n          <button\n            type=\"button\"\n            [class]=\"nodeClass('planner')\"\n            [attr.aria-pressed]=\"selectedAgentId() === 'planner'\"\n            (click)=\"selectAgent('planner')\"\n          >\n            <div class=\"space-y-3\">\n              <div class=\"flex items-center justify-between\">\n                <div class=\"flex flex-wrap items-center gap-2.5\">\n                  <div [class]=\"nodeIconClass('planner')\">\n                    <lucide-icon [img]=\"Compass\" class=\"size-4\" />\n                  </div>\n                  <div>\n                    <p class=\"text-foreground text-xs leading-none font-semibold\">Planner Agent</p>\n                    <p class=\"text-muted-foreground mt-0.5 text-xs\">Stage 01</p>\n                  </div>\n                </div>\n\n                @if (statusOf('planner') === 'completed') {\n                  <span ui-badge variant=\"success\" class=\"gap-1 text-xs\">\n                    <lucide-icon [img]=\"Check\" class=\"size-3\" />\n                    12s\n                  </span>\n                } @else if (statusOf('planner') === 'running') {\n                  <span ui-badge variant=\"outline\" class=\"border-primary/40 bg-primary/10 text-primary text-xs\">\n                    Running\n                  </span>\n                } @else {\n                  <span ui-badge variant=\"outline\" class=\"text-muted-foreground text-xs\">Queued</span>\n                }\n              </div>\n\n              <div class=\"space-y-1\">\n                <p class=\"text-muted-foreground line-clamp-2 text-xs leading-relaxed\">\n                  Deconstruct task into 4 sub-goals\n                </p>\n              </div>\n            </div>\n\n            <div class=\"border-border/60 mt-3 flex items-center justify-between border-t pt-2.5 text-xs\">\n              <span class=\"text-muted-foreground font-mono\">Claude 3.5</span>\n              <span class=\"text-foreground font-medium\">100% done</span>\n            </div>\n          </button>\n\n          <!-- Node 2: Research Agent -->\n          <button\n            type=\"button\"\n            [class]=\"nodeClass('researcher')\"\n            [attr.aria-pressed]=\"selectedAgentId() === 'researcher'\"\n            (click)=\"selectAgent('researcher')\"\n          >\n            <div class=\"space-y-3\">\n              <div class=\"flex items-center justify-between\">\n                <div class=\"flex flex-wrap items-center gap-2.5\">\n                  <div [class]=\"nodeIconClass('researcher')\">\n                    <lucide-icon [img]=\"Search\" class=\"size-4\" />\n                  </div>\n                  <div>\n                    <p class=\"text-foreground text-xs leading-none font-semibold\">Research Agent</p>\n                    <p class=\"text-muted-foreground mt-0.5 text-xs\">Stage 02</p>\n                  </div>\n                </div>\n\n                @if (statusOf('researcher') === 'completed') {\n                  <span ui-badge variant=\"success\" class=\"gap-1 text-xs\">\n                    <lucide-icon [img]=\"Check\" class=\"size-3\" />\n                    45s\n                  </span>\n                } @else if (statusOf('researcher') === 'running') {\n                  <span ui-badge variant=\"outline\" class=\"border-primary/40 bg-primary/10 text-primary text-xs\">\n                    Running\n                  </span>\n                } @else {\n                  <span ui-badge variant=\"outline\" class=\"text-muted-foreground text-xs\">Queued</span>\n                }\n              </div>\n\n              <div class=\"space-y-1\">\n                <p class=\"text-muted-foreground line-clamp-2 text-xs leading-relaxed\">\n                  Query documentation and verify API contracts\n                </p>\n              </div>\n            </div>\n\n            <div class=\"border-border/60 mt-3 flex items-center justify-between border-t pt-2.5 text-xs\">\n              <span class=\"text-muted-foreground font-mono\">GPT-4o</span>\n              <span class=\"text-foreground font-medium\">100% done</span>\n            </div>\n          </button>\n\n          <!-- Node 3: Code Engineer Agent -->\n          <button\n            type=\"button\"\n            [class]=\"nodeClass('engineer')\"\n            [attr.aria-pressed]=\"selectedAgentId() === 'engineer'\"\n            (click)=\"selectAgent('engineer')\"\n          >\n            <div class=\"space-y-3\">\n              <div class=\"flex items-center justify-between\">\n                <div class=\"flex flex-wrap items-center gap-2.5\">\n                  <div [class]=\"nodeIconClass('engineer')\">\n                    <lucide-icon [img]=\"Code2\" class=\"size-4\" />\n                  </div>\n                  <div>\n                    <p class=\"text-foreground text-xs leading-none font-semibold\">Code Engineer</p>\n                    <p class=\"text-muted-foreground mt-0.5 text-xs\">Stage 03</p>\n                  </div>\n                </div>\n\n                @if (statusOf('engineer') === 'completed') {\n                  <span ui-badge variant=\"success\" class=\"gap-1 text-xs\">\n                    <lucide-icon [img]=\"Check\" class=\"size-3\" />\n                    1m 17s\n                  </span>\n                } @else if (statusOf('engineer') === 'running') {\n                  <span\n                    ui-badge\n                    variant=\"outline\"\n                    class=\"border-primary/50 bg-primary/15 text-primary text-xs font-medium\"\n                  >\n                    <span class=\"relative mr-1 flex size-1.5\">\n                      <span class=\"bg-primary absolute inline-flex h-full w-full rounded-full opacity-75\"></span>\n                      <span class=\"bg-primary relative inline-flex size-1.5 rounded-full\"></span>\n                    </span>\n                    Streaming\n                  </span>\n                } @else {\n                  <span ui-badge variant=\"outline\" class=\"text-muted-foreground text-xs\">Queued</span>\n                }\n              </div>\n\n              <div class=\"space-y-1\">\n                <p class=\"text-muted-foreground line-clamp-2 text-xs leading-relaxed\">\n                  Generate component architecture &amp; unit tests\n                </p>\n              </div>\n            </div>\n\n            <div class=\"border-border/60 mt-3 flex items-center justify-between border-t pt-2.5 text-xs\">\n              <span class=\"text-muted-foreground font-mono\">Claude 3.5</span>\n              <span class=\"text-primary font-medium\">{{ progressOf('engineer') }}% active</span>\n            </div>\n          </button>\n\n          <!-- Node 4: Reviewer & QA Agent -->\n          <button\n            type=\"button\"\n            [class]=\"nodeClass('reviewer')\"\n            [attr.aria-pressed]=\"selectedAgentId() === 'reviewer'\"\n            (click)=\"selectAgent('reviewer')\"\n          >\n            <div class=\"space-y-3\">\n              <div class=\"flex items-center justify-between\">\n                <div class=\"flex flex-wrap items-center gap-2.5\">\n                  <div [class]=\"nodeIconClass('reviewer')\">\n                    <lucide-icon [img]=\"ShieldCheck\" class=\"size-4\" />\n                  </div>\n                  <div>\n                    <p class=\"text-foreground text-xs leading-none font-semibold\">Reviewer &amp; QA</p>\n                    <p class=\"text-muted-foreground mt-0.5 text-xs\">Stage 04</p>\n                  </div>\n                </div>\n\n                @if (statusOf('reviewer') === 'completed') {\n                  <span ui-badge variant=\"success\" class=\"gap-1 text-xs\">\n                    <lucide-icon [img]=\"Check\" class=\"size-3\" />\n                    Passed\n                  </span>\n                } @else if (statusOf('reviewer') === 'running') {\n                  <span ui-badge variant=\"outline\" class=\"border-primary/40 bg-primary/10 text-primary text-xs\">\n                    Running\n                  </span>\n                } @else {\n                  <span ui-badge variant=\"outline\" class=\"text-muted-foreground border-border/80 text-xs\">Queued</span>\n                }\n              </div>\n\n              <div class=\"space-y-1\">\n                <p class=\"text-muted-foreground line-clamp-2 text-xs leading-relaxed\">\n                  Validate TypeScript types and token standards\n                </p>\n              </div>\n            </div>\n\n            <div class=\"border-border/60 mt-3 flex items-center justify-between border-t pt-2.5 text-xs\">\n              <span class=\"text-muted-foreground font-mono\">Claude 3.5</span>\n              <span class=\"text-muted-foreground font-medium\">Pending</span>\n            </div>\n          </button>\n        </div>\n      </div>\n    </div>\n\n    <!-- Active Execution Detail Panel (2-Column Bento) -->\n    <div class=\"grid grid-cols-1 gap-6 lg:grid-cols-12\">\n      <!-- Left Column: Agent Overview, Thought Stream & Tool Invocations -->\n      <div class=\"space-y-6 lg:col-span-7\">\n        <!-- Active Agent Header & Progress -->\n        <div ui-card class=\"border-border bg-card shadow-xs\">\n          <div ui-card-header class=\"pb-4\">\n            <div class=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n              <div class=\"flex items-center gap-3\">\n                <div\n                  class=\"bg-primary/10 text-primary border-primary/20 flex size-10 items-center justify-center rounded-lg border\"\n                >\n                  <lucide-icon [img]=\"agentIcon()\" class=\"size-5\" />\n                </div>\n                <div>\n                  <div class=\"flex flex-wrap items-center gap-2\">\n                    <h3 ui-card-title class=\"text-base font-semibold\">{{ selectedAgent().name }}</h3>\n                    <span ui-badge variant=\"outline\" class=\"font-mono text-xs\">{{ selectedAgent().model }}</span>\n                  </div>\n                  <p ui-card-description class=\"text-xs\">{{ selectedAgent().task }}</p>\n                </div>\n              </div>\n\n              <div class=\"flex flex-wrap items-center gap-2\">\n                @if (selectedAgent().status === 'completed') {\n                  <span ui-badge variant=\"success\" class=\"text-xs\">Completed in {{ selectedAgent().duration }}</span>\n                } @else if (selectedAgent().status === 'running') {\n                  <span ui-badge variant=\"outline\" class=\"border-primary/40 bg-primary/10 text-primary text-xs\">\n                    <lucide-icon [img]=\"Activity\" [class]=\"'mr-1 size-3 animate-pulse'\" />\n                    Streaming • {{ selectedAgent().duration }}\n                  </span>\n                } @else {\n                  <span ui-badge variant=\"outline\" class=\"text-muted-foreground text-xs\">Queued</span>\n                }\n              </div>\n            </div>\n          </div>\n\n          <div ui-card-content class=\"space-y-4 pt-0\">\n            <div class=\"space-y-1.5\">\n              <div class=\"text-muted-foreground flex justify-between text-xs font-medium\">\n                <span>Task Execution State</span>\n                <span class=\"font-mono\">{{ selectedAgent().progress }}%</span>\n              </div>\n              <ui-progress [value]=\"selectedAgent().progress\" class=\"h-2\" />\n            </div>\n\n            <div class=\"bg-muted/30 border-border grid grid-cols-2 gap-3 rounded-lg border p-3 sm:grid-cols-4\">\n              <div>\n                <p class=\"text-muted-foreground text-xs\">Duration</p>\n                <p class=\"text-foreground font-mono text-xs font-semibold\">{{ selectedAgent().duration }}</p>\n              </div>\n              <div>\n                <p class=\"text-muted-foreground text-xs\">Tokens Output</p>\n                <p class=\"text-foreground font-mono text-xs font-semibold\">{{ selectedAgent().tokens }}</p>\n              </div>\n              <div>\n                <p class=\"text-muted-foreground text-xs\">Throughput</p>\n                <p class=\"text-foreground font-mono text-xs font-semibold\">{{ selectedAgent().speed }}</p>\n              </div>\n              <div>\n                <p class=\"text-muted-foreground text-xs\">Agent Role</p>\n                <p class=\"text-foreground truncate text-xs font-semibold\">{{ selectedAgent().role }}</p>\n              </div>\n            </div>\n          </div>\n        </div>\n\n        <!-- Agent Thought Stream Card -->\n        <div ui-card class=\"border-border bg-card shadow-xs\">\n          <div ui-card-header class=\"flex flex-row items-center justify-between pb-3\">\n            <div class=\"flex flex-wrap items-center gap-2\">\n              <lucide-icon [img]=\"Sparkles\" class=\"text-primary size-4\" />\n              <h3 ui-card-title class=\"text-sm font-semibold\">Agent Thought Stream &amp; Reasoning</h3>\n            </div>\n            <button\n              ui-button\n              variant=\"ghost\"\n              size=\"xs\"\n              class=\"text-muted-foreground hover:text-foreground h-7 text-xs\"\n              (click)=\"toggleAllThoughts()\"\n            >\n              Toggle Details\n            </button>\n          </div>\n\n          <div ui-card-content class=\"space-y-3 pt-0\">\n            @for (thought of selectedAgent().thoughts; track thought.id) {\n              <div class=\"border-border bg-muted/20 hover:bg-muted/30 rounded-lg border transition-colors\">\n                <button\n                  type=\"button\"\n                  class=\"focus-visible:ring-ring flex w-full cursor-pointer items-center justify-between rounded-lg p-3 text-left focus-visible:ring-2 focus-visible:outline-none\"\n                  [attr.aria-expanded]=\"expandedAttr(thought.id)\"\n                  (click)=\"toggleThought(thought.id)\"\n                >\n                  <div class=\"flex flex-wrap items-center gap-2.5\">\n                    <div [class]=\"thoughtIconClass(thought.status)\">\n                      @if (thought.status === 'completed') {\n                        <lucide-icon [img]=\"CheckCircle2\" class=\"size-4\" />\n                      } @else if (thought.status === 'running') {\n                        <lucide-icon [img]=\"Activity\" class=\"size-4\" />\n                      } @else {\n                        <div class=\"border-muted-foreground size-3 rounded-full border border-dashed\"></div>\n                      }\n                    </div>\n                    <p class=\"text-foreground text-xs font-medium\">{{ thought.title }}</p>\n                  </div>\n\n                  <div class=\"flex flex-wrap items-center gap-2\">\n                    <span ui-badge variant=\"outline\" class=\"font-mono text-xs\">{{ thought.duration }}</span>\n                    <lucide-icon\n                      [img]=\"isExpanded(thought.id) ? ChevronDown : ChevronRight\"\n                      class=\"text-muted-foreground size-3.5\"\n                    />\n                  </div>\n                </button>\n\n                @if (isExpanded(thought.id)) {\n                  <div\n                    class=\"border-border/60 bg-muted/40 text-muted-foreground border-t px-3 py-2.5 text-xs leading-relaxed\"\n                  >\n                    {{ thought.detail }}\n                  </div>\n                }\n              </div>\n            }\n          </div>\n        </div>\n\n        <!-- Tool Invocations Badge Row & Logs -->\n        <div ui-card class=\"border-border bg-card shadow-xs\">\n          <div ui-card-header class=\"pb-3\">\n            <div class=\"flex flex-wrap items-center gap-2\">\n              <lucide-icon [img]=\"Terminal\" class=\"text-primary size-4\" />\n              <h3 ui-card-title class=\"text-sm font-semibold\">Active Tool Invocations</h3>\n            </div>\n          </div>\n\n          <div ui-card-content class=\"space-y-3 pt-0\">\n            <!-- Badge Row -->\n            <div class=\"flex flex-wrap items-center gap-2\">\n              @for (tool of selectedAgent().tools; track tool.name) {\n                <span\n                  ui-badge\n                  variant=\"outline\"\n                  class=\"border-border bg-muted/40 hover:bg-muted text-foreground gap-1.5 px-2.5 py-1 text-xs font-medium\"\n                >\n                  <!-- size-3: React writes size-3.5, but the Badge's [&>svg]:size-3 wins there. -->\n                  <lucide-icon [img]=\"toolIcon(tool.icon)\" class=\"text-muted-foreground size-3\" />\n                  <span class=\"font-mono\">{{ tool.name }}</span>\n                  <span class=\"bg-primary/10 text-primary py-0.2 rounded-full px-1.5 text-xs font-bold\">\n                    {{ tool.count }}\n                  </span>\n                </span>\n              }\n            </div>\n\n            <!-- Execution Log Terminal Row -->\n            <div class=\"border-border bg-muted/50 overflow-x-auto rounded-lg border p-3 font-mono text-xs\">\n              <div class=\"text-muted-foreground space-y-1\">\n                <div class=\"flex flex-wrap items-center gap-2 whitespace-nowrap\">\n                  <span class=\"text-success font-semibold\">[02:14:02]</span>\n                  <span>GET https://uipkge.dev/r/button.json → 200 OK (38ms)</span>\n                </div>\n                <div class=\"flex flex-wrap items-center gap-2 whitespace-nowrap\">\n                  <span class=\"text-success font-semibold\">[02:14:05]</span>\n                  <span>READ packages/registry-react/components/card/card.tsx (12ms)</span>\n                </div>\n                <div class=\"flex flex-wrap items-center gap-2\">\n                  <span class=\"text-primary font-semibold\">[02:14:09]</span>\n                  <span>AST parse: 4 exports identified, 0 cycle violations</span>\n                </div>\n                <div class=\"flex flex-wrap items-center gap-2 whitespace-nowrap\">\n                  <span class=\"text-success font-semibold\">[02:14:14]</span>\n                  <span>Typecheck: 0 errors across 6 test suites</span>\n                </div>\n              </div>\n            </div>\n          </div>\n        </div>\n      </div>\n\n      <!-- Right Column: Live Artifact Output & Pipeline Actions -->\n      <div class=\"space-y-6 lg:col-span-5\">\n        <!-- Live Artifact Output Card -->\n        <div ui-card class=\"border-border bg-card shadow-xs\">\n          <div ui-card-header class=\"flex flex-row items-center justify-between pb-3\">\n            <div class=\"flex flex-wrap items-center gap-2 overflow-hidden\">\n              <lucide-icon [img]=\"FileCode2\" class=\"text-primary size-4 shrink-0\" />\n              <h3 ui-card-title class=\"truncate font-mono text-xs font-medium\">\n                {{ selectedAgent().artifactFileName }}\n              </h3>\n            </div>\n            <div class=\"flex flex-wrap items-center gap-2\">\n              <span ui-badge variant=\"secondary\" class=\"font-mono text-xs\">{{ selectedAgent().artifactSize }}</span>\n              <button ui-button variant=\"outline\" size=\"xs\" class=\"h-7 gap-1 px-1.5 text-xs\" (click)=\"copyArtifact()\">\n                <lucide-icon [img]=\"copied() ? Check : Copy\" class=\"size-3\" />\n                <span>{{ copied() ? 'Copied!' : 'Copy' }}</span>\n              </button>\n            </div>\n          </div>\n\n          <div ui-card-content class=\"pt-0\">\n            <div class=\"border-border bg-muted/40 relative overflow-hidden rounded-lg border font-mono text-xs\">\n              <!-- Window top bar -->\n              <div class=\"border-border/60 bg-muted/60 flex items-center justify-between border-b px-3 py-1.5\">\n                <div class=\"flex items-center gap-1.5\">\n                  <div class=\"bg-destructive/60 size-2.5 rounded-full\"></div>\n                  <div class=\"bg-warning/60 size-2.5 rounded-full\"></div>\n                  <div class=\"bg-success/60 size-2.5 rounded-full\"></div>\n                </div>\n                <span class=\"text-muted-foreground text-xs\">Live Generated Output</span>\n              </div>\n\n              <!-- Code area with syntax styling -->\n              <div class=\"max-h-[380px] overflow-auto p-3 text-xs leading-relaxed\">\n                <pre\n                  class=\"text-foreground font-mono whitespace-pre-wrap\"\n                ><code>{{ selectedAgent().artifactCode }}</code></pre>\n                @if (selectedAgent().status === 'running') {\n                  <span class=\"bg-primary ml-0.5 inline-block h-3.5 w-1.5 animate-pulse align-middle\"></span>\n                }\n              </div>\n            </div>\n          </div>\n        </div>\n\n        <!-- Pipeline Action Controls -->\n        <div ui-card class=\"border-border bg-card shadow-xs\">\n          <div ui-card-header class=\"pb-3\">\n            <div class=\"flex flex-wrap items-center gap-2\">\n              <lucide-icon [img]=\"Layers\" class=\"text-primary size-4\" />\n              <h3 ui-card-title class=\"text-sm font-semibold\">Pipeline Orchestrator Controls</h3>\n            </div>\n          </div>\n\n          <div ui-card-content class=\"space-y-3 pt-0\">\n            <div class=\"grid grid-cols-1 gap-2 sm:grid-cols-2\">\n              <button\n                ui-button\n                variant=\"default\"\n                size=\"sm\"\n                class=\"gap-1.5 px-2.5 text-xs font-medium\"\n                [disabled]=\"activeStepIndex() >= 4\"\n                (click)=\"stepForward()\"\n              >\n                <lucide-icon [img]=\"FastForward\" class=\"size-3.5\" />\n                <span>Step Forward</span>\n              </button>\n\n              <button\n                ui-button\n                variant=\"outline\"\n                size=\"sm\"\n                class=\"gap-1.5 px-2.5 text-xs font-medium\"\n                (click)=\"retryStep()\"\n              >\n                <lucide-icon [img]=\"RotateCcw\" class=\"size-3.5\" />\n                <span>Retry Step</span>\n              </button>\n\n              <button\n                ui-button\n                variant=\"outline\"\n                size=\"sm\"\n                class=\"gap-1.5 px-2.5 text-xs font-medium\"\n                (click)=\"rerunPipeline()\"\n              >\n                <lucide-icon [img]=\"RefreshCw\" class=\"size-3.5\" />\n                <span>Re-run Pipeline</span>\n              </button>\n\n              <button\n                ui-button\n                variant=\"outline\"\n                size=\"sm\"\n                class=\"gap-1.5 px-2.5 text-xs font-medium\"\n                (click)=\"togglePause()\"\n              >\n                <lucide-icon [img]=\"isPaused() ? Play : Pause\" class=\"size-3.5\" />\n                <span>{{ isPaused() ? 'Resume' : 'Pause' }}</span>\n              </button>\n            </div>\n\n            <p class=\"text-muted-foreground pt-1 text-center text-xs\">\n              Actions dispatch commands across connected autonomous agent nodes.\n            </p>\n          </div>\n        </div>\n      </div>\n    </div>\n  `,\n})\nexport class UiAiAgentOrchestratorComponent {\n  @Input('class') className?: string\n\n  readonly isPaused = signal(false)\n  readonly elapsedSeconds = signal(134)\n  readonly selectedAgentId = signal<AgentId>('engineer')\n  readonly activeStepIndex = signal(2)\n  readonly copied = signal(false)\n  readonly nodes = signal<AgentNode[]>(initialNodes)\n  readonly expandedThoughts = signal<Record<string, boolean>>({\n    t1: false,\n    t2: false,\n    t3: false,\n    t4: true,\n  })\n\n  readonly selectedAgent = computed(() => {\n    const nodes = this.nodes()\n    return nodes.find((n) => n.id === this.selectedAgentId()) ?? nodes[2]!\n  })\n\n  readonly formattedTime = computed(() => {\n    const elapsed = this.elapsedSeconds()\n    const mins = Math.floor(elapsed / 60)\n    const secs = elapsed % 60\n    return `${mins.toString().padStart(2, '0')}m:${secs.toString().padStart(2, '0')}s`\n  })\n\n  readonly overallProgress = computed(() => {\n    const nodes = this.nodes()\n    const completedCount = nodes.filter((n) => n.status === 'completed').length\n    const running = nodes.find((n) => n.status === 'running')\n    const runningBonus = running ? running.progress / 100 : 0\n    return Math.round(((completedCount + runningBonus) / nodes.length) * 100)\n  })\n\n  readonly stepLabel = computed(() => Math.min(this.activeStepIndex() + 1, 4))\n  readonly agentIcon = computed(() => AGENT_ICONS[this.selectedAgent().id])\n\n  protected readonly Activity = Activity\n  protected readonly Bot = Bot\n  protected readonly Check = Check\n  protected readonly CheckCircle2 = CheckCircle2\n  protected readonly ChevronDown = ChevronDown\n  protected readonly ChevronRight = ChevronRight\n  protected readonly Clock = Clock\n  protected readonly Code2 = Code2\n  protected readonly Compass = Compass\n  protected readonly Copy = Copy\n  protected readonly FastForward = FastForward\n  protected readonly FileCode2 = FileCode2\n  protected readonly Layers = Layers\n  protected readonly Pause = Pause\n  protected readonly Play = Play\n  protected readonly RefreshCw = RefreshCw\n  protected readonly RotateCcw = RotateCcw\n  protected readonly Search = Search\n  protected readonly ShieldCheck = ShieldCheck\n  protected readonly Sparkles = Sparkles\n  protected readonly Terminal = Terminal\n  protected readonly X = X\n\n  private timer: ReturnType<typeof setInterval> | undefined\n  private copyTimer: ReturnType<typeof setTimeout> | undefined\n\n  constructor() {\n    // Browser only, after the first render (React's useEffect).\n    afterNextRender(() => {\n      this.timer = setInterval(() => {\n        if (!this.isPaused() && this.activeStepIndex() < 4) {\n          this.elapsedSeconds.update((prev) => prev + 1)\n        }\n      }, 1000)\n    })\n    inject(DestroyRef).onDestroy(() => {\n      clearInterval(this.timer)\n      clearTimeout(this.copyTimer)\n    })\n  }\n\n  get hostClass(): string {\n    return cn('block w-full space-y-6', this.className)\n  }\n\n  protected statusOf(id: AgentId): NodeStatus {\n    return this.nodes().find((n) => n.id === id)?.status ?? 'queued'\n  }\n\n  protected progressOf(id: AgentId): number {\n    return this.nodes().find((n) => n.id === id)?.progress ?? 0\n  }\n\n  protected nodeClass(id: AgentId): string {\n    const style = NODE_STYLES[id]\n    const status = this.statusOf(id)\n    return cn(\n      NODE_BASE,\n      this.selectedAgentId() === id ? style.selected : style.idle,\n      status === 'completed' ? 'bg-card' : status === 'running' ? style.running : style.queued,\n    )\n  }\n\n  protected nodeIconClass(id: AgentId): string {\n    const style = NODE_STYLES[id]\n    const status = this.statusOf(id)\n    return cn(\n      'flex size-9 items-center justify-center rounded-lg border text-xs',\n      status === 'completed'\n        ? 'border-success/30 bg-success/10 text-success'\n        : status === 'running'\n          ? style.iconRunning\n          : style.iconQueued,\n    )\n  }\n\n  protected thoughtIconClass(status: ThoughtStep['status']): string {\n    return cn(\n      'flex size-5 shrink-0 items-center justify-center rounded-full',\n      status === 'completed'\n        ? 'text-success'\n        : status === 'running'\n          ? 'text-primary animate-spin'\n          : 'text-muted-foreground',\n    )\n  }\n\n  protected toolIcon(icon: string): LucideIconData {\n    switch (icon) {\n      case 'Globe':\n        return Globe\n      case 'FileText':\n        return FileText\n      case 'Terminal':\n        return Terminal\n      default:\n        return ShieldCheck\n    }\n  }\n\n  protected isExpanded(id: string): boolean {\n    return this.expandedThoughts()[id] === true\n  }\n\n  /** React's `aria-expanded={expandedThoughts[id]}`: omitted for a thought that was never toggled. */\n  protected expandedAttr(id: string): boolean | null {\n    return this.expandedThoughts()[id] ?? null\n  }\n\n  togglePause(): void {\n    this.isPaused.update((prev) => !prev)\n  }\n\n  selectAgent(id: AgentId): void {\n    this.selectedAgentId.set(id)\n  }\n\n  toggleThought(id: string): void {\n    this.expandedThoughts.update((prev) => ({ ...prev, [id]: !prev[id] }))\n  }\n\n  toggleAllThoughts(): void {\n    const expanded = this.expandedThoughts()\n    const thoughts = this.selectedAgent().thoughts\n    const anyClosed = thoughts.some((t) => !expanded[t.id])\n    const next: Record<string, boolean> = { ...expanded }\n    thoughts.forEach((t) => {\n      next[t.id] = anyClosed\n    })\n    this.expandedThoughts.set(next)\n  }\n\n  stepForward(): void {\n    const active = this.activeStepIndex()\n    const nodes = this.nodes()\n    if (active < nodes.length - 1) {\n      const nextIdx = active + 1\n      this.nodes.update((prev) =>\n        prev.map((node, idx) =>\n          idx === active\n            ? { ...node, status: 'completed', progress: 100 }\n            : idx === nextIdx\n              ? { ...node, status: 'running', progress: 45 }\n              : node,\n        ),\n      )\n      this.activeStepIndex.set(nextIdx)\n      this.selectedAgentId.set(nodes[nextIdx]!.id)\n    } else if (active === nodes.length - 1) {\n      this.nodes.update((prev) =>\n        prev.map((node, idx) => (idx === active ? { ...node, status: 'completed', progress: 100 } : node)),\n      )\n      this.activeStepIndex.set(4)\n    }\n  }\n\n  retryStep(): void {\n    const active = this.activeStepIndex()\n    const nodes = this.nodes()\n    if (active < nodes.length) {\n      this.nodes.update((prev) =>\n        prev.map((node, idx) => (idx === active ? { ...node, status: 'running', progress: 10 } : node)),\n      )\n      this.selectedAgentId.set(nodes[active]!.id)\n    }\n  }\n\n  rerunPipeline(): void {\n    this.elapsedSeconds.set(0)\n    this.isPaused.set(false)\n    this.activeStepIndex.set(0)\n    this.nodes.update((prev) =>\n      prev.map((node, idx) => ({\n        ...node,\n        status: idx === 0 ? 'running' : 'queued',\n        progress: idx === 0 ? 25 : 0,\n      })),\n    )\n    this.selectedAgentId.set('planner')\n  }\n\n  cancelWorkflow(): void {\n    this.isPaused.set(true)\n  }\n\n  async copyArtifact(): Promise<void> {\n    try {\n      await navigator.clipboard.writeText(this.selectedAgent().artifactCode)\n      this.copied.set(true)\n      clearTimeout(this.copyTimer)\n      this.copyTimer = setTimeout(() => {\n        this.copied.set(false)\n      }, 2000)\n    } catch {\n      // Clipboard fallback\n    }\n  }\n}\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/ai-agent-orchestrator/ai-agent-orchestrator.component.ts"
    },
    {
      "path": "packages/registry-angular/blocks/ai-agent-orchestrator/index.ts",
      "content": "export { UiAiAgentOrchestratorComponent } from './ai-agent-orchestrator.component'\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/ai-agent-orchestrator/index.ts"
    }
  ],
  "dependencies": [
    "lucide-angular"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/angular/badge.json",
    "https://uipkge.dev/r/angular/button.json",
    "https://uipkge.dev/r/angular/card.json",
    "https://uipkge.dev/r/angular/progress.json"
  ],
  "description": "Multi-agent workflow visualizer and execution graph. Displays real-time agent pipeline topology, active reasoning streams, tool invocation metrics, live code artifact generation, and pipeline control actions.",
  "categories": [
    "ai",
    "app"
  ]
}