@@ -280,7 +280,7 @@ message ID remains unknown until AI SDK first publishes the response and may
280280then come from the server. Message-based helpers resolve the run associated with
281281that node after this binding occurs.
282282
283- ` Thread ` creates a ` ThreadRunChat ` when ` sendMessage ` , ` startRun ` , or a
283+ ` AbstractThread ` creates a ` ThreadRunChat ` when ` sendMessage ` , ` startRun ` , or a
284284reconnection needs an AI SDK request lifecycle. Completed run records are
285285currently retained so their status and ownership information remain
286286addressable.
@@ -291,16 +291,27 @@ run has independent status, error, request serialization, and cancellation.
291291Automatic tool continuations remain in the same run and update the same
292292assistant response node.
293293
294- A new live run requires a non-assistant response parent. AI SDK interprets an
295- assistant message at the end of a request as the response to continue, not as
296- the parent of another response. Therefore, a bare ` startRun ` from an assistant
297- message is rejected. Branching from an assistant remains supported by attaching
298- a new input message with ` sendMessage ` and generating from that input.
294+ A new independent response requires a non-assistant response parent. AI SDK
295+ interprets an assistant message at the end of a request as the response to
296+ continue, not as the parent of another response. Therefore, a bare ` startRun `
297+ from an assistant message is rejected.
298+
299+ The ` useChat ` -compatible ` sendMessage ` surface keeps AI SDK's continuation
300+ semantics. Calling ` sendMessage() ` on a selected assistant continues that node,
301+ and passing an explicit assistant message attaches and streams into that same
302+ message ID. Neither operation creates a child response under the assistant.
303+ Applications create a branch below an assistant by attaching a new input
304+ message and generating from that input.
299305
300306This is a ` Thread ` live-run invariant, not a ` MessageTree ` invariant. The
301307tree remains role-agnostic so persisted, restored, or server-created data may
302308contain assistant-to-assistant edges.
303309
310+ Reconnection does not create response topology. It reactivates the existing
311+ assistant node, so its parent may have any role or be ` null ` . Resume checks
312+ concurrency capacity but does not apply the new-response parent-role rule,
313+ matching AI SDK's ` resumeStream ` behavior over the current message history.
314+
304315## AI SDK Integration
305316
306317` ThreadRunChat ` extends AI SDK's ` AbstractChat ` for one run. It reuses AI SDK
@@ -315,9 +326,10 @@ behavior for:
315326- ` sendAutomaticallyWhen `
316327- regeneration and reconnection
317328
318- The internal ` ThreadRunState ` presents one linear branch path to
319- ` AbstractChat ` . It writes accumulated assistant snapshots into ` Thread `
320- when AI SDK publishes the streaming response.
329+ The internal ` ThreadRunState ` presents one run-local linear branch path to
330+ ` AbstractChat ` . AI SDK may truncate that local path for regeneration without
331+ deleting nodes from the canonical tree. The state writes accumulated assistant
332+ snapshots into ` Thread ` when AI SDK publishes the streaming response.
321333
322334` ThreadRunChat ` does not insert a synthetic response into that path. AI SDK
323335creates the provisional assistant response using its normal last-message rules
@@ -369,6 +381,34 @@ As in AI SDK, expected transport and stream failures resolve after publishing
369381` AbstractChat ` reject ` sendMessage ` , ` resumeRun ` , and the corresponding
370382` finished ` promise.
371383
384+ ## Regeneration
385+
386+ ` regenerate({ messageId }) ` invokes ` AbstractChat.regenerate ` inside an isolated
387+ run adapter. The transport therefore receives AI SDK's native
388+ ` regenerate-message ` trigger and target ` messageId ` .
389+
390+ AI SDK truncates only the adapter's linear request path. The canonical tree
391+ retains the target response, then inserts the streamed replacement beside it
392+ using the run's reserved sibling order. A root assistant regenerates into
393+ another root. The cursor follows the replacement on its first write only when
394+ it still points to the regeneration target, so navigation during submission or
395+ streaming is not overwritten.
396+
397+ ### Known AI SDK Blocker
398+
399+ Regenerating an assistant whose parent is another assistant remains rejected.
400+ This is blocked by an AI SDK regeneration bug: after truncating the path to the
401+ assistant parent, AI SDK treats that trailing assistant as the response to
402+ continue. Regenerating ` [user, assistant A, assistant B] ` therefore produces
403+ ` [user, assistant A'] ` instead of creating a replacement sibling for
404+ ` assistant B ` .
405+
406+ The intended tree result is to preserve ` assistant B ` and create another child
407+ of ` assistant A ` . Once AI SDK distinguishes regeneration from normal trailing
408+ assistant continuation, ` Thread ` can remove this rejection and keep using the
409+ native regeneration lifecycle. Until then, rejecting the operation avoids
410+ silently mutating a shared ancestor.
411+
372412## Status and Cancellation
373413
374414Runs use the AI SDK ` ChatStatus ` values:
0 commit comments