@artooi/ag-ui-web-component 0.23.0 → 0.23.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.
Files changed (121) hide show
  1. package/CHANGELOG.md +73 -36
  2. package/README.md +7 -7
  3. package/dist/ag-ui-web-component.bundle.js +98 -117
  4. package/dist/ag-ui-web-component.bundle.js.map +3 -3
  5. package/dist/constants.d.ts +56 -85
  6. package/dist/constants.d.ts.map +1 -1
  7. package/dist/core/ag_ui_chat.d.ts +90 -127
  8. package/dist/core/ag_ui_chat.d.ts.map +1 -1
  9. package/dist/core/agui_client.d.ts +24 -30
  10. package/dist/core/agui_client.d.ts.map +1 -1
  11. package/dist/core/attachment.d.ts +9 -14
  12. package/dist/core/attachment.d.ts.map +1 -1
  13. package/dist/core/conversation_store.d.ts +20 -27
  14. package/dist/core/conversation_store.d.ts.map +1 -1
  15. package/dist/core/create_http_agent.d.ts +13 -15
  16. package/dist/core/create_http_agent.d.ts.map +1 -1
  17. package/dist/core/remote_conversation_store.d.ts +8 -9
  18. package/dist/core/remote_conversation_store.d.ts.map +1 -1
  19. package/dist/core/run_index.d.ts +11 -20
  20. package/dist/core/run_index.d.ts.map +1 -1
  21. package/dist/core/transcribe_audio.d.ts +8 -8
  22. package/dist/core/transcribe_audio.d.ts.map +1 -1
  23. package/dist/core/upload_attachment.d.ts +15 -18
  24. package/dist/core/upload_attachment.d.ts.map +1 -1
  25. package/dist/core/utils.d.ts +4 -6
  26. package/dist/core/utils.d.ts.map +1 -1
  27. package/dist/dom/animations.d.ts +22 -30
  28. package/dist/dom/animations.d.ts.map +1 -1
  29. package/dist/dom/dom_driver.d.ts +7 -7
  30. package/dist/dom/native_setter.d.ts +2 -2
  31. package/dist/dom/native_setter.d.ts.map +1 -1
  32. package/dist/index.js +290 -378
  33. package/dist/index.js.map +2 -2
  34. package/dist/skills/fill_template.d.ts +4 -5
  35. package/dist/skills/fill_template.d.ts.map +1 -1
  36. package/dist/skills/parse_skills.d.ts.map +1 -1
  37. package/dist/skills/skill.d.ts +7 -8
  38. package/dist/skills/skill.d.ts.map +1 -1
  39. package/dist/tools/client_tool_registry.d.ts +2 -2
  40. package/dist/tools/page_action_tools.d.ts +7 -10
  41. package/dist/tools/page_action_tools.d.ts.map +1 -1
  42. package/dist/tools/page_state.d.ts +5 -8
  43. package/dist/tools/page_state.d.ts.map +1 -1
  44. package/dist/tools/route_map.d.ts +7 -10
  45. package/dist/tools/route_map.d.ts.map +1 -1
  46. package/dist/ui/approval_card.d.ts +15 -20
  47. package/dist/ui/approval_card.d.ts.map +1 -1
  48. package/dist/ui/attach_copy_buttons.d.ts +4 -10
  49. package/dist/ui/attach_copy_buttons.d.ts.map +1 -1
  50. package/dist/ui/attachment_chips.d.ts +7 -10
  51. package/dist/ui/attachment_chips.d.ts.map +1 -1
  52. package/dist/ui/attachment_tray.d.ts +6 -6
  53. package/dist/ui/checkpoint_menu.d.ts +7 -8
  54. package/dist/ui/checkpoint_menu.d.ts.map +1 -1
  55. package/dist/ui/confirmation_card.d.ts +10 -15
  56. package/dist/ui/confirmation_card.d.ts.map +1 -1
  57. package/dist/ui/question_card.d.ts +12 -15
  58. package/dist/ui/question_card.d.ts.map +1 -1
  59. package/dist/ui/relative_time.d.ts +5 -7
  60. package/dist/ui/relative_time.d.ts.map +1 -1
  61. package/dist/ui/render_markdown.d.ts +8 -8
  62. package/dist/ui/render_markdown.d.ts.map +1 -1
  63. package/dist/ui/resize_handle.d.ts +21 -34
  64. package/dist/ui/resize_handle.d.ts.map +1 -1
  65. package/dist/ui/run_notice.d.ts +5 -7
  66. package/dist/ui/run_notice.d.ts.map +1 -1
  67. package/dist/ui/skills_menu.d.ts +4 -5
  68. package/dist/ui/skills_menu.d.ts.map +1 -1
  69. package/dist/ui/styles.d.ts +1 -1
  70. package/dist/ui/styles.d.ts.map +1 -1
  71. package/dist/ui/thoughts_block.d.ts +9 -11
  72. package/dist/ui/thoughts_block.d.ts.map +1 -1
  73. package/dist/ui/thread_drawer.d.ts +6 -5
  74. package/dist/ui/thread_drawer.d.ts.map +1 -1
  75. package/dist/ui/tool_call_card.d.ts +17 -25
  76. package/dist/ui/tool_call_card.d.ts.map +1 -1
  77. package/dist/ui/ui_strings.d.ts +6 -12
  78. package/dist/ui/ui_strings.d.ts.map +1 -1
  79. package/dist/ui/voice_input.d.ts +10 -11
  80. package/dist/ui/voice_input.d.ts.map +1 -1
  81. package/package.json +1 -1
  82. package/src/constants.ts +58 -87
  83. package/src/core/ag_ui_chat.ts +239 -267
  84. package/src/core/agui_client.ts +60 -71
  85. package/src/core/attachment.ts +9 -14
  86. package/src/core/conversation_store.ts +25 -33
  87. package/src/core/create_http_agent.ts +18 -22
  88. package/src/core/remote_conversation_store.ts +14 -15
  89. package/src/core/run_index.ts +14 -23
  90. package/src/core/transcribe_audio.ts +9 -10
  91. package/src/core/upload_attachment.ts +18 -21
  92. package/src/core/utils.ts +4 -6
  93. package/src/dom/animations.ts +33 -43
  94. package/src/dom/dom_driver.ts +7 -7
  95. package/src/dom/native_setter.ts +11 -12
  96. package/src/skills/fill_template.ts +4 -5
  97. package/src/skills/parse_skills.ts +3 -4
  98. package/src/skills/skill.ts +7 -8
  99. package/src/tools/client_tool_registry.ts +2 -2
  100. package/src/tools/page_action_tools.ts +12 -15
  101. package/src/tools/page_state.ts +5 -8
  102. package/src/tools/route_map.ts +15 -19
  103. package/src/ui/approval_card.ts +15 -20
  104. package/src/ui/attach_copy_buttons.ts +9 -18
  105. package/src/ui/attachment_chips.ts +7 -10
  106. package/src/ui/attachment_tray.ts +6 -6
  107. package/src/ui/checkpoint_menu.ts +7 -8
  108. package/src/ui/confirmation_card.ts +10 -15
  109. package/src/ui/question_card.ts +12 -15
  110. package/src/ui/relative_time.ts +5 -7
  111. package/src/ui/render_markdown.ts +25 -51
  112. package/src/ui/resize_handle.ts +25 -38
  113. package/src/ui/run_notice.ts +9 -12
  114. package/src/ui/skills_menu.ts +4 -5
  115. package/src/ui/styles.ts +79 -98
  116. package/src/ui/thoughts_block.ts +11 -13
  117. package/src/ui/thread_drawer.ts +6 -5
  118. package/src/ui/tool_call_card.ts +22 -32
  119. package/src/ui/ui_strings.ts +6 -12
  120. package/src/ui/voice_input.ts +10 -11
  121. package/src/version.ts +1 -1
