Skip to content

fix(gateway): honor env proxy for relay aiohttp with WSL-safe fallback - #11762

Closed
shajiang919 wants to merge 2 commits into
NousResearch:mainfrom
shajiang919:master
Closed

fix(gateway): honor env proxy for relay aiohttp with WSL-safe fallback#11762
shajiang919 wants to merge 2 commits into
NousResearch:mainfrom
shajiang919:master

Conversation

@shajiang919

Copy link
Copy Markdown

Summary

Gateway proxy mode (_run_agent_via_proxy) now builds aiohttp.ClientSession with explicit outbound proxy behavior aligned with gateway/platforms/base.py (resolve_proxy_url / proxy_kwargs_for_aiohttp), trust_env where appropriate, and a tunable read timeout. After a transport-level failure, the relay retries once with a direct session (no env-derived proxy kwargs) unless disabled.

Motivation

On WSL/Windows, HTTP_PROXY / HTTPS_PROXY often points at a host-only forwarder. Relay calls to GATEWAY_PROXY_URL can mis-route, hang until read timeout, or fail with connection errors. This change makes outbound behavior explicit and adds a safe fallback path.

Changes

  • New gateway/outbound_proxy.py: env parsing for HERMES_PROXY_TIMEOUT_MULTIPLIER, HERMES_GATEWAY_OUTBOUND_NO_PROXY, HERMES_GATEWAY_RELAY_NO_DIRECT_FALLBACK, and relay_client_session_proxy_bundle().
  • gateway/run.py: relay uses scaled ClientTimeout, proxy bundle kwargs, and optional direct retry.
  • .env.example: document the new variables.
  • tests/gateway/test_proxy_flow.py: unit tests for multiplier, no-proxy bundle, and HTTPS proxy resolution.

How to verify

pytest tests/gateway/test_proxy_flow.py -q

- Add outbound_proxy helpers for trust_env, resolve_proxy_url kwargs, and
  HERMES_PROXY_TIMEOUT_MULTIPLIER on relay ClientTimeout sock_read.
- Retry once without env proxy after transport errors unless disabled.
- Document HERMES_GATEWAY_OUTBOUND_NO_PROXY and related env vars in .env.example.
- Add tests/gateway/test_proxy_flow.py unit coverage.

Made-with: Cursor
@mxnstrexgl

Copy link
Copy Markdown

🤖 Automated PR Review

Security Scan

  • ✓ No hardcoded secrets
  • ✓ No injection vectors
  • .env.example changes only touch example config (no real creds)

Code Quality

  • ✓ New gateway/outbound_proxy.py module — clean separation of proxy concerns
  • ✓ WSL detection utility is well-isolated
  • ✓ Timeout multiplier with validation (rejects invalid/non-positive)
  • ✓ Good test coverage (7 tests for the new module)
  • ✓ Retry logic: proxy first → direct fallback is solid for WSL edge cases
  • ⚠️ _DEFAULT_SOCK_READ_SEC = 1800.0 (30 min) — verify this is intentional; could mask hung connections in production
  • ⚠️ The retry loop in run.py re-creates the full SSE parsing logic — consider extracting to a shared helper if proxy retry becomes a pattern
  • ⚠️ for/else + break pattern in the retry loop is correct but dense — consider a comment explaining the intent

Summary

Status: APPROVE ✓ (with suggestions)
Solid proxy handling refactor. WSL edge cases properly addressed. Tests are thorough.

Made-with: Cursor

# Conflicts:
#	gateway/run.py
@teknium1

Copy link
Copy Markdown
Contributor

Thanks for the focused proxy-relay work and the accompanying tests. This automated hermes-sweeper review is closing it under the repository's configuration policy.

  • The PR introduces non-secret behavioral environment controls for relay timeout, proxy bypass, and retry behavior in gateway/outbound_proxy.py (commit b89443fa7096).
  • AGENTS.md:102-105 requires behavioral settings such as timeouts and feature flags to live in config.yaml; .env is reserved for credentials.
  • A follow-up can re-scope these controls as gateway configuration fields, while retaining standard proxy-environment discovery only where needed.

Closed as not-planned per standing maintainer policy (env-var-for-config). This is a design-direction decision, not a code-quality judgment — see the Contribution Rubric in AGENTS.md for what the project is looking for. If you believe this policy was misapplied to your change, comment here and a maintainer will take a look.

@teknium1 teknium1 closed this Jul 12, 2026
@teknium1 teknium1 added the sweeper:not-planned Sweeper: closed per standing maintainer policy (design direction) label Jul 12, 2026
djbclark added a commit to djbclark/hermes-agent that referenced this pull request Aug 11, 2026
… into replayed tool_calls

Root cause for NousResearch#83714 (write_file/patch_tool writing literal
"...[truncated]" into files, PR NousResearch#83752's guard is the safety net, not
the fix): _truncate_tool_call_args_json() in the compression pass
shrinks long string values inside a PAST assistant message's
tool_calls[].function.arguments — the exact field that represents the
model's own prior generated output, replayed back to it verbatim on
every subsequent turn. The old marker, a bare "...[truncated]" suffix,
is indistinguishable from something the model itself could have
written (it's exactly the kind of terse ellipsis abbreviation models
already produce). A model conditioned on seeing itself "get away with"
that pattern in its own history imitates it in a new tool call,
writing the literal marker instead of real content.

This is the second bug from the same root text. The first (NousResearch#11762,
MiniMax 400s from unterminated JSON) was fixed by shrinking inside the
parsed structure so the JSON stays valid, but kept the same visible
marker text — fixing the syntax problem while leaving the imitation
problem untouched.

Fix: replace the marker with one deliberately NOT shaped like prose a
model would write — distinctive non-ASCII delimiters, an explicit "not
part of the original tool call" disclaimer, and a per-instance
char-count that won't match the next omission point even if copied
verbatim. The shrunk value stays a plain string (not a nested object)
so the NousResearch#11762 valid-JSON/matching-shape contract is unchanged — only
the marker text changed.

Checked context_compressor.py's other "...[truncated]" call sites
(_serialize_for_summary, _compact_fallback_turn, the user-message-only
one near _ACTIVE_TASK_MAX_CHARS) — none of them write into a value
that gets replayed as the main model's own assistant/tool_calls
history, so they don't share this priming risk and were left as-is.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/config Config system, migrations, profiles comp/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists sweeper:not-planned Sweeper: closed per standing maintainer policy (design direction) type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants