@artooi/ag-ui-web-component 0.18.0 → 0.20.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 +165 -1
- package/README.md +86 -4
- package/dist/ag-ui-web-component.bundle.js +256 -47
- package/dist/ag-ui-web-component.bundle.js.map +4 -4
- package/dist/core/ag_ui_chat.d.ts +5 -1
- package/dist/core/ag_ui_chat.d.ts.map +1 -1
- package/dist/core/agui_client.d.ts.map +1 -1
- package/dist/index.js +579 -69
- package/dist/index.js.map +4 -4
- package/dist/skills/parse_skills.d.ts.map +1 -1
- package/dist/skills/skill.d.ts +14 -4
- package/dist/skills/skill.d.ts.map +1 -1
- package/dist/ui/confirmation_card.d.ts +8 -2
- package/dist/ui/confirmation_card.d.ts.map +1 -1
- package/dist/ui/resize_handle.d.ts +81 -0
- package/dist/ui/resize_handle.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/tool_call_card.d.ts +26 -14
- package/dist/ui/tool_call_card.d.ts.map +1 -1
- package/dist/ui/ui_strings.d.ts +12 -4
- package/dist/ui/ui_strings.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/core/ag_ui_chat.ts +230 -10
- package/src/core/agui_client.ts +27 -1
- package/src/skills/parse_skills.ts +8 -2
- package/src/skills/skill.ts +14 -4
- package/src/ui/confirmation_card.ts +15 -5
- package/src/ui/resize_handle.ts +176 -0
- package/src/ui/skills_menu.ts +13 -1
- package/src/ui/styles.ts +217 -6
- package/src/ui/tool_call_card.ts +116 -58
- package/src/ui/ui_strings.ts +17 -5
- package/src/version.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,168 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.20.0] — 2026-08-11
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **The panel is resizable.** A drag handle on the corner the layout grows
|
|
15
|
+
toward (or the inner edge when docked), with the size persisted per tab and
|
|
16
|
+
restored before the first paint. Arrow keys resize from the keyboard, since a pointer-only control
|
|
17
|
+
has no equivalent elsewhere in the UI; style it via the `resize-handle` part.
|
|
18
|
+
|
|
19
|
+
Which axes are draggable is the placement's call: `full` and `page` get no
|
|
20
|
+
handle at all (a `100vw`/`100vh` layout has nothing to drag), `sidebar` /
|
|
21
|
+
`side` get width only, everything else gets both.
|
|
22
|
+
|
|
23
|
+
⚠ **It writes the custom properties, not inline `width` / `height`.** The
|
|
24
|
+
placement rules set those same properties, so an inline dimension would
|
|
25
|
+
outrank them — a panel dragged while floating would keep that width after
|
|
26
|
+
switching to fullscreen.
|
|
27
|
+
|
|
28
|
+
⭐ **Which corner the grip sits on is measured, not assumed.** A resize is
|
|
29
|
+
computed from the edge that stays still, and which edge that is belongs to the
|
|
30
|
+
*host's* layout rather than to `placement` — a floating panel is pinned
|
|
31
|
+
bottom-right, an embedded one goes wherever the page's CSS puts it. Deriving
|
|
32
|
+
it from `placement` was wrong for any host that right-aligns the element, and
|
|
33
|
+
the symptom was bad enough to read as a broken control: the panel shrank when
|
|
34
|
+
dragged outward and travelled by its opposite corner. The element now probes
|
|
35
|
+
its own geometry and reflects the result as `data-resize-anchor`.
|
|
36
|
+
|
|
37
|
+
### Changed
|
|
38
|
+
|
|
39
|
+
- **The `/` palette leads with the command.** Each row now reads
|
|
40
|
+
`/fill-article Fill the article` rather than the label alone (part
|
|
41
|
+
`skill-item-token`), and a chip's tooltip names the token it stands for. A
|
|
42
|
+
palette that shows only labels cannot teach its own vocabulary — a user who
|
|
43
|
+
never sees `/fill-article` has no way to learn to type it.
|
|
44
|
+
|
|
45
|
+
- **A skill blocked on an unfilled `{placeholder}` now hands back the
|
|
46
|
+
template.** The partially-filled prompt goes into the composer with the first
|
|
47
|
+
unresolved placeholder selected, so the next keystroke replaces it. Previously
|
|
48
|
+
the pick was refused with a hint and whatever the user had typed to open the
|
|
49
|
+
palette — a lone `/` — was left in the composer, which said nothing about what
|
|
50
|
+
the skill wanted or how to supply it. The hint now says what to do, too.
|
|
51
|
+
|
|
52
|
+
- ⚠ **Picking a skill now sends it.** It used to write the text into the
|
|
53
|
+
composer and wait for a second click unless the skill set
|
|
54
|
+
`sendImmediately: true` — so the default behaviour of a shortcut was to not
|
|
55
|
+
take the shortcut. Set `sendImmediately: false` to keep pre-filling, which is
|
|
56
|
+
worth doing where the user is expected to edit before sending.
|
|
57
|
+
|
|
58
|
+
- **`Skill.prompt` is now optional, and omitting it is the better default for
|
|
59
|
+
anything internal.** A skill with no prompt is **server-resolved**: picking it
|
|
60
|
+
sends the bare `/name` token and the agent expands it, from the harness
|
|
61
|
+
`Skills` capability or the server's own instructions.
|
|
62
|
+
|
|
63
|
+
⛔ **The prompt was the leak.** A catalog is either a fetched `GET` or an
|
|
64
|
+
inline `data-skills` attribute sitting in the page source, and a skill is
|
|
65
|
+
often where a project's internal workflow is written down most plainly — so
|
|
66
|
+
the client-side catalog published it to anyone who opened the page. Sending a
|
|
67
|
+
token instead keeps the wording on the server entirely, which is what
|
|
68
|
+
"trigger a `/command` without exposing the prompt" actually requires; hiding
|
|
69
|
+
the text behind a chip label would only have moved it off screen.
|
|
70
|
+
|
|
71
|
+
`parseSkills` accepts a catalog entry with no `prompt` rather than dropping
|
|
72
|
+
it — requiring the field would have silently discarded exactly the skills
|
|
73
|
+
whose wording was kept off the browser. Pairs with `django-ag-ui`'s
|
|
74
|
+
`SkillSpec.prompt` becoming optional.
|
|
75
|
+
|
|
76
|
+
## [0.19.0] — 2026-08-11
|
|
77
|
+
|
|
78
|
+
### Changed
|
|
79
|
+
|
|
80
|
+
- **A tool card's arguments and its result are now two labelled regions, not one
|
|
81
|
+
block.** Compact mode emitted `args: {...}` and the result into a single
|
|
82
|
+
`<pre>` separated by a blank line, with nothing marking where the call ended
|
|
83
|
+
and the answer began. Both payloads now have their own heading, their own
|
|
84
|
+
`part` (`tool-card-args` / `tool-card-result`, headings via
|
|
85
|
+
`tool-card-section-label`, body via `tool-card-body`), and are pretty-printed.
|
|
86
|
+
|
|
87
|
+
⚠ Breaking for anyone styling `tool-card-result` as a single combined block.
|
|
88
|
+
A call with no arguments no longer renders an empty `{}` in a box of its own.
|
|
89
|
+
|
|
90
|
+
- ⭐ **`data-tool-display` is now live.** Changing it restyles every card already
|
|
91
|
+
in the transcript, the way `data-answer-well` always has. The modes are pure
|
|
92
|
+
visibility over **one DOM shape**, selected by the shadow CSS from the host
|
|
93
|
+
attribute; previously each card baked its structure at construction from the
|
|
94
|
+
value read at that moment, so a change reached only cards created afterwards
|
|
95
|
+
and the setting appeared not to work until the next conversation.
|
|
96
|
+
|
|
97
|
+
`ToolCallCard`'s constructor consequently no longer takes a mode argument.
|
|
98
|
+
|
|
99
|
+
- **The confirmation card leaves once it is answered.** It stayed in the
|
|
100
|
+
transcript as a spent form with its buttons disabled, which read as an
|
|
101
|
+
outstanding question rather than a settled one. A prompt and a record are
|
|
102
|
+
different objects: the record is the tool card it gates, which settles to the
|
|
103
|
+
outcome and scrolls with the rest of the transcript.
|
|
104
|
+
|
|
105
|
+
- ⛔ **The confirmation card was appended to the wrong parent**, and it is the
|
|
106
|
+
reason it drifted to the foot of a turn. Every other inline card — tool,
|
|
107
|
+
approval, `ask_user`, run notices — goes into the turn's answer group; this
|
|
108
|
+
one went into the message list, so it became a sibling *after* the group and
|
|
109
|
+
anything that streamed afterwards rendered above it. It now joins the group
|
|
110
|
+
like its siblings.
|
|
111
|
+
|
|
112
|
+
### Added
|
|
113
|
+
|
|
114
|
+
- **A gated call records the decision**, from the client-side confirmation card
|
|
115
|
+
**and** the server-side approval interrupt. The tool card carries
|
|
116
|
+
`approved by you` / `declined by you` (part `tool-card-decision`, attribute
|
|
117
|
+
`data-decision`). Previously only a *refusal* left a trace — an approved call
|
|
118
|
+
simply ran, making a gated call's transcript identical to one that was never
|
|
119
|
+
gated, and the server-side gate left nothing at all even though it is the one
|
|
120
|
+
guarding tools that run on the backend.
|
|
121
|
+
|
|
122
|
+
⚠ **Session-scoped, like the "run interrupted" notice.** AG-UI carries no
|
|
123
|
+
approval message — the answer rides `resume[]` as transient run input — so a
|
|
124
|
+
reload restores the call and its result but not the note. Durable "who
|
|
125
|
+
approved what" is an audit concern, not a transcript one.
|
|
126
|
+
|
|
127
|
+
- **Each header control takes its own icon slot** — `icon-history`,
|
|
128
|
+
`icon-checkpoints`, `icon-new`, `icon-collapse` — with the built-in glyph as
|
|
129
|
+
the fallback, so existing embeds are unchanged. The glyph used to be the
|
|
130
|
+
button's own `textContent`: a host could restyle a control through its `part`,
|
|
131
|
+
or swap one character for another with a CSS `content` override, but could
|
|
132
|
+
never supply a brand `<img>` or `<svg>`.
|
|
133
|
+
|
|
134
|
+
- **`argumentsLabel`, `decisionApproved` and `decisionDeclined`** in `UiStrings`.
|
|
135
|
+
`resultLabel` / `errorLabel` / `declinedLabel` are now the result region's
|
|
136
|
+
heading rather than a toggle label, and `details` labels the toggle in every
|
|
137
|
+
mode.
|
|
138
|
+
|
|
139
|
+
### Fixed
|
|
140
|
+
|
|
141
|
+
- **A server that reuses a message id now gets a warning.** `@ag-ui/client`
|
|
142
|
+
appends to a message id already in its history rather than starting a new one,
|
|
143
|
+
so two answers merge into one transcript entry — silently, and the merged
|
|
144
|
+
entry is what gets persisted. The protocol has no rule to enforce and refusing
|
|
145
|
+
the event would be worse than the merge, so this warns and continues.
|
|
146
|
+
|
|
147
|
+
⭐ Found because the demo harness was doing exactly this, which is the
|
|
148
|
+
argument for the harness in miniature: the bug was the consumer's, the
|
|
149
|
+
invisibility was ours.
|
|
150
|
+
|
|
151
|
+
- **The demo playground covers the surface it is meant to demonstrate.** The
|
|
152
|
+
scripted agent now dispatches on the latest turn — a server-resolved skill, a
|
|
153
|
+
tool that throws, an `ask_user` question, or the form-filling script — instead
|
|
154
|
+
of replaying one script for everything, and the page gained header-icon,
|
|
155
|
+
German-strings and reset-size controls plus a short "what to try" guide.
|
|
156
|
+
|
|
157
|
+
⚠ Two harness defects were making the component look broken. Its follow-up
|
|
158
|
+
detection matched **any** tool message in the thread, so once a conversation
|
|
159
|
+
had run a single tool every later turn answered "Done" to everything. And the
|
|
160
|
+
page forced `flex: 1` on the element, which silently outranks the width a
|
|
161
|
+
resize writes — the drag worked and nothing moved.
|
|
162
|
+
|
|
163
|
+
- **The demo harness reused message ids**, which produced three symptoms that
|
|
164
|
+
all read as component bugs and were none of them. It streamed every follow-up
|
|
165
|
+
answer under a hardcoded id, and `@ag-ui/client` appends to a message id
|
|
166
|
+
already in its history rather than starting a new one — so repeating a prompt
|
|
167
|
+
grew a single entry, that entry replayed out of order after a reload (sitting
|
|
168
|
+
where it was first created, with the later prompts after it), and the
|
|
169
|
+
unfinished-run notice then fired correctly over the corrupted history. Fresh
|
|
170
|
+
ids per message, as a real server issues.
|
|
171
|
+
|
|
10
172
|
## [0.18.0] — 2026-08-10
|
|
11
173
|
|
|
12
174
|
### Added
|
|
@@ -877,7 +1039,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
877
1039
|
### Notes
|
|
878
1040
|
- First release — exercising the automated npm OIDC publish pipeline end-to-end.
|
|
879
1041
|
|
|
880
|
-
[Unreleased]: https://github.com/Artui/ag-ui-web-component/compare/v0.
|
|
1042
|
+
[Unreleased]: https://github.com/Artui/ag-ui-web-component/compare/v0.20.0...HEAD
|
|
1043
|
+
[0.20.0]: https://github.com/Artui/ag-ui-web-component/compare/v0.19.0...v0.20.0
|
|
1044
|
+
[0.19.0]: https://github.com/Artui/ag-ui-web-component/compare/v0.18.0...v0.19.0
|
|
881
1045
|
[0.18.0]: https://github.com/Artui/ag-ui-web-component/compare/v0.17.0...v0.18.0
|
|
882
1046
|
[0.17.0]: https://github.com/Artui/ag-ui-web-component/compare/v0.16.0...v0.17.0
|
|
883
1047
|
[0.16.0]: https://github.com/Artui/ag-ui-web-component/compare/v0.15.0...v0.16.0
|
package/README.md
CHANGED
|
@@ -164,6 +164,16 @@ That's the whole integration: an `endpoint` attribute pointing at your AG-UI ser
|
|
|
164
164
|
| `data-theme-toggle` | — | Boolean: show a built-in header light⇄dark toggle (persists per tab). Off by default. See [Theme toggle](#theme-toggle). |
|
|
165
165
|
| `data-strings` | `strings` | Partial JSON override of the UI string table (localization). The property wins key-by-key over the attribute; see [Internationalization](#internationalization-i18n). |
|
|
166
166
|
| `data-icon-url` | — | Header (and sidebar-rail) icon image URL. A slotted `slot="icon"` wins; see [Header & launcher icon](#header-and-launcher-icon). |
|
|
167
|
+
|
|
168
|
+
Each header control also takes its own icon slot — `icon-history`, `icon-checkpoints`,
|
|
169
|
+
`icon-new`, `icon-collapse` — with the built-in glyph as the fallback, so a host can project a
|
|
170
|
+
brand `<img>` or `<svg>` rather than only restyling the character:
|
|
171
|
+
|
|
172
|
+
```html
|
|
173
|
+
<ag-ui-chat endpoint="/agent/">
|
|
174
|
+
<svg slot="icon-new" width="16" height="16"><!-- ... --></svg>
|
|
175
|
+
</ag-ui-chat>
|
|
176
|
+
```
|
|
167
177
|
| `data-page-actions` | — | Opt-in built-in page-action tools: a comma list of `scroll` / `drag` (e.g. `"scroll,drag"`). See [Page-action tools](#page-action-tools). |
|
|
168
178
|
| `data-side` | — | CSS-only, for `placement="sidebar"`: which edge it docks to — `right` (default) / `left`. |
|
|
169
179
|
| `data-answer-well` | — | CSS-only boolean: box each assistant turn (its text, tool cards, and thinking) in one bordered "well". Off by default. See [The answer well](#the-answer-well). |
|
|
@@ -506,8 +516,29 @@ property), one of `inline` / `minimal` / `compact` / `full` (default `full`):
|
|
|
506
516
|
result behind its own toggle. Reads as one line of the answer — pairs with [the answer
|
|
507
517
|
well](#the-answer-well).
|
|
508
518
|
- `minimal` — tool name + status pill only.
|
|
509
|
-
- `compact` — name + status, with
|
|
510
|
-
- `full` —
|
|
519
|
+
- `compact` — name + status, with arguments *and* result behind a single collapsed toggle.
|
|
520
|
+
- `full` — arguments visible, result behind the toggle (the default).
|
|
521
|
+
|
|
522
|
+
Whichever mode is on, a settled card's body holds **two labelled regions** — `Arguments` and
|
|
523
|
+
`Result` (or `Error` / `Declined`) — each with its own part and each pretty-printed. They are
|
|
524
|
+
never run together into one block, so where the call ends and the answer begins is always
|
|
525
|
+
visible. Style them via the `tool-card-args` / `tool-card-result` parts, their headings via
|
|
526
|
+
`tool-card-section-label`, and the whole body via `tool-card-body`.
|
|
527
|
+
|
|
528
|
+
**The attribute is live.** Changing `data-tool-display` restyles every card already in the
|
|
529
|
+
transcript, the way `data-answer-well` does — the modes are pure visibility over one DOM shape,
|
|
530
|
+
selected by the shadow CSS from the host attribute.
|
|
531
|
+
|
|
532
|
+
A gated call carries the decision (`approved by you` / `declined by you`, part
|
|
533
|
+
`tool-card-decision`, attribute `data-decision`) — from the client-side confirmation card and
|
|
534
|
+
from the server-side approval interrupt alike. The prompt itself disappears once answered: a
|
|
535
|
+
prompt and a record are different objects, and the record is the card.
|
|
536
|
+
|
|
537
|
+
⚠ **The annotation is session-scoped**, like the "run interrupted" notice. AG-UI carries no
|
|
538
|
+
approval message — the answer rides `resume[]` as transient run input — so a reload restores the
|
|
539
|
+
tool call and its result but not the note that a human waved it through. If you need "who
|
|
540
|
+
approved what" durably, that is an audit concern rather than a transcript one; record it
|
|
541
|
+
server-side.
|
|
511
542
|
|
|
512
543
|
If a tool's schema carries an `x-summary` string (use `X_SUMMARY_KEY`), the card shows it on the
|
|
513
544
|
label instead of the raw tool name.
|
|
@@ -524,6 +555,43 @@ speed; the spin respects `prefers-reduced-motion`).
|
|
|
524
555
|
|
|
525
556
|
---
|
|
526
557
|
|
|
558
|
+
## Resizing the panel
|
|
559
|
+
|
|
560
|
+
The panel carries a drag handle on its leading corner (or leading edge, docked),
|
|
561
|
+
so a reader can widen it without the host having to re-theme anything.
|
|
562
|
+
|
|
563
|
+
- `placement="full"` / `placement="page"` get **no handle** — a full-bleed layout
|
|
564
|
+
is `100vw`/`100vh` by definition, so there is nothing to drag.
|
|
565
|
+
- `placement="sidebar"` / `placement="side"` get **width only**; the placement
|
|
566
|
+
owns the height.
|
|
567
|
+
- Everything else resizes on both axes.
|
|
568
|
+
|
|
569
|
+
**The grip sits at the corner your layout grows toward, and the component
|
|
570
|
+
measures which one that is.** A resize has to be computed from the edge that
|
|
571
|
+
stays still, and that belongs to *your* CSS rather than to `placement` — a
|
|
572
|
+
floating panel is pinned bottom-right, an embedded one goes wherever the page
|
|
573
|
+
puts it. The element probes its own geometry and reflects the result as
|
|
574
|
+
`data-resize-anchor` (e.g. `bottom-right` means those two edges are fixed), which
|
|
575
|
+
is what positions the grip.
|
|
576
|
+
|
|
577
|
+
A drag writes `--ag-ui-width` / `--ag-ui-height` on the host **as custom
|
|
578
|
+
properties, not inline `width`/`height`** — the placement rules set those same
|
|
579
|
+
properties, so an inline dimension would outrank them and a panel dragged while
|
|
580
|
+
floating would keep that width after switching to fullscreen.
|
|
581
|
+
|
|
582
|
+
⚠ **A host rule that sizes the element wins over both.** `ag-ui-chat { flex: 1 }`
|
|
583
|
+
stretches the panel to its container and the dragged width has no visible
|
|
584
|
+
effect — which reads as a broken control rather than as your stylesheet winning.
|
|
585
|
+
Give the element `flex: 0 1 auto` (plus `max-width: 100%`) if it lives in a flex
|
|
586
|
+
container.
|
|
587
|
+
|
|
588
|
+
The size persists per tab (`sessionStorage`, namespaced per element like the
|
|
589
|
+
collapsed and theme preferences) and is restored before the first paint.
|
|
590
|
+
Arrow keys resize from the keyboard (`Shift` for a larger step); style the grip
|
|
591
|
+
via the `resize-handle` part.
|
|
592
|
+
|
|
593
|
+
---
|
|
594
|
+
|
|
527
595
|
## Markdown rendering
|
|
528
596
|
|
|
529
597
|
Assistant bubbles render sanitized markdown/HTML via [`marked`](https://www.npmjs.com/package/marked)
|
|
@@ -589,7 +657,7 @@ opt-in via two attributes:
|
|
|
589
657
|
<ag-ui-chat endpoint="/agent/" data-prompt-chips="true" data-slash-commands="true"></ag-ui-chat>
|
|
590
658
|
```
|
|
591
659
|
|
|
592
|
-
A `Skill` is `{ name, title, description?, prompt
|
|
660
|
+
A `Skill` is `{ name, title, description?, prompt?, sendImmediately?, chip? }`. Skills are merged
|
|
593
661
|
from three sources — **backend → embed → client** (later wins by `name`):
|
|
594
662
|
|
|
595
663
|
- `data-skills-url` — a JSON endpoint, fetched with the element's `headers`.
|
|
@@ -598,11 +666,21 @@ from three sources — **backend → embed → client** (later wins by `name`):
|
|
|
598
666
|
|
|
599
667
|
```js
|
|
600
668
|
chat.setSkills([
|
|
669
|
+
// Server-resolved: no prompt here, so picking it sends the bare "/triage"
|
|
670
|
+
// token and the agent decides what it means.
|
|
671
|
+
{ name: "triage", title: "Triage this", chip: true },
|
|
672
|
+
// Client-side: the page owns the wording and fills the placeholders.
|
|
601
673
|
{ name: "summarize", title: "Summarize page", prompt: "Summarize {title}.", chip: true },
|
|
602
674
|
]);
|
|
603
675
|
```
|
|
604
676
|
|
|
605
|
-
|
|
677
|
+
**Prefer omitting `prompt` for anything internal.** A skill is often where a project's workflow is
|
|
678
|
+
written down most plainly, and a catalog is either a plain `GET` or sits in the page source — so
|
|
679
|
+
shipping the wording to the browser publishes it. Without a `prompt` the component sends `/name`
|
|
680
|
+
and the agent expands it (from the harness `Skills` capability, or your own instructions); the text
|
|
681
|
+
never leaves the server. `django-ag-ui`'s `SkillRegistry` supports this by leaving `prompt` unset.
|
|
682
|
+
|
|
683
|
+
A skill that *does* carry a `prompt` may use `{placeholder}` tokens; the `skillContext` property
|
|
606
684
|
(`() => Record<string, unknown>`) supplies the values, filled in before send. A missing placeholder
|
|
607
685
|
blocks the send and shows a hint instead.
|
|
608
686
|
|
|
@@ -610,6 +688,10 @@ blocks the send and shows a hint instead.
|
|
|
610
688
|
chat.skillContext = () => ({ title: document.title });
|
|
611
689
|
```
|
|
612
690
|
|
|
691
|
+
**Picking a skill sends it.** A chip that needs a second click to do anything is a two-step
|
|
692
|
+
shortcut. Set `sendImmediately: false` on a prompt-carrying skill to pre-fill the composer instead —
|
|
693
|
+
useful when the user is expected to edit before sending. A server-resolved skill always sends.
|
|
694
|
+
|
|
613
695
|
---
|
|
614
696
|
|
|
615
697
|
## MPA durability: surviving full page reloads
|