@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.
- package/CHANGELOG.md +73 -36
- package/README.md +7 -7
- package/dist/ag-ui-web-component.bundle.js +98 -117
- package/dist/ag-ui-web-component.bundle.js.map +3 -3
- package/dist/constants.d.ts +56 -85
- package/dist/constants.d.ts.map +1 -1
- package/dist/core/ag_ui_chat.d.ts +90 -127
- package/dist/core/ag_ui_chat.d.ts.map +1 -1
- package/dist/core/agui_client.d.ts +24 -30
- package/dist/core/agui_client.d.ts.map +1 -1
- package/dist/core/attachment.d.ts +9 -14
- package/dist/core/attachment.d.ts.map +1 -1
- package/dist/core/conversation_store.d.ts +20 -27
- package/dist/core/conversation_store.d.ts.map +1 -1
- package/dist/core/create_http_agent.d.ts +13 -15
- package/dist/core/create_http_agent.d.ts.map +1 -1
- package/dist/core/remote_conversation_store.d.ts +8 -9
- package/dist/core/remote_conversation_store.d.ts.map +1 -1
- package/dist/core/run_index.d.ts +11 -20
- package/dist/core/run_index.d.ts.map +1 -1
- package/dist/core/transcribe_audio.d.ts +8 -8
- package/dist/core/transcribe_audio.d.ts.map +1 -1
- package/dist/core/upload_attachment.d.ts +15 -18
- package/dist/core/upload_attachment.d.ts.map +1 -1
- package/dist/core/utils.d.ts +4 -6
- package/dist/core/utils.d.ts.map +1 -1
- package/dist/dom/animations.d.ts +22 -30
- package/dist/dom/animations.d.ts.map +1 -1
- package/dist/dom/dom_driver.d.ts +7 -7
- package/dist/dom/native_setter.d.ts +2 -2
- package/dist/dom/native_setter.d.ts.map +1 -1
- package/dist/index.js +290 -378
- package/dist/index.js.map +2 -2
- package/dist/skills/fill_template.d.ts +4 -5
- package/dist/skills/fill_template.d.ts.map +1 -1
- package/dist/skills/parse_skills.d.ts.map +1 -1
- package/dist/skills/skill.d.ts +7 -8
- package/dist/skills/skill.d.ts.map +1 -1
- package/dist/tools/client_tool_registry.d.ts +2 -2
- package/dist/tools/page_action_tools.d.ts +7 -10
- package/dist/tools/page_action_tools.d.ts.map +1 -1
- package/dist/tools/page_state.d.ts +5 -8
- package/dist/tools/page_state.d.ts.map +1 -1
- package/dist/tools/route_map.d.ts +7 -10
- package/dist/tools/route_map.d.ts.map +1 -1
- package/dist/ui/approval_card.d.ts +15 -20
- package/dist/ui/approval_card.d.ts.map +1 -1
- package/dist/ui/attach_copy_buttons.d.ts +4 -10
- package/dist/ui/attach_copy_buttons.d.ts.map +1 -1
- package/dist/ui/attachment_chips.d.ts +7 -10
- package/dist/ui/attachment_chips.d.ts.map +1 -1
- package/dist/ui/attachment_tray.d.ts +6 -6
- package/dist/ui/checkpoint_menu.d.ts +7 -8
- package/dist/ui/checkpoint_menu.d.ts.map +1 -1
- package/dist/ui/confirmation_card.d.ts +10 -15
- package/dist/ui/confirmation_card.d.ts.map +1 -1
- package/dist/ui/question_card.d.ts +12 -15
- package/dist/ui/question_card.d.ts.map +1 -1
- package/dist/ui/relative_time.d.ts +5 -7
- package/dist/ui/relative_time.d.ts.map +1 -1
- package/dist/ui/render_markdown.d.ts +8 -8
- package/dist/ui/render_markdown.d.ts.map +1 -1
- package/dist/ui/resize_handle.d.ts +21 -34
- package/dist/ui/resize_handle.d.ts.map +1 -1
- package/dist/ui/run_notice.d.ts +5 -7
- package/dist/ui/run_notice.d.ts.map +1 -1
- package/dist/ui/skills_menu.d.ts +4 -5
- package/dist/ui/skills_menu.d.ts.map +1 -1
- package/dist/ui/styles.d.ts +1 -1
- package/dist/ui/styles.d.ts.map +1 -1
- package/dist/ui/thoughts_block.d.ts +9 -11
- package/dist/ui/thoughts_block.d.ts.map +1 -1
- package/dist/ui/thread_drawer.d.ts +6 -5
- package/dist/ui/thread_drawer.d.ts.map +1 -1
- package/dist/ui/tool_call_card.d.ts +17 -25
- package/dist/ui/tool_call_card.d.ts.map +1 -1
- package/dist/ui/ui_strings.d.ts +6 -12
- package/dist/ui/ui_strings.d.ts.map +1 -1
- package/dist/ui/voice_input.d.ts +10 -11
- package/dist/ui/voice_input.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/constants.ts +58 -87
- package/src/core/ag_ui_chat.ts +239 -267
- package/src/core/agui_client.ts +60 -71
- package/src/core/attachment.ts +9 -14
- package/src/core/conversation_store.ts +25 -33
- package/src/core/create_http_agent.ts +18 -22
- package/src/core/remote_conversation_store.ts +14 -15
- package/src/core/run_index.ts +14 -23
- package/src/core/transcribe_audio.ts +9 -10
- package/src/core/upload_attachment.ts +18 -21
- package/src/core/utils.ts +4 -6
- package/src/dom/animations.ts +33 -43
- package/src/dom/dom_driver.ts +7 -7
- package/src/dom/native_setter.ts +11 -12
- package/src/skills/fill_template.ts +4 -5
- package/src/skills/parse_skills.ts +3 -4
- package/src/skills/skill.ts +7 -8
- package/src/tools/client_tool_registry.ts +2 -2
- package/src/tools/page_action_tools.ts +12 -15
- package/src/tools/page_state.ts +5 -8
- package/src/tools/route_map.ts +15 -19
- package/src/ui/approval_card.ts +15 -20
- package/src/ui/attach_copy_buttons.ts +9 -18
- package/src/ui/attachment_chips.ts +7 -10
- package/src/ui/attachment_tray.ts +6 -6
- package/src/ui/checkpoint_menu.ts +7 -8
- package/src/ui/confirmation_card.ts +10 -15
- package/src/ui/question_card.ts +12 -15
- package/src/ui/relative_time.ts +5 -7
- package/src/ui/render_markdown.ts +25 -51
- package/src/ui/resize_handle.ts +25 -38
- package/src/ui/run_notice.ts +9 -12
- package/src/ui/skills_menu.ts +4 -5
- package/src/ui/styles.ts +79 -98
- package/src/ui/thoughts_block.ts +11 -13
- package/src/ui/thread_drawer.ts +6 -5
- package/src/ui/tool_call_card.ts +22 -32
- package/src/ui/ui_strings.ts +6 -12
- package/src/ui/voice_input.ts +10 -11
- 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
|
-
|
|
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.
|
|
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.
|
|
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
|
-
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
-
|
|
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
|
-
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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.
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
1412
|
+
streamed thoughts region, the mic, and the header theme toggle.
|
|
1413
1413
|
|
|
1414
1414
|
### Parts and slots
|
|
1415
1415
|
|