@octavus/docs 0.0.1
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.
- package/LICENSE +22 -0
- package/content/01-getting-started/01-introduction.md +93 -0
- package/content/01-getting-started/02-quickstart.md +268 -0
- package/content/01-getting-started/_meta.md +4 -0
- package/content/02-server-sdk/01-overview.md +133 -0
- package/content/02-server-sdk/02-sessions.md +164 -0
- package/content/02-server-sdk/03-tools.md +242 -0
- package/content/02-server-sdk/04-streaming.md +211 -0
- package/content/02-server-sdk/_meta.md +4 -0
- package/content/03-client-sdk/01-overview.md +148 -0
- package/content/03-client-sdk/02-messages.md +207 -0
- package/content/03-client-sdk/03-streaming.md +215 -0
- package/content/03-client-sdk/04-execution-blocks.md +231 -0
- package/content/03-client-sdk/_meta.md +4 -0
- package/content/04-protocol/01-overview.md +142 -0
- package/content/04-protocol/02-input-resources.md +200 -0
- package/content/04-protocol/03-triggers.md +209 -0
- package/content/04-protocol/04-tools.md +255 -0
- package/content/04-protocol/05-handlers.md +251 -0
- package/content/04-protocol/06-agent-config.md +215 -0
- package/content/04-protocol/_meta.md +4 -0
- package/content/05-api-reference/01-overview.md +129 -0
- package/content/05-api-reference/02-sessions.md +232 -0
- package/content/05-api-reference/03-agents.md +222 -0
- package/content/05-api-reference/_meta.md +4 -0
- package/dist/chunk-2YMRODFE.js +421 -0
- package/dist/chunk-2YMRODFE.js.map +1 -0
- package/dist/chunk-6JQ3OMGF.js +421 -0
- package/dist/chunk-6JQ3OMGF.js.map +1 -0
- package/dist/chunk-ESGSYVGK.js +421 -0
- package/dist/chunk-ESGSYVGK.js.map +1 -0
- package/dist/chunk-GDCTM2SV.js +421 -0
- package/dist/chunk-GDCTM2SV.js.map +1 -0
- package/dist/chunk-J26MLMLN.js +421 -0
- package/dist/chunk-J26MLMLN.js.map +1 -0
- package/dist/chunk-LWYMRXBF.js +421 -0
- package/dist/chunk-LWYMRXBF.js.map +1 -0
- package/dist/chunk-NFVJQNDP.js +421 -0
- package/dist/chunk-NFVJQNDP.js.map +1 -0
- package/dist/chunk-SCKIOGKI.js +421 -0
- package/dist/chunk-SCKIOGKI.js.map +1 -0
- package/dist/chunk-VWPQ6ORV.js +421 -0
- package/dist/chunk-VWPQ6ORV.js.map +1 -0
- package/dist/chunk-WUNFFJ32.js +421 -0
- package/dist/chunk-WUNFFJ32.js.map +1 -0
- package/dist/chunk-XVSMRXBJ.js +421 -0
- package/dist/chunk-XVSMRXBJ.js.map +1 -0
- package/dist/content.d.ts +37 -0
- package/dist/content.js +17 -0
- package/dist/content.js.map +1 -0
- package/dist/docs.json +173 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/search-index.json +1 -0
- package/dist/search.d.ts +19 -0
- package/dist/search.js +30 -0
- package/dist/search.js.map +1 -0
- package/dist/sections.json +213 -0
- package/dist/types-BNRNBPDE.d.ts +28 -0
- package/dist/types-BltYGlWI.d.ts +36 -0
- package/package.json +52 -0
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Tools
|
|
3
|
+
description: Implementing tool handlers with the Server SDK.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Tools
|
|
7
|
+
|
|
8
|
+
Tools extend what agents can do. In Octavus, tools execute on your server, giving you full control over data access and authentication.
|
|
9
|
+
|
|
10
|
+
## Why Tools Run on Your Server
|
|
11
|
+
|
|
12
|
+
Unlike traditional AI platforms where tools run in a sandbox, Octavus tools execute in your backend:
|
|
13
|
+
|
|
14
|
+
- ✅ **Full data access** — Query your database directly
|
|
15
|
+
- ✅ **Your authentication** — Use your existing auth context
|
|
16
|
+
- ✅ **No data exposure** — Sensitive data never leaves your infrastructure
|
|
17
|
+
- ✅ **Custom logic** — Any complexity you need
|
|
18
|
+
|
|
19
|
+
## Defining Tool Handlers
|
|
20
|
+
|
|
21
|
+
Tool handlers are async functions that receive arguments and return results:
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
import type { ToolHandlers } from '@octavus/server-sdk';
|
|
25
|
+
|
|
26
|
+
const tools: ToolHandlers = {
|
|
27
|
+
'get-user-account': async (args) => {
|
|
28
|
+
const userId = args.userId as string;
|
|
29
|
+
|
|
30
|
+
// Query your database
|
|
31
|
+
const user = await db.users.findById(userId);
|
|
32
|
+
|
|
33
|
+
return {
|
|
34
|
+
name: user.name,
|
|
35
|
+
email: user.email,
|
|
36
|
+
plan: user.subscription.plan,
|
|
37
|
+
createdAt: user.createdAt.toISOString(),
|
|
38
|
+
};
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
'create-support-ticket': async (args) => {
|
|
42
|
+
const summary = args.summary as string;
|
|
43
|
+
const priority = args.priority as string;
|
|
44
|
+
|
|
45
|
+
// Create ticket in your system
|
|
46
|
+
const ticket = await ticketService.create({
|
|
47
|
+
summary,
|
|
48
|
+
priority,
|
|
49
|
+
source: 'ai-chat',
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
ticketId: ticket.id,
|
|
54
|
+
estimatedResponse: getEstimatedResponse(priority),
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Using Tools in Sessions
|
|
61
|
+
|
|
62
|
+
Pass tool handlers when attaching to a session:
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
const session = client.agentSessions.attach(sessionId, {
|
|
66
|
+
tools: {
|
|
67
|
+
'get-user-account': async (args) => {
|
|
68
|
+
// Implementation
|
|
69
|
+
},
|
|
70
|
+
'create-support-ticket': async (args) => {
|
|
71
|
+
// Implementation
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Tool Handler Signature
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
type ToolHandler = (args: Record<string, unknown>) => Promise<unknown>;
|
|
81
|
+
type ToolHandlers = Record<string, ToolHandler>;
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Arguments
|
|
85
|
+
|
|
86
|
+
Arguments are passed as a `Record<string, unknown>`. Type-check as needed:
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
'search-products': async (args) => {
|
|
90
|
+
const query = args.query as string;
|
|
91
|
+
const category = args.category as string | undefined;
|
|
92
|
+
const maxPrice = args.maxPrice as number | undefined;
|
|
93
|
+
|
|
94
|
+
return await productSearch({ query, category, maxPrice });
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Return Values
|
|
99
|
+
|
|
100
|
+
Return any JSON-serializable value. The result is:
|
|
101
|
+
1. Sent back to the LLM as context
|
|
102
|
+
2. Stored in session state
|
|
103
|
+
3. Optionally stored in a variable for protocol use
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
// Return object
|
|
107
|
+
return { id: '123', status: 'created' };
|
|
108
|
+
|
|
109
|
+
// Return array
|
|
110
|
+
return [{ id: '1' }, { id: '2' }];
|
|
111
|
+
|
|
112
|
+
// Return primitive
|
|
113
|
+
return 42;
|
|
114
|
+
|
|
115
|
+
// Return null for "no result"
|
|
116
|
+
return null;
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Error Handling
|
|
120
|
+
|
|
121
|
+
Throw errors for failures. They're captured and sent to the LLM:
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
'get-user-account': async (args) => {
|
|
125
|
+
const userId = args.userId as string;
|
|
126
|
+
|
|
127
|
+
const user = await db.users.findById(userId);
|
|
128
|
+
|
|
129
|
+
if (!user) {
|
|
130
|
+
throw new Error(`User not found: ${userId}`);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return user;
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
The LLM receives the error message and can respond appropriately (e.g., "I couldn't find that account").
|
|
138
|
+
|
|
139
|
+
## Tool Execution Flow
|
|
140
|
+
|
|
141
|
+
When the LLM calls a tool:
|
|
142
|
+
|
|
143
|
+
```mermaid
|
|
144
|
+
sequenceDiagram
|
|
145
|
+
participant LLM
|
|
146
|
+
participant Platform as Octavus Platform
|
|
147
|
+
participant SDK as Server SDK
|
|
148
|
+
participant UI as Your Frontend
|
|
149
|
+
|
|
150
|
+
LLM->>Platform: 1. Decides to call tool
|
|
151
|
+
Platform-->>UI: tool-call-start, tool-call-args
|
|
152
|
+
Platform-->>SDK: 2. tool-request (stream pauses)
|
|
153
|
+
|
|
154
|
+
Note over SDK: 3. Execute handler<br/>tools['get-user']()
|
|
155
|
+
|
|
156
|
+
SDK-->>UI: 4. tool-call-result
|
|
157
|
+
SDK->>Platform: 5. POST /trigger with results
|
|
158
|
+
Platform->>LLM: 6. Continue with results
|
|
159
|
+
LLM-->>Platform: Response
|
|
160
|
+
Platform-->>UI: text-delta events
|
|
161
|
+
|
|
162
|
+
Note over LLM,UI: 7. Repeat if more tools needed
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Accessing Request Context
|
|
166
|
+
|
|
167
|
+
For request-specific data (auth, headers), create handlers dynamically:
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
// In your API route
|
|
171
|
+
export async function POST(request: Request) {
|
|
172
|
+
const authToken = request.headers.get('Authorization');
|
|
173
|
+
const user = await validateToken(authToken);
|
|
174
|
+
|
|
175
|
+
const session = client.agentSessions.attach(sessionId, {
|
|
176
|
+
tools: {
|
|
177
|
+
'get-user-account': async (args) => {
|
|
178
|
+
// Use request context
|
|
179
|
+
return await db.users.findById(user.id);
|
|
180
|
+
},
|
|
181
|
+
'create-order': async (args) => {
|
|
182
|
+
// Create with user context
|
|
183
|
+
return await orderService.create({
|
|
184
|
+
...args,
|
|
185
|
+
userId: user.id,
|
|
186
|
+
createdBy: user.email,
|
|
187
|
+
});
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
const { stream } = session.trigger(triggerName, input);
|
|
193
|
+
return new Response(stream);
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## Best Practices
|
|
198
|
+
|
|
199
|
+
### 1. Validate Arguments
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
'create-ticket': async (args) => {
|
|
203
|
+
const summary = args.summary;
|
|
204
|
+
if (typeof summary !== 'string' || summary.length === 0) {
|
|
205
|
+
throw new Error('Summary is required');
|
|
206
|
+
}
|
|
207
|
+
// ...
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### 2. Handle Timeouts
|
|
212
|
+
|
|
213
|
+
```typescript
|
|
214
|
+
'external-api-call': async (args) => {
|
|
215
|
+
const controller = new AbortController();
|
|
216
|
+
const timeout = setTimeout(() => controller.abort(), 10000);
|
|
217
|
+
|
|
218
|
+
try {
|
|
219
|
+
const response = await fetch(url, { signal: controller.signal });
|
|
220
|
+
return await response.json();
|
|
221
|
+
} finally {
|
|
222
|
+
clearTimeout(timeout);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### 3. Log Tool Calls
|
|
228
|
+
|
|
229
|
+
```typescript
|
|
230
|
+
'search-products': async (args) => {
|
|
231
|
+
console.log('Tool call: search-products', { args });
|
|
232
|
+
|
|
233
|
+
const result = await productSearch(args);
|
|
234
|
+
|
|
235
|
+
console.log('Tool result: search-products', {
|
|
236
|
+
resultCount: result.length
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
return result;
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Streaming
|
|
3
|
+
description: Understanding stream events from the Server SDK.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Streaming
|
|
7
|
+
|
|
8
|
+
All Octavus responses stream in real-time using Server-Sent Events (SSE). This enables responsive UX with incremental updates.
|
|
9
|
+
|
|
10
|
+
## Stream Response
|
|
11
|
+
|
|
12
|
+
When you trigger an action, you get a readable stream:
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
const { stream } = session.trigger('user-message', {
|
|
16
|
+
USER_MESSAGE: 'Hello!'
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
// Return to frontend as streaming response
|
|
20
|
+
return new Response(stream, {
|
|
21
|
+
headers: {
|
|
22
|
+
'Content-Type': 'text/event-stream',
|
|
23
|
+
'Cache-Control': 'no-cache',
|
|
24
|
+
'Connection': 'keep-alive',
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Event Types
|
|
30
|
+
|
|
31
|
+
The stream emits various event types:
|
|
32
|
+
|
|
33
|
+
### Block Events
|
|
34
|
+
|
|
35
|
+
Track execution progress:
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
// Block started
|
|
39
|
+
{ type: 'block-start', blockId: '...', blockName: 'Respond to user', blockType: 'next-message', display: 'stream' }
|
|
40
|
+
|
|
41
|
+
// Block completed
|
|
42
|
+
{ type: 'block-end', blockId: '...', summary: 'Generated response' }
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Text Events
|
|
46
|
+
|
|
47
|
+
Streaming text content:
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
// Text generation started
|
|
51
|
+
{ type: 'text-start', id: '...' }
|
|
52
|
+
|
|
53
|
+
// Incremental text (most common event)
|
|
54
|
+
{ type: 'text-delta', content: 'Hello' }
|
|
55
|
+
{ type: 'text-delta', content: '!' }
|
|
56
|
+
{ type: 'text-delta', content: ' How' }
|
|
57
|
+
{ type: 'text-delta', content: ' can' }
|
|
58
|
+
{ type: 'text-delta', content: ' I' }
|
|
59
|
+
{ type: 'text-delta', content: ' help?' }
|
|
60
|
+
|
|
61
|
+
// Text generation ended
|
|
62
|
+
{ type: 'text-end', id: '...' }
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Tool Events
|
|
66
|
+
|
|
67
|
+
Tool call lifecycle:
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
// Tool call initiated
|
|
71
|
+
{ type: 'tool-call-start', toolCallId: '...', toolName: 'get-user-account', toolDescription: 'Looking up account' }
|
|
72
|
+
|
|
73
|
+
// Tool arguments (JSON string)
|
|
74
|
+
{ type: 'tool-call-args', toolCallId: '...', argsJson: '{"userId":"user-123"}' }
|
|
75
|
+
|
|
76
|
+
// Tool completed successfully
|
|
77
|
+
{ type: 'tool-call-result', toolCallId: '...', result: { name: 'Demo User', email: '...' } }
|
|
78
|
+
|
|
79
|
+
// Tool failed
|
|
80
|
+
{ type: 'tool-call-error', toolCallId: '...', error: 'User not found' }
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Thinking Events
|
|
84
|
+
|
|
85
|
+
Extended reasoning (for supported models):
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
// Thinking started
|
|
89
|
+
{ type: 'thinking-start', id: '...', thread: 'main' }
|
|
90
|
+
|
|
91
|
+
// Thinking content
|
|
92
|
+
{ type: 'thinking-delta', content: 'Let me analyze this request...' }
|
|
93
|
+
|
|
94
|
+
// Thinking ended
|
|
95
|
+
{ type: 'thinking-end', id: '...' }
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Resource Events
|
|
99
|
+
|
|
100
|
+
Resource updates:
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
{ type: 'resource-update', name: 'CONVERSATION_SUMMARY', value: 'User asked about...' }
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Completion Events
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
// Stream completed
|
|
110
|
+
{ type: 'done', finishReason: 'stop' }
|
|
111
|
+
|
|
112
|
+
// Possible finish reasons:
|
|
113
|
+
// - 'stop': Normal completion
|
|
114
|
+
// - 'tool-calls': Waiting for tool execution (handled by SDK)
|
|
115
|
+
// - 'length': Max tokens reached
|
|
116
|
+
// - 'error': Error occurred
|
|
117
|
+
|
|
118
|
+
// Error event
|
|
119
|
+
{ type: 'error', message: 'Something went wrong', code: 'EXECUTION_ERROR' }
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Display Modes
|
|
123
|
+
|
|
124
|
+
Each block/tool specifies how it should appear to users:
|
|
125
|
+
|
|
126
|
+
| Mode | Description |
|
|
127
|
+
|------|-------------|
|
|
128
|
+
| `hidden` | Not shown to user (background work) |
|
|
129
|
+
| `name` | Shows block/tool name |
|
|
130
|
+
| `description` | Shows description text |
|
|
131
|
+
| `stream` | Streams content to chat |
|
|
132
|
+
|
|
133
|
+
**Note**: Hidden events are filtered before reaching the client SDK. Your frontend only sees user-facing events.
|
|
134
|
+
|
|
135
|
+
## Stream Event Type
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
type StreamEvent =
|
|
139
|
+
| TextDeltaEvent
|
|
140
|
+
| TextStartEvent
|
|
141
|
+
| TextEndEvent
|
|
142
|
+
| ToolCallStartEvent
|
|
143
|
+
| ToolCallArgsEvent
|
|
144
|
+
| ToolCallResultEvent
|
|
145
|
+
| ToolCallErrorEvent
|
|
146
|
+
| ResourceUpdateEvent
|
|
147
|
+
| BlockStartEvent
|
|
148
|
+
| BlockEndEvent
|
|
149
|
+
| ThinkingStartEvent
|
|
150
|
+
| ThinkingDeltaEvent
|
|
151
|
+
| ThinkingEndEvent
|
|
152
|
+
| DoneEvent
|
|
153
|
+
| ErrorEvent;
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Handling Streams Manually
|
|
157
|
+
|
|
158
|
+
If you need to process the stream server-side:
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
import { safeParseStreamEvent } from '@octavus/core';
|
|
162
|
+
|
|
163
|
+
const { stream } = session.trigger('user-message', { USER_MESSAGE: 'Hello' });
|
|
164
|
+
|
|
165
|
+
const reader = stream.getReader();
|
|
166
|
+
const decoder = new TextDecoder();
|
|
167
|
+
|
|
168
|
+
let buffer = '';
|
|
169
|
+
|
|
170
|
+
while (true) {
|
|
171
|
+
const { done, value } = await reader.read();
|
|
172
|
+
if (done) break;
|
|
173
|
+
|
|
174
|
+
buffer += decoder.decode(value, { stream: true });
|
|
175
|
+
const lines = buffer.split('\n');
|
|
176
|
+
buffer = lines.pop() ?? '';
|
|
177
|
+
|
|
178
|
+
for (const line of lines) {
|
|
179
|
+
if (line.startsWith('data: ') && line !== 'data: [DONE]') {
|
|
180
|
+
const parsed = safeParseStreamEvent(JSON.parse(line.slice(6)));
|
|
181
|
+
if (parsed.success) {
|
|
182
|
+
const event = parsed.data;
|
|
183
|
+
|
|
184
|
+
switch (event.type) {
|
|
185
|
+
case 'text-delta':
|
|
186
|
+
process.stdout.write(event.content);
|
|
187
|
+
break;
|
|
188
|
+
case 'done':
|
|
189
|
+
console.log('\nDone:', event.finishReason);
|
|
190
|
+
break;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## Error Recovery
|
|
199
|
+
|
|
200
|
+
The SDK handles common error scenarios:
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
// Network errors are caught and emitted
|
|
204
|
+
{ type: 'error', message: 'Network request failed' }
|
|
205
|
+
|
|
206
|
+
// Tool errors are captured per-tool
|
|
207
|
+
{ type: 'tool-call-error', toolCallId: '...', error: 'Handler threw exception' }
|
|
208
|
+
|
|
209
|
+
// The stream always ends with either 'done' or 'error'
|
|
210
|
+
```
|
|
211
|
+
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Overview
|
|
3
|
+
description: Introduction to the Octavus Client SDK for building chat interfaces.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Client SDK Overview
|
|
7
|
+
|
|
8
|
+
The `@octavus/client-sdk` package provides React hooks for building chat interfaces with Octavus agents. It handles streaming, message state, and execution blocks.
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install @octavus/client-sdk
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Basic Usage
|
|
17
|
+
|
|
18
|
+
```tsx
|
|
19
|
+
import { useOctavusChat } from '@octavus/client-sdk';
|
|
20
|
+
|
|
21
|
+
function Chat({ sessionId }: { sessionId: string }) {
|
|
22
|
+
const {
|
|
23
|
+
messages,
|
|
24
|
+
status,
|
|
25
|
+
isLoading,
|
|
26
|
+
streamingText,
|
|
27
|
+
addUserMessage,
|
|
28
|
+
triggerAction,
|
|
29
|
+
} = useOctavusChat({
|
|
30
|
+
onTrigger: async (triggerName, input) => {
|
|
31
|
+
return fetch(`/api/chat/${sessionId}/trigger`, {
|
|
32
|
+
method: 'POST',
|
|
33
|
+
body: JSON.stringify({ triggerName, input }),
|
|
34
|
+
});
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const sendMessage = async (text: string) => {
|
|
39
|
+
addUserMessage(text);
|
|
40
|
+
await triggerAction('user-message', { USER_MESSAGE: text });
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<div>
|
|
45
|
+
{messages.map((msg) => (
|
|
46
|
+
<div key={msg.id}>{msg.content}</div>
|
|
47
|
+
))}
|
|
48
|
+
{streamingText && <div>{streamingText}</div>}
|
|
49
|
+
</div>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Key Features
|
|
55
|
+
|
|
56
|
+
### Real-time Streaming
|
|
57
|
+
|
|
58
|
+
Text streams incrementally as the LLM generates it:
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
const { streamingText, streamingParts } = useOctavusChat({...});
|
|
62
|
+
|
|
63
|
+
// streamingText: Current streaming text
|
|
64
|
+
// streamingParts: Structured parts (text, thinking, tool calls)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Message History
|
|
68
|
+
|
|
69
|
+
Messages are tracked automatically:
|
|
70
|
+
|
|
71
|
+
```tsx
|
|
72
|
+
const { messages } = useOctavusChat({...});
|
|
73
|
+
|
|
74
|
+
// Each message includes:
|
|
75
|
+
// - id: Unique identifier
|
|
76
|
+
// - role: 'user' | 'assistant'
|
|
77
|
+
// - content: Text content
|
|
78
|
+
// - parts: Ordered content parts
|
|
79
|
+
// - toolCalls: Tool call information
|
|
80
|
+
// - thinking: Extended reasoning (if enabled)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Execution Blocks
|
|
84
|
+
|
|
85
|
+
Track what the agent is doing:
|
|
86
|
+
|
|
87
|
+
```tsx
|
|
88
|
+
const { executionBlocks } = useOctavusChat({...});
|
|
89
|
+
|
|
90
|
+
// Shows active execution steps
|
|
91
|
+
// Useful for progress indicators
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Status Tracking
|
|
95
|
+
|
|
96
|
+
```tsx
|
|
97
|
+
const { status, isLoading } = useOctavusChat({...});
|
|
98
|
+
|
|
99
|
+
// status: 'idle' | 'loading' | 'streaming' | 'error'
|
|
100
|
+
// isLoading: true during loading or streaming
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Hook Reference
|
|
104
|
+
|
|
105
|
+
### useOctavusChat
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
function useOctavusChat(options: UseOctavusChatOptions): UseOctavusChatReturn;
|
|
109
|
+
|
|
110
|
+
interface UseOctavusChatOptions {
|
|
111
|
+
// Required: Function that calls your backend trigger endpoint
|
|
112
|
+
onTrigger: TriggerFunction;
|
|
113
|
+
|
|
114
|
+
// Optional: Pre-populate with existing messages (session restore)
|
|
115
|
+
initialMessages?: Message[];
|
|
116
|
+
|
|
117
|
+
// Optional: Callbacks
|
|
118
|
+
onMessage?: (message: Message) => void;
|
|
119
|
+
onError?: (error: Error) => void;
|
|
120
|
+
onDone?: () => void;
|
|
121
|
+
onResourceUpdate?: (name: string, value: unknown) => void;
|
|
122
|
+
onBlockStart?: (block: ExecutionBlock) => void;
|
|
123
|
+
onBlockEnd?: (block: ExecutionBlock) => void;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
interface UseOctavusChatReturn {
|
|
127
|
+
// State
|
|
128
|
+
messages: Message[];
|
|
129
|
+
status: ChatStatus;
|
|
130
|
+
isLoading: boolean;
|
|
131
|
+
error: Error | null;
|
|
132
|
+
streamingText: string;
|
|
133
|
+
streamingParts: MessagePart[];
|
|
134
|
+
executionBlocks: ExecutionBlock[];
|
|
135
|
+
thinkingText: string;
|
|
136
|
+
|
|
137
|
+
// Actions
|
|
138
|
+
addUserMessage: (content: string) => void;
|
|
139
|
+
triggerAction: (triggerName: string, input?: Record<string, unknown>) => Promise<void>;
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Next Steps
|
|
144
|
+
|
|
145
|
+
- [Messages](/docs/client-sdk/messages) — Working with message state
|
|
146
|
+
- [Streaming](/docs/client-sdk/streaming) — Building streaming UIs
|
|
147
|
+
- [Execution Blocks](/docs/client-sdk/execution-blocks) — Showing agent progress
|
|
148
|
+
|