mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-26 18:31:34 +01:00
Pinning to `approved[0]` alone dropped the failover `fetch` gave a multi-homed host, so one dead A record took the whole connection down. Walk the approved addresses in resolution order instead — but only for addresses that are unreachable. A peer that answers from an unapproved address is the rebinding defence firing, not a reachability problem, so it still fails closed on the first try rather than being retried past. Also close the gaps the response deadline left behind: - a connect timeout used to leak the half-open socket, since nothing above that point owned it yet; - both deadlines threw bare `Error`s, so callers that switch on the guard's error codes saw a timeout as an unclassified failure — they now carry `remote_http_response_timeout`; - a finished response left an armed socket timer behind; and - the default deadline drops from undici's 300 s to 30 s, which is already generous for metadata discovery, a token exchange or a JSON-RPC round trip. `tools/call` owns a caller-set budget an operator can raise to 60 s, so it passes `responseTimeoutMs` explicitly rather than being truncated by the tighter default. Covers each with a regression test, including a peer that dribbles header bytes forever — the case that rules out `req.setTimeout`, whose idle clock such a peer can reset indefinitely. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>