You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs: align documentation with View-based write and navigation API
Updates 17 doc pages to reflect the architecture changes where
send/regenerate/edit moved from ClientTransport to View, and branch
navigation (select, getSelectedIndex) moved from Tree to View.
- Feature pages: transport.send() → view.send(), tree.select() → view.select()
- React hook reference: ViewHandle now includes write ops and navigation;
useSend/useRegenerate/useEdit accept View; useTree has structural queries only
- Internals: Tree is a pure data structure; selection lives on View;
transport exposes _internalSend via SendDelegate
- Glossary: updated own-turn and flatten definitions
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
-**[Get started](./docs/get-started/)** - [Vercel AI SDK with useChat](./docs/get-started/vercel-use-chat.md), [Vercel AI SDK with useClientTransport](./docs/get-started/vercel-use-client-transport.md)
378
378
-**[Frameworks](./docs/frameworks/)** - [Vercel AI SDK](./docs/frameworks/vercel-ai-sdk.md)
Copy file name to clipboardExpand all lines: docs/features/concurrent-turns.md
+3-4Lines changed: 3 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,12 +6,12 @@ Without concurrent turn support, a transport must serialize interactions: one re
6
6
7
7
## How it works
8
8
9
-
Each call to `send()`, `regenerate()`, or `edit()` on the client creates a new turn. On the server, each incoming request calls `newTurn()`. Turns are identified by `turnId` and tracked by `clientId`.
9
+
Each call to `view.send()`, `view.regenerate()`, or `view.edit()` on the client creates a new turn. On the server, each incoming request calls `newTurn()`. Turns are identified by `turnId` and tracked by `clientId`.
10
10
11
11
```typescript
12
12
// Client: two sends in quick succession create two concurrent turns
13
-
const turnA =awaittransport.send(messageA);
14
-
const turnB =awaittransport.send(messageB);
13
+
const turnA =awaitview.send(messageA);
14
+
const turnB =awaitview.send(messageB);
15
15
16
16
// Each has its own stream
17
17
const readerA =turnA.stream.getReader();
@@ -97,4 +97,3 @@ Concurrent turns happen in these scenarios:
97
97
-**Interruption without cancel** - user sends a new message without stopping the current response (see [Interruption](interruption.md))
98
98
-**Multi-user** - two users on the same channel both send messages (see [Multi-client sync](multi-client.md))
99
99
-**Multi-agent** - a server creates multiple turns for different agents responding to the same prompt
100
-
-**Parallel tool execution** - a server creates separate turns for parallel tool call results
Copy file name to clipboardExpand all lines: docs/features/history.md
+3-3Lines changed: 3 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
1
# History and replay
2
2
3
-
`transport.view.loadOlder(limit)` loads conversation history from the Ably channel. A new client - after a page refresh, on a new device, or joining mid-conversation - can hydrate the full conversation from channel history without a separate database.
3
+
`view.loadOlder(limit)` loads conversation history from the Ably channel. A new client - after a page refresh, on a new device, or joining mid-conversation - can hydrate the full conversation from channel history without a separate database.
4
4
5
5
Without persistent history, page refresh means starting over. With AI Transport, messages are persisted on the Ably channel and decoded through the same codec used for live streaming.
6
6
@@ -14,7 +14,7 @@ await view.loadOlder(30);
14
14
// Call loadOlder again to fetch more older messages
15
15
```
16
16
17
-
History messages are inserted into the transport's conversation tree and trigger an `'update'` notification on the view. After loading history, `transport.view.flattenNodes().map(n => n.message)` returns the combined history + live messages - flattened along the currently selected branch. If the history contains forks (from regeneration or editing), only the active branch is included. Use the conversation tree to navigate between branches (see [Conversation branching](branching.md)).
17
+
History messages are inserted into the transport's conversation tree and trigger an `'update'` notification on the view. After loading history, `view.flattenNodes().map(n => n.message)` returns the combined history + live messages - flattened along the currently selected branch. If the history contains forks (from regeneration or editing), only the active branch is included. Use the conversation tree to navigate between branches (see [Conversation branching](branching.md)).
18
18
19
19
The `limit` parameter controls how many **complete domain messages** to return, not how many Ably wire messages to fetch. A single assistant message may span dozens of Ably messages (one per append). The implementation pages through Ably history until `limit` complete messages have been assembled.
History messages carry the same `x-ably-parent` and `x-ably-fork-of` headers as live messages. When loaded, they're inserted into the conversation tree with their full branch structure intact. A client loading history sees the same tree of branches and can navigate siblings just like a client that was present for the original conversation.
68
68
69
-
Because the tree may contain multiple branches, the view's `flattenNodes()` returns only the messages along the currently selected path - not every message ever published. To see alternative branches, use `useTree` or the tree's `getSiblings()` / `select()` methods.
69
+
Because the tree may contain multiple branches, the view's `flattenNodes()` returns only the messages along the currently selected path - not every message ever published. To see alternative branches, use `useView` or the view's `getSiblings()` / `select()` methods.
70
70
71
71
See [Conversation branching](branching.md) for the tree model.
Copy file name to clipboardExpand all lines: docs/features/optimistic-updates.md
+7-7Lines changed: 7 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,7 +6,7 @@ Without optimistic insertion, the user would see a gap between pressing "send" a
6
6
7
7
## How it works
8
8
9
-
The client generates a unique message ID (`x-ably-msg-id`) for each user message and inserts it into the conversation tree with no [serial](../internals/glossary.md#serial-ably) (Ably's server-assigned ordering identifier). The message is visible via `transport.view.flattenNodes()` immediately. The HTTP POST to the server is [fire-and-forget](../internals/glossary.md#fire-and-forget) - `send()` returns without waiting for the server to respond.
9
+
The client generates a unique message ID (`x-ably-msg-id`) for each user message and inserts it into the conversation tree with no [serial](../internals/glossary.md#serial-ably) (Ably's server-assigned ordering identifier). The message is visible via `view.flattenNodes()` immediately. The HTTP POST to the server is [fire-and-forget](../internals/glossary.md#fire-and-forget) - `send()` returns without waiting for the server to respond.
10
10
11
11
The server receives the user message and relays it onto the Ably channel, preserving the original `x-ably-msg-id`. All clients on the channel - including the sender - receive this relay. The sending client recognises its own message by matching the `x-ably-msg-id` against the set of IDs it optimistically inserted. Instead of creating a duplicate, it updates the existing entry with the server-assigned serial, which moves the message from the end of the list to its correct position in serial order. This process is called [optimistic reconciliation](../internals/glossary.md#optimistic-reconciliation).
12
12
@@ -30,20 +30,20 @@ sequenceDiagram
30
30
Optimistic updates are automatic - there is no opt-in or configuration. Every call to `send()`, `edit()`, or `regenerate()` that includes user messages uses the same mechanism.
31
31
32
32
```typescript
33
-
const turn =awaittransport.send(userMessage);
33
+
const view =transport.view;
34
+
const turn =awaitview.send(userMessage);
34
35
35
36
// The user message is already in the view - no waiting for the server
Copy file name to clipboardExpand all lines: docs/features/streaming.md
+7-8Lines changed: 7 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,7 +6,7 @@ Without a durable transport, streaming responses are ephemeral: if the connectio
6
6
7
7
## How it works
8
8
9
-
The server encoder creates an Ably message for each content stream (text, reasoning, tool input) and appends token deltas as they arrive. The client decoder accumulates these appends into complete messages.
9
+
The server encoder creates an Ably message for each content stream (text, reasoning) and appends token deltas as they arrive. The client decoder accumulates these appends into complete messages.
10
10
11
11
```mermaid
12
12
sequenceDiagram
@@ -64,11 +64,12 @@ transport.close();
64
64
On the client, every streaming event is accumulated into the conversation tree as it arrives. The view updates on every event, so the last assistant message grows token by token:
65
65
66
66
```typescript
67
-
const turn =awaittransport.send(userMessage);
67
+
const view =transport.view;
68
+
const turn =awaitview.send(userMessage);
68
69
69
70
// Subscribe to accumulated messages - updates on every token
|`finish`| Discrete message (terminal - closes the stream) |
112
111
|`error`| Discrete message (terminal - closes the stream with error) |
113
112
114
-
Multiple content streams can be active within a single turn (e.g., reasoning + text, or multiple tool calls). Each gets its own message with its own stream ID.
113
+
Multiple content streams can be active within a single turn (e.g., reasoning + text). Each gets its own message with its own stream ID.
115
114
116
115
See [React hooks reference](../reference/react-hooks.md) for the full `useView` and `useClientTransport` API. See [Cancel](cancel.md) for how streams are aborted. For the internal mechanics of message encoding, decoding, and recovery, see the [Encoder](../internals/encoder.md), [Decoder](../internals/decoder.md), and [Wire protocol](../internals/wire-protocol.md) internals pages.
0 commit comments