@ai-ecoverse/slicc-spectrum 2.9.1 → 2.9.2

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
@@ -52732,6 +52732,38 @@ var verbs2 = {
52732
52732
  function describe(action) {
52733
52733
  return verbs2[action.kind](action);
52734
52734
  }
52735
+ function recentActions(all2, shown6) {
52736
+ return all2.slice(-shown6).reverse();
52737
+ }
52738
+ function sameAction(a20, b10) {
52739
+ return a20.status === "done" && b10.status === "done" && a20.kind === b10.kind && a20.agentId === b10.agentId && a20.target === b10.target && a20.value === b10.value && a20.length === b10.length;
52740
+ }
52741
+ function foldActions(actions2) {
52742
+ const out = [];
52743
+ for (const action of actions2) {
52744
+ const prev = out.at(-1);
52745
+ if (prev && sameAction(prev.action, action)) {
52746
+ prev.count += 1;
52747
+ continue;
52748
+ }
52749
+ out.push({ action, count: 1 });
52750
+ }
52751
+ return out;
52752
+ }
52753
+ function pickImage(frame, shot, watching) {
52754
+ if (watching && frame) return frame;
52755
+ if (frame && (!shot || frame.at >= shot.at)) return frame;
52756
+ return shot ?? null;
52757
+ }
52758
+ function frameSize(box, dpr = 1, prior) {
52759
+ if (!box?.width || !box.height) return null;
52760
+ const width = Math.max(1, Math.round(box.width * dpr));
52761
+ const height = Math.max(1, Math.round(box.height * dpr));
52762
+ const slack = Math.max(2, Math.round(2 * dpr));
52763
+ if (prior && Math.abs(prior.width - width) <= slack && Math.abs(prior.height - height) <= slack)
52764
+ return { width: prior.width, height: prior.height, key: `${prior.width}x${prior.height}` };
52765
+ return { width, height, key: `${width}x${height}` };
52766
+ }
52735
52767
  var icons = {
52736
52768
  open: b`<swc-icon-open-in size="s"></swc-icon-open-in>`,
52737
52769
  goto: b`<swc-icon-link size="s"></swc-icon-link>`,
@@ -52776,8 +52808,9 @@ var SliccBrowser = class extends ModelElement {
52776
52808
  #last = null;
52777
52809
  #shown = actionPage;
52778
52810
  #anchor = null;
52811
+ #display = /* @__PURE__ */ new Map();
52812
+ #loading = /* @__PURE__ */ new Map();
52779
52813
  #expanded = new ViewSet(this, "browser");
52780
- #recent = new ViewState(this, "browser:recent", () => false);
52781
52814
  #chosen = new ViewState(this, "browser:tab", () => void 0);
52782
52815
  #scroll = new ViewScroll(this, "browser:scroll", {
52783
52816
  scroller: () => this.renderRoot.querySelector(".cards")?.parentElement ?? null,
@@ -52956,24 +52989,31 @@ var SliccBrowser = class extends ModelElement {
52956
52989
  .focused {
52957
52990
  display: grid;
52958
52991
  grid-template-columns: minmax(0, 1fr);
52959
- gap: var(--swc-spacing-300);
52960
- padding: var(--swc-spacing-300);
52992
+ gap: var(--swc-spacing-200);
52993
+ height: 100%;
52994
+ min-height: 0;
52995
+ padding: var(--swc-spacing-200);
52996
+ box-sizing: border-box;
52961
52997
  }
52962
52998
  .focused.wide {
52963
52999
  grid-template-columns: minmax(180px, 240px) minmax(0, 1fr);
52964
- align-items: start;
53000
+ grid-template-rows: minmax(0, 1fr);
53001
+ align-items: stretch;
52965
53002
  }
52966
53003
  .detail {
52967
53004
  display: flex;
52968
53005
  flex-direction: column;
52969
- gap: var(--swc-spacing-200);
53006
+ gap: var(--swc-spacing-100);
52970
53007
  min-width: 0;
53008
+ min-height: 0;
53009
+ height: 100%;
52971
53010
  }
52972
53011
  .bar,
52973
53012
  .address {
52974
53013
  display: flex;
52975
53014
  align-items: center;
52976
53015
  gap: var(--swc-spacing-100);
53016
+ flex: none;
52977
53017
  min-width: 0;
52978
53018
  }
52979
53019
  .bar sp-picker {
@@ -52981,13 +53021,14 @@ var SliccBrowser = class extends ModelElement {
52981
53021
  min-width: 0;
52982
53022
  max-width: 100%;
52983
53023
  }
52984
- .url {
53024
+ .address .url {
52985
53025
  flex: 1;
52986
53026
  min-width: 0;
52987
53027
  font-family: var(--swc-code-font-family-stack);
52988
53028
  color: var(--swc-neutral-subdued-content-color-default);
52989
53029
  }
52990
53030
  .detail .driving {
53031
+ flex: none;
52991
53032
  flex-wrap: nowrap;
52992
53033
  min-block-size: var(--swc-component-height-75);
52993
53034
  }
@@ -52997,6 +53038,18 @@ var SliccBrowser = class extends ModelElement {
52997
53038
  .detail .driving swc-button {
52998
53039
  flex: none;
52999
53040
  }
53041
+ .detail figure {
53042
+ flex: 0 1 auto;
53043
+ width: 100%;
53044
+ max-height: min(50vh, 100%);
53045
+ }
53046
+ .detail .feed {
53047
+ display: flex;
53048
+ flex-direction: column;
53049
+ flex: 1 1 10rem;
53050
+ min-height: 8rem;
53051
+ min-width: 0;
53052
+ }
53000
53053
  .swc-Link {
53001
53054
  font-size: inherit;
53002
53055
  }
@@ -53004,6 +53057,9 @@ var SliccBrowser = class extends ModelElement {
53004
53057
  display: flex;
53005
53058
  flex-direction: column;
53006
53059
  gap: var(--swc-spacing-50);
53060
+ min-height: 0;
53061
+ overflow: auto;
53062
+ overscroll-behavior: contain;
53007
53063
  }
53008
53064
  .tabs button {
53009
53065
  display: grid;
@@ -53047,19 +53103,20 @@ var SliccBrowser = class extends ModelElement {
53047
53103
  flex-direction: column;
53048
53104
  gap: var(--swc-spacing-75);
53049
53105
  margin: 0;
53106
+ min-height: 0;
53050
53107
  }
53051
53108
  .frame {
53052
53109
  display: grid;
53053
53110
  place-items: center;
53111
+ box-sizing: border-box;
53054
53112
  aspect-ratio: 16 / 10;
53113
+ width: 100%;
53114
+ max-height: inherit;
53055
53115
  overflow: hidden;
53056
53116
  border: var(--swc-border-width-100) solid var(--swc-gray-200);
53057
53117
  border-radius: var(--swc-corner-radius-medium-default);
53058
53118
  background: var(--swc-card-background-well-color);
53059
53119
  }
53060
- .wide .frame {
53061
- max-height: 50vh;
53062
- }
53063
53120
  .frame img {
53064
53121
  width: 100%;
53065
53122
  height: 100%;
@@ -53068,6 +53125,7 @@ var SliccBrowser = class extends ModelElement {
53068
53125
  user-select: none;
53069
53126
  }
53070
53127
  figcaption {
53128
+ flex: none;
53071
53129
  min-block-size: var(--swc-component-height-50);
53072
53130
  display: flex;
53073
53131
  align-items: center;
@@ -53160,10 +53218,15 @@ var SliccBrowser = class extends ModelElement {
53160
53218
  white-space: normal;
53161
53219
  user-select: text;
53162
53220
  }
53221
+ .feed h3,
53222
+ .feed .more {
53223
+ flex: none;
53224
+ }
53163
53225
  .actions {
53164
53226
  display: flex;
53165
53227
  flex-direction: column;
53166
- max-height: 20rem;
53228
+ flex: 1;
53229
+ min-height: 0;
53167
53230
  overflow: auto;
53168
53231
  }
53169
53232
  .actions li {
@@ -53187,11 +53250,10 @@ var SliccBrowser = class extends ModelElement {
53187
53250
  min-width: 0;
53188
53251
  overflow-wrap: anywhere;
53189
53252
  }
53190
- .last .what > :not(.full),
53191
- .last .url-toggle > span {
53192
- overflow: hidden;
53193
- text-overflow: ellipsis;
53194
- white-space: nowrap;
53253
+ .count {
53254
+ margin-inline-start: var(--swc-spacing-100);
53255
+ color: var(--swc-neutral-subdued-content-color-default);
53256
+ font-weight: var(--swc-bold-font-weight);
53195
53257
  }
53196
53258
  .actions .failure {
53197
53259
  color: var(--swc-negative-content-color-default);
@@ -53253,6 +53315,8 @@ var SliccBrowser = class extends ModelElement {
53253
53315
  subscribe(model) {
53254
53316
  this.#shots.clear();
53255
53317
  this.#frames.clear();
53318
+ this.#display.clear();
53319
+ this.#loading.clear();
53256
53320
  this.#pulse.clear();
53257
53321
  this.#shown = actionPage;
53258
53322
  const tabs = model.browser.list();
@@ -53367,10 +53431,26 @@ var SliccBrowser = class extends ModelElement {
53367
53431
  this.#running = false;
53368
53432
  }
53369
53433
  #image(id) {
53370
- const frame = this.#frames.get(id);
53371
- const shot = this.#shots.get(id);
53372
- if (frame && (!shot || frame.at >= shot.at)) return frame;
53373
- return shot ?? null;
53434
+ return pickImage(this.#frames.get(id), this.#shots.get(id), this.#watching?.tabId === id);
53435
+ }
53436
+ #hold(id, src) {
53437
+ const shown6 = this.#display.get(id);
53438
+ if (shown6 === src) return src;
53439
+ if (!shown6) {
53440
+ this.#display.set(id, src);
53441
+ return src;
53442
+ }
53443
+ if (this.#loading.get(id) === src) return shown6;
53444
+ this.#loading.set(id, src);
53445
+ const probe = document.createElement("img");
53446
+ probe.onload = () => {
53447
+ if (this.#loading.get(id) !== src) return;
53448
+ this.#loading.delete(id);
53449
+ this.#display.set(id, src);
53450
+ this.requestUpdate();
53451
+ };
53452
+ probe.src = src;
53453
+ return shown6;
53374
53454
  }
53375
53455
  #show(id) {
53376
53456
  this.#chosen.value = id;
@@ -53400,29 +53480,39 @@ var SliccBrowser = class extends ModelElement {
53400
53480
  if (visible3 && tab && !this.#ticker)
53401
53481
  this.#ticker = setInterval(() => this.requestUpdate(), 1e3);
53402
53482
  if (!(visible3 && tab)) this.#still();
53403
- const list6 = this.renderRoot.querySelector(".actions:not(.last)");
53404
- const last = list6?.lastElementChild?.getAttribute("data-action-id") ?? null;
53405
- if (list6 && this.#anchor !== null) list6.scrollTop = list6.scrollHeight - this.#anchor;
53406
- else if (list6 && last !== this.#last) list6.scrollTop = list6.scrollHeight;
53483
+ const list6 = this.renderRoot.querySelector(".actions");
53484
+ const head = list6?.firstElementChild?.getAttribute("data-action-id") ?? null;
53485
+ if (list6 && this.#anchor !== null) list6.scrollTop = this.#anchor;
53486
+ else if (list6 && head !== this.#last) list6.scrollTop = 0;
53407
53487
  this.#anchor = null;
53408
- this.#last = last;
53488
+ this.#last = head;
53409
53489
  }
53410
53490
  #still() {
53411
53491
  if (this.#ticker) clearInterval(this.#ticker);
53412
53492
  this.#ticker = null;
53413
53493
  }
53414
53494
  #settle(id) {
53415
- const box = id ? this.renderRoot.querySelector(".frame")?.getBoundingClientRect() : void 0;
53416
- const size4 = box?.width ? { width: Math.round(box.width), height: Math.round(box.height) } : void 0;
53417
- const key = size4 ? `${size4.width}x${size4.height}` : "";
53418
- if (this.#watching?.tabId === id && this.#watching?.size === key) return;
53495
+ if (!id) {
53496
+ this.#watching?.stop();
53497
+ this.#watching = null;
53498
+ return;
53499
+ }
53500
+ const box = this.renderRoot.querySelector(".frame")?.getBoundingClientRect();
53501
+ const area = box ? { width: box.width, height: box.height } : null;
53502
+ const prior = this.#watching?.tabId === id ? this.#watching.pixels : null;
53503
+ const sized = frameSize(area, globalThis.devicePixelRatio || 1, prior);
53504
+ const key = sized?.key ?? (this.#watching?.tabId === id ? this.#watching.size : "");
53505
+ const pixels = sized ? { width: sized.width, height: sized.height } : this.#watching?.tabId === id ? this.#watching.pixels : { width: 0, height: 0 };
53506
+ if (this.#watching?.tabId === id && this.#watching.size === key) return;
53419
53507
  this.#watching?.stop();
53420
- this.#watching = null;
53421
- if (!id) return;
53422
53508
  this.#watching = {
53423
53509
  tabId: id,
53424
53510
  size: key,
53425
- stop: this.model.browser.watch?.(id, size4)
53511
+ pixels,
53512
+ stop: this.model.browser.watch?.(
53513
+ id,
53514
+ sized ? { width: sized.width, height: sized.height } : void 0
53515
+ )
53426
53516
  };
53427
53517
  }
53428
53518
  #open() {
@@ -53524,24 +53614,26 @@ var SliccBrowser = class extends ModelElement {
53524
53614
  #view(tab) {
53525
53615
  const image2 = this.#image(tab.id);
53526
53616
  const now = Date.now();
53527
- const view = !image2 ? "none" : this.#watching?.tabId === tab.id && this.#frames.get(tab.id) === image2 && now - image2.at < fresh ? "live" : "shot";
53617
+ const liveFrame = !!image2 && this.#watching?.tabId === tab.id && this.#frames.get(tab.id) === image2 && now - image2.at < fresh;
53618
+ const view = !image2 ? "none" : liveFrame ? "live" : "shot";
53619
+ const src = image2 ? this.#hold(tab.id, image2.src) : null;
53528
53620
  return b`<figure data-view=${view}>
53529
53621
  <div class="frame">
53530
- ${image2 ? b`<img src=${image2.src} alt=${`${tab.title}, as the agent sees it`} draggable="false" />` : b`<swc-progress-circle size="m" label="Loading preview"></swc-progress-circle>`}
53622
+ ${src ? b`<img src=${src} alt=${`${tab.title}, as the agent sees it`} draggable="false" />` : b`<swc-progress-circle size="m" label="Loading preview"></swc-progress-circle>`}
53531
53623
  </div>
53532
53624
  <figcaption>
53533
53625
  ${view === "live" ? b`<swc-status-light size="s" variant="positive">Live</swc-status-light>` : b`<span>${image2 ? since2(image2.at, now) : "No preview yet"}</span>`}
53534
- <span>View only</span>
53626
+ <span>Watching only</span>
53535
53627
  </figcaption>
53536
53628
  </figure>`;
53537
53629
  }
53538
53630
  #more(total) {
53539
- const list6 = this.renderRoot.querySelector(".actions:not(.last)");
53540
- this.#anchor = list6.scrollHeight - list6.scrollTop;
53631
+ const list6 = this.renderRoot.querySelector(".actions");
53632
+ this.#anchor = list6.scrollTop;
53541
53633
  this.#shown += actionPage;
53542
53634
  const done2 = this.#shown >= total;
53543
53635
  void this.updateComplete.then(() => {
53544
- if (done2) this.focusOn(".actions:not(.last)");
53636
+ if (done2) this.focusOn(".actions");
53545
53637
  });
53546
53638
  this.requestUpdate();
53547
53639
  }
@@ -53554,12 +53646,12 @@ var SliccBrowser = class extends ModelElement {
53554
53646
  const open = this.#expanded.has(action.id);
53555
53647
  return b`<button class="url-toggle" data-action="action-url" aria-expanded=${open ? "true" : "false"} aria-controls=${`url-${action.id}`} @click=${() => this.#toggle(action.id)}><span>${describe(action)}</span><swc-icon-chevron-down class="chevron" size="s" aria-hidden="true"></swc-icon-chevron-down></button>${open ? b`<span class="full" id=${`url-${action.id}`}>${url}</span>` : A}`;
53556
53648
  }
53557
- #row(action) {
53649
+ #row(action, count2 = 1) {
53558
53650
  const failed2 = action.status === "failed";
53559
53651
  const url = linked.has(action.kind) ? action.value : void 0;
53560
- return b`<li data-action-id=${action.id} data-kind=${action.kind} data-status=${action.status} title=${url ?? A}>
53652
+ return b`<li data-action-id=${action.id} data-kind=${action.kind} data-status=${action.status} ?data-group=${count2 > 1} title=${url ?? A}>
53561
53653
  <span>${action.status === "running" ? b`<swc-progress-circle size="s" indeterminate label="Running"></swc-progress-circle>` : failed2 ? b`<swc-icon-alert-triangle size="s" aria-label="Failed"></swc-icon-alert-triangle>` : icons[action.kind]}</span>
53562
- <span class="what">${this.#what(action)}${failed2 && action.error ? b`<span class="failure">${action.error}</span>` : A}</span>
53654
+ <span class="what">${this.#what(action)}${count2 > 1 ? b`<span class="count">×${count2}</span>` : A}${failed2 && action.error ? b`<span class="failure">${action.error}</span>` : A}</span>
53563
53655
  <span class="who">${agentName(this.model, action.agentId)} ${time(action.at)}</span>
53564
53656
  </li>`;
53565
53657
  }
@@ -53570,23 +53662,21 @@ var SliccBrowser = class extends ModelElement {
53570
53662
  (action) => action.tabId === tab.id || action.tabId === null && action.agentId !== null && action.agentId === tab.agentId
53571
53663
  );
53572
53664
  if (!all2.length)
53573
- return b`<h3>Recent actions</h3><p class="muted" data-actions="none">No actions yet.</p>`;
53574
- const actions2 = all2.slice(-this.#shown);
53665
+ return b`<div class="feed"><h3>Recent actions</h3><p class="muted" data-actions="none">No actions yet.</p></div>`;
53666
+ const actions2 = recentActions(all2, this.#shown);
53667
+ const folded = foldActions(actions2);
53575
53668
  const more = all2.length > actions2.length ? b`<div class="more"><span>Showing the latest ${actions2.length} of ${all2.length}</span><swc-button size="s" variant="secondary" fill-style="outline" data-action="more-actions" @click=${() => this.#more(all2.length)}>Show more</swc-button></div>` : A;
53576
- if (this.#width >= narrowWidth)
53577
- return b`<h3>Recent actions</h3>${more}<ol class="actions" aria-label="Recent actions" tabindex="0">${actions2.map((action) => this.#row(action))}</ol>`;
53578
- const last = actions2.at(-1);
53579
- return b`<details ?open=${this.#recent.value} @toggle=${(event2) => this.#recent.value = event2.currentTarget.open}>
53580
- <summary><swc-icon-chevron-right class="chevron" size="s" aria-hidden="true"></swc-icon-chevron-right>Recent actions (${all2.length})</summary>
53581
- ${more}
53582
- <ol class="actions" aria-label="Earlier actions" tabindex="0">${actions2.slice(0, -1).map((action) => this.#row(action))}</ol>
53583
- </details>
53584
- <ol class="actions last" aria-label="Last action">${this.#row(last)}</ol>`;
53669
+ return b`<div class="feed">
53670
+ <h3>Recent actions</h3>
53671
+ ${more}
53672
+ <ol class="actions" aria-label="Recent actions" tabindex="0">${folded.map((item2) => this.#row(item2.action, item2.count))}</ol>
53673
+ </div>`;
53585
53674
  }
53586
53675
  #detail(tabs, tab) {
53587
53676
  const narrow = this.#width < narrowWidth;
53588
53677
  const wide2 = this.#width >= wideWidth;
53589
53678
  const copy = this.#copied === "url" ? "Copied" : this.#copied === "failed" ? "Couldn\u2019t copy" : "Copy";
53679
+ const watching = tab.controlled ? tab.agentId ? `Watching ${agentName(this.model, tab.agentId)}` : "In use" : "No agent is using this tab";
53590
53680
  return b`<div class=${`focused${wide2 ? " wide" : ""}${narrow ? " narrow" : ""}`}>
53591
53681
  ${wide2 ? this.#list(tabs, tab) : A}
53592
53682
  <section class="detail" aria-label=${tab.title}>
@@ -53605,7 +53695,7 @@ var SliccBrowser = class extends ModelElement {
53605
53695
  <swc-action-button size="s" quiet data-action="open-tab" accessible-label="Show in the browser" @click=${() => this.model?.browser.activate(tab.id)}><swc-icon-open-in slot="icon"></swc-icon-open-in>${narrow ? A : "Open"}</swc-action-button>
53606
53696
  </div>
53607
53697
  <div class="driving" data-driving=${tab.controlled ? tab.agentId ? "agent" : "user" : "none"}>
53608
- <swc-status-light size="m" variant=${tab.controlled ? "info" : "neutral"}>${tab.controlled ? this.#who(tab) : "No agent is using this tab"}</swc-status-light>
53698
+ <swc-status-light size="m" variant=${tab.controlled ? "info" : "neutral"}>${watching}</swc-status-light>
53609
53699
  ${tab.controlled ? this.#stopButton(tab, '[data-action="all-tabs"]') : A}
53610
53700
  </div>
53611
53701
  ${this.#view(tab)}
@@ -53634,7 +53724,7 @@ var SliccBrowser = class extends ModelElement {
53634
53724
  const tabs = this.model?.browser.list() ?? [];
53635
53725
  if (!tabs.length && this.model?.network?.status().browser?.via === null) return this.#offline();
53636
53726
  const tab = tabs.find((candidate) => candidate.id === this.#focus);
53637
- return tab ? b`<div class="scroll">${this.#detail(tabs, tab)}</div>` : this.#overview(tabs);
53727
+ return tab ? this.#detail(tabs, tab) : this.#overview(tabs);
53638
53728
  }
53639
53729
  };
53640
53730