/** * RAG (Retrieval-Augmented Generation) composable */ import { computed, type ComputedRef, type Ref, ref, reactive } from 'vue' import { useComplianceStore } from '../plugin' import type { SearchResponse, AssistantResponse, ChatMessage, LegalDocument, } from '@breakpilot/compliance-sdk-types' export interface UseRAGReturn { // Search search: (query: string, regulationCodes?: string[]) => Promise searchResults: Ref // Chat ask: (question: string, context?: string) => Promise chatHistory: Ref clearChat: () => void isTyping: Ref // Documents documents: ComputedRef availableRegulations: ComputedRef // Loading state isLoading: Ref error: Ref } export function useRAG(): UseRAGReturn { const store = useComplianceStore() const { state, rag } = store const isLoading = ref(false) const isTyping = ref(false) const error = ref(null) const searchResults = ref(null) const chatHistory = ref([]) // Search const search = async (query: string, regulationCodes?: string[]): Promise => { isLoading.value = true error.value = null try { const results = await rag.search(query, regulationCodes) searchResults.value = results return results } catch (err) { error.value = err instanceof Error ? err : new Error(String(err)) throw err } finally { isLoading.value = false } } // Chat const ask = async (question: string, context?: string): Promise => { isLoading.value = true isTyping.value = true error.value = null // Add user message to history chatHistory.value.push({ id: `msg_${Date.now()}`, role: 'user', content: question, timestamp: new Date().toISOString(), }) try { const response = await rag.ask(question, context) // Add assistant response to history chatHistory.value.push({ id: `msg_${Date.now()}`, role: 'assistant', content: response.answer, timestamp: new Date().toISOString(), citations: response.citations, }) return response } catch (err) { error.value = err instanceof Error ? err : new Error(String(err)) // Add error message to history chatHistory.value.push({ id: `msg_${Date.now()}`, role: 'assistant', content: 'Es ist ein Fehler aufgetreten. Bitte versuchen Sie es erneut.', timestamp: new Date().toISOString(), }) throw err } finally { isLoading.value = false isTyping.value = false } } const clearChat = (): void => { chatHistory.value = [] rag.clearHistory() } // Documents const documents = computed(() => state.legalDocuments) const availableRegulations = computed(() => { const codes = new Set() state.legalDocuments.forEach(doc => { if (doc.regulationCode) { codes.add(doc.regulationCode) } }) return Array.from(codes).sort() }) return { search, searchResults, ask, chatHistory, clearChat, isTyping, documents, availableRegulations, isLoading, error, } }