@artooi/ag-ui-web-component 0.25.2 → 0.26.1
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 +92 -1
- package/README.md +89 -0
- package/dist/ag-ui-web-component.bundle.js +73 -29
- package/dist/ag-ui-web-component.bundle.js.map +4 -4
- package/dist/constants.d.ts +10 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/core/ag_ui_chat.d.ts +19 -0
- package/dist/core/ag_ui_chat.d.ts.map +1 -1
- package/dist/core/agui_client.d.ts +12 -1
- package/dist/core/agui_client.d.ts.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +726 -165
- package/dist/index.js.map +4 -4
- package/dist/tools/client_tool_registry.d.ts +33 -1
- package/dist/tools/client_tool_registry.d.ts.map +1 -1
- package/dist/ui/chart_block.d.ts +39 -0
- package/dist/ui/chart_block.d.ts.map +1 -0
- package/dist/ui/chart_spec_from.d.ts +12 -0
- package/dist/ui/chart_spec_from.d.ts.map +1 -0
- package/dist/ui/chart_tool.d.ts +15 -0
- package/dist/ui/chart_tool.d.ts.map +1 -0
- package/dist/ui/styles.d.ts +1 -1
- package/dist/ui/styles.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/constants.ts +11 -0
- package/src/core/ag_ui_chat.ts +165 -3
- package/src/core/agui_client.ts +51 -3
- package/src/index.ts +8 -0
- package/src/tools/client_tool_registry.ts +34 -1
- package/src/ui/chart_block.ts +354 -0
- package/src/ui/chart_spec_from.ts +125 -0
- package/src/ui/chart_tool.ts +72 -0
- package/src/ui/styles.ts +44 -0
- package/src/version.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,95 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.26.1] — 2026-08-25
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- **A chart the server retracted stayed on screen.** When an update replaced a
|
|
15
|
+
chart with a payload that could not be drawn, the superseded chart was left in
|
|
16
|
+
place — showing numbers the server had already withdrawn, reading as current —
|
|
17
|
+
and then vanished on the next reload, because the *stored* content was the
|
|
18
|
+
version that could not be drawn. Live and reload now agree, and both say gone.
|
|
19
|
+
|
|
20
|
+
- **`enableCharts()` after the element connected silently dropped every chart in
|
|
21
|
+
restored history.** History replays on connect, and charts were off at that
|
|
22
|
+
moment, so they were skipped. That is the ordinary way to call it — you have
|
|
23
|
+
to query the element to call anything on it — so the first call now redraws
|
|
24
|
+
rather than the docs asking for an ordering nobody can satisfy. The README
|
|
25
|
+
example was that order.
|
|
26
|
+
|
|
27
|
+
- **A stacked chart wrote `NaN` into the DOM** for a series carrying more points
|
|
28
|
+
than there are labels. `renderChart` is exported, so it can be handed a spec
|
|
29
|
+
the validator would have refused; a cast there claimed that could not happen.
|
|
30
|
+
|
|
31
|
+
- **A sparse `labels` array was accepted**, drawing a chart with blank axis
|
|
32
|
+
labels — `Array.prototype.some` skips holes.
|
|
33
|
+
|
|
34
|
+
- **A spec inside the point budget could still block the main thread.** The
|
|
35
|
+
point limit bounds the data; the DOM is bounded by labels, since each emits an
|
|
36
|
+
axis node whatever the series count. Now capped at 2,000 labels, and the
|
|
37
|
+
ceiling applies again on every reload of a stored conversation.
|
|
38
|
+
|
|
39
|
+
### Documentation
|
|
40
|
+
|
|
41
|
+
- **Whether a pushed chart survives a reload depends on where the conversation
|
|
42
|
+
is stored**, and the README now says which is which. A client-side store keeps
|
|
43
|
+
activities; a server storing the thread as the model's message history does
|
|
44
|
+
not, because a pushed chart is deliberately not in that history. An
|
|
45
|
+
agent-requested chart survives either way — its spec travels as the tool
|
|
46
|
+
call's arguments.
|
|
47
|
+
|
|
48
|
+
### Changed
|
|
49
|
+
|
|
50
|
+
- **The handler/render split is now enforced by a signature rather than a
|
|
51
|
+
comment.** The replay path is handed the `render` function alone, never the
|
|
52
|
+
tool that owns it, so the code that runs on restore cannot reach `handler`.
|
|
53
|
+
The documentation claimed this guarantee was structural while the code passed
|
|
54
|
+
the whole tool around and relied on two call sites happening not to use it.
|
|
55
|
+
|
|
56
|
+
- The built-in chart tool no longer builds the chart twice per call, once only
|
|
57
|
+
to choose its reply string.
|
|
58
|
+
|
|
59
|
+
## [0.26.0] — 2026-08-25
|
|
60
|
+
|
|
61
|
+
### Added
|
|
62
|
+
|
|
63
|
+
- **Charts in the transcript**, by two routes that share one renderer, both
|
|
64
|
+
opt-in via a new `enableCharts(routes)` method. Nothing draws a chart unless a
|
|
65
|
+
host asks for it.
|
|
66
|
+
|
|
67
|
+
- `enableCharts(["tool"])` registers a `render_chart` frontend tool the agent
|
|
68
|
+
can call. The numbers are in its context, so it can discuss them.
|
|
69
|
+
- `enableCharts(["activity"])` draws a server-pushed `ACTIVITY_SNAPSHOT` of
|
|
70
|
+
type `chart`. The data never enters the model's context, there is no extra
|
|
71
|
+
model round, and only this route can update a chart in place — repeat a
|
|
72
|
+
`messageId` to redraw, or send an `ACTIVITY_DELTA` to move one series.
|
|
73
|
+
|
|
74
|
+
Bar, line, pie, scatter and stacked, drawn as SVG built with `createElement`
|
|
75
|
+
and never parsed from a string. That is the reason a chart is safe on a
|
|
76
|
+
surface that keeps `img` off by default: the model chooses the numbers, the
|
|
77
|
+
component chooses the DOM, so nothing chart-shaped reaches the sanitiser at
|
|
78
|
+
all. Six theme tokens, `--ag-ui-chart-1` through `--ag-ui-chart-6`, and three
|
|
79
|
+
parts: `chart-block`, `chart-title`, `chart-legend`.
|
|
80
|
+
|
|
81
|
+
- **`ClientTool.render`** — an optional, pure `(args) => Node | null` beside
|
|
82
|
+
`handler`, and **the only half a restored transcript replays**. Replaying a
|
|
83
|
+
tool's *effect* is out of the question — re-running a form-filling tool on
|
|
84
|
+
every reload is a bug — so the two halves are separated structurally rather
|
|
85
|
+
than by a flag: the restore path holds no reference to `handler`, so it cannot
|
|
86
|
+
run it whatever a tool author intended. `render` must be a pure, deterministic
|
|
87
|
+
function of its arguments; it runs again on every restore.
|
|
88
|
+
|
|
89
|
+
### Changed
|
|
90
|
+
|
|
91
|
+
- **`AgUiClientHandlers` gained a required `onActivityChanged` member**, and
|
|
92
|
+
`onActivity` now receives the activity's `messageId` as a third argument. Both
|
|
93
|
+
types are exported, so a consumer implementing the handler interface directly
|
|
94
|
+
must add the member; anyone using `<ag-ui-chat>` is unaffected.
|
|
95
|
+
- `ClientTool.handler` now receives an optional `callId` as a second argument,
|
|
96
|
+
for a handler that renders into the transcript and needs to place itself
|
|
97
|
+
against its own card. Existing one-parameter handlers are unaffected.
|
|
98
|
+
|
|
10
99
|
## [0.25.2] — 2026-08-25
|
|
11
100
|
|
|
12
101
|
### Fixed
|
|
@@ -1573,7 +1662,9 @@ hosts that both arrange the page the way it expects.
|
|
|
1573
1662
|
### Notes
|
|
1574
1663
|
- First release — exercising the automated npm OIDC publish pipeline end-to-end.
|
|
1575
1664
|
|
|
1576
|
-
[Unreleased]: https://github.com/Artui/ag-ui-web-component/compare/v0.
|
|
1665
|
+
[Unreleased]: https://github.com/Artui/ag-ui-web-component/compare/v0.26.1...HEAD
|
|
1666
|
+
[0.26.1]: https://github.com/Artui/ag-ui-web-component/compare/v0.26.0...v0.26.1
|
|
1667
|
+
[0.26.0]: https://github.com/Artui/ag-ui-web-component/compare/v0.25.2...v0.26.0
|
|
1577
1668
|
[0.25.2]: https://github.com/Artui/ag-ui-web-component/compare/v0.25.1...v0.25.2
|
|
1578
1669
|
[0.25.1]: https://github.com/Artui/ag-ui-web-component/compare/v0.25.0...v0.25.1
|
|
1579
1670
|
[0.25.0]: https://github.com/Artui/ag-ui-web-component/compare/v0.24.0...v0.25.0
|
package/README.md
CHANGED
|
@@ -856,6 +856,94 @@ ag-ui-chat {
|
|
|
856
856
|
|
|
857
857
|
---
|
|
858
858
|
|
|
859
|
+
## Charts
|
|
860
|
+
|
|
861
|
+
Markdown here goes through a narrow sanitiser and images are off by default — a
|
|
862
|
+
model-controlled image URL is fetched with no user interaction, which turns
|
|
863
|
+
prompt-injected page data into a zero-click exfiltration channel. So a chart
|
|
864
|
+
does not arrive as markup. It arrives as **data**, and the component builds the
|
|
865
|
+
SVG itself: the model chooses the numbers, the component chooses the DOM.
|
|
866
|
+
|
|
867
|
+
Off unless you ask for it, by either route or both:
|
|
868
|
+
|
|
869
|
+
```js
|
|
870
|
+
const chat = document.querySelector("ag-ui-chat");
|
|
871
|
+
chat.enableCharts(["tool", "activity"]);
|
|
872
|
+
```
|
|
873
|
+
|
|
874
|
+
Order does not matter. Calling it after the element is on the page redraws any
|
|
875
|
+
charts already in the restored history, so you do not have to reach the element
|
|
876
|
+
before it connects — which you generally cannot.
|
|
877
|
+
|
|
878
|
+
Specs are bounded, and anything outside is dropped rather than half-drawn: at
|
|
879
|
+
most **20,000 points** and **2,000 labels**, and every point a finite number no
|
|
880
|
+
larger than **1e15**. The first two keep a stored transcript from blocking the
|
|
881
|
+
main thread on every reload; the last one keeps the value range finite, since
|
|
882
|
+
scaling divides by it.
|
|
883
|
+
|
|
884
|
+
**`"tool"`** registers a `render_chart` tool the agent may call. The numbers are
|
|
885
|
+
in its context, so it can talk about them; it costs one model round.
|
|
886
|
+
|
|
887
|
+
**`"activity"`** draws a chart the server pushes as an `ACTIVITY_SNAPSHOT` with
|
|
888
|
+
`activityType: "chart"` (exported as `CHART_ACTIVITY_TYPE`). The data never
|
|
889
|
+
reaches the model, there is no extra round, and this is the only route that can
|
|
890
|
+
**update a chart in place** — the server repeats the same `messageId` to redraw
|
|
891
|
+
it, or sends an `ACTIVITY_DELTA` to move one series as a computation advances.
|
|
892
|
+
|
|
893
|
+
**Whether a pushed chart survives a reload depends on where the conversation is
|
|
894
|
+
stored.** A client-side store keeps activities, so it comes back. A server that
|
|
895
|
+
stores the thread as the model's message history does not — a pushed chart is
|
|
896
|
+
deliberately not in that history, which is the reason to push it. A chart the
|
|
897
|
+
agent asked for survives either way, because its spec travels as the tool call's
|
|
898
|
+
arguments and the component redraws from those without re-running anything.
|
|
899
|
+
|
|
900
|
+
Either way the payload is the same shape:
|
|
901
|
+
|
|
902
|
+
```json
|
|
903
|
+
{
|
|
904
|
+
"kind": "bar",
|
|
905
|
+
"title": "Signups this week",
|
|
906
|
+
"labels": ["Mon", "Tue", "Wed"],
|
|
907
|
+
"series": [{ "label": "new", "points": [12, 19, 9] }]
|
|
908
|
+
}
|
|
909
|
+
```
|
|
910
|
+
|
|
911
|
+
`kind` is one of `bar`, `line`, `pie`, `scatter`, `stacked`; anything else is
|
|
912
|
+
drawn as a bar rather than refused. Every series needs exactly one point per
|
|
913
|
+
label — a shorter one misaligns every value after the gap, and a chart that is
|
|
914
|
+
subtly wrong still reads as authoritative, so the whole spec is dropped instead.
|
|
915
|
+
A pie's slices are its labels, so it draws the first series only.
|
|
916
|
+
|
|
917
|
+
Theme the series with `--ag-ui-chart-1` … `--ag-ui-chart-6`, and style the block
|
|
918
|
+
through the `chart-block`, `chart-title` and `chart-legend` parts.
|
|
919
|
+
|
|
920
|
+
### Drawing something other than a chart
|
|
921
|
+
|
|
922
|
+
`render_chart` is built on a seam any tool can use. A `ClientTool` may declare a
|
|
923
|
+
pure `render` beside its `handler`:
|
|
924
|
+
|
|
925
|
+
```js
|
|
926
|
+
chat.registerTool({
|
|
927
|
+
name: "show_route",
|
|
928
|
+
description: "Draw the route on a map.",
|
|
929
|
+
parameters: { type: "object", properties: { stops: { type: "array" } } },
|
|
930
|
+
handler: () => "route shown",
|
|
931
|
+
render: (args) => buildMapElement(args.stops), // pure; no side effects
|
|
932
|
+
});
|
|
933
|
+
```
|
|
934
|
+
|
|
935
|
+
**`render` is the only half a restored transcript replays.** Replaying a tool's
|
|
936
|
+
*effect* is out of the question — re-running a form-filling tool on every reload
|
|
937
|
+
is a bug. The replay path is handed the `render` function alone, never the tool
|
|
938
|
+
that owns it, so the code that runs on restore cannot reach `handler` even by
|
|
939
|
+
mistake: adding a "no render? fall back to the handler" convenience there means
|
|
940
|
+
changing a type signature first, which is the moment the question gets asked.
|
|
941
|
+
|
|
942
|
+
That is why `render` has to be a pure, deterministic function of its arguments —
|
|
943
|
+
it runs again every time the conversation is restored.
|
|
944
|
+
|
|
945
|
+
---
|
|
946
|
+
|
|
859
947
|
## Tool-call display modes
|
|
860
948
|
|
|
861
949
|
How much a tool-call card shows is set via the `data-tool-display` attribute (or `toolDisplay`
|
|
@@ -1598,6 +1686,7 @@ component sets, so a new one cannot ship undocumented.
|
|
|
1598
1686
|
| Attachments | `attachment-tray`, `attachment-chips` (the read-only chips on sent bubbles), and the shared chip parts `attachment-chip`, `attachment-chip-icon`, `attachment-chip-name`, `attachment-chip-size`, `attachment-chip-bar`, `attachment-chip-bar-fill`, `attachment-chip-retry`, `attachment-chip-remove` |
|
|
1599
1687
|
| Skills | `skill-chips`, `skill-chip`, `skill-palette`, `skill-item`, `skill-item-title`, `skill-item-desc`, `skill-item-token`, `skill-hint` (the missing-placeholder hint) |
|
|
1600
1688
|
| Thread drawer | `drawer`, `drawer-backdrop`, `drawer-panel`, `drawer-header`, `drawer-title`, `drawer-new`, `drawer-list`, `drawer-empty`, `drawer-row`, `drawer-row-select`, `drawer-row-title`, `drawer-row-time`, `drawer-row-preview`, `drawer-row-actions`, `drawer-row-rename`, `drawer-row-delete`, `drawer-rename-input`, `drawer-confirm`, `drawer-confirm-label`, `drawer-confirm-yes`, `drawer-confirm-no` |
|
|
1689
|
+
| Charts | `chart-block`, `chart-title`, `chart-legend` |
|
|
1601
1690
|
| Checkpoints panel | `checkpoints`, `checkpoints-header`, `checkpoints-title`, `checkpoints-list`, `checkpoints-empty`, `checkpoint-row`, `checkpoint-label`, `checkpoint-time`, `checkpoint-id`, `checkpoint-branch`, `checkpoint-action` (plus `checkpoint-resume`, `checkpoint-fork`) |
|
|
1602
1691
|
|
|
1603
1692
|
> **Hiding `::part(header)` hides the controls inside it.** The history, checkpoints, new-chat,
|