@artooi/ag-ui-web-component 0.47.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 +135 -1
- package/README.md +171 -15
- package/dist/ag-ui-web-component.bundle.js +591 -176
- package/dist/ag-ui-web-component.bundle.js.map +4 -4
- package/dist/constants.d.ts +27 -2
- package/dist/constants.d.ts.map +1 -1
- package/dist/core/ag_ui_chat.d.ts +36 -3
- package/dist/core/ag_ui_chat.d.ts.map +1 -1
- 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/dom/highlight_overlay.d.ts +2 -1
- package/dist/dom/highlight_overlay.d.ts.map +1 -1
- package/dist/dom/ring_color.d.ts +8 -0
- package/dist/dom/ring_color.d.ts.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +926 -52
- 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 +16 -3
- 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 +11 -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_group_styles.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 +30 -2
- package/src/core/ag_ui_chat.ts +326 -26
- package/src/core/events/bar_height_detail.ts +5 -0
- package/src/dom/highlight_overlay.ts +2 -1
- package/src/dom/ring_color.ts +141 -4
- package/src/index.ts +4 -0
- package/src/tools/chat_surface_tools.ts +18 -8
- package/src/ui/history/conversation_history.ts +51 -7
- package/src/ui/placement/collapse_styles.ts +248 -2
- package/src/ui/placement/dock_styles.ts +91 -0
- package/src/ui/placement/panel_placement.ts +71 -3
- package/src/ui/placement/small_viewport_styles.ts +9 -0
- package/src/ui/placement/surface_for.ts +29 -18
- package/src/ui/progress/tool_group_styles.ts +49 -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 +28 -1
- package/src/ui/styles.ts +4 -0
- package/src/ui/themes/scheme_styles.ts +10 -1
- package/src/version.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,139 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.48.0] — 2026-11-07
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **Choose how a step group draws its calls.** A new `data-tool-group-display`
|
|
15
|
+
attribute and `toolGroupDisplay` property, one of `full`, `compact`,
|
|
16
|
+
`minimal` or `inline`, set how an opened group draws its calls under
|
|
17
|
+
`grouped`. Each draws the regions the flat card of that mode draws, as a row
|
|
18
|
+
of the group. It is read only under `grouped`, is live, and leaves an
|
|
19
|
+
approval's arguments and buttons on screen in every mode. Exported as
|
|
20
|
+
`TOOL_GROUP_DISPLAY` with the `ToolGroupDisplayMode` type. **Opt-in**: an
|
|
21
|
+
absent or unknown value reads as `full`, which is what a group drew before,
|
|
22
|
+
so a host sees no change until it sets the attribute.
|
|
23
|
+
- **Collapse into a bottom bar.** A new live `collapse-to` attribute chooses
|
|
24
|
+
what a collapsed panel becomes. `bar` draws a strip along the bottom edge in
|
|
25
|
+
place of the round launcher, with the title, the unread badge, a running
|
|
26
|
+
mark and a history button that opens and closes the conversation list as a
|
|
27
|
+
popover;
|
|
28
|
+
the panel rises from the bar's right end. `none` hides the collapsed widget
|
|
29
|
+
so the host's own toolbar drives it, and the `anchor` attribute or property
|
|
30
|
+
names the host element the panel rises from. Under both, the panel's height
|
|
31
|
+
stops at the bar or the anchor, so `--ag-ui-inset` is not needed, and a
|
|
32
|
+
docked panel can be resized but not moved. The read-only `barHeight`
|
|
33
|
+
property and the `ag-ui-bar-height` event (`BAR_HEIGHT_EVENT`, detail
|
|
34
|
+
`BarHeightDetail`) give the host the height to pad its page by. Under
|
|
35
|
+
`none` the element dispatches `ag-ui-toggle` once at connect with the state
|
|
36
|
+
it mounted in. On a phone the open panel stays full-bleed and the bar shows
|
|
37
|
+
only while collapsed. New parts `bar` and `bar-history`, and
|
|
38
|
+
`describeSurface()` reports `collapseTo`. **Opt-in**: absent,
|
|
39
|
+
`collapse-to` reads as `auto`, which leaves every placement as it was.
|
|
40
|
+
- **Clear a host toolbar under `collapse-to="none"`.** The new
|
|
41
|
+
`--ag-ui-anchor-gap` token sets the gap between the panel and the anchor it
|
|
42
|
+
rises from, for a host whose button sits inside a taller toolbar; a gap
|
|
43
|
+
wider than the gutter also comes off the panel's max height, so a tall panel
|
|
44
|
+
stays on screen. **Opt-in**: absent, the gap stays 8px.
|
|
45
|
+
|
|
46
|
+
### Changed
|
|
47
|
+
|
|
48
|
+
- **The chat surface tools describe every collapsed shape.** With
|
|
49
|
+
`data-page-actions` including `chat`, the `minimise_chat` tool no longer
|
|
50
|
+
promises a launcher: its description names the launcher, the rail, the
|
|
51
|
+
bottom bar or the page's own control, and its refusal on a placement with no
|
|
52
|
+
collapsed state no longer mentions a launcher. The report `describeSurface()`
|
|
53
|
+
returns, and so `read_chat_surface`, gains `collapseTo`, and a move
|
|
54
|
+
refused on a docked panel says it is docked. This reaches every host that
|
|
55
|
+
enables the chat tools, whatever `collapse-to` is: an agent prompt that
|
|
56
|
+
quoted the old wording sees new text. No host action is needed.
|
|
57
|
+
- **Tested against `@ag-ui/client` and `@ag-ui/core` 1.0.4.** The lockfile moves
|
|
58
|
+
from 1.0.3, and the declared range (`>=1.0.0 <2`) is unchanged, so a fresh
|
|
59
|
+
install of 0.47.0 already resolved 1.0.4. The element passes `threadId` to
|
|
60
|
+
the agent rather than reading the one 1.0.4 now creates on first read, and it
|
|
61
|
+
never edits a message the agent emits, which 1.0.4 now documents as
|
|
62
|
+
read-only. `zod` stays an undeclared peer of `@ag-ui/core`, as it was in
|
|
63
|
+
1.0.3. **No opt-in** and no behavioural change.
|
|
64
|
+
|
|
65
|
+
- **The demo shows the 0.47.0 additions.** The playground gains a card under
|
|
66
|
+
the form with a control and a readout for each: the `above-composer` slot
|
|
67
|
+
(also a checkbox on the full-page route, where it travels with the centred
|
|
68
|
+
composer), the thread API (`threadId`, `newChat()`, `switchThread()` and a
|
|
69
|
+
log of `ag-ui-thread` events), the `tool-card-status-*` and `tool-group-*`
|
|
70
|
+
parts (drawn in one colour each, with a census of the parts in the
|
|
71
|
+
transcript) and the `--ag-ui-ring` token. Demo only, nothing shipped
|
|
72
|
+
changes, and **a host owes nothing**.
|
|
73
|
+
|
|
74
|
+
### Fixed
|
|
75
|
+
|
|
76
|
+
- **A collapsed embedded chat no longer shows the above-composer slot.** The
|
|
77
|
+
collapse hid the composer and its stack but not the `above-composer` slot, so
|
|
78
|
+
a host's row stayed on screen under the header bar. The slot is hidden with
|
|
79
|
+
the composer and returns on expand. No opt-in: a host that kept content in
|
|
80
|
+
that slot to stay visible while collapsed should use the footer slot, which
|
|
81
|
+
collapse leaves alone.
|
|
82
|
+
|
|
83
|
+
- **`switchThread()` keeps the old thread when the store's load rejects.** The element
|
|
84
|
+
used to point at the new thread id, show an empty transcript and fire no
|
|
85
|
+
`ag-ui-thread`, so it named a thread it was not showing. It now stays on the thread
|
|
86
|
+
it was on, draws it again without an event, and the returned promise rejects with
|
|
87
|
+
the store's error. A second `switchThread()` for the thread still loading now
|
|
88
|
+
settles with that load, after the replay, instead of resolving at once. No host
|
|
89
|
+
opt-in.
|
|
90
|
+
- **`newChat()` before the element connects waits for the connect.** It used to mint a
|
|
91
|
+
thread in the unscoped store and fire `ag-ui-thread` for a chat that was not yet
|
|
92
|
+
shown, leaving `threadId` non-null against the README. Now `threadId` is `null` and
|
|
93
|
+
nothing fires until the element connects, which starts the new chat and fires one
|
|
94
|
+
`ag-ui-thread` with reason `new`. A host that called `newChat()` early and relied on
|
|
95
|
+
the immediate event or thread id reads them after connect instead.
|
|
96
|
+
|
|
97
|
+
- **Rings hold 3:1 against what they are drawn on.** The step group head's
|
|
98
|
+
focus ring was the accent at 55% over transparent, so a light host accent
|
|
99
|
+
fell to 1.6:1 on the default light panel (Django admin's `#79aec8`). Unset,
|
|
100
|
+
`--ag-ui-ring` is now two parts accent to three parts ink, which holds 3:1
|
|
101
|
+
against the panel for any accent in every theme and scheme; Quiet's ring
|
|
102
|
+
turns from a translucent grey to near-ink. The field highlight ring, when it
|
|
103
|
+
falls back to the chat's own accent, is now held to 3:1 against the surface
|
|
104
|
+
behind the target: a dark widget on a light page drew its near-white accent
|
|
105
|
+
at 1.1:1, and now draws the light half of its accent pair, or the accent
|
|
106
|
+
stepped toward black or white. **No opt-in is needed**, and a host's
|
|
107
|
+
`--ag-ui-ring`, `--ag-ui-highlight-ring-color` or page `--ag-ui-accent` is
|
|
108
|
+
still drawn exactly as given.
|
|
109
|
+
|
|
110
|
+
- **The docs no longer advise `--ag-ui-font: inherit`.** The README and the
|
|
111
|
+
0.45.0 entry said it would keep the page's font under any theme. It does
|
|
112
|
+
nothing: a CSS-wide keyword in a custom property applies to the custom
|
|
113
|
+
property itself, so it takes the parent's `--ag-ui-font`, which nothing sets,
|
|
114
|
+
and the theme's stack wins. Set `--ag-ui-font` to the page's family or to a
|
|
115
|
+
page token instead, for example `--ag-ui-font: var(--body-font)`. A host that
|
|
116
|
+
followed the old advice has to change it to get the page's font.
|
|
117
|
+
|
|
118
|
+
- **A chat never dragged no longer inherits a dragged size.** The size a drag
|
|
119
|
+
writes inline on the host was left undeclared on every other chat, so a chat
|
|
120
|
+
slotted into a dragged one, or under any page rule naming the private
|
|
121
|
+
property, came out at that size. It is now declared on `:host` like every
|
|
122
|
+
other private property. **No opt-in is needed.**
|
|
123
|
+
|
|
124
|
+
- **Picking a thread from the history drawer no longer leaves an unhandled
|
|
125
|
+
rejection when the store cannot load it.** The drawer's pick dropped the promise
|
|
126
|
+
`switchThread()` returns, so a store whose load rejected surfaced as an unhandled
|
|
127
|
+
rejection on the page. The pick now ends that rejection itself, and the thread on
|
|
128
|
+
screen stays as it was. No host opt-in.
|
|
129
|
+
|
|
130
|
+
- **A gated call with no arguments no longer draws an empty arguments box.** Under
|
|
131
|
+
`data-tool-display="compact"` and `"inline"`, the rule that shows a deferred call's
|
|
132
|
+
arguments outranked the `hidden` attribute the card sets when there are none, so an
|
|
133
|
+
empty box sat above the Approve button. The rule now skips a hidden section. No host
|
|
134
|
+
opt-in.
|
|
135
|
+
|
|
136
|
+
- **The theme toggle flips the scheme the panel is drawn in.** With no `light` or
|
|
137
|
+
`dark` word in `theme`, as under `auto` on a dark system or when a host rule sets
|
|
138
|
+
the element's `color-scheme`, the first press wrote `dark` over a panel that was
|
|
139
|
+
already dark, and the glyph offered dark. The toggle and its glyph now read the
|
|
140
|
+
drawn scheme. A `light` or `dark` word also now holds against a host rule that
|
|
141
|
+
sets `color-scheme` on the element, which used to win over it. No host opt-in.
|
|
142
|
+
|
|
10
143
|
## [0.47.0] — 2026-11-07
|
|
11
144
|
|
|
12
145
|
### Added
|
|
@@ -4846,7 +4979,8 @@ hosts that both arrange the page the way it expects.
|
|
|
4846
4979
|
### Notes
|
|
4847
4980
|
- First release — exercising the automated npm OIDC publish pipeline end-to-end.
|
|
4848
4981
|
|
|
4849
|
-
[Unreleased]: https://github.com/Artui/ag-ui-web-component/compare/v0.
|
|
4982
|
+
[Unreleased]: https://github.com/Artui/ag-ui-web-component/compare/v0.48.0...HEAD
|
|
4983
|
+
[0.48.0]: https://github.com/Artui/ag-ui-web-component/compare/v0.47.0...v0.48.0
|
|
4850
4984
|
[0.47.0]: https://github.com/Artui/ag-ui-web-component/compare/v0.46.0...v0.47.0
|
|
4851
4985
|
[0.46.0]: https://github.com/Artui/ag-ui-web-component/compare/v0.45.0...v0.46.0
|
|
4852
4986
|
[0.45.0]: https://github.com/Artui/ag-ui-web-component/compare/v0.44.0...v0.45.0
|
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,6 +208,8 @@ 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. |
|
|
@@ -234,7 +238,7 @@ same way: `icon-send`, `icon-stop`, `icon-attach`, `icon-voice`.
|
|
|
234
238
|
|
|
235
239
|
The element observes two groups of attributes, and they behave differently once it is in the DOM.
|
|
236
240
|
Nothing outside those groups is observed: a CSS-only attribute (`theme`, `density`, `data-side`,
|
|
237
|
-
`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`,
|
|
238
242
|
`data-tool-display`, `data-text-animation`, `data-runs-url`, `data-page-actions`,
|
|
239
243
|
`data-message-actions`, `data-max-tool-rounds`, `data-unread-badge`, `data-launcher-drag` and
|
|
240
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
|
|
@@ -242,7 +246,7 @@ neither camp is `data-launcher-icon-url`: it is read while the element connects,
|
|
|
242
246
|
below, but is not observed, so a late write is inert and says nothing.
|
|
243
247
|
|
|
244
248
|
**Live attributes.** Written at any time, before or after the element connects, and acted on
|
|
245
|
-
either way: `title-text`, `placement`, `credentials`, `user-key`, `user-name`.
|
|
249
|
+
either way: `title-text`, `placement`, `collapse-to`, `anchor`, `credentials`, `user-key`, `user-name`.
|
|
246
250
|
|
|
247
251
|
**Connect-time attributes.** Read once, while the element connects, to decide what chrome exists at
|
|
248
252
|
all — the tray, the mic, the skills menu, the header mark. Writing one afterwards has **no effect**;
|
|
@@ -265,8 +269,8 @@ element after the fact.
|
|
|
265
269
|
`approveWithEdits`, `agentFactory`, `getTools`, `getContext`, `routeMap`, `navigate`, `getPageMap`,
|
|
266
270
|
`autoInjectPageMap`, `conversationStore`, `uploadHandler`, `transcribeHandler`, `navigationResult`,
|
|
267
271
|
`skillContext`, `toolSummaries`, `formatToolPayload`, `formatRelativeTime`, `strings`,
|
|
268
|
-
`resolvePageTarget`, `sharedState`, `extraStyles` ([unstable](#d-extrastyles-the-last-mile)), plus the read-only `unread`, `unhandledActivityTypes`, `threadId` and `
|
|
269
|
-
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` /
|
|
270
274
|
`credentials`.
|
|
271
275
|
|
|
272
276
|
`headers` and `getHeaders` authenticate **every** request the element makes, not only the agent
|
|
@@ -1065,9 +1069,19 @@ dark scheme. When a call passes no `color`, the first of these that is set wins:
|
|
|
1065
1069
|
1. `--ag-ui-highlight-ring-color` on the target (so `:root` reaches every ring);
|
|
1066
1070
|
2. `--ag-ui-highlight-ring-color` on the chat — on `ag-ui-chat` or anything above it;
|
|
1067
1071
|
3. the target's `--ag-ui-accent`, so a page that themes its accent keeps the rings it has;
|
|
1068
|
-
4. the chat's resolved accent, its theme's default included;
|
|
1072
|
+
4. the chat's resolved accent, its theme's default included, held to 3:1 against the page (below);
|
|
1069
1073
|
5. the package indigo, when no chat is on the page at all.
|
|
1070
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
|
+
|
|
1071
1085
|
```css
|
|
1072
1086
|
/* Rings in the brand colour, whatever the widget's accent. */
|
|
1073
1087
|
ag-ui-chat { --ag-ui-highlight-ring-color: #0f766e; }
|
|
@@ -1160,9 +1174,11 @@ matching JS API:
|
|
|
1160
1174
|
widget is collapsed, and the page is not scrolled to it. A restore still loading or replaying
|
|
1161
1175
|
the conversation being left stops there, so nothing of it is drawn into the new chat, and a
|
|
1162
1176
|
run it was about to resume after a reload is not resumed: coming back to that conversation
|
|
1163
|
-
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`.
|
|
1164
1180
|
- `describeSurface()` — where the panel is and what can be done to it: placement, collapsed,
|
|
1165
|
-
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
|
|
1166
1182
|
the two reasons a move can fail into the one answer a caller needs.
|
|
1167
1183
|
- `moveTo(corner)` — send the panel to `top-left` / `top-right` / `bottom-left` / `bottom-right`,
|
|
1168
1184
|
returning whether it went. It takes the axes the same way a user drag does, so the launcher
|
|
@@ -1194,7 +1210,9 @@ one on screen with the drawer's own paths:
|
|
|
1194
1210
|
the drawer does. Returns a `Promise<void>` that resolves once the thread is drawn. **A run in
|
|
1195
1211
|
flight is cancelled**, as the drawer and `newChat()` cancel it; read `running` first if you
|
|
1196
1212
|
would rather wait. Switching to the thread already on screen does nothing, and so does a call
|
|
1197
|
-
before the element connects
|
|
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.
|
|
1198
1216
|
- `deleteThread(threadId)` — delete a stored thread, as the drawer row's delete does. Deleting
|
|
1199
1217
|
the thread on screen cancels its run and puts a fresh thread in its place; deleting another
|
|
1200
1218
|
leaves the screen alone. Prefer it to `conversationStore.clear()`, which deletes the record and
|
|
@@ -1382,6 +1400,105 @@ ag-ui-chat {
|
|
|
1382
1400
|
}
|
|
1383
1401
|
```
|
|
1384
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
|
+
|
|
1385
1502
|
---
|
|
1386
1503
|
|
|
1387
1504
|
## Charts
|
|
@@ -1557,7 +1674,7 @@ absent or unknown value reads as `grouped`):
|
|
|
1557
1674
|
|
|
1558
1675
|
- `grouped` — the default. A run's consecutive tool calls fold into one quiet row, **"Worked
|
|
1559
1676
|
through 5 steps"**, with a note such as **"1 failed"** beside it, and the calls one click down
|
|
1560
|
-
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
|
|
1561
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
|
|
1562
1679
|
[The step group](#the-step-group).
|
|
1563
1680
|
- `inline` — the lightest mode: a single status row (icon + summary, no card chrome) with the
|
|
@@ -1591,6 +1708,25 @@ each card is built: switching **to** `grouped` folds only the calls drawn afterw
|
|
|
1591
1708
|
switching **away** from it flattens the groups already drawn, by CSS, into exactly the cards the
|
|
1592
1709
|
new mode builds (the group stops generating a box and its row is hidden).
|
|
1593
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
|
+
|
|
1594
1730
|
### The step group
|
|
1595
1731
|
|
|
1596
1732
|
Under `grouped` the row reads, by state:
|
|
@@ -2844,6 +2980,7 @@ re-export point. Internal modules import from leaf paths.
|
|
|
2844
2980
|
| `SubmitDetail` | type | `detail` shape of the submit event. |
|
|
2845
2981
|
| `ThreadDetail` | type | `detail` shape of the `ag-ui-thread` event (`{ threadId, previousThreadId, reason }`). |
|
|
2846
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 }`). |
|
|
2847
2984
|
| `UnreadDetail` | type | `detail` shape of the `ag-ui-unread` event (`{ unread }`). |
|
|
2848
2985
|
| `AttachmentsDetail` | type | `detail` shape of the `ag-ui-attachments` event (`{ attachments, pending }`). |
|
|
2849
2986
|
| `StateDetail` | type | `detail` shape of the `ag-ui-state` event (`{ state }`). |
|
|
@@ -2876,7 +3013,7 @@ re-export point. Internal modules import from leaf paths.
|
|
|
2876
3013
|
| `PAGE_ACTIONS` | const | The page-action opt-in tokens (`scroll` / `drag`). |
|
|
2877
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. |
|
|
2878
3015
|
| `ChatSurface` | type | The narrow port those tools drive — `describeSurface` / `moveTo` / `setCollapsed`. The element satisfies it. |
|
|
2879
|
-
| `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. |
|
|
2880
3017
|
| `ChatCorner` | type | `"top-left"` / `"top-right"` / `"bottom-left"` / `"bottom-right"` — the argument to `moveTo`. |
|
|
2881
3018
|
| `CHAT_CORNERS` | const | Those four, as a list. |
|
|
2882
3019
|
| `isChatCorner(value)` | function | Whether a string names one of them. |
|
|
@@ -2951,6 +3088,7 @@ re-export point. Internal modules import from leaf paths.
|
|
|
2951
3088
|
| --- | --- | --- |
|
|
2952
3089
|
| `ToolCallCard` | class | A live tool-call card for the transcript. |
|
|
2953
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). |
|
|
2954
3092
|
| `ToolPayloadFormatter` | type | Draws one region of a card's body (`AgUiChat.formatToolPayload`); `null` falls through to the built-in pretty-print. |
|
|
2955
3093
|
| `ToolPayload` | type | The region being drawn: `arguments` (the parsed record) or `result` (the raw string and its outcome). |
|
|
2956
3094
|
| `ToolCallCardOptions` | type | Per-card wiring beyond name / args / label / strings — currently `formatPayload`. |
|
|
@@ -2994,6 +3132,7 @@ re-export point. Internal modules import from leaf paths.
|
|
|
2994
3132
|
| `SUBMIT_EVENT` | The submit CustomEvent name. |
|
|
2995
3133
|
| `THREAD_EVENT` | The conversation-changed CustomEvent name (`ag-ui-thread`). |
|
|
2996
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`). |
|
|
2997
3136
|
| `UNREAD_EVENT` | The unread-count CustomEvent name (`ag-ui-unread`). |
|
|
2998
3137
|
| `RUN_FINISHED_EVENT` | The interaction-finished CustomEvent name (`ag-ui-run-finished`). |
|
|
2999
3138
|
| `CUSTOM_AGENT_EVENT` | The agent-`CUSTOM` CustomEvent name (`ag-ui-custom`). |
|
|
@@ -3013,6 +3152,7 @@ re-export point. Internal modules import from leaf paths.
|
|
|
3013
3152
|
| `MESSAGE_ACTIONS` | The message-action tokens `data-message-actions` selects by (`copy` / `retry` / `feedback`). |
|
|
3014
3153
|
| `TOOL_CALL_STATUS` | Tool-call card status constants. |
|
|
3015
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`). |
|
|
3016
3156
|
| `TOOL_OUTCOME` | How a tool call ended, as a server states it on `TOOL_CALL_RESULT` (`success` / `failed` / `denied`). |
|
|
3017
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. |
|
|
3018
3158
|
| `X_SUMMARY_KEY` | JSON-Schema key carrying a short tool-card label. |
|
|
@@ -3124,11 +3264,20 @@ first, so each stays an override point. The tokens the themes add:
|
|
|
3124
3264
|
- **Charts:** `--ag-ui-chart-1` to `--ag-ui-chart-6`. A host's value beats the theme's.
|
|
3125
3265
|
- **Status marks:** `--ag-ui-ico-check`, `--ag-ui-ico-error`, `--ag-ui-ico-declined`, mask images
|
|
3126
3266
|
drawn in the state's colour, and `--ag-ui-ico-chevron`, the step group's disclosure chevron.
|
|
3127
|
-
- **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.
|
|
3128
3269
|
|
|
3129
3270
|
The font is part of the theme: Quiet, Soft and Ledger set their own stack (Inter, then the system
|
|
3130
|
-
UI font), and Classic inherits the page's font as the component always did.
|
|
3131
|
-
`--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.
|
|
3132
3281
|
|
|
3133
3282
|
#### Text on the accent
|
|
3134
3283
|
|
|
@@ -3318,6 +3467,10 @@ keeps between itself and that box. The size cap subtracts the same one, so a
|
|
|
3318
3467
|
panel grown to its limit reaches the far edge of the usable box and no further —
|
|
3319
3468
|
set it to `0` for a panel flush against the corner.
|
|
3320
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
|
+
|
|
3321
3474
|
`--ag-ui-keyboard-inset` overrides the lift an on-screen keyboard earns. The
|
|
3322
3475
|
widget measures the hidden band and publishes it as
|
|
3323
3476
|
`--ag-ui-visual-viewport-inset-bottom`; state this one instead to outrank that
|
|
@@ -3454,7 +3607,7 @@ component sets, so a new one cannot ship undocumented.
|
|
|
3454
3607
|
| --- | --- |
|
|
3455
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` |
|
|
3456
3609
|
| Header buttons | `header-button` on each, plus `history-button`, `checkpoints-button`, `new-button`, `collapse-button`, `theme-toggle` |
|
|
3457
|
-
| 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` |
|
|
3458
3611
|
| Answers | `answer` (the per-turn group), `message` (plus `message-user`, `message-assistant`), `code-copy` |
|
|
3459
3612
|
| Reasoning | `thoughts`, `thoughts-toggle`, `thoughts-body`, `thoughts-label` |
|
|
3460
3613
|
| Follow-up suggestions | `suggestions`, `suggestion-chip` |
|
|
@@ -3687,7 +3840,10 @@ mic appears even with no `data-transcribe-url`.
|
|
|
3687
3840
|
`slot="header-actions"`. For convenience, the boolean `data-theme-toggle` attribute adds a built-in
|
|
3688
3841
|
light⇄dark toggle to the header (part `theme-toggle`) that flips the scheme word of `theme` and
|
|
3689
3842
|
persists the choice per tab. Only the scheme changes: `soft` becomes `soft dark`, `soft dark`
|
|
3690
|
-
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:
|
|
3691
3847
|
on the next load it is put beside whatever theme name the markup carries, so `dark` chosen on a
|
|
3692
3848
|
`soft` page restores as `classic dark` on a `classic` one. Off by default so it never competes with
|
|
3693
3849
|
a host-supplied control.
|