feat(chat): enhance chat functionality with web search and article integration
- Updated ChatMessage and ChatWindow components to support inline web search results and articles. - Integrated new web search and RSS plugins into the chat system for real-time information retrieval. - Enhanced useContentPanel to manage web search results alongside existing media types. - Added ArticleOverlay component for displaying selected articles from search results. - Improved UI elements and styles for better user interaction with web search features. Made-with: Cursor
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const SAFE_URL_SCHEME = /^https?:\/\//i
|
||||
|
||||
export const useArticleOverlayStore = defineStore('articleOverlay', () => {
|
||||
const isOpen = ref(false)
|
||||
const url = ref<string | null>(null)
|
||||
const title = ref('')
|
||||
const content = ref<string | null>(null)
|
||||
const imgSrc = ref<string | null>(null)
|
||||
|
||||
function open(articleUrl: string, articleTitle = '', articleContent?: string, articleImgSrc?: string) {
|
||||
const trimmed = String(articleUrl ?? '').trim()
|
||||
if (!SAFE_URL_SCHEME.test(trimmed)) return
|
||||
try {
|
||||
new URL(trimmed)
|
||||
} catch {
|
||||
return
|
||||
}
|
||||
url.value = trimmed
|
||||
title.value = String(articleTitle ?? 'Article').slice(0, 200)
|
||||
content.value = typeof articleContent === 'string' && articleContent.trim().length > 0 ? articleContent.trim() : null
|
||||
imgSrc.value = typeof articleImgSrc === 'string' && articleImgSrc.trim().length > 0 ? articleImgSrc.trim() : null
|
||||
isOpen.value = true
|
||||
}
|
||||
|
||||
function close() {
|
||||
isOpen.value = false
|
||||
url.value = null
|
||||
title.value = ''
|
||||
content.value = null
|
||||
imgSrc.value = null
|
||||
}
|
||||
|
||||
return { isOpen, url, title, content, imgSrc, open, close }
|
||||
})
|
||||
@@ -1,6 +1,6 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref, computed, watch } from 'vue'
|
||||
import type { Message, Conversation } from '@aiui/core/types/message'
|
||||
import type { Message, Conversation, WebSearchResult } from '@aiui/core/types/message'
|
||||
|
||||
const isDev = import.meta.env.DEV
|
||||
let saveTimer: ReturnType<typeof setTimeout> | null = null
|
||||
@@ -52,6 +52,8 @@ export const useChatStore = defineStore('chat', () => {
|
||||
const savedSide = localStorage.getItem('aiui-panel-side') as 'left' | 'right' | null
|
||||
const panelSide = ref<'left' | 'right'>(savedSide ?? 'right')
|
||||
|
||||
const webSearchEnabled = ref(localStorage.getItem('aiui-web-search') !== 'false')
|
||||
|
||||
// Load chats from server on startup — _loaded gate prevents the watcher
|
||||
// from overwriting the file with empty data before the load completes
|
||||
if (isDev) {
|
||||
@@ -75,6 +77,10 @@ export const useChatStore = defineStore('chat', () => {
|
||||
localStorage.setItem('aiui-panel-side', val)
|
||||
})
|
||||
|
||||
watch(webSearchEnabled, (val) => {
|
||||
localStorage.setItem('aiui-web-search', String(val))
|
||||
})
|
||||
|
||||
watch(
|
||||
[conversations, activeConversationId],
|
||||
([conv, active]) => {
|
||||
@@ -134,6 +140,13 @@ export const useChatStore = defineStore('chat', () => {
|
||||
last.content += text
|
||||
}
|
||||
|
||||
function setMessageWebResults(conversationId: string, messageId: string, results: WebSearchResult[]) {
|
||||
const conv = conversations.value.get(conversationId)
|
||||
if (!conv) return
|
||||
const msg = conv.messages.find((m) => m.id === messageId)
|
||||
if (msg) msg.webResults = results
|
||||
}
|
||||
|
||||
function switchSide() {
|
||||
panelSide.value = panelSide.value === 'right' ? 'left' : 'right'
|
||||
}
|
||||
@@ -161,9 +174,11 @@ export const useChatStore = defineStore('chat', () => {
|
||||
isStreaming,
|
||||
loaded,
|
||||
panelSide,
|
||||
webSearchEnabled,
|
||||
createConversation,
|
||||
addMessage,
|
||||
appendToLastMessage,
|
||||
setMessageWebResults,
|
||||
switchSide,
|
||||
setActiveConversation,
|
||||
deleteConversation,
|
||||
|
||||
Reference in New Issue
Block a user