Minor Changes
-
#1150
81a8710Thanks @threepointone! - feat: addsanitizeMessageForPersistencehook and built-in Anthropic tool payload truncation- New protected hook:
sanitizeMessageForPersistence(message)— override this method to apply custom transformations to messages before they are persisted to storage. Runs after built-in sanitization. Default is identity (returns message unchanged). - Anthropic provider-executed tool truncation: Large string values in
inputandoutputof provider-executed tool parts (e.g. Anthropiccode_execution,text_editor) are now automatically truncated. These server-side tool payloads can exceed 200KB and are dead weight once the model has consumed the result.
Closes #1118
- New protected hook:
-
#1138
36e2020Thanks @threepointone! - Drop Zod v3 from peer dependency range — now requireszod ^4.0.0. Replace dynamicimport("ai")withz.fromJSONSchema()from Zod 4 for MCP tool schema conversion, removing theairuntime dependency from the agents core. RemoveensureJsonSchema().
Patch Changes
-
#1151
b0c52a5Thanks @whoiskatrin! - fix(ai-chat): simplify turn coordination API- rename
waitForPendingInteractionResolution()towaitUntilStable()and make it wait for a fully stable conversation state, including queued continuation turns - add
resetTurnState()for scoped clear handlers that need to abort active work and invalidate queued continuations - demote
isChatTurnActive(),waitForIdle(), andabortActiveTurn()to private — their behavior is subsumed bywaitUntilStable()andresetTurnState() - harden pending-interaction bookkeeping so rejected tool-result and approval applies do not leak as unhandled rejections
- rename
-
#1106
3184282Thanks @threepointone! - fix: abort/stop no longer creates duplicate split messages (issue #1100)When a user clicked stop during an active stream, the assistant message was split into two separate messages. This happened because
onAbortin the transport immediately removed therequestIdfromactiveRequestIds, causingonAgentMessageto treat in-flight server chunks as a new broadcast.WebSocketChatTransport:onAbortnow keeps therequestIdinactiveRequestIdsso in-flight server chunks are correctly skipped by the dedup guarduseAgentChat:onAgentMessagenow cleans up the kept ID when receivingdone: true, preventing a minor memory leak
-
#1142
5651eceThanks @whoiskatrin! - fix(ai-chat): serialize chat turns and expose turn control helpers- queue
onChatMessage()+_reply()work so user requests, tool continuations, andsaveMessages()never stream concurrently - make
saveMessages()wait for the queued turn to finish before resolving, and reuse the request id for reply cleanup - skip queued continuations and
saveMessages()calls that were enqueued before a chat clear - capture
saveMessages()context (_lastClientTools,_lastBody) at enqueue time so a later request cannot overwrite it before execution - add protected
isChatTurnActive(),waitForIdle(),abortActiveTurn(),hasPendingInteraction(), andwaitForPendingInteractionResolution()helpers for subclass code that needs to coordinate active turns and pending tool interactions
- queue
-
#1096
0d0b7d3Thanks @threepointone! - fix(ai-chat): prevent duplicate messages after tool calls and orphaned client IDs- CF_AGENT_MESSAGE_UPDATED handler no longer appends when message not found in client state, fixing race between transport stream and server broadcast
- _resolveMessageForToolMerge reconciles IDs by toolCallId regardless of tool state, preventing client nanoid IDs from leaking into persistent storage