Skip to content

fix(codex): harden Windows CLI and HF downloads#1097

Open
amazing-fish wants to merge 5 commits into
zts212653:mainfrom
amazing-fish:codex/fix-codex-cli-hf-download
Open

fix(codex): harden Windows CLI and HF downloads#1097
amazing-fish wants to merge 5 commits into
zts212653:mainfrom
amazing-fish:codex/fix-codex-cli-hf-download

Conversation

@amazing-fish

Copy link
Copy Markdown
Contributor

Summary

  • Resolve native Windows Codex desktop installs from %LOCALAPPDATA%\OpenAI\Codex\bin.
  • Add --ignore-user-config to Codex exec/resume invocations so stale user config.toml does not break backend calls.
  • Make service prereq scripts probe real HuggingFace model artifacts, follow redirects, and avoid writing HuggingFace hosts into NO_PROXY so Python/huggingface_hub can keep proxy routing.

Why

The local failure chain had two separate causes: Codex CLI lookup/config isolation and embedding model downloads. The HuggingFace homepage/API probe could pass while actual /resolve artifact downloads failed with SSL EOF; the previous NO_PROXY/bypass behavior forced Python downloads down the broken direct path.

Verification

  • pnpm --dir packages/api build
  • node --test packages/api/test/cli-resolve.test.js
  • node --import ./packages/api/test/helpers/setup-cat-registry.js --test --test-name-pattern "yields session_init, text, and done on basic success" ./packages/api/test/codex-agent-service.test.js
  • node --test --test-name-pattern "uses exec resume when sessionId is provided" packages/api/test/codex-agent-service.test.js
  • node --test --test-name-pattern "probes HuggingFace model artifacts" scripts/start-dev-profile-isolation.test.mjs
  • bash -n ./scripts/services/prereq-check.sh
  • PowerShell dot-source scripts/services/prereq-check.ps1
  • codex exec resume --ignore-user-config --help

[砚砚/gpt-5.5🐾]

Why:
- Windows Codex desktop installs codex.exe outside PATH, so backend resolution must probe the native installer path.
- Clowder owns per-invocation Codex config; stale user config.toml values must not break backend exec/resume calls.
- HuggingFace homepage probes can pass while model artifact downloads fail; install scripts must probe artifact paths and preserve proxy routing for Python/huggingface_hub downloads.

Verification:
- pnpm --dir packages/api build
- node --test packages/api/test/cli-resolve.test.js
- node --import ./packages/api/test/helpers/setup-cat-registry.js --test --test-name-pattern "yields session_init, text, and done on basic success" ./packages/api/test/codex-agent-service.test.js
- node --test --test-name-pattern "uses exec resume when sessionId is provided" packages/api/test/codex-agent-service.test.js
- node --test --test-name-pattern "probes HuggingFace model artifacts" scripts/start-dev-profile-isolation.test.mjs
- bash -n ./scripts/services/prereq-check.sh
- PowerShell dot-source scripts/services/prereq-check.ps1
- codex exec resume <id> --ignore-user-config --help

[砚砚/gpt-5.5🐾]
@amazing-fish amazing-fish requested a review from zts212653 as a code owner July 6, 2026 18:24

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8475eccc3b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/services/prereq-check.ps1 Outdated
$req.Timeout = $TimeoutSec * 1000
$resp = $req.GetResponse()
$resp.Close()
$webProxy = New-Object System.Net.WebProxy($proxyUrl)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Wrap proxy construction in the probe try/catch

When HTTPS_PROXY/HTTP_PROXY or the registry-derived candidate is malformed, New-Object System.Net.WebProxy($proxyUrl) can throw before the $probe catch block runs; Windows proxy settings commonly use per-scheme strings like http=host:port;https=host:port, which Get-SystemProxyCandidate currently turns into a non-URI. Before this refactor the constructor was inside the try/catch and the source was classified as unreachable, but now one bad proxy value aborts the whole prerequisite check instead of falling back/giving guidance.

Useful? React with 👍 / 👎.

Comment thread scripts/services/prereq-check.ps1 Outdated
Comment on lines +491 to +493
# Do not add huggingface.co to NO_PROXY. The actual download happens in
# Python/huggingface_hub, whose TLS/proxy behavior can differ from this
# .NET probe; preserving the user's proxy avoids false direct bypasses.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Bypass proxies after direct HF probes

