From 8d735953558e36efc32f1beaf1ffe17da293772f Mon Sep 17 00:00:00 2001 From: Aniket-508 Date: Tue, 21 Jul 2026 03:30:27 +0530 Subject: [PATCH] feat: add agent preview actions component for agent configuration and deployment --- components/agent-preview-actions.tsx | 495 +++++++++++++++++++++++++++ components/agent-preview.tsx | 12 + 2 files changed, 507 insertions(+) create mode 100644 components/agent-preview-actions.tsx diff --git a/components/agent-preview-actions.tsx b/components/agent-preview-actions.tsx new file mode 100644 index 0000000..49a15a9 --- /dev/null +++ b/components/agent-preview-actions.tsx @@ -0,0 +1,495 @@ +"use client"; + +import { + CheckIcon, + EllipsisIcon, + GlobeIcon, + LockIcon, + RocketIcon, + SquareTerminalIcon, +} from "lucide-react"; +import { useState } from "react"; +import { toast } from "sonner"; + +import { CodeBlockCommand } from "@/components/code-block-command"; +import { Button } from "@/components/ui/button"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog"; +import { + Drawer, + DrawerClose, + DrawerContent, + DrawerDescription, + DrawerFooter, + DrawerHeader, + DrawerTitle, + DrawerTrigger, +} from "@/components/ui/drawer"; +import { Input } from "@/components/ui/input"; +import { + NativeSelect, + NativeSelectOption, +} from "@/components/ui/native-select"; +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "@/components/ui/popover"; +import { + Tooltip, + TooltipContent, + TooltipTrigger, +} from "@/components/ui/tooltip"; +import type { FrameworkId } from "@/constants/agents"; +import { FRAMEWORK_LABEL, getAgent } from "@/constants/agents"; +import { SITE } from "@/constants/site"; +import { useIsMobile } from "@/hooks/use-mobile"; +import { cn } from "@/lib/utils"; + +const gitProviders = [ + { id: "github", label: "GitHub", mark: "GH" }, + { id: "gitlab", label: "GitLab", mark: "GL" }, + { id: "bitbucket", label: "Bitbucket", mark: "BB" }, +] as const; + +const deploymentProviders = [ + { id: "vercel", label: "Vercel", mark: "V" }, + { id: "cloudflare", label: "Cloudflare", mark: "CF" }, + { id: "railway", label: "Railway", mark: "RW" }, + { id: "digitalocean", label: "DigitalOcean", mark: "DO" }, + { id: "render", label: "Render", mark: "R" }, +] as const; + +type GitProvider = (typeof gitProviders)[number]["id"]; +type DeploymentProvider = (typeof deploymentProviders)[number]["id"]; + +const getInstallCommands = (framework: FrameworkId, agent: string) => { + const registryItem = `${SITE.REGISTRY}/${framework}/${agent}`; + + return { + bun: `bunx --bun shadcn@latest add ${registryItem}`, + npm: `npx shadcn@latest add ${registryItem}`, + pnpm: `pnpm dlx shadcn@latest add ${registryItem}`, + yarn: `yarn shadcn@latest add ${registryItem}`, + }; +}; + +const UtilityButton = ({ + label, + children, + ...props +}: { + label: string; + children: React.ReactNode; +} & Omit, "aria-label" | "children">) => ( + +); + +const InstallContent = ({ + agent, + framework, +}: { + agent: string; + framework: FrameworkId; +}) => { + const commands = getInstallCommands(framework, agent); + + return ( + <> +
+

Add to an existing project

+

+ Install the {FRAMEWORK_LABEL[framework]} version of this agent with + the shadcn CLI. +

