@artooi/ag-ui-web-component 0.1.0 → 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/CHANGELOG.md +102 -2
- package/README.md +235 -47
- package/dist/ag-ui-web-component.bundle.js +451 -46
- package/dist/ag-ui-web-component.bundle.js.map +4 -4
- package/dist/constants.d.ts +34 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/{ag_ui_chat.d.ts → core/ag_ui_chat.d.ts} +63 -6
- package/dist/core/ag_ui_chat.d.ts.map +1 -0
- package/dist/core/agui_client.d.ts.map +1 -0
- package/dist/core/conversation_store.d.ts.map +1 -0
- package/dist/core/create_http_agent.d.ts.map +1 -0
- package/dist/core/define_ag_ui_chat.d.ts.map +1 -0
- package/dist/dom/animations.d.ts +71 -0
- package/dist/dom/animations.d.ts.map +1 -0
- package/dist/{dom_driver.d.ts → dom/dom_driver.d.ts} +7 -1
- package/dist/dom/dom_driver.d.ts.map +1 -0
- package/dist/dom/native_setter.d.ts +5 -0
- package/dist/dom/native_setter.d.ts.map +1 -0
- package/dist/index.d.ts +19 -16
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3886 -388
- package/dist/index.js.map +4 -4
- package/dist/skills/fill_template.d.ts +17 -0
- package/dist/skills/fill_template.d.ts.map +1 -0
- package/dist/skills/parse_skills.d.ts +8 -0
- package/dist/skills/parse_skills.d.ts.map +1 -0
- package/dist/skills/skill.d.ts +24 -0
- package/dist/skills/skill.d.ts.map +1 -0
- package/dist/{client_tool_registry.d.ts → tools/client_tool_registry.d.ts} +6 -1
- package/dist/tools/client_tool_registry.d.ts.map +1 -0
- package/dist/tools/is_destructive.d.ts.map +1 -0
- package/dist/tools/is_navigates.d.ts.map +1 -0
- package/dist/tools/page_map.d.ts.map +1 -0
- package/dist/tools/route_map.d.ts +40 -0
- package/dist/tools/route_map.d.ts.map +1 -0
- package/dist/tools/state_hook.d.ts.map +1 -0
- package/dist/ui/confirmation_card.d.ts +22 -0
- package/dist/ui/confirmation_card.d.ts.map +1 -0
- package/dist/ui/render_markdown.d.ts +13 -0
- package/dist/ui/render_markdown.d.ts.map +1 -0
- package/dist/ui/reveal_words.d.ts +8 -0
- package/dist/ui/reveal_words.d.ts.map +1 -0
- package/dist/ui/skills_menu.d.ts +35 -0
- package/dist/ui/skills_menu.d.ts.map +1 -0
- package/dist/ui/styles.d.ts +2 -0
- package/dist/ui/styles.d.ts.map +1 -0
- package/dist/ui/tool_call_card.d.ts +35 -0
- package/dist/ui/tool_call_card.d.ts.map +1 -0
- package/package.json +5 -3
- package/src/constants.ts +38 -0
- package/src/core/ag_ui_chat.ts +786 -0
- package/src/{agui_client.ts → core/agui_client.ts} +1 -1
- package/src/{define_ag_ui_chat.ts → core/define_ag_ui_chat.ts} +1 -1
- package/src/dom/animations.ts +201 -0
- package/src/{dom_driver.ts → dom/dom_driver.ts} +35 -2
- package/src/dom/native_setter.ts +42 -0
- package/src/index.ts +61 -32
- package/src/skills/fill_template.ts +32 -0
- package/src/skills/parse_skills.ts +26 -0
- package/src/skills/skill.ts +23 -0
- package/src/{client_tool_registry.ts → tools/client_tool_registry.ts} +6 -4
- package/src/{is_destructive.ts → tools/is_destructive.ts} +1 -1
- package/src/{is_navigates.ts → tools/is_navigates.ts} +1 -1
- package/src/tools/route_map.ts +140 -0
- package/src/{state_hook.ts → tools/state_hook.ts} +1 -1
- package/src/ui/confirmation_card.ts +71 -0
- package/src/ui/render_markdown.ts +68 -0
- package/src/ui/reveal_words.ts +41 -0
- package/src/ui/skills_menu.ts +171 -0
- package/src/ui/styles.ts +631 -0
- package/src/{tool_call_card.ts → ui/tool_call_card.ts} +50 -19
- package/src/version.ts +1 -1
- package/dist/ag_ui_chat.d.ts.map +0 -1
- package/dist/agui_client.d.ts.map +0 -1
- package/dist/animations.d.ts +0 -33
- package/dist/animations.d.ts.map +0 -1
- package/dist/client_tool_registry.d.ts.map +0 -1
- package/dist/confirmation_modal.d.ts +0 -14
- package/dist/confirmation_modal.d.ts.map +0 -1
- package/dist/conversation_store.d.ts.map +0 -1
- package/dist/create_http_agent.d.ts.map +0 -1
- package/dist/define_ag_ui_chat.d.ts.map +0 -1
- package/dist/dom_driver.d.ts.map +0 -1
- package/dist/is_destructive.d.ts.map +0 -1
- package/dist/is_navigates.d.ts.map +0 -1
- package/dist/page_map.d.ts.map +0 -1
- package/dist/route_map.d.ts +0 -27
- package/dist/route_map.d.ts.map +0 -1
- package/dist/state_hook.d.ts.map +0 -1
- package/dist/styles.d.ts +0 -2
- package/dist/styles.d.ts.map +0 -1
- package/dist/tool_call_card.d.ts +0 -29
- package/dist/tool_call_card.d.ts.map +0 -1
- package/src/ag_ui_chat.ts +0 -411
- package/src/animations.ts +0 -86
- package/src/confirmation_modal.ts +0 -69
- package/src/route_map.ts +0 -83
- package/src/styles.ts +0 -296
- /package/dist/{agui_client.d.ts → core/agui_client.d.ts} +0 -0
- /package/dist/{conversation_store.d.ts → core/conversation_store.d.ts} +0 -0
- /package/dist/{create_http_agent.d.ts → core/create_http_agent.d.ts} +0 -0
- /package/dist/{define_ag_ui_chat.d.ts → core/define_ag_ui_chat.d.ts} +0 -0
- /package/dist/{is_destructive.d.ts → tools/is_destructive.d.ts} +0 -0
- /package/dist/{is_navigates.d.ts → tools/is_navigates.d.ts} +0 -0
- /package/dist/{page_map.d.ts → tools/page_map.d.ts} +0 -0
- /package/dist/{state_hook.d.ts → tools/state_hook.d.ts} +0 -0
- /package/src/{conversation_store.ts → core/conversation_store.ts} +0 -0
- /package/src/{create_http_agent.ts → core/create_http_agent.ts} +0 -0
- /package/src/{page_map.ts → tools/page_map.ts} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -7,7 +7,107 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.2.0] — 2026-06-02
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- **Markdown + HTML rendering** in assistant message bubbles (`renderMarkdown`),
|
|
14
|
+
sanitised with DOMPurify (scripts, event handlers, and `javascript:` URLs
|
|
15
|
+
stripped; links hardened with `target`/`rel`). User messages stay literal.
|
|
16
|
+
- **Pending indicator** — an animated "thinking" indicator shown while the agent
|
|
17
|
+
is awaited (before the first token and between tool rounds), honouring
|
|
18
|
+
`prefers-reduced-motion`.
|
|
19
|
+
- **New-chat button** in the header — clears the transcript, the persisted
|
|
20
|
+
conversation, and the in-memory run state, and mints a fresh thread.
|
|
21
|
+
- **Collapse seam** — a reflected `collapsed` attribute, a built-in header
|
|
22
|
+
toggle, a persisted (per-tab) collapsed state, and a `TOGGLE_EVENT`
|
|
23
|
+
(`ag-ui-toggle`) so a host can drive its own chrome.
|
|
24
|
+
- **Tool-call display modes** (`TOOL_DISPLAY`, `data-tool-display`): `minimal`
|
|
25
|
+
(name + status), `compact` (args + result behind one "Details" toggle), and
|
|
26
|
+
`full` (the default; original behaviour).
|
|
27
|
+
- **Richer action animations**: `pressThenClick`, `selectOption`,
|
|
28
|
+
`toggleControl` (+ `pressButton` / `selectControl` / `toggleCheckbox` driver
|
|
29
|
+
wrappers), all honouring `prefers-reduced-motion`.
|
|
30
|
+
- **Dynamic route syntax**: `Route.path` supports `:name` placeholders;
|
|
31
|
+
`navigate_to_route` substitutes path params (leftover params → query string)
|
|
32
|
+
and `list_routes` advertises each route's `pathParams`.
|
|
33
|
+
- `X_CONFIRM_KEY` (`x-confirm`) tool metadata for a human-readable confirmation
|
|
34
|
+
prompt.
|
|
35
|
+
- `setNativeValue` / `setNativeChecked` utilities (also used internally).
|
|
36
|
+
- **Theming** — a `theme` attribute (`light` / `dark` / `auto` / `code`); `auto`
|
|
37
|
+
follows `prefers-color-scheme`, `code` is a monospace terminal palette. Plus a
|
|
38
|
+
wider set of themeable `--ag-ui-*` variables.
|
|
39
|
+
- **Density + placement presets** — `density` (`comfortable` / `compact`) and
|
|
40
|
+
`placement` (`bottom-left` / `side` / `full` / `embedded`); `embedded` drops
|
|
41
|
+
the floating chrome and high z-index so the widget lives in the host layout.
|
|
42
|
+
- **Incoming-text animations** — `data-text-animation` (`none` / `fade` /
|
|
43
|
+
`word`), the last revealing assistant text word-by-word; honours
|
|
44
|
+
`prefers-reduced-motion`.
|
|
45
|
+
- **`confirmPredicate`** — a per-call `(toolName, args) => boolean | Promise`
|
|
46
|
+
hook deciding confirmation dynamically (authoritative over `x-destructive`).
|
|
47
|
+
- **Built-in `read_page` tool** — present when a `getPageMap` provider is set, so
|
|
48
|
+
the agent can re-read the page mid-turn after acting.
|
|
49
|
+
- **`x-summary`** tool metadata (`X_SUMMARY_KEY`) — a friendly label shown on the
|
|
50
|
+
tool-call card instead of the raw tool name.
|
|
51
|
+
- `observedAttributes` / `attributeChangedCallback` so a late `title-text`
|
|
52
|
+
change updates the header.
|
|
53
|
+
- Accessibility: `role="log"`/`aria-live` on the transcript, `role="status"` on
|
|
54
|
+
the pending indicator, `role="group"` on the confirmation card, input label.
|
|
55
|
+
- **Skills** — pre-defined prompts surfaced as **chips** (`data-prompt-chips`)
|
|
56
|
+
and/or a **`/`-command palette** (`data-slash-commands`), both opt-in over one
|
|
57
|
+
catalog. Catalog from the `skills` setter (`setSkills`), a `data-skills` JSON
|
|
58
|
+
embed, and/or a fetched `data-skills-url` (merged backend → embed → client).
|
|
59
|
+
Picking pre-fills the input (or auto-sends with `sendImmediately`); prompts
|
|
60
|
+
support `{placeholder}`s filled from `skillContext`, with a missing value
|
|
61
|
+
blocking the send and showing a hint. Exports the `Skill` type.
|
|
62
|
+
|
|
63
|
+
### Changed
|
|
64
|
+
- The destructive-action confirmation is now an **inline card in the transcript**
|
|
65
|
+
(Confirm / Cancel, with the `x-confirm` message) instead of a focus-stealing
|
|
66
|
+
modal overlay. `requestConfirmation` now renders inline; the
|
|
67
|
+
`confirmation_modal` module was removed.
|
|
68
|
+
- **Framework-controlled inputs now work.** `fillField` / `typeInto` /
|
|
69
|
+
`selectOption` / `toggleControl` / `setControlValue` set `value` / `checked`
|
|
70
|
+
through the **native prototype setter** before dispatching `input`, so
|
|
71
|
+
React/Vue/Svelte value-tracking sees the change (previously the field looked
|
|
72
|
+
filled but host state stayed empty).
|
|
73
|
+
- **Framework interop:** reflecting **property setters** for `endpoint`,
|
|
74
|
+
`toolDisplay`, and `collapsed` (React 19 assigns matching props as element
|
|
75
|
+
properties — getter-only props previously threw).
|
|
76
|
+
- `registerTool` is now **idempotent** — re-registering a tool name replaces it
|
|
77
|
+
instead of throwing (re-fired refs / React StrictMode).
|
|
78
|
+
|
|
79
|
+
### Fixed
|
|
80
|
+
- The Markdown/HTML allowlist now permits sanitised **`<img>`** (safe-scheme
|
|
81
|
+
`src`, no event handlers); `javascript:` srcs and disallowed tags (e.g.
|
|
82
|
+
`iframe`) are still stripped.
|
|
83
|
+
|
|
84
|
+
## [0.1.1] — 2026-06-01
|
|
85
|
+
|
|
86
|
+
### Changed
|
|
87
|
+
- CI: resolve the pnpm version from `package.json`'s `packageManager` only
|
|
88
|
+
(dropped the conflicting `version` input in the release/test workflows).
|
|
89
|
+
|
|
90
|
+
### Notes
|
|
91
|
+
- First fully-automated release via the npm OIDC publish pipeline — 0.1.0 was
|
|
92
|
+
the manual bootstrap publish that created the package.
|
|
93
|
+
|
|
94
|
+
## [0.1.0] — 2026-06-01
|
|
95
|
+
|
|
10
96
|
### Added
|
|
11
|
-
-
|
|
97
|
+
- `<ag-ui-chat>` Web Component over AG-UI: Shadow-DOM chat UI, a pluggable tool
|
|
98
|
+
registry (`registerTool`), the `x-destructive` confirmation modal, and the
|
|
99
|
+
DOM-driver + animation primitives.
|
|
100
|
+
- Durable conversation + resumable run loop that survives the full page reloads
|
|
101
|
+
of a multi-page app: `SessionStorageStore`, a persisted thread id, and
|
|
102
|
+
`x-navigates` checkpoints completed via `navigationResult` on the next mount.
|
|
103
|
+
- Host seams: `routeMap` (+ `list_routes` / `navigate_to_route`), an
|
|
104
|
+
auto-injected `getPageMap` context, `registerStateHook`, and an optional
|
|
105
|
+
client-side `navigate()` callback (SPA vs MPA).
|
|
106
|
+
|
|
107
|
+
### Notes
|
|
108
|
+
- First release — exercising the automated npm OIDC publish pipeline end-to-end.
|
|
12
109
|
|
|
13
|
-
[Unreleased]: https://github.com/Artui/ag-ui-web-component/compare/v0.
|
|
110
|
+
[Unreleased]: https://github.com/Artui/ag-ui-web-component/compare/v0.2.0...HEAD
|
|
111
|
+
[0.2.0]: https://github.com/Artui/ag-ui-web-component/compare/v0.1.1...v0.2.0
|
|
112
|
+
[0.1.1]: https://github.com/Artui/ag-ui-web-component/compare/v0.1.0...v0.1.1
|
|
113
|
+
[0.1.0]: https://github.com/Artui/ag-ui-web-component/releases/tag/v0.1.0
|
package/README.md
CHANGED
|
@@ -17,8 +17,13 @@ It wraps [`@ag-ui/client`](https://www.npmjs.com/package/@ag-ui/client)'s `HttpA
|
|
|
17
17
|
- Generic **DOM-driver primitives** (`fillField`, `clickElement`, `setControlValue`) and
|
|
18
18
|
**animation primitives** (`typeInto`, `highlightThenClick`, …) so the agent can drive the page
|
|
19
19
|
at human-readable speed.
|
|
20
|
-
-
|
|
21
|
-
carries `x-destructive: true`) before the handler
|
|
20
|
+
- An **inline confirmation card** that intercepts tool calls needing confirmation (those whose
|
|
21
|
+
JSON Schema carries `x-destructive: true`, or a per-call `confirmPredicate`) before the handler
|
|
22
|
+
runs — rendered right in the transcript, never a modal overlay.
|
|
23
|
+
- **Markdown + HTML rendering** of assistant replies (sanitized `marked` + DOMPurify), with
|
|
24
|
+
themes, density/placement presets, incoming-text animations, tool-call display modes, an
|
|
25
|
+
animated thinking indicator, and an opt-in **skills** palette (prompt chips + `/`-commands).
|
|
26
|
+
- A **new-chat** button and a **collapse** toggle built into the header.
|
|
22
27
|
- An **MPA durability story**: a durable conversation store, a stable thread id, and a resumable
|
|
23
28
|
run loop that survives full page reloads (`x-navigates` + `navigationResult`).
|
|
24
29
|
- **Host seams** for SPAs: a route map, an auto-injected page map, state hooks, and an optional
|
|
@@ -36,12 +41,16 @@ No framework, no Django, no admin specifics live here. Downstream consumers (e.g
|
|
|
36
41
|
- [Core concepts](#core-concepts)
|
|
37
42
|
- [The run loop and the AG-UI client](#the-run-loop-and-the-ag-ui-client)
|
|
38
43
|
- [Registering tools](#registering-tools)
|
|
39
|
-
- [
|
|
44
|
+
- [Inline confirmation (`x-destructive` / `x-confirm` / `confirmPredicate`)](#inline-confirmation-x-destructive--x-confirm--confirmpredicate)
|
|
40
45
|
- [DOM-driver and animation primitives](#dom-driver-and-animation-primitives)
|
|
46
|
+
- [New chat and collapse](#new-chat-and-collapse)
|
|
47
|
+
- [Tool-call display modes](#tool-call-display-modes)
|
|
48
|
+
- [Markdown rendering](#markdown-rendering)
|
|
49
|
+
- [Skills: prompt chips and slash palette](#skills-prompt-chips-and-slash-palette)
|
|
41
50
|
- [MPA durability: surviving full page reloads](#mpa-durability-surviving-full-page-reloads)
|
|
42
51
|
- [Host seams: the SPA story](#host-seams-the-spa-story)
|
|
43
52
|
- [Public API surface](#public-api-surface)
|
|
44
|
-
- [Theming](#theming)
|
|
53
|
+
- [Theming, density, and placement](#theming-density-and-placement)
|
|
45
54
|
- [Building the bundle](#building-the-bundle)
|
|
46
55
|
- [Compatibility](#compatibility)
|
|
47
56
|
|
|
@@ -110,7 +119,7 @@ Drop the element into your page and register the tools the agent may call:
|
|
|
110
119
|
});
|
|
111
120
|
|
|
112
121
|
// A destructive tool: x-destructive at the JSON-Schema root gates it behind
|
|
113
|
-
// the confirmation
|
|
122
|
+
// the inline confirmation card before the handler runs.
|
|
114
123
|
chat.registerTool({
|
|
115
124
|
name: "save_article",
|
|
116
125
|
description: "Save the article. Destructive — asks for confirmation.",
|
|
@@ -130,14 +139,32 @@ That's the whole integration: an `endpoint` attribute pointing at your AG-UI ser
|
|
|
130
139
|
|
|
131
140
|
### Attributes and properties
|
|
132
141
|
|
|
142
|
+
**Attributes** (set in HTML; the CSS-only ones are styling presets with no JS API):
|
|
143
|
+
|
|
133
144
|
| Attribute | Property | Notes |
|
|
134
145
|
| --- | --- | --- |
|
|
135
|
-
| `endpoint` | `endpoint`
|
|
136
|
-
| `title-text` | — | Header label; defaults to `"Assistant"`. |
|
|
137
|
-
|
|
|
138
|
-
|
|
|
139
|
-
|
|
140
|
-
|
|
146
|
+
| `endpoint` | `endpoint` | The AG-UI endpoint URL. Required to send. Reflecting getter + setter. |
|
|
147
|
+
| `title-text` | — | Header label; defaults to `"Assistant"`. The only **observed** attribute (live-updates the header). |
|
|
148
|
+
| `data-tool-display` | `toolDisplay` | Tool-call card detail: `minimal` / `compact` / `full` (default `full`). |
|
|
149
|
+
| `data-text-animation` | — | Incoming-text reveal: `none` (default) / `fade` / `word`. |
|
|
150
|
+
| `data-prompt-chips` | — | `"true"` to surface skills as chips. |
|
|
151
|
+
| `data-slash-commands` | — | `"true"` to enable the `/`-command palette. |
|
|
152
|
+
| `data-skills` | — | Inline JSON skill catalog. |
|
|
153
|
+
| `data-skills-url` | — | URL of a JSON skill catalog (fetched with `headers`). |
|
|
154
|
+
| `collapsed` | `collapsed` | Reflected boolean; collapses the widget. Persisted per-tab in `sessionStorage`. |
|
|
155
|
+
| `theme` | — | CSS-only: `light` (default) / `dark` / `auto` / `code`. |
|
|
156
|
+
| `density` | — | CSS-only: `comfortable` (default) / `compact`. |
|
|
157
|
+
| `placement` | — | CSS-only: `floating` (default) / `bottom-left` / `side` / `full` / `embedded`. |
|
|
158
|
+
|
|
159
|
+
**Properties** (JS only, not attributes): `headers`, `autoConfirm`, `confirmPredicate`,
|
|
160
|
+
`agentFactory`, `getTools`, `getContext`, `routeMap`, `navigate`, `getPageMap`,
|
|
161
|
+
`autoInjectPageMap`, `conversationStore`, `navigationResult`, `skillContext`, plus the mirrors
|
|
162
|
+
`endpoint` / `toolDisplay` / `collapsed`.
|
|
163
|
+
|
|
164
|
+
**Methods**: `registerTool`, `registerStateHook`, `setSkills`, `appendMessage`, `newChat`,
|
|
165
|
+
`setCollapsed`, `toggleCollapsed`.
|
|
166
|
+
|
|
167
|
+
A self-contained live playground lives in [`demo/`](demo/) — run `make demo` to serve it against a
|
|
141
168
|
mock AG-UI server.
|
|
142
169
|
|
|
143
170
|
---
|
|
@@ -146,9 +173,9 @@ mock AG-UI server.
|
|
|
146
173
|
|
|
147
174
|
### The run loop and the AG-UI client
|
|
148
175
|
|
|
149
|
-
`<ag-ui-chat>` is the view; [`AgUiClient`](src/agui_client.ts) is the orchestration layer over
|
|
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:
|
|
176
|
+
`<ag-ui-chat>` is the view; [`AgUiClient`](src/core/agui_client.ts) is the orchestration layer over
|
|
177
|
+
an AG-UI `AbstractAgent`. On the first send the element builds a client (via the overridable
|
|
178
|
+
`agentFactory`, which defaults to [`createHttpAgent`](src/core/create_http_agent.ts)). Each turn:
|
|
152
179
|
|
|
153
180
|
1. The user message is appended and the agent runs once.
|
|
154
181
|
2. AG-UI subscriber events are translated into the element's handlers — streaming text deltas
|
|
@@ -184,48 +211,181 @@ Names must be unique (registering a duplicate throws). Each `<ag-ui-chat>` eleme
|
|
|
184
211
|
registry, AG-UI client, and Shadow DOM, so **multiple instances on one page never interfere** —
|
|
185
212
|
there is no module-level shared state anywhere in the package.
|
|
186
213
|
|
|
187
|
-
###
|
|
214
|
+
### Inline confirmation (`x-destructive` / `x-confirm` / `confirmPredicate`)
|
|
215
|
+
|
|
216
|
+
When a tool call needs confirmation, the element appends an **inline confirmation card** (a
|
|
217
|
+
`<div class="confirm">`) to the transcript via
|
|
218
|
+
[`requestConfirmation`](src/ui/confirmation_card.ts) — it is not a modal overlay. The card reads
|
|
219
|
+
naturally after the assistant's explanation, never steals focus from the page, and stays in the
|
|
220
|
+
transcript as a resolved record after the decision:
|
|
221
|
+
|
|
222
|
+
- **Confirm** → the handler runs and the result is posted back.
|
|
223
|
+
- **Cancel** → a `"User declined the action."` result is posted; the agent acknowledges on its
|
|
224
|
+
next turn.
|
|
225
|
+
|
|
226
|
+
Whether a call is gated is decided in this order:
|
|
227
|
+
|
|
228
|
+
1. If `chat.autoConfirm === true`, the call **never** prompts (an "autopilot" toggle).
|
|
229
|
+
2. Else if `chat.confirmPredicate` is set, its boolean return is authoritative — given the tool
|
|
230
|
+
name + parsed args it decides per-call (so one tool can be instant for some args and confirmed
|
|
231
|
+
for others, which a static flag can't express).
|
|
232
|
+
3. Else the element falls back to [`isDestructive(parameters)`](src/tools/is_destructive.ts),
|
|
233
|
+
which reads the `x-destructive` JSON-Schema flag.
|
|
188
234
|
|
|
189
235
|
AG-UI has no built-in risk flag, so destructiveness is carried as a JSON-Schema extension at the
|
|
190
236
|
**schema root**: `parameters["x-destructive"] = true` (use the exported `X_DESTRUCTIVE_KEY`
|
|
191
|
-
constant). There is no parallel metadata channel
|
|
192
|
-
|
|
193
|
-
|
|
237
|
+
constant). There is no parallel metadata channel and no name heuristic — destructiveness is exactly
|
|
238
|
+
the `x-destructive` flag (or `confirmPredicate`). The registry forwards the flag verbatim to
|
|
239
|
+
`RunAgentInput.tools`.
|
|
194
240
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
dispatching to the handler:
|
|
241
|
+
If the schema carries an `x-confirm` string (use `X_CONFIRM_KEY`), the card shows it as the prompt;
|
|
242
|
+
otherwise it falls back to a generic `Run "<tool>"?`.
|
|
198
243
|
|
|
199
|
-
|
|
200
|
-
-
|
|
201
|
-
|
|
244
|
+
```js
|
|
245
|
+
// Per-call: confirm a delete only when it would remove more than one row.
|
|
246
|
+
chat.confirmPredicate = (name, args) =>
|
|
247
|
+
name === "delete_rows" && Array.isArray(args.ids) && args.ids.length > 1;
|
|
202
248
|
|
|
203
|
-
|
|
249
|
+
// Prompt text via x-confirm:
|
|
250
|
+
chat.registerTool({
|
|
251
|
+
name: "activate_project",
|
|
252
|
+
description: "Activate the current project.",
|
|
253
|
+
parameters: { type: "object", properties: {}, [X_DESTRUCTIVE_KEY]: true, [X_CONFIRM_KEY]: "Activate this project?" },
|
|
254
|
+
handler: async () => await api.activate(),
|
|
255
|
+
});
|
|
256
|
+
```
|
|
204
257
|
|
|
205
258
|
### DOM-driver and animation primitives
|
|
206
259
|
|
|
207
260
|
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
|
|
261
|
+
primitives. The **animation** primitives ([`animations.ts`](src/dom/animations.ts)) operate at
|
|
209
262
|
human-readable speed (configurable; pass small/zero durations in tests):
|
|
210
263
|
|
|
211
264
|
- `typeInto(el, value, { charDelayMs })` — clears and types a value character by character,
|
|
212
265
|
firing `input`/`change` events as a real user would.
|
|
213
|
-
- `highlightThenClick(el, { highlightMs })`
|
|
266
|
+
- `highlightThenClick(el, { highlightMs })` / `pressThenClick(el, options)` — outline/press an
|
|
267
|
+
element, pause, then click.
|
|
268
|
+
- `selectOption(el, value)` / `toggleControl(el, checked)` — animate a `<select>` / checkbox.
|
|
214
269
|
- `scrollIntoCenterView(el)` / `focusWithFlash(el, { flashMs })`.
|
|
270
|
+
- `prefersReducedMotion()` — honoured throughout so animations collapse to instant when the user
|
|
271
|
+
asks for reduced motion.
|
|
215
272
|
|
|
216
|
-
The **DOM-driver** primitives ([`dom_driver.ts`](src/dom_driver.ts)) compose those into the
|
|
273
|
+
The **DOM-driver** primitives ([`dom_driver.ts`](src/dom/dom_driver.ts)) compose those into the
|
|
217
274
|
operations a tool handler typically wants:
|
|
218
275
|
|
|
219
276
|
- `fillField(el, value, options)` — scroll to, focus-flash, and type into a text field.
|
|
220
|
-
- `clickElement(el, options)` — scroll to, highlight, and click.
|
|
277
|
+
- `clickElement(el, options)` / `pressButton(el, options)` — scroll to, highlight/press, and click.
|
|
278
|
+
- `selectControl(el, value)` / `toggleCheckbox(el, checked)` — animate a `<select>` / checkbox.
|
|
221
279
|
- `setControlValue(el, value)` — set a `<select>` or checkbox without animation, dispatching
|
|
222
280
|
`input`/`change`.
|
|
223
281
|
|
|
282
|
+
The native-setter helpers ([`native_setter.ts`](src/dom/native_setter.ts)) — `setNativeValue` /
|
|
283
|
+
`setNativeChecked` — set a control through its native prototype setter so React-controlled inputs
|
|
284
|
+
register the change.
|
|
285
|
+
|
|
224
286
|
Each takes an element the caller has already located; host packages wrap them with
|
|
225
287
|
environment-aware lookups (e.g. "find `#id_<name>`, then `fillField`").
|
|
226
288
|
|
|
227
289
|
---
|
|
228
290
|
|
|
291
|
+
## New chat and collapse
|
|
292
|
+
|
|
293
|
+
The header carries two built-in buttons: a new-chat (✚) button and a collapse (—) toggle. The
|
|
294
|
+
matching JS API:
|
|
295
|
+
|
|
296
|
+
- `newChat()` — clears the transcript and the persisted history, drops the in-memory run state,
|
|
297
|
+
and mints a new thread id.
|
|
298
|
+
- `setCollapsed(collapsed)` / `toggleCollapsed()` — collapse or expand the widget. The state is
|
|
299
|
+
reflected as the boolean `collapsed` attribute/property and persisted per-tab in
|
|
300
|
+
`sessionStorage`, so it survives a reload.
|
|
301
|
+
|
|
302
|
+
Each change emits an `ag-ui-toggle` event (the `TOGGLE_EVENT` constant) with
|
|
303
|
+
`detail: { collapsed: boolean }` (typed `ToggleDetail`), so a host can mirror the state in its own
|
|
304
|
+
chrome — or hide the built-in toggle and drive the `collapsed` attribute itself.
|
|
305
|
+
|
|
306
|
+
```js
|
|
307
|
+
chat.newChat();
|
|
308
|
+
chat.toggleCollapsed();
|
|
309
|
+
chat.addEventListener("ag-ui-toggle", (e) => console.log(e.detail.collapsed));
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
## Tool-call display modes
|
|
315
|
+
|
|
316
|
+
How much a tool-call card shows is set via the `data-tool-display` attribute (or `toolDisplay`
|
|
317
|
+
property), one of `minimal` / `compact` / `full` (default `full`):
|
|
318
|
+
|
|
319
|
+
- `minimal` — tool name + status pill only.
|
|
320
|
+
- `compact` — name + status, with args *and* result behind a single collapsed "Details" toggle.
|
|
321
|
+
- `full` — args inline, result behind its own toggle (the original behaviour).
|
|
322
|
+
|
|
323
|
+
If a tool's schema carries an `x-summary` string (use `X_SUMMARY_KEY`), the card shows it on the
|
|
324
|
+
label instead of the raw tool name.
|
|
325
|
+
|
|
326
|
+
```html
|
|
327
|
+
<ag-ui-chat endpoint="/agent/" data-tool-display="compact"></ag-ui-chat>
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
---
|
|
331
|
+
|
|
332
|
+
## Markdown rendering
|
|
333
|
+
|
|
334
|
+
Assistant bubbles render sanitized markdown/HTML via [`marked`](https://www.npmjs.com/package/marked)
|
|
335
|
+
(GitHub-flavoured, single-newline line breaks) piped through
|
|
336
|
+
[DOMPurify](https://www.npmjs.com/package/dompurify). User messages stay literal text. The
|
|
337
|
+
allowlist permits emphasis, code, lists, quotes, headings, links, tables, and images (`img`); links
|
|
338
|
+
are hardened with `target="_blank" rel="noopener noreferrer"`; `iframe`/`style`/scripting are
|
|
339
|
+
excluded. The exported helper `renderMarkdown(text)` does this standalone. `marked` and `dompurify`
|
|
340
|
+
are runtime dependencies.
|
|
341
|
+
|
|
342
|
+
An animated 3-dot "thinking" indicator (`role="status"`, with an aria-label) appears before the
|
|
343
|
+
first token and between tool rounds, honouring `prefers-reduced-motion`. It has no public API.
|
|
344
|
+
|
|
345
|
+
### Incoming-text animations
|
|
346
|
+
|
|
347
|
+
The `data-text-animation` attribute controls how a fully-received assistant message reveals:
|
|
348
|
+
`none` (default) / `fade` (a CSS fade) / `word` (JS word-by-word via the internal `wrapWords`
|
|
349
|
+
reveal). It honours `prefers-reduced-motion` (collapsing to instant).
|
|
350
|
+
|
|
351
|
+
```html
|
|
352
|
+
<ag-ui-chat endpoint="/agent/" data-text-animation="word"></ag-ui-chat>
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
---
|
|
356
|
+
|
|
357
|
+
## Skills: prompt chips and slash palette
|
|
358
|
+
|
|
359
|
+
Skills are pre-defined prompts the user can launch from a chip or the `/`-command palette. They are
|
|
360
|
+
opt-in via two attributes:
|
|
361
|
+
|
|
362
|
+
```html
|
|
363
|
+
<ag-ui-chat endpoint="/agent/" data-prompt-chips="true" data-slash-commands="true"></ag-ui-chat>
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
A `Skill` is `{ name, title, description?, prompt, sendImmediately?, chip? }`. Skills are merged
|
|
367
|
+
from three sources — **backend → embed → client** (later wins by `name`):
|
|
368
|
+
|
|
369
|
+
- `data-skills-url` — a JSON endpoint, fetched with the element's `headers`.
|
|
370
|
+
- `data-skills` — an inline JSON catalog.
|
|
371
|
+
- `setSkills(skills)` — set the client catalog from JS.
|
|
372
|
+
|
|
373
|
+
```js
|
|
374
|
+
chat.setSkills([
|
|
375
|
+
{ name: "summarize", title: "Summarize page", prompt: "Summarize {title}.", chip: true },
|
|
376
|
+
]);
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
A skill `prompt` may contain `{placeholder}` tokens; the `skillContext` property
|
|
380
|
+
(`() => Record<string, unknown>`) supplies the values, filled in before send. A missing placeholder
|
|
381
|
+
blocks the send and shows a hint instead.
|
|
382
|
+
|
|
383
|
+
```js
|
|
384
|
+
chat.skillContext = () => ({ title: document.title });
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
---
|
|
388
|
+
|
|
229
389
|
## MPA durability: surviving full page reloads
|
|
230
390
|
|
|
231
391
|
In a multi-page app, a tool that navigates reloads the whole page and destroys the in-memory run
|
|
@@ -234,10 +394,10 @@ mechanisms.
|
|
|
234
394
|
|
|
235
395
|
**1. Thread identity.** AG-UI's `thread_id` is the conversation key. It is generated once and
|
|
236
396
|
persisted (so the element reattaches after a reload) by the
|
|
237
|
-
[`ClientConversationStore`](src/conversation_store.ts).
|
|
397
|
+
[`ClientConversationStore`](src/core/conversation_store.ts).
|
|
238
398
|
|
|
239
399
|
**2. Durable conversation.** A pluggable `ClientConversationStore` holds the message list. The
|
|
240
|
-
default [`SessionStorageStore`](src/conversation_store.ts) keeps everything per-tab in
|
|
400
|
+
default [`SessionStorageStore`](src/core/conversation_store.ts) keeps everything per-tab in
|
|
241
401
|
`sessionStorage`, so the chat survives full page reloads and clears on tab close. `loadMessages`
|
|
242
402
|
is async-friendly, so a host can inject a server-backed store (e.g. one that rehydrates from a
|
|
243
403
|
history endpoint) for cross-tab/device durability:
|
|
@@ -249,7 +409,7 @@ chat.conversationStore = new MyServerBackedStore();
|
|
|
249
409
|
On mount the element rehydrates the transcript from the store, so the chat looks continuous.
|
|
250
410
|
|
|
251
411
|
**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))
|
|
412
|
+
`x-navigates: true` (use `X_NAVIGATES_KEY`; read back by [`isNavigates`](src/tools/is_navigates.ts))
|
|
253
413
|
triggers a full reload. Before the handler navigates, the element writes a checkpoint
|
|
254
414
|
(`{ toolCallId }`) to the store. On the next page mount it:
|
|
255
415
|
|
|
@@ -276,10 +436,16 @@ rather than by exploring:
|
|
|
276
436
|
- `list_routes` — read-only; lists the routes.
|
|
277
437
|
- `navigate_to_route(route_id, params?)` — resolves the id to a path and navigates.
|
|
278
438
|
|
|
439
|
+
A route `path` may contain `:param` segments — e.g. `/projects/:id/users/:userId/`.
|
|
440
|
+
`navigate_to_route` substitutes the path params (URL-encoded) and sends any leftover params as a
|
|
441
|
+
query string; a missing or empty required path param throws. The resolved shape is the exported
|
|
442
|
+
`RouteWithParams` type.
|
|
443
|
+
|
|
279
444
|
```js
|
|
280
445
|
chat.routeMap = [
|
|
281
446
|
{ id: "users", path: "/users", title: "Users", description: "Manage user accounts" },
|
|
282
447
|
{ id: "billing", path: "/billing", title: "Billing" },
|
|
448
|
+
{ id: "user-detail", path: "/projects/:id/users/:userId/", title: "User detail" },
|
|
283
449
|
];
|
|
284
450
|
```
|
|
285
451
|
|
|
@@ -333,6 +499,7 @@ re-export point. Internal modules import from leaf paths.
|
|
|
333
499
|
| `defineAgUiChat()` | function | Idempotently register the element. |
|
|
334
500
|
| `MessageRole` | type | Role of a rendered chat message. |
|
|
335
501
|
| `SubmitDetail` | type | `detail` shape of the submit event. |
|
|
502
|
+
| `ToggleDetail` | type | `detail` shape of the `ag-ui-toggle` event (`{ collapsed }`). |
|
|
336
503
|
|
|
337
504
|
### AG-UI client & agent
|
|
338
505
|
|
|
@@ -360,10 +527,12 @@ re-export point. Internal modules import from leaf paths.
|
|
|
360
527
|
| --- | --- | --- |
|
|
361
528
|
| `createRouteTools(...)` | function | Build the built-in `route.*` tools. |
|
|
362
529
|
| `Route` / `RouteMap` | type | Navigable-route shapes. |
|
|
530
|
+
| `RouteWithParams` | type | A route resolved with `:param` path segments + leftover query params. |
|
|
363
531
|
| `createPageMapContext(...)` | function | Build the per-run `page_map` context entry. |
|
|
364
532
|
| `PageMap` | type | The compact page-surface shape. |
|
|
365
533
|
| `createStateHookTools(hook)` | function | Build `read_<name>` / `set_<name>` tools. |
|
|
366
534
|
| `StateHook` | type | A state-binding declaration. |
|
|
535
|
+
| `Skill` | type | A launchable prompt (chip / `/`-command). |
|
|
367
536
|
|
|
368
537
|
### Durability
|
|
369
538
|
|
|
@@ -378,12 +547,14 @@ re-export point. Internal modules import from leaf paths.
|
|
|
378
547
|
| Export | Kind | Summary |
|
|
379
548
|
| --- | --- | --- |
|
|
380
549
|
| `ToolCallCard` | class | A live tool-call card for the transcript. |
|
|
381
|
-
| `ToolCallStatus` / `SettledStatus` | type | Card lifecycle states. |
|
|
382
|
-
| `requestConfirmation(host, request)` | function |
|
|
383
|
-
| `ConfirmationRequest` | type | What the
|
|
384
|
-
| `
|
|
385
|
-
| `
|
|
386
|
-
| `
|
|
550
|
+
| `ToolCallStatus` / `SettledStatus` / `ToolDisplayMode` | type | Card lifecycle states + display mode. |
|
|
551
|
+
| `requestConfirmation(host, request)` | function | Append the inline confirmation card to the transcript. |
|
|
552
|
+
| `ConfirmationRequest` | type | What the card displays. |
|
|
553
|
+
| `renderMarkdown(text)` | function | Render sanitized markdown/HTML (marked + DOMPurify). |
|
|
554
|
+
| `typeInto` / `highlightThenClick` / `pressThenClick` / `selectOption` / `toggleControl` / `scrollIntoCenterView` / `focusWithFlash` / `prefersReducedMotion` | function | Animation primitives. |
|
|
555
|
+
| `fillField` / `clickElement` / `pressButton` / `selectControl` / `setControlValue` / `toggleCheckbox` | function | DOM-driver primitives. |
|
|
556
|
+
| `setNativeValue` / `setNativeChecked` | function | Set a control via its native prototype setter (React-controlled inputs). |
|
|
557
|
+
| `TypeOptions` / `HighlightClickOptions` / `PressOptions` / `SelectOptions` / `ToggleOptions` / `FlashOptions` / `FillFieldOptions` / `TextLikeElement` | type | Primitive option shapes. |
|
|
387
558
|
|
|
388
559
|
### Constants
|
|
389
560
|
|
|
@@ -391,17 +562,22 @@ re-export point. Internal modules import from leaf paths.
|
|
|
391
562
|
| --- | --- |
|
|
392
563
|
| `ELEMENT_TAG` | The registered tag name (`ag-ui-chat`). |
|
|
393
564
|
| `SUBMIT_EVENT` | The submit CustomEvent name. |
|
|
565
|
+
| `TOGGLE_EVENT` | The collapse-toggle CustomEvent name (`ag-ui-toggle`). |
|
|
394
566
|
| `MESSAGE_ROLE` | Message role constants. |
|
|
395
567
|
| `TOOL_CALL_STATUS` | Tool-call card status constants. |
|
|
568
|
+
| `TOOL_DISPLAY` | Tool-call display-mode constants (`minimal` / `compact` / `full`). |
|
|
569
|
+
| `X_CONFIRM_KEY` | JSON-Schema key carrying a confirmation prompt. |
|
|
570
|
+
| `X_SUMMARY_KEY` | JSON-Schema key carrying a short tool-card label. |
|
|
396
571
|
| `MAX_TOOL_ROUNDS` | Upper bound on tool-call → re-run rounds per send. |
|
|
397
572
|
| `VERSION` | The package version string. |
|
|
398
573
|
|
|
399
574
|
---
|
|
400
575
|
|
|
401
|
-
## Theming
|
|
576
|
+
## Theming, density, and placement
|
|
402
577
|
|
|
403
|
-
The chat shell is styled inside its Shadow DOM and exposes
|
|
404
|
-
|
|
578
|
+
The chat shell is styled inside its Shadow DOM and exposes a large set of `--ag-ui-*` CSS custom
|
|
579
|
+
properties on `:host` (colors, status, surface, spacing, layout), so you theme it from outside
|
|
580
|
+
without piercing the shadow boundary. A few of the knobs:
|
|
405
581
|
|
|
406
582
|
```css
|
|
407
583
|
ag-ui-chat {
|
|
@@ -410,8 +586,7 @@ ag-ui-chat {
|
|
|
410
586
|
--ag-ui-fg: #1a1a2e;
|
|
411
587
|
--ag-ui-radius: 12px;
|
|
412
588
|
|
|
413
|
-
/* Layout
|
|
414
|
-
--ag-ui-position: fixed;
|
|
589
|
+
/* Layout */
|
|
415
590
|
--ag-ui-width: 380px;
|
|
416
591
|
--ag-ui-height: 560px;
|
|
417
592
|
--ag-ui-inset: auto 24px 24px auto;
|
|
@@ -419,8 +594,21 @@ ag-ui-chat {
|
|
|
419
594
|
}
|
|
420
595
|
```
|
|
421
596
|
|
|
422
|
-
|
|
423
|
-
|
|
597
|
+
For the common cases there are three CSS-reactive **preset attributes** (no JS API), so you don't
|
|
598
|
+
have to hand-tune the variables:
|
|
599
|
+
|
|
600
|
+
- `theme` — `light` (default) / `dark` / `auto` (follow the OS) / `code`.
|
|
601
|
+
- `density` — `comfortable` (default) / `compact`.
|
|
602
|
+
- `placement` — `floating` (default) / `bottom-left` / `side` / `full` / `embedded`. `embedded`
|
|
603
|
+
drops the fixed positioning and z-index so the widget sits in normal document flow.
|
|
604
|
+
|
|
605
|
+
```html
|
|
606
|
+
<ag-ui-chat endpoint="/agent/" theme="dark" density="compact" placement="side"></ag-ui-chat>
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
See [`src/ui/styles.ts`](src/ui/styles.ts) for the full variable + preset list. The
|
|
610
|
+
[`demo/`](demo/) live playground (`node demo/mock-server.mjs`) flips theme, density, placement,
|
|
611
|
+
text-animation, and tool-display live from a single page.
|
|
424
612
|
|
|
425
613
|
---
|
|
426
614
|
|
|
@@ -449,7 +637,7 @@ Other workflow targets (all identical in name to the sibling Python packages):
|
|
|
449
637
|
| `make test` | Vitest with a 100% line + branch + function + statement coverage gate. |
|
|
450
638
|
| `make lint` | `biome check .` + `tsc --noEmit`. |
|
|
451
639
|
| `make format` | `biome format --write .`. |
|
|
452
|
-
| `make demo` | Build, then serve `demo
|
|
640
|
+
| `make demo` | Build, then serve the live playground (`demo/themes/index.html`) on port 5173 via `demo/mock-server.mjs`. |
|
|
453
641
|
|
|
454
642
|
---
|
|
455
643
|
|
|
@@ -457,7 +645,7 @@ Other workflow targets (all identical in name to the sibling Python packages):
|
|
|
457
645
|
|
|
458
646
|
| Component | Floor | Tested |
|
|
459
647
|
| --- | --- | --- |
|
|
460
|
-
| Node (tooling/tests only) |
|
|
648
|
+
| Node (tooling/tests only) | 22 | 22, 24 |
|
|
461
649
|
| Browsers (runtime target) | ES2022 / evergreen | Chrome / Firefox / Safari 17+ |
|
|
462
650
|
| `@ag-ui/client` | latest 0.x | — |
|
|
463
651
|
|