@octavus/docs 0.0.6 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/content/01-getting-started/02-quickstart.md +28 -19
  2. package/content/02-server-sdk/01-overview.md +34 -17
  3. package/content/02-server-sdk/02-sessions.md +6 -3
  4. package/content/02-server-sdk/03-tools.md +4 -2
  5. package/content/02-server-sdk/04-streaming.md +12 -4
  6. package/content/03-client-sdk/01-overview.md +107 -42
  7. package/content/03-client-sdk/02-messages.md +71 -19
  8. package/content/03-client-sdk/03-streaming.md +38 -28
  9. package/content/03-client-sdk/05-socket-transport.md +414 -0
  10. package/content/03-client-sdk/06-http-transport.md +280 -0
  11. package/content/04-protocol/03-triggers.md +48 -21
  12. package/content/04-protocol/04-tools.md +25 -15
  13. package/content/05-api-reference/01-overview.md +3 -17
  14. package/content/06-examples/01-overview.md +27 -0
  15. package/content/06-examples/02-nextjs-chat.md +343 -0
  16. package/content/06-examples/03-socket-chat.md +392 -0
  17. package/content/06-examples/_meta.md +5 -0
  18. package/dist/chunk-232K4EME.js +439 -0
  19. package/dist/chunk-232K4EME.js.map +1 -0
  20. package/dist/chunk-2JDZLMS3.js +439 -0
  21. package/dist/chunk-2JDZLMS3.js.map +1 -0
  22. package/dist/chunk-5M7DS4DF.js +519 -0
  23. package/dist/chunk-5M7DS4DF.js.map +1 -0
  24. package/dist/chunk-7AS4ST73.js +421 -0
  25. package/dist/chunk-7AS4ST73.js.map +1 -0
  26. package/dist/chunk-H6JGSSAJ.js +519 -0
  27. package/dist/chunk-H6JGSSAJ.js.map +1 -0
  28. package/dist/chunk-JZRABTHU.js +519 -0
  29. package/dist/chunk-JZRABTHU.js.map +1 -0
  30. package/dist/chunk-OECAPVSX.js +439 -0
  31. package/dist/chunk-OECAPVSX.js.map +1 -0
  32. package/dist/chunk-OL5QDJ42.js +483 -0
  33. package/dist/chunk-OL5QDJ42.js.map +1 -0
  34. package/dist/chunk-PMOVVTHO.js +519 -0
  35. package/dist/chunk-PMOVVTHO.js.map +1 -0
  36. package/dist/chunk-R5MTVABN.js +439 -0
  37. package/dist/chunk-R5MTVABN.js.map +1 -0
  38. package/dist/chunk-RJ4H4YVA.js +519 -0
  39. package/dist/chunk-RJ4H4YVA.js.map +1 -0
  40. package/dist/chunk-S5U4IWCR.js +439 -0
  41. package/dist/chunk-S5U4IWCR.js.map +1 -0
  42. package/dist/chunk-UCJE36LL.js +519 -0
  43. package/dist/chunk-UCJE36LL.js.map +1 -0
  44. package/dist/chunk-WW7TRC7S.js +519 -0
  45. package/dist/chunk-WW7TRC7S.js.map +1 -0
  46. package/dist/content.js +1 -1
  47. package/dist/docs.json +57 -12
  48. package/dist/index.js +1 -1
  49. package/dist/search-index.json +1 -1
  50. package/dist/search.js +1 -1
  51. package/dist/search.js.map +1 -1
  52. package/dist/sections.json +65 -12
  53. package/package.json +2 -2
@@ -72,6 +72,7 @@ Create an endpoint that handles triggers and streams responses:
72
72
 
