/** * Template search helpers for document-generator. * * Two-tier search: * 1. Primary: own backend (compliance_legal_templates DB) — MIT-licensed, curated * 2. Fallback: RAG proxy (ai-compliance-sdk regulation search — law texts) */ import type { LegalTemplateResult } from '@/lib/sdk/types' export const TEMPLATES_API = '/api/sdk/v1/compliance/legal-templates' export const RAG_PROXY = '/api/sdk/v1/rag' export interface TemplateSearchParams { query: string templateType?: string licenseTypes?: string[] language?: 'de' | 'en' jurisdiction?: string limit?: number } /** * Search for legal templates. * * Tries own backend DB first (5 s timeout). Falls back to RAG proxy * (regulation texts — useful as reference, but not ready-made templates). * Returns an empty array if both services are down. */ export async function searchTemplates( params: TemplateSearchParams ): Promise { // 1. Primary: own backend — compliance_legal_templates table try { const url = new URL(TEMPLATES_API, window.location.origin) if (params.query) url.searchParams.set('query', params.query) if (params.templateType) url.searchParams.set('document_type', params.templateType) if (params.language) url.searchParams.set('language', params.language) url.searchParams.set('limit', String(params.limit || 20)) url.searchParams.set('status', 'published') const res = await fetch(url.toString(), { signal: AbortSignal.timeout(5000) }) if (res.ok) { const data = await res.json() return (data.templates || []).map(mapTemplateToResult) } } catch { // Backend not reachable — fall through to RAG } // 2. Fallback: RAG proxy (Gesetzestexte — Referenz, kein fertiges Template) try { const res = await fetch(`${RAG_PROXY}/search`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ query: params.query || '', limit: params.limit || 10 }), }) if (res.ok) { const data = await res.json() return (data.results || []).map((r: any, i: number) => ({ id: r.regulation_code || `rag-${i}`, score: r.score ?? 0.5, text: r.text || '', documentTitle: r.regulation_name || r.regulation_short || 'Dokument', templateType: 'regulation', clauseCategory: null, language: 'de', jurisdiction: 'eu', licenseId: null, licenseName: null, licenseUrl: null, attributionRequired: false, attributionText: null, sourceName: 'RAG', sourceUrl: null, sourceRepo: null, placeholders: [], isCompleteDocument: false, isModular: true, requiresCustomization: true, outputAllowed: true, modificationAllowed: true, distortionProhibited: false, source: 'rag' as const, })) } } catch { // both services failed } return [] } function mapTemplateToResult(r: any): LegalTemplateResult { return { id: r.id, score: 1.0, text: r.content || '', documentTitle: r.title, templateType: r.document_type, clauseCategory: null, language: r.language, jurisdiction: r.jurisdiction, licenseId: r.license_id as any, licenseName: r.license_name, licenseUrl: null, attributionRequired: r.attribution_required ?? false, attributionText: null, sourceName: r.source_name, sourceUrl: null, sourceRepo: null, placeholders: r.placeholders || [], isCompleteDocument: r.is_complete_document ?? true, isModular: false, requiresCustomization: (r.placeholders || []).length > 0, outputAllowed: true, modificationAllowed: true, distortionProhibited: false, source: 'db' as const, } } /** * Load all published templates without requiring a search query. * Used for the library-first UX (show all cards on initial load). */ export async function loadAllTemplates(limit = 200): Promise { try { const url = new URL(TEMPLATES_API, window.location.origin) url.searchParams.set('limit', String(limit)) url.searchParams.set('status', 'published') const res = await fetch(url.toString(), { signal: AbortSignal.timeout(5000) }) if (res.ok) { const data = await res.json() return (data.templates || []).map(mapTemplateToResult) } } catch { /* ignore */ } return [] } export async function getTemplatesStatus(): Promise { try { const res = await fetch(`${TEMPLATES_API}/status`, { signal: AbortSignal.timeout(5000) }) if (!res.ok) return null return res.json() } catch { return null } } export async function getSources(): Promise { try { // Fetch status to get type counts for building source objects const res = await fetch(`${TEMPLATES_API}/status`, { signal: AbortSignal.timeout(5000) }) if (!res.ok) return [] const data = await res.json() const byType: Record = data.by_type || {} const activeTypes = Object.keys(byType).filter(k => byType[k] > 0) return [ { name: 'BreakPilot Compliance', enabled: true, license_type: 'mit' as const, description: `${data.total || 0} selbst erstellte Vorlagen (MIT-Lizenz) — DE & EN`, template_types: activeTypes, }, ] } catch { return [] } }