Skip to content

fix: enable proxy support to resolve#1125

Merged
a7m-1st merged 8 commits intoeigent-ai:mainfrom
bittoby:fix/download-proxy-support
Feb 11, 2026
Merged

fix: enable proxy support to resolve#1125
a7m-1st merged 8 commits intoeigent-ai:mainfrom
bittoby:fix/download-proxy-support

Conversation

@bittoby
Copy link
Contributor

@bittoby bittoby commented Feb 2, 2026

Closes: #1092

Description

Add HTTP/HTTPS proxy support for dependency installation scripts to resolve download failures in proxy-required network environments.

Problem: When users have HTTP_PROXY/HTTPS_PROXY environment variables configured, the dependency download scripts (install-uv.js, install-bun.js) fail with the error:

"Client network socket disconnected before secure TLS connection was established"

Root Cause: resources/scripts/download.js used Node.js native https.get() directly without proxy support, which ignores system proxy settings.

Solution:

  • Add getProxyUrl() function to read proxy from environment variables (HTTP_PROXY, HTTPS_PROXY, and lowercase variants)
  • Implement HTTPS CONNECT tunnel method for secure connections through HTTP proxy
  • Add NO_PROXY support to bypass proxy for specific hosts
  • Pass proxy configuration from ~/.eigent/.env to child processes via runInstallScript()

Changes:

  • resources/scripts/download.js: Rewrote with full proxy support using CONNECT tunnel + TLS
  • electron/main/utils/process.ts: Pass proxy env vars to install script child processes

What is the purpose of this pull request?

  • Bug fix
  • New Feature
  • Documentation update
  • Other

@bittoby
Copy link
Contributor Author

bittoby commented Feb 2, 2026

@Wendong-Fan @a7m-1st Could you please review this PR? Thank you for your time.

@bittoby
Copy link
Contributor Author

bittoby commented Feb 5, 2026

Sorry for tagging again. @Wendong-Fan @4pmtong would you please review this PR? thank you

@Wendong-Fan Wendong-Fan added this to the Sprint 13 milestone Feb 5, 2026
Copy link
Collaborator

@Zephyroam Zephyroam left a comment

Choose a reason for hiding this comment

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

Thank you!

* @param {(response: http.IncomingMessage) => void} callback - Response callback
* @param {(error: Error) => void} onError - Error callback
*/
function makeRequest(url, callback, onError) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please remember to .destroy or .end all connections, e.g., connectReq, tlsSocket, req.

