+ "content": "\"use client\";\nimport React from \"react\";\nimport \"@copilotkit/react-ui/styles.css\";\nimport \"./style.css\";\nimport { CopilotKit, useCoAgentStateRender } from \"@copilotkit/react-core\";\nimport { CopilotChat } from \"@copilotkit/react-ui\";\nimport { useTheme } from \"next-themes\";\n\ninterface AgenticGenerativeUIProps {\n params: Promise<{\n integrationId: string;\n }>;\n}\n\nconst AgenticGenerativeUI: React.FC<AgenticGenerativeUIProps> = ({ params }) => {\n const { integrationId } = React.use(params);\n return (\n <CopilotKit\n runtimeUrl={`/api/copilotkit/${integrationId}`}\n showDevConsole={false}\n // agent lock to the relevant agent\n agent=\"agentic_generative_ui\"\n >\n <Chat />\n </CopilotKit>\n );\n};\n\ninterface AgentState {\n steps: {\n description: string;\n status: \"pending\" | \"completed\";\n }[];\n}\n\nconst Chat = () => {\n const { theme } = useTheme();\n useCoAgentStateRender<AgentState>({\n name: \"agentic_generative_ui\",\n render: ({ state }) => {\n if (!state.steps || state.steps.length === 0) {\n return null;\n }\n\n const completedCount = state.steps.filter((step) => step.status === \"completed\").length;\n const progressPercentage = (completedCount / state.steps.length) * 100;\n\n return (\n <div className=\"flex\">\n <div\n data-testid=\"task-progress\"\n className={`relative rounded-xl w-[700px] p-6 shadow-lg backdrop-blur-sm ${\n theme === \"dark\"\n ? \"bg-gradient-to-br from-slate-900 via-slate-800 to-slate-900 text-white border border-slate-700/50 shadow-2xl\"\n : \"bg-gradient-to-br from-white via-gray-50 to-white text-gray-800 border border-gray-200/80\"\n }`}\n >\n {/* Header */}\n <div className=\"mb-5\">\n <div className=\"flex items-center justify-between mb-3\">\n <h3 className=\"text-xl font-bold bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent\">\n Task Progress\n </h3>\n <div className={`text-sm ${theme === \"dark\" ? \"text-slate-400\" : \"text-gray-500\"}`}>\n {completedCount}/{state.steps.length} Complete\n </div>\n </div>\n\n {/* Progress Bar */}\n <div\n className={`relative h-2 rounded-full overflow-hidden ${theme === \"dark\" ? \"bg-slate-700\" : \"bg-gray-200\"}`}\n >\n <div\n className=\"absolute top-0 left-0 h-full bg-gradient-to-r from-blue-500 to-purple-500 rounded-full transition-all duration-1000 ease-out\"\n style={{ width: `${progressPercentage}%` }}\n />\n <div\n className={`absolute top-0 left-0 h-full w-full bg-gradient-to-r from-transparent to-transparent animate-pulse ${\n theme === \"dark\" ? \"via-white/20\" : \"via-white/40\"\n }`}\n />\n </div>\n </div>\n\n {/* Steps */}\n <div className=\"space-y-2\">\n {state.steps.map((step, index) => {\n const isCompleted = step.status === \"completed\";\n const isCurrentPending =\n step.status === \"pending\" &&\n index === state.steps.findIndex((s) => s.status === \"pending\");\n const isFuturePending = step.status === \"pending\" && !isCurrentPending;\n\n return (\n <div\n key={index}\n className={`relative flex items-center p-2.5 rounded-lg transition-all duration-500 ${\n isCompleted\n ? theme === \"dark\"\n ? \"bg-gradient-to-r from-green-900/30 to-emerald-900/20 border border-green-500/30\"\n : \"bg-gradient-to-r from-green-50 to-emerald-50 border border-green-200/60\"\n : isCurrentPending\n ? theme === \"dark\"\n ? \"bg-gradient-to-r from-blue-900/40 to-purple-900/30 border border-blue-500/50 shadow-lg shadow-blue-500/20\"\n : \"bg-gradient-to-r from-blue-50 to-purple-50 border border-blue-200/60 shadow-md shadow-blue-200/50\"\n : theme === \"dark\"\n ? \"bg-slate-800/50 border border-slate-600/30\"\n : \"bg-gray-50/50 border border-gray-200/60\"\n }`}\n >\n {/* Connector Line */}\n {index < state.steps.length - 1 && (\n <div\n className={`absolute left-5 top-full w-0.5 h-2 bg-gradient-to-b ${\n theme === \"dark\"\n ? \"from-slate-500 to-slate-600\"\n : \"from-gray-300 to-gray-400\"\n }`}\n />\n )}\n\n {/* Status Icon */}\n <div\n className={`flex-shrink-0 w-6 h-6 rounded-full flex items-center justify-center mr-2 ${\n isCompleted\n ? theme === \"dark\"\n ? \"bg-gradient-to-br from-green-500 to-emerald-600 shadow-lg shadow-green-500/30\"\n : \"bg-gradient-to-br from-green-500 to-emerald-600 shadow-md shadow-green-200\"\n : isCurrentPending\n ? theme === \"dark\"\n ? \"bg-gradient-to-br from-blue-500 to-purple-600 shadow-lg shadow-blue-500/30\"\n : \"bg-gradient-to-br from-blue-500 to-purple-600 shadow-md shadow-blue-200\"\n : theme === \"dark\"\n ? \"bg-slate-700 border border-slate-600\"\n : \"bg-gray-300 border border-gray-400\"\n }`}\n >\n {isCompleted ? (\n <CheckIcon />\n ) : isCurrentPending ? (\n <SpinnerIcon />\n ) : (\n <ClockIcon theme={theme} />\n )}\n </div>\n\n {/* Step Content */}\n <div className=\"flex-1 min-w-0\">\n <div\n data-testid=\"task-step-text\"\n className={`font-semibold transition-all duration-300 text-sm ${\n isCompleted\n ? theme === \"dark\"\n ? \"text-green-300\"\n : \"text-green-700\"\n : isCurrentPending\n ? theme === \"dark\"\n ? \"text-blue-300 text-base\"\n : \"text-blue-700 text-base\"\n : theme === \"dark\"\n ? \"text-slate-400\"\n : \"text-gray-500\"\n }`}\n >\n {step.description}\n </div>\n {isCurrentPending && (\n <div\n className={`text-sm mt-1 animate-pulse ${\n theme === \"dark\" ? \"text-blue-400\" : \"text-blue-600\"\n }`}\n >\n Processing...\n </div>\n )}\n </div>\n\n {/* Animated Background for Current Step */}\n {isCurrentPending && (\n <div\n className={`absolute inset-0 rounded-lg bg-gradient-to-r animate-pulse ${\n theme === \"dark\"\n ? \"from-blue-500/10 to-purple-500/10\"\n : \"from-blue-100/50 to-purple-100/50\"\n }`}\n />\n )}\n </div>\n );\n })}\n </div>\n\n {/* Decorative Elements */}\n <div\n className={`absolute top-3 right-3 w-16 h-16 rounded-full blur-xl ${\n theme === \"dark\"\n ? \"bg-gradient-to-br from-blue-500/10 to-purple-500/10\"\n : \"bg-gradient-to-br from-blue-200/30 to-purple-200/30\"\n }`}\n />\n <div\n className={`absolute bottom-3 left-3 w-12 h-12 rounded-full blur-xl ${\n theme === \"dark\"\n ? \"bg-gradient-to-br from-green-500/10 to-emerald-500/10\"\n : \"bg-gradient-to-br from-green-200/30 to-emerald-200/30\"\n }`}\n />\n </div>\n </div>\n );\n },\n });\n\n return (\n <div className=\"flex justify-center items-center h-full w-full\">\n <div className=\"h-full w-full md:w-8/10 md:h-8/10 rounded-lg\">\n <CopilotChat\n className=\"h-full rounded-2xl max-w-6xl mx-auto\"\n labels={{\n initial:\n \"Hi, I'm an agent! I can help you with anything you need and will show you progress as I work. What can I do for you?\",\n }}\n suggestions={[\n {\n title: \"Simple plan\",\n message: \"Please build a plan to go to mars in 5 steps.\",\n },\n {\n title: \"Complex plan\",\n message: \"Please build a plan to go to make pizza in 10 steps.\",\n },\n ]}\n />\n </div>\n </div>\n );\n};\n\n// Enhanced Icons\nfunction CheckIcon() {\n return (\n <svg className=\"w-4 h-4 text-white\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={3} d=\"M5 13l4 4L19 7\" />\n </svg>\n );\n}\n\nfunction SpinnerIcon() {\n return (\n <svg\n className=\"w-4 h-4 animate-spin text-white\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n />\n </svg>\n );\n}\n\nfunction ClockIcon({ theme }: { theme?: string }) {\n return (\n <svg\n className={`w-3 h-3 ${theme === \"dark\" ? \"text-slate-400\" : \"text-gray-600\"}`}\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" strokeWidth=\"2\" />\n <polyline points=\"12,6 12,12 16,14\" strokeWidth=\"2\" />\n </svg>\n );\n}\n\nexport default AgenticGenerativeUI;\n",
0 commit comments