@octavus/docs 0.0.5 → 0.0.7

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.
@@ -88,6 +88,6 @@ sequenceDiagram
88
88
 
89
89
  - [Quick Start](/docs/getting-started/quickstart) — Get your first agent running in minutes
90
90
  - [Server SDK](/docs/server-sdk/overview) — Learn about backend integration
91
- - [Client SDK](/docs/client-sdk/overview) — Build chat interfaces with React
91
+ - [Client SDK](/docs/client-sdk/overview) — Build chat interfaces with React (or other frameworks)
92
92
  - [Protocol Reference](/docs/protocol/overview) — Deep dive into agent protocols
93
93
 
@@ -21,8 +21,8 @@ Install the Octavus SDKs in your project:
21
21
  # Server SDK for backend
22
22
  npm install @octavus/server-sdk
23
23
 
24
- # Client SDK for frontend (React)
25
- npm install @octavus/client-sdk
24
+ # React bindings for frontend
25
+ npm install @octavus/react
26
26
  ```
27
27
 
28
28
  ## Backend Setup
@@ -118,14 +118,14 @@ export async function POST(request: Request) {
118
118
 
119
119
  ### 1. Create a Chat Component
120
120
 
121
- Use the `useOctavusChat` hook to build a chat interface:
121
+ Use the `useOctavusChat` hook with the HTTP transport:
122
122
 
123
123
  ```tsx
124
124
  // components/chat.tsx
125
125
  'use client';
126
126
 
127
- import { useOctavusChat, type UIMessage } from '@octavus/client-sdk';
128
- import { useState } from 'react';
127
+ import { useState, useMemo } from 'react';
128
+ import { useOctavusChat, createHttpTransport, type UIMessage } from '@octavus/react';
129
129
 
130
130
  interface ChatProps {
131
131
  sessionId: string;
@@ -134,15 +134,21 @@ interface ChatProps {
134
134
  export function Chat({ sessionId }: ChatProps) {
135
135
  const [inputValue, setInputValue] = useState('');
136
136
 
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
- });
137
+ // Create a stable transport instance
138
+ const transport = useMemo(
139
+ () =>
140
+ createHttpTransport({
141
+ triggerRequest: (triggerName, input) =>
142
+ fetch('/api/trigger', {
143
+ method: 'POST',
144
+ headers: { 'Content-Type': 'application/json' },
145
+ body: JSON.stringify({ sessionId, triggerName, input }),
146
+ }),
147
+ }),
148
+ [sessionId],
149
+ );
150
+
151
+ const { messages, status, error, send } = useOctavusChat({ transport });
146
152
 
147
153
  const isStreaming = status === 'streaming';
148
154
 
@@ -154,9 +160,11 @@ export function Chat({ sessionId }: ChatProps) {
154
160
  setInputValue('');
155
161
 
156
162
  // Add user message and trigger in one call
157
- await send('user-message', { USER_MESSAGE: message }, {
158
- userMessage: { content: message },
159
- });
163
+ await send(
164
+ 'user-message',
165
+ { USER_MESSAGE: message },
166
+ { userMessage: { content: message } },
167
+ );
160
168
  };
161
169
 
162
170
  return (
@@ -208,7 +216,7 @@ function MessageBubble({ message }: { message: UIMessage }) {
208
216
  }
209
217
  return null;
210
218
  })}
211
-
219
+
212
220
  {/* Streaming indicator */}
