@artooi/ag-ui-web-component 0.25.1 → 0.26.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 CHANGED
@@ -7,6 +7,65 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.26.0] — 2026-08-25
11
+
12
+ ### Added
13
+
14
+ - **Charts in the transcript**, by two routes that share one renderer, both
15
+ opt-in via a new `enableCharts(routes)` method. Nothing draws a chart unless a
16
+ host asks for it.
17
+
18
+ - `enableCharts(["tool"])` registers a `render_chart` frontend tool the agent
19
+ can call. The numbers are in its context, so it can discuss them.
20
+ - `enableCharts(["activity"])` draws a server-pushed `ACTIVITY_SNAPSHOT` of
21
+ type `chart`. The data never enters the model's context, there is no extra
22
+ model round, and only this route can update a chart in place — repeat a
23
+ `messageId` to redraw, or send an `ACTIVITY_DELTA` to move one series.
24
+
25
+ Bar, line, pie, scatter and stacked, drawn as SVG built with `createElement`
26
+ and never parsed from a string. That is the reason a chart is safe on a
27
+ surface that keeps `img` off by default: the model chooses the numbers, the
28
+ component chooses the DOM, so nothing chart-shaped reaches the sanitiser at
29
+ all. Six theme tokens, `--ag-ui-chart-1` through `--ag-ui-chart-6`, and three
30
+ parts: `chart-block`, `chart-title`, `chart-legend`.
31
+
32
+ - **`ClientTool.render`** — an optional, pure `(args) => Node | null` beside
33
+ `handler`, and **the only half a restored transcript replays**. Replaying a
34
+ tool's *effect* is out of the question — re-running a form-filling tool on
35
+ every reload is a bug — so the two halves are separated structurally rather
36
+ than by a flag: the restore path holds no reference to `handler`, so it cannot
37
+ run it whatever a tool author intended. `render` must be a pure, deterministic
38
+ function of its arguments; it runs again on every restore.
39
+
40
+ ### Changed
41
+
42
+ - **`AgUiClientHandlers` gained a required `onActivityChanged` member**, and
43
+ `onActivity` now receives the activity's `messageId` as a third argument. Both
44
+ types are exported, so a consumer implementing the handler interface directly
45
+ must add the member; anyone using `<ag-ui-chat>` is unaffected.
46
+ - `ClientTool.handler` now receives an optional `callId` as a second argument,
47
+ for a handler that renders into the transcript and needs to place itself
48
+ against its own card. Existing one-parameter handlers are unaffected.
49
+
50
+ ## [0.25.2] — 2026-08-25
51
+
52
+ ### Fixed
53
+
54
+ - **A server-side tool round went silent between the tool card and the answer.**
55
+ The pending indicator is hidden when a tool call arrives, so the card can be
56
+ the live thing on screen. Client-side tools put it back before returning their
57
+ result; the server-side path never did — so once a streamed result settled the
58
+ card, the wait while the server called the model again had nothing to own it.
59
+ With a large attachment inlined into the tool result, and re-sent with every
60
+ subsequent request, that is the longest pause in a run.
61
+
62
+ The indicator now returns when a streamed result settles a card, and is
63
+ cleared by whatever comes next: reasoning, the first text delta, the round
64
+ ending, or the terminal settle guarantee. This is not the case 0.2.1 removed
65
+ it for — that one runs after the run has ended, where nothing would clear it.
66
+ The terminal guarantee that shipped in the same release is what makes showing
67
+ it here safe.
68
+
10
69
  ## [0.25.1] — 2026-08-24
11
70
 
12
71
  ### Fixed
@@ -1554,7 +1613,9 @@ hosts that both arrange the page the way it expects.
1554
1613
  ### Notes
1555
1614
  - First release — exercising the automated npm OIDC publish pipeline end-to-end.
1556
1615
 
