Commit graph

7 commits

Author SHA1 Message Date
King Omar
ab6233ddbd Ranking: hybrid semantic search (Workers AI) + optional Claude reranker
- meiliSearch now runs Meili hybrid (semantic+keyword, SEMANTIC_RATIO=0.5) with
  a keyword-only fallback so search never hard-fails if the embedder hiccups
- Workers AI bge-small-en-v1.5 embedder configured on Meili (embeds on ingest)
- optional Claude reranker (?rerank=1) reorders/denoises the top 20 -> 10

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 13:09:39 +10:00
King Omar
877d674ae3 Add bootstrap script for dedicated search box (Node22+Meili+api+crawler)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 12:44:01 +10:00
King Omar
b0496a5ac1 Run crawler as guarded systemd service; fix stall
The crawl stalled when two crawler processes briefly overlapped on the same
WAL SQLite frontier (node:sqlite is synchronous, so a blocked write lock froze
the event loop). Fixes:
- run the crawler as a single-instance systemd service (search-crawler.service)
  with CPUQuota=150% + MemoryMax=1200M so it can't starve a shared VM
- add timeouts to all Meilisearch calls + resilient flush (an untimed hang was
  the amplifier that wedged every worker)
- crawl-diskguard.sh + cron: auto-stop the crawl and ntfy-alert if disk < 800MB

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 02:51:03 +10:00
King Omar
83329d0d58 Add AI answer box: cited Claude RAG over the index
API: /answer retrieves top-6 from Meili and has Claude (haiku-4.5) synthesize
a 2-4 sentence cited answer over ONLY those sources (no hallucinated facts/URLs),
with a 1h in-memory cache. Frontend: async answer card above results with inline
[n] citations linking to sources — loads without blocking the results render.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 02:30:07 +10:00
King Omar
c8cb4cbbe4 Overhaul crawler: depth crawl, link graph, robots, sitemaps, authority
Replace homepage-only crawling (the reason the index had ~9k docs and
useless results) with a real crawler:
- SQLite frontier (node:sqlite) — durable queue, seen-set, per-domain caps
- follows internal links to configurable depth, seeds from sitemap.xml
- robots.txt compliance + per-host politeness delay
- per-URL doc IDs (old id=domain overwrote every page of a site)
- link graph: cross-domain in-degree recorded as an authority signal
- authority score field + 'score:desc' ranking rule (relevance-first, authority tiebreak)
- body trimmed for the disk-bound VM

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 02:26:22 +10:00
King Omar
7e9eca6b0f Expose API via Cloudflare Tunnel over HTTPS/443
A deployed Worker's fetch() cannot reach the API on :3000, so publish it at
https://search-api.theradicalparty.com through a Cloudflare Tunnel. Point the
frontend API_URL at HTTPS/443, add cloudflared install to install-vm.sh
(driven by CLOUDFLARED_TOKEN), thread the token through deploy.sh, and add
docs/DEPLOY.md with the full tunnel + DNS setup.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 01:56:38 +10:00
King Omar
b3aea18d9c Initial commit: RADICAL_SEARCH self-hosted web search engine
Crawler (Majestic Million → undici → cheerio → Meilisearch), Hono search
API with P2P peer federation, Cloudflare Worker frontend, VM provisioning
scripts. Adds README, .gitignore, and moves VM credentials out of deploy.sh
into a git-ignored deploy.env.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 01:52:31 +10:00