Skip to content

fix(launcher): strip inherited proxy vars from opencode/pi/omp/codex/codebuddy launch env (#890) - #892

Merged
ranxianglei merged 3 commits into
masterfrom
2026-09-17_opencode-lower-proxy-strip
Sep 17, 2026
Merged

ranxianglei merged 3 commits into
masterfrom
2026-09-17_opencode-lower-proxy-strip

Conversation

@ranxianglei

@ranxianglei ranxianglei commented Sep 17, 2026 •

Copy link
Copy Markdown
Owner

What

Launchers inject uppercase HTTPS_PROXY (pointing at bili) into the client env, but spread raw process.env as the base — so lowercase http_proxy / https_proxy / all_proxy inherited from the user's shell survive. undici (Node), Bun, and reqwest prefer lowercase when both exist, so model traffic silently bypasses bili: no trace in the proxy logs at all, the session keeps growing until the upstream rejects it for context overflow (e.g. "maximum context length is 1048576 tokens... requested 3489289").

Fix: base the child env on stripInheritedProxy(process.env) (the same helper hermes/dsh/kimi/qoder/trae/jcode already use) for every client whose model traffic rides bili's cert-MITM or loopback rewrite:

Client Change
opencode { ...stripInheritedProxy(process.env), HTTPS_PROXY: origin, NODE_EXTRA_CA_CERTS: ca, BILLION_CONTEXT_PROXY: origin }
pi / omp buildPiEnv(..., stripInheritedProxy(process.env), ...)
codex (MITM mode) buildCodexEnv(..., stripInheritedProxy(process.env))
codebuddy buildCodebuddyEnv(..., stripInheritedProxy(process.env)) — loopback CODEBUDDY_BASE_URL traffic can no longer be hijacked by a user proxy
bili test pi path same treatment

Scope notes:

  • claude unchanged — Claude Code ignores proxy env vars for model traffic (routed via ANTHROPIC_BASE_URL / plugin).
  • codex direct mode (BILI_LAUNCHER_DIRECT=1) intentionally unchanged — in direct mode the model traffic does not reach bili by design, so the user's own egress config stays intact there.
  • BILLION_CONTEXT_PROXY and NODE_EXTRA_CA_CERTS are not generic proxy conventions — untouched.
  • Users who want external egress declare it in bili config (proxy, upstreamProxyMode, per-route providers[...].proxy) — visible in logs as [upstream-proxy] ... (source=config|auto|bili-env).

Closes #890

Verification

  • npm run typecheck ✅
  • npm test: 1675 tests, 1673 pass, 0 fail, 2 skipped (gated e2e) ✅
  • npm run build ✅
  • Regression tests: shared captureLaunchedClientEnv harness + one test per client (opencode/pi/omp/codex/codebuddy) — all 8 generic proxy vars stripped while HTTPS_PROXY points at bili, unrelated env vars survive, win32-safe fake-bin naming.

)

The opencode branch spread the full process.env, so lowercase http_proxy/https_proxy/all_proxy inherited from the user's shell survived alongside the uppercase HTTPS_PROXY bili injects. undici (and Bun) resolve the lowercase form first when both are present, so model traffic was silently routed to the user's own proxy instead of bili — no processTurn/forward traces in the bili log while the session kept growing until the upstream rejected it on context overflow.

Base the env on stripInheritedProxy(process.env), the same contract already used by hermes/dsh/kimi/qoder/trae/jcode. Regression test captures the spawned client env and asserts all eight generic proxy vars are stripped while unrelated vars are preserved.
@github-actions

github-actions Bot commented Sep 17, 2026 •

Copy link
Copy Markdown
Contributor

📦 Built Package Artifact

Branch: 2026-09-17_opencode-lower-proxy-strip (bc9db4a)

Option A — Install from npm PR tag (recommended)

npm install -g billion-context@pr-892

Each push to this PR publishes a new version under the pr-892 npm tag.

Option B — Download artifact

  1. Download the artifact from the Actions run
  2. Extract the tarball and install:
tar xzf billion-context-pr892.tgz
npm install -g package

Install instructions are refreshed on each push.

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[bot] 🏷 收到。这是针对 #890 的 PR(分支 2026-09-17_opencode-lower-proxy-strip),我按流程核对代码与 CI 状态后回复结论。

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[bot] 🏷 Review 结论:生产代码改动正确,但 CI 在 Windows 上红了——根因是新回归测试的测试桩问题,已在 PR 分支直接修掉(commit 8347f71),等 Windows CI 重跑。

