diff --git a/src/components/Settings/Elements/AddItemButton.tsx b/src/components/Settings/Elements/AddItemButton.tsx index e9450801..38e65a67 100644 --- a/src/components/Settings/Elements/AddItemButton.tsx +++ b/src/components/Settings/Elements/AddItemButton.tsx @@ -1,37 +1,37 @@ -import * as Dialog from "@radix-ui/react-dialog"; -import { useRef, useState } from "react"; -import { HiDocumentText, HiFolder } from "react-icons/hi"; -import TextareaAutosize from "react-textarea-autosize"; -import { Prompt, usePrompts } from "../../../hooks/usePrompts"; -import DialogPortal from "../../Layout/DialogPortal"; -import { getUUID } from "../../../lib/getUUID"; +import * as Dialog from '@radix-ui/react-dialog' +import { useRef, useState } from 'react' +import { HiDocumentText, HiFolder } from 'react-icons/hi' +import TextareaAutosize from 'react-textarea-autosize' +import { Prompt, usePrompts } from '../../../hooks/usePrompts' +import DialogPortal from '../../Layout/DialogPortal' +import { getUUID } from '../../../lib/getUUID' export const AddItemButton = ({ isCategory }: { isCategory: boolean }) => { - const [open, setOpen] = useState(false); - const [prompts, setPrompts] = usePrompts(); - const formRef = useRef(null); + const [open, setOpen] = useState(false) + const [prompts, setPrompts] = usePrompts() + const formRef = useRef(null) const handleAdd = () => { - if (!formRef.current || !formRef.current.reportValidity()) return; + if (!formRef.current || !formRef.current.reportValidity()) return - const formData = new FormData(formRef.current); + const formData = new FormData(formRef.current) - const newName = formData.get("promptName") as string; - const newPrompt = formData.get("prompt") as string; + const newName = formData.get('promptName') as string + const newPrompt = formData.get('prompt') as string const item = { id: getUUID(), name: newName, prompt: isCategory ? undefined : newPrompt, children: isCategory ? [] : undefined, - } as Prompt; + } as Prompt - const newPrompts = [...prompts, item]; - setPrompts([]); - setPrompts(newPrompts); + const newPrompts = [...prompts, item] + setPrompts([]) + setPrompts(newPrompts) - setOpen(false); - }; + setOpen(false) + } return ( @@ -52,7 +52,7 @@ export const AddItemButton = ({ isCategory }: { isCategory: boolean }) => { )} setOpen(false)} primaryText="Save" @@ -83,5 +83,5 @@ export const AddItemButton = ({ isCategory }: { isCategory: boolean }) => { - ); -}; + ) +} diff --git a/src/components/Settings/Elements/HistoryMenu.tsx b/src/components/Settings/Elements/HistoryMenu.tsx index 1ed089dd..2ef775a1 100644 --- a/src/components/Settings/Elements/HistoryMenu.tsx +++ b/src/components/Settings/Elements/HistoryMenu.tsx @@ -1,5 +1,3 @@ -const historyMenu = () => { +const historyMenu = () => {} -} - -export default historyMenu; +export default historyMenu diff --git a/src/components/Sidebar/chat/ChatHistory.tsx b/src/components/Sidebar/chat/ChatHistory.tsx index e713532c..6f773532 100644 --- a/src/components/Sidebar/chat/ChatHistory.tsx +++ b/src/components/Sidebar/chat/ChatHistory.tsx @@ -1,7 +1,7 @@ -import { useChatHistory } from '../../../hooks/useChatHistory'; -import * as Select from '@radix-ui/react-select'; -import { RiAddLine, RiTimeLine } from 'react-icons/ri'; -import { generateReadableRelativeDate } from '../../../utils/generateReadableDate'; +import { useChatHistory } from '../../../hooks/useChatHistory' +import * as Select from '@radix-ui/react-select' +import { RiAddLine, RiTimeLine } from 'react-icons/ri' +import { generateReadableRelativeDate } from '../../../utils/generateReadableDate' const ChatHistory = () => { const { @@ -9,10 +9,10 @@ const ChatHistory = () => { setCurrentChatId, currentChatId, getChatHistory, - createChatHistory - } = useChatHistory(); + createChatHistory, + } = useChatHistory() - const currentChat = getChatHistory(currentChatId); + const currentChat = getChatHistory(currentChatId) return (
@@ -34,7 +34,7 @@ const ChatHistory = () => { type='button' className='cdx-flex cdx-items-center cdx-bg-[#3B82F6] cdx-gap-1.5 cdx-px-2.5 cdx-py-1.5 cdx-rounded-sm cdx-font-medium' onClick={() => { - createChatHistory('New Chat'); + createChatHistory('New Chat') }} > @@ -70,7 +70,7 @@ const ChatHistory = () => {
- ); -}; + ) +} -export default ChatHistory; +export default ChatHistory diff --git a/src/components/Sidebar/chat/ChatInput.tsx b/src/components/Sidebar/chat/ChatInput.tsx index d14f08bd..7f626e5b 100644 --- a/src/components/Sidebar/chat/ChatInput.tsx +++ b/src/components/Sidebar/chat/ChatInput.tsx @@ -1,16 +1,16 @@ -import { useEffect, useState } from 'react'; -import TextareaAutosize from 'react-textarea-autosize'; -import { GiMagicBroom } from 'react-icons/gi'; -import { IoSend } from 'react-icons/io5'; -import { HiHand } from 'react-icons/hi'; -import ChatHistory from './ChatHistory'; +import { useEffect, useState } from 'react' +import TextareaAutosize from 'react-textarea-autosize' +import { GiMagicBroom } from 'react-icons/gi' +import { IoSend } from 'react-icons/io5' +import { HiHand } from 'react-icons/hi' +import ChatHistory from './ChatHistory' interface SidebarInputProps { - loading: boolean; - submitMessage: (prompt: string) => void; - clearMessages: () => void; - chatIsEmpty: boolean; - cancelRequest: () => void; + loading: boolean + submitMessage: (prompt: string) => void + clearMessages: () => void + chatIsEmpty: boolean + cancelRequest: () => void } export function SidebarInput({ @@ -18,24 +18,24 @@ export function SidebarInput({ submitMessage, clearMessages, chatIsEmpty, - cancelRequest + cancelRequest, }: SidebarInputProps) { - const [text, setText] = useState(''); - const [delayedLoading, setDelayedLoading] = useState(false); + const [text, setText] = useState('') + const [delayedLoading, setDelayedLoading] = useState(false) useEffect(() => { const handleLoadingTimeout = setTimeout(() => { - setDelayedLoading(loading); - }, 1000); + setDelayedLoading(loading) + }, 1000) return () => { - clearTimeout(handleLoadingTimeout); - }; - }, [loading]); + clearTimeout(handleLoadingTimeout) + } + }, [loading]) const handleSubmit = () => { - submitMessage(text); - setText(''); - }; + submitMessage(text) + setText('') + } return (
@@ -63,13 +63,13 @@ export function SidebarInput({ disabled={loading} className='cdx-p-3 cdx-w-full cdx-text-sm cdx-resize-none cdx-max-h-96 cdx-pb-0 cdx-bg-transparent !cdx-border-none focus:!cdx-outline-none' onChange={(e) => { - e.preventDefault(); - setText(e.target.value); + e.preventDefault() + setText(e.target.value) }} onKeyDown={(e) => { if (e.key === 'Enter' && !e.shiftKey) { - e.preventDefault(); - handleSubmit(); + e.preventDefault() + handleSubmit() } }} /> @@ -100,5 +100,5 @@ export function SidebarInput({
- ); + ) } diff --git a/src/components/Sidebar/chat/ChatList.tsx b/src/components/Sidebar/chat/ChatList.tsx index 05fea55b..6fdae23a 100644 --- a/src/components/Sidebar/chat/ChatList.tsx +++ b/src/components/Sidebar/chat/ChatList.tsx @@ -1,26 +1,26 @@ -import { ReactMarkdown } from "react-markdown/lib/react-markdown"; -import CodeBlock from "./markdown-components/CodeBlock"; -import remarkGfm from "remark-gfm"; -import { useEffect, useRef } from "react"; -import { Table } from "./markdown-components/Table"; -import remarkBreaks from "remark-breaks"; -import rehypeRaw from "rehype-raw"; -import { ChatMessage, ChatRole } from "../../../hooks/useCurrentChat"; +import { ReactMarkdown } from 'react-markdown/lib/react-markdown' +import CodeBlock from './markdown-components/CodeBlock' +import remarkGfm from 'remark-gfm' +import { useEffect, useRef } from 'react' +import { Table } from './markdown-components/Table' +import remarkBreaks from 'remark-breaks' +import rehypeRaw from 'rehype-raw' +import { ChatMessage, ChatRole } from '../../../hooks/useCurrentChat' interface ChatListProps { - messages: ChatMessage[]; + messages: ChatMessage[] } const ChatList = ({ messages }: ChatListProps) => { - const containerRef = useRef(null); + const containerRef = useRef(null) useEffect(() => { if (containerRef.current) { - containerRef.current.scrollTop = containerRef.current.scrollHeight; + containerRef.current.scrollTop = containerRef.current.scrollHeight } - }, [messages]); + }, [messages]) - const filteredMsgs = messages.filter((msg) => msg.role !== ChatRole.SYSTEM); + const filteredMsgs = messages.filter((msg) => msg.role !== ChatRole.SYSTEM) return (
{ .filter((msg) => msg.role !== ChatRole.SYSTEM) .map((msg, i) => (
@@ -60,13 +60,13 @@ const ChatList = ({ messages }: ChatListProps) => { table: Table, }} > - {msg.content.replace(/(?<=\n\n)(?![*-])\n/gi, " \n ")} + {msg.content.replace(/(?<=\n\n)(?![*-])\n/gi, ' \n ')}
)) )}
- ); -}; + ) +} -export default ChatList; +export default ChatList diff --git a/src/components/Sidebar/chat/index.tsx b/src/components/Sidebar/chat/index.tsx index a76ca40f..c4a86068 100644 --- a/src/components/Sidebar/chat/index.tsx +++ b/src/components/Sidebar/chat/index.tsx @@ -1,13 +1,13 @@ -import { useEffect } from 'react'; -import ChatList from './ChatList'; -import { SidebarInput } from './ChatInput'; -import { useChatCompletion } from '../../../hooks/useChatCompletion'; -import { SYSTEM_PROMPT } from '../../../config/prompts'; -import { Settings } from '../../../config/settings'; +import { useEffect } from 'react' +import ChatList from './ChatList' +import { SidebarInput } from './ChatInput' +import { useChatCompletion } from '../../../hooks/useChatCompletion' +import { SYSTEM_PROMPT } from '../../../config/prompts' +import { Settings } from '../../../config/settings' interface ChatProps { - settings: Settings; - chatId: string; + settings: Settings + chatId: string } const Chat = ({ settings, chatId }: ChatProps) => { @@ -17,25 +17,25 @@ const Chat = ({ settings, chatId }: ChatProps) => { apiKey: settings.chat.openAIKey!, mode: settings.chat.mode, systemPrompt: SYSTEM_PROMPT, - chatId - }); + chatId, + }) useEffect(() => { const handleWindowMessage = (event: MessageEvent) => { const { action, prompt } = event.data as { - action: string; - prompt: string; - }; + action: string + prompt: string + } if (action === 'generate') { - submitQuery(prompt); + submitQuery(prompt) } - }; - window.addEventListener('message', handleWindowMessage); + } + window.addEventListener('message', handleWindowMessage) return () => { - window.removeEventListener('message', handleWindowMessage); - }; - }, []); + window.removeEventListener('message', handleWindowMessage) + } + }, []) return ( <> @@ -48,7 +48,7 @@ const Chat = ({ settings, chatId }: ChatProps) => { cancelRequest={cancelRequest} /> - ); -}; + ) +} -export default Chat; +export default Chat diff --git a/src/components/Sidebar/index.tsx b/src/components/Sidebar/index.tsx index cd6e5c78..29fd44d9 100644 --- a/src/components/Sidebar/index.tsx +++ b/src/components/Sidebar/index.tsx @@ -1,14 +1,14 @@ -import Auth from "./auth"; -import Chat from "./chat"; -import Header from "./layout/header"; -import { useSettings } from "../../hooks/useSettings"; -import useThemeSync from "../../hooks/useThemeSync"; -import { useChatHistory } from "../../hooks/useChatHistory"; +import Auth from './auth' +import Chat from './chat' +import Header from './layout/header' +import { useSettings } from '../../hooks/useSettings' +import useThemeSync from '../../hooks/useThemeSync' +import { useChatHistory } from '../../hooks/useChatHistory' function Sidebar() { - const [settings] = useSettings(); - useThemeSync(); - const { currentChatId } = useChatHistory(); + const [settings] = useSettings() + useThemeSync() + const { currentChatId } = useChatHistory() return (
@@ -18,7 +18,7 @@ function Sidebar() { )}
- ); + ) } -export default Sidebar; +export default Sidebar diff --git a/src/components/Sidebar/layout/header.tsx b/src/components/Sidebar/layout/header.tsx index cb4d6394..3885d23c 100644 --- a/src/components/Sidebar/layout/header.tsx +++ b/src/components/Sidebar/layout/header.tsx @@ -1,27 +1,27 @@ -import { useEffect, useState } from "react"; -import { BsRobot } from "react-icons/bs"; -import { HiOutlineCog, HiX } from "react-icons/hi"; +import { useEffect, useState } from 'react' +import { BsRobot } from 'react-icons/bs' +import { HiOutlineCog, HiX } from 'react-icons/hi' const Header = () => { - const [shortcut, setShortcut] = useState(null); + const [shortcut, setShortcut] = useState(null) const onToggle = () => { - chrome.runtime.sendMessage({ action: "close-sidebar" }); - }; + chrome.runtime.sendMessage({ action: 'close-sidebar' }) + } - const settingsPage = chrome.runtime.getURL("/src/pages/settings/index.html"); + const settingsPage = chrome.runtime.getURL('/src/pages/settings/index.html') const handleModifyShortcut = () => { - chrome.tabs.update({ url: "chrome://extensions/shortcuts" }); - }; + chrome.tabs.update({ url: 'chrome://extensions/shortcuts' }) + } useEffect(() => { chrome.commands.getAll((commands) => { const command = commands.find( - (command) => command.name === "open-sidebar" - ); - if (command) setShortcut(command.shortcut || null); - }); - }, []); + (command) => command.name === 'open-sidebar', + ) + if (command) setShortcut(command.shortcut || null) + }) + }, []) return (
@@ -36,7 +36,7 @@ const Header = () => { className="cdx-flex cdx-items-center cdx-gap-2" > - {shortcut ? `Shortcut: ${shortcut}` : "No shortcut"} + {shortcut ? `Shortcut: ${shortcut}` : 'No shortcut'} {
- ); -}; + ) +} -export default Header; +export default Header diff --git a/src/hooks/useChatCompletion.tsx b/src/hooks/useChatCompletion.tsx index 5ab268f3..c2251ed3 100644 --- a/src/hooks/useChatCompletion.tsx +++ b/src/hooks/useChatCompletion.tsx @@ -1,16 +1,16 @@ -import { AvailableModels, Mode } from "../config/settings"; -import { ChatOpenAI } from "langchain/chat_models/openai"; -import { useCurrentChat, ChatRole } from "./useCurrentChat"; -import { useMemo } from "react"; -import { AIMessage, HumanMessage, SystemMessage } from "langchain/schema"; -import { useState } from "react"; +import { AvailableModels, Mode } from '../config/settings' +import { ChatOpenAI } from 'langchain/chat_models/openai' +import { useCurrentChat, ChatRole } from './useCurrentChat' +import { useMemo } from 'react' +import { AIMessage, HumanMessage, SystemMessage } from 'langchain/schema' +import { useState } from 'react' interface UseChatCompletionProps { - model: AvailableModels; - apiKey: string; - mode: Mode; - systemPrompt: string; - chatId: string; + model: AvailableModels + apiKey: string + mode: Mode + systemPrompt: string + chatId: string } export const useChatCompletion = ({ @@ -26,10 +26,10 @@ export const useChatCompletion = ({ addNewMessage, updateStoredMessages, clearMessages, - } = useCurrentChat(chatId); - const [generating, setGenerating] = useState(false); + } = useCurrentChat(chatId) + const [generating, setGenerating] = useState(false) - const controller = new AbortController(); + const controller = new AbortController() const chat = useMemo( () => @@ -39,22 +39,22 @@ export const useChatCompletion = ({ modelName: model, temperature: Number(mode), }), - [] - ); + [], + ) const submitQuery = async (query: string) => { - addNewMessage(ChatRole.USER, query); + addNewMessage(ChatRole.USER, query) const previousMessages = messages.map((msg) => { switch (msg.role) { case ChatRole.ASSISTANT: - return new AIMessage(msg.content); + return new AIMessage(msg.content) case ChatRole.SYSTEM: - return new SystemMessage(msg.content); + return new SystemMessage(msg.content) case ChatRole.USER: - return new HumanMessage(msg.content); + return new HumanMessage(msg.content) } - }); - setGenerating(true); + }) + setGenerating(true) const response = await chat.call( [ new SystemMessage(systemPrompt), @@ -68,18 +68,18 @@ export const useChatCompletion = ({ handleLLMNewToken: updateAssistantMessage, }, ], - } - ); - setGenerating(false); - updateStoredMessages(); - return response.content; - }; + }, + ) + setGenerating(false) + updateStoredMessages() + return response.content + } const cancelRequest = () => { - controller.abort(); - updateStoredMessages(); - setGenerating(false); - }; + controller.abort() + updateStoredMessages() + setGenerating(false) + } - return { messages, submitQuery, generating, cancelRequest, clearMessages }; -}; + return { messages, submitQuery, generating, cancelRequest, clearMessages } +} diff --git a/src/hooks/useChatHistory.tsx b/src/hooks/useChatHistory.tsx index 88a91363..6aeea7b4 100644 --- a/src/hooks/useChatHistory.tsx +++ b/src/hooks/useChatHistory.tsx @@ -1,21 +1,21 @@ -import { useMemo } from "react"; -import { getUUID } from "../lib/getUUID"; -import { useStorage } from "./useStorage"; +import { useMemo } from 'react' +import { getUUID } from '../lib/getUUID' +import { useStorage } from './useStorage' interface ChatHistory { - id: string; - name: string; - createdAt: string; - updatedAt: string; + id: string + name: string + createdAt: string + updatedAt: string } export const useChatHistory = () => { - const [history, setHistory] = useStorage("HISTORY", []); - const initialChatId = useMemo(getUUID, []); + const [history, setHistory] = useStorage('HISTORY', []) + const initialChatId = useMemo(getUUID, []) const [currentChatId, setCurrentChatId] = useStorage( - "CURRENT_CHAT_ID", - initialChatId - ); + 'CURRENT_CHAT_ID', + initialChatId, + ) const createChatHistory = (name: string, newId = getUUID()) => { setHistory((prev) => [ @@ -26,36 +26,36 @@ export const useChatHistory = () => { createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), }, - ]); - setCurrentChatId(newId); + ]) + setCurrentChatId(newId) - return newId; - }; + return newId + } chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => { - const tab = tabs[0]; + const tab = tabs[0] if (tab) { - console.log(tab); + console.log(tab) } - }); + }) if (currentChatId === initialChatId) { chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => { - const tab = tabs[0] as any; + const tab = tabs[0] as any if (tab) { - const data = JSON.parse(tab.vivExtData); - const url = data.urlForThumbnail; - const title = new URL(url).hostname; - createChatHistory(title); + const data = JSON.parse(tab.vivExtData) + const url = data.urlForThumbnail + const title = new URL(url).hostname + createChatHistory(title) } - }); + }) } const deleteChatHistory = (id: string) => { - setHistory((prev) => prev.filter((h) => h.id !== id)); - }; + setHistory((prev) => prev.filter((h) => h.id !== id)) + } const getChatHistory = (id: string) => { - return history.find((h) => h.id === id); - }; + return history.find((h) => h.id === id) + } return { currentChatId, @@ -64,5 +64,5 @@ export const useChatHistory = () => { deleteChatHistory, getChatHistory, history, - }; -}; + } +} diff --git a/src/hooks/useCurrentChat.tsx b/src/hooks/useCurrentChat.tsx index 3d228b47..8feb6e00 100644 --- a/src/hooks/useCurrentChat.tsx +++ b/src/hooks/useCurrentChat.tsx @@ -1,27 +1,27 @@ -import { useState } from "react"; -import { useStorage } from "./useStorage"; +import { useState } from 'react' +import { useStorage } from './useStorage' export enum ChatRole { - "USER" = "USER", - "ASSISTANT" = "ASSISTANT", - "SYSTEM" = "SYSTEM", + USER = 'USER', + ASSISTANT = 'ASSISTANT', + SYSTEM = 'SYSTEM', } export type ChatMessage = { - role: ChatRole; - content: string; - timestamp: number; -}; + role: ChatRole + content: string + timestamp: number +} export const useCurrentChat = (chatId: string) => { const [storedMessages, setStoredMessages] = useStorage( `CHAT-${chatId}`, - [] - ); - const [messages, setMessages] = useState(storedMessages); // we don't directly update storedMessages for performance reasons + [], + ) + const [messages, setMessages] = useState(storedMessages) // we don't directly update storedMessages for performance reasons const updateAssistantMessage = (chunk: string) => { - console.log("INSIDE UPDATE ASSISTANT MESSAGE"); + console.log('INSIDE UPDATE ASSISTANT MESSAGE') setMessages((messages) => { if (messages[messages.length - 1].role === ChatRole.USER) { return [ @@ -31,31 +31,31 @@ export const useCurrentChat = (chatId: string) => { content: chunk, timestamp: Date.now(), }, - ]; + ] } - const lastMessage = messages[messages.length - 1]; - lastMessage.content += chunk; - return [...messages]; - }); - }; + const lastMessage = messages[messages.length - 1] + lastMessage.content += chunk + return [...messages] + }) + } const addNewMessage = (role: ChatRole, message: string) => { const newMessage: ChatMessage = { role, content: message, timestamp: Date.now(), - }; - setMessages([...messages, newMessage]); - }; + } + setMessages([...messages, newMessage]) + } const updateStoredMessages = () => { - setStoredMessages(messages); - }; + setStoredMessages(messages) + } const clearMessages = () => { - setMessages([]); - updateStoredMessages(); - }; + setMessages([]) + updateStoredMessages() + } return { messages, @@ -63,5 +63,5 @@ export const useCurrentChat = (chatId: string) => { addNewMessage, updateStoredMessages, clearMessages, - }; -}; + } +} diff --git a/src/lib/getUUID.ts b/src/lib/getUUID.ts index e6a692c0..1563788a 100644 --- a/src/lib/getUUID.ts +++ b/src/lib/getUUID.ts @@ -5,7 +5,7 @@ export const getUUID = () => { const s4 = () => Math.floor((1 + Math.random()) * 0x10000) .toString(16) - .substring(1); + .substring(1) - return `${s4()}${s4()}-${s4()}${s4()}-${s4()}${s4()}`; -}; + return `${s4()}${s4()}-${s4()}${s4()}-${s4()}${s4()}` +}