@aparte/core 0.10.0 → 0.11.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.
Files changed (82) hide show
  1. package/dist/client/aparte-client.d.ts +54 -33
  2. package/dist/client/aparte-client.d.ts.map +1 -1
  3. package/dist/client/stream-adapter.d.ts +6 -1
  4. package/dist/client/stream-adapter.d.ts.map +1 -1
  5. package/dist/components/bubble/aparte-chat-bubble.d.ts +25 -4
  6. package/dist/components/bubble/aparte-chat-bubble.d.ts.map +1 -1
  7. package/dist/components/chat/aparte-chat.d.ts +8 -4
  8. package/dist/components/chat/aparte-chat.d.ts.map +1 -1
  9. package/dist/components/composer/aparte-composer-action.d.ts +5 -5
  10. package/dist/components/composer/aparte-composer-add-attachment.d.ts +5 -4
  11. package/dist/components/composer/aparte-composer-add-attachment.d.ts.map +1 -1
  12. package/dist/components/composer/aparte-composer-attachments.d.ts +5 -3
  13. package/dist/components/composer/aparte-composer-attachments.d.ts.map +1 -1
  14. package/dist/components/composer/aparte-composer-cancel.d.ts +2 -2
  15. package/dist/components/composer/aparte-composer-input.d.ts +8 -5
  16. package/dist/components/composer/aparte-composer-input.d.ts.map +1 -1
  17. package/dist/components/composer/aparte-composer-send.d.ts +2 -2
  18. package/dist/components/composer/aparte-composer-toolbar.d.ts +3 -3
  19. package/dist/components/composer/aparte-composer.d.ts +54 -10
  20. package/dist/components/composer/aparte-composer.d.ts.map +1 -1
  21. package/dist/components/conversation-list/aparte-conversation-list.d.ts +19 -12
  22. package/dist/components/conversation-list/aparte-conversation-list.d.ts.map +1 -1
  23. package/dist/components/elicitation/aparte-elicitation.d.ts +12 -0
  24. package/dist/components/elicitation/aparte-elicitation.d.ts.map +1 -1
  25. package/dist/components/status/aparte-chat-status.d.ts +9 -0
  26. package/dist/components/status/aparte-chat-status.d.ts.map +1 -1
  27. package/dist/components/viewport/aparte-chat-viewport.d.ts +15 -4
  28. package/dist/components/viewport/aparte-chat-viewport.d.ts.map +1 -1
  29. package/dist/config/aparte-config.d.ts +20 -1
  30. package/dist/config/aparte-config.d.ts.map +1 -1
  31. package/dist/config/locale.d.ts +43 -0
  32. package/dist/config/locale.d.ts.map +1 -1
  33. package/dist/custom-elements.json +8517 -7601
  34. package/dist/elicitation/approval-panel.d.ts +42 -0
  35. package/dist/elicitation/approval-panel.d.ts.map +1 -0
  36. package/dist/elicitation/index.d.ts +4 -1
  37. package/dist/elicitation/index.d.ts.map +1 -1
  38. package/dist/elicitation/panel.d.ts +1 -1
  39. package/dist/elicitation/panel.d.ts.map +1 -1
  40. package/dist/elicitation/types.d.ts +116 -9
  41. package/dist/elicitation/types.d.ts.map +1 -1
  42. package/dist/generated/element-attributes.d.ts +173 -0
  43. package/dist/generated/element-attributes.d.ts.map +1 -0
  44. package/dist/index.css +615 -92
  45. package/dist/index.d.ts +3 -3
  46. package/dist/index.d.ts.map +1 -1
  47. package/dist/index.js +341 -254
  48. package/dist/index.js.map +1 -1
  49. package/dist/index.node.d.ts +3 -3
  50. package/dist/index.node.d.ts.map +1 -1
  51. package/dist/index.node.js +46 -44
  52. package/dist/index.node.js.map +1 -1
  53. package/dist/interop/element-props.d.ts +26 -1
  54. package/dist/interop/element-props.d.ts.map +1 -1
  55. package/dist/{index-BnKBciDG.js → is-awaiting-reply-Cb7H3YfN.js} +1448 -1544
  56. package/dist/is-awaiting-reply-Cb7H3YfN.js.map +1 -0
  57. package/dist/primitives/select/aparte-optgroup.d.ts +3 -0
  58. package/dist/primitives/select/aparte-optgroup.d.ts.map +1 -1
  59. package/dist/primitives/select/aparte-option.d.ts +1 -0
  60. package/dist/primitives/select/aparte-option.d.ts.map +1 -1
  61. package/dist/primitives/select/aparte-select.d.ts +22 -18
  62. package/dist/primitives/select/aparte-select.d.ts.map +1 -1
  63. package/dist/renderers/segment-renderers.d.ts.map +1 -1
  64. package/dist/renderers/segments/artifact/card.d.ts.map +1 -1
  65. package/dist/renderers/segments/pipeline-waiting.d.ts.map +1 -1
  66. package/dist/renderers/segments/tool-call.d.ts.map +1 -1
  67. package/dist/types/element-attributes.d.ts +42 -0
  68. package/dist/types/element-attributes.d.ts.map +1 -0
  69. package/dist/types/event-map.d.ts +1 -2
  70. package/dist/types/event-map.d.ts.map +1 -1
  71. package/dist/types/index.d.ts +3 -2
  72. package/dist/types/index.d.ts.map +1 -1
  73. package/dist/types/segments.d.ts +1 -8
  74. package/dist/types/segments.d.ts.map +1 -1
  75. package/dist/types/tools.d.ts +15 -21
  76. package/dist/types/tools.d.ts.map +1 -1
  77. package/dist/utils/segments.d.ts +8 -0
  78. package/dist/utils/segments.d.ts.map +1 -1
  79. package/package.json +3 -2
  80. package/dist/index-BnKBciDG.js.map +0 -1
  81. package/dist/renderers/segments/progress.d.ts +0 -3
  82. package/dist/renderers/segments/progress.d.ts.map +0 -1
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { I as escapeAttr, D as cssEscape, $ as runWithConfig, Z as resolveConfig, a5 as mergeSegmentUpdate, J as escapeHtml, M as getSegmentRenderer, N as installDefaultRenderersOnce, r as AparteMessageRepository, a6 as stampSegmentActivity, a7 as stampSegmentOnInsert, a8 as stampSegmentOnUpdate, a9 as renumberSegments, aa as openSegmentIds, ab as isTerminalStatus, ac as adoptMessageSegments, O as isAwaitingReply, U as populateBubbleFromMessage, a4 as uuid, _ as revokeAttachmentUrls, a2 as subscribeConfigChange, w as buildElicitationPanel } from "./index-BnKBciDG.js";
2
- import { A, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, s, t, u, v, x, y, z, B, C, E, F, G, H, K, L, P, Q, R, S, T, V, W, X, Y, a0, a1, a3 } from "./index-BnKBciDG.js";
1
+ import { a4 as subscribeConfigChange, $ as resolveConfig, a1 as runWithConfig, p as AparteElicitationAbortError, x as buildApprovalPanel, y as buildElicitationPanel, K as escapeAttr, F as cssEscape, a7 as mergeSegmentUpdate, L as escapeHtml, O as getSegmentRenderer, P as installDefaultRenderersOnce, s as AparteMessageRepository, a8 as stampSegmentActivity, a9 as stampSegmentOnInsert, aa as stampSegmentOnUpdate, ab as renumberSegments, ac as openSegmentIds, ad as isTerminalStatus, ae as adoptMessageSegments, Q as isAwaitingReply, W as populateBubbleFromMessage, a6 as uuid, a0 as revokeAttachmentUrls } from "./is-awaiting-reply-Cb7H3YfN.js";
2
+ import { A, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, q, r, t, u, v, w, z, B, C, D, E, G, H, I, J, M, N, R, S, T, U, V, X, Y, Z, _, a2, a3, a5 } from "./is-awaiting-reply-Cb7H3YfN.js";
3
3
  class AparteOption extends HTMLElement {
4
4
  static get observedAttributes() {
5
5
  return ["value", "disabled", "selected", "data-status"];
@@ -631,6 +631,222 @@ class AparteProgressSpinner extends HTMLElement {
631
631
  if (!customElements.get("aparte-progress-spinner")) {
632
632
  customElements.define("aparte-progress-spinner", AparteProgressSpinner);
633
633
  }
634
+ class AparteElicitation extends HTMLElement {
635
+ _pending = null;
636
+ /**
637
+ * A turn ended — cancel the open question only if it was OUR turn.
638
+ *
639
+ * These two listeners sit on `window` and had no instance filter at all, so a
640
+ * Stop (or an error) in one chat cancelled the question a DIFFERENT chat was
641
+ * waiting on — and that chat's model was told the user had refused a question
642
+ * the user was still looking at. Same defect as the `compact()` handler that
643
+ * emptied both chats, which its four sibling handlers in `AparteClient` already
644
+ * guarded against.
645
+ *
646
+ * The leniency rule is the composer's, deliberately: an event with no
647
+ * `targetId` is for everyone (a single-chat app never sets one), and a chat we
648
+ * cannot identify accepts everything rather than becoming deaf. Only a
649
+ * MISMATCH is ignored.
650
+ */
651
+ _onTurnEnd = (e2) => {
652
+ const evtTargetId = e2.detail?.targetId;
653
+ const own = this._pendingTargetId();
654
+ if (evtTargetId && own && evtTargetId !== own) return;
655
+ this._cancelPending();
656
+ };
657
+ _unsubscribeConfig = null;
658
+ connectedCallback() {
659
+ this.style.display = "none";
660
+ this._unsubscribeConfig = subscribeConfigChange(this, () => this._relabelPending());
661
+ resolveConfig(this).setElicitationPresenter(this._present);
662
+ window.addEventListener("aparte-message-aborted", this._onTurnEnd);
663
+ window.addEventListener("aparte-message-error", this._onTurnEnd);
664
+ }
665
+ /**
666
+ * The boundary above us appeared, changed, or went away — move the
667
+ * registration with it.
668
+ *
669
+ * `connectedCallback` alone is not enough and cannot be: registering is a
670
+ * WRITE, and under all four wrappers it happens before `attachConfig` runs, so
671
+ * it lands on the global singleton. `requestUserInput()` then resolves the
672
+ * instance config, finds nothing, and answers the model `cancel` — the model
673
+ * hears the user refuse a question the user never saw.
674
+ *
675
+ * See {@link AparteConfigAware}.
676
+ */
677
+ aparteConfigChanged(next, previous) {
678
+ if (previous.getElicitationPresenter() === this._present) previous.setElicitationPresenter(null);
679
+ next.setElicitationPresenter(this._present);
680
+ }
681
+ disconnectedCallback() {
682
+ const cfg = resolveConfig(this);
683
+ if (cfg.getElicitationPresenter() === this._present) cfg.setElicitationPresenter(null);
684
+ window.removeEventListener("aparte-message-aborted", this._onTurnEnd);
685
+ window.removeEventListener("aparte-message-error", this._onTurnEnd);
686
+ this._unsubscribeConfig?.();
687
+ this._unsubscribeConfig = null;
688
+ this._cancelPending();
689
+ }
690
+ /**
691
+ * Re-apply the open question's strings, in place.
692
+ *
693
+ * Two owners, and both have to move or the panel goes bilingual: the panel's own
694
+ * defaults (`relabel`), and the Skip button, which this file builds and this file
695
+ * therefore has to re-text. The composer's one button is a third, and it already
696
+ * follows — `aparte-composer-send` remembers the panel state it was given.
697
+ */
698
+ _relabelPending() {
699
+ if (!this._pending) return;
700
+ const cfg = resolveConfig(this);
701
+ runWithConfig(cfg, () => this._pending.relabel());
702
+ }
703
+ _present = (request) => {
704
+ const composer = this._getComposer();
705
+ if (!composer) return Promise.reject(new AparteElicitationAbortError("no-presenter"));
706
+ return new Promise((resolve, reject) => {
707
+ let done = false;
708
+ const slot = {};
709
+ const close = () => {
710
+ if (done) return false;
711
+ done = true;
712
+ this._pending = null;
713
+ composer.hidePanel(slot.token);
714
+ return true;
715
+ };
716
+ const settle = (result) => {
717
+ if (close()) resolve(result);
718
+ };
719
+ const fail = (reason = "aborted") => {
720
+ if (close()) reject(new AparteElicitationAbortError(reason));
721
+ };
722
+ if (request.signal) {
723
+ if (request.signal.aborted) {
724
+ fail();
725
+ return;
726
+ }
727
+ request.signal.addEventListener("abort", () => fail(), { once: true });
728
+ }
729
+ const cfg = resolveConfig(this);
730
+ if (request.kind === "approval") {
731
+ const panel2 = runWithConfig(cfg, () => buildApprovalPanel(request.message, request.options ?? [], () => {
732
+ composer.setPanelSubmitEnabled(panel2.isComplete(), "submit");
733
+ }));
734
+ panel2.onSettle((answer) => settle({ action: "accept", content: answer }));
735
+ this._pending = { abort: () => fail(), composer, relabel: () => panel2.relabel() };
736
+ slot.token = composer.showPanel(panel2.el, {
737
+ submitEnabled: panel2.isComplete(),
738
+ mode: "submit",
739
+ // The composer's button carries the INSTRUCTION, which is written
740
+ // text — exactly the act that button already means. The options
741
+ // never route through it: a decision is its own click.
742
+ onSubmit: () => {
743
+ if (panel2.isComplete()) settle({ action: "accept", content: panel2.getContent() });
744
+ },
745
+ onEvict: () => fail()
746
+ });
747
+ panel2.focus();
748
+ return;
749
+ }
750
+ const schema = request.schema ?? { type: "string" };
751
+ const panel = runWithConfig(cfg, () => buildElicitationPanel(request.message, schema, () => {
752
+ composer.setPanelSubmitEnabled(panel.canProceed(), panel.mode());
753
+ }));
754
+ const skip = document.createElement("button");
755
+ skip.type = "button";
756
+ skip.className = "aparte-elic-skip";
757
+ skip.textContent = cfg.t("elicitationSkip");
758
+ skip.addEventListener("click", () => settle({ action: "decline" }));
759
+ panel.dismiss.appendChild(skip);
760
+ this._pending = {
761
+ abort: () => fail(),
762
+ composer,
763
+ relabel: () => {
764
+ panel.relabel();
765
+ skip.textContent = resolveConfig(this).t("elicitationSkip");
766
+ }
767
+ };
768
+ slot.token = composer.showPanel(panel.el, {
769
+ submitEnabled: panel.canProceed(),
770
+ mode: panel.mode(),
771
+ /*
772
+ * Something else took the slot — another request, a conversation switch,
773
+ * or a turn ending. The composer tears the panel down either way; only
774
+ * this callback can settle the promise, and without it the request hung
775
+ * AND `_pending` stayed set, so every later question was short-circuited
776
+ * for the life of the page. `cancel`, not `decline`: nobody declined
777
+ * anything, the question was taken away.
778
+ */
779
+ onEvict: () => fail(),
780
+ onSubmit: () => {
781
+ if (panel.mode() === "advance") {
782
+ panel.proceed();
783
+ composer.setPanelSubmitEnabled(panel.canProceed(), panel.mode());
784
+ return;
785
+ }
786
+ if (panel.isComplete()) settle({ action: "accept", content: panel.getContent() });
787
+ }
788
+ });
789
+ panel.focus();
790
+ });
791
+ };
792
+ _cancelPending() {
793
+ this._pending?.abort();
794
+ }
795
+ /**
796
+ * The host id of the chat whose composer holds the open panel.
797
+ *
798
+ * Walks up from the composer rather than from `this`, because the panel lives in
799
+ * the composer and that is what the turn belongs to. Matches the hosts
800
+ * `aparte-chat-bubble._resolveTargetId()` matches, for the reason written there:
801
+ * Angular's wrapper root IS the `<aparte-chat>` element, while the plain-root
802
+ * wrappers render a `[data-aparte-chat]` div instead, so matching only the tag
803
+ * resolves `undefined` on three wrappers out of four.
804
+ */
805
+ _pendingTargetId() {
806
+ let el = this._pending?.composer ?? null;
807
+ while (el) {
808
+ const tag = el.tagName?.toLowerCase();
809
+ const isHost = tag === "aparte-chat" || tag === "aparte-chat-component" || el.hasAttribute?.("data-aparte-chat");
810
+ if (isHost && el.id) return el.id;
811
+ el = el.parentElement;
812
+ }
813
+ return void 0;
814
+ }
815
+ /**
816
+ * The composer to present in: the nearest one in an ancestor subtree, and
817
+ * nothing else.
818
+ *
819
+ * There used to be a `document.querySelector('aparte-composer')` fallback, which
820
+ * is the "first chat on the page" bug this repo has now fixed in four other
821
+ * places: on a page with two chats, an elicitation that could not find its own
822
+ * composer mounted its panel in the OTHER chat's — so one conversation's question
823
+ * appeared under the other conversation, and answering it resolved a tool call
824
+ * belonging to a chat the user was not looking at.
825
+ *
826
+ * Returning `null` instead resolves `cancel`, which is honest: nothing was
827
+ * shown, so nothing was answered. The warning names the fix, because this is a
828
+ * setup mistake and only the developer can correct it — the guide's own example
829
+ * puts `<aparte-elicitation>` inside `<aparte-chat>`.
830
+ */
831
+ _getComposer() {
832
+ let node = this.parentElement;
833
+ while (node) {
834
+ const composer = node.querySelector("aparte-composer");
835
+ if (composer && typeof composer.showPanel === "function") return composer;
836
+ const tag = node.tagName?.toLowerCase();
837
+ const isChatBoundary = tag === "aparte-chat" || tag === "aparte-chat-component" || node.hasAttribute?.("data-aparte-chat");
838
+ if (isChatBoundary) break;
839
+ node = node.parentElement;
840
+ }
841
+ console.warn(
842
+ "[aparte-elicitation] No <aparte-composer> in this element's subtree, so the request was cancelled — the model will read that as a refusal. Move <aparte-elicitation> inside the <aparte-chat> it belongs to. It is deliberately NOT borrowing another chat's composer: on a page with two chats that put the question under the wrong one."
843
+ );
844
+ return null;
845
+ }
846
+ }
847
+ if (typeof customElements !== "undefined" && !customElements.get("aparte-elicitation")) {
848
+ customElements.define("aparte-elicitation", AparteElicitation);
849
+ }
634
850
  class AparteChat extends HTMLElement {
635
851
  static get observedAttributes() {
636
852
  return ["placeholder", "disabled", "center-empty", "attachments"];
@@ -683,6 +899,7 @@ class AparteChat extends HTMLElement {
683
899
  const attachments = this.hasAttribute("attachments");
684
900
  this.innerHTML = `
685
901
  <aparte-chat-viewport></aparte-chat-viewport>
902
+ <aparte-elicitation></aparte-elicitation>
686
903
  <aparte-composer${composerAttrs}>
687
904
  <div class="aparte-composer-shell">
688
905
  ${attachments ? "<aparte-composer-attachments></aparte-composer-attachments>" : ""}
@@ -935,7 +1152,7 @@ class AparteChatBubble extends HTMLElement {
935
1152
  }
936
1153
  /** Update a specific segment */
937
1154
  updateSegment(segmentId, updates) {
938
- const index = this._segments.findIndex((s2) => s2.id === segmentId);
1155
+ const index = this._segments.findIndex((s) => s.id === segmentId);
939
1156
  if (index !== -1) {
940
1157
  const updated = mergeSegmentUpdate(this._segments[index], updates);
941
1158
  this._segments[index] = updated;
@@ -944,7 +1161,7 @@ class AparteChatBubble extends HTMLElement {
944
1161
  }
945
1162
  /** Append content to a segment */
946
1163
  appendToSegment(segmentId, content) {
947
- const segment = this._segments.find((s2) => s2.id === segmentId);
1164
+ const segment = this._segments.find((s) => s.id === segmentId);
948
1165
  if (segment && "content" in segment) {
949
1166
  segment.content += content;
950
1167
  this._applySegmentUpdate(segmentId, segment, { content: segment.content });
@@ -970,7 +1187,7 @@ class AparteChatBubble extends HTMLElement {
970
1187
  * the human-in-the-loop control.
971
1188
  */
972
1189
  removeSegment(segmentId) {
973
- const index = this._segments.findIndex((s2) => s2.id === segmentId);
1190
+ const index = this._segments.findIndex((s) => s.id === segmentId);
974
1191
  if (index !== -1) {
975
1192
  this._segments.splice(index, 1);
976
1193
  }
@@ -1053,7 +1270,7 @@ class AparteChatBubble extends HTMLElement {
1053
1270
  } else {
1054
1271
  warnMissingRenderer(segment.type);
1055
1272
  const fallback = document.createElement("div");
1056
- fallback.className = "segment segment-unknown";
1273
+ fallback.className = "segment aparte-segment-unknown";
1057
1274
  fallback.textContent = `[Unknown segment type: ${segment.type}]`;
1058
1275
  this._segmentsEl.appendChild(fallback);
1059
1276
  }
@@ -1282,7 +1499,7 @@ class AparteChatBubble extends HTMLElement {
1282
1499
  } else {
1283
1500
  warnMissingRenderer(segment.type);
1284
1501
  const fallback = document.createElement("div");
1285
- fallback.className = "segment segment-unknown";
1502
+ fallback.className = "segment aparte-segment-unknown";
1286
1503
  fallback.textContent = `[Unknown segment type: ${segment.type}]`;
1287
1504
  this._segmentsEl.appendChild(fallback);
1288
1505
  }
@@ -1302,7 +1519,7 @@ class AparteChatBubble extends HTMLElement {
1302
1519
  _reflectError() {
1303
1520
  const message = this.querySelector(".aparte-message");
1304
1521
  if (!message) return;
1305
- const hasError = this._segments.some((s2) => s2.type === "error");
1522
+ const hasError = this._segments.some((s) => s.type === "error");
1306
1523
  if (hasError) message.setAttribute("data-error", "");
1307
1524
  else message.removeAttribute("data-error");
1308
1525
  }
@@ -1337,18 +1554,18 @@ class AparteChatBubble extends HTMLElement {
1337
1554
  const customAttachment = this._cfg.getAttachmentRenderer?.();
1338
1555
  if (customAttachment) {
1339
1556
  this._attachmentsEl.replaceChildren();
1340
- for (const a2 of this._attachments) {
1341
- const el = segmentRenderResultToElement(runWithConfig(this._cfg, () => customAttachment(a2)));
1557
+ for (const a4 of this._attachments) {
1558
+ const el = segmentRenderResultToElement(runWithConfig(this._cfg, () => customAttachment(a4)));
1342
1559
  if (el) this._attachmentsEl.appendChild(el);
1343
1560
  }
1344
1561
  return;
1345
1562
  }
1346
- this._attachmentsEl.innerHTML = this._attachments.map((a2) => {
1347
- const name = escapeHtml(a2.name);
1348
- if (a2.type.startsWith("image/")) {
1349
- return `<div class="aparte-thumb aparte-thumb--image" title="${name}"><img class="aparte-thumb__img" src="${escapeHtml(a2.url)}" alt="${name}" loading="lazy" /><span class="aparte-thumb__name">${name}</span></div>`;
1563
+ this._attachmentsEl.innerHTML = this._attachments.map((a4) => {
1564
+ const name = escapeHtml(a4.name);
1565
+ if (a4.type.startsWith("image/")) {
1566
+ return `<div class="aparte-thumb aparte-thumb--image" title="${name}"><img class="aparte-thumb__img" src="${escapeHtml(a4.url)}" alt="${name}" loading="lazy" /><span class="aparte-thumb__name">${name}</span></div>`;
1350
1567
  }
1351
- return `<div class="aparte-thumb aparte-thumb--file" title="${name}"><span class="aparte-thumb__ext">${escapeHtml(this._fileExt(a2.name))}</span><span class="aparte-thumb__name">${name}</span></div>`;
1568
+ return `<div class="aparte-thumb aparte-thumb--file" title="${name}"><span class="aparte-thumb__ext">${escapeHtml(this._fileExt(a4.name))}</span><span class="aparte-thumb__name">${name}</span></div>`;
1352
1569
  }).join("");
1353
1570
  if (!this._cfg.getHostHandlers().attachmentPreview) return;
1354
1571
  this._attachmentsEl.querySelectorAll(".aparte-thumb--image").forEach((tile) => {
@@ -1453,14 +1670,14 @@ class AparteChatBubble extends HTMLElement {
1453
1670
  const buttons = [];
1454
1671
  if (this._role === "user") {
1455
1672
  if (config.user) {
1456
- for (const a2 of config.user) buttons.push(this._actionButtonHtml(a2, icons, locale));
1673
+ for (const a4 of config.user) buttons.push(this._actionButtonHtml(a4, icons, locale));
1457
1674
  } else {
1458
1675
  if (config.copy) buttons.push(this._actionButtonHtml("copy", icons, locale));
1459
1676
  if (config.edit) buttons.push(this._actionButtonHtml("edit", icons, locale));
1460
1677
  }
1461
1678
  } else if (this._role === "assistant") {
1462
1679
  if (config.assistant) {
1463
- for (const a2 of config.assistant) buttons.push(this._actionButtonHtml(a2, icons, locale));
1680
+ for (const a4 of config.assistant) buttons.push(this._actionButtonHtml(a4, icons, locale));
1464
1681
  } else {
1465
1682
  if (config.copy) buttons.push(this._actionButtonHtml("copy", icons, locale));
1466
1683
  if (config.retry) buttons.push(this._actionButtonHtml("retry", icons, locale));
@@ -1495,16 +1712,16 @@ class AparteChatBubble extends HTMLElement {
1495
1712
  /** Append the registered custom action buttons for this bubble's role. */
1496
1713
  _appendCustomActions(icons) {
1497
1714
  if (!this._actionBarEl) return;
1498
- for (const a2 of this._cfg.getActions("bubble")) {
1499
- const roles = a2.bubble?.roles ?? ["user", "assistant"];
1715
+ for (const a4 of this._cfg.getActions("bubble")) {
1716
+ const roles = a4.bubble?.roles ?? ["user", "assistant"];
1500
1717
  if (!roles.includes(this._role)) continue;
1501
1718
  const btn = document.createElement("button");
1502
1719
  btn.className = "aparte-action-btn aparte-action-custom";
1503
- btn.dataset["action"] = `custom:${a2.id}`;
1504
- btn.setAttribute("aria-label", a2.label);
1505
- btn.setAttribute("title", a2.label);
1506
- const fromProvider = icons[a2.icon];
1507
- btn.innerHTML = a2.icon.startsWith("<") ? a2.icon : typeof fromProvider === "function" ? fromProvider() : a2.iconFallback ?? "";
1720
+ btn.dataset["action"] = `custom:${a4.id}`;
1721
+ btn.setAttribute("aria-label", a4.label);
1722
+ btn.setAttribute("title", a4.label);
1723
+ const fromProvider = icons[a4.icon];
1724
+ btn.innerHTML = a4.icon.startsWith("<") ? a4.icon : typeof fromProvider === "function" ? fromProvider() : a4.iconFallback ?? "";
1508
1725
  this._actionBarEl.appendChild(btn);
1509
1726
  }
1510
1727
  }
@@ -1570,12 +1787,12 @@ class AparteChatBubble extends HTMLElement {
1570
1787
  composed: true,
1571
1788
  detail
1572
1789
  }));
1573
- this._cfg.getActions("bubble").find((x2) => x2.id === actionId)?.onClick?.(e2);
1790
+ this._cfg.getActions("bubble").find((x) => x.id === actionId)?.onClick?.(e2);
1574
1791
  return;
1575
1792
  }
1576
1793
  switch (action) {
1577
1794
  case "copy": {
1578
- const text = this._content || this._segments.map((s2) => s2.content ?? "").join("\n");
1795
+ const text = this._content || this._segments.map((s) => s.content ?? "").join("\n");
1579
1796
  const icons = this._cfg.getIconProvider();
1580
1797
  const locale = this._cfg.getLocale();
1581
1798
  navigator.clipboard.writeText(text).then(() => {
@@ -2013,7 +2230,7 @@ class AparteChatViewport extends HTMLElement {
2013
2230
  if (!message.segments) {
2014
2231
  message.segments = [];
2015
2232
  }
2016
- const index = message.segments.findIndex((s2) => s2.id === segmentId);
2233
+ const index = message.segments.findIndex((s) => s.id === segmentId);
2017
2234
  const segment = index === -1 ? void 0 : message.segments[index];
2018
2235
  if (segment && "content" in segment) {
2019
2236
  message.segments[index] = {
@@ -2075,15 +2292,15 @@ class AparteChatViewport extends HTMLElement {
2075
2292
  this._notifyBubble(messageId, "addSegment", stamped);
2076
2293
  this._autoScroll();
2077
2294
  }
2078
- updateSegment(a2, b2, c2) {
2295
+ updateSegment(a4, b2, c2) {
2079
2296
  const clientForm = c2 === void 0 && typeof b2 === "object";
2080
- const messageId = clientForm ? this._activeMessageId() : a2;
2081
- const segmentId = clientForm ? a2 : b2;
2297
+ const messageId = clientForm ? this._activeMessageId() : a4;
2298
+ const segmentId = clientForm ? a4 : b2;
2082
2299
  const updates = clientForm ? b2 : c2;
2083
2300
  if (!messageId) return;
2084
2301
  const message = this._repo.getMessageById(messageId);
2085
2302
  if (!message?.segments) return;
2086
- const segmentIndex = message.segments.findIndex((s2) => s2.id === segmentId);
2303
+ const segmentIndex = message.segments.findIndex((s) => s.id === segmentId);
2087
2304
  if (segmentIndex !== -1) {
2088
2305
  const current = message.segments[segmentIndex];
2089
2306
  const stamped = stampSegmentOnUpdate(current, updates);
@@ -2091,14 +2308,14 @@ class AparteChatViewport extends HTMLElement {
2091
2308
  this._notifyBubble(messageId, "updateSegment", { segmentId, updates: stamped });
2092
2309
  }
2093
2310
  }
2094
- removeSegment(a2, b2) {
2311
+ removeSegment(a4, b2) {
2095
2312
  const clientForm = b2 === void 0;
2096
- const messageId = clientForm ? this._activeMessageId() : a2;
2097
- const segmentId = clientForm ? a2 : b2;
2313
+ const messageId = clientForm ? this._activeMessageId() : a4;
2314
+ const segmentId = clientForm ? a4 : b2;
2098
2315
  if (!messageId || !segmentId) return;
2099
2316
  const message = this._repo.getMessageById(messageId);
2100
2317
  if (message?.segments) {
2101
- const idx = message.segments.findIndex((s2) => s2.id === segmentId);
2318
+ const idx = message.segments.findIndex((s) => s.id === segmentId);
2102
2319
  if (idx !== -1) {
2103
2320
  message.segments.splice(idx, 1);
2104
2321
  renumberSegments(message.segments);
@@ -2930,6 +3147,20 @@ class AparteComposer extends HTMLElement {
2930
3147
  _panelMode = "submit";
2931
3148
  _panelSubmitEnabled = false;
2932
3149
  _panelOnSubmit = null;
3150
+ /**
3151
+ * Who owns the one panel slot, and how to tell them they lost it.
3152
+ *
3153
+ * There is exactly one slot, `showPanel` empties it unconditionally, and nothing
3154
+ * used to say whose it was. Three paths therefore closed a panel whose owner was
3155
+ * still awaiting an answer, and none of them told the owner: a second `showPanel`,
3156
+ * the owner-of-record's own `hidePanel`, and — the one that actually bit —
3157
+ * `_handleMessageDone`, which fires on EVERY turn end. A question still open when a
3158
+ * turn finished lost its panel while `<aparte-elicitation>` kept `_pending` set,
3159
+ * so the request never settled AND every later request was short-circuited for the
3160
+ * life of the page.
3161
+ */
3162
+ _panelToken = null;
3163
+ _panelOnEvict = null;
2933
3164
  // Internal bus events that represent an observable STATE change — these are
2934
3165
  // mirrored to the public `aparte-composer-change` DOM event. `submit`/`cancel`
2935
3166
  // are actions, not state, and are covered by `aparte-send`/`aparte-cancel`.
@@ -3097,9 +3328,14 @@ class AparteComposer extends HTMLElement {
3097
3328
  * used to set on a child: an attribute is themeable, is visible to a consumer's
3098
3329
  * own rules, and does not clobber a `display` the consumer had set (the restore
3099
3330
  * wrote `''`, not the previous value).
3331
+ *
3332
+ * Returns the TOKEN for this panel. Pass it back to `hidePanel` so a presenter
3333
+ * that has already lost the slot cannot close the panel that replaced it, and
3334
+ * supply `onEvict` to be told when that happens — an owner that is not told is an
3335
+ * owner whose promise nobody can settle.
3100
3336
  */
3101
3337
  showPanel(panel, options) {
3102
- this.hidePanel();
3338
+ this._evictPanel();
3103
3339
  const inputEl = this.querySelector("aparte-composer-input");
3104
3340
  this.setAttribute("data-panel-active", "");
3105
3341
  panel.dataset["apartePanel"] = "true";
@@ -3112,10 +3348,31 @@ class AparteComposer extends HTMLElement {
3112
3348
  this._panelSubmitEnabled = options?.submitEnabled ?? false;
3113
3349
  this._panelMode = options?.mode ?? "submit";
3114
3350
  this._panelOnSubmit = options?.onSubmit ?? null;
3351
+ this._panelOnEvict = options?.onEvict ?? null;
3352
+ const token = Symbol("aparte-composer-panel");
3353
+ this._panelToken = token;
3115
3354
  this._emit("panel-change", { active: true, submitEnabled: this._panelSubmitEnabled, mode: this._panelMode });
3355
+ return token;
3116
3356
  }
3117
- /** Remove the panel and restore the composer's own controls. */
3118
- hidePanel() {
3357
+ /**
3358
+ * Remove the panel and restore the composer's own controls.
3359
+ *
3360
+ * With a `token`, this closes the panel only if that token still owns the slot —
3361
+ * so a presenter settling late cannot tear down the panel that replaced it. With
3362
+ * no token it closes whatever is there, which is what a consumer driving the
3363
+ * composer directly means, and what `reset()` needs.
3364
+ */
3365
+ hidePanel(token) {
3366
+ if (token !== void 0 && token !== this._panelToken) return;
3367
+ this._teardownPanel();
3368
+ }
3369
+ /** Close the panel AND tell its owner, so a pending request never orphans. */
3370
+ _evictPanel() {
3371
+ const onEvict = this._panelOnEvict;
3372
+ this._teardownPanel();
3373
+ onEvict?.();
3374
+ }
3375
+ _teardownPanel() {
3119
3376
  const existing = this.querySelector("[data-aparte-panel]");
3120
3377
  if (existing) existing.remove();
3121
3378
  this.removeAttribute("data-panel-active");
@@ -3123,6 +3380,8 @@ class AparteComposer extends HTMLElement {
3123
3380
  this._panelSubmitEnabled = false;
3124
3381
  this._panelMode = "submit";
3125
3382
  this._panelOnSubmit = null;
3383
+ this._panelOnEvict = null;
3384
+ this._panelToken = null;
3126
3385
  this._emit("panel-change", { active: false, submitEnabled: false, mode: "submit" });
3127
3386
  this.focus();
3128
3387
  }
@@ -3200,7 +3459,7 @@ class AparteComposer extends HTMLElement {
3200
3459
  reset() {
3201
3460
  this.setValue("");
3202
3461
  this.clearAttachments();
3203
- if (this._panelActive) this.hidePanel();
3462
+ if (this._panelActive) this._evictPanel();
3204
3463
  }
3205
3464
  /** Focus the input primitive inside this composer. */
3206
3465
  focus() {
@@ -3269,7 +3528,7 @@ class AparteComposer extends HTMLElement {
3269
3528
  if (!this._isForThisComposer(e2)) return;
3270
3529
  this._streaming = false;
3271
3530
  this._emit("streaming-change", { streaming: false });
3272
- if (this._panelActive) this.hidePanel();
3531
+ if (this._panelActive) this._evictPanel();
3273
3532
  }
3274
3533
  }
3275
3534
  if (!customElements.get("aparte-composer")) {
@@ -3431,10 +3690,10 @@ class AparteComposerInput extends HTMLElement {
3431
3690
  }
3432
3691
  }
3433
3692
  _handleFocus() {
3434
- this.classList.add("is-focused");
3693
+ this.classList.add("aparte-is-focused");
3435
3694
  }
3436
3695
  _handleBlur() {
3437
- this.classList.remove("is-focused");
3696
+ this.classList.remove("aparte-is-focused");
3438
3697
  }
3439
3698
  _handlePaste(e2) {
3440
3699
  e2.preventDefault();
@@ -3477,9 +3736,9 @@ class AparteComposerInput extends HTMLElement {
3477
3736
  }
3478
3737
  _updatePlaceholder() {
3479
3738
  if (this._editor) {
3480
- const p2 = this._getPlaceholder();
3481
- this._editor.setAttribute("data-placeholder", p2);
3482
- this._editor.setAttribute("aria-label", p2);
3739
+ const p = this._getPlaceholder();
3740
+ this._editor.setAttribute("data-placeholder", p);
3741
+ this._editor.setAttribute("aria-label", p);
3483
3742
  }
3484
3743
  }
3485
3744
  _updatePlaceholderVisibility() {
@@ -3605,7 +3864,7 @@ class AparteComposerSend extends HTMLElement {
3605
3864
  const label = advancing ? cfg.t("elicitationNext") || "Next" : cfg.t("submitButton") || "Submit";
3606
3865
  this._button.setAttribute("aria-label", label);
3607
3866
  this._button.setAttribute("title", label);
3608
- this._button.classList.remove("is-streaming");
3867
+ this._button.classList.remove("aparte-is-streaming");
3609
3868
  }
3610
3869
  _handleClick(e2) {
3611
3870
  e2.preventDefault();
@@ -3621,7 +3880,7 @@ class AparteComposerSend extends HTMLElement {
3621
3880
  const label = resolveConfig(this).t("sendButton") || "Send";
3622
3881
  this._button.setAttribute("aria-label", label);
3623
3882
  this._button.setAttribute("title", label);
3624
- this._button.classList.remove("is-streaming");
3883
+ this._button.classList.remove("aparte-is-streaming");
3625
3884
  }
3626
3885
  _syncStreamingState(streaming) {
3627
3886
  if (!this._button) return;
@@ -3631,7 +3890,7 @@ class AparteComposerSend extends HTMLElement {
3631
3890
  const label = resolveConfig(this).t("stopButton") || "Stop";
3632
3891
  this._button.setAttribute("aria-label", label);
3633
3892
  this._button.setAttribute("title", label);
3634
- this._button.classList.add("is-streaming");
3893
+ this._button.classList.add("aparte-is-streaming");
3635
3894
  } else {
3636
3895
  this._syncState();
3637
3896
  }
@@ -3906,15 +4165,15 @@ class AparteComposerAddAttachment extends HTMLElement {
3906
4165
  const onDragOver = (e2) => {
3907
4166
  if (root.disabled) return;
3908
4167
  prevent(e2);
3909
- root.classList.add("is-dragover");
4168
+ root.classList.add("aparte-is-dragover");
3910
4169
  };
3911
4170
  const onDragLeave = (e2) => {
3912
4171
  prevent(e2);
3913
- root.classList.remove("is-dragover");
4172
+ root.classList.remove("aparte-is-dragover");
3914
4173
  };
3915
4174
  const onDrop = (e2) => {
3916
4175
  prevent(e2);
3917
- root.classList.remove("is-dragover");
4176
+ root.classList.remove("aparte-is-dragover");
3918
4177
  if (root.disabled) return;
3919
4178
  const files = e2.dataTransfer?.files;
3920
4179
  if (files?.length) this._getRoot()?.addAttachments(files);
@@ -4207,180 +4466,6 @@ class AparteConversationList extends HTMLElement {
4207
4466
  }
4208
4467
  }
4209
4468
  if (!customElements.get("aparte-conversation-list")) customElements.define("aparte-conversation-list", AparteConversationList);
4210
- class AparteElicitation extends HTMLElement {
4211
- _pending = null;
4212
- /**
4213
- * A turn ended — cancel the open question only if it was OUR turn.
4214
- *
4215
- * These two listeners sit on `window` and had no instance filter at all, so a
4216
- * Stop (or an error) in one chat cancelled the question a DIFFERENT chat was
4217
- * waiting on — and that chat's model was told the user had refused a question
4218
- * the user was still looking at. Same defect as the `compact()` handler that
4219
- * emptied both chats, which its four sibling handlers in `AparteClient` already
4220
- * guarded against.
4221
- *
4222
- * The leniency rule is the composer's, deliberately: an event with no
4223
- * `targetId` is for everyone (a single-chat app never sets one), and a chat we
4224
- * cannot identify accepts everything rather than becoming deaf. Only a
4225
- * MISMATCH is ignored.
4226
- */
4227
- _onTurnEnd = (e2) => {
4228
- const evtTargetId = e2.detail?.targetId;
4229
- const own = this._pendingTargetId();
4230
- if (evtTargetId && own && evtTargetId !== own) return;
4231
- this._cancelPending();
4232
- };
4233
- _unsubscribeConfig = null;
4234
- connectedCallback() {
4235
- this.style.display = "none";
4236
- this._unsubscribeConfig = subscribeConfigChange(this, () => this._relabelPending());
4237
- resolveConfig(this).setElicitationPresenter(this._present);
4238
- window.addEventListener("aparte-message-aborted", this._onTurnEnd);
4239
- window.addEventListener("aparte-message-error", this._onTurnEnd);
4240
- }
4241
- /**
4242
- * The boundary above us appeared, changed, or went away — move the
4243
- * registration with it.
4244
- *
4245
- * `connectedCallback` alone is not enough and cannot be: registering is a
4246
- * WRITE, and under all four wrappers it happens before `attachConfig` runs, so
4247
- * it lands on the global singleton. `requestUserInput()` then resolves the
4248
- * instance config, finds nothing, and answers the model `cancel` — the model
4249
- * hears the user refuse a question the user never saw.
4250
- *
4251
- * See {@link AparteConfigAware}.
4252
- */
4253
- aparteConfigChanged(next, previous) {
4254
- if (previous.getElicitationPresenter() === this._present) previous.setElicitationPresenter(null);
4255
- next.setElicitationPresenter(this._present);
4256
- }
4257
- disconnectedCallback() {
4258
- const cfg = resolveConfig(this);
4259
- if (cfg.getElicitationPresenter() === this._present) cfg.setElicitationPresenter(null);
4260
- window.removeEventListener("aparte-message-aborted", this._onTurnEnd);
4261
- window.removeEventListener("aparte-message-error", this._onTurnEnd);
4262
- this._unsubscribeConfig?.();
4263
- this._unsubscribeConfig = null;
4264
- this._cancelPending();
4265
- }
4266
- /**
4267
- * Re-apply the open question's strings, in place.
4268
- *
4269
- * Two owners, and both have to move or the panel goes bilingual: the panel's own
4270
- * defaults (`relabel`), and the Skip button, which this file builds and this file
4271
- * therefore has to re-text. The composer's one button is a third, and it already
4272
- * follows — `aparte-composer-send` remembers the panel state it was given.
4273
- */
4274
- _relabelPending() {
4275
- if (!this._pending) return;
4276
- const cfg = resolveConfig(this);
4277
- runWithConfig(cfg, () => this._pending.panel.relabel());
4278
- this._pending.skip.textContent = cfg.t("elicitationSkip");
4279
- }
4280
- _present = (request) => {
4281
- if (this._pending) return Promise.resolve({ action: "cancel" });
4282
- const composer = this._getComposer();
4283
- if (!composer) return Promise.resolve({ action: "cancel" });
4284
- return new Promise((resolve) => {
4285
- let done = false;
4286
- const settle = (result) => {
4287
- if (done) return;
4288
- done = true;
4289
- this._pending = null;
4290
- composer.hidePanel();
4291
- resolve(result);
4292
- };
4293
- if (request.signal) {
4294
- if (request.signal.aborted) {
4295
- settle({ action: "cancel" });
4296
- return;
4297
- }
4298
- request.signal.addEventListener("abort", () => settle({ action: "cancel" }), { once: true });
4299
- }
4300
- const cfg = resolveConfig(this);
4301
- const panel = runWithConfig(cfg, () => buildElicitationPanel(request.message, request.schema, () => {
4302
- composer.setPanelSubmitEnabled(panel.canProceed(), panel.mode());
4303
- }));
4304
- const skip = document.createElement("button");
4305
- skip.type = "button";
4306
- skip.className = "aparte-elic-skip";
4307
- skip.textContent = cfg.t("elicitationSkip");
4308
- skip.addEventListener("click", () => settle({ action: "decline" }));
4309
- panel.dismiss.appendChild(skip);
4310
- this._pending = { settle, composer, panel, skip };
4311
- composer.showPanel(panel.el, {
4312
- submitEnabled: panel.canProceed(),
4313
- mode: panel.mode(),
4314
- onSubmit: () => {
4315
- if (panel.mode() === "advance") {
4316
- panel.proceed();
4317
- composer.setPanelSubmitEnabled(panel.canProceed(), panel.mode());
4318
- return;
4319
- }
4320
- if (panel.isComplete()) settle({ action: "accept", content: panel.getContent() });
4321
- }
4322
- });
4323
- panel.focus();
4324
- });
4325
- };
4326
- _cancelPending() {
4327
- this._pending?.settle({ action: "cancel" });
4328
- }
4329
- /**
4330
- * The host id of the chat whose composer holds the open panel.
4331
- *
4332
- * Walks up from the composer rather than from `this`, because the panel lives in
4333
- * the composer and that is what the turn belongs to. Matches the hosts
4334
- * `aparte-chat-bubble._resolveTargetId()` matches, for the reason written there:
4335
- * Angular's wrapper root IS the `<aparte-chat>` element, while the plain-root
4336
- * wrappers render a `[data-aparte-chat]` div instead, so matching only the tag
4337
- * resolves `undefined` on three wrappers out of four.
4338
- */
4339
- _pendingTargetId() {
4340
- let el = this._pending?.composer ?? null;
4341
- while (el) {
4342
- const tag = el.tagName?.toLowerCase();
4343
- const isHost = tag === "aparte-chat" || tag === "aparte-chat-component" || el.hasAttribute?.("data-aparte-chat");
4344
- if (isHost && el.id) return el.id;
4345
- el = el.parentElement;
4346
- }
4347
- return void 0;
4348
- }
4349
- /**
4350
- * The composer to present in: the nearest one in an ancestor subtree, and
4351
- * nothing else.
4352
- *
4353
- * There used to be a `document.querySelector('aparte-composer')` fallback, which
4354
- * is the "first chat on the page" bug this repo has now fixed in four other
4355
- * places: on a page with two chats, an elicitation that could not find its own
4356
- * composer mounted its panel in the OTHER chat's — so one conversation's question
4357
- * appeared under the other conversation, and answering it resolved a tool call
4358
- * belonging to a chat the user was not looking at.
4359
- *
4360
- * Returning `null` instead resolves `cancel`, which is honest: nothing was
4361
- * shown, so nothing was answered. The warning names the fix, because this is a
4362
- * setup mistake and only the developer can correct it — the guide's own example
4363
- * puts `<aparte-elicitation>` inside `<aparte-chat>`.
4364
- */
4365
- _getComposer() {
4366
- let node = this.parentElement;
4367
- while (node) {
4368
- const composer = node.querySelector("aparte-composer");
4369
- if (composer && typeof composer.showPanel === "function") return composer;
4370
- const tag = node.tagName?.toLowerCase();
4371
- const isChatBoundary = tag === "aparte-chat" || tag === "aparte-chat-component" || node.hasAttribute?.("data-aparte-chat");
4372
- if (isChatBoundary) break;
4373
- node = node.parentElement;
4374
- }
4375
- console.warn(
4376
- "[aparte-elicitation] No <aparte-composer> in this element's subtree, so the request was cancelled — the model will read that as a refusal. Move <aparte-elicitation> inside the <aparte-chat> it belongs to. It is deliberately NOT borrowing another chat's composer: on a page with two chats that put the question under the wrong one."
4377
- );
4378
- return null;
4379
- }
4380
- }
4381
- if (typeof customElements !== "undefined" && !customElements.get("aparte-elicitation")) {
4382
- customElements.define("aparte-elicitation", AparteElicitation);
4383
- }
4384
4469
  function registerAllComponents() {
4385
4470
  const _chat = customElements.get("aparte-chat");
4386
4471
  const _viewport = customElements.get("aparte-chat-viewport");
@@ -4421,53 +4506,55 @@ export {
4421
4506
  n as AparteConversationManager,
4422
4507
  o as AparteDirectTransport,
4423
4508
  AparteElicitation,
4424
- p as AparteError,
4425
- q as AparteErrorCode,
4509
+ AparteElicitationAbortError,
4510
+ q as AparteError,
4511
+ r as AparteErrorCode,
4426
4512
  AparteMessageRepository,
4427
4513
  AparteOptgroup,
4428
4514
  AparteOption,
4429
4515
  AparteProgressSpinner,
4430
4516
  AparteSelect,
4431
- s as AparteStreamParser,
4432
- t as aparteGlobalConfig,
4433
- u as applyElementProps,
4434
- v as attachConfig,
4517
+ t as AparteStreamParser,
4518
+ u as aparteGlobalConfig,
4519
+ v as applyElementProps,
4520
+ w as attachConfig,
4521
+ buildApprovalPanel,
4435
4522
  buildElicitationPanel,
4436
- x as collectRendererStyles,
4437
- y as contentToText,
4438
- z as contextConfig,
4439
- B as createAparteChatHandler,
4440
- C as createStreamAdapter,
4523
+ z as collectRendererStyles,
4524
+ B as contentToText,
4525
+ C as contextConfig,
4526
+ D as createAparteChatHandler,
4527
+ E as createStreamAdapter,
4441
4528
  cssEscape,
4442
- E as declineDefaultRenderers,
4443
- F as defaultSanitizer,
4444
- G as deriveArtifactKind,
4445
- H as detachConfig,
4529
+ G as declineDefaultRenderers,
4530
+ H as defaultSanitizer,
4531
+ I as deriveArtifactKind,
4532
+ J as detachConfig,
4446
4533
  escapeAttr,
4447
4534
  escapeHtml,
4448
- K as filesToAttachments,
4449
- L as getAllRenderers,
4535
+ M as filesToAttachments,
4536
+ N as getAllRenderers,
4450
4537
  getSegmentRenderer,
4451
4538
  installDefaultRenderersOnce,
4452
4539
  isAwaitingReply,
4453
- P as isFormatAdapter,
4454
- Q as isSafeUrl,
4455
- R as isSegmentSettled,
4456
- S as parseAparteEventStream,
4457
- T as parseMarkdownToSegments,
4540
+ R as isFormatAdapter,
4541
+ S as isSafeUrl,
4542
+ T as isSegmentSettled,
4543
+ U as parseAparteEventStream,
4544
+ V as parseMarkdownToSegments,
4458
4545
  populateBubbleFromMessage,
4459
- V as readableToAsyncIterable,
4546
+ X as readableToAsyncIterable,
4460
4547
  registerAllComponents,
4461
- W as registerDefaultRenderers,
4462
- X as registerSegmentRenderer,
4463
- Y as requestUserInput,
4548
+ Y as registerDefaultRenderers,
4549
+ Z as registerSegmentRenderer,
4550
+ _ as requestUserInput,
4464
4551
  resolveConfig,
4465
4552
  revokeAttachmentUrls,
4466
4553
  runWithConfig,
4467
- a0 as segmentDuration,
4468
- a1 as segmentTiming,
4554
+ a2 as segmentDuration,
4555
+ a3 as segmentTiming,
4469
4556
  subscribeConfigChange,
4470
- a3 as unregisterSegmentRenderer,
4557
+ a5 as unregisterSegmentRenderer,
4471
4558
  uuid
4472
4559
  };
4473
4560
  //# sourceMappingURL=index.js.map