Files
codex-app-server/docs/chatgpt-codex-alignment.md
host 6aa4b45f2c align: 记白名单后端到端全绿结论
- 白名单 6 域名已同步主机并 reload,curl 验 3 个 200、
  time.is 仍 403、worldtimeapi 站侧 TLS 失败(timeapi 兜底)。
- 全新项目任务 6a267baf:web_search 6/6、web_fetch 1/4
  成功(weather.com.cn),答案报出上海时间与北京晴
  5°C、风力 3 级以下,带来源与快照时间,未编造高低温。
- 诚实边界:时间来自系统时钟 + UTC+8 换算,非 timeapi
  fetch;天气来自 fetch 成功的一级来源页。
清理已核,用户剩余 0,生产 health fd9fe5f。
2026-10-30 01:16:49 +08:00

211 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# codex-app-server 对齐 ChatGPT Codex:工具目录对照
来源:用户 2026-10-30 提供的 ChatGPT Codex 工具目录(ChatGPT Codex
在其自有 app 里的工具清单),对照对象是 codex-app-server 现生产
(main d4a517f,2026-10-29)与本分支第一批。
方向先说清:用户 2026-10-29 已定,往自动化编程任务平台方向
做生产级提升,不是个人 agent OS 方向。所以本对照只对齐
“编程任务平台”相关的能力,ChatGPT 托管专属能力不照搬,
见文末“不照搬”一节。
## 对照表
| ChatGPT Codex 能力 | codex-app-server 现状 | 结论 |
|---|---|---|
| 终端与文件:shell、读写工作区、看图片、apply_patch、看终端输出 | codex-core 工具 + worktree + 沙箱,host/cloud 已有 | 对齐 |
| 联网查询:网页搜索、打开网页、找页面内容 | websearch MCP(SearXNG / DuckDuckGo / Brave),生产 worker 带 `--websearch-mcp` 才播种 | 对齐(搜索本体) |
| 联网查询:天气、时区、股票、体育赛程 | 无专用垂类工具;本分支新增 `live-info` 技能,教 agent 用 web_search 查一级来源、带来源和快照时间,绝不编数字 | 第一批:技能对齐,工具未新增 |
| 图片生成:按描述生成、按已有图片编辑 | 无图片生成模型工具;查看/裁剪/缩放靠 PIL / ImageMagick(若装了)。本分支新增 `image-workflow` 技能,未配置生成工具时必须明说无法生成,绝不拿占位图顶替 | 第一批:流程对齐,生成能力仍缺工具 |
| 浏览器与界面操作(CUA):读界面、开网页、操作标签页、桌面应用 | 无。README 已写:Computer Use 是另一条管线,不在 host / CLI 中间层 | 不照搬,见下 |
| 协作代理:启动代理、发任务、看进度、等结果 | host delegate、模型内子代理、云端协调员/子任务 | 对齐 |
| Codex 任务与工作区:列项目/任务、读任务记录、建/切 worktree、开文件或终端面板、管理标题、归档、附件 | projects / tasks / fork / archive / uploads 已有;任务文件读取在 PR #146(未合) | 对齐,文件端点待 #146 |
| 自动化:创建/查看/更新定时任务和提醒 | automations --add + run-due、云端自动化 | 对齐 |
| 文档工具:LaTeX 编译、Word / PDF / 表格 / 演示文稿 | 无一等工具,只能靠 shell 调系统里装好的工具。本分支新增 `document-tools` 技能:先核查 pandoc / latexmk / python-docx 等,缺了明说,产出后必须重读验证 | 第一批:技能对齐,工具未新增 |
| 连接的应用与服务:GitHub、文档会话、Sites 等,须安装/授权 | GitHub PR 链路、MCP / skills / 插件已有;ChatGPT 的 Docs / Sites 连接器目录没有 | 部分,不照搬连接器目录 |
| 专项能力:管理插件、技能 | skills/list、`.agents/skills`、MCP 已有;本分支在 `cloud/skills/` 新增 3 个技能包 | 部分,第一批补技能包 |
| 专项能力:ChatGPT 宠物 | 无,ChatGPT app 专属 | 不照搬 |
| 专项能力:AIMemory Runner 远程运维 | 2026-10-28 已停用全部 7 个 aimemory 容器,数据未删但不在活跃能力里 | 不照搬,现不活跃 |
## 第一批做了什么(本分支)
- `cloud/skills/live-info/SKILL.md`:天气/时区/股票/体育,
查一级来源、带来源和快照时间、不编数字。
- `cloud/skills/document-tools/SKILL.md`:LaTeX / Word / PDF /
表格 / 演示文稿,先核查工具、缺了明说、产出后重读验证。
- `cloud/skills/image-workflow/SKILL.md`:已有图片处理 +
生成工具已配置时才生成,未配置时明说、绝不顶替。
- `cloud/tests/test_chatgpt_codex_skills.py`:校验每个技能
都有 name + description、名字与目录一致、无密钥占位、
正文非空。技能本身不改 worker 行为,生产行为不变。
- 本分支不改 worker 播种、不改生产配置、不部署。把技能
播种进租户 codex-home(仿 websearch MCP 的播种方式)
是下一批,需要单独评审 worker 改动。
## 第二批:技能播种进租户(本分支新增)
- `cloud/skill_seed.py`:仿 websearch MCP 播种,把
`cloud/skills/` 的 SKILL.md 拷进租户
`codex-home/skills/<名>/SKILL.md`。路径是实测纠正过的:
2026-10-30 主机实测,临时 codex-home(生产未动)先播
`.agents/skills/`,skills/list 只返回 5 个系统技能、3 个
自有技能一个没出现;改播 `skills/` 后返回 8 个,3 个自有
技能以 scope=user 出现。系统技能本身就在
`skills/.system/` 下,这就是用户技能目录的证据。租户
任务绝不能往任务 worktree 里播种(会污染任务 diff),
所以用租户 codex-home——这也是 websearch MCP 播种用的
通道。附带发现:Codex 自带系统技能里已有 imagegen
(生成/编辑位图),所以图片生成在 Codex 本体里不是
“无技能”,只是中转模型是否支持图片工具另待实测。
- `cloud/worker.py`:新增 `--seed-skills`(默认关,仿
`--websearch-mcp`),只在 `_tenant_dirs` 里调用播种;
老租户下一次任务自动合并;租户改过的技能文件绝不
覆盖(只上报 differs);播种失败只记日志、不阻塞任务
(技能是可选流程说明,不是已宣传就必须有的工具)。
- `cloud/tests/test_skill_seed_worker.py`:播种助手
(拷、幂等、缺包、租户改动不覆盖)+ worker 开关
(关 = 老行为、开 = 播真实包、老租户合并 + 改动存活)。
- 诚实边界:发现已实测(skills/list,scope=user),
模型在真实 Docker 租户任务里是否真调用 `$live-info`
并返回结果仍未实测——那需要带 `--seed-skills` 的
worker(部署或临时 worker,另等用户定),不是本批
能宣称的。本批不改生产配置、不部署,autoscaler 的
worker 参数里加 `--seed-skills` 是部署时另行应用的
主机步骤(unit 文件不在 deploy tar 里,仿 websearch)。
## 真实任务实测(2026-10-30,临时 worker,生产未部署)
- 隔离方式:测试任务带 `depends_on: ["skill-test-gate-never"]`,
生产 worker 只认领依赖已完成的任务,永远不会认领它;
临时 worker 不跑循环,只跑一次 `run_one(task=指定任务)`,
认领走 CAS,只跑这一个任务。临时 worker 代码在主机
`/tmp/skill-temp-worker/`(对齐分支 git archive),不动
`/opt` 生产代码;跑时用 codexsvc 身份 + 生产 DB 环境,
否则租户目录属主对不上容器 1003。
- 第一次失败,教训已记:用 repo_url 项目时 GitHub clone
在 684K 卡了 6 分钟以上,且 `run_one` 单任务模式没有
run_loop 的心跳线程,任务在 300 秒时被生产 worker 的
sweep 标 interrupted(心跳停滞),而 clone 还没完、
播种根本没跑到。第二次改用无 repo_url 的 test-repo
项目(本地模板,不 clone)+ 临时 runner 里补心跳线程
(每 30 秒刷 `_heartbeat_running_tasks`),问题消失。
- 第二次成功,任务 7235de8f…(临时用户 skilltest-15fd9f58,
临时项目 59961c66…,Docker,effort low,实际模型
gpt-5.6-sol,约 40 秒 completed,tokens 64335,
cost_record 425,error 空):租户 codex-home/skills/
里确有 3 个技能的 SKILL.md;trace 里 agent 真执行了
`sed -n '1,240p' /var/lib/codex-app-server/codex-home/skills/live-info/SKILL.md`
(容器内挂载路径),即技能不只是被列出,而是被读了;
最终答案以 `SKILL: live-info` 开头,并按技能规则明说
web_search 不可用、不编造实时数字。
- 仍未解决的独立问题:Docker 任务里 web_search 本身
因 DNS/联网失败而不可用(与 2026-10-28 websearch e2e
探针的 DuckDuckGo DNS 失败同类),技能发现/调用已证,
但 live-info 要真正查到天气/时间,还得先修 web_search
在 Docker 里的联网问题——那是另一批工作,不在本批
宣称范围内。
## web_search Docker 联网修法(2026-10-30,下一批)
- 定位(容器内直接跑 websearch.py,绕过模型):
SearXNG 默认 general 类别在容器里要 20.0 秒才回
(wikipedia / wikidata / brave / duckduckgo / google
引擎全部超时,只有 bing + 360search 回),正好撞
MCP 默认 20 秒超时;随后 DuckDuckGo 经 egress 代理
也超时(不是 DNS,是对方本身超时),于是整条链
失败。代理本身没问题:Tinyproxy 白名单早已放行
searx.diante.me 与 duckduckgo.com,容器经网关 8888
能到 SearXNG,只是太慢。
- 修法(本分支,未部署):`_provider_searxng` 默认
传 `engines=bing,360search`(`SEARXNG_ENGINES` 可
覆盖,空值恢复旧行为);worker 的搜索 env 透传
补上 `SEARXNG_ENGINES`。实测:同一容器、同一代理,
钉住引擎后 SearXNG 0.26 秒回 3 条(首条北京天气),
auto 链 0.15 秒走 SearXNG 成功;旧代码 20.0 秒。
- 测试:新增 `test_websearch_searxng.py` 3 项(默认
钉住、env 覆盖、空值恢复),连同 MCP / worker 测试
共 21 项全过。生产仍未部署此修法,live-info 端到
端再测另等用户定。
## MCP env 真正根因 + 端到端再测(2026-10-30)
- 再测先失败,暴露了更深一层:临时 worker 新代码
跑 live-info,MCP 链只有 duckduckgo,DNS 瞬间失败,
而同一任务里 Codex bash 的 env 明明有 SEARXNG_URL
与 proxy。结论:Codex 的 MCP 子进程不继承 Codex
进程 env,docker -e 再全也没用,env 必须写进
config.toml 的 `[mcp_servers.websearch.env]`。
手动给租户 config 加 env 后,同一项目里 web_search
立刻返回真实北京天气 3 条,证实。
- 代码修法(提交 dc9b29e):`ensure_websearch_mcp_env`
写/替换租户 config 的 env 小节(其它小节不动,
空 env 不写),worker 在 `_docker_task_context`
算出网关后、容器启动前调用它(网关此时才已知)。
测试新增 `test_websearch_mcp_env.py` 4 项,相关
共 33 项全过。
- 全新项目端到端再测(任务 537f8b7c,临时 worker
dc9b29e,生产未部署):代码修法生效——租户
config 里自动写进了 MCP env(含网关 10.20.21.1:8888
的 proxy 与 SEARXNG_URL),技能 3 个都在,web_search
6 次里 5 次成功;但最终仍未报出天气与时间,因为
web_fetch 4 次全败于 Tinyproxy `403 Filtered`:
模型要 fetch 的一级来源(open-meteo、worldtimeapi、
timeapi.io、time.is 等)都不在 egress 白名单里,
搜索摘要本身又没有可靠数字。下一层修法不是代码,
是主机 egress 白名单加这些一级来源域名并 reload
tinyproxy(同时改仓库 deploy/egress/tinyproxy-filter,
否则下次部署会 revert),属生产安全配置变更,
另等用户定。清理已核:两次测试的用户/项目/任务、
租户目录与网络、临时代码全删,用户剩余 0,
生产 health 当时 fd9fe5f、worker_ok。
## 白名单加完后端到端全绿(2026-10-30 01:0x)
- 白名单(用户点选后执行,提交 8255e6a):
worldtimeapi.org、timeapi.io、open-meteo.com、
weather.com.cn、meteoblue.com、accuweather.com;
刻意不加 time.is / time.org.cn / time.ms。
主机 /etc/tinyproxy/tinyproxy-filter 已同步(旧文件
备份 /tmp/tinyproxy-filter.bak-202610300105,diff
只多了新行),tinyproxy reload 成功(pid 未变)。
curl 经代理验:timeapi.io、open-meteo、
weather.com.cn 均 200;time.is 仍正确 403;
worldtimeapi 被放行但自身 TLS 握手失败(站侧,
时间有 timeapi.io 兜底)。
- 全新项目端到端(任务 6a267baf,临时 worker
8255e6a,生产未部署代码):completed,web_search
6/6 成功,web_fetch 1/4 成功(成功的是
weather.com.cn,其余被挡的仍是未加白名单的
次级天气站,属预期);最终答案以 SKILL: live-info
开头,报出 Asia/Shanghai 2026-10-30 01:08:59
(UTC+8)(来源:容器 UTC 时钟 + UTC+8 偏移,
快照 2026-10-29 17:08:59 UTC,无夏令时)与
北京 2026-10-29 晴、5°C、风力 3 级以下(来源:
中国天气网 weather.com.cn 101010100 页面,
标 2026-10-29 18:00 更新,未编造日高低温)。
诚实边界:时间来自系统时钟 + 偏移换算,不是
timeapi.io 的 fetch 结果;天气数字来自 fetch
成功的一级来源页。清理已核:用户/项目/任务、
租户目录与网络、临时代码全删,用户剩余 0,
生产 health 仍 fd9fe5f、worker_ok,主机白名单
新域名仍在(回滚办法:恢复备份文件 + reload)。
- 清理已核:第二次测试的用户/项目/任务、租户目录、
临时 worker 代码与临时 key 全部删除,用户剩余 0,
生产 health 仍 3696dad、worker_ok;第一次测试的
临时行与租户目录也已同样清理。
## 不照搬(诚实边界)
- CUA / 桌面操作:需要浏览器自动化 + 桌面操作基础设施,
不是加一个技能就能对齐的,且与“自动化编程任务平台”
方向不符;若用户另行立项,再单独评估 Playwright /
浏览器 MCP 路线。
- 图片生成模型:需要图片生成模型或 API 配置,codex-app-server
现用中转 chat 模型,没有图片生成工具;技能只能管“有工具
时怎么用、没工具时怎么明说”,不能凭空变出生成能力。
- ChatGPT 连接器目录(Docs / Sites 等)与宠物:ChatGPT
托管服务专属,需要 OAuth 与托管后端,不在开源宿主编排层
的范围里。
- AIMemory Runner:已停用,不为对齐而恢复;恢复需用户
另行定是否启用 docker 自启与数据清理。