@agno-hq/chat-react 0.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/LICENSE +21 -0
- package/README.md +270 -0
- package/dist/index.cjs +1967 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +835 -0
- package/dist/index.d.ts +835 -0
- package/dist/index.js +1928 -0
- package/dist/index.js.map +1 -0
- package/dist/styles.css +1293 -0
- package/package.json +66 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Agno
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
# @agno-hq/chat-react
|
|
2
|
+
|
|
3
|
+
Headless React hook (`useAgnoChat`) plus drop-in UI components for streaming **any
|
|
4
|
+
Agno agent, team, or workflow** from an [AgentOS](https://docs.agno.com) backend.
|
|
5
|
+
|
|
6
|
+
It speaks the AgentOS HTTP run protocol directly: it POSTs to the run endpoint,
|
|
7
|
+
parses the streamed events, and accumulates them into render-ready messages —
|
|
8
|
+
content, tool calls, reasoning, citations, media — while exposing the raw event
|
|
9
|
+
feed, live status, and human-in-the-loop pauses.
|
|
10
|
+
|
|
11
|
+
```tsx
|
|
12
|
+
import { AgnoChat } from '@agno-hq/chat-react'
|
|
13
|
+
import '@agno-hq/chat-react/styles.css'
|
|
14
|
+
|
|
15
|
+
export default function Page() {
|
|
16
|
+
return <AgnoChat baseUrl="http://localhost:7777" showEventLog allowFiles />
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
That's the zero-wiring widget: it discovers the agents/teams/workflows on your
|
|
21
|
+
AgentOS, shows a selector, and runs a full chat. For full control, use the hook.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Install
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install @agno-hq/chat-react
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
`react` and `react-dom` (>=18) are peer dependencies. The library ships
|
|
32
|
+
compiled ESM + CommonJS bundles with bundled type declarations, so it works out
|
|
33
|
+
of the box in any modern bundler (Vite, Next.js, Webpack, etc.) with no extra
|
|
34
|
+
config. Import the stylesheet once (see below).
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## The hook: `useAgnoChat`
|
|
39
|
+
|
|
40
|
+
```tsx
|
|
41
|
+
import { useAgnoChat, ChatWindow } from '@agno-hq/chat-react'
|
|
42
|
+
import '@agno-hq/chat-react/styles.css'
|
|
43
|
+
|
|
44
|
+
function Chat() {
|
|
45
|
+
const chat = useAgnoChat({
|
|
46
|
+
baseUrl: 'http://localhost:7777',
|
|
47
|
+
entity: { type: 'agent', id: 'agno_assist', name: 'Agno Assist' },
|
|
48
|
+
userId: 'user-123',
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
return <ChatWindow chat={chat} />
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
`entity.type` is `'agent' | 'team' | 'workflow'` and `entity.id` is the
|
|
56
|
+
agent/team/workflow id — the same hook drives all three.
|
|
57
|
+
|
|
58
|
+
### What the hook returns
|
|
59
|
+
|
|
60
|
+
| Value | Type | Description |
|
|
61
|
+
|---|---|---|
|
|
62
|
+
| `messages` | `ChatMessage[]` | Full transcript, oldest first. |
|
|
63
|
+
| `streamingMessage` | `ChatMessage \| null` | The agent message currently streaming. |
|
|
64
|
+
| `events` | `RunEventData[]` | Every raw event from the latest run, in order. |
|
|
65
|
+
| `currentEvent` | `RunEventData \| null` | The most recent event. |
|
|
66
|
+
| `status` | `'idle' \| 'streaming' \| 'paused' \| 'completed' \| 'error' \| 'cancelled'` | Run lifecycle. |
|
|
67
|
+
| `activity` | `string \| null` | Live label, e.g. `"Calling get_weather"`, `"Reasoning"`. |
|
|
68
|
+
| `isStreaming` / `isPaused` | `boolean` | Convenience flags. |
|
|
69
|
+
| `error` | `string \| null` | Last error message. |
|
|
70
|
+
| `sessionId` | `string \| undefined` | Auto-captured from the first run. |
|
|
71
|
+
| `tools` | `ToolExecution[]` | Tool calls of the active message. |
|
|
72
|
+
| `reasoning` | `ReasoningStep[]` | Reasoning steps of the active message. |
|
|
73
|
+
| `pendingRequirements` | `RunRequirement[]` | Outstanding human-in-the-loop asks. |
|
|
74
|
+
|
|
75
|
+
### Actions
|
|
76
|
+
|
|
77
|
+
| Action | Description |
|
|
78
|
+
|---|---|
|
|
79
|
+
| `sendMessage(text, { files? })` | Send a message and stream the response. |
|
|
80
|
+
| `cancel()` | Abort the active run (also calls the cancel endpoint). |
|
|
81
|
+
| `continueRun({ tools?, stepRequirements? })` | Resume a paused run with resolved requirements. |
|
|
82
|
+
| `respondToConfirmation(approve)` | Approve/reject pending tool confirmations, then continue. |
|
|
83
|
+
| `submitUserInput(values)` | Provide values for pending input fields, then continue. |
|
|
84
|
+
| `reset()` | Clear the transcript and start a new session. |
|
|
85
|
+
| `setMessages(...)` | Replace the transcript (e.g. after restoring a session). |
|
|
86
|
+
| `client` | The underlying `AgnoClient` for discovery/session calls. |
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Components
|
|
91
|
+
|
|
92
|
+
All components are styled by `@agno-hq/chat-react/styles.css` (dark by default; add
|
|
93
|
+
the `agno-light` class on a wrapper for light mode). Every piece is exported so
|
|
94
|
+
you can compose your own layout.
|
|
95
|
+
|
|
96
|
+
| Component | Purpose |
|
|
97
|
+
|---|---|
|
|
98
|
+
| `<AgnoChat>` | All-in-one widget: discovery, selector, chat, optional event log. |
|
|
99
|
+
| `<ChatWindow chat={chat}>` | Full chat surface built from a `useAgnoChat` result. |
|
|
100
|
+
| `<MessageList>` | Auto-scrolling transcript with live status + footer slot. |
|
|
101
|
+
| `<Message>` | A single message: content, tools, reasoning, media, citations. |
|
|
102
|
+
| `<ChatInput>` | Multiline input with file attach, send, and stop. |
|
|
103
|
+
| `<ToolCalls>` | Collapsible tool-call cards (name, args, result, status). |
|
|
104
|
+
| `<Reasoning>` | Collapsible reasoning-steps panel. |
|
|
105
|
+
| `<Citations>` | References / source URLs. |
|
|
106
|
+
| `<Multimedia>` | Images, video, and audio attachments. |
|
|
107
|
+
| `<StatusIndicator>` | Animated "what is it doing now" line. |
|
|
108
|
+
| `<EventLog>` | Developer feed of every raw run event. |
|
|
109
|
+
| `<HumanInput>` | Human-in-the-loop panel (confirm / reject / input). |
|
|
110
|
+
| `<EntitySelector>` | Dropdown of agents, teams, and workflows. |
|
|
111
|
+
| `<SessionList>` | Sidebar of past sessions — click to load, trash to delete. |
|
|
112
|
+
| `<Markdown>` | The built-in lightweight Markdown renderer. |
|
|
113
|
+
|
|
114
|
+
### Bring your own Markdown
|
|
115
|
+
|
|
116
|
+
The built-in renderer covers code blocks, inline code, bold/italic, links,
|
|
117
|
+
headings and lists. For full GFM (tables, etc.), pass `renderMarkdown`:
|
|
118
|
+
|
|
119
|
+
```tsx
|
|
120
|
+
import ReactMarkdown from 'react-markdown'
|
|
121
|
+
import remarkGfm from 'remark-gfm'
|
|
122
|
+
|
|
123
|
+
<ChatWindow
|
|
124
|
+
chat={chat}
|
|
125
|
+
renderMarkdown={(c) => <ReactMarkdown remarkPlugins={[remarkGfm]}>{c}</ReactMarkdown>}
|
|
126
|
+
/>
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## Human-in-the-loop
|
|
132
|
+
|
|
133
|
+
When a run pauses for a tool confirmation or for user input, `status` becomes
|
|
134
|
+
`'paused'` and `pendingRequirements` / the paused message's `tool_calls`
|
|
135
|
+
describe what's needed. `<ChatWindow>` renders `<HumanInput>` automatically; to
|
|
136
|
+
build your own UI, call:
|
|
137
|
+
|
|
138
|
+
```tsx
|
|
139
|
+
await chat.respondToConfirmation(true) // approve pending tool calls
|
|
140
|
+
await chat.respondToConfirmation(false) // reject
|
|
141
|
+
await chat.submitUserInput({ city: 'Lisbon' }) // fill input fields, then continue
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Agents and teams resume via the `/continue` endpoint with resolved `tools`;
|
|
145
|
+
workflows resume with `step_requirements`. The hook picks the right one based on
|
|
146
|
+
the selected entity type.
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Session history
|
|
151
|
+
|
|
152
|
+
The hook tracks past sessions for the selected entity:
|
|
153
|
+
|
|
154
|
+
```tsx
|
|
155
|
+
const chat = useAgnoChat({ baseUrl, entity })
|
|
156
|
+
|
|
157
|
+
chat.sessions // SessionEntry[]
|
|
158
|
+
chat.sessionsLoading // boolean
|
|
159
|
+
await chat.refreshSessions() // fetch the list
|
|
160
|
+
await chat.loadSession(sessionId) // load a transcript into the chat
|
|
161
|
+
await chat.deleteSession(sessionId)
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Render them with `<SessionList>`:
|
|
165
|
+
|
|
166
|
+
```tsx
|
|
167
|
+
<SessionList
|
|
168
|
+
sessions={chat.sessions}
|
|
169
|
+
activeSessionId={chat.sessionId}
|
|
170
|
+
loading={chat.sessionsLoading}
|
|
171
|
+
onSelect={chat.loadSession}
|
|
172
|
+
onDelete={chat.deleteSession}
|
|
173
|
+
onNew={chat.reset}
|
|
174
|
+
/>
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
The all-in-one widget shows this sidebar with `showSessions`:
|
|
178
|
+
|
|
179
|
+
```tsx
|
|
180
|
+
<AgnoChat baseUrl="http://localhost:7777" showSessions showEventLog />
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## Lower-level API
|
|
186
|
+
|
|
187
|
+
```tsx
|
|
188
|
+
import { AgnoClient, streamRun } from '@agno-hq/chat-react'
|
|
189
|
+
|
|
190
|
+
const client = new AgnoClient({ baseUrl: 'http://localhost:7777', headers: { Authorization: 'Bearer …' } })
|
|
191
|
+
|
|
192
|
+
await client.getEntities() // agents + teams + workflows
|
|
193
|
+
await client.getSessions('agent', 'agno_assist')
|
|
194
|
+
await client.getSessionRuns('agent', sessionId) // rehydrate history
|
|
195
|
+
await client.cancelRun('agent', 'agno_assist', runId)
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
`streamRun` is the raw streaming primitive (parses the wire format and emits
|
|
199
|
+
normalised events) if you want to bypass the hook entirely.
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## Running the example
|
|
204
|
+
|
|
205
|
+
The `example/` folder is a Vite app demonstrating both the widget and the hook
|
|
206
|
+
(with a live status panel + event log). It imports the library from source.
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
cd example
|
|
210
|
+
npm install
|
|
211
|
+
npm run dev
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Then open the app, set your AgentOS URL (default `http://localhost:7777`), and
|
|
215
|
+
pick an agent, team, or workflow.
|
|
216
|
+
|
|
217
|
+
> Start an AgentOS first — see the Agno cookbooks under `cookbook/05_agent_os/`.
|
|
218
|
+
|
|
219
|
+
### CORS
|
|
220
|
+
|
|
221
|
+
The chat runs in the browser, so **your AgentOS must allow the page's origin**.
|
|
222
|
+
The example dev server is pinned to port **5173** (`strictPort`), so add that
|
|
223
|
+
origin when constructing AgentOS:
|
|
224
|
+
|
|
225
|
+
```python
|
|
226
|
+
AgentOS(..., cors_allowed_origins=["http://localhost:5173"])
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
A symptom of a CORS mismatch is an empty entity dropdown and a
|
|
230
|
+
`Disallowed CORS origin` response to the preflight request.
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## Notes
|
|
235
|
+
|
|
236
|
+
- **Auth / headers** — pass `headers` (or a pre-built `client`) to send an
|
|
237
|
+
`Authorization` header on every request.
|
|
238
|
+
- **Sessions** — `sessionId` is captured automatically on the first run. To
|
|
239
|
+
restore history, call `client.getSessionRuns(...)` and map runs into
|
|
240
|
+
`ChatMessage[]`, then `chat.setMessages(...)`.
|
|
241
|
+
- **Wire format** — handles both AgentOS streaming shapes (the legacy flat event
|
|
242
|
+
objects and the `{ event, data }` SSE envelope).
|
|
243
|
+
- **Dependencies** — the library itself depends only on React (peer). The
|
|
244
|
+
example additionally uses Vite.
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## Local development
|
|
249
|
+
|
|
250
|
+
```bash
|
|
251
|
+
git clone https://github.com/agno-agi/agno-chat-react.git
|
|
252
|
+
cd agno-chat-react
|
|
253
|
+
npm install
|
|
254
|
+
npm run typecheck # tsc --noEmit
|
|
255
|
+
npm run build # tsup -> dist/ (ESM + CJS + .d.ts)
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
The published package is built with [tsup](https://tsup.egoist.dev) into
|
|
259
|
+
`dist/` (ESM `index.js`, CommonJS `index.cjs`, type declarations, and
|
|
260
|
+
`styles.css`). The `example/` app, however, resolves the library straight from
|
|
261
|
+
`src/` via a Vite alias, so you can develop against live changes without
|
|
262
|
+
rebuilding — see [Running the example](#running-the-example). `prepublishOnly`
|
|
263
|
+
runs the typecheck and build automatically, so `npm publish` always ships a
|
|
264
|
+
fresh `dist/`.
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## License
|
|
269
|
+
|
|
270
|
+
[MIT](./LICENSE) © Agno
|