"use client"; import { CopilotKit, useCopilotAction, useCopilotChat } from "@copilotkit/react-core"; import { CopilotKitCSSProperties, CopilotChat } from "@copilotkit/react-ui"; import { useState } from "react"; import { useUser } from "@auth0/nextjs-auth0/client"; import LoginButton from "@/components/LoginButton"; import LogoutButton from "@/components/LogoutButton"; // Block input and show indicator while agent is processing function LoadingOverlay() { try { const { isLoading } = useCopilotChat(); if (!isLoading) return null; return ( <> {/* Overlay to block input area */}
e.stopPropagation()} /> {/* Thinking indicator */}
Thinking...
); } catch { return null; } } // Chat content with CopilotKit hooks - must be inside CopilotKit provider function ChatContent({ themeColor, setThemeColor }: { themeColor: string; setThemeColor: (color: string) => void }) { useCopilotAction({ name: "setThemeColor", parameters: [{ name: "themeColor", description: "The theme color to set. Make sure to pick nice colors.", required: true, }], handler({ themeColor }) { setThemeColor(themeColor); }, }); return (
); } export default function CopilotKitPage() { const [themeColor, setThemeColor] = useState("#6366f1"); const [sourcesOnlyMode, setSourcesOnlyMode] = useState(false); const { user, isLoading: authLoading } = useUser(); // Dynamic runtime URL based on sources-only mode const runtimeUrl = sourcesOnlyMode ? "/api/copilotkit?sourcesOnly=true" : "/api/copilotkit"; // Show loading state while checking authentication if (authLoading) { return (
Loading...
); } // If not authenticated, show login page if (!user) { return (
Auth0 Logo

Cavepedia

Welcome! Please log in to access the AI Cave Chat.

); } // If authenticated, show the CopilotKit chat with user profile return (
{/* Header with user profile and logout */}

Cavepedia

{user.picture && ( {user.name )}
{user.name} {(user as any).roles && (user as any).roles.length > 0 && ( {(user as any).roles.join(', ')} )}
{/* CopilotKit Chat */}
); }