@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
|
@@ -8,6 +8,56 @@ export type ToolDisplayMode = (typeof TOOL_DISPLAY)[keyof typeof TOOL_DISPLAY];
|
|
|
8
8
|
export type UnsettledStatus = typeof TOOL_CALL_STATUS.PENDING | typeof TOOL_CALL_STATUS.DEFERRED;
|
|
9
9
|
/** The terminal states a card settles into (everything unsettled excluded). */
|
|
10
10
|
export type SettledStatus = Exclude<ToolCallStatus, UnsettledStatus>;
|
|
11
|
+
/**
|
|
12
|
+
* One region of a card's body, handed to a host {@link ToolPayloadFormatter}.
|
|
13
|
+
*
|
|
14
|
+
* A discriminated union rather than three positional parameters because the two
|
|
15
|
+
* halves do not carry the same thing: arguments are the parsed record the call
|
|
16
|
+
* was made with, and a result is the raw string the tool returned, which may not
|
|
17
|
+
* be JSON at all. Flattening both into one `payload` parameter would force every
|
|
18
|
+
* formatter to re-derive which it had before it could read it, and the
|
|
19
|
+
* arguments would arrive re-serialised for no reason.
|
|
20
|
+
*
|
|
21
|
+
* `toolName` is the raw tool name, not the card's `x-summary` label -- a
|
|
22
|
+
* formatter dispatches on identity, and the label is a display string a server
|
|
23
|
+
* may change.
|
|
24
|
+
*/
|
|
25
|
+
export type ToolPayload = {
|
|
26
|
+
readonly kind: "arguments";
|
|
27
|
+
readonly toolName: string;
|
|
28
|
+
readonly args: Record<string, unknown>;
|
|
29
|
+
} | {
|
|
30
|
+
readonly kind: "result";
|
|
31
|
+
readonly toolName: string;
|
|
32
|
+
readonly status: SettledStatus;
|
|
33
|
+
readonly text: string;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Renders one region of a tool card's body, for a host that would rather show a
|
|
37
|
+
* table or a summary line than a wall of pretty-printed JSON.
|
|
38
|
+
*
|
|
39
|
+
* Return a `Node` to take the region over, a `string` to replace its text, or
|
|
40
|
+
* `null` to fall through to the built-in pretty-print -- so a formatter that
|
|
41
|
+
* only cares about one tool, or only about results, declines the rest rather
|
|
42
|
+
* than reimplementing them.
|
|
43
|
+
*
|
|
44
|
+
* **Presentation only.** The model reads the tool result from its own copy of
|
|
45
|
+
* the message, which this never touches, so anything said here is said to the
|
|
46
|
+
* person and not to the agent. Translating a value -- an enum constant into a
|
|
47
|
+
* friendly label, an epoch into a date -- belongs on the server, where it also
|
|
48
|
+
* reaches the model's prose; doing it here would make the card and the answer
|
|
49
|
+
* beside it disagree about what happened.
|
|
50
|
+
*
|
|
51
|
+
* A returned string is set as text, never parsed as markup: this is not a
|
|
52
|
+
* second HTML channel into the transcript, and a host that wants elements
|
|
53
|
+
* builds them itself and returns the node.
|
|
54
|
+
*/
|
|
55
|
+
export type ToolPayloadFormatter = (payload: ToolPayload) => Node | string | null;
|
|
56
|
+
/** Optional per-card wiring beyond the name, arguments, label and strings. */
|
|
57
|
+
export interface ToolCallCardOptions {
|
|
58
|
+
/** Host presentation hook for both body regions. See {@link ToolPayloadFormatter}. */
|
|
59
|
+
readonly formatPayload?: ToolPayloadFormatter;
|
|
60
|
+
}
|
|
11
61
|
/**
|
|
12
62
|
* A live tool-call card for the chat transcript.
|
|
13
63
|
*
|
|
@@ -27,6 +77,12 @@ export type SettledStatus = Exclude<ToolCallStatus, UnsettledStatus>;
|
|
|
27
77
|
* `--ag-ui-tool-icon-*` custom properties or the `tool-card-icon` part without
|
|
28
78
|
* the card reaching into the host stylesheet.
|
|
29
79
|
*
|
|
80
|
+
* Either region may be drawn by the host instead: `options.formatPayload` is
|
|
81
|
+
* asked about each one and pretty-prints as before whenever it declines. The
|
|
82
|
+
* arguments are offered from the constructor and the result from {@link settle},
|
|
83
|
+
* because that is when each exists -- so a formatter is asked twice per card,
|
|
84
|
+
* potentially long apart.
|
|
85
|
+
*
|
|
30
86
|
* Pure DOM. The host appends {@link element} into its shadow root; all visible
|
|
31
87
|
* text comes from {@link UiStrings}.
|
|
32
88
|
*/
|
|
@@ -48,6 +104,22 @@ export declare class ToolCallCard {
|
|
|
48
104
|
* Empty until used, and hidden while empty by the shadow CSS.
|
|
49
105
|
*/
|
|
50
106
|
readonly approvalSlot: HTMLDivElement;
|
|
107
|
+
/**
|
|
108
|
+
* Where a *nested* run's progress renders — the sub-agent this call delegated
|
|
109
|
+
* to, narrating itself while the card waits.
|
|
110
|
+
*
|
|
111
|
+
* A slot rather than a rendered thing, on the same reasoning as
|
|
112
|
+
* {@link approvalSlot}: the card owns the position and something else owns the
|
|
113
|
+
* content. What makes the position right is that the wire keys a delegation on
|
|
114
|
+
* this card's own `toolCallId`, so the run being narrated is the one this card
|
|
115
|
+
* already stands for.
|
|
116
|
+
*
|
|
117
|
+
* Placed above the Details toggle rather than inside the body, because the
|
|
118
|
+
* body is what the display modes hide — and a progress line that only appears
|
|
119
|
+
* in `full` mode would leave exactly the stall it exists to end. Empty on every
|
|
120
|
+
* card that delegated nothing, and hidden while empty by the shadow CSS.
|
|
121
|
+
*/
|
|
122
|
+
readonly subagentSlot: HTMLDivElement;
|
|
51
123
|
/**
|
|
52
124
|
* The arguments this call was made with.
|
|
53
125
|
*
|
|
@@ -56,7 +128,7 @@ export declare class ToolCallCard {
|
|
|
56
128
|
* still exist when the user is asked to approve, edit or deny the call.
|
|
57
129
|
*/
|
|
58
130
|
readonly args: Record<string, unknown>;
|
|
59
|
-
constructor(name: string, args: Record<string, unknown>, summary?: string, strings?: UiStrings);
|
|
131
|
+
constructor(name: string, args: Record<string, unknown>, summary?: string, strings?: UiStrings, options?: ToolCallCardOptions);
|
|
60
132
|
/**
|
|
61
133
|
* Move between the two states that are not an outcome — `pending` (running)
|
|
62
134
|
* and `deferred` (gated, waiting on a person).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool_call_card.d.ts","sourceRoot":"","sources":["../../src/ui/tool_call_card.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACtE,OAAO,EAAsB,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAErE,4CAA4C;AAC5C,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,OAAO,gBAAgB,CAAC,CAAC;AAEtF,sCAAsC;AACtC,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,OAAO,YAAY,CAAC,CAAC;AAE/E,iEAAiE;AACjE,MAAM,MAAM,eAAe,GAAG,OAAO,gBAAgB,CAAC,OAAO,GAAG,OAAO,gBAAgB,CAAC,QAAQ,CAAC;AAEjG,+EAA+E;AAC/E,MAAM,MAAM,aAAa,GAAG,OAAO,CAAC,cAAc,EAAE,eAAe,CAAC,CAAC;AA+BrE
|
|
1
|
+
{"version":3,"file":"tool_call_card.d.ts","sourceRoot":"","sources":["../../src/ui/tool_call_card.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACtE,OAAO,EAAsB,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAErE,4CAA4C;AAC5C,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,OAAO,gBAAgB,CAAC,CAAC;AAEtF,sCAAsC;AACtC,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,OAAO,YAAY,CAAC,CAAC;AAE/E,iEAAiE;AACjE,MAAM,MAAM,eAAe,GAAG,OAAO,gBAAgB,CAAC,OAAO,GAAG,OAAO,gBAAgB,CAAC,QAAQ,CAAC;AAEjG,+EAA+E;AAC/E,MAAM,MAAM,aAAa,GAAG,OAAO,CAAC,cAAc,EAAE,eAAe,CAAC,CAAC;AA+BrE;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,WAAW,GACnB;IACE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACxC,GACD;IACE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB,CAAC;AAEN;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,GAAG,MAAM,GAAG,IAAI,CAAC;AAElF,8EAA8E;AAC9E,MAAM,WAAW,mBAAmB;IAClC,sFAAsF;IACtF,QAAQ,CAAC,aAAa,CAAC,EAAE,oBAAoB,CAAC;CAC/C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,qBAAa,YAAY;;IACvB,kEAAkE;IAClE,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IAEjC;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,YAAY,EAAE,cAAc,CAAC;IAEtC;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,YAAY,EAAE,cAAc,CAAC;IAStC;;;;;;OAMG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAMvC,YACE,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,CAAC,EAAE,MAAM,EAChB,OAAO,GAAE,SAA8B,EACvC,OAAO,GAAE,mBAAwB,EAkFlC;IAED;;;;;;OAMG;IACH,IAAI,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI,CAMlC;IAED;;;;OAIG;IACH,cAAc,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU,GAAG,IAAI,CAKlD;IAED,gFAAgF;IAChF,IAAI,OAAO,IAAI,OAAO,CAErB;IAED;;;OAGG;IACH,MAAM,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAgBhD;CAkEF"}
|
package/dist/ui/ui_strings.d.ts
CHANGED
|
@@ -123,6 +123,16 @@ export interface UiStrings {
|
|
|
123
123
|
declinedLabel: string;
|
|
124
124
|
/** Label on the toggle that expands a tool card's body. */
|
|
125
125
|
details: string;
|
|
126
|
+
/**
|
|
127
|
+
* The delegation row's text before the server's own status line lands.
|
|
128
|
+
*
|
|
129
|
+
* A fallback, not a state: every announcement carries a pre-rendered `status`,
|
|
130
|
+
* and this only shows if one arrives unusable. The row is the expander, so it
|
|
131
|
+
* must never be blank.
|
|
132
|
+
*/
|
|
133
|
+
subAgentWorking: string;
|
|
134
|
+
/** `aria-label` of the region holding the sub-agent's own tool calls. */
|
|
135
|
+
subAgentSteps: string;
|
|
126
136
|
/** `aria-label` of the editable arguments field on an approval card. */
|
|
127
137
|
approvalEditArgs: string;
|
|
128
138
|
/** Shown when the edited arguments are not valid JSON. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui_strings.d.ts","sourceRoot":"","sources":["../../src/ui/ui_strings.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"ui_strings.d.ts","sourceRoot":"","sources":["../../src/ui/ui_strings.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@artooi/ag-ui-web-component",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.30.0",
|
|
4
4
|
"description": "Framework-free <ag-ui-chat> Web Component over the AG-UI protocol. Drop-in chat sidebar with a pluggable client-side tool registry, DOM driver primitives, animations, and destructive-action confirmation modal.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
package/src/constants.ts
CHANGED
|
@@ -119,6 +119,45 @@ export const SUGGESTIONS_ACTIVITY_TYPE = "suggestions";
|
|
|
119
119
|
*/
|
|
120
120
|
export const INVALIDATE_CUSTOM_NAME = "ag_ui.invalidate";
|
|
121
121
|
|
|
122
|
+
/**
|
|
123
|
+
* The AG-UI `CUSTOM` event `name` carrying a delegated sub-agent's progress.
|
|
124
|
+
*
|
|
125
|
+
* Matched exactly, and namespaced the way {@link INVALIDATE_CUSTOM_NAME} is, so
|
|
126
|
+
* it cannot collide with a host's own custom events on the same open field.
|
|
127
|
+
*
|
|
128
|
+
* Routed to the delegating tool card rather than dispatched to the page: the
|
|
129
|
+
* payload keys on the **parent's own `delegate_task` call id**, so what it
|
|
130
|
+
* describes is already on screen and the progress belongs beside it. Every other
|
|
131
|
+
* name still reaches the host as {@link CUSTOM_AGENT_EVENT}.
|
|
132
|
+
*
|
|
133
|
+
* Deliberately on the imperative carrier and not on an activity, which means it
|
|
134
|
+
* is **never persisted and never replayed**. That is the right half of the
|
|
135
|
+
* split: a delegation that was live an hour ago is not live now, and replaying
|
|
136
|
+
* its progress on a thread restore would be a lie about a run that is over. On a
|
|
137
|
+
* reload mid-run the nested detail is gone and the tool card remains.
|
|
138
|
+
*/
|
|
139
|
+
export const SUBAGENT_CUSTOM_NAME = "ag_ui.subagent";
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* The phases one delegation moves through, as the server spells them.
|
|
143
|
+
*
|
|
144
|
+
* Exactly one `STARTED` opens a delegation and exactly one `FINISHED` or
|
|
145
|
+
* `FAILED` closes it; the two tool phases repeat in between, once per call the
|
|
146
|
+
* child makes and once per result it gets back.
|
|
147
|
+
*
|
|
148
|
+
* `FAILED` carries **no exception text**, deliberately — the same reasoning that
|
|
149
|
+
* redacts a `RUN_ERROR`, since an exception's words are written for an operator.
|
|
150
|
+
* The detail rides the ordinary `TOOL_CALL_RESULT` for that delegation, on the
|
|
151
|
+
* card the progress is already attached to.
|
|
152
|
+
*/
|
|
153
|
+
export const SUBAGENT_PHASE = {
|
|
154
|
+
STARTED: "started",
|
|
155
|
+
TOOL_CALL: "tool_call",
|
|
156
|
+
TOOL_RESULT: "tool_result",
|
|
157
|
+
FINISHED: "finished",
|
|
158
|
+
FAILED: "failed",
|
|
159
|
+
} as const;
|
|
160
|
+
|
|
122
161
|
/** Roles a chat message can take. */
|
|
123
162
|
export const MESSAGE_ROLE = {
|
|
124
163
|
USER: "user",
|
|
@@ -158,9 +197,32 @@ export const X_NAVIGATES_KEY = "x-navigates";
|
|
|
158
197
|
*/
|
|
159
198
|
export const READ_PAGE_TOOL = "read_page";
|
|
160
199
|
|
|
161
|
-
/**
|
|
200
|
+
/**
|
|
201
|
+
* Default upper bound on frontend tool-call → re-run rounds within one send.
|
|
202
|
+
* Overridable via `data-max-tool-rounds`, or `AgUiClientConfig.maxToolRounds`
|
|
203
|
+
* for a host driving the client directly.
|
|
204
|
+
*/
|
|
162
205
|
export const MAX_TOOL_ROUNDS = 10;
|
|
163
206
|
|
|
207
|
+
/**
|
|
208
|
+
* The actions a finished assistant message's row can carry, and the tokens
|
|
209
|
+
* `data-message-actions` selects them by.
|
|
210
|
+
*
|
|
211
|
+
* All three are on when the attribute is absent. Naming them individually
|
|
212
|
+
* rather than shipping one on/off switch is what the three differ over: feedback
|
|
213
|
+
* is only useful to a host listening for {@link FEEDBACK_EVENT}, retry re-runs
|
|
214
|
+
* the agent and a constrained surface may not permit that, and copy is the one
|
|
215
|
+
* nobody objects to. A single switch would make dropping either of the first two
|
|
216
|
+
* cost the third, and a host that only wanted one gone would rebuild the row
|
|
217
|
+
* from `attachMessageActions` -- reimplementing the part names, the accessible
|
|
218
|
+
* grouping and the retry hand-off to lose two buttons.
|
|
219
|
+
*/
|
|
220
|
+
export const MESSAGE_ACTIONS = {
|
|
221
|
+
COPY: "copy",
|
|
222
|
+
RETRY: "retry",
|
|
223
|
+
FEEDBACK: "feedback",
|
|
224
|
+
} as const;
|
|
225
|
+
|
|
164
226
|
/**
|
|
165
227
|
* Lifecycle status of a rendered tool-call card. A card opens as `PENDING`
|
|
166
228
|
* while the call runs, then settles to `DONE`, `ERROR`, or `DECLINED`.
|
package/src/core/ag_ui_chat.ts
CHANGED
|
@@ -15,10 +15,13 @@ import {
|
|
|
15
15
|
INVALIDATE_CUSTOM_NAME,
|
|
16
16
|
INVALIDATE_EVENT,
|
|
17
17
|
LOAD_CAPABILITY_TOOL,
|
|
18
|
+
MAX_TOOL_ROUNDS,
|
|
19
|
+
MESSAGE_ACTIONS,
|
|
18
20
|
MESSAGE_ROLE,
|
|
19
21
|
READ_PAGE_TOOL,
|
|
20
22
|
RUN_FINISHED_EVENT,
|
|
21
23
|
STATE_EVENT,
|
|
24
|
+
SUBAGENT_CUSTOM_NAME,
|
|
22
25
|
SUBMIT_EVENT,
|
|
23
26
|
SUGGESTIONS_ACTIVITY_TYPE,
|
|
24
27
|
TOGGLE_EVENT,
|
|
@@ -79,10 +82,16 @@ import { renderRunNotice } from "../ui/run_notice.js";
|
|
|
79
82
|
import { SkillsMenu } from "../ui/skills_menu.js";
|
|
80
83
|
import { createStickToBottom, type StickToBottom } from "../ui/stick_to_bottom.js";
|
|
81
84
|
import { STYLES } from "../ui/styles.js";
|
|
85
|
+
import { SubAgentPanel } from "../ui/subagent_panel.js";
|
|
86
|
+
import { subAgentUpdate } from "../ui/subagent_update.js";
|
|
82
87
|
import { renderSuggestionChips } from "../ui/suggestion_chips.js";
|
|
83
88
|
import { ThoughtsBlock } from "../ui/thoughts_block.js";
|
|
84
89
|
import { ThreadDrawer } from "../ui/thread_drawer.js";
|
|
85
|
-
import {
|
|
90
|
+
import {
|
|
91
|
+
ToolCallCard,
|
|
92
|
+
type ToolDisplayMode,
|
|
93
|
+
type ToolPayloadFormatter,
|
|
94
|
+
} from "../ui/tool_call_card.js";
|
|
86
95
|
import { DEFAULT_UI_STRINGS, mergeUiStrings, type UiStrings } from "../ui/ui_strings.js";
|
|
87
96
|
import { VoiceInput } from "../ui/voice_input.js";
|
|
88
97
|
import {
|
|
@@ -532,6 +541,31 @@ export class AgUiChat extends HTMLElement {
|
|
|
532
541
|
*/
|
|
533
542
|
toolSummaries: Record<string, string> = {};
|
|
534
543
|
|
|
544
|
+
/**
|
|
545
|
+
* Optional presentation hook for the two payload regions of a tool-call card
|
|
546
|
+
* -- the arguments and the result. Unset (the default) leaves both
|
|
547
|
+
* pretty-printed as JSON.
|
|
548
|
+
*
|
|
549
|
+
* The seam exists because a wide result has no good rendering as JSON: a
|
|
550
|
+
* thirty-field row is a wall of text where the host wanted a table, or a
|
|
551
|
+
* sentence. `ClientTool.render` cannot answer it -- it is handed the
|
|
552
|
+
* *arguments* only, and a server-side tool has no `ClientTool` at all, so the
|
|
553
|
+
* result region was the one part of the transcript a host could not reach.
|
|
554
|
+
*
|
|
555
|
+
* **Presentation, not translation.** The card and the model already read
|
|
556
|
+
* separate copies of a tool result: the model's is maintained by
|
|
557
|
+
* `@ag-ui/client` from the same event and persisted with the history, and the
|
|
558
|
+
* card has always shown that string reformatted. So a formatter changes what
|
|
559
|
+
* the person reads and nothing the agent reads -- which makes restyling safe
|
|
560
|
+
* and *rewording* a way to make the card disagree with the prose beside it.
|
|
561
|
+
* Rename a value on the server, where it reaches both.
|
|
562
|
+
*
|
|
563
|
+
* Read at render time rather than captured, so a host that sets it from a
|
|
564
|
+
* framework effect after the first card still formats the results that settle
|
|
565
|
+
* afterwards. See {@link ToolPayloadFormatter}.
|
|
566
|
+
*/
|
|
567
|
+
formatToolPayload: ToolPayloadFormatter | null = null;
|
|
568
|
+
|
|
535
569
|
/**
|
|
536
570
|
* Localizable UI strings — a partial override merged over the English
|
|
537
571
|
* {@link DEFAULT_UI_STRINGS}. Resolved once on connect (so set it before the
|
|
@@ -586,6 +620,16 @@ export class AgUiChat extends HTMLElement {
|
|
|
586
620
|
readonly #toolRegistry = new ClientToolRegistry();
|
|
587
621
|
/** Tool-call cards awaiting execution, keyed by call id. */
|
|
588
622
|
readonly #toolCards = new Map<string, ToolCallCard>();
|
|
623
|
+
/**
|
|
624
|
+
* The live delegation panels, keyed by the **parent's** `delegate_task` call
|
|
625
|
+
* id — which is what the wire keys a sub-agent's progress on, so this map and
|
|
626
|
+
* {@link #toolCards} answer to the same key.
|
|
627
|
+
*
|
|
628
|
+
* Kept beside the cards rather than on them, so a card stays a card: the tool
|
|
629
|
+
* card holds the slot and this holds what went into it, the same division the
|
|
630
|
+
* approval prompt already uses.
|
|
631
|
+
*/
|
|
632
|
+
readonly #subagentPanels = new Map<string, SubAgentPanel>();
|
|
589
633
|
/**
|
|
590
634
|
* Call ids whose card was already settled from a streamed server-side result
|
|
591
635
|
* (`TOOL_CALL_RESULT`), so the post-run executeTool sweep doesn't overwrite
|
|
@@ -1744,6 +1788,42 @@ export class AgUiChat extends HTMLElement {
|
|
|
1744
1788
|
this.#quoting = "";
|
|
1745
1789
|
}
|
|
1746
1790
|
|
|
1791
|
+
/**
|
|
1792
|
+
* The tool-round budget from `data-max-tool-rounds`, for one send.
|
|
1793
|
+
*
|
|
1794
|
+
* Anything unparseable becomes `NaN`, which {@link AgUiClient} rejects along
|
|
1795
|
+
* with a bound below one -- so the two ways of setting this are validated in
|
|
1796
|
+
* one place rather than agreeing by coincidence.
|
|
1797
|
+
*/
|
|
1798
|
+
#maxToolRounds(): number {
|
|
1799
|
+
const attr = this.getAttribute("data-max-tool-rounds");
|
|
1800
|
+
return attr === null ? MAX_TOOL_ROUNDS : Number.parseInt(attr, 10);
|
|
1801
|
+
}
|
|
1802
|
+
|
|
1803
|
+
/**
|
|
1804
|
+
* Which message actions a finished bubble offers, from
|
|
1805
|
+
* `data-message-actions`.
|
|
1806
|
+
*
|
|
1807
|
+
* Absent means all of them, so the attribute only ever subtracts: the row
|
|
1808
|
+
* shipped without an off switch and a host that never sets this must keep
|
|
1809
|
+
* exactly what it had. A value names the survivors, which makes
|
|
1810
|
+
* `data-message-actions="false"` -- the spelling its sibling
|
|
1811
|
+
* `data-quote-selection` uses -- an empty set by falling out of the same rule
|
|
1812
|
+
* rather than by a case of its own.
|
|
1813
|
+
*/
|
|
1814
|
+
#messageActions(): ReadonlySet<string> {
|
|
1815
|
+
const attr = this.getAttribute("data-message-actions");
|
|
1816
|
+
if (attr === null) {
|
|
1817
|
+
return new Set(Object.values(MESSAGE_ACTIONS));
|
|
1818
|
+
}
|
|
1819
|
+
return new Set(
|
|
1820
|
+
attr
|
|
1821
|
+
.split(",")
|
|
1822
|
+
.map((token) => token.trim())
|
|
1823
|
+
.filter((token) => token !== ""),
|
|
1824
|
+
);
|
|
1825
|
+
}
|
|
1826
|
+
|
|
1747
1827
|
/** The client-side upload size cap from `data-attachment-max-bytes`. */
|
|
1748
1828
|
#attachmentMaxBytes(): number {
|
|
1749
1829
|
const attr = this.getAttribute("data-attachment-max-bytes");
|
|
@@ -2381,6 +2461,11 @@ export class AgUiChat extends HTMLElement {
|
|
|
2381
2461
|
this.#thoughts = null;
|
|
2382
2462
|
this.#hidePending();
|
|
2383
2463
|
this.#toolCards.clear();
|
|
2464
|
+
// The panels go with the cards they hung off. Nothing restores them: the
|
|
2465
|
+
// progress rode the imperative carrier and was never persisted, which is
|
|
2466
|
+
// the correct half of that split -- a delegation that was live before this
|
|
2467
|
+
// transcript was wiped is not live now.
|
|
2468
|
+
this.#subagentPanels.clear();
|
|
2384
2469
|
this.#serverSettled.clear();
|
|
2385
2470
|
this.#cardElements.clear();
|
|
2386
2471
|
this.#activityBlocks.clear();
|
|
@@ -3414,6 +3499,7 @@ export class AgUiChat extends HTMLElement {
|
|
|
3414
3499
|
onPersist: (messages) => this.conversationStore.saveMessages(this.#threadId, messages),
|
|
3415
3500
|
onStateChanged: (state) => this.#onSharedStateChanged(state),
|
|
3416
3501
|
connectionLostMessage: this.#strings.connectionLost,
|
|
3502
|
+
maxToolRounds: this.#maxToolRounds(),
|
|
3417
3503
|
});
|
|
3418
3504
|
}
|
|
3419
3505
|
return this.#client;
|
|
@@ -3437,32 +3523,45 @@ export class AgUiChat extends HTMLElement {
|
|
|
3437
3523
|
* Every finished bubble gets copy and feedback -- both are safe on a message
|
|
3438
3524
|
* of any age. Retry moves to the newest, because it is the only one where
|
|
3439
3525
|
* re-running answers the same question rather than rewriting history.
|
|
3526
|
+
*
|
|
3527
|
+
* `data-message-actions` subtracts from that. The row is built only when
|
|
3528
|
+
* something survives to go in it: an empty row still takes its margin, still
|
|
3529
|
+
* answers to the `message-actions` part, and still reads to a screen reader
|
|
3530
|
+
* as a group of actions with none in it.
|
|
3440
3531
|
*/
|
|
3441
3532
|
#attachActions(bubble: HTMLDivElement, options: { rateable?: boolean } = {}): void {
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3533
|
+
const enabled = this.#messageActions();
|
|
3534
|
+
const copyable = enabled.has(MESSAGE_ACTIONS.COPY);
|
|
3535
|
+
// A failed run is copyable -- error text is what people paste into a bug
|
|
3536
|
+
// report -- but not rateable: a rating is a statement about an *answer*,
|
|
3537
|
+
// and mixing "the connection dropped" into that signal makes the host's
|
|
3538
|
+
// feedback data say less than it did before.
|
|
3539
|
+
const rateable = options.rateable !== false && enabled.has(MESSAGE_ACTIONS.FEEDBACK);
|
|
3540
|
+
if (copyable || rateable) {
|
|
3541
|
+
attachMessageActions(bubble, {
|
|
3542
|
+
strings: this.#strings,
|
|
3543
|
+
// Read at click time, not captured: a bubble rendered from markdown
|
|
3544
|
+
// holds its text in the DOM, and that is what the user sees and means
|
|
3545
|
+
// to copy.
|
|
3546
|
+
...(copyable ? { text: () => bubble.textContent as string } : {}),
|
|
3547
|
+
...(rateable
|
|
3548
|
+
? {
|
|
3549
|
+
onFeedback: (rating: "up" | "down") => {
|
|
3550
|
+
this.dispatchEvent(
|
|
3551
|
+
new CustomEvent<FeedbackDetail>(FEEDBACK_EVENT, {
|
|
3552
|
+
detail: { content: bubble.textContent as string, rating },
|
|
3553
|
+
bubbles: true,
|
|
3554
|
+
composed: true,
|
|
3555
|
+
}),
|
|
3556
|
+
);
|
|
3557
|
+
},
|
|
3558
|
+
}
|
|
3559
|
+
: {}),
|
|
3560
|
+
});
|
|
3561
|
+
}
|
|
3562
|
+
if (enabled.has(MESSAGE_ACTIONS.RETRY)) {
|
|
3563
|
+
this.#moveRetryTo(messageActionBar(bubble, this.#strings));
|
|
3564
|
+
}
|
|
3466
3565
|
}
|
|
3467
3566
|
|
|
3468
3567
|
/** Move the Retry button onto `bar`, taking it off whoever held it. */
|
|
@@ -3822,6 +3921,10 @@ export class AgUiChat extends HTMLElement {
|
|
|
3822
3921
|
this.#dispatchInvalidation(value);
|
|
3823
3922
|
return;
|
|
3824
3923
|
}
|
|
3924
|
+
if (name === SUBAGENT_CUSTOM_NAME) {
|
|
3925
|
+
this.#reportSubAgent(value);
|
|
3926
|
+
return;
|
|
3927
|
+
}
|
|
3825
3928
|
// Straight out to the host page, uninterpreted. This is the imperative
|
|
3826
3929
|
// carrier: whatever it means, it means it to the page, not to the
|
|
3827
3930
|
// transcript -- so it is dispatched and deliberately not rendered,
|
|
@@ -4008,6 +4111,52 @@ export class AgUiChat extends HTMLElement {
|
|
|
4008
4111
|
);
|
|
4009
4112
|
}
|
|
4010
4113
|
|
|
4114
|
+
/**
|
|
4115
|
+
* Draw one step of a delegated sub-agent's progress, on the card that
|
|
4116
|
+
* delegated.
|
|
4117
|
+
*
|
|
4118
|
+
* `delegationId` is the parent's own `delegate_task` tool-call id, so the
|
|
4119
|
+
* attachment point is a card this element already drew on `TOOL_CALL_START`.
|
|
4120
|
+
* That is the whole design: a run that hands work to a sub-agent used to read
|
|
4121
|
+
* as a stall -- the card sat at "running…" for the child's entire duration --
|
|
4122
|
+
* and the fix is to narrate *into* the thing that was already standing there,
|
|
4123
|
+
* rather than to float a second element with the same identity.
|
|
4124
|
+
*
|
|
4125
|
+
* A progress event for a call this client never drew is dropped. It has no
|
|
4126
|
+
* card to attach to, and inventing a floating one is precisely the alternative
|
|
4127
|
+
* that was rejected: parent and child interleave in the transcript with
|
|
4128
|
+
* nothing marking whose is whose, and the persisted transcript -- which never
|
|
4129
|
+
* held the progress at all -- would not match what was on screen.
|
|
4130
|
+
*
|
|
4131
|
+
* Nothing here writes to the conversation store. `CUSTOM` never enters
|
|
4132
|
+
* `agent.messages`, so a reload mid-run leaves the tool card and loses the
|
|
4133
|
+
* nested detail, which is the intended behaviour rather than a gap.
|
|
4134
|
+
*/
|
|
4135
|
+
#reportSubAgent(value: unknown): void {
|
|
4136
|
+
const update = subAgentUpdate(value);
|
|
4137
|
+
if (update === null) {
|
|
4138
|
+
return;
|
|
4139
|
+
}
|
|
4140
|
+
const card = this.#toolCards.get(update.delegationId);
|
|
4141
|
+
if (card === undefined) {
|
|
4142
|
+
return;
|
|
4143
|
+
}
|
|
4144
|
+
let panel = this.#subagentPanels.get(update.delegationId);
|
|
4145
|
+
if (panel === undefined) {
|
|
4146
|
+
// Created on whichever phase arrives first rather than only on `started`.
|
|
4147
|
+
// The contract says exactly one opens a delegation, and a client that
|
|
4148
|
+
// insisted on it would answer a server that dropped one frame by showing
|
|
4149
|
+
// nothing at all for the rest of the run.
|
|
4150
|
+
panel = new SubAgentPanel(this.#strings);
|
|
4151
|
+
this.#subagentPanels.set(update.delegationId, panel);
|
|
4152
|
+
card.subagentSlot.appendChild(panel.element);
|
|
4153
|
+
}
|
|
4154
|
+
panel.report(update);
|
|
4155
|
+
// The card grew, and the transcript is usually pinned to the foot while a
|
|
4156
|
+
// run is in flight.
|
|
4157
|
+
this.#scroller.follow();
|
|
4158
|
+
}
|
|
4159
|
+
|
|
4011
4160
|
/** A muted "⏹ Stopped" line in the transcript (distinct from the ⚠️ error bubble). */
|
|
4012
4161
|
#appendStoppedNote(): void {
|
|
4013
4162
|
const note = document.createElement("div");
|
|
@@ -4404,7 +4553,12 @@ export class AgUiChat extends HTMLElement {
|
|
|
4404
4553
|
: (this.toolSummaries[call.name] ??
|
|
4405
4554
|
this.#toolCatalog[call.name]?.summary ??
|
|
4406
4555
|
prettifyToolName(call.name));
|
|
4407
|
-
const card = new ToolCallCard(call.name, call.args, summary, this.#strings
|
|
4556
|
+
const card = new ToolCallCard(call.name, call.args, summary, this.#strings, {
|
|
4557
|
+
// A thunk over the live property, not the property itself: the card keeps
|
|
4558
|
+
// this for the life of the call, and the result region is filled when the
|
|
4559
|
+
// tool settles -- which can be long after a host set the hook.
|
|
4560
|
+
formatPayload: (payload) => this.formatToolPayload?.(payload) ?? null,
|
|
4561
|
+
});
|
|
4408
4562
|
this.#toolCards.set(call.id, card);
|
|
4409
4563
|
this.#ensureGroup().appendChild(card.element);
|
|
4410
4564
|
this.#updateEmptyState();
|
package/src/core/agui_client.ts
CHANGED
|
@@ -182,6 +182,22 @@ export interface AgUiClientConfig extends AgUiRunInputs {
|
|
|
182
182
|
* passes its localized string.
|
|
183
183
|
*/
|
|
184
184
|
connectionLostMessage?: string;
|
|
185
|
+
/**
|
|
186
|
+
* Upper bound on frontend tool-call to re-run rounds within one
|
|
187
|
+
* {@link AgUiClient.send}. Defaults to {@link MAX_TOOL_ROUNDS}.
|
|
188
|
+
*
|
|
189
|
+
* The default suits a chat whose tools answer questions. A page-driving
|
|
190
|
+
* deployment reaches it legitimately -- filling a form field by field is one
|
|
191
|
+
* round each -- and the symptom is not an error but an answer that stops
|
|
192
|
+
* mid-task, which reads as the model giving up. Raise it where a turn is
|
|
193
|
+
* expected to take many small steps.
|
|
194
|
+
*
|
|
195
|
+
* Read once, when the client is built. The bound is a property of the
|
|
196
|
+
* deployment rather than of a run, so re-reading it per round would only make
|
|
197
|
+
* a mid-run change possible, and a mid-run change to how long the run may
|
|
198
|
+
* last is not a thing a host has any way to reason about.
|
|
199
|
+
*/
|
|
200
|
+
maxToolRounds?: number;
|
|
185
201
|
}
|
|
186
202
|
|
|
187
203
|
/**
|
|
@@ -219,6 +235,7 @@ export class AgUiClient {
|
|
|
219
235
|
*/
|
|
220
236
|
readonly #closedMessageIds = new Set<string>();
|
|
221
237
|
readonly #connectionLostMessage: string;
|
|
238
|
+
readonly #maxToolRounds: number;
|
|
222
239
|
// Set by cancel(); reset at the top of each #run(). Checked by the loop so
|
|
223
240
|
// a cancel between frontend-tool rounds doesn't start another round.
|
|
224
241
|
#cancelled = false;
|
|
@@ -232,6 +249,12 @@ export class AgUiClient {
|
|
|
232
249
|
this.#resolveInterrupts = config.resolveInterrupts ?? null;
|
|
233
250
|
this.#onPersist = config.onPersist ?? (() => {});
|
|
234
251
|
this.#connectionLostMessage = config.connectionLostMessage ?? "Connection lost";
|
|
252
|
+
// Validated here rather than at each caller, so the element's attribute and
|
|
253
|
+
// a direct consumer get the same answer. A bound below one -- or a NaN from
|
|
254
|
+
// an unparseable attribute -- is not a smaller budget but a send that runs
|
|
255
|
+
// the agent zero times, which would look exactly like a broken endpoint.
|
|
256
|
+
const rounds = config.maxToolRounds ?? MAX_TOOL_ROUNDS;
|
|
257
|
+
this.#maxToolRounds = rounds >= 1 ? Math.floor(rounds) : MAX_TOOL_ROUNDS;
|
|
235
258
|
const onStateChanged = config.onStateChanged;
|
|
236
259
|
if (onStateChanged !== undefined) {
|
|
237
260
|
// The agent applies STATE_SNAPSHOT / STATE_DELTA itself; subscribing is
|
|
@@ -270,7 +293,8 @@ export class AgUiClient {
|
|
|
270
293
|
*
|
|
271
294
|
* When the agent calls frontend tools, this executes them and re-runs the
|
|
272
295
|
* agent with the results, looping until the agent stops calling frontend
|
|
273
|
-
* tools (bounded by {@link
|
|
296
|
+
* tools (bounded by {@link AgUiClientConfig.maxToolRounds}, which defaults to
|
|
297
|
+
* {@link MAX_TOOL_ROUNDS}).
|
|
274
298
|
*
|
|
275
299
|
* `attachments` ride on the user message as a non-standard field so the
|
|
276
300
|
* default store round-trips them for history replay; see
|
|
@@ -389,7 +413,7 @@ export class AgUiClient {
|
|
|
389
413
|
// continues an unfinished frontend-tool round after a page load; this stays
|
|
390
414
|
// inside one #run().
|
|
391
415
|
let resume: ResumeEntry[] | undefined;
|
|
392
|
-
for (let round = 0; round <
|
|
416
|
+
for (let round = 0; round < this.#maxToolRounds; round += 1) {
|
|
393
417
|
// A cancel during the previous round's tool execution lands here: the
|
|
394
418
|
// running handler completed, but no further round starts.
|
|
395
419
|
if (this.#cancelled) {
|
package/src/index.ts
CHANGED
|
@@ -11,6 +11,7 @@ export {
|
|
|
11
11
|
INVALIDATE_EVENT,
|
|
12
12
|
LOAD_CAPABILITY_TOOL,
|
|
13
13
|
MAX_TOOL_ROUNDS,
|
|
14
|
+
MESSAGE_ACTIONS,
|
|
14
15
|
MESSAGE_ROLE,
|
|
15
16
|
RUN_FINISHED_EVENT,
|
|
16
17
|
STATE_EVENT,
|
|
@@ -193,8 +194,11 @@ export {
|
|
|
193
194
|
export {
|
|
194
195
|
type SettledStatus,
|
|
195
196
|
ToolCallCard,
|
|
197
|
+
type ToolCallCardOptions,
|
|
196
198
|
type ToolCallStatus,
|
|
197
199
|
type ToolDisplayMode,
|
|
200
|
+
type ToolPayload,
|
|
201
|
+
type ToolPayloadFormatter,
|
|
198
202
|
} from "./ui/tool_call_card.js";
|
|
199
203
|
export { DEFAULT_UI_STRINGS, mergeUiStrings, type UiStrings } from "./ui/ui_strings.js";
|
|
200
204
|
export { VERSION } from "./version.js";
|