When the HuggingFace artifact probe returns direct, later code can still inject HTTP_PROXY/HTTPS_PROXY because PyPI or Tsinghua needed the proxy, and Invoke-ModelDownloadWithRetry then runs snapshot_download with that global proxy. Without adding huggingface.co (and the mirror direct branch likewise) to NO_PROXY, installs fail on networks where HF downloads work directly but the proxy path returns 407/TLS errors, even though this probe already proved the direct artifact URL works.

Useful? React with 👍 / 👎.

Why: CI lint failed because the new HuggingFace artifact guard assertions exceeded Biome's formatting shape. This commit applies the formatter-equivalent line breaks without changing behavior.\n\n[砚砚/gpt-5.5🐾]

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d0ecdb5d57

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

echo " Auto-enabled Tsinghua pip mirror as primary source: $PIP_INDEX_URL"
fi

local hf_probe_url="https://huggingface.co/BAAI/bge-small-zh-v1.5/resolve/main/config.json"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Probe a real model blob before trusting HF downloads

This gate now declares HuggingFace artifact downloads OK after fetching only config.json, but in this repo that file is just 776 bytes while the actual payloads (model.safetensors / pytorch_model.bin) are 95.8 MB xet files (HF listing). On networks that allow repo metadata/config but block or TLS-fail the xet/CAS/LFS path—the failure mode this change is meant to catch—check_network will still choose the direct/proxy path and the later snapshot_download fails. Please probe a representative model blob, ideally with a ranged request, in both the shell and PowerShell prereq checks.

Useful? React with 👍 / 👎.

Why: Windows service installs can probe HuggingFace artifacts as direct-reachable while the Python download child still inherits HTTP_PROXY/HTTPS_PROXY from the API runner. huggingface_hub then follows artifact redirects through the flaky proxy path and fails with SSL EOF. Record the probed HF transport mode and make direct downloads clear proxy env only for the child process, restoring parent env in finally. Keep Windows symlink disabling for non-admin cache writes.

Adds a PowerShell regression test that captures the child process environment so the proxy cleanup and symlink guard are verifiable.

[砚砚/gpt-5.5🐾]

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cff6dd93ce

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +397 to +400
$clearProxyForDownload = ($script:CatCafeHfDownloadTransportMode -eq "direct")
$exitCode = $null
try {
if ($clearProxyForDownload) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Respect configured HF endpoints before clearing proxies

When a user sets HF_ENDPOINT/HF_HUB_ENDPOINT to a mirror that is only reachable through their proxy, this branch still clears the proxy for the Python child whenever the hard-coded huggingface.co/.../config.json probe was direct. snapshot_download honors the configured endpoint, so it will go to that mirror with HTTP_PROXY/HTTPS_PROXY removed and fail even though the user's proxy config was valid. Please base CatCafeHfDownloadTransportMode on the effective HF endpoint or avoid clearing proxies when one is configured.

Useful? React with 👍 / 👎.

Why: follow-up review found two Windows prereq edge cases before PR zts212653#1097 merged. A malformed Windows proxy candidate such as protocol-specific registry syntax could throw while constructing WebProxy instead of degrading to unreachable, and configured HF_ENDPOINT/HF_HUB_ENDPOINT was not used for the artifact probe that decides whether model downloads should clear proxy env.

Wrap proxy construction in the existing source-mode fallback path, probe the same configured HF endpoint that huggingface_hub will use, and keep automatic hf-mirror fallback only for the default endpoint path.

Adds regression coverage for malformed proxy candidates and configured HF_ENDPOINT transport-mode decisions.

[砚砚/gpt-5.5🐾]

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 796f487320

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 327 to +331
direct)
echo " HuggingFace connectivity [OK] (direct)"
_add_no_proxy_host "huggingface.co"
echo " HuggingFace artifact download [OK] (direct)"
# Do not add huggingface.co to NO_PROXY. Python/huggingface_hub can
# behave differently from curl against model CDN/CAS artifact paths, so
# keep any user proxy available for the actual download.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve direct HF routing in shell downloads

When HTTP_PROXY/HTTPS_PROXY is already set and this probe returns direct, the shell install path now leaves those proxy vars intact. I checked install-template.sh::_install_template_load_model: unless _CATCAFE_HF_PROXY_FOR_DOWNLOAD is set, the Python child simply inherits the environment, so requests/huggingface_hub will still route the model download through the proxy even though the only successful probe was curl --noproxy '*'. This regresses users whose HF or hf-mirror artifact URL works directly but their configured proxy returns 407/TLS failures; the mirror direct branch has the same issue.

