agentic-ui-kit 0.0.0-stage → 0.2.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 +241 -2
- package/dist/core.js +1 -0
- package/dist/index.js +2875 -0
- package/dist/sse-BA_ebMcH.js +408 -0
- package/dist/styles.css +3 -0
- package/dist/tailwind.css +350 -0
- package/dist/types/core/src/blocks.d.ts +22 -0
- package/dist/types/core/src/events.d.ts +75 -0
- package/dist/types/core/src/index.d.ts +7 -0
- package/dist/types/core/src/partial-json.d.ts +7 -0
- package/dist/types/core/src/reduce.d.ts +33 -0
- package/dist/types/core/src/sse.d.ts +8 -0
- package/dist/types/core/src/types.d.ts +171 -0
- package/dist/types/react/src/components/activity-group.d.ts +13 -0
- package/dist/types/react/src/components/approval-card.d.ts +11 -0
- package/dist/types/react/src/components/attachments.d.ts +78 -0
- package/dist/types/react/src/components/chat-header.d.ts +30 -0
- package/dist/types/react/src/components/chat-list.d.ts +47 -0
- package/dist/types/react/src/components/composer.d.ts +45 -0
- package/dist/types/react/src/components/context-panel.d.ts +13 -0
- package/dist/types/react/src/components/markdown.d.ts +8 -0
- package/dist/types/react/src/components/message-list.d.ts +18 -0
- package/dist/types/react/src/components/messages.d.ts +33 -0
- package/dist/types/react/src/components/model-picker.d.ts +16 -0
- package/dist/types/react/src/components/token-counter.d.ts +16 -0
- package/dist/types/react/src/components/tools.d.ts +68 -0
- package/dist/types/react/src/components/word-fade.d.ts +19 -0
- package/dist/types/react/src/core.d.ts +1 -0
- package/dist/types/react/src/hooks/agent.d.ts +86 -0
- package/dist/types/react/src/hooks/sidebar-state.d.ts +18 -0
- package/dist/types/react/src/hooks/smooth-text.d.ts +9 -0
- package/dist/types/react/src/hooks/sse-transport.d.ts +15 -0
- package/dist/types/react/src/hooks/use-chat.d.ts +68 -0
- package/dist/types/react/src/index.d.ts +57 -0
- package/dist/types/react/src/primitives/appearance.d.ts +38 -0
- package/dist/types/react/src/primitives/badge.d.ts +15 -0
- package/dist/types/react/src/primitives/button.d.ts +32 -0
- package/dist/types/react/src/primitives/caret.d.ts +4 -0
- package/dist/types/react/src/primitives/chat-theme.d.ts +22 -0
- package/dist/types/react/src/primitives/code-block.d.ts +13 -0
- package/dist/types/react/src/primitives/context-menu.d.ts +13 -0
- package/dist/types/react/src/primitives/disclosure.d.ts +16 -0
- package/dist/types/react/src/primitives/highlight.d.ts +13 -0
- package/dist/types/react/src/primitives/menu.d.ts +52 -0
- package/dist/types/react/src/primitives/overlay.d.ts +21 -0
- package/dist/types/react/src/primitives/panel.d.ts +19 -0
- package/dist/types/react/src/primitives/tooltip.d.ts +10 -0
- package/dist/types/react/src/views/app-shell.d.ts +20 -0
- package/dist/types/react/src/views/chat-view.d.ts +51 -0
- package/dist/types/react/src/views/sidebar.d.ts +38 -0
- package/package.json +80 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 bushshrub
|
|
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
CHANGED
|
@@ -1,3 +1,242 @@
|
|
|
1
|
-
#
|
|
1
|
+
# agentic-ui-kit
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
React components for LLM chat and agentic apps: streaming replies with Markdown, math and code; thinking and
|
|
4
|
+
tool-call rows; approvals; tools that change the page around the chat. Themed entirely with CSS variables, so it
|
|
5
|
+
can take on your app's look.
|
|
6
|
+
|
|
7
|
+
> [!WARNING]
|
|
8
|
+
> **This is AI-written slop. You probably shouldn't use it.**
|
|
9
|
+
> It isn't reviewed or hardened, the API will change without notice, and it may stop being maintained at
|
|
10
|
+
> any time. If you still want to try it, pin an exact version, or fork it and treat the code as your own.
|
|
11
|
+
|
|
12
|
+

