@octavus/docs 1.0.0 → 2.1.0
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/content/01-getting-started/02-quickstart.md +8 -5
- package/content/02-server-sdk/01-overview.md +22 -6
- package/content/02-server-sdk/02-sessions.md +80 -10
- package/content/02-server-sdk/03-tools.md +39 -14
- package/content/02-server-sdk/04-streaming.md +55 -7
- package/content/02-server-sdk/05-cli.md +9 -9
- package/content/03-client-sdk/01-overview.md +22 -9
- package/content/03-client-sdk/02-messages.md +6 -4
- package/content/03-client-sdk/03-streaming.md +7 -3
- package/content/03-client-sdk/05-socket-transport.md +40 -44
- package/content/03-client-sdk/06-http-transport.md +81 -17
- package/content/03-client-sdk/07-structured-output.md +3 -2
- package/content/03-client-sdk/08-file-uploads.md +6 -4
- package/content/03-client-sdk/10-client-tools.md +557 -0
- package/content/04-protocol/02-input-resources.md +12 -0
- package/content/04-protocol/03-triggers.md +8 -5
- package/content/04-protocol/06-handlers.md +10 -0
- package/content/04-protocol/07-agent-config.md +34 -1
- package/content/05-api-reference/01-overview.md +18 -0
- package/content/05-api-reference/02-sessions.md +2 -0
- package/content/05-api-reference/03-agents.md +12 -0
- package/content/06-examples/02-nextjs-chat.md +12 -7
- package/content/06-examples/03-socket-chat.md +34 -40
- package/content/07-migration/01-v1-to-v2.md +366 -0
- package/content/07-migration/_meta.md +4 -0
- package/dist/chunk-3ER2T7S7.js +663 -0
- package/dist/chunk-3ER2T7S7.js.map +1 -0
- package/dist/chunk-GI574O6S.js +1435 -0
- package/dist/chunk-GI574O6S.js.map +1 -0
- package/dist/{chunk-WJ2W3DUC.js → chunk-HFF2TVGV.js} +13 -13
- package/dist/chunk-HFF2TVGV.js.map +1 -0
- package/dist/chunk-KUB6BGPR.js +1435 -0
- package/dist/chunk-KUB6BGPR.js.map +1 -0
- package/dist/chunk-S5JUVAKE.js +1409 -0
- package/dist/chunk-S5JUVAKE.js.map +1 -0
- package/dist/chunk-TMJG4CJH.js +1409 -0
- package/dist/chunk-TMJG4CJH.js.map +1 -0
- package/dist/chunk-WKCT4ABS.js +1435 -0
- package/dist/chunk-WKCT4ABS.js.map +1 -0
- package/dist/chunk-YJPO6KOJ.js +1435 -0
- package/dist/chunk-YJPO6KOJ.js.map +1 -0
- package/dist/chunk-ZSCRYD5P.js +1409 -0
- package/dist/chunk-ZSCRYD5P.js.map +1 -0
- package/dist/content.js +1 -1
- package/dist/docs.json +44 -26
- package/dist/index.js +1 -1
- package/dist/search-index.json +1 -1
- package/dist/search.js +1 -1
- package/dist/search.js.map +1 -1
- package/dist/sections.json +52 -26
- package/package.json +1 -1
- package/dist/chunk-WJ2W3DUC.js.map +0 -1
|
@@ -7,6 +7,18 @@ description: Agent management API endpoints.
|
|
|
7
7
|
|
|
8
8
|
Manage agent definitions including protocols and prompts.
|
|
9
9
|
|
|
10
|
+
## Permissions
|
|
11
|
+
|
|
12
|
+
| Endpoint | Method | Permission Required |
|
|
13
|
+
| ---------------------- | ------ | ------------------- |
|
|
14
|
+
| `/api/agents` | GET | Agents OR Sessions |
|
|
15
|
+
| `/api/agents/:id` | GET | Agents OR Sessions |
|
|
16
|
+
| `/api/agents` | POST | Agents |
|
|
17
|
+
| `/api/agents/:id` | PATCH | Agents |
|
|
18
|
+
| `/api/agents/validate` | POST | Agents |
|
|
19
|
+
|
|
20
|
+
Read endpoints work with either permission since both the CLI (for sync) and Server SDK (for sessions) need to read agent definitions.
|
|
21
|
+
|
|
10
22
|
## List Agents
|
|
11
23
|
|
|
12
24
|
Get all agents in the project.
|
|
@@ -114,12 +114,13 @@ import { toSSEStream } from '@octavus/server-sdk';
|
|
|
114
114
|
import { octavus } from '@/lib/octavus';
|
|
115
115
|
|
|
116
116
|
export async function POST(request: Request) {
|
|
117
|
-
const
|
|
117
|
+
const body = await request.json();
|
|
118
|
+
const { sessionId, ...payload } = body;
|
|
118
119
|
|
|
119
120
|
// Attach to the session with tool handlers
|
|
120
121
|
const session = octavus.agentSessions.attach(sessionId, {
|
|
121
122
|
tools: {
|
|
122
|
-
//
|
|
123
|
+
// Server-side tool handlers run on YOUR server, not Octavus
|
|
123
124
|
'get-user-account': async (args) => {
|
|
124
125
|
const userId = args.userId as string;
|
|
125
126
|
// Fetch from your database
|
|
@@ -143,11 +144,14 @@ export async function POST(request: Request) {
|
|
|
143
144
|
estimatedResponse: '24 hours',
|
|
144
145
|
};
|
|
145
146
|
},
|
|
147
|
+
|
|
148
|
+
// Tools without handlers here are forwarded to the client
|
|
149
|
+
// See Client Tools docs for handling on frontend
|
|
146
150
|
},
|
|
147
151
|
});
|
|
148
152
|
|
|
149
|
-
//
|
|
150
|
-
const events = session.
|
|
153
|
+
// execute() handles both triggers and client tool continuations
|
|
154
|
+
const events = session.execute(payload, { signal: request.signal });
|
|
151
155
|
|
|
152
156
|
return new Response(toSSEStream(events), {
|
|
153
157
|
headers: {
|
|
@@ -159,7 +163,7 @@ export async function POST(request: Request) {
|
|
|
159
163
|
}
|
|
160
164
|
```
|
|
161
165
|
|
|
162
|
-
**Protocol Note:** Tool names and arguments are defined in your agent's protocol YAML. The tool handlers here must match those definitions.
|
|
166
|
+
**Protocol Note:** Tool names and arguments are defined in your agent's protocol YAML. The tool handlers here must match those definitions. Tools without server handlers are forwarded to the client.
|
|
163
167
|
|
|
164
168
|
## Step 7: Build the Chat Component
|
|
165
169
|
|
|
@@ -181,11 +185,12 @@ export function Chat({ sessionId }: ChatProps) {
|
|
|
181
185
|
const transport = useMemo(
|
|
182
186
|
() =>
|
|
183
187
|
createHttpTransport({
|
|
184
|
-
|
|
188
|
+
request: (payload, options) =>
|
|
185
189
|
fetch('/api/trigger', {
|
|
186
190
|
method: 'POST',
|
|
187
191
|
headers: { 'Content-Type': 'application/json' },
|
|
188
|
-
body: JSON.stringify({ sessionId,
|
|
192
|
+
body: JSON.stringify({ sessionId, ...payload }),
|
|
193
|
+
signal: options?.signal,
|
|
189
194
|
}),
|
|
190
195
|
}),
|
|
191
196
|
[sessionId],
|
|
@@ -79,7 +79,7 @@ This is the core of socket integration. Each connection gets its own session:
|
|
|
79
79
|
```typescript
|
|
80
80
|
// server/octavus/socket-handler.ts
|
|
81
81
|
import type { Connection } from 'sockjs';
|
|
82
|
-
import { OctavusClient, type AgentSession } from '@octavus/server-sdk';
|
|
82
|
+
import { OctavusClient, type AgentSession, type SocketMessage } from '@octavus/server-sdk';
|
|
83
83
|
|
|
84
84
|
const octavus = new OctavusClient({
|
|
85
85
|
baseUrl: process.env.OCTAVUS_API_URL!,
|
|
@@ -91,7 +91,8 @@ const AGENT_ID = process.env.OCTAVUS_AGENT_ID!;
|
|
|
91
91
|
export function createSocketHandler() {
|
|
92
92
|
return (conn: Connection) => {
|
|
93
93
|
let session: AgentSession | null = null;
|
|
94
|
-
|
|
94
|
+
|
|
95
|
+
const send = (data: unknown) => conn.write(JSON.stringify(data));
|
|
95
96
|
|
|
96
97
|
conn.on('data', (rawData: string) => {
|
|
97
98
|
void handleMessage(rawData);
|
|
@@ -100,25 +101,17 @@ export function createSocketHandler() {
|
|
|
100
101
|
async function handleMessage(rawData: string) {
|
|
101
102
|
const msg = JSON.parse(rawData);
|
|
102
103
|
|
|
103
|
-
// Handle stop
|
|
104
|
-
if (msg.type === 'stop') {
|
|
105
|
-
abortController?.abort();
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Handle trigger
|
|
110
|
-
if (msg.type === 'trigger') {
|
|
104
|
+
// Handle trigger, continue, and stop messages
|
|
105
|
+
if (msg.type === 'trigger' || msg.type === 'continue' || msg.type === 'stop') {
|
|
111
106
|
// Create session lazily on first trigger
|
|
112
|
-
if (!session) {
|
|
107
|
+
if (!session && msg.type === 'trigger') {
|
|
113
108
|
const sessionId = await octavus.agentSessions.create(AGENT_ID, {
|
|
114
|
-
// Initial input variables from your protocol
|
|
115
109
|
COMPANY_NAME: 'Acme Corp',
|
|
116
110
|
});
|
|
117
111
|
|
|
118
112
|
session = octavus.agentSessions.attach(sessionId, {
|
|
119
113
|
tools: {
|
|
120
114
|
'get-user-account': async () => {
|
|
121
|
-
// Fetch from your database
|
|
122
115
|
return { name: 'Demo User', plan: 'pro' };
|
|
123
116
|
},
|
|
124
117
|
'create-support-ticket': async () => {
|
|
@@ -128,25 +121,16 @@ export function createSocketHandler() {
|
|
|
128
121
|
});
|
|
129
122
|
}
|
|
130
123
|
|
|
131
|
-
|
|
124
|
+
if (!session) return;
|
|
132
125
|
|
|
133
|
-
//
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
for await (const event of events) {
|
|
138
|
-
if (abortController.signal.aborted) break;
|
|
139
|
-
conn.write(JSON.stringify(event));
|
|
140
|
-
}
|
|
141
|
-
} catch {
|
|
142
|
-
// Handle errors
|
|
143
|
-
}
|
|
126
|
+
// handleSocketMessage manages abort controller internally
|
|
127
|
+
await session.handleSocketMessage(msg as SocketMessage, {
|
|
128
|
+
onEvent: send,
|
|
129
|
+
});
|
|
144
130
|
}
|
|
145
131
|
}
|
|
146
132
|
|
|
147
|
-
conn.on('close', () => {
|
|
148
|
-
abortController?.abort();
|
|
149
|
-
});
|
|
133
|
+
conn.on('close', () => {});
|
|
150
134
|
};
|
|
151
135
|
}
|
|
152
136
|
```
|
|
@@ -358,26 +342,29 @@ conn.write(
|
|
|
358
342
|
|
|
359
343
|
## Protocol Integration
|
|
360
344
|
|
|
361
|
-
###
|
|
345
|
+
### Messages
|
|
362
346
|
|
|
363
|
-
The socket handler receives
|
|
347
|
+
The socket handler receives messages and forwards them to Octavus:
|
|
364
348
|
|
|
365
349
|
```typescript
|
|
366
|
-
// Client sends:
|
|
350
|
+
// Client sends trigger:
|
|
367
351
|
{ type: 'trigger', triggerName: 'user-message', input: { USER_MESSAGE: 'Hello' } }
|
|
368
352
|
|
|
369
|
-
//
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
353
|
+
// Client sends continuation (after client tool handling):
|
|
354
|
+
{ type: 'continue', executionId: '...', toolResults: [...] }
|
|
355
|
+
|
|
356
|
+
// Client sends stop:
|
|
357
|
+
{ type: 'stop' }
|
|
358
|
+
|
|
359
|
+
// Server handles all three with handleSocketMessage:
|
|
360
|
+
await session.handleSocketMessage(msg, {
|
|
361
|
+
onEvent: (event) => conn.write(JSON.stringify(event)),
|
|
362
|
+
});
|
|
376
363
|
```
|
|
377
364
|
|
|
378
365
|
### Tools
|
|
379
366
|
|
|
380
|
-
Tools are defined in your agent's protocol
|
|
367
|
+
Tools are defined in your agent's protocol. Server-side tools have handlers, client-side tools don't:
|
|
381
368
|
|
|
382
369
|
```yaml
|
|
383
370
|
# protocol.yaml
|
|
@@ -387,18 +374,25 @@ tools:
|
|
|
387
374
|
parameters:
|
|
388
375
|
userId:
|
|
389
376
|
type: string
|
|
377
|
+
|
|
378
|
+
get-browser-location:
|
|
379
|
+
description: Get user's location from browser
|
|
380
|
+
# No server handler - handled on client
|
|
390
381
|
```
|
|
391
382
|
|
|
392
383
|
```typescript
|
|
393
|
-
// Server tool
|
|
384
|
+
// Server tool handlers (only for server tools)
|
|
394
385
|
tools: {
|
|
395
386
|
'get-user-account': async (args) => {
|
|
396
387
|
const userId = args.userId as string;
|
|
397
388
|
return await db.users.find(userId);
|
|
398
389
|
},
|
|
390
|
+
// get-browser-location has no handler - forwarded to client
|
|
399
391
|
}
|
|
400
392
|
```
|
|
401
393
|
|
|
394
|
+
See [Client Tools](/docs/client-sdk/client-tools) for handling tools on the frontend.
|
|
395
|
+
|
|
402
396
|
## Meteor Integration Note
|
|
403
397
|
|
|
404
398
|
Meteor's bundler may have issues with ES6 imports of `sockjs-client`:
|
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Migrating from v1 to v2
|
|
3
|
+
description: Complete guide for upgrading from Octavus SDK v1.x to v2.0.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Migrating from v1 to v2
|
|
7
|
+
|
|
8
|
+
This guide covers all breaking changes and new features in Octavus SDK v2.0.0.
|
|
9
|
+
|
|
10
|
+
## Overview
|
|
11
|
+
|
|
12
|
+
Version 2.0.0 introduces **client-side tool execution**, allowing tools to run in the browser with support for both automatic execution and interactive user input. This required changes to the transport layer and streaming protocol.
|
|
13
|
+
|
|
14
|
+
## Breaking Changes
|
|
15
|
+
|
|
16
|
+
### HTTP Transport Configuration
|
|
17
|
+
|
|
18
|
+
The `triggerRequest` option has been renamed to `request` and the function signature changed to support both trigger and continuation requests.
|
|
19
|
+
|
|
20
|
+
**Before (v1):**
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
import { createHttpTransport } from '@octavus/client-sdk';
|
|
24
|
+
|
|
25
|
+
const transport = createHttpTransport({
|
|
26
|
+
triggerRequest: (triggerName, input, options) =>
|
|
27
|
+
fetch('/api/trigger', {
|
|
28
|
+
method: 'POST',
|
|
29
|
+
headers: { 'Content-Type': 'application/json' },
|
|
30
|
+
body: JSON.stringify({ sessionId, triggerName, input }),
|
|
31
|
+
signal: options?.signal,
|
|
32
|
+
}),
|
|
33
|
+
});
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**After (v2):**
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
import { createHttpTransport } from '@octavus/client-sdk';
|
|
40
|
+
|
|
41
|
+
const transport = createHttpTransport({
|
|
42
|
+
request: (payload, options) =>
|
|
43
|
+
fetch('/api/trigger', {
|
|
44
|
+
method: 'POST',
|
|
45
|
+
headers: { 'Content-Type': 'application/json' },
|
|
46
|
+
body: JSON.stringify({ sessionId, ...payload }),
|
|
47
|
+
signal: options?.signal,
|
|
48
|
+
}),
|
|
49
|
+
});
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The `payload` parameter is a discriminated union with `type: 'trigger' | 'continue'`:
|
|
53
|
+
|
|
54
|
+
- **Trigger request:** `{ type: 'trigger', triggerName: string, input?: Record<string, unknown> }`
|
|
55
|
+
- **Continue request:** `{ type: 'continue', executionId: string, toolResults: ToolResult[] }`
|
|
56
|
+
|
|
57
|
+
### Server SDK Route Handler
|
|
58
|
+
|
|
59
|
+
Server-side route handlers should use the new `execute()` method which handles both triggers and continuations via the request type.
|
|
60
|
+
|
|
61
|
+
**Before (v1):**
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
// app/api/trigger/route.ts
|
|
65
|
+
import { AgentSession, toSSEStream } from '@octavus/server-sdk';
|
|
66
|
+
|
|
67
|
+
export async function POST(request: Request) {
|
|
68
|
+
const { sessionId, triggerName, input } = await request.json();
|
|
69
|
+
|
|
70
|
+
const session = new AgentSession({
|
|
71
|
+
sessionId,
|
|
72
|
+
agentId: 'your-agent-id',
|
|
73
|
+
apiKey: process.env.OCTAVUS_API_KEY!,
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
const events = session.trigger(triggerName, input, { signal: request.signal });
|
|
77
|
+
return new Response(toSSEStream(events), {
|
|
78
|
+
headers: { 'Content-Type': 'text/event-stream' },
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
**After (v2):**
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
// app/api/trigger/route.ts
|
|
87
|
+
import { AgentSession, toSSEStream, type SessionRequest } from '@octavus/server-sdk';
|
|
88
|
+
|
|
89
|
+
export async function POST(request: Request) {
|
|
90
|
+
const body = (await request.json()) as { sessionId: string } & SessionRequest;
|
|
91
|
+
const { sessionId, ...sessionRequest } = body;
|
|
92
|
+
|
|
93
|
+
const session = new AgentSession({
|
|
94
|
+
sessionId,
|
|
95
|
+
agentId: 'your-agent-id',
|
|
96
|
+
apiKey: process.env.OCTAVUS_API_KEY!,
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
const events = session.execute(sessionRequest, { signal: request.signal });
|
|
100
|
+
return new Response(toSSEStream(events), {
|
|
101
|
+
headers: { 'Content-Type': 'text/event-stream' },
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
The `SessionRequest` type is a discriminated union:
|
|
107
|
+
|
|
108
|
+
- **Trigger:** `{ type: 'trigger', triggerName: string, input?: Record<string, unknown> }`
|
|
109
|
+
- **Continue:** `{ type: 'continue', executionId: string, toolResults: ToolResult[] }`
|
|
110
|
+
|
|
111
|
+
### Export Changes
|
|
112
|
+
|
|
113
|
+
The SDKs no longer use star exports (`export * from '@octavus/core'`). Instead, they use explicit type exports and value exports. This improves tree-shaking but may require import adjustments.
|
|
114
|
+
|
|
115
|
+
**If you were importing schemas:**
|
|
116
|
+
|
|
117
|
+
Some Zod schemas are no longer re-exported from `@octavus/server-sdk`. If you need validation schemas, import them directly from `@octavus/core`:
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
// Before (v1) - some schemas were re-exported
|
|
121
|
+
import { fileUploadRequestSchema } from '@octavus/server-sdk';
|
|
122
|
+
|
|
123
|
+
// After (v2) - import from core if needed
|
|
124
|
+
import { fileReferenceSchema } from '@octavus/core';
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
**Type imports remain the same:**
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
// Types are still available
|
|
131
|
+
import type { StreamEvent, UIMessage, FileReference } from '@octavus/client-sdk';
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Custom Transport Interface
|
|
135
|
+
|
|
136
|
+
Custom transport implementations must now implement the `continueWithToolResults()` method:
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
interface Transport {
|
|
140
|
+
trigger(triggerName: string, input?: Record<string, unknown>): AsyncIterable<StreamEvent>;
|
|
141
|
+
continueWithToolResults(executionId: string, results: ToolResult[]): AsyncIterable<StreamEvent>;
|
|
142
|
+
stop(): void;
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### New ChatStatus Value
|
|
147
|
+
|
|
148
|
+
The `ChatStatus` type now includes `'awaiting-input'`:
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
// v1
|
|
152
|
+
type ChatStatus = 'idle' | 'streaming' | 'error';
|
|
153
|
+
|
|
154
|
+
// v2
|
|
155
|
+
type ChatStatus = 'idle' | 'streaming' | 'error' | 'awaiting-input';
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Update any status checks that assume only three values.
|
|
159
|
+
|
|
160
|
+
### Stream Event Changes
|
|
161
|
+
|
|
162
|
+
Two stream events have been modified:
|
|
163
|
+
|
|
164
|
+
**StartEvent and FinishEvent now include executionId:**
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
interface StartEvent {
|
|
168
|
+
type: 'start';
|
|
169
|
+
messageId?: string;
|
|
170
|
+
executionId?: string; // New in v2
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
interface FinishEvent {
|
|
174
|
+
type: 'finish';
|
|
175
|
+
finishReason: FinishReason;
|
|
176
|
+
executionId?: string; // New in v2
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
**New FinishReason:**
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
// Added 'client-tool-calls' to FinishReason
|
|
184
|
+
type FinishReason =
|
|
185
|
+
| 'stop'
|
|
186
|
+
| 'tool-calls'
|
|
187
|
+
| 'client-tool-calls' // New in v2
|
|
188
|
+
| 'length'
|
|
189
|
+
| 'content-filter'
|
|
190
|
+
| 'error'
|
|
191
|
+
| 'other';
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
**New ClientToolRequestEvent:**
|
|
195
|
+
|
|
196
|
+
```typescript
|
|
197
|
+
interface ClientToolRequestEvent {
|
|
198
|
+
type: 'client-tool-request';
|
|
199
|
+
executionId: string;
|
|
200
|
+
toolCalls: PendingToolCall[];
|
|
201
|
+
serverToolResults?: ToolResult[];
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
## New Features
|
|
206
|
+
|
|
207
|
+
### Client-Side Tools
|
|
208
|
+
|
|
209
|
+
v2 introduces client-side tool execution, allowing tools to run in the browser. This is useful for:
|
|
210
|
+
|
|
211
|
+
- Accessing browser APIs (geolocation, clipboard, etc.)
|
|
212
|
+
- Interactive tools requiring user input (confirmations, forms, selections)
|
|
213
|
+
- Tools that need access to client-side state
|
|
214
|
+
|
|
215
|
+
See the [Client Tools guide](/docs/client-sdk/client-tools) for full documentation.
|
|
216
|
+
|
|
217
|
+
#### Automatic Client Tools
|
|
218
|
+
|
|
219
|
+
Tools that execute automatically without user interaction:
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
import { useOctavusChat, createHttpTransport } from '@octavus/react';
|
|
223
|
+
|
|
224
|
+
function Chat() {
|
|
225
|
+
const { messages, send, status } = useOctavusChat({
|
|
226
|
+
transport: createHttpTransport({
|
|
227
|
+
request: (payload, options) =>
|
|
228
|
+
fetch('/api/trigger', {
|
|
229
|
+
method: 'POST',
|
|
230
|
+
headers: { 'Content-Type': 'application/json' },
|
|
231
|
+
body: JSON.stringify({ sessionId, ...payload }),
|
|
232
|
+
signal: options?.signal,
|
|
233
|
+
}),
|
|
234
|
+
}),
|
|
235
|
+
clientTools: {
|
|
236
|
+
'get-browser-location': async (args, ctx) => {
|
|
237
|
+
const pos = await new Promise((resolve, reject) => {
|
|
238
|
+
navigator.geolocation.getCurrentPosition(resolve, reject);
|
|
239
|
+
});
|
|
240
|
+
return { lat: pos.coords.latitude, lng: pos.coords.longitude };
|
|
241
|
+
},
|
|
242
|
+
'get-clipboard': async () => {
|
|
243
|
+
return await navigator.clipboard.readText();
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
// ... rest of component
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
#### Interactive Client Tools
|
|
253
|
+
|
|
254
|
+
Tools that require user interaction before completing:
|
|
255
|
+
|
|
256
|
+
```typescript
|
|
257
|
+
import { useOctavusChat, createHttpTransport } from '@octavus/react';
|
|
258
|
+
|
|
259
|
+
function Chat() {
|
|
260
|
+
const { messages, send, status, pendingClientTools } = useOctavusChat({
|
|
261
|
+
transport: createHttpTransport({
|
|
262
|
+
request: (payload, options) =>
|
|
263
|
+
fetch('/api/trigger', {
|
|
264
|
+
method: 'POST',
|
|
265
|
+
headers: { 'Content-Type': 'application/json' },
|
|
266
|
+
body: JSON.stringify({ sessionId, ...payload }),
|
|
267
|
+
signal: options?.signal,
|
|
268
|
+
}),
|
|
269
|
+
}),
|
|
270
|
+
clientTools: {
|
|
271
|
+
'request-confirmation': 'interactive',
|
|
272
|
+
'select-option': 'interactive',
|
|
273
|
+
},
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
// Render UI for pending interactive tools
|
|
277
|
+
const confirmationTools = pendingClientTools['request-confirmation'] ?? [];
|
|
278
|
+
|
|
279
|
+
return (
|
|
280
|
+
<div>
|
|
281
|
+
{/* Chat messages */}
|
|
282
|
+
|
|
283
|
+
{/* Interactive tool UI */}
|
|
284
|
+
{confirmationTools.map((tool) => (
|
|
285
|
+
<ConfirmationModal
|
|
286
|
+
key={tool.toolCallId}
|
|
287
|
+
message={tool.args.message as string}
|
|
288
|
+
onConfirm={() => tool.submit({ confirmed: true })}
|
|
289
|
+
onCancel={() => tool.cancel('User declined')}
|
|
290
|
+
/>
|
|
291
|
+
))}
|
|
292
|
+
</div>
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### New Types for Client Tools
|
|
298
|
+
|
|
299
|
+
```typescript
|
|
300
|
+
// Context provided to automatic tool handlers
|
|
301
|
+
interface ClientToolContext {
|
|
302
|
+
toolCallId: string;
|
|
303
|
+
toolName: string;
|
|
304
|
+
signal: AbortSignal;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Handler types
|
|
308
|
+
type ClientToolHandler =
|
|
309
|
+
| ((args: Record<string, unknown>, ctx: ClientToolContext) => Promise<unknown>)
|
|
310
|
+
| 'interactive';
|
|
311
|
+
|
|
312
|
+
// Interactive tool with bound submit/cancel methods
|
|
313
|
+
interface InteractiveTool {
|
|
314
|
+
toolCallId: string;
|
|
315
|
+
toolName: string;
|
|
316
|
+
args: Record<string, unknown>;
|
|
317
|
+
submit: (result: unknown) => void;
|
|
318
|
+
cancel: (reason?: string) => void;
|
|
319
|
+
}
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### pendingClientTools Property
|
|
323
|
+
|
|
324
|
+
Both `OctavusChat` and `useOctavusChat` now expose `pendingClientTools`:
|
|
325
|
+
|
|
326
|
+
```typescript
|
|
327
|
+
// Record keyed by tool name, with array of pending tools
|
|
328
|
+
const pendingClientTools: Record<string, InteractiveTool[]>;
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
This allows multiple simultaneous calls to the same tool (e.g., batch confirmations).
|
|
332
|
+
|
|
333
|
+
## Migration Checklist
|
|
334
|
+
|
|
335
|
+
Use this checklist to ensure you've addressed all breaking changes:
|
|
336
|
+
|
|
337
|
+
- [ ] Update all Octavus packages to v2.0.0
|
|
338
|
+
- [ ] Update HTTP transport from `triggerRequest` to `request` with new signature
|
|
339
|
+
- [ ] Update server route handlers to use `execute()` with `SessionRequest` type
|
|
340
|
+
- [ ] Update any status checks to handle `'awaiting-input'`
|
|
341
|
+
- [ ] Update custom transport implementations to include `continueWithToolResults()`
|
|
342
|
+
- [ ] Review any direct schema imports and update if needed
|
|
343
|
+
- [ ] (Optional) Add client-side tools for browser-based functionality
|
|
344
|
+
|
|
345
|
+
## Package Versions
|
|
346
|
+
|
|
347
|
+
All packages should be updated together to ensure compatibility:
|
|
348
|
+
|
|
349
|
+
```json
|
|
350
|
+
{
|
|
351
|
+
"dependencies": {
|
|
352
|
+
"@octavus/core": "^2.0.0",
|
|
353
|
+
"@octavus/client-sdk": "^2.0.0",
|
|
354
|
+
"@octavus/server-sdk": "^2.0.0",
|
|
355
|
+
"@octavus/react": "^2.0.0"
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
## Need Help?
|
|
361
|
+
|
|
362
|
+
If you encounter issues during migration:
|
|
363
|
+
|
|
364
|
+
- Check the [Client Tools documentation](/docs/client-sdk/client-tools) for the new features
|
|
365
|
+
- Review the [HTTP Transport](/docs/client-sdk/http-transport) and [Server SDK Sessions](/docs/server-sdk/sessions) docs for updated APIs
|
|
366
|
+
- [Open an issue](https://github.com/octavus-ai/js-sdk/issues) on GitHub if you find a bug
|