diff --git a/web-app/src/containers/ChatInput.tsx b/web-app/src/containers/ChatInput.tsx index 6e314a0f52..a85a02a25d 100644 --- a/web-app/src/containers/ChatInput.tsx +++ b/web-app/src/containers/ChatInput.tsx @@ -4,7 +4,6 @@ import TextareaAutosize from 'react-textarea-autosize' import { cn } from '@/lib/utils' import { usePrompt } from '@/hooks/usePrompt' import { useThreads } from '@/hooks/useThreads' -import { useThreadManagement } from '@/hooks/useThreadManagement' import { useCallback, useEffect, useRef, useState } from 'react' import { Button } from '@/components/ui/button' import { @@ -53,8 +52,7 @@ type ChatInputProps = { const ChatInput = ({ model, className, - initialMessage, - projectId, + initialMessage }: ChatInputProps) => { const textareaRef = useRef(null) const [isFocused, setIsFocused] = useState(false) @@ -68,8 +66,6 @@ const ChatInput = ({ const prompt = usePrompt((state) => state.prompt) const setPrompt = usePrompt((state) => state.setPrompt) const currentThreadId = useThreads((state) => state.currentThreadId) - const updateThread = useThreads((state) => state.updateThread) - const { getFolderById } = useThreadManagement() const { t } = useTranslation() const spellCheckChatInput = useGeneralSetting( (state) => state.spellCheckChatInput @@ -196,27 +192,8 @@ const ChatInput = ({ ) setUploadedFiles([]) - // Handle project assignment for new threads - if (projectId && !currentThreadId) { - const project = getFolderById(projectId) - if (project) { - // Use setTimeout to ensure the thread is created first - setTimeout(() => { - const newCurrentThreadId = useThreads.getState().currentThreadId - if (newCurrentThreadId) { - updateThread(newCurrentThreadId, { - metadata: { - project: { - id: project.id, - name: project.name, - updated_at: project.updated_at, - }, - }, - }) - } - }, 100) - } - } + // Note: Project assignment for new threads is now handled directly in useChat.ts + // when creating the thread, ensuring the project system prompt is applied from the first message } useEffect(() => { diff --git a/web-app/src/containers/LeftPanel.tsx b/web-app/src/containers/LeftPanel.tsx index f24dcec0d0..e0e7accc58 100644 --- a/web-app/src/containers/LeftPanel.tsx +++ b/web-app/src/containers/LeftPanel.tsx @@ -212,11 +212,11 @@ const LeftPanel = () => { } } - const handleProjectSave = (name: string) => { + const handleProjectSave = (name: string, systemPrompt?: string) => { if (editingProjectKey) { - updateFolder(editingProjectKey, name) + updateFolder(editingProjectKey, name, systemPrompt) } else { - const newProject = addFolder(name) + const newProject = addFolder(name, systemPrompt) // Navigate to the newly created project navigate({ to: '/project/$projectId', diff --git a/web-app/src/containers/dialogs/AddProjectDialog.tsx b/web-app/src/containers/dialogs/AddProjectDialog.tsx index f0fda648c2..cf709e7c87 100644 --- a/web-app/src/containers/dialogs/AddProjectDialog.tsx +++ b/web-app/src/containers/dialogs/AddProjectDialog.tsx @@ -8,6 +8,7 @@ import { } from '@/components/ui/dialog' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' +import { Textarea } from '@/components/ui/textarea' import { useThreadManagement } from '@/hooks/useThreadManagement' import { toast } from 'sonner' import { useTranslation } from '@/i18n/react-i18next-compat' @@ -20,8 +21,9 @@ interface AddProjectDialogProps { id: string name: string updated_at: number + systemPrompt?: string } - onSave: (name: string) => void + onSave: (name: string, systemPrompt?: string) => void } export default function AddProjectDialog({ @@ -33,11 +35,13 @@ export default function AddProjectDialog({ }: AddProjectDialogProps) { const { t } = useTranslation() const [name, setName] = useState(initialData?.name || '') + const [systemPrompt, setSystemPrompt] = useState(initialData?.systemPrompt || '') const { folders } = useThreadManagement() useEffect(() => { if (open) { setName(initialData?.name || '') + setSystemPrompt(initialData?.systemPrompt || '') } }, [open, initialData]) @@ -58,16 +62,23 @@ export default function AddProjectDialog({ return } - onSave(trimmedName) + onSave(trimmedName, systemPrompt.trim() || undefined) // Show detailed success message if (editingKey && initialData) { - toast.success( - t('projects.addProjectDialog.renameSuccess', { - oldName: initialData.name, - newName: trimmedName - }) - ) + const nameChanged = trimmedName !== initialData.name + + if (nameChanged) { + toast.success( + t('projects.addProjectDialog.renameSuccess', { + oldName: initialData.name, + newName: trimmedName + }) + ) + } else { + // Only system prompt changed + toast.success(t('projects.addProjectDialog.updateSuccess', { projectName: trimmedName })) + } } else { toast.success(t('projects.addProjectDialog.createSuccess', { projectName: trimmedName })) } @@ -78,11 +89,15 @@ export default function AddProjectDialog({ const handleCancel = () => { onOpenChange(false) setName('') + setSystemPrompt('') } // Check if the button should be disabled const isButtonDisabled = - !name.trim() || (editingKey && name.trim() === initialData?.name) + !name.trim() || + (editingKey && + name.trim() === initialData?.name && + systemPrompt.trim() === (initialData?.systemPrompt)) return ( @@ -110,6 +125,18 @@ export default function AddProjectDialog({ }} /> +
+ +