mirror of
https://github.com/khoaliber/khoj.git
synced 2026-03-07 21:29:13 +00:00
Merge branch 'features/clean-up-authenticated-data' of github.com:khoj-ai/khoj into features/update-home-page
This commit is contained in:
@@ -140,7 +140,11 @@ function CreateAgentCard(props: CreateAgentCardProps) {
|
|||||||
Create Agent
|
Create Agent
|
||||||
</div>
|
</div>
|
||||||
</DialogTrigger>
|
</DialogTrigger>
|
||||||
<DialogContent className={"lg:max-w-screen-lg overflow-y-scroll max-h-screen"}>
|
<DialogContent
|
||||||
|
className={
|
||||||
|
"lg:max-w-screen-lg py-4 overflow-y-scroll h-full md:h-4/6 rounded-lg flex flex-col"
|
||||||
|
}
|
||||||
|
>
|
||||||
<DialogHeader>Create Agent</DialogHeader>
|
<DialogHeader>Create Agent</DialogHeader>
|
||||||
{!props.userProfile && showLoginPrompt && (
|
{!props.userProfile && showLoginPrompt && (
|
||||||
<LoginPrompt
|
<LoginPrompt
|
||||||
@@ -300,35 +304,37 @@ export default function Agents() {
|
|||||||
<div className={`pt-6 md:pt-8 flex justify-between`}>
|
<div className={`pt-6 md:pt-8 flex justify-between`}>
|
||||||
<h1 className="text-3xl flex items-center">Agents</h1>
|
<h1 className="text-3xl flex items-center">Agents</h1>
|
||||||
<div className="ml-auto float-right border p-2 pt-3 rounded-xl font-bold hover:bg-stone-100 dark:hover:bg-neutral-900">
|
<div className="ml-auto float-right border p-2 pt-3 rounded-xl font-bold hover:bg-stone-100 dark:hover:bg-neutral-900">
|
||||||
{authenticatedData && (
|
<CreateAgentCard
|
||||||
<CreateAgentCard
|
data={{
|
||||||
data={{
|
slug: "",
|
||||||
slug: "",
|
name: "",
|
||||||
name: "",
|
persona: "",
|
||||||
persona: "",
|
color: "",
|
||||||
color: "",
|
icon: "",
|
||||||
icon: "",
|
privacy_level: "private",
|
||||||
privacy_level: "private",
|
managed_by_admin: false,
|
||||||
managed_by_admin: false,
|
chat_model: "",
|
||||||
chat_model: "",
|
input_tools: [],
|
||||||
input_tools: [],
|
output_modes: [],
|
||||||
output_modes: [],
|
}}
|
||||||
}}
|
userProfile={
|
||||||
userProfile={authenticatedData}
|
authenticationLoading
|
||||||
isMobileWidth={isMobileWidth}
|
? null
|
||||||
filesOptions={filesData || []}
|
: (authenticatedData ?? null)
|
||||||
modelOptions={userConfig?.chat_model_options || []}
|
}
|
||||||
selectedChatModelOption={defaultModelOption?.name || ""}
|
isMobileWidth={isMobileWidth}
|
||||||
isSubscribed={isSubscribed}
|
filesOptions={filesData || []}
|
||||||
setAgentChangeTriggered={setAgentChangeTriggered}
|
modelOptions={userConfig?.chat_model_options || []}
|
||||||
inputToolOptions={
|
selectedChatModelOption={defaultModelOption?.name || ""}
|
||||||
agentConfigurationOptions?.input_tools || {}
|
isSubscribed={isSubscribed}
|
||||||
}
|
setAgentChangeTriggered={setAgentChangeTriggered}
|
||||||
outputModeOptions={
|
inputToolOptions={
|
||||||
agentConfigurationOptions?.output_modes || {}
|
agentConfigurationOptions?.input_tools || {}
|
||||||
}
|
}
|
||||||
/>
|
outputModeOptions={
|
||||||
)}
|
agentConfigurationOptions?.output_modes || {}
|
||||||
|
}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{showLoginPrompt && (
|
{showLoginPrompt && (
|
||||||
|
|||||||
@@ -429,7 +429,7 @@ export function AgentCard(props: AgentCardProps) {
|
|||||||
{props.editCard ? (
|
{props.editCard ? (
|
||||||
<DialogContent
|
<DialogContent
|
||||||
className={
|
className={
|
||||||
"lg:max-w-screen-lg py-4 overflow-y-scroll h-4/6 rounded-lg flex flex-col"
|
"lg:max-w-screen-lg py-4 overflow-y-scroll h-full md:h-4/6 rounded-lg flex flex-col"
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<DialogTitle>
|
<DialogTitle>
|
||||||
@@ -535,6 +535,8 @@ export function AgentModificationForm(props: AgentModificationFormProps) {
|
|||||||
const basicFields = [
|
const basicFields = [
|
||||||
{ name: "name", label: "Name" },
|
{ name: "name", label: "Name" },
|
||||||
{ name: "persona", label: "Personality" },
|
{ name: "persona", label: "Personality" },
|
||||||
|
{ name: "color", label: "Color" },
|
||||||
|
{ name: "icon", label: "Icon" },
|
||||||
];
|
];
|
||||||
|
|
||||||
const toolsFields = [
|
const toolsFields = [
|
||||||
@@ -545,17 +547,15 @@ export function AgentModificationForm(props: AgentModificationFormProps) {
|
|||||||
const knowledgeBaseFields = [{ name: "files", label: "Knowledge Base" }];
|
const knowledgeBaseFields = [{ name: "files", label: "Knowledge Base" }];
|
||||||
|
|
||||||
const customizationFields = [
|
const customizationFields = [
|
||||||
{ name: "color", label: "Color" },
|
|
||||||
{ name: "icon", label: "Icon" },
|
|
||||||
{ name: "chat_model", label: "Chat Model" },
|
{ name: "chat_model", label: "Chat Model" },
|
||||||
{ name: "privacy_level", label: "Privacy Level" },
|
{ name: "privacy_level", label: "Privacy Level" },
|
||||||
];
|
];
|
||||||
|
|
||||||
const formGroups = [
|
const formGroups = [
|
||||||
{ fields: basicFields, label: "Basic Settings", tabName: "basic" },
|
{ fields: basicFields, label: "1. Basic Settings", tabName: "basic" },
|
||||||
{ fields: customizationFields, label: "Customization & Access", tabName: "customize" },
|
{ fields: customizationFields, label: "2. Model & Privacy", tabName: "customize" },
|
||||||
{ fields: knowledgeBaseFields, label: "Knowledge Base", tabName: "knowledge" },
|
{ fields: knowledgeBaseFields, label: "3. Knowledge Base", tabName: "knowledge" },
|
||||||
{ fields: toolsFields, label: "Tools Settings", tabName: "tools" },
|
{ fields: toolsFields, label: "4. Tools", tabName: "tools" },
|
||||||
];
|
];
|
||||||
|
|
||||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||||
@@ -754,7 +754,7 @@ export function AgentModificationForm(props: AgentModificationFormProps) {
|
|||||||
control={props.form.control}
|
control={props.form.control}
|
||||||
name="chat_model"
|
name="chat_model"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="my-3 grid gap-2">
|
<FormItem className="my-2 grid gap-2">
|
||||||
<FormLabel>Chat Model</FormLabel>
|
<FormLabel>Chat Model</FormLabel>
|
||||||
<FormDescription>
|
<FormDescription>
|
||||||
{!props.isSubscribed ? (
|
{!props.isSubscribed ? (
|
||||||
@@ -801,7 +801,7 @@ export function AgentModificationForm(props: AgentModificationFormProps) {
|
|||||||
control={props.form.control}
|
control={props.form.control}
|
||||||
name="privacy_level"
|
name="privacy_level"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="my-3 grid gap-2">
|
<FormItem className="my-2 grid gap-2">
|
||||||
<FormLabel>
|
<FormLabel>
|
||||||
<div>Privacy Level</div>
|
<div>Privacy Level</div>
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
@@ -858,7 +858,7 @@ export function AgentModificationForm(props: AgentModificationFormProps) {
|
|||||||
control={props.form.control}
|
control={props.form.control}
|
||||||
name="color"
|
name="color"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="space-y-3">
|
<FormItem className="space-y-3 my-2">
|
||||||
<FormLabel>Color</FormLabel>
|
<FormLabel>Color</FormLabel>
|
||||||
<Select onValueChange={field.onChange} defaultValue={field.value}>
|
<Select onValueChange={field.onChange} defaultValue={field.value}>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
@@ -892,7 +892,7 @@ export function AgentModificationForm(props: AgentModificationFormProps) {
|
|||||||
control={props.form.control}
|
control={props.form.control}
|
||||||
name="icon"
|
name="icon"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="space-y-3">
|
<FormItem className="space-y-3 my-2">
|
||||||
<FormLabel>Icon</FormLabel>
|
<FormLabel>Icon</FormLabel>
|
||||||
<Select onValueChange={field.onChange} defaultValue={field.value}>
|
<Select onValueChange={field.onChange} defaultValue={field.value}>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
@@ -928,12 +928,12 @@ export function AgentModificationForm(props: AgentModificationFormProps) {
|
|||||||
control={props.form.control}
|
control={props.form.control}
|
||||||
name="persona"
|
name="persona"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="space-y-1 grid gap-2">
|
<FormItem className="space-y-1 my-2 grid gap-2">
|
||||||
<FormLabel>Personality</FormLabel>
|
<FormLabel>Personality</FormLabel>
|
||||||
<FormDescription>
|
<FormDescription>
|
||||||
What is the personality, thought process, or tuning of this
|
What is the personality, thought process, or tuning of this
|
||||||
agent? Get creative; this is how you can influence the agent
|
agent? This is where you can provide any instructions to the
|
||||||
constitution.
|
agent.
|
||||||
</FormDescription>
|
</FormDescription>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Textarea
|
<Textarea
|
||||||
@@ -954,7 +954,7 @@ export function AgentModificationForm(props: AgentModificationFormProps) {
|
|||||||
control={props.form.control}
|
control={props.form.control}
|
||||||
name="files"
|
name="files"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="flex flex-col gap-2">
|
<FormItem className="my-2 flex flex-col gap-2">
|
||||||
<FormLabel>Knowledge Base</FormLabel>
|
<FormLabel>Knowledge Base</FormLabel>
|
||||||
<FormDescription>
|
<FormDescription>
|
||||||
Which information should be part of its digital brain?{" "}
|
Which information should be part of its digital brain?{" "}
|
||||||
@@ -1259,7 +1259,7 @@ export function AgentModificationForm(props: AgentModificationFormProps) {
|
|||||||
<Form {...props.form}>
|
<Form {...props.form}>
|
||||||
<form
|
<form
|
||||||
onSubmit={props.form.handleSubmit(handleSubmit)}
|
onSubmit={props.form.handleSubmit(handleSubmit)}
|
||||||
className="space-y-6 h-full flex flex-col justify-between"
|
className="space-y-6 pb-4 h-full flex flex-col justify-between"
|
||||||
>
|
>
|
||||||
<Tabs defaultValue="basic" value={formGroups[currentStep].tabName}>
|
<Tabs defaultValue="basic" value={formGroups[currentStep].tabName}>
|
||||||
<TabsList className="grid grid-cols-2 md:grid-cols-4 gap-2 h-fit">
|
<TabsList className="grid grid-cols-2 md:grid-cols-4 gap-2 h-fit">
|
||||||
@@ -1267,13 +1267,15 @@ export function AgentModificationForm(props: AgentModificationFormProps) {
|
|||||||
<TabsTrigger
|
<TabsTrigger
|
||||||
key={group.tabName}
|
key={group.tabName}
|
||||||
value={group.tabName}
|
value={group.tabName}
|
||||||
|
className={`text-center ${areRequiredFieldsCompletedForCurrentStep(group) ? "" : "text-red-500"}`}
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
setCurrentStep(
|
setCurrentStep(
|
||||||
formGroups.findIndex((g) => g.tabName === group.tabName),
|
formGroups.findIndex((g) => g.tabName === group.tabName),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{group.label}
|
{group.label}{" "}
|
||||||
|
{!areRequiredFieldsCompletedForCurrentStep(group) && "*"}
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
))}
|
))}
|
||||||
</TabsList>
|
</TabsList>
|
||||||
@@ -1304,7 +1306,7 @@ export function AgentModificationForm(props: AgentModificationFormProps) {
|
|||||||
}
|
}
|
||||||
className={`items-center ${isSaving ? "bg-stone-100 dark:bg-neutral-900" : ""} text-white ${colorOptionClassName}`}
|
className={`items-center ${isSaving ? "bg-stone-100 dark:bg-neutral-900" : ""} text-white ${colorOptionClassName}`}
|
||||||
>
|
>
|
||||||
Next
|
Continue
|
||||||
<ArrowRight className="ml-2 h-4 w-4" />
|
<ArrowRight className="ml-2 h-4 w-4" />
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@@ -883,13 +883,9 @@ const fetchChatHistory = async (url: string) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const useChatSessionsFetchRequest = (url: string) => {
|
export const useChatSessionsFetchRequest = (url: string) => {
|
||||||
const { data, error } = useSWR<ChatHistory[]>(url, fetchChatHistory);
|
const { data, isLoading, error } = useSWR<ChatHistory[]>(url, fetchChatHistory);
|
||||||
|
|
||||||
return {
|
return { data, isLoading, error };
|
||||||
data,
|
|
||||||
isLoading: !error && !data,
|
|
||||||
isError: error,
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
interface SidePanelProps {
|
interface SidePanelProps {
|
||||||
@@ -965,10 +961,12 @@ export default function AllConversations(props: SidePanelProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<SidebarGroup>
|
<SidebarGroup>
|
||||||
<SidebarGroupLabel className="!p-0 m-0 px-0">Conversations</SidebarGroupLabel>
|
|
||||||
<div className={`flex justify-between flex-col`}>
|
<div className={`flex justify-between flex-col`}>
|
||||||
{authenticatedData && (
|
{authenticatedData && (
|
||||||
<>
|
<>
|
||||||
|
<SidebarGroupLabel className="!p-0 m-0 px-0">
|
||||||
|
Conversations
|
||||||
|
</SidebarGroupLabel>
|
||||||
<div
|
<div
|
||||||
className={`${props.sideBarOpen ? "border-l-2 border-light-blue-500 border-opacity-25 " : ""}`}
|
className={`${props.sideBarOpen ? "border-l-2 border-light-blue-500 border-opacity-25 " : ""}`}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -20,9 +20,12 @@ import { Gear } from "@phosphor-icons/react/dist/ssr";
|
|||||||
import { Plus } from "@phosphor-icons/react";
|
import { Plus } from "@phosphor-icons/react";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import AllConversations from "../allConversations/allConversations";
|
import AllConversations from "../allConversations/allConversations";
|
||||||
import NavMenu from "../navMenu/navMenu";
|
import FooterMenu from "../navMenu/navMenu";
|
||||||
import { useSidebar } from "@/components/ui/sidebar";
|
import { useSidebar } from "@/components/ui/sidebar";
|
||||||
import { useIsMobileWidth } from "@/app/common/utils";
|
import { useIsMobileWidth } from "@/app/common/utils";
|
||||||
|
import { UserPlusIcon } from "lucide-react";
|
||||||
|
import { useAuthenticatedData } from "@/app/common/auth";
|
||||||
|
import LoginPrompt from "../loginPrompt/loginPrompt";
|
||||||
|
|
||||||
// Menu items.
|
// Menu items.
|
||||||
const items = [
|
const items = [
|
||||||
@@ -63,12 +66,21 @@ interface AppSidebarProps {
|
|||||||
|
|
||||||
export function AppSidebar(props: AppSidebarProps) {
|
export function AppSidebar(props: AppSidebarProps) {
|
||||||
const isMobileWidth = useIsMobileWidth();
|
const isMobileWidth = useIsMobileWidth();
|
||||||
|
const { data, isLoading, error } = useAuthenticatedData();
|
||||||
|
|
||||||
const { state, open, setOpen, openMobile, setOpenMobile, isMobile, toggleSidebar } =
|
const { state, open, setOpen, openMobile, setOpenMobile, isMobile, toggleSidebar } =
|
||||||
useSidebar();
|
useSidebar();
|
||||||
|
|
||||||
|
const [showLoginPrompt, setShowLoginPrompt] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isLoading && !data) {
|
||||||
|
setShowLoginPrompt(true);
|
||||||
|
}
|
||||||
|
}, [isLoading, data]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Sidebar collapsible={"icon"} variant="sidebar">
|
<Sidebar collapsible={"icon"} variant="sidebar" className="md:py-2">
|
||||||
<SidebarHeader>
|
<SidebarHeader>
|
||||||
<SidebarMenu className="p-0 m-0">
|
<SidebarMenu className="p-0 m-0">
|
||||||
<SidebarMenuItem className="p-0 m-0">
|
<SidebarMenuItem className="p-0 m-0">
|
||||||
@@ -82,7 +94,6 @@ export function AppSidebar(props: AppSidebarProps) {
|
|||||||
<SidebarMenuButton asChild>
|
<SidebarMenuButton asChild>
|
||||||
<a className="flex items-center gap-2 no-underline" href="/">
|
<a className="flex items-center gap-2 no-underline" href="/">
|
||||||
<KhojLogo className="w-14 h-auto" />
|
<KhojLogo className="w-14 h-auto" />
|
||||||
<span className="text-lg">Khoj</span>
|
|
||||||
</a>
|
</a>
|
||||||
</SidebarMenuButton>
|
</SidebarMenuButton>
|
||||||
)}
|
)}
|
||||||
@@ -90,9 +101,29 @@ export function AppSidebar(props: AppSidebarProps) {
|
|||||||
</SidebarMenu>
|
</SidebarMenu>
|
||||||
</SidebarHeader>
|
</SidebarHeader>
|
||||||
<SidebarContent>
|
<SidebarContent>
|
||||||
|
{showLoginPrompt && (
|
||||||
|
<LoginPrompt
|
||||||
|
onOpenChange={(isOpen) => setShowLoginPrompt(isOpen)}
|
||||||
|
isMobileWidth={isMobileWidth}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<SidebarGroup>
|
<SidebarGroup>
|
||||||
<SidebarGroupContent>
|
<SidebarGroupContent>
|
||||||
<SidebarMenu className="p-0 m-0">
|
<SidebarMenu className="p-0 m-0">
|
||||||
|
{!isLoading && !data && (
|
||||||
|
<SidebarMenuItem className="p-0 m-0 list-none">
|
||||||
|
<SidebarMenuButton
|
||||||
|
asChild
|
||||||
|
variant={"default"}
|
||||||
|
onClick={() => setShowLoginPrompt(true)}
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<UserPlusIcon />
|
||||||
|
<span>Sign up to get started</span>
|
||||||
|
</div>
|
||||||
|
</SidebarMenuButton>
|
||||||
|
</SidebarMenuItem>
|
||||||
|
)}
|
||||||
{items.map((item) => (
|
{items.map((item) => (
|
||||||
<SidebarMenuItem key={item.title} className="p-0 list-none m-0">
|
<SidebarMenuItem key={item.title} className="p-0 list-none m-0">
|
||||||
<SidebarMenuButton asChild>
|
<SidebarMenuButton asChild>
|
||||||
@@ -117,7 +148,7 @@ export function AppSidebar(props: AppSidebarProps) {
|
|||||||
</SidebarGroup>
|
</SidebarGroup>
|
||||||
</SidebarContent>
|
</SidebarContent>
|
||||||
<SidebarFooter>
|
<SidebarFooter>
|
||||||
<NavMenu sideBarIsOpen={open} />
|
<FooterMenu sideBarIsOpen={open} />
|
||||||
</SidebarFooter>
|
</SidebarFooter>
|
||||||
</Sidebar>
|
</Sidebar>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ interface NavMenuProps {
|
|||||||
sideBarIsOpen: boolean;
|
sideBarIsOpen: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function NavMenu({ sideBarIsOpen }: NavMenuProps) {
|
export default function FooterMenu({ sideBarIsOpen }: NavMenuProps) {
|
||||||
const {
|
const {
|
||||||
data: userData,
|
data: userData,
|
||||||
error: authenticationError,
|
error: authenticationError,
|
||||||
@@ -106,13 +106,13 @@ export default function NavMenu({ sideBarIsOpen }: NavMenuProps) {
|
|||||||
>
|
>
|
||||||
<AvatarImage src={userData?.photo} alt="user profile" />
|
<AvatarImage src={userData?.photo} alt="user profile" />
|
||||||
<AvatarFallback className="bg-transparent hover:bg-muted">
|
<AvatarFallback className="bg-transparent hover:bg-muted">
|
||||||
{userData?.username[0].toUpperCase()}
|
{userData.username[0].toUpperCase()}
|
||||||
</AvatarFallback>
|
</AvatarFallback>
|
||||||
</Avatar>
|
</Avatar>
|
||||||
{sideBarIsOpen && (
|
{sideBarIsOpen && (
|
||||||
<>
|
<>
|
||||||
<p>{userData?.username}</p>
|
<p>{userData?.username}</p>
|
||||||
<ChevronUp className="w-6 h-6" />
|
<ChevronUp className="w-6 h-6 ml-auto" />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -3,9 +3,6 @@ import { noto_sans, noto_sans_arabic } from "@/app/fonts";
|
|||||||
import "./globals.css";
|
import "./globals.css";
|
||||||
import { ContentSecurityPolicy } from "./common/layoutHelper";
|
import { ContentSecurityPolicy } from "./common/layoutHelper";
|
||||||
|
|
||||||
import { SidebarProvider, SidebarTrigger } from "@/components/ui/sidebar";
|
|
||||||
import { AppSidebar } from "@/app/components/appSidebar/appSidebar";
|
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "Khoj AI - Ask Anything",
|
title: "Khoj AI - Ask Anything",
|
||||||
description:
|
description:
|
||||||
|
|||||||
Reference in New Issue
Block a user