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

Fix chat dave #89

Merged
merged 2 commits into from
Oct 5, 2024
Merged
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
6 changes: 0 additions & 6 deletions ai_course_bot/ai-chatbot/app/api/chat/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,6 @@ export async function POST(req: Request) {
var apiHost: string =
process.env['ROAR_BACKEND_HOST'] || 'http://0.0.0.0:9000'

if (courseId == 'CS 61A') {
apiHost = process.env['CS_61A_BACKEND_HOST'] || apiHost
} else if (courseId == 'EE 106b') {
apiHost = process.env['EE106B_BACKEND_HOST'] || apiHost
}

const apiUrl: string = apiHost + '/api/chat/completions'

try {
Expand Down
54 changes: 4 additions & 50 deletions ai_course_bot/ai-chatbot/app/core/components/chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,11 @@ import { ChatPanel } from '@/tai/components/chat-panel'
import { EmptyScreen } from '@/tai/components/empty-screen'
import { ChatScrollAnchor } from '@/tai/components/chat-scroll-anchor'
import { useLocalStorage } from '@/tai/lib/hooks/use-local-storage'
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle
} from '@/tai/components/ui/dialog'
import { useState } from 'react'
import { Button } from './ui/button'
import { Input } from './ui/input'
import { toast } from 'react-hot-toast'
import { usePathname, useRouter } from 'next/navigation'
import { SelectCourse } from '@/tai/components/select-course'
import { useSession } from 'next-auth/react'
import { m } from 'framer-motion'
import emitter from '@/tai/utils/eventEmitter'

const IS_PREVIEW = process.env.VERCEL_ENV === 'preview'
export interface ChatProps extends React.ComponentProps<'div'> {
Expand All @@ -40,8 +29,6 @@ export function Chat({ id, initialMessages, className }: ChatProps) {
'ai-token',
null
)
const [previewTokenDialog, setPreviewTokenDialog] = useState(IS_PREVIEW)
const [previewTokenInput, setPreviewTokenInput] = useState(previewToken ?? '')

const saveChat = async (
prev_messages: Message[],
Expand Down Expand Up @@ -85,6 +72,9 @@ export function Chat({ id, initialMessages, className }: ChatProps) {
if (!path.includes('chat')) {
window.history.replaceState({}, '', `/chat/${id}`)
router.replace(`/chat/${id}`)
setTimeout(() => {
emitter.emit('historyUpdated')
}, 2000)
}
} catch (error) {
console.error('Error saving chat:', error)
Expand Down Expand Up @@ -137,42 +127,6 @@ export function Chat({ id, initialMessages, className }: ChatProps) {
input={input}
setInput={setInput}
/>

<Dialog open={previewTokenDialog} onOpenChange={setPreviewTokenDialog}>
<DialogContent>
<DialogHeader>
<DialogTitle>Enter your OpenAI Key</DialogTitle>
<DialogDescription>
If you have not obtained your OpenAI API key, you can do so by{' '}
<a
href="https://platform.openai.com/signup/"
className="underline"
>
signing up
</a>{' '}
on the OpenAI website. This is only necessary for preview
environments so that the open source community can test the app.
The token will be saved to your browser&apos;s local storage under
the name <code className="font-mono">ai-token</code>.
</DialogDescription>
</DialogHeader>
<Input
value={previewTokenInput}
placeholder="OpenAI API key"
onChange={e => setPreviewTokenInput(e.target.value)}
/>
<DialogFooter className="items-center">
<Button
onClick={() => {
setPreviewToken(previewTokenInput)
setPreviewTokenDialog(false)
}}
>
Save Token
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { useRouter } from 'next/navigation'
import * as React from 'react'
import { toast } from 'react-hot-toast'
import emitter from '@/tai/utils/eventEmitter'

import { ServerActionResult, type Chat } from '@/tai/lib/types'
import {
Expand Down Expand Up @@ -111,6 +112,8 @@ export function SidebarActions({
router.refresh()
router.push('/')
toast.success('Chat deleted')

emitter.emit('historyUpdated')
})
}}
>
Expand Down
43 changes: 35 additions & 8 deletions ai_course_bot/ai-chatbot/app/core/components/sidebar-list.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,48 @@
'use client'
import { clearChats, getChats } from '@/tai/utils/actions'
import { ClearHistory } from '@/tai/components/clear-history'
import { SidebarItems } from '@/tai/components/sidebar-items'
import { ThemeToggle } from '@/tai/components/theme-toggle'
import { cache } from 'react'
import { useState, useEffect } from 'react'
import emitter from '@/tai/utils/eventEmitter'
import { type Chat } from '@/tai/lib/types'

interface SidebarListProps {
userId?: string
children?: React.ReactNode
}

const loadChats = cache(async (userId?: string) => {
return await getChats(userId)
})
export function SidebarList({ userId }: SidebarListProps) {
const [chats, setChats] = useState<Chat[] | undefined>(undefined)

const loadChats = async () => {
try {
const data = await getChats(userId)
setChats(data)
} catch (error) {
console.error('Error fetching chats:', error)
}
}

useEffect(() => {
loadChats()

const handleChatSaved = () => {
loadChats()
}

emitter.on('historyUpdated', handleChatSaved)

return () => {
emitter.off('historyUpdated', handleChatSaved)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])

export async function SidebarList({ userId }: SidebarListProps) {
const chats = await loadChats(userId)
return (
<div className="flex flex-1 flex-col overflow-hidden">
<div className="flex-1 overflow-auto">
{chats?.length ? (
{chats === undefined ? null : chats.length > 0 ? (
<div className="space-y-2 px-2">
<SidebarItems chats={chats} />
</div>
Expand All @@ -30,7 +54,10 @@ export async function SidebarList({ userId }: SidebarListProps) {
</div>
<div className="flex items-center justify-between p-4">
<ThemeToggle />
<ClearHistory clearChats={clearChats} isEnabled={chats?.length > 0} />
<ClearHistory
clearChats={clearChats}
isEnabled={!!(chats?.length ?? 0)}
/>
</div>
</div>
)
Expand Down
5 changes: 5 additions & 0 deletions ai_course_bot/ai-chatbot/app/core/utils/eventEmitter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import mitt from 'mitt'

const emitter = mitt()

export default emitter
27 changes: 23 additions & 4 deletions ai_course_bot/ai-chatbot/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion ai_course_bot/ai-chatbot/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"focus-trap-react": "^10.2.3",
"framer-motion": "^10.18.0",
"geist": "^1.2.1",
"mitt": "^3.0.1",
"nanoid": "^5.0.4",
"next": "^14.1.0",
"next-auth": "5.0.0-beta.4",
Expand All @@ -44,7 +45,8 @@
"react-syntax-highlighter": "^15.5.0",
"react-textarea-autosize": "^8.5.3",
"remark-gfm": "^3.0.1",
"remark-math": "^5.1.1"
"remark-math": "^5.1.1",
"swr": "^2.2.5"
},
"devDependencies": {
"@tailwindcss/typography": "^0.5.10",
Expand Down
Loading