73
73
  ```typescript
74
74
  // app/api/trigger/route.ts
75
+ import { toSSEStream } from '@octavus/server-sdk';
75
76
  import { octavus } from '@/lib/octavus';
76
77
 
77
78
  export async function POST(request: Request) {
@@ -100,11 +101,11 @@ export async function POST(request: Request) {
100
101
  },
101
102
  });
102
103
 
103
- // Trigger the action and get the stream
104
- const { stream } = session.trigger(triggerName, input);
104
+ // Trigger the action and convert to SSE stream
105
+ const events = session.trigger(triggerName, input);
105
106
 
106
107
  // Return as streaming response
107
- return new Response(stream, {
108
+ return new Response(toSSEStream(events), {
108
109
  headers: {
109
110
  'Content-Type': 'text/event-stream',
110
111
  'Cache-Control': 'no-cache',
@@ -118,14 +119,14 @@ export async function POST(request: Request) {
118
119
 
119
120
  ### 1. Create a Chat Component
120
121
 
121
- Use the `useOctavusChat` hook to build a chat interface:
122
+ Use the `useOctavusChat` hook with the HTTP transport:
122
123
 
123
124
  ```tsx
124
125
  // components/chat.tsx
125
126
  'use client';
126
127
 
127
- import { useOctavusChat, type UIMessage } from '@octavus/react';
128
- import { useState } from 'react';
128
+ import { useState, useMemo } from 'react';
129
+ import { useOctavusChat, createHttpTransport, type UIMessage } from '@octavus/react';
129
130
 
