@artooi/ag-ui-web-component 0.46.0 → 0.48.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 +221 -1
- package/README.md +298 -31
- package/dist/ag-ui-web-component.bundle.js +597 -177
- package/dist/ag-ui-web-component.bundle.js.map +4 -4
- package/dist/constants.d.ts +37 -2
- package/dist/constants.d.ts.map +1 -1
- package/dist/core/ag_ui_chat.d.ts +73 -2
- package/dist/core/ag_ui_chat.d.ts.map +1 -1
- package/dist/core/chat_registry.d.ts +23 -0
- package/dist/core/chat_registry.d.ts.map +1 -0
- package/dist/core/events/bar_height_detail.d.ts +6 -0
- package/dist/core/events/bar_height_detail.d.ts.map +1 -0
- package/dist/core/events/run_finished_detail.d.ts +6 -0
- package/dist/core/events/run_finished_detail.d.ts.map +1 -1
- package/dist/core/events/thread_detail.d.ts +27 -0
- package/dist/core/events/thread_detail.d.ts.map +1 -0
- package/dist/core/run_handlers.d.ts +6 -1
- package/dist/core/run_handlers.d.ts.map +1 -1
- package/dist/dom/animations.d.ts +21 -6
- package/dist/dom/animations.d.ts.map +1 -1
- package/dist/dom/highlight_overlay.d.ts +8 -1
- package/dist/dom/highlight_overlay.d.ts.map +1 -1
- package/dist/dom/ring_color.d.ts +22 -0
- package/dist/dom/ring_color.d.ts.map +1 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1164 -95
- package/dist/index.js.map +4 -4
- package/dist/tools/chat_surface_tools.d.ts +8 -1
- package/dist/tools/chat_surface_tools.d.ts.map +1 -1
- package/dist/ui/history/conversation_history.d.ts +24 -2
- package/dist/ui/history/conversation_history.d.ts.map +1 -1
- package/dist/ui/placement/collapse_styles.d.ts.map +1 -1
- package/dist/ui/placement/dock_styles.d.ts +2 -0
- package/dist/ui/placement/dock_styles.d.ts.map +1 -0
- package/dist/ui/placement/panel_placement.d.ts +17 -0
- package/dist/ui/placement/panel_placement.d.ts.map +1 -1
- package/dist/ui/placement/small_viewport_styles.d.ts.map +1 -1
- package/dist/ui/placement/surface_for.d.ts +21 -17
- package/dist/ui/placement/surface_for.d.ts.map +1 -1
- package/dist/ui/progress/tool_call_card.d.ts.map +1 -1
- package/dist/ui/progress/tool_group_styles.d.ts.map +1 -1
- package/dist/ui/progress/tool_step_group.d.ts.map +1 -1
- package/dist/ui/progress/tool_step_styles.d.ts.map +1 -1
- package/dist/ui/shell/build_launcher.d.ts +15 -4
- package/dist/ui/shell/build_launcher.d.ts.map +1 -1
- package/dist/ui/shell/token_styles.d.ts.map +1 -1
- package/dist/ui/styles.d.ts.map +1 -1
- package/dist/ui/themes/scheme_styles.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/constants.ts +41 -2
- package/src/core/ag_ui_chat.ts +430 -27
- package/src/core/chat_registry.ts +53 -0
- package/src/core/events/bar_height_detail.ts +5 -0
- package/src/core/events/run_finished_detail.ts +6 -0
- package/src/core/events/thread_detail.ts +26 -0
- package/src/core/run_handlers.ts +9 -4
- package/src/dom/animations.ts +30 -31
- package/src/dom/highlight_overlay.ts +10 -5
- package/src/dom/ring_color.ts +222 -0
- package/src/index.ts +7 -0
- package/src/tools/chat_surface_tools.ts +18 -8
- package/src/ui/history/conversation_history.ts +75 -7
- package/src/ui/placement/collapse_styles.ts +248 -2
- package/src/ui/placement/dock_styles.ts +91 -0
- package/src/ui/placement/embedded_styles.ts +2 -2
- package/src/ui/placement/panel_placement.ts +105 -12
- package/src/ui/placement/preset_styles.ts +1 -1
- package/src/ui/placement/sidebar_styles.ts +1 -1
- package/src/ui/placement/small_viewport_styles.ts +14 -0
- package/src/ui/placement/surface_for.ts +29 -18
- package/src/ui/progress/tool_call_card.ts +18 -8
- package/src/ui/progress/tool_group_styles.ts +49 -0
- package/src/ui/progress/tool_step_group.ts +3 -0
- package/src/ui/progress/tool_step_styles.ts +5 -3
- package/src/ui/shell/build_launcher.ts +32 -5
- package/src/ui/shell/token_styles.ts +30 -3
- package/src/ui/styles.ts +4 -0
- package/src/ui/themes/scheme_styles.ts +10 -1
- package/src/version.ts +1 -1
package/README.md
CHANGED
|
@@ -48,6 +48,7 @@ No framework, no Django, no admin specifics live here. Downstream consumers (e.g
|
|
|
48
48
|
- [Page-action tools](#page-action-tools)
|
|
49
49
|
- [New chat and collapse](#new-chat-and-collapse)
|
|
50
50
|
- [Collapsing to the launcher](#collapsing-to-the-launcher)
|
|
51
|
+
- [Collapsing to a bottom bar](#collapsing-to-a-bottom-bar)
|
|
51
52
|
- [Tool-call display modes](#tool-call-display-modes)
|
|
52
53
|
- [Delegated sub-agents](#delegated-sub-agents)
|
|
53
54
|
- [Markdown rendering](#markdown-rendering)
|
|
@@ -178,6 +179,7 @@ another origin, add `credentials="include"` too; see
|
|
|
178
179
|
| `credentials` | `credentials` | Cookie policy for every request the element makes: `omit` / `same-origin` / `include`. Unset means the browser default (`same-origin`), which sends no cookies cross-origin. See [Authenticating requests](#authenticating-requests). |
|
|
179
180
|
| `title-text` | — | Header label; defaults to `"Assistant"`. Live: writing it after the element connects re-labels the header. See [When each attribute is read](#when-each-attribute-is-read). |
|
|
180
181
|
| `data-tool-display` | `toolDisplay` | How tool calls are drawn: `grouped` (the default: a run's consecutive calls fold into one row) / `inline` / `minimal` / `compact` / `full` (per-call cards; `full` was the default before `grouped`). An unknown value reads as `grouped`. See [Tool-call display modes](#tool-call-display-modes). |
|
|
182
|
+
| `data-tool-group-display` | `toolGroupDisplay` | How an opened step group draws its calls under `grouped`: `full` (the default) / `compact` / `minimal` / `inline`. Ignored under the four card modes. An absent or unknown value reads as `full`. See [Choosing how a group draws its calls](#choosing-how-a-group-draws-its-calls). |
|
|
181
183
|
| `data-text-animation` | — | Incoming-text reveal: `none` (default) / `fade` / `word`. |
|
|
182
184
|
| `data-prompt-chips` | — | Present (bare, or any value but `"false"`) to surface skills as chips. |
|
|
183
185
|
| `data-slash-commands` | — | Present (bare, or any value but `"false"`) to enable the `/`-command palette. |
|
|
@@ -206,10 +208,13 @@ another origin, add `credentials="include"` too; see
|
|
|
206
208
|
| `data-side` | — | CSS-only, for `placement="sidebar"`: which edge it docks to — `right` (default) / `left`. |
|
|
207
209
|
| `data-answer-well` | — | CSS-only boolean: box each assistant turn (its text, tool cards, and thinking) in one bordered "well". Off by default. See [The answer well](#the-answer-well). |
|
|
208
210
|
| `collapsed` | `collapsed` | Reflected boolean; collapses the widget to its [launcher](#collapsing-to-the-launcher) (a rail under `placement="sidebar"`, the header bar under `embedded`). Persisted per tab. `placement="page"` has no collapsed state and ignores it. |
|
|
211
|
+
| `collapse-to` | — | What the panel collapses to: `auto` (the default; absent or any other value reads the same) leaves every placement as it is, `bar` draws a strip along the bottom edge in place of the round launcher, `none` hides the collapsed widget so the host's own control brings it back. Live. See [Collapsing to a bottom bar](#collapsing-to-a-bottom-bar). |
|
|
212
|
+
| `anchor` | `anchor` | Under `collapse-to="none"`, a selector for the host's element the panel rises from, right-aligned to it. The `anchor` property takes an element instead and wins over the attribute. Live. |
|
|
209
213
|
| `data-dragging` | — | **Written by the element, not by you.** Stamped on whichever handle a gesture is currently using, so the styles can react and so the element knows not to re-place the widget under a drag in progress. Cleared on `pointerup` and on `pointercancel`. |
|
|
210
214
|
| `data-expand-corner` | — | **Written by the element, not by you.** It stamps the corner a dragged or agent-moved panel opens from, so the collapse animation starts where the panel actually is. Listed because the element reads its own stamp back; setting it yourself is overwritten on the next move. |
|
|
211
215
|
| `data-greeting` | — | CSS-only: `off` turns the [greeting layout](#the-greeting-on-an-empty-page) off under `placement="page"`, where it is on by default. Any other value turns it on under `placement="embedded"`. No other placement has it. |
|
|
212
216
|
| `data-empty` | — | **Written by the element, not by you.** Present while the conversation has nothing in it, which is when the greeting shows. Public as a styling hook, so the chrome around a full-page chat can react to the same state, e.g. `ag-ui-chat[data-empty] ~ .page-footer { display: none }`. |
|
|
217
|
+
| `data-running` | — | **Written by the element, not by you.** Present while an interaction is in flight, the same state that shows the Stop button (see the `running` property). Public as a styling hook, as `data-empty` is, so the chrome around the chat can react to it, e.g. `ag-ui-chat[data-running] ~ .toolbar button { pointer-events: none }`. |
|
|
213
218
|
| `data-small-viewport` | — | CSS-only: `off` keeps the desktop layout at every width, opting out of the [small-viewport override](#small-viewports). Everything that override sets is a token you can re-state; its trigger is a media query, which is the one thing you cannot. |
|
|
214
219
|
| `data-paste-attach` | — | When to turn a long text paste into an attachment instead of composer text: absent for the 5000-character default, `off` to never, or a positive number of characters. Only acts where `data-attachments-url` (or a custom `uploadHandler`) gives it somewhere to go. |
|
|
215
220
|
| `data-starters` | — | JSON array of prompts offered on an empty transcript, e.g. `'["Summarise this page"]'`. Fallback content for `slot="empty"`, so slotting your own replaces them. Shares the four-prompt and 120-character limits with the suggestion chips a run pushes. Read once at connect. |
|
|
@@ -233,7 +238,7 @@ same way: `icon-send`, `icon-stop`, `icon-attach`, `icon-voice`.
|
|
|
233
238
|
|
|
234
239
|
The element observes two groups of attributes, and they behave differently once it is in the DOM.
|
|
235
240
|
Nothing outside those groups is observed: a CSS-only attribute (`theme`, `density`, `data-side`,
|
|
236
|
-
`data-answer-well`) is read by the stylesheet rather than by script, and `endpoint`,
|
|
241
|
+
`data-answer-well`, `data-tool-group-display`) is read by the stylesheet rather than by script, and `endpoint`,
|
|
237
242
|
`data-tool-display`, `data-text-animation`, `data-runs-url`, `data-page-actions`,
|
|
238
243
|
`data-message-actions`, `data-max-tool-rounds`, `data-unread-badge`, `data-launcher-drag` and
|
|
239
244
|
`data-quote-selection` are re-read at each use, so a late write to any of those simply takes effect. The one attribute in
|
|
@@ -241,7 +246,7 @@ neither camp is `data-launcher-icon-url`: it is read while the element connects,
|
|
|
241
246
|
below, but is not observed, so a late write is inert and says nothing.
|
|
242
247
|
|
|
243
248
|
**Live attributes.** Written at any time, before or after the element connects, and acted on
|
|
244
|
-
either way: `title-text`, `placement`, `credentials`, `user-key`, `user-name`.
|
|
249
|
+
either way: `title-text`, `placement`, `collapse-to`, `anchor`, `credentials`, `user-key`, `user-name`.
|
|
245
250
|
|
|
246
251
|
**Connect-time attributes.** Read once, while the element connects, to decide what chrome exists at
|
|
247
252
|
all — the tray, the mic, the skills menu, the header mark. Writing one afterwards has **no effect**;
|
|
@@ -264,8 +269,8 @@ element after the fact.
|
|
|
264
269
|
`approveWithEdits`, `agentFactory`, `getTools`, `getContext`, `routeMap`, `navigate`, `getPageMap`,
|
|
265
270
|
`autoInjectPageMap`, `conversationStore`, `uploadHandler`, `transcribeHandler`, `navigationResult`,
|
|
266
271
|
`skillContext`, `toolSummaries`, `formatToolPayload`, `formatRelativeTime`, `strings`,
|
|
267
|
-
`resolvePageTarget`, `sharedState`, `extraStyles` ([unstable](#d-extrastyles-the-last-mile)), plus the read-only `unread` and `
|
|
268
|
-
the attribute mirrors `endpoint` / `userKey` / `userName` / `toolDisplay` / `collapsed` /
|
|
272
|
+
`resolvePageTarget`, `sharedState`, `anchor` (an element, which wins over the attribute's selector), `extraStyles` ([unstable](#d-extrastyles-the-last-mile)), plus the read-only `unread`, `unhandledActivityTypes`, `threadId`, `running` and `barHeight`, and
|
|
273
|
+
the attribute mirrors `endpoint` / `userKey` / `userName` / `toolDisplay` / `toolGroupDisplay` / `collapsed` /
|
|
269
274
|
`credentials`.
|
|
270
275
|
|
|
271
276
|
`headers` and `getHeaders` authenticate **every** request the element makes, not only the agent
|
|
@@ -289,7 +294,8 @@ labels are fetched automatically — per card, `x-summary` → an explicit
|
|
|
289
294
|
`sharedState` is AG-UI shared state, documented under
|
|
290
295
|
[the run loop](#the-run-loop-and-the-ag-ui-client); `unread` and `unhandledActivityTypes` are
|
|
291
296
|
read-only counters, covered under [the unread badge](#the-unread-badge) and
|
|
292
|
-
[finding out what arrived](#finding-out-what-arrived)
|
|
297
|
+
[finding out what arrived](#finding-out-what-arrived); `threadId` and `running` are covered under
|
|
298
|
+
[driving the conversation from your own chrome](#driving-the-conversation-from-your-own-chrome).
|
|
293
299
|
|
|
294
300
|
Code blocks in an agent's answer carry a **copy button**, revealed on hover or
|
|
295
301
|
keyboard focus and styleable via the `code-copy` part. Override its labels with
|
|
@@ -298,14 +304,17 @@ the `copyCode` / `copied` / `copyFailed` strings.
|
|
|
298
304
|
**Methods**: `registerTool`, `registerPageState`, `registerActivityRenderer`, `setSkills`,
|
|
299
305
|
`sendMessage`, `attachFile`, `appendMessage`, `retryLastTurn`, `quote`, `offerQuoteInPage`,
|
|
300
306
|
`enableCharts`, `newChat`, `setCollapsed`, `toggleCollapsed`, `describeSurface`, `moveTo`,
|
|
301
|
-
`toggleTheme`, `openThreads`, `closeThreads`,
|
|
307
|
+
`resetSize`, `toggleTheme`, `openThreads`, `closeThreads`, `switchThread`, `deleteThread`,
|
|
302
308
|
`openCheckpoints`, `closeCheckpoints`, `toggleCheckpoints`, `reload`, and the deprecated
|
|
303
309
|
`registerStateHook` (renamed to `registerPageState`).
|
|
304
310
|
|
|
305
311
|
### Sending from your own UI
|
|
306
312
|
|
|
307
313
|
`sendMessage(content, attachments?)` sends as if the user had typed it — user bubble,
|
|
308
|
-
`ag-ui-submit` event, run started.
|
|
314
|
+
`ag-ui-submit` event, run started. `ag-ui-submit` means a turn was sent, not that a run started:
|
|
315
|
+
a Retry and a run continued from the checkpoint panel start runs without one. To know whether
|
|
316
|
+
anything is running, read [`running`](#driving-the-conversation-from-your-own-chrome) or style on
|
|
317
|
+
`data-running`. Use it for an "Ask about this order" button, a command
|
|
309
318
|
palette, a prompt fired when your page mounts the chat, or a composer of your own replacing the
|
|
310
319
|
built-in one.
|
|
311
320
|
|
|
@@ -960,8 +969,8 @@ human-readable speed (configurable; pass small/zero durations in tests):
|
|
|
960
969
|
paints outside the border box and any `overflow: hidden` ancestor sharing the element's box (a
|
|
961
970
|
card, a table cell) clips it away entirely. It holds for **1200 ms** by default and fades out
|
|
962
971
|
over the last third — a 200 ms blink is not long enough to be *found* by someone who does not
|
|
963
|
-
yet know where to look. The colour
|
|
964
|
-
|
|
972
|
+
yet know where to look. The colour is `color` when passed, else — see
|
|
973
|
+
[Ring colour](#ring-colour) — the widget's own accent.
|
|
965
974
|
`flash` leaves focus alone; `focusWithFlash` moves it — see "Flash versus focus" below.
|
|
966
975
|
- `prefersReducedMotion()` — honoured by every primitive that *moves* something: the hold delays
|
|
967
976
|
in `pressThenClick` / `selectOption` / `toggleControl` collapse to instant, `scrollIntoCenterView`
|
|
@@ -999,11 +1008,13 @@ operations a tool handler typically wants:
|
|
|
999
1008
|
**Themed from the element you point at, not from the widget.** The overlay is appended to the
|
|
1000
1009
|
document body so it can escape the clipping it exists to avoid, which means a `var()` in its own
|
|
1001
1010
|
style would resolve against the body — so every token is read from the *target's* computed style
|
|
1002
|
-
instead
|
|
1003
|
-
|
|
1011
|
+
instead. Set them wherever they inherit to the elements the agent touches, usually `:root`. The
|
|
1012
|
+
ring colour is the one exception, read from the widget as well; see
|
|
1013
|
+
[Ring colour](#ring-colour).
|
|
1004
1014
|
|
|
1005
1015
|
```css
|
|
1006
1016
|
:root {
|
|
1017
|
+
--ag-ui-highlight-ring-color: #0f766e; /* also read from ag-ui-chat; see Ring colour */
|
|
1007
1018
|
--ag-ui-highlight-scrim: rgba(15, 15, 25, 0.45);
|
|
1008
1019
|
--ag-ui-highlight-gradient: linear-gradient(115deg, transparent 20%, #4f46e5 50%, transparent 80%);
|
|
1009
1020
|
--ag-ui-highlight-ring-width: 3; /* unitless; px */
|
|
@@ -1047,6 +1058,39 @@ register the change.
|
|
|
1047
1058
|
Each takes an element the caller has already located; host packages wrap them with
|
|
1048
1059
|
environment-aware lookups (e.g. "find `#id_<name>`, then `fillField`").
|
|
1049
1060
|
|
|
1061
|
+
#### Ring colour
|
|
1062
|
+
|
|
1063
|
+
Every ring the driver draws — the flash outline, the overlay ring, the press and toggle halo — is
|
|
1064
|
+
drawn in the host's page, outside the widget, so a token set on `ag-ui-chat` never reaches it
|
|
1065
|
+
through the cascade. The driver reads the widget directly instead, so on a page that themes
|
|
1066
|
+
nothing the rings follow the widget's theme: Quiet's near-black, Soft's violet, the dark half in a
|
|
1067
|
+
dark scheme. When a call passes no `color`, the first of these that is set wins:
|
|
1068
|
+
|
|
1069
|
+
1. `--ag-ui-highlight-ring-color` on the target (so `:root` reaches every ring);
|
|
1070
|
+
2. `--ag-ui-highlight-ring-color` on the chat — on `ag-ui-chat` or anything above it;
|
|
1071
|
+
3. the target's `--ag-ui-accent`, so a page that themes its accent keeps the rings it has;
|
|
1072
|
+
4. the chat's resolved accent, its theme's default included, held to 3:1 against the page (below);
|
|
1073
|
+
5. the package indigo, when no chat is on the page at all.
|
|
1074
|
+
|
|
1075
|
+
The chat's own accent follows the widget's scheme, not the page's, so a dark widget's near-white
|
|
1076
|
+
accent would all but vanish on a light page. When the ring falls to step 4 it is measured against
|
|
1077
|
+
**the surface behind the target**: the background of the target's parent, and of each element
|
|
1078
|
+
above it until one is opaque, composited over the page canvas (which follows the root's
|
|
1079
|
+
`color-scheme`). The target's own fill is not that surface, because the ring is drawn outside its
|
|
1080
|
+
box: a white field on a dark page is ringed on the dark page. Background images are not read. The
|
|
1081
|
+
ring takes the first of these that holds 3:1 there (WCAG 2.4.13): the accent as the chat resolves
|
|
1082
|
+
it, the other half of the chat's `light-dark()` pair, or the accent stepped toward black or white.
|
|
1083
|
+
Steps 1 to 3 are a host's own choice and are drawn as given, contrast or not.
|
|
1084
|
+
|
|
1085
|
+
```css
|
|
1086
|
+
/* Rings in the brand colour, whatever the widget's accent. */
|
|
1087
|
+
ag-ui-chat { --ag-ui-highlight-ring-color: #0f766e; }
|
|
1088
|
+
```
|
|
1089
|
+
|
|
1090
|
+
The halo of `pressThenClick` and `toggleControl` is the chosen colour at 40%. "The chat" is the
|
|
1091
|
+
most recently connected `<ag-ui-chat>`; on a page with two, pass the one acting as the `chat`
|
|
1092
|
+
option (`RingOwnerOptions`, which every ring-drawing primitive and `showHighlightOverlay` take).
|
|
1093
|
+
|
|
1050
1094
|
### Page-action tools
|
|
1051
1095
|
|
|
1052
1096
|
Two built-in client tools let the agent perform common page interactions without every host
|
|
@@ -1130,14 +1174,19 @@ matching JS API:
|
|
|
1130
1174
|
widget is collapsed, and the page is not scrolled to it. A restore still loading or replaying
|
|
1131
1175
|
the conversation being left stops there, so nothing of it is drawn into the new chat, and a
|
|
1132
1176
|
run it was about to resume after a reload is not resumed: coming back to that conversation
|
|
1133
|
-
later answers the interrupted call as not finished.
|
|
1177
|
+
later answers the interrupted call as not finished. Called before the element connects (or while
|
|
1178
|
+
it is out of the document), it waits: `threadId` stays `null` and nothing fires until the
|
|
1179
|
+
element connects, which then starts the new chat, so the one `ag-ui-thread` event is a `new`.
|
|
1134
1180
|
- `describeSurface()` — where the panel is and what can be done to it: placement, collapsed,
|
|
1135
|
-
whether it can be moved, whether it fills the screen, its box and the viewport. `movable` folds
|
|
1181
|
+
what it collapses to (`collapseTo`), whether it can be moved, whether it fills the screen, its box and the viewport. `movable` folds
|
|
1136
1182
|
the two reasons a move can fail into the one answer a caller needs.
|
|
1137
1183
|
- `moveTo(corner)` — send the panel to `top-left` / `top-right` / `bottom-left` / `bottom-right`,
|
|
1138
1184
|
returning whether it went. It takes the axes the same way a user drag does, so the launcher
|
|
1139
1185
|
travels with it and switching placement hands them back. Returns `false` rather than pretending
|
|
1140
1186
|
when the placement owns its position or the panel fills the screen.
|
|
1187
|
+
- `resetSize()` — drop a size the user dragged, and its stored copy, so the placement's own
|
|
1188
|
+
size and your `--ag-ui-width` / `--ag-ui-height` apply again. For a host that enters a sized
|
|
1189
|
+
state of its own (an expanded mode): a user's drag outranks host tokens, so call this first.
|
|
1141
1190
|
- `setCollapsed(collapsed)` / `toggleCollapsed()` — collapse or expand the widget. The state is
|
|
1142
1191
|
reflected as the boolean `collapsed` attribute/property and persisted per-tab in
|
|
1143
1192
|
`sessionStorage`, so it survives a reload.
|
|
@@ -1152,6 +1201,51 @@ chat.toggleCollapsed();
|
|
|
1152
1201
|
chat.addEventListener("ag-ui-toggle", (e) => console.log(e.detail.collapsed));
|
|
1153
1202
|
```
|
|
1154
1203
|
|
|
1204
|
+
### Driving the conversation from your own chrome
|
|
1205
|
+
|
|
1206
|
+
A host that lists conversations in its own bar, rather than in the built-in drawer, drives the
|
|
1207
|
+
one on screen with the drawer's own paths:
|
|
1208
|
+
|
|
1209
|
+
- `switchThread(threadId)` — put a stored thread on screen and replay it, as picking its row in
|
|
1210
|
+
the drawer does. Returns a `Promise<void>` that resolves once the thread is drawn. **A run in
|
|
1211
|
+
flight is cancelled**, as the drawer and `newChat()` cancel it; read `running` first if you
|
|
1212
|
+
would rather wait. Switching to the thread already on screen does nothing, and so does a call
|
|
1213
|
+
before the element connects; a second call for the thread that is still loading settles with
|
|
1214
|
+
that load, after the replay. If the store rejects the load, the element stays on the thread it
|
|
1215
|
+
was on, redraws it, fires no `ag-ui-thread`, and the promise rejects with the store's error.
|
|
1216
|
+
- `deleteThread(threadId)` — delete a stored thread, as the drawer row's delete does. Deleting
|
|
1217
|
+
the thread on screen cancels its run and puts a fresh thread in its place; deleting another
|
|
1218
|
+
leaves the screen alone. Prefer it to `conversationStore.clear()`, which deletes the record and
|
|
1219
|
+
nothing else: the run, the transcript and the drawer are left pointing at it.
|
|
1220
|
+
- `threadId` *(read-only)* — the thread on screen, `null` before the element first connects.
|
|
1221
|
+
It only reads. `conversationStore.threadId()` mints and stores a thread when the store points
|
|
1222
|
+
at none, so asking it which conversation is showing can start one.
|
|
1223
|
+
- `running` *(read-only)* — whether an interaction is in flight: the composer's own state, the
|
|
1224
|
+
one it shows Stop for, across every tool round, a Retry and a checkpoint continuation as well
|
|
1225
|
+
as a send. Reflected on the element as the `data-running` attribute, written by the element
|
|
1226
|
+
rather than by you, as `data-empty` is, so the chrome around the chat can style on it.
|
|
1227
|
+
|
|
1228
|
+
Every change of conversation fires one **`ag-ui-thread`** event (the `THREAD_EVENT` constant),
|
|
1229
|
+
after the transcript has been replaced, so a listener reads the conversation it is told about.
|
|
1230
|
+
`detail` is `{ threadId, previousThreadId, reason }` (typed `ThreadDetail`). `previousThreadId`
|
|
1231
|
+
is the thread the previous event reported, `null` before the first, and `reason` is one of:
|
|
1232
|
+
|
|
1233
|
+
| `reason` | When |
|
|
1234
|
+
| --- | --- |
|
|
1235
|
+
| `new` | `newChat()` or the built-in New chat button. |
|
|
1236
|
+
| `switch` | `switchThread()` or a row picked in the drawer. Two switches made before the first had replayed report only the second. |
|
|
1237
|
+
| `delete` | The thread on screen was deleted, and a fresh one took its place. |
|
|
1238
|
+
| `restore` | The stored thread was replayed: when the element connects (`previousThreadId` is `null` the first time), or by `reload()`. |
|
|
1239
|
+
| `rescope` | A `user-key` change handed the element to another principal, live or while it was out of the document. |
|
|
1240
|
+
|
|
1241
|
+
A page reload keeps restoring the thread, as [MPA durability](#mpa-durability-surviving-full-page-reloads) describes, and
|
|
1242
|
+
reports it as `restore`. Ignore a `reason` you do not know: more may be added.
|
|
1243
|
+
|
|
1244
|
+
```js
|
|
1245
|
+
chat.addEventListener("ag-ui-thread", (e) => myBar.markActive(e.detail.threadId));
|
|
1246
|
+
myBar.onPick = (threadId) => chat.switchThread(threadId);
|
|
1247
|
+
```
|
|
1248
|
+
|
|
1155
1249
|
### The composer's own keys
|
|
1156
1250
|
|
|
1157
1251
|
**Enter during a run queues.** A second run cannot start while one is in flight —
|
|
@@ -1306,6 +1400,105 @@ ag-ui-chat {
|
|
|
1306
1400
|
}
|
|
1307
1401
|
```
|
|
1308
1402
|
|
|
1403
|
+
### Collapsing to a bottom bar
|
|
1404
|
+
|
|
1405
|
+
`collapse-to` chooses what a collapsed panel becomes, for a host whose layout has a bottom
|
|
1406
|
+
toolbar. It is opt-in: absent, `auto`, or any other value leaves every placement as the
|
|
1407
|
+
sections above describe. It is live, like `placement`.
|
|
1408
|
+
|
|
1409
|
+
- **`bar`: the component's own bar.** A strip along the whole bottom edge of the viewport, in
|
|
1410
|
+
place of the round launcher: the title, the [unread badge](#the-unread-badge), and a running
|
|
1411
|
+
indicator while an interaction is in flight. Pressing the strip toggles the panel, which rises
|
|
1412
|
+
from the bar's right end with the bar still beneath it as the minimise target. The bar's
|
|
1413
|
+
history button opens the conversation list as a popover above the bar, without expanding the
|
|
1414
|
+
panel, its outer edge in line with the panel's on a wide viewport, and a second press closes
|
|
1415
|
+
it; `openThreads()` while collapsed opens it too. Expanding the panel closes the popover, so the
|
|
1416
|
+
panel opens on the conversation. It replaces the launcher only, so it applies to the corner
|
|
1417
|
+
placements, `side` and `full`: `sidebar` keeps its rail, `embedded` its header bar, and `page`
|
|
1418
|
+
has no collapsed state at all.
|
|
1419
|
+
- **`none`: your own bar.** Collapsed is hidden: nothing of the widget is left to see or hit,
|
|
1420
|
+
under every collapsible placement. Your bar's button drives the [public
|
|
1421
|
+
API](#driving-the-conversation-from-your-own-chrome) (`collapsed`, `toggleCollapsed()`), and
|
|
1422
|
+
`anchor` names the element the panel rises from, right-aligned to it. An anchor that resolves
|
|
1423
|
+
to nothing opens the panel from the placement's own corner, with one console warning.
|
|
1424
|
+
|
|
1425
|
+
```html
|
|
1426
|
+
<nav class="toolbar">
|
|
1427
|
+
<!-- ... -->
|
|
1428
|
+
<button id="agent-button" type="button">Agent</button>
|
|
1429
|
+
</nav>
|
|
1430
|
+
<ag-ui-chat endpoint="/agent/" collapse-to="none" anchor="#agent-button"></ag-ui-chat>
|
|
1431
|
+
<script type="module">
|
|
1432
|
+
const chat = document.querySelector("ag-ui-chat");
|
|
1433
|
+
const button = document.getElementById("agent-button");
|
|
1434
|
+
button.addEventListener("click", () => chat.toggleCollapsed());
|
|
1435
|
+
// Under none the element announces the state it mounted in, once, so the
|
|
1436
|
+
// button can be labelled before anyone presses it.
|
|
1437
|
+
chat.addEventListener("ag-ui-toggle", (e) => {
|
|
1438
|
+
button.setAttribute("aria-pressed", String(!e.detail.collapsed));
|
|
1439
|
+
});
|
|
1440
|
+
</script>
|
|
1441
|
+
```
|
|
1442
|
+
|
|
1443
|
+
**Clearing your toolbar.** Under `none` the panel stands `--ag-ui-anchor-gap` (default `8px`)
|
|
1444
|
+
above the anchor's top edge. The anchor is the button, not the toolbar around it, so a button
|
|
1445
|
+
sitting inside a taller toolbar puts the panel's foot across the toolbar's top border. Set the gap
|
|
1446
|
+
to the button's distance from the toolbar's top plus the clearance you want:
|
|
1447
|
+
|
|
1448
|
+
```css
|
|
1449
|
+
/* The button stands 7px below the toolbar's top edge; clear it by 8px. */
|
|
1450
|
+
ag-ui-chat {
|
|
1451
|
+
--ag-ui-anchor-gap: 15px;
|
|
1452
|
+
}
|
|
1453
|
+
```
|
|
1454
|
+
|
|
1455
|
+
A gap wider than the gutter is taken off the panel's max height as well, so a tall panel still
|
|
1456
|
+
stops at the top of the window.
|
|
1457
|
+
|
|
1458
|
+
Under `none` the element dispatches `ag-ui-toggle` once as it connects, with whichever state it
|
|
1459
|
+
mounted in, collapsed or open. Under `auto` and `bar` it does not, as before. That event touches
|
|
1460
|
+
neither the stored state nor the unread count.
|
|
1461
|
+
|
|
1462
|
+
**The page's space is yours.** The bar is fixed over the page, so a host pads its own page by
|
|
1463
|
+
the bar's height. The component never writes your CSS, and a custom property cannot carry the
|
|
1464
|
+
height up to your page (it inherits down, never up), so it hands you a number:
|
|
1465
|
+
`barHeight` (CSS px, read-only) and an `ag-ui-bar-height` event (the `BAR_HEIGHT_EVENT`
|
|
1466
|
+
constant, detail `{ height }`) on every change, including a font-size change. Both read `0`
|
|
1467
|
+
where no bar is drawn: under `auto` and `none`, and on a phone while the panel is open.
|
|
1468
|
+
|
|
1469
|
+
```js
|
|
1470
|
+
const chat = document.querySelector("ag-ui-chat");
|
|
1471
|
+
const pad = () => {
|
|
1472
|
+
document.documentElement.style.setProperty("--chat-bar-height", `${chat.barHeight}px`);
|
|
1473
|
+
};
|
|
1474
|
+
chat.addEventListener("ag-ui-bar-height", pad);
|
|
1475
|
+
pad();
|
|
1476
|
+
```
|
|
1477
|
+
|
|
1478
|
+
```css
|
|
1479
|
+
body {
|
|
1480
|
+
padding-bottom: var(--chat-bar-height, 0px);
|
|
1481
|
+
}
|
|
1482
|
+
```
|
|
1483
|
+
|
|
1484
|
+
**No inset needed.** Under `bar` and `none` you do not set `--ag-ui-inset` to keep the panel off
|
|
1485
|
+
your toolbar: its max height is the viewport less the bar's height (or, under `none`, the
|
|
1486
|
+
distance to the anchor's top) and one gutter, and its bottom sits on the bar or the anchor.
|
|
1487
|
+
|
|
1488
|
+
**Docked means not moved.** A docked panel cannot be dragged by its header or launcher, and
|
|
1489
|
+
`moveTo` refuses, because a position the user chose would take it away from the bar or the
|
|
1490
|
+
anchor. Resizing still works on wide viewports: the edges standing on the bar or the anchor
|
|
1491
|
+
stay put and the free ones follow the grip, and `resetSize()` still drops the dragged size.
|
|
1492
|
+
|
|
1493
|
+
**Phones.** At 600px or less the open panel stays full-bleed, over the bar, and the header's
|
|
1494
|
+
minimise control is the way back; the bar shows only while collapsed, so no second strip sits
|
|
1495
|
+
at the bottom edge while the keyboard is up.
|
|
1496
|
+
|
|
1497
|
+
The bar is styled through the parts `bar` (the strip's wrapper, holding the launcher and the
|
|
1498
|
+
history button) and `bar-history`, and the launcher's own parts (`launcher`, `rail-label`,
|
|
1499
|
+
`launcher-badge`) inside it.
|
|
1500
|
+
|
|
1501
|
+
|
|
1309
1502
|
---
|
|
1310
1503
|
|
|
1311
1504
|
## Charts
|
|
@@ -1481,7 +1674,7 @@ absent or unknown value reads as `grouped`):
|
|
|
1481
1674
|
|
|
1482
1675
|
- `grouped` — the default. A run's consecutive tool calls fold into one quiet row, **"Worked
|
|
1483
1676
|
through 5 steps"**, with a note such as **"1 failed"** beside it, and the calls one click down
|
|
1484
|
-
as `full` cards. Anything else in the turn (text, a confirmation, a question) ends the group, and
|
|
1677
|
+
as `full` cards, or in the mode `data-tool-group-display` names. Anything else in the turn (text, a confirmation, a question) ends the group, and
|
|
1485
1678
|
the next call starts a new one; a call's own rendered output does not. A group of one call shows that call's own label. See
|
|
1486
1679
|
[The step group](#the-step-group).
|
|
1487
1680
|
- `inline` — the lightest mode: a single status row (icon + summary, no card chrome) with the
|
|
@@ -1498,6 +1691,16 @@ never run together into one block, so where the call ends and the answer begins
|
|
|
1498
1691
|
visible. Style them via the `tool-card-args` / `tool-card-result` parts, their headings via
|
|
1499
1692
|
`tool-card-section-label`, and the whole body via `tool-card-body`.
|
|
1500
1693
|
|
|
1694
|
+
**A card names its status as a part.** `::part()` takes no attribute selector, so a rule on
|
|
1695
|
+
`tool-card-status` reaches every outcome alike. The card and its status pill each carry a modifier
|
|
1696
|
+
beside the base part, one of `pending`, `deferred`, `done`, `error`, `declined` or `interrupted`,
|
|
1697
|
+
and it is replaced whenever the status changes:
|
|
1698
|
+
|
|
1699
|
+
```css
|
|
1700
|
+
ag-ui-chat::part(tool-card-error) { border-color: crimson; }
|
|
1701
|
+
ag-ui-chat::part(tool-card-status-error) { font-weight: 700; }
|
|
1702
|
+
```
|
|
1703
|
+
|
|
1501
1704
|
**The attribute is live.** Changing `data-tool-display` between the four card modes restyles every
|
|
1502
1705
|
card already in the transcript, the way `data-answer-well` does — the modes are pure visibility
|
|
1503
1706
|
over one DOM shape, selected by the shadow CSS from the host attribute. Grouping is decided as
|
|
@@ -1505,6 +1708,25 @@ each card is built: switching **to** `grouped` folds only the calls drawn afterw
|
|
|
1505
1708
|
switching **away** from it flattens the groups already drawn, by CSS, into exactly the cards the
|
|
1506
1709
|
new mode builds (the group stops generating a box and its row is hidden).
|
|
1507
1710
|
|
|
1711
|
+
### Choosing how a group draws its calls
|
|
1712
|
+
|
|
1713
|
+
Under `grouped`, an opened group draws its calls as `full` cards unless the
|
|
1714
|
+
`data-tool-group-display` attribute (or `toolGroupDisplay` property) names another of the card
|
|
1715
|
+
modes: `compact`, `minimal` or `inline`. Each draws the regions the flat card of that mode draws,
|
|
1716
|
+
laid out as a row of the group's list rather than as a boxed card. An absent or unknown value
|
|
1717
|
+
reads as `full`, so nothing changes for a host that does not set it.
|
|
1718
|
+
|
|
1719
|
+
```html
|
|
1720
|
+
<ag-ui-chat endpoint="/agent/" data-tool-group-display="compact"></ag-ui-chat>
|
|
1721
|
+
```
|
|
1722
|
+
|
|
1723
|
+
It is read only under `grouped`. Under one of the four card modes the groups are flattened into
|
|
1724
|
+
that mode's cards and the inner value is ignored; switching back to `grouped` applies it again.
|
|
1725
|
+
It is live like the outer attribute: changing it restyles groups already in the transcript.
|
|
1726
|
+
|
|
1727
|
+
A call waiting on an approval shows its arguments and its Approve and Deny buttons in every inner
|
|
1728
|
+
mode, as it does in every card mode, and Approve takes focus when the group opens for it.
|
|
1729
|
+
|
|
1508
1730
|
### The step group
|
|
1509
1731
|
|
|
1510
1732
|
Under `grouped` the row reads, by state:
|
|
@@ -1536,7 +1758,8 @@ steps and `data-open` whether the cards are showing; the head is a button with `
|
|
|
1536
1758
|
order, rather than inside it, so a chart is never one click down. It does not end the group: a
|
|
1537
1759
|
later call joins the group above it, which is also how a restored conversation draws the run.
|
|
1538
1760
|
|
|
1539
|
-
Parts: `tool-group
|
|
1761
|
+
Parts: `tool-group` (with the state beside it as `tool-group-waiting`, `tool-group-running`,
|
|
1762
|
+
`tool-group-done` or `tool-group-error`), `tool-group-head` (the button), `tool-group-icon`, `tool-group-label`,
|
|
1540
1763
|
`tool-group-meta` (holding one `.tool-group-note` per note), `tool-group-list` (the cards), and
|
|
1541
1764
|
`tool-card-repeat` on a repeated step. The focus ring is `--ag-ui-ring` and the disclosure chevron
|
|
1542
1765
|
`--ag-ui-ico-chevron`. Strings (`strings` / `data-strings`): `toolGroupSteps`,
|
|
@@ -1722,11 +1945,30 @@ and which grip carries the keyboard.
|
|
|
1722
1945
|
|
|
1723
1946
|
### Sizes, keyboard, and parts
|
|
1724
1947
|
|
|
1725
|
-
A drag writes `--
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1948
|
+
A drag writes the private `--_drag-width` / `--_drag-height` on the host, not
|
|
1949
|
+
your `--ag-ui-width` / `--ag-ui-height` tokens, which stay yours. The precedence
|
|
1950
|
+
is:
|
|
1951
|
+
|
|
1952
|
+
- **Above 600px**, the dragged size beats a host's `--ag-ui-width` /
|
|
1953
|
+
`--ag-ui-height`, `!important` included, so a user who resized the panel keeps
|
|
1954
|
+
their size. A host that enters a sized state of its own (an "expanded" class,
|
|
1955
|
+
a mode switch) calls `resetSize()` when it does, which drops the dragged size
|
|
1956
|
+
and its stored copy and hands control back to the host tokens. A host with no
|
|
1957
|
+
such state needs nothing.
|
|
1958
|
+
- **At 600px or less**, the small-viewport shape ignores the dragged size
|
|
1959
|
+
entirely, for the placements that block covers (`floating`, `bottom-left`,
|
|
1960
|
+
`sidebar`, `side` and the default): the panel is full-bleed whatever was
|
|
1961
|
+
dragged or stored, and a window narrowed after a wide-window drag goes
|
|
1962
|
+
full-bleed too. `page` is already that shape, and `embedded` is left to the
|
|
1963
|
+
host's own box, so neither is touched by the block. `data-small-viewport="off"`
|
|
1964
|
+
keeps a dragged size at every width on the covered placements.
|
|
1965
|
+
|
|
1966
|
+
A dragged size is a private property, so a host should not read it back from
|
|
1967
|
+
the element's inline style; use `getBoundingClientRect()`, or `resetSize()` to
|
|
1968
|
+
clear it.
|
|
1969
|
+
|
|
1970
|
+
**A custom property alone does not leave placement in charge** — an inline custom
|
|
1971
|
+
property still outranks a `:host([placement=…])` rule setting the same property. So the
|
|
1730
1972
|
component enforces the split directly: **a placement owns the axes it fixes**,
|
|
1731
1973
|
and a dragged or persisted size is only ever applied to the ones it leaves free.
|
|
1732
1974
|
Switching placement hands the owned axes back. Without that, a height dragged
|
|
@@ -2450,8 +2692,10 @@ chat.navigate = (path) => router.push(path); // SPA: in-page, no reload
|
|
|
2450
2692
|
Route map + `navigate()` and the reload model are the same feature seen from two ends.
|
|
2451
2693
|
|
|
2452
2694
|
**`ag-ui-run-finished`** *(event)* — an interaction has ended, and here is what ran in it.
|
|
2453
|
-
`detail: { tools: readonly ToolRun[] }` (typed `RunFinishedDetail`), where
|
|
2454
|
-
`{ name, side: "server" | "client" }` in settle order.
|
|
2695
|
+
`detail: { threadId, tools: readonly ToolRun[], invalidated }` (typed `RunFinishedDetail`), where
|
|
2696
|
+
each `ToolRun` is `{ name, side: "server" | "client" }` in settle order. `threadId` is the thread
|
|
2697
|
+
the run belonged to, which is not always the one on screen: a run that a new chat or a thread
|
|
2698
|
+
switch stopped still reports once its request closes.
|
|
2455
2699
|
|
|
2456
2700
|
**This is the seam for a host that renders data the agent can change.** A server-side tool writes
|
|
2457
2701
|
without your page's knowledge: nothing else the element dispatches implies "something may have moved
|
|
@@ -2734,7 +2978,9 @@ re-export point. Internal modules import from leaf paths.
|
|
|
2734
2978
|
| `defineAgUiChat()` | function | Idempotently register the element. |
|
|
2735
2979
|
| `MessageRole` | type | Role of a rendered chat message. |
|
|
2736
2980
|
| `SubmitDetail` | type | `detail` shape of the submit event. |
|
|
2981
|
+
| `ThreadDetail` | type | `detail` shape of the `ag-ui-thread` event (`{ threadId, previousThreadId, reason }`). |
|
|
2737
2982
|
| `ToggleDetail` | type | `detail` shape of the `ag-ui-toggle` event (`{ collapsed }`). |
|
|
2983
|
+
| `BarHeightDetail` | type | `detail` shape of the `ag-ui-bar-height` event (`{ height }`). |
|
|
2738
2984
|
| `UnreadDetail` | type | `detail` shape of the `ag-ui-unread` event (`{ unread }`). |
|
|
2739
2985
|
| `AttachmentsDetail` | type | `detail` shape of the `ag-ui-attachments` event (`{ attachments, pending }`). |
|
|
2740
2986
|
| `StateDetail` | type | `detail` shape of the `ag-ui-state` event (`{ state }`). |
|
|
@@ -2767,7 +3013,7 @@ re-export point. Internal modules import from leaf paths.
|
|
|
2767
3013
|
| `PAGE_ACTIONS` | const | The page-action opt-in tokens (`scroll` / `drag`). |
|
|
2768
3014
|
| `createChatSurfaceTools(surface)` | function | Build the opt-in `read_chat_surface` / `move_chat` / `minimise_chat` / `restore_chat` tools, which let the agent move the panel it is speaking from. |
|
|
2769
3015
|
| `ChatSurface` | type | The narrow port those tools drive — `describeSurface` / `moveTo` / `setCollapsed`. The element satisfies it. |
|
|
2770
|
-
| `ChatSurfaceReport` | type | What `describeSurface()` answers: placement, collapsed, collapsible, movable, draggable, fullBleed, and the panel's box against the viewport it sits in. |
|
|
3016
|
+
| `ChatSurfaceReport` | type | What `describeSurface()` answers: placement, collapsed, collapseTo, collapsible, movable, draggable, fullBleed, and the panel's box against the viewport it sits in. |
|
|
2771
3017
|
| `ChatCorner` | type | `"top-left"` / `"top-right"` / `"bottom-left"` / `"bottom-right"` — the argument to `moveTo`. |
|
|
2772
3018
|
| `CHAT_CORNERS` | const | Those four, as a list. |
|
|
2773
3019
|
| `isChatCorner(value)` | function | Whether a string names one of them. |
|
|
@@ -2842,6 +3088,7 @@ re-export point. Internal modules import from leaf paths.
|
|
|
2842
3088
|
| --- | --- | --- |
|
|
2843
3089
|
| `ToolCallCard` | class | A live tool-call card for the transcript. |
|
|
2844
3090
|
| `ToolCallStatus` / `SettledStatus` / `ToolDisplayMode` | type | Card lifecycle states + display mode. |
|
|
3091
|
+
| `ToolGroupDisplayMode` | type | How an opened step group draws its calls (`TOOL_GROUP_DISPLAY`'s values). |
|
|
2845
3092
|
| `ToolPayloadFormatter` | type | Draws one region of a card's body (`AgUiChat.formatToolPayload`); `null` falls through to the built-in pretty-print. |
|
|
2846
3093
|
| `ToolPayload` | type | The region being drawn: `arguments` (the parsed record) or `result` (the raw string and its outcome). |
|
|
2847
3094
|
| `ToolCallCardOptions` | type | Per-card wiring beyond name / args / label / strings — currently `formatPayload`. |
|
|
@@ -2875,7 +3122,7 @@ re-export point. Internal modules import from leaf paths.
|
|
|
2875
3122
|
| `HighlightOverlayOptions` | type | Options for `showHighlightOverlay`. |
|
|
2876
3123
|
| `fillField` / `clickElement` / `pressButton` / `selectControl` / `setControlValue` / `toggleCheckbox` | function | DOM-driver primitives. |
|
|
2877
3124
|
| `setNativeValue` / `setNativeChecked` | function | Set a control via its native prototype setter (React-controlled inputs). |
|
|
2878
|
-
| `TypeOptions` / `HighlightClickOptions` / `PressOptions` / `SelectOptions` / `ToggleOptions` / `FlashOptions` / `ScrollOptions` / `FillFieldOptions` / `TextLikeElement` | type | Primitive option shapes. |
|
|
3125
|
+
| `TypeOptions` / `HighlightClickOptions` / `PressOptions` / `SelectOptions` / `ToggleOptions` / `FlashOptions` / `ScrollOptions` / `FillFieldOptions` / `TextLikeElement` / `RingOwnerOptions` | type | Primitive option shapes. `RingOwnerOptions` is the `chat` the ring-drawing ones share; see [Ring colour](#ring-colour). |
|
|
2879
3126
|
|
|
2880
3127
|
### Constants
|
|
2881
3128
|
|
|
@@ -2883,7 +3130,9 @@ re-export point. Internal modules import from leaf paths.
|
|
|
2883
3130
|
| --- | --- |
|
|
2884
3131
|
| `ELEMENT_TAG` | The registered tag name (`ag-ui-chat`). |
|
|
2885
3132
|
| `SUBMIT_EVENT` | The submit CustomEvent name. |
|
|
3133
|
+
| `THREAD_EVENT` | The conversation-changed CustomEvent name (`ag-ui-thread`). |
|
|
2886
3134
|
| `TOGGLE_EVENT` | The collapse-toggle CustomEvent name (`ag-ui-toggle`). |
|
|
3135
|
+
| `BAR_HEIGHT_EVENT` | The bottom bar's height CustomEvent name (`ag-ui-bar-height`). |
|
|
2887
3136
|
| `UNREAD_EVENT` | The unread-count CustomEvent name (`ag-ui-unread`). |
|
|
2888
3137
|
| `RUN_FINISHED_EVENT` | The interaction-finished CustomEvent name (`ag-ui-run-finished`). |
|
|
2889
3138
|
| `CUSTOM_AGENT_EVENT` | The agent-`CUSTOM` CustomEvent name (`ag-ui-custom`). |
|
|
@@ -2903,6 +3152,7 @@ re-export point. Internal modules import from leaf paths.
|
|
|
2903
3152
|
| `MESSAGE_ACTIONS` | The message-action tokens `data-message-actions` selects by (`copy` / `retry` / `feedback`). |
|
|
2904
3153
|
| `TOOL_CALL_STATUS` | Tool-call card status constants. |
|
|
2905
3154
|
| `TOOL_DISPLAY` | Tool-call display-mode constants (`inline` / `minimal` / `compact` / `full`). |
|
|
3155
|
+
| `TOOL_GROUP_DISPLAY` | How an opened step group draws its calls under `grouped` (`inline` / `minimal` / `compact` / `full`). |
|
|
2906
3156
|
| `TOOL_OUTCOME` | How a tool call ended, as a server states it on `TOOL_CALL_RESULT` (`success` / `failed` / `denied`). |
|
|
2907
3157
|
| `X_CONFIRM_KEY` | Confirmation-prompt key: on a tool's JSON Schema for a client-side confirmation, and in an AG-UI interrupt's `metadata` for a server-side approval. |
|
|
2908
3158
|
| `X_SUMMARY_KEY` | JSON-Schema key carrying a short tool-card label. |
|
|
@@ -3014,11 +3264,20 @@ first, so each stays an override point. The tokens the themes add:
|
|
|
3014
3264
|
- **Charts:** `--ag-ui-chart-1` to `--ag-ui-chart-6`. A host's value beats the theme's.
|
|
3015
3265
|
- **Status marks:** `--ag-ui-ico-check`, `--ag-ui-ico-error`, `--ag-ui-ico-declined`, mask images
|
|
3016
3266
|
drawn in the state's colour, and `--ag-ui-ico-chevron`, the step group's disclosure chevron.
|
|
3017
|
-
- **Focus:** `--ag-ui-ring`, the step group head's focus outline
|
|
3267
|
+
- **Focus:** `--ag-ui-ring`, the step group head's focus outline. Unset, it is two parts accent
|
|
3268
|
+
to three parts ink (`--ag-ui-fg`), which holds 3:1 against the panel for any accent.
|
|
3018
3269
|
|
|
3019
3270
|
The font is part of the theme: Quiet, Soft and Ledger set their own stack (Inter, then the system
|
|
3020
|
-
UI font), and Classic inherits the page's font as the component always did.
|
|
3021
|
-
`--ag-ui-font
|
|
3271
|
+
UI font), and Classic inherits the page's font as the component always did. To take the page's font
|
|
3272
|
+
under any theme, set `--ag-ui-font` to the page's family, or to the page's own font token:
|
|
3273
|
+
|
|
3274
|
+
```css
|
|
3275
|
+
ag-ui-chat { --ag-ui-font: var(--body-font); } /* or the family itself */
|
|
3276
|
+
```
|
|
3277
|
+
|
|
3278
|
+
`--ag-ui-font: inherit` does not do this. A CSS-wide keyword in a custom property applies to the
|
|
3279
|
+
custom property itself, so it takes the `--ag-ui-font` of the parent, which nothing sets, and the
|
|
3280
|
+
theme's stack wins.
|
|
3022
3281
|
|
|
3023
3282
|
#### Text on the accent
|
|
3024
3283
|
|
|
@@ -3208,6 +3467,10 @@ keeps between itself and that box. The size cap subtracts the same one, so a
|
|
|
3208
3467
|
panel grown to its limit reaches the far edge of the usable box and no further —
|
|
3209
3468
|
set it to `0` for a panel flush against the corner.
|
|
3210
3469
|
|
|
3470
|
+
`--ag-ui-anchor-gap` (default `8px`) is the gap between the panel and the button
|
|
3471
|
+
it rises from under `collapse-to="none"`; see [Collapsing to a bottom
|
|
3472
|
+
bar](#collapsing-to-a-bottom-bar).
|
|
3473
|
+
|
|
3211
3474
|
`--ag-ui-keyboard-inset` overrides the lift an on-screen keyboard earns. The
|
|
3212
3475
|
widget measures the hidden band and publishes it as
|
|
3213
3476
|
`--ag-ui-visual-viewport-inset-bottom`; state this one instead to outrank that
|
|
@@ -3344,15 +3607,15 @@ component sets, so a new one cannot ship undocumented.
|
|
|
3344
3607
|
| --- | --- |
|
|
3345
3608
|
| Shell | `panel`, `header`, `title`, `icon`, `header-controls`, `messages`, `empty`, `greeting`, `pending`, `stopped`, `jump-latest`, and one per resize grip: `resize-handle` plus `resize-handle-top`, `resize-handle-bottom`, `resize-handle-left`, `resize-handle-right`, `resize-handle-top-left`, `resize-handle-top-right`, `resize-handle-bottom-left`, `resize-handle-bottom-right` |
|
|
3346
3609
|
| Header buttons | `header-button` on each, plus `history-button`, `checkpoints-button`, `new-button`, `collapse-button`, `theme-toggle` |
|
|
3347
|
-
| Collapsed widget | `launcher`, `launcher-icon`, `launcher-badge`, `rail-label` |
|
|
3610
|
+
| Collapsed widget | `launcher`, `launcher-icon`, `launcher-badge`, `rail-label`, `bar` (the [bottom bar](#collapsing-to-a-bottom-bar)'s wrapper, around the launcher), `bar-history` |
|
|
3348
3611
|
| Answers | `answer` (the per-turn group), `message` (plus `message-user`, `message-assistant`), `code-copy` |
|
|
3349
3612
|
| Reasoning | `thoughts`, `thoughts-toggle`, `thoughts-body`, `thoughts-label` |
|
|
3350
3613
|
| Follow-up suggestions | `suggestions`, `suggestion-chip` |
|
|
3351
3614
|
| Message actions | `message-actions`, `message-action` (plus `message-action-retry`, `message-action-copy`, `message-action-up`, `message-action-down`), and the icon holder inside each: `message-action-icon` (plus `message-action-icon-retry`, `message-action-icon-copy`, `message-action-icon-up`, `message-action-icon-down`) |
|
|
3352
3615
|
| Queued messages | `queued`, `queued-chip` |
|
|
3353
3616
|
| Run notices | `run-notice` (plus `run-notice-interrupted`, `run-notice-attachment-pending`, `run-notice-compaction`, `run-notice-skill`, `run-notice-history-replaced`, `run-notice-chart-undrawable`, `run-notice-surface`, `run-notice-not-connected`), `run-notice-icon`, `run-notice-text`, `run-notice-undo` |
|
|
3354
|
-
| Tool cards | `tool-card`, `tool-card-head`, `tool-card-icon`, `tool-card-name`, `tool-card-status`, `tool-card-decision`, `tool-card-toggle`, `tool-card-body`, `tool-card-section` (plus `tool-card-args-section`, `tool-card-result-section`), `tool-card-section-label` (plus `tool-card-args-label`, `tool-card-result-label`), `tool-card-args`, `tool-card-result`, `tool-card-approval`, `tool-card-subagent`, `tool-card-repeat` |
|
|
3355
|
-
| Tool-step group | `tool-group`, `tool-group-head`, `tool-group-icon`, `tool-group-label`, `tool-group-meta`, `tool-group-list` |
|
|
3617
|
+
| Tool cards | `tool-card` (plus one status modifier: `tool-card-pending`, `tool-card-deferred`, `tool-card-done`, `tool-card-error`, `tool-card-declined`, `tool-card-interrupted`), `tool-card-head`, `tool-card-icon`, `tool-card-name`, `tool-card-status` (plus `tool-card-status-pending`, `tool-card-status-deferred`, `tool-card-status-done`, `tool-card-status-error`, `tool-card-status-declined`, `tool-card-status-interrupted`), `tool-card-decision`, `tool-card-toggle`, `tool-card-body`, `tool-card-section` (plus `tool-card-args-section`, `tool-card-result-section`), `tool-card-section-label` (plus `tool-card-args-label`, `tool-card-result-label`), `tool-card-args`, `tool-card-result`, `tool-card-approval`, `tool-card-subagent`, `tool-card-repeat` |
|
|
3618
|
+
| Tool-step group | `tool-group` (plus one state modifier: `tool-group-waiting`, `tool-group-running`, `tool-group-done`, `tool-group-error`), `tool-group-head`, `tool-group-icon`, `tool-group-label`, `tool-group-meta`, `tool-group-list` |
|
|
3356
3619
|
| Delegated sub-agents | `subagent`, `subagent-row`, `subagent-icon`, `subagent-status`, `subagent-steps`, `subagent-step`, `subagent-step-icon`, `subagent-step-name` |
|
|
3357
3620
|
| Client-side confirmation | `confirm`, `confirm-body`, `confirm-args`, `confirm-actions`, `confirm-button` (plus `confirm-confirm`, `confirm-cancel`, `confirm-always`) |
|
|
3358
3621
|
| Server-side approval | `approval`, `approval-body`, `approval-actions`, `approval-button` (plus `approval-approve`, `approval-deny`), `approval-edit`, `approval-args`, `approval-error` |
|
|
@@ -3393,6 +3656,7 @@ with a matching `slot=`):
|
|
|
3393
3656
|
| `header-actions` | Extra controls between the title and the built-in buttons. |
|
|
3394
3657
|
| `greeting` | The greeting's text, above the empty state, where the [greeting layout](#the-greeting-on-an-empty-page) is on. Replaces the text only; `empty` and the starters still render beneath it. |
|
|
3395
3658
|
| `empty` | The empty-state shown before any message. |
|
|
3659
|
+
| `above-composer` | Directly above the composer, below the skill chips, hint, queued turns and attachment tray. Takes no space when empty, and moves with the composer in the [greeting layout](#the-greeting-on-an-empty-page). |
|
|
3396
3660
|
| `footer` | Below the composer. |
|
|
3397
3661
|
| `launcher` | The collapsed widget's mark — the floating launcher, or the sidebar rail. |
|
|
3398
3662
|
| `icon-send` / `icon-stop` | The composer button's two glyphs (idle and mid-run). |
|
|
@@ -3576,7 +3840,10 @@ mic appears even with no `data-transcribe-url`.
|
|
|
3576
3840
|
`slot="header-actions"`. For convenience, the boolean `data-theme-toggle` attribute adds a built-in
|
|
3577
3841
|
light⇄dark toggle to the header (part `theme-toggle`) that flips the scheme word of `theme` and
|
|
3578
3842
|
persists the choice per tab. Only the scheme changes: `soft` becomes `soft dark`, `soft dark`
|
|
3579
|
-
becomes `soft light`, and `auto` becomes
|
|
3843
|
+
becomes `soft light`, and `auto` becomes the opposite of what the system shows, an explicit
|
|
3844
|
+
choice. With no scheme word the toggle flips the scheme the panel is drawn in, so a host rule
|
|
3845
|
+
that sets the element's `color-scheme` (to follow the page's own dark mode) is flipped from,
|
|
3846
|
+
and the written word then holds against that rule. Only the scheme is saved, too:
|
|
3580
3847
|
on the next load it is put beside whatever theme name the markup carries, so `dark` chosen on a
|
|
3581
3848
|
`soft` page restores as `classic dark` on a `classic` one. Off by default so it never competes with
|
|
3582
3849
|
a host-supplied control.
|