Skip to content

fix(messaging): restore per-account Discord proxy for gateway WebSocket#5081

Closed
latenighthackathon wants to merge 1 commit into
NVIDIA:mainfrom
latenighthackathon:fix/discord-gateway-account-proxy
Closed

fix(messaging): restore per-account Discord proxy for gateway WebSocket#5081
latenighthackathon wants to merge 1 commit into
NVIDIA:mainfrom
latenighthackathon:fix/discord-gateway-account-proxy

Conversation

@latenighthackathon

@latenighthackathon latenighthackathon commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Summary

A sandbox onboarded with the Discord channel comes up degraded: the bot sends via the Discord REST API but never establishes the Discord Gateway WebSocket, so it receives zero inbound MESSAGE_CREATE / mention events. This is the same symptom as #3894.

The Discord gateway client honors only the per-account proxy (channels.discord.accounts.default.proxy), not the managed env proxy. In extensions/discord/src/monitor/gateway-plugin.ts, the gateway socket is opened with the classic ws transport and an explicit agent that tunnels through the proxy only when the per-account value is set; otherwise it falls back to a direct-DNS https.Agent, which has no resolver to answer in a proxy-only sandbox (EAI_AGAIN). This is unchanged across OpenClaw 2026.5.18, 2026.5.27, and 2026.6.1, so a version bump does not address it.

#3935 set the per-account Discord proxy to fix #3894. The config-generator port in #4277 narrowed the per-account proxy assignment to Telegram only, relying on the top-level managed proxy (applied via HTTP(S)_PROXY env injection) to cover Discord. The gateway client does not read those env vars, so dropping the per-account proxy re-regressed #3894.

This restores Discord to the per-account proxy assignment, mirroring Telegram.

Related Issue

Closes #5075 (re-regression of #3894).

Changes

  • scripts/generate-openclaw-config.mts: set account.proxy = proxyUrl for Discord as well as Telegram, so the generated channels.discord.accounts.default.proxy routes the gateway client through the sandbox proxy. Telegram keeps its groupPolicy: "open".
  • test/generate-openclaw-config.test.ts: update the Discord proxy expectations (previously asserted absent) to expect the per-account proxy, and rename the affected cases.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)

Verification

  • npx vitest run --project cli test/generate-openclaw-config.test.ts — 133/133 pass
  • npm run typecheck:cli — clean

Signed-off-by: latenighthackathon latenighthackathon@users.noreply.github.com

Summary by CodeRabbit

  • Bug Fixes

    • Discord now consistently uses per-account proxy settings, matching Telegram behavior and avoiding missed proxy assignments.
    • Fixed regression where Discord account proxy wasn’t written alongside managed/global proxy settings.
  • Tests

    • Improved test coverage to validate per-account proxy routing and the regression fix across proxy scenarios.

@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 01396c11-6379-4257-94d2-90700c6737f5

📥 Commits

Reviewing files that changed from the base of the PR and between ad3a1d7 and 5cf4bd9.

📒 Files selected for processing (2)
  • scripts/generate-openclaw-config.mts
  • test/generate-openclaw-config.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • scripts/generate-openclaw-config.mts
  • test/generate-openclaw-config.test.ts

📝 Walkthrough

Walkthrough

The PR restores per-account proxy assignment for Discord in the OpenClaw config generator (matching Telegram) and updates tests to assert the Discord account proxy is written in managed, per-account, deferred, loopback, and combined routing scenarios.

Changes

Discord Gateway Proxy Configuration

Layer / File(s) Summary
Config generator per-account proxy assignment
scripts/generate-openclaw-config.mts
Per-account proxy assignment now applies account.proxy = proxyUrl to both telegram and discord accounts. Comments added clarifying that the Discord gateway client and Telegram long-poll client honor only per-account proxy configuration.
Test updates and assertions for Discord account proxy
test/generate-openclaw-config.test.ts
Vitest imports adjusted; tests updated to expect config.channels.discord.accounts.default.proxy is set to the managed proxy URL for canonical routing, set to per-account proxy when provided, written alongside the managed proxy in a regression test, preserved when managed proxy is deferred, ignores loopback env var, and matches per-account proxy in the Telegram+Discord scenario.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

