@artooi/ag-ui-web-component 0.14.1 → 0.16.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,108 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.16.0] — 2026-08-09
11
+
12
+ ### Added
13
+
14
+ - **A stale-page guard on frontend tool calls.** A round's context records the
15
+ page it describes; if the page moves before the agent's tool call arrives, the
16
+ call is refused with a result telling the agent to call `read_page` and retry,
17
+ instead of running the handler. Most stale calls would simply miss and report
18
+ a failure — the case this prevents is the other one, where a same-named
19
+ control on the *new* page matches and the agent silently acts on the wrong
20
+ page. `read_page` itself and tools marked `x-navigates` are exempt, and the
21
+ guard is inert unless a `getPageMap` provider is set.
22
+ - **New `UiStrings` keys `runInterrupted` and `pageMoved`**, both overridable
23
+ like every other string.
24
+
25
+ ### Changed
26
+
27
+ - **Toolchain majors: Vitest 3 → 4 and TypeScript 5.9 → 7**, plus `marked`
28
+ 18.0.9, Biome 2.5.7, `@types/node` 26.1.2. All development dependencies — the
29
+ emitted `.d.ts` files are **byte-identical** to the 5.9 output (verified by
30
+ building both and diffing; only the source maps move), so consumers see no
31
+ change.
32
+
33
+ ⚠ **Vitest 4 takes a provider *instance*, not the string `"playwright"`.**
34
+ The provider moved to its own package (`@vitest/browser-playwright`) and, with
35
+ v8 coverage, the old string form is a hard error rather than a deprecation.
36
+
37
+ ⚠ **TypeScript 7 requires `rootDir` explicitly** (TS5011) instead of
38
+ inferring it from the common source directory. Set to the value 5.x inferred,
39
+ so the published layout is unchanged.
40
+
41
+ ### Fixed
42
+
43
+ - **A run interrupted by navigation no longer vanishes silently.** If the page
44
+ navigates or reloads while a run is in flight — routine in an MPA — the
45
+ element is destroyed with it, and on the next mount the transcript replayed
46
+ with the answer simply missing and no indication anything had gone wrong. The
47
+ element now reports it as an inline notice. Detected from the shape of the
48
+ transcript (`send()` persists the user turn *before* starting the run, so a
49
+ history ending on that turn means nothing came back), which is why it needs no
50
+ `ClientConversationStore` change and no `pagehide` listener — neither of which
51
+ would fire on a crash or a force-quit anyway.
52
+
53
+ It is deliberately **a notice, not a resume**: AG-UI has no
54
+ resume-an-aborted-run primitive, so re-sending the accumulated messages is
55
+ semantically a new run and would re-execute any server-side tool the agent had
56
+ already performed. The agent-initiated case is unaffected — a navigating tool
57
+ still checkpoints and resumes exactly as before.
58
+
59
+ - **Six branches that were never actually covered.** Vitest 4's v8 provider
60
+ remaps coverage more precisely, and the 100% gate stopped being satisfiable —
61
+ not because anything regressed, but because v3 had been crediting six
62
+ branches and three callbacks that no test reached. Each is now genuinely
63
+ tested: the paperclip button opening the file picker, the built-in
64
+ transcription handler (every prior voice test supplied its own), a page-action
65
+ tool resolving through `resolvePageTarget`, a non-`Enter` keystroke in a
66
+ question card, a submit click with no answer, a non-string `error` in a
67
+ transcription error body, and a restored history message with an unrecognised
68
+ role.
69
+
70
+ ⭐ **One was a flaw in the test harness, not a missing test.** `makeFakeAgent`
71
+ ended a clean run by calling `onRunFinalized` alone, so the client's
72
+ `RUN_FINISHED` path could only ever be reached through `emit.interrupt()` —
73
+ the ordinary success outcome every real run carries was never exercised. The
74
+ fake now emits both events, in the order a real agent does.
75
+
76
+ `route_map`'s unreachable guard was restructured away rather than tested: its
77
+ regex capture group is mandatory, so the `undefined` case existed only to
78
+ satisfy `noUncheckedIndexedAccess` and no test could ever have reached it.
79
+
80
+ ## [0.15.0] — 2026-08-08
81
+
82
+ ### Changed
83
+
84
+ - **Sanitisation is now tested in a real browser.** `vitest.config.ts` defines
85
+ two projects: **happy-dom** for the bulk of the suite, and **Chromium**
86
+ (Playwright) for the tests whose subject is sanitisation. Coverage stays
87
+ unified at 100% across both.
88
+
89
+ ⚠ **A correctness requirement, not an optimisation.** DOMPurify 3.4.8+
90
+ silently stops sanitising under happy-dom — `<script>` and `<img>` pass
91
+ straight through, and ordinary markdown loses its `<p>` wrapper. A
92
+ happy-dom-only suite can therefore go green while this component ships no
93
+ sanitisation at all, which is the one failure it must never ship.
94
+
95
+ ⭐ **The experiment settles what the pin never could**: dompurify 3.4.13
96
+ sanitises correctly in Chromium. The defect is happy-dom's DOM emulation, not
97
+ a DOMPurify regression — so **consumers were never exposed**, and the risk was
98
+ confined to the test environment the whole time.
99
+
100
+ The browser run also *removes* a workaround instead of carrying it: happy-dom
101
+ eagerly **executed** inline `<script>` while DOMPurify parsed into its scratch
102
+ document, so the suite had to stub `alert`. A real browser parses into an
103
+ inert context.
104
+
105
+ ### Security
106
+
107
+ - **`dompurify` is a normal caret range again** (`^3.4.13`), lifting the
108
+ exact-version pin — and with it the **five advisories** that pin was holding
109
+ open (three LOW, two MEDIUM). The browser project is what made that safe, and
110
+ is the standing acceptance check.
111
+
10
112
  ## [0.14.1] — 2026-08-07
