@artooi/ag-ui-web-component 0.45.0 → 0.47.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 +146 -1
- package/README.md +191 -25
- package/dist/ag-ui-web-component.bundle.js +399 -157
- package/dist/ag-ui-web-component.bundle.js.map +4 -4
- package/dist/constants.d.ts +14 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/core/ag_ui_chat.d.ts +47 -4
- package/dist/core/ag_ui_chat.d.ts.map +1 -1
- package/dist/core/chat_registry.d.ts +23 -0
- package/dist/core/chat_registry.d.ts.map +1 -0
- package/dist/core/events/run_finished_detail.d.ts +6 -0
- package/dist/core/events/run_finished_detail.d.ts.map +1 -1
- package/dist/core/events/thread_detail.d.ts +27 -0
- package/dist/core/events/thread_detail.d.ts.map +1 -0
- package/dist/core/run_handlers.d.ts +6 -1
- package/dist/core/run_handlers.d.ts.map +1 -1
- package/dist/dom/animations.d.ts +21 -6
- package/dist/dom/animations.d.ts.map +1 -1
- package/dist/dom/highlight_overlay.d.ts +7 -1
- package/dist/dom/highlight_overlay.d.ts.map +1 -1
- package/dist/dom/ring_color.d.ts +14 -0
- package/dist/dom/ring_color.d.ts.map +1 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +857 -86
- package/dist/index.js.map +4 -4
- package/dist/tools/tool_catalog.d.ts +5 -0
- package/dist/tools/tool_catalog.d.ts.map +1 -1
- package/dist/tools/tool_dispatch.d.ts.map +1 -1
- package/dist/ui/history/conversation_history.d.ts +10 -1
- package/dist/ui/history/conversation_history.d.ts.map +1 -1
- package/dist/ui/interrupts/confirmation_styles.d.ts.map +1 -1
- package/dist/ui/placement/panel_placement.d.ts +6 -0
- package/dist/ui/placement/panel_placement.d.ts.map +1 -1
- package/dist/ui/placement/small_viewport_styles.d.ts.map +1 -1
- package/dist/ui/placement/surface_for.d.ts +12 -1
- package/dist/ui/placement/surface_for.d.ts.map +1 -1
- package/dist/ui/progress/thoughts_styles.d.ts.map +1 -1
- package/dist/ui/progress/tool_call_card.d.ts +8 -0
- package/dist/ui/progress/tool_call_card.d.ts.map +1 -1
- package/dist/ui/progress/tool_group_styles.d.ts +2 -0
- package/dist/ui/progress/tool_group_styles.d.ts.map +1 -0
- package/dist/ui/progress/tool_step_group.d.ts +47 -0
- package/dist/ui/progress/tool_step_group.d.ts.map +1 -0
- package/dist/ui/progress/tool_step_styles.d.ts.map +1 -1
- package/dist/ui/shell/token_styles.d.ts.map +1 -1
- package/dist/ui/styles.d.ts.map +1 -1
- package/dist/ui/themes/ledger_styles.d.ts.map +1 -1
- package/dist/ui/themes/soft_styles.d.ts.map +1 -1
- package/dist/ui/transcript/groups_tool_steps.d.ts +13 -0
- package/dist/ui/transcript/groups_tool_steps.d.ts.map +1 -0
- package/dist/ui/transcript/message_styles.d.ts.map +1 -1
- package/dist/ui/transcript/transcript.d.ts +16 -1
- package/dist/ui/transcript/transcript.d.ts.map +1 -1
- package/dist/ui/ui_strings.d.ts +18 -0
- package/dist/ui/ui_strings.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/constants.ts +15 -1
- package/src/core/ag_ui_chat.ts +122 -11
- package/src/core/chat_registry.ts +53 -0
- package/src/core/events/run_finished_detail.ts +6 -0
- package/src/core/events/thread_detail.ts +26 -0
- package/src/core/run_handlers.ts +9 -4
- package/src/dom/animations.ts +30 -31
- package/src/dom/highlight_overlay.ts +9 -5
- package/src/dom/ring_color.ts +85 -0
- package/src/index.ts +3 -0
- package/src/tools/tool_catalog.ts +23 -10
- package/src/tools/tool_dispatch.ts +26 -11
- package/src/ui/history/conversation_history.ts +28 -4
- package/src/ui/interrupts/confirmation_styles.ts +0 -2
- package/src/ui/placement/embedded_styles.ts +2 -2
- package/src/ui/placement/panel_placement.ts +34 -9
- package/src/ui/placement/preset_styles.ts +1 -1
- package/src/ui/placement/sidebar_styles.ts +1 -1
- package/src/ui/placement/small_viewport_styles.ts +5 -0
- package/src/ui/placement/surface_for.ts +12 -1
- package/src/ui/progress/thoughts_styles.ts +0 -2
- package/src/ui/progress/tool_call_card.ts +29 -8
- package/src/ui/progress/tool_group_styles.ts +232 -0
- package/src/ui/progress/tool_step_group.ts +272 -0
- package/src/ui/progress/tool_step_styles.ts +0 -2
- package/src/ui/shell/token_styles.ts +4 -2
- package/src/ui/styles.ts +5 -0
- package/src/ui/themes/ledger_styles.ts +15 -0
- package/src/ui/themes/soft_styles.ts +20 -0
- package/src/ui/transcript/groups_tool_steps.ts +16 -0
- package/src/ui/transcript/message_styles.ts +0 -2
- package/src/ui/transcript/transcript.ts +109 -3
- package/src/ui/ui_strings.ts +31 -0
- package/src/version.ts +1 -1
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@ var UNREAD_EVENT = "ag-ui-unread";
|
|
|
6
6
|
var STATE_EVENT = "ag-ui-state";
|
|
7
7
|
var ATTACHMENT_EVENT = "ag-ui-attachments";
|
|
8
8
|
var RUN_FINISHED_EVENT = "ag-ui-run-finished";
|
|
9
|
+
var THREAD_EVENT = "ag-ui-thread";
|
|
9
10
|
var CUSTOM_AGENT_EVENT = "ag-ui-custom";
|
|
10
11
|
var INVALIDATE_EVENT = "ag-ui-invalidate";
|
|
11
12
|
var FEEDBACK_EVENT = "ag-ui-feedback";
|
|
@@ -55,6 +56,7 @@ var ATTACHMENT_STATUS = {
|
|
|
55
56
|
};
|
|
56
57
|
var DEFAULT_ATTACHMENT_MAX_BYTES = 10 * 1024 * 1024;
|
|
57
58
|
var TOOL_DISPLAY = {
|
|
59
|
+
GROUPED: "grouped",
|
|
58
60
|
INLINE: "inline",
|
|
59
61
|
MINIMAL: "minimal",
|
|
60
62
|
COMPACT: "compact",
|
|
@@ -353,8 +355,79 @@ var ClientToolRegistry = class {
|
|
|
353
355
|
}
|
|
354
356
|
};
|
|
355
357
|
|
|
358
|
+
// src/core/chat_registry.ts
|
|
359
|
+
var CONNECTED_CHATS = /* @__PURE__ */ new Set();
|
|
360
|
+
var ChatRegistration = class {
|
|
361
|
+
#chat;
|
|
362
|
+
constructor(chat) {
|
|
363
|
+
this.#chat = chat;
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Join, as the most recently connected chat. An element moved in the DOM
|
|
367
|
+
* left on disconnect before it reconnected, so it rejoins at the end and no
|
|
368
|
+
* entry needs removing first.
|
|
369
|
+
*/
|
|
370
|
+
join() {
|
|
371
|
+
CONNECTED_CHATS.add(this.#chat);
|
|
372
|
+
}
|
|
373
|
+
/** Leave. The previous chat, if one is still connected, becomes the latest. */
|
|
374
|
+
leave() {
|
|
375
|
+
CONNECTED_CHATS.delete(this.#chat);
|
|
376
|
+
}
|
|
377
|
+
/** The most recently connected chat still in the document, or `null`. */
|
|
378
|
+
static latest() {
|
|
379
|
+
let latest = null;
|
|
380
|
+
for (const chat of CONNECTED_CHATS) {
|
|
381
|
+
latest = chat;
|
|
382
|
+
}
|
|
383
|
+
return latest;
|
|
384
|
+
}
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
// src/dom/ring_color.ts
|
|
388
|
+
var RING_TOKEN = "--ag-ui-highlight-ring-color";
|
|
389
|
+
var ACCENT_TOKEN = "--ag-ui-accent";
|
|
390
|
+
var CHAT_ACCENT = "--_accent";
|
|
391
|
+
var PACKAGE_ACCENT = "#4f46e5";
|
|
392
|
+
function ringColor(target, chat) {
|
|
393
|
+
const onTarget = readToken(target, RING_TOKEN);
|
|
394
|
+
if (onTarget !== "") {
|
|
395
|
+
return onTarget;
|
|
396
|
+
}
|
|
397
|
+
const owner = chat ?? ChatRegistration.latest();
|
|
398
|
+
const onChat = owner === null ? "" : resolveOn(owner, RING_TOKEN);
|
|
399
|
+
if (onChat !== "") {
|
|
400
|
+
return onChat;
|
|
401
|
+
}
|
|
402
|
+
const accent = readToken(target, ACCENT_TOKEN);
|
|
403
|
+
if (accent !== "") {
|
|
404
|
+
return accent;
|
|
405
|
+
}
|
|
406
|
+
const chatAccent = owner === null ? "" : resolveOn(owner, CHAT_ACCENT);
|
|
407
|
+
return chatAccent === "" ? PACKAGE_ACCENT : chatAccent;
|
|
408
|
+
}
|
|
409
|
+
function readToken(el2, name) {
|
|
410
|
+
return window.getComputedStyle(el2).getPropertyValue(name).trim();
|
|
411
|
+
}
|
|
412
|
+
function resolveOn(chat, name) {
|
|
413
|
+
const value = readToken(chat, name);
|
|
414
|
+
const root = chat.shadowRoot;
|
|
415
|
+
if (value === "" || root === null) {
|
|
416
|
+
return value;
|
|
417
|
+
}
|
|
418
|
+
const probe = document.createElement("span");
|
|
419
|
+
probe.hidden = true;
|
|
420
|
+
probe.style.color = value;
|
|
421
|
+
if (probe.style.color === "") {
|
|
422
|
+
return "";
|
|
423
|
+
}
|
|
424
|
+
root.appendChild(probe);
|
|
425
|
+
const resolved = window.getComputedStyle(probe).color;
|
|
426
|
+
probe.remove();
|
|
427
|
+
return resolved;
|
|
428
|
+
}
|
|
429
|
+
|
|
356
430
|
// src/dom/highlight_overlay.ts
|
|
357
|
-
var ACCENT = "#4f46e5";
|
|
358
431
|
function tokenOn(target, name, fallback) {
|
|
359
432
|
const value = window.getComputedStyle(target).getPropertyValue(name).trim();
|
|
360
433
|
return value === "" ? fallback : value;
|
|
@@ -439,7 +512,7 @@ function safeColor(value) {
|
|
|
439
512
|
return CSS.supports("color", value) ? value : null;
|
|
440
513
|
}
|
|
441
514
|
function ringPaint(target, options) {
|
|
442
|
-
const color = safeColor(options.color) ??
|
|
515
|
+
const color = safeColor(options.color) ?? ringColor(target, options.chat);
|
|
443
516
|
if (options.gradient !== true) {
|
|
444
517
|
return `border-color: ${color}`;
|
|
445
518
|
}
|
|
@@ -503,9 +576,6 @@ function setNativeChecked(el2, checked) {
|
|
|
503
576
|
}
|
|
504
577
|
|
|
505
578
|
// src/dom/animations.ts
|
|
506
|
-
var ACCENT2 = "#4f46e5";
|
|
507
|
-
var ACCENT_HALO = "rgba(79, 70, 229, 0.4)";
|
|
508
|
-
var ACCENT_PROPERTY = "--ag-ui-accent";
|
|
509
579
|
function delay(ms) {
|
|
510
580
|
return new Promise((resolve) => {
|
|
511
581
|
setTimeout(resolve, ms);
|
|
@@ -520,12 +590,8 @@ function motionDelay(ms) {
|
|
|
520
590
|
}
|
|
521
591
|
return delay(ms);
|
|
522
592
|
}
|
|
523
|
-
function
|
|
524
|
-
|
|
525
|
-
return themed === "" ? fallback : themed;
|
|
526
|
-
}
|
|
527
|
-
function ringShadow(el2) {
|
|
528
|
-
return `0 0 0 3px ${accentColor(el2, ACCENT_HALO)}`;
|
|
593
|
+
function ringShadow(el2, chat) {
|
|
594
|
+
return `0 0 0 3px color-mix(in srgb, ${ringColor(el2, chat)} 40%, transparent)`;
|
|
529
595
|
}
|
|
530
596
|
async function typeInto(el2, value, options = {}) {
|
|
531
597
|
const charDelayMs = options.charDelayMs ?? 35;
|
|
@@ -544,7 +610,7 @@ async function highlightThenClick(el2, options = {}) {
|
|
|
544
610
|
const highlightMs = options.highlightMs ?? 280;
|
|
545
611
|
const previousOutline = el2.style.outline;
|
|
546
612
|
const previousOffset = el2.style.outlineOffset;
|
|
547
|
-
el2.style.outline = `2px solid ${
|
|
613
|
+
el2.style.outline = `2px solid ${ringColor(el2, options.chat)}`;
|
|
548
614
|
el2.style.outlineOffset = "2px";
|
|
549
615
|
await delay(highlightMs);
|
|
550
616
|
el2.style.outline = previousOutline;
|
|
@@ -596,7 +662,8 @@ async function flashRing(el2, options, focusByDefault) {
|
|
|
596
662
|
scrim: options.scrim === true,
|
|
597
663
|
gradient: options.gradient === true,
|
|
598
664
|
...options.color === void 0 ? {} : { color: options.color },
|
|
599
|
-
...options.ringPadding === void 0 ? {} : { padding: options.ringPadding }
|
|
665
|
+
...options.ringPadding === void 0 ? {} : { padding: options.ringPadding },
|
|
666
|
+
...options.chat === void 0 ? {} : { chat: options.chat }
|
|
600
667
|
});
|
|
601
668
|
await delay(flashMs);
|
|
602
669
|
dismiss();
|
|
@@ -605,7 +672,7 @@ async function flashRing(el2, options, focusByDefault) {
|
|
|
605
672
|
const previousOutline = el2.style.outline;
|
|
606
673
|
const previousOffset = el2.style.outlineOffset;
|
|
607
674
|
const previousTransition = el2.style.transition;
|
|
608
|
-
const color = options.color ??
|
|
675
|
+
const color = options.color ?? ringColor(el2, options.chat);
|
|
609
676
|
el2.style.outline = `3px solid ${color}`;
|
|
610
677
|
el2.style.outlineOffset = "2px";
|
|
611
678
|
const fadeMs = prefersReducedMotion() ? 0 : Math.round(flashMs * FLASH_FADE_RATIO);
|
|
@@ -632,7 +699,7 @@ async function pressThenClick(el2, options = {}) {
|
|
|
632
699
|
const previousShadow = el2.style.boxShadow;
|
|
633
700
|
el2.style.transition = "transform 80ms ease";
|
|
634
701
|
el2.style.transform = "scale(0.96)";
|
|
635
|
-
el2.style.boxShadow = ringShadow(el2);
|
|
702
|
+
el2.style.boxShadow = ringShadow(el2, options.chat);
|
|
636
703
|
await motionDelay(pressMs);
|
|
637
704
|
el2.style.transform = previousTransform;
|
|
638
705
|
el2.style.transition = previousTransition;
|
|
@@ -655,7 +722,7 @@ async function selectOption(el2, value, options = {}) {
|
|
|
655
722
|
const highlightMs = options.highlightMs ?? 220;
|
|
656
723
|
const previousOutline = el2.style.outline;
|
|
657
724
|
const previousOffset = el2.style.outlineOffset;
|
|
658
|
-
el2.style.outline = `2px solid ${
|
|
725
|
+
el2.style.outline = `2px solid ${ringColor(el2, options.chat)}`;
|
|
659
726
|
el2.style.outlineOffset = "2px";
|
|
660
727
|
await motionDelay(highlightMs);
|
|
661
728
|
setNativeValue(el2, option.value);
|
|
@@ -667,7 +734,7 @@ async function selectOption(el2, value, options = {}) {
|
|
|
667
734
|
async function toggleControl(el2, checked, options = {}) {
|
|
668
735
|
const flashMs = options.flashMs ?? 200;
|
|
669
736
|
const previousShadow = el2.style.boxShadow;
|
|
670
|
-
el2.style.boxShadow = ringShadow(el2);
|
|
737
|
+
el2.style.boxShadow = ringShadow(el2, options.chat);
|
|
671
738
|
await motionDelay(flashMs);
|
|
672
739
|
setNativeChecked(el2, checked);
|
|
673
740
|
el2.dispatchEvent(new Event("input", { bubbles: true }));
|
|
@@ -1014,6 +1081,13 @@ var DEFAULT_UI_STRINGS = {
|
|
|
1014
1081
|
declinedLabel: "Declined",
|
|
1015
1082
|
interruptedLabel: "Not finished",
|
|
1016
1083
|
details: "Details",
|
|
1084
|
+
toolGroupSteps: "{count} steps",
|
|
1085
|
+
toolGroupWorking: "Working through {count} steps",
|
|
1086
|
+
toolGroupWorked: "Worked through {count} steps",
|
|
1087
|
+
toolGroupWaiting: "{count} waiting for you",
|
|
1088
|
+
toolGroupFailed: "{count} failed",
|
|
1089
|
+
toolGroupDeclined: "{count} declined",
|
|
1090
|
+
toolStepRepeat: "({n})",
|
|
1017
1091
|
subAgentWorking: "Working\u2026",
|
|
1018
1092
|
subAgentDelegatedTo: "Delegated to {agent}",
|
|
1019
1093
|
subAgentFinished: "{agent} finished",
|
|
@@ -1447,14 +1521,19 @@ var ToolCatalog = class {
|
|
|
1447
1521
|
});
|
|
1448
1522
|
const renderer = this.#host.askUserRenderer();
|
|
1449
1523
|
let answer;
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1524
|
+
this.#host.setAsking(callId, true);
|
|
1525
|
+
try {
|
|
1526
|
+
if (renderer === null) {
|
|
1527
|
+
answer = await builtIn();
|
|
1528
|
+
} else {
|
|
1529
|
+
try {
|
|
1530
|
+
answer = await renderer.call(this.#host.element, request, { signal });
|
|
1531
|
+
} catch (error) {
|
|
1532
|
+
answer = await this.#afterRendererFailed(error, signal, callId, builtIn);
|
|
1533
|
+
}
|
|
1457
1534
|
}
|
|
1535
|
+
} finally {
|
|
1536
|
+
this.#host.setAsking(callId, false);
|
|
1458
1537
|
}
|
|
1459
1538
|
this.#host.decision.close();
|
|
1460
1539
|
this.#host.updateEmptyState();
|
|
@@ -1752,6 +1831,7 @@ var ToolDispatch = class {
|
|
|
1752
1831
|
const card = this.#host.transcript.cardFor(call);
|
|
1753
1832
|
this.#host.transcript.forgetCard(call.id);
|
|
1754
1833
|
this.#host.transcript.setCardElement(call.id, card.element);
|
|
1834
|
+
this.#host.transcript.holdRunning(call.id, card);
|
|
1755
1835
|
const tool = this.#host.tools.wasAdvertised(call.name) ? this.#host.tools.resolve(call.name) : null;
|
|
1756
1836
|
if (tool === null) {
|
|
1757
1837
|
if (!this.#host.transcript.isServerSettled(call.id)) {
|
|
@@ -1784,15 +1864,21 @@ var ToolDispatch = class {
|
|
|
1784
1864
|
request.message = confirmText;
|
|
1785
1865
|
}
|
|
1786
1866
|
const signal = this.#host.decision.open();
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1867
|
+
card.setAsking(true);
|
|
1868
|
+
let accepted;
|
|
1869
|
+
try {
|
|
1870
|
+
const decision = requestConfirmation(this.#host.transcript.ensureGroup(), request, {
|
|
1871
|
+
signal,
|
|
1872
|
+
strings: this.#host.strings(),
|
|
1873
|
+
// Offered only where it can be honoured -- see `#confirmationRule`.
|
|
1874
|
+
...rule === "destructive" ? { onAlwaysAllow: () => this.#sessionApproved.add(call.name) } : {}
|
|
1875
|
+
});
|
|
1876
|
+
this.#host.transcript.updateEmptyState();
|
|
1877
|
+
this.#host.transcript.follow();
|
|
1878
|
+
accepted = await decision;
|
|
1879
|
+
} finally {
|
|
1880
|
+
card.setAsking(false);
|
|
1881
|
+
}
|
|
1796
1882
|
this.#host.decision.close();
|
|
1797
1883
|
if (this.#host.tenure() !== tenure) {
|
|
1798
1884
|
return null;
|
|
@@ -1893,6 +1979,9 @@ var ToolDispatch = class {
|
|
|
1893
1979
|
request.args = card.args;
|
|
1894
1980
|
}
|
|
1895
1981
|
card?.mark(TOOL_CALL_STATUS.DEFERRED);
|
|
1982
|
+
if (card !== void 0) {
|
|
1983
|
+
this.#host.transcript.revealStep(card);
|
|
1984
|
+
}
|
|
1896
1985
|
const builtIn = () => requestApproval(card?.approvalSlot ?? this.#host.transcript.ensureGroup(), request, {
|
|
1897
1986
|
signal,
|
|
1898
1987
|
strings: this.#host.strings(),
|
|
@@ -4399,7 +4488,7 @@ var ConversationHistory = class {
|
|
|
4399
4488
|
this.#host.conversationStore().setActiveThread(threadId);
|
|
4400
4489
|
this.#threadId = threadId;
|
|
4401
4490
|
this.#host.setRunning(false);
|
|
4402
|
-
await this.rehydrate();
|
|
4491
|
+
await this.rehydrate("switch");
|
|
4403
4492
|
}
|
|
4404
4493
|
/** Rename a thread, then reload the list that shows its title. */
|
|
4405
4494
|
renameThread(threadId, title) {
|
|
@@ -4417,6 +4506,7 @@ var ConversationHistory = class {
|
|
|
4417
4506
|
this.#host.resetState();
|
|
4418
4507
|
this.adoptActiveThread();
|
|
4419
4508
|
this.#host.setRunning(false);
|
|
4509
|
+
this.#host.threadChanged(this.#threadId, "delete");
|
|
4420
4510
|
}
|
|
4421
4511
|
void this.refreshDrawer();
|
|
4422
4512
|
}
|
|
@@ -4593,8 +4683,11 @@ var ConversationHistory = class {
|
|
|
4593
4683
|
* for the run it would have resumed -- unless what replaced it is a restore
|
|
4594
4684
|
* of the same conversation, still current, which answers for that run
|
|
4595
4685
|
* instead; see `#forgetStopped`.
|
|
4686
|
+
*
|
|
4687
|
+
* `reason` is what the thread event this restore ends with reports as why
|
|
4688
|
+
* the conversation changed. A restore that is stopped reports nothing.
|
|
4596
4689
|
*/
|
|
4597
|
-
async rehydrate() {
|
|
4690
|
+
async rehydrate(reason) {
|
|
4598
4691
|
this.#generation += 1;
|
|
4599
4692
|
const generation = this.#generation;
|
|
4600
4693
|
const threadId = this.#threadId;
|
|
@@ -4644,11 +4737,17 @@ var ConversationHistory = class {
|
|
|
4644
4737
|
}
|
|
4645
4738
|
}
|
|
4646
4739
|
}
|
|
4740
|
+
if (checkpoint === null) {
|
|
4741
|
+
this.#noticeIfRunUnfinished(messages);
|
|
4742
|
+
}
|
|
4743
|
+
this.#host.threadChanged(threadId, reason);
|
|
4647
4744
|
if (checkpoint !== null) {
|
|
4745
|
+
if (!this.#restoring(generation)) {
|
|
4746
|
+
this.#forgetStopped(store, threadId, checkpoint);
|
|
4747
|
+
return;
|
|
4748
|
+
}
|
|
4648
4749
|
await this.#resumeFrom(checkpoint, generation);
|
|
4649
|
-
return;
|
|
4650
4750
|
}
|
|
4651
|
-
this.#noticeIfRunUnfinished(messages);
|
|
4652
4751
|
} finally {
|
|
4653
4752
|
hold.release();
|
|
4654
4753
|
if (this.#loading === waiting) {
|
|
@@ -5629,6 +5728,8 @@ function surfaceFor(placement) {
|
|
|
5629
5728
|
|
|
5630
5729
|
// src/ui/placement/panel_placement.ts
|
|
5631
5730
|
var SIZE_KEY = "ag-ui-chat:size";
|
|
5731
|
+
var DRAG_WIDTH = "--_drag-width";
|
|
5732
|
+
var DRAG_HEIGHT = "--_drag-height";
|
|
5632
5733
|
var LAUNCHER_KEY = "ag-ui-chat:launcher";
|
|
5633
5734
|
function asPoint(value) {
|
|
5634
5735
|
if (typeof value !== "object" || value === null) {
|
|
@@ -5712,6 +5813,17 @@ var PanelPlacement = class {
|
|
|
5712
5813
|
restoreSize() {
|
|
5713
5814
|
this.#applySize(this.#readSize());
|
|
5714
5815
|
}
|
|
5816
|
+
/**
|
|
5817
|
+
* Drop the dragged size and its stored copy, so the placement's own size and
|
|
5818
|
+
* the host's tokens apply again. For a host entering a sized state of its
|
|
5819
|
+
* own, which a user's drag would otherwise outrank.
|
|
5820
|
+
*/
|
|
5821
|
+
resetSize() {
|
|
5822
|
+
this.#host.element.style.removeProperty(DRAG_WIDTH);
|
|
5823
|
+
this.#host.element.style.removeProperty(DRAG_HEIGHT);
|
|
5824
|
+
this.#host.clearPreference(SIZE_KEY);
|
|
5825
|
+
this.syncResizeAnchor();
|
|
5826
|
+
}
|
|
5715
5827
|
/**
|
|
5716
5828
|
* A zero-sized box carrying the host's viewport insets as padding, so they
|
|
5717
5829
|
* can be read back as used pixel lengths. See the `.viewport-probe` rule for
|
|
@@ -5900,12 +6012,12 @@ var PanelPlacement = class {
|
|
|
5900
6012
|
*/
|
|
5901
6013
|
#measureAnchor() {
|
|
5902
6014
|
const before = this.#host.element.getBoundingClientRect();
|
|
5903
|
-
const width = this.#host.element.style.getPropertyValue(
|
|
5904
|
-
const height = this.#host.element.style.getPropertyValue(
|
|
6015
|
+
const width = this.#host.element.style.getPropertyValue(DRAG_WIDTH);
|
|
6016
|
+
const height = this.#host.element.style.getPropertyValue(DRAG_HEIGHT);
|
|
5905
6017
|
const shrunk = this.#probeAnchor(before, -1);
|
|
5906
6018
|
const grown = shrunk.x === null || shrunk.y === null ? this.#probeAnchor(before, 1) : shrunk;
|
|
5907
|
-
this.#restoreProperty(
|
|
5908
|
-
this.#restoreProperty(
|
|
6019
|
+
this.#restoreProperty(DRAG_WIDTH, width);
|
|
6020
|
+
this.#restoreProperty(DRAG_HEIGHT, height);
|
|
5909
6021
|
return {
|
|
5910
6022
|
// Neither direction moved it: the axis cannot be resized at all, so the
|
|
5911
6023
|
// floating default is the best answer available and is the one the
|
|
@@ -5951,7 +6063,7 @@ var PanelPlacement = class {
|
|
|
5951
6063
|
/**
|
|
5952
6064
|
* Write a dragged size onto the host, on the axes this placement leaves free.
|
|
5953
6065
|
*
|
|
5954
|
-
* Writing
|
|
6066
|
+
* Writing a custom property rather than inline `width` / `height` does not
|
|
5955
6067
|
* by itself leave placement in charge: an inline custom property still
|
|
5956
6068
|
* outranks a `:host([placement=…])` rule setting the same property, so a
|
|
5957
6069
|
* height dragged while floating would cap a docked sidebar asking for
|
|
@@ -5965,10 +6077,10 @@ var PanelPlacement = class {
|
|
|
5965
6077
|
return;
|
|
5966
6078
|
}
|
|
5967
6079
|
if (size.width !== void 0) {
|
|
5968
|
-
this.#host.element.style.setProperty(
|
|
6080
|
+
this.#host.element.style.setProperty(DRAG_WIDTH, `${size.width}px`);
|
|
5969
6081
|
}
|
|
5970
6082
|
if (size.height !== void 0 && axis === "both") {
|
|
5971
|
-
this.#host.element.style.setProperty(
|
|
6083
|
+
this.#host.element.style.setProperty(DRAG_HEIGHT, `${size.height}px`);
|
|
5972
6084
|
}
|
|
5973
6085
|
}
|
|
5974
6086
|
/**
|
|
@@ -5981,10 +6093,10 @@ var PanelPlacement = class {
|
|
|
5981
6093
|
releaseOwnedAxes() {
|
|
5982
6094
|
const axis = this.#resizeAxis();
|
|
5983
6095
|
if (axis !== "both") {
|
|
5984
|
-
this.#host.element.style.removeProperty(
|
|
6096
|
+
this.#host.element.style.removeProperty(DRAG_HEIGHT);
|
|
5985
6097
|
}
|
|
5986
6098
|
if (axis === "none") {
|
|
5987
|
-
this.#host.element.style.removeProperty(
|
|
6099
|
+
this.#host.element.style.removeProperty(DRAG_WIDTH);
|
|
5988
6100
|
}
|
|
5989
6101
|
}
|
|
5990
6102
|
/**
|
|
@@ -6887,9 +6999,7 @@ var ToolCallCard = class {
|
|
|
6887
6999
|
this.#formatPayload = options.formatPayload ?? null;
|
|
6888
7000
|
this.element = document.createElement("div");
|
|
6889
7001
|
this.element.className = "tool-call";
|
|
6890
|
-
this.element.setAttribute("part", "tool-card");
|
|
6891
7002
|
this.element.setAttribute("data-tool-name", name);
|
|
6892
|
-
this.element.setAttribute("data-status", TOOL_CALL_STATUS.PENDING);
|
|
6893
7003
|
this.element.setAttribute("data-expanded", "false");
|
|
6894
7004
|
const head = document.createElement("div");
|
|
6895
7005
|
head.className = "tool-call-head";
|
|
@@ -6904,8 +7014,7 @@ var ToolCallCard = class {
|
|
|
6904
7014
|
label.textContent = summary ?? name;
|
|
6905
7015
|
this.#status = document.createElement("span");
|
|
6906
7016
|
this.#status.className = "tool-call-status";
|
|
6907
|
-
this.#
|
|
6908
|
-
this.#status.textContent = statusLabels(strings)[TOOL_CALL_STATUS.PENDING];
|
|
7017
|
+
this.#setStatus(TOOL_CALL_STATUS.PENDING);
|
|
6909
7018
|
this.#decision = document.createElement("span");
|
|
6910
7019
|
this.#decision.className = "tool-call-decision";
|
|
6911
7020
|
this.#decision.setAttribute("part", "tool-card-decision");
|
|
@@ -6953,8 +7062,17 @@ var ToolCallCard = class {
|
|
|
6953
7062
|
if (this.#settled) {
|
|
6954
7063
|
return;
|
|
6955
7064
|
}
|
|
6956
|
-
this
|
|
6957
|
-
|
|
7065
|
+
this.#setStatus(status);
|
|
7066
|
+
}
|
|
7067
|
+
/**
|
|
7068
|
+
* Say whether a prompt is open on this call, a question it asked or a
|
|
7069
|
+
* confirmation it needs. A flag of its own beside the status, which stays
|
|
7070
|
+
* `pending`: the call is still running as far as the status goes, and a card
|
|
7071
|
+
* display mode that reads the status draws it exactly as before. The step
|
|
7072
|
+
* group reads the flag to tell a call waiting on a person from one working.
|
|
7073
|
+
*/
|
|
7074
|
+
setAsking(asking) {
|
|
7075
|
+
this.element.toggleAttribute("data-asking", asking);
|
|
6958
7076
|
}
|
|
6959
7077
|
/**
|
|
6960
7078
|
* Record that a human approved or declined this call, as a line in the card.
|
|
@@ -6979,8 +7097,7 @@ var ToolCallCard = class {
|
|
|
6979
7097
|
return;
|
|
6980
7098
|
}
|
|
6981
7099
|
this.#settled = true;
|
|
6982
|
-
this
|
|
6983
|
-
this.#status.textContent = statusLabels(this.#strings)[status];
|
|
7100
|
+
this.#setStatus(status);
|
|
6984
7101
|
this.#resultLabel.textContent = resultLabels(this.#strings)[status];
|
|
6985
7102
|
this.#renderPayload(
|
|
6986
7103
|
this.#resultBody,
|
|
@@ -6989,6 +7106,20 @@ var ToolCallCard = class {
|
|
|
6989
7106
|
);
|
|
6990
7107
|
this.#resultSection.hidden = false;
|
|
6991
7108
|
}
|
|
7109
|
+
/**
|
|
7110
|
+
* Write the status everywhere it is read from, in one place so they cannot
|
|
7111
|
+
* disagree: `data-status` for the shadow CSS, the pill's text, and the part
|
|
7112
|
+
* lists. `::part()` takes no attribute selector, so the card and its pill also
|
|
7113
|
+
* name the status as a part (`tool-card-error`, `tool-card-status-error`), the
|
|
7114
|
+
* modifier convention a run notice uses, and a host styles failures alone.
|
|
7115
|
+
* Setting the whole list replaces the previous modifier.
|
|
7116
|
+
*/
|
|
7117
|
+
#setStatus(status) {
|
|
7118
|
+
this.element.setAttribute("data-status", status);
|
|
7119
|
+
this.element.setAttribute("part", `tool-card tool-card-${status}`);
|
|
7120
|
+
this.#status.setAttribute("part", `tool-card-status tool-card-status-${status}`);
|
|
7121
|
+
this.#status.textContent = statusLabels(this.#strings)[status];
|
|
7122
|
+
}
|
|
6992
7123
|
/**
|
|
6993
7124
|
* Fill one body region, offering it to the host formatter first.
|
|
6994
7125
|
*
|
|
@@ -8038,8 +8169,6 @@ var CONFIRMATION_STYLES = `
|
|
|
8038
8169
|
padding: 8px 10px;
|
|
8039
8170
|
max-height: 140px;
|
|
8040
8171
|
overflow: auto;
|
|
8041
|
-
/* Scrolling past the end of this must not scroll the page behind it. */
|
|
8042
|
-
overscroll-behavior: contain;
|
|
8043
8172
|
font-size: 12px;
|
|
8044
8173
|
font-family: ui-monospace, "SF Mono", Menlo, monospace;
|
|
8045
8174
|
background: var(--_assistant-bg);
|
|
@@ -8342,8 +8471,8 @@ var EMBEDDED_STYLES = `
|
|
|
8342
8471
|
the widget lives in the host's own layout (fixes overlay/z-index clashes). */
|
|
8343
8472
|
:host([placement="embedded"]) {
|
|
8344
8473
|
--_position: var(--ag-ui-position, static);
|
|
8345
|
-
--_width: var(--ag-ui-width, 100%);
|
|
8346
|
-
--_height: var(--ag-ui-height, 100%);
|
|
8474
|
+
--_width: var(--_drag-width, var(--ag-ui-width, 100%));
|
|
8475
|
+
--_height: var(--_drag-height, var(--ag-ui-height, 100%));
|
|
8347
8476
|
--_max-width: var(--ag-ui-max-width, 100%);
|
|
8348
8477
|
--_max-height: var(--ag-ui-max-height, 100%);
|
|
8349
8478
|
--_shadow: var(--ag-ui-shadow, none);
|
|
@@ -8601,7 +8730,7 @@ var PRESET_STYLES = `
|
|
|
8601
8730
|
|
|
8602
8731
|
:host([placement="side"]) {
|
|
8603
8732
|
--_inset: var(--ag-ui-inset, calc(var(--_viewport-inset-top) + var(--_keyboard-inset-top)) var(--_viewport-inset-right) var(--_viewport-inset-bottom) auto);
|
|
8604
|
-
--_width: var(--ag-ui-width, 420px);
|
|
8733
|
+
--_width: var(--_drag-width, var(--ag-ui-width, 420px));
|
|
8605
8734
|
--_height: var(--ag-ui-height, var(--_viewport-height));
|
|
8606
8735
|
--_max-height: var(--ag-ui-max-height, var(--_viewport-height));
|
|
8607
8736
|
--_panel-radius: var(--ag-ui-panel-radius, 0);
|
|
@@ -8817,7 +8946,7 @@ var SIDEBAR_STYLES = `
|
|
|
8817
8946
|
host-managed push instead. */
|
|
8818
8947
|
:host([placement="sidebar"]) {
|
|
8819
8948
|
--_inset: var(--ag-ui-inset, calc(var(--_viewport-inset-top) + var(--_keyboard-inset-top)) var(--_viewport-inset-right) var(--_viewport-inset-bottom) auto);
|
|
8820
|
-
--_width: var(--ag-ui-width, 420px);
|
|
8949
|
+
--_width: var(--_drag-width, var(--ag-ui-width, 420px));
|
|
8821
8950
|
--_height: var(--ag-ui-height, var(--_viewport-height));
|
|
8822
8951
|
--_max-height: var(--ag-ui-max-height, var(--_viewport-height));
|
|
8823
8952
|
--_panel-radius: var(--ag-ui-panel-radius, 0);
|
|
@@ -8916,6 +9045,11 @@ var SMALL_VIEWPORT_STYLES = `
|
|
|
8916
9045
|
fine-pointered and small, and conflating the two gets both wrong. What the
|
|
8917
9046
|
pointer decides is which controls make sense, further down.
|
|
8918
9047
|
|
|
9048
|
+
The size the user dragged is deliberately not read here. The desktop
|
|
9049
|
+
placements read it before the host token, and this block restates the sizes
|
|
9050
|
+
without it, so a persisted or freshly dragged size cannot change the shape
|
|
9051
|
+
of a phone, and a window narrowed after a drag goes full-bleed.
|
|
9052
|
+
|
|
8919
9053
|
Two placements are left alone. "page" is already this shape. "embedded" sits
|
|
8920
9054
|
in a box the host sized and placed, and taking that over would break the app
|
|
8921
9055
|
shell it was embedded into -- the host is the only party that knows whether
|
|
@@ -9057,8 +9191,6 @@ var THOUGHTS_STYLES = `
|
|
|
9057
9191
|
border-left: 2px solid var(--_border);
|
|
9058
9192
|
max-height: 220px;
|
|
9059
9193
|
overflow: auto;
|
|
9060
|
-
/* Scrolling past the end of this must not scroll the page behind it. */
|
|
9061
|
-
overscroll-behavior: contain;
|
|
9062
9194
|
white-space: pre-wrap;
|
|
9063
9195
|
word-break: break-word;
|
|
9064
9196
|
font-family: inherit;
|
|
@@ -9075,6 +9207,225 @@ var THOUGHTS_STYLES = `
|
|
|
9075
9207
|
}
|
|
9076
9208
|
`;
|
|
9077
9209
|
|
|
9210
|
+
// src/ui/progress/tool_group_styles.ts
|
|
9211
|
+
var CARD_MODES = [
|
|
9212
|
+
'[data-tool-display="inline"]',
|
|
9213
|
+
'[data-tool-display="minimal"]',
|
|
9214
|
+
'[data-tool-display="compact"]',
|
|
9215
|
+
'[data-tool-display="full"]'
|
|
9216
|
+
].join(", ");
|
|
9217
|
+
var GROUPED = `:host(:where(:not(${CARD_MODES})))`;
|
|
9218
|
+
var CARDS = `:host(:is(${CARD_MODES}))`;
|
|
9219
|
+
var TOOL_GROUP_STYLES = `
|
|
9220
|
+
/* \u2500\u2500 The folded tool-step group \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
|
|
9221
|
+
One quiet row per run of consecutive calls, the cards one click down as
|
|
9222
|
+
plain lines rather than boxes. Every rule is scoped to grouped mode, so
|
|
9223
|
+
none of it reaches a group drawn earlier once the host moves to a card
|
|
9224
|
+
mode. */
|
|
9225
|
+
${GROUPED} .tool-group {
|
|
9226
|
+
align-self: stretch;
|
|
9227
|
+
display: flex;
|
|
9228
|
+
flex-direction: column;
|
|
9229
|
+
min-width: 0;
|
|
9230
|
+
}
|
|
9231
|
+
|
|
9232
|
+
${GROUPED} .tool-group-head {
|
|
9233
|
+
appearance: none;
|
|
9234
|
+
align-self: flex-start;
|
|
9235
|
+
max-width: 100%;
|
|
9236
|
+
display: inline-flex;
|
|
9237
|
+
align-items: center;
|
|
9238
|
+
gap: 8px;
|
|
9239
|
+
margin: 0 0 0 -6px;
|
|
9240
|
+
padding: 4px 6px;
|
|
9241
|
+
border: 0;
|
|
9242
|
+
border-radius: 6px;
|
|
9243
|
+
background: transparent;
|
|
9244
|
+
color: var(--_muted);
|
|
9245
|
+
font: inherit;
|
|
9246
|
+
font-size: var(--_text-sm);
|
|
9247
|
+
line-height: 1.3;
|
|
9248
|
+
text-align: left;
|
|
9249
|
+
cursor: pointer;
|
|
9250
|
+
}
|
|
9251
|
+
|
|
9252
|
+
${GROUPED} .tool-group-head:hover {
|
|
9253
|
+
background: var(--_hover);
|
|
9254
|
+
color: var(--_fg);
|
|
9255
|
+
}
|
|
9256
|
+
|
|
9257
|
+
${GROUPED} .tool-group-head:focus-visible {
|
|
9258
|
+
outline: 2px solid var(--_ring);
|
|
9259
|
+
outline-offset: 1px;
|
|
9260
|
+
}
|
|
9261
|
+
|
|
9262
|
+
${GROUPED} .tool-group-label {
|
|
9263
|
+
min-width: 0;
|
|
9264
|
+
font-weight: 500;
|
|
9265
|
+
color: var(--_ink-2);
|
|
9266
|
+
overflow-wrap: anywhere;
|
|
9267
|
+
}
|
|
9268
|
+
|
|
9269
|
+
${GROUPED} .tool-group-meta {
|
|
9270
|
+
min-width: 0;
|
|
9271
|
+
color: var(--_muted);
|
|
9272
|
+
overflow-wrap: anywhere;
|
|
9273
|
+
}
|
|
9274
|
+
|
|
9275
|
+
/* Each note opens with a middle dot, which also parts the first note from
|
|
9276
|
+
the label. */
|
|
9277
|
+
${GROUPED} .tool-group-note::before {
|
|
9278
|
+
content: "\\00B7";
|
|
9279
|
+
margin: 0 6px 0 2px;
|
|
9280
|
+
}
|
|
9281
|
+
|
|
9282
|
+
${GROUPED} .tool-group[data-state="error"] .tool-group-meta {
|
|
9283
|
+
color: var(--_danger);
|
|
9284
|
+
}
|
|
9285
|
+
|
|
9286
|
+
${GROUPED} .tool-group-icon {
|
|
9287
|
+
flex: none;
|
|
9288
|
+
box-sizing: border-box;
|
|
9289
|
+
width: 14px;
|
|
9290
|
+
height: 14px;
|
|
9291
|
+
background: currentColor;
|
|
9292
|
+
mask: var(--_ico-check) center / contain no-repeat;
|
|
9293
|
+
color: var(--_success);
|
|
9294
|
+
}
|
|
9295
|
+
|
|
9296
|
+
${GROUPED} .tool-group[data-state="error"] .tool-group-icon {
|
|
9297
|
+
mask-image: var(--_ico-error);
|
|
9298
|
+
color: var(--_danger);
|
|
9299
|
+
}
|
|
9300
|
+
|
|
9301
|
+
${GROUPED} .tool-group[data-state="running"] .tool-group-icon {
|
|
9302
|
+
mask: none;
|
|
9303
|
+
background: none;
|
|
9304
|
+
border: 2px solid var(--_muted);
|
|
9305
|
+
border-top-color: transparent;
|
|
9306
|
+
border-radius: 50%;
|
|
9307
|
+
animation: ag-ui-tool-spin var(--_tool-spin-duration) linear infinite;
|
|
9308
|
+
}
|
|
9309
|
+
|
|
9310
|
+
/* Waiting on the user: a steady accent dot rather than a spinner, and the
|
|
9311
|
+
count in the accent's ink. */
|
|
9312
|
+
${GROUPED} .tool-group[data-state="waiting"] .tool-group-icon {
|
|
9313
|
+
mask: none;
|
|
9314
|
+
border-radius: 50%;
|
|
9315
|
+
transform: scale(0.6);
|
|
9316
|
+
background: var(--_accent);
|
|
9317
|
+
}
|
|
9318
|
+
|
|
9319
|
+
${GROUPED} .tool-group[data-state="waiting"] .tool-group-meta {
|
|
9320
|
+
color: var(--_accent-ink);
|
|
9321
|
+
font-weight: 500;
|
|
9322
|
+
}
|
|
9323
|
+
|
|
9324
|
+
${GROUPED} .tool-group-chevron {
|
|
9325
|
+
flex: none;
|
|
9326
|
+
width: 12px;
|
|
9327
|
+
height: 12px;
|
|
9328
|
+
background: currentColor;
|
|
9329
|
+
mask: var(--_ico-chevron) center / contain no-repeat;
|
|
9330
|
+
opacity: 0.7;
|
|
9331
|
+
transition: transform var(--_motion) var(--_ease);
|
|
9332
|
+
}
|
|
9333
|
+
|
|
9334
|
+
${GROUPED} .tool-group[data-open="true"] .tool-group-chevron {
|
|
9335
|
+
transform: rotate(90deg);
|
|
9336
|
+
}
|
|
9337
|
+
|
|
9338
|
+
@media (prefers-reduced-motion: reduce) {
|
|
9339
|
+
${GROUPED} .tool-group[data-state="running"] .tool-group-icon {
|
|
9340
|
+
animation: none;
|
|
9341
|
+
}
|
|
9342
|
+
}
|
|
9343
|
+
|
|
9344
|
+
${GROUPED} .tool-group-list {
|
|
9345
|
+
display: flex;
|
|
9346
|
+
flex-direction: column;
|
|
9347
|
+
gap: 2px;
|
|
9348
|
+
margin: 2px 0 4px 6px;
|
|
9349
|
+
padding-left: 13px;
|
|
9350
|
+
border-left: 1px solid var(--_border);
|
|
9351
|
+
}
|
|
9352
|
+
|
|
9353
|
+
${GROUPED} .tool-group[data-open="false"] .tool-group-list {
|
|
9354
|
+
display: none;
|
|
9355
|
+
}
|
|
9356
|
+
|
|
9357
|
+
/* A card inside the group is one line of the list: icon, name, and its
|
|
9358
|
+
Details control at the end, with the arguments and result opening under
|
|
9359
|
+
the whole row. */
|
|
9360
|
+
${GROUPED} .tool-group .tool-call {
|
|
9361
|
+
max-width: 100%;
|
|
9362
|
+
align-self: stretch;
|
|
9363
|
+
flex-flow: row wrap;
|
|
9364
|
+
align-items: center;
|
|
9365
|
+
gap: 2px 10px;
|
|
9366
|
+
padding: 3px 0;
|
|
9367
|
+
border: 0;
|
|
9368
|
+
border-radius: 0;
|
|
9369
|
+
background: transparent;
|
|
9370
|
+
color: var(--_ink-2);
|
|
9371
|
+
font-family: inherit;
|
|
9372
|
+
font-size: var(--_text-sm);
|
|
9373
|
+
}
|
|
9374
|
+
|
|
9375
|
+
${GROUPED} .tool-group .tool-call-head {
|
|
9376
|
+
flex: 1 1 auto;
|
|
9377
|
+
justify-content: flex-start;
|
|
9378
|
+
}
|
|
9379
|
+
|
|
9380
|
+
${GROUPED} .tool-group .tool-call-name {
|
|
9381
|
+
flex: 0 1 auto;
|
|
9382
|
+
font-weight: 450;
|
|
9383
|
+
}
|
|
9384
|
+
|
|
9385
|
+
/* The repeat ordinal on a step whose label an earlier step has. */
|
|
9386
|
+
${GROUPED} .tool-call-repeat {
|
|
9387
|
+
color: var(--_muted);
|
|
9388
|
+
font-variant-numeric: tabular-nums;
|
|
9389
|
+
}
|
|
9390
|
+
|
|
9391
|
+
${GROUPED} .tool-group .tool-call-toggle {
|
|
9392
|
+
font-family: inherit;
|
|
9393
|
+
font-size: var(--_text-xs);
|
|
9394
|
+
color: var(--_muted);
|
|
9395
|
+
}
|
|
9396
|
+
|
|
9397
|
+
${GROUPED} .tool-group .tool-call-body,
|
|
9398
|
+
${GROUPED} .tool-group .tool-call-approval,
|
|
9399
|
+
${GROUPED} .tool-group .tool-call-subagent {
|
|
9400
|
+
flex-basis: 100%;
|
|
9401
|
+
}
|
|
9402
|
+
|
|
9403
|
+
/* Grouping is decided as each card is built, so a card mode set afterwards
|
|
9404
|
+
finds groups already drawn. It flattens them: the group and its list stop
|
|
9405
|
+
generating boxes, the row and the repeat ordinals go, and every card lays
|
|
9406
|
+
out as a direct child of the answer, exactly as a card built in that mode
|
|
9407
|
+
does. */
|
|
9408
|
+
${CARDS} .tool-group,
|
|
9409
|
+
${CARDS} .tool-group-list {
|
|
9410
|
+
display: contents;
|
|
9411
|
+
}
|
|
9412
|
+
|
|
9413
|
+
${CARDS} .tool-group-head,
|
|
9414
|
+
${CARDS} .tool-call-repeat {
|
|
9415
|
+
display: none;
|
|
9416
|
+
}
|
|
9417
|
+
|
|
9418
|
+
/* Each of these declares its own display, which beats the user-agent rule for
|
|
9419
|
+
the hidden attribute, so each needs its own. The host prefix is there for
|
|
9420
|
+
weight, not scope: it lifts these over the card-mode rules above that set
|
|
9421
|
+
display, which are heavier than a bare class and attribute. */
|
|
9422
|
+
:host .tool-group[hidden],
|
|
9423
|
+
:host .tool-group-head[hidden],
|
|
9424
|
+
:host .tool-group-list[hidden] {
|
|
9425
|
+
display: none;
|
|
9426
|
+
}
|
|
9427
|
+
`;
|
|
9428
|
+
|
|
9078
9429
|
// src/ui/progress/tool_step_styles.ts
|
|
9079
9430
|
var TOOL_STEP_STYLES = `
|
|
9080
9431
|
.tool-call {
|
|
@@ -9271,8 +9622,6 @@ var TOOL_STEP_STYLES = `
|
|
|
9271
9622
|
padding: 6px 8px;
|
|
9272
9623
|
max-height: 160px;
|
|
9273
9624
|
overflow: auto;
|
|
9274
|
-
/* Scrolling past the end of this must not scroll the page behind it. */
|
|
9275
|
-
overscroll-behavior: contain;
|
|
9276
9625
|
background: var(--_bg);
|
|
9277
9626
|
border: 1px solid var(--_border);
|
|
9278
9627
|
border-radius: 6px;
|
|
@@ -9718,6 +10067,7 @@ var TOKEN_STYLES = `
|
|
|
9718
10067
|
--_line-strong: var(--ag-ui-line-strong, color-mix(in oklch, var(--_fg) 20%, var(--_bg)));
|
|
9719
10068
|
--_wash: var(--ag-ui-wash, color-mix(in oklch, var(--_fg) 4.5%, var(--_bg)));
|
|
9720
10069
|
--_accent-ink: var(--ag-ui-accent-ink, color-mix(in oklch, var(--_accent) 82%, var(--_fg)));
|
|
10070
|
+
--_ring: var(--ag-ui-ring, color-mix(in oklch, var(--_accent) 55%, transparent));
|
|
9721
10071
|
/* The user's turn is the accent at a whisper. With Quiet's graphite accent
|
|
9722
10072
|
that is a neutral wash; once a host sets a brand accent it becomes a tint
|
|
9723
10073
|
of the brand, which is the one thing Soft does that Quiet keeps. */
|
|
@@ -9980,8 +10330,8 @@ var TOKEN_STYLES = `
|
|
|
9980
10330
|
grid/flex layout) to embed it in the page flow instead of floating. */
|
|
9981
10331
|
--_position: var(--ag-ui-position, fixed);
|
|
9982
10332
|
--_z-index: var(--ag-ui-z-index, 2147483000);
|
|
9983
|
-
--_width: var(--ag-ui-width, 380px);
|
|
9984
|
-
--_height: var(--ag-ui-height, 560px);
|
|
10333
|
+
--_width: var(--_drag-width, var(--ag-ui-width, 380px));
|
|
10334
|
+
--_height: var(--_drag-height, var(--ag-ui-height, 560px));
|
|
9985
10335
|
/* The gutter a resting floating panel keeps between itself and the edge of
|
|
9986
10336
|
the box the host left free. One number, because the inset below spends it
|
|
9987
10337
|
and the cap beneath has to know it was spent. */
|
|
@@ -10049,6 +10399,7 @@ var TOKEN_STYLES = `
|
|
|
10049
10399
|
--_ico-check: var(--ag-ui-ico-check, url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3.5 8.5l3 3 6-7'/%3E%3C/svg%3E"));
|
|
10050
10400
|
--_ico-error: var(--ag-ui-ico-error, url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.6' stroke-linecap='round'%3E%3Ccircle cx='8' cy='8' r='6.2'/%3E%3Cpath d='M8 4.9v3.7M8 11.1v.1'/%3E%3C/svg%3E"));
|
|
10051
10401
|
--_ico-declined: var(--ag-ui-ico-declined, url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.6' stroke-linecap='round'%3E%3Ccircle cx='8' cy='8' r='6.2'/%3E%3Cpath d='M3.8 12.2l8.4-8.4'/%3E%3C/svg%3E"));
|
|
10402
|
+
--_ico-chevron: var(--ag-ui-ico-chevron, url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 3.5l4.5 4.5L6 12.5'/%3E%3C/svg%3E"));
|
|
10052
10403
|
}
|
|
10053
10404
|
|
|
10054
10405
|
/* The colour drawn on the accent, from the accent's own luminance: white on
|
|
@@ -10267,6 +10618,21 @@ var LEDGER_STYLES = `
|
|
|
10267
10618
|
letter-spacing: 0.01em;
|
|
10268
10619
|
}
|
|
10269
10620
|
|
|
10621
|
+
/* The step group's row reads as a ledger heading. Unscoped to grouped mode:
|
|
10622
|
+
a card mode hides the row and drops the list's box, so neither reaches a
|
|
10623
|
+
flattened card. */
|
|
10624
|
+
:host([theme~="ledger"]) .tool-group-head {
|
|
10625
|
+
font-family: var(--_code-font);
|
|
10626
|
+
font-size: var(--_text-xs);
|
|
10627
|
+
border-radius: 2px;
|
|
10628
|
+
text-transform: uppercase;
|
|
10629
|
+
letter-spacing: 0.06em;
|
|
10630
|
+
}
|
|
10631
|
+
|
|
10632
|
+
:host([theme~="ledger"]) .tool-group-list {
|
|
10633
|
+
border-left: 1px dashed var(--_line-strong);
|
|
10634
|
+
}
|
|
10635
|
+
|
|
10270
10636
|
:host([theme~="ledger"]) .chart-block {
|
|
10271
10637
|
border-top: 1px solid var(--_line-strong);
|
|
10272
10638
|
border-bottom: 1px solid var(--_line);
|
|
@@ -10650,6 +11016,26 @@ var SOFT_STYLES = `
|
|
|
10650
11016
|
color: var(--_accent-ink);
|
|
10651
11017
|
}
|
|
10652
11018
|
|
|
11019
|
+
/* The step group's row as a tinted pill. Unscoped to grouped mode: a card
|
|
11020
|
+
mode hides the row and drops the list's box, so neither reaches a
|
|
11021
|
+
flattened card. */
|
|
11022
|
+
:host([theme~="soft"]) .tool-group-head {
|
|
11023
|
+
background: var(--_tint);
|
|
11024
|
+
border: 1px solid var(--_border);
|
|
11025
|
+
border-radius: 999px;
|
|
11026
|
+
padding: 5px 12px 5px 9px;
|
|
11027
|
+
margin-left: 0;
|
|
11028
|
+
}
|
|
11029
|
+
|
|
11030
|
+
:host([theme~="soft"]) .tool-group-head:hover {
|
|
11031
|
+
background: var(--_tint-2);
|
|
11032
|
+
}
|
|
11033
|
+
|
|
11034
|
+
:host([theme~="soft"]) .tool-group-list {
|
|
11035
|
+
border-left-color: var(--_tint-2);
|
|
11036
|
+
margin-left: 14px;
|
|
11037
|
+
}
|
|
11038
|
+
|
|
10653
11039
|
:host([theme~="soft"]) .chart-block {
|
|
10654
11040
|
background: var(--_bg);
|
|
10655
11041
|
border: 1px solid var(--_border);
|
|
@@ -11318,8 +11704,6 @@ var MESSAGE_STYLES = `
|
|
|
11318
11704
|
.message--assistant pre {
|
|
11319
11705
|
padding: 8px 10px;
|
|
11320
11706
|
overflow: auto;
|
|
11321
|
-
/* Scrolling past the end of this must not scroll the page behind it. */
|
|
11322
|
-
overscroll-behavior: contain;
|
|
11323
11707
|
background: var(--_bg);
|
|
11324
11708
|
border: 1px solid var(--_border);
|
|
11325
11709
|
border-radius: 6px;
|
|
@@ -11627,6 +12011,10 @@ var STYLES = [
|
|
|
11627
12011
|
QUESTION_STYLES,
|
|
11628
12012
|
SKILL_STYLES,
|
|
11629
12013
|
HISTORY_STYLES,
|
|
12014
|
+
// The step group restates, inside a group, card rules the modules above set
|
|
12015
|
+
// at rest; it outweighs them rather than relying on order, and sits ahead
|
|
12016
|
+
// of the themes so a theme restating a group rule at equal weight wins.
|
|
12017
|
+
TOOL_GROUP_STYLES,
|
|
11630
12018
|
// Each theme's structure comes last: it restates rules the modules above
|
|
11631
12019
|
// set at rest, at equal weight. Classic and code have no structural
|
|
11632
12020
|
// module; they are the base stylesheet, and classic adds only its
|
|
@@ -15854,6 +16242,201 @@ var ThoughtsBlock = class {
|
|
|
15854
16242
|
}
|
|
15855
16243
|
};
|
|
15856
16244
|
|
|
16245
|
+
// src/ui/progress/tool_step_group.ts
|
|
16246
|
+
var OPEN_STATUSES = /* @__PURE__ */ new Set([
|
|
16247
|
+
TOOL_CALL_STATUS.PENDING,
|
|
16248
|
+
TOOL_CALL_STATUS.DEFERRED
|
|
16249
|
+
]);
|
|
16250
|
+
var RUNNING_SUBAGENT = `.tool-call-subagent > .subagent:is(${[
|
|
16251
|
+
SUBAGENT_PHASE.STARTED,
|
|
16252
|
+
SUBAGENT_PHASE.TOOL_CALL,
|
|
16253
|
+
SUBAGENT_PHASE.TOOL_RESULT
|
|
16254
|
+
].map((phase) => `[data-phase="${phase}"]`).join(", ")})`;
|
|
16255
|
+
var WATCHED_ATTRIBUTES = [
|
|
16256
|
+
"data-status",
|
|
16257
|
+
"data-asking",
|
|
16258
|
+
"data-phase",
|
|
16259
|
+
"data-agent"
|
|
16260
|
+
];
|
|
16261
|
+
var ToolStepGroup = class {
|
|
16262
|
+
element;
|
|
16263
|
+
#strings;
|
|
16264
|
+
#list;
|
|
16265
|
+
#head;
|
|
16266
|
+
#label;
|
|
16267
|
+
#meta;
|
|
16268
|
+
/** The steps, in order. Cards only ever join a group, so this is its list's children. */
|
|
16269
|
+
#steps = [];
|
|
16270
|
+
/** Whether the group has already opened itself for the current wait. */
|
|
16271
|
+
#openedForWait = false;
|
|
16272
|
+
constructor(strings) {
|
|
16273
|
+
this.#strings = strings;
|
|
16274
|
+
this.element = document.createElement("div");
|
|
16275
|
+
this.element.className = "tool-group";
|
|
16276
|
+
this.element.setAttribute("part", "tool-group");
|
|
16277
|
+
this.element.setAttribute("data-open", "false");
|
|
16278
|
+
this.#head = document.createElement("button");
|
|
16279
|
+
this.#head.type = "button";
|
|
16280
|
+
this.#head.className = "tool-group-head";
|
|
16281
|
+
this.#head.setAttribute("part", "tool-group-head");
|
|
16282
|
+
this.#head.setAttribute("aria-expanded", "false");
|
|
16283
|
+
const icon = document.createElement("span");
|
|
16284
|
+
icon.className = "tool-group-icon";
|
|
16285
|
+
icon.setAttribute("part", "tool-group-icon");
|
|
16286
|
+
icon.setAttribute("aria-hidden", "true");
|
|
16287
|
+
this.#label = document.createElement("span");
|
|
16288
|
+
this.#label.className = "tool-group-label";
|
|
16289
|
+
this.#label.setAttribute("part", "tool-group-label");
|
|
16290
|
+
this.#meta = document.createElement("span");
|
|
16291
|
+
this.#meta.className = "tool-group-meta";
|
|
16292
|
+
this.#meta.setAttribute("part", "tool-group-meta");
|
|
16293
|
+
const chevron = document.createElement("span");
|
|
16294
|
+
chevron.className = "tool-group-chevron";
|
|
16295
|
+
chevron.setAttribute("aria-hidden", "true");
|
|
16296
|
+
this.#head.append(icon, this.#label, this.#meta, chevron);
|
|
16297
|
+
this.#head.addEventListener("click", () => {
|
|
16298
|
+
this.setOpen(this.element.getAttribute("data-open") !== "true");
|
|
16299
|
+
});
|
|
16300
|
+
this.#list = document.createElement("div");
|
|
16301
|
+
this.#list.className = "tool-group-list";
|
|
16302
|
+
this.#list.setAttribute("part", "tool-group-list");
|
|
16303
|
+
this.element.append(this.#head, this.#list);
|
|
16304
|
+
new MutationObserver(() => {
|
|
16305
|
+
this.#refresh();
|
|
16306
|
+
}).observe(this.#list, {
|
|
16307
|
+
attributes: true,
|
|
16308
|
+
attributeFilter: [...WATCHED_ATTRIBUTES],
|
|
16309
|
+
subtree: true
|
|
16310
|
+
});
|
|
16311
|
+
}
|
|
16312
|
+
/**
|
|
16313
|
+
* Add a card's element as the group's next step, under the label the card
|
|
16314
|
+
* was built with.
|
|
16315
|
+
*
|
|
16316
|
+
* A step whose label an earlier step already has gets a repeat ordinal,
|
|
16317
|
+
* "Fill field (2)", in an element of its own beside the card's name. The
|
|
16318
|
+
* name itself is never rewritten, so a group flattened back into per-call
|
|
16319
|
+
* cards by a card display mode shows exactly the label the card was built
|
|
16320
|
+
* with, and the CSS hides the ordinal there.
|
|
16321
|
+
*/
|
|
16322
|
+
add(card, name) {
|
|
16323
|
+
const seen = this.#steps.filter((step) => step.name === name).length + 1;
|
|
16324
|
+
let label = name;
|
|
16325
|
+
if (seen > 1) {
|
|
16326
|
+
const repeat = document.createElement("span");
|
|
16327
|
+
repeat.className = "tool-call-repeat";
|
|
16328
|
+
repeat.setAttribute("part", "tool-card-repeat");
|
|
16329
|
+
repeat.textContent = fillUiString(this.#strings.toolStepRepeat, { n: seen });
|
|
16330
|
+
card.querySelector(".tool-call-name")?.after(repeat);
|
|
16331
|
+
label = `${name} ${repeat.textContent}`;
|
|
16332
|
+
}
|
|
16333
|
+
this.#steps.push({ element: card, name, label });
|
|
16334
|
+
this.#list.append(card);
|
|
16335
|
+
this.#refresh();
|
|
16336
|
+
}
|
|
16337
|
+
/** Show or hide the per-step cards. */
|
|
16338
|
+
setOpen(open) {
|
|
16339
|
+
this.element.setAttribute("data-open", String(open));
|
|
16340
|
+
this.#head.setAttribute("aria-expanded", String(open));
|
|
16341
|
+
}
|
|
16342
|
+
/**
|
|
16343
|
+
* Open the group now, for the wait that is about to start.
|
|
16344
|
+
*
|
|
16345
|
+
* The group opens itself from its mutation observer, which runs a tick after
|
|
16346
|
+
* the card is marked deferred. The approval prompt is drawn, and takes focus,
|
|
16347
|
+
* in the same tick as the mark, while the list is still out of the layout: the
|
|
16348
|
+
* focus is dropped and the scroll it would cause never happens. So the caller
|
|
16349
|
+
* that is about to draw the prompt opens the group first, and this marks the
|
|
16350
|
+
* wait as already answered for, so the observer's later refresh does not open
|
|
16351
|
+
* it again over a user who folded it.
|
|
16352
|
+
*/
|
|
16353
|
+
reveal() {
|
|
16354
|
+
this.#openedForWait = true;
|
|
16355
|
+
this.setOpen(true);
|
|
16356
|
+
}
|
|
16357
|
+
/**
|
|
16358
|
+
* The row's note for a running sub-agent, naming it, or `null` when no step
|
|
16359
|
+
* is delegating right now. Only a step that is itself still running counts.
|
|
16360
|
+
*/
|
|
16361
|
+
#delegation() {
|
|
16362
|
+
for (const { element } of this.#steps) {
|
|
16363
|
+
const panel = element.getAttribute("data-status") === TOOL_CALL_STATUS.PENDING ? element.querySelector(RUNNING_SUBAGENT) : null;
|
|
16364
|
+
if (panel !== null) {
|
|
16365
|
+
const agent = panel.getAttribute("data-agent");
|
|
16366
|
+
return agent === null ? this.#strings.subAgentWorking : fillUiString(this.#strings.subAgentDelegatedTo, { agent });
|
|
16367
|
+
}
|
|
16368
|
+
}
|
|
16369
|
+
return null;
|
|
16370
|
+
}
|
|
16371
|
+
#refresh() {
|
|
16372
|
+
const strings = this.#strings;
|
|
16373
|
+
const steps = this.#steps;
|
|
16374
|
+
const statuses = steps.map((step) => step.element.getAttribute("data-status") ?? "");
|
|
16375
|
+
const open = steps.filter((_2, i) => OPEN_STATUSES.has(statuses[i]));
|
|
16376
|
+
const count = (status) => statuses.filter((s) => s === status).length;
|
|
16377
|
+
const failed = count(TOOL_CALL_STATUS.ERROR);
|
|
16378
|
+
const declined = count(TOOL_CALL_STATUS.DECLINED);
|
|
16379
|
+
const deferred = count(TOOL_CALL_STATUS.DEFERRED);
|
|
16380
|
+
const asking = steps.filter((step) => step.element.hasAttribute("data-asking")).length;
|
|
16381
|
+
const waiting = deferred + asking;
|
|
16382
|
+
const total = steps.length;
|
|
16383
|
+
if (deferred > 0 && !this.#openedForWait) {
|
|
16384
|
+
this.#openedForWait = true;
|
|
16385
|
+
this.setOpen(true);
|
|
16386
|
+
} else if (deferred === 0) {
|
|
16387
|
+
this.#openedForWait = false;
|
|
16388
|
+
}
|
|
16389
|
+
let state = "done";
|
|
16390
|
+
if (waiting > 0) {
|
|
16391
|
+
state = "waiting";
|
|
16392
|
+
} else if (open.length > 0) {
|
|
16393
|
+
state = "running";
|
|
16394
|
+
} else if (failed > 0) {
|
|
16395
|
+
state = "error";
|
|
16396
|
+
}
|
|
16397
|
+
this.element.setAttribute("data-state", state);
|
|
16398
|
+
this.element.setAttribute("part", `tool-group tool-group-${state}`);
|
|
16399
|
+
this.element.setAttribute("data-count", String(total));
|
|
16400
|
+
const only = total === 1 ? steps[0] : void 0;
|
|
16401
|
+
if (only !== void 0) {
|
|
16402
|
+
this.#label.textContent = only.label;
|
|
16403
|
+
} else {
|
|
16404
|
+
const template = state === "waiting" ? strings.toolGroupSteps : state === "running" ? strings.toolGroupWorking : strings.toolGroupWorked;
|
|
16405
|
+
this.#label.textContent = fillUiString(template, { count: total });
|
|
16406
|
+
}
|
|
16407
|
+
const notes = [];
|
|
16408
|
+
const delegation = this.#delegation();
|
|
16409
|
+
const current = open[0];
|
|
16410
|
+
if (waiting > 0) {
|
|
16411
|
+
notes.push(fillUiString(strings.toolGroupWaiting, { count: waiting }));
|
|
16412
|
+
} else if (delegation !== null) {
|
|
16413
|
+
notes.push(delegation);
|
|
16414
|
+
} else if (current !== void 0 && total > 1) {
|
|
16415
|
+
notes.push(current.label);
|
|
16416
|
+
}
|
|
16417
|
+
if (failed > 0) {
|
|
16418
|
+
notes.push(fillUiString(strings.toolGroupFailed, { count: failed }));
|
|
16419
|
+
}
|
|
16420
|
+
if (declined > 0) {
|
|
16421
|
+
notes.push(fillUiString(strings.toolGroupDeclined, { count: declined }));
|
|
16422
|
+
}
|
|
16423
|
+
this.#meta.replaceChildren(
|
|
16424
|
+
...notes.map((text4) => {
|
|
16425
|
+
const note = document.createElement("span");
|
|
16426
|
+
note.className = "tool-group-note";
|
|
16427
|
+
note.textContent = text4;
|
|
16428
|
+
return note;
|
|
16429
|
+
})
|
|
16430
|
+
);
|
|
16431
|
+
this.#meta.hidden = notes.length === 0;
|
|
16432
|
+
}
|
|
16433
|
+
};
|
|
16434
|
+
|
|
16435
|
+
// src/ui/transcript/groups_tool_steps.ts
|
|
16436
|
+
function groupsToolSteps(mode) {
|
|
16437
|
+
return mode === TOOL_DISPLAY.GROUPED;
|
|
16438
|
+
}
|
|
16439
|
+
|
|
15857
16440
|
// src/ui/transcript/render_or_warn.ts
|
|
15858
16441
|
function renderOrWarn(render, subject) {
|
|
15859
16442
|
try {
|
|
@@ -15960,6 +16543,12 @@ var Transcript = class {
|
|
|
15960
16543
|
#toolCards = /* @__PURE__ */ new Map();
|
|
15961
16544
|
/** Card elements by call id, so a rendering handler can find its own card. */
|
|
15962
16545
|
#cardElements = /* @__PURE__ */ new Map();
|
|
16546
|
+
/**
|
|
16547
|
+
* Cards whose call is being run, by call id. A card leaves the awaiting ones
|
|
16548
|
+
* the moment its call is dispatched, and a handler that opens a prompt on its
|
|
16549
|
+
* own card is still running long after, so it is found here.
|
|
16550
|
+
*/
|
|
16551
|
+
#running = /* @__PURE__ */ new Map();
|
|
15963
16552
|
/**
|
|
15964
16553
|
* Call ids whose card was already settled from a streamed server-side result
|
|
15965
16554
|
* (`TOOL_CALL_RESULT`), so the post-run executeTool sweep doesn't overwrite
|
|
@@ -15980,6 +16569,24 @@ var Transcript = class {
|
|
|
15980
16569
|
// the answer group while a reasoning model thinks and collapsed once the
|
|
15981
16570
|
// answer's first text token arrives. `null` outside a reasoning turn.
|
|
15982
16571
|
#thoughts = null;
|
|
16572
|
+
/** The step group behind each group element, so a new card can find its run. */
|
|
16573
|
+
#stepGroups = /* @__PURE__ */ new WeakMap();
|
|
16574
|
+
/**
|
|
16575
|
+
* An empty comment after each step group that has rendered output, which
|
|
16576
|
+
* every later output is placed before, so a group's outputs come out in call
|
|
16577
|
+
* order. Every card of a round joins its group before any handler runs, so
|
|
16578
|
+
* placing each output straight after the group would put the newest first;
|
|
16579
|
+
* and a marker rather than the last output, because an output may be a
|
|
16580
|
+
* fragment, which leaves nothing behind to place the next one after.
|
|
16581
|
+
*/
|
|
16582
|
+
#groupEnds = /* @__PURE__ */ new WeakMap();
|
|
16583
|
+
/**
|
|
16584
|
+
* The step group element each placed output belongs to. A tool's own output
|
|
16585
|
+
* does not end its group: the next call joins the group above it. Without
|
|
16586
|
+
* that, replay -- which draws each restored call's output before the next
|
|
16587
|
+
* call's card -- would split a run the live stream drew as one group.
|
|
16588
|
+
*/
|
|
16589
|
+
#outputGroups = /* @__PURE__ */ new WeakMap();
|
|
15983
16590
|
constructor(host) {
|
|
15984
16591
|
this.#host = host;
|
|
15985
16592
|
}
|
|
@@ -16075,6 +16682,18 @@ var Transcript = class {
|
|
|
16075
16682
|
forgetCards() {
|
|
16076
16683
|
this.#serverSettled.clear();
|
|
16077
16684
|
this.#cardElements.clear();
|
|
16685
|
+
this.#running.clear();
|
|
16686
|
+
}
|
|
16687
|
+
/** Remember the card of a call being run, for {@link setAsking}. */
|
|
16688
|
+
holdRunning(callId, card) {
|
|
16689
|
+
this.#running.set(callId, card);
|
|
16690
|
+
}
|
|
16691
|
+
/**
|
|
16692
|
+
* Say whether a prompt is open on the card of a running call. A call id of
|
|
16693
|
+
* none, or one no card was held for, has no card to say it on.
|
|
16694
|
+
*/
|
|
16695
|
+
setAsking(callId, asking) {
|
|
16696
|
+
this.#running.get(callId)?.setAsking(asking);
|
|
16078
16697
|
}
|
|
16079
16698
|
/** Empty the list back to its empty-state region. The last half of wiping it. */
|
|
16080
16699
|
empty() {
|
|
@@ -16248,7 +16867,23 @@ var Transcript = class {
|
|
|
16248
16867
|
if (node === null) {
|
|
16249
16868
|
return;
|
|
16250
16869
|
}
|
|
16251
|
-
this.#cardElements.get(call.id)
|
|
16870
|
+
const anchor = this.#cardElements.get(call.id);
|
|
16871
|
+
const group = anchor?.closest(".tool-group");
|
|
16872
|
+
if (group === null || group === void 0) {
|
|
16873
|
+
anchor?.after(node);
|
|
16874
|
+
} else {
|
|
16875
|
+
let end = this.#groupEnds.get(group);
|
|
16876
|
+
if (end === void 0) {
|
|
16877
|
+
end = document.createComment("");
|
|
16878
|
+
group.after(end);
|
|
16879
|
+
this.#groupEnds.set(group, end);
|
|
16880
|
+
}
|
|
16881
|
+
const placed = node instanceof DocumentFragment ? [...node.children] : [node];
|
|
16882
|
+
end.before(node);
|
|
16883
|
+
for (const output of placed) {
|
|
16884
|
+
this.#outputGroups.set(output, group);
|
|
16885
|
+
}
|
|
16886
|
+
}
|
|
16252
16887
|
this.afterGrew();
|
|
16253
16888
|
}
|
|
16254
16889
|
/** Update the empty state and follow the foot, after the transcript grew. */
|
|
@@ -16276,11 +16911,49 @@ var Transcript = class {
|
|
|
16276
16911
|
formatPayload: (payload) => this.#host.formatToolPayload(payload)
|
|
16277
16912
|
});
|
|
16278
16913
|
this.#toolCards.set(call.id, card);
|
|
16279
|
-
this.
|
|
16914
|
+
if (groupsToolSteps(this.#host.toolDisplay())) {
|
|
16915
|
+
this.#stepGroup().add(card.element, summary);
|
|
16916
|
+
} else {
|
|
16917
|
+
this.ensureGroup().appendChild(card.element);
|
|
16918
|
+
}
|
|
16280
16919
|
this.updateEmptyState();
|
|
16281
16920
|
this.follow();
|
|
16282
16921
|
return card;
|
|
16283
16922
|
}
|
|
16923
|
+
/**
|
|
16924
|
+
* Open the step group ``card`` sits in, at once, ahead of a prompt about to be
|
|
16925
|
+
* drawn inside it. A no-op for a card drawn in a card display mode, which has
|
|
16926
|
+
* no group.
|
|
16927
|
+
*/
|
|
16928
|
+
revealStep(card) {
|
|
16929
|
+
const group = card.element.closest(".tool-group");
|
|
16930
|
+
(group === null ? void 0 : this.#stepGroups.get(group))?.reveal();
|
|
16931
|
+
}
|
|
16932
|
+
/**
|
|
16933
|
+
* The step group a new card joins. Consecutive cards share one, and so do
|
|
16934
|
+
* cards separated only by the group's own rendered output; anything else in
|
|
16935
|
+
* between (text, a confirmation, a question) starts the next.
|
|
16936
|
+
*
|
|
16937
|
+
* The pending dots are not skipped over: a tool call takes them down before
|
|
16938
|
+
* its card is drawn, so they are never what a card finds at the foot of the
|
|
16939
|
+
* turn.
|
|
16940
|
+
*/
|
|
16941
|
+
#stepGroup() {
|
|
16942
|
+
const answer = this.ensureGroup();
|
|
16943
|
+
const last = answer.lastElementChild;
|
|
16944
|
+
const existing = last === null ? void 0 : this.#stepGroups.get(this.#outputGroups.get(last) ?? last);
|
|
16945
|
+
if (existing !== void 0) {
|
|
16946
|
+
return existing;
|
|
16947
|
+
}
|
|
16948
|
+
const group = new ToolStepGroup(this.#host.strings());
|
|
16949
|
+
this.#stepGroups.set(group.element, group);
|
|
16950
|
+
if (last === null) {
|
|
16951
|
+
answer.prepend(group.element);
|
|
16952
|
+
} else {
|
|
16953
|
+
last.after(group.element);
|
|
16954
|
+
}
|
|
16955
|
+
return group;
|
|
16956
|
+
}
|
|
16284
16957
|
};
|
|
16285
16958
|
|
|
16286
16959
|
// src/core/activity_registry.ts
|
|
@@ -17429,8 +18102,13 @@ var RunHandlers = class {
|
|
|
17429
18102
|
* A handler table for one AG-UI client. Every table built for the current
|
|
17430
18103
|
* conversation draws into the same transcript and shares its bookkeeping, so
|
|
17431
18104
|
* a continuation run reports into the interaction the user is looking at.
|
|
18105
|
+
*
|
|
18106
|
+
* `threadId` is the thread the client was built for, named on the
|
|
18107
|
+
* run-finished detail. Taken here rather than read when the run settles,
|
|
18108
|
+
* because a stopped run settles after the reset that stopped it, when the
|
|
18109
|
+
* thread on screen is already the next one.
|
|
17432
18110
|
*/
|
|
17433
|
-
forClient() {
|
|
18111
|
+
forClient(threadId) {
|
|
17434
18112
|
const ledger = this.#ledger;
|
|
17435
18113
|
const attached = () => ledger === this.#ledger;
|
|
17436
18114
|
const { onSettled, ...drawing } = this.#tableFor(ledger);
|
|
@@ -17440,7 +18118,7 @@ var RunHandlers = class {
|
|
|
17440
18118
|
if (attached()) {
|
|
17441
18119
|
onSettled();
|
|
17442
18120
|
}
|
|
17443
|
-
this.#dispatchRunFinished(ledger);
|
|
18121
|
+
this.#dispatchRunFinished(ledger, threadId);
|
|
17444
18122
|
}
|
|
17445
18123
|
};
|
|
17446
18124
|
}
|
|
@@ -17593,7 +18271,7 @@ var RunHandlers = class {
|
|
|
17593
18271
|
* server is a fact about the run, and a name can appear on both sides across a
|
|
17594
18272
|
* conversation.
|
|
17595
18273
|
*/
|
|
17596
|
-
#dispatchRunFinished(ledger) {
|
|
18274
|
+
#dispatchRunFinished(ledger, threadId) {
|
|
17597
18275
|
const tools = ledger.tools.map(({ id, name }) => ({
|
|
17598
18276
|
name,
|
|
17599
18277
|
side: ledger.serverSettled.has(id) ? "server" : "client"
|
|
@@ -17604,7 +18282,7 @@ var RunHandlers = class {
|
|
|
17604
18282
|
ledger.invalidated.clear();
|
|
17605
18283
|
this.#host.element.dispatchEvent(
|
|
17606
18284
|
new CustomEvent(RUN_FINISHED_EVENT, {
|
|
17607
|
-
detail: { tools, invalidated },
|
|
18285
|
+
detail: { threadId, tools, invalidated },
|
|
17608
18286
|
bubbles: true,
|
|
17609
18287
|
composed: true
|
|
17610
18288
|
})
|
|
@@ -18423,6 +19101,11 @@ var AgUiChat = class extends HTMLElement {
|
|
|
18423
19101
|
* then a host's {@link sendMessage} waits for it rather than refusing.
|
|
18424
19102
|
*/
|
|
18425
19103
|
#restoreHold = null;
|
|
19104
|
+
/**
|
|
19105
|
+
* The thread the latest {@link THREAD_EVENT} reported, which the next one
|
|
19106
|
+
* names as the thread it replaced; `null` before the first.
|
|
19107
|
+
*/
|
|
19108
|
+
#shownThread = null;
|
|
18426
19109
|
/** The decision a run is suspended on, which a Stop abandons. */
|
|
18427
19110
|
#decision = new PendingDecision();
|
|
18428
19111
|
/**
|
|
@@ -18440,6 +19123,7 @@ var AgUiChat = class extends HTMLElement {
|
|
|
18440
19123
|
askUser: () => this.askUser,
|
|
18441
19124
|
askUserRenderer: () => this.askUserRenderer,
|
|
18442
19125
|
decision: this.#decision,
|
|
19126
|
+
setAsking: (callId, asking) => this.#transcript.setAsking(callId, asking),
|
|
18443
19127
|
ensureGroup: () => this.#transcript.ensureGroup(),
|
|
18444
19128
|
strings: () => this.#strings,
|
|
18445
19129
|
hidePending: () => this.#transcript.hidePending(),
|
|
@@ -18453,6 +19137,8 @@ var AgUiChat = class extends HTMLElement {
|
|
|
18453
19137
|
allowImages: () => this.allowImages,
|
|
18454
19138
|
follow: () => this.#transcript.follow()
|
|
18455
19139
|
});
|
|
19140
|
+
// This chat's place among the connected ones, which a free highlight ring reads.
|
|
19141
|
+
#chatRegistration = new ChatRegistration(this);
|
|
18456
19142
|
/**
|
|
18457
19143
|
* Which storage keys are this element's: the namespace it claims, the keys
|
|
18458
19144
|
* its layout preferences live under, and the built-in store scoped to them.
|
|
@@ -18492,6 +19178,7 @@ var AgUiChat = class extends HTMLElement {
|
|
|
18492
19178
|
resolveTool: (name) => this.#tools.resolve(name),
|
|
18493
19179
|
toolSummaries: () => this.toolSummaries,
|
|
18494
19180
|
serverSummary: (name) => this.#tools.summary(name),
|
|
19181
|
+
toolDisplay: () => this.toolDisplay,
|
|
18495
19182
|
// A thunk over the live property, not the property itself: the card keeps
|
|
18496
19183
|
// this for the life of the call, and the result region is filled when the
|
|
18497
19184
|
// tool settles -- which can be long after a host set the hook.
|
|
@@ -18699,7 +19386,8 @@ var AgUiChat = class extends HTMLElement {
|
|
|
18699
19386
|
},
|
|
18700
19387
|
cancelRun: () => this.#cancelRun(),
|
|
18701
19388
|
resetState: () => this.#resetState(),
|
|
18702
|
-
setRunning: (running) => this.#setRunning(running)
|
|
19389
|
+
setRunning: (running) => this.#setRunning(running),
|
|
19390
|
+
threadChanged: (threadId, reason) => this.#dispatchThread(threadId, reason)
|
|
18703
19391
|
});
|
|
18704
19392
|
}
|
|
18705
19393
|
/** Attributes the element reacts to after it has been connected. */
|
|
@@ -18963,18 +19651,23 @@ var AgUiChat = class extends HTMLElement {
|
|
|
18963
19651
|
}
|
|
18964
19652
|
/**
|
|
18965
19653
|
* How much detail tool-call cards show, from the `data-tool-display`
|
|
18966
|
-
* attribute (`minimal` / `inline` / `compact` / `full`).
|
|
19654
|
+
* attribute (`grouped` / `minimal` / `inline` / `compact` / `full`).
|
|
19655
|
+
* Defaults to `grouped`, for an absent attribute and for a value the
|
|
19656
|
+
* element does not know; `full` is the per-call card default before
|
|
19657
|
+
* `grouped` existed.
|
|
18967
19658
|
*
|
|
18968
|
-
*
|
|
18969
|
-
* restyles every card already in the
|
|
18970
|
-
*
|
|
19659
|
+
* The four card modes are applied by the shadow CSS from the attribute
|
|
19660
|
+
* itself, so changing between them restyles every card already in the
|
|
19661
|
+
* transcript. Whether calls fold into a step group is decided as each card
|
|
19662
|
+
* is built: switching to `grouped` folds only the calls drawn afterwards,
|
|
19663
|
+
* and switching away flattens the existing groups, again by CSS.
|
|
18971
19664
|
*/
|
|
18972
19665
|
get toolDisplay() {
|
|
18973
19666
|
const attr = this.getAttribute("data-tool-display");
|
|
18974
|
-
if (attr === TOOL_DISPLAY.INLINE || attr === TOOL_DISPLAY.MINIMAL || attr === TOOL_DISPLAY.COMPACT) {
|
|
19667
|
+
if (attr === TOOL_DISPLAY.INLINE || attr === TOOL_DISPLAY.MINIMAL || attr === TOOL_DISPLAY.COMPACT || attr === TOOL_DISPLAY.FULL) {
|
|
18975
19668
|
return attr;
|
|
18976
19669
|
}
|
|
18977
|
-
return TOOL_DISPLAY.
|
|
19670
|
+
return TOOL_DISPLAY.GROUPED;
|
|
18978
19671
|
}
|
|
18979
19672
|
set toolDisplay(value) {
|
|
18980
19673
|
this.setAttribute("data-tool-display", value);
|
|
@@ -19007,6 +19700,7 @@ var AgUiChat = class extends HTMLElement {
|
|
|
19007
19700
|
}
|
|
19008
19701
|
this.#connectedBefore = true;
|
|
19009
19702
|
this.#storage.claim();
|
|
19703
|
+
this.#chatRegistration.join();
|
|
19010
19704
|
this.#placement.restoreSize();
|
|
19011
19705
|
requestAnimationFrame(() => {
|
|
19012
19706
|
this.#placement.restoreLauncherPosition();
|
|
@@ -19044,7 +19738,7 @@ var AgUiChat = class extends HTMLElement {
|
|
|
19044
19738
|
this.#voice.wire();
|
|
19045
19739
|
this.#history.adoptActiveThread();
|
|
19046
19740
|
queueMicrotask(() => this.#startup());
|
|
19047
|
-
void this.#history.rehydrate();
|
|
19741
|
+
void this.#history.rehydrate(changed && held !== "" ? "rescope" : "restore");
|
|
19048
19742
|
if (changed) {
|
|
19049
19743
|
void this.#history.refreshDrawer();
|
|
19050
19744
|
}
|
|
@@ -19097,7 +19791,7 @@ var AgUiChat = class extends HTMLElement {
|
|
|
19097
19791
|
await Promise.all([
|
|
19098
19792
|
this.#tools.fetchCatalog(),
|
|
19099
19793
|
this.#skills.fetch(),
|
|
19100
|
-
this.#history.rehydrate()
|
|
19794
|
+
this.#history.rehydrate("restore")
|
|
19101
19795
|
]);
|
|
19102
19796
|
}
|
|
19103
19797
|
/**
|
|
@@ -19113,6 +19807,7 @@ var AgUiChat = class extends HTMLElement {
|
|
|
19113
19807
|
window.visualViewport?.removeEventListener("resize", this.#onViewportResize);
|
|
19114
19808
|
window.visualViewport?.removeEventListener("scroll", this.#onViewportResize);
|
|
19115
19809
|
this.#storage.release();
|
|
19810
|
+
this.#chatRegistration.leave();
|
|
19116
19811
|
this.#cancelRun();
|
|
19117
19812
|
this.#excerpts.detachPageOffer();
|
|
19118
19813
|
this.#attachments.tray?.dispose();
|
|
@@ -19260,6 +19955,26 @@ var AgUiChat = class extends HTMLElement {
|
|
|
19260
19955
|
get unread() {
|
|
19261
19956
|
return this.#unread;
|
|
19262
19957
|
}
|
|
19958
|
+
/**
|
|
19959
|
+
* The thread on screen; `null` before the element first connects.
|
|
19960
|
+
*
|
|
19961
|
+
* Only reads. `conversationStore.threadId()` mints and stores a thread when
|
|
19962
|
+
* the store points at none, so a host asking which conversation is showing
|
|
19963
|
+
* could start one; this never does. {@link THREAD_EVENT} says when it changes.
|
|
19964
|
+
*/
|
|
19965
|
+
get threadId() {
|
|
19966
|
+
const threadId = this.#history.threadId;
|
|
19967
|
+
return threadId === "" ? null : threadId;
|
|
19968
|
+
}
|
|
19969
|
+
/**
|
|
19970
|
+
* Whether an interaction is in flight: the composer's own state, the one that
|
|
19971
|
+
* shows Stop. It spans every tool round, a retry and a checkpoint
|
|
19972
|
+
* continuation as well as a send, which {@link SUBMIT_EVENT} alone does not.
|
|
19973
|
+
* Reflected as `data-running` on the element, for a host's CSS.
|
|
19974
|
+
*/
|
|
19975
|
+
get running() {
|
|
19976
|
+
return this.#running;
|
|
19977
|
+
}
|
|
19263
19978
|
/**
|
|
19264
19979
|
* Whether to mount collapsed.
|
|
19265
19980
|
*
|
|
@@ -19310,6 +20025,13 @@ var AgUiChat = class extends HTMLElement {
|
|
|
19310
20025
|
moveTo(corner, options = {}) {
|
|
19311
20026
|
return this.#placement.moveTo(corner, options);
|
|
19312
20027
|
}
|
|
20028
|
+
/**
|
|
20029
|
+
* Drop a size the user dragged, and its stored copy, so the placement's
|
|
20030
|
+
* default and the host's `--ag-ui-width` / `--ag-ui-height` apply again.
|
|
20031
|
+
*/
|
|
20032
|
+
resetSize() {
|
|
20033
|
+
this.#placement.resetSize();
|
|
20034
|
+
}
|
|
19313
20035
|
/** Flip the collapsed state. Bound to the built-in header toggle. */
|
|
19314
20036
|
toggleCollapsed() {
|
|
19315
20037
|
this.setCollapsed(!this.collapsed);
|
|
@@ -19379,7 +20101,7 @@ var AgUiChat = class extends HTMLElement {
|
|
|
19379
20101
|
this.#voice.dispose();
|
|
19380
20102
|
this.#voice.wire();
|
|
19381
20103
|
this.#history.adoptActiveThread();
|
|
19382
|
-
void this.#history.rehydrate();
|
|
20104
|
+
void this.#history.rehydrate("rescope");
|
|
19383
20105
|
void this.#history.refreshDrawer();
|
|
19384
20106
|
}
|
|
19385
20107
|
/**
|
|
@@ -19440,6 +20162,34 @@ var AgUiChat = class extends HTMLElement {
|
|
|
19440
20162
|
closeCheckpoints() {
|
|
19441
20163
|
this.#checkpoints.close();
|
|
19442
20164
|
}
|
|
20165
|
+
/**
|
|
20166
|
+
* Put a stored thread on screen, as picking it in the conversation list does,
|
|
20167
|
+
* for a host that lists conversations in its own chrome.
|
|
20168
|
+
*
|
|
20169
|
+
* Resolves once the thread has been replayed, when {@link THREAD_EVENT} has
|
|
20170
|
+
* fired. **A run in flight is cancelled**, as the list and {@link newChat} do;
|
|
20171
|
+
* a host that would rather wait reads {@link running} first. The thread
|
|
20172
|
+
* already on screen is left alone, and so is everything before the element
|
|
20173
|
+
* connects, since until then it has no store to read the thread from.
|
|
20174
|
+
*/
|
|
20175
|
+
async switchThread(threadId) {
|
|
20176
|
+
if (!this.#connected) {
|
|
20177
|
+
return;
|
|
20178
|
+
}
|
|
20179
|
+
await this.#history.switchThread(threadId);
|
|
20180
|
+
}
|
|
20181
|
+
/**
|
|
20182
|
+
* Delete a stored thread, as the conversation list's delete does. Deleting the
|
|
20183
|
+
* thread on screen cancels its run and puts a fresh thread in its place, and
|
|
20184
|
+
* {@link THREAD_EVENT} reports it; deleting another leaves the screen alone.
|
|
20185
|
+
* Does nothing before the element connects.
|
|
20186
|
+
*/
|
|
20187
|
+
deleteThread(threadId) {
|
|
20188
|
+
if (!this.#connected) {
|
|
20189
|
+
return;
|
|
20190
|
+
}
|
|
20191
|
+
this.#history.deleteThread(threadId);
|
|
20192
|
+
}
|
|
19443
20193
|
/**
|
|
19444
20194
|
* Open the checkpoints panel, or close it if it is already open — what the
|
|
19445
20195
|
* built-in ⭯ button does, because a control that opens a panel is read as the
|
|
@@ -19472,6 +20222,7 @@ var AgUiChat = class extends HTMLElement {
|
|
|
19472
20222
|
this.#history.startThread();
|
|
19473
20223
|
this.#setRunning(false);
|
|
19474
20224
|
this.#setUnread(0);
|
|
20225
|
+
this.#dispatchThread(this.#history.threadId, "new");
|
|
19475
20226
|
if (!this.collapsed) {
|
|
19476
20227
|
this.#input.focus({ preventScroll: true });
|
|
19477
20228
|
}
|
|
@@ -19664,6 +20415,8 @@ var AgUiChat = class extends HTMLElement {
|
|
|
19664
20415
|
},
|
|
19665
20416
|
onFilesPicked: () => this.#attachments.onFilesPicked()
|
|
19666
20417
|
});
|
|
20418
|
+
const aboveComposer = document.createElement("slot");
|
|
20419
|
+
aboveComposer.name = "above-composer";
|
|
19667
20420
|
const footer = document.createElement("slot");
|
|
19668
20421
|
footer.name = "footer";
|
|
19669
20422
|
this.#messagesWrap.className = "messages-wrap";
|
|
@@ -19676,6 +20429,7 @@ var AgUiChat = class extends HTMLElement {
|
|
|
19676
20429
|
this.#composerHint,
|
|
19677
20430
|
this.#queuedRow,
|
|
19678
20431
|
this.#attachSlot,
|
|
20432
|
+
aboveComposer,
|
|
19679
20433
|
inputRow,
|
|
19680
20434
|
footer,
|
|
19681
20435
|
this.#drawer.element,
|
|
@@ -19843,6 +20597,21 @@ var AgUiChat = class extends HTMLElement {
|
|
|
19843
20597
|
this.#sending = null;
|
|
19844
20598
|
this.#history.stopContinuation();
|
|
19845
20599
|
}
|
|
20600
|
+
/**
|
|
20601
|
+
* Say the conversation on screen changed: {@link THREAD_EVENT}.
|
|
20602
|
+
*
|
|
20603
|
+
* The thread it replaced is the one last reported, rather than the one the
|
|
20604
|
+
* element last pointed at: a switch superseded before it replayed never drew
|
|
20605
|
+
* its thread, so naming it as the previous one left a host's own list
|
|
20606
|
+
* marking a thread that was never shown and still marking the one that was.
|
|
20607
|
+
*/
|
|
20608
|
+
#dispatchThread(threadId, reason) {
|
|
20609
|
+
const detail = { threadId, previousThreadId: this.#shownThread, reason };
|
|
20610
|
+
this.#shownThread = threadId;
|
|
20611
|
+
this.dispatchEvent(
|
|
20612
|
+
new CustomEvent(THREAD_EVENT, { detail, bubbles: true, composed: true })
|
|
20613
|
+
);
|
|
20614
|
+
}
|
|
19846
20615
|
/**
|
|
19847
20616
|
* Swap the composer button between Send (idle) and Stop (running).
|
|
19848
20617
|
*
|
|
@@ -19860,6 +20629,7 @@ var AgUiChat = class extends HTMLElement {
|
|
|
19860
20629
|
this.#send.title = label;
|
|
19861
20630
|
this.#send.setAttribute("aria-label", label);
|
|
19862
20631
|
this.#send.dataset["state"] = running ? "running" : "idle";
|
|
20632
|
+
this.toggleAttribute("data-running", running);
|
|
19863
20633
|
if (settled) {
|
|
19864
20634
|
this.#flushQueued();
|
|
19865
20635
|
}
|
|
@@ -20148,7 +20918,7 @@ var AgUiChat = class extends HTMLElement {
|
|
|
20148
20918
|
});
|
|
20149
20919
|
return new AgUiClient({
|
|
20150
20920
|
agent,
|
|
20151
|
-
handlers: this.#runHandlers.forClient(),
|
|
20921
|
+
handlers: this.#runHandlers.forClient(threadId),
|
|
20152
20922
|
getTools: () => this.#tools.advertise(),
|
|
20153
20923
|
getContext: () => this.#dispatch.buildContext(),
|
|
20154
20924
|
executeTool: (call) => this.#dispatch.execute(call),
|
|
@@ -20342,7 +21112,7 @@ function setControlValue(el2, value) {
|
|
|
20342
21112
|
}
|
|
20343
21113
|
|
|
20344
21114
|
// src/version.ts
|
|
20345
|
-
var VERSION = "0.
|
|
21115
|
+
var VERSION = "0.47.0";
|
|
20346
21116
|
export {
|
|
20347
21117
|
ATTACHMENT_EVENT,
|
|
20348
21118
|
AgUiChat,
|
|
@@ -20375,6 +21145,7 @@ export {
|
|
|
20375
21145
|
SUBMIT_EVENT,
|
|
20376
21146
|
SUGGESTIONS_ACTIVITY_TYPE,
|
|
20377
21147
|
SessionStorageStore,
|
|
21148
|
+
THREAD_EVENT,
|
|
20378
21149
|
TOGGLE_EVENT,
|
|
20379
21150
|
TOOL_CALL_STATUS,
|
|
20380
21151
|
TOOL_DISPLAY,
|