Merge pull request #114 from openqj/feat-websearch-docker-env
fix: pass search env into Docker task containers (SEARXNG_URL was lost)
This commit is contained in:
3 files changed
+66
No files matched your search
@@ -3,6 +3,22 @@
|
||||
语义化版本见 `VERSION`(当前 0.1.0)。以下按日期倒序,只列已交付
|
||||
的大项,每项附实测证据;未建成的东西在“诚实边界”里明说,不夸大。
|
||||
|
||||
## 2026-10-28:网页搜索 Docker env 透传(e2e 失败后的修复)
|
||||
|
||||
- 根因:Docker 任务容器不继承 worker 进程环境,只拿
|
||||
extra_env(-e);`SEARXNG_URL` 只写进 worker unit 的
|
||||
EnvironmentFile 时,容器内 codex -> MCP 根本看不到它,
|
||||
auto 链跳过 SearXNG、只剩 DuckDuckGo,实弹 e2e 报错
|
||||
“all search providers failed: duckduckgo (DNS)”。
|
||||
- 修复:`cloud/worker.py _docker_task_context` 把 worker 环境
|
||||
里已设置的 `SEARXNG_URL` / `PERPLEXITY_API_KEY` /
|
||||
`EXA_API_KEY` / `TAVILY_API_KEY` / `BRAVE_API_KEY` 合并进
|
||||
extra_env(值不进日志;付费 key 与网关 key 同款走法)。
|
||||
- 单测:新增 2 个(有/无搜索 env 时的容器 env),连同
|
||||
websearch 旧测、租户隔离旧测共 25 个通过;cloud 全量
|
||||
1038 个通过(skip 4)。只本地提交,未推、未建 PR、
|
||||
未合并、未部署;重跑 e2e 须等本修复部署后。
|
||||
|
||||
## 2026-10-28:网页搜索接 worker + egress(公开 SearXNG 路)
|
||||
|
||||
- `cloud/worker.py --websearch-mcp`(默认关):开启后
|
||||
|
||||
@@ -99,6 +99,42 @@ class WorkerWebsearchTestCase(unittest.TestCase):
|
||||
self.assertEqual(config.count("[mcp_servers.websearch]"), 1)
|
||||
|
||||
|
||||
class DockerEnvTestCase(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.tmp = tempfile.TemporaryDirectory()
|
||||
self.db_path = os.path.join(self.tmp.name, "control.db")
|
||||
init_db(self.db_path)
|
||||
|
||||
def tearDown(self):
|
||||
self.tmp.cleanup()
|
||||
|
||||
def _docker_context(self):
|
||||
worker = Worker(self.db_path, "/fake/host.py",
|
||||
env={"XCM_API_KEY": "test-placeholder"},
|
||||
tenant_isolation=False, egress_proxy_port=None)
|
||||
return worker._docker_task_context({"project_id": "projA"})
|
||||
|
||||
def test_searxng_url_passes_into_container_env(self):
|
||||
from unittest import mock
|
||||
with mock.patch.dict(os.environ,
|
||||
{"SEARXNG_URL": "http://searx.diante.me"}):
|
||||
ok, _, _, env, err = self._docker_context()
|
||||
self.assertTrue(ok)
|
||||
self.assertIsNone(err)
|
||||
self.assertEqual(env.get("SEARXNG_URL"), "http://searx.diante.me")
|
||||
|
||||
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",
|
||||
"TAVILY_API_KEY", "BRAVE_API_KEY"):
|
||||
os.environ.pop(k, None)
|
||||
ok, _, _, env, err = self._docker_context()
|
||||
self.assertTrue(ok)
|
||||
self.assertIsNone(err)
|
||||
self.assertIsNone(env)
|
||||
|
||||
|
||||
class EgressFilterTestCase(unittest.TestCase):
|
||||
def test_search_domains_present_in_basic_form(self):
|
||||
lines = open(REPO_ROOT / "deploy" / "egress" /
|
||||
|
||||
@@ -2200,6 +2200,20 @@ class Worker:
|
||||
"NO_PROXY": "localhost,127.0.0.1",
|
||||
"no_proxy": "localhost,127.0.0.1",
|
||||
}
|
||||
# 搜索 env 透传:Docker 容器不继承 worker 进程环境,只拿
|
||||
# extra_env(-e),所以 worker 环境里的搜索配置若不显式
|
||||
# 放进这里,容器内 codex -> MCP 永远看不到 SEARXNG_URL,
|
||||
# auto 链会跳过 SearXNG、只剩 DuckDuckGo(实弹 e2e 已证实)。
|
||||
# 只透传已设置的项,值绝不进日志;付费 key 与网关 key 一样
|
||||
# 走 extra_env(容器内进程本就需要它调 API)。
|
||||
search_env = {
|
||||
k: os.environ[k]
|
||||
for k in ("SEARXNG_URL", "PERPLEXITY_API_KEY", "EXA_API_KEY",
|
||||
"TAVILY_API_KEY", "BRAVE_API_KEY")
|
||||
if os.environ.get(k)
|
||||
}
|
||||
if search_env:
|
||||
proxy_env = _merge_env(proxy_env, search_env)
|
||||
return (True, tenant_mounts, tenant_network, proxy_env, None)
|
||||
|
||||
def _run_fork(self, task, quota_check=None):
|
||||
|
||||
Reference in new issue
Block a user