mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-07-21 21:48:04 +00:00
get_artifact ran its filesystem work directly on the event loop: virtual-path resolution (os.path.abspath via .resolve()), exists/is_file probes, MIME sniffing (mimetypes lazily stats the system MIME DB on first use), full-file read_text/read_bytes, is_text_file_by_content (open+read), and .skill ZIP open+extract. So serving any artifact blocked the loop for the whole read; `make detect-blocking-io` flagged it. Same class as #3457 / #3529. Offload each branch's IO via asyncio.to_thread: one sync helper per branch (_load_skill_archive_member, _read_artifact_payload) folds stat + MIME + read / extract into a single worker hop and returns a small (kind, mime, payload) plan the handler turns into the response on the loop. FileResponse (download / active content) keeps streaming the file itself. Behavior, branching, error codes, and security boundaries are unchanged. Add tests/blocking_io/test_artifacts_router.py anchor (text / binary / .skill member), verified red->green under the strict Blockbuster gate. The gate also caught a blocking call the static scan missed: resolve_thread_virtual_path's .resolve() (os.path.abspath), now offloaded too. Co-authored-by: ly-wang19 <ly-wang19@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>