130
131
  interface ChatProps {
131
132
  sessionId: string;
@@ -134,15 +135,21 @@ interface ChatProps {
134
135
  export function Chat({ sessionId }: ChatProps) {
135
136
  const [inputValue, setInputValue] = useState('');
136
137
 
137
- const { messages, status, error, send } = useOctavusChat({
138
- onTrigger: async (triggerName, input) => {
139
- return fetch('/api/trigger', {
140
- method: 'POST',
141
- headers: { 'Content-Type': 'application/json' },
142
- body: JSON.stringify({ sessionId, triggerName, input }),
143
- });
144
- },
145
- });
138
+ // Create a stable transport instance
139
+ const transport = useMemo(
140
+ () =>
141
+ createHttpTransport({
142
+ triggerRequest: (triggerName, input) =>
143
+ fetch('/api/trigger', {
144
+ method: 'POST',
145
+ headers: { 'Content-Type': 'application/json' },
146
+ body: JSON.stringify({ sessionId, triggerName, input }),
147
+ }),
148
+ }),
149
+ [sessionId],
150
+ );
151
+
152
+ const { messages, status, error, send } = useOctavusChat({ transport });
146
153
 
147
154
  const isStreaming = status === 'streaming';
148
155
 
@@ -154,9 +161,11 @@ export function Chat({ sessionId }: ChatProps) {
154
161
  setInputValue('');
155
162
 
156
163
  // Add user message and trigger in one call
157
- await send('user-message', { USER_MESSAGE: message }, {
158
- userMessage: { content: message },
159
- });
164
+ await send(
165
+ 'user-message',
166
+ { USER_MESSAGE: message },
167
+ { userMessage: { content: message } },
168
+ );
160
169
  };
161
170
 
162
171
  return (
@@ -208,7 +217,7 @@ function MessageBubble({ message }: { message: UIMessage }) {
208
217
  }
209
218
  return null;
210
219
  })}
211
-
220
+
212
221
  {/* Streaming indicator */}
213
222
  {message.status === 'streaming' && (
214
223
  <span className="inline-block w-2 h-4 bg-gray-400 animate-pulse ml-1" />
@@ -34,13 +34,13 @@ Create and manage agent sessions:
34
34
 
35
35
  ```typescript
36
36
  // Create a new session
37
- const sessionId = await client.agentSessions.create('support-chat', {
37
+ const sessionId = await client.agentSessions.create('agent-id', {
38
38
  COMPANY_NAME: 'Acme Corp',
39
39
  PRODUCT_NAME: 'Widget Pro',
40
40
  });
41
41
 
42
- // Get session state
43
- const state = await client.agentSessions.get(sessionId);
42
+ // Get UI-ready session messages (for session restore)
43
+ const session = await client.agentSessions.getMessages(sessionId);
44
44
  ```
45
45
 
46
46
  ### Tool Handlers
@@ -63,12 +63,15 @@ const session = client.agentSessions.attach(sessionId, {
63
63
  All responses stream in real-time:
64
64
 
65
65
  ```typescript
66
- const { stream } = session.trigger('user-message', {
67
- USER_MESSAGE: 'Hello!'
66
+ import { toSSEStream } from '@octavus/server-sdk';
67
+
68
+ // trigger() returns an async generator of events
69
+ const events = session.trigger('user-message', {
70
+ USER_MESSAGE: 'Hello!',
68
71
  });
69
72
 
70
- // Use as a streaming response
71
- return new Response(stream, {
73
+ // Convert to SSE stream for HTTP responses
74
+ return new Response(toSSEStream(events), {
72
75
  headers: { 'Content-Type': 'text/event-stream' },
73
76
  });
74
77
  ```
@@ -88,7 +91,7 @@ interface OctavusClientConfig {
88
91
  class OctavusClient {
89
92
  readonly agents: AgentsApi;
90
93
  readonly agentSessions: AgentSessionsApi;
91
-
94
+
92
95
  constructor(config: OctavusClientConfig);
93
96
  }
94
97
  ```
@@ -101,24 +104,35 @@ Manages agent sessions.
101
104
  class AgentSessionsApi {
102
105
  // Create a new session
103
106
  async create(agentId: string, input?: Record<string, unknown>): Promise<string>;
104
-
105
- // Get session state (includes UI-ready messages)
106
- async get(sessionId: string): Promise<UISessionState>;
107
-
107
+
108
+ // Get full session state (for debugging/internal use)
109
+ async get(sessionId: string): Promise<SessionState>;
110
+
111
+ // Get UI-ready messages (for client display)
112
+ async getMessages(sessionId: string): Promise<UISessionState>;
113
+
108
114
  // Attach to a session for triggering
109
115
  attach(sessionId: string, options?: SessionAttachOptions): AgentSession;
110
116
  }
111
117
 
112
- interface UISessionState {
118
+ // Full session state (internal format)
119
+ interface SessionState {
113
120
  id: string;
114
121
  agentId: string;
115
122
  input: Record<string, unknown>;
116
123
  variables: Record<string, unknown>;
117
124
  resources: Record<string, unknown>;
118
- messages: UIMessage[]; // UI-ready messages for session restore
125
+ messages: ChatMessage[]; // Internal message format
119
126
  createdAt: string;
120
127
  updatedAt: string;
121
128
  }
129
+
130
+ // UI-ready session state
131
+ interface UISessionState {
132
+ sessionId: string;
133
+ agentId: string;
134
+ messages: UIMessage[]; // UI-ready messages for frontend
135
+ }
122
136
  ```
123
137
 
124
138
  ### AgentSession
@@ -127,15 +141,18 @@ Handles triggering and streaming for a specific session.
127
141
 
128
142
  ```typescript
129
143
  class AgentSession {
130
- // Trigger an action and stream the response
144
+ // Trigger an action and stream parsed events
131
145
  trigger(
132
146
  triggerName: string,
133
147
  input?: Record<string, unknown>
134
- ): { stream: ReadableStream<Uint8Array> };
135
-
148
+ ): AsyncGenerator<StreamEvent>;
149
+
136
150
  // Get the session ID
137
151
  getSessionId(): string;
138
152
  }
153
+
154
+ // Helper to convert events to SSE stream
155
+ function toSSEStream(events: AsyncIterable<StreamEvent>): ReadableStream<Uint8Array>;
139
156
  ```
140
157
 
141
158
  ## Next Steps
@@ -95,12 +95,15 @@ const session = client.agentSessions.attach(sessionId, {
95
95
  Once attached, trigger actions on the session:
96
96
 
97
97
  ```typescript
98
- const { stream } = session.trigger('user-message', {
98
+ import { toSSEStream } from '@octavus/server-sdk';
99
+
100
+ // trigger() returns an async generator of events
101
+ const events = session.trigger('user-message', {
99
102
  USER_MESSAGE: 'How do I reset my password?',
100
103
  });
101
104
 
102
- // Return the stream to your frontend
103
- return new Response(stream, {
105
+ // Convert to SSE stream for HTTP responses
106
+ return new Response(toSSEStream(events), {
104
107
  headers: { 'Content-Type': 'text/event-stream' },
105
108
  });
106
109
  ```
@@ -168,6 +168,8 @@ sequenceDiagram
168
168
  For request-specific data (auth, headers), create handlers dynamically:
169
169
 
170
170
  ```typescript
171
+ import { toSSEStream } from '@octavus/server-sdk';
172
+
171
173
  // In your API route
172
174
  export async function POST(request: Request) {
173
175
  const authToken = request.headers.get('Authorization');
@@ -190,8 +192,8 @@ export async function POST(request: Request) {
190
192
  },
191
193
  });
192
194
 
193
- const { stream } = session.trigger(triggerName, input);
194
- return new Response(stream);
195
+ const events = session.trigger(triggerName, input);
196
+ return new Response(toSSEStream(events));
195
197
  }
196
198
  ```
197
199
 
@@ -9,21 +9,29 @@ All Octavus responses stream in real-time using Server-Sent Events (SSE). This e
9
9
 
10
10
  ## Stream Response
11
11
 
12
- When you trigger an action, you get a readable stream:
12
+ When you trigger an action, you get an async generator of parsed events:
13
13
 
14
14
  ```typescript
15
- const { stream } = session.trigger('user-message', {
15
+ import { toSSEStream } from '@octavus/server-sdk';
16
+
17
+ // trigger() returns an async generator of StreamEvent
18
+ const events = session.trigger('user-message', {
16
19
  USER_MESSAGE: 'Hello!'
17
20
  });
18
21
 
19
- // Return to frontend as streaming response
20
- return new Response(stream, {
22
+ // For HTTP endpoints, convert to SSE stream
23
+ return new Response(toSSEStream(events), {
21
24
  headers: {
22
25
  'Content-Type': 'text/event-stream',
23
26
  'Cache-Control': 'no-cache',
24
27
  'Connection': 'keep-alive',
25
28
  },
26
29
  });
30
+
31
+ // For sockets, iterate events directly
32
+ for await (const event of events) {
33
+ conn.write(JSON.stringify(event));
34
+ }
27
35
  ```
28
36
 
29
37
  ## Event Types
@@ -32,27 +32,50 @@ npm install @octavus/client-sdk
32
32
 
33
33
  **Current version:** `{{VERSION:@octavus/client-sdk}}`
34
34
 
35
+ ## Transport Pattern
36
+
37
+ The Client SDK uses a **transport abstraction** to handle communication with your backend. This gives you flexibility in how events are delivered:
38
+
39
+ | Transport | Use Case | Docs |
40
+ |-----------|----------|------|
41
+ | `createHttpTransport` | HTTP/SSE (Next.js, Express, etc.) | [HTTP Transport](/docs/client-sdk/http-transport) |
42
+ | `createSocketTransport` | WebSocket, SockJS, or other socket protocols | [Socket Transport](/docs/client-sdk/socket-transport) |
43
+
44
+ When the transport changes (e.g., when `sessionId` changes), the `useOctavusChat` hook automatically reinitializes with the new transport.
45
+
46
+ > **Recommendation**: Use HTTP transport unless you specifically need WebSocket features (custom real-time events, Meteor/Phoenix, etc.).
47
+
35
48
  ## React Usage
36
49
 
37
50
  The `useOctavusChat` hook provides state management and streaming for React applications:
38
51
 
39
52
  ```tsx
40
- import { useOctavusChat, type UIMessage } from '@octavus/react';
53
+ import { useMemo } from 'react';
54
+ import { useOctavusChat, createHttpTransport, type UIMessage } from '@octavus/react';
41
55
 
42
56
  function Chat({ sessionId }: { sessionId: string }) {
43
- const { messages, status, send } = useOctavusChat({
44
- onTrigger: async (triggerName, input) => {
45
- return fetch(`/api/trigger`, {
46
- method: 'POST',
47
- body: JSON.stringify({ sessionId, triggerName, input }),
48
- });
49
- },
50
- });
57
+ // Create a stable transport instance (memoized on sessionId)
58
+ const transport = useMemo(
59
+ () =>
60
+ createHttpTransport({
61
+ triggerRequest: (triggerName, input) =>
62
+ fetch('/api/trigger', {
63
+ method: 'POST',
64
+ headers: { 'Content-Type': 'application/json' },
65
+ body: JSON.stringify({ sessionId, triggerName, input }),
66
+ }),
67
+ }),
68
+ [sessionId],
69
+ );
70
+
71
+ const { messages, status, send } = useOctavusChat({ transport });
51
72
 
52
73
  const sendMessage = async (text: string) => {
53
- await send('user-message', { USER_MESSAGE: text }, {
54
- userMessage: { content: text },
55
- });
74
+ await send(
75
+ 'user-message',
76
+ { USER_MESSAGE: text },
77
+ { userMessage: { content: text } },
78
+ );
56
79
  };
57
80
 
58
81
  return (
@@ -83,17 +106,19 @@ function MessageBubble({ message }: { message: UIMessage }) {
83
106
  The `OctavusChat` class can be used with any framework or vanilla JavaScript:
84
107
 
85
108
  ```typescript
86
- import { OctavusChat } from '@octavus/client-sdk';
109
+ import { OctavusChat, createHttpTransport } from '@octavus/client-sdk';
87
110
 
88
- const chat = new OctavusChat({
89
- onTrigger: async (triggerName, input) => {
90
- return fetch('/api/trigger', {
111
+ const transport = createHttpTransport({
112
+ triggerRequest: (triggerName, input) =>
113
+ fetch('/api/trigger', {
91
114
  method: 'POST',
115
+ headers: { 'Content-Type': 'application/json' },
92
116
  body: JSON.stringify({ sessionId, triggerName, input }),
93
- });
94
- },
117
+ }),
95
118
  });
96
119
 
120
+ const chat = new OctavusChat({ transport });
121
+
97
122
  // Subscribe to state changes
98
123
  const unsubscribe = chat.subscribe(() => {
99
124
  console.log('Messages:', chat.messages);
@@ -102,9 +127,11 @@ const unsubscribe = chat.subscribe(() => {
102
127
  });
103
128
 
104
129
  // Send a message
105
- await chat.send('user-message', { USER_MESSAGE: 'Hello' }, {
106
- userMessage: { content: 'Hello' },
107
- });
130
+ await chat.send(
131
+ 'user-message',
132
+ { USER_MESSAGE: 'Hello' },
133
+ { userMessage: { content: 'Hello' } },
134
+ );
108
135
 
109
136
  // Cleanup when done
110
137
  unsubscribe();
@@ -117,12 +144,14 @@ unsubscribe();
117
144
  The `send` function handles both user message display and agent triggering in one call:
118
145
 
119
146
  ```tsx
120
- const { send } = useOctavusChat({...});
147
+ const { send } = useOctavusChat({ transport });
121
148
 
122
149
  // Add user message to UI and trigger agent
123
- await send('user-message', { USER_MESSAGE: text }, {
124
- userMessage: { content: text },
125
- });
150
+ await send(
151
+ 'user-message',
152
+ { USER_MESSAGE: text },
153
+ { userMessage: { content: text } },
154
+ );
126
155
 
127
156
  // Trigger without adding a user message (e.g., button click)
128
157
  await send('request-human');
@@ -133,7 +162,7 @@ await send('request-human');
133
162
  Messages contain ordered `parts` for rich content:
134
163
 
135
164
  ```tsx
136
- const { messages } = useOctavusChat({...});
165
+ const { messages } = useOctavusChat({ transport });
137
166
 
138
167
  // Each message has typed parts
139
168
  message.parts.map((part) => {
@@ -149,7 +178,7 @@ message.parts.map((part) => {
149
178
  ### Status Tracking
150
179
 
151
180
  ```tsx
152
- const { status } = useOctavusChat({...});
181
+ const { status } = useOctavusChat({ transport });
153
182
 
154
183
  // status: 'idle' | 'streaming' | 'error'
155
184
  ```
@@ -157,7 +186,7 @@ const { status } = useOctavusChat({...});
157
186
  ### Stop Streaming
158
187
 
159
188
  ```tsx
160
- const { stop } = useOctavusChat({...});
189
+ const { stop } = useOctavusChat({ transport });
161
190
 
162
191
  // Stop current stream and finalize message
163
192
  stop();
@@ -171,12 +200,12 @@ stop();
171
200
  function useOctavusChat(options: OctavusChatOptions): UseOctavusChatReturn;
172
201
 
173
202
  interface OctavusChatOptions {
174
- // Required: Function that calls your backend trigger endpoint
175
- onTrigger: TriggerFunction;
176
-
203
+ // Required: Transport for streaming events
204
+ transport: Transport;
205
+
177
206
  // Optional: Pre-populate with existing messages (session restore)
178
207
  initialMessages?: UIMessage[];
179
-
208
+
180
209
  // Optional: Callbacks
181
210
  onError?: (error: Error) => void;
182
211
  onFinish?: () => void;
@@ -188,7 +217,7 @@ interface UseOctavusChatReturn {
188
217
  messages: UIMessage[];
189
218
  status: ChatStatus; // 'idle' | 'streaming' | 'error'
190
219
  error: Error | null;
191
-
220
+
192
221
  // Actions
193
222
  send: (
194
223
  triggerName: string,
@@ -198,16 +227,49 @@ interface UseOctavusChatReturn {
198
227
  stop: () => void;
199
228
  }
200
229
 
201
- type TriggerFunction = (
202
- triggerName: string,
203
- input?: Record<string, unknown>,
204
- ) => Promise<Response>;
205
-
206
230
  interface UserMessageInput {
207
231
  content: string;
208
232
  }
209
233
  ```
210
234
 
235
+ ## Transport Reference
236
+
237
+ ### createHttpTransport
238
+
239
+ Creates an HTTP/SSE transport using native `fetch()`:
240
+
241
+ ```typescript
242
+ import { createHttpTransport } from '@octavus/react';
243
+
244
+ const transport = createHttpTransport({
245
+ triggerRequest: (triggerName, input) =>
246
+ fetch('/api/trigger', {
247
+ method: 'POST',
248
+ headers: { 'Content-Type': 'application/json' },
249
+ body: JSON.stringify({ sessionId, triggerName, input }),
250
+ }),
251
+ });
252
+ ```
253
+
254
+ ### createSocketTransport
255
+
256
+ Creates a WebSocket/SockJS transport for real-time connections:
257
+
258
+ ```typescript
259
+ import { createSocketTransport } from '@octavus/react';
260
+
261
+ const transport = createSocketTransport({
262
+ connect: () =>
263
+ new Promise((resolve, reject) => {
264
+ const ws = new WebSocket(`wss://api.example.com/stream?sessionId=${sessionId}`);
265
+ ws.onopen = () => resolve(ws);
266
+ ws.onerror = () => reject(new Error('Connection failed'));
267
+ }),
268
+ });
269
+ ```
270
+
271
+ For detailed WebSocket/SockJS usage including custom events, reconnection patterns, and server-side implementation, see [Socket Transport](/docs/client-sdk/socket-transport).
272
+
211
273
  ## Class Reference (Framework-Agnostic)
212
274
 
213
275
  ### OctavusChat
@@ -215,12 +277,12 @@ interface UserMessageInput {
215
277
  ```typescript
216
278
  class OctavusChat {
217
279
  constructor(options: OctavusChatOptions);
218
-
280
+
219
281
  // State (read-only)
220
282
  readonly messages: UIMessage[];
221
283
  readonly status: ChatStatus;
222
284
  readonly error: Error | null;
223
-
285
+
224
286
  // Actions
225
287
  send(
226
288
  triggerName: string,
@@ -228,7 +290,7 @@ class OctavusChat {
228
290
  options?: { userMessage?: UserMessageInput }
229
291
  ): Promise<void>;
230
292
  stop(): void;
231
-
293
+
232
294
  // Subscription
233
295
  subscribe(callback: () => void): () => void; // Returns unsubscribe function
234
296
  }
@@ -236,6 +298,9 @@ class OctavusChat {
236
298
 
237
299
  ## Next Steps
238
300
 
301
+ - [HTTP Transport](/docs/client-sdk/http-transport) — HTTP/SSE integration (recommended)
302
+ - [Socket Transport](/docs/client-sdk/socket-transport) — WebSocket and SockJS integration
239
303
  - [Messages](/docs/client-sdk/messages) — Working with message state
240
304
  - [Streaming](/docs/client-sdk/streaming) — Building streaming UIs
241
- - [Execution Blocks](/docs/client-sdk/execution-blocks) — Showing agent progress
305
+ - [Operations](/docs/client-sdk/execution-blocks) — Showing agent progress
306
+ - [Examples](/docs/examples/overview) — Complete working examples
@@ -24,10 +24,10 @@ interface UIMessage {
24
24
  Messages contain ordered `parts` that preserve content ordering:
25
25
 
26
26
  ```typescript
27
- type UIMessagePart =
28
- | UITextPart
29
- | UIReasoningPart
30
- | UIToolCallPart
27
+ type UIMessagePart =
28
+ | UITextPart
29
+ | UIReasoningPart
30
+ | UIToolCallPart
31
31
  | UIOperationPart;
32
32
 
33
33
  // Text content
@@ -73,13 +73,35 @@ interface UIOperationPart {
73
73
  ## Sending Messages
74
74
 
75
75
  ```tsx
76
- const { send } = useOctavusChat({...});
76
+ import { useMemo } from 'react';
77
+ import { useOctavusChat, createHttpTransport } from '@octavus/react';
78
+
79
+ function Chat({ sessionId }: { sessionId: string }) {
80
+ const transport = useMemo(
81
+ () =>
82
+ createHttpTransport({
83
+ triggerRequest: (triggerName, input) =>
84
+ fetch('/api/trigger', {
85
+ method: 'POST',
86
+ headers: { 'Content-Type': 'application/json' },
87
+ body: JSON.stringify({ sessionId, triggerName, input }),
88
+ }),
89
+ }),
90
+ [sessionId],
91
+ );
77
92
 
78
- async function handleSend(text: string) {
79
- // Add user message to UI and trigger agent
80
- await send('user-message', { USER_MESSAGE: text }, {
81
- userMessage: { content: text },
82
- });
93
+ const { send } = useOctavusChat({ transport });
94
+
95
+ async function handleSend(text: string) {
96
+ // Add user message to UI and trigger agent
97
+ await send(
98
+ 'user-message',
99
+ { USER_MESSAGE: text },
100
+ { userMessage: { content: text } },
101
+ );
102
+ }
103
+
104
+ // ...
83
105
  }
84
106
  ```
85
107
 
@@ -201,24 +223,54 @@ function PartRenderer({ part }: { part: UIMessagePart }) {
201
223
 
202
224
  ## Session Restore
203
225
 
204
- When restoring a session, pass existing messages:
226
+ When restoring a session, fetch messages from your backend and pass them to the hook:
205
227
 
206
228
  ```tsx
207
- // Fetch session state from your backend
208
- const sessionState = await fetchSession(sessionId);
229
+ import { useMemo } from 'react';
230
+ import { useOctavusChat, createHttpTransport, type UIMessage } from '@octavus/react';
209
231
 
210
- // Pass to hook
211
- const { messages } = useOctavusChat({
212
- initialMessages: sessionState.messages,
213
- onTrigger: ...
214
- });
232
+ interface ChatProps {
233
+ sessionId: string;
234
+ initialMessages: UIMessage[];
235
+ }
236
+
237
+ function Chat({ sessionId, initialMessages }: ChatProps) {
238
+ const transport = useMemo(
239
+ () =>
240
+ createHttpTransport({
241
+ triggerRequest: (triggerName, input) =>
242
+ fetch('/api/trigger', {
243
+ method: 'POST',
244
+ headers: { 'Content-Type': 'application/json' },
245
+ body: JSON.stringify({ sessionId, triggerName, input }),
246
+ }),
247
+ }),
248
+ [sessionId],
249
+ );
250
+
251
+ // Pass existing messages to restore the conversation
252
+ const { messages } = useOctavusChat({
253
+ transport,
254
+ initialMessages,
255
+ });
256
+
257
+ // ...
258
+ }
259
+ ```
260
+
261
+ On your backend, use `agentSessions.getMessages()` to fetch UI-ready messages:
262
+
263
+ ```typescript
264
+ // Server-side
265
+ const session = await client.agentSessions.getMessages(sessionId);
266
+ // session.messages is UIMessage[] ready for the client
215
267
  ```
216
268
 
217
269
  ## Callbacks
218
270
 
219
271
  ```tsx
220
272
  useOctavusChat({
221
- onTrigger: ...,
273
+ transport,
222
274
  onFinish: () => {
223
275
  console.log('Stream completed');
224
276
  // Scroll to bottom, play sound, etc.