* fix: wrap blocking readability call with asyncio.to_thread in web_fetch
The readability extractor internally spawns a Node.js subprocess via
readabilipy, which blocks the async event loop and causes a
BlockingError when web_fetch is invoked inside LangGraph's async
runtime.
Wrap the synchronous extract_article call with asyncio.to_thread to
offload it to a thread pool, unblocking the event loop.
Note: community/infoquest/tools.py has the same latent issue and
should be addressed in a follow-up PR.
Closes#2152
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: verify web_fetch offloads extraction via asyncio.to_thread
Add a regression test that monkeypatches asyncio.to_thread to confirm
readability extraction is offloaded to a worker thread, preventing
future refactors from reintroducing the blocking call.
Addresses Copilot review feedback on #2157.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Willem Jiang <willem.jiang@gmail.com>