Version Packages - #995
Merged
Merged
Conversation
github-actions
Bot
force-pushed
the
changeset-release/main
branch
23 times, most recently
from
March 2, 2026 10:45
6bc1872 to
7abab09
Compare
github-actions
Bot
force-pushed
the
changeset-release/main
branch
from
March 2, 2026 11:31
7abab09 to
bf66177
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.
Releases
agents@0.7.0
Minor Changes
#1024
e9ae070Thanks @threepointone! - Overhaul observability:diagnostics_channel, leaner events, error tracking.Breaking changes to
agents/observabilitytypesBaseEvent: RemovedidanddisplayMessagefields. Events now contain onlytype,payload, andtimestamp. Thepayloadtype is now strict — accessing undeclared fields is a type error. Narrow onevent.typebefore accessing payload properties.Observability.emit(): Removed the optionalctxsecond parameter.AgentObservabilityEvent: Split combined union types so each event has its own discriminant (enables properExtract-based type narrowing). Added new error event types.If you have a custom
Observabilityimplementation, update youremitsignature toemit(event: ObservabilityEvent): void.diagnostics_channel replaces console.log
The default
genericObservabilityimplementation no longer logs every event to the console. Instead, events are published to named diagnostics channels using the Node.jsdiagnostics_channelAPI. Publishing to a channel with no subscribers is a no-op, eliminating logspam.Seven named channels, one per event domain:
agents:state— state sync eventsagents:rpc— RPC method calls and errorsagents:message— message request/response/clear/cancel/error + tool result/approvalagents:schedule— schedule and queue create/execute/cancel/retry/error eventsagents:lifecycle— connection and destroy eventsagents:workflow— workflow start/event/approve/reject/terminate/pause/resume/restartagents:mcp— MCP client connect/authorize/discover eventsNew error events
Error events are now emitted at failure sites instead of (or alongside)
console.error:rpc:error— RPC method failures (includes method name and error message)schedule:error— schedule callback failures after all retries exhaustedqueue:error— queue callback failures after all retries exhaustedReduced boilerplate
All 20+ inline
emitblocks in the Agent class have been replaced with a private_emit()helper that auto-generates timestamps, reducing each call site from ~10 lines to 1.Typed subscribe helper
A new
subscribe()function is exported fromagents/observabilitywith full type narrowing per channel:Tail Worker integration
In production, all diagnostics channel messages are automatically forwarded to Tail Workers via
event.diagnosticsChannelEvents— no subscription needed in the agent itself.TracingChannel potential
The
diagnostics_channelAPI also providesTracingChannelfor start/end/error spans withAsyncLocalStorageintegration, opening the door to end-to-end tracing of RPC calls, workflow steps, and schedule executions.#1029
c898308Thanks @threepointone! - Add experimentalkeepAlive()andkeepAliveWhile()methods to the Agent class. Keeps the Durable Object alive via alarm heartbeats (every 30 seconds), preventing idle eviction during long-running work.keepAlive()returns a disposer function;keepAliveWhile(fn)runs an async function and automatically cleans up the heartbeat when it completes.AIChatAgentnow automatically callskeepAliveWhile()during_reply()streaming, preventing idle eviction during long LLM generations.Patch Changes
#1020
70ebb05Thanks @threepointone! - udpate dependencies#1035
24cf279Thanks @threepointone! - MCP protocol handling improvements:RPCServerTransport.handle()now returns a proper JSON-RPC-32600 Invalid Requesterror response for malformed messages instead of throwing an unhandled exception. This aligns with the JSON-RPC 2.0 spec requirement that servers respond with error objects.McpAgentnow overridesshouldSendProtocolMessages()to suppressCF_AGENT_IDENTITY,CF_AGENT_STATE, andCF_AGENT_MCP_SERVERSframes on MCP transport connections (detected via thecf-mcp-methodheader). Regular WebSocket connections to a hybrid McpAgent are unaffected.AuthorizationinAccess-Control-Allow-Headerswith wildcard origin. The warning was noisy and unhelpful — the combination is valid for non-credentialed requests and does not pose a real security risk.#996
baf6751Thanks @threepointone! - Fix race condition where MCP tools are intermittently unavailable in onChatMessage after hibernation.agents: AddedMCPClientManager.waitForConnections(options?)which awaits all in-flight connection and discovery operations. Accepts an optional{ timeout }in milliseconds. Background restore promises fromrestoreConnectionsFromStorage()are now tracked so callers can wait for them to settle.@cloudflare/ai-chat: AddedwaitForMcpConnectionsopt-in config onAIChatAgent. Set totrueto wait indefinitely, or{ timeout: 10_000 }to cap the wait. Default isfalse(non-blocking, preserving existing behavior). For lower-level control, callthis.mcp.waitForConnections()directly in youronChatMessage.#1035
24cf279Thanks @threepointone! - Fixthis.sqlto throwSqlErrordirectly instead of routing throughonErrorPreviously, SQL errors from
this.sqlwere passed tothis.onError(), which by default logged the error and re-threw it. This caused confusing double error logs and made it impossible to catch SQL errors with a simple try/catch aroundthis.sqlcalls ifonErrorwas overridden to swallow errors.Now,
this.sqlwraps failures inSqlError(which includes the query string for debugging) and throws directly. TheonErrorlifecycle hook is reserved for WebSocket connection errors and unhandled server errors, not SQL errors.#1022
c2bfd3cThanks @threepointone! - Remove redundant unawaitedupdatePropscalls in MCP transport handlers that caused sporadic "Failed to pop isolated storage stack frame" errors in test environments. Props are already delivered throughgetAgentByName→onStart, making the extra calls unnecessary. Also removes the RPC experimental warning fromaddMcpServer.#1003
d24936cThanks @threepointone! - Fix:throw new Error()in AgentWorkflow now triggersonWorkflowErroron the AgentPreviously, throwing an error inside a workflow's
run()method would halt the workflow but never notify the Agent viaonWorkflowError. Only explicitstep.reportError()calls triggered the callback, but those did not halt the workflow.Now, unhandled errors in
run()are automatically caught and reported to the Agent before re-throwing. A double-notification guard (_errorReportedflag) ensures that ifstep.reportError()was already called before the throw, the auto-report is skipped.#1040
766f20bThanks @threepointone! - ChangedaddMcpServerdedup logic to match on both server name AND URL for HTTP transport. Previously, callingaddMcpServerwith the same name but a different URL would silently return the stale connection. Now each unique (name, URL) pair is treated as a separate connection. RPC transport continues to dedup by name only.#997
a570ea5Thanks @threepointone! - Security hardening for Agent and MCP subsystems:consumeStatewarning logs to prevent sensitive data leakagesendIdentityOnConnectwarning: When using custom routing (where the instance name is not visible in the URL), a one-time console warning now informs developers that the instance name is being sent to clients. Setstatic options = { sendIdentityOnConnect: false }to opt out, ortrueto silence the warning.#992
4fcf179Thanks @Muhammad-Bin-Ali! - Fix email routing to handle lowercased agent names from email infrastructureEmail servers normalize addresses to lowercase, so
SomeAgent+id@domain.comarrives assomeagent+id@domain.com. The router now registers a lowercase key in addition to the original binding name and kebab-case version, so all three forms resolve correctly.@cloudflare/ai-chat@0.1.6
Patch Changes
#1040
766f20bThanks @threepointone! - ChangedwaitForMcpConnectionsdefault fromfalseto{ timeout: 10_000 }. MCP connections are now waited on by default with a 10-second timeout, sogetAITools()returns the full set of tools inonChatMessagewithout requiring explicit opt-in. SetwaitForMcpConnections = falseto restore the previous behavior.#1020
70ebb05Thanks @threepointone! - udpate dependencies#1013
11aaaffThanks @threepointone! - Fix Gemini "missing thought_signature" error when using client-side tools withaddToolOutput.The server-side message builder (
applyChunkToParts) was droppingproviderMetadatafrom tool-input stream chunks instead of storing it ascallProviderMetadataon tool UIMessage parts. WhenconvertToModelMessageslater read the persisted messages for the continuation call,callProviderMetadatawas undefined, so Gemini never received itsthought_signatureback and rejected the request.callProviderMetadata(mapped from streamproviderMetadata) on tool parts intool-input-start,tool-input-available, andtool-input-errorhandlers — both create and update pathsproviderExecutedon tool parts (used byconvertToModelMessagesfor provider-executed tools like Gemini code execution)titleon tool parts (tool display name)providerExecutedtoStreamChunkDatatype explicitly#989
8404954Thanks @threepointone! - Fix active streams losing UI state after reconnect and dead streams after DO hibernation.replayCompletesignal after replaying stored chunks for live streams, so the client flushes accumulated parts to React state immediately instead of waiting for the next live chunk._isLiveflag onResumableStream. On reconnect, senddone: true, complete the stream, and reconstruct/persist the partial assistant message from stored chunks.activeStreamRefonreplayComplete(keeps stream alive for subsequent live chunks) and ondoneduring replay (finalizes orphaned streams).#996
baf6751Thanks @threepointone! - Fix race condition where MCP tools are intermittently unavailable in onChatMessage after hibernation.agents: AddedMCPClientManager.waitForConnections(options?)which awaits all in-flight connection and discovery operations. Accepts an optional{ timeout }in milliseconds. Background restore promises fromrestoreConnectionsFromStorage()are now tracked so callers can wait for them to settle.@cloudflare/ai-chat: AddedwaitForMcpConnectionsopt-in config onAIChatAgent. Set totrueto wait indefinitely, or{ timeout: 10_000 }to cap the wait. Default isfalse(non-blocking, preserving existing behavior). For lower-level control, callthis.mcp.waitForConnections()directly in youronChatMessage.#993
f706e3fThanks @ferdousbhai! - fix(ai-chat): preserve server tool outputs when client sends approval-responded state_mergeIncomingWithServerStatenow treatsapproval-respondedthe same asinput-availablewhen the server already hasoutput-availablefor a tool call,preventing stale client state from overwriting completed tool results.
#1038
e61cb4aThanks @threepointone! - fix(ai-chat): preserve server-generated assistant messages when client appends new messagesThe
_deleteStaleRowsreconciliation inpersistMessagesnow only deletes DB rows when the incoming message set is a subset of the server state (e.g. regenerate trims the conversation). When the client sends new message IDs not yet known to the server, stale deletion is skipped to avoid destroying assistant messages the client hasn't seen.#1014
74a3815Thanks @threepointone! - Fixregenerate()leaving stale assistant messages in SQLiteBug 1 — Transport drops
triggerfield:WebSocketChatTransport.sendMessageswas not including thetriggerfield(e.g.
"regenerate-message","submit-message") in the body payload sentto the server. The AI SDK passes this field so the server can distinguish
between a new message and a regeneration request. Fixed by adding
trigger: options.triggerto the serialized body.On the server side,
triggeris now destructured out of the parsed bodyalongside
messagesandclientTools, so it does not leak intooptions.bodyinonChatMessage. Users who inspectoptions.bodywillnot see any change in behavior.
Bug 2 —
persistMessagesnever deletes stale rows:persistMessagesonly performedINSERT ... ON CONFLICT DO UPDATE(upsert),so when
regenerate()removed the last assistant message from the client'sarray, the old row persisted in SQLite. On the next
_loadMessagesFromDb,the stale assistant message reappeared in
this.messages, causing:user message)
Fixed by adding an internal
_deleteStaleRowsoption topersistMessages.When the chat-request handler (
CF_AGENT_USE_CHAT_REQUEST) callspersistMessages, it passes{ _deleteStaleRows: true }, which deletesany DB rows whose IDs are absent from the incoming (post-merge) message set.
This uses the post-merge IDs from
_mergeIncomingWithServerStatetocorrectly handle cases where client assistant IDs are remapped to server IDs.
The
_deleteStaleRowsflag is internal only (@internalJSDoc) and isnever passed by user code or other handlers (
CF_AGENT_CHAT_MESSAGES,_reply,saveMessages). The default behavior ofpersistMessages(upsert-only, no deletes) is unchanged.
Bug 3 — Content-based reconciliation mismatches identical messages:
_reconcileAssistantIdsWithServerStateused a single-pass cursor for bothexact-ID and content-based matching. When an exact-ID match jumped the
cursor forward, it skipped server messages needed for content matching
of later identical-text assistant messages (e.g. "Sure", "I understand").
Rewritten with a two-pass approach: Pass 1 resolves all exact-ID matches
and claims server indices. Pass 2 does content-based matching only over
unclaimed server indices. This prevents exact-ID matches from interfering
with content matching, fixing duplicate rows in long conversations with
repeated short assistant responses.
#999
95753daThanks @threepointone! - FixuseChatstatusstaying"ready"during stream resumption after page refresh.Four issues prevented stream resumption from working:
onAgentMessagealways handledCF_AGENT_STREAM_RESUMINGbefore the transport's listener, bypassing the AI SDK pipeline.useMemocreated new transport instances across renders and Strict Mode cycles. When_pkchanged (async queries, socket recreation), the resolver was stranded on the old transport whileonAgentMessagecalledhandleStreamResumingon the new one._pkchange: Usingagent._pkas theuseChatidcaused the AI SDK to recreate the Chat when the socket changed, abandoning the in-flightmakeRequest(including resume). The resume effect wouldn't re-fire on the new Chat.STREAM_RESUMINGfrom bothonConnectand theRESUME_REQUESThandler, causing duplicate ACKs and double replay without deduplication.Fixes:
addEventListener-based detection withhandleStreamResuming()— a synchronous methodonAgentMessagecalls directly, eliminating the race.useRef, created once). Updatetransport.agentevery render so sends/listeners always use the latest socket. The resolver survives_pkchanges because the transport instance never changes.initialMessagesCacheKeybased on URL + agent + name) instead ofagent._pk, preventing Chat recreation on socket changes.localRequestIdsRefguard to skip duplicateSTREAM_RESUMINGmessages for streams already handled by the transport.#1029
c898308Thanks @threepointone! - Add experimentalkeepAlive()andkeepAliveWhile()methods to the Agent class. Keeps the Durable Object alive via alarm heartbeats (every 30 seconds), preventing idle eviction during long-running work.keepAlive()returns a disposer function;keepAliveWhile(fn)runs an async function and automatically cleans up the heartbeat when it completes.AIChatAgentnow automatically callskeepAliveWhile()during_reply()streaming, preventing idle eviction during long LLM generations.@cloudflare/codemode@0.1.2
Patch Changes
70ebb05Thanks @threepointone! - udpate dependencieshono-agents@3.0.7
Patch Changes
70ebb05Thanks @threepointone! - udpate dependencies