feat: chat stop button, image paste, vision AI, search fixes
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 43s

- Add stop button to all chat interfaces (floating, contextual, full-page)
- Add conversation sliding window (50 messages) to prevent context overflow
- Add chat timeout warning (30s toast)
- Force response language in chat system prompt (mandatory per-locale)
- Add image paste from clipboard in all note editors (card, list, input)
- Fix upload API to infer extension from MIME type for clipboard images
- Add image description support in note AI chat (base64 vision)
- Fix search regex crash on special characters (escape user input)
- Fix search case-insensitivity on PostgreSQL (mode: 'insensitive')
- Add try/catch around semantic search in chat route (prevent blocking)
- Add new chat button to floating AI assistant
- Fix empty thinking bubbles for reasoning models (filter non-text parts)
- Remove duplicate AI assistant toggle from note editor header
- Improve link metadata scraping (timeout, content-type check, relative URLs)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-04-27 22:34:07 +02:00
parent 3b8152c7c0
commit ae89f8a014
13 changed files with 354 additions and 127 deletions

View File

@@ -40,6 +40,7 @@ export function ChatContainer({ initialConversations, notebooks, webSearchAvaila
sendMessage,
status,
setMessages,
stop,
} = useChat({
transport,
onError: (error) => {
@@ -49,6 +50,15 @@ export function ChatContainer({ initialConversations, notebooks, webSearchAvaila
const isLoading = status === 'submitted' || status === 'streaming'
// Timeout warning: show toast if response takes > 30s
useEffect(() => {
if (!isLoading) return
const timer = setTimeout(() => {
toast.warning(t('chat.timeoutWarning') || 'Response is taking longer than expected...')
}, 30000)
return () => clearTimeout(timer)
}, [isLoading, t])
// Sync historyMessages after each completed streaming response
// so the display doesn't revert to stale history
useEffect(() => {
@@ -190,6 +200,7 @@ export function ChatContainer({ initialConversations, notebooks, webSearchAvaila
<ChatInput
onSend={handleSendMessage}
isLoading={isLoading}
onStop={stop}
notebooks={notebooks}
currentNotebookId={selectedNotebook || null}
webSearchEnabled={webSearchEnabled}