@artooi/ag-ui-web-component 0.17.0 → 0.18.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.
@@ -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
@@ -450,6 +450,9 @@ var DEFAULT_UI_STRINGS = {
450
450
  collapse: "Collapse",
451
451
  expand: "Expand",
452
452
  toggleTheme: "Toggle theme",
453
+ copyCode: "Copy",
454
+ copied: "Copied",
455
+ copyFailed: "Copy failed",
453
456
  checkpoints: "Continue a run",
454
457
  noCheckpoints: "Nothing to continue yet.",
455
458
  resumeRun: "Resume",
@@ -531,12 +534,12 @@ function mergeUiStrings(overrides) {
531
534
 
532
535
  // src/ui/approval_card.ts
533
536
  function actionButton(modifier, label) {
534
- const button = document.createElement("button");
535
- button.type = "button";
536
- button.className = `approval-btn approval-btn--${modifier}`;
537
- button.setAttribute("part", `approval-button approval-${modifier}`);
538
- button.textContent = label;
539
- return button;
537
+ const button2 = document.createElement("button");
538
+ button2.type = "button";
539
+ button2.className = `approval-btn approval-btn--${modifier}`;
540
+ button2.setAttribute("part", `approval-button approval-${modifier}`);
541
+ button2.textContent = label;
542
+ return button2;
540
543
  }
541
544
  function requestApproval(host, request, options = {}) {
542
545
  const strings = options.strings ?? DEFAULT_UI_STRINGS;
@@ -583,6 +586,55 @@ function requestApproval(host, request, options = {}) {
583
586
  });
584
587
  }
585
588
 
589
+ // src/ui/attach_copy_buttons.ts
590
+ var CONFIRM_MS = 1500;
591
+ function attachCopyButtons(root, strings) {
592
+ for (const pre of Array.from(root.querySelectorAll("pre"))) {
593
+ const code = pre.querySelector("code");
594
+ if (code === null || pre.querySelector(".code-copy") !== null) {
595
+ continue;
596
+ }
597
+ pre.classList.add("has-copy");
598
+ pre.append(button(code, strings));
599
+ }
600
+ }
601
+ function button(code, strings) {
602
+ const text2 = code.textContent;
603
+ const copy = document.createElement("button");
604
+ copy.type = "button";
605
+ copy.className = "code-copy";
606
+ copy.setAttribute("part", "code-copy");
607
+ copy.textContent = strings.copyCode;
608
+ copy.title = strings.copyCode;
609
+ copy.setAttribute("aria-label", strings.copyCode);
610
+ copy.addEventListener("click", () => {
611
+ void writeText(text2).then((ok) => {
612
+ confirm(copy, ok ? strings.copied : strings.copyFailed, strings);
613
+ });
614
+ });
615
+ return copy;
616
+ }
617
+ async function writeText(text2) {
618
+ const clipboard = navigator.clipboard;
619
+ if (clipboard === void 0) {
620
+ return false;
621
+ }
622
+ try {
623
+ await clipboard.writeText(text2);
624
+ return true;
625
+ } catch {
626
+ return false;
627
+ }
628
+ }
629
+ function confirm(copy, message, strings) {
630
+ copy.textContent = message;
631
+ copy.dataset["state"] = message === strings.copied ? "copied" : "failed";
632
+ setTimeout(() => {
633
+ copy.textContent = strings.copyCode;
634
+ delete copy.dataset["state"];
635
+ }, CONFIRM_MS);
636
+ }
637
+
586
638
  // src/ui/attachment_chips.ts
587
639
  function renderAttachmentChips(refs) {
588
640
  const list = document.createElement("div");
@@ -885,6 +937,8 @@ var CheckpointMenu = class {
885
937
  #onPick;
886
938
  #list;
887
939
  #heading;
940
+ /** What had focus before the panel opened, restored on close. */
941
+ #lastFocused = null;
888
942
  #strings;
889
943
  #runs = [];
890
944
  constructor(onPick, strings = DEFAULT_UI_STRINGS) {
@@ -895,6 +949,7 @@ var CheckpointMenu = class {
895
949
  this.element.setAttribute("part", "checkpoints");
896
950
  this.element.setAttribute("role", "dialog");
897
951
  this.element.setAttribute("aria-label", strings.checkpoints);
952
+ this.element.tabIndex = -1;
898
953
  this.element.hidden = true;
899
954
  const header = document.createElement("div");
900
955
  header.className = "checkpoints-header";
@@ -908,12 +963,7 @@ var CheckpointMenu = class {
908
963
  this.#list.className = "checkpoints-list";
909
964
  this.#list.setAttribute("part", "checkpoints-list");
910
965
  this.element.append(header, this.#list);
911
- this.element.addEventListener("keydown", (event) => {
912
- if (event.key === "Escape") {
913
- event.stopPropagation();
914
- this.close();
915
- }
916
- });
966
+ this.element.addEventListener("keydown", (event) => this.#onKeydown(event));
917
967
  }
918
968
  /** Replace the rows. The host passes only `continuable` runs. */
919
969
  setRuns(runs) {
@@ -928,10 +978,52 @@ var CheckpointMenu = class {
928
978
  this.#render();
929
979
  }
930
980
  open() {
981
+ if (this.open_) {
982
+ return;
983
+ }
984
+ this.#lastFocused = this.#activeElement();
931
985
  this.element.hidden = false;
986
+ (this.#focusables()[0] ?? this.element).focus();
932
987
  }
933
988
  close() {
989
+ if (!this.open_) {
990
+ return;
991
+ }
934
992
  this.element.hidden = true;
993
+ this.#lastFocused?.focus();
994
+ this.#lastFocused = null;
995
+ }
996
+ /** The focused element within this panel's root (shadow-aware). */
997
+ #activeElement() {
998
+ return this.element.getRootNode().activeElement;
999
+ }
1000
+ /** The panel's tabbable controls, in document order. */
1001
+ #focusables() {
1002
+ return Array.from(this.element.querySelectorAll("button, [tabindex]")).filter(
1003
+ (el) => !el.hidden
1004
+ );
1005
+ }
1006
+ /** Escape closes; Tab is trapped so focus cannot wander behind the dialog. */
1007
+ #onKeydown(event) {
1008
+ if (event.key === "Escape") {
1009
+ event.stopPropagation();
1010
+ this.close();
1011
+ return;
1012
+ }
1013
+ if (event.key !== "Tab") {
1014
+ return;
1015
+ }
1016
+ const focusables = this.#focusables();
1017
+ const first = focusables[0];
1018
+ const last = focusables[focusables.length - 1];
1019
+ const active = this.#activeElement();
1020
+ if (event.shiftKey && active === first) {
1021
+ event.preventDefault();
1022
+ last?.focus();
1023
+ } else if (!event.shiftKey && active === last) {
1024
+ event.preventDefault();
1025
+ first?.focus();
1026
+ }
935
1027
  }
936
1028
  get open_() {
937
1029
  return !this.element.hidden;
@@ -975,27 +1067,27 @@ var CheckpointMenu = class {
975
1067
  return row;
976
1068
  }
977
1069
  #action(runId, verb, label) {
978
- const button = document.createElement("button");
979
- button.type = "button";
980
- button.className = `checkpoint-action checkpoint-${verb}`;
981
- button.setAttribute("part", `checkpoint-action checkpoint-${verb}`);
982
- button.textContent = label;
983
- button.addEventListener("click", () => {
1070
+ const button2 = document.createElement("button");
1071
+ button2.type = "button";
1072
+ button2.className = `checkpoint-action checkpoint-${verb}`;
1073
+ button2.setAttribute("part", `checkpoint-action checkpoint-${verb}`);
1074
+ button2.textContent = label;
1075
+ button2.addEventListener("click", () => {
984
1076
  this.close();
985
1077
  this.#onPick(runId, verb);
986
1078
  });
987
- return button;
1079
+ return button2;
988
1080
  }
989
1081
  };
990
1082
 
991
1083
  // src/ui/confirmation_card.ts
992
1084
  function actionButton2(modifier, label) {
993
- const button = document.createElement("button");
994
- button.type = "button";
995
- button.className = `confirm-btn confirm-btn--${modifier}`;
996
- button.setAttribute("part", `confirm-button confirm-${modifier}`);
997
- button.textContent = label;
998
- return button;
1085
+ const button2 = document.createElement("button");
1086
+ button2.type = "button";
1087
+ button2.className = `confirm-btn confirm-btn--${modifier}`;
1088
+ button2.setAttribute("part", `confirm-button confirm-${modifier}`);
1089
+ button2.textContent = label;
1090
+ return button2;
999
1091
  }
1000
1092
  function requestConfirmation(host, request, options = {}) {
1001
1093
  const strings = options.strings ?? DEFAULT_UI_STRINGS;
@@ -1018,7 +1110,7 @@ function requestConfirmation(host, request, options = {}) {
1018
1110
  actions.className = "confirm-actions";
1019
1111
  actions.setAttribute("part", "confirm-actions");
1020
1112
  const cancel = actionButton2("cancel", strings.cancel);
1021
- const confirm = actionButton2("confirm", strings.confirm);
1113
+ const confirm2 = actionButton2("confirm", strings.confirm);
1022
1114
  let settled = false;
1023
1115
  const close = (accepted) => {
1024
1116
  if (settled) {
@@ -1026,21 +1118,21 @@ function requestConfirmation(host, request, options = {}) {
1026
1118
  }
1027
1119
  settled = true;
1028
1120
  cancel.disabled = true;
1029
- confirm.disabled = true;
1121
+ confirm2.disabled = true;
1030
1122
  card.setAttribute("data-resolved", accepted ? "confirmed" : "declined");
1031
1123
  resolve(accepted);
1032
1124
  };
1033
1125
  cancel.addEventListener("click", () => close(false));
1034
- confirm.addEventListener("click", () => close(true));
1126
+ confirm2.addEventListener("click", () => close(true));
1035
1127
  options.signal?.addEventListener("abort", () => close(false), { once: true });
1036
- actions.append(cancel, confirm);
1128
+ actions.append(cancel, confirm2);
1037
1129
  card.append(body, args, actions);
1038
1130
  host.appendChild(card);
1039
1131
  if (options.signal?.aborted === true) {
1040
1132
  close(false);
1041
1133
  return;
1042
1134
  }
1043
- confirm.focus();
1135
+ confirm2.focus();
1044
1136
  });
1045
1137
  }
1046
1138
 
@@ -4193,13 +4285,13 @@ var SkillsMenu = class {
4193
4285
  const chipSkills = this.#chipsEnabled ? this.#skills.filter((skill) => skill.chip === true) : [];
4194
4286
  this.chips.hidden = chipSkills.length === 0;
4195
4287
  for (const skill of chipSkills) {
4196
- const button = document.createElement("button");
4197
- button.type = "button";
4198
- button.className = "skill-chip";
4199
- button.setAttribute("part", "skill-chip");
4200
- button.textContent = skill.title;
4201
- button.addEventListener("click", () => this.#pick(skill));
4202
- this.chips.appendChild(button);
4288
+ const button2 = document.createElement("button");
4289
+ button2.type = "button";
4290
+ button2.className = "skill-chip";
4291
+ button2.setAttribute("part", "skill-chip");
4292
+ button2.textContent = skill.title;
4293
+ button2.addEventListener("click", () => this.#pick(skill));
4294
+ this.chips.appendChild(button2);
4203
4295
  }
4204
4296
  }
4205
4297
  #renderPalette() {
@@ -4740,6 +4832,52 @@ var STYLES = `
4740
4832
  padding: 0;
4741
4833
  }
4742
4834
 
4835
+ /* The copy button sits inside the block, so it scrolls with wide code rather
4836
+ than floating over the bubble. Positioning is on the pre; the button only
4837
+ appears once one has been attached. */
4838
+ .message--assistant pre.has-copy {
4839
+ position: relative;
4840
+ }
4841
+
4842
+ .code-copy {
4843
+ position: absolute;
4844
+ top: 4px;
4845
+ right: 4px;
4846
+ padding: 2px 8px;
4847
+ font: inherit;
4848
+ font-size: 0.75em;
4849
+ line-height: 1.6;
4850
+ color: var(--ag-ui-muted);
4851
+ background: var(--ag-ui-surface);
4852
+ border: 1px solid var(--ag-ui-border);
4853
+ border-radius: 4px;
4854
+ cursor: pointer;
4855
+ opacity: 0;
4856
+ transition: opacity 0.12s ease;
4857
+ }
4858
+
4859
+ /* Revealed on hover or keyboard focus. Focus matters as much as hover here:
4860
+ hidden-until-hover is invisible to a keyboard user otherwise. */
4861
+ .message--assistant pre.has-copy:hover .code-copy,
4862
+ .code-copy:focus-visible {
4863
+ opacity: 1;
4864
+ }
4865
+
4866
+ .code-copy:hover {
4867
+ color: var(--ag-ui-text);
4868
+ background: var(--ag-ui-hover);
4869
+ }
4870
+
4871
+ .code-copy[data-state="copied"] {
4872
+ opacity: 1;
4873
+ color: var(--ag-ui-text);
4874
+ }
4875
+
4876
+ .code-copy[data-state="failed"] {
4877
+ opacity: 1;
4878
+ color: var(--ag-ui-danger, var(--ag-ui-text));
4879
+ }
4880
+
4743
4881
  .message--assistant blockquote {
4744
4882
  padding-left: 10px;
4745
4883
  border-left: 3px solid var(--ag-ui-border);
@@ -6053,9 +6191,9 @@ var ThreadDrawer = class {
6053
6191
  }
6054
6192
  /** Swap a row for an inline "Delete? [Delete] [Cancel]" confirm. */
6055
6193
  #confirmDelete(row, meta) {
6056
- const confirm = document.createElement("div");
6057
- confirm.className = "drawer-confirm";
6058
- confirm.setAttribute("part", "drawer-confirm");
6194
+ const confirm2 = document.createElement("div");
6195
+ confirm2.className = "drawer-confirm";
6196
+ confirm2.setAttribute("part", "drawer-confirm");
6059
6197
  const label = document.createElement("span");
6060
6198
  label.className = "drawer-confirm-label";
6061
6199
  label.setAttribute("part", "drawer-confirm-label");
@@ -6072,8 +6210,8 @@ var ThreadDrawer = class {
6072
6210
  no.setAttribute("part", "drawer-confirm-no");
6073
6211
  no.textContent = this.#strings.cancel;
6074
6212
  no.addEventListener("click", () => this.#renderList());
6075
- confirm.append(label, yes, no);
6076
- row.replaceChildren(confirm);
6213
+ confirm2.append(label, yes, no);
6214
+ row.replaceChildren(confirm2);
6077
6215
  }
6078
6216
  };
6079
6217
 
@@ -7647,6 +7785,22 @@ var AgUiChat = class extends HTMLElement {
7647
7785
  this.#attachTray?.dispose();
7648
7786
  this.#voice?.dispose();
7649
7787
  }
7788
+ /**
7789
+ * Read an opt-in flag attribute the way HTML reads a boolean attribute.
7790
+ *
7791
+ * Present means on — bare (`data-prompt-chips`), empty
7792
+ * (`data-prompt-chips=""`) or any value except the literal `"false"`. These
7793
+ * were compared against the string `"true"`, so writing the attribute bare —
7794
+ * the spelling every native boolean attribute uses, and the one a reader
7795
+ * reaches for first — silently *disabled* the feature it names, with nothing
7796
+ * to indicate why the chips never appeared.
7797
+ *
7798
+ * `="false"` still turns it off, so an explicit opt-out keeps working.
7799
+ */
7800
+ #flag(name) {
7801
+ const value = this.getAttribute(name);
7802
+ return value !== null && value !== "false";
7803
+ }
7650
7804
  /** Parse the inline `data-strings` JSON overrides (empty when absent/malformed). */
7651
7805
  #readStringOverrides() {
7652
7806
  const raw = this.getAttribute("data-strings");
@@ -7827,8 +7981,8 @@ Use the read_attachment tool with an id to read a file's contents.`
7827
7981
  }
7828
7982
  /** Wire the skill surfaces: opt-in flags, embedded catalog, optional fetch. */
7829
7983
  #initSkills() {
7830
- this.#skillsMenu.enableChips(this.getAttribute("data-prompt-chips") === "true");
7831
- this.#skillsMenu.enableSlash(this.getAttribute("data-slash-commands") === "true");
7984
+ this.#skillsMenu.enableChips(this.#flag("data-prompt-chips"));
7985
+ this.#skillsMenu.enableSlash(this.#flag("data-slash-commands"));
7832
7986
  this.#embedSkills = this.#readEmbeddedSkills();
7833
7987
  this.#recomputeSkills();
7834
7988
  void this.#fetchSkills();
@@ -8169,6 +8323,7 @@ Use the read_attachment tool with an id to read a file's contents.`
8169
8323
  bubble.setAttribute("part", `message message-${role}`);
8170
8324
  if (role === MESSAGE_ROLE.ASSISTANT) {
8171
8325
  bubble.innerHTML = renderMarkdown(content, { allowImages: this.allowImages });
8326
+ attachCopyButtons(bubble, this.#strings);
8172
8327
  this.#ensureGroup().appendChild(bubble);
8173
8328
  } else {
8174
8329
  this.#currentGroup = null;
@@ -8325,14 +8480,14 @@ Use the read_attachment tool with an id to read a file's contents.`
8325
8480
  }
8326
8481
  /** Build a header control button (icon glyph + localized title/aria). */
8327
8482
  #headerButton(modifier, label, glyph) {
8328
- const button = document.createElement("button");
8329
- button.type = "button";
8330
- button.className = `header-btn header-btn--${modifier}`;
8331
- button.setAttribute("part", `header-button ${modifier}-button`);
8332
- button.title = label;
8333
- button.setAttribute("aria-label", label);
8334
- button.textContent = glyph;
8335
- return button;
8483
+ const button2 = document.createElement("button");
8484
+ button2.type = "button";
8485
+ button2.className = `header-btn header-btn--${modifier}`;
8486
+ button2.setAttribute("part", `header-button ${modifier}-button`);
8487
+ button2.title = label;
8488
+ button2.setAttribute("aria-label", label);
8489
+ button2.textContent = glyph;
8490
+ return button2;
8336
8491
  }
8337
8492
  /**
8338
8493
  * An icon holder wrapping a `<slot>` so a host can project custom markup; with
@@ -8676,6 +8831,7 @@ Use the read_attachment tool with an id to read a file's contents.`
8676
8831
  if (this.#streamDeltas <= 1) {
8677
8832
  this.#revealWords(bubble);
8678
8833
  }
8834
+ attachCopyButtons(bubble, this.#strings);
8679
8835
  this.#streamingBubble = null;
8680
8836
  },
8681
8837
  onToolCall: (call) => {
@@ -8903,7 +9059,7 @@ function setControlValue(el, value) {
8903
9059
  }
8904
9060
 
8905
9061
  // src/version.ts
8906
- var VERSION = "0.17.0";
9062
+ var VERSION = "0.18.0";
8907
9063
  export {
8908
9064
  ATTACHMENT_EVENT,
8909
9065
  AgUiChat,