package/CHANGELOG.md CHANGED
@@ -7,6 +7,42 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.23.1] — 2026-08-13
11
+
12
+ ### Fixed
13
+
14
+ - **A reloaded conversation lost every turn after the first plain answer.**
15
+ Restoring stored history iterated `message.toolCalls` behind an
16
+ `!== undefined` check, and an assistant turn that called no tool can arrive
17
+ carrying `null`: the protocol's Python models declare
18
+ `tool_calls: list[ToolCall] | None`, so a server dumping them without
19
+ `exclude_none` sends exactly that, while `@ag-ui/core` types the field
20
+ optional-and-not-nullable — TypeScript therefore offered no hint that the value
21
+ was reachable. Iterating it threw `TypeError: toolCalls is not iterable`
22
+ *inside* the replay, which aborted at that message and left every later turn
23
+ out of the transcript. Nothing surfaced: no error state, no partial-history
24
+ notice, just a short conversation. Measured against a server-backed store, a
25
+ 54-message thread restored as two bubbles and one tool card.
26
+
27
+ Two things follow from where the throw happened, and both are now closed.
28
+ Tool calls are **narrowed rather than trusted** — the same stance
29
+ `messageAttachments` already takes for the neighbouring field on the same
30
+ message, and for the same reason. And a **shapeless entry is skipped instead of
31
+ ending the replay**: a stored call with no `id`, no `function.name`, or a
32
+ `null` where an object belongs no longer costs the rest of the conversation.
33
+ A call whose `arguments` are missing or not a string still renders, with empty
34
+ arguments, because its name is the part worth showing.
35
+
36
+ Only a **server-backed** history reaches this: the default
37
+ `SessionStorageStore` round-trips client-shaped objects through JSON, where an
38
+ absent field stays absent, so the `null` never appears. Anything reading a
39
+ thread index — `data-threads-url` — did, including every Django admin
40
+ configured with a conversation store. There the cost was worse than a short
41
+ transcript: each navigating tool reloads the page and the run continues only
42
+ because the component rehydrates and completes the pending call, so a thread
43
+ that had answered once abandoned its next multi-step task at the first
44
+ navigation.
45
+
10
46
  ## [0.23.0] — 2026-08-12
