面向 Codex Desktop 的「token 优先」代码/日志/文档/OCR/图片推理卸载网关。它把大型源码、提取文本、 日志或少量页面图打包后,交给已登录的网页版大模型(ChatGPT / DeepSeek / Qwen / Gemini)做只读 推理,再把结构化短结论交回 Codex 本地核验、修改与测试。Web 大模型只负责分析,不拥有执行权限。
Codex Desktop
-> 全局 AGENTS.md 路由判断(可选)
-> web-ingest standalone Skill(本仓库 skills/web-ingest/,先做本地页面预摄取)
-> web-llm-page-extract Skill(同上下文有界 DOM、系统剪贴板、结构化回执与终态清理)
-> agentchat-code-offload 组合 Skill(本仓库 skill/,兼容入口并注入历史 Provider runner)
-> Luna model-routing Skill(本仓库 skills/luna-model-routing/,原生 subagents + Web-LLM 成本路由)
-> codex-agentchat-offload Adapter(本仓库 adapter/,调用 repomix 打包)
-> 临时 BROWSER_PROMPT_FILE + OFFLOAD_REQUEST_FILE
-> web-provider-runner(本仓库 skill/scripts/)
-> ChatGPT / DeepSeek / Qwen / Gemini 网页 Provider
-> 结构化短回答 -> Codex 本地核验、修改、测试
命名沿用了历史上的「AgentChat」,但当前实现直接驱动网页 Provider,不再经过独立的 AgentChat 平台。
- macOS / Linux(文档分析用到 macOS
textutil,PDF 用到pdftotext) - Node.js 与 npm
rg(ripgrep,用于 symbol/文本搜索)pdftotext(poppler,仅 PDF 文档分析需要;缺失时其余功能仍可用)- 一个 Codex 可驱动的浏览器,并已登录上述网页大模型(见下文“浏览器登录”)
git clone https://github.com/zxfd/codex-code-offload.git
cd codex-code-offload
./install.shinstall.sh 会把:
skill/软链到~/.codex/skills/agentchat-code-offload/skills/web-ingest/软链到~/.agents/skills/web-ingest/skills/web-llm-page-extract/软链到~/.agents/skills/web-llm-page-extract/skills/luna-model-routing/软链到~/.agents/skills/luna-model-routing/skills/repo-execution/软链到~/.agents/skills/repo-execution/adapter/软链到~/.local/share/codex-code-offload/(可用CODEX_CODE_OFFLOAD_HOME覆盖)- 创建状态目录
~/.local/state/codex-web-reasoning/ - 在 adapter 目录执行
npm install安装repomix
所有源码路径均基于 $HOME 计算,不依赖本机用户名;换一台机器克隆后直接 ./install.sh 即可。
安装脚本会先拒绝覆盖已存在的非任务实体或指向其他目标的软链,再对 standalone Skill 执行完整性校验和本地健康检查。目标已存在且无法确认归属时保持原状并中止。
卸载网关复用你浏览器里已经登录的网页会话,不使用 API key。首次使用前,在同一浏览器里登录:
- ChatGPT:https://chatgpt.com/
- DeepSeek:https://chat.deepseek.com/(并使用“专家模式”)
- Qwen:https://chat.qwen.ai/
- Gemini:https://gemini.google.com/app
Codex 通过浏览器自动化驱动这些页面。登录状态、模型/强度选择与可见附件确认都由 Skill 内部校验。
ChatGPT 新会话加载时,当前思考强度控件可能比输入框更晚出现。Adapter 会在初始选择阶段等待最多 10 秒再决定是否打开完整模型菜单;若限流弹窗临时移除了控件的无障碍名称,输入框和发送按钮会改用 composer 内的稳定结构定位。若仍无法确认,这类发送前 UI 瞬态失败不会写入 Provider 负面健康缓存,下一请求仍会重新核验 ChatGPT。长驻调用方会按源码修改时间刷新 Runner 和 Provider Adapter,避免代码更新后继续执行旧模块。
需要同时传递长文本和图片时,可在单一 ChatGPT multimodal 路由上使用经过字节数与 SHA-256 回执校验的系统剪贴板文本;仍强制 local_fallback: false、唯一 Provider、结构化响应验证和逐张附件计数确认。若 ChatGPT 把长粘贴自动折叠为文本附件,Adapter 会通过“在文本字段中显示”还原其段落内容并再次校验原始哈希,避免把输入框暂时为空误判成粘贴失败。
把 config/agents-md-offload-block.md 中的片段合并到你的全局 AGENTS.md,Codex 就会在大型分析任务
上默认走本网关;不合并时仍可手动按 skill/SKILL.md 调用。
skills/web-ingest/是网站无关的 standalone Skill:只接受单个 URL,负责本地文本/视觉信号、同源重定向、隐私阻断、临时暂存和清理。它不选择具体 Provider、不执行外传,也不静态依赖web-provider-runner.mjs。skills/web-llm-page-extract/在web-ingest之上提供真实运行入口:调用方显式提供任务词组,脚本在同一 Chrome 标签内选出可见任务子树,写入并校验有界 DOM,经 macOStext/plain剪贴板粘贴到唯一 ChatGPT Provider,严格验证本次新 JSON 回复,然后归档会话、关闭标签并清理临时工件。skill/保留代码、日志、文档和图片推理所需的 Provider 适配器;页面到 Web-LLM 的完整闭环统一使用skills/web-llm-page-extract/,其底层预摄取统一使用skills/web-ingest/。skills/luna-model-routing/让主 Luna 保留实现、测试、Git 和最终验收,只把真正独立、读多写少的探索与核验交给原生 Codex subagents;超过 token gate 的重推理优先进入agentchat-code-offload。它不使用codex_app__create_thread模拟 subagent,也不依赖clientThreadId解析。
典型检查:
node /Users/gin/.agents/skills/web-ingest/scripts/health-check.mjs \
--root /Users/gin/.agents/skills/web-ingest
node /Users/gin/.agents/skills/repo-execution/scripts/verify-installed-skill.mjs \
--source "$PWD/skills/web-ingest" \
--installed /Users/gin/.agents/skills/web-ingest
node /Users/gin/.agents/skills/repo-execution/scripts/verify-installed-skill.mjs \
--source "$PWD/skills/web-llm-page-extract" \
--installed /Users/gin/.agents/skills/web-llm-page-extract
node /Users/gin/.agents/skills/web-llm-page-extract/scripts/health-check.mjs \
--root /Users/gin/.agents/skills/web-llm-page-extractweb-ingest 始终只做本地预摄取。只有调用方取得针对当前页面数据和一个具名 ChatGPT Provider 的明确审批后,web-llm-page-extract 才会通过端到端入口把有界 DOM 写入系统剪贴板;入口强制唯一 Provider、local_fallback: false、粘贴哈希确认、严格 JSON 和终态清理,审批不会自动转移或触发 fallback。
skill/ Codex Skill(SKILL.md + 浏览器自动化脚本)
skills/ 协作型路由 Skill 与稳定仓库执行规范
adapter/ 本地打包与安全边界 Adapter(codex-agentchat-offload.mjs + providers.json)
config/ 全局 AGENTS.md 路由片段
install.sh 一键安装(软链 + npm install)
uninstall.sh 卸载(仅移除软链与状态目录,不改动仓库文件)
ChatGPT 的发送和回答确认是同一个请求闭环:adapter 会记录发送前 assistant 消息数量,只接受发送后新增的 assistant 消息,并等待该消息稳定完成。发送按钮出现超时等“结果不确定”的情况会继续观察同一请求,绝不盲目重复发送;发送后的异常也不会写入负面健康缓存,避免一次浏览器状态抖动导致后续请求直接 fallback。回归测试可运行:
node --test skill/scripts/tests/chatgpt-response-confirmation.test.mjs每轮 Web-LLM 对话在确认终局回答后,才由对应 Provider Adapter 清理会话,然后关闭 Chrome 标签;NEED_MORE_CONTEXT 续聊不会提前清理。ChatGPT 使用“更多 → 归档”,不刷新页面并确认归档菜单关闭;归档失败时保留标签供恢复。
Qwen 采用“会话行菜单 → 归档”,并且只在“归档”成功确认后关闭标签;归档动作会被视为首选清理路径,失败会保留标签供后续恢复。
DeepSeek 当前真实页面没有归档项,固定使用“会话行菜单 → 删除 → 删除该对话”,确认当前会话链接已从侧栏消失后才关闭标签。删除是不可恢复操作,只有 DeepSeek 的显式清理策略会执行它。
Gemini 现已固化为“会话行菜单 → 删除 → 删除”清理,菜单名称为“打开对话操作菜单。”;删除确认弹窗标题为“要删除对话吗?”,按钮为“删除”。清理前要求当前 URL 为 Gemini 会话页;清理时不刷新页面,确认会话层级已移除或 URL 变化后才允许 Runner 关闭标签。providers.json 已将 gemini-current.target.conversation_cleanup 固定为 delete。
DeepSeek 每次发送前还会确认“专家模式”和“深度思考”均已开启;任一控件无法确认,当前 Provider 失败并按既定路由继续。调用 runner 时必须传入 browserChannel: "chrome"。
Web-LLM 普通回答默认等待 600 秒;开启深度思考后,Adapter 会按配置延长预算:350K 保留输出配置最长等待 900 秒,其他深度思考请求至少等待 720 秒,并继续以“停止回答”控件判断是否仍在生成。该预算用于避免把仍在生成的可用回答误判为超时,不等同于对外部 Provider 可用性的 99% 保证。
- Adapter 拒绝敏感路径、glob、仓库外路径与明显的凭证文本;只打包用户显式选择的仓库内文件。
- PDF/DOCX/RTF 先本地提取为有界文本,再扫描凭证后发送,原始二进制不离开本机。
- Web 大模型的回答一律视为未经验证的假设,Codex 负责本地核验、修改与测试。
- 不读取或输出 Cookie、登录数据库、token、密钥和无关私密会话。
./uninstall.sh只会移除指向本仓库目标的 Skill/Adapter 软链(包括 ~/.agents/skills/web-ingest 与 ~/.agents/skills/web-llm-page-extract)和状态目录;非软链实体、指向其他目标的软链均保留,仓库文件本身不改动。