@artooi/ag-ui-web-component 0.10.0 → 0.11.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 +44 -1
- package/README.md +89 -7
- package/dist/ag-ui-web-component.bundle.js +175 -54
- package/dist/ag-ui-web-component.bundle.js.map +4 -4
- package/dist/core/ag_ui_chat.d.ts +29 -0
- package/dist/core/ag_ui_chat.d.ts.map +1 -1
- package/dist/core/agui_client.d.ts +28 -1
- package/dist/core/agui_client.d.ts.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +589 -72
- package/dist/index.js.map +4 -4
- package/dist/ui/approval_card.d.ts +51 -0
- package/dist/ui/approval_card.d.ts.map +1 -0
- package/dist/ui/attachment_chips.d.ts.map +1 -1
- package/dist/ui/attachment_tray.d.ts.map +1 -1
- package/dist/ui/question_card.d.ts +52 -0
- package/dist/ui/question_card.d.ts.map +1 -0
- 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.map +1 -1
- package/dist/ui/thread_drawer.d.ts.map +1 -1
- package/dist/ui/ui_strings.d.ts +16 -0
- package/dist/ui/ui_strings.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/core/ag_ui_chat.ts +172 -3
- package/src/core/agui_client.ts +86 -11
- package/src/index.ts +14 -0
- package/src/ui/approval_card.ts +119 -0
- package/src/ui/attachment_chips.ts +5 -0
- package/src/ui/attachment_tray.ts +8 -0
- package/src/ui/question_card.ts +216 -0
- package/src/ui/skills_menu.ts +6 -0
- package/src/ui/styles.ts +121 -0
- package/src/ui/thoughts_block.ts +1 -0
- package/src/ui/thread_drawer.ts +11 -0
- package/src/ui/ui_strings.ts +30 -0
- package/src/version.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,48 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.11.0] — 2026-07-14
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **Server-side tool approval — the browser half of the human-in-the-loop gate.**
|
|
15
|
+
When a gated server-side tool defers instead of executing, the run finishes on
|
|
16
|
+
an AG-UI *interrupt*; the client now renders an inline **approval card**
|
|
17
|
+
(`requestApproval`, next to the pending tool-call card) and, on the user's
|
|
18
|
+
decision, resumes the run with the answer via the protocol's `resume[]`.
|
|
19
|
+
Approve runs the tool (its result streams back into the same card); deny sends
|
|
20
|
+
a `cancelled` answer so the model learns it was declined and the card settles
|
|
21
|
+
as declined. No `@ag-ui/*` dependency bump — the interrupt/resume types already
|
|
22
|
+
ship in the pinned `0.0.x`. `AgUiClient` gains a `resolveInterrupts` config hook
|
|
23
|
+
and exports `InterruptResponse` / `ResolveInterrupts`. The card is fully
|
|
24
|
+
customizable: `strings` (`approveAction` / `approvalPrompt` / `approve` /
|
|
25
|
+
`deny`), a `::part()` surface (`approval`, `-body`, `-actions`, `-button`,
|
|
26
|
+
`-approve`, `-deny`), and an `approvalRenderer` hook that fully replaces the UI
|
|
27
|
+
(given the request + a Stop `AbortSignal`, resolves approve/deny). Exports
|
|
28
|
+
`ApprovalRenderer`.
|
|
29
|
+
- **`ask_user` — a built-in typed-question frontend tool (opt-in).** Set
|
|
30
|
+
`askUser = true` on `<ag-ui-chat>` to offer the agent an `ask_user(question,
|
|
31
|
+
options?, allow_custom?)` tool: calling it renders an inline **question card**
|
|
32
|
+
(`requestQuestion` — radio choices and/or a free-text field) and returns the
|
|
33
|
+
chosen or typed answer as the tool result, reusing the existing frontend-tool
|
|
34
|
+
path (no new protocol). Off by default, like the other built-in tool groups, so
|
|
35
|
+
the advertised catalog is unchanged until a host opts in. The card is **fully
|
|
36
|
+
customizable**: localized `strings` (`askUserAction` / `otherOption` /
|
|
37
|
+
`answerPlaceholder` / `submit`), a full `::part()` surface (`question`,
|
|
38
|
+
`question-body`, `-options`, `-choice`, `-radio`, `-input`, `-actions`,
|
|
39
|
+
`-button`), and a `askUserRenderer` hook that fully replaces the UI with a
|
|
40
|
+
host-supplied renderer (given the request + a Stop `AbortSignal`, resolves the
|
|
41
|
+
answer). Exports `QuestionRenderer`.
|
|
42
|
+
- **Complete `::part()` coverage sweep.** Every rendered UI element now exposes a
|
|
43
|
+
`part` for `::part()` styling — closing gaps in the attachment chips
|
|
44
|
+
(`attachment-chips` and the shared `attachment-chip*` parts, now on both the
|
|
45
|
+
composer tray and the read-only chips on sent bubbles), the skills UI
|
|
46
|
+
(`skill-chips` / `skill-chip` / `skill-palette` / `skill-item*` / `skill-hint`),
|
|
47
|
+
the history-drawer row internals (`drawer-row-title` / `-time` / `-preview` /
|
|
48
|
+
`-actions` / `-rename` / `-delete`, the inline `drawer-rename-input`, and the
|
|
49
|
+
`drawer-confirm*` delete prompt), plus `thoughts-label`, `question-choice-text`,
|
|
50
|
+
and the `stopped` note. All are documented in the README "Available parts" list.
|
|
51
|
+
|
|
10
52
|
## [0.10.0] — 2026-07-02
|
|
11
53
|
|
|
12
54
|
### Added
|
|
@@ -453,7 +495,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
453
495
|
### Notes
|
|
454
496
|
- First release — exercising the automated npm OIDC publish pipeline end-to-end.
|
|
455
497
|
|
|
456
|
-
[Unreleased]: https://github.com/Artui/ag-ui-web-component/compare/v0.
|
|
498
|
+
[Unreleased]: https://github.com/Artui/ag-ui-web-component/compare/v0.11.0...HEAD
|
|
499
|
+
[0.11.0]: https://github.com/Artui/ag-ui-web-component/compare/v0.10.0...v0.11.0
|
|
457
500
|
[0.10.0]: https://github.com/Artui/ag-ui-web-component/compare/v0.9.0...v0.10.0
|
|
458
501
|
[0.9.0]: https://github.com/Artui/ag-ui-web-component/compare/v0.8.1...v0.9.0
|
|
459
502
|
[0.8.1]: https://github.com/Artui/ag-ui-web-component/compare/v0.8.0...v0.8.1
|
package/README.md
CHANGED
|
@@ -171,7 +171,7 @@ That's the whole integration: an `endpoint` attribute pointing at your AG-UI ser
|
|
|
171
171
|
| `placement` | — | CSS-only: `floating` (default) / `bottom-left` / `side` / `sidebar` / `full` / `page` / `embedded`. |
|
|
172
172
|
|
|
173
173
|
**Properties** (JS only, not attributes): `headers`, `allowImages`, `autoConfirm`,
|
|
174
|
-
`confirmPredicate`, `agentFactory`, `getTools`, `getContext`, `routeMap`, `navigate`,
|
|
174
|
+
`confirmPredicate`, `askUser`, `agentFactory`, `getTools`, `getContext`, `routeMap`, `navigate`,
|
|
175
175
|
`getPageMap`, `autoInjectPageMap`, `conversationStore`, `uploadHandler`, `transcribeHandler`,
|
|
176
176
|
`navigationResult`, `skillContext`, `toolSummaries`, `strings`, `resolvePageTarget`, plus the
|
|
177
177
|
mirrors `endpoint` / `toolDisplay` / `collapsed`.
|
|
@@ -234,7 +234,8 @@ AG-UI has no server-side cancel route: cancelling **aborts the streaming request
|
|
|
234
234
|
round starts. A frontend tool handler already running completes, but its result doesn't trigger
|
|
235
235
|
a re-run.
|
|
236
236
|
- An **open confirmation card is declined** (`data-resolved="declined"`) — cancelling the run
|
|
237
|
-
answers the pending question.
|
|
237
|
+
answers the pending question. Likewise an open **approval card** is denied and an open
|
|
238
|
+
**question card** (`ask_user`) resolves with an empty answer.
|
|
238
239
|
- The new `onCancelled()` handler fires instead of `onError()`; `onSettled()` still follows
|
|
239
240
|
(the terminal-rest guarantee), returning the button to **Send**.
|
|
240
241
|
|
|
@@ -308,6 +309,73 @@ chat.registerTool({
|
|
|
308
309
|
});
|
|
309
310
|
```
|
|
310
311
|
|
|
312
|
+
The confirmation card gates **client-registered** tools *before* they run. A **server-side**
|
|
313
|
+
tool runs on the server, so the browser can't intercept it the same way — that is what the
|
|
314
|
+
approval card below is for.
|
|
315
|
+
|
|
316
|
+
### Server-side tool approval (interrupts)
|
|
317
|
+
|
|
318
|
+
When the server gates a destructive tool (e.g. django-ag-ui's `ToolGuard`), the tool **defers**
|
|
319
|
+
instead of executing and the run finishes on an AG-UI *interrupt*. The element then appends an
|
|
320
|
+
**inline approval card** (a `<div class="approval">`) via
|
|
321
|
+
[`requestApproval`](src/ui/approval_card.ts), next to the pending tool-call card:
|
|
322
|
+
|
|
323
|
+
- **Approve** → the run resumes and the server runs the tool; its result streams back into the
|
|
324
|
+
same card.
|
|
325
|
+
- **Deny** → the run resumes carrying a `cancelled` answer, so the model learns the tool was
|
|
326
|
+
declined; the pending card settles as declined.
|
|
327
|
+
|
|
328
|
+
This uses the AG-UI protocol's own interrupt/resume mechanism (`RunAgentInput.resume[]`) — the
|
|
329
|
+
wire stays vanilla AG-UI. A **Stop** while an approval card is open denies every open card and
|
|
330
|
+
cancels the run. No configuration is needed on the client; the gate is enabled server-side.
|
|
331
|
+
|
|
332
|
+
Like the question card, the approval card is customizable at three levels: **text** (`strings`:
|
|
333
|
+
`approveAction` / `approvalPrompt` / `approve` / `deny`), **CSS** (`::part()`: `approval`,
|
|
334
|
+
`approval-body`, `approval-actions`, `approval-button`, `approval-approve`, `approval-deny`), and
|
|
335
|
+
**full replacement** via `chat.approvalRenderer` — given the request (`message` + `toolName`) and
|
|
336
|
+
a Stop `AbortSignal`, render your own UI and resolve `true`/`false`:
|
|
337
|
+
|
|
338
|
+
```js
|
|
339
|
+
chat.approvalRenderer = (request, { signal }) =>
|
|
340
|
+
myConfirmDialog(request.message ?? `Run ${request.toolName}?`, { signal });
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### Asking the user a question (`ask_user`)
|
|
344
|
+
|
|
345
|
+
Set `chat.askUser = true` to offer the agent a built-in `ask_user` frontend tool. When the agent
|
|
346
|
+
calls it, the element renders an **inline question card** (a `<div class="question">`) via
|
|
347
|
+
[`requestQuestion`](src/ui/question_card.ts) and returns the user's answer as the tool result:
|
|
348
|
+
|
|
349
|
+
```js
|
|
350
|
+
chat.askUser = true; // opt in; off by default so the tool catalog is unchanged otherwise
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
`ask_user(question, options?, allow_custom?)` renders `options` as radio buttons, adds a free-text
|
|
354
|
+
field when `allow_custom` is set (or when no options are given), and feeds the chosen or typed
|
|
355
|
+
answer back through the normal frontend-tool path — no new protocol. A **Stop** dismisses an open
|
|
356
|
+
question with an empty answer.
|
|
357
|
+
|
|
358
|
+
The question card is **fully customizable** at three levels:
|
|
359
|
+
|
|
360
|
+
- **Text** — every label is a `strings` key: `askUserAction` (the card's `aria-label`),
|
|
361
|
+
`otherOption`, `answerPlaceholder`, `submit`.
|
|
362
|
+
- **CSS** — every element exposes a `::part()`: `question`, `question-body`, `question-options`,
|
|
363
|
+
`question-choice`, `question-radio`, `question-input`, `question-actions`, `question-button`
|
|
364
|
+
(plus the `--ag-ui-*` theme variables). No shadow piercing.
|
|
365
|
+
- **Full replacement** — set `chat.askUserRenderer` to own the entire UI. Given the parsed request
|
|
366
|
+
and an `AbortSignal` (fired on Stop), render anything — a native modal, a framework component —
|
|
367
|
+
and resolve with the answer (empty string = no answer). The built-in card is bypassed entirely.
|
|
368
|
+
|
|
369
|
+
```js
|
|
370
|
+
// Level 1+2: restyle the built-in card.
|
|
371
|
+
chat.strings = { submit: "Answer", answerPlaceholder: "Type here…" };
|
|
372
|
+
// ag-ui-chat::part(question) { border-radius: 0; }
|
|
373
|
+
|
|
374
|
+
// Level 3: replace the card with your own UI.
|
|
375
|
+
chat.askUserRenderer = (request, { signal }) =>
|
|
376
|
+
myModal.ask(request.question, request.options, { allowCustom: request.allowCustom, signal });
|
|
377
|
+
```
|
|
378
|
+
|
|
311
379
|
### DOM-driver and animation primitives
|
|
312
380
|
|
|
313
381
|
So the agent can visibly drive the host page, the package ships generic, framework-free
|
|
@@ -792,14 +860,28 @@ ag-ui-chat::part(tool-card) { font-family: var(--my-mono); }
|
|
|
792
860
|
|
|
793
861
|
Available parts: `panel`, `header`, `title`, `icon`, `header-controls`, `header-button`
|
|
794
862
|
(plus `history-button` / `new-button` / `collapse-button` / `theme-toggle`), `messages`,
|
|
795
|
-
`answer` (the per-turn group), `thoughts` (plus `thoughts-toggle` / `thoughts-body`
|
|
796
|
-
|
|
863
|
+
`answer` (the per-turn group), `thoughts` (plus `thoughts-toggle` / `thoughts-body` /
|
|
864
|
+
`thoughts-label`), `message`
|
|
865
|
+
(plus `message-user` / `message-assistant`), `empty`, `pending`, `stopped` (the "⏹ Stopped" note),
|
|
866
|
+
`tool-card`
|
|
797
867
|
(plus `tool-card-head` / `-icon` / `-name` / `-status` / `-args` / `-toggle` / `-result`),
|
|
798
868
|
`confirm` (plus `confirm-body` /
|
|
799
|
-
`-args` / `-actions` / `-button` / `-cancel` / `-confirm`),
|
|
800
|
-
`
|
|
869
|
+
`-args` / `-actions` / `-button` / `-cancel` / `-confirm`),
|
|
870
|
+
`approval` (plus `approval-body` / `-actions` / `-button` / `-approve` / `-deny`),
|
|
871
|
+
`question` (plus `question-body` / `-options` / `-choice` / `-choice-text` / `-radio` / `-input` /
|
|
872
|
+
`-actions` / `-button`), `composer`, `input`, `send`,
|
|
873
|
+
`attach-button`, `voice-button`,
|
|
874
|
+
the attachment chips — `attachment-tray` and `attachment-chips` (the read-only chips on sent
|
|
875
|
+
bubbles) with the shared chip parts `attachment-chip` (plus `-icon` / `-name` / `-size` / `-bar` /
|
|
876
|
+
`-bar-fill` / `-retry` / `-remove`),
|
|
877
|
+
the skills UI (`skill-chips`, `skill-chip`, `skill-palette`, `skill-item`, `skill-item-title`,
|
|
878
|
+
`skill-item-desc`, and the missing-placeholder `skill-hint`),
|
|
879
|
+
`launcher`, `launcher-icon`, and the drawer parts
|
|
801
880
|
(`drawer`, `drawer-backdrop`, `drawer-panel`, `drawer-header`, `drawer-title`, `drawer-new`,
|
|
802
|
-
`drawer-list`, `drawer-empty`, `drawer-row`, `drawer-row-select`
|
|
881
|
+
`drawer-list`, `drawer-empty`, `drawer-row`, `drawer-row-select`, `drawer-row-title`,
|
|
882
|
+
`drawer-row-time`, `drawer-row-preview`, `drawer-row-actions`, `drawer-row-rename`,
|
|
883
|
+
`drawer-row-delete`, `drawer-rename-input`, `drawer-confirm`, `drawer-confirm-label`,
|
|
884
|
+
`drawer-confirm-yes`, `drawer-confirm-no`).
|
|
803
885
|
|
|
804
886
|
Coarse **slots** let you replace whole regions with your own markup (project light-DOM children
|
|
805
887
|
with a matching `slot=`):
|