@artooi/ag-ui-web-component 0.29.0 → 0.30.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 +199 -1
- package/README.md +196 -33
- package/dist/ag-ui-web-component.bundle.js +211 -28
- package/dist/ag-ui-web-component.bundle.js.map +4 -4
- package/dist/constants.d.ts +60 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/core/ag_ui_chat.d.ts +25 -1
- package/dist/core/ag_ui_chat.d.ts.map +1 -1
- package/dist/core/agui_client.d.ts +18 -1
- package/dist/core/agui_client.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +578 -35
- package/dist/index.js.map +4 -4
- package/dist/ui/message_actions.d.ts +14 -4
- package/dist/ui/message_actions.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/subagent_panel.d.ts +92 -0
- package/dist/ui/subagent_panel.d.ts.map +1 -0
- package/dist/ui/subagent_update.d.ts +19 -0
- package/dist/ui/subagent_update.d.ts.map +1 -0
- package/dist/ui/tool_call_card.d.ts +73 -1
- package/dist/ui/tool_call_card.d.ts.map +1 -1
- package/dist/ui/ui_strings.d.ts +10 -0
- package/dist/ui/ui_strings.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/constants.ts +63 -1
- package/src/core/ag_ui_chat.ts +180 -26
- package/src/core/agui_client.ts +26 -2
- package/src/index.ts +4 -0
- package/src/ui/message_actions.ts +20 -8
- package/src/ui/styles.ts +183 -0
- package/src/ui/subagent_panel.ts +213 -0
- package/src/ui/subagent_update.ts +80 -0
- package/src/ui/tool_call_card.ts +129 -3
- package/src/ui/ui_strings.ts +15 -0
- package/src/version.ts +1 -1
package/src/ui/tool_call_card.ts
CHANGED
|
@@ -42,6 +42,61 @@ function formatPayload(text: string): string {
|
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
/**
|
|
46
|
+
* One region of a card's body, handed to a host {@link ToolPayloadFormatter}.
|
|
47
|
+
*
|
|
48
|
+
* A discriminated union rather than three positional parameters because the two
|
|
49
|
+
* halves do not carry the same thing: arguments are the parsed record the call
|
|
50
|
+
* was made with, and a result is the raw string the tool returned, which may not
|
|
51
|
+
* be JSON at all. Flattening both into one `payload` parameter would force every
|
|
52
|
+
* formatter to re-derive which it had before it could read it, and the
|
|
53
|
+
* arguments would arrive re-serialised for no reason.
|
|
54
|
+
*
|
|
55
|
+
* `toolName` is the raw tool name, not the card's `x-summary` label -- a
|
|
56
|
+
* formatter dispatches on identity, and the label is a display string a server
|
|
57
|
+
* may change.
|
|
58
|
+
*/
|
|
59
|
+
export type ToolPayload =
|
|
60
|
+
| {
|
|
61
|
+
readonly kind: "arguments";
|
|
62
|
+
readonly toolName: string;
|
|
63
|
+
readonly args: Record<string, unknown>;
|
|
64
|
+
}
|
|
65
|
+
| {
|
|
66
|
+
readonly kind: "result";
|
|
67
|
+
readonly toolName: string;
|
|
68
|
+
readonly status: SettledStatus;
|
|
69
|
+
readonly text: string;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Renders one region of a tool card's body, for a host that would rather show a
|
|
74
|
+
* table or a summary line than a wall of pretty-printed JSON.
|
|
75
|
+
*
|
|
76
|
+
* Return a `Node` to take the region over, a `string` to replace its text, or
|
|
77
|
+
* `null` to fall through to the built-in pretty-print -- so a formatter that
|
|
78
|
+
* only cares about one tool, or only about results, declines the rest rather
|
|
79
|
+
* than reimplementing them.
|
|
80
|
+
*
|
|
81
|
+
* **Presentation only.** The model reads the tool result from its own copy of
|
|
82
|
+
* the message, which this never touches, so anything said here is said to the
|
|
83
|
+
* person and not to the agent. Translating a value -- an enum constant into a
|
|
84
|
+
* friendly label, an epoch into a date -- belongs on the server, where it also
|
|
85
|
+
* reaches the model's prose; doing it here would make the card and the answer
|
|
86
|
+
* beside it disagree about what happened.
|
|
87
|
+
*
|
|
88
|
+
* A returned string is set as text, never parsed as markup: this is not a
|
|
89
|
+
* second HTML channel into the transcript, and a host that wants elements
|
|
90
|
+
* builds them itself and returns the node.
|
|
91
|
+
*/
|
|
92
|
+
export type ToolPayloadFormatter = (payload: ToolPayload) => Node | string | null;
|
|
93
|
+
|
|
94
|
+
/** Optional per-card wiring beyond the name, arguments, label and strings. */
|
|
95
|
+
export interface ToolCallCardOptions {
|
|
96
|
+
/** Host presentation hook for both body regions. See {@link ToolPayloadFormatter}. */
|
|
97
|
+
readonly formatPayload?: ToolPayloadFormatter;
|
|
98
|
+
}
|
|
99
|
+
|
|
45
100
|
/**
|
|
46
101
|
* A live tool-call card for the chat transcript.
|
|
47
102
|
*
|
|
@@ -61,6 +116,12 @@ function formatPayload(text: string): string {
|
|
|
61
116
|
* `--ag-ui-tool-icon-*` custom properties or the `tool-card-icon` part without
|
|
62
117
|
* the card reaching into the host stylesheet.
|
|
63
118
|
*
|
|
119
|
+
* Either region may be drawn by the host instead: `options.formatPayload` is
|
|
120
|
+
* asked about each one and pretty-prints as before whenever it declines. The
|
|
121
|
+
* arguments are offered from the constructor and the result from {@link settle},
|
|
122
|
+
* because that is when each exists -- so a formatter is asked twice per card,
|
|
123
|
+
* potentially long apart.
|
|
124
|
+
*
|
|
64
125
|
* Pure DOM. The host appends {@link element} into its shadow root; all visible
|
|
65
126
|
* text comes from {@link UiStrings}.
|
|
66
127
|
*/
|
|
@@ -83,6 +144,23 @@ export class ToolCallCard {
|
|
|
83
144
|
*/
|
|
84
145
|
readonly approvalSlot: HTMLDivElement;
|
|
85
146
|
|
|
147
|
+
/**
|
|
148
|
+
* Where a *nested* run's progress renders — the sub-agent this call delegated
|
|
149
|
+
* to, narrating itself while the card waits.
|
|
150
|
+
*
|
|
151
|
+
* A slot rather than a rendered thing, on the same reasoning as
|
|
152
|
+
* {@link approvalSlot}: the card owns the position and something else owns the
|
|
153
|
+
* content. What makes the position right is that the wire keys a delegation on
|
|
154
|
+
* this card's own `toolCallId`, so the run being narrated is the one this card
|
|
155
|
+
* already stands for.
|
|
156
|
+
*
|
|
157
|
+
* Placed above the Details toggle rather than inside the body, because the
|
|
158
|
+
* body is what the display modes hide — and a progress line that only appears
|
|
159
|
+
* in `full` mode would leave exactly the stall it exists to end. Empty on every
|
|
160
|
+
* card that delegated nothing, and hidden while empty by the shadow CSS.
|
|
161
|
+
*/
|
|
162
|
+
readonly subagentSlot: HTMLDivElement;
|
|
163
|
+
|
|
86
164
|
readonly #status: HTMLSpanElement;
|
|
87
165
|
readonly #decision: HTMLSpanElement;
|
|
88
166
|
readonly #toggle: HTMLButtonElement;
|
|
@@ -98,6 +176,9 @@ export class ToolCallCard {
|
|
|
98
176
|
* still exist when the user is asked to approve, edit or deny the call.
|
|
99
177
|
*/
|
|
100
178
|
readonly args: Record<string, unknown>;
|
|
179
|
+
/** The raw tool name, kept for the payloads handed to {@link ToolPayloadFormatter}. */
|
|
180
|
+
readonly #name: string;
|
|
181
|
+
readonly #formatPayload: ToolPayloadFormatter | null;
|
|
101
182
|
#settled = false;
|
|
102
183
|
|
|
103
184
|
constructor(
|
|
@@ -105,9 +186,12 @@ export class ToolCallCard {
|
|
|
105
186
|
args: Record<string, unknown>,
|
|
106
187
|
summary?: string,
|
|
107
188
|
strings: UiStrings = DEFAULT_UI_STRINGS,
|
|
189
|
+
options: ToolCallCardOptions = {},
|
|
108
190
|
) {
|
|
109
191
|
this.#strings = strings;
|
|
110
192
|
this.args = args;
|
|
193
|
+
this.#name = name;
|
|
194
|
+
this.#formatPayload = options.formatPayload ?? null;
|
|
111
195
|
|
|
112
196
|
this.element = document.createElement("div");
|
|
113
197
|
this.element.className = "tool-call";
|
|
@@ -146,7 +230,11 @@ export class ToolCallCard {
|
|
|
146
230
|
head.append(icon, label, this.#status, this.#decision);
|
|
147
231
|
|
|
148
232
|
const argsSection = this.#section("args", strings.argumentsLabel);
|
|
149
|
-
|
|
233
|
+
this.#renderPayload(
|
|
234
|
+
argsSection.body,
|
|
235
|
+
{ kind: "arguments", toolName: name, args },
|
|
236
|
+
JSON.stringify(args, null, 2),
|
|
237
|
+
);
|
|
150
238
|
// Drop the region rather than frame an empty object.
|
|
151
239
|
argsSection.root.hidden = Object.keys(args).length === 0;
|
|
152
240
|
|
|
@@ -175,7 +263,11 @@ export class ToolCallCard {
|
|
|
175
263
|
this.approvalSlot.className = "tool-call-approval";
|
|
176
264
|
this.approvalSlot.setAttribute("part", "tool-card-approval");
|
|
177
265
|
|
|
178
|
-
this.
|
|
266
|
+
this.subagentSlot = document.createElement("div");
|
|
267
|
+
this.subagentSlot.className = "tool-call-subagent";
|
|
268
|
+
this.subagentSlot.setAttribute("part", "tool-card-subagent");
|
|
269
|
+
|
|
270
|
+
this.element.append(head, this.subagentSlot, this.#toggle, body, this.approvalSlot);
|
|
179
271
|
}
|
|
180
272
|
|
|
181
273
|
/**
|
|
@@ -224,10 +316,44 @@ export class ToolCallCard {
|
|
|
224
316
|
this.element.setAttribute("data-status", status);
|
|
225
317
|
this.#status.textContent = statusLabels(this.#strings)[status];
|
|
226
318
|
this.#resultLabel.textContent = resultLabels(this.#strings)[status];
|
|
227
|
-
this.#
|
|
319
|
+
this.#renderPayload(
|
|
320
|
+
this.#resultBody,
|
|
321
|
+
{ kind: "result", toolName: this.#name, status, text },
|
|
322
|
+
formatPayload(text),
|
|
323
|
+
);
|
|
228
324
|
this.#resultSection.hidden = false;
|
|
229
325
|
}
|
|
230
326
|
|
|
327
|
+
/**
|
|
328
|
+
* Fill one body region, offering it to the host formatter first.
|
|
329
|
+
*
|
|
330
|
+
* `fallback` is computed by the caller rather than here because the two
|
|
331
|
+
* regions build it differently -- arguments are already parsed, a result is a
|
|
332
|
+
* string that may or may not be JSON -- and because a formatter that takes
|
|
333
|
+
* the region over should not have paid for a pretty-print nobody sees. It is
|
|
334
|
+
* cheap either way; the point is that the built-in rendering stays written
|
|
335
|
+
* once, beside the payload it belongs to.
|
|
336
|
+
*
|
|
337
|
+
* The `data-formatted` marker is what the shadow CSS reads to relax the
|
|
338
|
+
* preformatted whitespace on a region a host owns -- a table inherits it as
|
|
339
|
+
* mangled cell spacing, a sentence as line breaks nobody typed. Marked for a
|
|
340
|
+
* returned string too: one rule, and a summary line wants ordinary wrapping
|
|
341
|
+
* as much as a table does.
|
|
342
|
+
*/
|
|
343
|
+
#renderPayload(body: HTMLPreElement, payload: ToolPayload, fallback: string): void {
|
|
344
|
+
const rendered = this.#formatPayload === null ? null : this.#formatPayload(payload);
|
|
345
|
+
if (rendered === null) {
|
|
346
|
+
body.textContent = fallback;
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
body.setAttribute("data-formatted", "true");
|
|
350
|
+
if (typeof rendered === "string") {
|
|
351
|
+
body.textContent = rendered;
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
body.replaceChildren(rendered);
|
|
355
|
+
}
|
|
356
|
+
|
|
231
357
|
/** Build one labelled region of the body: a heading plus a payload block. */
|
|
232
358
|
#section(
|
|
233
359
|
kind: string,
|
package/src/ui/ui_strings.ts
CHANGED
|
@@ -131,6 +131,18 @@ export interface UiStrings {
|
|
|
131
131
|
/** Label on the toggle that expands a tool card's body. */
|
|
132
132
|
details: string;
|
|
133
133
|
|
|
134
|
+
// ── Delegated sub-agent ─────────────────────────────────────────────────────
|
|
135
|
+
/**
|
|
136
|
+
* The delegation row's text before the server's own status line lands.
|
|
137
|
+
*
|
|
138
|
+
* A fallback, not a state: every announcement carries a pre-rendered `status`,
|
|
139
|
+
* and this only shows if one arrives unusable. The row is the expander, so it
|
|
140
|
+
* must never be blank.
|
|
141
|
+
*/
|
|
142
|
+
subAgentWorking: string;
|
|
143
|
+
/** `aria-label` of the region holding the sub-agent's own tool calls. */
|
|
144
|
+
subAgentSteps: string;
|
|
145
|
+
|
|
134
146
|
// ── Confirmation card ───────────────────────────────────────────────────────
|
|
135
147
|
/** `aria-label` of the editable arguments field on an approval card. */
|
|
136
148
|
approvalEditArgs: string;
|
|
@@ -319,6 +331,9 @@ export const DEFAULT_UI_STRINGS: UiStrings = {
|
|
|
319
331
|
declinedLabel: "Declined",
|
|
320
332
|
details: "Details",
|
|
321
333
|
|
|
334
|
+
subAgentWorking: "Working…",
|
|
335
|
+
subAgentSteps: "Steps the sub-agent took",
|
|
336
|
+
|
|
322
337
|
approvalEditArgs: "Edit the arguments before approving",
|
|
323
338
|
approvalArgsInvalid: "That is not valid JSON, so nothing was sent.",
|
|
324
339
|
approvalArgsNotAnObject: "Arguments have to be a JSON object.",
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const VERSION: string = "0.
|
|
1
|
+
export const VERSION: string = "0.30.0";
|