websearch: 默认 auto 付费冻结,SearXNG 优先 + 显式解冻开关

- 默认 auto 只走免费链 searxng -> duckduckgo;即使环境里有
  付费 key 也不调用 Perplexity/Exa/Tavily/Brave,SearXNG
  失败也不回落付费,默认使用零付费花费。
- 付费后端代码/测试/文档全部保留;显式 pin(tavily/exa/
  perplexity/brave)仍照常调用,是有意覆盖不是默认。
- 解冻开关 WEBSEARCH_ENABLE_PAID,仅精确值 "1" 才恢复旧链
  (perplexity/exa/tavily/brave/searxng/duckduckgo),默认关;
  开关经 worker search_env 透传进 MCP config env。
- HttpClient 超时/DNS 失败改报显式错误(timeout after Ns /
  URL error),绝不把超时写成“无结果”。
- SearXNG 默认参数核实:代码无 SEARXNG_URL 硬编码默认值;
  SEARXNG_ENGINES 默认 bing,360search 已在基线;WEBSEARCH_TIMEOUT
  默认 20 秒。主机 env 实测仅 SEARXNG_URL=http://searx.diante.me
  一行,故默认 pin 生效;文档 https 漂移改回 http(主机 nginx
  仅听 80、无 443 vhost,https 在 TLS 层即失败)。
- 旧测试更新原因:test_websearch_mcp 原断言默认 auto 为
  perplexity 优先,与新冻结语义直接冲突,故改为断言冻结后
  的 searxng -> duckduckgo 回退 + 不泄漏 key;旧 perplexity ->
  exa 回退断言移至解冻开关测试(WEBSEARCH_ENABLE_PAID=1 下)。
  未删断言、未加 skip、未放宽门禁。
- 文档另删 WEBSEARCH_PROVIDERS 说法:代码从未实现该变量。
- 未推、未建 PR、未合并、未部署、未改主机 env/nginx/filter/
  证书、未做付费后端 live 验证、未创建生产任务。
This commit is contained in:
host committed 2026-11-01 14:15:54 +00:00
1 parent 0602d06136
commit 3a56f83114
7 files changed
+492 -43

No files matched your search

+15 -1
View File
@@ -124,10 +124,24 @@ class DockerEnvTestCase(unittest.TestCase):
self.assertIsNone(err)
self.assertEqual(env.get("SEARXNG_URL"), "http://searx.diante.me")
def test_paid_unfreeze_switch_passes_into_container_env(self):
# The freeze switch must reach the MCP process (which reads
# only config.toml env, never worker env); without this
# passthrough, WEBSEARCH_ENABLE_PAID=1 on the host would
# silently leave default auto frozen inside containers.
from unittest import mock
with mock.patch.dict(os.environ,
{"WEBSEARCH_ENABLE_PAID": "1"}):
ok, _, _, env, err = self._docker_context()
self.assertTrue(ok)
self.assertIsNone(err)
self.assertEqual(env.get("WEBSEARCH_ENABLE_PAID"), "1")
def test_no_search_env_means_no_extra_env(self):
from unittest import mock
with mock.patch.dict(os.environ, {}, clear=False):
for k in ("SEARXNG_URL", "PERPLEXITY_API_KEY", "EXA_API_KEY",
for k in ("SEARXNG_URL", "WEBSEARCH_ENABLE_PAID",
"PERPLEXITY_API_KEY", "EXA_API_KEY",
"TAVILY_API_KEY", "BRAVE_API_KEY"):
os.environ.pop(k, None)
ok, _, _, env, err = self._docker_context()