{"repo": "austin-holdheide/searxng-ai-summary-plugin", "files": {"README.md": {"c7926fe07952eb49ec0a0f84174fc053a7f4bee5": {"t": 1785674377.3232417, "n": 10010, "h": "cffd3e304819ca49", "c": "# SearXNG AI Summary Plugin\n\n![SearXNG AI Summary Plugin](images/Ai%20Summary.png)\n\nAdds a streaming AI summary above search results using any OpenAI-compatible endpoint — just like Google's AI Overview and DuckDuckGo's Search Assist. Built for self-hosted SearXNG with Docker.\n\n---\n\n## Features\n\n- **Instant results** — search results load at full speed, summary streams in after\n- **Typewriter effect** — text appears character by character as the LLM generates it\n- **\"More\" button** — expands into a structured deep-dive powered by a smarter model\n- **Progressive rendering** — sections appear as they complete, not all at once\n- **Code blocks** — commands render with syntax highlighting and a Copy button\n- **Generating indicator** — spinning loader shows while the More panel is still generating\n- **Auto-injected** — no template files need editing, ever\n- **Dark/light theme** — follows SearXNG's theme automatically\n- **Any OpenAI-compatible backend** — LM Studio, Ollama, OpenAI, Groq, and more\n\n---\n\n\n## How It Works\n\n### The Async Flow\n\n```\nUser types query\n │\n ▼\nSearXNG queries engines ───────────────── Results appear instantly (no wait)\n │\n ▼\nBrowser loads ai_summary.js (auto-injected by the plugin)\n │\n ▼\nJS creates summary box with blinking cursor above results\n │\n ▼\nJS reads result snippets from the page DOM\n │\n ▼\nJS opens SSE stream → POST /ai_summary\n │\n ▼\nFlask streams tokens from fast model ──── Characters appear one by one\n │\n ▼\nStream ends → \"More ▾\" button appears\n │\n ▼ (user clicks More)\nJS opens SSE stream → POST /ai_summary_more\n │\n ├── overview arrives → renders paragraph\n ├── section 1 closes → renders heading + bullets/code blocks\n ├── section 2 closes → renders heading + bullets/code blocks\n ├── follow_up closes → renders \"Explore More\" questions\n └── stream ends → generating indicator disappears\n```\n\n### Why Two Settings Blocks\n\nSearXNG's `PluginCfg` dataclass only accepts `active: true/false`. Putting any\nother key under a plugin entry crashes SearXNG on startup:\n\n```\nTypeError: PluginCfg.__init__() got an unexpected keyword argument 'base_url'\n```\n\nThe fix is two separate blocks in `settings.yml`:\n\n```yaml\n# Block 1 — inside plugins: (ONLY active: allowed here)\nplugins:\n searx.plugins.ai_summary.SXNGPlugin:\n active: true\n\n# Block 2 — new top-level key (all LLM config goes here)\nai_summary:\n base_url: \"http://127.0.0.1:1234/v1\"\n model: \"google/gemma-3-1b\"\n model_more: \"openai/gpt-oss-20b\"\n ...\n```\n\nThe plugin reads Block 2 via `get_setting(\"ai_summary.base_url\")`.\n\n### How the Script Is Injected\n\nThe plugin's `init(app)` method runs once at Flask startup and registers:\n\n1. **`POST /ai_summary`** — streaming SSE endpoint for the compact summary\n2. **`POST /ai_summary_more`** — streaming SSE endpoint for the More panel\n3. **`after_request` hook** — appends `