@ai-ecoverse/slicc-spectrum 2.0.3 → 2.1.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/dist/slicc-ui.js CHANGED
@@ -37451,6 +37451,16 @@ var SliccChat = class _SliccChat extends ThemedElement {
37451
37451
  background: var(--swc-background-elevated-color);
37452
37452
  box-shadow: var(--swc-drop-shadow-elevated);
37453
37453
  }
37454
+ .older {
37455
+ display: flex;
37456
+ align-items: center;
37457
+ justify-content: center;
37458
+ gap: var(--swc-spacing-100);
37459
+ min-block-size: var(--swc-component-height-100);
37460
+ margin-block-end: var(--swc-spacing-200);
37461
+ font-size: var(--swc-font-size-100);
37462
+ color: var(--swc-neutral-subdued-content-color-default);
37463
+ }
37454
37464
  .empty {
37455
37465
  color: var(--swc-neutral-subdued-content-color-default);
37456
37466
  text-align: center;
@@ -37556,7 +37566,7 @@ var SliccChat = class _SliccChat extends ThemedElement {
37556
37566
  #tick;
37557
37567
  #tail = "";
37558
37568
  #held = "";
37559
- #mark = 0;
37569
+ #mark = "";
37560
37570
  #all = false;
37561
37571
  #seen = "";
37562
37572
  #focused = (event2) => {
@@ -37605,7 +37615,75 @@ var SliccChat = class _SliccChat extends ThemedElement {
37605
37615
  const log = this.#log();
37606
37616
  if (!this.#stuck && log.scrollHeight <= log.clientHeight) this.#follow();
37607
37617
  else this.#pin(false);
37618
+ this.#check();
37608
37619
  });
37620
+ #paging = /* @__PURE__ */ new Set();
37621
+ #stopped = /* @__PURE__ */ new Map();
37622
+ #shown = { agent: "", head: "" };
37623
+ #anchor = null;
37624
+ #first(id) {
37625
+ return id && this.model?.agent.messages(id)[0]?.id || "";
37626
+ }
37627
+ #check() {
37628
+ const log = this.#log();
37629
+ if (log.scrollTop < log.clientHeight) void this.#earlier();
37630
+ }
37631
+ async #earlier() {
37632
+ const agent = this.model?.agent;
37633
+ const id = this.#id();
37634
+ const head = this.#first(id);
37635
+ if (!agent?.hasOlder?.(id) || this.#paging.has(id) || this.#stopped.get(id)?.head === head)
37636
+ return;
37637
+ this.#paging.add(id);
37638
+ this.requestUpdate();
37639
+ try {
37640
+ const found = await agent.older(id, head);
37641
+ const now = this.#first(id);
37642
+ if (!found.length || now === head) this.#stopped.set(id, { head: now, failed: false });
37643
+ } catch {
37644
+ this.#stopped.set(id, { head, failed: true });
37645
+ }
37646
+ this.#paging.delete(id);
37647
+ this.requestUpdate();
37648
+ await this.updateComplete;
37649
+ if (this.#id() === id) this.#check();
37650
+ }
37651
+ #retry(id) {
37652
+ this.#log().focus({ preventScroll: true });
37653
+ this.#stopped.delete(id);
37654
+ void this.#earlier();
37655
+ }
37656
+ #keep(agent) {
37657
+ const log = this.#log();
37658
+ const top = log.getBoundingClientRect().top;
37659
+ const card2 = [...log.querySelector("swc-conversation-thread")?.children ?? []].find(
37660
+ (child) => !child.matches(".day") && child.getBoundingClientRect().bottom > top
37661
+ );
37662
+ return {
37663
+ agent,
37664
+ card: card2,
37665
+ offset: card2 ? card2.getBoundingClientRect().top - top : 0,
37666
+ top: log.scrollTop,
37667
+ height: log.scrollHeight
37668
+ };
37669
+ }
37670
+ #restore() {
37671
+ const { agent, card: card2, offset: offset3, top, height } = this.#anchor;
37672
+ this.#anchor = null;
37673
+ if (agent !== this.#id()) return;
37674
+ const log = this.#log();
37675
+ log.scrollTop = card2?.isConnected ? log.scrollTop + card2.getBoundingClientRect().top - log.getBoundingClientRect().top - offset3 : top + log.scrollHeight - height;
37676
+ this.#last = log.scrollTop;
37677
+ this.#height = log.scrollHeight;
37678
+ }
37679
+ #olderRow(id, head) {
37680
+ const stop = this.#stopped.get(id);
37681
+ if (stop?.failed && stop.head === head)
37682
+ return b`<div class="older" role="alert" data-older="failed"><span>Couldn’t load earlier messages.</span><swc-action-button size="s" quiet data-action="retry-older" @click=${() => this.#retry(id)}>Retry</swc-action-button></div>`;
37683
+ const paging = this.#paging.has(id);
37684
+ if (!paging && (!this.model?.agent.hasOlder?.(id) || stop?.head === head)) return A;
37685
+ return b`<div class="older" role="status" data-older="loading" aria-busy=${paging ? "true" : "false"}>Loading earlier messages…</div>`;
37686
+ }
37609
37687
  #fitted;