|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
npm install agentic-ui-kit
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Requires React 19. React is an optional peer dependency, so a server can use `agentic-ui-kit/core` on its own.
|
|
21
|
+
|
|
22
|
+
| Import | What it is |
|
|
23
|
+
| ---------------------------- | ------------------------------------------------------------------------------ |
|
|
24
|
+
| `agentic-ui-kit` | React components and hooks |
|
|
25
|
+
| `agentic-ui-kit/core` | Types, stream events, the message reducer, SSE helpers. No React, no DOM. |
|
|
26
|
+
| `agentic-ui-kit/styles.css` | Precompiled styles, for apps without Tailwind |
|
|
27
|
+
| `agentic-ui-kit/tailwind.css`| The same styles as Tailwind v4 source, for apps that use Tailwind |
|
|
28
|
+
|
|
29
|
+
### Install from source
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
git clone https://github.com/bushshrub/agentic-ui-kit
|
|
33
|
+
cd agentic-ui-kit && pnpm install
|
|
34
|
+
pnpm --filter agentic-ui-kit pack # builds and writes agentic-ui-kit-0.1.0.tgz here
|
|
35
|
+
cd ../your-app && npm install ../agentic-ui-kit/agentic-ui-kit-0.1.0.tgz
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Quick start
|
|
39
|
+
|
|
40
|
+
```tsx
|
|
41
|
+
import { ChatView, sseTransport, useChat } from "agentic-ui-kit";
|
|
42
|
+
import "agentic-ui-kit/styles.css";
|
|
43
|
+
|
|
44
|
+
const transport = sseTransport({ url: "/api/chat" });
|
|
45
|
+
|
|
46
|
+
export function App() {
|
|
47
|
+
const chat = useChat({ transport });
|
|
48
|
+
return (
|
|
49
|
+
<div style={{ height: "100dvh" }}>
|
|
50
|
+
<ChatView
|
|
51
|
+
messages={chat.messages}
|
|
52
|
+
busy={chat.busy}
|
|
53
|
+
onSend={(text) => chat.send(text)}
|
|
54
|
+
onStop={chat.stop}
|
|
55
|
+
approvals={chat.approvals}
|
|
56
|
+
onApprove={chat.respond}
|
|
57
|
+
/>
|
|
58
|
+
</div>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
`ChatView` sizes itself from its container, so it works as a full page, a side panel or a small box in a form
|
|
64
|
+
(`density="full" | "panel" | "inline"`), and several fit side by side.
|
|
65
|
+
|
|
66
|
+
### Using Tailwind v4?
|
|
67
|
+
|
|
68
|
+
Import the Tailwind source instead of `styles.css`, so utilities are generated once by your build:
|
|
69
|
+
|
|
70
|
+
```css
|
|
71
|
+
@import "tailwindcss";
|
|
72
|
+
@import "agentic-ui-kit/tailwind.css";
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
`styles.css` includes Tailwind's base reset (preflight). In an app that already has its own reset, use
|
|
76
|
+
`tailwind.css`.
|
|
77
|
+
|
|
78
|
+
## The backend
|
|
79
|
+
|
|
80
|
+
The kit talks to your backend through a `Transport`. `sseTransport` POSTs the request as JSON and reads a
|
|
81
|
+
`text/event-stream` of events back. Your server translates whatever model API it uses into these events:
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
import { formatEvent, type StreamEvent } from "agentic-ui-kit/core";
|
|
85
|
+
import type { SseRequestBody } from "agentic-ui-kit";
|
|
86
|
+
|
|
87
|
+
export async function POST(request: Request) {
|
|
88
|
+
const body = (await request.json()) as SseRequestBody; // { message, history, model, tools, context, ... }
|
|
89
|
+
const runId = crypto.randomUUID();
|
|
90
|
+
let seq = 0;
|
|
91
|
+
|
|
92
|
+
const stream = new ReadableStream({
|
|
93
|
+
async start(controller) {
|
|
94
|
+
const send = (event: object) =>
|
|
95
|
+
controller.enqueue(new TextEncoder().encode(formatEvent({ ...event, runId, seq: seq++ } as StreamEvent)));
|
|
96
|
+
|
|
97
|
+
send({ type: "run.start", messageId: crypto.randomUUID(), parentId: body.message.id, createdAt: new Date().toISOString() });
|
|
98
|
+
send({ type: "part.start", part: { type: "text", id: "p1", text: "", status: "streaming" } });
|
|
99
|
+
for await (const chunk of callYourModel(body.history)) send({ type: "part.delta", partId: "p1", text: chunk });
|
|
100
|
+
send({ type: "part.end", partId: "p1" });
|
|
101
|
+
send({ type: "run.end", status: "done" });
|
|
102
|
+
controller.close();
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
return new Response(stream, { headers: { "content-type": "text/event-stream" } });
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
| Event | Meaning |
|
|
110
|
+
| ------------ | ----------------------------------------------------------------------------------------------- |
|
|
111
|
+
| `run.start` | A reply starts. Reusing an existing `messageId` continues that message (after tools ran). |
|
|
112
|
+
| `part.start` | A new part: `text`, `thinking`, `tool_call`, attachments, or your own custom type. |
|
|
113
|
+
| `part.delta` | Appends `text`, or `inputJson` for a tool call's arguments as the model writes them. |
|
|
114
|
+
| `part.update`| Sets fields: `status`, `title`, `subtitle`, `result`, `error`, … |
|
|
115
|
+
| `part.end` | Closes a part. A tool call's input is parsed here; invalid JSON fails the call. |
|
|
116
|
+
| `run.usage` | Token counts so far. |
|
|
117
|
+
| `run.end` | `done`, `stopped` or `error`. |
|
|
118
|
+
| `title` | A title for the conversation. |
|
|
119
|
+
|
|
120
|
+
Every event carries `runId` and an increasing `seq`, so a client can resume a dropped stream. Not using SSE?
|
|
121
|
+
Implement `Transport` yourself: one `send(request)` that returns an async iterable of events.
|
|
122
|
+
|
|
123
|
+
## Agent tools
|
|
124
|
+
|
|
125
|
+

|
|
126
|
+
|
|
127
|
+
Pages register the tools they own while they are mounted, so the model's tools follow what's on screen. One
|
|
128
|
+
definition covers both kinds:
|
|
129
|
+
|
|
130
|
+
- **Client tools** have `execute`. They run in the browser and can change the page directly; the result is
|
|
131
|
+
sent back and the model continues.
|
|
132
|
+
- **Server tools** run on your backend. The page still sees every call, through `onCall` (each change, e.g.
|
|
133
|
+
arguments streaming in) and `onResult` (once, done or failed), and can draw previews or refresh data.
|
|
134
|
+
|
|
135
|
+
```tsx
|
|
136
|
+
import { AgentProvider, useAgentContext, useChatTool } from "agentic-ui-kit";
|
|
137
|
+
|
|
138
|
+
function ApplicationForm() {
|
|
139
|
+
const [values, setValues] = useState(empty);
|
|
140
|
+
useAgentContext("application", values); // sent with each request
|
|
141
|
+
|
|
142
|
+
// Client tool: the model fills in the form on screen.
|
|
143
|
+
useChatTool({
|
|
144
|
+
name: "fill_fields",
|
|
145
|
+
description: "Fill in fields of the application form.",
|
|
146
|
+
inputSchema: { type: "object", properties: { fields: { type: "object" } }, required: ["fields"] },
|
|
147
|
+
execute: ({ fields }) => {
|
|
148
|
+
setValues((v) => ({ ...v, ...fields }));
|
|
149
|
+
return { filled: Object.keys(fields) };
|
|
150
|
+
},
|
|
151
|
+
view: { label: (call) => (call.status === "done" ? "Filled in the form" : "Filling in the form") },
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
// Server tool that needs the user's OK: the backend sets `needsApproval` on the call.
|
|
155
|
+
useChatTool({
|
|
156
|
+
name: "submit_application",
|
|
157
|
+
view: { ask: () => "Submit your application?" },
|
|
158
|
+
onResult: (call) => call.status === "done" && setSubmitted(true),
|
|
159
|
+
});
|
|
160
|
+
// ...
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Wrap the page and the chat so they share tools and context.
|
|
164
|
+
<AgentProvider>
|
|
165
|
+
<ApplicationForm />
|
|
166
|
+
<Assistant /> {/* uses useChat() and ChatView as in the quick start */}
|
|
167
|
+
</AgentProvider>;
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
While a tool call's arguments stream in, `call.partialInput` holds what has been written so far, parsed from
|
|
171
|
+
incomplete JSON. Use it to show a preview as the model writes: draw calendar events field by field, or type an
|
|
172
|
+
edit into an open file. If the stream breaks or the arguments aren't valid JSON, the call ends with
|
|
173
|
+
`status: "error"` and the preview should go away.
|
|
174
|
+
|
|
175
|
+
A tool's `view` sets how it looks in the chat: `label`, `subtitle`, `summary`, a `Detail` component for the
|
|
176
|
+
expanded row and the approval card, and `ask` for the approval question. `Block` renders a call on its own
|
|
177
|
+
instead of inside the activity group.
|
|
178
|
+
|
|
179
|
+
## Theming
|
|
180
|
+
|
|
181
|
+
Every colour, font, radius and width is a `--chat-*` CSS variable. Set them on `:root` to theme the whole app,
|
|
182
|
+
or on any element to theme part of it:
|
|
183
|
+
|
|
184
|
+
```css
|
|
185
|
+
:root {
|
|
186
|
+
--chat-bg: #fbfaf7;
|
|
187
|
+
--chat-fg: #1f1d1a;
|
|
188
|
+
--chat-accent: #c4552d;
|
|
189
|
+
--chat-font-sans: "IBM Plex Sans", sans-serif;
|
|
190
|
+
--chat-radius-md: 10px;
|
|
191
|
+
color-scheme: light;
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
To theme only part of a page, wrap it in `<ChatTheme theme="mine">` and match `[data-chat-theme="mine"]` in
|
|
196
|
+
your CSS. Menus and dialogs opened inside then render into that element, so they get the same theme.
|
|
197
|
+
|
|
198
|
+
`ChatTheme` also takes two appearance props. `codeThemes` picks the Shiki themes for code blocks and Markdown
|
|
199
|
+
fences (any bundled theme id; an unknown id falls back to the default with one console warning):
|
|
200
|
+
`<ChatTheme codeThemes={{ light: "catppuccin-latte", dark: "dracula" }}>`. Blocks keep `--chat-code-bg` unless you
|
|
201
|
+
add `background: "theme"`, which uses the Shiki theme's own background and text color. `motion` is `"system"`
|
|
202
|
+
(default: follow the OS reduced-motion setting), `"reduce"` (always use the reduced rules) or `"full"` (keep
|
|
203
|
+
animations even when the OS asks for less). It sets `data-chat-motion` on the element; an app that does not use
|
|
204
|
+
`ChatTheme` can put `data-chat-motion="reduce"` on `<html>` instead.
|
|
205
|
+
|
|
206
|
+
The full list of variables is at the top of
|
|
207
|
+
[`packages/react/src/styles.css`](packages/react/src/styles.css).
|
|
208
|
+
|
|
209
|
+
## What's in the kit
|
|
210
|
+
|
|
211
|
+
The React package has four layers, each built only from the ones before it:
|
|
212
|
+
|
|
213
|
+
| Layer | Examples |
|
|
214
|
+
| ---------- | --------------------------------------------------------------------------------------------- |
|
|
215
|
+
| Primitives | `Button`, `IconButton`, `Menu`, `ContextMenu`, `Modal`, `Drawer`, `Panel`, `Tooltip`, `CodeBlock`, `ChatTheme` |
|
|
216
|
+
| Hooks | `useChat`, `sseTransport`, `AgentProvider`, `useAgentTool`, `useAgentContext`, `useSmoothText` |
|
|
217
|
+
| Components | `Composer`, `ModelPicker`, `MessageList`, `ActivityGroup`, `ApprovalCard`, `Markdown`, `ChatHeader`, `ChatList`, `ContextPanel` |
|
|
218
|
+
| Views | `ChatView`, `AppShell`, `Sidebar` |
|
|
219
|
+
|
|
220
|
+
Use `ChatView` for the whole thing, or build your own layout from the components.
|
|
221
|
+
|
|
222
|
+
Bundle size: Markdown, KaTeX and Shiki are most of it, about 345 KB gzipped for a chat page. Shiki's language
|
|
223
|
+
grammars load on demand.
|
|
224
|
+
|
|
225
|
+
## Development
|
|
226
|
+
|
|
227
|
+
```sh
|
|
228
|
+
pnpm install
|
|
229
|
+
pnpm storybook # playground on http://localhost:6006: components, host themes, agent tool examples
|
|
230
|
+
pnpm -r typecheck
|
|
231
|
+
pnpm test # vitest in packages/core and packages/react
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
| Path | Contents |
|
|
235
|
+
| ----------------- | -------------------------------------------------------------- |
|
|
236
|
+
| `packages/core` | Types, events, reducer, SSE. Bundled into `agentic-ui-kit/core`. |
|
|
237
|
+
| `packages/react` | The published `agentic-ui-kit` package |
|
|
238
|
+
| `apps/playground` | Storybook |
|
|
239
|
+
|
|
240
|
+
## License
|
|
241
|
+
|
|
242
|
+
MIT
|
package/dist/core.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { a as activityTokens, o as applyEvent, s as awaitingToolCalls, c as estimateTokens, t as formatEvent, r as isActivityPart, l as outputTokens, p as parsePartialJson, n as readEventStream, u as reduceEvents, d as resolveEffort, f as settleToolCall, i as toBlocks } from "./sse-BA_ebMcH.js";
|