{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "workflow-node-sheet",
  "title": "Workflow Node Sheet",
  "description": "A side sheet with a step's settings, model, ports, run log and output.",
  "dependencies": [
    "@xyflow/react",
    "cn",
    "lucide-react"
  ],
  "registryDependencies": [
    "badge",
    "button",
    "https://ui.usenotra.com/r/notra-select.json",
    "sheet",
    "tabs"
  ],
  "files": [
    {
      "path": "registry/notra/workflow/components/workflow-block-icon.tsx",
      "content": "import { cn } from \"cn\";\n\nimport { WORKFLOW_KINDS } from \"../constants/workflow\";\nimport { findModel } from \"../lib/workflow\";\nimport type { WorkflowBlockIconProps } from \"../types/workflow\";\nimport { WORKFLOW_LOGOS, WorkflowLogo } from \"./workflow-logo\";\n\nexport const WorkflowBlockIcon = ({\n  block,\n  className,\n}: WorkflowBlockIconProps) => {\n  const logo = block.logo ?? findModel(block.model)?.logo;\n  const kind = WORKFLOW_KINDS[block.kind];\n  const KindIcon = kind.icon;\n\n  if (logo && WORKFLOW_LOGOS[logo].tile) {\n    return (\n      <span\n        className={cn(\n          \"flex size-7 shrink-0 overflow-hidden rounded-md\",\n          className\n        )}\n        data-slot=\"workflow-block-icon\"\n      >\n        <WorkflowLogo className=\"size-full\" name={logo} />\n      </span>\n    );\n  }\n\n  return (\n    <span\n      className={cn(\n        \"flex size-7 shrink-0 items-center justify-center rounded-md\",\n        logo\n          ? \"bg-background border-foreground/10 border\"\n          : cn(\"ring-1 ring-inset\", kind.tileClassName),\n        className\n      )}\n      data-slot=\"workflow-block-icon\"\n    >\n      {logo ? (\n        <WorkflowLogo className=\"size-[58%]\" name={logo} />\n      ) : (\n        <KindIcon className=\"size-1/2\" />\n      )}\n    </span>\n  );\n};\n",
      "type": "registry:component",
      "target": "components/workflow/components/workflow-block-icon.tsx"
    },
    {
      "path": "registry/notra/workflow/components/workflow-logo.tsx",
      "content": "import { cn } from \"cn\";\n\nimport type {\n  WorkflowLogoConfig,\n  WorkflowLogoName,\n  WorkflowLogoProps,\n} from \"../types/workflow\";\nimport {\n  AhrefsLogo,\n  AnthropicLogo,\n  BrowserbaseLogo,\n  ClaudeLogo,\n  ContextDevLogo,\n  DeepSeekLogo,\n  FirecrawlLogo,\n  GeminiLogo,\n  GitHubLogo,\n  GmailLogo,\n  GoogleLogo,\n  GoogleSheetsLogo,\n  GrokLogo,\n  LinearLogo,\n  MistralLogo,\n  NotionLogo,\n  OpenAILogo,\n  PerplexityLogo,\n  PostHogLogo,\n  ResendLogo,\n  SlackLogo,\n  WebflowLogo,\n  WordPressLogo,\n} from \"./workflow-logos\";\n\nexport const WORKFLOW_LOGOS: Record<WorkflowLogoName, WorkflowLogoConfig> = {\n  ahrefs: { label: \"Ahrefs\", logo: AhrefsLogo },\n  anthropic: { label: \"Anthropic\", logo: AnthropicLogo },\n  browserbase: { label: \"Browserbase\", logo: BrowserbaseLogo, tile: true },\n  claude: { label: \"Claude\", logo: ClaudeLogo },\n  deepseek: { label: \"DeepSeek\", logo: DeepSeekLogo },\n  \"context-dev\": { label: \"context.dev\", logo: ContextDevLogo, tile: true },\n  firecrawl: { label: \"Firecrawl\", logo: FirecrawlLogo },\n  gemini: { label: \"Gemini\", logo: GeminiLogo },\n  github: { label: \"GitHub\", logo: GitHubLogo },\n  gmail: { label: \"Gmail\", logo: GmailLogo },\n  google: { label: \"Google\", logo: GoogleLogo },\n  \"google-sheets\": { label: \"Google Sheets\", logo: GoogleSheetsLogo },\n  grok: { label: \"Grok\", logo: GrokLogo },\n  linear: { label: \"Linear\", logo: LinearLogo },\n  mistral: { label: \"Mistral\", logo: MistralLogo },\n  notion: { label: \"Notion\", logo: NotionLogo },\n  openai: { label: \"OpenAI\", logo: OpenAILogo },\n  perplexity: { label: \"Perplexity\", logo: PerplexityLogo },\n  posthog: { label: \"PostHog\", logo: PostHogLogo },\n  resend: { label: \"Resend\", logo: ResendLogo },\n  slack: { label: \"Slack\", logo: SlackLogo },\n  webflow: { label: \"Webflow\", logo: WebflowLogo },\n  wordpress: { label: \"WordPress\", logo: WordPressLogo },\n};\n\nexport const WorkflowLogo = ({\n  className,\n  name,\n  ...props\n}: WorkflowLogoProps) => {\n  const Logo = WORKFLOW_LOGOS[name].logo;\n  return (\n    <Logo\n      className={cn(\"size-4 shrink-0 overflow-visible\", className)}\n      data-slot=\"workflow-logo\"\n      {...props}\n    />\n  );\n};\n",
      "type": "registry:component",
      "target": "components/workflow/components/workflow-logo.tsx"
    },
    {
      "path": "registry/notra/workflow/components/workflow-logos.tsx",
      "content": "import type { SVGProps } from \"react\";\n\nexport const OpenAILogo = (props: SVGProps<SVGSVGElement>) => (\n  <svg\n    viewBox=\"105.31 105.31 400.39 400.39\"\n    fill=\"currentColor\"\n    aria-hidden=\"true\"\n    {...props}\n  >\n    <path\n      fillRule=\"evenodd\"\n      clipRule=\"evenodd\"\n      d=\"M252.794 108.802C289.191 99.0484 326.265 110.305 351.148 135.135C385.113 126.072 422.85 134.862 449.492 161.505C476.136 188.149 484.925 225.888 475.862 259.85V259.854C500.696 284.735 511.95 321.81 502.198 358.207C492.447 394.602 464.161 421.084 430.215 430.217C421.083 464.162 394.603 492.448 358.206 502.199C321.812 511.951 284.734 500.693 259.852 475.864C225.887 484.927 188.15 476.137 161.507 449.495C134.864 422.851 126.073 385.111 135.136 351.149C110.304 326.266 99.0496 289.192 108.801 252.795C118.552 216.4 146.84 189.918 180.784 180.785C189.917 146.841 216.396 118.553 252.794 108.802ZM374.292 407.145C374.292 411.271 372.092 415.086 368.517 417.148L283.723 466.102C302.487 480.585 327.555 486.459 352.217 479.852C386.997 470.532 410.068 439.312 410.555 405.006V317.717C410.555 315.08 409.125 312.621 406.843 311.303L374.292 292.509V407.145ZM251.868 415.897C248.296 417.959 243.893 417.959 240.317 415.897L155.526 366.942C152.366 390.436 159.811 415.08 177.866 433.136H177.863C203.325 458.594 241.896 462.962 271.85 446.232L347.449 402.586C349.735 401.268 351.148 398.8 351.148 396.163V358.579L251.868 415.897ZM368.602 220.628C366.319 219.309 363.474 219.318 361.191 220.637L328.641 239.431L427.921 296.749C431.496 298.811 433.697 302.627 433.697 306.752V404.661C455.622 395.654 473.244 376.881 479.851 352.218C489.169 317.442 473.668 281.85 444.201 264.274L368.602 220.628ZM177.303 206.34C155.377 215.348 137.756 234.122 131.148 258.783C121.832 293.561 137.331 329.153 166.799 346.727L242.398 390.373C244.68 391.692 247.525 391.684 249.807 390.366L282.357 371.572L183.078 314.253C179.504 312.189 177.303 308.375 177.303 304.251V206.34ZM259.849 279.145V331.858L305.5 358.213L351.15 331.858V279.145L305.5 252.789L259.849 279.145ZM327.276 144.9C308.512 130.418 283.445 124.543 258.782 131.15C224.002 140.471 200.931 171.691 200.445 205.995V293.286C200.445 295.923 201.875 298.381 204.158 299.7L236.707 318.493V203.856C236.707 199.731 238.909 195.916 242.483 193.853L327.276 144.9ZM433.137 177.867C407.675 152.407 369.103 148.038 339.149 164.769L263.55 208.415C261.265 209.734 259.852 212.202 259.852 214.838V252.423L359.132 195.105C362.703 193.041 367.108 193.041 370.682 195.105L455.473 244.06C458.635 220.567 451.189 195.922 433.135 177.867H433.137Z\"\n    />\n  </svg>\n);\n\nexport const AnthropicLogo = (props: SVGProps<SVGSVGElement>) => (\n  <svg\n    viewBox=\"0 3.52 24 16.48\"\n    fill=\"currentColor\"\n    aria-hidden=\"true\"\n    {...props}\n  >\n    <path d=\"M13.827 3.52h3.603L24 20h-3.603l-6.57-16.48zm-7.258 0h3.767L16.906 20h-3.674l-1.343-3.461H5.017l-1.344 3.46H0L6.57 3.522zm4.132 9.959L8.453 7.687 6.205 13.48H10.7z\" />\n  </svg>\n);\n\nexport const ClaudeLogo = (props: SVGProps<SVGSVGElement>) => (\n  <svg viewBox=\"0 0 256 257\" aria-hidden=\"true\" {...props}>\n    <path\n      fill=\"#D97757\"\n      d=\"m50.228 170.321 50.357-28.257.843-2.463-.843-1.361h-2.462l-8.426-.518-28.775-.778-24.952-1.037-24.175-1.296-6.092-1.297L0 125.796l.583-3.759 5.12-3.434 7.324.648 16.202 1.101 24.304 1.685 17.629 1.037 26.118 2.722h4.148l.583-1.685-1.426-1.037-1.101-1.037-25.147-17.045-27.22-18.017-14.258-10.37-7.713-5.25-3.888-4.925-1.685-10.758 7-7.713 9.397.649 2.398.648 9.527 7.323 20.35 15.75L94.817 91.9l3.889 3.24 1.555-1.102.195-.777-1.75-2.917-14.453-26.118-15.425-26.572-6.87-11.018-1.814-6.61c-.648-2.723-1.102-4.991-1.102-7.778l7.972-10.823L71.42 0 82.05 1.426l4.472 3.888 6.61 15.101 10.694 23.786 16.591 32.34 4.861 9.592 2.592 8.879.973 2.722h1.685v-1.556l1.36-18.211 2.528-22.36 2.463-28.776.843-8.1 4.018-9.722 7.971-5.25 6.222 2.981 5.12 7.324-.713 4.73-3.046 19.768-5.962 30.98-3.889 20.739h2.268l2.593-2.593 10.499-13.934 17.628-22.036 7.778-8.749 9.073-9.657 5.833-4.601h11.018l8.1 12.055-3.628 12.443-11.342 14.388-9.398 12.184-13.48 18.147-8.426 14.518.778 1.166 2.01-.194 30.46-6.481 16.462-2.982 19.637-3.37 8.88 4.148.971 4.213-3.5 8.62-20.998 5.184-24.628 4.926-36.682 8.685-.454.324.519.648 16.526 1.555 7.065.389h17.304l32.21 2.398 8.426 5.574 5.055 6.805-.843 5.184-12.962 6.611-17.498-4.148-40.83-9.721-14-3.5h-1.944v1.167l11.666 11.406 21.387 19.314 26.767 24.887 1.36 6.157-3.434 4.86-3.63-.518-23.526-17.693-9.073-7.972-20.545-17.304h-1.36v1.814l4.73 6.935 25.017 37.59 1.296 11.536-1.814 3.76-6.481 2.268-7.13-1.297-14.647-20.544-15.1-23.138-12.185-20.739-1.49.843-7.194 77.448-3.37 3.953-7.778 2.981-6.48-4.925-3.436-7.972 3.435-15.749 4.148-20.544 3.37-16.333 3.046-20.285 1.815-6.74-.13-.454-1.49.194-15.295 20.999-23.267 31.433-18.406 19.702-4.407 1.75-7.648-3.954.713-7.064 4.277-6.286 25.47-32.405 15.36-20.092 9.917-11.6-.065-1.686h-.583L44.07 198.125l-12.055 1.555-5.185-4.86.648-7.972 2.463-2.593 20.35-13.999-.064.065Z\"\n    />\n  </svg>\n);\n\nexport const GeminiLogo = (props: SVGProps<SVGSVGElement>) => (\n  <svg viewBox=\"0 0 296 298\" fill=\"none\" aria-hidden=\"true\" {...props}>\n    <mask\n      id=\"gemini-a\"\n      width=\"296\"\n      height=\"298\"\n      x=\"0\"\n      y=\"0\"\n      maskUnits=\"userSpaceOnUse\"\n      style={{ maskType: \"alpha\" }}\n    >\n      <path\n        fill=\"#3186FF\"\n        d=\"M141.201 4.886c2.282-6.17 11.042-6.071 13.184.148l5.985 17.37a184.004 184.004 0 0 0 111.257 113.049l19.304 6.997c6.143 2.227 6.156 10.91.02 13.155l-19.35 7.082a184.001 184.001 0 0 0-109.495 109.385l-7.573 20.629c-2.241 6.105-10.869 6.121-13.133.025l-7.908-21.296a184 184 0 0 0-109.02-108.658l-19.698-7.239c-6.102-2.243-6.118-10.867-.025-13.132l20.083-7.467A183.998 183.998 0 0 0 133.291 26.28l7.91-21.394Z\"\n      />\n    </mask>\n    <g mask=\"url(#gemini-a)\">\n      <g filter=\"url(#gemini-b)\">\n        <ellipse cx=\"163\" cy=\"149\" fill=\"#3689FF\" rx=\"196\" ry=\"159\" />\n      </g>\n      <g filter=\"url(#gemini-c)\">\n        <ellipse cx=\"33.5\" cy=\"142.5\" fill=\"#F6C013\" rx=\"68.5\" ry=\"72.5\" />\n      </g>\n      <g filter=\"url(#gemini-d)\">\n        <ellipse cx=\"19.5\" cy=\"148.5\" fill=\"#F6C013\" rx=\"68.5\" ry=\"72.5\" />\n      </g>\n      <g filter=\"url(#gemini-e)\">\n        <path\n          fill=\"#FA4340\"\n          d=\"M194 10.5C172 82.5 65.5 134.333 22.5 135L144-66l50 76.5Z\"\n        />\n      </g>\n      <g filter=\"url(#gemini-f)\">\n        <path\n          fill=\"#FA4340\"\n          d=\"M190.5-12.5C168.5 59.5 62 111.333 19 112L140.5-89l50 76.5Z\"\n        />\n      </g>\n      <g filter=\"url(#gemini-g)\">\n        <path\n          fill=\"#14BB69\"\n          d=\"M194.5 279.5C172.5 207.5 66 155.667 23 155l121.5 201 50-76.5Z\"\n        />\n      </g>\n      <g filter=\"url(#gemini-h)\">\n        <path\n          fill=\"#14BB69\"\n          d=\"M196.5 320.5C174.5 248.5 68 196.667 25 196l121.5 201 50-76.5Z\"\n        />\n      </g>\n    </g>\n    <defs>\n      <filter\n        id=\"gemini-b\"\n        width=\"464\"\n        height=\"390\"\n        x=\"-69\"\n        y=\"-46\"\n        colorInterpolationFilters=\"sRGB\"\n        filterUnits=\"userSpaceOnUse\"\n      >\n        <feFlood floodOpacity=\"0\" result=\"BackgroundImageFix\" />\n        <feBlend in=\"SourceGraphic\" in2=\"BackgroundImageFix\" result=\"shape\" />\n        <feGaussianBlur\n          result=\"effect1_foregroundBlur_69_17998\"\n          stdDeviation=\"18\"\n        />\n      </filter>\n      <filter\n        id=\"gemini-c\"\n        width=\"265\"\n        height=\"273\"\n        x=\"-99\"\n        y=\"6\"\n        colorInterpolationFilters=\"sRGB\"\n        filterUnits=\"userSpaceOnUse\"\n      >\n        <feFlood floodOpacity=\"0\" result=\"BackgroundImageFix\" />\n        <feBlend in=\"SourceGraphic\" in2=\"BackgroundImageFix\" result=\"shape\" />\n        <feGaussianBlur\n          result=\"effect1_foregroundBlur_69_17998\"\n          stdDeviation=\"32\"\n        />\n      </filter>\n      <filter\n        id=\"gemini-d\"\n        width=\"265\"\n        height=\"273\"\n        x=\"-113\"\n        y=\"12\"\n        colorInterpolationFilters=\"sRGB\"\n        filterUnits=\"userSpaceOnUse\"\n      >\n        <feFlood floodOpacity=\"0\" result=\"BackgroundImageFix\" />\n        <feBlend in=\"SourceGraphic\" in2=\"BackgroundImageFix\" result=\"shape\" />\n        <feGaussianBlur\n          result=\"effect1_foregroundBlur_69_17998\"\n          stdDeviation=\"32\"\n        />\n      </filter>\n      <filter\n        id=\"gemini-e\"\n        width=\"299.5\"\n        height=\"329\"\n        x=\"-41.5\"\n        y=\"-130\"\n        colorInterpolationFilters=\"sRGB\"\n        filterUnits=\"userSpaceOnUse\"\n      >\n        <feFlood floodOpacity=\"0\" result=\"BackgroundImageFix\" />\n        <feBlend in=\"SourceGraphic\" in2=\"BackgroundImageFix\" result=\"shape\" />\n        <feGaussianBlur\n          result=\"effect1_foregroundBlur_69_17998\"\n          stdDeviation=\"32\"\n        />\n      </filter>\n      <filter\n        id=\"gemini-f\"\n        width=\"299.5\"\n        height=\"329\"\n        x=\"-45\"\n        y=\"-153\"\n        colorInterpolationFilters=\"sRGB\"\n        filterUnits=\"userSpaceOnUse\"\n      >\n        <feFlood floodOpacity=\"0\" result=\"BackgroundImageFix\" />\n        <feBlend in=\"SourceGraphic\" in2=\"BackgroundImageFix\" result=\"shape\" />\n        <feGaussianBlur\n          result=\"effect1_foregroundBlur_69_17998\"\n          stdDeviation=\"32\"\n        />\n      </filter>\n      <filter\n        id=\"gemini-g\"\n        width=\"299.5\"\n        height=\"329\"\n        x=\"-41\"\n        y=\"91\"\n        colorInterpolationFilters=\"sRGB\"\n        filterUnits=\"userSpaceOnUse\"\n      >\n        <feFlood floodOpacity=\"0\" result=\"BackgroundImageFix\" />\n        <feBlend in=\"SourceGraphic\" in2=\"BackgroundImageFix\" result=\"shape\" />\n        <feGaussianBlur\n          result=\"effect1_foregroundBlur_69_17998\"\n          stdDeviation=\"32\"\n        />\n      </filter>\n      <filter\n        id=\"gemini-h\"\n        width=\"299.5\"\n        height=\"329\"\n        x=\"-39\"\n        y=\"132\"\n        colorInterpolationFilters=\"sRGB\"\n        filterUnits=\"userSpaceOnUse\"\n      >\n        <feFlood floodOpacity=\"0\" result=\"BackgroundImageFix\" />\n        <feBlend in=\"SourceGraphic\" in2=\"BackgroundImageFix\" result=\"shape\" />\n        <feGaussianBlur\n          result=\"effect1_foregroundBlur_69_17998\"\n          stdDeviation=\"32\"\n        />\n      </filter>\n    </defs>\n  </svg>\n);\n\nexport const PerplexityLogo = (props: SVGProps<SVGSVGElement>) => (\n  <svg viewBox=\"8.94 4 30.12 40\" aria-hidden=\"true\" {...props}>\n    <path\n      fill=\"none\"\n      stroke=\"#20808d\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      d=\"M24 4.5v39M13.73 16.573v-9.99L24 16.573m0 14.5L13.73 41.417V27.01L24 16.573m0 0l10.27-9.99v9.99\"\n    />\n    <path\n      fill=\"none\"\n      stroke=\"#20808d\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      d=\"M13.73 31.396H9.44V16.573h29.12v14.823h-4.29\"\n    />\n    <path\n      fill=\"none\"\n      stroke=\"#20808d\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      d=\"M24 16.573L34.27 27.01v14.407L24 31.073\"\n    />\n  </svg>\n);\n\nexport const MistralLogo = (props: SVGProps<SVGSVGElement>) => (\n  <svg viewBox=\"0 0 256 233\" aria-hidden=\"true\" {...props}>\n    <path d=\"M186.18182 0h46.54545v46.54545h-46.54545z\" />\n    <path fill=\"#F7D046\" d=\"M209.45454 0h46.54545v46.54545h-46.54545z\" />\n    <path d=\"M0 0h46.54545v46.54545H0zM0 46.54545h46.54545V93.0909H0zM0 93.09091h46.54545v46.54545H0zM0 139.63636h46.54545v46.54545H0zM0 186.18182h46.54545v46.54545H0z\" />\n    <path fill=\"#F7D046\" d=\"M23.27273 0h46.54545v46.54545H23.27273z\" />\n    <path\n      fill=\"#F2A73B\"\n      d=\"M209.45454 46.54545h46.54545V93.0909h-46.54545zM23.27273 46.54545h46.54545V93.0909H23.27273z\"\n    />\n    <path d=\"M139.63636 46.54545h46.54545V93.0909h-46.54545z\" />\n    <path\n      fill=\"#F2A73B\"\n      d=\"M162.90909 46.54545h46.54545V93.0909h-46.54545zM69.81818 46.54545h46.54545V93.0909H69.81818z\"\n    />\n    <path\n      fill=\"#EE792F\"\n      d=\"M116.36364 93.09091h46.54545v46.54545h-46.54545zM162.90909 93.09091h46.54545v46.54545h-46.54545zM69.81818 93.09091h46.54545v46.54545H69.81818z\"\n    />\n    <path d=\"M93.09091 139.63636h46.54545v46.54545H93.09091z\" />\n    <path\n      fill=\"#EB5829\"\n      d=\"M116.36364 139.63636h46.54545v46.54545h-46.54545z\"\n    />\n    <path\n      fill=\"#EE792F\"\n      d=\"M209.45454 93.09091h46.54545v46.54545h-46.54545zM23.27273 93.09091h46.54545v46.54545H23.27273z\"\n    />\n    <path d=\"M186.18182 139.63636h46.54545v46.54545h-46.54545z\" />\n    <path\n      fill=\"#EB5829\"\n      d=\"M209.45454 139.63636h46.54545v46.54545h-46.54545z\"\n    />\n    <path d=\"M186.18182 186.18182h46.54545v46.54545h-46.54545z\" />\n    <path fill=\"#EB5829\" d=\"M23.27273 139.63636h46.54545v46.54545H23.27273z\" />\n    <path\n      fill=\"#EA3326\"\n      d=\"M209.45454 186.18182h46.54545v46.54545h-46.54545zM23.27273 186.18182h46.54545v46.54545H23.27273z\"\n    />\n  </svg>\n);\n\nexport const DeepSeekLogo = (props: SVGProps<SVGSVGElement>) => (\n  <svg viewBox=\"0 3 24 17.66\" aria-hidden=\"true\" {...props}>\n    <path\n      fill=\"#4D6BFE\"\n      d=\"M23.748 4.482c-.254-.124-.364.113-.512.234-.051.039-.094.09-.137.136-.372.397-.806.657-1.373.626-.829-.046-1.537.214-2.163.848-.133-.782-.575-1.248-1.247-1.548-.352-.156-.708-.311-.955-.65-.172-.241-.219-.51-.305-.774-.055-.16-.11-.323-.293-.35-.2-.031-.278.136-.356.276-.313.572-.434 1.202-.422 1.84.027 1.436.633 2.58 1.838 3.393.137.093.172.187.129.323-.082.28-.18.552-.266.833-.055.179-.137.217-.329.14a5.526 5.526 0 0 1-1.736-1.18c-.857-.828-1.631-1.742-2.597-2.458a11.365 11.365 0 0 0-.689-.471c-.985-.957.13-1.743.388-1.836.27-.098.093-.432-.779-.428-.872.004-1.67.295-2.687.684a3.055 3.055 0 0 1-.465.137 9.597 9.597 0 0 0-2.883-.102c-1.885.21-3.39 1.102-4.497 2.623C.082 8.606-.231 10.684.152 12.85c.403 2.284 1.569 4.175 3.36 5.653 1.858 1.533 3.997 2.284 6.438 2.14 1.482-.085 3.133-.284 4.994-1.86.47.234.962.327 1.78.397.63.059 1.236-.03 1.705-.128.735-.156.684-.837.419-.961-2.155-1.004-1.682-.595-2.113-.926 1.096-1.296 2.746-2.642 3.392-7.003.05-.347.007-.565 0-.845-.004-.17.035-.237.23-.256a4.173 4.173 0 0 0 1.545-.475c1.396-.763 1.96-2.015 2.093-3.517.02-.23-.004-.467-.247-.588zM11.581 18c-2.089-1.642-3.102-2.183-3.52-2.16-.392.024-.321.471-.235.763.09.288.207.486.371.739.114.167.192.416-.113.603-.673.416-1.842-.14-1.897-.167-1.361-.802-2.5-1.86-3.301-3.307-.774-1.393-1.224-2.887-1.298-4.482-.02-.386.093-.522.477-.592a4.696 4.696 0 0 1 1.529-.039c2.132.312 3.946 1.265 5.468 2.774.868.86 1.525 1.887 2.202 2.891.72 1.066 1.494 2.082 2.48 2.914.348.292.625.514.891.677-.802.09-2.14.11-3.054-.614zm1-6.44a.306.306 0 0 1 .415-.287.302.302 0 0 1 .2.288.306.306 0 0 1-.31.307.303.303 0 0 1-.304-.308zm3.11 1.596c-.2.081-.399.151-.59.16a1.245 1.245 0 0 1-.798-.254c-.274-.23-.47-.358-.552-.758a1.73 1.73 0 0 1 .016-.588c.07-.327-.008-.537-.239-.727-.187-.156-.426-.199-.688-.199a.559.559 0 0 1-.254-.078.253.253 0 0 1-.114-.358c.028-.054.16-.186.192-.21.356-.202.767-.136 1.146.016.352.144.618.408 1.001.782.391.451.462.576.685.914.176.265.336.537.445.848.067.195-.019.354-.25.452z\"\n    />\n  </svg>\n);\n\nexport const GrokLogo = (props: SVGProps<SVGSVGElement>) => (\n  <svg\n    viewBox=\"0 0 1024 1024\"\n    fill=\"currentColor\"\n    aria-hidden=\"true\"\n    {...props}\n  >\n    <path d=\"M395.479 633.828L735.91 381.105C752.599 368.715 776.454 373.548 784.406 392.792C826.26 494.285 807.561 616.253 724.288 699.996C641.016 783.739 525.151 802.104 419.247 760.277L303.556 814.143C469.49 928.202 670.987 899.995 796.901 773.282C896.776 672.843 927.708 535.937 898.785 412.476L899.047 412.739C857.105 231.37 909.358 158.874 1016.4 10.6326C1018.93 7.11771 1021.47 3.60279 1024 0L883.144 141.651V141.212L395.392 633.916\" />\n    <path d=\"M325.226 695.251C206.128 580.84 226.662 403.776 328.285 301.668C403.431 226.097 526.549 195.254 634.026 240.596L749.454 186.994C728.657 171.88 702.007 155.623 671.424 144.2C533.19 86.9942 367.693 115.465 255.323 228.382C147.234 337.081 113.244 504.215 171.613 646.833C215.216 753.423 143.739 828.818 71.7385 904.916C46.2237 931.893 20.6216 958.87 0 987.429L325.139 695.339\" />\n  </svg>\n);\n\nexport const BrowserbaseLogo = (props: SVGProps<SVGSVGElement>) => (\n  <svg viewBox=\"0 0 200 200\" fill=\"none\" aria-hidden=\"true\" {...props}>\n    <rect x=\"30\" y=\"36\" width=\"134\" height=\"124\" fill=\"white\" />\n    <path d=\"M111.168 116.901H83.168V109.901H111.168V116.901Z\" fill=\"#FF4500\" />\n    <path d=\"M111.168 86.208H83.168V79.208H111.168V86.208Z\" fill=\"#FF4500\" />\n    <path\n      fillRule=\"evenodd\"\n      clipRule=\"evenodd\"\n      d=\"M200 200H0V0H200V200ZM55.4453 147.815H128.678L145.259 131.234V111.891L131.441 98.0723L142.495 87.0186V69.0557L125.914 52.4756H55.4453V147.815Z\"\n      fill=\"#FF4500\"\n    />\n  </svg>\n);\n\nexport const ContextDevLogo = (props: SVGProps<SVGSVGElement>) => (\n  <svg viewBox=\"0 0 180 180\" fill=\"none\" aria-hidden=\"true\" {...props}>\n    <rect width=\"180\" height=\"180\" fill=\"#2663EB\" />\n    <g transform=\"translate(22 45) scale(0.1658)\" fill=\"#FFFFFF\">\n      <path\n        fillRule=\"evenodd\"\n        d=\"M287.56,0H745.26A27.06,27.06,0,0,1,772.32,27.06V484.77A27.06,27.06,0,0,1,745.26,511.83H284.51A24.01,24.01,0,0,1,260.5,487.82V27.06A27.06,27.06,0,0,1,287.56,0ZM260.5,358.28a153.55,153.55,0,1,0,307.1,0a153.55,153.55,0,1,0,-307.1,0Z\"\n      />\n      <circle cx=\"153.55\" cy=\"377.64\" r=\"153.55\" />\n    </g>\n  </svg>\n);\n\nexport const FirecrawlLogo = (props: SVGProps<SVGSVGElement>) => (\n  <svg viewBox=\"0 0 50 72\" fill=\"none\" aria-hidden=\"true\" {...props}>\n    <path\n      fill=\"#fa5d19\"\n      d=\"M41.715 23.193c-2.762.82-4.844 2.675-6.37 4.69-.327.432-1.01.107-.88-.423 2.92-12.007-.937-21.986-12.961-26.898a.803.803 0 0 0-1.085.937c5.47 21.961-17.537 20.109-14.63 45.005.05.427-.43.72-.78.47-1.09-.782-2.307-2.415-3.142-3.562a.502.502 0 0 0-.887.16c-.665 2.404-.98 4.67-.98 6.92 0 8.749 4.497 16.45 11.304 20.915.39.255.89-.11.758-.557a13.5 13.5 0 0 1-.563-3.697c0-.788.05-1.593.173-2.343.285-1.885.94-3.68 2.04-5.314 3.772-5.663 11.334-11.132 10.127-18.56-.078-.47.477-.78.827-.457 5.328 4.868 6.383 11.415 5.508 17.287-.075.51.564.782.887.382a11.6 11.6 0 0 1 2.892-2.587c.27-.168.63-.04.733.26.602 1.752 1.497 3.397 2.342 5.042a13.46 13.46 0 0 1 .905 9.982.502.502 0 0 0 .755.57C45.5 66.95 50 59.248 50 50.494c0-3.043-.532-6.025-1.54-8.82-2.112-5.862-7.472-10.264-6.117-17.904.065-.365-.273-.682-.628-.577\"\n    />\n  </svg>\n);\n\nexport const ResendLogo = (props: SVGProps<SVGSVGElement>) => (\n  <svg\n    viewBox=\"450 450 900 900\"\n    fill=\"currentColor\"\n    aria-hidden=\"true\"\n    {...props}\n  >\n    <path d=\"M1000.46 450C1174.77 450 1278.43 553.669 1278.43 691.282C1278.43 828.896 1174.77 932.563 1000.46 932.563H912.382L1350 1350H1040.82L707.794 1033.48C683.944 1011.47 672.936 985.781 672.935 963.765C672.935 932.572 694.959 905.049 737.161 893.122L908.712 847.244C973.85 829.812 1018.81 779.353 1018.81 713.298C1018.8 632.567 952.745 585.78 871.095 585.78H450V450H1000.46Z\" />\n  </svg>\n);\n\nexport const SlackLogo = (props: SVGProps<SVGSVGElement>) => (\n  <svg viewBox=\"0 0 2447.6 2452.5\" aria-hidden=\"true\" {...props}>\n    <g clipRule=\"evenodd\" fillRule=\"evenodd\">\n      <path\n        d=\"m897.4 0c-135.3.1-244.8 109.9-244.7 245.2-.1 135.3 109.5 245.1 244.8 245.2h244.8v-245.1c.1-135.3-109.5-245.1-244.9-245.3.1 0 .1 0 0 0m0 654h-652.6c-135.3.1-244.9 109.9-244.8 245.2-.2 135.3 109.4 245.1 244.7 245.3h652.7c135.3-.1 244.9-109.9 244.8-245.2.1-135.4-109.5-245.2-244.8-245.3z\"\n        fill=\"#36c5f0\"\n      />\n      <path\n        d=\"m2447.6 899.2c.1-135.3-109.5-245.1-244.8-245.2-135.3.1-244.9 109.9-244.8 245.2v245.3h244.8c135.3-.1 244.9-109.9 244.8-245.3zm-652.7 0v-654c.1-135.2-109.4-245-244.7-245.2-135.3.1-244.9 109.9-244.8 245.2v654c-.2 135.3 109.4 245.1 244.7 245.3 135.3-.1 244.9-109.9 244.8-245.3z\"\n        fill=\"#2eb67d\"\n      />\n      <path\n        d=\"m1550.1 2452.5c135.3-.1 244.9-109.9 244.8-245.2.1-135.3-109.5-245.1-244.8-245.2h-244.8v245.2c-.1 135.2 109.5 245 244.8 245.2zm0-654.1h652.7c135.3-.1 244.9-109.9 244.8-245.2.2-135.3-109.4-245.1-244.7-245.3h-652.7c-135.3.1-244.9 109.9-244.8 245.2-.1 135.4 109.4 245.2 244.7 245.3z\"\n        fill=\"#ecb22e\"\n      />\n      <path\n        d=\"m0 1553.2c-.1 135.3 109.5 245.1 244.8 245.2 135.3-.1 244.9-109.9 244.8-245.2v-245.2h-244.8c-135.3.1-244.9 109.9-244.8 245.2zm652.7 0v654c-.2 135.3 109.4 245.1 244.7 245.3 135.3-.1 244.9-109.9 244.8-245.2v-653.9c.2-135.3-109.4-245.1-244.7-245.3-135.4 0-244.9 109.8-244.8 245.1 0 0 0 .1 0 0\"\n        fill=\"#e01e5a\"\n      />\n    </g>\n  </svg>\n);\n\nexport const GmailLogo = (props: SVGProps<SVGSVGElement>) => (\n  <svg viewBox=\"0 64.72 512 384.1\" aria-hidden=\"true\" {...props}>\n    <g fill=\"none\" fillRule=\"evenodd\">\n      <g fillRule=\"nonzero\">\n        <path\n          fill=\"#4285f4\"\n          d=\"M34.91 448.818h81.454V251L0 163.727V413.91c0 19.287 15.622 34.91 34.91 34.91z\"\n        />\n        <path\n          fill=\"#34a853\"\n          d=\"M395.636 448.818h81.455c19.287 0 34.909-15.622 34.909-34.909V163.727L395.636 251z\"\n        />\n        <path\n          fill=\"#fbbc04\"\n          d=\"M395.636 99.727V251L512 163.727v-46.545c0-43.142-49.25-67.782-83.782-41.891z\"\n        />\n      </g>\n      <path\n        fill=\"#ea4335\"\n        d=\"M116.364 251V99.727L256 204.455 395.636 99.727V251L256 355.727z\"\n      />\n      <path\n        fill=\"#c5221f\"\n        fillRule=\"nonzero\"\n        d=\"M0 117.182v46.545L116.364 251V99.727L83.782 75.291C49.25 49.4 0 74.04 0 117.18z\"\n      />\n    </g>\n  </svg>\n);\n\nexport const NotionLogo = (props: SVGProps<SVGSVGElement>) => (\n  <svg viewBox=\"0 0 256 268\" aria-hidden=\"true\" {...props}>\n    <path\n      fill=\"#FFF\"\n      d=\"M16.092 11.538 164.09.608c18.179-1.56 22.85-.508 34.28 7.801l47.243 33.282C253.406 47.414 256 48.975 256 55.207v182.527c0 11.439-4.155 18.205-18.696 19.24L65.44 267.378c-10.913.517-16.11-1.043-21.825-8.327L8.826 213.814C2.586 205.487 0 199.254 0 191.97V29.726c0-9.352 4.155-17.153 16.092-18.188Z\"\n    />\n    <path d=\"M164.09.608 16.092 11.538C4.155 12.573 0 20.374 0 29.726v162.245c0 7.284 2.585 13.516 8.826 21.843l34.789 45.237c5.715 7.284 10.912 8.844 21.825 8.327l171.864-10.404c14.532-1.035 18.696-7.801 18.696-19.24V55.207c0-5.911-2.336-7.614-9.21-12.66l-1.185-.856L198.37 8.409C186.94.1 182.27-.952 164.09.608ZM69.327 52.22c-14.033.945-17.216 1.159-25.186-5.323L23.876 30.778c-2.06-2.086-1.026-4.69 4.163-5.207l142.274-10.395c11.947-1.043 18.17 3.12 22.842 6.758l24.401 17.68c1.043.525 3.638 3.637.517 3.637L71.146 52.095l-1.819.125Zm-16.36 183.954V81.222c0-6.767 2.077-9.887 8.3-10.413L230.02 60.93c5.724-.517 8.31 3.12 8.31 9.879v153.917c0 6.767-1.044 12.49-10.387 13.008l-161.487 9.361c-9.343.517-13.489-2.594-13.489-10.921ZM212.377 89.53c1.034 4.681 0 9.362-4.681 9.897l-7.783 1.542v114.404c-6.758 3.637-12.981 5.715-18.18 5.715-8.308 0-10.386-2.604-16.609-10.396l-50.898-80.079v77.476l16.1 3.646s0 9.362-12.989 9.362l-35.814 2.077c-1.043-2.086 0-7.284 3.63-8.318l9.351-2.595V109.823l-12.98-1.052c-1.044-4.68 1.55-11.439 8.826-11.965l38.426-2.585 52.958 81.113v-71.76l-13.498-1.552c-1.043-5.733 3.111-9.896 8.3-10.404l35.84-2.087Z\" />\n  </svg>\n);\n\nexport const GoogleLogo = (props: SVGProps<SVGSVGElement>) => (\n  <svg viewBox=\"0 0 268.152 273.883\" aria-hidden=\"true\" {...props}>\n    <defs>\n      <linearGradient id=\"google-a\">\n        <stop offset=\"0\" stopColor=\"#0fbc5c\" />\n        <stop offset=\"1\" stopColor=\"#0cba65\" />\n      </linearGradient>\n      <linearGradient id=\"google-g\">\n        <stop offset=\".231\" stopColor=\"#0fbc5f\" />\n        <stop offset=\".312\" stopColor=\"#0fbc5f\" />\n        <stop offset=\".366\" stopColor=\"#0fbc5e\" />\n        <stop offset=\".458\" stopColor=\"#0fbc5d\" />\n        <stop offset=\".54\" stopColor=\"#12bc58\" />\n        <stop offset=\".699\" stopColor=\"#28bf3c\" />\n        <stop offset=\".771\" stopColor=\"#38c02b\" />\n        <stop offset=\".861\" stopColor=\"#52c218\" />\n        <stop offset=\".915\" stopColor=\"#67c30f\" />\n        <stop offset=\"1\" stopColor=\"#86c504\" />\n      </linearGradient>\n      <linearGradient id=\"google-h\">\n        <stop offset=\".142\" stopColor=\"#1abd4d\" />\n        <stop offset=\".248\" stopColor=\"#6ec30d\" />\n        <stop offset=\".312\" stopColor=\"#8ac502\" />\n        <stop offset=\".366\" stopColor=\"#a2c600\" />\n        <stop offset=\".446\" stopColor=\"#c8c903\" />\n        <stop offset=\".54\" stopColor=\"#ebcb03\" />\n        <stop offset=\".616\" stopColor=\"#f7cd07\" />\n        <stop offset=\".699\" stopColor=\"#fdcd04\" />\n        <stop offset=\".771\" stopColor=\"#fdce05\" />\n        <stop offset=\".861\" stopColor=\"#ffce0a\" />\n      </linearGradient>\n      <linearGradient id=\"google-f\">\n        <stop offset=\".316\" stopColor=\"#ff4c3c\" />\n        <stop offset=\".604\" stopColor=\"#ff692c\" />\n        <stop offset=\".727\" stopColor=\"#ff7825\" />\n        <stop offset=\".885\" stopColor=\"#ff8d1b\" />\n        <stop offset=\"1\" stopColor=\"#ff9f13\" />\n      </linearGradient>\n      <linearGradient id=\"google-b\">\n        <stop offset=\".231\" stopColor=\"#ff4541\" />\n        <stop offset=\".312\" stopColor=\"#ff4540\" />\n        <stop offset=\".458\" stopColor=\"#ff4640\" />\n        <stop offset=\".54\" stopColor=\"#ff473f\" />\n        <stop offset=\".699\" stopColor=\"#ff5138\" />\n        <stop offset=\".771\" stopColor=\"#ff5b33\" />\n        <stop offset=\".861\" stopColor=\"#ff6c29\" />\n        <stop offset=\"1\" stopColor=\"#ff8c18\" />\n      </linearGradient>\n      <linearGradient id=\"google-d\">\n        <stop offset=\".408\" stopColor=\"#fb4e5a\" />\n        <stop offset=\"1\" stopColor=\"#ff4540\" />\n      </linearGradient>\n      <linearGradient id=\"google-c\">\n        <stop offset=\".132\" stopColor=\"#0cba65\" />\n        <stop offset=\".21\" stopColor=\"#0bb86d\" />\n        <stop offset=\".297\" stopColor=\"#09b479\" />\n        <stop offset=\".396\" stopColor=\"#08ad93\" />\n        <stop offset=\".477\" stopColor=\"#0aa6a9\" />\n        <stop offset=\".568\" stopColor=\"#0d9cc6\" />\n        <stop offset=\".667\" stopColor=\"#1893dd\" />\n        <stop offset=\".769\" stopColor=\"#258bf1\" />\n        <stop offset=\".859\" stopColor=\"#3086ff\" />\n      </linearGradient>\n      <linearGradient id=\"google-e\">\n        <stop offset=\".366\" stopColor=\"#ff4e3a\" />\n        <stop offset=\".458\" stopColor=\"#ff8a1b\" />\n        <stop offset=\".54\" stopColor=\"#ffa312\" />\n        <stop offset=\".616\" stopColor=\"#ffb60c\" />\n        <stop offset=\".771\" stopColor=\"#ffcd0a\" />\n        <stop offset=\".861\" stopColor=\"#fecf0a\" />\n        <stop offset=\".915\" stopColor=\"#fecf08\" />\n        <stop offset=\"1\" stopColor=\"#fdcd01\" />\n      </linearGradient>\n      <linearGradient\n        href=\"#google-a\"\n        id=\"google-s\"\n        x1=\"219.7\"\n        x2=\"254.467\"\n        y1=\"329.535\"\n        y2=\"329.535\"\n        gradientUnits=\"userSpaceOnUse\"\n      />\n      <radialGradient\n        href=\"#google-b\"\n        id=\"google-m\"\n        cx=\"109.627\"\n        cy=\"135.862\"\n        r=\"71.46\"\n        fx=\"109.627\"\n        fy=\"135.862\"\n        gradientTransform=\"matrix(-1.93688 1.043 1.45573 2.55542 290.525 -400.634)\"\n        gradientUnits=\"userSpaceOnUse\"\n      />\n      <radialGradient\n        href=\"#google-c\"\n        id=\"google-n\"\n        cx=\"45.259\"\n        cy=\"279.274\"\n        r=\"71.46\"\n        fx=\"45.259\"\n        fy=\"279.274\"\n        gradientTransform=\"matrix(-3.5126 -4.45809 -1.69255 1.26062 870.8 191.554)\"\n        gradientUnits=\"userSpaceOnUse\"\n      />\n      <radialGradient\n        href=\"#google-d\"\n        id=\"google-l\"\n        cx=\"304.017\"\n        cy=\"118.009\"\n        r=\"47.854\"\n        fx=\"304.017\"\n        fy=\"118.009\"\n        gradientTransform=\"matrix(2.06435 0 0 2.59204 -297.679 -151.747)\"\n        gradientUnits=\"userSpaceOnUse\"\n      />\n      <radialGradient\n        href=\"#google-e\"\n        id=\"google-o\"\n        cx=\"181.001\"\n        cy=\"177.201\"\n        r=\"71.46\"\n        fx=\"181.001\"\n        fy=\"177.201\"\n        gradientTransform=\"matrix(-.24858 2.08314 2.96249 .33417 -255.146 -331.164)\"\n        gradientUnits=\"userSpaceOnUse\"\n      />\n      <radialGradient\n        href=\"#google-f\"\n        id=\"google-p\"\n        cx=\"207.673\"\n        cy=\"108.097\"\n        r=\"41.102\"\n        fx=\"207.673\"\n        fy=\"108.097\"\n        gradientTransform=\"matrix(-1.2492 1.34326 -3.89684 -3.4257 880.501 194.905)\"\n        gradientUnits=\"userSpaceOnUse\"\n      />\n      <radialGradient\n        href=\"#google-g\"\n        id=\"google-r\"\n        cx=\"109.627\"\n        cy=\"135.862\"\n        r=\"71.46\"\n        fx=\"109.627\"\n        fy=\"135.862\"\n        gradientTransform=\"matrix(-1.93688 -1.043 1.45573 -2.55542 290.525 838.683)\"\n        gradientUnits=\"userSpaceOnUse\"\n      />\n      <radialGradient\n        href=\"#google-h\"\n        id=\"google-j\"\n        cx=\"154.87\"\n        cy=\"145.969\"\n        r=\"71.46\"\n        fx=\"154.87\"\n        fy=\"145.969\"\n        gradientTransform=\"matrix(-.0814 -1.93722 2.92674 -.11625 -215.135 632.86)\"\n        gradientUnits=\"userSpaceOnUse\"\n      />\n      <filter\n        id=\"google-q\"\n        width=\"1.097\"\n        height=\"1.116\"\n        x=\"-.048\"\n        y=\"-.058\"\n        colorInterpolationFilters=\"sRGB\"\n      >\n        <feGaussianBlur stdDeviation=\"1.701\" />\n      </filter>\n      <filter\n        id=\"google-k\"\n        width=\"1.033\"\n        height=\"1.02\"\n        x=\"-.017\"\n        y=\"-.01\"\n        colorInterpolationFilters=\"sRGB\"\n      >\n        <feGaussianBlur stdDeviation=\".242\" />\n      </filter>\n      <clipPath id=\"google-i\" clipPathUnits=\"userSpaceOnUse\">\n        <path d=\"M371.378 193.24H237.083v53.438h77.167c-1.241 7.563-4.026 15.003-8.105 21.786-4.674 7.773-10.451 13.69-16.373 18.196-17.74 13.498-38.42 16.258-52.783 16.258-36.283 0-67.283-23.286-79.285-54.928-.484-1.149-.805-2.335-1.197-3.507a81.115 81.115 0 0 1-4.101-25.448c0-9.226 1.569-18.057 4.43-26.398 11.285-32.897 42.985-57.467 80.179-57.467 7.481 0 14.685.884 21.517 2.648a77.668 77.668 0 0 1 33.425 18.25l40.834-39.712c-24.839-22.616-57.219-36.32-95.844-36.32-30.878 0-59.386 9.553-82.748 25.7-18.945 13.093-34.483 30.625-44.97 50.985-9.753 18.879-15.094 39.8-15.094 62.294 0 22.495 5.35 43.633 15.103 62.337v.126c10.302 19.857 25.368 36.954 43.678 49.988 15.997 11.386 44.68 26.551 84.031 26.551 22.63 0 42.687-4.051 60.375-11.644 12.76-5.478 24.065-12.622 34.301-21.804 13.525-12.132 24.117-27.139 31.347-44.404 7.23-17.265 11.097-36.79 11.097-57.957 0-9.858-.998-19.87-2.689-28.968Z\" />\n      </clipPath>\n    </defs>\n    <g\n      clipPath=\"url(#google-i)\"\n      transform=\"matrix(.95792 0 0 .98525 -90.174 -78.856)\"\n    >\n      <path\n        fill=\"url(#google-j)\"\n        d=\"M92.076 219.958c.148 22.14 6.501 44.983 16.117 63.424v.127c6.949 13.392 16.445 23.97 27.26 34.452l65.327-23.67c-12.36-6.235-14.246-10.055-23.105-17.026-9.054-9.066-15.802-19.473-20.004-31.677h-.17l.17-.127c-2.765-8.058-3.037-16.613-3.14-25.503Z\"\n        filter=\"url(#google-k)\"\n      />\n      <path\n        fill=\"url(#google-l)\"\n        d=\"M237.083 79.025c-6.456 22.526-3.988 44.421 0 57.161 7.457.006 14.64.888 21.45 2.647a77.662 77.662 0 0 1 33.424 18.25l41.88-40.726c-24.81-22.59-54.667-37.297-96.754-37.332Z\"\n        filter=\"url(#google-k)\"\n      />\n      <path\n        fill=\"url(#google-m)\"\n        d=\"M236.943 78.847c-31.67 0-60.91 9.798-84.871 26.359a145.533 145.533 0 0 0-24.332 21.15c-1.904 17.744 14.257 39.551 46.262 39.37 15.528-17.936 38.495-29.542 64.056-29.542l.07.002-1.044-57.335c-.048 0-.093-.004-.14-.004Z\"\n        filter=\"url(#google-k)\"\n      />\n      <path\n        fill=\"url(#google-n)\"\n        d=\"m341.475 226.379-28.268 19.285c-1.24 7.562-4.028 15.002-8.107 21.786-4.674 7.772-10.45 13.69-16.373 18.196-17.702 13.47-38.328 16.244-52.687 16.255-14.842 25.102-17.444 37.675 1.043 57.934 22.877-.016 43.157-4.117 61.046-11.796 12.931-5.551 24.388-12.792 34.761-22.097 13.706-12.295 24.442-27.503 31.769-45 7.327-17.497 11.245-37.282 11.245-58.734Z\"\n        filter=\"url(#google-k)\"\n      />\n      <path\n        fill=\"#3086ff\"\n        d=\"M234.996 191.21v57.498h136.006c1.196-7.874 5.152-18.064 5.152-26.5 0-9.858-.996-21.899-2.687-30.998Z\"\n        filter=\"url(#google-k)\"\n      />\n      <path\n        fill=\"url(#google-o)\"\n        d=\"M128.39 124.327c-8.394 9.119-15.564 19.326-21.249 30.364-9.753 18.879-15.094 41.83-15.094 64.324 0 .317.026.627.029.944 4.32 8.224 59.666 6.649 62.456 0-.004-.31-.039-.613-.039-.924 0-9.226 1.57-16.026 4.43-24.367 3.53-10.289 9.056-19.763 16.123-27.926 1.602-2.031 5.875-6.397 7.121-9.016.475-.997-.862-1.557-.937-1.908-.083-.393-1.876-.077-2.277-.37-1.275-.929-3.8-1.414-5.334-1.845-3.277-.921-8.708-2.953-11.725-5.06-9.536-6.658-24.417-14.612-33.505-24.216Z\"\n        filter=\"url(#google-k)\"\n      />\n      <path\n        fill=\"url(#google-p)\"\n        d=\"M162.099 155.857c22.112 13.301 28.471-6.714 43.173-12.977l-25.574-52.664a144.74 144.74 0 0 0-26.543 14.504c-12.316 8.512-23.192 18.9-32.176 30.72Z\"\n        filter=\"url(#google-q)\"\n      />\n      <path\n        fill=\"url(#google-r)\"\n        d=\"M171.099 290.222c-29.683 10.641-34.33 11.023-37.062 29.29a144.806 144.806 0 0 0 16.792 13.984c15.996 11.386 46.766 26.551 86.118 26.551.046 0 .09-.004.137-.004v-59.157l-.094.002c-14.736 0-26.512-3.843-38.585-10.527-2.977-1.648-8.378 2.777-11.123.799-3.786-2.729-12.9 2.35-16.183-.938Z\"\n        filter=\"url(#google-k)\"\n      />\n      <path\n        fill=\"url(#google-s)\"\n        d=\"M219.7 299.023v59.996c5.506.64 11.236 1.028 17.247 1.028 6.026 0 11.855-.307 17.52-.872v-59.748a105.119 105.119 0 0 1-17.477 1.461c-5.932 0-11.7-.686-17.29-1.865Z\"\n        filter=\"url(#google-k)\"\n        opacity=\".5\"\n      />\n    </g>\n  </svg>\n);\n\nexport const GoogleSheetsLogo = (props: SVGProps<SVGSVGElement>) => (\n  <svg viewBox=\"0 0 74 100\" fill=\"none\" aria-hidden=\"true\" {...props}>\n    <mask\n      id=\"google-sheets-mask0_1-52\"\n      style={{ maskType: \"alpha\" }}\n      maskUnits=\"userSpaceOnUse\"\n      x=\"1\"\n      y=\"1\"\n      width=\"71\"\n      height=\"98\"\n    >\n      <path\n        d=\"M45.398 1.43036H7.86688C4.22415 1.43036 1.24374 4.41077 1.24374 8.0535V91.9465C1.24374 95.5893 4.22415 98.5697 7.86688 98.5697H65.2674C68.9101 98.5697 71.8905 95.5893 71.8905 91.9465V27.9229L45.398 1.43036Z\"\n        fill=\"white\"\n      />\n    </mask>\n    <g mask=\"url(#google-sheets-mask0_1-52)\">\n      <path\n        d=\"M45.398 1.43036H7.86688C4.22415 1.43036 1.24374 4.41077 1.24374 8.0535V91.9465C1.24374 95.5893 4.22415 98.5697 7.86688 98.5697H65.2674C68.9101 98.5697 71.8905 95.5893 71.8905 91.9465V27.9229L56.4365 16.8843L45.398 1.43036Z\"\n        fill=\"#0F9D58\"\n      />\n    </g>\n    <mask\n      id=\"google-sheets-mask1_1-52\"\n      style={{ maskType: \"alpha\" }}\n      maskUnits=\"userSpaceOnUse\"\n      x=\"1\"\n      y=\"1\"\n      width=\"71\"\n      height=\"98\"\n    >\n      <path\n        d=\"M45.398 1.43036H7.86688C4.22415 1.43036 1.24374 4.41077 1.24374 8.0535V91.9465C1.24374 95.5893 4.22415 98.5697 7.86688 98.5697H65.2674C68.9101 98.5697 71.8905 95.5893 71.8905 91.9465V27.9229L45.398 1.43036Z\"\n        fill=\"white\"\n      />\n    </mask>\n    <g mask=\"url(#google-sheets-mask1_1-52)\">\n      <path\n        d=\"M18.9054 48.8962V80.908H54.2288V48.8962H18.9054ZM34.3594 76.4926H23.3209V70.9733H34.3594V76.4926ZM34.3594 67.6617H23.3209V62.1424H34.3594V67.6617ZM34.3594 58.8309H23.3209V53.3116H34.3594V58.8309ZM49.8134 76.4926H38.7748V70.9733H49.8134V76.4926ZM49.8134 67.6617H38.7748V62.1424H49.8134V67.6617ZM49.8134 58.8309H38.7748V53.3116H49.8134V58.8309Z\"\n        fill=\"#F1F1F1\"\n      />\n    </g>\n    <mask\n      id=\"google-sheets-mask2_1-52\"\n      style={{ maskType: \"alpha\" }}\n      maskUnits=\"userSpaceOnUse\"\n      x=\"1\"\n      y=\"1\"\n      width=\"71\"\n      height=\"98\"\n    >\n      <path\n        d=\"M45.398 1.43036H7.86688C4.22415 1.43036 1.24374 4.41077 1.24374 8.0535V91.9465C1.24374 95.5893 4.22415 98.5697 7.86688 98.5697H65.2674C68.9101 98.5697 71.8905 95.5893 71.8905 91.9465V27.9229L45.398 1.43036Z\"\n        fill=\"white\"\n      />\n    </mask>\n    <g mask=\"url(#google-sheets-mask2_1-52)\">\n      <path\n        d=\"M47.3352 25.9856L71.8905 50.5354V27.9229L47.3352 25.9856Z\"\n        fill=\"url(#google-sheets-paint0_linear_1-52)\"\n      />\n    </g>\n    <mask\n      id=\"google-sheets-mask3_1-52\"\n      style={{ maskType: \"alpha\" }}\n      maskUnits=\"userSpaceOnUse\"\n      x=\"1\"\n      y=\"1\"\n      width=\"71\"\n      height=\"98\"\n    >\n      <path\n        d=\"M45.398 1.43036H7.86688C4.22415 1.43036 1.24374 4.41077 1.24374 8.0535V91.9465C1.24374 95.5893 4.22415 98.5697 7.86688 98.5697H65.2674C68.9101 98.5697 71.8905 95.5893 71.8905 91.9465V27.9229L45.398 1.43036Z\"\n        fill=\"white\"\n      />\n    </mask>\n    <g mask=\"url(#google-sheets-mask3_1-52)\">\n      <path\n        d=\"M45.398 1.43036V21.2998C45.398 24.959 48.3618 27.9229 52.0211 27.9229H71.8905L45.398 1.43036Z\"\n        fill=\"#87CEAC\"\n      />\n    </g>\n    <mask\n      id=\"google-sheets-mask4_1-52\"\n      style={{ maskType: \"alpha\" }}\n      maskUnits=\"userSpaceOnUse\"\n      x=\"1\"\n      y=\"1\"\n      width=\"71\"\n      height=\"98\"\n    >\n      <path\n        d=\"M45.398 1.43036H7.86688C4.22415 1.43036 1.24374 4.41077 1.24374 8.0535V91.9465C1.24374 95.5893 4.22415 98.5697 7.86688 98.5697H65.2674C68.9101 98.5697 71.8905 95.5893 71.8905 91.9465V27.9229L45.398 1.43036Z\"\n        fill=\"white\"\n      />\n    </mask>\n    <g mask=\"url(#google-sheets-mask4_1-52)\">\n      <path\n        d=\"M7.86688 1.43036C4.22415 1.43036 1.24374 4.41077 1.24374 8.0535V8.60542C1.24374 4.9627 4.22415 1.98229 7.86688 1.98229H45.398V1.43036H7.86688Z\"\n        fill=\"white\"\n        fillOpacity=\"0.2\"\n      />\n    </g>\n    <mask\n      id=\"google-sheets-mask5_1-52\"\n      style={{ maskType: \"alpha\" }}\n      maskUnits=\"userSpaceOnUse\"\n      x=\"1\"\n      y=\"1\"\n      width=\"71\"\n      height=\"98\"\n    >\n      <path\n        d=\"M45.398 1.43036H7.86688C4.22415 1.43036 1.24374 4.41077 1.24374 8.0535V91.9465C1.24374 95.5893 4.22415 98.5697 7.86688 98.5697H65.2674C68.9101 98.5697 71.8905 95.5893 71.8905 91.9465V27.9229L45.398 1.43036Z\"\n        fill=\"white\"\n      />\n    </mask>\n    <g mask=\"url(#google-sheets-mask5_1-52)\">\n      <path\n        d=\"M65.2674 98.0177H7.86688C4.22415 98.0177 1.24374 95.0373 1.24374 91.3946V91.9465C1.24374 95.5893 4.22415 98.5697 7.86688 98.5697H65.2674C68.9101 98.5697 71.8905 95.5893 71.8905 91.9465V91.3946C71.8905 95.0373 68.9101 98.0177 65.2674 98.0177Z\"\n        fill=\"#263238\"\n        fillOpacity=\"0.2\"\n      />\n    </g>\n    <mask\n      id=\"google-sheets-mask6_1-52\"\n      style={{ maskType: \"alpha\" }}\n      maskUnits=\"userSpaceOnUse\"\n      x=\"1\"\n      y=\"1\"\n      width=\"71\"\n      height=\"98\"\n    >\n      <path\n        d=\"M45.398 1.43036H7.86688C4.22415 1.43036 1.24374 4.41077 1.24374 8.0535V91.9465C1.24374 95.5893 4.22415 98.5697 7.86688 98.5697H65.2674C68.9101 98.5697 71.8905 95.5893 71.8905 91.9465V27.9229L45.398 1.43036Z\"\n        fill=\"white\"\n      />\n    </mask>\n    <g mask=\"url(#google-sheets-mask6_1-52)\">\n      <path\n        d=\"M52.0211 27.9229C48.3618 27.9229 45.398 24.959 45.398 21.2998V21.8517C45.398 25.511 48.3618 28.4748 52.0211 28.4748H71.8905V27.9229H52.0211Z\"\n        fill=\"#263238\"\n        fillOpacity=\"0.1\"\n      />\n    </g>\n    <path\n      d=\"M45.398 1.43036H7.86688C4.22415 1.43036 1.24374 4.41077 1.24374 8.0535V91.9465C1.24374 95.5893 4.22415 98.5697 7.86688 98.5697H65.2674C68.9101 98.5697 71.8905 95.5893 71.8905 91.9465V27.9229L45.398 1.43036Z\"\n      fill=\"url(#google-sheets-paint1_radial_1-52)\"\n    />\n    <defs>\n      <linearGradient\n        id=\"google-sheets-paint0_linear_1-52\"\n        x1=\"59.6142\"\n        y1=\"28.0935\"\n        x2=\"59.6142\"\n        y2=\"50.5388\"\n        gradientUnits=\"userSpaceOnUse\"\n      >\n        <stop stopColor=\"#263238\" stopOpacity=\"0.2\" />\n        <stop offset=\"1\" stopColor=\"#263238\" stopOpacity=\"0.02\" />\n      </linearGradient>\n      <radialGradient\n        id=\"google-sheets-paint1_radial_1-52\"\n        cx=\"0\"\n        cy=\"0\"\n        r=\"1\"\n        gradientUnits=\"userSpaceOnUse\"\n        gradientTransform=\"translate(3.48187 3.36121) scale(113.917)\"\n      >\n        <stop stopColor=\"white\" stopOpacity=\"0.1\" />\n        <stop offset=\"1\" stopColor=\"white\" stopOpacity=\"0\" />\n      </radialGradient>\n    </defs>\n  </svg>\n);\n\nexport const WebflowLogo = (props: SVGProps<SVGSVGElement>) => (\n  <svg viewBox=\"0 0 1080 674\" fill=\"none\" aria-hidden=\"true\" {...props}>\n    <path\n      fill=\"#146EF5\"\n      fillRule=\"evenodd\"\n      d=\"M1080 0 735.386 673.684H411.695l144.221-279.203h-6.471C430.464 548.934 252.942 650.61-.0005 673.684v-275.34s161.8135-9.557 256.9385-109.568H-.0005V.0053H288.771V237.515l6.481-.026L413.254.0053h218.39V236.009l6.482-.01L760.555 0H1080Z\"\n      clipRule=\"evenodd\"\n    />\n  </svg>\n);\n\nexport const WordPressLogo = (props: SVGProps<SVGSVGElement>) => (\n  <svg viewBox=\"0 0 122.52 122.523\" aria-hidden=\"true\" {...props}>\n    <g fill=\"#21759b\">\n      <path d=\"m8.708 61.26c0 20.802 12.089 38.779 29.619 47.298l-25.069-68.686c-2.916 6.536-4.55 13.769-4.55 21.388z\" />\n      <path d=\"m96.74 58.608c0-6.495-2.333-10.993-4.334-14.494-2.664-4.329-5.161-7.995-5.161-12.324 0-4.831 3.664-9.328 8.825-9.328.233 0 .454.029.681.042-9.35-8.566-21.807-13.796-35.489-13.796-18.36 0-34.513 9.42-43.91 23.688 1.233.037 2.395.063 3.382.063 5.497 0 14.006-.667 14.006-.667 2.833-.167 3.167 3.994.337 4.329 0 0-2.847.335-6.015.501l19.138 56.925 11.501-34.493-8.188-22.434c-2.83-.166-5.511-.501-5.511-.501-2.832-.166-2.5-4.496.332-4.329 0 0 8.679.667 13.843.667 5.496 0 14.006-.667 14.006-.667 2.835-.167 3.168 3.994.337 4.329 0 0-2.853.335-6.015.501l18.992 56.494 5.242-17.517c2.272-7.269 4.001-12.49 4.001-16.989z\" />\n      <path d=\"m62.184 65.857-15.768 45.819c4.708 1.384 9.687 2.141 14.846 2.141 6.12 0 11.989-1.058 17.452-2.979-.141-.225-.269-.464-.374-.724z\" />\n      <path d=\"m107.376 36.046c.226 1.674.354 3.471.354 5.404 0 5.333-.996 11.328-3.996 18.824l-16.053 46.413c15.624-9.111 26.133-26.038 26.133-45.426.001-9.137-2.333-17.729-6.438-25.215z\" />\n      <path d=\"m61.262 0c-33.779 0-61.262 27.481-61.262 61.26 0 33.783 27.483 61.263 61.262 61.263 33.778 0 61.265-27.48 61.265-61.263-.001-33.779-27.487-61.26-61.265-61.26zm0 119.715c-32.23 0-58.453-26.223-58.453-58.455 0-32.23 26.222-58.451 58.453-58.451 32.229 0 58.45 26.221 58.45 58.451 0 32.232-26.221 58.455-58.45 58.455z\" />\n    </g>\n  </svg>\n);\n\nexport const LinearLogo = (props: SVGProps<SVGSVGElement>) => (\n  <svg viewBox=\"0 0 100 100\" fill=\"none\" aria-hidden=\"true\" {...props}>\n    <path\n      fill=\"#5E6AD2\"\n      d=\"M1.225 61.523c-.222-.949.908-1.546 1.597-.857l36.512 36.512c.69.69.092 1.82-.857 1.597-18.425-4.323-32.93-18.827-37.252-37.252ZM.002 46.889a.99.99 0 0 0 .29.76L52.35 99.71c.201.2.478.307.76.29 2.37-.149 4.695-.46 6.963-.927.765-.157 1.03-1.096.478-1.648L2.576 39.448c-.552-.551-1.491-.286-1.648.479a50.067 50.067 0 0 0-.926 6.962ZM4.21 29.705a.988.988 0 0 0 .208 1.1l64.776 64.776c.289.29.726.375 1.1.208a49.908 49.908 0 0 0 5.185-2.684.981.981 0 0 0 .183-1.54L8.436 24.336a.981.981 0 0 0-1.541.183 49.896 49.896 0 0 0-2.684 5.185Zm8.448-11.631a.986.986 0 0 1-.045-1.354C21.78 6.46 35.111 0 49.952 0 77.592 0 100 22.407 100 50.048c0 14.84-6.46 28.172-16.72 37.338a.986.986 0 0 1-1.354-.045L12.659 18.074Z\"\n    />\n  </svg>\n);\n\nexport const GitHubLogo = (props: SVGProps<SVGSVGElement>) => (\n  <svg\n    viewBox=\"0 0 1024 1024\"\n    fill=\"currentColor\"\n    aria-hidden=\"true\"\n    {...props}\n  >\n    <path\n      fillRule=\"evenodd\"\n      d=\"M512 0C229.12 0 0 229.12 0 512c0 226.56 146.56 417.92 350.08 485.76 25.6 4.48 35.2-10.88 35.2-24.32 0-12.16-.64-52.48-.64-95.36-128.64 23.68-161.92-31.36-172.16-60.16-5.76-14.72-30.72-60.16-52.48-72.32-17.92-9.6-43.52-33.28-.64-33.92 40.32-.64 69.12 37.12 78.72 52.48 46.08 77.44 119.68 55.68 149.12 42.24 4.48-33.28 17.92-55.68 32.64-68.48-113.92-12.8-232.96-56.96-232.96-252.8 0-55.68 19.84-101.76 52.48-137.6-5.12-12.8-23.04-65.28 5.12-135.68 0 0 42.88-13.44 140.8 52.48 40.96-11.52 84.48-17.28 128-17.28s87.04 5.76 128 17.28c97.92-66.56 140.8-52.48 140.8-52.48 28.16 70.4 10.24 122.88 5.12 135.68 32.64 35.84 52.48 81.28 52.48 137.6 0 196.48-119.68 240-233.6 252.8 18.56 16 34.56 46.72 34.56 94.72 0 68.48-.64 123.52-.64 140.8 0 13.44 9.6 29.44 35.2 24.32C877.44 929.92 1024 737.92 1024 512 1024 229.12 794.88 0 512 0\"\n      clipRule=\"evenodd\"\n    />\n  </svg>\n);\n\nexport const AhrefsLogo = (props: SVGProps<SVGSVGElement>) => (\n  <svg viewBox=\"16 8 96 112\" fill=\"none\" aria-hidden=\"true\" {...props}>\n    <path\n      d=\"m24 8v24h64v16l-26.104 0.456c-35.096 3.256-45.896 11.624-45.896 36.504v6.512c0 19.064 14.328 28.528 32 28.528 7.984 0 16.32-1.56 25.04-5.976l14.96-6.024v12h24v-112zm64 76-18.112 7.472c-6.296 3.488-12.832 5.344-17.92 5.344-6.288 0-11.968-1.136-11.968-8.816v-5.12c0.48-8.136 7.376-11.176 26.256-13.032l21.744-1.848z\"\n      fill=\"#f80\"\n    />\n  </svg>\n);\n\nexport const PostHogLogo = (props: SVGProps<SVGSVGElement>) => (\n  <svg viewBox=\"0 2.41 47.99 26.58\" fill=\"none\" aria-hidden=\"true\" {...props}>\n    <path\n      fill=\"#1D4AFF\"\n      d=\"M10.891 17.206a1 1 0 0 1-1.788 0l-.882-1.763a1 1 0 0 1 0-.894l.882-1.763a1 1 0 0 1 1.788 0l.882 1.763a1 1 0 0 1 0 .894l-.882 1.763zm0 9.997a1 1 0 0 1-1.788 0L8.22 25.44a1 1 0 0 1 0-.894l.882-1.763a1 1 0 0 1 1.788 0l.882 1.763a1 1 0 0 1 0 .894l-.882 1.763z\"\n    />\n    <path\n      fill=\"#F9BD2B\"\n      d=\"M0 23.408c0-.89 1.077-1.337 1.707-.707l4.583 4.583c.63.63.184 1.708-.707 1.708H1a1 1 0 0 1-1-1v-4.584zm0-4.828a1 1 0 0 0 .293.708l9.411 9.41a1 1 0 0 0 .707.294h5.17c.89 0 1.337-1.077.707-1.707l-14.58-14.58C1.077 12.074 0 12.52 0 13.41v5.17zm0-9.997a1 1 0 0 0 .293.707L19.7 28.7a1 1 0 0 0 .707.293h5.17c.89 0 1.337-1.078.707-1.708L1.707 2.707C1.077 2.077 0 2.523 0 3.414v5.17zm9.997 0a1 1 0 0 0 .293.707l17.994 17.995c.63.63 1.707.183 1.707-.708v-5.169a1 1 0 0 0-.293-.707L11.704 2.707c-.63-.63-1.707-.184-1.707.707v5.17zm11.704-5.876c-.63-.63-1.707-.184-1.707.707v5.17a1 1 0 0 0 .293.706l7.997 7.998c.63.63 1.707.183 1.707-.708v-5.169a1 1 0 0 0-.293-.707l-7.997-7.997z\"\n    />\n    <path\n      fill=\"#000\"\n      d=\"m42.525 23.53-9.413-9.412c-.63-.63-1.707-.184-1.707.707v13.167a1 1 0 0 0 1 1h14.58a1 1 0 0 0 1-1v-1.2c0-.552-.449-.993-.997-1.064a7.723 7.723 0 0 1-4.463-2.197zm-6.321 2.263a1.6 1.6 0 1 1 0-3.2 1.6 1.6 0 0 1 0 3.2z\"\n    />\n    <path\n      fill=\"#1D4AFF\"\n      d=\"M0 27.992a1 1 0 0 0 1 1h4.583c.891 0 1.337-1.078.707-1.708l-4.583-4.583c-.63-.63-1.707-.184-1.707.707v4.584zm9.997-16.995-8.29-8.29C1.077 2.077 0 2.523 0 3.414v5.17a1 1 0 0 0 .293.706l9.704 9.705v-7.998zm-8.29 1.707c-.63-.63-1.707-.184-1.707.707v5.17a1 1 0 0 0 .293.706l9.704 9.705v-7.998l-8.29-8.29z\"\n    />\n    <path\n      fill=\"#F54E00\"\n      d=\"M19.994 11.411a1 1 0 0 0-.293-.707l-7.997-7.997c-.63-.63-1.707-.184-1.707.707v5.17a1 1 0 0 0 .293.706l9.704 9.705V11.41zm-9.997 17.58h5.583c.891 0 1.337-1.077.707-1.707l-6.29-6.29v7.998zm0-17.994v7.583a1 1 0 0 0 .293.708l9.704 9.704v-7.584a1 1 0 0 0-.293-.707l-9.704-9.704z\"\n    />\n  </svg>\n);\n",
      "type": "registry:component",
      "target": "components/workflow/components/workflow-logos.tsx"
    },
    {
      "path": "registry/notra/workflow/components/workflow-model-select.tsx",
      "content": "\"use client\";\n\nimport { cn } from \"cn\";\n\nimport {\n  Select,\n  SelectContent,\n  SelectItem,\n  SelectTrigger,\n  SelectValue,\n} from \"../../select/components/select\";\nimport { WORKFLOW_MODELS } from \"../constants/workflow\";\nimport type { WorkflowModelSelectProps } from \"../types/workflow\";\nimport { WorkflowLogo } from \"./workflow-logo\";\n\nexport const WorkflowModelSelect = ({\n  className,\n  defaultValue,\n  disabled,\n  id,\n  models = WORKFLOW_MODELS,\n  onValueChange,\n  value,\n}: WorkflowModelSelectProps) => (\n  <Select\n    defaultValue={defaultValue}\n    disabled={disabled}\n    onValueChange={(next) => {\n      if (typeof next === \"string\") {\n        onValueChange?.(next);\n      }\n    }}\n    value={value}\n  >\n    <SelectTrigger\n      className={cn(\"w-full\", className)}\n      data-slot=\"workflow-model-select\"\n      id={id}\n    >\n      <SelectValue>\n        {(current: string | null) => {\n          const model = models.find((item) => item.id === current);\n          return model ? (\n            <span className=\"flex items-center gap-2\">\n              <WorkflowLogo className=\"size-3.5\" name={model.logo} />\n              {model.label}\n            </span>\n          ) : (\n            \"Choose a model\"\n          );\n        }}\n      </SelectValue>\n    </SelectTrigger>\n    <SelectContent>\n      {models.map((model) => (\n        <SelectItem key={model.id} value={model.id}>\n          <WorkflowLogo className=\"size-3.5\" name={model.logo} />\n          {model.label}\n          <span className=\"text-muted-foreground ml-auto pl-3 text-xs\">\n            {model.provider}\n          </span>\n        </SelectItem>\n      ))}\n    </SelectContent>\n  </Select>\n);\n",
      "type": "registry:component",
      "target": "components/workflow/components/workflow-model-select.tsx"
    },
    {
      "path": "registry/notra/workflow/components/workflow-node-sheet.tsx",
      "content": "\"use client\";\n\nimport { Trash2Icon } from \"lucide-react\";\n\nimport { Button } from \"@/components/ui/button\";\nimport {\n  Sheet,\n  SheetContent,\n  SheetDescription,\n  SheetFooter,\n  SheetHeader,\n  SheetTitle,\n} from \"@/components/ui/sheet\";\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from \"@/components/ui/tabs\";\n\nimport {\n  Select,\n  SelectContent,\n  SelectItem,\n  SelectTrigger,\n  SelectValue,\n} from \"../../select/components/select\";\nimport { WORKFLOW_KINDS } from \"../constants/workflow\";\nimport { WORKFLOW_SECTION_TITLE_CLASS } from \"../constants/workflow-ui\";\nimport {\n  getInputPorts,\n  getOutputPorts,\n  isDeterministic,\n} from \"../lib/workflow\";\nimport type {\n  WorkflowBranchSelectProps,\n  WorkflowNodeSettingsProps,\n  WorkflowNodeSheetProps,\n  WorkflowPortListProps,\n} from \"../types/workflow\";\nimport { WorkflowBlockIcon } from \"./workflow-block-icon\";\nimport { WorkflowModelSelect } from \"./workflow-model-select\";\nimport { WorkflowRunLog } from \"./workflow-run-log\";\nimport {\n  WorkflowDeterminismBadge,\n  WorkflowStatusBadge,\n} from \"./workflow-status\";\nimport { WorkflowTimer } from \"./workflow-timer\";\n\nconst PortList = ({ ports, title }: WorkflowPortListProps) =>\n  ports.some((port) => port.label) ? (\n    <div className=\"flex flex-col gap-1.5\">\n      <h3 className={WORKFLOW_SECTION_TITLE_CLASS}>{title}</h3>\n      <div className=\"flex flex-wrap gap-1.5\">\n        {ports.map((port) => (\n          <span\n            className=\"bg-muted max-w-full truncate rounded-md px-2 py-0.5 font-mono text-[0.6875rem]\"\n            key={port.id}\n          >\n            {port.label ?? port.id}\n          </span>\n        ))}\n      </div>\n    </div>\n  ) : null;\n\nconst WorkflowBranchSelect = ({\n  node,\n  onBranchChange,\n  outputs,\n}: WorkflowBranchSelectProps) =>\n  outputs.length > 1 ? (\n    <div className=\"flex flex-col gap-1.5\">\n      <label\n        className=\"text-sm leading-none font-medium\"\n        htmlFor={`${node.id}-branch`}\n      >\n        Path to follow\n      </label>\n      <Select\n        onValueChange={(branch) => {\n          if (typeof branch === \"string\") {\n            onBranchChange(node.id, branch);\n          }\n        }}\n        value={node.branch ?? outputs[0]?.id}\n      >\n        <SelectTrigger className=\"w-full\" id={`${node.id}-branch`}>\n          <SelectValue>\n            {(value: string | null) =>\n              outputs.find((port) => port.id === value)?.label ?? value\n            }\n          </SelectValue>\n        </SelectTrigger>\n        <SelectContent>\n          {outputs.map((port) => (\n            <SelectItem key={port.id} value={port.id}>\n              {port.label ?? port.id}\n            </SelectItem>\n          ))}\n        </SelectContent>\n      </Select>\n      <p className=\"text-muted-foreground text-xs\">\n        The preview run follows this path and skips the others.\n      </p>\n    </div>\n  ) : null;\n\nconst WorkflowNodeSettings = ({\n  node,\n  onBranchChange,\n  onModelChange,\n}: WorkflowNodeSettingsProps) => {\n  const outputs = getOutputPorts(node);\n  return (\n    <>\n      {node.description && (\n        <p className=\"text-muted-foreground text-sm\">{node.description}</p>\n      )}\n      {node.kind === \"ai\" && onModelChange && (\n        <div className=\"flex flex-col gap-1.5\">\n          <label\n            className=\"text-sm leading-none font-medium\"\n            htmlFor={`${node.id}-model`}\n          >\n            Model\n          </label>\n          <WorkflowModelSelect\n            id={`${node.id}-model`}\n            onValueChange={(model) => onModelChange(node.id, model)}\n            value={node.model}\n          />\n          <p className=\"text-muted-foreground text-xs\">\n            The same input can give a different answer on each run. Keep the\n            temperature low for classification.\n          </p>\n        </div>\n      )}\n      {onBranchChange && (\n        <WorkflowBranchSelect\n          node={node}\n          onBranchChange={onBranchChange}\n          outputs={outputs}\n        />\n      )}\n      {node.fields && node.fields.length > 0 && (\n        <dl className=\"border-table-card-border bg-table-card divide-table-row-border divide-y rounded-xl border text-[0.8125rem]\">\n          {node.fields.map((field) => (\n            <div\n              className=\"grid grid-cols-1 gap-1 px-3 py-2 sm:grid-cols-[8rem_minmax(0,1fr)] sm:gap-3\"\n              key={field.label}\n            >\n              <dt className=\"text-muted-foreground\">{field.label}</dt>\n              <dd className=\"font-mono text-xs leading-5 break-words\">\n                {field.value}\n              </dd>\n            </div>\n          ))}\n        </dl>\n      )}\n      <PortList ports={getInputPorts(node)} title=\"Inputs\" />\n      <PortList ports={outputs} title=\"Outputs\" />\n    </>\n  );\n};\n\nexport const WorkflowNodeSheet = ({\n  log = [],\n  node,\n  onBranchChange,\n  onDelete,\n  onModelChange,\n  state,\n  ...props\n}: WorkflowNodeSheetProps) => {\n  const status = state?.status ?? \"idle\";\n  const nodeLog = node ? log.filter((entry) => entry.nodeId === node.id) : [];\n\n  return (\n    <Sheet {...props}>\n      <SheetContent\n        className=\"gap-0 sm:max-w-md\"\n        data-slot=\"workflow-node-sheet\"\n      >\n        {node && (\n          <>\n            <SheetHeader className=\"border-foreground/10 gap-3 border-b p-4\">\n              <div className=\"flex items-center gap-3 pr-8\">\n                <WorkflowBlockIcon\n                  block={node}\n                  className=\"size-9 rounded-lg [&_svg]:size-4.5\"\n                />\n                <div className=\"flex min-w-0 flex-col\">\n                  <SheetTitle className=\"truncate\">{node.title}</SheetTitle>\n                  <SheetDescription className=\"text-xs\">\n                    {WORKFLOW_KINDS[node.kind].label}\n                  </SheetDescription>\n                </div>\n              </div>\n              <div className=\"flex flex-wrap items-center gap-1.5\">\n                <WorkflowStatusBadge status={status} />\n                <WorkflowDeterminismBadge\n                  deterministic={isDeterministic(node)}\n                />\n                {state && state.elapsedMs > 0 && (\n                  <WorkflowTimer\n                    className=\"ml-auto\"\n                    ms={state.elapsedMs}\n                    running={status === \"running\" || status === \"waiting\"}\n                  />\n                )}\n              </div>\n            </SheetHeader>\n            <Tabs className=\"min-h-0 flex-1 gap-0\" defaultValue=\"settings\">\n              <TabsList className=\"mx-4 mt-3 w-[calc(100%-2rem)]\">\n                <TabsTrigger value=\"settings\">Settings</TabsTrigger>\n                <TabsTrigger value=\"run\">Run</TabsTrigger>\n                <TabsTrigger value=\"output\">Output</TabsTrigger>\n              </TabsList>\n              <TabsContent\n                className=\"flex flex-col gap-5 overflow-y-auto p-4\"\n                value=\"settings\"\n              >\n                <WorkflowNodeSettings\n                  node={node}\n                  onBranchChange={onBranchChange}\n                  onModelChange={onModelChange}\n                />\n              </TabsContent>\n              <TabsContent className=\"overflow-y-auto py-3\" value=\"run\">\n                <WorkflowRunLog\n                  emptyLabel=\"This step hasn't run yet.\"\n                  entries={nodeLog}\n                />\n              </TabsContent>\n              <TabsContent className=\"overflow-y-auto p-4\" value=\"output\">\n                {node.output && status === \"success\" ? (\n                  <pre className=\"bg-muted overflow-x-auto rounded-lg p-3 font-mono text-xs leading-5\">\n                    {node.output}\n                  </pre>\n                ) : (\n                  <p className=\"text-muted-foreground text-xs\">\n                    {node.output\n                      ? \"The output shows up when this step completes.\"\n                      : \"This step has no output to show.\"}\n                  </p>\n                )}\n              </TabsContent>\n            </Tabs>\n            {onDelete && (\n              <SheetFooter className=\"border-foreground/10 border-t p-3\">\n                <Button onClick={() => onDelete(node.id)} variant=\"outline\">\n                  <Trash2Icon data-icon=\"inline-start\" />\n                  Delete step\n                </Button>\n              </SheetFooter>\n            )}\n          </>\n        )}\n      </SheetContent>\n    </Sheet>\n  );\n};\n",
      "type": "registry:component",
      "target": "components/workflow/components/workflow-node-sheet.tsx"
    },
    {
      "path": "registry/notra/workflow/components/workflow-run-log.tsx",
      "content": "import { cn } from \"cn\";\n\nimport { formatClock } from \"../lib/workflow\";\nimport type { WorkflowLogLevel, WorkflowRunLogProps } from \"../types/workflow\";\n\nconst LEVEL_CLASS: Record<WorkflowLogLevel, string> = {\n  error: \"bg-red-500\",\n  info: \"bg-primary\",\n  skip: \"bg-muted-foreground/40\",\n  success: \"bg-emerald-500\",\n};\n\nexport const WorkflowRunLog = ({\n  className,\n  emptyLabel = \"Run the workflow to see its log.\",\n  entries,\n  ...props\n}: WorkflowRunLogProps) => (\n  <div\n    className={cn(\n      \"flex flex-col font-mono text-[0.75rem] leading-5\",\n      className\n    )}\n    data-slot=\"workflow-run-log\"\n    role=\"log\"\n    {...props}\n  >\n    {entries.length === 0 ? (\n      <p className=\"text-muted-foreground px-3 py-4 font-sans text-xs\">\n        {emptyLabel}\n      </p>\n    ) : (\n      entries.map((entry) => (\n        <div\n          className=\"hover:bg-muted/60 motion-safe:animate-in motion-safe:fade-in-0 grid grid-cols-[4.5rem_0.5rem_minmax(0,1fr)] items-baseline gap-2.5 px-3 py-0.5\"\n          data-level={entry.level}\n          data-slot=\"workflow-run-log-entry\"\n          key={entry.id}\n        >\n          <span className=\"text-muted-foreground tabular-nums\">\n            {formatClock(entry.at)}\n          </span>\n          <span\n            aria-hidden=\"true\"\n            className={cn(\n              \"size-1.5 self-center rounded-full\",\n              LEVEL_CLASS[entry.level]\n            )}\n          />\n          <span className=\"min-w-0 break-words\">\n            <span className=\"text-foreground font-medium\">{entry.title}</span>\n            <span\n              className={cn(\n                \"text-muted-foreground\",\n                entry.level === \"error\" && \"text-red-600 dark:text-red-400\"\n              )}\n            >\n              {\" \"}\n              {entry.message}\n            </span>\n          </span>\n        </div>\n      ))\n    )}\n  </div>\n);\n",
      "type": "registry:component",
      "target": "components/workflow/components/workflow-run-log.tsx"
    },
    {
      "path": "registry/notra/workflow/components/workflow-status.tsx",
      "content": "import { cn } from \"cn\";\nimport {\n  CheckIcon,\n  CircleDashedIcon,\n  CircleIcon,\n  DicesIcon,\n  HourglassIcon,\n  LoaderCircleIcon,\n  MinusIcon,\n  RulerIcon,\n  XIcon,\n} from \"lucide-react\";\n\nimport { Badge } from \"@/components/ui/badge\";\n\nimport { WORKFLOW_STATUSES } from \"../constants/workflow\";\nimport {\n  WORKFLOW_LED_CLASS,\n  WORKFLOW_PILL_BOTTOM_CLASS,\n  WORKFLOW_PILL_CLASS,\n  WORKFLOW_PILL_TOP_CLASS,\n} from \"../constants/workflow-ui\";\nimport type {\n  WorkflowDeterminismBadgeProps,\n  WorkflowStatusBadgeProps,\n  WorkflowStatusGlyphProps,\n  WorkflowStatusIndicatorProps,\n  WorkflowStatusPillProps,\n} from \"../types/workflow\";\n\nconst StatusGlyph = ({ status }: WorkflowStatusGlyphProps) => {\n  switch (status) {\n    case \"running\": {\n      return <LoaderCircleIcon className=\"size-3.5 animate-spin\" />;\n    }\n    case \"waiting\": {\n      return <HourglassIcon className=\"size-3.5 motion-safe:animate-pulse\" />;\n    }\n    case \"success\": {\n      return <CheckIcon className=\"size-3.5\" strokeWidth={2.5} />;\n    }\n    case \"error\": {\n      return <XIcon className=\"size-3.5\" strokeWidth={2.5} />;\n    }\n    case \"skipped\": {\n      return <MinusIcon className=\"size-3.5\" />;\n    }\n    case \"queued\": {\n      return <CircleDashedIcon className=\"size-3.5\" />;\n    }\n    default: {\n      return <CircleIcon className=\"size-3.5\" />;\n    }\n  }\n};\n\nexport const WorkflowStatusIndicator = ({\n  className,\n  status,\n  ...props\n}: WorkflowStatusIndicatorProps) => (\n  <span\n    className={cn(\n      \"inline-flex size-4 shrink-0 items-center justify-center\",\n      WORKFLOW_STATUSES[status].className,\n      className\n    )}\n    data-slot=\"workflow-status-indicator\"\n    data-status={status}\n    {...props}\n  >\n    <StatusGlyph status={status} />\n    <span className=\"sr-only\">{WORKFLOW_STATUSES[status].label}</span>\n  </span>\n);\n\nexport const WorkflowStatusBadge = ({\n  className,\n  status,\n  ...props\n}: WorkflowStatusBadgeProps) => (\n  <Badge\n    className={cn(\"gap-1 pl-1\", WORKFLOW_STATUSES[status].className, className)}\n    data-slot=\"workflow-status-badge\"\n    data-status={status}\n    variant=\"outline\"\n    {...props}\n  >\n    <StatusGlyph status={status} />\n    {WORKFLOW_STATUSES[status].label}\n  </Badge>\n);\n\nexport const WorkflowDeterminismBadge = ({\n  className,\n  deterministic,\n  ...props\n}: WorkflowDeterminismBadgeProps) => (\n  <Badge\n    className={cn(\n      \"text-muted-foreground gap-1 font-normal\",\n      !deterministic &&\n        \"border-violet-500/30 text-violet-600 dark:text-violet-300\",\n      className\n    )}\n    data-slot=\"workflow-determinism-badge\"\n    title={\n      deterministic\n        ? \"Same input, same output\"\n        : \"Uses a language model, so the output can change between runs\"\n    }\n    variant=\"outline\"\n    {...props}\n  >\n    {deterministic ? <RulerIcon /> : <DicesIcon />}\n    {deterministic ? \"Deterministic\" : \"Non-deterministic\"}\n  </Badge>\n);\n\nexport const WorkflowStatusPill = ({\n  className,\n  status,\n  ...props\n}: WorkflowStatusPillProps) => (\n  <span\n    className={cn(WORKFLOW_PILL_CLASS, className)}\n    data-slot=\"workflow-status-pill\"\n    data-status={status}\n    title={WORKFLOW_STATUSES[status].label}\n    {...props}\n  >\n    <span className={WORKFLOW_PILL_TOP_CLASS}>\n      <span\n        className={cn(\n          WORKFLOW_LED_CLASS,\n          WORKFLOW_STATUSES[status].ledClassName\n        )}\n      />\n    </span>\n    {status !== \"idle\" && (\n      <span className={WORKFLOW_PILL_BOTTOM_CLASS}>\n        <StatusGlyph status={status} />\n      </span>\n    )}\n    <span className=\"sr-only\">{WORKFLOW_STATUSES[status].label}</span>\n  </span>\n);\n",
      "type": "registry:component",
      "target": "components/workflow/components/workflow-status.tsx"
    },
    {
      "path": "registry/notra/workflow/components/workflow-timer.tsx",
      "content": "import { cn } from \"cn\";\n\nimport { formatDuration } from \"../lib/workflow\";\nimport type { WorkflowTimerProps } from \"../types/workflow\";\n\nexport const WorkflowTimer = ({\n  className,\n  ms,\n  running,\n  ...props\n}: WorkflowTimerProps) => (\n  <span\n    className={cn(\n      \"text-muted-foreground inline-flex items-center gap-1 font-mono text-[0.6875rem] leading-4 tabular-nums\",\n      running && \"text-foreground\",\n      className\n    )}\n    data-running={running || undefined}\n    data-slot=\"workflow-timer\"\n    {...props}\n  >\n    {running && (\n      <span\n        aria-hidden=\"true\"\n        className=\"bg-primary size-1.5 rounded-full motion-safe:animate-pulse\"\n      />\n    )}\n    <time dateTime={`PT${(ms / 1000).toFixed(1)}S`}>{formatDuration(ms)}</time>\n  </span>\n);\n",
      "type": "registry:component",
      "target": "components/workflow/components/workflow-timer.tsx"
    },
    {
      "path": "registry/notra/workflow/constants/workflow-ui.ts",
      "content": "import type {\n  WorkflowBannerConfig,\n  WorkflowEdgeStatus,\n  WorkflowRunPhase,\n} from \"../types/workflow\";\n\nexport const WORKFLOW_NODE_WIDTH = 256;\n\nexport const WORKFLOW_NODE_DROP_OFFSET_Y = 24;\n\nexport const WORKFLOW_COLUMN = 320;\n\nexport const WORKFLOW_FIT_PADDING = 0.12;\n\nexport const WORKFLOW_FIT_MIN_ZOOM = 0.6;\n\nexport const WORKFLOW_FIT_MAX_ZOOM = 1;\n\nexport const WORKFLOW_FIT_EDGE_PX = 32;\n\nexport const WORKFLOW_FIT_VIEW_OPTIONS = {\n  maxZoom: WORKFLOW_FIT_MAX_ZOOM,\n  padding: WORKFLOW_FIT_PADDING,\n};\n\nexport const WORKFLOW_ZOOM_DURATION_MS = 200;\n\nexport const WORKFLOW_FIT_DURATION_MS = 300;\n\nexport const WORKFLOW_MINIMAP_STYLE = { height: 96, width: 144 };\n\nexport const WORKFLOW_PATTERN_STRENGTH = {\n  cross: 22,\n  dots: 24,\n  gridMajor: 12,\n  gridMinor: 5,\n  lines: 7,\n};\n\nexport const WORKFLOW_PORT_ROW_CLASS =\n  \"text-muted-foreground border-table-card-border relative flex h-7.5 min-w-0 items-center border-t px-3 text-[0.6875rem] font-medium\";\n\nexport const WORKFLOW_CHIP_CLASS =\n  \"bg-foreground/[0.05] text-muted-foreground inline-flex h-5 min-w-0 items-center gap-1 rounded-full px-2 text-[0.6875rem] leading-none tabular-nums [&_svg]:size-3 [&_svg]:shrink-0\";\n\nexport const WORKFLOW_BANNERS: Record<\n  \"error\" | \"waiting\",\n  WorkflowBannerConfig\n> = {\n  error: {\n    className: \"text-red-600 dark:text-red-400\",\n    label: \"Failed\",\n    message: \"Check the run log\",\n  },\n  waiting: {\n    className: \"text-amber-600 dark:text-amber-400\",\n    label: \"Waiting\",\n    message: \"Needs approval\",\n  },\n};\n\nexport const WORKFLOW_PILL_CLASS =\n  \"bg-table-shell border-table-shell-border text-muted-foreground inline-flex h-9 w-7 shrink-0 flex-col overflow-hidden rounded-lg border [&_svg]:size-3\";\n\nexport const WORKFLOW_PILL_TOP_CLASS =\n  \"flex flex-1 items-center justify-center\";\n\nexport const WORKFLOW_PILL_BOTTOM_CLASS =\n  \"border-table-shell-border flex flex-1 items-center justify-center border-t\";\n\nexport const WORKFLOW_LED_CLASS =\n  \"ring-background/60 size-1.5 rounded-full ring-2 transition-colors duration-300\";\n\nexport const WORKFLOW_EDGE_COLOR: Record<WorkflowEdgeStatus, string> = {\n  active: \"text-primary\",\n  done: \"text-primary/70\",\n  idle: \"text-muted-foreground/70\",\n  skipped: \"text-muted-foreground/25\",\n};\n\nexport const WORKFLOW_EDGE_DASH = \"0 10\";\n\nexport const WORKFLOW_EDGE_STEP_OPTIONS = { borderRadius: 24, offset: 24 };\n\nexport const WORKFLOW_EDGE_RADIUS = 24;\n\nexport const WORKFLOW_EDGE_LANE_GAP = 16;\n\nexport const WORKFLOW_RUN_LABELS: Record<WorkflowRunPhase, string> = {\n  done: \"Run again\",\n  idle: \"Run workflow\",\n  running: \"Stop\",\n};\n\nexport const WORKFLOW_RUN_RING_RADIUS = 10;\n\nexport const WORKFLOW_RUN_RING_LENGTH = 2 * Math.PI * WORKFLOW_RUN_RING_RADIUS;\n\nexport const WORKFLOW_SECTION_TITLE_CLASS =\n  \"text-muted-foreground text-[0.6875rem] font-medium tracking-wide uppercase\";\n\nexport const WORKFLOW_EDGE_REVERSE_STYLE = { animationDirection: \"reverse\" };\n\nexport const WORKFLOW_SKIPPED_DIM_CLASS =\n  \"transition-opacity duration-300 group-data-[status=skipped]/node:opacity-45\";\n\nexport const WORKFLOW_BRANCH_RAIL_CLASS =\n  \"border-table-card-border bg-table-card/60 divide-table-card-border mt-0.5 divide-y rounded-[14px] border\";\n\nexport const WORKFLOW_BRANCH_ROW_CLASS =\n  \"relative flex h-10 min-w-0 items-center gap-2.5 px-3\";\n\nexport const WORKFLOW_BRANCH_LED_CLASS =\n  \"size-2 shrink-0 rounded-full ring-2 transition-[background-color,box-shadow,opacity] duration-300\";\n\nexport const WORKFLOW_RULE_TOKEN_CLASS =\n  \"bg-foreground/[0.05] text-foreground/80 inline-flex h-5 max-w-full min-w-0 items-center truncate rounded-md px-1.5 text-[0.6875rem] whitespace-nowrap\";\n",
      "type": "registry:lib",
      "target": "components/workflow/constants/workflow-ui.ts"
    },
    {
      "path": "registry/notra/workflow/constants/workflow.ts",
      "content": "import {\n  FlagIcon,\n  GitForkIcon,\n  HourglassIcon,\n  MailIcon,\n  MergeIcon,\n  PlugIcon,\n  RepeatIcon,\n  SparklesIcon,\n  SplitIcon,\n  SquareFunctionIcon,\n  UserCheckIcon,\n  ZapIcon,\n} from \"lucide-react\";\n\nimport type {\n  WorkflowKindConfig,\n  WorkflowModel,\n  WorkflowNodeKind,\n  WorkflowNodeStatus,\n  WorkflowPort,\n  WorkflowStatusConfig,\n} from \"../types/workflow\";\n\nexport const WORKFLOW_DEFAULT_DURATION_MS = 900;\n\nexport const WORKFLOW_EDGE_TRAVEL_MS = 450;\n\nexport const WORKFLOW_TICK_MS = 50;\n\nexport const WORKFLOW_BLOCK_MIME = \"application/x-workflow-block\";\n\nexport const WORKFLOW_IN_PORT: WorkflowPort = { id: \"in\" };\n\nexport const WORKFLOW_OUT_PORT: WorkflowPort = { id: \"out\" };\n\nexport const WORKFLOW_KINDS: Record<WorkflowNodeKind, WorkflowKindConfig> = {\n  ai: {\n    icon: SparklesIcon,\n    label: \"AI step\",\n    tileClassName:\n      \"bg-violet-500/10 text-violet-600 ring-violet-500/20 dark:text-violet-300\",\n  },\n  approval: {\n    icon: UserCheckIcon,\n    label: \"Human approval\",\n    tileClassName:\n      \"bg-pink-500/10 text-pink-600 ring-pink-500/20 dark:text-pink-300\",\n  },\n  condition: {\n    icon: SplitIcon,\n    label: \"If / else\",\n    tileClassName:\n      \"bg-orange-500/10 text-orange-600 ring-orange-500/20 dark:text-orange-300\",\n  },\n  delay: {\n    icon: HourglassIcon,\n    label: \"Wait\",\n    tileClassName:\n      \"bg-zinc-500/10 text-zinc-600 ring-zinc-500/20 dark:text-zinc-300\",\n  },\n  email: {\n    icon: MailIcon,\n    label: \"Email\",\n    tileClassName:\n      \"bg-emerald-500/10 text-emerald-600 ring-emerald-500/20 dark:text-emerald-300\",\n  },\n  integration: {\n    icon: PlugIcon,\n    label: \"Integration\",\n    tileClassName:\n      \"bg-sky-500/10 text-sky-600 ring-sky-500/20 dark:text-sky-300\",\n  },\n  loop: {\n    icon: RepeatIcon,\n    label: \"For each\",\n    tileClassName:\n      \"bg-indigo-500/10 text-indigo-600 ring-indigo-500/20 dark:text-indigo-300\",\n  },\n  merge: {\n    icon: MergeIcon,\n    label: \"Merge\",\n    tileClassName:\n      \"bg-teal-500/10 text-teal-600 ring-teal-500/20 dark:text-teal-300\",\n  },\n  output: {\n    icon: FlagIcon,\n    label: \"Output\",\n    tileClassName:\n      \"bg-zinc-500/10 text-zinc-600 ring-zinc-500/20 dark:text-zinc-300\",\n  },\n  switch: {\n    icon: GitForkIcon,\n    label: \"Decision\",\n    tileClassName:\n      \"bg-orange-500/10 text-orange-600 ring-orange-500/20 dark:text-orange-300\",\n  },\n  task: {\n    icon: SquareFunctionIcon,\n    label: \"Task\",\n    tileClassName:\n      \"bg-blue-500/10 text-blue-600 ring-blue-500/20 dark:text-blue-300\",\n  },\n  trigger: {\n    icon: ZapIcon,\n    label: \"Trigger\",\n    tileClassName:\n      \"bg-amber-500/10 text-amber-600 ring-amber-500/20 dark:text-amber-300\",\n  },\n};\n\nexport const WORKFLOW_NON_DETERMINISTIC_KINDS: WorkflowNodeKind[] = [\"ai\"];\n\nexport const WORKFLOW_STATUSES: Record<\n  WorkflowNodeStatus,\n  WorkflowStatusConfig\n> = {\n  error: {\n    className: \"text-red-600 dark:text-red-400\",\n    label: \"Failed\",\n    ledClassName: \"bg-red-500 shadow-[0_0_6px_var(--color-red-500)]\",\n  },\n  idle: {\n    className: \"text-muted-foreground\",\n    label: \"Idle\",\n    ledClassName: \"bg-muted-foreground/35\",\n  },\n  queued: {\n    className: \"text-muted-foreground\",\n    label: \"Queued\",\n    ledClassName: \"bg-muted-foreground/35\",\n  },\n  running: {\n    className: \"text-primary\",\n    label: \"Running\",\n    ledClassName:\n      \"bg-primary shadow-[0_0_6px_var(--color-primary,var(--primary))] motion-safe:animate-pulse\",\n  },\n  skipped: {\n    className: \"text-muted-foreground\",\n    label: \"Skipped\",\n    ledClassName: \"bg-muted-foreground/20\",\n  },\n  success: {\n    className: \"text-emerald-600 dark:text-emerald-400\",\n    label: \"Completed\",\n    ledClassName: \"bg-emerald-500 shadow-[0_0_6px_var(--color-emerald-500)]\",\n  },\n  waiting: {\n    className: \"text-amber-600 dark:text-amber-400\",\n    label: \"Waiting for approval\",\n    ledClassName:\n      \"bg-amber-500 shadow-[0_0_6px_var(--color-amber-500)] motion-safe:animate-pulse\",\n  },\n};\n\nexport const WORKFLOW_NODE_RING: Record<WorkflowNodeStatus, string> = {\n  error: \"border-red-500/60\",\n  idle: \"\",\n  queued: \"\",\n  running:\n    \"border-primary shadow-[0_0_0_0.3rem_color-mix(in_oklab,var(--color-primary,var(--primary))_14%,transparent)]\",\n  skipped: \"\",\n  success: \"border-emerald-500/50\",\n  waiting:\n    \"border-amber-500 shadow-[0_0_0_0.3rem_color-mix(in_oklab,var(--color-amber-500)_14%,transparent)]\",\n};\n\nexport const WORKFLOW_MODELS: WorkflowModel[] = [\n  {\n    id: \"claude-opus-5-5\",\n    label: \"Claude Opus 5.5\",\n    logo: \"claude\",\n    provider: \"Anthropic\",\n  },\n  {\n    id: \"claude-sonnet-5-5\",\n    label: \"Claude Sonnet 5.5\",\n    logo: \"claude\",\n    provider: \"Anthropic\",\n  },\n  {\n    id: \"claude-haiku-5-5\",\n    label: \"Claude Haiku 5.5\",\n    logo: \"claude\",\n    provider: \"Anthropic\",\n  },\n  { id: \"gpt-5\", label: \"GPT-5\", logo: \"openai\", provider: \"OpenAI\" },\n  { id: \"gpt-5-mini\", label: \"GPT-5 mini\", logo: \"openai\", provider: \"OpenAI\" },\n  {\n    id: \"gemini-2-5-pro\",\n    label: \"Gemini 2.5 Pro\",\n    logo: \"gemini\",\n    provider: \"Google\",\n  },\n  {\n    id: \"sonar-pro\",\n    label: \"Sonar Pro\",\n    logo: \"perplexity\",\n    provider: \"Perplexity\",\n  },\n  { id: \"grok-4\", label: \"Grok 4\", logo: \"grok\", provider: \"xAI\" },\n  {\n    id: \"mistral-large\",\n    label: \"Mistral Large\",\n    logo: \"mistral\",\n    provider: \"Mistral\",\n  },\n  {\n    id: \"deepseek-v3\",\n    label: \"DeepSeek V3\",\n    logo: \"deepseek\",\n    provider: \"DeepSeek\",\n  },\n];\n",
      "type": "registry:lib",
      "target": "components/workflow/constants/workflow.ts"
    },
    {
      "path": "registry/notra/workflow/lib/workflow.ts",
      "content": "import { getSmoothStepPath } from \"@xyflow/react\";\nimport type { ReactFlowState } from \"@xyflow/react\";\n\nimport {\n  WORKFLOW_DEFAULT_DURATION_MS,\n  WORKFLOW_EDGE_TRAVEL_MS,\n  WORKFLOW_IN_PORT,\n  WORKFLOW_MODELS,\n  WORKFLOW_NON_DETERMINISTIC_KINDS,\n  WORKFLOW_OUT_PORT,\n} from \"../constants/workflow\";\nimport {\n  WORKFLOW_EDGE_LANE_GAP,\n  WORKFLOW_EDGE_RADIUS,\n  WORKFLOW_EDGE_STEP_OPTIONS,\n} from \"../constants/workflow-ui\";\nimport type {\n  WorkflowAnchor,\n  WorkflowBlock,\n  WorkflowEdgeData,\n  WorkflowEdgeLane,\n  WorkflowEdgeStatus,\n  WorkflowLogEntry,\n  WorkflowNodeData,\n  WorkflowNodeState,\n  WorkflowPoint,\n  WorkflowPort,\n  WorkflowRunPhase,\n  WorkflowSchedule,\n} from \"../types/workflow\";\n\nexport const getInputPorts = (node: WorkflowNodeData): WorkflowPort[] =>\n  node.inputs ?? (node.kind === \"trigger\" ? [] : [WORKFLOW_IN_PORT]);\n\nexport const getOutputPorts = (node: WorkflowNodeData): WorkflowPort[] =>\n  node.outputs ?? (node.kind === \"output\" ? [] : [WORKFLOW_OUT_PORT]);\n\nexport const isDeterministic = (node: Pick<WorkflowNodeData, \"kind\">) =>\n  !WORKFLOW_NON_DETERMINISTIC_KINDS.includes(node.kind);\n\nexport const findModel = (id?: string) =>\n  WORKFLOW_MODELS.find((model) => model.id === id);\n\nconst byPosition = (a: WorkflowNodeData, b: WorkflowNodeData) =>\n  a.position.x - b.position.x || a.position.y - b.position.y;\n\nexport const getRunOrder = (\n  nodes: WorkflowNodeData[],\n  edges: WorkflowEdgeData[]\n) => {\n  const indegree = new Map(nodes.map((node) => [node.id, 0]));\n  for (const edge of edges) {\n    if (indegree.has(edge.target) && indegree.has(edge.source)) {\n      indegree.set(edge.target, (indegree.get(edge.target) ?? 0) + 1);\n    }\n  }\n\n  const byId = new Map(nodes.map((node) => [node.id, node]));\n  const ready = nodes.filter((node) => indegree.get(node.id) === 0);\n  const order: string[] = [];\n  while (ready.length > 0) {\n    ready.sort(byPosition);\n    const node = ready.shift();\n    if (!node) {\n      break;\n    }\n    order.push(node.id);\n    for (const edge of edges) {\n      if (edge.source !== node.id) {\n        continue;\n      }\n      const left = (indegree.get(edge.target) ?? 0) - 1;\n      indegree.set(edge.target, left);\n      const target = byId.get(edge.target);\n      if (left === 0 && target) {\n        ready.push(target);\n      }\n    }\n  }\n\n  const ordered = new Set(order);\n  const rest = nodes.filter((node) => !ordered.has(node.id)).sort(byPosition);\n  return [...order, ...rest.map((node) => node.id)];\n};\n\nexport const scheduleRun = (\n  nodes: WorkflowNodeData[],\n  edges: WorkflowEdgeData[]\n): WorkflowSchedule => {\n  const order = getRunOrder(nodes, edges);\n  const schedule: WorkflowSchedule = {\n    edges: {},\n    nodes: {},\n    order,\n    totalMs: 0,\n  };\n\n  const byId = new Map(nodes.map((node) => [node.id, node]));\n  for (const id of order) {\n    const node = byId.get(id);\n    if (!node) {\n      continue;\n    }\n    const incoming = edges\n      .filter((edge) => edge.target === id)\n      .map((edge) => schedule.edges[edge.id])\n      .filter((run) => run !== undefined);\n    const taken = incoming.filter((run) => run.taken);\n    const settled = Math.max(0, ...incoming.map((run) => run.end));\n\n    if (incoming.length > 0 && taken.length === 0) {\n      schedule.nodes[id] = { end: settled, start: settled, status: \"skipped\" };\n    } else {\n      const start = Math.max(0, ...taken.map((run) => run.end));\n      schedule.nodes[id] = {\n        end: start + (node.durationMs ?? WORKFLOW_DEFAULT_DURATION_MS),\n        start,\n        status: node.fail ? \"error\" : \"success\",\n      };\n    }\n\n    const run = schedule.nodes[id];\n    for (const edge of edges.filter((item) => item.source === id)) {\n      const port = edge.sourcePort ?? WORKFLOW_OUT_PORT.id;\n      const isTaken =\n        run.status === \"success\" &&\n        (node.branch === undefined || node.branch === port);\n      schedule.edges[edge.id] = {\n        end: run.end + (isTaken ? WORKFLOW_EDGE_TRAVEL_MS : 0),\n        start: run.end,\n        taken: isTaken,\n      };\n    }\n    schedule.totalMs = Math.max(schedule.totalMs, run.end);\n  }\n\n  return schedule;\n};\n\nexport const getNodeState = (\n  node: WorkflowNodeData | undefined,\n  schedule: WorkflowSchedule,\n  phase: WorkflowRunPhase,\n  elapsedMs: number\n): WorkflowNodeState => {\n  const run = node ? schedule.nodes[node.id] : undefined;\n  if (!(node && run) || phase === \"idle\") {\n    return { elapsedMs: 0, status: \"idle\" };\n  }\n  if (elapsedMs < run.start) {\n    return { elapsedMs: 0, status: \"queued\" };\n  }\n  if (run.status === \"skipped\") {\n    return { elapsedMs: 0, status: \"skipped\" };\n  }\n  if (elapsedMs < run.end) {\n    return {\n      elapsedMs: elapsedMs - run.start,\n      status: node.kind === \"approval\" ? \"waiting\" : \"running\",\n    };\n  }\n  return { elapsedMs: run.end - run.start, status: run.status };\n};\n\nexport const getEdgeState = (\n  id: string,\n  schedule: WorkflowSchedule,\n  phase: WorkflowRunPhase,\n  elapsedMs: number\n): WorkflowEdgeStatus => {\n  const run = schedule.edges[id];\n  if (!run || phase === \"idle\" || elapsedMs < run.start) {\n    return \"idle\";\n  }\n  if (!run.taken) {\n    return \"skipped\";\n  }\n  return elapsedMs < run.end ? \"active\" : \"done\";\n};\n\nexport const formatDuration = (ms: number) => {\n  if (ms < 60_000) {\n    return `${(ms / 1000).toFixed(1)}s`;\n  }\n  if (ms < 3_600_000) {\n    const minutes = Math.floor(ms / 60_000);\n    const seconds = Math.floor((ms % 60_000) / 1000);\n    return `${minutes}m ${String(seconds).padStart(2, \"0\")}s`;\n  }\n  const hours = Math.floor(ms / 3_600_000);\n  const minutes = Math.floor((ms % 3_600_000) / 60_000);\n  return `${hours}h ${String(minutes).padStart(2, \"0\")}m`;\n};\n\nexport const formatRate = (rate: number) => `${Math.round(rate * 100)}%`;\n\nexport const formatClock = (ms: number) => {\n  const minutes = Math.floor(ms / 60_000);\n  const seconds = Math.floor((ms % 60_000) / 1000);\n  const tenths = Math.floor((ms % 1000) / 100);\n  return `${String(minutes).padStart(2, \"0\")}:${String(seconds).padStart(2, \"0\")}.${tenths}`;\n};\n\nconst branchLabel = (node: WorkflowNodeData) =>\n  getOutputPorts(node).find((port) => port.id === node.branch)?.label ??\n  node.branch;\n\nexport const getRunLog = (\n  nodes: WorkflowNodeData[],\n  schedule: WorkflowSchedule,\n  phase: WorkflowRunPhase,\n  elapsedMs: number\n): WorkflowLogEntry[] => {\n  if (phase === \"idle\") {\n    return [];\n  }\n  const entries: WorkflowLogEntry[] = [];\n  const byId = new Map(nodes.map((node) => [node.id, node]));\n  for (const id of schedule.order) {\n    const node = byId.get(id);\n    const run = schedule.nodes[id];\n    if (!(node && run) || elapsedMs < run.start) {\n      continue;\n    }\n    const base = { nodeId: id, title: node.title };\n    if (run.status === \"skipped\") {\n      entries.push({\n        ...base,\n        at: run.start,\n        id: `${id}:skip`,\n        level: \"skip\",\n        message: \"Skipped, no earlier step led here\",\n      });\n      continue;\n    }\n    entries.push({\n      ...base,\n      at: run.start,\n      id: `${id}:start`,\n      level: \"info\",\n      message: node.kind === \"approval\" ? \"Waiting for approval\" : \"Started\",\n    });\n    if (elapsedMs < run.end) {\n      continue;\n    }\n    const took = run.end - run.start;\n    let message = `Completed in ${formatDuration(took)}`;\n    if (run.status === \"error\") {\n      message = `Failed after ${formatDuration(took)}`;\n    } else if (node.branch !== undefined) {\n      message = `Took the \"${branchLabel(node)}\" branch`;\n    }\n    entries.push({\n      ...base,\n      at: run.end,\n      id: `${id}:end`,\n      level: run.status === \"error\" ? \"error\" : \"success\",\n      message,\n    });\n  }\n  return entries.sort((a, b) => a.at - b.at);\n};\n\nconst getEdgeMidX = (\n  from: WorkflowPoint,\n  to: WorkflowPoint,\n  radius: number,\n  offset: number\n) => {\n  const room = Math.max(0, Math.abs(to.x - from.x) / 2 - radius * 2);\n  return (from.x + to.x) / 2 + Math.max(-room, Math.min(room, offset));\n};\n\nexport const getEdgePath = (\n  from: WorkflowPoint,\n  to: WorkflowPoint,\n  radius = WORKFLOW_EDGE_RADIUS,\n  offset = 0\n) => {\n  const dx = to.x - from.x;\n  const dy = to.y - from.y;\n  const midX = getEdgeMidX(from, to, radius, offset);\n  const r = Math.min(\n    radius,\n    Math.abs(dy) / 2,\n    Math.abs(midX - from.x),\n    Math.abs(to.x - midX)\n  );\n  if (r < 0.5) {\n    return `M ${from.x} ${from.y} L ${to.x} ${to.y}`;\n  }\n  const sx = Math.sign(dx);\n  const sy = Math.sign(dy);\n  const sweep = sx * sy > 0 ? 1 : 0;\n  return [\n    `M ${from.x} ${from.y}`,\n    `L ${midX - sx * r} ${from.y}`,\n    `A ${r} ${r} 0 0 ${sweep} ${midX} ${from.y + sy * r}`,\n    `L ${midX} ${to.y - sy * r}`,\n    `A ${r} ${r} 0 0 ${1 - sweep} ${midX + sx * r} ${to.y}`,\n    `L ${to.x} ${to.y}`,\n  ].join(\" \");\n};\n\nexport const getFlowEdgePath = (\n  source: WorkflowAnchor,\n  target: WorkflowAnchor,\n  reverse = false,\n  offset = 0\n): [string, number, number] => {\n  const [from, to] = reverse ? [target, source] : [source, target];\n  if (target.x > source.x) {\n    return [\n      getEdgePath(from, to, WORKFLOW_EDGE_RADIUS, offset),\n      getEdgeMidX(from, to, WORKFLOW_EDGE_RADIUS, offset),\n      (source.y + target.y) / 2,\n    ];\n  }\n  const [path, labelX, labelY] = getSmoothStepPath({\n    ...WORKFLOW_EDGE_STEP_OPTIONS,\n    sourcePosition: from.position,\n    sourceX: from.x,\n    sourceY: from.y,\n    targetPosition: to.position,\n    targetX: to.x,\n    targetY: to.y,\n  });\n  return [path, labelX, labelY];\n};\n\nconst getHandleAnchor = (\n  state: ReactFlowState,\n  nodeId: string,\n  type: \"source\" | \"target\",\n  handleId?: string | null\n) => {\n  const node = state.nodeLookup.get(nodeId);\n  const handle = node?.internals.handleBounds?.[type]?.find(\n    (item) => item.id === handleId\n  );\n  if (!(node && handle)) {\n    return;\n  }\n  const { x, y } = node.internals.positionAbsolute;\n  return {\n    x: x + handle.x + (type === \"source\" ? handle.width : 0),\n    y: y + handle.y + handle.height / 2,\n  };\n};\n\nexport const getEdgeLaneOffset = (state: ReactFlowState, edgeId: string) => {\n  const edge = state.edgeLookup.get(edgeId);\n  if (!edge) {\n    return 0;\n  }\n  const lanes: WorkflowEdgeLane[] = [];\n  for (const item of state.edges) {\n    if (item.target !== edge.target) {\n      continue;\n    }\n    const from = getHandleAnchor(\n      state,\n      item.source,\n      \"source\",\n      item.sourceHandle\n    );\n    const to = getHandleAnchor(state, item.target, \"target\", item.targetHandle);\n    if (from && to && to.x > from.x && to.y !== from.y) {\n      lanes.push({ down: to.y > from.y, from, id: item.id, to });\n    }\n  }\n  const own = lanes.find((lane) => lane.id === edgeId);\n  if (!own) {\n    return 0;\n  }\n  const sign = own.down ? 1 : -1;\n  const group = lanes\n    .filter((lane) => lane.down === own.down)\n    .toSorted(\n      (a, b) => sign * (a.to.y - b.to.y) || sign * (a.from.y - b.from.y)\n    );\n  const rank = group.findIndex((lane) => lane.id === edgeId);\n  return ((group.length - 1) / 2 - rank) * WORKFLOW_EDGE_LANE_GAP;\n};\n\nexport const createNodeFromBlock = (\n  block: WorkflowBlock,\n  position: WorkflowPoint\n): WorkflowNodeData => ({\n  branch:\n    block.outputs && block.outputs.length > 1\n      ? block.outputs[0]?.id\n      : undefined,\n  description: block.description,\n  durationMs: block.durationMs,\n  id: `${block.id}-${Date.now().toString(36)}`,\n  inputs: block.inputs,\n  kind: block.kind,\n  logo: block.logo,\n  model: block.model,\n  outputs: block.outputs,\n  position,\n  title: block.title,\n});\n",
      "type": "registry:lib",
      "target": "components/workflow/lib/workflow.ts"
    },
    {
      "path": "registry/notra/workflow/types/workflow.ts",
      "content": "import type { Edge, Node, Position } from \"@xyflow/react\";\nimport type { ComponentProps, ComponentType, ReactNode, SVGProps } from \"react\";\n\nexport type WorkflowNodeKind =\n  | \"trigger\"\n  | \"task\"\n  | \"ai\"\n  | \"integration\"\n  | \"condition\"\n  | \"switch\"\n  | \"merge\"\n  | \"loop\"\n  | \"delay\"\n  | \"approval\"\n  | \"email\"\n  | \"output\";\n\nexport type WorkflowNodeStatus =\n  | \"idle\"\n  | \"queued\"\n  | \"running\"\n  | \"waiting\"\n  | \"success\"\n  | \"error\"\n  | \"skipped\";\n\nexport type WorkflowEdgeStatus = \"idle\" | \"active\" | \"done\" | \"skipped\";\n\nexport type WorkflowRunPhase = \"idle\" | \"running\" | \"done\";\n\nexport type WorkflowLogoName =\n  | \"openai\"\n  | \"anthropic\"\n  | \"claude\"\n  | \"gemini\"\n  | \"perplexity\"\n  | \"mistral\"\n  | \"deepseek\"\n  | \"grok\"\n  | \"browserbase\"\n  | \"context-dev\"\n  | \"firecrawl\"\n  | \"resend\"\n  | \"slack\"\n  | \"gmail\"\n  | \"notion\"\n  | \"google\"\n  | \"google-sheets\"\n  | \"webflow\"\n  | \"wordpress\"\n  | \"linear\"\n  | \"github\"\n  | \"ahrefs\"\n  | \"posthog\";\n\nexport type WorkflowLogLevel = \"info\" | \"success\" | \"error\" | \"skip\";\n\nexport type WorkflowIcon = ComponentType<SVGProps<SVGSVGElement>>;\n\nexport interface WorkflowPoint {\n  x: number;\n  y: number;\n}\n\nexport interface WorkflowAnchor extends WorkflowPoint {\n  position: Position;\n}\n\nexport interface WorkflowPort {\n  id: string;\n  label?: string;\n  hint?: string;\n  rate?: number;\n}\n\nexport interface WorkflowRule {\n  subject: string;\n  operator: string;\n  value: string;\n}\n\nexport interface WorkflowField {\n  label: string;\n  value: string;\n}\n\nexport interface WorkflowNodeData {\n  id: string;\n  kind: WorkflowNodeKind;\n  title: string;\n  description?: string;\n  position: WorkflowPoint;\n  inputs?: WorkflowPort[];\n  outputs?: WorkflowPort[];\n  logo?: WorkflowLogoName;\n  model?: string;\n  durationMs?: number;\n  branch?: string;\n  rule?: WorkflowRule;\n  fail?: boolean;\n  fields?: WorkflowField[];\n  output?: string;\n}\n\nexport interface WorkflowEdgeData {\n  id: string;\n  source: string;\n  sourcePort?: string;\n  target: string;\n  targetPort?: string;\n  label?: string;\n  animated?: boolean;\n}\n\nexport interface WorkflowEdgeLane {\n  id: string;\n  down: boolean;\n  from: WorkflowPoint;\n  to: WorkflowPoint;\n}\n\nexport interface WorkflowGraph {\n  edges: WorkflowEdgeData[];\n  nodes: WorkflowNodeData[];\n}\n\nexport interface WorkflowTemplate extends WorkflowGraph {\n  id: string;\n  title: string;\n  description: string;\n  category: string;\n}\n\nexport interface WorkflowKindConfig {\n  icon: WorkflowIcon;\n  label: string;\n  tileClassName: string;\n}\n\nexport interface WorkflowStatusConfig {\n  className: string;\n  label: string;\n  ledClassName: string;\n}\n\nexport interface WorkflowLogoConfig {\n  label: string;\n  logo: WorkflowIcon;\n  tile?: boolean;\n}\n\nexport interface WorkflowModel {\n  id: string;\n  label: string;\n  logo: WorkflowLogoName;\n  provider: string;\n}\n\nexport interface WorkflowBlock {\n  id: string;\n  title: string;\n  description: string;\n  group: string;\n  kind: WorkflowNodeKind;\n  logo?: WorkflowLogoName;\n  model?: string;\n  inputs?: WorkflowPort[];\n  outputs?: WorkflowPort[];\n  durationMs?: number;\n}\n\nexport interface WorkflowNodeRun {\n  start: number;\n  end: number;\n  status: \"success\" | \"error\" | \"skipped\";\n}\n\nexport interface WorkflowEdgeRun {\n  start: number;\n  end: number;\n  taken: boolean;\n}\n\nexport interface WorkflowSchedule {\n  edges: Record<string, WorkflowEdgeRun>;\n  nodes: Record<string, WorkflowNodeRun>;\n  order: string[];\n  totalMs: number;\n}\n\nexport interface WorkflowNodeState {\n  elapsedMs: number;\n  status: WorkflowNodeStatus;\n}\n\nexport interface WorkflowLogEntry {\n  at: number;\n  id: string;\n  level: WorkflowLogLevel;\n  message: string;\n  nodeId: string;\n  title: string;\n}\n\nexport interface WorkflowRunSummary {\n  id: string;\n  durationMs: number;\n  startedAt: string;\n  status: \"success\" | \"error\" | \"running\";\n  trigger: string;\n  steps: number;\n}\n\nexport interface WorkflowRun {\n  edgeState: (id: string) => WorkflowEdgeStatus;\n  elapsedMs: number;\n  nodeState: (id: string) => WorkflowNodeState;\n  phase: WorkflowRunPhase;\n  play: () => void;\n  schedule: WorkflowSchedule;\n  stop: () => void;\n  totalMs: number;\n}\n\nexport type WorkflowLogoProps = Omit<SVGProps<SVGSVGElement>, \"name\"> & {\n  name: WorkflowLogoName;\n};\n\nexport interface WorkflowFlowNodeData extends Record<string, unknown> {\n  node: WorkflowNodeData;\n  state?: WorkflowNodeState;\n}\n\nexport interface WorkflowFlowEdgeData extends Record<string, unknown> {\n  animated?: boolean;\n  reverse?: boolean;\n  label?: string;\n  status: WorkflowEdgeStatus;\n}\n\nexport type WorkflowFlowNode = Node<WorkflowFlowNodeData, \"workflow\">;\n\nexport type WorkflowFlowEdge = Edge<WorkflowFlowEdgeData, \"workflow\">;\n\nexport type WorkflowCanvasBackgroundVariant =\n  | \"dots\"\n  | \"lines\"\n  | \"cross\"\n  | \"grid\"\n  | \"none\";\n\nexport interface WorkflowCanvasBackgroundProps {\n  gap?: number;\n  variant?: WorkflowCanvasBackgroundVariant;\n}\n\nexport type WorkflowNodeSizes = Record<\n  string,\n  { height: number; width: number }\n>;\n\nexport interface WorkflowPortListProps {\n  ports: WorkflowPort[];\n  title: string;\n}\n\nexport interface WorkflowControlsProps {\n  toolbar?: ReactNode;\n}\n\nexport interface WorkflowBannerConfig {\n  className: string;\n  label: string;\n  message: string;\n}\n\nexport interface WorkflowStatusGlyphProps {\n  status: WorkflowNodeStatus;\n}\n\nexport interface WorkflowTemplatePreviewProps {\n  template: WorkflowTemplate;\n}\n\nexport interface WorkflowCanvasProps {\n  className?: string;\n  /** Follows new steps as they are added or move, like a workflow being written. */\n  autoFit?: boolean;\n  focusId?: string;\n  background?: WorkflowCanvasBackgroundVariant;\n  gap?: number;\n  nodes: WorkflowNodeData[];\n  edges: WorkflowEdgeData[];\n  nodeState?: (id: string) => WorkflowNodeState;\n  edgeState?: (id: string) => WorkflowEdgeStatus;\n  selectedId?: string;\n  controls?: boolean;\n  minimap?: boolean;\n  toolbar?: ReactNode;\n  minZoom?: number;\n  maxZoom?: number;\n  /** The smallest zoom that fits the whole graph; below it, the view shows the first or last steps instead. */\n  fitMinZoom?: number;\n  onSelectNode?: (id: string) => void;\n  onNodeMove?: (id: string, position: WorkflowPoint) => void;\n  onNodeRemove?: (id: string) => void;\n  onConnect?: (edge: Omit<WorkflowEdgeData, \"id\">) => void;\n  onDropBlock?: (blockId: string, position: WorkflowPoint) => void;\n}\n\nexport type WorkflowNodeCardProps = ComponentProps<\"div\"> & {\n  node: WorkflowNodeData;\n  state?: WorkflowNodeState;\n  selected?: boolean;\n  connectable?: boolean;\n  children?: ReactNode;\n};\n\nexport interface WorkflowHandleProps {\n  active?: boolean;\n  className?: string;\n  connectable?: boolean;\n  portId: string;\n  type: \"source\" | \"target\";\n}\n\nexport type WorkflowEdgeProps = ComponentProps<\"g\"> & {\n  path: string;\n  reverse?: boolean;\n  status?: WorkflowEdgeStatus;\n  animated?: boolean;\n};\n\nexport type WorkflowTimerProps = ComponentProps<\"span\"> & {\n  ms: number;\n  running?: boolean;\n};\n\nexport type WorkflowStatusIndicatorProps = ComponentProps<\"span\"> & {\n  status: WorkflowNodeStatus;\n};\n\nexport type WorkflowStatusBadgeProps = ComponentProps<\"span\"> & {\n  status: WorkflowNodeStatus;\n};\n\nexport type WorkflowStatusPillProps = ComponentProps<\"span\"> & {\n  status: WorkflowNodeStatus;\n};\n\nexport type WorkflowDeterminismBadgeProps = ComponentProps<\"span\"> & {\n  deterministic: boolean;\n};\n\nexport type WorkflowRunButtonProps = Omit<\n  ComponentProps<\"button\">,\n  \"children\"\n> & {\n  phase: WorkflowRunPhase;\n  progress?: number;\n  onPlay?: () => void;\n  onStop?: () => void;\n};\n\nexport type WorkflowNodePaletteProps = ComponentProps<\"div\"> & {\n  blocks: WorkflowBlock[];\n  onAdd?: (block: WorkflowBlock) => void;\n};\n\nexport interface WorkflowNodeBranchProps {\n  connectable?: boolean;\n  node: WorkflowNodeData;\n  port: WorkflowPort;\n  status: WorkflowNodeStatus;\n}\n\nexport interface WorkflowNodeBannerProps {\n  status: WorkflowNodeStatus;\n}\n\nexport interface WorkflowNodeSummaryProps {\n  children?: ReactNode;\n  node: WorkflowNodeData;\n}\n\nexport interface WorkflowNodeEngineProps {\n  node: WorkflowNodeData;\n}\n\nexport interface WorkflowNodeFooterProps {\n  node: WorkflowNodeData;\n  state?: WorkflowNodeState;\n}\n\nexport interface WorkflowBranchSelectProps {\n  node: WorkflowNodeData;\n  outputs: WorkflowPort[];\n  onBranchChange: (id: string, branch: string) => void;\n}\n\nexport type WorkflowNodeSettingsProps = Pick<\n  WorkflowNodeSheetProps,\n  \"onBranchChange\" | \"onModelChange\"\n> & {\n  node: WorkflowNodeData;\n};\n\nexport type WorkflowNodeSheetProps = WorkflowOverlayProps & {\n  node?: WorkflowNodeData;\n  state?: WorkflowNodeState;\n  log?: WorkflowLogEntry[];\n  onDelete?: (id: string) => void;\n  onModelChange?: (id: string, model: string) => void;\n  onBranchChange?: (id: string, branch: string) => void;\n};\n\nexport type WorkflowRunLogProps = ComponentProps<\"div\"> & {\n  entries: WorkflowLogEntry[];\n  emptyLabel?: string;\n};\n\nexport type WorkflowRunTimelineProps = ComponentProps<\"div\"> & {\n  nodes: WorkflowNodeData[];\n  schedule: WorkflowSchedule;\n  elapsedMs: number;\n  phase: WorkflowRunPhase;\n};\n\nexport type WorkflowRunHistoryProps = Omit<\n  ComponentProps<\"div\">,\n  \"onSelect\"\n> & {\n  runs: WorkflowRunSummary[];\n  selectedId?: string;\n  onSelect?: (id: string) => void;\n};\n\nexport interface WorkflowModelSelectProps {\n  className?: string;\n  defaultValue?: string;\n  disabled?: boolean;\n  id?: string;\n  models?: WorkflowModel[];\n  onValueChange?: (value: string) => void;\n  value?: string;\n}\n\nexport type WorkflowTemplateCardProps = ComponentProps<\"div\"> & {\n  template: WorkflowTemplate;\n  onUse?: (template: WorkflowTemplate) => void;\n};\n\nexport type WorkflowTemplateDialogProps = WorkflowOverlayProps & {\n  template?: WorkflowTemplate;\n  onUse?: (template: WorkflowTemplate) => void;\n};\n\nexport interface WorkflowBlockIconProps {\n  block: Pick<WorkflowBlock, \"kind\" | \"logo\" | \"model\">;\n  className?: string;\n}\n\nexport interface WorkflowOverlayProps {\n  defaultOpen?: boolean;\n  onOpenChange?: (open: boolean) => void;\n  open?: boolean;\n}\n\nexport interface WorkflowCanvasBackgroundOption {\n  label: string;\n  value: WorkflowCanvasBackgroundVariant;\n}\n\nexport interface WorkflowNodeDemo {\n  node: WorkflowNodeData;\n  state: WorkflowNodeState;\n}\n\nexport interface WorkflowEdgeDemo {\n  animated?: boolean;\n  label: string;\n  status: WorkflowEdgeStatus;\n}\n",
      "type": "registry:lib",
      "target": "components/workflow/types/workflow.ts"
    }
  ],
  "cssVars": {
    "theme": {
      "color-table-shell": "var(--table-shell)",
      "color-table-shell-border": "var(--table-shell-border)",
      "color-table-card": "var(--table-card)",
      "color-table-card-border": "var(--table-card-border)",
      "color-table-row-border": "var(--table-row-border)",
      "shadow-table-card": "var(--table-card-shadow)"
    },
    "light": {
      "table-shell": "#f3f3f2",
      "table-shell-border": "#e7e7e5",
      "table-card": "#ffffff",
      "table-card-border": "#e5e5e5",
      "table-row-border": "#efefee",
      "table-card-shadow": "0 1px 2px hsl(240 10% 10% / 0.06), 0 2px 8px -2px hsl(240 10% 10% / 0.06)"
    },
    "dark": {
      "table-shell": "#161616",
      "table-shell-border": "#232323",
      "table-card": "#1f1f1f",
      "table-card-border": "#333333",
      "table-row-border": "#292929",
      "table-card-shadow": "inset 0 1px 0 hsl(0 0% 100% / 0.05), inset 0 0 0 1px hsl(0 0% 100% / 0.015), inset 0 12px 18px -16px hsl(0 0% 100% / 0.035)"
    }
  },
  "type": "registry:component"
}