✅ 生产代码验证通过

  • stripInheritedProxy(src/launcher.ts:1902)覆盖全部 8 个通用代理变量(http/https/all/no × 大小写),与 hermes/dsh/kimi/qoder/trae/jcode 的合同一致;opencode 无条件注入 HTTPS_PROXY,故无条件 strip,对应关系成立。
  • 「遗留」一节逐条核实为真:buildPiEnv(:544)/buildCodexEnv(:577)/codex directUrl 均为 { ...process.env } 基底、未 strip;claude 忽略代理 env。范围划分合理,同意 one-issue-one-scope。

❌ 发现的 CI 失败(windows-latest 22,test job)
新增测试在 Windows 上挂死:Promise resolution is still pending but the event loop has already resolved(ERR_TEST_FAILURE),并级联取消同文件后续测试(kimi 系列)。Linux 全绿所以本地没暴露。

根因(测试桩,非生产代码):fake 二进制命名为无扩展名的 fake-opencode。Windows 下 planClientSpawn(src/launcher.ts:2124)对无扩展名命令一律走 cmd.exe /d /s /c 包装(CreateProcess 无法直接执行扩展名解析),于是 spawnImpl 实际收到的是 cmd.exe 而非 fake 路径——测试里 if (cmd === fakeOc) 永不命中,落入兜底的 makeFakeChild(从不 emit exit),runClient 的 promise 永不 resolve。本文件其余 9 个 full-runLaunch 测试全部遵循 win32 ? "fake-X.exe" : "fake-X" 约定,唯独此新测试偏离了。已用 planClientSpawn 单元级实证:fake-opencode → comspec 包装;fake-opencode.exe → 直接 spawn。

修复(已推送到 PR 分支,8347f71,9+/2-)

  1. fakeOc 改为平台条件命名,对齐文件内既有约定;
  2. 顺手把断言补到与 PR 描述一致:预置全部 8 个通用代理变量,新增 ALL_PROXY/no_proxy 剥离断言与 HTTPS_PROXY === origin 断言(原先只覆盖 5 个)。

本地验证(@8347f71):npm run typecheck ✅ | npm test 1671 tests / 1669 pass / 0 fail / 2 skipped(gated e2e)✅ | npm run build ✅

一句话中文摘要:修复了新回归测试在 Windows 上因 fake 二进制缺 .exe 后缀被 cmd.exe 包装导致测试挂死的问题(生产代码本身正确),已直接在 PR 分支补 commit 并补齐 8 变量全覆盖断言,本地全绿,待 Windows CI 重跑通过后即可合并。

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[bot] 🏷 CI 全绿,PR 可以合并。 ✅

修复 commit 8347f71 的完整 CI(8/8 success):

  • test (ubuntu-latest, 22) / test (ubuntu-latest, 24) ✅
  • test (windows-latest, 22) / test (windows-latest, 24) ✅(此前 22 挂死、24 未出结果的两个 job 现在都过了)
  • version-guard / build-artifact / e2e-fake-codex / codex overlay ✅

合并操作按仓库规范由人工执行:#892

一句话中文摘要:Windows 测试挂死的根因(fake 二进制缺 .exe 后缀被 cmd.exe 包装、spawnImpl 匹配不到)已修复并补齐 8 变量全覆盖断言,四个平台测试 job 全部通过,可以合并;合并后 Closes #890。

… launch env (#890)

Owner-approved scope extension of the opencode fix: these four clients also spread raw process.env into the child env while injecting uppercase HTTPS_PROXY, so an inherited lowercase http(s)_proxy/all_proxy (which undici/Bun/reqwest prefer) silently routes model traffic around bili.

- pi / omp: buildPiEnv now receives stripInheritedProxy(process.env)

- codex MITM: buildCodexEnv now receives stripInheritedProxy(process.env); direct mode (BILI_LAUNCHER_DIRECT=1) intentionally unchanged — its model traffic bypasses bili by design, so the user's egress config stays intact

- codebuddy: buildCodebuddyEnv now receives stripInheritedProxy(process.env) (loopback CODEBUDDY_BASE_URL traffic can no longer be hijacked by a user proxy)

- runTestPi (bili test pi path) follows suit

- claude unchanged: Claude Code ignores proxy env vars for model traffic

Regression tests: shared captureLaunchedClientEnv harness + one test per client asserting all 8 generic proxy vars are stripped while HTTPS_PROXY points at bili and unrelated vars survive.
@ranxianglei ranxianglei changed the title fix(launcher): strip inherited proxy vars from opencode launch env fix(launcher): strip inherited proxy vars from opencode/pi/omp/codex/codebuddy launch env (#890) Sep 17, 2026
@ranxianglei
ranxianglei merged commit b2aa36b into master Sep 17, 2026
8 checks passed
@ranxianglei
ranxianglei deleted the 2026-09-17_opencode-lower-proxy-strip branch October 15, 2026 05:32
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.

[Suggestion] 建议 launcher 一并覆盖常见小写代理变量(http_proxy / https_proxy)

1 participant