Skip to content

feat(ai-provider): route provider HTTP through proxy-aware net.fetch#16207

Open
DeJeune wants to merge 1 commit into
mainfrom
DeJeune/ai-customfetch-proxy
Open

feat(ai-provider): route provider HTTP through proxy-aware net.fetch#16207
DeJeune wants to merge 1 commit into
mainfrom
DeJeune/ai-customfetch-proxy

Conversation

@DeJeune

@DeJeune DeJeune commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator

What this PR does

Before this PR:

  • AI provider HTTP requests ran on Node's globalThis.fetch (undici). The app proxy reached them only through the undici global-dispatcher patch in NodeProxyController, and provider-specific fetch wrappers (e.g. CherryAI request signing) called the global fetch directly.

After this PR:

  • A composable customFetch built on Electron net.fetch is added and installed as the default base fetch for every provider config in providerToAiSdkConfig (settings.fetch ??= customFetch). net.fetch runs on Chromium's network stack, so requests honour the app proxy configured by ProxyManager via session.setProxy() / app.setProxy().
  • Provider-specific wrappers compose on top of customFetch instead of being replaced: the CherryAI signing wrapper now calls customFetch, and the dev-mode HTTP-trace wrapper layers above it — the proxy-aware net.fetch stays the innermost network call in every case.

N/A

Why we need it and why it was done in this way

Routing AI provider traffic through net.fetch makes the configured app proxy apply on Chromium's network stack (PAC / SOCKS / auth handled natively, consistent with the rest of the app's net.fetch usage), rather than depending solely on the symbol-based undici dispatcher patch.

The following tradeoffs were made:

  • customFetch is the innermost base; higher layers (provider signing, HTTP trace) wrap it. Installed via ??= so a provider that ships its own fetch wrapper is preserved, not clobbered.

The following alternatives were considered:

  • Relying only on the undici global-dispatcher patch — fragile (depends on internal undici symbols) and not consistent with the app's session proxy.
  • Unconditionally setting providerSettings.fetch = customFetch — would clobber provider wrappers such as CherryAI request signing.

Links to places where the discussion took place: N/A

Breaking changes

None.

Special notes for your reviewer

The custom image transports (dmxapi / ppio / ovms) that call bare fetch(...) directly are intentionally out of scope — they still proxy via the undici dispatcher patch. This PR unifies the provider-config fetch path only.

Checklist

This checklist is not enforcing, but it's a reminder of items that could be relevant to every PR.
Approvers are expected to review this list.

  • Branch: This PR targets the correct branch — main for active development, v1 for v1 maintenance fixes
  • PR: The PR description is expressive enough and will help future contributors
  • Code: Write code that humans can understand and Keep it simple
  • Refactor: You have left the code cleaner than you found it (Boy Scout Rule)
  • Upgrade: Impact of this change on upgrade flows was considered and addressed if required
  • Documentation: A user-guide update was considered and is present (link) or not required. Check this only when the PR introduces or changes a user-facing feature or behavior.
  • Self-review: I have reviewed my own code (e.g., via /gh-pr-review, gh pr diff, or GitHub UI) before requesting review from others

Release note

AI provider requests now route through Electron net.fetch so the configured app proxy (system/custom, including SOCKS) reliably applies to model traffic.

Add a composable `customFetch` (Electron `net.fetch`) and install it as the
default base fetch in `providerToAiSdkConfig`. `net.fetch` runs on Chromium's
network stack, so it honours the app proxy configured by ProxyManager via
session.setProxy()/app.setProxy() — unlike Node's globalThis.fetch (undici).

`settings.fetch ??= customFetch` preserves provider-specific fetch wrappers:
the CherryAI request-signing wrapper now composes onto customFetch instead of
the global fetch, and the HTTP-trace wrapper layers on top — keeping the proxy
as the innermost network call in every case.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: suyao <sy20010504@gmail.com>
@DeJeune DeJeune requested review from a team and EurFelux June 19, 2026 04:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant