🎯 OmniRoute 搜索与图片能力最终审计(2026-09-24)
历史值说明: 本文中的
207.174.28.120只记录审计当时事实,不得作为当前端点或恢复值。当前边缘逻辑身份以edge.yohan.fun和 P10 权威计划为准。2026-09-27 当前边界: 本文记录过的
gemini-web-session.service、gemini-egress-mm/dd.service、edge-ssh-socks.sh、独立 Chrome profile、9333CDP 和 Privoxy/VNC 固定出口均为已退役历史实验,不得恢复。Gemini Web 现在只允许使用 OmniRoute 官方 Provider、官方管理 API 和官方 VNC 登录/harvest;RR 当前无上述自建服务或进程。
📌 结论摘要
本轮只读审计的结论是:搜索路径应显式治理。 统一方向是本地 local_search_registry 主路径加 OmniRoute 显式 Search Provider 辅助,不能依赖 OmniRoute 自动模式作为稳定默认。原因是 /v1/search 不与 21 个聊天模型共用路由,当前自动结果实际命中 ollama-search,返回体大、相关性和结果形态不稳定;通用搜索实测最佳为 serper-search,深度检索再按任务选择 tavily-search、perplexity-search、exa-search 或 firecrawl。
图片侧结论同样需要分开:图片生成已证实,Codex 端取回仍未闭环。 官方 3.8.50 的 gemini-web/nano-banana-web 只走模型/API 方式,不需要再包一层专用 MCP。2026-09-25 用户完成官方 VNC 登录后,官方 harvest 成功了,但 headless 生图仍使用旧会话;根因是官方执行器优先读取 api_key,而 harvest 只更新 provider_specific_data.cookie。通过官方 PATCH /api/providers/{id} 把首选 api_key 同步为新 Cookie 后,response_format=url 真实生成成功,且在同一 Cookie 会话内可下载为 50501 字节 JPEG。无登录态直取同一 URL 仍是 HTTP 403 HTML;b64_json 因官方 3.8.50 在授权 Playwright 上下文之外下载源图,仍返回 HTTP 502。官方 /v1/images/edits 对 gemini-web 返回 HTTP 400,因此当前只能确认“生成成功且可在授权会话取回”,不能声明 101 Codex 图片闭环已经可用。
版本与规则方面,RR 当前是官方 omniroute@3.8.50,与 npm latest、GitHub Release v3.8.50 一致。官方 issue #14760 已精确记录 b64_json 403,并且 PR #14787 给出的修复方向正是“在同一个授权 Playwright 上下文内下载图片”;该 PR 当前仍未合入正式发布。全局和项目规则已固定为只允许官方资源。 源码修改、补丁、私有 Fork、重新编译或改写安装包均被禁止。
🗂️ 目录
🧩 背景与目标
101 Codex 使用第三方通道模型资源,原生 Web Search、MCP/连接器、桌面控制和浏览器控制能力不能按官方 Codex 的完整形态使用。桌面和浏览器链路已由 Cua、Webbridge 与 Playwright 等多层方案补足;本轮只收口剩余两个问题:
- Web 搜索与发现应如何在 101 本地和 OmniRoute 之间选择、测试和治理。
- OmniRoute 的 Gemini Web 能否承担图片生成和图片编辑,以及应采用模型方式还是 MCP 方式。
这里必须区分“网页产品能力”和“OmniRoute 官方接口能力”。用户可以在 gemini.google.com 页面中上传参考图并编辑,但 OmniRoute 是否暴露对应 HTTP/MCP 入口,只能以已部署官方版本和官方包实现为准。
📊 官方版本与资源边界
RR 只读复核显示服务状态正常,未发现本轮代码改动或服务漂移。当前生产版本、发布来源与包指纹如下:
| 项目 | 当前结果 | 依据 |
|---|---|---|
| RR 服务 | agentmeshos-omniroute.service active/running,PID 467763,NRestarts=0,ActiveEnterTimestamp=2026-09-25 03:41:23 CST |
systemctl show 与 /proc/<pid>/environ 回读 |
| 健康 | /healthz=ok |
curl http://127.0.0.1:39180/healthz |
| 生产版本 | 3.8.50 |
RR 全局 npm 包版本 |
| 官方 npm | 3.8.50 |
npm view omniroute version engines --json |
| 官方 Release | v3.8.50,发布于 2026-08-26T19:30:30Z |
GitHub Releases API |
| 官方包 SHA-256 | 738c58af1faae8c57eb643a939d1191f8d7e083d9295ef61687d2bff04878c29 |
temp/omniroute-audit/omniroute-3.8.50.tgz |
| Node 要求 | >=22.22.2 <23 || >=24.0.0 <27 |
官方 package.json 与 npm 元数据 |
四个核心实现与官方 tarball 的 SHA-256 一致,RR 生产包没有落入私有补丁:
| 文件 | SHA-256 |
|---|---|
package.json |
46394660a338155902350761999849bfa539e6fdc5aef74d7b69765a6ba788a2 |
open-sse/executors/gemini-web.ts |
c76289416ea121a4a3e58c473c695535d6807a8cccaadcbf7399abe41bb468aa |
open-sse/handlers/imageGeneration/providers/geminiWeb.ts |
af59e51a12eb60c0ed3cad1a040fd65e6a338579a5865e866b9116a910827985 |
open-sse/config/searchRegistry.ts |
ad028f4179722234710db472eb7f2fda69c6142de5619401ad6bc3541063899e |
因此本轮结论可作为官方 3.8.50 行为基线;一旦官方升级或此包指纹变化,搜索、图片和权限验收必须重新执行。
🔎 搜索与发现
结论
Search Provider 不是聊天模型。 OmniRoute 官方注册表注释写明:搜索提供者没有 “models”,Provider 本身就是搜索执行器。101 Codex 可以同时看到本地 local_search_registry 和远程 omniroute MCP,但 Codex 当前没有本地强制优先级;若不增加提示规则或客户端策略,模型仍可能自行选择。稳产建议是把本地 SearXNG 当作通用搜索主路径,把 OmniRoute 当作显式补充通道,而不是依赖 Omni 自动模式。
自动路由真实行为
官方 searchRegistry.ts 的自动选择逻辑是筛选已配置、非 fallbackOnly 且支持目标类型的 Provider,然后选择最低 costPerQuery。官方 executeWebSearch.ts 会优先寻找有凭据的常规 Provider,再选择 fallback-only Provider,并只预选一个备用 Provider。它不是按剩余额度、健康状态、错误分类、冷却窗口和结果质量做完整动态路由。
101 自动查询 OpenAI Codex official documentation 实际命中 ollama-search。该结果虽然返回 3 条,但单个正文可达到约 49 万字符,自动结果文件超过 1 MB,相关性和可消费性不稳定,因此不能作为日常默认。
文档查询实测
下表中的输出是同一文档类查询 OpenAI Codex official documentation 的只读对照;“结果数”来自官方 /v1/search 响应,“成本”来自官方响应用量字段。
| Provider | 结果数 | 耗时 ms | 成本 USD | 判定 |
|---|---|---|---|---|
auto / ollama-search |
3 | 1353 | 0 | 可用但不稳定,不作为默认 |
context7 |
3 | 647 | 0 | 仅文档语料,自动模式排除 |
duckduckgo-free |
0 | 183 | 0 | 免费兜底,本次无结果 |
exa-search |
3 | 977 | 0.007 | 适合语义检索 |
firecrawl |
3 | 888 | 0.002 | 适合搜索后抓取 |
google-pse-search |
0 | 0 | 0 | 未配置有效凭据 |
jina-search |
0 | 0 | 0 | 上游 HTTP 402 |
linkup-search |
0 | 0 | 0 | 未配置有效凭据 |
perplexity-search |
3 | 783 | 0.005 | 适合带综合答案的深度检索 |
searchapi-search |
3 | 3342 | 0.004 | 可用但延迟明显更高 |
searxng-search |
0 | 0 | 0 | 仍指向官方默认 localhost:8888,未指向 101 的 8090 |
serper-search |
3 | 668 | 0.001 | 当前通用 Web 搜索最优选择 |
tavily-search |
3 | 1151 | 0.008 | 适合深度检索 |
youcom-search |
3 | 702 | 0.005 | 可用,作为补充 |
上述结果保存在 temp/omniroute-e2e-20260924/search/。失败文件也保留 HTTP 错误原文,例如 Google PSE 和 Linkup 的“未配置凭据”、Jina 的 HTTP 402、SearXNG 的错误本地地址。
最终搜索策略
| 场景 | 推荐通道 | 原因 |
|---|---|---|
| 101 日常 Web 搜索 | local_search_registry / 101 SearXNG 127.0.0.1:8090 |
自有链路、结果结构稳定、无外部 Provider 波动 |
| OmniRoute 通用搜索 | 显式 serper-search |
本次延迟约 668 ms、成本 0.001 USD、相关性最好 |
| OmniRoute 深度检索 | tavily-search 或 perplexity-search |
覆盖内容更完整,但成本更高 |
| 文档/库检索 | context7 |
官方定位为文档语料,明确排除自动通用搜索 |
| 语义检索 | exa-search |
适合按语义召回,不替代普通 SERP |
| 抓取/内容抽取 | firecrawl |
官方把搜索与抓取能力放在同一 Provider 链路上 |
101 当前“让模型自行选择本地和 Omni”可以保留,但必须在规则或提示中明确:泛化查询优先本地;使用 Omni 时必须显式指定 Provider;不要依赖自动模式。OmniRoute 自身无法控制 Codex 选择哪一个 MCP,因此如果后续要求确定性优先级,落点应在 Codex 客户端策略,而不是再套一层网关或修改 Omni 源码。
🖼️ 图片生成与编辑
结论
官方 headless 生图已打通,Codex 端消费仍未闭环。 2026-09-25 用户完成官方 VNC 登录后,官方 harvest 返回 harvested: true 且连接验证通过。随后发现的真实根因是凭据优先级:官方执行器先读 api_key,harvest 却只更新 provider_specific_data.cookie,因此生图仍在使用旧会话。通过官方 PATCH /api/providers/{id} 同步首选 api_key 后,官方连接测试返回 valid: true,response_format=url 生图返回 HTTP 200。该图片在同一 Cookie 会话内可下载为 50501 字节 JPEG,但无登录态直取仍是 403 HTML;b64_json 因官方 3.8.50 在授权上下文之外下载源图而继续返回 502。图片编辑在官方 /v1/images/edits 上仍不支持 gemini-web。不需要再做一个专用 MCP 包装层:MCP 若只是包装同一个 HTTP 端点,不会解决 Cookie、下载 403 或编辑能力缺失。
url 与 b64_json
| 返回格式 | 通俗解释 | 当前结论 |
|---|---|---|
url |
网关返回一个图片链接,Codex 或浏览器再访问链接显示图片 | Gemini Web 生成本身 HTTP 200;无登录态直取 HTTP 403 HTML,但同一 Gemini Cookie 会话内可取得 200 image/jpeg,共 50501 字节 |
b64_json |
图片内容直接编码在 JSON 响应里,调用方不用再下载链接 | 对普通 API Provider 有价值;Gemini Web 当前仍由 OmniRoute 在授权上下文之外抓取源图,返回 HTTP 502,错误为远程图片下载 403 |
因此用户即使看到“生成成功”或拿到链接,也不能直接等同于 Codex 可以在对话中显示或保存图片。当前判断标准是生成与取回两段都通过;只通过生成只说明上游产出了文件引用。
图片能力矩阵
| 能力 | 官方 3.8.50 结果 | 依据 |
|---|---|---|
| Gemini Web Cookie 恢复 | 官方 VNC harvest 返回 harvested: true,validation.valid: true;写入 providerSpecificData.cookie |
2026-09-25 官方 /api/vnc-session/{connectionId}/{sessionId}/harvest 返回 |
| 凭据优先级根因 | 旧 api_key 为 1746 字符、15 个 Cookie;新 harvest Cookie 为 2397 字符、23 个 Cookie,两者 SHA-256 不同;执行器优先使用旧 api_key |
RR provider_connections 解密后的无泄漏摘要;旧 SHA-256 3cb66e...,新 SHA-256 bd6427... |
| 官方配置同步 | 官方 PATCH /api/providers/{id} 返回 HTTP 200,api_key 与最新 provider_specific_data.cookie 一致;连接测试 HTTP 200、valid: true |
RR /root/.omniroute/backups/gemini-web-connection-before-api-key-sync-2026-09-24T20-22-00-033Z.json |
| Gemini Web 生图 | 官方入口返回 HTTP 200、1 个 lh3.googleusercontent.com URL;实测生成耗时约 36.8 秒 |
RR /tmp/omniroute-gemini-image-e2e-20260925.mjs 与本轮 OpenAI 兼容入口响应 |
| Gemini Web 图片消费 | 无登录态 URL 直取 HTTP 403 HTML;同一 Cookie Playwright 上下文请求返回 HTTP 200、image/jpeg、50501 字节,并保存为有效 JPEG |
RR /root/.omniroute/image-tests/gemini-web-e2e-1790281427880.jpeg |
Gemini Web 生图 + b64_json |
HTTP 502,官方错误为 Remote image fetch error 403;图片已经生成,但官方下载阶段没有携带会话 Cookie |
2026-09-25 官方入口复测结果 |
Gemini Web /v1/images/edits |
HTTP 400:Image edit is not supported for built-in provider "gemini-web" |
官方 3.8.50 构建产物 |
| Gemini Web 聊天传图编辑 | 不成立;执行器只过滤并输入字符串消息,图片 part 不会可靠传入网页 | open-sse/executors/gemini-web.ts 的 buildGeminiPrompt |
| Gemini Web 聊天路径 | 文本和带图编辑均曾返回 HTTP 504,原因是本机 request queue 15 秒执行上限 | RR /root/.omniroute/image-tests/e2e-gemini-web-chat-text-after-cleanup-20260924.json |
官方编辑错误还明确给出可替代方向:adobe-firefly、chatgpt-web、codex 或自定义 OpenAI-compatible 图片 Provider。若这些官方 Provider 未配置或稳定性不足,方案只能是等待上游支持、恢复 Gemini Web 会话后仅做生成,或选择其他官方支持的编辑 Provider;禁止通过补丁给 3.8.50 添加私有 /v1/images/edits 分支。
凭据优先级根因与官方配置修复(2026-09-25)
harvest 成功不等于执行器使用了新会话。 官方 resolveGeminiWebCookie() 的读取顺序是 api_key、credentials.cookie、providerSpecificData.cookie、最后才拼 __Secure-1PSID 与 __Secure-1PSIDTS。官方 VNC harvest 只更新 providerSpecificData.cookie 和两个 __Secure-1PSID* 字段,不更新已有 api_key;现有连接又保留着 2026-09-24 的旧 Cookie,因此 headless 请求继续读取旧会话。
这个问题没有通过改代码解决。验证和修复顺序如下:
- 先对数据库中旧
api_key与 harvest 新 Cookie 做解密后的长度、字段名和 SHA-256 比对,确认两者确实不同,且旧api_key是执行器首选来源。 - 用官方管理 API
PATCH /api/providers/fefdf6be-2231-403f-a51e-08ba519d8c5a只提交新的apiKey,不改 Omni 包、不重启服务。 - 回读数据库确认
api_key == providerSpecificData.cookie,再执行官方连接测试。 - 重新调用官方
/v1/images/generations,确认response_format=url已从旧会话的“Are you signed in”错误转为 HTTP 200 并生成图片。
修复前整行连接已保存到 RR /root/.omniroute/backups/gemini-web-connection-before-api-key-sync-2026-09-24T20-22-00-033Z.json,权限 0600。回滚时可在 Omni 停写窗口内从该文件恢复并重新执行官方连接测试;不得直接覆盖整个数据库。
官方 VNC 浏览器登录路径(2026-09-25)
根因是 headless 不复用常驻 Chrome profile。 官方 3.8.50 的 gemini-web 执行器不连接 RR 常驻 Chrome 的 127.0.0.1:9333 CDP,也不复用 /root/.gemini-login-profile。官方 VNC 提供了合规的登录与 harvest 路径;本次登录成功后,用新 Cookie 的新 headless 上下文已能在 Gemini 页面看到账号和历史会话,不再显示登录或地区错误。
官方包同时提供了 /api/vnc-session 浏览器登录流程:Omni 启动隔离 Chromium 容器,操作者在 VNC 页面完成 Google 登录,再由官方 CDP harvest 只回收该 Provider 声明的 Cookie 和存储字段,写回指定 provider_connections 行。gemini-web 在官方 provider 清单中标记为支持该流程;这不是新增 MCP,也不是修改 Omni 源码。
| 实施项 | 当前结果 | 证据或路径 |
|---|---|---|
| 官方 VNC 镜像 | 已按官方 v3.8.50 包内 README 从官方 Dockerfile 构建 omniroute-vnc-chromium:local,镜像 ID sha256:01de7051ebb2b86667584e4726303f6eaab0665b97706c10075ef09ea5b10b0a,大小约 1.18 GB |
RR /root/omniroute-vnc-build/chromium/;Dockerfile SHA-256 c80d744776d7dee1215a5249e37be16c471263165144842351e3212fdccf01e1 |
| 容器自检 | VNC 与 CDP 端口均可用,容器内浏览器为 Chrome/153.0.8010.52 |
RR 临时容器探针,完成后已删除 |
| 宿主集成 | 新增 systemd drop-in,只恢复 Docker socket 可见性,继续隔离 /etc/agentmeshos、/etc/nomad.d、/etc/ssh 和 Runtime 目录 |
RR /etc/systemd/system/agentmeshos-omniroute.service.d/vnc-browser-login.conf;SHA-256 cff905d85819cf5b7043a56c93cb2ede08477473f0e6b4443c54a0d24b7dfa79 |
| 服务验证 | Omni 重启后 active、NRestarts=0、/healthz=ok,/api/vnc-session 返回 HTTP 200,且 gemini-web 出现在 VNC Provider 清单中 |
2026-09-25 RR 只读回读 |
| VNC 地区限制根因 | 旧 VNC 容器的 CHROME_CLI 没有 --proxy-server,浏览器直接使用 RR 公网 96.44.133.235;宿主 OmniRoute 的 HTTP(S)_PROXY 只覆盖 headless 执行器,容器不继承 |
docker inspect 旧容器环境与 systemctl show 宿主环境对照 |
| MM 出口固定 | 新增包外 systemd drop-in,使用官方变量把 VNC Chromium 固定到宿主 Privoxy;Privoxy 原有 .google.com、.googleusercontent.com、.gstatic.com 规则继续经 gemini-egress-mm.service 的 127.0.0.1:11080 SOCKS5 转发到 MM 207.174.28.120 |
RR /etc/systemd/system/agentmeshos-omniroute.service.d/vnc-gemini-egress.conf;SHA-256 ab1996c94d81d699e07d737cb3d414a985e6310320bfc7974b14198206e523c5 |
| Docker 访问边界 | Privoxy 监听 172.17.0.1:8118,UFW 仅允许 Docker 默认网桥 172.17.0.0/16 访问该目标端口;其他公网入口未放行 |
RR /etc/privoxy/config 与 ufw status;配置 SHA-256 e224107b5f91b348ba5b6a9072079d0b8b493a9c0f7e11f64f385c8128c19d3d |
| 新容器实参 | 新会话容器 CHROME_CLI 和 Chromium 进程均包含 --proxy-server=http://172.17.0.1:8118;容器经该代理访问 Google 与 Gemini 均 HTTP 200 |
RR docker inspect efad7b456242、docker exec ps、容器内 curl 探针 |
| VNC 地区检查 | 会话 f783cf81-3a95-4e0d-bab8-0adcad1e17dc 打开 https://gemini.google.com/app;CDP 页面文本 HAS_REGION_UNAVAILABLE=false,页面仍显示 Sign in |
RR CDP 127.0.0.1:32779/json 与 Runtime.evaluate |
| 第二次 502 根因 | 首个 VNC 容器从 1790276943 启动,到 1790278760 被 Docker 以 exit 137 销毁,存活 1817 秒;官方默认 OMNIROUTE_VNC_MAX_MS=1800000,因此 /touch 只能保 idle,不能延长 max |
RR docker events 与官方 manifest.ts 默认值 |
| 会话时长修复 | 官方 env 固定为 OMNIROUTE_VNC_IDLE_MS=86400000、OMNIROUTE_VNC_MAX_MS=86400000;新会话不再在 30 分钟被官方计时器销毁 |
RR /etc/systemd/system/agentmeshos-omniroute.service.d/vnc-gemini-egress.conf;SHA-256 ecfeaffb554d480dc95c7531f3715e164ce60353458efecc25bf11958446d43f |
| 当前新会话 | c6182281-a0b5-4640-b13f-65bb6417c28d,VNC 127.0.0.1:32780,CDP 127.0.0.1:32781;容器仍带 MM 代理参数 |
RR 官方 API、docker inspect 与 docker port |
| Home 可访问入口 | https://omni.yohan.fun:8443/ 经 MM Nginx 回源到 100.64.0.1:39275,再转发到当前 VNC 127.0.0.1:32780;socat 使用 Restart=always 并在反向验证中自动换 PID 后恢复 HTTP 200 |
101 curl -I、RR socat 监听与主动终止回归 |
| VNC 登录与 harvest | 用户完成登录后,CDP 页面 HAS_SIGN_IN=false、HAS_REGION_UNAVAILABLE=false;官方 harvest 返回 harvested: true、3 个更新字段、validation.valid: true |
2026-09-25 官方 VNC/CDP 与 harvest 响应 |
| 新 Cookie 的 headless 会话 | 注入 provider_specific_data.cookie 后,Gemini 页面显示账号名和最近会话,不再显示 Sign in;该会话能生成图片并在同一上下文取回 JPEG |
RR /tmp/gemini-web-fresh-cookie-probe-20260925.mjs 与官方图片入口复测 |
登录动作必须由用户在官方 VNC 页面完成,不能把账号密码或 2FA 交给 Agent 保存。当前可以确认“登录成功、harvest 成功、官方生图成功、授权会话内可取回 JPEG”;不能确认“Codex 可直接显示或保存图片”以及“官方 API 图片编辑可用”。只有官方修复进入正式版本并通过 b64_json 与编辑 E2E 后,才能把 101 Codex 图片闭环声明为完成。
当前未决项
VNC 登录和官方 headless 生图已经完成,剩余阻塞已经从“会话问题”收敛为“官方取回实现问题”。官方 issue #14760 与当前 3.8.50 实验完全一致,官方 PR #14787 的修复是在同一个授权 Playwright 上下文内下载图片,但尚未进入正式发布。要按“Codex 图片可用”声明,必须继续满足两个真实验收:b64_json 或等价可消费响应能在 101 Codex 中直接使用;带图编辑能从官方入口提交并取回结果。当前不采用源码补丁、私有 MCP 或第二层网关;等待官方发布期间,最多只能采用“先生成 URL,再由持有官方 Cookie 的会话取回”的两步临时操作。
🧩 规则与治理
规则已经落到全局和项目边界,目的是防止升级后被本地补丁覆盖,也防止后续为了短期功能继续走私有构建。
| 边界 | 当前规则 | 文件 |
|---|---|---|
| 全局 | 搜索场景和图片验收门槛已经固定;只允许官方 npm/Release、官方镜像、官方 CLI/API 和控制台配置 | /root/.codex/AGENTS.md |
| 全局细则 | 搜索按本地主路径和显式 Provider 回退;禁止把“生成成功”写成“端到端可用”;禁止源码修改、补丁、私有 Fork/分支/镜像、重新编译、替换包文件、改写构建产物 | /root/.codex/docs/core-operating-rules.md |
| 项目架构 | 官方 OmniRoute 是唯一模型/Provider/路由权威 | docs/architecture/03_总体架构设计.md |
| 项目规范 | 宿主层 systemd/代理可保留,但不得改包内容 | docs/architecture/05_技术选型说明.md、docs/architecture/06_工程规范.md |
| 部署 | 外部适配要有用途、路径、回滚点和升级后 Smoke | docs/architecture/07_部署规范.md |
| 协作 | 故障只能通过官方控制台、API、升级、包外配置或数据恢复处理 | docs/architecture/08_AI协作规范.md |
Codex 规则落点
搜索与图片路由已于 2026-09-24 写入 Codex 常驻规则和核心细则。修改前先备份,再按原文件权限写回;回滚时可直接比对以下指纹恢复,不得改装为项目内脚本或第二层网关。
| 文件 | 修改前 SHA-256 | 修改后 SHA-256 | 备份 |
|---|---|---|---|
/root/.codex/AGENTS.md |
38fc749c32240979c93680be00e264b0e3e83b9e2510be598222cbc0fb5bbeb1 |
f912545eb80933834f731f28165a9370e632c0700ae6b8fcb1d183e184084e71 |
/root/.codex/backups/omniroute-search-image-rules-20260924T2025/AGENTS.md |
/root/.codex/docs/core-operating-rules.md |
cacdbe7907703b1edf31971dc2eaf21118206b388d548690207b9ef42a2a761d |
52564db3caa9ec0a68161ee62452073dc216ce9fbefc20f3c2fd9c72047f0501 |
/root/.codex/backups/omniroute-search-image-rules-20260924T2025/core-operating-rules.md |
2026-09-24 的初始审计没有修改 OmniRoute 源码、没有重新编译、没有替换已安装包、没有重启服务。2026-09-25 为启用官方 VNC 流程,新增了包外 systemd drop-in 并重启 Omni;随后又新增 VNC 出口代理配置并再次重启 Omni。官方 npm 包、源码和构建产物均未修改。temp/ 下历史补丁脚本只作为审计材料,不得在后续生产流程中执行。
🧪 验证与复核
本轮使用的只读验证命令与结果如下:
| 验证项 | 结果 |
|---|---|
| 101 MCP 可见性 | local_search_registry、omniroute 均 enabled;Omni MCP 当前只暴露 Web Search 与 Web Fetch,没有图片生成或编辑工具,因此图片仍应走模型/API |
| RR 版本 | 官方 3.8.50 |
| RR 健康 | ok |
| RR 重启次数 | NRestarts=0 |
| 官方 VNC 服务能力 | /api/vnc-session 返回 HTTP 200;33 个 VNC Provider 中包含 gemini-web |
| 官方 VNC 浏览器 | VNC/CDP 正常,浏览器为 Chrome/153.0.8010.52;当前 Gemini 页面无登录提示和地区限制,账号历史可见 |
| VNC 出口代理 | 容器实际使用 http://172.17.0.1:8118,Privoxy 上游为 MM SOCKS5 127.0.0.1:11080,MM 出口 207.174.28.120 |
| VNC 页面状态 | CDP 文本匹配 HAS_SIGN_IN=false、HAS_REGION_UNAVAILABLE=false;不是地区提示伪装 |
| VNC 会话寿命 | 新会话使用官方 OMNIROUTE_VNC_IDLE_MS=86400000、OMNIROUTE_VNC_MAX_MS=86400000;03:42 至 04:05 连续探测约 23 分 55 秒,容器、端口和公网 HTTP 200 均无变化 |
| 访问桥故障恢复 | 主动终止 socat 旧 PID 471298 后,systemd 自动拉起新 PID 471442,公网入口仍为 HTTP 200 |
| OmniRoute 重启后 | active/running、NRestarts=0、/healthz=ok;新进程环境包含官方 OMNIROUTE_VNC_CHROMIUM_ARGS 和会话时长参数 |
| 官方 tarball 指纹 | 与审计目录中的 3.8.50 包一致 |
| Gemini Web 会话 | 官方 VNC 登录和 harvest 已完成;旧 api_key 与新 Cookie 不一致的问题已由官方管理 API 修正,连接测试 valid: true |
| Gemini Web 生成 | HTTP 200,返回 1 个 Google 图片 URL,耗时约 36.8 秒 |
| Gemini Web 图片取回 | 无 Cookie 请求 HTTP 403 HTML;同 Cookie Playwright 上下文 HTTP 200、JPEG、50501 字节,可解码 |
Gemini Web b64_json 消费 |
HTTP 502,官方下载器仍返回远程图片 403;对应官方 issue #14760,修复 PR #14787 尚未发布 |
| Gemini Web 编辑 | 官方 /v1/images/edits 返回 HTTP 400,当前版本不支持 |
| 搜索结果证据 | temp/omniroute-e2e-20260924/search/ |
| 图片结果证据 | RR /root/.omniroute/image-tests/gemini-web-e2e-1790281427880.jpeg;本轮无泄漏摘要与官方接口复测脚本位于项目 temp/gemini-web-*20260925.mjs、temp/omniroute-gemini-*20260925.mjs |
101 上手工验证搜索时,应优先让 Codex 调用 local_search_registry;需要验证 Omni 时,测试请求必须显式带 provider,例如选择 serper-search。不要用自动模式的一次成功作为长期稳定性证明。
🔁 回滚方案
2026-09-24 的初始审计没有生产服务、包内容、配置或数据库变更,因此当时不需要服务回滚。2026-09-25 的 VNC 集成新增了包外 systemd drop-in;回滚时删除 /etc/systemd/system/agentmeshos-omniroute.service.d/vnc-browser-login.conf,执行 systemctl daemon-reload 并重启 Omni,或在需要完整恢复时使用备份目录 /root/omniroute-systemd-backup-20260925T014634+0800/。项目文档可通过对应 Git 提交反向回滚;全局 /root/.codex 规则不属于项目仓库,修改时应保留变更前后副本,回滚时逐条恢复,不得用未经验证的历史配置覆盖。
VNC 出口代理的独立回滚点如下。该修复只改宿主层,回滚不涉及 OmniRoute 包或数据库:
| 对象 | 修复前 | 修复后 / 当前 | 回滚动作 |
|---|---|---|---|
| Privoxy 主配置 | SHA-256 845df06d418ce746fb9351ecc66012828ef3a420136847d2cc896c6b6827d1e8 |
SHA-256 e224107b5f91b348ba5b6a9072079d0b8b493a9c0f7e11f64f385c8128c19d3d |
从 /root/omniroute-vnc-egress-backup-20260925T030255+0800/privoxy.config.before 恢复,重启 privoxy.service |
| VNC Chromium 参数 | 无 OMNIROUTE_VNC_CHROMIUM_ARGS,容器直连 RR |
RR /etc/systemd/system/agentmeshos-omniroute.service.d/vnc-gemini-egress.conf,SHA-256 ab1996c94d81d699e07d737cb3d414a985e6310320bfc7974b14198206e523c5 |
删除该 drop-in,执行 systemctl daemon-reload && systemctl restart agentmeshos-omniroute.service |
| Docker 到宿主代理放行 | 无 | UFW 允许 172.17.0.0/16 -> 172.17.0.1:8118/tcp |
执行 ufw delete allow from 172.17.0.0/16 to 172.17.0.1 port 8118 proto tcp |
| 历史自建出口服务(已退役) | 当时已有 | gemini-egress-mm.service enabled/running,DD 为备份 |
不得恢复;当前 Gemini Web 只使用官方 Provider/VNC,不依赖常驻 Chrome 或宿主出口服务 |
| VNC 会话时长 | 官方默认 idle 10 分钟、max 30 分钟 | idle/max 均固定为 24 小时 | 从 /root/omniroute-vnc-session-lifetime-backup-20260925T034058+0800/vnc-gemini-egress.conf.before 恢复 drop-in,重启 OmniRoute |
| Gemini Web 首选凭据 | 旧 api_key,1746 字符、15 个 Cookie |
与当前 providerSpecificData.cookie 一致,2397 字符、23 个 Cookie |
仅在需要恢复旧连接状态时,从 /root/.omniroute/backups/gemini-web-connection-before-api-key-sync-2026-09-24T20-22-00-033Z.json 恢复;恢复后必须重新执行官方连接测试 |
完整备份目录为 /root/omniroute-vnc-egress-backup-20260925T030255+0800/,其中保留修复前两文件和 before.sha256。回滚后必须重新启动一个新的官方 VNC 会话,并重新确认容器不再带 --proxy-server;不能只凭配置文件删除就宣告回滚成功。
若未来升级 OmniRoute,回滚必须先恢复已验证数据快照,再恢复上一官方包版本,并在切换后验证健康、搜索显式 Provider、签名鉴权、模型调用和图片生成;不得通过恢复私有源码或重新编译回滚。
⚠️ 风险与未决项
- Gemini Web 会话已闭环:VNC 登录、官方 harvest、首选凭据同步和官方连接测试均通过;后续再次 harvest 时必须重新同步
api_key,否则旧的api_key仍会优先于新 Cookie。 - Gemini Web 生成与消费分离:
url生成和授权会话取回已经通过,但无登录态 URL 仍是 403,b64_json仍因官方下载器缺少 Cookie 返回 502;在官方修复发布前,不能把结果声明为 101 Codex 可直接消费。 - Gemini Web 图片编辑未闭环:
/v1/images/edits不支持该内置 Provider,聊天入口的带图编辑也未通过;网页能力不能替代官方网关能力。 - 上游修复未发布:官方 issue
#14760与已复现问题完全一致,PR#14787采用“授权上下文内下载”的修复思路,但当前 npmlatest和 GitHub Release 仍是3.8.50;不能从 PR 私自移植。 - 搜索优先级现已落到 Codex 规则:日常搜索先本地,本地失败后回退 Omni 并显式指定 Provider;该约束仍依赖 Codex 运行时实际加载全局规则。
- 自动搜索不应作为稳定依赖:当前自动模式等价于最低成本已配置 Provider,本次为
ollama-search,不是完整健康/额度路由。 - Docker 默认网桥内的容器都可访问
172.17.0.1:8118;当前通过源网段、目标地址和单端口三重限制降低暴露面,如果后续引入不可信多租户容器,必须进一步拆出专用网桥或代理 ACL。 - VNC 临时访问入口和
/touch保活绑定当前会话 ID;会话过期后需要按官方 API 重新建会话并更新端口映射,但 MM 出口参数、Privoxy 监听和 UFW 规则会在 OmniRoute 重启后继续生效。 - 版本行为绑定:本文结论只对官方 3.8.50 及所列包指纹成立;官方升级后必须重新验证。
✅ 未决项 / 需要用户决策
当前的不再是登录或地区问题,也不需要用户继续操作 VNC。需要决策的是“是否接受等待官方发布”:
| 选项 | 结果 | 影响 |
|---|---|---|
| 等待官方修复版本 | 保持 3.8.50,不做源码改动;官方发布包含 #14787 的版本后,按官方升级流程验证 b64_json 和图片编辑 |
最稳妥,符合只使用官方资源规则;期间只能使用授权会话两步取图 |
| 现在做 Codex 侧两步取图 | 先调用 Omni 的 url 生成,再用持有 Gemini Cookie 的 RR 会话下载并落到本地,由 Codex 显示文件 |
可以立即取得图片,但这是客户端后处理,不是 Omni 官方 b64_json 能力;用户需明确接受这一条临时路径 |
不采用的方案是修改 Omni 源码、把 PR #14787 直接打到生产包、重新编译,或在前面再套一层网关。这些操作会产生升级覆盖和双重路由问题,违反现有多节点统一边界。