├── public ├── monogram-mb.png ├── stylized-sw.png ├── mobile-app-ui.png ├── abstract-letter-aj.png ├── pandora-ocean-scene.png ├── diverse-group-avatars.png ├── modern-website-design.png ├── modern-website-thumbnail.png ├── diverse-futuristic-avatars.png ├── diverse-group-futuristic-avatars.png ├── diverse-group-futuristic-setting.png ├── placeholder-logo.png ├── placeholder.jpg ├── placeholder-user.jpg ├── placeholder-logo.svg └── placeholder.svg ├── pnpm-lock.yaml ├── agentic-ui ├── index.ts ├── hooks │ └── use-agent-actions.ts ├── components │ ├── metric-card-grid.tsx │ ├── fallback-component.tsx │ ├── metric-card.tsx │ ├── toggle-switch.tsx │ ├── info-banner.tsx │ ├── timeline.tsx │ ├── tab-layout.tsx │ ├── avatar-card.tsx │ ├── progress-bar.tsx │ ├── confirmation-card.tsx │ ├── accordion-content.tsx │ ├── message-feed.tsx │ ├── checklist-with-progress.tsx │ └── markdown-renderer.tsx └── ag-ui-client.ts ├── postcss.config.mjs ├── lib └── utils.ts ├── components ├── ui │ ├── aspect-ratio.tsx │ ├── skeleton.tsx │ ├── collapsible.tsx │ ├── use-mobile.tsx │ ├── textarea.tsx │ ├── label.tsx │ ├── input.tsx │ ├── separator.tsx │ ├── progress.tsx │ ├── toaster.tsx │ ├── sonner.tsx │ ├── checkbox.tsx │ ├── slider.tsx │ ├── switch.tsx │ ├── badge.tsx │ ├── tooltip.tsx │ ├── hover-card.tsx │ ├── popover.tsx │ ├── avatar.tsx │ ├── radio-group.tsx │ ├── toggle.tsx │ ├── alert.tsx │ ├── scroll-area.tsx │ ├── resizable.tsx │ ├── toggle-group.tsx │ ├── tabs.tsx │ ├── button.tsx │ ├── card.tsx │ ├── accordion.tsx │ ├── input-otp.tsx │ ├── calendar.tsx │ ├── breadcrumb.tsx │ ├── pagination.tsx │ └── table.tsx ├── theme-provider.tsx └── model-selector.tsx ├── types ├── next-auth.d.ts └── message.ts ├── app ├── page.tsx ├── api │ ├── copilotkit │ │ └── route.ts │ ├── auth │ │ └── [...nextauth] │ │ │ └── route.ts │ └── ai-proxy │ │ └── route.ts ├── ClientLayout.tsx ├── layout.tsx ├── globals.css └── auth │ └── signin │ └── page.tsx ├── next.config.mjs ├── data ├── scenarios │ ├── toggle-switch-scenario.ts │ ├── info-banner-scenario.ts │ ├── metric-card-scenario.ts │ ├── progress-bar-scenario.ts │ ├── payment-details-form-scenario.ts │ ├── confirmation-card-scenario.ts │ ├── rating-selector-scenario.ts │ ├── avatar-card-scenario.ts │ ├── date-time-range-picker-scenario.ts │ ├── chart-scenario.ts │ ├── approval-workflow-card-scenario.ts │ ├── theme-toggle-scenario.ts │ ├── user-form-scenario.ts │ ├── checklist-with-progress-scenario.ts │ ├── data-table-scenario.ts │ ├── cart-summary-panel-scenario.ts │ ├── location-map-scenario.ts │ ├── route-planner-map-scenario.ts │ ├── metric-card-grid-scenario.ts │ ├── search-with-filters-scenario.ts │ ├── markdown-renderer-scenario.ts │ ├── code-snippet-viewer-scenario.ts │ ├── toast-stack-scenario.ts │ ├── mention-input-scenario.ts │ ├── team-member-list-scenario.ts │ ├── language-selector-scenario.ts │ ├── order-status-tracker-scenario.ts │ ├── timeline-scenario.ts │ ├── editable-data-table-scenario.ts │ ├── kanban-board-scenario.ts │ ├── multi-step-form-scenario.ts │ ├── environment-switcher-scenario.ts │ ├── org-chart-viewer-scenario.ts │ ├── accordion-content-scenario.ts │ ├── message-feed-scenario.ts │ ├── product-catalog-grid-scenario.ts │ ├── modal-prompt-scenario.ts │ ├── color-picker-popover-scenario.ts │ ├── column-toggle-table-scenario.ts │ ├── threaded-comments-scenario.ts │ ├── data-grid-scenario.ts │ ├── image-gallery-scenario.ts │ └── tab-layout-scenario.ts ├── component-descriptions │ ├── message-feed-description.ts │ ├── info-banner-description.ts │ ├── timeline-description.ts │ ├── chart-description.ts │ ├── team-member-list-description.ts │ ├── order-status-tracker-description.ts │ ├── metric-card-description.ts │ ├── kanban-board-description.ts │ ├── checklist-with-progress-description.ts │ ├── payment-details-form-description.ts │ ├── product-catalog-grid-description.ts │ ├── avatar-card-description.ts │ ├── toggle-switch-description.ts │ ├── search-with-filters-description.ts │ ├── user-form-description.ts │ ├── multi-step-form-description.ts │ ├── rating-selector-description.ts │ ├── confirmation-card-description.ts │ ├── date-time-range-picker-description.ts │ ├── approval-workflow-card-description.ts │ ├── progress-bar-description.ts │ ├── data-table-description.ts │ ├── cart-summary-panel-description.ts │ ├── data-grid-description.ts │ └── ai-prompt-builder-description.ts └── component-descriptions.ts ├── .gitignore ├── components.json ├── jest.config.js ├── hooks └── use-mobile.tsx ├── tsconfig.json ├── LICENSE ├── jest.setup.js ├── services └── component-adapter.ts ├── tailwind.config.ts ├── styles └── globals.css └── package.json /public/monogram-mb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vivek100/AgenticGenUI/HEAD/public/monogram-mb.png -------------------------------------------------------------------------------- /public/stylized-sw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vivek100/AgenticGenUI/HEAD/public/stylized-sw.png -------------------------------------------------------------------------------- /public/mobile-app-ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vivek100/AgenticGenUI/HEAD/public/mobile-app-ui.png -------------------------------------------------------------------------------- /public/abstract-letter-aj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vivek100/AgenticGenUI/HEAD/public/abstract-letter-aj.png -------------------------------------------------------------------------------- /public/pandora-ocean-scene.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vivek100/AgenticGenUI/HEAD/public/pandora-ocean-scene.png -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '9.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false -------------------------------------------------------------------------------- /public/diverse-group-avatars.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vivek100/AgenticGenUI/HEAD/public/diverse-group-avatars.png -------------------------------------------------------------------------------- /public/modern-website-design.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vivek100/AgenticGenUI/HEAD/public/modern-website-design.png -------------------------------------------------------------------------------- /public/modern-website-thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vivek100/AgenticGenUI/HEAD/public/modern-website-thumbnail.png -------------------------------------------------------------------------------- /public/diverse-futuristic-avatars.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vivek100/AgenticGenUI/HEAD/public/diverse-futuristic-avatars.png -------------------------------------------------------------------------------- /public/diverse-group-futuristic-avatars.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vivek100/AgenticGenUI/HEAD/public/diverse-group-futuristic-avatars.png -------------------------------------------------------------------------------- /public/diverse-group-futuristic-setting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vivek100/AgenticGenUI/HEAD/public/diverse-group-futuristic-setting.png -------------------------------------------------------------------------------- /agentic-ui/index.ts: -------------------------------------------------------------------------------- 1 | // Export all components and utilities 2 | export * from "./components" 3 | export * from "./hooks" 4 | export * from "./registry" 5 | -------------------------------------------------------------------------------- /postcss.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('postcss-load-config').Config} */ 2 | const config = { 3 | plugins: { 4 | tailwindcss: {}, 5 | }, 6 | }; 7 | 8 | export default config; 9 | -------------------------------------------------------------------------------- /lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { type ClassValue, clsx } from "clsx" 2 | import { twMerge } from "tailwind-merge" 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)) 6 | } 7 | -------------------------------------------------------------------------------- /components/ui/aspect-ratio.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio" 4 | 5 | const AspectRatio = AspectRatioPrimitive.Root 6 | 7 | export { AspectRatio } 8 | -------------------------------------------------------------------------------- /types/next-auth.d.ts: -------------------------------------------------------------------------------- 1 | import type { DefaultSession } from "next-auth" 2 | 3 | declare module "next-auth" { 4 | interface Session { 5 | user: { 6 | id: string 7 | } & DefaultSession["user"] 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /app/page.tsx: -------------------------------------------------------------------------------- 1 | import { AgentDemoApp } from "@/components/agent-demo-app" 2 | 3 | export default function Home() { 4 | return ( 5 |
6 | 7 |
8 | ) 9 | } 10 | -------------------------------------------------------------------------------- /types/message.ts: -------------------------------------------------------------------------------- 1 | // Message types 2 | export type MessageType = 3 | | { type: "user"; content: string; timestamp: Date } 4 | | { type: "assistant"; content: string; timestamp: Date } 5 | | { type: "component"; content: any; timestamp: Date } 6 | | { type: "event"; content: any; timestamp: Date } 7 | -------------------------------------------------------------------------------- /next.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = { 3 | reactStrictMode: true, 4 | eslint: { 5 | ignoreDuringBuilds: true, 6 | }, 7 | typescript: { 8 | ignoreBuildErrors: true, 9 | }, 10 | images: { 11 | unoptimized: true, 12 | }, 13 | }; 14 | 15 | export default nextConfig; 16 | -------------------------------------------------------------------------------- /components/ui/skeleton.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from "@/lib/utils" 2 | 3 | function Skeleton({ 4 | className, 5 | ...props 6 | }: React.HTMLAttributes) { 7 | return ( 8 |
12 | ) 13 | } 14 | 15 | export { Skeleton } 16 | -------------------------------------------------------------------------------- /data/scenarios/toggle-switch-scenario.ts: -------------------------------------------------------------------------------- 1 | export const toggleSwitchScenario = { 2 | tool: "renderComponent", 3 | payload: { 4 | componentType: "toggleswitch", 5 | props: { 6 | title: "Notifications", 7 | description: "Enable or disable email notifications", 8 | settingId: "email-notifications", 9 | }, 10 | }, 11 | } 12 | -------------------------------------------------------------------------------- /data/scenarios/info-banner-scenario.ts: -------------------------------------------------------------------------------- 1 | export const infoBannerScenario = { 2 | tool: "renderComponent", 3 | payload: { 4 | componentType: "infobanner", 5 | props: { 6 | title: "System Maintenance", 7 | message: "The system will be down for maintenance on Sunday from 2-4 AM.", 8 | type: "warning", 9 | }, 10 | }, 11 | } 12 | -------------------------------------------------------------------------------- /components/theme-provider.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import * as React from 'react' 4 | import { 5 | ThemeProvider as NextThemesProvider, 6 | type ThemeProviderProps, 7 | } from 'next-themes' 8 | 9 | export function ThemeProvider({ children, ...props }: ThemeProviderProps) { 10 | return {children} 11 | } 12 | -------------------------------------------------------------------------------- /data/scenarios/metric-card-scenario.ts: -------------------------------------------------------------------------------- 1 | export const metricCardScenario = { 2 | tool: "renderComponent", 3 | payload: { 4 | componentType: "metriccard", 5 | props: { 6 | title: "Total Users", 7 | value: "1,234", 8 | description: "Total users in the system", 9 | trend: { value: 12, isPositive: true }, 10 | }, 11 | }, 12 | } 13 | -------------------------------------------------------------------------------- /data/scenarios/progress-bar-scenario.ts: -------------------------------------------------------------------------------- 1 | export const progressBarScenario = { 2 | tool: "renderComponent", 3 | payload: { 4 | componentType: "progressbar", 5 | props: { 6 | title: "Data Import", 7 | description: "Importing user data from CSV", 8 | value: 65, 9 | max: 100, 10 | interactive: true, 11 | }, 12 | }, 13 | } 14 | -------------------------------------------------------------------------------- /data/scenarios/payment-details-form-scenario.ts: -------------------------------------------------------------------------------- 1 | export const paymentDetailsFormScenario = { 2 | tool: "renderComponent", 3 | payload: { 4 | componentType: "paymentdetailsform", 5 | props: { 6 | title: "Payment Information", 7 | description: "Enter your payment details to complete your purchase", 8 | amount: 529.96, 9 | }, 10 | }, 11 | } 12 | -------------------------------------------------------------------------------- /data/scenarios/confirmation-card-scenario.ts: -------------------------------------------------------------------------------- 1 | export const confirmationCardScenario = { 2 | tool: "renderComponent", 3 | payload: { 4 | componentType: "confirmationcard", 5 | props: { 6 | title: "Delete Account", 7 | message: "Are you sure you want to delete your account? This action cannot be undone.", 8 | importance: "critical", 9 | }, 10 | }, 11 | } 12 | -------------------------------------------------------------------------------- /data/scenarios/rating-selector-scenario.ts: -------------------------------------------------------------------------------- 1 | export const ratingSelectorScenario = { 2 | tool: "renderComponent", 3 | payload: { 4 | componentType: "ratingselector", 5 | props: { 6 | title: "Product Feedback", 7 | description: "Let us know what you think about our product", 8 | label: "How would you rate your experience?", 9 | max: 5, 10 | }, 11 | }, 12 | } 13 | -------------------------------------------------------------------------------- /components/ui/collapsible.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import * as CollapsiblePrimitive from "@radix-ui/react-collapsible" 4 | 5 | const Collapsible = CollapsiblePrimitive.Root 6 | 7 | const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger 8 | 9 | const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent 10 | 11 | export { Collapsible, CollapsibleTrigger, CollapsibleContent } 12 | -------------------------------------------------------------------------------- /data/scenarios/avatar-card-scenario.ts: -------------------------------------------------------------------------------- 1 | export const avatarCardScenario = { 2 | tool: "renderComponent", 3 | payload: { 4 | componentType: "avatarcard", 5 | props: { 6 | name: "Alex Johnson", 7 | role: "Senior Developer", 8 | description: "Full-stack developer with 5 years of experience", 9 | status: "online", 10 | badges: ["React", "Node.js", "TypeScript"], 11 | }, 12 | }, 13 | } 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # next.js 7 | /.next/ 8 | /out/ 9 | 10 | # production 11 | /build 12 | 13 | # debug 14 | npm-debug.log* 15 | yarn-debug.log* 16 | yarn-error.log* 17 | .pnpm-debug.log* 18 | 19 | # env files 20 | .env* 21 | 22 | # vercel 23 | .vercel 24 | 25 | # typescript 26 | *.tsbuildinfo 27 | next-env.d.ts -------------------------------------------------------------------------------- /data/component-descriptions/message-feed-description.ts: -------------------------------------------------------------------------------- 1 | export const messageFeedDescription = { 2 | description: "Displays a read-only chat history", 3 | props: [ 4 | { name: "title", type: "string", description: "Feed title" }, 5 | { name: "description", type: "string", description: "Optional description" }, 6 | { name: "messages", type: "Array", description: "Messages to display" }, 7 | ], 8 | events: [], 9 | toolCalls: [], 10 | } 11 | -------------------------------------------------------------------------------- /data/component-descriptions/info-banner-description.ts: -------------------------------------------------------------------------------- 1 | export const infoBannerDescription = { 2 | description: "Displays a status message or notification", 3 | props: [ 4 | { name: "title", type: "string", description: "Banner title" }, 5 | { name: "message", type: "string", description: "Banner message" }, 6 | { name: "type", type: "'info' | 'success' | 'warning' | 'error'", description: "Banner type" }, 7 | ], 8 | events: [], 9 | toolCalls: [], 10 | } 11 | -------------------------------------------------------------------------------- /data/component-descriptions/timeline-description.ts: -------------------------------------------------------------------------------- 1 | export const timelineDescription = { 2 | description: "Displays event logs with timestamps", 3 | props: [ 4 | { name: "title", type: "string", description: "Timeline title" }, 5 | { name: "description", type: "string", description: "Optional description" }, 6 | { name: "events", type: "Array", description: "Timeline events to display" }, 7 | ], 8 | events: [], 9 | toolCalls: [], 10 | } 11 | -------------------------------------------------------------------------------- /data/scenarios/date-time-range-picker-scenario.ts: -------------------------------------------------------------------------------- 1 | export const dateTimeRangePickerScenario = { 2 | tool: "renderComponent", 3 | payload: { 4 | componentType: "datetimerangepicker", 5 | props: { 6 | title: "Schedule Meeting", 7 | description: "Select start and end date/time for your meeting", 8 | startDate: new Date(new Date().setDate(new Date().getDate() + 1)), 9 | endDate: new Date(new Date().setDate(new Date().getDate() + 1)), 10 | }, 11 | }, 12 | } 13 | -------------------------------------------------------------------------------- /data/scenarios/chart-scenario.ts: -------------------------------------------------------------------------------- 1 | export const chartScenario = { 2 | tool: "renderComponent", 3 | payload: { 4 | componentType: "chart", 5 | props: { 6 | title: "Monthly Revenue", 7 | description: "Revenue over the last 6 months", 8 | data: [ 9 | { x: "Jan", y: 1000 }, 10 | { x: "Feb", y: 1500 }, 11 | { x: "Mar", y: 1200 }, 12 | { x: "Apr", y: 1800 }, 13 | { x: "May", y: 2200 }, 14 | { x: "Jun", y: 2500 }, 15 | ], 16 | }, 17 | }, 18 | } 19 | -------------------------------------------------------------------------------- /data/scenarios/approval-workflow-card-scenario.ts: -------------------------------------------------------------------------------- 1 | export const approvalWorkflowCardScenario = { 2 | tool: "renderComponent", 3 | payload: { 4 | componentType: "approvalworkflowcard", 5 | props: { 6 | title: "Expense Approval", 7 | description: "Please review this expense request", 8 | message: 9 | "John Doe has requested reimbursement for $250.00 for office supplies purchased on May 10, 2023. Receipts have been attached to the request.", 10 | requireComment: true, 11 | }, 12 | }, 13 | } 14 | -------------------------------------------------------------------------------- /app/api/copilotkit/route.ts: -------------------------------------------------------------------------------- 1 | import { CopilotRuntime, OpenAIAdapter, copilotRuntimeNextJSAppRouterEndpoint } from "@copilotkit/runtime" 2 | import type { NextRequest } from "next/server" 3 | 4 | const serviceAdapter = new OpenAIAdapter() 5 | const runtime = new CopilotRuntime() 6 | 7 | export const POST = async (req: NextRequest) => { 8 | const { handleRequest } = copilotRuntimeNextJSAppRouterEndpoint({ 9 | runtime, 10 | serviceAdapter, 11 | endpoint: "/api/copilotkit", 12 | }) 13 | 14 | return handleRequest(req) 15 | } 16 | -------------------------------------------------------------------------------- /components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "default", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.ts", 8 | "css": "app/globals.css", 9 | "baseColor": "neutral", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils", 16 | "ui": "@/components/ui", 17 | "lib": "@/lib", 18 | "hooks": "@/hooks" 19 | }, 20 | "iconLibrary": "lucide" 21 | } -------------------------------------------------------------------------------- /data/scenarios/theme-toggle-scenario.ts: -------------------------------------------------------------------------------- 1 | export const themeToggleScenario = { 2 | tool: "renderComponent", 3 | payload: { 4 | componentType: "themetoggle", 5 | props: { 6 | title: "Theme Preference", 7 | description: "Choose your preferred color scheme", 8 | themes: [ 9 | { id: "light", name: "Light", icon: "sun" }, 10 | { id: "dark", name: "Dark", icon: "moon" }, 11 | { id: "system", name: "System", icon: "monitor" }, 12 | ], 13 | currentTheme: "system", 14 | }, 15 | }, 16 | } 17 | -------------------------------------------------------------------------------- /public/placeholder-logo.png: -------------------------------------------------------------------------------- 1 | �PNG 2 |  3 | IHDR�M��0PLTEZ? tRNS� �@��`P0p���w �IDATx��ؽJ3Q�7'��%�|?� ���E�l�7���(X�D������w`����[�*t����D���mD�}��4; ;�DDDDDDDDDDDD_�_İ��!�y�`�_�:�� ;Ļ�'|� ��;.I"����3*5����J�1�� �T��FI�� ��=��3܃�2~�b���0��U9\��]�4�#w0��Gt\&1 �?21,���o!e�m��ĻR�����5�� ؽAJ�9��R)�5�0.FFASaǃ�T�#|�K���I�������1� 4 | M������N"��$����G�V�T� ��T^^��A�$S��h(�������G]co"J׸^^�'�=���%� �W�6Ы�W��w�a�߇*�^^�YG�c���`'F����������������^5_�,�S�%IEND�B`� -------------------------------------------------------------------------------- /data/component-descriptions/chart-description.ts: -------------------------------------------------------------------------------- 1 | export const chartDescription = { 2 | description: "Renders JSON data as a chart preview", 3 | props: [ 4 | { name: "title", type: "string", description: "Chart title" }, 5 | { name: "description", type: "string", description: "Optional description" }, 6 | { name: "data", type: "Array<{x: string | number, y: number}>", description: "Data points for the chart" }, 7 | { name: "type", type: "'line' | 'bar'", description: "Chart type (defaults to line)" }, 8 | ], 9 | events: [], 10 | toolCalls: [], 11 | } 12 | -------------------------------------------------------------------------------- /data/scenarios/user-form-scenario.ts: -------------------------------------------------------------------------------- 1 | export const userFormScenario = { 2 | tool: "renderComponent", 3 | payload: { 4 | componentType: "userform", 5 | props: { 6 | title: "Create User", 7 | description: "Add a new user to the system", 8 | fields: [ 9 | { id: "name", label: "Full Name", type: "text", required: true }, 10 | { id: "email", label: "Email Address", type: "email", required: true }, 11 | { id: "role", label: "Role", type: "text" }, 12 | { id: "notes", label: "Notes", type: "textarea" }, 13 | ], 14 | }, 15 | }, 16 | } 17 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | const nextJest = require('next/jest') 2 | 3 | const createJestConfig = nextJest({ 4 | // Provide the path to your Next.js app to load next.config.js and .env files 5 | dir: './', 6 | }) 7 | 8 | // Add any custom config to be passed to Jest 9 | const customJestConfig = { 10 | setupFilesAfterEnv: ['/jest.setup.js'], 11 | testEnvironment: 'jsdom', 12 | moduleNameMapper: { 13 | '^@/(.*)$': '/$1', 14 | }, 15 | } 16 | 17 | // createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async 18 | module.exports = createJestConfig(customJestConfig) -------------------------------------------------------------------------------- /data/component-descriptions/team-member-list-description.ts: -------------------------------------------------------------------------------- 1 | export const teamMemberListDescription = { 2 | description: "Displays a team with roles", 3 | props: [ 4 | { name: "title", type: "string", description: "List title" }, 5 | { name: "description", type: "string", description: "Optional description" }, 6 | { name: "members", type: "Array", description: "Team members to display" }, 7 | ], 8 | events: [], 9 | toolCalls: [ 10 | { 11 | name: "selectTeamMember", 12 | description: "Called when a team member is selected", 13 | args: "{ memberId: string }", 14 | }, 15 | ], 16 | } 17 | -------------------------------------------------------------------------------- /hooks/use-mobile.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | 3 | const MOBILE_BREAKPOINT = 768 4 | 5 | export function useIsMobile() { 6 | const [isMobile, setIsMobile] = React.useState(undefined) 7 | 8 | React.useEffect(() => { 9 | const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`) 10 | const onChange = () => { 11 | setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) 12 | } 13 | mql.addEventListener("change", onChange) 14 | setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) 15 | return () => mql.removeEventListener("change", onChange) 16 | }, []) 17 | 18 | return !!isMobile 19 | } 20 | -------------------------------------------------------------------------------- /app/ClientLayout.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import type React from "react" 4 | 5 | import { SessionProvider } from "next-auth/react" 6 | import { ThemeProvider } from "@/components/theme-provider" 7 | import { Toaster } from "@/components/ui/toaster" 8 | import "@/app/globals.css" 9 | 10 | export default function ClientLayout({ 11 | children, 12 | }: { 13 | children: React.ReactNode 14 | }) { 15 | return ( 16 | 17 | 18 | {children} 19 | 20 | 21 | 22 | ) 23 | } 24 | -------------------------------------------------------------------------------- /components/ui/use-mobile.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | 3 | const MOBILE_BREAKPOINT = 768 4 | 5 | export function useIsMobile() { 6 | const [isMobile, setIsMobile] = React.useState(undefined) 7 | 8 | React.useEffect(() => { 9 | const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`) 10 | const onChange = () => { 11 | setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) 12 | } 13 | mql.addEventListener("change", onChange) 14 | setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) 15 | return () => mql.removeEventListener("change", onChange) 16 | }, []) 17 | 18 | return !!isMobile 19 | } 20 | -------------------------------------------------------------------------------- /data/component-descriptions/order-status-tracker-description.ts: -------------------------------------------------------------------------------- 1 | export const orderStatusTrackerDescription = { 2 | description: "Tracks order status through defined steps", 3 | props: [ 4 | { name: "title", type: "string", description: "Tracker title" }, 5 | { name: "description", type: "string", description: "Optional description" }, 6 | { name: "status", type: "string", description: "Current status ID" }, 7 | { 8 | name: "steps", 9 | type: "Array<{id: string, label: string, description?: string, date?: string, icon?: string}>", 10 | description: "Status steps", 11 | }, 12 | ], 13 | events: [], 14 | toolCalls: [], 15 | } 16 | -------------------------------------------------------------------------------- /data/component-descriptions/metric-card-description.ts: -------------------------------------------------------------------------------- 1 | export const metricCardDescription = { 2 | description: "Displays a numeric value with a label and optional trend indicator", 3 | props: [ 4 | { name: "title", type: "string", description: "Title of the metric" }, 5 | { name: "value", type: "string | number", description: "Value to display" }, 6 | { name: "description", type: "string", description: "Optional description text" }, 7 | { name: "trend", type: "object", description: "Optional trend data with value and direction" }, 8 | { name: "icon", type: "ReactNode", description: "Optional icon to display" }, 9 | ], 10 | events: [], 11 | toolCalls: [], 12 | } 13 | -------------------------------------------------------------------------------- /data/component-descriptions/kanban-board-description.ts: -------------------------------------------------------------------------------- 1 | export const kanbanBoardDescription = { 2 | description: "Drag-and-drop task board", 3 | props: [ 4 | { name: "title", type: "string", description: "Board title" }, 5 | { name: "description", type: "string", description: "Optional description" }, 6 | { name: "columns", type: "Array", description: "Board columns with tasks" }, 7 | ], 8 | events: [], 9 | toolCalls: [ 10 | { 11 | name: "updateKanbanBoard", 12 | description: "Called when a task is moved", 13 | args: "{ taskId: string, sourceColumnId: string, targetColumnId: string, updatedBoard: Array }", 14 | }, 15 | ], 16 | } 17 | -------------------------------------------------------------------------------- /data/component-descriptions/checklist-with-progress-description.ts: -------------------------------------------------------------------------------- 1 | export const checklistWithProgressDescription = { 2 | description: "Interactive checklist with progress indicator", 3 | props: [ 4 | { name: "title", type: "string", description: "Checklist title" }, 5 | { name: "description", type: "string", description: "Optional description" }, 6 | { name: "items", type: "Array", description: "Checklist items" }, 7 | ], 8 | events: [], 9 | toolCalls: [ 10 | { 11 | name: "updateChecklistProgress", 12 | description: "Called when an item is checked/unchecked", 13 | args: "{ items: Array, progress: number }", 14 | }, 15 | ], 16 | } 17 | -------------------------------------------------------------------------------- /agentic-ui/hooks/use-agent-actions.ts: -------------------------------------------------------------------------------- 1 | import { callTool, sendResponse } from "../ag-ui-client" 2 | 3 | /** 4 | * Hook for interacting with the agent 5 | * Provides methods for sending responses and calling tools 6 | */ 7 | export function useAgentActions() { 8 | return { 9 | /** 10 | * Send a response back to the agent 11 | * @param msg Message to send 12 | */ 13 | sendAgentResponse: (msg: string) => sendResponse({ type: "agentResponse", payload: msg }), 14 | 15 | /** 16 | * Call a tool with arguments 17 | * @param tool Tool name 18 | * @param args Tool arguments 19 | */ 20 | callTool: (tool: string, args: any) => callTool({ tool, args }), 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /data/component-descriptions/payment-details-form-description.ts: -------------------------------------------------------------------------------- 1 | export const paymentDetailsFormDescription = { 2 | description: "Collects payment details", 3 | props: [ 4 | { name: "title", type: "string", description: "Form title" }, 5 | { name: "description", type: "string", description: "Optional description" }, 6 | { name: "amount", type: "number", description: "Payment amount" }, 7 | { name: "currency", type: "string", description: "Currency code" }, 8 | ], 9 | events: [], 10 | toolCalls: [ 11 | { 12 | name: "processPayment", 13 | description: "Called when payment is submitted", 14 | args: "{ amount: number, currency: string, last4: string }", 15 | }, 16 | ], 17 | } 18 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["dom", "dom.iterable", "esnext"], 4 | "allowJs": true, 5 | "target": "ES6", 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "noEmit": true, 9 | "esModuleInterop": true, 10 | "module": "esnext", 11 | "moduleResolution": "bundler", 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "jsx": "preserve", 15 | "incremental": true, 16 | "plugins": [ 17 | { 18 | "name": "next" 19 | } 20 | ], 21 | "paths": { 22 | "@/*": ["./*"] 23 | } 24 | }, 25 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 26 | "exclude": ["node_modules"] 27 | } 28 | -------------------------------------------------------------------------------- /data/component-descriptions/product-catalog-grid-description.ts: -------------------------------------------------------------------------------- 1 | export const productCatalogGridDescription = { 2 | description: "Displays a grid of product cards", 3 | props: [ 4 | { name: "title", type: "string", description: "Grid title" }, 5 | { name: "description", type: "string", description: "Optional description" }, 6 | { name: "products", type: "Array", description: "Products to display" }, 7 | { name: "currency", type: "string", description: "Currency code for prices" }, 8 | ], 9 | events: [], 10 | toolCalls: [ 11 | { 12 | name: "selectProduct", 13 | description: "Called when a product is selected", 14 | args: "{ productId: string }", 15 | }, 16 | ], 17 | } 18 | -------------------------------------------------------------------------------- /data/component-descriptions/avatar-card-description.ts: -------------------------------------------------------------------------------- 1 | export const avatarCardDescription = { 2 | description: "Displays user profile picture + info", 3 | props: [ 4 | { name: "name", type: "string", description: "User name" }, 5 | { name: "role", type: "string", description: "Optional user role" }, 6 | { name: "imageUrl", type: "string", description: "Optional profile image URL" }, 7 | { name: "description", type: "string", description: "Optional description" }, 8 | { name: "status", type: "'online' | 'offline' | 'away' | 'busy'", description: "Optional status" }, 9 | { name: "badges", type: "string[]", description: "Optional badges to display" }, 10 | ], 11 | events: [], 12 | toolCalls: [], 13 | } 14 | -------------------------------------------------------------------------------- /data/component-descriptions/toggle-switch-description.ts: -------------------------------------------------------------------------------- 1 | export const toggleSwitchDescription = { 2 | description: "On/Off toggle with agent or tool trigger", 3 | props: [ 4 | { name: "title", type: "string", description: "Toggle title" }, 5 | { name: "description", type: "string", description: "Optional description" }, 6 | { name: "defaultChecked", type: "boolean", description: "Initial state" }, 7 | { name: "settingId", type: "string", description: "Unique ID for the setting" }, 8 | ], 9 | events: [], 10 | toolCalls: [ 11 | { 12 | name: "toggleSetting", 13 | description: "Called when toggle is changed", 14 | args: "{ settingId: string, enabled: boolean }", 15 | }, 16 | ], 17 | } 18 | -------------------------------------------------------------------------------- /data/component-descriptions/search-with-filters-description.ts: -------------------------------------------------------------------------------- 1 | export const searchWithFiltersDescription = { 2 | description: "Search input with filter chips", 3 | props: [ 4 | { name: "title", type: "string", description: "Search title" }, 5 | { name: "description", type: "string", description: "Optional description" }, 6 | { name: "placeholder", type: "string", description: "Search input placeholder" }, 7 | { name: "filters", type: "Array", description: "Available filters" }, 8 | ], 9 | events: [], 10 | toolCalls: [ 11 | { 12 | name: "searchWithFilters", 13 | description: "Called when search is performed", 14 | args: "{ searchTerm: string, filters: Array }", 15 | }, 16 | ], 17 | } 18 | -------------------------------------------------------------------------------- /app/layout.tsx: -------------------------------------------------------------------------------- 1 | import type React from "react" 2 | import { Inter } from "next/font/google" 3 | import ClientLayout from "./ClientLayout" 4 | 5 | const inter = Inter({ subsets: ["latin"] }) 6 | 7 | export const metadata = { 8 | title: "AgenticGenUI", 9 | description: "A generative UI library for building AI-powered interfaces with CopilotKit integration", 10 | generator: 'v0.dev' 11 | } 12 | 13 | export default function RootLayout({ 14 | children, 15 | }: { 16 | children: React.ReactNode 17 | }) { 18 | return ( 19 | 20 | 21 | {children} 22 | 23 | 24 | ) 25 | } 26 | 27 | 28 | import './globals.css' -------------------------------------------------------------------------------- /data/scenarios/checklist-with-progress-scenario.ts: -------------------------------------------------------------------------------- 1 | export const checklistWithProgressScenario = { 2 | tool: "renderComponent", 3 | payload: { 4 | componentType: "checklistwithprogress", 5 | props: { 6 | title: "Project Launch Checklist", 7 | description: "Tasks to complete before launch", 8 | items: [ 9 | { id: "task-1", label: "Complete user testing", checked: true }, 10 | { id: "task-2", label: "Fix critical bugs", checked: true }, 11 | { id: "task-3", label: "Update documentation", checked: false }, 12 | { id: "task-4", label: "Prepare marketing materials", checked: false }, 13 | { id: "task-5", label: "Deploy to production", checked: false }, 14 | ], 15 | }, 16 | }, 17 | } 18 | -------------------------------------------------------------------------------- /data/scenarios/data-table-scenario.ts: -------------------------------------------------------------------------------- 1 | export const dataTableScenario = { 2 | tool: "renderComponent", 3 | payload: { 4 | componentType: "datatable", 5 | props: { 6 | title: "User List", 7 | description: "All registered users", 8 | columns: [ 9 | { key: "id", label: "ID" }, 10 | { key: "name", label: "Name" }, 11 | { key: "email", label: "Email" }, 12 | { key: "role", label: "Role" }, 13 | ], 14 | data: [ 15 | { id: 1, name: "John Doe", email: "john@example.com", role: "Admin" }, 16 | { id: 2, name: "Jane Smith", email: "jane@example.com", role: "User" }, 17 | { id: 3, name: "Bob Johnson", email: "bob@example.com", role: "Editor" }, 18 | ], 19 | }, 20 | }, 21 | } 22 | -------------------------------------------------------------------------------- /components/ui/textarea.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | 3 | import { cn } from "@/lib/utils" 4 | 5 | const Textarea = React.forwardRef< 6 | HTMLTextAreaElement, 7 | React.ComponentProps<"textarea"> 8 | >(({ className, ...props }, ref) => { 9 | return ( 10 |