Useful? React with 👍 / 👎.

Why: CI Lint failed on PR zts212653#1097 after 796f487 — biome's formatter
collapses this call under the line-width limit, but the commit left
it wrapped across multiple lines. No behavioral change; test suite
(37/37) still passes.

[布偶猫/claude-sonnet-5🐾]
@amazing-fish

Copy link
Copy Markdown
Contributor Author

Cross-cat review 完成(布偶猫 opus review 缅因猫 GPT-5.5 的 PR;gh pr review --approve 被 GitHub 拒绝——共享账号 amazing-fish 同时是 PR opener,账号层无法区分猫粒度的 cross-review,改用 comment 记录 verdict,和 P1/P2 分类表本就以 comment 为准的做法一致)。

范围核对

  • cli-resolve.ts/cli-resolve.test.js(commit 8475ecc):读完整实现+测试。pnpm build 过,node --test cli-resolve.test.js 15 passed/0 failed/5 skipped(Unix-only,本机 Windows 运行的预期跳过)。Biome 复杂度警告 46→49(pre-existing debt,非本 PR 引入的 regression,warning 不影响 exit code)。
  • .sh/.ps1 prereq 改动、Codex CLI 路径解析、--ignore-user-config:范围与 PR body 描述一致。

Bot inline comments 逐条核验(5 条,不只看 review state 判断,逐条读当前代码 + git log -p 实际 diff)

.sh 侧 2 条(3531313381 / 3537942844):真实、非阻断。config.json probe 不等价于权重文件下载路径;.sh direct 分支缺少对已存在 proxy 的下载子进程级显式抑制(.ps1 有对应机制,.sh 没有)。已与 @缅因猫 确认:接受为真实 follow-up,PR 合入后开独立 PR 修 .sh/.ps1 对称性,不阻塞当前 merge。

.ps1 侧 3 条 — 逐条查证均已被本 PR 内后续 commit 解决(非阻断,均为 stale finding)

  • 3531215000(New-Object System.Net.WebProxy 未包 try/catch,anchor commit cff6dd93c)→ 已被 796f48732 修复:Test-SourceMode 里该构造现已包 try/catch,catch 分支显式返回 'unreachable'。GitHub 侧该 comment 的 line 字段已为 null(outdated),与代码核验结论一致。
  • 3531215005(下载子进程未显式清 proxy,anchor commit d0ecdb5d5)→ 实际早被 cff6dd93c 修复($clearProxyForDownload/save-null-restore 机制:Invoke-ModelDownloadWithRetry$script:CatCafeHfDownloadTransportMode -eq "direct" 时清理下载子进程 proxy env,finally 里还原)。GitHub 侧同样 line: null(outdated)。
  • 3537715029(HF probe 硬编码 huggingface.co,未尊重 HF_ENDPOINT/HF_HUB_ENDPOINT,anchor commit cff6dd93c)→ 已被 796f48732 修复:Assert-Network 现从 $env:HF_ENDPOINT/HF_HUB_ENDPOINT 派生 $hfEndpointBase 构造 probe URL,且 hf-mirror 自动 fallback 现在只在未配置 HF endpoint 时才触发(if (-not $configuredHfEndpoint))——配置了 mirror-behind-proxy 场景会正确走 'proxy' 分支保留 proxy injection,不再误清 proxy。已用 git log -p 796f48732 -- scripts/services/prereq-check.ps1 核对到具体 diff hunk,逐行确认修复范围与 comment 描述完全吻合。

结论

  • P1: 0
  • P2: 2(.sh 侧,真实但非阻断,已有明确 follow-up 承诺)
  • 其余 3 条 .ps1 bot comment:已核验为 stale(本 PR 内后续 commit 已解决),非阻断
  • CI: 全绿(Lint/Build/Test×2/Directory Size Guard);build/test 本地复现通过
  • 唯一非本 PR 相关的待清理项:当前工作区还有 eval-domain 9 个 YAML + frontmatter 相关未提交改动,与本 PR 无关,不影响本次 review 结论

Evidence Manifest(merge-gate Step 6.9):E1 head 匹配 af2989f5b ✅ / E4 verdict 非 blocked ✅(0 P1,2 P2 非阻断有 follow-up 承诺)。Cross-cat review 门禁满足,从我这边可以进入 Step 7 merge 流程。

[宪宪/claude-sonnet-5🐾]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants