From 93e973b85175a9d6ebeaca0c925afd9038410c68 Mon Sep 17 00:00:00 2001 From: samlhuillier Date: Sun, 29 Sep 2024 11:22:18 +0100 Subject: [PATCH 1/4] move props around --- .../ChatConfigComponents/DBSearchFilters.tsx | 34 +++++++++++++--- src/components/Chat/StartChat.tsx | 39 +++---------------- 2 files changed, 33 insertions(+), 40 deletions(-) diff --git a/src/components/Chat/ChatConfigComponents/DBSearchFilters.tsx b/src/components/Chat/ChatConfigComponents/DBSearchFilters.tsx index 55651d4c..c7ac3056 100644 --- a/src/components/Chat/ChatConfigComponents/DBSearchFilters.tsx +++ b/src/components/Chat/ChatConfigComponents/DBSearchFilters.tsx @@ -1,16 +1,38 @@ -import React from 'react' +import React, { useCallback } from 'react' import { Slider } from '@/components/ui/slider' import DateRangePicker from '../../ui/date-picker' import { DatabaseSearchFilters } from '../types' interface DbSearchFiltersProps { dbSearchFilters: DatabaseSearchFilters - onSliderChange: (value: number[]) => void - onDateChange: (from: Date | undefined, to: Date | undefined) => void + onFiltersChange: (newFilters: DatabaseSearchFilters) => void } -const DbSearchFilters: React.FC = ({ dbSearchFilters, onSliderChange, onDateChange }) => { +const DbSearchFilters: React.FC = ({ dbSearchFilters, onFiltersChange }) => { const inverseLogScale = (value: number) => Math.round(Math.log(value + 1) * 25) + const logScale = (value: number) => Math.round(Math.exp(value / 25) - 1) + + const handleSliderChange = useCallback( + (value: number[]) => { + const scaledValue = logScale(value[0]) + onFiltersChange({ + ...dbSearchFilters, + limit: scaledValue, + }) + }, + [dbSearchFilters, onFiltersChange], + ) + + const handleDateChange = useCallback( + (from: Date | undefined, to: Date | undefined) => { + onFiltersChange({ + ...dbSearchFilters, + minDate: from, + maxDate: to, + }) + }, + [dbSearchFilters, onFiltersChange], + ) return (
@@ -20,7 +42,7 @@ const DbSearchFilters: React.FC = ({ dbSearchFilters, onSl min={0} max={100} step={1} - onValueChange={onSliderChange} + onValueChange={handleSliderChange} />
{dbSearchFilters.limit} @@ -29,7 +51,7 @@ const DbSearchFilters: React.FC = ({ dbSearchFilters, onSl
Filter search by date (last modified): - +
) diff --git a/src/components/Chat/StartChat.tsx b/src/components/Chat/StartChat.tsx index 2ff67d82..6bb44462 100644 --- a/src/components/Chat/StartChat.tsx +++ b/src/components/Chat/StartChat.tsx @@ -2,7 +2,7 @@ import React, { useCallback, useEffect, useState } from 'react' import { PiPaperPlaneRight } from 'react-icons/pi' import { LLMConfig } from 'electron/main/electron-store/storeConfig' import '../../styles/chat.css' -import { AgentConfig, ToolDefinition } from './types' +import { AgentConfig, ToolDefinition, DatabaseSearchFilters } from './types' import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select' import { Card, CardDescription } from '../ui/card' import { allAvailableToolDefinitions } from './tools' @@ -51,45 +51,17 @@ const StartChat: React.FC = ({ defaultModelName, handleNewChatMe setSelectedLLM(value) } - const handleSliderChange = useCallback((value: number[]) => { - const logScale = (_value: number) => Math.round(Math.exp(_value / 25) - 1) - const scaledValue = logScale(value[0]) - setAgentConfig((prevConfig) => ({ - ...prevConfig, - dbSearchFilters: prevConfig.dbSearchFilters - ? { - ...prevConfig.dbSearchFilters, - limit: scaledValue, - } - : { - limit: scaledValue, - minDate: new Date(new Date().setFullYear(new Date().getFullYear() - 1)), - maxDate: new Date(), - }, - })) - }, []) - const handleToolsChange = (tools: ToolDefinition[]) => { setSelectedTools(tools) setAgentConfig((prevConfig) => ({ ...prevConfig, toolDefinitions: tools })) } - const handleDateChange = (from: Date | undefined, to: Date | undefined) => { + const handleDbSearchFiltersChange = useCallback((newFilters: DatabaseSearchFilters) => { setAgentConfig((prevConfig) => ({ ...prevConfig, - dbSearchFilters: prevConfig.dbSearchFilters - ? { - ...prevConfig.dbSearchFilters, - minDate: from, - maxDate: to, - } - : { - limit: 33, - minDate: from, - maxDate: to, - }, + dbSearchFilters: newFilters, })) - } + }, []) const handleDbSearchToggle = (checked: boolean) => { setAgentConfig((prevConfig) => ({ @@ -195,8 +167,7 @@ const StartChat: React.FC = ({ defaultModelName, handleNewChatMe {agentConfig.dbSearchFilters && ( )} From 87d6f611d8d2ca3fcdab820f4f50b99e3ac7769b Mon Sep 17 00:00:00 2001 From: samlhuillier Date: Sun, 29 Sep 2024 11:31:03 +0100 Subject: [PATCH 2/4] working drawer --- package-lock.json | 13 +++++ package.json | 1 + src/components/Chat/StartChat.tsx | 43 ++++++++++++--- src/components/ui/drawer.tsx | 89 +++++++++++++++++++++++++++++++ 4 files changed, 140 insertions(+), 6 deletions(-) create mode 100644 src/components/ui/drawer.tsx diff --git a/package-lock.json b/package-lock.json index 54c85ac4..ffcd4d0e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -102,6 +102,7 @@ "use-debounce": "^10.0.1", "uuid": "^10.0.0", "uuidv4": "^6.2.13", + "vaul": "^1.0.0", "vectordb": "0.4.10", "zod": "^3.23.8" }, @@ -22480,6 +22481,18 @@ "spdx-expression-parse": "^3.0.0" } }, + "node_modules/vaul": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/vaul/-/vaul-1.0.0.tgz", + "integrity": "sha512-TegfMkwy86RSvSiIVREG6OqgRL7agqRsKYyWYacyVUAdpcIi34QoCOED476Mbf8J5d06e1hygSdvJhehlxEBhQ==", + "dependencies": { + "@radix-ui/react-dialog": "^1.1.1" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + } + }, "node_modules/vectordb": { "version": "0.4.10", "cpu": [ diff --git a/package.json b/package.json index 709fec36..030f6cfc 100644 --- a/package.json +++ b/package.json @@ -121,6 +121,7 @@ "use-debounce": "^10.0.1", "uuid": "^10.0.0", "uuidv4": "^6.2.13", + "vaul": "^1.0.0", "vectordb": "0.4.10", "zod": "^3.23.8" }, diff --git a/src/components/Chat/StartChat.tsx b/src/components/Chat/StartChat.tsx index 6bb44462..48ec9531 100644 --- a/src/components/Chat/StartChat.tsx +++ b/src/components/Chat/StartChat.tsx @@ -14,6 +14,16 @@ import DbSearchFilters from './ChatConfigComponents/DBSearchFilters' import exampleAgents from './ChatConfigComponents/exampleAgents' import PromptEditor from './ChatConfigComponents/PromptEditor' import ToolSelector from './ChatConfigComponents/ToolSelector' +import { + Drawer, + DrawerClose, + DrawerContent, + DrawerDescription, + DrawerFooter, + DrawerHeader, + DrawerTitle, + DrawerTrigger, +} from '@/components/ui/drawer' interface StartChatProps { defaultModelName: string @@ -26,6 +36,7 @@ const StartChat: React.FC = ({ defaultModelName, handleNewChatMe const [userTextFieldInput, setUserTextFieldInput] = useState('') const [agentConfig, setAgentConfig] = useState(exampleAgents[0]) const [selectedTools, setSelectedTools] = useState(agentConfig.toolDefinitions) + const [isDrawerOpen, setIsDrawerOpen] = useState(false) useEffect(() => { const fetchLLMModels = async () => { @@ -74,6 +85,9 @@ const StartChat: React.FC = ({ defaultModelName, handleNewChatMe } : undefined, })) + if (checked) { + setIsDrawerOpen(true) + } } return ( @@ -164,12 +178,29 @@ const StartChat: React.FC = ({ defaultModelName, handleNewChatMe - {agentConfig.dbSearchFilters && ( - - )} + + + + + + + Database Search Filters + Configure your database search filters + + {agentConfig.dbSearchFilters && ( + + )} + + + + + + + + diff --git a/src/components/ui/drawer.tsx b/src/components/ui/drawer.tsx new file mode 100644 index 00000000..9b3b5c19 --- /dev/null +++ b/src/components/ui/drawer.tsx @@ -0,0 +1,89 @@ +/* eslint-disable react/prop-types */ +/* eslint-disable react/jsx-props-no-spreading */ +import * as React from 'react' +import { Drawer as DrawerPrimitive } from 'vaul' + +import { cn } from '@/lib/utils' + +const Drawer = ({ shouldScaleBackground = true, ...props }: React.ComponentProps) => ( + +) +Drawer.displayName = 'Drawer' + +const DrawerTrigger = DrawerPrimitive.Trigger + +const DrawerPortal = DrawerPrimitive.Portal + +const DrawerClose = DrawerPrimitive.Close + +const DrawerOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DrawerOverlay.displayName = DrawerPrimitive.Overlay.displayName + +const DrawerContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + +
+ {children} + + +)) +DrawerContent.displayName = 'DrawerContent' + +const DrawerHeader = ({ className, ...props }: React.HTMLAttributes) => ( +
+) +DrawerHeader.displayName = 'DrawerHeader' + +const DrawerFooter = ({ className, ...props }: React.HTMLAttributes) => ( +
+) +DrawerFooter.displayName = 'DrawerFooter' + +const DrawerTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DrawerTitle.displayName = DrawerPrimitive.Title.displayName + +const DrawerDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DrawerDescription.displayName = DrawerPrimitive.Description.displayName + +export { + Drawer, + DrawerPortal, + DrawerOverlay, + DrawerTrigger, + DrawerClose, + DrawerContent, + DrawerHeader, + DrawerFooter, + DrawerTitle, + DrawerDescription, +} From 91ad3189f299dc6ff12ec34b61ffcdb274419056 Mon Sep 17 00:00:00 2001 From: samlhuillier Date: Sun, 29 Sep 2024 11:50:32 +0100 Subject: [PATCH 3/4] change settings icon --- src/components/Chat/StartChat.tsx | 39 +++++++++++++++++-------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/src/components/Chat/StartChat.tsx b/src/components/Chat/StartChat.tsx index 48ec9531..50b77eea 100644 --- a/src/components/Chat/StartChat.tsx +++ b/src/components/Chat/StartChat.tsx @@ -1,5 +1,6 @@ import React, { useCallback, useEffect, useState } from 'react' import { PiPaperPlaneRight } from 'react-icons/pi' +import { FiSettings } from 'react-icons/fi' import { LLMConfig } from 'electron/main/electron-store/storeConfig' import '../../styles/chat.css' import { AgentConfig, ToolDefinition, DatabaseSearchFilters } from './types' @@ -85,9 +86,6 @@ const StartChat: React.FC = ({ defaultModelName, handleNewChatMe } : undefined, })) - if (checked) { - setIsDrawerOpen(true) - } } return ( @@ -167,21 +165,28 @@ const StartChat: React.FC = ({ defaultModelName, handleNewChatMe onToolsChange={handleToolsChange} /> -
- - -
- - - - +
+ + + + + +
Database Search Filters From 37851a3f8d02e527486d6d33f934f1f93434d69f Mon Sep 17 00:00:00 2001 From: samlhuillier Date: Mon, 30 Sep 2024 20:49:54 +0100 Subject: [PATCH 4/4] move prompt editor to main settings of chat --- package-lock.json | 11 ++- package.json | 2 + .../ChatConfigComponents/PromptEditor.tsx | 71 ++++++++++--------- .../ChatConfigComponents/exampleAgents.ts | 5 -- src/components/Chat/StartChat.tsx | 13 ++-- src/components/Chat/tools.ts | 2 +- src/components/Common/MarkdownRenderer.tsx | 5 +- .../LLMSettings/modals/NewOllamaModel.tsx | 4 +- 8 files changed, 67 insertions(+), 46 deletions(-) diff --git a/package-lock.json b/package-lock.json index ffcd4d0e..d4fc75df 100644 --- a/package-lock.json +++ b/package-lock.json @@ -71,6 +71,7 @@ "katex": "^0.16.10", "langchain": "^0.1.5", "lit": "^3.0.0", + "lodash": "^4.17.21", "lodash.debounce": "^4.0.8", "lucide-react": "^0.435.0", "marked": "^12.0.1", @@ -110,6 +111,7 @@ "@electron/notarize": "2.3.2", "@playwright/test": "^1.37.1", "@types/jest": "^29.5.11", + "@types/lodash": "^4.17.9", "@types/react": "^18.2.20", "@types/react-dom": "^18.2.7", "@types/react-window": "^1.8.8", @@ -5529,6 +5531,12 @@ "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.5.tgz", "integrity": "sha512-yg6E+u0/+Zjva+buc3EIb+29XEg4wltq7cSmd4Uc2EE/1nUVmxyzpX6gUXD0V8jIrG0r7YeOGVIbYRkxeooCtw==" }, + "node_modules/@types/lodash": { + "version": "4.17.9", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.9.tgz", + "integrity": "sha512-w9iWudx1XWOHW5lQRS9iKpK/XuRhnN+0T7HvdCCd802FYkT1AMTnxndJHGrNJwRoRHkslGr4S29tjm1cT7x/7w==", + "dev": true + }, "node_modules/@types/long": { "version": "4.0.2", "license": "MIT" @@ -14730,7 +14738,8 @@ }, "node_modules/lodash": { "version": "4.17.21", - "license": "MIT" + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, "node_modules/lodash.assignwith": { "version": "4.2.0", diff --git a/package.json b/package.json index 030f6cfc..6a29c7b8 100644 --- a/package.json +++ b/package.json @@ -90,6 +90,7 @@ "katex": "^0.16.10", "langchain": "^0.1.5", "lit": "^3.0.0", + "lodash": "^4.17.21", "lodash.debounce": "^4.0.8", "lucide-react": "^0.435.0", "marked": "^12.0.1", @@ -129,6 +130,7 @@ "@electron/notarize": "2.3.2", "@playwright/test": "^1.37.1", "@types/jest": "^29.5.11", + "@types/lodash": "^4.17.9", "@types/react": "^18.2.20", "@types/react-dom": "^18.2.7", "@types/react-window": "^1.8.8", diff --git a/src/components/Chat/ChatConfigComponents/PromptEditor.tsx b/src/components/Chat/ChatConfigComponents/PromptEditor.tsx index aaf926d1..1d7530c1 100644 --- a/src/components/Chat/ChatConfigComponents/PromptEditor.tsx +++ b/src/components/Chat/ChatConfigComponents/PromptEditor.tsx @@ -1,10 +1,9 @@ -import React, { useState } from 'react' +import React, { useState, useEffect, useCallback } from 'react' +import { debounce } from 'lodash' import { PromptTemplate } from '../types' -import { DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from '@/components/ui/dialog' import { Label } from '@/components/ui/label' import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select' import { Textarea } from '@/components/ui/textarea' -import { Button } from '@/components/ui/button' const PromptEditor: React.FC<{ promptTemplate: PromptTemplate @@ -12,20 +11,42 @@ const PromptEditor: React.FC<{ }> = ({ promptTemplate, onSave }) => { const [editedPrompt, setEditedPrompt] = useState(promptTemplate) - const handleSave = () => { - onSave(editedPrompt) + // eslint-disable-next-line react-hooks/exhaustive-deps + const debouncedSave = useCallback( + debounce((newPromptTemplate: PromptTemplate) => { + onSave(newPromptTemplate) + }, 500), + [onSave], + ) + + useEffect(() => { + debouncedSave(editedPrompt) + }, [editedPrompt, debouncedSave]) + + const updateRole = (index: number, newRole: 'system' | 'user') => { + setEditedPrompt((prevPrompt) => { + const updatedPrompt = [...prevPrompt] + updatedPrompt[index] = { ...updatedPrompt[index], role: newRole } + return updatedPrompt + }) + } + + const updateContent = (index: number, newContent: string) => { + setEditedPrompt((prevPrompt) => { + const updatedPrompt = [...prevPrompt] + updatedPrompt[index] = { ...updatedPrompt[index], content: newContent } + return updatedPrompt + }) } return ( - - - Edit Prompt Template - - Customize the prompt template for your AI assistant. Use the variables {`{QUERY}`} and {`{CONTEXT}`} to - reference the user's query and the context searched (if you toggle the "make initial search" - option in settings). - - +
+

Edit Prompt Template

+

+ Customize the prompt template for your AI assistant. Use the variables {`{QUERY}`} and {`{CONTEXT}`} to + reference the user's query and the context searched (if you toggle the "make initial search" + option in settings). +

{editedPrompt.map((prompt, index) => ( // eslint-disable-next-line react/no-array-index-key @@ -34,14 +55,7 @@ const PromptEditor: React.FC<{ - updateRole(index, value)}> @@ -58,21 +72,14 @@ const PromptEditor: React.FC<{