Files
Heimgeist/src/WebsearchSettings.jsx
Victor Giers 728c7763e2 Add web search enrichment feature with source persistence and UI integration
Introduce optional web search enrichment flow for chat and regenerate requests. New /websearch endpoint calls enrich_prompt via SearXNG and returns enriched_prompt + citation sources.

DB: add sources_json column to chat_messages via ensure_sources_column migration helper.

Backend: persist sources_json for assistant replies (streaming and non-streaming); extend ChatRequest/RegenerateRequest to accept enriched_message and sources; history endpoint returns sources.

Frontend: add toggle for web search, settings for SearXNG URL + engines, and optional enrichment calls in sendMessage/regenerate. Render citation sources as rounded chips labeled with base domain under assistant replies.

Dependencies: add beautifulsoup4, httpx[http2], numpy for enrichment pipeline.
2025-08-27 04:27:18 +02:00

62 lines
1.5 KiB
JavaScript

// src/WebsearchSettings.jsx
import React, { useEffect, useMemo, useState } from 'react';
export default function WebsearchSettings({
searxUrl,
setSearxUrl,
engines,
setEngines,
}) {
const KNOWN_ENGINES = useMemo(
() => ["google","bing","yahoo","duckduckgo","brave","github","stackoverflow","reddit","arxiv"],
[]
);
const [custom, setCustom] = useState("");
const toggleEngine = (name) => {
const set = new Set(engines || []);
if (set.has(name)) set.delete(name); else set.add(name);
setEngines(Array.from(set));
};
const addCustom = () => {
const name = custom.trim();
if (!name) return;
const set = new Set(engines || []);
set.add(name);
setEngines(Array.from(set));
setCustom("");
};
return (
<div className="settings-content-panel">
<div className="setting-section">
<h3>SearXNG URL</h3>
<input
type="text"
className="input"
value={searxUrl}
onChange={e => setSearxUrl(e.target.value)}
placeholder="e.g., http://localhost:8888"
/>
</div>
<div className="setting-section">
<h3>Search Engines</h3>
<div className="engine-grid">
{KNOWN_ENGINES.map(name => (
<label key={name} className="engine-row">
<input
type="checkbox"
checked={Array.isArray(engines) ? engines.includes(name) : false}
onChange={() => toggleEngine(name)}
/>
<span>{name}</span>
</label>
))}
</div>
</div>
</div>
);
}