Only restore env vars when we actually modified them (noProxyDidModify
flag). Prevents silently deleting a user's NO_PROXY that already
contains loopback entries. Added regression test.
Fix Greptile review: when call A exits before call B, the isFirst flag
on B is false, so the restore condition (refCount===0 && isFirst) was
never true and NO_PROXY leaked permanently.
Remove '&& isFirst' so any last exiter (refCount===0) restores the
original env vars. Added explicit reverse-exit-order regression test.
Address Greptile review feedback:
- Replace snapshot/restore pattern with reference counter to prevent
permanent NO_PROXY env-var leak under concurrent async calls
- Include [::1] in the alreadyCoversLocalhost guard
- Add concurrency regression test
When HTTP_PROXY / HTTPS_PROXY / ALL_PROXY environment variables are set,
CDP connections to localhost/127.0.0.1 can be incorrectly routed through
the proxy (e.g. via global-agent or undici proxy dispatcher), causing
browser control to fail.
Fix:
- New cdp-proxy-bypass module with utilities for direct localhost connections
- WebSocket (ws) CDP connections: pass explicit http.Agent to bypass any
global proxy agent patching
- fetch-based CDP probes: wrap in withNoProxyForLocalhost() to temporarily
set NO_PROXY for the duration of the call
- Playwright connectOverCDP: wrap in withNoProxyForLocalhost() since
Playwright reads env vars internally
- 13 new tests covering getDirectAgentForCdp, hasProxyEnv, and
withNoProxyForLocalhost (env save/restore, error recovery)
* fix(browser): include Chrome stderr and sandbox hint in CDP startup error (#29312)
When Chrome fails to start and CDP times out, the error message previously
contained no diagnostic information, making it impossible to determine why
Chrome couldn't start (e.g. missing --no-sandbox in containers, GPU issues,
shared memory errors).
This change:
- Collects Chrome's stderr output and includes up to 2000 chars in the error
- On Linux, if noSandbox is not set, appends a hint to try browser.noSandbox: true
Closes#29312
* chore(browser): format chrome startup diagnostics
* fix(browser): detach stderr listener after Chrome starts to prevent memory leak
Named the anonymous listener so it can be removed via proc.stderr.off()
once CDP is confirmed reachable. Also clears the stderrChunks array on
success so the buffered data is eligible for GC.
Fixes the unbounded memory growth reported in code review: a long-lived
Chrome process emitting periodic warnings would keep appending to
stderrChunks indefinitely since the listener was never removed.
Addresses review comment from chatgpt-codex-connector on PR #29355.
* changelog: note cdp startup diagnostics improvement
---------
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
Co-authored-by: 派尼尔 <painier@openclaw.ai>
In headless or noSandbox server environments (like Ubuntu Server), the
Chrome extension relay cannot work because there is no GUI browser to
attach to. Previously, the default profile was 'chrome' (extension relay)
which caused snapshot/screenshot operations to fail with:
'Chrome extension relay is running, but no tab is connected...'
This fix prefers the 'openclaw' profile (Playwright native mode) when
browser.headless=true or browser.noSandbox=true, while preserving the
'chrome' default for GUI environments where extension relay works.
Fixes: https://github.com/openclaw/openclaw/issues/14895🤖 AI-assisted (Claude), fully tested: pnpm build && pnpm check && pnpm test