11
47
 
12
48
  Attachment chips, which turned out to be the least finished corner of 0.22.
@@ -206,7 +242,7 @@ hosts that both arrange the page the way it expects.
206
242
  `overflow: hidden` ancestor sharing the element's box — a card, a table cell —
207
243
  clipped it entirely while the tool reported success. And 200 ms is below the
208
244
  threshold at which someone who does not know where to look notices anything.
209
- Neither our tests nor the consumer's could have found the second one:
245
+ Neither our tests nor the consumer's could have found the second one:
210
246
  headless Chromium hides the scroll race, and no automated check has an opinion
211
247
  about whether a human sees a 200 ms ring.
212
248
 
@@ -222,7 +258,7 @@ hosts that both arrange the page the way it expects.
222
258
  explicit-duration contract, and the docs now say so instead of overclaiming.
223
259
 
224
260
  - **The tool and skill catalog fetches are deferred by one microtask**, so a React
225
- `ref` assigned in the same commit as insertion is honoured. The thread-history
261
+ `ref` assigned in the same commit as insertion is honoured. The thread-history
226
262
  request is deliberately **not** deferred: a deferred replay can land after a
227
263
  `sendMessage()` and duplicate the transcript. Configure before you insert, or
228
264
  call `reload()`; the new React recipe in the README shows both.
@@ -234,7 +270,7 @@ hosts that both arrange the page the way it expects.
234
270
  `data-resize-anchor="<y>-<x>"`, but the rules meant to read it were written as
235
271
  `[data-resize-anchor~="left"]` — and `~=` matches whitespace-separated words
236
272
  while the stamped value is a single hyphenated token, so they could never
237
- match. **The cursor rules used `=` and did match**, so the pointer followed
273
+ match. **The cursor rules used `=` and did match**, so the pointer followed
238
274
  the measurement while the grip stayed where `placement` had guessed: for any
239
275
  host that aligns the panel the other way, the cursor promised a diagonal the
240
276
  grip was not on, and the grip sat on the corner that stays put.
@@ -260,14 +296,14 @@ hosts that both arrange the page the way it expects.
260
296
 
261
297
  ### Fixed
262
298
 
263
- - **`placement="side"` (and `sidebar`) stopped being full height once the
299
+ - **`placement="side"` (and `sidebar`) stopped being full height once the
264
300
  panel had been resized.** A dragged size is written as a custom property on
265
301
  the host, and an inline custom property **outranks a `:host([placement=…])`
266
302
  rule setting the same property** — so a height dragged while floating capped a
267
303
  docked sidebar that had asked for `100vh`. Since the size persists per tab,
268
304
  one drag broke every later visit.
269
305
 
270
- **The previous release claimed this was already handled, and the reasoning
306
+ **The previous release claimed this was already handled, and the reasoning
271
307
  was wrong.** Writing `--ag-ui-height` rather than inline `height` was supposed
272
308
  to leave placement with the final say; it does not, because the indirection
273
309
  changes nothing about the cascade. The fix is explicit rather than
@@ -291,12 +327,12 @@ hosts that both arrange the page the way it expects.
291
327
  handle at all (a `100vw`/`100vh` layout has nothing to drag), `sidebar` /
292
328
  `side` get width only, everything else gets both.
293
329
 
