import type { UIMessage } from 'ai' import { useAppConfig, useRuntimeConfig } from '#imports' import { createSharedComposable, useLocalStorage } from '@vueuse/core' import { computed, ref, watch } from 'vue' import type { FaqCategory, FaqQuestions, LocalizedFaqQuestions } from '../types' function normalizeFaqQuestions(questions: FaqQuestions): FaqCategory[] { if (!questions || (Array.isArray(questions) && questions.length === 0)) { return [] } if (typeof questions[0] === 'string') { return [{ category: 'Questions', items: questions as string[], }] } return questions as FaqCategory[] } export const useAssistant = createSharedComposable(() => { const config = useRuntimeConfig() const appConfig = useAppConfig() const assistantRuntimeConfig = config.public.assistant as { enabled?: boolean } | undefined const assistantConfig = appConfig.assistant as { faqQuestions?: FaqQuestions | LocalizedFaqQuestions } | undefined const docusRuntimeConfig = appConfig.docus as { locale?: string } | undefined const isEnabled = computed(() => assistantRuntimeConfig?.enabled ?? false) const storageOpen = useLocalStorage('assistant-open', false) const messages = useLocalStorage('assistant-messages', []) const isOpen = ref(false) const isStudioExpanded = ref(false) onNuxtReady(() => { nextTick(() => { isOpen.value = storageOpen.value }) isStudioExpanded.value = document.body.hasAttribute('data-expand-sidebar') const observer = new MutationObserver(() => { isStudioExpanded.value = document.body.hasAttribute('data-expand-sidebar') }) observer.observe(document.body, { attributes: true, attributeFilter: ['data-expand-sidebar'] }) }) watch(isOpen, (value) => { storageOpen.value = value }) const faqQuestions = computed(() => { const faqConfig = assistantConfig?.faqQuestions if (!faqConfig) return [] if (!Array.isArray(faqConfig)) { const localizedConfig = faqConfig as LocalizedFaqQuestions const currentLocale = docusRuntimeConfig?.locale || 'en' const defaultLocale = config.public.i18n?.defaultLocale || 'en' const questions = localizedConfig[currentLocale] || localizedConfig[defaultLocale] || Object.values(localizedConfig)[0] return normalizeFaqQuestions(questions || []) } return normalizeFaqQuestions(faqConfig) }) function open(initialMessage?: string, clearPrevious = false) { if (isStudioExpanded.value) return if (clearPrevious) { messages.value = [] } if (initialMessage) { messages.value = [...messages.value, { id: String(Date.now()), role: 'user' as const, parts: [{ type: 'text' as const, text: initialMessage }], }] } isOpen.value = true } function close() { isOpen.value = false } function toggle() { if (isStudioExpanded.value) return isOpen.value = !isOpen.value } return { isEnabled, isOpen, isStudioExpanded, messages, faqQuestions, open, close, toggle, } })