8760937439
* fix(memory): use asyncio.to_thread for blocking file I/O in aupdate_memory `_finalize_update` performs synchronous blocking operations (os.mkdir, file open/write/rename/stat) that were called directly from the async `aupdate_memory` method, causing `BlockingError` from blockbuster when running under an ASGI server. Wrap the call with `asyncio.to_thread` to offload all blocking I/O to a thread pool. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(memory): use unique temp filename to prevent concurrent write collision `file_path.with_suffix(".tmp")` produces a fixed path — concurrent saves for the same agent (now possible after wrapping _finalize_update in asyncio.to_thread) would clobber the same temp file. Use a UUID-suffixed temp file so each write is isolated. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(memory): also offload _prepare_update_prompt to thread pool FileMemoryStorage.load() inside _prepare_update_prompt performs synchronous stat() and file read, blocking the event loop just like _finalize_update did. Wrap _prepare_update_prompt in asyncio.to_thread for the same reason. The async path now has no blocking file I/O on the event loop: to_thread(_prepare_update_prompt) → await model.ainvoke() → to_thread(_finalize_update) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>