+
+ + + ); +}; + +const ProviderButton = ({ + label, + mark, + onClick, + selected, +}: { + label: string; + mark: string; + onClick: () => void; + selected: boolean; +}) => ( + +); + +const DeploymentConfiguration = ({ + agent, + framework, +}: { + agent: string; + framework: FrameworkId; +}) => { + const [gitProvider, setGitProvider] = useState("github"); + const [deploymentProvider, setDeploymentProvider] = + useState("vercel"); + const [repositoryName, setRepositoryName] = useState(`${agent}-agent`); + const agentTitle = getAgent(agent)?.shortTitle ?? agent; + const frameworkLabel = FRAMEWORK_LABEL[framework]; + + const handleContinue = (repositoryOnly: boolean) => { + toast.info("Provider connection is the next implementation step", { + description: repositoryOnly + ? `The ${gitProviders.find(({ id }) => id === gitProvider)?.label} repository flow is ready to be connected.` + : `${agentTitle} is configured for ${deploymentProviders.find(({ id }) => id === deploymentProvider)?.label} with ${frameworkLabel}; OAuth and repository generation still need to be connected.`, + }); + }; + + return ( + <> +
+
+ Save code to +
+ {gitProviders.map((provider) => ( + setGitProvider(provider.id)} + selected={gitProvider === provider.id} + /> + ))} +
+
+ +
+ + +
+ +
+ Deploy on +
+ {deploymentProviders.map((provider) => ( + setDeploymentProvider(provider.id)} + selected={deploymentProvider === provider.id} + /> + ))} +
+
+ +
+
+
+ +
+ + +
+ + ); +}; + +const DesktopActions = ({ + agent, + deployOpen, + framework, + installOpen, + setDeployOpen, + setInstallOpen, +}: { + agent: string; + deployOpen: boolean; + framework: FrameworkId; + installOpen: boolean; + setDeployOpen: (open: boolean) => void; + setInstallOpen: (open: boolean) => void; +}) => ( +
+ + + + + + + + + + + Add to existing project + + + + + + + + + + + + + + + + + + Create repository and deploy + + + + + Create & deploy + + Generate a complete {FRAMEWORK_LABEL[framework]} backend for this + agent, save it to your Git provider, and deploy it. + + + + + +
+); + +const MobileActions = ({ + agent, + deployOpen, + framework, + installOpen, + setDeployOpen, + setInstallOpen, +}: { + agent: string; + deployOpen: boolean; + framework: FrameworkId; + installOpen: boolean; + setDeployOpen: (open: boolean) => void; + setInstallOpen: (open: boolean) => void; +}) => { + const [actionsOpen, setActionsOpen] = useState(false); + const commands = getInstallCommands(framework, agent); + + const openAction = (action: "install" | "deploy") => { + setActionsOpen(false); + window.setTimeout(() => { + if (action === "install") { + setInstallOpen(true); + } else { + setDeployOpen(true); + } + }, 180); + }; + + return ( + <> + + + + + + + + + Agent actions + + Add this agent to a project or create a deployable backend. + + +
+ + +
+ + + + + +
+
+ + + + + Add to an existing project + + Install the {FRAMEWORK_LABEL[framework]} agent with the shadcn + CLI. + + +
+ +
+ + + + + +
+
+ + + + + Create & deploy + + Generate a complete {FRAMEWORK_LABEL[framework]} backend, save it + to your Git provider, and deploy it. + + +
+ +
+
+
+ + ); +}; + +export const AgentPreviewActions = ({ + agent, + framework, +}: { + agent: string; + framework: FrameworkId; +}) => { + const [installOpen, setInstallOpen] = useState(false); + const [deployOpen, setDeployOpen] = useState(false); + const isMobile = useIsMobile(); + + const props = { + agent, + deployOpen, + framework, + installOpen, + setDeployOpen, + setInstallOpen, + }; + + return isMobile ? ( + + ) : ( + + ); +}; diff --git a/components/agent-preview.tsx b/components/agent-preview.tsx index c1f0372..2c82e12 100644 --- a/components/agent-preview.tsx +++ b/components/agent-preview.tsx @@ -2,6 +2,7 @@ import { useCallback, useMemo, useRef, useState } from "react"; +import { AgentPreviewActions } from "@/components/agent-preview-actions"; import { CopyButton } from "@/components/copy-button"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; @@ -304,6 +305,17 @@ export const AgentPreview = ({ return (
+
+
+
+ +
+
{inputFields.map((field) => (