area: networking, area: sandbox, integration: openclaw, bug-fix

Suggested reviewers

  • cv

Poem

🐰 A little rabbit hops on code so bright,
It nudges proxies back into the light.
Discord's gateway opens, webs hum clear,
Bots hear the whispers they were meant to hear.
Hooray — connections hop, and all is right!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: restoring per-account Discord proxy configuration for the gateway WebSocket connection.
Linked Issues check ✅ Passed The PR directly addresses the coding requirements from both #3894 and #5075: restores per-account proxy assignment for Discord in generate-openclaw-config.mts and updates corresponding tests.
Out of Scope Changes check ✅ Passed All changes are directly scoped to the linked issue requirements: modifications to proxy configuration and test expectations for Discord, with no unrelated alterations.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

The Discord gateway client honors only the per-account proxy, not the
managed env proxy, so without channels.discord.accounts.default.proxy it
resolves gateway.discord.gg via direct DNS and fails with EAI_AGAIN in a
proxy-only sandbox, leaving the inbound half of Discord black-holed.

NVIDIA#3935 set this proxy to fix NVIDIA#3894. The config-generator port in NVIDIA#4277
narrowed the per-account proxy assignment to Telegram only, relying on
the top-level managed proxy to cover Discord. The managed proxy is applied
via HTTP(S)_PROXY env injection, but the gateway client builds its own ws
agent and tunnels only when the per-account proxy is set (verified in
OpenClaw 2026.5.18, 2026.5.27, and 2026.6.1), so the change re-regressed
NVIDIA#3894.

Restore Discord to the per-account proxy assignment, mirroring Telegram,
and update the generator tests accordingly.

Closes NVIDIA#5075

Signed-off-by: latenighthackathon <latenighthackathon@users.noreply.github.com>
@latenighthackathon latenighthackathon force-pushed the fix/discord-gateway-account-proxy branch from ad3a1d7 to 5cf4bd9 Compare June 9, 2026 20:27
@wscurran wscurran added area: messaging Messaging channels, bridges, manifests, or channel lifecycle area: networking DNS, proxy, TLS, ports, host aliases, or connectivity area: sandbox OpenShell sandbox lifecycle, runtime, config, or recovery bug-fix PR fixes a bug or regression integration: discord Discord integration or channel behavior labels Jun 9, 2026
@wscurran

wscurran commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

✨ Thanks for submitting this PR restoring the per-account Discord proxy for the gateway WebSocket. This proposes a way to fix the regression where the Discord bot sends via REST API but never establishes the Gateway WebSocket connection in proxy-only sandboxes.


Related open PRs:


Related open issues:

@latenighthackathon latenighthackathon removed their assignment Jun 10, 2026
@prekshivyas prekshivyas self-assigned this Jun 10, 2026

@prekshivyas prekshivyas left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed (code + security checklist). Re-adds account.proxy for the Discord channel (alongside Telegram) in the config generator so channels.discord.accounts.default.proxy is emitted again and the gateway WebSocket routes through the sandbox proxy; updates 6 test cases. Re-fix of the #3894#4277 regression.

