@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.
- package/content/01-getting-started/02-quickstart.md +28 -19
- package/content/02-server-sdk/01-overview.md +34 -17
- package/content/02-server-sdk/02-sessions.md +6 -3
- package/content/02-server-sdk/03-tools.md +4 -2
- package/content/02-server-sdk/04-streaming.md +12 -4
- package/content/03-client-sdk/01-overview.md +107 -42
- package/content/03-client-sdk/02-messages.md +71 -19
- package/content/03-client-sdk/03-streaming.md +38 -28
- package/content/03-client-sdk/05-socket-transport.md +414 -0
- package/content/03-client-sdk/06-http-transport.md +280 -0
- package/content/04-protocol/03-triggers.md +48 -21
- package/content/04-protocol/04-tools.md +25 -15
- package/content/05-api-reference/01-overview.md +3 -17
- package/content/06-examples/01-overview.md +27 -0
- package/content/06-examples/02-nextjs-chat.md +343 -0
- package/content/06-examples/03-socket-chat.md +392 -0
- package/content/06-examples/_meta.md +5 -0
- package/dist/chunk-232K4EME.js +439 -0
- package/dist/chunk-232K4EME.js.map +1 -0
- package/dist/chunk-2JDZLMS3.js +439 -0
- package/dist/chunk-2JDZLMS3.js.map +1 -0
- package/dist/chunk-5M7DS4DF.js +519 -0
- package/dist/chunk-5M7DS4DF.js.map +1 -0
- package/dist/chunk-7AS4ST73.js +421 -0
- package/dist/chunk-7AS4ST73.js.map +1 -0
- package/dist/chunk-H6JGSSAJ.js +519 -0
- package/dist/chunk-H6JGSSAJ.js.map +1 -0
- package/dist/chunk-JZRABTHU.js +519 -0
- package/dist/chunk-JZRABTHU.js.map +1 -0
- package/dist/chunk-OECAPVSX.js +439 -0
- package/dist/chunk-OECAPVSX.js.map +1 -0
- package/dist/chunk-OL5QDJ42.js +483 -0
- package/dist/chunk-OL5QDJ42.js.map +1 -0
- package/dist/chunk-PMOVVTHO.js +519 -0
- package/dist/chunk-PMOVVTHO.js.map +1 -0
- package/dist/chunk-R5MTVABN.js +439 -0
- package/dist/chunk-R5MTVABN.js.map +1 -0
- package/dist/chunk-RJ4H4YVA.js +519 -0
- package/dist/chunk-RJ4H4YVA.js.map +1 -0
- package/dist/chunk-S5U4IWCR.js +439 -0
- package/dist/chunk-S5U4IWCR.js.map +1 -0
- package/dist/chunk-UCJE36LL.js +519 -0
- package/dist/chunk-UCJE36LL.js.map +1 -0
- package/dist/chunk-WW7TRC7S.js +519 -0
- package/dist/chunk-WW7TRC7S.js.map +1 -0
- package/dist/content.js +1 -1
- package/dist/docs.json +57 -12
- 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 +65 -12
- package/package.json +2 -2
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Next.js Chat
|
|
3
|
+
description: Building a chat interface with Next.js and HTTP transport.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Next.js Chat Example
|
|
7
|
+
|
|
8
|
+
This example builds a support chat interface using Next.js App Router with HTTP/SSE transport. This is the recommended pattern for most web applications.
|
|
9
|
+
|
|
10
|
+
## What You're Building
|
|
11
|
+
|
|
12
|
+
A chat interface that:
|
|
13
|
+
- Creates sessions server-side
|
|
14
|
+
- Streams AI responses in real-time
|
|
15
|
+
- Handles tool calls on your server
|
|
16
|
+
- Shows typing status during streaming
|
|
17
|
+
|
|
18
|
+
## Architecture
|
|
19
|
+
|
|
20
|
+
```mermaid
|
|
21
|
+
flowchart LR
|
|
22
|
+
Browser["Browser<br/>(React)"] -->|"POST /api/chat"| NextJS["Next.js API<br/>Routes"]
|
|
23
|
+
NextJS -->|"SSE"| Browser
|
|
24
|
+
NextJS --> Platform["Octavus Platform"]
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Prerequisites
|
|
28
|
+
|
|
29
|
+
- Next.js 14+ with App Router
|
|
30
|
+
- Octavus account with API key
|
|
31
|
+
- An agent configured in Octavus
|
|
32
|
+
|
|
33
|
+
## Step 1: Install Dependencies
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npm install @octavus/server-sdk @octavus/react
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Step 2: Configure Environment
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
# .env.local
|
|
43
|
+
OCTAVUS_API_URL=https://octavus.ai
|
|
44
|
+
OCTAVUS_API_KEY=your-api-key
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Step 3: Create the Octavus Client
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
// lib/octavus.ts
|
|
51
|
+
import { OctavusClient } from '@octavus/server-sdk';
|
|
52
|
+
|
|
53
|
+
export const octavus = new OctavusClient({
|
|
54
|
+
baseUrl: process.env.OCTAVUS_API_URL!,
|
|
55
|
+
apiKey: process.env.OCTAVUS_API_KEY!,
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Step 4: Create Session Endpoint
|
|
60
|
+
|
|
61
|
+
Sessions hold conversation state. Create one when the user opens the chat:
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
// app/api/sessions/route.ts
|
|
65
|
+
import { NextResponse } from 'next/server';
|
|
66
|
+
import { octavus } from '@/lib/octavus';
|
|
67
|
+
|
|
68
|
+
export async function POST(request: Request) {
|
|
69
|
+
const { agentId, input } = await request.json();
|
|
70
|
+
|
|
71
|
+
// Create a new session with initial input variables
|
|
72
|
+
const sessionId = await octavus.agentSessions.create(agentId, input);
|
|
73
|
+
|
|
74
|
+
return NextResponse.json({ sessionId });
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**Protocol Note:** The `input` object contains variables defined in your agent's protocol. For example, if your agent has `COMPANY_NAME` as an input variable:
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
const sessionId = await octavus.agentSessions.create(agentId, {
|
|
82
|
+
COMPANY_NAME: 'Acme Corp',
|
|
83
|
+
USER_ID: user.id,
|
|
84
|
+
});
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Step 5: Create Trigger Endpoint
|
|
88
|
+
|
|
89
|
+
Triggers execute agent actions. The `user-message` trigger is the most common:
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
// app/api/trigger/route.ts
|
|
93
|
+
import { toSSEStream } from '@octavus/server-sdk';
|
|
94
|
+
import { octavus } from '@/lib/octavus';
|
|
95
|
+
|
|
96
|
+
export async function POST(request: Request) {
|
|
97
|
+
const { sessionId, triggerName, input } = await request.json();
|
|
98
|
+
|
|
99
|
+
// Attach to the session with tool handlers
|
|
100
|
+
const session = octavus.agentSessions.attach(sessionId, {
|
|
101
|
+
tools: {
|
|
102
|
+
// Tool handlers run on YOUR server, not Octavus
|
|
103
|
+
'get-user-account': async (args) => {
|
|
104
|
+
const userId = args.userId as string;
|
|
105
|
+
// Fetch from your database
|
|
106
|
+
const user = await db.users.findUnique({ where: { id: userId } });
|
|
107
|
+
return {
|
|
108
|
+
name: user.name,
|
|
109
|
+
email: user.email,
|
|
110
|
+
plan: user.plan,
|
|
111
|
+
};
|
|
112
|
+
},
|
|
113
|
+
|
|
114
|
+
'create-support-ticket': async (args) => {
|
|
115
|
+
const ticket = await db.tickets.create({
|
|
116
|
+
data: {
|
|
117
|
+
summary: args.summary as string,
|
|
118
|
+
priority: args.priority as string,
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
return {
|
|
122
|
+
ticketId: ticket.id,
|
|
123
|
+
estimatedResponse: '24 hours',
|
|
124
|
+
};
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
// trigger() returns parsed events, toSSEStream() converts to SSE format
|
|
130
|
+
const events = session.trigger(triggerName, input);
|
|
131
|
+
|
|
132
|
+
return new Response(toSSEStream(events), {
|
|
133
|
+
headers: {
|
|
134
|
+
'Content-Type': 'text/event-stream',
|
|
135
|
+
'Cache-Control': 'no-cache',
|
|
136
|
+
Connection: 'keep-alive',
|
|
137
|
+
},
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
**Protocol Note:** Tool names and arguments are defined in your agent's protocol YAML. The tool handlers here must match those definitions.
|
|
143
|
+
|
|
144
|
+
## Step 6: Build the Chat Component
|
|
145
|
+
|
|
146
|
+
```tsx
|
|
147
|
+
// components/Chat.tsx
|
|
148
|
+
'use client';
|
|
149
|
+
|
|
150
|
+
import { useState, useMemo } from 'react';
|
|
151
|
+
import { useOctavusChat, createHttpTransport } from '@octavus/react';
|
|
152
|
+
|
|
153
|
+
interface ChatProps {
|
|
154
|
+
sessionId: string;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export function Chat({ sessionId }: ChatProps) {
|
|
158
|
+
const [inputValue, setInputValue] = useState('');
|
|
159
|
+
|
|
160
|
+
// Create transport - memoized on sessionId
|
|
161
|
+
const transport = useMemo(
|
|
162
|
+
() =>
|
|
163
|
+
createHttpTransport({
|
|
164
|
+
triggerRequest: (triggerName, input) =>
|
|
165
|
+
fetch('/api/trigger', {
|
|
166
|
+
method: 'POST',
|
|
167
|
+
headers: { 'Content-Type': 'application/json' },
|
|
168
|
+
body: JSON.stringify({ sessionId, triggerName, input }),
|
|
169
|
+
}),
|
|
170
|
+
}),
|
|
171
|
+
[sessionId],
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
const { messages, status, send } = useOctavusChat({ transport });
|
|
175
|
+
|
|
176
|
+
const handleSubmit = async (e: React.FormEvent) => {
|
|
177
|
+
e.preventDefault();
|
|
178
|
+
if (!inputValue.trim() || status === 'streaming') return;
|
|
179
|
+
|
|
180
|
+
const message = inputValue.trim();
|
|
181
|
+
setInputValue('');
|
|
182
|
+
|
|
183
|
+
// Send triggers the 'user-message' action
|
|
184
|
+
// The third argument adds the user message to the UI
|
|
185
|
+
await send(
|
|
186
|
+
'user-message',
|
|
187
|
+
{ USER_MESSAGE: message },
|
|
188
|
+
{ userMessage: { content: message } },
|
|
189
|
+
);
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
return (
|
|
193
|
+
<div className="flex flex-col h-screen">
|
|
194
|
+
{/* Messages */}
|
|
195
|
+
<div className="flex-1 overflow-y-auto p-4 space-y-4">
|
|
196
|
+
{messages.map((msg) => (
|
|
197
|
+
<div
|
|
198
|
+
key={msg.id}
|
|
199
|
+
className={msg.role === 'user' ? 'text-right' : 'text-left'}
|
|
200
|
+
>
|
|
201
|
+
<div
|
|
202
|
+
className={`inline-block p-3 rounded-lg ${
|
|
203
|
+
msg.role === 'user'
|
|
204
|
+
? 'bg-blue-500 text-white'
|
|
205
|
+
: 'bg-gray-100'
|
|
206
|
+
}`}
|
|
207
|
+
>
|
|
208
|
+
{msg.parts.map((part, i) => {
|
|
209
|
+
if (part.type === 'text') {
|
|
210
|
+
return <p key={i}>{part.text}</p>;
|
|
211
|
+
}
|
|
212
|
+
if (part.type === 'tool-call') {
|
|
213
|
+
return (
|
|
214
|
+
<div key={i} className="text-sm opacity-70">
|
|
215
|
+
Using {part.toolName}...
|
|
216
|
+
</div>
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
return null;
|
|
220
|
+
})}
|
|
221
|
+
</div>
|
|
222
|
+
</div>
|
|
223
|
+
))}
|
|
224
|
+
</div>
|
|
225
|
+
|
|
226
|
+
{/* Input */}
|
|
227
|
+
<form onSubmit={handleSubmit} className="p-4 border-t">
|
|
228
|
+
<div className="flex gap-2">
|
|
229
|
+
<input
|
|
230
|
+
type="text"
|
|
231
|
+
value={inputValue}
|
|
232
|
+
onChange={(e) => setInputValue(e.target.value)}
|
|
233
|
+
placeholder="Type a message..."
|
|
234
|
+
className="flex-1 px-4 py-2 border rounded-lg"
|
|
235
|
+
disabled={status === 'streaming'}
|
|
236
|
+
/>
|
|
237
|
+
<button
|
|
238
|
+
type="submit"
|
|
239
|
+
disabled={status === 'streaming'}
|
|
240
|
+
className="px-4 py-2 bg-blue-500 text-white rounded-lg"
|
|
241
|
+
>
|
|
242
|
+
{status === 'streaming' ? 'Sending...' : 'Send'}
|
|
243
|
+
</button>
|
|
244
|
+
</div>
|
|
245
|
+
</form>
|
|
246
|
+
</div>
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
## Step 7: Create the Page
|
|
252
|
+
|
|
253
|
+
```tsx
|
|
254
|
+
// app/chat/page.tsx
|
|
255
|
+
'use client';
|
|
256
|
+
|
|
257
|
+
import { useEffect, useState } from 'react';
|
|
258
|
+
import { Chat } from '@/components/Chat';
|
|
259
|
+
|
|
260
|
+
const AGENT_ID = 'your-agent-id'; // From Octavus dashboard
|
|
261
|
+
|
|
262
|
+
export default function ChatPage() {
|
|
263
|
+
const [sessionId, setSessionId] = useState<string | null>(null);
|
|
264
|
+
|
|
265
|
+
useEffect(() => {
|
|
266
|
+
// Create session on mount
|
|
267
|
+
fetch('/api/sessions', {
|
|
268
|
+
method: 'POST',
|
|
269
|
+
headers: { 'Content-Type': 'application/json' },
|
|
270
|
+
body: JSON.stringify({
|
|
271
|
+
agentId: AGENT_ID,
|
|
272
|
+
input: {
|
|
273
|
+
COMPANY_NAME: 'Acme Corp',
|
|
274
|
+
},
|
|
275
|
+
}),
|
|
276
|
+
})
|
|
277
|
+
.then((res) => res.json())
|
|
278
|
+
.then((data) => setSessionId(data.sessionId));
|
|
279
|
+
}, []);
|
|
280
|
+
|
|
281
|
+
if (!sessionId) {
|
|
282
|
+
return <div className="p-8">Loading...</div>;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
return <Chat sessionId={sessionId} />;
|
|
286
|
+
}
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
## Protocol Integration
|
|
290
|
+
|
|
291
|
+
Your agent's protocol defines the triggers and tools. Here's how the code maps to protocol:
|
|
292
|
+
|
|
293
|
+
### Triggers
|
|
294
|
+
|
|
295
|
+
```yaml
|
|
296
|
+
# In your agent's protocol.yaml
|
|
297
|
+
triggers:
|
|
298
|
+
user-message:
|
|
299
|
+
description: User sends a chat message
|
|
300
|
+
input:
|
|
301
|
+
USER_MESSAGE:
|
|
302
|
+
type: string
|
|
303
|
+
description: The user's message
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
The `send()` call maps directly:
|
|
307
|
+
|
|
308
|
+
```typescript
|
|
309
|
+
await send(
|
|
310
|
+
'user-message', // trigger name
|
|
311
|
+
{ USER_MESSAGE: message }, // trigger inputs
|
|
312
|
+
{ userMessage: { content: message } },
|
|
313
|
+
);
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
### Tools
|
|
317
|
+
|
|
318
|
+
```yaml
|
|
319
|
+
# In your agent's protocol.yaml
|
|
320
|
+
tools:
|
|
321
|
+
get-user-account:
|
|
322
|
+
description: Fetch user account details
|
|
323
|
+
parameters:
|
|
324
|
+
userId:
|
|
325
|
+
type: string
|
|
326
|
+
description: The user ID to look up
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
Tool handlers receive the parameters as `args`:
|
|
330
|
+
|
|
331
|
+
```typescript
|
|
332
|
+
'get-user-account': async (args) => {
|
|
333
|
+
const userId = args.userId as string;
|
|
334
|
+
// ...
|
|
335
|
+
}
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
## Next Steps
|
|
339
|
+
|
|
340
|
+
- [Protocol Overview](/docs/protocol/overview) — Define agent behavior
|
|
341
|
+
- [Messages](/docs/client-sdk/messages) — Rich message rendering
|
|
342
|
+
- [Streaming](/docs/client-sdk/streaming) — Advanced streaming UI
|
|
343
|
+
|