运行时崩溃 · 模块互操作

Gemini CLI 报 HttpsProxyAgent is not a constructor 深度排查与模块解耦

Gemini CLI 在检测到 HTTP_PROXY 环境变量时抛出 TypeError: HttpsProxyAgent is not a constructor,属于 Node.js 生态中 CommonJS 与 ESM 具名导出的打包兼容性 Bug。排查重点在于解耦应用层代理,改走内核 TUN 转发或国内免梯直连中转。

更新日期:2026-09-16·作者:词元AI中转站 技术团队·主词:Gemini CLI 代理报错
异常类型TypeError: xxx is not a constructor
阻断层级客户端 Node.js 模块实例化阶段
架构解法TUN 内核转发 / 免代理中转专线直通

1. Bug 本质:Node.js ESM/CJS 导出的历史断层

在使用 Node.js 开发的 CLI 工具中,网络代理普遍依赖开源库 https-proxy-agent。然而在该库从 5.x 版本向 6.x/7.x 版本演进的过程中,其导出格式经历了重大变革:

版本代际 模块导出标准 导出形态 典型引用方式
旧版本 (v5.x) CommonJS module.exports = HttpsProxyAgent; const HttpsProxyAgent = require('https-proxy-agent');
新版本 (v6.x / v7.x) TypeScript / ESM export { HttpsProxyAgent };
export default HttpsProxyAgent;
import { HttpsProxyAgent } from 'https-proxy-agent';

当 Gemini CLI 使用 esbuild 或 Webpack 将依赖打包为单个可执行单文件(Bundle)时,如果打包配置中的 ESM 互操作(Interop)参数不严谨,编译产物在运行时实际上获取到的是一个外层包裹对象:

运行时对象形态对比(问题所在)
// 开发者预期的结果:
const AgentClass = HttpsProxyAgent; // 是一个 Function / Class

// 实际运行时拿到的对象结构:
const AgentClass = {
  __esModule: true,
  HttpsProxyAgent: class HttpsProxyAgent extends Agent { ... },
  default: class HttpsProxyAgent extends Agent { ... }
};

// 执行以下语句时,直接抛出 TypeError!
const agent = new AgentClass(proxyUrl);
// 报错:TypeError: HttpsProxyAgent is not a constructor

2. 为什么该报错意味着请求“从未离开本机”

许多开发者在遇到该报错时,习惯性地怀疑“是不是梯子挂了”、“是不是端口写错了”或者“Google 账号被风控了”。这些判断都是完全错误的:

  • 物理层面未触网:该异常属于 JavaScript 引擎在执行主线程函数时的语法类型错误(TypeError)。此时底层套接字(Socket)根本没有分配,操作系统网卡没有发出任何一个 SYN 数据包。
  • 与服务器端点无关:无论你的目标 Base URL 是 Google 官方、Vertex AI 还是第三方中转站,代码在拼装 HTTP Agent 的第 0 步就已崩溃,远端服务器的访问日志中绝对不可能有该请求的记录。

3. 终端验证:进程级环境变量净化与对照实验

要 100% 确认该 Bug 是否由代理环境变量触发,最简单的方法是在当前子进程中临时剔除代理变量,进行对照实验:

macOS / Linux 进程隔离验证命令
# 1. 打印当前残留的代理变量
env | grep -i proxy

# 2. 临时剔除所有代理变量并启动最小请求
env -u HTTP_PROXY -u HTTPS_PROXY -u http_proxy -u https_proxy gemini --prompt "ping"

在 Windows PowerShell 中,可使用一次性子进程进行验证:

PowerShell 净化命令
# 临时清空当前会话的代理变量
$env:HTTP_PROXY=""
$env:HTTPS_PROXY=""
$env:http_proxy=""
$env:https_proxy=""

# 再次运行 gemini
gemini --prompt "ping"

若清空变量后 CLI 不再弹出 TypeError,即可铁证证明故障点正是 CLI 内部的代理构造分支。

