@artooi/ag-ui-web-component 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/CHANGELOG.md +13 -0
- package/LICENSE +21 -0
- package/README.md +471 -0
- package/dist/ag-ui-web-component.bundle.js +319 -0
- package/dist/ag-ui-web-component.bundle.js.map +7 -0
- package/dist/ag_ui_chat.d.ts +85 -0
- package/dist/ag_ui_chat.d.ts.map +1 -0
- package/dist/agui_client.d.ts +99 -0
- package/dist/agui_client.d.ts.map +1 -0
- package/dist/animations.d.ts +33 -0
- package/dist/animations.d.ts.map +1 -0
- package/dist/client_tool_registry.d.ts +32 -0
- package/dist/client_tool_registry.d.ts.map +1 -0
- package/dist/confirmation_modal.d.ts +14 -0
- package/dist/confirmation_modal.d.ts.map +1 -0
- package/dist/constants.d.ts +40 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/conversation_store.d.ts +54 -0
- package/dist/conversation_store.d.ts.map +1 -0
- package/dist/create_http_agent.d.ts +22 -0
- package/dist/create_http_agent.d.ts.map +1 -0
- package/dist/define_ag_ui_chat.d.ts +9 -0
- package/dist/define_ag_ui_chat.d.ts.map +1 -0
- package/dist/dom_driver.d.ts +24 -0
- package/dist/dom_driver.d.ts.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1159 -0
- package/dist/index.js.map +7 -0
- package/dist/is_destructive.d.ts +8 -0
- package/dist/is_destructive.d.ts.map +1 -0
- package/dist/is_navigates.d.ts +9 -0
- package/dist/is_navigates.d.ts.map +1 -0
- package/dist/page_map.d.ts +16 -0
- package/dist/page_map.d.ts.map +1 -0
- package/dist/route_map.d.ts +27 -0
- package/dist/route_map.d.ts.map +1 -0
- package/dist/state_hook.d.ts +23 -0
- package/dist/state_hook.d.ts.map +1 -0
- package/dist/styles.d.ts +2 -0
- package/dist/styles.d.ts.map +1 -0
- package/dist/tool_call_card.d.ts +29 -0
- package/dist/tool_call_card.d.ts.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/package.json +79 -0
- package/src/ag_ui_chat.ts +411 -0
- package/src/agui_client.ts +212 -0
- package/src/animations.ts +86 -0
- package/src/client_tool_registry.ts +56 -0
- package/src/confirmation_modal.ts +69 -0
- package/src/constants.ts +48 -0
- package/src/conversation_store.ts +103 -0
- package/src/create_http_agent.ts +40 -0
- package/src/define_ag_ui_chat.ts +15 -0
- package/src/dom_driver.ts +60 -0
- package/src/index.ts +60 -0
- package/src/is_destructive.ts +11 -0
- package/src/is_navigates.ts +12 -0
- package/src/page_map.ts +25 -0
- package/src/route_map.ts +83 -0
- package/src/state_hook.ts +44 -0
- package/src/styles.ts +296 -0
- package/src/tool_call_card.ts +95 -0
- package/src/version.ts +1 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- Initial scaffold.
|
|
12
|
+
|
|
13
|
+
[Unreleased]: https://github.com/Artui/ag-ui-web-component/compare/v0.1.0...HEAD
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Artur Veres
|
|
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,471 @@
|
|
|
1
|
+
# @artooi/ag-ui-web-component
|
|
2
|
+
|
|
3
|
+
[](https://github.com/Artui/ag-ui-web-component/actions/workflows/tests.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/@artooi/ag-ui-web-component)
|
|
5
|
+
[](https://github.com/Artui/ag-ui-web-component/blob/main/LICENSE)
|
|
6
|
+
|
|
7
|
+
A **framework-free** `<ag-ui-chat>` Web Component over the [AG-UI](https://docs.ag-ui.com)
|
|
8
|
+
protocol. Drop it into any page — SPA or MPA, any framework or none — point it at an AG-UI
|
|
9
|
+
endpoint, and you get a streaming chat sidebar that can call tools you register in the browser.
|
|
10
|
+
|
|
11
|
+
It wraps [`@ag-ui/client`](https://www.npmjs.com/package/@ag-ui/client)'s `HttpAgent` and ships:
|
|
12
|
+
|
|
13
|
+
- A Custom Element with a self-contained Shadow DOM chat UI (header, scrolling transcript,
|
|
14
|
+
input row), themeable via CSS custom properties.
|
|
15
|
+
- A pluggable **client-side tool registry** — `registerTool({ name, description, parameters,
|
|
16
|
+
handler })`; every registered tool is added to each run's `RunAgentInput.tools`.
|
|
17
|
+
- Generic **DOM-driver primitives** (`fillField`, `clickElement`, `setControlValue`) and
|
|
18
|
+
**animation primitives** (`typeInto`, `highlightThenClick`, …) so the agent can drive the page
|
|
19
|
+
at human-readable speed.
|
|
20
|
+
- A **confirmation modal** that intercepts destructive tool calls (those whose JSON Schema
|
|
21
|
+
carries `x-destructive: true`) before the handler runs.
|
|
22
|
+
- An **MPA durability story**: a durable conversation store, a stable thread id, and a resumable
|
|
23
|
+
run loop that survives full page reloads (`x-navigates` + `navigationResult`).
|
|
24
|
+
- **Host seams** for SPAs: a route map, an auto-injected page map, state hooks, and an optional
|
|
25
|
+
`navigate()` callback.
|
|
26
|
+
|
|
27
|
+
No framework, no Django, no admin specifics live here. Downstream consumers (e.g.
|
|
28
|
+
`django-admin-agent`) register their own tool handlers on top via the pluggable registry.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Table of contents
|
|
33
|
+
|
|
34
|
+
- [Install](#install)
|
|
35
|
+
- [Quickstart](#quickstart)
|
|
36
|
+
- [Core concepts](#core-concepts)
|
|
37
|
+
- [The run loop and the AG-UI client](#the-run-loop-and-the-ag-ui-client)
|
|
38
|
+
- [Registering tools](#registering-tools)
|
|
39
|
+
- [The confirmation modal (`x-destructive`)](#the-confirmation-modal-x-destructive)
|
|
40
|
+
- [DOM-driver and animation primitives](#dom-driver-and-animation-primitives)
|
|
41
|
+
- [MPA durability: surviving full page reloads](#mpa-durability-surviving-full-page-reloads)
|
|
42
|
+
- [Host seams: the SPA story](#host-seams-the-spa-story)
|
|
43
|
+
- [Public API surface](#public-api-surface)
|
|
44
|
+
- [Theming](#theming)
|
|
45
|
+
- [Building the bundle](#building-the-bundle)
|
|
46
|
+
- [Compatibility](#compatibility)
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Install
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
npm install @artooi/ag-ui-web-component
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
The package ships two builds (see [`package.json` exports](package.json)):
|
|
57
|
+
|
|
58
|
+
| Entry | What it is | When to use |
|
|
59
|
+
| --- | --- | --- |
|
|
60
|
+
| `@artooi/ag-ui-web-component` | ESM library build; `@ag-ui/*` stay **external** | You bundle the app yourself (Vite, webpack, esbuild) and want to dedupe `@ag-ui/*`. |
|
|
61
|
+
| `@artooi/ag-ui-web-component/bundle` | ESM bundle with `@ag-ui/*` **inlined**, minified | Drop in via a single `<script type="module">` with no build step. |
|
|
62
|
+
| `@artooi/ag-ui-web-component/style.css` | Extracted CSS sidecar | Rarely needed — styles are injected into the Shadow DOM at runtime. |
|
|
63
|
+
|
|
64
|
+
### The vendored-bundle story
|
|
65
|
+
|
|
66
|
+
The `/bundle` entry inlines every dependency into one self-contained ESM file
|
|
67
|
+
(`dist/ag-ui-web-component.bundle.js`). This is the artefact intended for **vendoring**: a host
|
|
68
|
+
that can't (or won't) run a JS build — for example a Django app — copies the built bundle into its
|
|
69
|
+
`static/` directory and serves it directly. `django-admin-agent` re-vendors a pinned built bundle
|
|
70
|
+
on every release. For SPA hosts that already have a bundler, import the bare package name instead
|
|
71
|
+
so `@ag-ui/client` / `@ag-ui/core` are deduped against the rest of your app.
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Quickstart
|
|
76
|
+
|
|
77
|
+
Drop the element into your page and register the tools the agent may call:
|
|
78
|
+
|
|
79
|
+
```html
|
|
80
|
+
<script type="module">
|
|
81
|
+
import {
|
|
82
|
+
defineAgUiChat,
|
|
83
|
+
fillField,
|
|
84
|
+
clickElement,
|
|
85
|
+
X_DESTRUCTIVE_KEY,
|
|
86
|
+
} from "@artooi/ag-ui-web-component";
|
|
87
|
+
|
|
88
|
+
// Register the <ag-ui-chat> Custom Element. Idempotent and SSR-safe — it is an
|
|
89
|
+
// explicit call, not an import side effect, so the package stays tree-shakeable.
|
|
90
|
+
defineAgUiChat();
|
|
91
|
+
|
|
92
|
+
const chat = document.querySelector("ag-ui-chat");
|
|
93
|
+
|
|
94
|
+
// Extra request headers (e.g. CSRF) sent to the AG-UI endpoint.
|
|
95
|
+
chat.headers = { "X-CSRFToken": getCsrfToken() };
|
|
96
|
+
|
|
97
|
+
// A non-destructive tool: fills a text field with a typing animation.
|
|
98
|
+
chat.registerTool({
|
|
99
|
+
name: "fill_field",
|
|
100
|
+
description: "Fill a text input by id with a value.",
|
|
101
|
+
parameters: {
|
|
102
|
+
type: "object",
|
|
103
|
+
properties: { field: { type: "string" }, value: { type: "string" } },
|
|
104
|
+
required: ["field", "value"],
|
|
105
|
+
},
|
|
106
|
+
handler: async ({ field, value }) => {
|
|
107
|
+
await fillField(document.getElementById(field), String(value));
|
|
108
|
+
return "ok";
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// A destructive tool: x-destructive at the JSON-Schema root gates it behind
|
|
113
|
+
// the confirmation modal before the handler runs.
|
|
114
|
+
chat.registerTool({
|
|
115
|
+
name: "save_article",
|
|
116
|
+
description: "Save the article. Destructive — asks for confirmation.",
|
|
117
|
+
parameters: { type: "object", properties: {}, [X_DESTRUCTIVE_KEY]: true },
|
|
118
|
+
handler: async () => {
|
|
119
|
+
await clickElement(document.getElementById("save"));
|
|
120
|
+
return "saved";
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
</script>
|
|
124
|
+
|
|
125
|
+
<ag-ui-chat endpoint="/agent/" title-text="Assistant"></ag-ui-chat>
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
That's the whole integration: an `endpoint` attribute pointing at your AG-UI server, optional
|
|
129
|
+
`headers`, and the tools you want the agent to be able to invoke in the browser.
|
|
130
|
+
|
|
131
|
+
### Attributes and properties
|
|
132
|
+
|
|
133
|
+
| Attribute | Property | Notes |
|
|
134
|
+
| --- | --- | --- |
|
|
135
|
+
| `endpoint` | `endpoint` (getter) | The AG-UI endpoint URL. Required to send. |
|
|
136
|
+
| `title-text` | — | Header label; defaults to `"Assistant"`. |
|
|
137
|
+
| — | `headers` | `Record<string, string>` of extra HTTP headers. |
|
|
138
|
+
| — | `autoConfirm` | When `true`, destructive tools run without the modal. |
|
|
139
|
+
|
|
140
|
+
A self-contained working example lives in [`demo/`](demo/) — run `make demo` to serve it against a
|
|
141
|
+
mock AG-UI server.
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Core concepts
|
|
146
|
+
|
|
147
|
+
### The run loop and the AG-UI client
|
|
148
|
+
|
|
149
|
+
`<ag-ui-chat>` is the view; [`AgUiClient`](src/agui_client.ts) is the orchestration layer over an
|
|
150
|
+
AG-UI `AbstractAgent`. On the first send the element builds a client (via the overridable
|
|
151
|
+
`agentFactory`, which defaults to [`createHttpAgent`](src/create_http_agent.ts)). Each turn:
|
|
152
|
+
|
|
153
|
+
1. The user message is appended and the agent runs once.
|
|
154
|
+
2. AG-UI subscriber events are translated into the element's handlers — streaming text deltas
|
|
155
|
+
render into a bubble; each `TOOL_CALL_END` becomes a tool-call card.
|
|
156
|
+
3. Any **frontend** tool calls collected during the run are executed locally, their results are
|
|
157
|
+
appended as `tool` messages, and the agent is re-run with the results.
|
|
158
|
+
4. This repeats until the agent stops calling frontend tools, bounded by `MAX_TOOL_ROUNDS`.
|
|
159
|
+
|
|
160
|
+
Tool calls the client doesn't own (server-side tools the server already executed) are left alone —
|
|
161
|
+
the loop doesn't re-run them. The current tool catalog and context are read **fresh on every run**
|
|
162
|
+
(`getTools()` / `getContext()`), so they always reflect the current page state.
|
|
163
|
+
|
|
164
|
+
### Registering tools
|
|
165
|
+
|
|
166
|
+
A tool is a `ClientTool`: `{ name, description, parameters, handler }`, where `parameters` is a
|
|
167
|
+
**JSON Schema** and `handler` receives the parsed args and returns a value that is JSON-serialised
|
|
168
|
+
into the tool-result message. Register them on the element:
|
|
169
|
+
|
|
170
|
+
```js
|
|
171
|
+
chat.registerTool({
|
|
172
|
+
name: "search_products",
|
|
173
|
+
description: "Search the catalog.",
|
|
174
|
+
parameters: {
|
|
175
|
+
type: "object",
|
|
176
|
+
properties: { query: { type: "string" } },
|
|
177
|
+
required: ["query"],
|
|
178
|
+
},
|
|
179
|
+
handler: async ({ query }) => await api.search(query),
|
|
180
|
+
});
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Names must be unique (registering a duplicate throws). Each `<ag-ui-chat>` element owns its own
|
|
184
|
+
registry, AG-UI client, and Shadow DOM, so **multiple instances on one page never interfere** —
|
|
185
|
+
there is no module-level shared state anywhere in the package.
|
|
186
|
+
|
|
187
|
+
### The confirmation modal (`x-destructive`)
|
|
188
|
+
|
|
189
|
+
AG-UI has no built-in risk flag, so destructiveness is carried as a JSON-Schema extension at the
|
|
190
|
+
**schema root**: `parameters["x-destructive"] = true` (use the exported `X_DESTRUCTIVE_KEY`
|
|
191
|
+
constant). There is no parallel metadata channel — the flag lives on the schema, the registry
|
|
192
|
+
forwards it verbatim to `RunAgentInput.tools`, and [`isDestructive`](src/is_destructive.ts) reads
|
|
193
|
+
it back.
|
|
194
|
+
|
|
195
|
+
When the agent calls a destructive tool, the element shows the
|
|
196
|
+
[confirmation modal](src/confirmation_modal.ts) (rendered inside its own Shadow DOM) **before**
|
|
197
|
+
dispatching to the handler:
|
|
198
|
+
|
|
199
|
+
- **Confirm** → the handler runs and the result is posted back.
|
|
200
|
+
- **Cancel / dismiss** → a `"User declined the action."` result is posted; the agent acknowledges
|
|
201
|
+
on its next turn.
|
|
202
|
+
|
|
203
|
+
Set `chat.autoConfirm = true` to bypass the modal (an "autopilot" toggle).
|
|
204
|
+
|
|
205
|
+
### DOM-driver and animation primitives
|
|
206
|
+
|
|
207
|
+
So the agent can visibly drive the host page, the package ships generic, framework-free
|
|
208
|
+
primitives. The **animation** primitives ([`animations.ts`](src/animations.ts)) operate at
|
|
209
|
+
human-readable speed (configurable; pass small/zero durations in tests):
|
|
210
|
+
|
|
211
|
+
- `typeInto(el, value, { charDelayMs })` — clears and types a value character by character,
|
|
212
|
+
firing `input`/`change` events as a real user would.
|
|
213
|
+
- `highlightThenClick(el, { highlightMs })` — outlines an element, pauses, then clicks.
|
|
214
|
+
- `scrollIntoCenterView(el)` / `focusWithFlash(el, { flashMs })`.
|
|
215
|
+
|
|
216
|
+
The **DOM-driver** primitives ([`dom_driver.ts`](src/dom_driver.ts)) compose those into the
|
|
217
|
+
operations a tool handler typically wants:
|
|
218
|
+
|
|
219
|
+
- `fillField(el, value, options)` — scroll to, focus-flash, and type into a text field.
|
|
220
|
+
- `clickElement(el, options)` — scroll to, highlight, and click.
|
|
221
|
+
- `setControlValue(el, value)` — set a `<select>` or checkbox without animation, dispatching
|
|
222
|
+
`input`/`change`.
|
|
223
|
+
|
|
224
|
+
Each takes an element the caller has already located; host packages wrap them with
|
|
225
|
+
environment-aware lookups (e.g. "find `#id_<name>`, then `fillField`").
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## MPA durability: surviving full page reloads
|
|
230
|
+
|
|
231
|
+
In a multi-page app, a tool that navigates reloads the whole page and destroys the in-memory run
|
|
232
|
+
loop. The package keeps the conversation continuous across that boundary with three generic
|
|
233
|
+
mechanisms.
|
|
234
|
+
|
|
235
|
+
**1. Thread identity.** AG-UI's `thread_id` is the conversation key. It is generated once and
|
|
236
|
+
persisted (so the element reattaches after a reload) by the
|
|
237
|
+
[`ClientConversationStore`](src/conversation_store.ts).
|
|
238
|
+
|
|
239
|
+
**2. Durable conversation.** A pluggable `ClientConversationStore` holds the message list. The
|
|
240
|
+
default [`SessionStorageStore`](src/conversation_store.ts) keeps everything per-tab in
|
|
241
|
+
`sessionStorage`, so the chat survives full page reloads and clears on tab close. `loadMessages`
|
|
242
|
+
is async-friendly, so a host can inject a server-backed store (e.g. one that rehydrates from a
|
|
243
|
+
history endpoint) for cross-tab/device durability:
|
|
244
|
+
|
|
245
|
+
```js
|
|
246
|
+
chat.conversationStore = new MyServerBackedStore();
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
On mount the element rehydrates the transcript from the store, so the chat looks continuous.
|
|
250
|
+
|
|
251
|
+
**3. Resumable loop (`x-navigates` + `navigationResult`).** A tool whose schema carries
|
|
252
|
+
`x-navigates: true` (use `X_NAVIGATES_KEY`; read back by [`isNavigates`](src/is_navigates.ts))
|
|
253
|
+
triggers a full reload. Before the handler navigates, the element writes a checkpoint
|
|
254
|
+
(`{ toolCallId }`) to the store. On the next page mount it:
|
|
255
|
+
|
|
256
|
+
1. restores the transcript,
|
|
257
|
+
2. completes the dangling navigating tool call by supplying a result built from the landed page
|
|
258
|
+
via the overridable **`navigationResult(checkpoint)`** callback (defaults to
|
|
259
|
+
`{ navigated: true, url }`; a host can return a page snapshot or post-reload validation errors
|
|
260
|
+
instead),
|
|
261
|
+
3. and resumes the run loop from there.
|
|
262
|
+
|
|
263
|
+
The MPA round-trip becomes a clean observation point instead of a dropped conversation.
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## Host seams: the SPA story
|
|
268
|
+
|
|
269
|
+
`<ag-ui-chat>` is a generic embedding kit; these typed seams let a host feed the agent richer
|
|
270
|
+
context up front so it explores less. All are framework-free and admin-agnostic.
|
|
271
|
+
|
|
272
|
+
**`routeMap: RouteMap`** — a manifest of navigable routes (`{ id, path, title?, group?,
|
|
273
|
+
description? }`). When set, the element exposes two built-in tools so the agent navigates by intent
|
|
274
|
+
rather than by exploring:
|
|
275
|
+
|
|
276
|
+
- `list_routes` — read-only; lists the routes.
|
|
277
|
+
- `navigate_to_route(route_id, params?)` — resolves the id to a path and navigates.
|
|
278
|
+
|
|
279
|
+
```js
|
|
280
|
+
chat.routeMap = [
|
|
281
|
+
{ id: "users", path: "/users", title: "Users", description: "Manage user accounts" },
|
|
282
|
+
{ id: "billing", path: "/billing", title: "Billing" },
|
|
283
|
+
];
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
**`getPageMap(): PageMap`** — a per-run provider returning the current page's compact actionable
|
|
287
|
+
surface (field names/types/labels, button labels+handles — *not* values). It is auto-injected into
|
|
288
|
+
each run's `context` as a `page_map` entry (toggle with `autoInjectPageMap`). Recomputed every run
|
|
289
|
+
so it reflects the page the agent is currently looking at:
|
|
290
|
+
|
|
291
|
+
```js
|
|
292
|
+
chat.getPageMap = () => ({ fields: introspectForm(), buttons: visibleButtons() });
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
**`registerStateHook({ name, read, write?, schema? })`** — ergonomic sugar over `registerTool` for
|
|
296
|
+
SPA app state (Redux/Zustand/signals). It auto-generates a `read_<name>` (read-only) tool and, when
|
|
297
|
+
`write` is supplied, a `set_<name>` tool stamped `x-destructive`:
|
|
298
|
+
|
|
299
|
+
```js
|
|
300
|
+
chat.registerStateHook({
|
|
301
|
+
name: "cart",
|
|
302
|
+
read: () => store.getState().cart,
|
|
303
|
+
write: ({ items }) => store.dispatch(setCart(items)),
|
|
304
|
+
schema: { type: "object", properties: { items: { type: "array" } } },
|
|
305
|
+
});
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
**`navigate(path): void`** *(optional)* — a host routing callback. **This single seam is what
|
|
309
|
+
distinguishes an SPA from an MPA.** When set, `navigate_to_route` routes client-side (no reload) and
|
|
310
|
+
the in-memory run loop simply continues — the whole resumable-loop / checkpoint machinery is
|
|
311
|
+
bypassed. When unset, navigation falls back to `window.location` and the MPA reload model above
|
|
312
|
+
applies.
|
|
313
|
+
|
|
314
|
+
```js
|
|
315
|
+
chat.navigate = (path) => router.push(path); // SPA: in-page, no reload
|
|
316
|
+
// leave unset for an MPA: window.location + checkpoint/resume
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
Route map + `navigate()` and the reload model are the same feature seen from two ends.
|
|
320
|
+
|
|
321
|
+
---
|
|
322
|
+
|
|
323
|
+
## Public API surface
|
|
324
|
+
|
|
325
|
+
Everything below is re-exported from the package root ([`src/index.ts`](src/index.ts)) — the only
|
|
326
|
+
re-export point. Internal modules import from leaf paths.
|
|
327
|
+
|
|
328
|
+
### Element & registration
|
|
329
|
+
|
|
330
|
+
| Export | Kind | Summary |
|
|
331
|
+
| --- | --- | --- |
|
|
332
|
+
| `AgUiChat` | class | The `<ag-ui-chat>` Custom Element. |
|
|
333
|
+
| `defineAgUiChat()` | function | Idempotently register the element. |
|
|
334
|
+
| `MessageRole` | type | Role of a rendered chat message. |
|
|
335
|
+
| `SubmitDetail` | type | `detail` shape of the submit event. |
|
|
336
|
+
|
|
337
|
+
### AG-UI client & agent
|
|
338
|
+
|
|
339
|
+
| Export | Kind | Summary |
|
|
340
|
+
| --- | --- | --- |
|
|
341
|
+
| `AgUiClient` | class | Orchestration layer over an AG-UI `AbstractAgent`. |
|
|
342
|
+
| `AgUiClientConfig` / `AgUiClientHandlers` / `AgUiRunInputs` | type | Client config, lifecycle handlers, per-run input providers. |
|
|
343
|
+
| `AgUiToolCall` / `ToolExecution` / `ExecuteTool` | type | Tool-call shape, execution result, executor signature. |
|
|
344
|
+
| `createHttpAgent(options)` | function | Default agent factory (wraps `HttpAgent`). |
|
|
345
|
+
| `AgentFactory` / `HttpAgentOptions` | type | Factory signature and its options. |
|
|
346
|
+
|
|
347
|
+
### Tools & flags
|
|
348
|
+
|
|
349
|
+
| Export | Kind | Summary |
|
|
350
|
+
| --- | --- | --- |
|
|
351
|
+
| `ClientToolRegistry` | class | Per-element tool registry. |
|
|
352
|
+
| `ClientTool` | type | A frontend tool declaration. |
|
|
353
|
+
| `isDestructive(parameters)` | function | Read the `x-destructive` flag. |
|
|
354
|
+
| `isNavigates(parameters)` | function | Read the `x-navigates` flag. |
|
|
355
|
+
| `X_DESTRUCTIVE_KEY` / `X_NAVIGATES_KEY` | const | The JSON-Schema extension keys. |
|
|
356
|
+
|
|
357
|
+
### Host seams
|
|
358
|
+
|
|
359
|
+
| Export | Kind | Summary |
|
|
360
|
+
| --- | --- | --- |
|
|
361
|
+
| `createRouteTools(...)` | function | Build the built-in `route.*` tools. |
|
|
362
|
+
| `Route` / `RouteMap` | type | Navigable-route shapes. |
|
|
363
|
+
| `createPageMapContext(...)` | function | Build the per-run `page_map` context entry. |
|
|
364
|
+
| `PageMap` | type | The compact page-surface shape. |
|
|
365
|
+
| `createStateHookTools(hook)` | function | Build `read_<name>` / `set_<name>` tools. |
|
|
366
|
+
| `StateHook` | type | A state-binding declaration. |
|
|
367
|
+
|
|
368
|
+
### Durability
|
|
369
|
+
|
|
370
|
+
| Export | Kind | Summary |
|
|
371
|
+
| --- | --- | --- |
|
|
372
|
+
| `SessionStorageStore` | class | Default per-tab conversation store. |
|
|
373
|
+
| `ClientConversationStore` | type | The persistence seam. |
|
|
374
|
+
| `NavigationCheckpoint` | type | The pre-reload checkpoint marker. |
|
|
375
|
+
|
|
376
|
+
### UI & DOM primitives
|
|
377
|
+
|
|
378
|
+
| Export | Kind | Summary |
|
|
379
|
+
| --- | --- | --- |
|
|
380
|
+
| `ToolCallCard` | class | A live tool-call card for the transcript. |
|
|
381
|
+
| `ToolCallStatus` / `SettledStatus` | type | Card lifecycle states. |
|
|
382
|
+
| `requestConfirmation(host, request)` | function | Render the confirmation modal. |
|
|
383
|
+
| `ConfirmationRequest` | type | What the modal displays. |
|
|
384
|
+
| `typeInto` / `highlightThenClick` / `scrollIntoCenterView` / `focusWithFlash` | function | Animation primitives. |
|
|
385
|
+
| `fillField` / `clickElement` / `setControlValue` | function | DOM-driver primitives. |
|
|
386
|
+
| `TypeOptions` / `HighlightClickOptions` / `FlashOptions` / `FillFieldOptions` / `TextLikeElement` | type | Primitive option shapes. |
|
|
387
|
+
|
|
388
|
+
### Constants
|
|
389
|
+
|
|
390
|
+
| Export | Summary |
|
|
391
|
+
| --- | --- |
|
|
392
|
+
| `ELEMENT_TAG` | The registered tag name (`ag-ui-chat`). |
|
|
393
|
+
| `SUBMIT_EVENT` | The submit CustomEvent name. |
|
|
394
|
+
| `MESSAGE_ROLE` | Message role constants. |
|
|
395
|
+
| `TOOL_CALL_STATUS` | Tool-call card status constants. |
|
|
396
|
+
| `MAX_TOOL_ROUNDS` | Upper bound on tool-call → re-run rounds per send. |
|
|
397
|
+
| `VERSION` | The package version string. |
|
|
398
|
+
|
|
399
|
+
---
|
|
400
|
+
|
|
401
|
+
## Theming
|
|
402
|
+
|
|
403
|
+
The chat shell is styled inside its Shadow DOM and exposes CSS custom properties on `:host`, so you
|
|
404
|
+
theme it from outside without piercing the shadow boundary. A few of the knobs:
|
|
405
|
+
|
|
406
|
+
```css
|
|
407
|
+
ag-ui-chat {
|
|
408
|
+
--ag-ui-accent: #4f46e5;
|
|
409
|
+
--ag-ui-bg: #ffffff;
|
|
410
|
+
--ag-ui-fg: #1a1a2e;
|
|
411
|
+
--ag-ui-radius: 12px;
|
|
412
|
+
|
|
413
|
+
/* Layout — float (default) or embed in your own flow with --ag-ui-position: static */
|
|
414
|
+
--ag-ui-position: fixed;
|
|
415
|
+
--ag-ui-width: 380px;
|
|
416
|
+
--ag-ui-height: 560px;
|
|
417
|
+
--ag-ui-inset: auto 24px 24px auto;
|
|
418
|
+
--ag-ui-shadow: 0 12px 32px rgba(20, 20, 50, 0.18);
|
|
419
|
+
}
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
See [`src/styles.ts`](src/styles.ts) for the full list, and [`demo/themes/`](demo/themes/) for
|
|
423
|
+
worked examples (default, dark, embedded, and a "claude" theme).
|
|
424
|
+
|
|
425
|
+
---
|
|
426
|
+
|
|
427
|
+
## Building the bundle
|
|
428
|
+
|
|
429
|
+
The build is driven by [esbuild](esbuild.config.mjs) plus `tsc` for type declarations:
|
|
430
|
+
|
|
431
|
+
```bash
|
|
432
|
+
make build # node esbuild.config.mjs && tsc -p tsconfig.build.json
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
This produces, into `dist/`:
|
|
436
|
+
|
|
437
|
+
- `index.js` — the ESM library build; `@ag-ui/*` are left **external** so npm consumers dedupe
|
|
438
|
+
them.
|
|
439
|
+
- `ag-ui-web-component.bundle.js` — the **vendored** ESM bundle, every dependency inlined and
|
|
440
|
+
minified, suitable for direct `<script type="module">` embedding.
|
|
441
|
+
- `ag-ui-web-component.bundle.css` — the extracted CSS sidecar.
|
|
442
|
+
- `index.d.ts` (+ source maps) — type declarations; emitted `.js` import specifiers are preserved
|
|
443
|
+
so consumers resolve types without extra flags.
|
|
444
|
+
|
|
445
|
+
Other workflow targets (all identical in name to the sibling Python packages):
|
|
446
|
+
|
|
447
|
+
| Target | What it does |
|
|
448
|
+
| --- | --- |
|
|
449
|
+
| `make test` | Vitest with a 100% line + branch + function + statement coverage gate. |
|
|
450
|
+
| `make lint` | `biome check .` + `tsc --noEmit`. |
|
|
451
|
+
| `make format` | `biome format --write .`. |
|
|
452
|
+
| `make demo` | Build, then serve `demo/` against a mock AG-UI server. |
|
|
453
|
+
|
|
454
|
+
---
|
|
455
|
+
|
|
456
|
+
## Compatibility
|
|
457
|
+
|
|
458
|
+
| Component | Floor | Tested |
|
|
459
|
+
| --- | --- | --- |
|
|
460
|
+
| Node (tooling/tests only) | 20 | 20, 22, 24 |
|
|
461
|
+
| Browsers (runtime target) | ES2022 / evergreen | Chrome / Firefox / Safari 17+ |
|
|
462
|
+
| `@ag-ui/client` | latest 0.x | — |
|
|
463
|
+
|
|
464
|
+
The shipped artefact targets evergreen browsers (Shadow DOM, Custom Elements v1, ES2022). Node is
|
|
465
|
+
only the build/test runtime, not a runtime target.
|
|
466
|
+
|
|
467
|
+
---
|
|
468
|
+
|
|
469
|
+
## License
|
|
470
|
+
|
|
471
|
+
[MIT](LICENSE) © Artur Veres
|