diff --git a/packages/coding-agent/src/core/http-dispatcher.ts b/packages/coding-agent/src/core/http-dispatcher.ts index 2ec8144e..0910f4d6 100644 --- a/packages/coding-agent/src/core/http-dispatcher.ts +++ b/packages/coding-agent/src/core/http-dispatcher.ts @@ -10,6 +10,9 @@ export const HTTP_IDLE_TIMEOUT_CHOICES = [ { label: "disabled", timeoutMs: 0 }, ] as const; +const originalGlobalFetch = globalThis.fetch; +let installedGlobalFetch: typeof globalThis.fetch | undefined; + export function parseHttpIdleTimeoutMs(value: unknown): number | undefined { if (typeof value === "string") { const trimmed = value.trim(); @@ -58,5 +61,13 @@ export function configureHttpDispatcher(timeoutMs: number = DEFAULT_HTTP_IDLE_TI // Keep fetch and the dispatcher on the same undici implementation. Node 26.0's // bundled fetch can otherwise consume compressed responses through npm undici's // dispatcher without decompressing them, causing response.json() failures. - undici.install?.(); + // If a caller replaced fetch after module load, preserve that deliberate override. + const shouldInstallGlobals = + installedGlobalFetch === undefined + ? globalThis.fetch === originalGlobalFetch + : globalThis.fetch === installedGlobalFetch; + if (shouldInstallGlobals) { + undici.install?.(); + installedGlobalFetch = globalThis.fetch; + } }