Approve. Verified against source:

  • On main only telegram received account.proxy; this widens the condition to telegram || discord while keeping groupPolicy:"open" Telegram-only — confirmed at main vs. head. No change for Slack/WhatsApp.
  • The per-account proxy reuses the same managed sandbox egress proxyUrl (http://${NEMOCLAW_PROXY_HOST||10.200.0.1}:${PORT||3128}) that feeds config.proxy — no new/attacker-controllable destination, so no new SSRF surface; traffic stays on the existing egress path.
  • The 6 flipped test assertions are consistent (incl. the loopback-decoy case correctly still expecting the default).

Security: all 9 pass — no token/credential in the proxy value, no logging change.

One caveat (couldn't verify here): the load-bearing assumption is that OpenClaw's Discord gateway plugin honors the per-account proxy for the WebSocket (and ignores HTTP_PROXY for it). That code is in the external OpenClaw package, not in this repo, so I couldn't confirm it from source — it rests on the e2e rationale from #3935/#5075. Worth confirming the gateway-connect e2e (socket connects, MESSAGE_CREATE received) in CI/staging before relying on it. Approving on the config-generator change, which is correct and well-tested.

Nit: the import reordering in the test file is unrelated noise (harmless).

@prekshivyas prekshivyas added the v0.0.64 Release target label Jun 11, 2026
@latenighthackathon

Copy link
Copy Markdown
Contributor Author

Closing this in favor of a fresh PR: an upstream refactor moved channel-config generation out of scripts/generate-openclaw-config.mts (which this PR edits) into the manifest + template-resolver path, so this diff no longer applies.

The underlying bug (#5075) is still present, just relocated: src/lib/messaging/channels/discord/template-resolver.ts resolves discordProxyUrl to undefined, while telegram's resolver resolves proxyUrl to the real proxy. So channels.discord.accounts.default.proxy is still unset and the gateway WebSocket still can't egress the sandbox proxy. A new PR fixes it at the template-resolver. Cheers!

cv added a commit that referenced this pull request Jun 13, 2026
…WebSocket connects (#5248)

## Summary

A sandbox with the Discord channel comes up degraded: the bot sends via
the Discord REST API but never establishes the gateway WebSocket, so it
receives zero inbound events. This is the regression tracked in #5075
(originally #3894).

`channels.discord.accounts.default.proxy` is rendered from the
`{{discordProxyUrl}}` template, but
`src/lib/messaging/channels/discord/template-resolver.ts` resolved that
reference to `undefined`, so the Discord account was emitted with no
proxy. The Discord gateway client honors only the per-account proxy (it
ignores the managed env proxy), so the gateway WebSocket cannot egress
the deny-by-default sandbox network namespace.

Telegram's resolver already resolves its `proxyUrl` to the sandbox
proxy; Discord was the lone gap.

## Related Issue

Closes #5075.

> Note: an earlier PR (#5081) fixed this in
`scripts/generate-openclaw-config.mts`, but channel-config generation
has since moved to the manifest + template-resolver path, so that fix
site no longer exists. This re-targets the same bug at the current site.

## Changes

- `src/lib/messaging/channels/discord/template-resolver.ts`: resolve
`discordProxyUrl` to the sandbox proxy URL
(`NEMOCLAW_PROXY_HOST`/`NEMOCLAW_PROXY_PORT`, default
`http://10.200.0.1:3128`) instead of `undefined`, mirroring the telegram
resolver.
- `test/discord-template-resolver-proxy.test.ts`: assert
`discordProxyUrl` resolves to the default proxy and honors host/port
overrides.

## Type of Change

- [x] Bug fix (non-breaking change which fixes an issue)

## Verification

- `npx vitest run --project cli
test/discord-template-resolver-proxy.test.ts
test/messaging-build-applier.test.ts` — 18/18 pass
- `npm run typecheck:cli` and `npm run build:cli` — clean

Signed-off-by: latenighthackathon
<latenighthackathon@users.noreply.github.com>


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Discord messaging now consistently resolves a proxy URL, using
configured host/port or sensible defaults.

* **Bug Fixes**
* Fixed case where Discord proxy URL could be missing; now reliably
populated.

* **Tests**
* Added and updated tests to validate Discord proxy URL resolution for
default and custom proxy configurations.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Signed-off-by: latenighthackathon <latenighthackathon@users.noreply.github.com>
Co-authored-by: latenighthackathon <latenighthackathon@users.noreply.github.com>
Co-authored-by: Carlos Villela <cvillela@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: messaging Messaging channels, bridges, manifests, or channel lifecycle area: networking DNS, proxy, TLS, ports, host aliases, or connectivity area: sandbox OpenShell sandbox lifecycle, runtime, config, or recovery bug-fix PR fixes a bug or regression integration: discord Discord integration or channel behavior v0.0.64 Release target

Projects

None yet

3 participants