@rodrigocoliveira/agno-react 1.0.1 → 1.0.2
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/README.md +361 -81
- package/dist/index.js +3 -3
- package/dist/ui.d.mts +891 -0
- package/dist/ui.d.ts +891 -0
- package/dist/ui.js +3625 -0
- package/dist/ui.mjs +3455 -0
- package/package.json +118 -12
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @rodrigocoliveira/agno-react
|
|
2
2
|
|
|
3
|
-
React hooks for Agno client with full TypeScript support.
|
|
3
|
+
React hooks and pre-built UI components for Agno client with full TypeScript support.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -12,11 +12,14 @@ This package includes `@rodrigocoliveira/agno-client` and `@rodrigocoliveira/agn
|
|
|
12
12
|
|
|
13
13
|
## Features
|
|
14
14
|
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
15
|
+
- **Easy Integration** — Drop-in React hooks for Agno agents
|
|
16
|
+
- **Context Provider** — Manages client lifecycle automatically
|
|
17
|
+
- **Real-time Updates** — React state synced with streaming updates
|
|
18
|
+
- **Pre-built UI Components** — Compound components and primitives via `/ui` sub-path
|
|
19
|
+
- **Audio Recording & Transcription** — Record audio to send or transcribe to text
|
|
20
|
+
- **Frontend Tool Execution (HITL)** — Execute agent tools in the browser
|
|
21
|
+
- **Type-Safe** — Full TypeScript support
|
|
22
|
+
- **Familiar API** — Matches the original Agno React hooks design
|
|
20
23
|
|
|
21
24
|
## Quick Start
|
|
22
25
|
|
|
@@ -32,13 +35,9 @@ function App() {
|
|
|
32
35
|
endpoint: 'http://localhost:7777',
|
|
33
36
|
mode: 'agent',
|
|
34
37
|
agentId: 'your-agent-id',
|
|
35
|
-
userId: 'user-123',
|
|
36
|
-
headers: {
|
|
37
|
-
|
|
38
|
-
},
|
|
39
|
-
params: { // Optional: Global query params for all requests
|
|
40
|
-
locale: 'en-US'
|
|
41
|
-
}
|
|
38
|
+
userId: 'user-123',
|
|
39
|
+
headers: { 'X-API-Version': 'v2' },
|
|
40
|
+
params: { locale: 'en-US' }
|
|
42
41
|
}}
|
|
43
42
|
>
|
|
44
43
|
<YourComponents />
|
|
@@ -80,6 +79,36 @@ function ChatComponent() {
|
|
|
80
79
|
}
|
|
81
80
|
```
|
|
82
81
|
|
|
82
|
+
### 3. Or Use Pre-built UI Components
|
|
83
|
+
|
|
84
|
+
For a full-featured chat interface with minimal code, use the compound components from the `/ui` sub-path:
|
|
85
|
+
|
|
86
|
+
```tsx
|
|
87
|
+
import { AgnoChat } from '@rodrigocoliveira/agno-react/ui';
|
|
88
|
+
|
|
89
|
+
function ChatPage() {
|
|
90
|
+
return (
|
|
91
|
+
<AgnoChat>
|
|
92
|
+
<AgnoChat.Messages>
|
|
93
|
+
<AgnoChat.EmptyState>
|
|
94
|
+
<h3>Welcome!</h3>
|
|
95
|
+
<p>Start a conversation with the agent.</p>
|
|
96
|
+
<AgnoChat.SuggestedPrompts
|
|
97
|
+
prompts={[
|
|
98
|
+
{ text: 'What can you help me with?' },
|
|
99
|
+
{ text: 'Show me a code example' },
|
|
100
|
+
]}
|
|
101
|
+
/>
|
|
102
|
+
</AgnoChat.EmptyState>
|
|
103
|
+
</AgnoChat.Messages>
|
|
104
|
+
<AgnoChat.ToolStatus />
|
|
105
|
+
<AgnoChat.ErrorBar />
|
|
106
|
+
<AgnoChat.Input placeholder="Ask me anything..." />
|
|
107
|
+
</AgnoChat>
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
83
112
|
## API Reference
|
|
84
113
|
|
|
85
114
|
### AgnoProvider
|
|
@@ -93,8 +122,8 @@ Provider component that creates and manages an `AgnoClient` instance.
|
|
|
93
122
|
```
|
|
94
123
|
|
|
95
124
|
**Props:**
|
|
96
|
-
- `config` (AgnoClientConfig)
|
|
97
|
-
- `children` (ReactNode)
|
|
125
|
+
- `config` (AgnoClientConfig) — Client configuration
|
|
126
|
+
- `children` (ReactNode) — Child components
|
|
98
127
|
|
|
99
128
|
### useAgnoClient()
|
|
100
129
|
|
|
@@ -145,12 +174,6 @@ await sendMessage('Hello!', {
|
|
|
145
174
|
await sendMessage('Hello!', {
|
|
146
175
|
params: { temperature: '0.7', max_tokens: '500' }
|
|
147
176
|
});
|
|
148
|
-
|
|
149
|
-
// Send with both headers and params
|
|
150
|
-
await sendMessage('Hello!', {
|
|
151
|
-
headers: { 'X-Request-ID': '12345' },
|
|
152
|
-
params: { debug: 'true' }
|
|
153
|
-
});
|
|
154
177
|
```
|
|
155
178
|
|
|
156
179
|
#### `clearMessages()`
|
|
@@ -167,96 +190,353 @@ Hook for session management.
|
|
|
167
190
|
const {
|
|
168
191
|
sessions, // SessionEntry[] - Available sessions
|
|
169
192
|
currentSessionId, // string | undefined - Current session ID
|
|
170
|
-
loadSession, // (sessionId) => Promise<ChatMessage[]>
|
|
171
|
-
fetchSessions, // () => Promise<SessionEntry[]>
|
|
193
|
+
loadSession, // (sessionId, options?) => Promise<ChatMessage[]>
|
|
194
|
+
fetchSessions, // (options?) => Promise<SessionEntry[]>
|
|
172
195
|
isLoading, // boolean - Is loading session
|
|
173
196
|
error, // string | undefined - Current error
|
|
174
197
|
} = useAgnoSession();
|
|
175
198
|
```
|
|
176
199
|
|
|
177
|
-
|
|
200
|
+
### useAgnoActions()
|
|
201
|
+
|
|
202
|
+
Hook for common actions and initialization.
|
|
178
203
|
|
|
179
204
|
```tsx
|
|
180
|
-
|
|
181
|
-
|
|
205
|
+
const {
|
|
206
|
+
initialize, // (options?) => Promise<{ agents, teams }>
|
|
207
|
+
checkStatus, // (options?) => Promise<boolean>
|
|
208
|
+
fetchAgents, // (options?) => Promise<AgentDetails[]>
|
|
209
|
+
fetchTeams, // (options?) => Promise<TeamDetails[]>
|
|
210
|
+
updateConfig, // (updates) => void
|
|
211
|
+
isInitializing, // boolean
|
|
212
|
+
error, // string | undefined
|
|
213
|
+
} = useAgnoActions();
|
|
214
|
+
```
|
|
182
215
|
|
|
183
|
-
|
|
184
|
-
// Fetch sessions with optional query params
|
|
185
|
-
fetchSessions({ params: { limit: '50', status: 'active' } });
|
|
186
|
-
}, [fetchSessions]);
|
|
216
|
+
### useAgnoToolExecution()
|
|
187
217
|
|
|
188
|
-
|
|
189
|
-
// Load session with optional params
|
|
190
|
-
loadSession(sessionId, { params: { include_metadata: 'true' } });
|
|
191
|
-
};
|
|
218
|
+
Hook for frontend tool execution (Human-in-the-Loop).
|
|
192
219
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
220
|
+
```tsx
|
|
221
|
+
const toolHandlers = {
|
|
222
|
+
show_alert: async (args) => {
|
|
223
|
+
alert(args.content);
|
|
224
|
+
return { success: true };
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
// Auto-execute tools immediately
|
|
229
|
+
useAgnoToolExecution(toolHandlers);
|
|
230
|
+
|
|
231
|
+
// Or require manual confirmation
|
|
232
|
+
useAgnoToolExecution(toolHandlers, false);
|
|
205
233
|
```
|
|
206
234
|
|
|
207
|
-
###
|
|
235
|
+
### useAgnoMemory()
|
|
208
236
|
|
|
209
|
-
Hook for
|
|
237
|
+
Hook for memory management.
|
|
210
238
|
|
|
211
239
|
```tsx
|
|
212
240
|
const {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
} =
|
|
241
|
+
memories,
|
|
242
|
+
topics,
|
|
243
|
+
isLoading,
|
|
244
|
+
fetchMemories,
|
|
245
|
+
createMemory,
|
|
246
|
+
updateMemory,
|
|
247
|
+
deleteMemory,
|
|
248
|
+
} = useAgnoMemory();
|
|
221
249
|
```
|
|
222
250
|
|
|
223
|
-
|
|
251
|
+
### useAgnoCustomEvents()
|
|
252
|
+
|
|
253
|
+
Hook for listening to custom events yielded by the backend.
|
|
224
254
|
|
|
225
255
|
```tsx
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
256
|
+
useAgnoCustomEvents((event) => {
|
|
257
|
+
console.log('Custom event:', event);
|
|
258
|
+
});
|
|
259
|
+
```
|
|
229
260
|
|
|
230
|
-
|
|
231
|
-
// Initialize with optional params
|
|
232
|
-
initialize({ params: { filter: 'active' } });
|
|
233
|
-
}, [initialize]);
|
|
261
|
+
---
|
|
234
262
|
|
|
235
|
-
|
|
236
|
-
// Fetch agents with custom params
|
|
237
|
-
fetchAgents({ params: { page: '2', limit: '20' } });
|
|
238
|
-
};
|
|
263
|
+
## Pre-built UI Components (`/ui` sub-path)
|
|
239
264
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
265
|
+
The library ships with a complete set of pre-built UI components accessible via `@rodrigocoliveira/agno-react/ui`. These components provide a production-ready chat interface with full customization support.
|
|
266
|
+
|
|
267
|
+
### Peer Dependencies
|
|
243
268
|
|
|
244
|
-
|
|
269
|
+
UI components rely on optional peer dependencies. Install only what you need:
|
|
245
270
|
|
|
271
|
+
```bash
|
|
272
|
+
# Core UI dependencies
|
|
273
|
+
npm install @radix-ui/react-slot class-variance-authority clsx tailwind-merge lucide-react
|
|
274
|
+
|
|
275
|
+
# For markdown rendering
|
|
276
|
+
npm install shiki streamdown
|
|
277
|
+
|
|
278
|
+
# For auto-scroll behavior
|
|
279
|
+
npm install use-stick-to-bottom
|
|
280
|
+
|
|
281
|
+
# For additional primitives (as needed)
|
|
282
|
+
npm install @radix-ui/react-accordion @radix-ui/react-avatar @radix-ui/react-collapsible \
|
|
283
|
+
@radix-ui/react-tooltip @radix-ui/react-dropdown-menu @radix-ui/react-hover-card \
|
|
284
|
+
@radix-ui/react-select cmdk
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### Import Path
|
|
288
|
+
|
|
289
|
+
All UI components are imported from the `/ui` sub-path:
|
|
290
|
+
|
|
291
|
+
```tsx
|
|
292
|
+
import { AgnoChat, AgnoChatInterface, AgnoChatInput, Button, Response } from '@rodrigocoliveira/agno-react/ui';
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
### AgnoChat (Compound Component)
|
|
298
|
+
|
|
299
|
+
The primary way to build a full-featured chat interface. Uses a compound component pattern — compose only the pieces you need.
|
|
300
|
+
|
|
301
|
+
```tsx
|
|
302
|
+
import { AgnoChat } from '@rodrigocoliveira/agno-react/ui';
|
|
303
|
+
import type { ToolHandler } from '@rodrigocoliveira/agno-react';
|
|
304
|
+
|
|
305
|
+
const toolHandlers: Record<string, ToolHandler> = {
|
|
306
|
+
show_alert: async (args) => {
|
|
307
|
+
alert(args.content);
|
|
308
|
+
return { success: true };
|
|
309
|
+
},
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
function ChatPage() {
|
|
246
313
|
return (
|
|
247
|
-
<
|
|
248
|
-
<
|
|
249
|
-
|
|
250
|
-
<
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
314
|
+
<AgnoChat toolHandlers={toolHandlers} autoExecuteTools={true}>
|
|
315
|
+
<AgnoChat.Messages
|
|
316
|
+
userAvatar={<img src="/user.png" className="h-8 w-8 rounded-full" />}
|
|
317
|
+
assistantAvatar={<img src="/bot.png" className="h-8 w-8 rounded-full" />}
|
|
318
|
+
messageItemProps={{
|
|
319
|
+
showToolCalls: false,
|
|
320
|
+
showReasoning: false,
|
|
321
|
+
renderActions: (message) => (
|
|
322
|
+
<button onClick={() => navigator.clipboard.writeText(message.content || '')}>
|
|
323
|
+
Copy
|
|
324
|
+
</button>
|
|
325
|
+
),
|
|
326
|
+
}}
|
|
327
|
+
>
|
|
328
|
+
<AgnoChat.EmptyState>
|
|
329
|
+
<h3>Welcome!</h3>
|
|
330
|
+
<p>How can I help you today?</p>
|
|
331
|
+
<AgnoChat.SuggestedPrompts
|
|
332
|
+
prompts={[
|
|
333
|
+
{ icon: <span>⚡</span>, text: 'What can you help me with?' },
|
|
334
|
+
{ icon: <span>💡</span>, text: 'Show me a code example' },
|
|
335
|
+
]}
|
|
336
|
+
/>
|
|
337
|
+
</AgnoChat.EmptyState>
|
|
338
|
+
</AgnoChat.Messages>
|
|
339
|
+
|
|
340
|
+
<AgnoChat.ToolStatus className="bg-violet-500/5 border-violet-500/20" />
|
|
341
|
+
<AgnoChat.ErrorBar className="bg-red-500/5" />
|
|
342
|
+
<AgnoChat.Input
|
|
343
|
+
placeholder="Ask me anything..."
|
|
344
|
+
showAudioRecorder={true}
|
|
345
|
+
audioMode="transcribe"
|
|
346
|
+
transcriptionEndpoint="http://localhost:8000/transcribe"
|
|
347
|
+
/>
|
|
348
|
+
</AgnoChat>
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
**Sub-components:**
|
|
354
|
+
|
|
355
|
+
| Component | Description |
|
|
356
|
+
|-----------|-------------|
|
|
357
|
+
| `AgnoChat` | Root wrapper. Accepts `toolHandlers` and `autoExecuteTools` props. |
|
|
358
|
+
| `AgnoChat.Messages` | Message list with auto-scroll. Accepts `userAvatar`, `assistantAvatar`, `messageItemProps`. |
|
|
359
|
+
| `AgnoChat.EmptyState` | Shown when there are no messages. Place inside `Messages`. |
|
|
360
|
+
| `AgnoChat.SuggestedPrompts` | Clickable prompt suggestions. Place inside `EmptyState`. |
|
|
361
|
+
| `AgnoChat.ToolStatus` | Status bar shown when tools are executing. |
|
|
362
|
+
| `AgnoChat.ErrorBar` | Error display bar. |
|
|
363
|
+
| `AgnoChat.Input` | Chat input with file uploads and optional audio recorder. |
|
|
364
|
+
|
|
365
|
+
---
|
|
366
|
+
|
|
367
|
+
### AgnoChatInterface
|
|
368
|
+
|
|
369
|
+
A single-component shortcut that renders a complete chat interface. Less flexible than `AgnoChat` but requires zero composition.
|
|
370
|
+
|
|
371
|
+
```tsx
|
|
372
|
+
import { AgnoChatInterface } from '@rodrigocoliveira/agno-react/ui';
|
|
373
|
+
|
|
374
|
+
function ChatPage() {
|
|
375
|
+
return (
|
|
376
|
+
<AgnoChatInterface
|
|
377
|
+
placeholder="Type a message..."
|
|
378
|
+
suggestedPrompts={[
|
|
379
|
+
{ text: 'What can you help me with?' },
|
|
380
|
+
{ text: 'Explain how you work' },
|
|
381
|
+
]}
|
|
382
|
+
toolHandlers={toolHandlers}
|
|
383
|
+
showAudioRecorder={true}
|
|
384
|
+
userAvatar={<img src="/user.png" />}
|
|
385
|
+
assistantAvatar={<img src="/bot.png" />}
|
|
386
|
+
emptyState={<div>Start a conversation!</div>}
|
|
387
|
+
classNames={{
|
|
388
|
+
root: 'h-full',
|
|
389
|
+
messagesArea: 'px-4',
|
|
390
|
+
inputArea: 'border-t',
|
|
391
|
+
}}
|
|
392
|
+
/>
|
|
256
393
|
);
|
|
257
394
|
}
|
|
258
395
|
```
|
|
259
396
|
|
|
397
|
+
**Key props:** `className`, `classNames`, `renderMessage`, `renderInput`, `emptyState`, `headerSlot`, `inputToolbarSlot`, `suggestedPrompts`, `toolHandlers`, `autoExecuteTools`, `placeholder`, `userAvatar`, `assistantAvatar`, `fileUpload`, `showAudioRecorder`, `messageItemProps`, `chatInputProps`.
|
|
398
|
+
|
|
399
|
+
---
|
|
400
|
+
|
|
401
|
+
### AgnoChatInput
|
|
402
|
+
|
|
403
|
+
Standalone chat input component with file uploads, audio recording, and transcription support.
|
|
404
|
+
|
|
405
|
+
```tsx
|
|
406
|
+
import { AgnoChatInput } from '@rodrigocoliveira/agno-react/ui';
|
|
407
|
+
|
|
408
|
+
<AgnoChatInput
|
|
409
|
+
onSend={(message) => { /* handle message */ }}
|
|
410
|
+
placeholder="Type a message..."
|
|
411
|
+
showAudioRecorder={true}
|
|
412
|
+
showAttachments={true}
|
|
413
|
+
audioMode="transcribe"
|
|
414
|
+
transcriptionEndpoint="http://localhost:8000/transcribe"
|
|
415
|
+
parseTranscriptionResponse={(data) => data.text}
|
|
416
|
+
onRequestPermission={async () => {
|
|
417
|
+
// WebView: request mic permission from native bridge
|
|
418
|
+
return await NativeBridge.requestMicPermission();
|
|
419
|
+
}}
|
|
420
|
+
fileUpload={{
|
|
421
|
+
accept: 'image/*,.pdf',
|
|
422
|
+
multiple: true,
|
|
423
|
+
maxFiles: 5,
|
|
424
|
+
maxFileSize: 10 * 1024 * 1024,
|
|
425
|
+
}}
|
|
426
|
+
/>
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
**Props:**
|
|
430
|
+
|
|
431
|
+
| Prop | Type | Default | Description |
|
|
432
|
+
|------|------|---------|-------------|
|
|
433
|
+
| `onSend` | `(message: string \| FormData) => void` | required | Called when the user sends a message |
|
|
434
|
+
| `disabled` | `boolean` | `false` | Disable the input |
|
|
435
|
+
| `placeholder` | `string` | — | Input placeholder text |
|
|
436
|
+
| `showAudioRecorder` | `boolean` | `false` | Show the audio recorder button |
|
|
437
|
+
| `showAttachments` | `boolean` | `true` | Show the file attachment button |
|
|
438
|
+
| `audioMode` | `'send' \| 'transcribe'` | `'send'` | Audio recording behavior |
|
|
439
|
+
| `transcriptionEndpoint` | `string` | — | URL to POST audio for transcription (required when `audioMode='transcribe'`) |
|
|
440
|
+
| `transcriptionHeaders` | `Record<string, string>` | — | Extra headers for transcription requests |
|
|
441
|
+
| `parseTranscriptionResponse` | `(data: unknown) => string` | — | Custom parser for transcription API response |
|
|
442
|
+
| `onRequestPermission` | `() => Promise<boolean>` | — | WebView mic permission bridge callback |
|
|
443
|
+
| `fileUpload` | `FileUploadConfig` | — | File upload configuration |
|
|
444
|
+
| `status` | `ChatStatus` | — | Input status (`'idle'`, `'submitted'`, `'streaming'`, `'error'`) |
|
|
445
|
+
| `extraTools` | `ReactNode` | — | Additional toolbar buttons |
|
|
446
|
+
|
|
447
|
+
---
|
|
448
|
+
|
|
449
|
+
### Audio Recorder & Transcription
|
|
450
|
+
|
|
451
|
+
The library includes an `AudioRecorder` component that supports two modes:
|
|
452
|
+
|
|
453
|
+
#### Send mode (default)
|
|
454
|
+
|
|
455
|
+
Records audio, encodes to WAV, and sends the blob directly as a file attachment:
|
|
456
|
+
|
|
457
|
+
```tsx
|
|
458
|
+
<AgnoChatInput
|
|
459
|
+
onSend={handleSend}
|
|
460
|
+
showAudioRecorder={true}
|
|
461
|
+
audioMode="send"
|
|
462
|
+
/>
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
The audio blob is wrapped in a `FormData` with `message="Audio message"` and the WAV file.
|
|
466
|
+
|
|
467
|
+
#### Transcribe mode
|
|
468
|
+
|
|
469
|
+
Records audio, sends it to a transcription endpoint, and inserts the resulting text into the input:
|
|
470
|
+
|
|
471
|
+
```tsx
|
|
472
|
+
<AgnoChatInput
|
|
473
|
+
onSend={handleSend}
|
|
474
|
+
showAudioRecorder={true}
|
|
475
|
+
audioMode="transcribe"
|
|
476
|
+
transcriptionEndpoint="http://localhost:8000/transcribe"
|
|
477
|
+
parseTranscriptionResponse={(data) => data.text}
|
|
478
|
+
/>
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
The component POSTs the WAV file to the endpoint and expects a JSON response. The default parser checks `data.text`, `data.transcript`, and `data.transcription` fields. Provide `parseTranscriptionResponse` to handle custom response shapes.
|
|
482
|
+
|
|
483
|
+
#### WebView Permission Bridging
|
|
484
|
+
|
|
485
|
+
For WebView environments where microphone access requires a native bridge:
|
|
486
|
+
|
|
487
|
+
```tsx
|
|
488
|
+
<AgnoChatInput
|
|
489
|
+
onSend={handleSend}
|
|
490
|
+
showAudioRecorder={true}
|
|
491
|
+
onRequestPermission={async () => {
|
|
492
|
+
// Ask the native app for mic permission before getUserMedia
|
|
493
|
+
return await NativeBridge.requestMicPermission();
|
|
494
|
+
}}
|
|
495
|
+
/>
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
The `onRequestPermission` callback is called before the browser's `getUserMedia`. Return `true` to proceed or `false` to cancel.
|
|
499
|
+
|
|
500
|
+
---
|
|
501
|
+
|
|
502
|
+
### Primitive Components
|
|
503
|
+
|
|
504
|
+
Thin wrappers over Radix UI primitives with Tailwind styling via `class-variance-authority`:
|
|
505
|
+
|
|
506
|
+
| Component | Description |
|
|
507
|
+
|-----------|-------------|
|
|
508
|
+
| `Button` | Button with variants (`default`, `outline`, `ghost`, `destructive`, etc.) |
|
|
509
|
+
| `Badge` | Status badge with variants |
|
|
510
|
+
| `Avatar`, `AvatarImage`, `AvatarFallback` | User/assistant avatar |
|
|
511
|
+
| `InputGroup`, `InputGroupAddon`, `InputGroupButton`, `InputGroupInput`, `InputGroupTextarea` | Composable input groups |
|
|
512
|
+
| `Collapsible`, `CollapsibleTrigger`, `CollapsibleContent` | Expandable sections |
|
|
513
|
+
| `Tooltip`, `TooltipTrigger`, `TooltipContent`, `TooltipProvider` | Hover tooltips |
|
|
514
|
+
| `Accordion`, `AccordionItem`, `AccordionTrigger`, `AccordionContent` | Collapsible accordion |
|
|
515
|
+
| `DropdownMenu` + sub-parts | Dropdown menu |
|
|
516
|
+
| `HoverCard`, `HoverCardTrigger`, `HoverCardContent` | Hover card |
|
|
517
|
+
| `Select` + sub-parts | Select dropdown |
|
|
518
|
+
| `Command`, `CommandInput`, `CommandList`, `CommandItem`, ... | Command palette (cmdk) |
|
|
519
|
+
|
|
520
|
+
---
|
|
521
|
+
|
|
522
|
+
### Base Components
|
|
523
|
+
|
|
524
|
+
Higher-level components for building chat interfaces:
|
|
525
|
+
|
|
526
|
+
| Component | Description |
|
|
527
|
+
|-----------|-------------|
|
|
528
|
+
| `Message`, `MessageContent`, `MessageAvatar` | Low-level message layout shell |
|
|
529
|
+
| `Conversation`, `ConversationContent`, `ConversationEmptyState`, `ConversationScrollButton` | Scrollable conversation container with auto-scroll |
|
|
530
|
+
| `Response` | Markdown renderer with syntax highlighting (shiki + streamdown) |
|
|
531
|
+
| `Tool`, `ToolHeader`, `ToolContent`, `ToolInput`, `ToolOutput` | Collapsible tool call display |
|
|
532
|
+
| `CodeBlock`, `CodeBlockCopyButton` | Syntax-highlighted code block with copy button |
|
|
533
|
+
| `Artifact`, `ArtifactHeader`, `ArtifactContent`, ... | Artifact panel layout |
|
|
534
|
+
| `StreamingIndicator` | Animated typing/loading indicator |
|
|
535
|
+
| `AudioRecorder` | Audio recording with WAV encoding via AudioWorklet |
|
|
536
|
+
| `PromptInput` + sub-parts | Fully composable input system with attachments, speech, model select |
|
|
537
|
+
|
|
538
|
+
---
|
|
539
|
+
|
|
260
540
|
## Complete Example
|
|
261
541
|
|
|
262
542
|
```tsx
|
package/dist/index.js
CHANGED
|
@@ -28,8 +28,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
28
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
29
|
|
|
30
30
|
// src/index.ts
|
|
31
|
-
var
|
|
32
|
-
__export(
|
|
31
|
+
var src_exports = {};
|
|
32
|
+
__export(src_exports, {
|
|
33
33
|
AgnoProvider: () => AgnoProvider,
|
|
34
34
|
ComponentRegistry: () => ComponentRegistry,
|
|
35
35
|
GenerativeUIRenderer: () => GenerativeUIRenderer,
|
|
@@ -67,7 +67,7 @@ __export(index_exports, {
|
|
|
67
67
|
useAgnoTraces: () => useAgnoTraces,
|
|
68
68
|
useToolHandlers: () => useToolHandlers
|
|
69
69
|
});
|
|
70
|
-
module.exports = __toCommonJS(
|
|
70
|
+
module.exports = __toCommonJS(src_exports);
|
|
71
71
|
|
|
72
72
|
// src/context/AgnoContext.tsx
|
|
73
73
|
var import_react = require("react");
|