@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.
Files changed (65) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/LICENSE +21 -0
  3. package/README.md +471 -0
  4. package/dist/ag-ui-web-component.bundle.js +319 -0
  5. package/dist/ag-ui-web-component.bundle.js.map +7 -0
  6. package/dist/ag_ui_chat.d.ts +85 -0
  7. package/dist/ag_ui_chat.d.ts.map +1 -0
  8. package/dist/agui_client.d.ts +99 -0
  9. package/dist/agui_client.d.ts.map +1 -0
  10. package/dist/animations.d.ts +33 -0
  11. package/dist/animations.d.ts.map +1 -0
  12. package/dist/client_tool_registry.d.ts +32 -0
  13. package/dist/client_tool_registry.d.ts.map +1 -0
  14. package/dist/confirmation_modal.d.ts +14 -0
  15. package/dist/confirmation_modal.d.ts.map +1 -0
  16. package/dist/constants.d.ts +40 -0
  17. package/dist/constants.d.ts.map +1 -0
  18. package/dist/conversation_store.d.ts +54 -0
  19. package/dist/conversation_store.d.ts.map +1 -0
  20. package/dist/create_http_agent.d.ts +22 -0
  21. package/dist/create_http_agent.d.ts.map +1 -0
  22. package/dist/define_ag_ui_chat.d.ts +9 -0
  23. package/dist/define_ag_ui_chat.d.ts.map +1 -0
  24. package/dist/dom_driver.d.ts +24 -0
  25. package/dist/dom_driver.d.ts.map +1 -0
  26. package/dist/index.d.ts +18 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +1159 -0
  29. package/dist/index.js.map +7 -0
  30. package/dist/is_destructive.d.ts +8 -0
  31. package/dist/is_destructive.d.ts.map +1 -0
  32. package/dist/is_navigates.d.ts +9 -0
  33. package/dist/is_navigates.d.ts.map +1 -0
  34. package/dist/page_map.d.ts +16 -0
  35. package/dist/page_map.d.ts.map +1 -0
  36. package/dist/route_map.d.ts +27 -0
  37. package/dist/route_map.d.ts.map +1 -0
  38. package/dist/state_hook.d.ts +23 -0
  39. package/dist/state_hook.d.ts.map +1 -0
  40. package/dist/styles.d.ts +2 -0
  41. package/dist/styles.d.ts.map +1 -0
  42. package/dist/tool_call_card.d.ts +29 -0
  43. package/dist/tool_call_card.d.ts.map +1 -0
  44. package/dist/version.d.ts +2 -0
  45. package/dist/version.d.ts.map +1 -0
  46. package/package.json +79 -0
  47. package/src/ag_ui_chat.ts +411 -0
  48. package/src/agui_client.ts +212 -0
  49. package/src/animations.ts +86 -0
  50. package/src/client_tool_registry.ts +56 -0
  51. package/src/confirmation_modal.ts +69 -0
  52. package/src/constants.ts +48 -0
  53. package/src/conversation_store.ts +103 -0
  54. package/src/create_http_agent.ts +40 -0
  55. package/src/define_ag_ui_chat.ts +15 -0
  56. package/src/dom_driver.ts +60 -0
  57. package/src/index.ts +60 -0
  58. package/src/is_destructive.ts +11 -0
  59. package/src/is_navigates.ts +12 -0
  60. package/src/page_map.ts +25 -0
  61. package/src/route_map.ts +83 -0
  62. package/src/state_hook.ts +44 -0
  63. package/src/styles.ts +296 -0
  64. package/src/tool_call_card.ts +95 -0
  65. 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
+ [![CI](https://github.com/Artui/ag-ui-web-component/workflows/tests/badge.svg)](https://github.com/Artui/ag-ui-web-component/actions/workflows/tests.yml)
4
+ [![npm](https://img.shields.io/npm/v/@artooi/ag-ui-web-component.svg)](https://www.npmjs.com/package/@artooi/ag-ui-web-component)
5
+ [![License](https://img.shields.io/npm/l/@artooi/ag-ui-web-component.svg)](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