294
- **It writes the custom properties, not inline `width` / `height`.** The
330
+ **It writes the custom properties, not inline `width` / `height`.** The
295
331
  placement rules set those same properties, so an inline dimension would
296
332
  outrank them — a panel dragged while floating would keep that width after
297
333
  switching to fullscreen.
298
334
 
299
- **Which corner the grip sits on is measured, not assumed.** A resize is
335
+ **Which corner the grip sits on is measured, not assumed.** A resize is
300
336
  computed from the edge that stays still, and which edge that is belongs to the
301
337
  *host's* layout rather than to `placement` — a floating panel is pinned
302
338
  bottom-right, an embedded one goes wherever the page's CSS puts it. Deriving
@@ -320,7 +356,7 @@ hosts that both arrange the page the way it expects.
320
356
  palette — a lone `/` — was left in the composer, which said nothing about what
321
357
  the skill wanted or how to supply it. The hint now says what to do, too.
322
358
 
323
- - **Picking a skill now sends it.** It used to write the text into the
359
+ - **Picking a skill now sends it.** It used to write the text into the
324
360
  composer and wait for a second click unless the skill set
325
361
  `sendImmediately: true` — so the default behaviour of a shortcut was to not
326
362
  take the shortcut. Set `sendImmediately: false` to keep pre-filling, which is
@@ -331,7 +367,7 @@ hosts that both arrange the page the way it expects.
331
367
  sends the bare `/name` token and the agent expands it, from the harness
332
368
  `Skills` capability or the server's own instructions.
333
369
 
334
- **The prompt was the leak.** A catalog is either a fetched `GET` or an
370
+ **The prompt was the leak.** A catalog is either a fetched `GET` or an
335
371
  inline `data-skills` attribute sitting in the page source, and a skill is
336
372
  often where a project's internal workflow is written down most plainly — so
337
373
  the client-side catalog published it to anyone who opened the page. Sending a
@@ -355,10 +391,10 @@ hosts that both arrange the page the way it expects.
355
391
  `part` (`tool-card-args` / `tool-card-result`, headings via
356
392
  `tool-card-section-label`, body via `tool-card-body`), and are pretty-printed.
357
393
 
358
- Breaking for anyone styling `tool-card-result` as a single combined block.
394
+ Breaking for anyone styling `tool-card-result` as a single combined block.
359
395
  A call with no arguments no longer renders an empty `{}` in a box of its own.
360
396
 
361
- - **`data-tool-display` is now live.** Changing it restyles every card already
397
+ - **`data-tool-display` is now live.** Changing it restyles every card already
362
398
  in the transcript, the way `data-answer-well` always has. The modes are pure
363
399
  visibility over **one DOM shape**, selected by the shadow CSS from the host
364
400
  attribute; previously each card baked its structure at construction from the
@@ -373,7 +409,7 @@ hosts that both arrange the page the way it expects.
373
409
  different objects: the record is the tool card it gates, which settles to the
374
410
  outcome and scrolls with the rest of the transcript.
375
411
 
376
- - **The confirmation card was appended to the wrong parent**, and it is the
412
+ - **The confirmation card was appended to the wrong parent**, and it is the
377
413
  reason it drifted to the foot of a turn. Every other inline card — tool,
378
414
  approval, `ask_user`, run notices — goes into the turn's answer group; this
379
415
  one went into the message list, so it became a sibling *after* the group and
@@ -390,7 +426,7 @@ hosts that both arrange the page the way it expects.
390
426
  gated, and the server-side gate left nothing at all even though it is the one
391
427
  guarding tools that run on the backend.
392
428
 
393
- **Session-scoped, like the "run interrupted" notice.** AG-UI carries no
429
+ **Session-scoped, like the "run interrupted" notice.** AG-UI carries no
394
430
  approval message — the answer rides `resume[]` as transient run input — so a
395
431
  reload restores the call and its result but not the note. Durable "who
396
432
  approved what" is an audit concern, not a transcript one.
@@ -415,7 +451,7 @@ hosts that both arrange the page the way it expects.
415
451
  entry is what gets persisted. The protocol has no rule to enforce and refusing
416
452
  the event would be worse than the merge, so this warns and continues.
417
453
 
418
- Found because the demo harness was doing exactly this, which is the
454
+ Found because the demo harness was doing exactly this, which is the
419
455
  argument for the harness in miniature: the bug was the consumer's, the
420
456
  invisibility was ours.
421
457
 
