Full Changelog: 0.3.0...0.4.0
This release introduces external data hydration: an app that owns its message store can seed a conversation from it and reconcile only the unstored tail off the Ably channel, instead of replaying the whole history. The new View.loadUntil() pages back to the newest message you already hold and returns just the missing tail, so you compose [...stored, ...tail] with no duplicates. See the external hydration demo. The release also includes a number of other improvements; see the full details below.
Breaking Changes
-
The agent's
run.messagesnow returns only the messages belonging to the run, rather than all messages for the full conversation. In order to obtain the full set of messages for the conversation (for example, in order to pass it as input to the LLM) drain therun.viewand accessrun.view.getMessages():// before (0.3.0): run.messages held the whole conversation after loadConversation() await run.loadConversation(); const messages = run.messages; // after (0.4.0): drain run.view, then read it while (run.view.hasOlder()) await run.view.loadOlder(); const messages = run.view.getMessages().map((m) => m.message);
-
Renamed the run types onto a shared read-model: client
ActiveRun→ClientRun<TMessage>, agentRun→AgentRun(both exposerunId,status,error,messages). #223 -
ClientRun.runIdis now a synchronousstring(wasPromise<string>);await run.startedbefore reading it. The agent'srunIdis unchanged. #223 -
ClientView.send/regenerate/editnow resolve toPromise<ClientRun<TMessage>>. #223 -
Removed the agent's
loadConversation()(withLoadConversationOptions/maxRuns); drainrun.viewinstead, andrun.start()now awaits the newrun.located. #227 -
View<TMessage>is now read-only; sibling navigation and the write path move toClientView<TInput, TMessage>(extendsView).session.view/createClientView()already returnClientView, so only code naming the oldView<TInput, TMessage>needs updating. #220 -
Renamed
BranchSelection→BranchHandleand removedselectSibling; select viabranchSelection(codecMessageId).select(index). #219 -
Removed the agent's
RunView;run.viewis now a read-onlyView<TMessage>(readrun.view.getMessages()), andMessageNodeis no longer exported. #221 -
ClientView.send/editnow reject a send with more than one new message (InvalidArgument); the array form stays for the wire-only inputs that resolve one turn (e.g. parallel tool results). #213 -
Removed
ClientRun.optimisticCodecMessageIds; readClientRun.inputCodecMessageId. #213 -
Removed the
ClientSessionOptions.messagesseed; compose[...stored, ...live]yourself over theloadOlder()walk. #227 -
Removed
AgentSessionOptions.inputEventLookupTimeoutMsand theInputEventNotFounderror code;run.locatedhas no deadline, so race your own timeout. #227 -
Removed
AgentSessionOptions.onError; subscribe viasession.on('error', ...). #223
New Features
View.loadUntil(predicate)pages history back to the first message your store already holds (the seam) and returns only the messages newer than it, so you hydrate from your own store and reconcile just the unstored tail. #234- React seed hooks for that recipe:
useMessagesWithSeed(generic and Vercel) and amessagesseed option onuseMessageSync, which compose your stored prefix with the live channel and run the seam walk for you. #229 View.loadOlder()returns the page it revealed (CodecMessage[], oldest-first;[]when exhausted), the building block for the seam walk. #226- Added
historyPageSize(ClientSessionOptions/AgentSessionOptions, default 100) to tune the history fetch size per round trip. #226 - The agent gains a real paginating, read-only
run.viewover the sameViewbase as the client, replacing its old messages-only read. #221
Bug Fixes
- The agent no longer feeds incomplete ancestor runs (still streaming, suspended, cancelled, or errored) into the model prompt, so a dangling tool call from a concurrent or interrupted turn no longer makes the provider reject the request. #237
- Fixed a stale message left at the end of the conversation after regenerating a non-head message in a multi-message reply. #215
- Vercel: two tabs sharing a
clientIdno longer error with "inputs array is empty"; a tab with no new inputs waits for the other tab's run and repaints when it completes. #224 - Fixed sends intermittently failing with
unable to send; channel is initializedafter a rapid subscribe/unsubscribe cycle (e.g. React StrictMode in development);connect()now attaches the channel explicitly. #229