@artooi/ag-ui-web-component 0.47.0 → 0.49.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 +205 -1
- package/README.md +235 -16
- package/dist/ag-ui-web-component.bundle.js +647 -181
- 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 +44 -5
- 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 +1184 -69
- 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 +16 -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 +32 -19
- 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/quiet_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 +335 -28
- 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 +13 -5
- 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 +95 -0
- package/src/ui/placement/panel_placement.ts +300 -16
- package/src/ui/placement/small_viewport_styles.ts +9 -0
- package/src/ui/placement/surface_for.ts +58 -22
- package/src/ui/progress/tool_group_styles.ts +52 -2
- 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 +58 -1
- package/src/ui/styles.ts +4 -0
- package/src/ui/themes/quiet_styles.ts +19 -3
- package/src/ui/themes/scheme_styles.ts +10 -1
- package/src/version.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,208 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.49.0] — 2026-11-07
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **`--ag-ui-header-btn-hover`, the header buttons' hover square.** Drawn
|
|
15
|
+
exactly as given under Quiet and a host's own theme word, whether or not
|
|
16
|
+
`--ag-ui-header-fg` is set. Unset, the square follows the header text as
|
|
17
|
+
below, or is the panel's hover shade when that is unset too. A host that
|
|
18
|
+
prefers the lightening square of its old `::part(header-button):hover`
|
|
19
|
+
rule sets this token to that colour instead of keeping the rule.
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
|
|
23
|
+
- **A docked panel moves and remembers where it was put.** Under
|
|
24
|
+
`collapse-to="bar"`, and under `collapse-to="none"` with or without an
|
|
25
|
+
`anchor`, a corner panel on a wide viewport now moves by its header and by
|
|
26
|
+
`moveTo`, like the default corner panel. Minimising and reopening, and a
|
|
27
|
+
reload, bring it back where it was dragged, and a panel never dragged still
|
|
28
|
+
opens at the dock. A dragged panel stays inside the viewport and above the
|
|
29
|
+
bar, or above the anchor's top under `none` (the anchor gap no longer
|
|
30
|
+
applies once dragged), and a stored spot is held there if the window or the
|
|
31
|
+
bar changed since. Once dragged off, every resize edge follows its grip.
|
|
32
|
+
`resetSize()` returns a dragged docked panel to the dock and forgets the
|
|
33
|
+
stored spot; under `auto` it still drops only the size. The spot is stored
|
|
34
|
+
apart from the corner panel's, so a spot dragged under `auto` never lands on
|
|
35
|
+
a docked panel. On a phone the panel stays full-bleed and does not move.
|
|
36
|
+
`describeSurface()` and `read_chat_surface` report `movable: true` and
|
|
37
|
+
`draggable: true` for it on a wide viewport, and `move_chat` no longer
|
|
38
|
+
refuses with "the panel is docked". `side` and `full` under `bar`, and
|
|
39
|
+
`sidebar` and `embedded` under `none`, still own their position; they now
|
|
40
|
+
report `draggable: true` where they reported `false`, so a refused move
|
|
41
|
+
there names the placement rather than the dock or the page. **A host has
|
|
42
|
+
nothing to do**: every host using `bar` or `none` gets the movable panel on
|
|
43
|
+
upgrade. A host that wants the 0.48.0 fixed dock sets
|
|
44
|
+
`data-launcher-drag="false"`, which turns the header drag and `moveTo` off
|
|
45
|
+
here as it does on a corner panel.
|
|
46
|
+
|
|
47
|
+
### Fixed
|
|
48
|
+
|
|
49
|
+
- **Quiet's header buttons follow `--ag-ui-header-fg`.** The accent recipe
|
|
50
|
+
(0.45.0) put the accent on the header, but Quiet drew the history, new-chat,
|
|
51
|
+
theme and collapse buttons in its third ink at 0.85 opacity, about 1.2:1 on
|
|
52
|
+
a `#3d5afe` header, and hovered them on the panel's near-white or near-black
|
|
53
|
+
shade. Once a host sets `--ag-ui-header-fg`, the buttons draw in it at full
|
|
54
|
+
opacity, and the hover square is the opposite of that text at 18% (darker
|
|
55
|
+
under white text, lighter under dark), so a hovered button reads at least
|
|
56
|
+
what the host's header pair reads: white on `#3d5afe` is 5.1:1 at rest and
|
|
57
|
+
about 7:1 hovered. Browsers without relative colour syntax (Firefox 120
|
|
58
|
+
to 127, Safari 17.5 and 17.6) mix the square from the text itself instead.
|
|
59
|
+
This applies under Quiet and under a host's own theme word, which starts
|
|
60
|
+
from Quiet, in every scheme; Soft, Ledger, Classic and code are unchanged.
|
|
61
|
+
Unset, nothing changes. **No opt-in is needed.** A host that
|
|
62
|
+
wrote `ag-ui-chat::part(header-button) { color: var(--ag-ui-header-fg) }`
|
|
63
|
+
and the `:hover` background beside it may delete both: kept, the colour
|
|
64
|
+
rule is harmless, but the page's 18% tint of the text still beats the new
|
|
65
|
+
square, and on a mid-tone accent it takes the hovered glyph under 4.5:1
|
|
66
|
+
(3.75:1 on `#3d5afe`). Delete the hover background at least; to keep a
|
|
67
|
+
lightening square, set `--ag-ui-header-btn-hover` to it. With the header
|
|
68
|
+
text set, the header buttons no longer read `--ag-ui-hover`; the rest of
|
|
69
|
+
the panel still does. A host that sets neither `--ag-ui-header-fg`
|
|
70
|
+
nor `--ag-ui-tool-fg`, the Django admin among them, sees no change.
|
|
71
|
+
- **`--ag-ui-tool-fg` reaches the calls in a step group.** Under the grouped
|
|
72
|
+
default (0.46.0) every call in a group was drawn in the second ink whatever
|
|
73
|
+
the token said, so the recipe's tool colour reached nothing. A set
|
|
74
|
+
`--ag-ui-tool-fg` now colours grouped calls under every theme; unset, they
|
|
75
|
+
keep the second ink, Classic included. **No opt-in is needed**, but a host
|
|
76
|
+
that set the token and kept the grouped default sees its calls in that
|
|
77
|
+
colour from this release.
|
|
78
|
+
|
|
79
|
+
## [0.48.0] — 2026-11-07
|
|
80
|
+
|
|
81
|
+
### Added
|
|
82
|
+
|
|
83
|
+
- **Choose how a step group draws its calls.** A new `data-tool-group-display`
|
|
84
|
+
attribute and `toolGroupDisplay` property, one of `full`, `compact`,
|
|
85
|
+
`minimal` or `inline`, set how an opened group draws its calls under
|
|
86
|
+
`grouped`. Each draws the regions the flat card of that mode draws, as a row
|
|
87
|
+
of the group. It is read only under `grouped`, is live, and leaves an
|
|
88
|
+
approval's arguments and buttons on screen in every mode. Exported as
|
|
89
|
+
`TOOL_GROUP_DISPLAY` with the `ToolGroupDisplayMode` type. **Opt-in**: an
|
|
90
|
+
absent or unknown value reads as `full`, which is what a group drew before,
|
|
91
|
+
so a host sees no change until it sets the attribute.
|
|
92
|
+
- **Collapse into a bottom bar.** A new live `collapse-to` attribute chooses
|
|
93
|
+
what a collapsed panel becomes. `bar` draws a strip along the bottom edge in
|
|
94
|
+
place of the round launcher, with the title, the unread badge, a running
|
|
95
|
+
mark and a history button that opens and closes the conversation list as a
|
|
96
|
+
popover;
|
|
97
|
+
the panel rises from the bar's right end. `none` hides the collapsed widget
|
|
98
|
+
so the host's own toolbar drives it, and the `anchor` attribute or property
|
|
99
|
+
names the host element the panel rises from. Under both, the panel's height
|
|
100
|
+
stops at the bar or the anchor, so `--ag-ui-inset` is not needed, and a
|
|
101
|
+
docked panel can be resized but not moved. The read-only `barHeight`
|
|
102
|
+
property and the `ag-ui-bar-height` event (`BAR_HEIGHT_EVENT`, detail
|
|
103
|
+
`BarHeightDetail`) give the host the height to pad its page by. Under
|
|
104
|
+
`none` the element dispatches `ag-ui-toggle` once at connect with the state
|
|
105
|
+
it mounted in. On a phone the open panel stays full-bleed and the bar shows
|
|
106
|
+
only while collapsed. New parts `bar` and `bar-history`, and
|
|
107
|
+
`describeSurface()` reports `collapseTo`. **Opt-in**: absent,
|
|
108
|
+
`collapse-to` reads as `auto`, which leaves every placement as it was.
|
|
109
|
+
- **Clear a host toolbar under `collapse-to="none"`.** The new
|
|
110
|
+
`--ag-ui-anchor-gap` token sets the gap between the panel and the anchor it
|
|
111
|
+
rises from, for a host whose button sits inside a taller toolbar; a gap
|
|
112
|
+
wider than the gutter also comes off the panel's max height, so a tall panel
|
|
113
|
+
stays on screen. **Opt-in**: absent, the gap stays 8px.
|
|
114
|
+
|
|
115
|
+
### Changed
|
|
116
|
+
|
|
117
|
+
- **The chat surface tools describe every collapsed shape.** With
|
|
118
|
+
`data-page-actions` including `chat`, the `minimise_chat` tool no longer
|
|
119
|
+
promises a launcher: its description names the launcher, the rail, the
|
|
120
|
+
bottom bar or the page's own control, and its refusal on a placement with no
|
|
121
|
+
collapsed state no longer mentions a launcher. The report `describeSurface()`
|
|
122
|
+
returns, and so `read_chat_surface`, gains `collapseTo`, and a move
|
|
123
|
+
refused on a docked panel says it is docked. This reaches every host that
|
|
124
|
+
enables the chat tools, whatever `collapse-to` is: an agent prompt that
|
|
125
|
+
quoted the old wording sees new text. No host action is needed.
|
|
126
|
+
- **Tested against `@ag-ui/client` and `@ag-ui/core` 1.0.4.** The lockfile moves
|
|
127
|
+
from 1.0.3, and the declared range (`>=1.0.0 <2`) is unchanged, so a fresh
|
|
128
|
+
install of 0.47.0 already resolved 1.0.4. The element passes `threadId` to
|
|
129
|
+
the agent rather than reading the one 1.0.4 now creates on first read, and it
|
|
130
|
+
never edits a message the agent emits, which 1.0.4 now documents as
|
|
131
|
+
read-only. `zod` stays an undeclared peer of `@ag-ui/core`, as it was in
|
|
132
|
+
1.0.3. **No opt-in** and no behavioural change.
|
|
133
|
+
|
|
134
|
+
- **The demo shows the 0.47.0 additions.** The playground gains a card under
|
|
135
|
+
the form with a control and a readout for each: the `above-composer` slot
|
|
136
|
+
(also a checkbox on the full-page route, where it travels with the centred
|
|
137
|
+
composer), the thread API (`threadId`, `newChat()`, `switchThread()` and a
|
|
138
|
+
log of `ag-ui-thread` events), the `tool-card-status-*` and `tool-group-*`
|
|
139
|
+
parts (drawn in one colour each, with a census of the parts in the
|
|
140
|
+
transcript) and the `--ag-ui-ring` token. Demo only, nothing shipped
|
|
141
|
+
changes, and **a host owes nothing**.
|
|
142
|
+
|
|
143
|
+
### Fixed
|
|
144
|
+
|
|
145
|
+
- **A collapsed embedded chat no longer shows the above-composer slot.** The
|
|
146
|
+
collapse hid the composer and its stack but not the `above-composer` slot, so
|
|
147
|
+
a host's row stayed on screen under the header bar. The slot is hidden with
|
|
148
|
+
the composer and returns on expand. No opt-in: a host that kept content in
|
|
149
|
+
that slot to stay visible while collapsed should use the footer slot, which
|
|
150
|
+
collapse leaves alone.
|
|
151
|
+
|
|
152
|
+
- **`switchThread()` keeps the old thread when the store's load rejects.** The element
|
|
153
|
+
used to point at the new thread id, show an empty transcript and fire no
|
|
154
|
+
`ag-ui-thread`, so it named a thread it was not showing. It now stays on the thread
|
|
155
|
+
it was on, draws it again without an event, and the returned promise rejects with
|
|
156
|
+
the store's error. A second `switchThread()` for the thread still loading now
|
|
157
|
+
settles with that load, after the replay, instead of resolving at once. No host
|
|
158
|
+
opt-in.
|
|
159
|
+
- **`newChat()` before the element connects waits for the connect.** It used to mint a
|
|
160
|
+
thread in the unscoped store and fire `ag-ui-thread` for a chat that was not yet
|
|
161
|
+
shown, leaving `threadId` non-null against the README. Now `threadId` is `null` and
|
|
162
|
+
nothing fires until the element connects, which starts the new chat and fires one
|
|
163
|
+
`ag-ui-thread` with reason `new`. A host that called `newChat()` early and relied on
|
|
164
|
+
the immediate event or thread id reads them after connect instead.
|
|
165
|
+
|
|
166
|
+
- **Rings hold 3:1 against what they are drawn on.** The step group head's
|
|
167
|
+
focus ring was the accent at 55% over transparent, so a light host accent
|
|
168
|
+
fell to 1.6:1 on the default light panel (Django admin's `#79aec8`). Unset,
|
|
169
|
+
`--ag-ui-ring` is now two parts accent to three parts ink, which holds 3:1
|
|
170
|
+
against the panel for any accent in every theme and scheme; Quiet's ring
|
|
171
|
+
turns from a translucent grey to near-ink. The field highlight ring, when it
|
|
172
|
+
falls back to the chat's own accent, is now held to 3:1 against the surface
|
|
173
|
+
behind the target: a dark widget on a light page drew its near-white accent
|
|
174
|
+
at 1.1:1, and now draws the light half of its accent pair, or the accent
|
|
175
|
+
stepped toward black or white. **No opt-in is needed**, and a host's
|
|
176
|
+
`--ag-ui-ring`, `--ag-ui-highlight-ring-color` or page `--ag-ui-accent` is
|
|
177
|
+
still drawn exactly as given.
|
|
178
|
+
|
|
179
|
+
- **The docs no longer advise `--ag-ui-font: inherit`.** The README and the
|
|
180
|
+
0.45.0 entry said it would keep the page's font under any theme. It does
|
|
181
|
+
nothing: a CSS-wide keyword in a custom property applies to the custom
|
|
182
|
+
property itself, so it takes the parent's `--ag-ui-font`, which nothing sets,
|
|
183
|
+
and the theme's stack wins. Set `--ag-ui-font` to the page's family or to a
|
|
184
|
+
page token instead, for example `--ag-ui-font: var(--body-font)`. A host that
|
|
185
|
+
followed the old advice has to change it to get the page's font.
|
|
186
|
+
|
|
187
|
+
- **A chat never dragged no longer inherits a dragged size.** The size a drag
|
|
188
|
+
writes inline on the host was left undeclared on every other chat, so a chat
|
|
189
|
+
slotted into a dragged one, or under any page rule naming the private
|
|
190
|
+
property, came out at that size. It is now declared on `:host` like every
|
|
191
|
+
other private property. **No opt-in is needed.**
|
|
192
|
+
|
|
193
|
+
- **Picking a thread from the history drawer no longer leaves an unhandled
|
|
194
|
+
rejection when the store cannot load it.** The drawer's pick dropped the promise
|
|
195
|
+
`switchThread()` returns, so a store whose load rejected surfaced as an unhandled
|
|
196
|
+
rejection on the page. The pick now ends that rejection itself, and the thread on
|
|
197
|
+
screen stays as it was. No host opt-in.
|
|
198
|
+
|
|
199
|
+
- **A gated call with no arguments no longer draws an empty arguments box.** Under
|
|
200
|
+
`data-tool-display="compact"` and `"inline"`, the rule that shows a deferred call's
|
|
201
|
+
arguments outranked the `hidden` attribute the card sets when there are none, so an
|
|
202
|
+
empty box sat above the Approve button. The rule now skips a hidden section. No host
|
|
203
|
+
opt-in.
|
|
204
|
+
|
|
205
|
+
- **The theme toggle flips the scheme the panel is drawn in.** With no `light` or
|
|
206
|
+
`dark` word in `theme`, as under `auto` on a dark system or when a host rule sets
|
|
207
|
+
the element's `color-scheme`, the first press wrote `dark` over a panel that was
|
|
208
|
+
already dark, and the glyph offered dark. The toggle and its glyph now read the
|
|
209
|
+
drawn scheme. A `light` or `dark` word also now holds against a host rule that
|
|
210
|
+
sets `color-scheme` on the element, which used to win over it. No host opt-in.
|
|
211
|
+
|
|
10
212
|
## [0.47.0] — 2026-11-07
|
|
11
213
|
|
|
12
214
|
### Added
|
|
@@ -4846,7 +5048,9 @@ hosts that both arrange the page the way it expects.
|
|
|
4846
5048
|
### Notes
|
|
4847
5049
|
- First release — exercising the automated npm OIDC publish pipeline end-to-end.
|
|
4848
5050
|
|
|
4849
|
-
[Unreleased]: https://github.com/Artui/ag-ui-web-component/compare/v0.
|
|
5051
|
+
[Unreleased]: https://github.com/Artui/ag-ui-web-component/compare/v0.49.0...HEAD
|
|
5052
|
+
[0.49.0]: https://github.com/Artui/ag-ui-web-component/compare/v0.48.0...v0.49.0
|
|
5053
|
+
[0.48.0]: https://github.com/Artui/ag-ui-web-component/compare/v0.47.0...v0.48.0
|
|
4850
5054
|
[0.47.0]: https://github.com/Artui/ag-ui-web-component/compare/v0.46.0...v0.47.0
|
|
4851
5055
|
[0.46.0]: https://github.com/Artui/ag-ui-web-component/compare/v0.45.0...v0.46.0
|
|
4852
5056
|
[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. Under either, a corner panel still moves by its header and `moveTo` on a wide viewport, and remembers where it was dragged. 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,17 +1174,22 @@ 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
|
|
1169
1185
|
travels with it and switching placement hands them back. Returns `false` rather than pretending
|
|
1170
|
-
when the placement owns its position or the panel fills the screen.
|
|
1186
|
+
when the placement owns its position or the panel fills the screen. Under `collapse-to="bar"`
|
|
1187
|
+
or `"none"` it moves the panel within the room above the bar or the anchor.
|
|
1171
1188
|
- `resetSize()` — drop a size the user dragged, and its stored copy, so the placement's own
|
|
1172
1189
|
size and your `--ag-ui-width` / `--ag-ui-height` apply again. For a host that enters a sized
|
|
1173
1190
|
state of its own (an expanded mode): a user's drag outranks host tokens, so call this first.
|
|
1191
|
+
Under `collapse-to="bar"` or `"none"` it also returns a panel the user dragged off its dock to
|
|
1192
|
+
the dock and forgets the stored spot; a corner panel under `auto` keeps its dragged position.
|
|
1174
1193
|
- `setCollapsed(collapsed)` / `toggleCollapsed()` — collapse or expand the widget. The state is
|
|
1175
1194
|
reflected as the boolean `collapsed` attribute/property and persisted per-tab in
|
|
1176
1195
|
`sessionStorage`, so it survives a reload.
|
|
@@ -1194,7 +1213,9 @@ one on screen with the drawer's own paths:
|
|
|
1194
1213
|
the drawer does. Returns a `Promise<void>` that resolves once the thread is drawn. **A run in
|
|
1195
1214
|
flight is cancelled**, as the drawer and `newChat()` cancel it; read `running` first if you
|
|
1196
1215
|
would rather wait. Switching to the thread already on screen does nothing, and so does a call
|
|
1197
|
-
before the element connects
|
|
1216
|
+
before the element connects; a second call for the thread that is still loading settles with
|
|
1217
|
+
that load, after the replay. If the store rejects the load, the element stays on the thread it
|
|
1218
|
+
was on, redraws it, fires no `ag-ui-thread`, and the promise rejects with the store's error.
|
|
1198
1219
|
- `deleteThread(threadId)` — delete a stored thread, as the drawer row's delete does. Deleting
|
|
1199
1220
|
the thread on screen cancels its run and puts a fresh thread in its place; deleting another
|
|
1200
1221
|
leaves the screen alone. Prefer it to `conversationStore.clear()`, which deletes the record and
|
|
@@ -1382,6 +1403,126 @@ ag-ui-chat {
|
|
|
1382
1403
|
}
|
|
1383
1404
|
```
|
|
1384
1405
|
|
|
1406
|
+
### Collapsing to a bottom bar
|
|
1407
|
+
|
|
1408
|
+
`collapse-to` chooses what a collapsed panel becomes, for a host whose layout has a bottom
|
|
1409
|
+
toolbar. It is opt-in: absent, `auto`, or any other value leaves every placement as the
|
|
1410
|
+
sections above describe. It is live, like `placement`.
|
|
1411
|
+
|
|
1412
|
+
- **`bar`: the component's own bar.** A strip along the whole bottom edge of the viewport, in
|
|
1413
|
+
place of the round launcher: the title, the [unread badge](#the-unread-badge), and a running
|
|
1414
|
+
indicator while an interaction is in flight. Pressing the strip toggles the panel, which rises
|
|
1415
|
+
from the bar's right end with the bar still beneath it as the minimise target. The bar's
|
|
1416
|
+
history button opens the conversation list as a popover above the bar, without expanding the
|
|
1417
|
+
panel, its outer edge in line with the panel's on a wide viewport, and a second press closes
|
|
1418
|
+
it; `openThreads()` while collapsed opens it too. Expanding the panel closes the popover, so the
|
|
1419
|
+
panel opens on the conversation. It replaces the launcher only, so it applies to the corner
|
|
1420
|
+
placements, `side` and `full`: `sidebar` keeps its rail, `embedded` its header bar, and `page`
|
|
1421
|
+
has no collapsed state at all.
|
|
1422
|
+
- **`none`: your own bar.** Collapsed is hidden: nothing of the widget is left to see or hit,
|
|
1423
|
+
under every collapsible placement. Your bar's button drives the [public
|
|
1424
|
+
API](#driving-the-conversation-from-your-own-chrome) (`collapsed`, `toggleCollapsed()`), and
|
|
1425
|
+
`anchor` names the element the panel rises from, right-aligned to it. An anchor that resolves
|
|
1426
|
+
to nothing opens the panel from the placement's own corner, with one console warning.
|
|
1427
|
+
|
|
1428
|
+
```html
|
|
1429
|
+
<nav class="toolbar">
|
|
1430
|
+
<!-- ... -->
|
|
1431
|
+
<button id="agent-button" type="button">Agent</button>
|
|
1432
|
+
</nav>
|
|
1433
|
+
<ag-ui-chat endpoint="/agent/" collapse-to="none" anchor="#agent-button"></ag-ui-chat>
|
|
1434
|
+
<script type="module">
|
|
1435
|
+
const chat = document.querySelector("ag-ui-chat");
|
|
1436
|
+
const button = document.getElementById("agent-button");
|
|
1437
|
+
button.addEventListener("click", () => chat.toggleCollapsed());
|
|
1438
|
+
// Under none the element announces the state it mounted in, once, so the
|
|
1439
|
+
// button can be labelled before anyone presses it.
|
|
1440
|
+
chat.addEventListener("ag-ui-toggle", (e) => {
|
|
1441
|
+
button.setAttribute("aria-pressed", String(!e.detail.collapsed));
|
|
1442
|
+
});
|
|
1443
|
+
</script>
|
|
1444
|
+
```
|
|
1445
|
+
|
|
1446
|
+
**Clearing your toolbar.** Under `none` the panel stands `--ag-ui-anchor-gap` (default `8px`)
|
|
1447
|
+
above the anchor's top edge. The anchor is the button, not the toolbar around it, so a button
|
|
1448
|
+
sitting inside a taller toolbar puts the panel's foot across the toolbar's top border. Set the gap
|
|
1449
|
+
to the button's distance from the toolbar's top plus the clearance you want:
|
|
1450
|
+
|
|
1451
|
+
```css
|
|
1452
|
+
/* The button stands 7px below the toolbar's top edge; clear it by 8px. */
|
|
1453
|
+
ag-ui-chat {
|
|
1454
|
+
--ag-ui-anchor-gap: 15px;
|
|
1455
|
+
}
|
|
1456
|
+
```
|
|
1457
|
+
|
|
1458
|
+
A gap wider than the gutter is taken off the panel's max height as well, so a tall panel still
|
|
1459
|
+
stops at the top of the window.
|
|
1460
|
+
|
|
1461
|
+
Under `none` the element dispatches `ag-ui-toggle` once as it connects, with whichever state it
|
|
1462
|
+
mounted in, collapsed or open. Under `auto` and `bar` it does not, as before. That event touches
|
|
1463
|
+
neither the stored state nor the unread count.
|
|
1464
|
+
|
|
1465
|
+
**The page's space is yours.** The bar is fixed over the page, so a host pads its own page by
|
|
1466
|
+
the bar's height. The component never writes your CSS, and a custom property cannot carry the
|
|
1467
|
+
height up to your page (it inherits down, never up), so it hands you a number:
|
|
1468
|
+
`barHeight` (CSS px, read-only) and an `ag-ui-bar-height` event (the `BAR_HEIGHT_EVENT`
|
|
1469
|
+
constant, detail `{ height }`) on every change, including a font-size change. Both read `0`
|
|
1470
|
+
where no bar is drawn: under `auto` and `none`, and on a phone while the panel is open.
|
|
1471
|
+
|
|
1472
|
+
```js
|
|
1473
|
+
const chat = document.querySelector("ag-ui-chat");
|
|
1474
|
+
const pad = () => {
|
|
1475
|
+
document.documentElement.style.setProperty("--chat-bar-height", `${chat.barHeight}px`);
|
|
1476
|
+
};
|
|
1477
|
+
chat.addEventListener("ag-ui-bar-height", pad);
|
|
1478
|
+
pad();
|
|
1479
|
+
```
|
|
1480
|
+
|
|
1481
|
+
```css
|
|
1482
|
+
body {
|
|
1483
|
+
padding-bottom: var(--chat-bar-height, 0px);
|
|
1484
|
+
}
|
|
1485
|
+
```
|
|
1486
|
+
|
|
1487
|
+
**No inset needed.** Under `bar` and `none` you do not set `--ag-ui-inset` to keep the panel off
|
|
1488
|
+
your toolbar: its max height is the viewport less the bar's height (or, under `none`, the
|
|
1489
|
+
distance to the anchor's top) and one gutter, and its bottom sits on the bar or the anchor.
|
|
1490
|
+
|
|
1491
|
+
**Docked, and still movable.** On a wide viewport a docked corner panel (the corner placements
|
|
1492
|
+
under `bar`, or under `none` with or without an anchor) moves by its header, and `moveTo` moves
|
|
1493
|
+
it, as it would the corner panel it is; `describeSurface()` reports `movable: true`. There is no
|
|
1494
|
+
launcher to drag: the bar and your own control stay where they are.
|
|
1495
|
+
|
|
1496
|
+
- **Above the dock.** A dragged panel stays inside the viewport and above the bar's top edge, so it
|
|
1497
|
+
never covers the bar it minimises to. Under `none` with an anchor it stays above the anchor's
|
|
1498
|
+
top edge the same way, because the anchor is your own way back and has to stay in view;
|
|
1499
|
+
`--ag-ui-anchor-gap` no longer applies once the panel is dragged, and the screen-edge margin
|
|
1500
|
+
(8px) does. Under `none` with no anchor only the viewport holds it, as for a corner panel.
|
|
1501
|
+
- **Remembered like a corner panel.** Minimising and reopening brings it back where it was
|
|
1502
|
+
dragged, and so does a reload. The spot is kept apart from the one a corner panel stores under
|
|
1503
|
+
`auto`, so switching `collapse-to` never puts one surface's spot on the other. A spot that no
|
|
1504
|
+
longer fits, because the window shrank or the bar grew, is held inside the room that is left
|
|
1505
|
+
and comes back whole when there is room again.
|
|
1506
|
+
- **Resizing.** A panel standing on its dock keeps the edges on the bar or the anchor still and the
|
|
1507
|
+
free ones follow the grip. Once dragged off, every edge follows its grip, as on a corner panel.
|
|
1508
|
+
- **Back to the dock.** `resetSize()` drops the dragged size and returns the panel to its dock,
|
|
1509
|
+
forgetting the stored spot, so a reload opens it there too.
|
|
1510
|
+
- **Keeping it fixed.** `data-launcher-drag="false"` turns the header drag and `moveTo` off here as
|
|
1511
|
+
everywhere else, and the panel stays on its dock.
|
|
1512
|
+
|
|
1513
|
+
Placements that own their position (`side` and `full` under `bar`, `sidebar` and `embedded`
|
|
1514
|
+
under `none`) do not move, as without `collapse-to`.
|
|
1515
|
+
|
|
1516
|
+
**Phones.** At 600px or less the open panel stays full-bleed, over the bar, and the header's
|
|
1517
|
+
minimise control is the way back; the bar shows only while collapsed, so no second strip sits
|
|
1518
|
+
at the bottom edge while the keyboard is up. The panel does not move there, and a spot dragged on
|
|
1519
|
+
a wide viewport does not apply: it comes back when the window is wide again.
|
|
1520
|
+
|
|
1521
|
+
The bar is styled through the parts `bar` (the strip's wrapper, holding the launcher and the
|
|
1522
|
+
history button) and `bar-history`, and the launcher's own parts (`launcher`, `rail-label`,
|
|
1523
|
+
`launcher-badge`) inside it.
|
|
1524
|
+
|
|
1525
|
+
|
|
1385
1526
|
---
|
|
1386
1527
|
|
|
1387
1528
|
## Charts
|
|
@@ -1557,7 +1698,7 @@ absent or unknown value reads as `grouped`):
|
|
|
1557
1698
|
|
|
1558
1699
|
- `grouped` — the default. A run's consecutive tool calls fold into one quiet row, **"Worked
|
|
1559
1700
|
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
|
|
1701
|
+
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
1702
|
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
1703
|
[The step group](#the-step-group).
|
|
1563
1704
|
- `inline` — the lightest mode: a single status row (icon + summary, no card chrome) with the
|
|
@@ -1591,6 +1732,25 @@ each card is built: switching **to** `grouped` folds only the calls drawn afterw
|
|
|
1591
1732
|
switching **away** from it flattens the groups already drawn, by CSS, into exactly the cards the
|
|
1592
1733
|
new mode builds (the group stops generating a box and its row is hidden).
|
|
1593
1734
|
|
|
1735
|
+
### Choosing how a group draws its calls
|
|
1736
|
+
|
|
1737
|
+
Under `grouped`, an opened group draws its calls as `full` cards unless the
|
|
1738
|
+
`data-tool-group-display` attribute (or `toolGroupDisplay` property) names another of the card
|
|
1739
|
+
modes: `compact`, `minimal` or `inline`. Each draws the regions the flat card of that mode draws,
|
|
1740
|
+
laid out as a row of the group's list rather than as a boxed card. An absent or unknown value
|
|
1741
|
+
reads as `full`, so nothing changes for a host that does not set it.
|
|
1742
|
+
|
|
1743
|
+
```html
|
|
1744
|
+
<ag-ui-chat endpoint="/agent/" data-tool-group-display="compact"></ag-ui-chat>
|
|
1745
|
+
```
|
|
1746
|
+
|
|
1747
|
+
It is read only under `grouped`. Under one of the four card modes the groups are flattened into
|
|
1748
|
+
that mode's cards and the inner value is ignored; switching back to `grouped` applies it again.
|
|
1749
|
+
It is live like the outer attribute: changing it restyles groups already in the transcript.
|
|
1750
|
+
|
|
1751
|
+
A call waiting on an approval shows its arguments and its Approve and Deny buttons in every inner
|
|
1752
|
+
mode, as it does in every card mode, and Approve takes focus when the group opens for it.
|
|
1753
|
+
|
|
1594
1754
|
### The step group
|
|
1595
1755
|
|
|
1596
1756
|
Under `grouped` the row reads, by state:
|
|
@@ -2844,6 +3004,7 @@ re-export point. Internal modules import from leaf paths.
|
|
|
2844
3004
|
| `SubmitDetail` | type | `detail` shape of the submit event. |
|
|
2845
3005
|
| `ThreadDetail` | type | `detail` shape of the `ag-ui-thread` event (`{ threadId, previousThreadId, reason }`). |
|
|
2846
3006
|
| `ToggleDetail` | type | `detail` shape of the `ag-ui-toggle` event (`{ collapsed }`). |
|
|
3007
|
+
| `BarHeightDetail` | type | `detail` shape of the `ag-ui-bar-height` event (`{ height }`). |
|
|
2847
3008
|
| `UnreadDetail` | type | `detail` shape of the `ag-ui-unread` event (`{ unread }`). |
|
|
2848
3009
|
| `AttachmentsDetail` | type | `detail` shape of the `ag-ui-attachments` event (`{ attachments, pending }`). |
|
|
2849
3010
|
| `StateDetail` | type | `detail` shape of the `ag-ui-state` event (`{ state }`). |
|
|
@@ -2876,7 +3037,7 @@ re-export point. Internal modules import from leaf paths.
|
|
|
2876
3037
|
| `PAGE_ACTIONS` | const | The page-action opt-in tokens (`scroll` / `drag`). |
|
|
2877
3038
|
| `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
3039
|
| `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. |
|
|
3040
|
+
| `ChatSurfaceReport` | type | What `describeSurface()` answers: placement, collapsed, collapseTo, collapsible, movable, draggable, fullBleed, and the panel's box against the viewport it sits in. |
|
|
2880
3041
|
| `ChatCorner` | type | `"top-left"` / `"top-right"` / `"bottom-left"` / `"bottom-right"` — the argument to `moveTo`. |
|
|
2881
3042
|
| `CHAT_CORNERS` | const | Those four, as a list. |
|
|
2882
3043
|
| `isChatCorner(value)` | function | Whether a string names one of them. |
|
|
@@ -2951,6 +3112,7 @@ re-export point. Internal modules import from leaf paths.
|
|
|
2951
3112
|
| --- | --- | --- |
|
|
2952
3113
|
| `ToolCallCard` | class | A live tool-call card for the transcript. |
|
|
2953
3114
|
| `ToolCallStatus` / `SettledStatus` / `ToolDisplayMode` | type | Card lifecycle states + display mode. |
|
|
3115
|
+
| `ToolGroupDisplayMode` | type | How an opened step group draws its calls (`TOOL_GROUP_DISPLAY`'s values). |
|
|
2954
3116
|
| `ToolPayloadFormatter` | type | Draws one region of a card's body (`AgUiChat.formatToolPayload`); `null` falls through to the built-in pretty-print. |
|
|
2955
3117
|
| `ToolPayload` | type | The region being drawn: `arguments` (the parsed record) or `result` (the raw string and its outcome). |
|
|
2956
3118
|
| `ToolCallCardOptions` | type | Per-card wiring beyond name / args / label / strings — currently `formatPayload`. |
|
|
@@ -2994,6 +3156,7 @@ re-export point. Internal modules import from leaf paths.
|
|
|
2994
3156
|
| `SUBMIT_EVENT` | The submit CustomEvent name. |
|
|
2995
3157
|
| `THREAD_EVENT` | The conversation-changed CustomEvent name (`ag-ui-thread`). |
|
|
2996
3158
|
| `TOGGLE_EVENT` | The collapse-toggle CustomEvent name (`ag-ui-toggle`). |
|
|
3159
|
+
| `BAR_HEIGHT_EVENT` | The bottom bar's height CustomEvent name (`ag-ui-bar-height`). |
|
|
2997
3160
|
| `UNREAD_EVENT` | The unread-count CustomEvent name (`ag-ui-unread`). |
|
|
2998
3161
|
| `RUN_FINISHED_EVENT` | The interaction-finished CustomEvent name (`ag-ui-run-finished`). |
|
|
2999
3162
|
| `CUSTOM_AGENT_EVENT` | The agent-`CUSTOM` CustomEvent name (`ag-ui-custom`). |
|
|
@@ -3013,6 +3176,7 @@ re-export point. Internal modules import from leaf paths.
|
|
|
3013
3176
|
| `MESSAGE_ACTIONS` | The message-action tokens `data-message-actions` selects by (`copy` / `retry` / `feedback`). |
|
|
3014
3177
|
| `TOOL_CALL_STATUS` | Tool-call card status constants. |
|
|
3015
3178
|
| `TOOL_DISPLAY` | Tool-call display-mode constants (`inline` / `minimal` / `compact` / `full`). |
|
|
3179
|
+
| `TOOL_GROUP_DISPLAY` | How an opened step group draws its calls under `grouped` (`inline` / `minimal` / `compact` / `full`). |
|
|
3016
3180
|
| `TOOL_OUTCOME` | How a tool call ended, as a server states it on `TOOL_CALL_RESULT` (`success` / `failed` / `denied`). |
|
|
3017
3181
|
| `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
3182
|
| `X_SUMMARY_KEY` | JSON-Schema key carrying a short tool-card label. |
|
|
@@ -3124,11 +3288,20 @@ first, so each stays an override point. The tokens the themes add:
|
|
|
3124
3288
|
- **Charts:** `--ag-ui-chart-1` to `--ag-ui-chart-6`. A host's value beats the theme's.
|
|
3125
3289
|
- **Status marks:** `--ag-ui-ico-check`, `--ag-ui-ico-error`, `--ag-ui-ico-declined`, mask images
|
|
3126
3290
|
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
|
|
3291
|
+
- **Focus:** `--ag-ui-ring`, the step group head's focus outline. Unset, it is two parts accent
|
|
3292
|
+
to three parts ink (`--ag-ui-fg`), which holds 3:1 against the panel for any accent.
|
|
3128
3293
|
|
|
3129
3294
|
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
|
|
3295
|
+
UI font), and Classic inherits the page's font as the component always did. To take the page's font
|
|
3296
|
+
under any theme, set `--ag-ui-font` to the page's family, or to the page's own font token:
|
|
3297
|
+
|
|
3298
|
+
```css
|
|
3299
|
+
ag-ui-chat { --ag-ui-font: var(--body-font); } /* or the family itself */
|
|
3300
|
+
```
|
|
3301
|
+
|
|
3302
|
+
`--ag-ui-font: inherit` does not do this. A CSS-wide keyword in a custom property applies to the
|
|
3303
|
+
custom property itself, so it takes the `--ag-ui-font` of the parent, which nothing sets, and the
|
|
3304
|
+
theme's stack wins.
|
|
3132
3305
|
|
|
3133
3306
|
#### Text on the accent
|
|
3134
3307
|
|
|
@@ -3153,6 +3326,45 @@ fallback white (2.5:1), as it always was. What they miss is the correction for a
|
|
|
3153
3326
|
mid-tone brand accent can fall under 4.5:1 there, under any theme. If you support those browsers
|
|
3154
3327
|
and set a mid-tone accent, set `--ag-ui-on-accent` yourself. There is no script path.
|
|
3155
3328
|
|
|
3329
|
+
#### Keeping a brand accent on the header
|
|
3330
|
+
|
|
3331
|
+
Quiet draws the header, the launcher and the tool names in the panel's own colours, so a host that
|
|
3332
|
+
sets only `--ag-ui-accent` gets a neutral header. To put the accent back without leaving Quiet, set
|
|
3333
|
+
the surfaces to the accent and the text on them to a colour that reads on it:
|
|
3334
|
+
|
|
3335
|
+
```css
|
|
3336
|
+
ag-ui-chat {
|
|
3337
|
+
--ag-ui-header-bg: #3d5afe;
|
|
3338
|
+
--ag-ui-header-fg: #ffffff;
|
|
3339
|
+
--ag-ui-launcher-bg: #3d5afe;
|
|
3340
|
+
--ag-ui-launcher-fg: #ffffff;
|
|
3341
|
+
--ag-ui-tool-fg: #3d5afe;
|
|
3342
|
+
}
|
|
3343
|
+
```
|
|
3344
|
+
|
|
3345
|
+
- **The header buttons follow `--ag-ui-header-fg`.** Unset, Quiet draws them in its third ink at
|
|
3346
|
+
0.85 opacity, on a hover square of the panel's hover shade. Once you set the header text they
|
|
3347
|
+
draw in it at full opacity, and the hover square is the opposite of that text at about a fifth
|
|
3348
|
+
(a darker square under white text, a lighter one under dark text), so a hovered button reads at
|
|
3349
|
+
least what your header pair reads. The same holds under a theme word of your own, which starts
|
|
3350
|
+
from Quiet. No `::part(header-button)` rule is needed. The opposite is computed with relative
|
|
3351
|
+
colour syntax; the browsers without it (see the fallback above) mix the square from the text
|
|
3352
|
+
itself, which on a mid-tone header can take the hovered glyph under your pair (white on
|
|
3353
|
+
`#3d5afe`: 3.75:1).
|
|
3354
|
+
- **`--ag-ui-header-btn-hover` sets the hover square outright** under Quiet and a theme word of your
|
|
3355
|
+
own, whether or not the header text is set, and is drawn exactly as given. Classic, Soft and
|
|
3356
|
+
Ledger draw their own squares and do not read it. For a square that lightens under white text
|
|
3357
|
+
instead, at the cost of contrast on a mid-tone header:
|
|
3358
|
+
|
|
3359
|
+
```css
|
|
3360
|
+
ag-ui-chat { --ag-ui-header-btn-hover: color-mix(in srgb, #ffffff 18%, transparent); }
|
|
3361
|
+
```
|
|
3362
|
+
- **`--ag-ui-tool-fg` colours every tool call**, in a step group as well as in the card displays.
|
|
3363
|
+
Unset, a grouped call is drawn in the second ink (`--ag-ui-ink-2`) under every theme.
|
|
3364
|
+
- Pick the pair yourself: `--ag-ui-header-fg` is not derived from the header colour the way
|
|
3365
|
+
`--ag-ui-on-accent` is from the accent. Under Soft and Ledger the header buttons keep their own
|
|
3366
|
+
third ink whatever you set.
|
|
3367
|
+
|
|
3156
3368
|
#### Overriding a theme, lightest layer first
|
|
3157
3369
|
|
|
3158
3370
|
Four layers, each documented and each lighter than the next. Reach for the first one that does
|
|
@@ -3318,6 +3530,10 @@ keeps between itself and that box. The size cap subtracts the same one, so a
|
|
|
3318
3530
|
panel grown to its limit reaches the far edge of the usable box and no further —
|
|
3319
3531
|
set it to `0` for a panel flush against the corner.
|
|
3320
3532
|
|
|
3533
|
+
`--ag-ui-anchor-gap` (default `8px`) is the gap between the panel and the button
|
|
3534
|
+
it rises from under `collapse-to="none"`; see [Collapsing to a bottom
|
|
3535
|
+
bar](#collapsing-to-a-bottom-bar).
|
|
3536
|
+
|
|
3321
3537
|
`--ag-ui-keyboard-inset` overrides the lift an on-screen keyboard earns. The
|
|
3322
3538
|
widget measures the hidden band and publishes it as
|
|
3323
3539
|
`--ag-ui-visual-viewport-inset-bottom`; state this one instead to outrank that
|
|
@@ -3454,7 +3670,7 @@ component sets, so a new one cannot ship undocumented.
|
|
|
3454
3670
|
| --- | --- |
|
|
3455
3671
|
| 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
3672
|
| 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` |
|
|
3673
|
+
| 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
3674
|
| Answers | `answer` (the per-turn group), `message` (plus `message-user`, `message-assistant`), `code-copy` |
|
|
3459
3675
|
| Reasoning | `thoughts`, `thoughts-toggle`, `thoughts-body`, `thoughts-label` |
|
|
3460
3676
|
| Follow-up suggestions | `suggestions`, `suggestion-chip` |
|
|
@@ -3687,7 +3903,10 @@ mic appears even with no `data-transcribe-url`.
|
|
|
3687
3903
|
`slot="header-actions"`. For convenience, the boolean `data-theme-toggle` attribute adds a built-in
|
|
3688
3904
|
light⇄dark toggle to the header (part `theme-toggle`) that flips the scheme word of `theme` and
|
|
3689
3905
|
persists the choice per tab. Only the scheme changes: `soft` becomes `soft dark`, `soft dark`
|
|
3690
|
-
becomes `soft light`, and `auto` becomes
|
|
3906
|
+
becomes `soft light`, and `auto` becomes the opposite of what the system shows, an explicit
|
|
3907
|
+
choice. With no scheme word the toggle flips the scheme the panel is drawn in, so a host rule
|
|
3908
|
+
that sets the element's `color-scheme` (to follow the page's own dark mode) is flipped from,
|
|
3909
|
+
and the written word then holds against that rule. Only the scheme is saved, too:
|
|
3691
3910
|
on the next load it is put beside whatever theme name the markup carries, so `dark` chosen on a
|
|
3692
3911
|
`soft` page restores as `classic dark` on a `classic` one. Off by default so it never competes with
|
|
3693
3912
|
a host-supplied control.
|