@@ -425,7 +461,7 @@ hosts that both arrange the page the way it expects.
425
461
  of replaying one script for everything, and the page gained header-icon,
426
462
  German-strings and reset-size controls plus a short "what to try" guide.
427
463
 
428
- Two harness defects were making the component look broken. Its follow-up
464
+ Two harness defects were making the component look broken. Its follow-up
429
465
  detection matched **any** tool message in the thread, so once a conversation
430
466
  had run a single tool every later turn answered "Done" to everything. And the
431
467
  page forced `flex: 1` on the element, which silently outranks the width a
@@ -454,7 +490,7 @@ hosts that both arrange the page the way it expects.
454
490
  keyboard user), styleable via the `code-copy` part, with `copyCode` /
455
491
  `copied` / `copyFailed` in `UiStrings`.
456
492
 
457
- **It reports failure rather than always claiming success.** The Clipboard
493
+ **It reports failure rather than always claiming success.** The Clipboard
458
494
  API needs a secure context and is simply absent in some embeddings; a button
459
495
  that always says "Copied" sends the reader off to paste stale clipboard
460
496
  content and find out somewhere else entirely.
@@ -473,7 +509,7 @@ hosts that both arrange the page the way it expects.
473
509
  drawer had done this correctly all along. Focus now moves in on open, is
474
510
  restored on close, and Tab is trapped while it is open.
475
511
 
476
- **With no continuable runs the panel holds no controls**, so the panel
512
+ **With no continuable runs the panel holds no controls**, so the panel
477
513
  itself is focusable as the fallback — otherwise "move focus to the first
478
514
  control" silently does nothing in exactly the case where the user has least to
479
515
  go on.
@@ -495,7 +531,7 @@ hosts that both arrange the page the way it expects.
495
531
  the composer, clears it, and calls this, so the two paths cannot drift.
496
532
 
497
533
  It no-ops while a run is in flight — a second concurrent run would orphan the
498
- first — and for an entirely empty message. Unlike the built-in Send it does
534
+ first — and for an entirely empty message. Unlike the built-in Send it does
499
535
  **not** consult the attachment tray: what you pass is what is sent, so a host
500
536
  composer stays in charge of its own state.
501
537
 
@@ -511,7 +547,7 @@ hosts that both arrange the page the way it expects.
511
547
  a send. `detail` carries `{ attachments, pending }`: the durable refs of
512
548
  everything settled, and how many are still in flight.
513
549
 
514
- **This is what makes `sendMessage` usable with files at all.** The tray only
550
+ **This is what makes `sendMessage` usable with files at all.** The tray only
515
551
  ever spoke to the built-in Send button, so a host composer had no way to tell a
516
552
  settled upload from one still uploading — the same information the built-in
517
553
  Send needs, which was simply not exposed. The tray's `onChange` hook already
@@ -527,13 +563,13 @@ hosts that both arrange the page the way it expects.
527
563
  `data-strings`, `data-icon-url`.
528
564
 
529
565
  Each is read once while connecting, to decide what chrome exists at all, and
530
- no later read revisits the decision. **The symptom is an affordance that
566
+ no later read revisits the decision. **The symptom is an affordance that
531
567
  simply never appears** — which reads as a broken component rather than a
532
568
  mis-timed assignment, and it is the common React/Vue shape: the element mounts
533
569
  on the first render pass and the framework patches attributes in on the next.
534
570
 
535
571
  Set them before the element enters the DOM, or remove and re-insert it to
536
- apply a new value. The attributes that genuinely *are* re-read per use —
572
+ apply a new value. The attributes that genuinely *are* re-read per use —
537
573
  `data-runs-url`, `data-page-actions`, `data-text-animation`,
538
574
  `data-tool-display`, `endpoint`, and CSS-reactive `theme` / `collapsed` — are
539
575
  deliberately excluded, since a late change works there and a warning would be
@@ -547,7 +583,7 @@ hosts that both arrange the page the way it expects.
547
583
  So the panel ignored `theme="dark"` entirely and rendered light-on-dark unless
548
584
  a host happened to set three variables documented nowhere. Now derived from the
549
585
  real theme tokens, with a new theme-aware `--ag-ui-hover` defined in every
550
- theme block. The fallbacks are what hid it: they made an unthemed panel look
586
+ theme block. The fallbacks are what hid it: they made an unthemed panel look
551
587
  deliberate.
552
588
 
553
589
  `checkpoints-title` and `checkpoint-label` also gain `part` attributes — they
