@artooi/ag-ui-web-component 0.7.0 → 0.8.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 +30 -1
- package/README.md +46 -9
- package/dist/ag-ui-web-component.bundle.js +134 -11
- package/dist/ag-ui-web-component.bundle.js.map +3 -3
- package/dist/constants.d.ts +5 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/core/ag_ui_chat.d.ts +4 -0
- package/dist/core/ag_ui_chat.d.ts.map +1 -1
- package/dist/index.js +176 -10
- package/dist/index.js.map +2 -2
- 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 +13 -6
- package/dist/ui/tool_call_card.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/constants.ts +5 -0
- package/src/core/ag_ui_chat.ts +54 -5
- package/src/ui/styles.ts +123 -0
- package/src/ui/tool_call_card.ts +23 -8
- package/src/version.ts +1 -1
package/dist/constants.d.ts
CHANGED
|
@@ -77,12 +77,17 @@ export declare const DEFAULT_ATTACHMENT_MAX_BYTES: number;
|
|
|
77
77
|
* How much detail a tool-call card shows. Set via the `data-tool-display`
|
|
78
78
|
* attribute on `<ag-ui-chat>`; defaults to `full` (back-compatible).
|
|
79
79
|
*
|
|
80
|
+
* - `inline` — the lightest mode: a single status row (icon + summary) with no
|
|
81
|
+
* surrounding card chrome, the result tucked behind its own toggle. Reads as
|
|
82
|
+
* one line of the answer rather than a boxed card — pairs with the answer
|
|
83
|
+
* well (page mode).
|
|
80
84
|
* - `minimal` — just the tool name + status pill. No args, no result body.
|
|
81
85
|
* - `compact` — name + status, with args *and* result tucked behind a single
|
|
82
86
|
* collapsed "Details" toggle. The light default for dense UIs.
|
|
83
87
|
* - `full` — args shown inline, result behind its own toggle (the original).
|
|
84
88
|
*/
|
|
85
89
|
export declare const TOOL_DISPLAY: {
|
|
90
|
+
readonly INLINE: "inline";
|
|
86
91
|
readonly MINIMAL: "minimal";
|
|
87
92
|
readonly COMPACT: "compact";
|
|
88
93
|
readonly FULL: "full";
|
package/dist/constants.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAGA,wEAAwE;AACxE,eAAO,MAAM,WAAW,eAAe,CAAC;AAExC;;;;GAIG;AACH,eAAO,MAAM,YAAY,iBAAiB,CAAC;AAE3C;;;;;GAKG;AACH,eAAO,MAAM,YAAY,iBAAiB,CAAC;AAE3C,qCAAqC;AACrC,eAAO,MAAM,YAAY;;;CAGf,CAAC;AAEX;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,kBAAkB,CAAC;AAEjD;;;;;GAKG;AACH,eAAO,MAAM,aAAa,cAAc,CAAC;AAEzC;;;;GAIG;AACH,eAAO,MAAM,aAAa,cAAc,CAAC;AAEzC;;;;;GAKG;AACH,eAAO,MAAM,eAAe,gBAAgB,CAAC;AAE7C,yEAAyE;AACzE,eAAO,MAAM,eAAe,KAAK,CAAC;AAElC;;;GAGG;AACH,eAAO,MAAM,gBAAgB;;;;;CAKnB,CAAC;AAEX;;;;GAIG;AACH,eAAO,MAAM,iBAAiB;;;;CAIpB,CAAC;AAEX;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,QAAmB,CAAC;AAE7D
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAGA,wEAAwE;AACxE,eAAO,MAAM,WAAW,eAAe,CAAC;AAExC;;;;GAIG;AACH,eAAO,MAAM,YAAY,iBAAiB,CAAC;AAE3C;;;;;GAKG;AACH,eAAO,MAAM,YAAY,iBAAiB,CAAC;AAE3C,qCAAqC;AACrC,eAAO,MAAM,YAAY;;;CAGf,CAAC;AAEX;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,kBAAkB,CAAC;AAEjD;;;;;GAKG;AACH,eAAO,MAAM,aAAa,cAAc,CAAC;AAEzC;;;;GAIG;AACH,eAAO,MAAM,aAAa,cAAc,CAAC;AAEzC;;;;;GAKG;AACH,eAAO,MAAM,eAAe,gBAAgB,CAAC;AAE7C,yEAAyE;AACzE,eAAO,MAAM,eAAe,KAAK,CAAC;AAElC;;;GAGG;AACH,eAAO,MAAM,gBAAgB;;;;;CAKnB,CAAC;AAEX;;;;GAIG;AACH,eAAO,MAAM,iBAAiB;;;;CAIpB,CAAC;AAEX;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,QAAmB,CAAC;AAE7D;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,YAAY;;;;;CAKf,CAAC"}
|
|
@@ -184,6 +184,10 @@ export declare class AgUiChat extends HTMLElement {
|
|
|
184
184
|
* Assistant content is rendered as sanitised markdown/HTML; user content
|
|
185
185
|
* stays literal text (no need to parse what the user typed, and it avoids
|
|
186
186
|
* rendering user-authored markup).
|
|
187
|
+
*
|
|
188
|
+
* Assistant bubbles land in the current answer group (WELL-1), opening one if
|
|
189
|
+
* needed; a user bubble closes the prior group and sits directly in the list
|
|
190
|
+
* (the well wraps the *assistant* turn, the user message precedes it).
|
|
187
191
|
*/
|
|
188
192
|
appendMessage(role: MessageRole, content: string): HTMLDivElement;
|
|
189
193
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ag_ui_chat.d.ts","sourceRoot":"","sources":["../../src/core/ag_ui_chat.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"ag_ui_chat.d.ts","sourceRoot":"","sources":["../../src/core/ag_ui_chat.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -24,6 +24,7 @@ var ATTACHMENT_STATUS = {
|
|
|
24
24
|
};
|
|
25
25
|
var DEFAULT_ATTACHMENT_MAX_BYTES = 10 * 1024 * 1024;
|
|
26
26
|
var TOOL_DISPLAY = {
|
|
27
|
+
INLINE: "inline",
|
|
27
28
|
MINIMAL: "minimal",
|
|
28
29
|
COMPACT: "compact",
|
|
29
30
|
FULL: "full"
|
|
@@ -3488,6 +3489,17 @@ var STYLES = `
|
|
|
3488
3489
|
--ag-ui-danger: #b91c1c;
|
|
3489
3490
|
--ag-ui-muted: #6b7280;
|
|
3490
3491
|
|
|
3492
|
+
/* Tool-call status icon glyphs (override to re-theme) + spinner speed.
|
|
3493
|
+
The pending state is the animated ring; the settled states use these. */
|
|
3494
|
+
--ag-ui-tool-icon-done: "\u2713";
|
|
3495
|
+
--ag-ui-tool-icon-error: "\u2715";
|
|
3496
|
+
--ag-ui-tool-icon-declined: "\u2298";
|
|
3497
|
+
--ag-ui-tool-spin-duration: 0.7s;
|
|
3498
|
+
|
|
3499
|
+
/* Answer well (opt-in via data-answer-well) \u2014 boxes a whole assistant turn. */
|
|
3500
|
+
--ag-ui-well-bg: transparent;
|
|
3501
|
+
--ag-ui-well-border: var(--ag-ui-border);
|
|
3502
|
+
|
|
3491
3503
|
/* Surface \u2014 set --ag-ui-shadow: none for a flush, embedded panel. */
|
|
3492
3504
|
--ag-ui-shadow: 0 12px 32px rgba(20, 20, 50, 0.18);
|
|
3493
3505
|
--ag-ui-font: inherit;
|
|
@@ -3510,6 +3522,8 @@ var STYLES = `
|
|
|
3510
3522
|
--ag-ui-inset: auto 24px 24px auto;
|
|
3511
3523
|
--ag-ui-max-width: calc(100vw - 48px);
|
|
3512
3524
|
--ag-ui-max-height: calc(100vh - 48px);
|
|
3525
|
+
/* Reading-column width for placement="page" (full-bleed, centred content). */
|
|
3526
|
+
--ag-ui-content-max-width: 820px;
|
|
3513
3527
|
|
|
3514
3528
|
position: var(--ag-ui-position);
|
|
3515
3529
|
inset: var(--ag-ui-inset);
|
|
@@ -3597,6 +3611,34 @@ var STYLES = `
|
|
|
3597
3611
|
--ag-ui-radius: 0;
|
|
3598
3612
|
}
|
|
3599
3613
|
|
|
3614
|
+
/* Page (PAGE-1): full-bleed background with a centred reading column. Unlike
|
|
3615
|
+
"full" (edge-to-edge, left-aligned messages) the content sits in a column
|
|
3616
|
+
capped at --ag-ui-content-max-width. The column is produced by symmetric auto
|
|
3617
|
+
padding on the scroll area + composer (no per-row wrapper), so user pills
|
|
3618
|
+
still right-align and the assistant well spans the column. */
|
|
3619
|
+
:host([placement="page"]) {
|
|
3620
|
+
--ag-ui-inset: 0;
|
|
3621
|
+
--ag-ui-width: 100vw;
|
|
3622
|
+
--ag-ui-height: 100vh;
|
|
3623
|
+
--ag-ui-max-width: 100vw;
|
|
3624
|
+
--ag-ui-max-height: 100vh;
|
|
3625
|
+
--ag-ui-radius: 0;
|
|
3626
|
+
}
|
|
3627
|
+
|
|
3628
|
+
:host([placement="page"]) .messages {
|
|
3629
|
+
padding-inline: max(var(--ag-ui-pad), calc((100% - var(--ag-ui-content-max-width)) / 2));
|
|
3630
|
+
}
|
|
3631
|
+
|
|
3632
|
+
:host([placement="page"]) .input-row {
|
|
3633
|
+
padding-inline: max(12px, calc((100% - var(--ag-ui-content-max-width)) / 2));
|
|
3634
|
+
}
|
|
3635
|
+
|
|
3636
|
+
/* In the reading column the assistant well uses the full width; the user
|
|
3637
|
+
message stays a right-aligned pill (its default align-self + max-width). */
|
|
3638
|
+
:host([placement="page"]) .message--assistant {
|
|
3639
|
+
max-width: 100%;
|
|
3640
|
+
}
|
|
3641
|
+
|
|
3600
3642
|
/* Sidebar (CUST-3): a full-height docked panel that slides open/closed and
|
|
3601
3643
|
collapses to a slim icon rail (not the floating launcher). Docked right by
|
|
3602
3644
|
default; data-side="left" docks it left. Overlay by default \u2014 set
|
|
@@ -3793,6 +3835,27 @@ var STYLES = `
|
|
|
3793
3835
|
display: none;
|
|
3794
3836
|
}
|
|
3795
3837
|
|
|
3838
|
+
/* \u2500\u2500 Answer group / well (WELL-1) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
3839
|
+
One .answer per assistant turn wraps the streamed text, its tool cards,
|
|
3840
|
+
and the pending indicator so a whole answer reads (and can be boxed) as one
|
|
3841
|
+
unit. A flex column on the message-list gap, stretched to the list width so
|
|
3842
|
+
its children keep their own left/right alignment. data-answer-well opts into
|
|
3843
|
+
the bordered "well"; without it the layout is today's flat stack. */
|
|
3844
|
+
.answer {
|
|
3845
|
+
display: flex;
|
|
3846
|
+
flex-direction: column;
|
|
3847
|
+
gap: var(--ag-ui-space);
|
|
3848
|
+
align-self: stretch;
|
|
3849
|
+
min-width: 0;
|
|
3850
|
+
}
|
|
3851
|
+
|
|
3852
|
+
:host([data-answer-well]) .answer {
|
|
3853
|
+
padding: var(--ag-ui-pad);
|
|
3854
|
+
background: var(--ag-ui-well-bg);
|
|
3855
|
+
border: 1px solid var(--ag-ui-well-border);
|
|
3856
|
+
border-radius: var(--ag-ui-radius);
|
|
3857
|
+
}
|
|
3858
|
+
|
|
3796
3859
|
.message {
|
|
3797
3860
|
max-width: 80%;
|
|
3798
3861
|
padding: var(--ag-ui-msg-pad);
|
|
@@ -3965,10 +4028,71 @@ var STYLES = `
|
|
|
3965
4028
|
}
|
|
3966
4029
|
|
|
3967
4030
|
.tool-call-name {
|
|
4031
|
+
flex: 1;
|
|
4032
|
+
min-width: 0;
|
|
3968
4033
|
font-weight: 600;
|
|
3969
4034
|
word-break: break-word;
|
|
3970
4035
|
}
|
|
3971
4036
|
|
|
4037
|
+
/* Leading status icon (CARD-1). Empty in the DOM \u2014 the glyph/spinner is drawn
|
|
4038
|
+
here from the card's data-status, so it stays themeable. */
|
|
4039
|
+
.tool-call-icon {
|
|
4040
|
+
flex: none;
|
|
4041
|
+
box-sizing: border-box;
|
|
4042
|
+
display: inline-flex;
|
|
4043
|
+
align-items: center;
|
|
4044
|
+
justify-content: center;
|
|
4045
|
+
width: 14px;
|
|
4046
|
+
height: 14px;
|
|
4047
|
+
font-size: 12px;
|
|
4048
|
+
line-height: 1;
|
|
4049
|
+
}
|
|
4050
|
+
|
|
4051
|
+
/* Pending: a real spinning ring. Speed is tunable; reduced motion stops it. */
|
|
4052
|
+
.tool-call[data-status="pending"] .tool-call-icon {
|
|
4053
|
+
border: 2px solid var(--ag-ui-muted);
|
|
4054
|
+
border-top-color: transparent;
|
|
4055
|
+
border-radius: 50%;
|
|
4056
|
+
animation: ag-ui-tool-spin var(--ag-ui-tool-spin-duration) linear infinite;
|
|
4057
|
+
}
|
|
4058
|
+
|
|
4059
|
+
@keyframes ag-ui-tool-spin {
|
|
4060
|
+
to { transform: rotate(360deg); }
|
|
4061
|
+
}
|
|
4062
|
+
|
|
4063
|
+
/* Settled: a themeable glyph coloured by outcome. */
|
|
4064
|
+
.tool-call[data-status="done"] .tool-call-icon::before {
|
|
4065
|
+
content: var(--ag-ui-tool-icon-done);
|
|
4066
|
+
color: var(--ag-ui-success);
|
|
4067
|
+
}
|
|
4068
|
+
|
|
4069
|
+
.tool-call[data-status="error"] .tool-call-icon::before {
|
|
4070
|
+
content: var(--ag-ui-tool-icon-error);
|
|
4071
|
+
color: var(--ag-ui-danger);
|
|
4072
|
+
}
|
|
4073
|
+
|
|
4074
|
+
.tool-call[data-status="declined"] .tool-call-icon::before {
|
|
4075
|
+
content: var(--ag-ui-tool-icon-declined);
|
|
4076
|
+
color: var(--ag-ui-muted);
|
|
4077
|
+
}
|
|
4078
|
+
|
|
4079
|
+
@media (prefers-reduced-motion: reduce) {
|
|
4080
|
+
.tool-call[data-status="pending"] .tool-call-icon {
|
|
4081
|
+
animation: none;
|
|
4082
|
+
}
|
|
4083
|
+
}
|
|
4084
|
+
|
|
4085
|
+
/* Inline display mode (CARD-1): the lightest card \u2014 drop the box chrome so the
|
|
4086
|
+
status row reads as one line of the answer; the result toggle still expands
|
|
4087
|
+
below it. */
|
|
4088
|
+
.tool-call[data-display="inline"] {
|
|
4089
|
+
max-width: 100%;
|
|
4090
|
+
background: transparent;
|
|
4091
|
+
border: none;
|
|
4092
|
+
padding: 2px 0;
|
|
4093
|
+
gap: 2px;
|
|
4094
|
+
}
|
|
4095
|
+
|
|
3972
4096
|
.tool-call-status {
|
|
3973
4097
|
flex: none;
|
|
3974
4098
|
padding: 1px 8px;
|
|
@@ -4740,15 +4864,19 @@ var ToolCallCard = class {
|
|
|
4740
4864
|
const head = document.createElement("div");
|
|
4741
4865
|
head.className = "tool-call-head";
|
|
4742
4866
|
head.setAttribute("part", "tool-card-head");
|
|
4867
|
+
const icon = document.createElement("span");
|
|
4868
|
+
icon.className = "tool-call-icon";
|
|
4869
|
+
icon.setAttribute("part", "tool-card-icon");
|
|
4870
|
+
icon.setAttribute("aria-hidden", "true");
|
|
4743
4871
|
const label = document.createElement("span");
|
|
4744
4872
|
label.className = "tool-call-name";
|
|
4745
4873
|
label.setAttribute("part", "tool-card-name");
|
|
4746
|
-
label.textContent =
|
|
4874
|
+
label.textContent = summary ?? name;
|
|
4747
4875
|
this.#status = document.createElement("span");
|
|
4748
4876
|
this.#status.className = "tool-call-status";
|
|
4749
4877
|
this.#status.setAttribute("part", "tool-card-status");
|
|
4750
4878
|
this.#status.textContent = statusLabels(strings)[TOOL_CALL_STATUS.PENDING];
|
|
4751
|
-
head.append(label, this.#status);
|
|
4879
|
+
head.append(icon, label, this.#status);
|
|
4752
4880
|
this.element.append(head);
|
|
4753
4881
|
if (mode === TOOL_DISPLAY.FULL) {
|
|
4754
4882
|
const argsEl = document.createElement("pre");
|
|
@@ -4764,8 +4892,8 @@ var ToolCallCard = class {
|
|
|
4764
4892
|
}
|
|
4765
4893
|
/**
|
|
4766
4894
|
* Flip the status pill to ``status`` and, unless in `minimal` mode, append a
|
|
4767
|
-
* collapsed body behind a click-to-expand toggle: the result alone (`full`
|
|
4768
|
-
* or the args + result together (`compact`).
|
|
4895
|
+
* collapsed body behind a click-to-expand toggle: the result alone (`full` /
|
|
4896
|
+
* `inline`), or the args + result together (`compact`).
|
|
4769
4897
|
*/
|
|
4770
4898
|
settle(status, text2) {
|
|
4771
4899
|
this.#settled = true;
|
|
@@ -5481,6 +5609,13 @@ var AgUiChat = class extends HTMLElement {
|
|
|
5481
5609
|
// it; ≤1 ⇒ it arrived at once and the word reveal is appropriate.
|
|
5482
5610
|
#streamDeltas = 0;
|
|
5483
5611
|
#pending = null;
|
|
5612
|
+
// The current assistant turn's grouping container (WELL-1). One `.answer`
|
|
5613
|
+
// wraps everything a single answer produces — streamed text, tool cards, the
|
|
5614
|
+
// pending indicator — so it can be boxed as one "well" by CSS. Opened on the
|
|
5615
|
+
// turn's first run start, closed at settle, so it spans the whole multi-round
|
|
5616
|
+
// frontend-tool loop (which is several AG-UI runs), not one run. `null`
|
|
5617
|
+
// between turns; user bubbles never enter it.
|
|
5618
|
+
#currentGroup = null;
|
|
5484
5619
|
#threadId = "";
|
|
5485
5620
|
#initialMessages = [];
|
|
5486
5621
|
// Skill catalog by source; merged backend → embed → client (later wins).
|
|
@@ -5614,7 +5749,7 @@ var AgUiChat = class extends HTMLElement {
|
|
|
5614
5749
|
*/
|
|
5615
5750
|
get toolDisplay() {
|
|
5616
5751
|
const attr = this.getAttribute("data-tool-display");
|
|
5617
|
-
if (attr === TOOL_DISPLAY.MINIMAL || attr === TOOL_DISPLAY.COMPACT) {
|
|
5752
|
+
if (attr === TOOL_DISPLAY.INLINE || attr === TOOL_DISPLAY.MINIMAL || attr === TOOL_DISPLAY.COMPACT) {
|
|
5618
5753
|
return attr;
|
|
5619
5754
|
}
|
|
5620
5755
|
return TOOL_DISPLAY.FULL;
|
|
@@ -5881,6 +6016,7 @@ Use the read_attachment tool with an id to read a file's contents.`
|
|
|
5881
6016
|
#resetState() {
|
|
5882
6017
|
this.#client = null;
|
|
5883
6018
|
this.#streamingBubble = null;
|
|
6019
|
+
this.#currentGroup = null;
|
|
5884
6020
|
this.#hidePending();
|
|
5885
6021
|
this.#toolCards.clear();
|
|
5886
6022
|
this.#serverSettled.clear();
|
|
@@ -6012,6 +6148,10 @@ Use the read_attachment tool with an id to read a file's contents.`
|
|
|
6012
6148
|
* Assistant content is rendered as sanitised markdown/HTML; user content
|
|
6013
6149
|
* stays literal text (no need to parse what the user typed, and it avoids
|
|
6014
6150
|
* rendering user-authored markup).
|
|
6151
|
+
*
|
|
6152
|
+
* Assistant bubbles land in the current answer group (WELL-1), opening one if
|
|
6153
|
+
* needed; a user bubble closes the prior group and sits directly in the list
|
|
6154
|
+
* (the well wraps the *assistant* turn, the user message precedes it).
|
|
6015
6155
|
*/
|
|
6016
6156
|
appendMessage(role, content) {
|
|
6017
6157
|
const bubble = document.createElement("div");
|
|
@@ -6019,14 +6159,34 @@ Use the read_attachment tool with an id to read a file's contents.`
|
|
|
6019
6159
|
bubble.setAttribute("part", `message message-${role}`);
|
|
6020
6160
|
if (role === MESSAGE_ROLE.ASSISTANT) {
|
|
6021
6161
|
bubble.innerHTML = renderMarkdown(content, { allowImages: this.allowImages });
|
|
6162
|
+
this.#ensureGroup().appendChild(bubble);
|
|
6022
6163
|
} else {
|
|
6164
|
+
this.#currentGroup = null;
|
|
6023
6165
|
bubble.textContent = content;
|
|
6166
|
+
this.#messages.appendChild(bubble);
|
|
6024
6167
|
}
|
|
6025
|
-
this.#messages.appendChild(bubble);
|
|
6026
6168
|
this.#updateEmptyState();
|
|
6027
6169
|
this.#messages.scrollTop = this.#messages.scrollHeight;
|
|
6028
6170
|
return bubble;
|
|
6029
6171
|
}
|
|
6172
|
+
/**
|
|
6173
|
+
* The open answer group, creating and appending it on first use. Everything a
|
|
6174
|
+
* single assistant turn renders (text, tool cards, the pending indicator)
|
|
6175
|
+
* goes inside it, so the opt-in `data-answer-well` styling can box the whole
|
|
6176
|
+
* turn. Idempotent across the turn's runs — it persists until {@link #handlers}'
|
|
6177
|
+
* `onSettled` nulls it.
|
|
6178
|
+
*/
|
|
6179
|
+
#ensureGroup() {
|
|
6180
|
+
if (this.#currentGroup === null) {
|
|
6181
|
+
const group = document.createElement("div");
|
|
6182
|
+
group.className = "answer";
|
|
6183
|
+
group.setAttribute("part", "answer");
|
|
6184
|
+
this.#currentGroup = group;
|
|
6185
|
+
this.#messages.appendChild(group);
|
|
6186
|
+
this.#updateEmptyState();
|
|
6187
|
+
}
|
|
6188
|
+
return this.#currentGroup;
|
|
6189
|
+
}
|
|
6030
6190
|
#render() {
|
|
6031
6191
|
const style = document.createElement("style");
|
|
6032
6192
|
style.textContent = STYLES;
|
|
@@ -6332,6 +6492,7 @@ Use the read_attachment tool with an id to read a file's contents.`
|
|
|
6332
6492
|
return {
|
|
6333
6493
|
onRunStart: () => {
|
|
6334
6494
|
this.#setRunning(true);
|
|
6495
|
+
this.#ensureGroup();
|
|
6335
6496
|
this.#showPending();
|
|
6336
6497
|
},
|
|
6337
6498
|
onTextDelta: (buffer) => {
|
|
@@ -6382,6 +6543,11 @@ Use the read_attachment tool with an id to read a file's contents.`
|
|
|
6382
6543
|
card.settle(TOOL_CALL_STATUS.DONE, this.#strings.noResult);
|
|
6383
6544
|
}
|
|
6384
6545
|
}
|
|
6546
|
+
if (this.#currentGroup !== null && this.#currentGroup.childElementCount === 0) {
|
|
6547
|
+
this.#currentGroup.remove();
|
|
6548
|
+
this.#updateEmptyState();
|
|
6549
|
+
}
|
|
6550
|
+
this.#currentGroup = null;
|
|
6385
6551
|
}
|
|
6386
6552
|
};
|
|
6387
6553
|
}
|
|
@@ -6392,7 +6558,7 @@ Use the read_attachment tool with an id to read a file's contents.`
|
|
|
6392
6558
|
note.setAttribute("part", "stopped");
|
|
6393
6559
|
note.setAttribute("role", "status");
|
|
6394
6560
|
note.textContent = this.#strings.stopped;
|
|
6395
|
-
this.#
|
|
6561
|
+
this.#ensureGroup().appendChild(note);
|
|
6396
6562
|
this.#updateEmptyState();
|
|
6397
6563
|
this.#messages.scrollTop = this.#messages.scrollHeight;
|
|
6398
6564
|
}
|
|
@@ -6416,7 +6582,7 @@ Use the read_attachment tool with an id to read a file's contents.`
|
|
|
6416
6582
|
pending.appendChild(dot);
|
|
6417
6583
|
}
|
|
6418
6584
|
this.#pending = pending;
|
|
6419
|
-
this.#
|
|
6585
|
+
this.#ensureGroup().appendChild(pending);
|
|
6420
6586
|
this.#updateEmptyState();
|
|
6421
6587
|
this.#messages.scrollTop = this.#messages.scrollHeight;
|
|
6422
6588
|
}
|
|
@@ -6449,7 +6615,7 @@ Use the read_attachment tool with an id to read a file's contents.`
|
|
|
6449
6615
|
const summary = typeof labelled === "string" ? labelled : this.toolSummaries[call.name] ?? this.#toolCatalog[call.name] ?? prettifyToolName(call.name);
|
|
6450
6616
|
const card = new ToolCallCard(call.name, call.args, this.toolDisplay, summary, this.#strings);
|
|
6451
6617
|
this.#toolCards.set(call.id, card);
|
|
6452
|
-
this.#
|
|
6618
|
+
this.#ensureGroup().appendChild(card.element);
|
|
6453
6619
|
this.#updateEmptyState();
|
|
6454
6620
|
this.#messages.scrollTop = this.#messages.scrollHeight;
|
|
6455
6621
|
return card;
|
|
@@ -6496,7 +6662,7 @@ function setControlValue(el, value) {
|
|
|
6496
6662
|
}
|
|
6497
6663
|
|
|
6498
6664
|
// src/version.ts
|
|
6499
|
-
var VERSION = "0.
|
|
6665
|
+
var VERSION = "0.8.0";
|
|
6500
6666
|
export {
|
|
6501
6667
|
AgUiChat,
|
|
6502
6668
|
AgUiClient,
|