"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 */}
>
);
} 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 (
);
}
// If not authenticated, show login page
if (!user) {
return (
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 as any).roles && (user as any).roles.length > 0 && (
{(user as any).roles.join(', ')}
)}
{/* CopilotKit Chat */}
);
}