@@ -592,11 +628,11 @@ hosts that both arrange the page the way it expects.
592
628
  building both and diffing; only the source maps move), so consumers see no
593
629
  change.
594
630
 
595
- **Vitest 4 takes a provider *instance*, not the string `"playwright"`.**
631
+ **Vitest 4 takes a provider *instance*, not the string `"playwright"`.**
596
632
  The provider moved to its own package (`@vitest/browser-playwright`) and, with
597
633
  v8 coverage, the old string form is a hard error rather than a deprecation.
598
634
 
599
- **TypeScript 7 requires `rootDir` explicitly** (TS5011) instead of
635
+ **TypeScript 7 requires `rootDir` explicitly** (TS5011) instead of
600
636
  inferring it from the common source directory. Set to the value 5.x inferred,
601
637
  so the published layout is unchanged.
602
638
 
@@ -629,7 +665,7 @@ hosts that both arrange the page the way it expects.
629
665
  transcription error body, and a restored history message with an unrecognised
630
666
  role.
631
667
 
632
- **One was a flaw in the test harness, not a missing test.** `makeFakeAgent`
668
+ **One was a flaw in the test harness, not a missing test.** `makeFakeAgent`
633
669
  ended a clean run by calling `onRunFinalized` alone, so the client's
634
670
  `RUN_FINISHED` path could only ever be reached through `emit.interrupt()` —
635
671
  the ordinary success outcome every real run carries was never exercised. The
@@ -648,13 +684,13 @@ hosts that both arrange the page the way it expects.
648
684
  (Playwright) for the tests whose subject is sanitisation. Coverage stays
649
685
  unified at 100% across both.
650
686
 
651
- **A correctness requirement, not an optimisation.** DOMPurify 3.4.8+
687
+ **A correctness requirement, not an optimisation.** DOMPurify 3.4.8+
652
688
  silently stops sanitising under happy-dom — `<script>` and `<img>` pass
653
689
  straight through, and ordinary markdown loses its `<p>` wrapper. A
654
690
  happy-dom-only suite can therefore go green while this component ships no
655
691
  sanitisation at all, which is the one failure it must never ship.
656
692
 
657
- **The experiment settles what the pin never could**: dompurify 3.4.13
693
+ **The experiment settles what the pin never could**: dompurify 3.4.13
658
694
  sanitises correctly in Chromium. The defect is happy-dom's DOM emulation, not
659
695
  a DOMPurify regression — so **consumers were never exposed**, and the risk was
660
696
  confined to the test environment the whole time.
@@ -680,13 +716,13 @@ hosts that both arrange the page the way it expects.
680
716
  are transitive, so they are pinned through `overrides` — there is no direct
681
717
  dependency to bump.
682
718
 
683
- **`overrides` now live in `pnpm-workspace.yaml`**, not the `pnpm` field in
719
+ **`overrides` now live in `pnpm-workspace.yaml`**, not the `pnpm` field in
684
720
  `package.json`; pnpm 11 ignores the latter and only warns. And an override
685
721
  must be scoped to its major — an unbounded `brace-expansion: ">=2.1.2"`
686
722
  resolves to 5.x, whose export shape `minimatch` cannot call, breaking `glob`
687
723
  at runtime.
688
724
 
