github cloudflare/agents @cloudflare/ai-chat@0.8.1

4 hours ago

Patch Changes

  • #1661 41315b6 Thanks @threepointone! - Heal a malformed tool_use.input when loading persisted messages.

    AIChatAgent delegates convertToModelMessages to your onChatMessage, so it has no framework-side pre-send pass to repair a transcript. A session that persisted a non-object tool inputnull, undefined, "", an array, or a raw string — before the write-side guard shipped would therefore keep 400ing with tool_use.input: Input should be an object on every turn, wedged across reconnects/redeploys/evictions.

    autoTransformMessage (run on every load) now normalizes malformed tool inputs to {} (parsing stringified-JSON objects, and leaving healthy object inputs untouched), so existing wedged sessions self-heal on their next load without per-DO storage surgery. Healthy messages are returned by reference, so the persistence cache stays a no-op for them.

  • #1654 f34cd30 Thanks @cjol! - Fix isStreaming staying true after aborting during server-side tool calls.

  • #1657 7bff8d7 Thanks @threepointone! - fix(think): serialize parallel client-tool result/approval applies so siblings aren't clobbered (#1649 follow-up)

    The auto-continuation barrier added in #1651 stopped premature continuation, but a deeper race remained in Think. Each tool-result/tool-approval WebSocket message fired an independent read-modify-write of the whole assistant message, and _applyToolUpdateToMessages awaits a storage read before its write. When the model fanned out parallel tool calls, the concurrent applies all read the same input-available snapshot, each patched only its own part, and the last write clobbered its siblings back to input-available. The continuation barrier then timed out and the transcript-repair backstop errored the lost calls with "The tool call was interrupted before a result was recorded."

    Applies are now chained off a serialization tail so each read-modify-write commits atomically in arrival order. _pendingInteractionPromise still tracks the newest link, so the barrier's single-slot wake-up transitively waits for every predecessor.

    The same serialization is applied to @cloudflare/ai-chat defensively: its apply is currently synchronous (no await between the message read and the SQLite write), so it does not exhibit this clobber today, but the queue keeps the invariant safe if that ever changes.

Don't miss a new agents release

NewReleases is sending notifications on new releases.