From f50fb735604e7eb3b291c5f140d9aa4953493cd9 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 27 Apr 2026 11:30:20 +0100 Subject: [PATCH] fix(whatsapp): honor env proxy during QR login --- CHANGELOG.md | 1 + docs/channels/troubleshooting.md | 11 ++++---- docs/channels/whatsapp.md | 7 +++++ extensions/whatsapp/package.json | 1 + extensions/whatsapp/src/session.test.ts | 27 +++++++++++++++++++ extensions/whatsapp/src/session.ts | 36 ++++++++++++++++--------- pnpm-lock.yaml | 3 +++ 7 files changed, 69 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae15b4601c8..6832703579f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ Docs: https://docs.openclaw.ai ### Fixes - Channels/setup: treat bundled channel plugins as already bundled during `channels add` and onboarding, enabling them without writing redundant `plugins.load.paths` entries or path install records. Fixes #72740. Thanks @iCodePoet. +- WhatsApp: honor gateway `HTTPS_PROXY` / `HTTP_PROXY` env vars for QR-login WebSocket connections, while respecting `NO_PROXY`, so proxied networks no longer fall back to direct `mmg.whatsapp.net` connections that time out with 408. Fixes #72547; supersedes #72692. Thanks @mebusw and @SymbolStar. - Agents/OpenAI-compatible: retry replay-safe empty `stop` turns once for `openai-completions` endpoints, so transient empty local backend responses no longer surface as “Agent couldn't generate a response” when a continuation succeeds. Fixes #72751. Thanks @moooV252. - Git hooks: skip ignored staged paths when formatting and restaging pre-commit files, so merge commits no longer abort when `.gitignore` newly ignores staged merged content. Fixes #72744. Thanks @100yenadmin. - Memory-core/dreaming: add a supported `dreaming.model` knob for Dream Diary narrative subagents, wired through phase config and the existing plugin subagent model-override trust gate. Refs #65963. Thanks @esqandil and @mjamiv. diff --git a/docs/channels/troubleshooting.md b/docs/channels/troubleshooting.md index 653cfc81c0b..fffe943c47c 100644 --- a/docs/channels/troubleshooting.md +++ b/docs/channels/troubleshooting.md @@ -31,11 +31,12 @@ Healthy baseline: ### WhatsApp failure signatures -| Symptom | Fastest check | Fix | -| ------------------------------- | --------------------------------------------------- | ------------------------------------------------------- | -| Connected but no DM replies | `openclaw pairing list whatsapp` | Approve sender or switch DM policy/allowlist. | -| Group messages ignored | Check `requireMention` + mention patterns in config | Mention the bot or relax mention policy for that group. | -| Random disconnect/relogin loops | `openclaw channels status --probe` + logs | Re-login and verify credentials directory is healthy. | +| Symptom | Fastest check | Fix | +| ------------------------------- | --------------------------------------------------- | -------------------------------------------------------- | +| Connected but no DM replies | `openclaw pairing list whatsapp` | Approve sender or switch DM policy/allowlist. | +| Group messages ignored | Check `requireMention` + mention patterns in config | Mention the bot or relax mention policy for that group. | +| QR login times out with 408 | Check gateway `HTTPS_PROXY` / `HTTP_PROXY` env | Set a reachable proxy; use `NO_PROXY` only for bypasses. | +| Random disconnect/relogin loops | `openclaw channels status --probe` + logs | Re-login and verify credentials directory is healthy. | Full troubleshooting: [WhatsApp troubleshooting](/channels/whatsapp#troubleshooting) diff --git a/docs/channels/whatsapp.md b/docs/channels/whatsapp.md index ae3bfe97d10..7cc59d248d3 100644 --- a/docs/channels/whatsapp.md +++ b/docs/channels/whatsapp.md @@ -526,6 +526,13 @@ Behavior notes: + + Symptom: `openclaw channels login --channel whatsapp` fails before showing a usable QR code with `status=408 Request Time-out` or a TLS socket disconnect. + + WhatsApp Web login uses the gateway host's standard proxy environment (`HTTPS_PROXY`, `HTTP_PROXY`, lowercase variants, and `NO_PROXY`). Verify the gateway process inherits the proxy env and that `NO_PROXY` does not match `mmg.whatsapp.net`. + + + Outbound sends fail fast when no active gateway listener exists for the target account. diff --git a/extensions/whatsapp/package.json b/extensions/whatsapp/package.json index ec14e62f3e8..22422cf2b6d 100644 --- a/extensions/whatsapp/package.json +++ b/extensions/whatsapp/package.json @@ -5,6 +5,7 @@ "type": "module", "dependencies": { "@whiskeysockets/baileys": "7.0.0-rc.9", + "https-proxy-agent": "^9.0.0", "jimp": "^1.6.1", "typebox": "1.1.33", "undici": "8.1.0" diff --git a/extensions/whatsapp/src/session.test.ts b/extensions/whatsapp/src/session.test.ts index be3d70dfc41..d6b0e50af58 100644 --- a/extensions/whatsapp/src/session.test.ts +++ b/extensions/whatsapp/src/session.test.ts @@ -204,6 +204,33 @@ describe("web session", () => { ); }); + it("uses lowercase HTTPS proxy before uppercase for WA WebSocket connection", async () => { + vi.stubEnv("HTTPS_PROXY", "http://upper-proxy.test:8080"); + vi.stubEnv("https_proxy", "http://lower-proxy.test:8080"); + + await createWaSocket(false, false); + + const passed = (baileys.makeWASocket as ReturnType).mock.calls[0]?.[0] as { + agent?: { proxy?: URL }; + }; + expect(passed.agent).toBeDefined(); + expect(passed.agent?.proxy?.href).toContain("lower-proxy.test"); + }); + + it("skips WA WebSocket env proxy agent when NO_PROXY covers WhatsApp Web", async () => { + vi.stubEnv("HTTPS_PROXY", "http://proxy.test:8080"); + vi.stubEnv("NO_PROXY", "mmg.whatsapp.net"); + + await createWaSocket(false, false); + + const passed = (baileys.makeWASocket as ReturnType).mock.calls[0]?.[0] as { + agent?: unknown; + fetchAgent?: unknown; + }; + expect(passed.agent).toBeUndefined(); + expect(passed.fetchAgent).toBeDefined(); + }); + it("does not create a proxy agent when no env proxy is configured", async () => { for (const key of [ "ALL_PROXY", diff --git a/extensions/whatsapp/src/session.ts b/extensions/whatsapp/src/session.ts index 3fea5bab278..bee5f91521e 100644 --- a/extensions/whatsapp/src/session.ts +++ b/extensions/whatsapp/src/session.ts @@ -1,9 +1,13 @@ import { randomUUID } from "node:crypto"; import fsSync from "node:fs"; import type { Agent } from "node:https"; +import { HttpsProxyAgent } from "https-proxy-agent"; import { formatCliCommand } from "openclaw/plugin-sdk/cli-runtime"; import { VERSION } from "openclaw/plugin-sdk/cli-runtime"; -import { resolveAmbientNodeProxyAgent } from "openclaw/plugin-sdk/extension-shared"; +import { + resolveEnvHttpProxyUrl, + shouldUseEnvHttpProxyForUrl, +} from "openclaw/plugin-sdk/infra-runtime"; import { danger, success } from "openclaw/plugin-sdk/runtime-env"; import { getChildLogger, toPinoLikeLogger } from "openclaw/plugin-sdk/runtime-env"; import { ensureDir, resolveUserPath } from "openclaw/plugin-sdk/text-runtime"; @@ -58,6 +62,7 @@ export { export type { CredsQueueWaitResult } from "./creds-persistence.js"; const LOGGED_OUT_STATUS = DisconnectReason?.loggedOut ?? 401; +const WHATSAPP_WEBSOCKET_PROXY_TARGET = "https://mmg.whatsapp.net/"; const CREDS_FLUSH_TIMEOUT_MESSAGE = "Queued WhatsApp creds save did not finish before auth bootstrap; skipping repair and continuing with primary creds."; @@ -210,17 +215,24 @@ export async function createWaSocket( async function resolveEnvProxyAgent( logger: ReturnType, ): Promise { - return resolveAmbientNodeProxyAgent({ - onError: (err) => { - logger.warn( - { error: String(err) }, - "Failed to initialize env proxy agent for WhatsApp WebSocket connection", - ); - }, - onUsingProxy: () => { - logger.info("Using ambient env proxy for WhatsApp WebSocket connection"); - }, - }); + if (!shouldUseEnvHttpProxyForUrl(WHATSAPP_WEBSOCKET_PROXY_TARGET)) { + return undefined; + } + const proxyUrl = resolveEnvHttpProxyUrl("https"); + if (!proxyUrl) { + return undefined; + } + try { + const agent = new HttpsProxyAgent(proxyUrl) as Agent; + logger.info("Using ambient env proxy for WhatsApp WebSocket connection"); + return agent; + } catch (error) { + logger.warn( + { error: String(error) }, + "Failed to initialize env proxy agent for WhatsApp WebSocket connection", + ); + return undefined; + } } async function resolveEnvFetchDispatcher( diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2489a300f0a..b8d5e777002 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1446,6 +1446,9 @@ importers: '@whiskeysockets/baileys': specifier: 7.0.0-rc.9 version: 7.0.0-rc.9(patch_hash=23ec8efe1484afa57c51b96955ba331d1467521a8e676a18c2690da7e70a6201)(audio-decode@2.2.3)(jimp@1.6.1)(sharp@0.34.5) + https-proxy-agent: + specifier: ^9.0.0 + version: 9.0.0 jimp: specifier: ^1.6.1 version: 1.6.1