689
- - **Four `dompurify` advisories are knowingly left open** (three LOW, one
725
+ - **Four `dompurify` advisories are knowingly left open** (three LOW, one
690
726
  MEDIUM), and the dependency is now pinned to **exactly `3.4.7`** rather than
691
727
  `^3.4.7`.
692
728
 
@@ -695,7 +731,7 @@ hosts that both arrange the page the way it expects.
695
731
  again against dompurify 3.4.13 with happy-dom 20.11.1 — moving the test DOM
696
732
  forward does not fix it.
697
733
 
698
- **The pin was previously a caret range**, so the hold existed only in the
734
+ **The pin was previously a caret range**, so the hold existed only in the
699
735
  lockfile and nowhere in the manifest, undocumented — a `pnpm update` would
700
736
  have silently disabled sanitisation. It is now exact, explained at the import
701
737
  site in `src/ui/render_markdown.ts`, and recorded in `CLAUDE.md`.
@@ -722,7 +758,7 @@ hosts that both arrange the page the way it expects.
722
758
  client. It now renders as `Using skill <id>` **instead of** the raw tool
723
759
  card it would otherwise produce.
724
760
 
725
- Not to be confused with the existing `Skill` catalog — that is a *human*
761
+ Not to be confused with the existing `Skill` catalog — that is a *human*
726
762
  affordance (a prompt the user launches from the chip row or `/`-palette).
727
763
  An agent skill is chosen by the model mid-run. Only the latter emits a
728
764
  notice.
@@ -929,7 +965,7 @@ hosts that both arrange the page the way it expects.
929
965
  / `onReasoningEnd`, wired from `@ag-ui/client`'s `REASONING_*` subscriber
930
966
  callbacks (which also cover the deprecated `THINKING_*` family).
931
967
  - **Voice input.** Set `data-transcribe-url` (django-ag-ui's
932
- `TranscribeView`) to reveal a 🎤 mic button in the composer (part
968
+ `TranscribeView`) to reveal a mic button in the composer (part
933
969
  `voice-button`): it records via `MediaRecorder`, POSTs the clip, and drops the
934
970
  returned transcript into the textarea. A pluggable `transcribeHandler` —
935
971
  `(audio: Blob) => Promise<string>` — swaps the transport (a different STT
@@ -974,7 +1010,7 @@ hosts that both arrange the page the way it expects.
974
1010
  + summary, no box chrome) with the result behind its own toggle. Every
975
1011
  tool-call card now leads with a CSS-drawn **status icon** (part
976
1012
  `tool-card-icon`): a spinning ring while running, then a check / cross / slash
977
- on success / error / decline, replacing the hardcoded `🔧` glyph. Re-theme via
1013
+ on success / error / decline, replacing the hardcoded `` glyph. Re-theme via
978
1014
  `--ag-ui-tool-icon-done` / `--ag-ui-tool-icon-error` / `--ag-ui-tool-icon-declined`
979
1015
  and `--ag-ui-tool-spin-duration`; the spin respects `prefers-reduced-motion`.
980
1016
 
@@ -1025,7 +1061,7 @@ hosts that both arrange the page the way it expects.
1025
1061
  ### Added
1026
1062
 
1027
1063
  - **File uploads.** Set `data-attachments-url` (django-ag-ui's `AttachmentsView`)
1028
- to reveal a 📎 picker + drag-and-drop on the composer. Each file uploads
1064
+ to reveal a picker + drag-and-drop on the composer. Each file uploads
1029
1065
  out-of-band (multipart, with the element's `headers`) into a pending tray —
1030
1066
  one chip per file with a progress bar, settling to `ready` or `error` (with
1031
1067
  retry / remove). On send, the ready files' refs render as read-only chips on
@@ -1041,7 +1077,7 @@ hosts that both arrange the page the way it expects.
1041
1077
  `(file, onProgress) => Promise<AttachmentRef>` — swaps the built-in multipart
1042
1078
  upload for a custom one (a resumable `tus-js-client` adapter, direct-to-S3
1043
1079
  multipart, …) without touching the tray, chips, or AG-UI wire. When set, the
1044
- 📎 affordance appears even with no `data-attachments-url`. Defaults to the
1080
+ affordance appears even with no `data-attachments-url`. Defaults to the
1045
1081
  built-in `uploadAttachment`.
1046
1082
  - **New exports:** `uploadAttachment` + `UploadOptions` + `UploadHandler`, the
1047
1083
  `AttachmentRef` type, and `messageAttachments`. `AgUiClient.send` gains an
@@ -1310,7 +1346,8 @@ hosts that both arrange the page the way it expects.
1310
1346
  ### Notes
1311
1347
  - First release — exercising the automated npm OIDC publish pipeline end-to-end.
1312
1348
 
1313
- [Unreleased]: https://github.com/Artui/ag-ui-web-component/compare/v0.23.0...HEAD
1349
+ [Unreleased]: https://github.com/Artui/ag-ui-web-component/compare/v0.23.1...HEAD
1350
+ [0.23.1]: https://github.com/Artui/ag-ui-web-component/compare/v0.23.0...v0.23.1
1314
1351
  [0.23.0]: https://github.com/Artui/ag-ui-web-component/compare/v0.22.0...v0.23.0
1315
1352
  [0.22.0]: https://github.com/Artui/ag-ui-web-component/compare/v0.21.0...v0.22.0
1316
1353
  [0.21.0]: https://github.com/Artui/ag-ui-web-component/compare/v0.20.1...v0.21.0
package/README.md CHANGED
@@ -420,7 +420,7 @@ AG-UI has no server-side cancel route: cancelling **aborts the streaming request
420
420
 
421
421
  - Partial assistant text already streamed **stays in the transcript** and is persisted via
422
422
  `onPersist`, so a reload shows the truncated exchange. A muted **"⏹ Stopped"** note is appended
423
- (`.stopped-note`) — a deliberate stop is not an error, so no ⚠️ bubble.
423
+ (`.stopped-note`) — a deliberate stop is not an error, so no bubble.
424
424
  - The run loop stops: tool calls collected before the abort are **not executed**, and no further
425
425
  round starts. A frontend tool handler already running completes, but its result doesn't trigger
426
426
  a re-run.
@@ -784,7 +784,7 @@ A gated call carries the decision (`approved by you` / `declined by you`, part
784
784
  from the server-side approval interrupt alike. The prompt itself disappears once answered: a
785
785
  prompt and a record are different objects, and the record is the card.
786
786
 
787
- **The annotation is session-scoped**, like the "run interrupted" notice. AG-UI carries no
787
+ **The annotation is session-scoped**, like the "run interrupted" notice. AG-UI carries no
788
788
  approval message — the answer rides `resume[]` as transient run input — so a reload restores the
789
789
  tool call and its result but not the note that a human waved it through. If you need "who
790
790
  approved what" durably, that is an audit concern rather than a transcript one; record it
@@ -827,14 +827,14 @@ is what positions the grip.
827
827
  A drag writes `--ag-ui-width` / `--ag-ui-height` on the host as custom
828
828
  properties.
829
829
 
830
- **That alone does not leave placement in charge** — an inline custom property
830
+ **That alone does not leave placement in charge** — an inline custom property
831
831
  still outranks a `:host([placement=…])` rule setting the same property. So the
832
832
  component enforces the split directly: **a placement owns the axes it fixes**,
833
833
  and a dragged or persisted size is only ever applied to the ones it leaves free.
834
834
  Switching placement hands the owned axes back. Without that, a height dragged
835
835
  while floating capped a docked sidebar that had asked for `100vh`.
836
836
 
837
- **A host rule that sizes the element wins over both.** `ag-ui-chat { flex: 1 }`
837
+ **A host rule that sizes the element wins over both.** `ag-ui-chat { flex: 1 }`
838
838
  stretches the panel to its container and the dragged width has no visible
839
839
  effect — which reads as a broken control rather than as your stylesheet winning.
840
840
  Give the element `flex: 0 1 auto` (plus `max-width: 100%`) if it lives in a flex
@@ -1149,7 +1149,7 @@ error — a history affordance that fails is empty, not broken.
1149
1149
  ## File uploads
1150
1150
 
1151
1151
  Set **`data-attachments-url`** (django-ag-ui's `AttachmentsView`) to let the user attach files
1152
- to a message. A 📎 button and drag-and-drop appear on the composer; each picked file uploads
1152
+ to a message. A button and drag-and-drop appear on the composer; each picked file uploads
1153
1153
  out-of-band (multipart, with the element's `headers`) and shows a chip in a pending tray —
1154
1154
  `uploading` (with a progress bar) → `ready`, or `error` with a retry. On send, the ready files'
1155
1155
  **refs** ride on the user bubble as read-only chips and the agent reads their contents
@@ -1178,7 +1178,7 @@ See [Authenticating requests](#authenticating-requests).
1178
1178
  `uploadHandler`. Set your own to use a different transport — a resumable
1179
1179
  [`tus-js-client`](https://github.com/tus/tus-js-client) adapter, direct-to-S3 multipart, etc.
1180
1180
  — without touching the tray, the chips, or the AG-UI wire (refs are transport-agnostic). The
1181
- handler is `(file, onProgress) => Promise<AttachmentRef>`; when set, the 📎 affordance appears
1181
+ handler is `(file, onProgress) => Promise<AttachmentRef>`; when set, the affordance appears
1182
1182
  even with no `data-attachments-url`, and your handler owns its own endpoint and headers:
1183
1183
 
1184
1184
  ```js
@@ -1409,7 +1409,7 @@ have to hand-tune the variables:
1409
1409
  See [`src/ui/styles.ts`](src/ui/styles.ts) for the full variable + preset list. The
1410
1410
  [`demo/`](demo/) live playground (`node demo/mock-server.mjs`) flips theme, density, placement,
1411
1411
  text-animation, tool-display, and the answer well live from a single page, and demos the
1412
- streamed thoughts region, the 🎤 mic, and the header theme toggle.
1412
+ streamed thoughts region, the mic, and the header theme toggle.
1413
1413
 
1414
1414
  ### Parts and slots
1415
1415