diff --git a/src/interface/web/app/chat/chat.module.css b/src/interface/web/app/chat/chat.module.css
index 2ab692ea..1e2ee8ce 100644
--- a/src/interface/web/app/chat/chat.module.css
+++ b/src/interface/web/app/chat/chat.module.css
@@ -121,6 +121,7 @@ div.agentIndicator {
div.chatLayout {
gap: 0;
+ grid-template-columns: 1fr;
}
}
diff --git a/src/interface/web/app/chat/page.tsx b/src/interface/web/app/chat/page.tsx
index 7a508b7d..53a7ebc3 100644
--- a/src/interface/web/app/chat/page.tsx
+++ b/src/interface/web/app/chat/page.tsx
@@ -141,22 +141,22 @@ export default function Chat() {
return (
- {title}
+ Khoj AI - {title}
-
}>
-
)
}
diff --git a/src/interface/web/app/components/chatHistory/chatHistory.tsx b/src/interface/web/app/components/chatHistory/chatHistory.tsx
index 39462d9d..e594a824 100644
--- a/src/interface/web/app/components/chatHistory/chatHistory.tsx
+++ b/src/interface/web/app/components/chatHistory/chatHistory.tsx
@@ -118,7 +118,7 @@ export default function ChatHistory(props: ChatHistoryProps) {
setReferencePanelData={setReferencePanelData}
setShowReferencePanel={setShowReferencePanel}
customClassName='fullHistory'
- borderLeftColor='orange-400'
+ borderLeftColor='orange-500'
/>
))}
{
diff --git a/src/interface/web/app/components/chatMessage/chatMessage.module.css b/src/interface/web/app/components/chatMessage/chatMessage.module.css
index 328a1ba6..307050f5 100644
--- a/src/interface/web/app/components/chatMessage/chatMessage.module.css
+++ b/src/interface/web/app/components/chatMessage/chatMessage.module.css
@@ -14,7 +14,7 @@ div.chatMessageWrapper {
div.khojfullHistory {
border-color: var(--border-color);
border-width: 1px;
- padding-left: 24px;
+ padding-left: 4px;
}
div.youfullHistory {
@@ -105,6 +105,7 @@ button.codeCopyButton:hover {
}
div.feedbackButtons img,
+button.codeCopyButton img,
button.copyButton img {
width: 24px;
}
diff --git a/src/interface/web/app/components/chatMessage/chatMessage.tsx b/src/interface/web/app/components/chatMessage/chatMessage.tsx
index abb47233..15d6d400 100644
--- a/src/interface/web/app/components/chatMessage/chatMessage.tsx
+++ b/src/interface/web/app/components/chatMessage/chatMessage.tsx
@@ -154,6 +154,7 @@ export default function ChatMessage(props: ChatMessageProps) {
useEffect(() => {
if (messageRef.current) {
const preElements = messageRef.current.querySelectorAll('pre > .hljs');
+ console.log("make copy button");
preElements.forEach((preElement) => {
const copyButton = document.createElement('button');
const copyImage = document.createElement('img');
@@ -212,7 +213,8 @@ export default function ChatMessage(props: ChatMessageProps) {
classes.push(styles[chatMessage.by]);
if (chatMessage.by === "khoj") {
- classes.push(`border-l-4 border-opacity-50 border-l-orange-500 border-l-${props.borderLeftColor}`);
+ const dynamicBorderColor = `border-l-${props.borderLeftColor}`;
+ classes.push(`border-l-4 border-opacity-50 border-l-orange-400 ${dynamicBorderColor}`);
}
return classes.join(' ');
diff --git a/src/interface/web/app/components/loading/loading.tsx b/src/interface/web/app/components/loading/loading.tsx
index 709a1eaa..4f7ed1c8 100644
--- a/src/interface/web/app/components/loading/loading.tsx
+++ b/src/interface/web/app/components/loading/loading.tsx
@@ -1,26 +1,17 @@
import styles from './loading.module.css';
+import { CircleNotch } from '@phosphor-icons/react';
+
export default function Loading() {
- // return (
- //
- //
- //
- // )
return (
);
+}
+export function InlineLoading() {
return (
-
-
- Loading...
-
-
+
)
}
diff --git a/src/interface/web/app/components/navMenu/navMenu.tsx b/src/interface/web/app/components/navMenu/navMenu.tsx
index 5749e90c..3d829b1c 100644
--- a/src/interface/web/app/components/navMenu/navMenu.tsx
+++ b/src/interface/web/app/components/navMenu/navMenu.tsx
@@ -78,7 +78,7 @@ export default function NavMenu(props: NavMenuProps) {
:
-
+
Chat
diff --git a/src/interface/web/app/components/sidePanel/chatHistorySidePanel.tsx b/src/interface/web/app/components/sidePanel/chatHistorySidePanel.tsx
index 5c844738..e9fa2c78 100644
--- a/src/interface/web/app/components/sidePanel/chatHistorySidePanel.tsx
+++ b/src/interface/web/app/components/sidePanel/chatHistorySidePanel.tsx
@@ -9,10 +9,19 @@ import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar";
import Link from "next/link";
import useSWR from "swr";
+import {
+ Collapsible,
+ CollapsibleContent,
+ CollapsibleTrigger,
+} from "@/components/ui/collapsible";
+
+import { InlineLoading } from "../loading/loading";
+
import {
Dialog,
DialogContent,
DialogDescription,
+ DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
@@ -20,6 +29,8 @@ import {
import { ScrollArea } from "@/components/ui/scroll-area";
+import { ArrowRight, ArrowLeft, ArrowDown, Spinner } from "@phosphor-icons/react";
+
interface ChatHistory {
conversation_id: string;
slug: string;
@@ -35,9 +46,21 @@ import {
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
+import {
+ Popover,
+ PopoverContent,
+ PopoverTrigger,
+} from "@/components/ui/popover";
+
import { Pencil, Trash, Share } from "@phosphor-icons/react";
-import { Button } from "@/components/ui/button";
+import { Button, buttonVariants } from "@/components/ui/button";
+import { Input } from "@/components/ui/input";
+import { Label } from "@/components/ui/label";
+import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from "@/components/ui/alert-dialog";
+
+// Define a fetcher function
+const fetcher = (url: string) => fetch(url).then((res) => res.json());
interface GroupedChatHistory {
[key: string]: ChatHistory[];
@@ -47,7 +70,7 @@ function renameConversation(conversationId: string, newTitle: string) {
const editUrl = `/api/chat/title?client=web&conversation_id=${conversationId}&title=${newTitle}`;
fetch(editUrl, {
- method: 'POST',
+ method: 'PATCH',
headers: {
'Content-Type': 'application/json',
},
@@ -62,7 +85,7 @@ function renameConversation(conversationId: string, newTitle: string) {
});
}
-function shareConversation(conversationId: string) {
+function shareConversation(conversationId: string, setShareUrl: (url: string) => void) {
const shareUrl = `/api/chat/share?client=web&conversation_id=${conversationId}`;
fetch(shareUrl, {
@@ -74,6 +97,7 @@ function shareConversation(conversationId: string) {
.then(response => response.json())
.then(data => {
console.log(data);
+ setShareUrl(data.url);
})
.catch(err => {
console.error(err);
@@ -82,7 +106,7 @@ function shareConversation(conversationId: string) {
}
function deleteConversation(conversationId: string) {
- const deleteUrl = `/api/chat/delete?client=web&conversation_id=${conversationId}`;
+ const deleteUrl = `/api/chat/history?client=web&conversation_id=${conversationId}`;
fetch(deleteUrl, {
method: 'DELETE',
@@ -100,28 +124,354 @@ function deleteConversation(conversationId: string) {
});
}
+
+interface FilesMenuProps {
+ conversationId: string;
+}
+
+function FilesMenu(props: FilesMenuProps) {
+ // Use SWR to fetch files
+ const { data: files, error } = useSWR('/api/config/data/computer', fetcher);
+ const { data: selectedFiles, error: selectedFilesError } = useSWR(`/api/chat/conversation/file-filters/${props.conversationId}`, fetcher);
+ const [isOpen, setIsOpen] = useState(false);
+ const [searchInput, setSearchInput] = useState('');
+ const [filteredFiles, setFilteredFiles] = useState([]);
+
+ // Function to handle file click
+ const handleFileClick = (filename: string) => {
+ console.log(`File clicked: ${filename}`);
+ // Implement the logic you want to execute on file click
+ };
+
+ useEffect(() => {
+ if (!files) return;
+ if (searchInput === '') {
+ setFilteredFiles(files);
+ } else {
+ let filteredFiles = files.filter((filename: string) => filename.toLowerCase().includes(searchInput.toLowerCase()));
+ setFilteredFiles(filteredFiles);
+ }
+ }, [searchInput, files]);
+
+ if (error) return Failed to load files
;
+ if (!files) return ;
+
+ return (
+ <>
+ {/*
+
+ {files.length === 0 ? (
+
+ ) : (
+ files.map((filename: string) => (
+ - handleFileClick(filename)}>
+ {filename}
+
+ ))
+ )}
+
+ {files.length > 0 && }
+ */}
+
+
+
+
+
+
+ Manage Files
+
+ Using {files.length} files
+
+
+
+
+
+
+
+ setSearchInput(e.target.value)} />
+ {
+ filteredFiles.length === 0 && (
+
+ No files found
+
+ )
+ }
+ {
+ filteredFiles.map((filename: string) => (
+
+ {filename}
+
+ ))
+ }
+
+
+ {/*
+
+
+ Manage Files
+
+ Using {files.length} files
+
+
+
+
+
+
+
+ setSearchInput(e.target.value)} />
+ {
+ filteredFiles.length === 0 && (
+
+ No files found
+
+ )
+ }
+ {
+ filteredFiles.map((filename: string) => (
+
+ {filename}
+
+ ))
+ }
+
+ */}
+ >
+ )
+
+}
+
+interface SessionsAndFilesProps {
+ webSocketConnected?: boolean;
+ setEnabled: (enabled: boolean) => void;
+ subsetOrganizedData: GroupedChatHistory | null;
+ organizedData: GroupedChatHistory | null;
+ data: ChatHistory[] | null;
+ userProfile: UserProfile | null;
+}
+
+function SessionsAndFiles(props: SessionsAndFilesProps) {
+ return (
+ <>
+
+
+
+
+
+ {props.subsetOrganizedData != null && Object.keys(props.subsetOrganizedData).map((agentName) => (
+
+
+ {
+ props.subsetOrganizedData &&
+
+ }
+ {agentName}
+
+ {props.subsetOrganizedData && props.subsetOrganizedData[agentName].map((chatHistory) => (
+
+ ))}
+
+ ))}
+
+
+ {
+ (props.data && props.data.length > 5) && (
+
+ )
+ }
+
+ {props.userProfile &&
+
+ }>
+ )
+}
+
interface ChatSessionActionMenuProps {
conversationId: string;
}
function ChatSessionActionMenu(props: ChatSessionActionMenuProps) {
+ const [renamedTitle, setRenamedTitle] = useState('');
+ const [isRenaming, setIsRenaming] = useState(false);
+ const [isSharing, setIsSharing] = useState(false);
+ const [isDeleting, setIsDeleting] = useState(false);
+ const [shareUrl, setShareUrl] = useState('');
+ const [showShareUrl, setShowShareUrl] = useState(false);
+
+ const [isOpen, setIsOpen] = useState(false);
+
+ useEffect(() => {
+ if (isSharing) {
+ shareConversation(props.conversationId, setShareUrl);
+ setShowShareUrl(true);
+ setIsSharing(false);
+ }
+ }, [isSharing]);
+
+ if (isRenaming) {
+ return (
+
+ )
+ }
+
+ if (isSharing || showShareUrl) {
+ if (shareUrl) {
+ navigator.clipboard.writeText(shareUrl);
+ }
+ return (
+
+ )
+ }
+
+ if (isDeleting) {
+ console.log("Deleting");
+ return (
+ setIsDeleting(open)}>
+
+
+ Delete Conversation
+
+ Are you sure you want to delete this conversation? This action cannot be undone.
+
+
+
+ Cancel
+ {
+ deleteConversation(props.conversationId);
+ setIsDeleting(false);
+ }}
+ className="bg-rose-500 hover:bg-rose-600">Delete
+
+
+
+ )
+ }
return (
-
+ setIsOpen(open)}
+ open={isOpen}>
:
-
- shareConversation(props.conversationId)}>
+ setIsSharing(true)}>
Share
- deleteConversation(props.conversationId)}>
+ setIsDeleting(true)}>
Delete
@@ -151,27 +501,24 @@ interface ChatSessionsModalProps {
data: GroupedChatHistory | null;
}
-
-// function ConversationList()
-
function ChatSessionsModal({ data }: ChatSessionsModalProps) {
return (