11
113
 
12
114
  ### Security
@@ -646,7 +748,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
646
748
  ### Notes
647
749
  - First release — exercising the automated npm OIDC publish pipeline end-to-end.
648
750
 
649
- [Unreleased]: https://github.com/Artui/ag-ui-web-component/compare/v0.14.1...HEAD
751
+ [Unreleased]: https://github.com/Artui/ag-ui-web-component/compare/v0.16.0...HEAD
752
+ [0.16.0]: https://github.com/Artui/ag-ui-web-component/compare/v0.15.0...v0.16.0
753
+ [0.15.0]: https://github.com/Artui/ag-ui-web-component/compare/v0.14.1...v0.15.0
650
754
  [0.14.1]: https://github.com/Artui/ag-ui-web-component/compare/v0.14.0...v0.14.1
651
755
  [0.14.0]: https://github.com/Artui/ag-ui-web-component/compare/v0.13.0...v0.14.0
652
756
  [0.13.0]: https://github.com/Artui/ag-ui-web-component/compare/v0.12.0...v0.13.0
package/README.md CHANGED
@@ -648,13 +648,24 @@ chat.routeMap = [
648
648
 
649
649
  **`getPageMap(): PageMap`** — a per-run provider returning the current page's compact actionable
650
650
  surface (field names/types/labels, button labels+handles — *not* values). It is auto-injected into
651
- each run's `context` as a `page_map` entry (toggle with `autoInjectPageMap`). Recomputed every run
652
- so it reflects the page the agent is currently looking at:
651
+ each run's `context` as a `page_map` entry (toggle with `autoInjectPageMap`):
653
652
 
654
653
  ```js
655
654
  chat.getPageMap = () => ({ fields: introspectForm(), buttons: visibleButtons() });
656
655
  ```
657
656
 
657
+ It is recomputed at the top of **every tool round**, not once per `send()` — so after the agent
658
+ acts, the next round already sees the resulting page. Within a round the agent can pull a fresh
659
+ view at any time with the built-in `read_page` tool, which is registered whenever this provider is
660
+ set.
661
+
662
+ That leaves one window: the page can move *after* a round's context was built but *before* the
663
+ agent's tool call arrives — the user clicks a link, or presses back. Calls landing in that window
664
+ are **refused** with a result telling the agent to call `read_page` and retry. Most would have
665
+ missed anyway; the guard exists for the case where a same-named control on the new page matches and
666
+ the agent would otherwise act on the wrong page without either side noticing. `read_page` and tools
667
+ marked `x-navigates` are exempt, and the guard is inert when no `getPageMap` is set.
668
+
658
669
  **`registerPageState({ name, read, write?, schema? })`** — ergonomic sugar over `registerTool` for
659
670
  SPA app state (Redux/Zustand/signals). It auto-generates a `read_<name>` (read-only) tool and, when
660
671
  `write` is supplied, a `set_<name>` tool stamped `x-destructive`: