42c240f580
Direct-Anthropic requests used a single shared _anthropic_client, and the stale/interrupt watchdog closed + rebuilt it from the poll (stranger) thread at four sites (non-streaming stale/interrupt, streaming stale/interrupt). Closing a client whose TLS socket a worker thread was still reading released the FD from a stranger thread; the kernel recycled it under a live SSL BIO, which then wrote a 24-byte TLS record into an unrelated SQLite header (cron/executions.db), bricking every cron on the profile. Same shape as the OpenAI-only #29507 fix, but the Anthropic path never got the owner-thread contract. Extend the #29507 ownership contract to Anthropic: build a per-request client (_create_request_anthropic_client), register it with the request-client holder tagged by kind, and route _close_request_client_once by kind — a stranger thread only shuts the request client's sockets down (_abort_request_anthropic_client), while the owning worker performs the SDK close (_close_request_anthropic_client). The shared _anthropic_client is now never closed from inside a request (streaming or non-streaming), including the worker retry-cleanup sites, since each attempt builds a fresh request client. The #28161 no-hang guarantee is preserved: the poll-thread socket abort unblocks the worker immediately. Salvages the approach from #51688 (@raymondyan-zhijie), reimplemented onto current main (non-streaming dispatch was refactored into _dispatch_nonstreaming_api_request; streaming grew _cancel_current_stream_attempt and worker retry-cleanup sites). Tests updated to the request-local mechanism (incl. replacing a banned source-reading test with a behavior test) plus new regression coverage proving the watchdog aborts the request client and never touches the shared client. Co-authored-by: raymondyan-zhijie <32435458+raymondyan-zhijie@users.noreply.github.com>