Add deleteChatHistory method to PageAssitDatabase class and systemPromptForNonRagOption functions to ollama service
This commit is contained in:
		
							parent
							
								
									c1efb2d5cb
								
							
						
					
					
						commit
						b54527cab5
					
				
							
								
								
									
										40
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										40
									
								
								package.json
									
									
									
									
									
								
							| @ -1,8 +1,8 @@ | |||||||
| { | { | ||||||
|   "name": "pageassist", |   "name": "pageassist", | ||||||
|   "displayName": "Page Assist - AI Powered Browser Assistant", |   "displayName": "Page Assist - Browse the Internet with Your Local AI Models", | ||||||
|   "version": "0.0.1", |   "version": "1.0.0", | ||||||
|   "description": "Use your local AI models to assist you in your daily browsing.", |   "description": "Page Assist is a browser extension that allows you to browse the internet with your local AI models. It is a privacy-focused and open-source project.", | ||||||
|   "author": "n4ze3m", |   "author": "n4ze3m", | ||||||
|   "scripts": { |   "scripts": { | ||||||
|     "dev": "plasmo dev", |     "dev": "plasmo dev", | ||||||
| @ -55,32 +55,30 @@ | |||||||
|   }, |   }, | ||||||
|   "manifest": { |   "manifest": { | ||||||
|     "host_permissions": [ |     "host_permissions": [ | ||||||
|       "https://*/*", |  | ||||||
|       "http://*/*", |       "http://*/*", | ||||||
|       "http://*:11434/api/tags", |       "https://*/*" | ||||||
|       "http://*:11434/api/chat", |  | ||||||
|       "https://*:11434/api/tags", |  | ||||||
|       "https://*:11434/api/chat" |  | ||||||
|     ], |     ], | ||||||
|     "web_accessible_resources": [ |     "commands": { | ||||||
|       { |       "_execute_action": { | ||||||
|         "resources": [ |         "suggested_key": { | ||||||
|           "popup.html" |           "default": "Ctrl+Shift+L" | ||||||
|         ], |         } | ||||||
|         "matches": [ |       }, | ||||||
|           "https://*/*", |       "execute_side_panel": { | ||||||
|           "http://*/*" |         "description": "Open the side panel", | ||||||
|         ] |         "suggested_key": { | ||||||
|  |           "default": "Ctrl+Shift+P" | ||||||
|  |         } | ||||||
|       } |       } | ||||||
|     ], |     }, | ||||||
|     "permissions": [ |     "permissions": [ | ||||||
|       "storage", |       "storage", | ||||||
|       "activeTab", |       "activeTab", | ||||||
|       "scripting", |       "scripting", | ||||||
|       "declarativeNetRequest", |       "declarativeNetRequest", | ||||||
|       "declarativeNetRequestFeedback", |  | ||||||
|       "action", |       "action", | ||||||
|       "unlimitedStorage" |       "unlimitedStorage", | ||||||
|  |       "contextMenus" | ||||||
|     ] |     ] | ||||||
|   } |   } | ||||||
| } | } | ||||||
| @ -12,5 +12,37 @@ chrome.runtime.onMessage.addListener(async (message) => { | |||||||
| }) | }) | ||||||
| 
 | 
 | ||||||
| chrome.action.onClicked.addListener((tab) => { | chrome.action.onClicked.addListener((tab) => { | ||||||
|   chrome.tabs.create({url: chrome.runtime.getURL("options.html")}); |   chrome.tabs.create({ url: chrome.runtime.getURL("options.html") }) | ||||||
| }); | }) | ||||||
|  | 
 | ||||||
