@octavus/docs 2.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/02-server-sdk/02-sessions.md +29 -0
- package/content/03-client-sdk/05-socket-transport.md +24 -49
- package/content/06-examples/03-socket-chat.md +17 -37
- package/dist/chunk-GI574O6S.js +1435 -0
- package/dist/chunk-GI574O6S.js.map +1 -0
- package/dist/chunk-KUB6BGPR.js +1435 -0
- package/dist/chunk-KUB6BGPR.js.map +1 -0
- package/dist/chunk-WKCT4ABS.js +1435 -0
- package/dist/chunk-WKCT4ABS.js.map +1 -0
- package/dist/content.js +1 -1
- package/dist/docs.json +6 -6
- 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 +6 -6
- package/package.json +1 -1
|
@@ -162,6 +162,35 @@ const events = session.execute(request, {
|
|
|
162
162
|
|
|
163
163
|
When the client aborts the request, the signal propagates through to the LLM provider, stopping generation immediately. Any partial content is preserved.
|
|
164
164
|
|
|
165
|
+
## WebSocket Handling
|
|
166
|
+
|
|
167
|
+
For WebSocket integrations, use `handleSocketMessage()` which manages abort controller lifecycle internally:
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
import type { SocketMessage } from '@octavus/server-sdk';
|
|
171
|
+
|
|
172
|
+
// In your socket handler
|
|
173
|
+
conn.on('data', async (rawData: string) => {
|
|
174
|
+
const msg = JSON.parse(rawData);
|
|
175
|
+
|
|
176
|
+
if (msg.type === 'trigger' || msg.type === 'continue' || msg.type === 'stop') {
|
|
177
|
+
await session.handleSocketMessage(msg as SocketMessage, {
|
|
178
|
+
onEvent: (event) => conn.write(JSON.stringify(event)),
|
|
179
|
+
onFinish: () => sendMessagesUpdate(), // Optional callback after streaming
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
The `handleSocketMessage()` method:
|
|
186
|
+
|
|
187
|
+
- Handles `trigger`, `continue`, and `stop` messages
|
|
188
|
+
- Automatically aborts previous requests when a new one arrives
|
|
189
|
+
- Streams events via the `onEvent` callback
|
|
190
|
+
- Calls `onFinish` after streaming completes (not called if aborted)
|
|
191
|
+
|
|
192
|
+
See [Socket Chat Example](/docs/examples/socket-chat) for a complete implementation.
|
|
193
|
+
|
|
165
194
|
## Session Lifecycle
|
|
166
195
|
|
|
167
196
|
```mermaid
|
|
@@ -131,7 +131,7 @@ The server creates a session on first trigger message:
|
|
|
131
131
|
|
|
132
132
|
```typescript
|
|
133
133
|
import sockjs from 'sockjs';
|
|
134
|
-
import { OctavusClient, type AgentSession } from '@octavus/server-sdk';
|
|
134
|
+
import { OctavusClient, type AgentSession, type SocketMessage } from '@octavus/server-sdk';
|
|
135
135
|
|
|
136
136
|
const client = new OctavusClient({
|
|
137
137
|
baseUrl: process.env.OCTAVUS_API_URL!,
|
|
@@ -141,7 +141,8 @@ const client = new OctavusClient({
|
|
|
141
141
|
function createSocketHandler() {
|
|
142
142
|
return (conn: sockjs.Connection) => {
|
|
143
143
|
let session: AgentSession | null = null;
|
|
144
|
-
|
|
144
|
+
|
|
145
|
+
const send = (data: unknown) => conn.write(JSON.stringify(data));
|
|
145
146
|
|
|
146
147
|
conn.on('data', (rawData: string) => {
|
|
147
148
|
void handleMessage(rawData);
|
|
@@ -150,17 +151,10 @@ function createSocketHandler() {
|
|
|
150
151
|
async function handleMessage(rawData: string) {
|
|
151
152
|
const msg = JSON.parse(rawData);
|
|
152
153
|
|
|
153
|
-
if (msg.type === 'stop') {
|
|
154
|
-
abortController?.abort();
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// Handle both trigger and continue messages
|
|
159
|
-
if (msg.type === 'trigger' || msg.type === 'continue') {
|
|
154
|
+
if (msg.type === 'trigger' || msg.type === 'continue' || msg.type === 'stop') {
|
|
160
155
|
// Create session lazily on first trigger
|
|
161
156
|
if (!session && msg.type === 'trigger') {
|
|
162
157
|
const sessionId = await client.agentSessions.create('your-agent-id', {
|
|
163
|
-
// Initial input variables
|
|
164
158
|
COMPANY_NAME: 'Acme Corp',
|
|
165
159
|
});
|
|
166
160
|
session = client.agentSessions.attach(sessionId, {
|
|
@@ -173,24 +167,14 @@ function createSocketHandler() {
|
|
|
173
167
|
|
|
174
168
|
if (!session) return;
|
|
175
169
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
const events = session.execute(msg, {
|
|
180
|
-
signal: abortController.signal,
|
|
170
|
+
// handleSocketMessage manages abort controller internally
|
|
171
|
+
await session.handleSocketMessage(msg as SocketMessage, {
|
|
172
|
+
onEvent: send,
|
|
181
173
|
});
|
|
182
|
-
|
|
183
|
-
try {
|
|
184
|
-
for await (const event of events) {
|
|
185
|
-
conn.write(JSON.stringify(event));
|
|
186
|
-
}
|
|
187
|
-
} catch {
|
|
188
|
-
// Handle errors
|
|
189
|
-
}
|
|
190
174
|
}
|
|
191
175
|
}
|
|
192
176
|
|
|
193
|
-
conn.on('close', () =>
|
|
177
|
+
conn.on('close', () => {});
|
|
194
178
|
};
|
|
195
179
|
}
|
|
196
180
|
|
|
@@ -245,9 +229,12 @@ When `sessionId` changes, the hook automatically reinitializes with the new tran
|
|
|
245
229
|
When using client-provided sessionId, the server must handle an `init` message:
|
|
246
230
|
|
|
247
231
|
```typescript
|
|
232
|
+
import type { SocketMessage } from '@octavus/server-sdk';
|
|
233
|
+
|
|
248
234
|
sockServer.on('connection', (conn) => {
|
|
249
235
|
let session: AgentSession | null = null;
|
|
250
|
-
|
|
236
|
+
|
|
237
|
+
const send = (data: unknown) => conn.write(JSON.stringify(data));
|
|
251
238
|
|
|
252
239
|
conn.on('data', (rawData: string) => {
|
|
253
240
|
void handleMessage(rawData);
|
|
@@ -266,35 +253,23 @@ sockServer.on('connection', (conn) => {
|
|
|
266
253
|
return;
|
|
267
254
|
}
|
|
268
255
|
|
|
269
|
-
if (msg.type === 'stop') {
|
|
270
|
-
abortController?.abort();
|
|
271
|
-
return;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
256
|
// All other messages require initialized session
|
|
275
257
|
if (!session) {
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
}),
|
|
284
|
-
);
|
|
258
|
+
send({
|
|
259
|
+
type: 'error',
|
|
260
|
+
errorType: 'validation_error',
|
|
261
|
+
message: 'Session not initialized. Send init message first.',
|
|
262
|
+
source: 'platform',
|
|
263
|
+
retryable: false,
|
|
264
|
+
});
|
|
285
265
|
return;
|
|
286
266
|
}
|
|
287
267
|
|
|
288
|
-
//
|
|
289
|
-
if (msg.type === 'trigger' || msg.type === 'continue') {
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
const events = session.execute(msg, { signal: abortController.signal });
|
|
294
|
-
|
|
295
|
-
for await (const event of events) {
|
|
296
|
-
conn.write(JSON.stringify(event));
|
|
297
|
-
}
|
|
268
|
+
// handleSocketMessage handles trigger, continue, and stop
|
|
269
|
+
if (msg.type === 'trigger' || msg.type === 'continue' || msg.type === 'stop') {
|
|
270
|
+
await session.handleSocketMessage(msg as SocketMessage, {
|
|
271
|
+
onEvent: send,
|
|
272
|
+
});
|
|
298
273
|
}
|
|
299
274
|
}
|
|
300
275
|
});
|
|
@@ -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,57 +101,36 @@ 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 and continue messages
|
|
110
|
-
if (msg.type === 'trigger' || msg.type === 'continue') {
|
|
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
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
|
-
// Server-side tool handlers
|
|
121
114
|
'get-user-account': async () => {
|
|
122
|
-
// Fetch from your database
|
|
123
115
|
return { name: 'Demo User', plan: 'pro' };
|
|
124
116
|
},
|
|
125
117
|
'create-support-ticket': async () => {
|
|
126
118
|
return { ticketId: 'TKT-123', estimatedResponse: '24h' };
|
|
127
119
|
},
|
|
128
|
-
// Tools without handlers are forwarded to the client
|
|
129
120
|
},
|
|
130
121
|
});
|
|
131
122
|
}
|
|
132
123
|
|
|
133
124
|
if (!session) return;
|
|
134
125
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
try {
|
|
141
|
-
for await (const event of events) {
|
|
142
|
-
if (abortController.signal.aborted) break;
|
|
143
|
-
conn.write(JSON.stringify(event));
|
|
144
|
-
}
|
|
145
|
-
} catch {
|
|
146
|
-
// Handle errors
|
|
147
|
-
}
|
|
126
|
+
// handleSocketMessage manages abort controller internally
|
|
127
|
+
await session.handleSocketMessage(msg as SocketMessage, {
|
|
128
|
+
onEvent: send,
|
|
129
|
+
});
|
|
148
130
|
}
|
|
149
131
|
}
|
|
150
132
|
|
|
151
|
-
conn.on('close', () => {
|
|
152
|
-
abortController?.abort();
|
|
153
|
-
});
|
|
133
|
+
conn.on('close', () => {});
|
|
154
134
|
};
|
|
155
135
|
}
|
|
156
136
|
```
|
|
@@ -373,13 +353,13 @@ The socket handler receives messages and forwards them to Octavus:
|
|
|
373
353
|
// Client sends continuation (after client tool handling):
|
|
374
354
|
{ type: 'continue', executionId: '...', toolResults: [...] }
|
|
375
355
|
|
|
376
|
-
//
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
}
|
|
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
|
+
});
|
|
383
363
|
```
|
|
384
364
|
|
|
385
365
|
### Tools
|