From 8ff821515da0beefc9f531e632444be5714f90a8 Mon Sep 17 00:00:00 2001 From: can1357 Date: Thu, 16 Jul 2026 03:11:02 +0200 Subject: [PATCH] fix(ai): honor NO_PROXY ports for secure websockets --- packages/ai/src/utils/proxy.ts | 2 +- packages/ai/test/openai-codex-stream.test.ts | 2 +- packages/ai/test/proxy.test.ts | 5 +++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/ai/src/utils/proxy.ts b/packages/ai/src/utils/proxy.ts index 00e5e0f50..33fb0b12b 100644 --- a/packages/ai/src/utils/proxy.ts +++ b/packages/ai/src/utils/proxy.ts @@ -61,7 +61,7 @@ export function shouldBypassProxy(urlObj: URL): boolean { .map(r => r.trim()) .filter(Boolean); const targetHost = urlObj.hostname.toLowerCase(); - const targetPort = urlObj.port || (urlObj.protocol === "https:" ? "443" : "80"); + const targetPort = urlObj.port || (urlObj.protocol === "https:" || urlObj.protocol === "wss:" ? "443" : "80"); for (const rule of rules) { if (rule === "*") { diff --git a/packages/ai/test/openai-codex-stream.test.ts b/packages/ai/test/openai-codex-stream.test.ts index 631124382..56699f1e0 100644 --- a/packages/ai/test/openai-codex-stream.test.ts +++ b/packages/ai/test/openai-codex-stream.test.ts @@ -1466,7 +1466,7 @@ describe("openai-codex streaming", () => { it("bypasses configured proxies for NO_PROXY websocket targets", async () => { Bun.env.PI_PROXY_CODEX_PROXY_TEST = "http://127.0.0.1:7890"; - Bun.env.NO_PROXY = "chatgpt.com"; + Bun.env.NO_PROXY = "chatgpt.com:443"; __resetProxyCache(); let capturedProxy: string | undefined; class NoProxyWebSocket extends MockWebSocket { diff --git a/packages/ai/test/proxy.test.ts b/packages/ai/test/proxy.test.ts index 6ea0a78a9..55afee998 100644 --- a/packages/ai/test/proxy.test.ts +++ b/packages/ai/test/proxy.test.ts @@ -190,6 +190,11 @@ describe("shouldBypassProxy NO_PROXY rules", () => { expect(shouldBypassProxy(new URL("https://api.sakana.ai/v1"))).toBe(false); expect(shouldBypassProxy(new URL("http://api.sakana.ai:8080/v1"))).toBe(true); }); + + it("uses port 443 for secure websocket targets", () => { + Bun.env.NO_PROXY = "api.sakana.ai:443"; + expect(shouldBypassProxy(new URL("wss://api.sakana.ai/v1"))).toBe(true); + }); }); describe("wrapFetchForProxy", () => {