* if a proxy is configured, or an empty object if not.
*/
function getProxyEnvVars(): Record<string, string> {
const proxyUrl = readGlobalEnvKey('HTTP_PROXY');
Copy link
Collaborator

Choose a reason for hiding this comment

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

If the user sets different proxies for HTTP and HTTPS?

console.log(`Using proxy: ${maskProxyUrl(proxyUrl)}`);

const proxy = new URL(proxyUrl);
const proxyPort = parseInt(proxy.port, 10) || 80;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Default port for http is 80, but the port for https is 443.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the feedback! @Zephyroam
The proxyPort variable is for the proxy server itself, not the target website.
Most HTTP proxy servers listen on port 80. Even when you're downloading HTTPS content, you connect to the proxy via HTTP first, then the proxy establishes the secure tunnel to the HTTPS target.
The default 80 is for connecting to the proxy server, and 443 is already handled separately for HTTPS targets.

Actually, the code does handle HTTPS default port correctly. Look at line 108:
const targetPort = parseInt(targetUrl.port, 10) || (isHttps ? 443 : 80);

So we have:
proxyPort = 80 (default) - for the proxy server connection
targetPort = 443 (default for HTTPS) or 80 (default for HTTP) - for the target website
The code is working as intended!

@bittoby
Copy link
Contributor Author

bittoby commented Feb 6, 2026

@Zephyroam I updated according to your feedback. please review again, thanks

@bittoby bittoby requested a review from Zephyroam February 6, 2026 20:10
@Wendong-Fan Wendong-Fan modified the milestones: Sprint 13, Sprint 14 Feb 8, 2026
@bittoby
Copy link
Contributor Author

bittoby commented Feb 9, 2026

@Zephyroam @Wendong-Fan Sorry for tagging you again. It would appreciate to merge this PR

Copy link
Collaborator

@Zephyroam Zephyroam left a comment

Choose a reason for hiding this comment

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

LGTM. Thanks!

@a7m-1st a7m-1st mentioned this pull request Feb 10, 2026
4 tasks
Copy link
Collaborator

@a7m-1st a7m-1st left a comment

Choose a reason for hiding this comment

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

Apologies @bittoby that I couldn't review earlier. This PR lgtm, just some in consistencies regarding previous PR.

Lastly just a small question, currently can config only via ~.eigent/.env, how about inline or via .env.development?:

SET HTTP_PROXY=http://127.0.0.1:7890
SET HTTPS_PROXY=http://127.0.0.1:7890
C:\Users\cloud\AppData\Local\Programs\Eigent\Eigent.exe

P.S.:
We can support process.env.HTTP_PROXY for process envs, or readEnvValue for .env.development values

Comment on lines 44 to 45
const httpProxy = readGlobalEnvKey('HTTP_PROXY');
const httpsProxy = readGlobalEnvKey('HTTPS_PROXY');
Copy link
Collaborator

Choose a reason for hiding this comment

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

In PR #1096 , you were checking for HTTP_PROXY, shouldn't we also check for HTTPS_PROXY? Also missing the small letter variants you defined later

proxyUrl = readGlobalEnvKey('HTTP_PROXY');
if (proxyUrl) {
  log.info(`[PROXY] Applying proxy configuration: ${maskProxyUrl(proxyUrl)}`);
  app.commandLine.appendSwitch('proxy-server', proxyUrl);
} else {
  log.info('[PROXY] No proxy configured');
}

Comment on lines 51 to 69
const result: Record<string, string> = {};

if (httpProxy) {
result.HTTP_PROXY = httpProxy;
result.http_proxy = httpProxy;
log.info(
`[INSTALL SCRIPT] HTTP Proxy configured: ${maskProxyUrl(httpProxy)}`
);
}

if (httpsProxy) {
result.HTTPS_PROXY = httpsProxy;
result.https_proxy = httpsProxy;
log.info(
`[INSTALL SCRIPT] HTTPS Proxy configured: ${maskProxyUrl(httpsProxy)}`
);
}

return result;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Lastly I think we can simplify this logic drastically by returning:
{ HTTPS_PROXY: httpsProxy, HTTP_PROXY: httpProxy }

@bittoby
Copy link
Contributor Author

bittoby commented Feb 10, 2026

Thanks for your feedback! @a7m-1st I updated all according to your feedback. Please review again. Thanks

@Wendong-Fan Wendong-Fan requested a review from a7m-1st February 10, 2026 13:51
@a7m-1st
Copy link
Collaborator

a7m-1st commented Feb 10, 2026

Just pushed some changes:

  1. Simplified your implementation of readEnvValue as it's duplicate in init.ts
  2. Now HTTPS or HTTP proxy config is visible in the UI, not only HTTP
  3. Frontend reads from .env.username, .env and .env.development (on dev) and deletes from all if wants to remove. The main concerning change: I have updated the env-remove logic to not only remove in the mcp block, but also to remove any wanted key from .env.development
flowchart LR
    subgraph "Proxy Configuration Sources (Priority Order)"
        A1["1. Process Environment<br/>(HTTP_PROXY, HTTPS_PROXY)<br/>Highest Priority"]
        A2["2. .env.development<br/>(Development Mode Only)"]
        A3["3. ~/.eigent/.env<br/>(Global Config)<br/>Lowest Priority"]
    end

    subgraph "Application Startup"
        B1["App Launch"]
        B2["readEnvValueWithPriority()"]
        B3{"Proxy Found?"}
        B4["Apply to Electron<br/>app.commandLine.appendSwitch()"]
        B5["Set proxyUrl variable"]
    end

    subgraph "Proxy Write Operations (env-write)"
        C1["User Sets Proxy<br/>in Settings UI"]
        C2["Write to User .env<br/>~/.eigent/.env.{email}"]
        C3["Write to Global .env<br/>~/.eigent/.env"]
        C4["Write to .env.development<br/>(if exists)"]
    end

    subgraph "Proxy Remove Operations (env-remove)"
        D1["User Removes Proxy<br/>in Settings UI"]
        D2["Remove from User .env<br/>~/.eigent/.env.{email}"]
        D3["Remove from Global .env<br/>~/.eigent/.env"]
        D4["Remove from .env.development<br/>(anywhere in file)"]
    end

    subgraph "Proxy Usage"
        E1["Main Electron Process<br/>(WebContents)"]
        E2["Backend Python Process<br/>(reads global .env)"]
        E3["WebViews<br/>(inherit from main)"]
        E4["CDP Browser<br/>(separate profile)"]
    end

    A1 --> B2
    A2 --> B2
    A3 --> B2
    B1 --> B2
    B2 --> B3
    B3 -->|Yes| B4
    B3 -->|Yes| B5
    B4 --> E1
    B5 --> E2
    E1 --> E3
    E1 --> E4

    C1 --> C2
    C2 --> C3
    C3 --> C4

    D1 --> D2
    D2 --> D3
    D3 --> D4

    style A1 fill:#e1f5e1
    style A2 fill:#fff4e1
    style A3 fill:#ffe1e1
    style B4 fill:#d4e3fc
    style C1 fill:#ffd4e5
    style D1 fill:#ffdddd
Loading

@bittoby
Copy link
Contributor Author

bittoby commented Feb 10, 2026

Thanks @a7m-1st 👍 . @Wendong-Fan can you merge this PR?

@a7m-1st a7m-1st merged commit 53d8830 into eigent-ai:main Feb 11, 2026
7 checks passed
@bittoby bittoby deleted the fix/download-proxy-support branch February 11, 2026 11:36
@a7m-1st
Copy link
Collaborator

a7m-1st commented Feb 11, 2026

Merged successfully, thanks @bittoby & @Zephyroam for your contributions !

@bittoby
Copy link
Contributor Author

bittoby commented Feb 11, 2026

Thank you @a7m-1st 👍

Comment on lines -243 to +253
const proxyEnv = proxyUrl
? {
HTTP_PROXY: proxyUrl,
HTTPS_PROXY: proxyUrl,
http_proxy: proxyUrl,
https_proxy: proxyUrl,
}
: {};
const proxyEnv = {
HTTP_PROXY: readEnvValueWithPriority('HTTP_PROXY'),
HTTPS_PROXY: readEnvValueWithPriority('HTTPS_PROXY'),
http_proxy: readEnvValueWithPriority('http_proxy'),
https_proxy: readEnvValueWithPriority('https_proxy'),
// Ensure local connections bypass proxy
NO_PROXY:
readEnvValueWithPriority('NO_PROXY') || 'localhost,127.0.0.1,.local',
no_proxy:
readEnvValueWithPriority('no_proxy') || 'localhost,127.0.0.1,.local',
};
Copy link
Collaborator

@nitpicker55555 nitpicker55555 Feb 11, 2026

Choose a reason for hiding this comment

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

I am not sure why this change was made. The original code had a complete ternary condition:

proxyUrl ? { ... } : {}

When no proxy was provided, it returned an empty object and did not pollute the environment variables.

However, after this change, the ternary condition was removed and the return value of readEnvValueWithPriority() is written directly into the object. When there is no proxy, all four keys are null. Once passed to the child process, they become the string "null", which uv then treats as a proxy address during dependency installation, ultimately causing DNS resolution failures.

@bittoby @a7m-1st

This PR was reverted because it caused DNS resolution errors during dependency installation.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I updated the code yesterday, but I didn't manage to catch it while testing, perhaps bcz uv install didn't trigger in my case. Apologies for the hassle.
Thanks for reverting it @nitpicker55555

Copy link
Contributor

Choose a reason for hiding this comment

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

thanks @nitpicker55555 for pointing this out, could @bittoby or @a7m-1st reopen a PR and add additional fix, then we can review & merge this

Copy link
Collaborator

Choose a reason for hiding this comment

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

@a7m-1st @Wendong-Fan I get one fix pr
In #1226, I tested and is work

Copy link
Collaborator

Choose a reason for hiding this comment

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

Hi there, thanks @nitpicker55555. In addition to the enhancements I added, I think your PR would do.

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.

[BUG] Dependency installation script fails to download in proxy environment when start the frontend

5 participants