213
221
  {message.status === 'streaming' && (
214
222
  <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,8 +63,8 @@ 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
+ const { stream } = session.trigger('user-message', {
67
+ USER_MESSAGE: 'Hello!',
68
68
  });
69
69
 
70
70
  // Use as a streaming response
@@ -88,7 +88,7 @@ interface OctavusClientConfig {
88
88
  class OctavusClient {
89
89
  readonly agents: AgentsApi;
90
90
  readonly agentSessions: AgentSessionsApi;
91
-
91
+
92
92
  constructor(config: OctavusClientConfig);
93
93
  }
94
94
  ```
@@ -101,24 +101,35 @@ Manages agent sessions.
101
101
  class AgentSessionsApi {
102
102
  // Create a new session
103
103
  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
-
104
+
105
+ // Get full session state (for debugging/internal use)
106
+ async get(sessionId: string): Promise<SessionState>;
107
+
108
+ // Get UI-ready messages (for client display)
109
+ async getMessages(sessionId: string): Promise<UISessionState>;
110
+
108
111
  // Attach to a session for triggering
109
112
  attach(sessionId: string, options?: SessionAttachOptions): AgentSession;
110
113
  }
111
114
 
112
- interface UISessionState {
115
+ // Full session state (internal format)
116
+ interface SessionState {
113
117
  id: string;
114
118
  agentId: string;
115
119
  input: Record<string, unknown>;
116
120
  variables: Record<string, unknown>;
117
121
  resources: Record<string, unknown>;
118
- messages: UIMessage[]; // UI-ready messages for session restore
122
+ messages: ChatMessage[]; // Internal message format
119
123
  createdAt: string;
120
124
  updatedAt: string;
121
125
  }
126
+
127
+ // UI-ready session state
128
+ interface UISessionState {
129
+ sessionId: string;
130
+ agentId: string;
131
+ messages: UIMessage[]; // UI-ready messages for frontend
132
+ }
122
133
  ```
123
134
 
124
135
  ### AgentSession
@@ -132,7 +143,7 @@ class AgentSession {
132
143
  triggerName: string,
133
144
  input?: Record<string, unknown>
134
145
  ): { stream: ReadableStream<Uint8Array> };
135
-
146
+
136
147
  // Get the session ID
137
148
  getSessionId(): string;
138
149
  }
@@ -1,39 +1,77 @@
1
1
  ---
2
2
  title: Overview
3
- description: Introduction to the Octavus Client SDK for building chat interfaces.
3
+ description: Introduction to the Octavus Client SDKs for building chat interfaces.
4
4
  ---
5
5
 
6
6
  # Client SDK Overview
7
7
 
8
- The `@octavus/client-sdk` package provides React hooks for building chat interfaces with Octavus agents. It handles streaming, message state, and real-time updates.
8
+ Octavus provides two packages for frontend integration:
9
9
 
10
- **Current version:** `{{VERSION:@octavus/client-sdk}}`
10
+ | Package | Purpose | Use When |
11
+ |---------|---------|----------|
12
+ | `@octavus/react` | React hooks and bindings | Building React applications |
13
+ | `@octavus/client-sdk` | Framework-agnostic core | Using Vue, Svelte, vanilla JS, or custom integrations |
14
+
15
+ **Most users should install `@octavus/react`** — it includes everything from `@octavus/client-sdk` plus React-specific hooks.
11
16
 
12
17
  ## Installation
13
18
 
19
+ ### React Applications
20
+
21
+ ```bash
22
+ npm install @octavus/react
23
+ ```
24
+
25
+ **Current version:** `{{VERSION:@octavus/react}}`
26
+
27
+ ### Other Frameworks
28
+
14
29
  ```bash
15
30
  npm install @octavus/client-sdk
16
31
  ```
17
32
 
18
- ## Basic Usage
33
+ **Current version:** `{{VERSION:@octavus/client-sdk}}`
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 |
40
+ |-----------|----------|
41
+ | `createHttpTransport` | HTTP/SSE (Next.js, Express, etc.) |
42
+ | `createSocketTransport` | WebSocket, SockJS, or other socket protocols |
43
+
44
+ ## React Usage
45
+
46
+ The `useOctavusChat` hook provides state management and streaming for React applications:
19
47
 
20
48
  ```tsx
21
- import { useOctavusChat, type UIMessage } from '@octavus/client-sdk';
49
+ import { useMemo } from 'react';
50
+ import { useOctavusChat, createHttpTransport, type UIMessage } from '@octavus/react';
22
51
 
23
52
  function Chat({ sessionId }: { sessionId: string }) {
24
- const { messages, status, send } = useOctavusChat({
25
- onTrigger: async (triggerName, input) => {
26
- return fetch(`/api/trigger`, {
27
- method: 'POST',
28
- body: JSON.stringify({ sessionId, triggerName, input }),
29
- });
30
- },
31
- });
53
+ // Create a stable transport instance (memoized on sessionId)
54
+ const transport = useMemo(
55
+ () =>
56
+ createHttpTransport({
57
+ triggerRequest: (triggerName, input) =>
58
+ fetch('/api/trigger', {
59
+ method: 'POST',
60
+ headers: { 'Content-Type': 'application/json' },
61
+ body: JSON.stringify({ sessionId, triggerName, input }),
62
+ }),
63
+ }),
64
+ [sessionId],
65
+ );
66
+
67
+ const { messages, status, send } = useOctavusChat({ transport });
32
68
 
33
69
  const sendMessage = async (text: string) => {
34
- await send('user-message', { USER_MESSAGE: text }, {
35
- userMessage: { content: text },
36
- });
70
+ await send(
71
+ 'user-message',
72
+ { USER_MESSAGE: text },
73
+ { userMessage: { content: text } },
74
+ );
37
75
  };
38
76
 
39
77
  return (
@@ -59,6 +97,42 @@ function MessageBubble({ message }: { message: UIMessage }) {
59
97
  }
60
98
  ```
61
99
 
100
+ ## Framework-Agnostic Usage
101
+
102
+ The `OctavusChat` class can be used with any framework or vanilla JavaScript:
103
+
104
+ ```typescript
105
+ import { OctavusChat, createHttpTransport } from '@octavus/client-sdk';
106
+
107
+ const transport = createHttpTransport({
108
+ triggerRequest: (triggerName, input) =>
109
+ fetch('/api/trigger', {
110
+ method: 'POST',
111
+ headers: { 'Content-Type': 'application/json' },
112
+ body: JSON.stringify({ sessionId, triggerName, input }),
113
+ }),
114
+ });
115
+
116
+ const chat = new OctavusChat({ transport });
117
+
118
+ // Subscribe to state changes
119
+ const unsubscribe = chat.subscribe(() => {
120
+ console.log('Messages:', chat.messages);
121
+ console.log('Status:', chat.status);
122
+ // Update your UI here
123
+ });
124
+
125
+ // Send a message
126
+ await chat.send(
127
+ 'user-message',
128
+ { USER_MESSAGE: 'Hello' },
129
+ { userMessage: { content: 'Hello' } },
130
+ );
131
+
132
+ // Cleanup when done
133
+ unsubscribe();
134
+ ```
135
+
62
136
  ## Key Features
63
137
 
64
138
  ### Unified Send Function
@@ -66,12 +140,14 @@ function MessageBubble({ message }: { message: UIMessage }) {
66
140
  The `send` function handles both user message display and agent triggering in one call:
67
141
 
68
142
  ```tsx
69
- const { send } = useOctavusChat({...});
143
+ const { send } = useOctavusChat({ transport });
70
144
 
71
145
  // Add user message to UI and trigger agent
72
- await send('user-message', { USER_MESSAGE: text }, {
73
- userMessage: { content: text },
74
- });
146
+ await send(
147
+ 'user-message',
148
+ { USER_MESSAGE: text },
149
+ { userMessage: { content: text } },
150
+ );
75
151
 
76
152
  // Trigger without adding a user message (e.g., button click)
77
153
  await send('request-human');
@@ -82,7 +158,7 @@ await send('request-human');
82
158
  Messages contain ordered `parts` for rich content:
83
159
 
84
160
  ```tsx
85
- const { messages } = useOctavusChat({...});
161
+ const { messages } = useOctavusChat({ transport });
86
162
 
87
163
  // Each message has typed parts
88
164
  message.parts.map((part) => {
@@ -98,7 +174,7 @@ message.parts.map((part) => {
98
174
  ### Status Tracking
99
175
 
100
176
  ```tsx
101
- const { status } = useOctavusChat({...});
177
+ const { status } = useOctavusChat({ transport });
102
178
 
103
179
  // status: 'idle' | 'streaming' | 'error'
104
180
  ```
@@ -106,26 +182,26 @@ const { status } = useOctavusChat({...});
106
182
  ### Stop Streaming
107
183
 
108
184
  ```tsx
109
- const { stop } = useOctavusChat({...});
185
+ const { stop } = useOctavusChat({ transport });
110
186
 
111
187
  // Stop current stream and finalize message
112
188
  stop();
113
189
  ```
114
190
 
115
- ## Hook Reference
191
+ ## Hook Reference (React)
116
192
 
117
193
  ### useOctavusChat
118
194
 
119
195
  ```typescript
120
- function useOctavusChat(options: UseOctavusChatOptions): UseOctavusChatReturn;
196
+ function useOctavusChat(options: OctavusChatOptions): UseOctavusChatReturn;
197
+
198
+ interface OctavusChatOptions {
199
+ // Required: Transport for streaming events
200
+ transport: Transport;
121
201
 
122
- interface UseOctavusChatOptions {
123
- // Required: Function that calls your backend trigger endpoint
124
- onTrigger: TriggerFunction;
125
-
126
202
  // Optional: Pre-populate with existing messages (session restore)
127
203
  initialMessages?: UIMessage[];
128
-
204
+
129
205
  // Optional: Callbacks
130
206
  onError?: (error: Error) => void;
131
207
  onFinish?: () => void;
@@ -137,7 +213,7 @@ interface UseOctavusChatReturn {
137
213
  messages: UIMessage[];
138
214
  status: ChatStatus; // 'idle' | 'streaming' | 'error'
139
215
  error: Error | null;
140
-
216
+
141
217
  // Actions
142
218
  send: (
143
219
  triggerName: string,
@@ -147,18 +223,78 @@ interface UseOctavusChatReturn {
147
223
  stop: () => void;
148
224
  }
149
225
 
150
- type TriggerFunction = (
151
- triggerName: string,
152
- input?: Record<string, unknown>,
153
- ) => Promise<Response>;
154
-
155
226
  interface UserMessageInput {
156
227
  content: string;
157
228
  }
158
229
  ```
159
230
 
231
+ ## Transport Reference
232
+
233
+ ### createHttpTransport
234
+
235
+ Creates an HTTP/SSE transport using native `fetch()`:
236
+
237
+ ```typescript
238
+ import { createHttpTransport } from '@octavus/react';
239
+
240
+ const transport = 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
+ ```
249
+
250
+ ### createSocketTransport
251
+
252
+ Creates a WebSocket/SockJS transport for real-time connections:
253
+
254
+ ```typescript
255
+ import { createSocketTransport } from '@octavus/react';
256
+
257
+ const transport = createSocketTransport({
258
+ connect: () =>
259
+ new Promise((resolve, reject) => {
260
+ const ws = new WebSocket(`wss://api.example.com/stream?sessionId=${sessionId}`);
261
+ ws.onopen = () => resolve(ws);
262
+ ws.onerror = () => reject(new Error('Connection failed'));
263
+ }),
264
+ });
265
+ ```
266
+
267
+ For detailed WebSocket/SockJS usage including custom events, reconnection patterns, and server-side implementation, see [Socket Transport](/docs/client-sdk/socket-transport).
268
+
269
+ ## Class Reference (Framework-Agnostic)
270
+
271
+ ### OctavusChat
272
+
273
+ ```typescript
274
+ class OctavusChat {
275
+ constructor(options: OctavusChatOptions);
276
+
277
+ // State (read-only)
278
+ readonly messages: UIMessage[];
279
+ readonly status: ChatStatus;
280
+ readonly error: Error | null;
281
+
282
+ // Actions
283
+ send(
284
+ triggerName: string,
285
+ input?: Record<string, unknown>,
286
+ options?: { userMessage?: UserMessageInput }
287
+ ): Promise<void>;
288
+ stop(): void;
289
+
290
+ // Subscription
291
+ subscribe(callback: () => void): () => void; // Returns unsubscribe function
292
+ }
293
+ ```
294
+
160
295
  ## Next Steps
161
296
 
162
297
  - [Messages](/docs/client-sdk/messages) — Working with message state
163
298
  - [Streaming](/docs/client-sdk/streaming) — Building streaming UIs
164
- - [Execution Blocks](/docs/client-sdk/execution-blocks) — Showing agent progress
299
+ - [Operations](/docs/client-sdk/execution-blocks) — Showing agent progress
300
+ - [Socket Transport](/docs/client-sdk/socket-transport) — WebSocket and SockJS integration
@@ -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
 
@@ -121,7 +143,7 @@ function MessageBubble({ message }: { message: UIMessage }) {
121
143
  ### Rendering Parts
122
144
 
123
145
  ```tsx
124
- import { isOtherThread, type UIMessagePart } from '@octavus/client-sdk';
146
+ import { isOtherThread, type UIMessagePart } from '@octavus/react';
125
147
 
126
148
  function PartRenderer({ part }: { part: UIMessagePart }) {
127
149
  // Check if part belongs to a named thread (e.g., "summary")
@@ -180,7 +202,7 @@ function TextPart({ part }: { part: UITextPart }) {
180
202
  Content from named threads (like "summary") is identified by the `thread` property. Use the `isOtherThread` helper:
181
203
 
182
204
  ```tsx
183
- import { isOtherThread } from '@octavus/client-sdk';
205
+ import { isOtherThread } from '@octavus/react';
184
206
 
185
207
  function PartRenderer({ part }: { part: UIMessagePart }) {
186
208
  if (isOtherThread(part)) {
@@ -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.