import React from 'react'; import { Header, Segment, Form, Button, Icon, Message, Card, Label, Divider, Accordion } from 'semantic-ui-react'; import superagent from 'superagent'; import ExperimentalWrapper from './ExperimentalWrapper.jsx'; // Simple markdown to HTML converter for basic formatting function renderMarkdown(text) { if (!text) return ''; let html = text // Escape HTML .replace(/&/g, '&') .replace(//g, '>') // Code blocks (```...```) .replace(/```(\w*)\n([\s\S]*?)```/g, '
$2')
// Inline code (`...`)
.replace(/`([^`]+)`/g, '$1')
// Headers
.replace(/^### (.+)$/gm, '')
// Single line breaks
.replace(/\n/g, '
');
// Wrap consecutive
' + html + '
'; } export default class KBQuery extends React.Component { constructor(props) { super(props); this.state = { query: '', answer: null, sources: [], metadata: null, loading: false, error: null, includeContext: true, useReranking: true, expandedSources: {} }; } async onSubmit(e) { e.preventDefault(); const { query, includeContext, useReranking } = this.state; if (!query.trim()) { this.setState({ error: 'Please enter a question' }); return; } this.setState({ loading: true, error: null, answer: null, sources: [] }); try { const res = await superagent .post('/api/admin/kb/query') .send({ query: query.trim(), options: { limit: 10, includeContext: includeContext, useReranking: useReranking } }); this.setState({ answer: res.body.answer, sources: res.body.sources || [], metadata: res.body.metadata, loading: false }); } catch (error) { console.error('Query failed:', error); this.setState({ error: error.response?.body?.details || error.response?.body?.error || error.message, loading: false }); } } toggleSource(index) { this.setState(prevState => ({ expandedSources: { ...prevState.expandedSources, [index]: !prevState.expandedSources[index] } })); } renderAnswer() { const { answer, sources, metadata, expandedSources } = this.state; if (!answer) return null; return ({error}