1557
- [Unreleased]: https://github.com/Artui/ag-ui-web-component/compare/v0.25.1...HEAD
1616
+ [Unreleased]: https://github.com/Artui/ag-ui-web-component/compare/v0.26.0...HEAD
1617
+ [0.26.0]: https://github.com/Artui/ag-ui-web-component/compare/v0.25.2...v0.26.0
1618
+ [0.25.2]: https://github.com/Artui/ag-ui-web-component/compare/v0.25.1...v0.25.2
1558
1619
  [0.25.1]: https://github.com/Artui/ag-ui-web-component/compare/v0.25.0...v0.25.1
1559
1620
  [0.25.0]: https://github.com/Artui/ag-ui-web-component/compare/v0.24.0...v0.25.0
1560
1621
  [0.24.0]: https://github.com/Artui/ag-ui-web-component/compare/v0.23.1...v0.24.0
package/README.md CHANGED
@@ -856,6 +856,74 @@ 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
+ **`"tool"`** registers a `render_chart` tool the agent may call. The numbers are
875
+ in its context, so it can talk about them; it costs one model round.
876
+
877
+ **`"activity"`** draws a chart the server pushes as an `ACTIVITY_SNAPSHOT` with
878
+ `activityType: "chart"` (exported as `CHART_ACTIVITY_TYPE`). The data never
879
+ reaches the model, there is no extra round, and this is the only route that can
880
+ **update a chart in place** — the server repeats the same `messageId` to redraw
881
+ it, or sends an `ACTIVITY_DELTA` to move one series as a computation advances.
882
+
883
+ Either way the payload is the same shape:
884
+
885
+ ```json
886
+ {
887
+ "kind": "bar",
888
+ "title": "Signups this week",
889
+ "labels": ["Mon", "Tue", "Wed"],
890
+ "series": [{ "label": "new", "points": [12, 19, 9] }]
891
+ }
892
+ ```
893
+
894
+ `kind` is one of `bar`, `line`, `pie`, `scatter`, `stacked`; anything else is
895
+ drawn as a bar rather than refused. Every series needs exactly one point per
896
+ label — a shorter one misaligns every value after the gap, and a chart that is
897
+ subtly wrong still reads as authoritative, so the whole spec is dropped instead.
898
+ A pie's slices are its labels, so it draws the first series only.
899
+
900
+ Theme the series with `--ag-ui-chart-1` … `--ag-ui-chart-6`, and style the block
901
+ through the `chart-block`, `chart-title` and `chart-legend` parts.
902
+
903
+ ### Drawing something other than a chart
904
+
905
+ `render_chart` is built on a seam any tool can use. A `ClientTool` may declare a
906
+ pure `render` beside its `handler`:
907
+
908
+ ```js
909
+ chat.registerTool({
910
+ name: "show_route",
911
+ description: "Draw the route on a map.",
912
+ parameters: { type: "object", properties: { stops: { type: "array" } } },
913
+ handler: () => "route shown",
914
+ render: (args) => buildMapElement(args.stops), // pure; no side effects
915
+ });
916
+ ```
917
+
918
+ **`render` is the only half a restored transcript replays.** Replaying a tool's
919
+ *effect* is out of the question — re-running a form-filling tool on every reload
920
+ is a bug — so the restore path holds no reference to `handler` and cannot run
921
+ it. That makes the guarantee structural rather than a promise, and it is why
922
+ `render` has to be a pure, deterministic function of its arguments: it runs
923
+ again every time the conversation is restored.
924
+
925
+ ---
926
+
859
927
  ## Tool-call display modes
860
928
 
861
929
  How much a tool-call card shows is set via the `data-tool-display` attribute (or `toolDisplay`
@@ -1598,6 +1666,7 @@ component sets, so a new one cannot ship undocumented.
1598
1666
  | 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
1667
  | 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
1668
  | 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` |
1669
+ | Charts | `chart-block`, `chart-title`, `chart-legend` |
1601
1670
  | 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
1671
 
1603
1672
  > **Hiding `::part(header)` hides the controls inside it.** The history, checkpoints, new-chat,