p3: search API, pinned sources, cache, CLI

POST /v1/search and /v2/search fan in SearXNG, Brave LLM Context, and
Tavily from config-fixed endpoints. Public sources refuse private A
records; SearXNG is a loopback-only client, not the fetch guard.

Cache keys include caller class. Restricted callers search like the
fleet; logs omit query, hosts, URLs, and upstream errors. Degraded
results are not stored. Tavily sends search_depth=basic and drops
answer. Missing keys surface in /healthz.

Default-on sources stay off until the bake-off. Query harvest is not
in this commit.
This commit is contained in:
2026-09-23 12:17:51 -07:00
parent 3687636ed7
commit d7873403ff
27 changed files with 2361 additions and 21 deletions
+35
View File
@@ -16,6 +16,7 @@ type File struct {
Dixie Dixie `toml:"dixie"`
Digest Digest `toml:"digest"`
Context Context `toml:"context"`
Search Search `toml:"search"`
}
type Dixie struct {
@@ -39,6 +40,40 @@ type Context struct {
PermitRestricted []string `toml:"permit_restricted"`
}
// Search is the [search] block. Sources default off; bake-off picks defaults.
type Search struct {
K int `toml:"k"`
Timeout string `toml:"timeout"`
Rerank *bool `toml:"rerank"`
Digest bool `toml:"digest"`
CacheTTL string `toml:"cache_ttl"`
SearxNG SearchSource `toml:"searxng"`
BraveLLM SearchSource `toml:"brave_llm"`
Tavily TavilySource `toml:"tavily"`
}
type SearchSource struct {
Enabled bool `toml:"enabled"`
URL string `toml:"url"`
}
type TavilySource struct {
Enabled bool `toml:"enabled"`
URL string `toml:"url"`
DailyCreditCap int `toml:"daily_credit_cap"`
}
func (s Search) RerankOn() bool {
if s.Rerank == nil {
return true
}
return *s.Rerank
}
func (s Search) AnyEnabled() bool {
return s.SearxNG.Enabled || s.BraveLLM.Enabled || s.Tavily.Enabled
}
// SelfIP is the [self_ip] block.
type SelfIP struct {
Sources []string `toml:"sources"`