fix(browser): hint WSL portproxy CDP empty replies (#85379) · openclaw/openclaw@933f01c
steipete
·
2026-05-23
·
via Recent Commits to openclaw:main
| Original file line number | Diff line number | Diff line change |
|---|
@@ -55,6 +55,7 @@ Docs: https://docs.openclaw.ai
|
55 | 55 | - Dashboard/CLI: allow macOS browser launching through `open` even when SSH environment variables are present, while preserving Linux SSH no-display protection. Fixes #67088. Thanks @theglove44. |
56 | 56 | - Codex app-server: keep native web search observations out of mirrored chat transcripts while preserving tool progress telemetry. Fixes #85109. Thanks @ugitmebaby. |
57 | 57 | - OpenCode Go: strip unsupported Kimi reasoning replay fields before provider requests so repeated `kimi-k2.6` turns do not fail schema validation. Fixes #83812. Thanks @Sleeck. |
| 58 | +- Browser/CDP: add a WSL2 portproxy self-loop hint when Chrome DevTools endpoints accept connections but return an empty HTTP reply. Fixes #59209. Thanks @Owlock. |
58 | 59 | - Agents/OpenAI: preserve structured provider error code, type, and redacted body metadata on boundary-aware transport failures. |
59 | 60 | - Doctor/Codex: point native Codex asset warnings at the canonical `openclaw migrate plan codex` preview command. Fixes #84948. Thanks @markoa. |
60 | 61 | - CLI/models: make `capability model auth logout --agent` remove auth profiles from the selected non-default agent store. Fixes #85092. Thanks @islandpreneur007. |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -57,6 +57,12 @@ function elapsedSince(startedAt: number): number {
|
57 | 57 | |
58 | 58 | export function safeChromeCdpErrorMessage(error: unknown): string { |
59 | 59 | const message = error instanceof Error ? error.message : String(error); |
| 60 | +const cause = error instanceof Error ? error.cause : undefined; |
| 61 | +const causeMessage = |
| 62 | +cause instanceof Error ? cause.message : typeof cause === "string" ? cause : undefined; |
| 63 | +if (message && causeMessage && !message.includes(causeMessage)) { |
| 64 | +return redactSensitiveText(`${message}: ${causeMessage}`); |
| 65 | +} |
60 | 66 | return redactSensitiveText(message || "unknown error"); |
61 | 67 | } |
62 | 68 | |
@@ -247,7 +253,15 @@ export function formatChromeCdpDiagnostic(diagnostic: ChromeCdpDiagnostic): stri
|
247 | 253 | return `CDP diagnostic: ready after ${diagnostic.elapsedMs}ms; cdp=${redactedCdpUrl}; websocket=${redactedWsUrl}.${browser}`; |
248 | 254 | } |
249 | 255 | const websocket = redactedWsUrl ? `; websocket=${redactedWsUrl}` : ""; |
250 | | -return `CDP diagnostic: ${diagnostic.code} after ${diagnostic.elapsedMs}ms; cdp=${redactedCdpUrl}${websocket}; ${diagnostic.message}.`; |
| 256 | +const wslPortproxyHint = |
| 257 | +diagnostic.code === "http_unreachable" && isLikelyEmptyHttpReply(diagnostic.message) |
| 258 | + ? " In WSL2-to-Windows Chrome setups, this can be a stale netsh portproxy self-loop where svchost/iphlpsvc owns the CDP port instead of chrome.exe; verify with tasklist /svc and curl /json/version, then remove any 127.0.0.1:9222 -> 127.0.0.1:9222 portproxy rule." |
| 259 | + : ""; |
| 260 | +return `CDP diagnostic: ${diagnostic.code} after ${diagnostic.elapsedMs}ms; cdp=${redactedCdpUrl}${websocket}; ${diagnostic.message}.${wslPortproxyHint}`; |
| 261 | +} |
| 262 | + |
| 263 | +function isLikelyEmptyHttpReply(message: string): boolean { |
| 264 | +return /empty reply|other side closed|socket closed|terminated before response/i.test(message); |
251 | 265 | } |
252 | 266 | |
253 | 267 | export async function diagnoseChromeCdp( |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -633,6 +633,19 @@ describe("browser chrome helpers", () => {
|
633 | 633 | expect(formatted).not.toContain("supersecret123"); |
634 | 634 | }); |
635 | 635 | |
| 636 | +it("adds a WSL2 portproxy hint for empty HTTP CDP replies", () => { |
| 637 | +const formatted = formatChromeCdpDiagnostic({ |
| 638 | +ok: false, |
| 639 | +code: "http_unreachable", |
| 640 | +cdpUrl: "http://172.30.144.1:9222", |
| 641 | +message: "fetch failed: other side closed", |
| 642 | +elapsedMs: 12, |
| 643 | +}); |
| 644 | + |
| 645 | +expect(formatted).toContain("svchost/iphlpsvc owns the CDP port"); |
| 646 | +expect(formatted).toContain("127.0.0.1:9222 -> 127.0.0.1:9222"); |
| 647 | +}); |
| 648 | + |
636 | 649 | it("probes direct ws:// CDP URLs (with /devtools/ path) via handshake instead of HTTP", async () => { |
637 | 650 | // A direct WS endpoint like ws://host/devtools/browser/<uuid> is already |
638 | 651 | // the handshake target — isChromeReachable must NOT hit /json/version. |
|
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。