fix(ai): respect proxy envs in bun's websocket

fixes #4346
This commit is contained in:
haoqixu
2026-05-10 02:45:44 +08:00
parent 3d5cbe98c3
commit 8c2e3eddec
3 changed files with 33 additions and 3 deletions

1
package-lock.json generated
View File

@@ -7337,6 +7337,7 @@
"openai": "6.26.0",
"partial-json": "^0.1.7",
"proxy-agent": "^6.5.0",
"proxy-from-env": "^1.1.0",
"typebox": "^1.1.24",
"undici": "^7.19.1",
"zod-to-json-schema": "^3.24.6"

View File

@@ -73,11 +73,12 @@
"@aws-sdk/client-bedrock-runtime": "^3.1030.0",
"@google/genai": "^1.40.0",
"@mistralai/mistralai": "^2.2.0",
"typebox": "^1.1.24",
"chalk": "^5.6.2",
"openai": "6.26.0",
"partial-json": "^0.1.7",
"proxy-agent": "^6.5.0",
"proxy-from-env": "^1.1.0",
"typebox": "^1.1.24",
"undici": "^7.19.1",
"zod-to-json-schema": "^3.24.6"
},

View File

@@ -711,7 +711,35 @@ type WebSocketConstructor = new (
protocols?: string | string[] | { headers?: Record<string, string> },
) => WebSocketLike;
function getWebSocketConstructor(): WebSocketConstructor | null {
let _cachedWebsocket: WebSocketConstructor | null = null;
async function getWebSocketConstructor(): Promise<WebSocketConstructor | null> {
if (_cachedWebsocket) return _cachedWebsocket;
// bun doesn't respect http proxy envs, ref: https://github.com/oven-sh/bun/issues/15489
// TODO: remove this when bun supports proxy envs in websocket.
if (
process?.versions?.bun &&
(process.env.HTTP_PROXY || process.env.HTTPS_PROXY || process.env.http_proxy || process.env.https_proxy)
) {
const m = await dynamicImport("proxy-from-env");
const getProxyForUrl = (m as { getProxyForUrl: (url: string | object | URL) => string }).getProxyForUrl;
_cachedWebsocket = class extends WebSocket {
constructor(url: string | URL, options?: string | string[] | Record<string, unknown>) {
let _opts: Record<string, unknown> = {};
if (Array.isArray(options) || typeof options === "string") {
_opts = { protocols: options };
} else {
_opts = { ...options };
}
const proxy = getProxyForUrl(url.toString().replace(/^wss:/, "https:").replace(/^ws:/, "http:"));
super(url, { ..._opts, ...(proxy ? { proxy } : {}) } as any);
}
};
return _cachedWebsocket;
}
const ctor = (globalThis as { WebSocket?: unknown }).WebSocket;
if (typeof ctor !== "function") return null;
return ctor as unknown as WebSocketConstructor;
@@ -760,7 +788,7 @@ function scheduleSessionWebSocketExpiry(sessionId: string, entry: CachedWebSocke
}
async function connectWebSocket(url: string, headers: Headers, signal?: AbortSignal): Promise<WebSocketLike> {
const WebSocketCtor = getWebSocketConstructor();
const WebSocketCtor = await getWebSocketConstructor();
if (!WebSocketCtor) {
throw new Error("WebSocket transport is not available in this runtime");
}