Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wip: continuous thread logic and UI. #305

Draft
wants to merge 2 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import React from 'react'
import BrowseChatbotDetails from '@/components/routes/browse/browse-chatbot-details'
import { BrowseChatMessageList } from '@/components/routes/browse/browse-chat-message-list'
import { getMessages } from '@/services/hasura'
import { ExternalLink } from '@/components/shared/external-link'
import { toSlug } from 'mb-lib'

export type MessagePair = {
userMessage: Message
Expand All @@ -44,6 +46,8 @@ export function BrowseChatMessages({
chatbot?: Chatbot
}) {
const [messages, setMessages] = React.useState<Message[]>([])
const { name: categoryName } = chatbot?.categories[0].category || { name: '' }
const { name: chatBotName } = chatbot || { name: '' }

// Fetch messages for the specified thread ID
const fetchMessages = async () => {
Expand All @@ -68,6 +72,10 @@ export function BrowseChatMessages({
messages={messages}
isThread
/>

<div className="border-t border-t-iron dark:border-t-mirage pt-6 text-center mt-44 lg:mt-96">
<ExternalLink href={`/c/${toSlug(categoryName)}/${toSlug(chatBotName)}?continuousThreadId=${threadId}`}>Continue Thread</ExternalLink>
</div>
</div>
</div>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,42 @@
import { ThreadPopup } from '@/components/routes/thread/thread-popup'
import { useThread } from '@/lib/hooks/use-thread'
import { cn } from '@/lib/utils'
import { useSearchParams } from 'next/navigation'
import { useEffect } from 'react'
import type * as React from 'react'
import { getThread } from '@/services/hasura'
import { useSession } from 'next-auth/react'

//* ChatLayoutSection provides the main chat area layout with optional thread popup and responsive styling.
export function ChatLayoutSection({ children }: { children: React.ReactNode }) {
const { sectionRef, isOpenPopup } = useThread()
const { data: session } = useSession()
const { sectionRef, isOpenPopup, setIsOpenPopup, setActiveThread, setIsActiveThreadContinuous } = useThread()
const searchParams = useSearchParams()
const continuousThreadId = searchParams.get('continuousThreadId')

// Get the continuousThread from the query param url
const getContinuousThread = async () => {
if (!session?.user) return
if (!continuousThreadId) return

try {
const thread = await getThread({
threadId: continuousThreadId,
jwt: session!.user?.hasuraJwt,
});

setActiveThread(thread);
setIsActiveThreadContinuous(true)
setIsOpenPopup(true);
} catch (error) {
console.error('Error getting continuous thread from the query param:', error)
throw error
}
}

useEffect(() => {
getContinuousThread();
}, [session?.user])

return (
<section
Expand Down
54 changes: 4 additions & 50 deletions apps/masterbots.ai/components/routes/chat/chat-options.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,3 @@
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle
} from '@/components/ui/alert-dialog'
import { Button } from '@/components/ui/button'
import {
DropdownMenu,
Expand All @@ -16,7 +6,6 @@ import {
DropdownMenuSeparator,
DropdownMenuTrigger
} from '@/components/ui/dropdown-menu'
import { IconSpinner } from '@/components/ui/icons'
import { useThreadVisibility } from '@/lib/hooks/use-thread-visibility'
import { BadgeCheck, Eye, EyeOff, MoreVertical, Trash } from 'lucide-react'
import type { Thread } from 'mb-genql'
Expand All @@ -25,6 +14,7 @@ import type React from 'react'
import { useState } from 'react'
import toast from 'react-hot-toast'
import { ShareButton } from './share-button'
import { AlertDialogue } from '@/components/shared/alert-dialogue'

interface ChatOptionsProps {
threadId: string
Expand All @@ -40,8 +30,8 @@ export function ChatOptions({ threadId, thread, isBrowse }: ChatOptionsProps) {
const text =
thread?.messages[1]?.content.substring(0, 100) ?? 'No description found...'
const url = `/${toSlug(thread.chatbot.categories[0].category.name)}/${thread.threadId}`
const [isDeleteOpen, setIsDeleteOpen] = useState(false)
const [isDeleting, setIsDeleting] = useState(false)
const [isDeleteOpen, setIsDeleteOpen] = useState<boolean>(false)
const [isDeleting, setIsDeleting] = useState<boolean>(false)

const handleDelete = async (
e: React.MouseEvent<HTMLButtonElement, MouseEvent>
Expand All @@ -58,45 +48,9 @@ export function ChatOptions({ threadId, thread, isBrowse }: ChatOptionsProps) {
setIsDeleteOpen(false)
}

const AlertDialogue = ({
deleteDialogOpen
}: {
deleteDialogOpen: boolean
}) => (
<AlertDialog open={deleteDialogOpen}>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>
<AlertDialogDescription>
This will permanently delete your thread and remove your data from
our servers.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel
onClick={e => {
e.stopPropagation()
setIsDeleteOpen(false)
}}
>
Cancel
</AlertDialogCancel>
<AlertDialogAction
onClick={e => {
e.stopPropagation()
handleDelete(e)
}}
>
{isDeleting && <IconSpinner className="w-4 h-4 animate-spin" />}
Delete
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
)
return (
<div className="flex items-center gap-1 sm:gap-3 pt-[3px]">
<AlertDialogue deleteDialogOpen={isDeleteOpen} />
<AlertDialogue title="Are you absolutely sure?" description="This will permanently delete your thread and remove your data from our servers." deleteDialogOpen={isDeleteOpen} isDeleting={isDeleting} setIsDeleteOpen={setIsDeleteOpen} handleDelete={handleDelete} />
{!isBrowse && (
<div className="flex items-center gap-1 sm:gap-3">
<div>
Expand Down
21 changes: 16 additions & 5 deletions apps/masterbots.ai/components/routes/chat/chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

/**
* Chat Component
*
*
* A complex chat interface that handles:
* - Message management for new and existing chat threads
* - Integration with AI models for message processing and responses
Expand All @@ -14,15 +14,15 @@
* - Chat thread creation and state management
* - Message improvement and metadata extraction using AI
* - Automatic scrolling behavior
*
*
* Key Features:
* - Supports both popup and inline chat modes
* - Handles message processing states (processing, digesting, generating, etc.)
* - Manages chat thread creation and persistence
* - Integrates with multiple chatbot models
* - Provides real-time message streaming
* - Maintains chat history and system prompts
*
*
* State Management:
* - Uses useChat for message handling
* - Manages loading states for UI feedback
Expand Down Expand Up @@ -58,7 +58,7 @@ import { useScroll } from "framer-motion";
import { uniqBy } from "lodash";
import { useSession } from "next-auth/react";
import { useParams } from "next/navigation";
import React, { useEffect } from "react";
import React, { useEffect, useState } from "react";
import { toast } from "react-hot-toast";

export function Chat({
Expand Down Expand Up @@ -91,7 +91,6 @@ export function Chat({
const isNewChat = Boolean(!params.threadId && !activeThread);
const { selectedModel, clientType } = useModel();
const [loadingState, setLoadingState] = React.useState<ChatLoadingState>();

const { messages, append, reload, stop, isLoading, input, setInput } =
useChat({
initialMessages:
Expand Down Expand Up @@ -260,6 +259,18 @@ export function Chat({
setLoadingState("ready");

setIsNewResponse(true);
// console.log('userMessage', userMessage);
// let appendMessages = isNewChat
// ? { ...userMessage, content: userContent }
// : {
// ...userMessage,
// content: followingQuestionsPrompt(userContent, allMessages),
// }
// // TODO: looks for a better way to append messages or maybe a different chat architecture for continuous chat.
// appendMessages = isActiveThreadContinuous ? {
// ...userMessage,
// content: followingQuestionsPrompt(userContent, allMessages),
// } : appendMessages

return append(
isNewChat
Expand Down
Loading