When you customize networking (HTTP agents, proxy dispatchers, sandboxes, or long-running requests), follow these rules:
1) Preserve loopback/direct routing semantics
2) Guarantee cancellation/termination for all request paths
3) Handle disconnect/cancellation consistently
4) Keep platform-specific network/sandbox policies compatible
Example pattern (HTTP agent + preserved loopback + AbortSignal):
import { fetch as undiciFetch, Agent as HttpAgent } from "undici";
const loopbackAgent = new HttpAgent({ headersTimeout: 0, bodyTimeout: 0 });
export function makeFetchWithTimeouts(
agentForRemote: any, // your proxy-aware agent
) {
return async function fetchWithPolicy(input: RequestInfo | URL, init: RequestInit = {}) {
const url = typeof input === "string" ? new URL(input) : new URL(input.toString());
// Preserve direct loopback routing even when HTTP_PROXY is set.
const isLoopback = url.hostname === "localhost" || url.hostname === "127.0.0.1" || url.hostname === "::1";
const dispatcher = isLoopback ? loopbackAgent : agentForRemote;
// Ensure cancellation applies to *all* paths, including fallbacks.
// (Also apply a bounded timeout via AbortController if needed.)
return undiciFetch(url, {
...init,
dispatcher,
signal: init.signal,
});
};
}
Apply this standard anywhere you touch HTTP dispatchers/agents, retry/fallback logic, or socket disconnect handling—so local models still work under proxies, requests don’t hang indefinitely, and network policy doesn’t accidentally break sandboxing.