Skip to content

Commit

Permalink
Merge pull request #62 from Royal-lobster:chat-prompts
Browse files Browse the repository at this point in the history
Adds prompt selection and model selection with in sidebar input
  • Loading branch information
Royal-lobster authored Apr 13, 2024
2 parents 9fa6bb7 + bbd3b29 commit f5b594c
Show file tree
Hide file tree
Showing 38 changed files with 311 additions and 197 deletions.
5 changes: 5 additions & 0 deletions .changeset/eleven-dogs-remain.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"syncia": minor
---

Adds prompt selection and model selection with in sidebar input
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@
"dependencies": {
"@dnd-kit/core": "^6.0.8",
"@dnd-kit/sortable": "^7.0.2",
"@langchain/community": "^0.0.27",
"@langchain/community": "^0.0.48",
"@langchain/core": "^0.1.57",
"@langchain/openai": "^0.0.28",
"@radix-ui/react-dialog": "^1.0.3",
"@radix-ui/react-dropdown-menu": "^2.0.4",
"@radix-ui/react-select": "^2.0.0",
Expand All @@ -34,7 +36,7 @@
"dnd-kit-sortable-tree": "^0.1.58",
"endent": "^2.1.0",
"jotai": "^2.4.3",
"langchain": "^0.1.17",
"langchain": "^0.1.33",
"object-hash": "^3.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
Expand Down
2 changes: 1 addition & 1 deletion src/components/Layout/DialogPortal.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react'
import type React from 'react'
import * as Dialog from '@radix-ui/react-dialog'
import { HiX } from 'react-icons/hi'

Expand Down
5 changes: 2 additions & 3 deletions src/components/Layout/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import React from 'react'
import { BsRobot } from 'react-icons/bs'

const Header = () => {
return (
<div>
<h1 className='cdx-flex cdx-items-center cdx-gap-3 items-center cdx-text-5xl cdx-mb-2 dark:cdx-text-neutral-100 cdx-text-neutral-800'>
<BsRobot className='cdx-text-blue-400' />
<h1 className="cdx-flex cdx-items-center cdx-gap-3 items-center cdx-text-5xl cdx-mb-2 dark:cdx-text-neutral-100 cdx-text-neutral-800">
<BsRobot className="cdx-text-blue-400" />
<span>Syncia</span>
</h1>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/components/QuickMenu/RecursiveItem.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as DropdownMenu from '@radix-ui/react-dropdown-menu'
import { ContentClassNames, ItemClassNames } from '.'
import { Prompt } from '../../hooks/usePrompts'
import type { Prompt } from '../../hooks/usePrompts'
import { HiOutlineChevronRight } from 'react-icons/hi'

type RecursiveItemProps = {
Expand Down
2 changes: 1 addition & 1 deletion src/components/Settings/Elements/AddItemButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ 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 { type Prompt, usePrompts } from '../../../hooks/usePrompts'
import DialogPortal from '../../Layout/DialogPortal'
import { getUUID } from '../../../lib/getUUID'

Expand Down
6 changes: 3 additions & 3 deletions src/components/Settings/Elements/DeletePromptButton.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useState } from 'react'
import { Prompt, usePrompts } from '../../../hooks/usePrompts'
import { type Prompt, usePrompts } from '../../../hooks/usePrompts'
import * as Dialog from '@radix-ui/react-dialog'
import { HiTrash } from 'react-icons/hi'
import DialogPortal from '../../Layout/DialogPortal'
Expand All @@ -11,11 +11,11 @@ export const DeletePromptButton = ({ id }: { id: string }) => {
const handleDelete = () => {
const removeItem = (items: Prompt[], id: string): Prompt[] => {
const newItems = items.filter((item) => item.id !== id)
newItems.forEach((item) => {
for (const item of newItems) {
if (item.children) {
item.children = removeItem(item.children, id)
}
})
}
return newItems
}
setPrompts([])
Expand Down
2 changes: 1 addition & 1 deletion src/components/Settings/Elements/EditPromptButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as Dialog from '@radix-ui/react-dialog'
import { useRef, useState } from 'react'
import { HiPencilAlt } from 'react-icons/hi'
import TextareaAutosize from 'react-textarea-autosize'
import { Prompt, usePrompts } from '../../../hooks/usePrompts'
import { type Prompt, usePrompts } from '../../../hooks/usePrompts'
import DialogPortal from '../../Layout/DialogPortal'

export const EditPromptButton = ({
Expand Down
10 changes: 5 additions & 5 deletions src/components/Settings/Elements/FieldWrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react'
import type React from 'react'

interface FieldWrapperProps {
title: string
Expand All @@ -18,20 +18,20 @@ const FieldWrapper = ({
return (
<form
data-row={row || undefined}
className='cdx-flex cdx-flex-col cdx-gap-1 data-[row]:cdx-items-center cdx-my-4 data-[row]:cdx-flex-row data-[row]:cdx-justify-between data-[row]:cdx-gap-2'
className="cdx-flex cdx-flex-col cdx-gap-1 data-[row]:cdx-items-center cdx-my-4 data-[row]:cdx-flex-row data-[row]:cdx-justify-between data-[row]:cdx-gap-2"
onSubmit={onSubmit}
>
<div>
<label className='cdx-text-xl dark:cdx-text-neutral-200 cdx-text-neutral-700'>
<label className="cdx-text-xl dark:cdx-text-neutral-200 cdx-text-neutral-700">
{title}
</label>
{description && (
<p className='cdx-text-sm cdx-mt-2 cdx-text-neutral-400'>
<p className="cdx-text-sm cdx-mt-2 cdx-text-neutral-400">
{description}
</p>
)}
</div>
<div className='cdx-mt-2'>{children}</div>
<div className="cdx-mt-2">{children}</div>
</form>
)
}
Expand Down
43 changes: 9 additions & 34 deletions src/components/Settings/Sections/ChatSettings.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import React, { useCallback, useEffect } from 'react'
import SectionHeading from '../Elements/SectionHeading'
import FieldWrapper from '../Elements/FieldWrapper'
import * as Switch from '@radix-ui/react-switch'
import React, { useState } from 'react'
import { AiOutlineEye, AiOutlineEyeInvisible } from 'react-icons/ai'
import { useSettings } from '../../../hooks/useSettings'
import { validateApiKey } from '../../../lib/validApiKey'
import { AvailableModels, Mode } from '../../../config/settings'
import { useChatModels } from '../../../hooks/useChatModels'
import { capitalizeText } from '../../../lib/capitalizeText'
import { useState } from 'react'
import { AiOutlineEye, AiOutlineEyeInvisible } from 'react-icons/ai'
import axios from 'axios'
import * as Switch from '@radix-ui/react-switch'
import { validateApiKey } from '../../../lib/validApiKey'
import FieldWrapper from '../Elements/FieldWrapper'
import SectionHeading from '../Elements/SectionHeading'
import { type AvailableModels, Mode } from '../../../config/settings'

const ChatSettings = () => {
const [settings, setSettings] = useSettings()
const [showPassword, setShowPassword] = useState(false)
const [dynamicModels, setDynamicModels] = useState<string[]>([])
const { availableModels, fetchLocalModels } = useChatModels()
const OpenAiApiKeyInputRef = React.useRef<HTMLInputElement>(null)

const chatSettings = settings.chat
Expand Down Expand Up @@ -50,30 +49,6 @@ const ChatSettings = () => {
}
}

const fetchLocalModels = useCallback(async () => {
if (chatSettings.showLocalModels) {
const {
data: { models },
} = await axios<{ models: { name: string }[] }>(
'http://localhost:11434/api/tags',
)
if (models) {
setDynamicModels(models.map((m) => m.name))
}
} else {
setDynamicModels([])
}
}, [chatSettings.showLocalModels])

useEffect(() => {
fetchLocalModels()
}, [fetchLocalModels])

const availableModels = [
...Object.entries(AvailableModels),
...dynamicModels.map((m) => [m, m]),
]

return (
<div className="cdx-w-full cdx-flex-shrink-0 cdx-rounded-md">
<SectionHeading title="Chat" />
Expand Down
5 changes: 2 additions & 3 deletions src/components/Sidebar/auth/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,9 @@ const Auth = () => {
const handleOpenAiKeySubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault()
const data = new FormData(e.currentTarget)
const key = data.get('openAiKey')
const isVaildApiKey: boolean = await validateApiKey(key as string)
const key = data.get('openAiKey') as string | null

if (key && isVaildApiKey) {
if (key && (await validateApiKey(key))) {
setSettings((prev) => ({
...prev,
chat: {
Expand Down
35 changes: 35 additions & 0 deletions src/components/Sidebar/chat/ChangeChatModel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { BsRobot } from 'react-icons/bs'
import type { AvailableModels } from '../../../config/settings'
import { useChatModels } from '../../../hooks/useChatModels'
import { capitalizeText } from '../../../lib/capitalizeText'

const ChangeChatModel = () => {
const { availableModels, activeChatModel, setActiveChatModel } =
useChatModels()
return (
<div className="cdx-flex cdx-items-center cdx-gap-1 cdx-text-neutral-500 dark:cdx-bg-black/20 cdx-bg-black/10 cdx-border cdx-rounded-md cdx-border-neutral-400/30 dark:cdx-border-neutral-500/30 cdx-py-1 cdx-px-3">
<BsRobot size={18} className="cdx-flex-shrink-0" />
<select
value={activeChatModel}
className="cdx-bg-transparent !m-0 !p-0 cdx-box-border cdx-w-min focus:cdx-outline-none focus:cdx-ring-1"
onChange={(e) => {
setActiveChatModel(e.target.value as AvailableModels)
}}
>
{availableModels.map(([modal, value]) => (
<option key={modal} value={value}>
{capitalizeText(
modal
.toLowerCase()
.replace('gpt', 'GPT')
.replace('3_5', '3.5')
.replaceAll('_', ' '),
)}
</option>
))}
</select>
</div>
)
}

export default ChangeChatModel
5 changes: 2 additions & 3 deletions src/components/Sidebar/chat/ChatHistory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,8 @@ const ChatHistory = () => {
return (
<div>
<DropdownMenu.Root>
<DropdownMenu.Trigger className="cdx-border cdx-max-w-[280px] dark:cdx-bg-neutral-800/80 cdx-backdrop-blur cdx-border-neutral-500/20 cdx-flex cdx-gap-2 cdx-items-center cdx-py-2 cdx-px-3 cdx-text-sm cdx-text-neutral-700 dark:cdx-text-neutral-300 cdx-rounded-md">
<RiTimeLine size={18} className="cdx-flex-shrink-0" />{' '}
<span className="cdx-truncate">{currentChat?.name}</span>
<DropdownMenu.Trigger className="cdx-flex cdx-items-center cdx-gap-1 cdx-text-neutral-500 dark:cdx-bg-black/20 cdx-bg-black/10 cdx-border cdx-rounded-md cdx-border-neutral-400/30 dark:cdx-border-neutral-500/30 cdx-py-1 cdx-px-3">
<RiTimeLine size={18} className="cdx-flex-shrink-0" /> History
</DropdownMenu.Trigger>
<DropdownMenu.Content
side="top"
Expand Down
39 changes: 22 additions & 17 deletions src/components/Sidebar/chat/ChatInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,13 @@ import ChatHistory from './ChatHistory'
import { useChatHistory } from '../../../hooks/useChatHistory'
import WebPageContentToggle from './WebPageContentToggle'
import ImageCaptureButton from './ImageCaptureButton'
import { MessageDraft, useMessageDraft } from '../../../hooks/useMessageDraft'
import {
type MessageDraft,
useMessageDraft,
} from '../../../hooks/useMessageDraft'
import FilePreviewBar from './FilePreviewBar'
import MessageDraftLengthCounter from './MessageDraftLengthCounter'
import ChangeChatModel from './ChangeChatModel'
import InsertPromptToDraftButton from './InsertPromptToDraftButton'

interface SidebarInputProps {
loading: boolean
Expand Down Expand Up @@ -52,10 +56,10 @@ export function SidebarInput({
}, [loading])

const handleSubmit = async () => {
let context
let context: string | undefined
if (isWebpageContextOn) {
const pageContent = new Promise((resolve) => {
window.addEventListener('message', function (event) {
window.addEventListener('message', (event) => {
const { action, payload } = event.data
if (action === 'get-page-content') {
resolve(payload)
Expand Down Expand Up @@ -98,14 +102,17 @@ export function SidebarInput({
<button
type="button"
onClick={clearMessages}
className="cdx-rounded-full cdx-h-10 cdx-w-10 cdx-grid cdx-place-items-center cdx-text-center cdx-bg-blue-500 hover:cdx-bg-blue-700 cdx-text-white"
className="cdx-rounded-full cdx-h-8 cdx-w-8 cdx-grid cdx-place-items-center cdx-text-center cdx-bg-blue-500 hover:cdx-bg-blue-700 cdx-text-white"
>
<GiMagicBroom size={18} className="mx-auto" />
<GiMagicBroom size={16} className="mx-auto" />
</button>
) : (
<div />
)}
{(history.length || !chatIsEmpty) && <ChatHistory />}
<div className="cdx-flex cdx-gap-2">
<ChangeChatModel />
{(history.length || !chatIsEmpty) && <ChatHistory />}
</div>
</div>

<div className="cdx-m-2 cdx-rounded-md cdx-border dark:cdx-border-neutral-800 cdx-border-neutral-300 dark:cdx-bg-neutral-900/90 cdx-bg-neutral-200/90 focus:cdx-outline-none focus:cdx-ring-2 focus:cdx-ring-blue-900 focus:cdx-ring-opacity-50">
Expand Down Expand Up @@ -134,16 +141,14 @@ export function SidebarInput({
}}
/>
<div className="cdx-flex cdx-justify-between cdx-items-center cdx-p-3">
{isVisionModel ? (
<ImageCaptureButton addMessageDraftFile={addMessageDraftFile} />
) : (
<div>
<MessageDraftLengthCounter
length={messageDraft.text.length}
MAX_LENGTH={MAX_MESSAGE_LENGTH}
/>
</div>
)}
<div className="cdx-flex cdx-gap-2">
{isVisionModel && (
<ImageCaptureButton addMessageDraftFile={addMessageDraftFile} />
)}
<InsertPromptToDraftButton
setMessageDraftText={setMessageDraftText}
/>
</div>
<div className="cdx-flex cdx-items-center cdx-justify-center cdx-gap-4">
<WebPageContentToggle />
{!delayedLoading ? sendButton : stopButton}
Expand Down
2 changes: 1 addition & 1 deletion src/components/Sidebar/chat/ChatList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ReactMarkdown } from 'react-markdown/lib/react-markdown'
import rehypeRaw from 'rehype-raw'
import remarkBreaks from 'remark-breaks'
import remarkGfm from 'remark-gfm'
import { ChatMessage, ChatRole } from '../../../hooks/useCurrentChat'
import { type ChatMessage, ChatRole } from '../../../hooks/useCurrentChat'
import FilePreviewBar from './FilePreviewBar'
import CodeBlock from './markdown-components/CodeBlock'
import { Table } from './markdown-components/Table'
Expand Down
6 changes: 3 additions & 3 deletions src/components/Sidebar/chat/ImageCaptureButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const ImageCaptureButton = ({
const handleScreenshotClick = async () => {
const imageBlob: Blob = await new Promise((resolve) => {
window.parent.postMessage({ action: 'get-screenshot-image' }, '*')
window.addEventListener('message', function (event) {
window.addEventListener('message', (event) => {
const { action, payload } = event.data
if (action === 'get-screenshot-image') {
resolve(payload)
Expand All @@ -24,9 +24,9 @@ const ImageCaptureButton = ({
<button
onClick={handleScreenshotClick}
type="button"
className="cdx-bg-neutral-300 cdx-text-neutral-500 dark:cdx-text-neutral-200 dark:cdx-bg-neutral-800 cdx-p-2 cdx-rounded"
className="cdx-bg-neutral-300 cdx-text-neutral-500 dark:cdx-text-neutral-200 dark:cdx-bg-neutral-800 cdx-p-1.5 cdx-rounded"
>
<RiScreenshot2Line size={20} />
<RiScreenshot2Line size={18} />
</button>
)
}
Expand Down
Loading

0 comments on commit f5b594c

Please sign in to comment.