Search providers: SearXNG and Brave with ranking #67

2 Commits
Author SHA1 Message Date
dev_agentandClaude Opus 5.5 01523f634b Reject malformed search bodies and report unranked candidates
CI / ci (push) Successful in 1m35s
CI / ci (pull_request) Successful in 1m35s
SearXNG now requires a results array and Brave requires "type": "search"
with a results array in any web object, so `{}` is ErrSearchResponse
instead of an empty search. Rank no longer drops failed candidates: it
returns the ranked ones with ErrCandidatesUnranked joined with each
unranked candidate's URL and reason, or ErrNoUsableRecipe when none rank.
Adds an HTTPS ranking test through the SSRF-safe Fetcher.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 13:27:07 -04:00
dev_agentandClaude Opus 5.5 26928b538b Add SearXNG and Brave recipe search providers with ranking
CI / ci (push) Successful in 1m35s
CI / ci (pull_request) Successful in 1m36s
recipes.SearchProvider.Search(ctx, query, n) returns []Candidate{URL,
Title, Snippet}, appending " recipe" when the query lacks the word.
SearXNG calls {MEALQUEST_SEARXNG_URL}/search?q=…&format=json&categories=general
directly (the configured endpoint may be internal); Brave calls the Web
Search API with the key decrypted from recipe_search_settings. Redirects
are not followed; 401/403, 429, other non-2xx and malformed bodies map to
distinct errors.

recipes.Rank fetches and extracts the top 5 candidates, rejects those
without ingredients or an image, and scores the rest by
harness.Similarity of the recipe title to the dish name plus
completeness (ingredients, image, steps, minutes). harness.Similarity
exposes the existing Jaccard score used by Similar.

Maestro task 10c25cb5-3774-419c-87e1-3f87a3d1391d.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 13:17:27 -04:00