fix(bots): apply the configured network proxy to Client-owned bot traffic - #5159
Draft
ying-hua wants to merge 1 commit into
Draft
fix(bots): apply the configured network proxy to Client-owned bot traffic#5159ying-hua wants to merge 1 commit into
ying-hua wants to merge 1 commit into
Conversation
…ffic `setActiveProxy` had no production caller, so `resolveActiveProxy()` always returned null and the bot bridges' `proxiedFetch` never built a proxy dispatcher. Every bot request went direct whatever Network settings said, which on a blocked network surfaces as the `Fetch timeout` in apache#5091. Model execution is unaffected because it resolves the proxy inside the Host and injects a transport per connection. The bot bridges cannot: `BotRegistry` is constructed in the Client process, and the resolved proxy — including its credential — only exists Host-side. Add `network-proxy.resolve` so the Host can serve that resolved proxy, and apply it in the Client at Host registration and whenever a settings patch writes the proxy policy. A non-local Host describes a different machine's network, so its policy is never adopted; the Client stays direct instead. Refs apache#5091 Generated-by: Claude Code
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
setActiveProxyhad no production caller anywhere in the repository, soresolveActiveProxy()always returnednulland the bot bridges'proxiedFetchnever built a proxy dispatcher. Every bot request went direct whatever the Network settings said. On a blocked network that surfaces as theFetch timeoutin the report, and it explains why enabling TUN was the only thing that worked — TUN intercepts below the application, so it needs no cooperation from this seam.Model execution was never affected: it resolves the proxy inside the Host and injects a transport per connection. The bot bridges cannot do that.
BotRegistryis constructed in the Client process, the local Host is a separate spawned process, and the resolved proxy — including its credential — only exists Host-side. That is the actual gap; the protocol exposed onlynetwork-proxy.test.So this adds
network-proxy.resolve, served byHostNetworkProxyCoordinatorfrom the existingresolveNetworkProxyExecution()andtoRuntimePolicyProxy(), and applies the result in the Client at Host registration and whenever a settings patch writes the proxy policy.Two decisions worth flagging:
remoteorenvironmentHost describes the wrong network. Those profiles are not even asked — the Client stays direct rather than guessing.RUNTIME_HOST_COMPATIBILITY_EPOCHgoes to 141. Two builds can share an epoch and differ in operations, so without the bump a Client could reach an already-running older local Host that cannot answer the new operation — and a Client cannot tell that refusal apart from a proxy that is genuinely unset.The fix covers every bot platform, not just Telegram —
telegram,discord,qq,dingtalkandwechatbridges, credential verification inbot-test.ts, and the Desktop onboarding and QQ scan-login paths all shareproxiedFetch.Fixes #5091
Verification
Reproduced and verified on Windows 11 with Clash, TUN off and system proxy on at
127.0.0.1:7897.HTTP_PROXY/HTTPS_PROXYwere stripped from the process to match a normal desktop launch.Driving the real chain end to end — Host coordinator → protocol codec → applier →
setActiveProxy→ the bots'proxiedFetch→ a live request toapi.telegram.org:A is
maintoday, and its error string and 10s duration match the report. The middle line confirms the non-local gate holds. Only the local Host applies the proxy.Checks run locally:
npm run lint,npm run format:check,npm run check:asf-headers— cleannpm run typecheck— clean across all workspacesnpx knip— no new findingsnetwork-proxy-coordinatorandclient-network-proxysuites, plusruntime-host-settings-ipc-main,proxied-fetchandprotocolNot run: the full workspace suite and the Desktop E2E specs.
Two Runtime Host suites do not pass on this machine, and neither is evidence about this change:
handshake-compatibility.test.tsfails 4 of 6, identically on unmodifiedupstream/main(RuntimeHostTransportError: read_eof).host-kernel.test.tsis unstable here regardless of the change: unmodifiedupstream/mainfails 4 of 81, and the failing set differs between runs (write EPIPE,Runtime Host did not enter composition,shutdown did not cleanly close every resource). This branch failed 1–2 of 81 across runs — a subset of what cleanmainproduces — so I cannot attribute or exonerate individual tests here, only report that the suite is flaky on this machine before the change.framed-transport.test.tspasses 6 of 6. These look like the local Windows platform-fixture and cleanup problems tracked in #5059; someone on Linux or macOS should confirm both suites.Security
network-proxy.resolvesends the proxy credential from the Host to the Client. That is new, and SECURITY.md calls outproxiedFetchspecifically, so it deserves explicit review. The reasoning: a Client that runs its own outbound traffic cannot dial an authenticated proxy without the secret, and the alternative — a separate Client-side proxy setting — duplicates configuration the user has already entered. The failure path returns a fixed message rather than the underlying error, which can carry credential material, and there is a test for that.If you would rather keep the secret Host-side, the alternative is a dedicated Client-owned bot proxy setting (option 1 in the report). Happy to switch.
AI use
Select exactly one:
Tool(s) and scope: Claude Code — root-cause investigation, the implementation, and the tests, under my direction and review. Commits carry
Generated-by: Claude Code.Checklist
Does this PR entail a change in behavior?