37610
37688
  #fit = new ResizeObserver(([entry]) => {
37611
37689
  this.style.setProperty("--composer-height", `${entry.target.offsetHeight}px`);
@@ -37663,6 +37741,7 @@ var SliccChat = class _SliccChat extends ThemedElement {
37663
37741
  this.#stuck = false;
37664
37742
  this.#last = log.scrollTop;
37665
37743
  this.#height = log.scrollHeight;
37744
+ this.#check();
37666
37745
  };
37667
37746
  #intent = {
37668
37747
  passive: true,
@@ -37725,6 +37804,17 @@ var SliccChat = class _SliccChat extends ThemedElement {
37725
37804
  clearInterval(this.#tick);
37726
37805
  this.#tick = void 0;
37727
37806
  }
37807
+ willUpdate(changed2) {
37808
+ super.willUpdate(changed2);
37809
+ const id = this.#id();
37810
+ const head = this.#first(id);
37811
+ const shown5 = this.#shown;
37812
+ if (this.hasUpdated && !this.#anchor && id === shown5.agent && shown5.head && head !== shown5.head) {
37813
+ this.#anchor = this.#keep(id);
37814
+ requestAnimationFrame(() => this.#restore());
37815
+ }
37816
+ this.#shown = { agent: id, head };
37817
+ }
37728
37818
  updated() {
37729
37819
  this.#attach();
37730
37820
  const timed = this.isConnected && this.#timed();
@@ -38017,12 +38107,25 @@ var SliccChat = class _SliccChat extends ThemedElement {
38017
38107
  this.#seen = id;
38018
38108
  this.#all = false;
38019
38109
  this.#details.clear();
38110
+ this.#stopped.delete(id);
38020
38111
  }
38021
38112
  #probe() {
38022
38113
  if (this.#handlers.surface || this.#probed === this.color) return;
38023
38114
  this.#probed = this.color;
38024
38115
  this.#handlers.surface = readSurface(this.renderRoot);
38025
38116
  }
38117
+ #thread(items, older, blank2) {
38118
+ if (items.length)
38119
+ return b`<swc-conversation-thread>${c(
38120
+ items,
38121
+ ([key]) => key,
38122
+ ([, item2]) => item2
38123
+ )}</swc-conversation-thread>`;
38124
+ if (this.model?.tabs?.state().role === "connecting")
38125
+ return b`<div class="empty" data-connecting>${connecting}</div>`;
38126
+ if (this.model?.agent.starting?.() || older) return A;
38127
+ return b`<div class="empty" data-empty>${blank2}</div>`;
38128
+ }
38026
38129
  render() {
38027
38130
  this.#handlers.color = this.color;
38028
38131
  this.#handlers.model = this.model ?? null;
@@ -38037,8 +38140,10 @@ var SliccChat = class _SliccChat extends ThemedElement {
38037
38140
  const messages = agent ? this.model?.agent.messages(agent.id) ?? [] : [];
38038
38141
  this.#tail = messages.at(-1)?.id ?? "";
38039
38142
  const { items, asks } = dock(agent ? this.#items(messages, agent) : [], messages, seat);
38040
- const count2 = items.filter(([key]) => !key.startsWith("day:")).length;
38041
- if (!this.behind) this.#mark = count2;
38143
+ const keys = items.flatMap(([key]) => key.startsWith("day:") ? [] : [key]);
38144
+ if (!this.behind) this.#mark = keys.at(-1) ?? "";
38145
+ const seen = keys.lastIndexOf(this.#mark);
38146
+ const older = agent ? this.#olderRow(agent.id, messages[0]?.id ?? "") : A;
38042
38147
  return b`
38043
38148
  <header ?data-compact=${this.compact}>
38044
38149
  ${agent ? this.#meta(agent, !messages.length) : this.#agentless()}
@@ -38060,14 +38165,11 @@ var SliccChat = class _SliccChat extends ThemedElement {
38060
38165
  @pointerdown=${this.#hold}
38061
38166
  >
38062
38167
  <div class="column" @keydown=${this.#keys}>
38063
- ${items.length ? b`<swc-conversation-thread>${c(
38064
- items,
38065
- ([key]) => key,
38066
- ([, item2]) => item2
38067
- )}</swc-conversation-thread>` : this.model?.tabs?.state().role === "connecting" ? b`<div class="empty" data-connecting>${connecting}</div>` : this.model?.agent.starting?.() ? A : b`<div class="empty" data-empty>${empty3(watch2, seat, agent?.name ?? "the agent")}</div>`}
38168
+ ${older}
38169
+ ${this.#thread(items, older !== A, empty3(watch2, seat, agent?.name ?? "the agent"))}
38068
38170
  </div>
38069
38171
  </div>
38070
- ${this.behind ? this.#latest(count2 - this.#mark) : A}
38172
+ ${this.behind ? this.#latest(seen < 0 ? 0 : keys.length - 1 - seen) : A}
38071
38173
  </div>
38072
38174
  ${this.dropping ? b`<swc-dropzone dragged size="l" aria-label="Attach files" dragged-message="" data-surface="drop">
38073
38175
  <swc-illustrated-message>