4. 方案一:开启系统级 TUN 虚拟网卡规避应用层代理

在必须跨国访问官方端点的网络环境下,如果你无法等待官方发布修复版本的 CLI,推荐开启系统级 **TUN(虚拟网卡)模式**:

  • TUN 模式会在操作系统内核层创建一个虚拟网络接口(如 utunwintun),接管全操作系统的所有 IP 层流量。
  • 开启 TUN 模式后,请**彻底从 .bashrc.zshrc 或系统变量中删除 HTTP_PROXYHTTPS_PROXY**。
  • Gemini CLI 在没有检测到代理环境变量时,会顺畅走 Node.js 原生的 https.Agent 代码分支,完美绕过存在缺陷的第三方代理依赖库;而此时底层 TCP 数据流早已被操作系统透明转发至目标节点。

5. 方案二:架构终极方案——国内专线中转免代理直连

对于大部分国内企业开发团队和个人开发者,依赖本地多层代理客户端不仅容易触发各种运行时的环境 Bug,还会带来严重的网络抖动、DNS 污染和高延迟。

最彻底、最稳定的工业级解法是直接接入词元AI中转聚合网络(统一接入端点:https://api.gpt345.com/v1):

免代理直连中转服务配置
# 彻底清空所有本地代理配置
unset HTTP_PROXY HTTPS_PROXY http_proxy https_proxy

# 配置词元中转统一端点与长效 API Key
export OPENAI_BASE_URL="https://api.gpt345.com/v1"
export OPENAI_API_KEY="sk-gpt345-enterprise-api-key"

# 享受 100% 原生 HTTPS 专线直通加速
curl https://api.gpt345.com/v1/chat/completions \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gemini-3-8-flash",
    "messages": [{"role": "user", "content": "国内专线免梯直连测试"}]
  }'

该架构彻底移除了繁琐的代理中继环路,将调用链路收敛为标准的 TCP/TLS 直连,毫秒级响应,杜绝一切由于 Node 代理库打包不良导致的进程崩溃。

6. 常见问题与排错手册

?为什么明明代理服务正常,Gemini CLI 却秒退报 HttpsProxyAgent is not a constructor?

因为该错误发生在 Node.js 内存对象初始化阶段。依赖库 https-proxy-agent 在大版本迭代中调整了 CommonJS 与 ESM 导出规范,CLI 打包工具在导入时未能解构出实际的 Class 构造函数,导致在执行 new 操作时触发 JavaScript 运行时类型异常。此时网络请求根本尚未发出。

?修改 API Key 或者调整代理端口能修复这个问题吗?

完全不能。这是客户端代码逻辑与第三方依赖库的语法兼容错误,与密钥有效性、服务器配额或代理端口无关。只要环境变量中存在 HTTP_PROXY / HTTPS_PROXY,CLI 就会进入损坏的代理分支代码。

?如何在不修改 CLI 源码的前提下绕过该代理 Bug?

最佳方案是开启系统级 TUN 虚拟网卡模式,或使用 Transparent Proxy 透明转发,随后执行 unset HTTP_PROXY HTTPS_PROXY 清除环境变量。CLI 将回退使用 Node 原生 https.Agent 发起连接,流量由操作系统内核自动转发,完全规避损坏的 JS 代理库。

?国内生产环境如何彻底告别代理依赖?

接入词元AI中转聚合网络(https://api.gpt345.com/v1)。该中转服务具备国内专线节点,支持原生 HTTPS 直连,彻底无需挂载任何代理工具和环境变量,从物理层面消除代理层故障。

* 本文由 词元AI中转站 技术团队根据 Node.js 模块规范与前端工程打包生态原创整理。遇到构造器报错请优先排查运行时依赖。最后修订:2026-09-16。

参考资料:TooTallNate/proxy-agents 官方仓库 · Node.js Packages Module System Specs