|  | chrome.commands.onCommand.addListener((command) => { | ||||||
|  |   switch (command) { | ||||||
|  |     case "execute_side_panel": | ||||||
|  |       chrome.tabs.query({ active: true, currentWindow: true }, async (tabs) => { | ||||||
|  |         const tab = tabs[0] | ||||||
|  |         await chrome.sidePanel.open({ | ||||||
|  |           tabId: tab.id | ||||||
|  |         }) | ||||||
|  |       }) | ||||||
|  |       break | ||||||
|  |     default: | ||||||
|  |       break | ||||||
|  |   } | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | chrome.contextMenus.create({ | ||||||
|  |   id: "open-side-panel-pa", | ||||||
|  |   title: "Open Side Panel to Chat", | ||||||
|  |   contexts: ["all"] | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | chrome.contextMenus.onClicked.addListener((info, tab) => { | ||||||
|  |   if (info.menuItemId === "open-side-panel-pa") { | ||||||
|  |     chrome.tabs.query({ active: true, currentWindow: true }, async (tabs) => { | ||||||
|  |       const tab = tabs[0] | ||||||
|  |       await chrome.sidePanel.open({ | ||||||
|  |         tabId: tab.id | ||||||
|  |       }) | ||||||
|  |     }) | ||||||
|  |   } | ||||||
|  | }) | ||||||
|  | |||||||
| @ -15,11 +15,13 @@ import logoImage from "data-base64:~assets/icon.png" | |||||||
| 
 | 
 | ||||||
| import { Link, useParams, useLocation, useNavigate } from "react-router-dom" | import { Link, useParams, useLocation, useNavigate } from "react-router-dom" | ||||||
| import { Sidebar } from "./Sidebar" | import { Sidebar } from "./Sidebar" | ||||||
| import { Drawer, Layout, Select } from "antd" | import { Drawer, Layout, Modal, Select } from "antd" | ||||||
| import { useQuery } from "@tanstack/react-query" | import { useQuery } from "@tanstack/react-query" | ||||||
| import { fetchModels } from "~services/ollama" | import { fetchModels } from "~services/ollama" | ||||||
| import { useMessageOption } from "~hooks/useMessageOption" | import { useMessageOption } from "~hooks/useMessageOption" | ||||||
| import { PanelLeftIcon, Settings2 } from "lucide-react" | import { PanelLeftIcon, Settings2 } from "lucide-react" | ||||||
|  | import { Settings } from "./Settings" | ||||||
|  | import { useDarkMode } from "~hooks/useDarkmode" | ||||||
| 
 | 
 | ||||||
| const navigation = [ | const navigation = [ | ||||||
|   { name: "Embed", href: "/bot/:id", icon: TagIcon }, |   { name: "Embed", href: "/bot/:id", icon: TagIcon }, | ||||||
| @ -51,8 +53,7 @@ export default function OptionLayout({ | |||||||
|   children: React.ReactNode |   children: React.ReactNode | ||||||
| }) { | }) { | ||||||
|   const [sidebarOpen, setSidebarOpen] = useState(false) |   const [sidebarOpen, setSidebarOpen] = useState(false) | ||||||
|   const params = useParams<{ id: string }>() |   const [open, setOpen] = useState(false) | ||||||
|   const location = useLocation() |  | ||||||
| 
 | 
 | ||||||
|   const { |   const { | ||||||
|     data: models, |     data: models, | ||||||
| @ -66,9 +67,10 @@ export default function OptionLayout({ | |||||||
| 
 | 
 | ||||||
|   const { selectedModel, setSelectedModel } = useMessageOption() |   const { selectedModel, setSelectedModel } = useMessageOption() | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|   return ( |   return ( | ||||||
|     <Layout className="bg-white dark:bg-[#171717] md:flex"> |     <Layout className="bg-white dark:bg-[#171717] md:flex"> | ||||||
|       <div className="flex items-center p-3 fixed flex-row justify-between border-b border-gray-200 dark:border-gray-800 bg-white dark:bg-[#171717] w-full z-10"> |       <div className="flex items-center p-3 fixed flex-row justify-between border-b border-gray-200 dark:border-gray-600 bg-white dark:bg-[#171717] w-full z-10"> | ||||||
|         <div className="flex items-center flex-row gap-3"> |         <div className="flex items-center flex-row gap-3"> | ||||||
|           <div> |           <div> | ||||||
|             <button |             <button | ||||||
| @ -92,7 +94,12 @@ export default function OptionLayout({ | |||||||
|             /> |             /> | ||||||
|           </div> |           </div> | ||||||
|         </div> |         </div> | ||||||
|         <button className="text-gray-500 dark:text-gray-400"> |         <button> | ||||||
|  | 
 | ||||||
|  |         </button> | ||||||
|  |         <button | ||||||
|  |           onClick={() => setOpen(true)} | ||||||
|  |           className="text-gray-500 dark:text-gray-400"> | ||||||
|           <CogIcon className="w-6 h-6" /> |           <CogIcon className="w-6 h-6" /> | ||||||
|         </button> |         </button> | ||||||
|       </div> |       </div> | ||||||
| @ -104,10 +111,19 @@ export default function OptionLayout({ | |||||||
|         placement="left" |         placement="left" | ||||||
|         closeIcon={null} |         closeIcon={null} | ||||||
|         onClose={() => setSidebarOpen(false)} |         onClose={() => setSidebarOpen(false)} | ||||||
|         open={sidebarOpen} |         open={sidebarOpen}> | ||||||
|       > |  | ||||||
|         <Sidebar /> |         <Sidebar /> | ||||||
|       </Drawer> |       </Drawer> | ||||||
|  | 
 | ||||||
|  |       <Modal | ||||||
|  |         open={open} | ||||||
|  |         width={800} | ||||||
|  |         title={"Settings"} | ||||||
|  |         onOk={() => setOpen(false)} | ||||||
|  |         footer={null} | ||||||
|  |         onCancel={() => setOpen(false)}> | ||||||
|  |         <Settings setClose={() => setOpen(false)} /> | ||||||
|  |       </Modal> | ||||||
|     </Layout> |     </Layout> | ||||||
|   ) |   ) | ||||||
| } | } | ||||||
|  | |||||||
| @ -2,6 +2,7 @@ import React from "react" | |||||||
| import { useMessage } from "~hooks/useMessage" | import { useMessage } from "~hooks/useMessage" | ||||||
| import { useMessageOption } from "~hooks/useMessageOption" | import { useMessageOption } from "~hooks/useMessageOption" | ||||||
| import { PlaygroundMessage } from "./PlaygroundMessage" | import { PlaygroundMessage } from "./PlaygroundMessage" | ||||||
|  | import { PlaygroundEmpty } from "./PlaygroundEmpty" | ||||||
| 
 | 
 | ||||||
| export const PlaygroundChat = () => { | export const PlaygroundChat = () => { | ||||||
|   const { messages } = useMessageOption() |   const { messages } = useMessageOption() | ||||||
| @ -13,7 +14,11 @@ export const PlaygroundChat = () => { | |||||||
|   }) |   }) | ||||||
|   return ( |   return ( | ||||||
|     <div className="grow flex flex-col md:translate-x-0 transition-transform duration-300 ease-in-out"> |     <div className="grow flex flex-col md:translate-x-0 transition-transform duration-300 ease-in-out"> | ||||||
|       {/* {messages.length === 0 && <div>no message</div>} */} |       {messages.length === 0 && ( | ||||||
|  |         <div className="mt-32"> | ||||||
|  |           <PlaygroundEmpty /> | ||||||
|  |         </div> | ||||||
|  |       )} | ||||||
|       {messages.length > 0 && <div className="w-full h-14 flex-shrink-0"></div>} |       {messages.length > 0 && <div className="w-full h-14 flex-shrink-0"></div>} | ||||||
|       {messages.map((message, index) => ( |       {messages.map((message, index) => ( | ||||||
|         <PlaygroundMessage |         <PlaygroundMessage | ||||||
|  | |||||||
							
								
								
									
										86
									
								
								src/components/Option/Playground/PlaygroundEmpty.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								src/components/Option/Playground/PlaygroundEmpty.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,86 @@ | |||||||
|  | import { useQuery } from "@tanstack/react-query" | ||||||
|  | import { useEffect, useState } from "react" | ||||||
|  | import { useMessage } from "~hooks/useMessage" | ||||||
|  | import { useMessageOption } from "~hooks/useMessageOption" | ||||||
|  | import { | ||||||
|  |   getOllamaURL, | ||||||
|  |   isOllamaRunning, | ||||||
|  |   setOllamaURL as saveOllamaURL | ||||||
|  | } from "~services/ollama" | ||||||
|  | 
 | ||||||
|  | export const PlaygroundEmpty = () => { | ||||||
|  |   const [ollamaURL, setOllamaURL] = useState<string>("") | ||||||
|  |   const { | ||||||
|  |     data: ollamaInfo, | ||||||
|  |     status: ollamaStatus, | ||||||
|  |     refetch, | ||||||
|  |     isRefetching | ||||||
|  |   } = useQuery({ | ||||||
|  |     queryKey: ["ollamaStatus"], | ||||||
|  |     queryFn: async () => { | ||||||
|  |       const ollamaURL = await getOllamaURL() | ||||||
|  |       const isOk = await isOllamaRunning() | ||||||
|  | 
 | ||||||
|  |       return { | ||||||
|  |         isOk, | ||||||
|  |         ollamaURL | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   }) | ||||||
|  | 
 | ||||||
|  |   useEffect(() => { | ||||||
|  |     if (ollamaInfo?.ollamaURL) { | ||||||
|  |       setOllamaURL(ollamaInfo.ollamaURL) | ||||||
|  |     } | ||||||
|  |   }, [ollamaInfo]) | ||||||
|  | 
 | ||||||
|  |   return ( | ||||||
|  |     <div className="mx-auto sm:max-w-xl px-4 mt-10"> | ||||||
|  |       <div className="rounded-lg justify-center items-center flex flex-col border p-8 bg-white dark:bg-[#262626] shadow-sm dark:border-gray-600"> | ||||||
|  |         {(ollamaStatus === "pending" || isRefetching) && ( | ||||||
|  |           <div className="inline-flex items-center space-x-2"> | ||||||
|  |             <div className="w-3 h-3 bg-blue-500 rounded-full animate-bounce"></div> | ||||||
|  |             <p className="dark:text-gray-400 text-gray-900"> | ||||||
|  |               Searching for Your Ollama 🦙 | ||||||
|  |             </p> | ||||||
|  |           </div> | ||||||
|  |         )} | ||||||
|  |         {!isRefetching && ollamaStatus === "success" ? ( | ||||||
|  |           ollamaInfo.isOk ? ( | ||||||
|  |             <div className="inline-flex  items-center space-x-2"> | ||||||
|  |               <div className="w-3 h-3 bg-green-500 rounded-full"></div> | ||||||
|  |               <p className="dark:text-gray-400 text-gray-900"> | ||||||
|  |                 Ollama is running 🦙 | ||||||
|  |               </p> | ||||||
|  |             </div> | ||||||
|  |           ) : ( | ||||||
|  |             <div className="flex flex-col space-y-2 justify-center items-center"> | ||||||
|  |               <div className="inline-flex  space-x-2"> | ||||||
|  |                 <div className="w-3 h-3 bg-red-500 rounded-full"></div> | ||||||
|  |                 <p className="dark:text-gray-400 text-gray-900"> | ||||||
|  |                   Unable to connect to Ollama 🦙 | ||||||
|  |                 </p> | ||||||
|  |               </div> | ||||||
|  | 
 | ||||||
|  |               <input | ||||||
|  |                 className="bg-gray-100 dark:bg-[#262626] dark:text-gray-100 rounded-md px-4 py-2 mt-2 w-full" | ||||||
|  |                 type="url" | ||||||
|  |                 value={ollamaURL} | ||||||
|  |                 onChange={(e) => setOllamaURL(e.target.value)} | ||||||
|  |               /> | ||||||
|  | 
 | ||||||
|  |               <button | ||||||
|  |                 onClick={() => { | ||||||
|  |                   saveOllamaURL(ollamaURL) | ||||||
|  |                   refetch() | ||||||
|  |                 }} | ||||||
|  |                 className="bg-pink-500 mt-4 hover:bg-pink-600 text-white px-4 py-2 rounded-md dark:bg-pink-600 dark:hover:bg-pink-700"> | ||||||
|  |                 Retry | ||||||
|  |               </button> | ||||||
|  |             </div> | ||||||
|  |           ) | ||||||
|  |         ) : null} | ||||||
|  |       </div> | ||||||
|  |     </div> | ||||||
|  |   ) | ||||||
|  | } | ||||||
| @ -66,7 +66,7 @@ export const PlaygroundForm = ({ dropedFile }: Props) => { | |||||||
|   }) |   }) | ||||||
| 
 | 
 | ||||||
|   return ( |   return ( | ||||||
|     <div className="p-3 md:p-6 md:bg-white dark:bg-black border rounded-t-xl border-black/10 dark:border-gray-800"> |     <div className="p-3 md:p-6 md:bg-white dark:bg-[#262626] border rounded-t-xl border-black/10 dark:border-gray-600"> | ||||||
|       <div className="flex-grow space-y-6 "> |       <div className="flex-grow space-y-6 "> | ||||||
|         <div |         <div | ||||||
|           className={`h-full rounded-md shadow relative ${ |           className={`h-full rounded-md shadow relative ${ | ||||||
| @ -82,7 +82,7 @@ export const PlaygroundForm = ({ dropedFile }: Props) => { | |||||||
|               onClick={() => { |               onClick={() => { | ||||||
|                 form.setFieldValue("image", "") |                 form.setFieldValue("image", "") | ||||||
|               }} |               }} | ||||||
|               className="absolute top-2 right-2 bg-white dark:bg-black p-1 rounded-full hover:bg-gray-100 dark:hover:bg-gray-600 text-black dark:text-gray-100"> |               className="absolute top-2 right-2 bg-white  dark:bg-[#262626] p-1 rounded-full hover:bg-gray-100 dark:hover:bg-gray-600 text-black dark:text-gray-100"> | ||||||
|               <XMarkIcon className="h-5 w-5" /> |               <XMarkIcon className="h-5 w-5" /> | ||||||
|             </button> |             </button> | ||||||
|           </div> |           </div> | ||||||
| @ -109,7 +109,7 @@ export const PlaygroundForm = ({ dropedFile }: Props) => { | |||||||
|               }) |               }) | ||||||
|             })} |             })} | ||||||
|             className="shrink-0 flex-grow  flex items-center "> |             className="shrink-0 flex-grow  flex items-center "> | ||||||
|             <div className="flex items-center p-2 rounded-2xl border  bg-gray-100 w-full dark:bg-black dark:border-gray-800"> |             <div className="flex items-center p-2 rounded-2xl border  bg-gray-100 w-full dark:bg-[#262626] dark:border-gray-600"> | ||||||
|               <button |               <button | ||||||
|                 type="button" |                 type="button" | ||||||
|                 onClick={() => { |                 onClick={() => { | ||||||
| @ -162,7 +162,7 @@ export const PlaygroundForm = ({ dropedFile }: Props) => { | |||||||
|               /> |               /> | ||||||
|               <button |               <button | ||||||
|                 disabled={isSending || form.values.message.length === 0} |                 disabled={isSending || form.values.message.length === 0} | ||||||
|                 className="ml-2 flex items-center justify-center w-10 h-10  text-white bg-black rounded-xl disabled:opacity-50"> |                 className="ml-2 flex items-center justify-center w-10 h-10  text-white bg-[#262626] rounded-xl disabled:opacity-50"> | ||||||
|                 <svg |                 <svg | ||||||
|                   xmlns="http://www.w3.org/2000/svg" |                   xmlns="http://www.w3.org/2000/svg" | ||||||
|                   fill="none" |                   fill="none" | ||||||
|  | |||||||
							
								
								
									
										39
									
								
								src/components/Option/Settings.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								src/components/Option/Settings.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,39 @@ | |||||||
|  | import { Tabs } from "antd" | ||||||
|  | import { SettingsOllama } from "./Settings/ollama" | ||||||
|  | import { SettingPrompt } from "./Settings/prompt" | ||||||
|  | import { SettingOther } from "./Settings/other" | ||||||
|  | 
 | ||||||
|  | type Props = { | ||||||
|  |   setClose: (close: boolean) => void | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export const Settings = ({ setClose }: Props) => { | ||||||
|  |   return ( | ||||||
|  |     <div className="my-6"> | ||||||
|  |       <Tabs | ||||||
|  |         tabPosition="left" | ||||||
|  |         defaultActiveKey="1" | ||||||
|  |         items={[ | ||||||
|  |           { | ||||||
|  |             id: "1", | ||||||
|  |             key: "1", | ||||||
|  |             label: "Prompt", | ||||||
|  |             children: <SettingPrompt /> | ||||||
|  |           }, | ||||||
|  |           { | ||||||
|  |             id: "2", | ||||||
|  |             key: "2", | ||||||
|  |             label: "Ollama", | ||||||
|  |             children: <SettingsOllama /> | ||||||
|  |           }, | ||||||
|  |           { | ||||||
|  |             id: "3", | ||||||
|  |             key: "3", | ||||||
|  |             label: "Other", | ||||||
|  |             children: <SettingOther /> | ||||||
|  |           } | ||||||
|  |         ]} | ||||||
|  |       /> | ||||||
|  |     </div> | ||||||
|  |   ) | ||||||
|  | } | ||||||
							
								
								
									
										55
									
								
								src/components/Option/Settings/ollama.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								src/components/Option/Settings/ollama.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,55 @@ | |||||||
|  | import { useQuery } from "@tanstack/react-query" | ||||||
|  | import { useEffect, useState } from "react" | ||||||
|  | import { SaveButton } from "~components/Common/SaveButton" | ||||||
|  | import { getOllamaURL, setOllamaURL as saveOllamaURL } from "~services/ollama" | ||||||
|  | 
 | ||||||
|  | export const SettingsOllama = () => { | ||||||
|  |   const [ollamaURL, setOllamaURL] = useState<string>("") | ||||||
|  |   const { data: ollamaInfo } = useQuery({ | ||||||
|  |     queryKey: ["fetchOllamURL"], | ||||||
|  |     queryFn: async () => { | ||||||
|  |       const ollamaURL = await getOllamaURL() | ||||||
|  | 
 | ||||||
|  |       return { | ||||||
|  |         ollamaURL | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   }) | ||||||
|  | 
 | ||||||
|  |    | ||||||
|  |   useEffect(() => { | ||||||
|  |     if (ollamaInfo?.ollamaURL) { | ||||||
|  |       setOllamaURL(ollamaInfo.ollamaURL) | ||||||
|  |     } | ||||||
|  |   }, [ollamaInfo]) | ||||||
|  | 
 | ||||||
|  |   return ( | ||||||
|  |     <div className=""> | ||||||
|  |       <div> | ||||||
|  |         <label | ||||||
|  |           htmlFor="ollamaURL" | ||||||
|  |           className="text-sm font-medium dark:text-gray-200"> | ||||||
|  |           Ollama URL | ||||||
|  |         </label> | ||||||
|  |         <input | ||||||
|  |           type="url" | ||||||
|  |           id="ollamaURL" | ||||||
|  |           value={ollamaURL} | ||||||
|  |           onChange={(e) => { | ||||||
|  |             setOllamaURL(e.target.value) | ||||||
|  |           }} | ||||||
|  |           placeholder="Your Ollama URL" | ||||||
|  |           className="w-full p-2 border border-gray-300 rounded-md dark:bg-[#262626] dark:text-gray-100" | ||||||
|  |         /> | ||||||
|  |       </div> | ||||||
|  |       <div className="flex justify-end"> | ||||||
|  |         <SaveButton | ||||||
|  |           onClick={() => { | ||||||
|  |             saveOllamaURL(ollamaURL) | ||||||
|  |           }} | ||||||
|  |           className="mt-2" | ||||||
|  |         /> | ||||||
|  |       </div> | ||||||
|  |     </div> | ||||||
|  |   ) | ||||||
|  | } | ||||||
							
								
								
									
										52
									
								
								src/components/Option/Settings/other.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								src/components/Option/Settings/other.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,52 @@ | |||||||
|  | import { useQueryClient } from "@tanstack/react-query" | ||||||
|  | import { useDarkMode } from "~hooks/useDarkmode" | ||||||
|  | import { useMessageOption } from "~hooks/useMessageOption" | ||||||
|  | import { PageAssitDatabase } from "~libs/db" | ||||||
|  | 
 | ||||||
|  | export const SettingOther = () => { | ||||||
|  |   const { clearChat } = useMessageOption() | ||||||
|  | 
 | ||||||
|  |   const queryClient = useQueryClient() | ||||||
|  | 
 | ||||||
|  |   const { mode, toggleDarkMode } = useDarkMode() | ||||||
|  | 
 | ||||||
|  |   return ( | ||||||
|  |     <div className="flex flex-col space-y-4"> | ||||||
|  |       <div className="flex flex-row justify-between"> | ||||||
|  |         <span className="text-gray-500 dark:text-gray-400 text-lg"> | ||||||
|  |           Change Theme | ||||||
|  |         </span> | ||||||
|  | 
 | ||||||
|  |         <button | ||||||
|  |           onClick={toggleDarkMode} | ||||||
|  |           className="bg-blue-500 dark:bg-blue-600 text-white dark:text-gray-200 px-4 py-2 rounded-md"> | ||||||
|  |           {mode === "dark" ? "Light" : "Dark"} | ||||||
|  |         </button> | ||||||
|  |       </div> | ||||||
|  |       <div className="flex flex-row justify-between"> | ||||||
|  |         <span className="text-gray-500 dark:text-gray-400 text-lg"> | ||||||
|  |           Delete Chat History | ||||||
|  |         </span> | ||||||
|  | 
 | ||||||
|  |         <button | ||||||
|  |           onClick={async () => { | ||||||
|  |             const confirm = window.confirm( | ||||||
|  |               "Are you sure you want to delete your chat history? This action cannot be undone." | ||||||
|  |             ) | ||||||
|  | 
 | ||||||
|  |             if (confirm) { | ||||||
|  |               const db = new PageAssitDatabase() | ||||||
|  |               await db.deleteChatHistory() | ||||||
|  |               queryClient.invalidateQueries({ | ||||||
|  |                 queryKey: ["fetchChatHistory"] | ||||||
|  |               }) | ||||||
|  |               clearChat() | ||||||
|  |             } | ||||||
|  |           }} | ||||||
|  |           className="bg-red-500 dark:bg-red-600 text-white dark:text-gray-200 px-4 py-2 rounded-md"> | ||||||
|  |           Delete | ||||||
|  |         </button> | ||||||
|  |       </div> | ||||||
|  |     </div> | ||||||
|  |   ) | ||||||
|  | } | ||||||
							
								
								
									
										56
									
								
								src/components/Option/Settings/prompt.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								src/components/Option/Settings/prompt.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,56 @@ | |||||||
|  | import { useQuery } from "@tanstack/react-query" | ||||||
|  | import { useEffect, useState } from "react" | ||||||
|  | import { SaveButton } from "~components/Common/SaveButton" | ||||||
|  | import { | ||||||
|  |   setSystemPromptForNonRagOption, | ||||||
|  |   systemPromptForNonRagOption | ||||||
|  | } from "~services/ollama" | ||||||
|  | 
 | ||||||
|  | export const SettingPrompt = () => { | ||||||
|  |   const [ollamaPrompt, setOllamaPrompt] = useState<string>("") | ||||||
|  |   const { data: ollamaInfo } = useQuery({ | ||||||
|  |     queryKey: ["fetchOllaPrompt"], | ||||||
|  |     queryFn: async () => { | ||||||
|  |       const prompt = await systemPromptForNonRagOption() | ||||||
|  | 
 | ||||||
|  |       return { | ||||||
|  |         prompt | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   }) | ||||||
|  | 
 | ||||||
|  |   useEffect(() => { | ||||||
|  |     if (ollamaInfo?.prompt) { | ||||||
|  |       setOllamaPrompt(ollamaInfo.prompt) | ||||||
|  |     } | ||||||
|  |   }, [ollamaInfo]) | ||||||
|  | 
 | ||||||
|  |   return ( | ||||||
|  |     <div className=""> | ||||||
|  |       <div> | ||||||
|  |         <label htmlFor="ollamaPrompt" className="text-sm font-medium dark:text-gray-200"> | ||||||
|  |             System Prompt | ||||||
|  |         </label> | ||||||
|  |       <textarea | ||||||
|  |         value={ollamaPrompt} | ||||||
|  |         rows={5} | ||||||
|  |         id="ollamaPrompt" | ||||||
|  |         placeholder="Your System Prompt" | ||||||
|  |         onChange={(e) => { | ||||||
|  |           setOllamaPrompt(e.target.value) | ||||||
|  |         }} | ||||||
|  |         className="w-full p-2 border border-gray-300 rounded-md dark:bg-[#262626] dark:text-gray-100" | ||||||
|  |       /> | ||||||
|  |       </div> | ||||||
|  | 
 | ||||||
|  |       <div className="flex justify-end"> | ||||||
|  |       <SaveButton | ||||||
|  |         onClick={() => { | ||||||
|  |           setSystemPromptForNonRagOption(ollamaPrompt) | ||||||
|  |         }} | ||||||
|  |         className="mt-2" | ||||||
|  |       /> | ||||||
|  |       </div> | ||||||
|  |     </div> | ||||||
|  |   ) | ||||||
|  | } | ||||||
| @ -1,29 +0,0 @@ | |||||||
| export {} |  | ||||||
| import { Storage } from "@plasmohq/storage" |  | ||||||
| 
 |  | ||||||
| const storage = new Storage() |  | ||||||
| 
 |  | ||||||
| const sidePanelController = async () => { |  | ||||||
|   const sidepanelCommand = await storage.get("sidepanel-command") |  | ||||||
|   const command = sidepanelCommand || "Ctrl+0" |  | ||||||
| 
 |  | ||||||
|   document.addEventListener("keydown", (event) => { |  | ||||||
|     let pressedKey = "" |  | ||||||
|     if (event.ctrlKey) { |  | ||||||
|       pressedKey += "Ctrl+" |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if (event.shiftKey) { |  | ||||||
|       pressedKey += "Shift+" |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     pressedKey += event.key |  | ||||||
| 
 |  | ||||||
|     if (pressedKey === command) { |  | ||||||
|       chrome.runtime.sendMessage({ type: "sidepanel" }) |  | ||||||
|     } |  | ||||||
|   }) |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| sidePanelController() |  | ||||||
| @ -1,6 +1,6 @@ | |||||||
| import React from "react" | import React from "react" | ||||||
| import { cleanUrl } from "~libs/clean-url" | import { cleanUrl } from "~libs/clean-url" | ||||||
| import { getOllamaURL, systemPromptForNonRag } from "~services/ollama" | import { getOllamaURL, systemPromptForNonRagOption } from "~services/ollama" | ||||||
| import { type ChatHistory, type Message } from "~store/option" | import { type ChatHistory, type Message } from "~store/option" | ||||||
| import { ChatOllama } from "@langchain/community/chat_models/ollama" | import { ChatOllama } from "@langchain/community/chat_models/ollama" | ||||||
| import { | import { | ||||||
| @ -139,7 +139,7 @@ export const useMessageOption = () => { | |||||||
|     setMessages(newMessage) |     setMessages(newMessage) | ||||||
| 
 | 
 | ||||||
|     try { |     try { | ||||||
|       const prompt = await systemPromptForNonRag() |       const prompt = await systemPromptForNonRagOption() | ||||||
| 
 | 
 | ||||||
|       message = message.trim().replaceAll("\n", " ") |       message = message.trim().replaceAll("\n", " ") | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -79,6 +79,14 @@ export class PageAssitDatabase { | |||||||
|   async clear() { |   async clear() { | ||||||
|     this.db.clear() |     this.db.clear() | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|  |   async deleteChatHistory() { | ||||||
|  |     const chatHistories = await this.getChatHistories() | ||||||
|  |     for (const history of chatHistories) { | ||||||
|  |       this.db.remove(history.id) | ||||||
|  |     } | ||||||
|  |     this.db.remove("chatHistories") | ||||||
|  |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const generateID = () => { | const generateID = () => { | ||||||
|  | |||||||
| @ -121,3 +121,12 @@ export const setPromptForRag = async ( | |||||||
|   await storage.set("systemPromptForRag", prompt) |   await storage.set("systemPromptForRag", prompt) | ||||||
|   await storage.set("questionPromptForRag", questionPrompt) |   await storage.set("questionPromptForRag", questionPrompt) | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | export const systemPromptForNonRagOption = async () => { | ||||||
|  |   const prompt = await storage.get("systemPromptForNonRagOption") | ||||||
|  |   return prompt | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export const setSystemPromptForNonRagOption = async (prompt: string) => { | ||||||
|  |   await storage.set("systemPromptForNonRagOption", prompt) | ||||||
|  | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user