@ai-ecoverse/slicc-spectrum 1.65.0 → 1.65.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
@@ -24,7 +24,7 @@ import {
24
24
  } from "./chunk-EN3XGF2M.js";
25
25
  import {
26
26
  define
27
- } from "./chunk-XI74SELH.js";
27
+ } from "./chunk-ZGJM5WUN.js";
28
28
  import {
29
29
  isVaultFailure,
30
30
  nameProblem,
@@ -9548,100 +9548,499 @@ function prompt(options) {
9548
9548
  return element2.result;
9549
9549
  }
9550
9550
 
9551
- // node_modules/@adobe/spectrum-wc-icons/dist/AlertDiamond.js
9552
- function e74() {
9553
- return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path fill="var(--swc-icon-color, currentColor)" d="M10 18.795a2.24 2.24 0 0 1-1.591-.66l-6.545-6.544a2.254 2.254 0 0 1 0-3.182l6.545-6.545c.849-.85 2.333-.85 3.182 0l6.545 6.545a2.254 2.254 0 0 1 0 3.182l-6.545 6.545c-.425.425-.99.659-1.591.659m0-16.09c-.2 0-.389.078-.53.22L2.925 9.47a.75.75 0 0 0 0 1.06l6.545 6.545a.77.77 0 0 0 1.06 0l6.545-6.545a.75.75 0 0 0 0-1.06L10.53 2.925a.75.75 0 0 0-.53-.22"/><path fill="var(--swc-icon-color, currentColor)" d="M10 14.998a.9.9 0 0 1-.627-.228.956.956 0 0 1 0-1.285.87.87 0 0 1 .626-.234c.237-.01.466.08.633.247a.86.86 0 0 1 .242.627.88.88 0 0 1-.228.639.86.86 0 0 1-.647.234M10 11.625a.75.75 0 0 1-.75-.75v-5a.75.75 0 0 1 1.5 0v5a.75.75 0 0 1-.75.75"/></svg>';
9551
+ // node_modules/@adobe/spectrum-wc/dist/components/progress-circle/progress-circle.js
9552
+ var t45 = i`@keyframes swc-fills-rotate{0%{transform:rotate(var(--swc-progress-circle-rotate-start, -90deg))}to{transform:rotate(var(--swc-progress-circle-rotate-end, 270deg))}}@keyframes swc-dashoffset-animation{0%,to{stroke-dashoffset:75px}30%{stroke-dashoffset:var(--swc-progress-circle-dashoffset-30, 20px)}}:host{display:inline-block;align-self:center;justify-self:center;place-self:center}*{box-sizing:border-box}.swc-ProgressCircle{--_swc-progress-circle-size: var(--swc-progress-circle-size, var(--swc-progress-circle-size-medium));--_swc-progress-circle-track-border-color: var(--swc-progress-circle-track-border-color, var(--swc-gray-300));--_swc-progress-circle-fill-border-color: var(--swc-progress-circle-fill-border-color, var(--swc-accent-color-900));--_swc-progress-circle-thickness: var(--swc-progress-circle-thickness, var(--swc-progress-circle-thickness-medium));display:inline-block;position:relative;inline-size:var(--_swc-progress-circle-size);block-size:var(--_swc-progress-circle-size);direction:ltr;transform:translateZ(0)}.swc-ProgressCircle-fill,.swc-ProgressCircle-track{inline-size:var(--_swc-progress-circle-size);block-size:var(--_swc-progress-circle-size)}.swc-ProgressCircle-track{stroke:var(--_swc-progress-circle-track-border-color);stroke-width:var(--_swc-progress-circle-thickness)}.swc-ProgressCircle-fill{stroke:var(--_swc-progress-circle-fill-border-color);stroke-width:var(--_swc-progress-circle-thickness);transform:rotate(-90deg);transform-origin:center}.swc-ProgressCircle--indeterminate .swc-ProgressCircle-fill{transform-origin:center;animation:swc-fills-rotate 1s cubic-bezier(.6,.1,.3,.9) infinite,swc-dashoffset-animation 1s cubic-bezier(.25,.1,.25,1.3) infinite;will-change:transform}:host([size=\"s\"]){--swc-progress-circle-size: var(--swc-progress-circle-size-small);--swc-progress-circle-thickness: var(--swc-progress-circle-thickness-small)}:host([size=\"l\"]){--swc-progress-circle-size: var(--swc-progress-circle-size-large);--swc-progress-circle-thickness: var(--swc-progress-circle-thickness-large)}.swc-ProgressCircle:where(.swc-ProgressCircle--staticWhite){--swc-progress-circle-track-border-color: var(--swc-transparent-white-300);--swc-progress-circle-fill-border-color: var(--swc-transparent-white-900)}.swc-ProgressCircle:where(.swc-ProgressCircle--staticBlack){--swc-progress-circle-track-border-color: var(--swc-transparent-black-300);--swc-progress-circle-fill-border-color: var(--swc-transparent-black-900)}@media(prefers-reduced-motion:reduce){.swc-ProgressCircle--indeterminate .swc-ProgressCircle-fill{--swc-progress-circle-dashoffset-30: 0;--swc-progress-circle-rotate-start: 0deg;--swc-progress-circle-rotate-end: 360deg;animation-duration:15s;animation-timing-function:linear,linear}}@media(forced-colors:active){.swc-ProgressCircle{--swc-progress-circle-fill-border-color: Highlight;@media(prefers-color-scheme:dark){--swc-progress-circle-track-border-color: var(--swc-transparent-white-300)}@media(prefers-color-scheme:light){--swc-progress-circle-track-border-color: var(--swc-transparent-black-300)}}}`;
9553
+
9554
+ // node_modules/@adobe/spectrum-wc-core/dist/components/progress-circle/ProgressCircle.types.js
9555
+ var e74 = [
9556
+ "s",
9557
+ "m",
9558
+ "l"
9559
+ ];
9560
+ var t46 = ["white", "black"];
9561
+
9562
+ // node_modules/@adobe/spectrum-wc-core/dist/components/progress-circle/ProgressCircle.base.js
9563
+ var u16;
9564
+ var d13 = class e75 extends i12(i9, { validSizes: e74 }) {
9565
+ constructor(...e119) {
9566
+ super(...e119), this.label = "", this.progress = null, this.languageResolver = new i10(this);
9567
+ }
9568
+ static hasMeaningfulLightDomChildren(e119) {
9569
+ for (let n36 of e119.childNodes) {
9570
+ var t88;
9571
+ if (n36.nodeType === Node.ELEMENT_NODE || n36.nodeType === Node.TEXT_NODE && (t88 = n36.textContent) != null && t88.trim()) return true;
9572
+ }
9573
+ return false;
9574
+ }
9575
+ hasAccessibleName() {
9576
+ return !!(this.label || this.getAttribute("aria-label") || this.getAttribute("aria-labelledby"));
9577
+ }
9578
+ static clampProgress(e119) {
9579
+ return Number.isFinite(e119) ? Math.min(100, Math.max(0, e119)) : 0;
9580
+ }
9581
+ formatProgress() {
9582
+ var e119;
9583
+ return new Intl.NumberFormat(this.languageResolver.language, {
9584
+ style: "percent",
9585
+ unitDisplay: "narrow"
9586
+ }).format(((e119 = this.progress) == null ? 0 : e119) / 100);
9587
+ }
9588
+ warnDeprecatedLightDomChildren() {
9589
+ r9(this, e75.hasMeaningfulLightDomChildren(this), `<${this.localName}> no longer has a default slot. Light DOM children are not rendered and are not used for an accessible name. Use the "label" attribute or property, or "aria-label" / "aria-labelledby" on the host instead.`, "https://spectrum-web-components.adobe.com/?path=/docs/components-progress-circle--docs", { level: "deprecation" });
9590
+ }
9591
+ willUpdate(t88) {
9592
+ if (t88.has("progress") && this.progress !== null) {
9593
+ let t89 = e75.clampProgress(this.progress);
9594
+ t89 !== this.progress && (this.progress = t89);
9595
+ }
9596
+ super.willUpdate(t88);
9597
+ }
9598
+ firstUpdated(e119) {
9599
+ super.firstUpdated(e119), this.setAttribute("role", "progressbar");
9600
+ }
9601
+ updated(t88) {
9602
+ if (super.updated(t88), t88.has("progress") && (this.progress !== null && this.progress >= 0 ? (this.setAttribute("aria-valuemin", "0"), this.setAttribute("aria-valuemax", "100"), this.setAttribute("aria-valuenow", String(this.progress)), this.setAttribute("aria-valuetext", this.formatProgress())) : (this.removeAttribute("aria-valuemin"), this.removeAttribute("aria-valuemax"), this.removeAttribute("aria-valuenow"), this.removeAttribute("aria-valuetext"))), this.progress !== null && t88.has(e27) && this.setAttribute("aria-valuetext", this.formatProgress()), t88.has("label") && (this.label.length ? this.setAttribute("aria-label", this.label) : t88.get("label") === this.getAttribute("aria-label") && this.removeAttribute("aria-label")), t88.has("label") && !this.hasAccessibleName() && (this.setAttribute("aria-label", e75.DEFAULT_LABEL), r9(this, true, `<${this.localName}> requires an accessible name. A default label of "${e75.DEFAULT_LABEL}" has been applied, but a more specific label should be provided via:`, "https://spectrum-web-components.adobe.com/?path=/docs/components-progress-circle--docs", {
9603
+ type: "accessibility",
9604
+ issues: [
9605
+ 'value supplied to the "label" attribute, which will be displayed visually as part of the element, or',
9606
+ 'value supplied to the "aria-label" attribute, which will only be provided to screen readers, or',
9607
+ 'an element ID reference supplied to the "aria-labelledby" attribute, which will be provided by screen readers and will need to be managed manually by the parent application.'
9608
+ ]
9609
+ })), t88.has("staticColor") && this.staticColor !== void 0) {
9610
+ let e119 = this.constructor;
9611
+ n10(this, {
9612
+ prop: "static-color",
9613
+ value: this.staticColor,
9614
+ valid: e119.STATIC_COLORS,
9615
+ url: "https://spectrum-web-components.adobe.com/?path=/docs/components-progress-circle--docs"
9616
+ });
9617
+ }
9618
+ t14() && this.warnDeprecatedLightDomChildren();
9619
+ }
9620
+ };
9621
+ u16 = d13, u16.DEFAULT_LABEL = "Loading", e24([n({
9622
+ type: String,
9623
+ reflect: true,
9624
+ attribute: "static-color"
9625
+ })], d13.prototype, "staticColor", void 0), e24([n({ type: String })], d13.prototype, "label", void 0), e24([n({
9626
+ type: Number,
9627
+ reflect: true
9628
+ })], d13.prototype, "progress", void 0);
9629
+
9630
+ // node_modules/@adobe/spectrum-wc/dist/components/progress-circle/ProgressCircle.js
9631
+ var l14;
9632
+ var u17 = class extends d13 {
9633
+ static get styles() {
9634
+ return [t45];
9635
+ }
9636
+ computeDashOffset() {
9637
+ if (this.progress !== null) return this.progress === 0 ? 98 : 100 - this.progress;
9638
+ }
9639
+ render() {
9640
+ let e119 = this.size === "s" ? 2 : this.size === "l" ? 6 : 4, t88 = `calc(50% - ${e119 / 2}px)`;
9641
+ return b`
9642
+ <div
9643
+ class=${e3({
9644
+ "swc-ProgressCircle": true,
9645
+ "swc-ProgressCircle--indeterminate": this.progress === null,
9646
+ [`swc-ProgressCircle--static${e14(this.staticColor)}`]: this.staticColor !== void 0
9647
+ })}
9648
+ >
9649
+ <svg aria-hidden="true" fill="none" width="100%" height="100%">
9650
+ <circle
9651
+ cx="50%"
9652
+ cy="50%"
9653
+ r=${`calc(50% - ${e119}px)`}
9654
+ stroke-width=${e119}
9655
+ />
9656
+ <circle
9657
+ cx="50%"
9658
+ cy="50%"
9659
+ class="swc-ProgressCircle-track"
9660
+ r=${t88}
9661
+ />
9662
+ <circle
9663
+ cx="50%"
9664
+ cy="50%"
9665
+ r=${t88}
9666
+ class="swc-ProgressCircle-fill"
9667
+ pathLength="100"
9668
+ stroke-dasharray="100 200"
9669
+ stroke-dashoffset=${o2(this.computeDashOffset())}
9670
+ stroke-linecap="round"
9671
+ />
9672
+ </svg>
9673
+ </div>
9674
+ `;
9675
+ }
9676
+ };
9677
+ l14 = u17, l14.STATIC_COLORS = t46, e12([n({
9678
+ reflect: true,
9679
+ attribute: "static-color"
9680
+ })], u17.prototype, "staticColor", void 0);
9681
+
9682
+ // node_modules/@adobe/spectrum-wc/dist/components/progress-circle/swc-progress-circle.js
9683
+ e25("swc-progress-circle", u17);
9684
+
9685
+ // node_modules/@adobe/spectrum-wc-icons/dist/AlertTriangle.js
9686
+ function e76() {
9687
+ return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path fill="var(--swc-icon-color, currentColor)" d="M10 15.123a.9.9 0 0 1-.627-.228.956.956 0 0 1 0-1.285.87.87 0 0 1 .626-.234c.237-.01.466.08.633.247a.86.86 0 0 1 .242.627.88.88 0 0 1-.228.639.86.86 0 0 1-.647.234M10 11.75a.75.75 0 0 1-.75-.75V7a.75.75 0 0 1 1.5 0v4a.75.75 0 0 1-.75.75"/><path fill="var(--swc-icon-color, currentColor)" d="M16.733 18H3.267c-.8 0-1.523-.41-1.933-1.098s-.427-1.518-.046-2.222L8.02 2.232a2.248 2.248 0 0 1 3.958 0l6.733 12.448c.381.704.364 1.535-.046 2.222S17.534 18 16.733 18M10 2.553a.73.73 0 0 0-.66.392L2.607 15.393a.74.74 0 0 0 .016.74.74.74 0 0 0 .644.367h13.466a.74.74 0 0 0 .644-.366.74.74 0 0 0 .016-.741L10.66 2.945a.73.73 0 0 0-.66-.392"/></svg>';
9554
9688
  }
9555
9689
 
9556
- // node_modules/@adobe/spectrum-wc-icons/dist/swc-icon-alert-diamond.js
9690
+ // node_modules/@adobe/spectrum-wc-icons/dist/swc-icon-alert-triangle.js
9557
9691
  var o47 = class extends a10 {
9558
9692
  static get styles() {
9559
9693
  return [t40];
9560
9694
  }
9561
9695
  render() {
9562
9696
  return b`
9563
- <span class="swc-Icon">${o16(e74())}</span>
9697
+ <span class="swc-Icon">${o16(e76())}</span>
9564
9698
  `;
9565
9699
  }
9566
9700
  };
9567
- e25("swc-icon-alert-diamond", o47);
9701
+ e25("swc-icon-alert-triangle", o47);
9568
9702
 
9569
- // node_modules/@adobe/spectrum-wc-icons/dist/FolderAdd.js
9570
- function e75() {
9571
- return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path fill="var(--swc-icon-color, currentColor)" d="M8.373 15.498H3.25a.75.75 0 0 1-.75-.75v-8.25h14.25a.75.75 0 0 1 .75.75V9.07a.75.75 0 0 0 1.5 0V7.248c0-1.24-1.01-2.25-2.25-2.25h-5.964a.75.75 0 0 1-.566-.258L8.515 2.773a2.25 2.25 0 0 0-1.7-.775H3.25C2.01 1.998 1 3.008 1 4.248v10.5c0 1.24 1.01 2.25 2.25 2.25h5.123a.75.75 0 0 0 0-1.5m-5.123-12h3.565a.75.75 0 0 1 .567.258l1.076 1.242H2.5v-.75a.75.75 0 0 1 .75-.75"/><path fill="var(--swc-icon-color, currentColor)" d="M15 10.498a4.5 4.5 0 1 0 0 9 4.5 4.5 0 0 0 0-9m2.5 5.125h-1.875v1.875a.625.625 0 1 1-1.25 0v-1.875H12.5a.625.625 0 1 1 0-1.25h1.875v-1.875a.625.625 0 1 1 1.25 0v1.875H17.5a.625.625 0 1 1 0 1.25"/></svg>';
9703
+ // node_modules/@adobe/spectrum-wc-icons/dist/UserFollowing.js
9704
+ function e77() {
9705
+ return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path fill="var(--swc-icon-color, currentColor)" d="M15 10.5a4.5 4.5 0 1 0 0 9 4.5 4.5 0 0 0 0-9m2.4 3.35L15.09 17a.623.623 0 0 1-.968.048l-1.439-1.599a.625.625 0 0 1 .93-.836l.924 1.028 1.855-2.53a.625.625 0 1 1 1.007.74M2.274 18.752a.75.75 0 0 1-.733-.91c.596-2.73 3.313-5.025 6.608-5.58a.75.75 0 0 1 .249 1.48c-2.706.455-4.923 2.273-5.391 4.42a.75.75 0 0 1-.733.59m7.726-7.9c-2.485 0-4.507-2.153-4.507-4.8s2.022-4.8 4.507-4.8 4.507 2.153 4.507 4.8-2.022 4.8-4.507 4.8m0-8.1c-1.658 0-3.007 1.48-3.007 3.3s1.349 3.3 3.007 3.3 3.007-1.48 3.007-3.3-1.349-3.3-3.007-3.3"/></svg>';
9572
9706
  }
9573
9707
 
9574
- // node_modules/@adobe/spectrum-wc-icons/dist/swc-icon-folder-add.js
9708
+ // node_modules/@adobe/spectrum-wc-icons/dist/swc-icon-user-following.js
9575
9709
  var o48 = class extends a10 {
9576
9710
  static get styles() {
9577
9711
  return [t40];
9578
9712
  }
9579
9713
  render() {
9580
9714
  return b`
9581
- <span class="swc-Icon">${o16(e75())}</span>
9715
+ <span class="swc-Icon">${o16(e77())}</span>
9582
9716
  `;
9583
9717
  }
9584
9718
  };
9585
- e25("swc-icon-folder-add", o48);
9719
+ e25("swc-icon-user-following", o48);
9586
9720
 
9587
- // src/app/files.ts
9588
- function relative(path) {
9589
- return path.replace(/^\//, "");
9590
- }
9591
- function basename(path) {
9592
- return path.slice(path.lastIndexOf("/") + 1);
9721
+ // src/app/follow.ts
9722
+ var lights = {
9723
+ connecting: ["info", (owner) => `Connecting to ${owner}`],
9724
+ connected: ["positive", (owner) => `Following ${owner}`],
9725
+ reconnecting: ["notice", (owner) => `Reconnecting to ${owner}`],
9726
+ unlinked: ["negative", (owner) => `Unlinked from ${owner}`],
9727
+ failed: ["negative", (owner) => `Can\u2019t reach ${owner}`]
9728
+ };
9729
+ function followLight(state3) {
9730
+ const [variant, text2] = lights[state3.link];
9731
+ return { variant, text: text2(state3.owner) };
9593
9732
  }
9594
- function treePaths(entries) {
9595
- return entries.map((entry) => relative(entry.path) + (entry.kind === "directory" ? "/" : ""));
9733
+ function followPage(state3) {
9734
+ if (!state3) return null;
9735
+ const { owner } = state3;
9736
+ if (state3.link === "connecting")
9737
+ return {
9738
+ kind: "connecting",
9739
+ title: `Connecting to ${owner}\u2026`,
9740
+ body: `This device follows ${owner}. Its agent shows here once it\u2019s connected.`
9741
+ };
9742
+ if (state3.link === "unlinked")
9743
+ return {
9744
+ kind: "unlinked",
9745
+ title: `${owner} unlinked this device`,
9746
+ body: `To follow it again, open a new link from ${owner}.`
9747
+ };
9748
+ if (state3.link === "failed")
9749
+ return {
9750
+ kind: "failed",
9751
+ title: `Can\u2019t follow ${owner}`,
9752
+ body: state3.error ?? `The link to ${owner} failed.`
9753
+ };
9754
+ if (state3.access.view) return null;
9755
+ const where2 = state3.name ? `next to ${state3.name}` : "for this device";
9756
+ return {
9757
+ kind: "waiting",
9758
+ title: `Waiting for ${owner} to allow this device`,
9759
+ body: `On ${owner}, choose Allow ${where2} in Network \u203A Linked devices.`
9760
+ };
9596
9761
  }
9597
- function treeStatus(changes2) {
9598
- return changes2.map((change) => ({ path: relative(change.path), status: change.status }));
9762
+ function list(items, last) {
9763
+ if (items.length < 2) return items.join("");
9764
+ return `${items.slice(0, -1).join(", ")} ${last} ${items.at(-1)}`;
9599
9765
  }
9600
- function ancestors(paths) {
9601
- const out = /* @__PURE__ */ new Set();
9602
- for (const path of paths) {
9603
- const parts2 = relative(path).split("/").slice(0, -1);
9604
- for (let i25 = 1; i25 <= parts2.length; i25++) out.add(parts2.slice(0, i25).join("/"));
9605
- }
9606
- return [...out];
9766
+ function followCan(state3) {
9767
+ const allowed = ["watch the agent"];
9768
+ const missing = [];
9769
+ (state3.access.control ? allowed : missing).push("send prompts");
9770
+ (state3.access.terminal ? allowed : missing).push("open terminals");
9771
+ const can = `This device can ${list(allowed, "and")}.`;
9772
+ return missing.length ? `${can} To ${list(missing, "or")}, allow it on ${state3.owner}.` : can;
9607
9773
  }
9608
- function agentName(model, id) {
9609
- if (!id) return "you";
9610
- return model?.agent.list().find((agent) => agent.id === id)?.name ?? id;
9774
+ function following(model) {
9775
+ const state3 = model?.follow?.state();
9776
+ return state3 && !followPage(state3) ? state3 : null;
9611
9777
  }
9612
- function author(model, change) {
9613
- return change.agentId === null && change.repo ? null : agentName(model, change.agentId);
9778
+ function watchOnly(model) {
9779
+ const state3 = following(model);
9780
+ if (!state3 || state3.access.control) return "";
9781
+ return `Watch only. To send prompts from this device, allow Control for it on ${state3.owner}.`;
9614
9782
  }
9615
- function request(target, type, path) {
9616
- target.dispatchEvent(new CustomEvent(type, { detail: { path }, bubbles: true, composed: true }));
9783
+ function terminalsAllowed(model) {
9784
+ const state3 = model?.follow?.state();
9785
+ return !state3 || !!state3.access.terminal;
9617
9786
  }
9618
- var panelCss = i`
9619
- :host {
9620
- display: flex;
9621
- flex-direction: column;
9622
- height: 100%;
9623
- min-height: 0;
9624
- background: var(--swc-background-layer-2-color);
9625
- color: var(--swc-neutral-content-color-default);
9626
- font-family: var(--swc-sans-font-family-stack);
9627
- font-size: var(--swc-font-size-75);
9628
- }
9629
- .bar {
9630
- display: flex;
9631
- align-items: center;
9632
- gap: var(--swc-spacing-100);
9633
- flex: none;
9634
- min-height: var(--swc-component-height-100);
9635
- padding: 0 var(--swc-spacing-100) 0 var(--swc-spacing-200);
9636
- border-bottom: var(--swc-border-width-100) solid var(--swc-gray-200);
9637
- background: var(--swc-background-layer-1-color);
9638
- color: var(--swc-neutral-subdued-content-color-default);
9639
- white-space: nowrap;
9640
- overflow: hidden;
9787
+ var SliccFollow = class extends ModelElement {
9788
+ static properties = {
9789
+ ...ModelElement.properties,
9790
+ page: { type: Boolean, reflect: true },
9791
+ compact: { type: Boolean, reflect: true },
9792
+ busy: { state: true },
9793
+ error: { state: true }
9794
+ };
9795
+ constructor() {
9796
+ super();
9797
+ this.page = false;
9798
+ this.compact = false;
9799
+ this.busy = "";
9800
+ this.error = "";
9641
9801
  }
9642
- .bar .path {
9643
- font-family: var(--swc-code-font-family-stack);
9644
- color: var(--swc-neutral-content-color-default);
9802
+ static styles = [
9803
+ shared,
9804
+ i`
9805
+ :host {
9806
+ display: inline-block;
9807
+ }
9808
+ :host([page]) {
9809
+ display: block;
9810
+ max-width: 480px;
9811
+ }
9812
+ .chip swc-status-light {
9813
+ align-self: center;
9814
+ }
9815
+ :host([compact]) .chip .text {
9816
+ display: none;
9817
+ }
9818
+ .panel {
9819
+ display: grid;
9820
+ gap: var(--swc-spacing-200);
9821
+ width: calc(var(--swc-spacing-400) * 11);
9822
+ max-width: 100%;
9823
+ padding: var(--swc-spacing-300);
9824
+ box-sizing: border-box;
9825
+ font-size: var(--swc-font-size-100);
9826
+ color: var(--swc-neutral-content-color-default);
9827
+ }
9828
+ h2 {
9829
+ margin: 0;
9830
+ font-size: var(--swc-font-size-300);
9831
+ font-weight: var(--swc-bold-font-weight);
9832
+ line-height: var(--swc-heading-line-height);
9833
+ color: var(--swc-heading-color);
9834
+ }
9835
+ .page h2 {
9836
+ font-size: var(--swc-font-size-500);
9837
+ }
9838
+ .page > p {
9839
+ font-size: var(--swc-font-size-200);
9840
+ }
9841
+ .panel h2 {
9842
+ font-size: var(--swc-font-size-100);
9843
+ }
9844
+ p {
9845
+ margin: 0;
9846
+ }
9847
+ .muted {
9848
+ color: var(--swc-neutral-subdued-content-color-default);
9849
+ }
9850
+ .page {
9851
+ display: grid;
9852
+ gap: var(--swc-spacing-300);
9853
+ justify-items: center;
9854
+ text-align: center;
9855
+ }
9856
+ .actions {
9857
+ display: flex;
9858
+ flex-wrap: wrap;
9859
+ justify-content: center;
9860
+ gap: var(--swc-spacing-200);
9861
+ }
9862
+ .panel .actions {
9863
+ justify-content: flex-start;
9864
+ }
9865
+ .error {
9866
+ display: flex;
9867
+ align-items: flex-start;
9868
+ gap: var(--swc-spacing-75);
9869
+ color: var(--swc-negative-content-color-default);
9870
+ --swc-icon-color: var(--swc-negative-content-color-default);
9871
+ }
9872
+ `
9873
+ ];
9874
+ subscribe(model) {
9875
+ const port = model.follow;
9876
+ return port ? [port.on("follow", () => this.requestUpdate())] : [];
9877
+ }
9878
+ async leave() {
9879
+ const port = this.model?.follow;
9880
+ if (!port || this.busy) return;
9881
+ const state3 = port.state();
9882
+ if (state3.link !== "unlinked") {
9883
+ const ok2 = await confirm({
9884
+ title: `Stop following ${state3.owner}?`,
9885
+ body: `This device forgets the link. To follow ${state3.owner} again, open a new link from it.`,
9886
+ action: "Leave",
9887
+ variant: "confirmation"
9888
+ });
9889
+ if (!ok2) return;
9890
+ }
9891
+ await this.#run("leave", () => port.leave());
9892
+ }
9893
+ async retry() {
9894
+ const port = this.model?.follow;
9895
+ if (!port?.retry || this.busy) return;
9896
+ await this.#run("retry", () => port.retry?.());
9897
+ }
9898
+ async #run(busy, task) {
9899
+ this.busy = busy;
9900
+ this.error = "";
9901
+ try {
9902
+ await task();
9903
+ } catch (error) {
9904
+ this.error = error instanceof Error ? error.message : String(error);
9905
+ } finally {
9906
+ this.busy = "";
9907
+ }
9908
+ }
9909
+ #error() {
9910
+ return this.error ? b`<p class="error" role="alert" data-error><swc-icon-alert-triangle size="s" aria-hidden="true"></swc-icon-alert-triangle><span>${this.error}</span></p>` : A;
9911
+ }
9912
+ #leaveButton() {
9913
+ return b`<swc-button size="m" variant="secondary" fill-style="outline" data-action="leave" ?pending=${this.busy === "leave"} ?disabled=${!!this.busy && this.busy !== "leave"} @click=${() => this.leave()}>Leave</swc-button>`;
9914
+ }
9915
+ #page(page) {
9916
+ return b`<div class="page" data-follow-page=${page.kind}>
9917
+ ${page.kind === "connecting" || page.kind === "waiting" ? b`<swc-progress-circle size="m" indeterminate label=${page.kind === "waiting" ? "Waiting" : "Connecting"} aria-hidden="true"></swc-progress-circle>` : A}
9918
+ <h2 aria-live="polite">${page.title}</h2>
9919
+ <p class="muted">${page.body}</p>
9920
+ ${this.#error()}
9921
+ <div class="actions">
9922
+ ${page.kind === "failed" && this.model?.follow?.retry ? b`<swc-button size="m" variant="accent" data-action="retry" ?pending=${this.busy === "retry"} ?disabled=${!!this.busy && this.busy !== "retry"} @click=${() => this.retry()}>Try again</swc-button>` : A}
9923
+ ${this.#leaveButton()}
9924
+ </div>
9925
+ </div>`;
9926
+ }
9927
+ render() {
9928
+ const state3 = this.model?.follow?.state();
9929
+ if (!state3) return A;
9930
+ const page = followPage(state3);
9931
+ if (this.page) return page ? this.#page(page) : A;
9932
+ const light = followLight(state3);
9933
+ return b`<swc-action-button id="chip" class="chip" size="s" quiet data-follow=${state3.link} accessible-label=${light.text}>
9934
+ ${this.compact ? b`<swc-icon-user-following slot="icon" size="s" aria-hidden="true"></swc-icon-user-following>` : A}
9935
+ <swc-status-light size="s" variant=${light.variant}><span class="text">${light.text}</span></swc-status-light>
9936
+ </swc-action-button>
9937
+ <swc-tooltip for="chip" placement="bottom">${light.text}</swc-tooltip>
9938
+ <swc-popover for="chip" placement="bottom-end" accessible-label=${light.text}>
9939
+ <div class="panel">
9940
+ <h2>${light.text}</h2>
9941
+ ${state3.link === "reconnecting" ? b`<p class="muted" data-reconnecting>The link to ${state3.owner} dropped. The conversation may be out of date until it’s back${state3.access.control ? ", and sending waits until then" : ""}.</p>` : A}
9942
+ <p data-can>${followCan(state3)}</p>
9943
+ ${this.#error()}
9944
+ <div class="actions">${this.#leaveButton()}</div>
9945
+ </div>
9946
+ </swc-popover>`;
9947
+ }
9948
+ };
9949
+
9950
+ // node_modules/@adobe/spectrum-wc-icons/dist/AlertDiamond.js
9951
+ function e78() {
9952
+ return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path fill="var(--swc-icon-color, currentColor)" d="M10 18.795a2.24 2.24 0 0 1-1.591-.66l-6.545-6.544a2.254 2.254 0 0 1 0-3.182l6.545-6.545c.849-.85 2.333-.85 3.182 0l6.545 6.545a2.254 2.254 0 0 1 0 3.182l-6.545 6.545c-.425.425-.99.659-1.591.659m0-16.09c-.2 0-.389.078-.53.22L2.925 9.47a.75.75 0 0 0 0 1.06l6.545 6.545a.77.77 0 0 0 1.06 0l6.545-6.545a.75.75 0 0 0 0-1.06L10.53 2.925a.75.75 0 0 0-.53-.22"/><path fill="var(--swc-icon-color, currentColor)" d="M10 14.998a.9.9 0 0 1-.627-.228.956.956 0 0 1 0-1.285.87.87 0 0 1 .626-.234c.237-.01.466.08.633.247a.86.86 0 0 1 .242.627.88.88 0 0 1-.228.639.86.86 0 0 1-.647.234M10 11.625a.75.75 0 0 1-.75-.75v-5a.75.75 0 0 1 1.5 0v5a.75.75 0 0 1-.75.75"/></svg>';
9953
+ }
9954
+
9955
+ // node_modules/@adobe/spectrum-wc-icons/dist/swc-icon-alert-diamond.js
9956
+ var o49 = class extends a10 {
9957
+ static get styles() {
9958
+ return [t40];
9959
+ }
9960
+ render() {
9961
+ return b`
9962
+ <span class="swc-Icon">${o16(e78())}</span>
9963
+ `;
9964
+ }
9965
+ };
9966
+ e25("swc-icon-alert-diamond", o49);
9967
+
9968
+ // node_modules/@adobe/spectrum-wc-icons/dist/FolderAdd.js
9969
+ function e79() {
9970
+ return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path fill="var(--swc-icon-color, currentColor)" d="M8.373 15.498H3.25a.75.75 0 0 1-.75-.75v-8.25h14.25a.75.75 0 0 1 .75.75V9.07a.75.75 0 0 0 1.5 0V7.248c0-1.24-1.01-2.25-2.25-2.25h-5.964a.75.75 0 0 1-.566-.258L8.515 2.773a2.25 2.25 0 0 0-1.7-.775H3.25C2.01 1.998 1 3.008 1 4.248v10.5c0 1.24 1.01 2.25 2.25 2.25h5.123a.75.75 0 0 0 0-1.5m-5.123-12h3.565a.75.75 0 0 1 .567.258l1.076 1.242H2.5v-.75a.75.75 0 0 1 .75-.75"/><path fill="var(--swc-icon-color, currentColor)" d="M15 10.498a4.5 4.5 0 1 0 0 9 4.5 4.5 0 0 0 0-9m2.5 5.125h-1.875v1.875a.625.625 0 1 1-1.25 0v-1.875H12.5a.625.625 0 1 1 0-1.25h1.875v-1.875a.625.625 0 1 1 1.25 0v1.875H17.5a.625.625 0 1 1 0 1.25"/></svg>';
9971
+ }
9972
+
9973
+ // node_modules/@adobe/spectrum-wc-icons/dist/swc-icon-folder-add.js
9974
+ var o50 = class extends a10 {
9975
+ static get styles() {
9976
+ return [t40];
9977
+ }
9978
+ render() {
9979
+ return b`
9980
+ <span class="swc-Icon">${o16(e79())}</span>
9981
+ `;
9982
+ }
9983
+ };
9984
+ e25("swc-icon-folder-add", o50);
9985
+
9986
+ // src/app/files.ts
9987
+ function relative(path) {
9988
+ return path.replace(/^\//, "");
9989
+ }
9990
+ function basename(path) {
9991
+ return path.slice(path.lastIndexOf("/") + 1);
9992
+ }
9993
+ function treePaths(entries) {
9994
+ return entries.map((entry) => relative(entry.path) + (entry.kind === "directory" ? "/" : ""));
9995
+ }
9996
+ function treeStatus(changes2) {
9997
+ return changes2.map((change) => ({ path: relative(change.path), status: change.status }));
9998
+ }
9999
+ function ancestors(paths) {
10000
+ const out = /* @__PURE__ */ new Set();
10001
+ for (const path of paths) {
10002
+ const parts2 = relative(path).split("/").slice(0, -1);
10003
+ for (let i25 = 1; i25 <= parts2.length; i25++) out.add(parts2.slice(0, i25).join("/"));
10004
+ }
10005
+ return [...out];
10006
+ }
10007
+ function agentName(model, id) {
10008
+ if (!id) return "you";
10009
+ return model?.agent.list().find((agent) => agent.id === id)?.name ?? id;
10010
+ }
10011
+ function author(model, change) {
10012
+ return change.agentId === null && change.repo ? null : agentName(model, change.agentId);
10013
+ }
10014
+ function request(target, type, path) {
10015
+ target.dispatchEvent(new CustomEvent(type, { detail: { path }, bubbles: true, composed: true }));
10016
+ }
10017
+ var panelCss = i`
10018
+ :host {
10019
+ display: flex;
10020
+ flex-direction: column;
10021
+ height: 100%;
10022
+ min-height: 0;
10023
+ background: var(--swc-background-layer-2-color);
10024
+ color: var(--swc-neutral-content-color-default);
10025
+ font-family: var(--swc-sans-font-family-stack);
10026
+ font-size: var(--swc-font-size-75);
10027
+ }
10028
+ .bar {
10029
+ display: flex;
10030
+ align-items: center;
10031
+ gap: var(--swc-spacing-100);
10032
+ flex: none;
10033
+ min-height: var(--swc-component-height-100);
10034
+ padding: 0 var(--swc-spacing-100) 0 var(--swc-spacing-200);
10035
+ border-bottom: var(--swc-border-width-100) solid var(--swc-gray-200);
10036
+ background: var(--swc-background-layer-1-color);
10037
+ color: var(--swc-neutral-subdued-content-color-default);
10038
+ white-space: nowrap;
10039
+ overflow: hidden;
10040
+ }
10041
+ .bar .path {
10042
+ font-family: var(--swc-code-font-family-stack);
10043
+ color: var(--swc-neutral-content-color-default);
9645
10044
  overflow: hidden;
9646
10045
  text-overflow: ellipsis;
9647
10046
  }
@@ -10209,8 +10608,9 @@ async function deleteCone(model, agent, trigger2) {
10209
10608
  variant: "confirmation",
10210
10609
  trigger: trigger2
10211
10610
  });
10212
- if (ok2) model.agent.freeze?.(agent.id);
10213
- return ok2;
10611
+ const allowed = ok2 && !watchOnly(model);
10612
+ if (allowed) model.agent.freeze?.(agent.id);
10613
+ return allowed;
10214
10614
  }
10215
10615
  var frozenKinds = {
10216
10616
  cone: ["indigo", "Cone"],
@@ -10275,7 +10675,8 @@ var SliccFreezer = class extends ModelElement {
10275
10675
  return [
10276
10676
  model.agent.on("frozen", update),
10277
10677
  model.agent.on("active", update),
10278
- model.agent.on("agents", update)
10678
+ model.agent.on("agents", update),
10679
+ ...model.follow ? [model.follow.on("follow", update)] : []
10279
10680
  ];
10280
10681
  }
10281
10682
  focus() {
@@ -10289,7 +10690,7 @@ var SliccFreezer = class extends ModelElement {
10289
10690
  variant: "destructive",
10290
10691
  trigger: trigger2
10291
10692
  });
10292
- if (ok2) this.model?.agent.discard(cone.id);
10693
+ if (ok2 && !watchOnly(this.model)) this.model?.agent.discard(cone.id);
10293
10694
  }
10294
10695
  #named(cone) {
10295
10696
  const rows = this.model?.agent.frozen() ?? [];
@@ -10304,6 +10705,7 @@ var SliccFreezer = class extends ModelElement {
10304
10705
  if (cone.live) {
10305
10706
  return b`<swc-action-button size="s" quiet data-action="open" accessible-label=${`Open ${this.#named(cone)}`} @click=${() => model.agent.select(cone.id)}>Open</swc-action-button>`;
10306
10707
  }
10708
+ if (watchOnly(model)) return b``;
10307
10709
  return b`<swc-action-button size="s" quiet data-action="thaw" accessible-label=${`Thaw ${this.#named(cone)}`} @click=${() => model.agent.thaw(cone.id)}>Thaw</swc-action-button>
10308
10710
  <swc-action-button size="s" quiet data-action="remove" accessible-label=${`Remove ${this.#named(cone)}`} @click=${(event2) => this.#remove(cone, event2.currentTarget)}>Remove</swc-action-button>`;
10309
10711
  }
@@ -10455,7 +10857,8 @@ var SliccAgents = class extends ModelElement {
10455
10857
  return [
10456
10858
  model.agent.on("agents", () => this.requestUpdate()),
10457
10859
  model.agent.on("active", () => this.requestUpdate()),
10458
- watchTitles(model, () => this.requestUpdate())
10860
+ watchTitles(model, () => this.requestUpdate()),
10861
+ ...model.follow ? [model.follow.on("follow", () => this.requestUpdate())] : []
10459
10862
  ];
10460
10863
  }
10461
10864
  #select(id) {
@@ -10494,595 +10897,196 @@ var SliccAgents = class extends ModelElement {
10494
10897
  }
10495
10898
  }
10496
10899
  }
10497
- #droppable(agent) {
10498
- return agent.kind === "scoop" && Boolean(this.model?.agent.drop);
10499
- }
10500
- #deletable(agent) {
10501
- return agent.kind === "cone" && !agent.frozen && Boolean(this.model?.agent.freeze);
10502
- }
10503
- async #deleteCone(agent, trigger2) {
10504
- if (!await deleteCone(this.model, agent, trigger2)) return;
10505
- await this.updateComplete;
10506
- this.focus();
10507
- }
10508
- async #drop(agent, trigger2) {
10509
- const port = this.model?.agent;
10510
- if (!port?.drop) return;
10511
- const ok2 = await confirm({
10512
- title: `Drop scoop ${agent.name}?`,
10513
- body: "It stops, and its working folder is deleted. Its conversation and reports are kept. You can\u2019t undo this.",
10514
- action: "Drop",
10515
- variant: "destructive",
10516
- trigger: trigger2
10517
- });
10518
- if (!ok2) return;
10519
- const { [agent.id]: _9, ...rest } = this.errors;
10520
- this.errors = rest;
10521
- try {
10522
- await port.drop(agent.id);
10523
- } catch (error) {
10524
- const message = error instanceof Error ? error.message : String(error);
10525
- this.errors = { ...this.errors, [agent.id]: `Couldn\u2019t drop ${agent.name}: ${message}` };
10526
- return;
10527
- }
10528
- const current = port.active();
10529
- const stale = current === agent.id || !port.list().some((candidate) => candidate.id === current);
10530
- if (stale && agent.parentId) port.select(agent.parentId);
10531
- await this.updateComplete;
10532
- this.focus();
10533
- }
10534
- #dropButton(agent) {
10535
- if (!this.#droppable(agent)) return A;
10536
- const id = `drop-${agent.id}`;
10537
- const label = `Drop scoop ${agent.name}`;
10538
- return b`<swc-action-button
10539
- id=${id}
10540
- class="drop"
10541
- size="l"
10542
- quiet
10543
- tabindex="-1"
10544
- data-action="drop"
10545
- accessible-label=${label}
10546
- @click=${(event2) => {
10547
- event2.stopPropagation();
10548
- void this.#drop(agent, event2.currentTarget);
10549
- }}
10550
- ><swc-icon-close slot="icon"></swc-icon-close></swc-action-button
10551
- ><swc-tooltip for=${id} placement="start">${label}</swc-tooltip>`;
10552
- }
10553
- #deleteButton(agent) {
10554
- if (!this.#deletable(agent)) return A;
10555
- const id = `delete-${agent.id}`;
10556
- const label = `Delete cone ${coneLabel(this.model, agent)}`;
10557
- return b`<swc-action-button
10558
- id=${id}
10559
- class="drop"
10560
- size="l"
10561
- quiet
10562
- tabindex="-1"
10563
- data-action="delete-cone"
10564
- accessible-label=${label}
10565
- @click=${(event2) => {
10566
- event2.stopPropagation();
10567
- void this.#deleteCone(agent, event2.currentTarget);
10568
- }}
10569
- ><swc-icon-delete slot="icon"></swc-icon-delete></swc-action-button
10570
- ><swc-tooltip for=${id} placement="start">${label}</swc-tooltip>`;
10571
- }
10572
- #row(agent, active) {
10573
- const selected = agent.id === active;
10574
- const error = this.errors[agent.id];
10575
- const model = this.model;
10576
- const title = agent.kind === "cone" ? agentTitle(model, agent) : null;
10577
- const label = `${coneLabel(model, agent)}: ${statusLabel[agent.status]}, ${percent(agent.contextFill)} context${agent.unread ? `, ${agent.unread} unread` : ""}${error ? `. ${error}` : ""}`;
10578
- return b`<li
10579
- role="option"
10580
- class=${agent.kind}
10581
- data-id=${agent.id}
10582
- aria-selected=${selected ? "true" : "false"}
10583
- aria-label=${label}
10584
- tabindex=${selected ? "0" : "-1"}
10585
- aria-keyshortcuts=${this.#droppable(agent) || this.#deletable(agent) ? "Delete" : A}
10586
- title=${label}
10587
- @click=${() => this.#select(agent.id)}
10588
- >
10589
- <span class="name">${agent.name}</span>
10590
- ${title === null ? A : b`<span class="title">${title || untitled}</span>`}
10591
- ${agent.unread ? b`<swc-badge class="unread" size="s" variant="accent">${agent.unread}</swc-badge>` : A}
10592
- <span class="fill">${percent(agent.contextFill)}</span>
10593
- ${statusLight(agent.status)}
10594
- ${this.#dropButton(agent)}
10595
- ${this.#deleteButton(agent)}
10596
- ${error ? b`<span class="error">${error}</span>` : A}
10597
- </li>`;
10598
- }
10599
- render() {
10600
- const agents = ordered(this.model?.agent.list() ?? []);
10601
- const active = this.model?.agent.active() ?? "";
10602
- const errors = Object.values(this.errors);
10603
- return b`<ul role="listbox" aria-label="Cones and scoops" @keydown=${this.#keydown}>
10604
- ${agents.map((agent) => this.#row(agent, active))}
10605
- </ul>
10606
- <div class="sr" role="status">${errors.at(-1) ?? ""}</div>`;
10607
- }
10608
- };
10609
-
10610
- // node_modules/lit-html/directives/keyed.js
10611
- var i17 = e2(class extends i3 {
10612
- constructor() {
10613
- super(...arguments), this.key = A;
10614
- }
10615
- render(r39, t88) {
10616
- return this.key = r39, t88;
10617
- }
10618
- update(r39, [t88, e119]) {
10619
- return t88 !== this.key && (p(r39), this.key = t88), e119;
10620
- }
10621
- });
10622
-
10623
- // node_modules/lit-html/static.js
10624
- var a12 = /* @__PURE__ */ Symbol.for("");
10625
- var o49 = (t88) => {
10626
- if (t88?.r === a12) return t88?._$litStatic$;
10627
- };
10628
- var s9 = (t88) => ({ _$litStatic$: t88, r: a12 });
10629
- var l14 = /* @__PURE__ */ new Map();
10630
- var n28 = (t88) => (r39, ...e119) => {
10631
- const a22 = e119.length;
10632
- let s19, i25;
10633
- const n36 = [], u27 = [];
10634
- let c27, $6 = 0, f11 = false;
10635
- for (; $6 < a22; ) {
10636
- for (c27 = r39[$6]; $6 < a22 && void 0 !== (i25 = e119[$6], s19 = o49(i25)); ) c27 += s19 + r39[++$6], f11 = true;
10637
- $6 !== a22 && u27.push(i25), n36.push(c27), $6++;
10638
- }
10639
- if ($6 === a22 && n36.push(r39[a22]), f11) {
10640
- const t89 = n36.join("$$lit$$");
10641
- void 0 === (r39 = l14.get(t89)) && (n36.raw = n36, l14.set(t89, r39 = n36)), e119 = u27;
10642
- }
10643
- return t88(r39, ...e119);
10644
- };
10645
- var u16 = n28(b);
10646
- var c17 = n28(w);
10647
- var $2 = n28(T);
10648
-
10649
- // src/app/dips.ts
10650
- var dipType = "application/x-slicc-sprinkle";
10651
- var Dips = class extends Emitter {
10652
- key = "slicc-ui.dips";
10653
- #out = /* @__PURE__ */ new Set();
10654
- #storage = null;
10655
- load(storage) {
10656
- this.#storage = storage;
10657
- try {
10658
- const saved = JSON.parse(storage?.getItem(this.key) ?? "[]");
10659
- this.#out = new Set(Array.isArray(saved) ? saved.filter((id) => typeof id === "string") : []);
10660
- } catch {
10661
- this.#out = /* @__PURE__ */ new Set();
10662
- }
10663
- this.emit("change", this.list());
10664
- }
10665
- list() {
10666
- return [...this.#out];
10667
- }
10668
- has(id) {
10669
- return this.#out.has(id);
10670
- }
10671
- detach(id) {
10672
- if (this.#out.has(id)) return;
10673
- this.#out.add(id);
10674
- this.#storage?.setItem(this.key, JSON.stringify(this.list()));
10675
- this.emit("change", this.list());
10676
- }
10677
- };
10678
- function dipsOf(node) {
10679
- let current = node;
10680
- while (current) {
10681
- const found = current.dips;
10682
- if (found instanceof Dips) return found;
10683
- current = current.parentNode ?? current.host ?? null;
10684
- }
10685
- return null;
10686
- }
10687
-
10688
- // node_modules/@adobe/spectrum-wc/dist/components/progress-circle/progress-circle.js
10689
- var t45 = i`@keyframes swc-fills-rotate{0%{transform:rotate(var(--swc-progress-circle-rotate-start, -90deg))}to{transform:rotate(var(--swc-progress-circle-rotate-end, 270deg))}}@keyframes swc-dashoffset-animation{0%,to{stroke-dashoffset:75px}30%{stroke-dashoffset:var(--swc-progress-circle-dashoffset-30, 20px)}}:host{display:inline-block;align-self:center;justify-self:center;place-self:center}*{box-sizing:border-box}.swc-ProgressCircle{--_swc-progress-circle-size: var(--swc-progress-circle-size, var(--swc-progress-circle-size-medium));--_swc-progress-circle-track-border-color: var(--swc-progress-circle-track-border-color, var(--swc-gray-300));--_swc-progress-circle-fill-border-color: var(--swc-progress-circle-fill-border-color, var(--swc-accent-color-900));--_swc-progress-circle-thickness: var(--swc-progress-circle-thickness, var(--swc-progress-circle-thickness-medium));display:inline-block;position:relative;inline-size:var(--_swc-progress-circle-size);block-size:var(--_swc-progress-circle-size);direction:ltr;transform:translateZ(0)}.swc-ProgressCircle-fill,.swc-ProgressCircle-track{inline-size:var(--_swc-progress-circle-size);block-size:var(--_swc-progress-circle-size)}.swc-ProgressCircle-track{stroke:var(--_swc-progress-circle-track-border-color);stroke-width:var(--_swc-progress-circle-thickness)}.swc-ProgressCircle-fill{stroke:var(--_swc-progress-circle-fill-border-color);stroke-width:var(--_swc-progress-circle-thickness);transform:rotate(-90deg);transform-origin:center}.swc-ProgressCircle--indeterminate .swc-ProgressCircle-fill{transform-origin:center;animation:swc-fills-rotate 1s cubic-bezier(.6,.1,.3,.9) infinite,swc-dashoffset-animation 1s cubic-bezier(.25,.1,.25,1.3) infinite;will-change:transform}:host([size=\"s\"]){--swc-progress-circle-size: var(--swc-progress-circle-size-small);--swc-progress-circle-thickness: var(--swc-progress-circle-thickness-small)}:host([size=\"l\"]){--swc-progress-circle-size: var(--swc-progress-circle-size-large);--swc-progress-circle-thickness: var(--swc-progress-circle-thickness-large)}.swc-ProgressCircle:where(.swc-ProgressCircle--staticWhite){--swc-progress-circle-track-border-color: var(--swc-transparent-white-300);--swc-progress-circle-fill-border-color: var(--swc-transparent-white-900)}.swc-ProgressCircle:where(.swc-ProgressCircle--staticBlack){--swc-progress-circle-track-border-color: var(--swc-transparent-black-300);--swc-progress-circle-fill-border-color: var(--swc-transparent-black-900)}@media(prefers-reduced-motion:reduce){.swc-ProgressCircle--indeterminate .swc-ProgressCircle-fill{--swc-progress-circle-dashoffset-30: 0;--swc-progress-circle-rotate-start: 0deg;--swc-progress-circle-rotate-end: 360deg;animation-duration:15s;animation-timing-function:linear,linear}}@media(forced-colors:active){.swc-ProgressCircle{--swc-progress-circle-fill-border-color: Highlight;@media(prefers-color-scheme:dark){--swc-progress-circle-track-border-color: var(--swc-transparent-white-300)}@media(prefers-color-scheme:light){--swc-progress-circle-track-border-color: var(--swc-transparent-black-300)}}}`;
10690
-
10691
- // node_modules/@adobe/spectrum-wc-core/dist/components/progress-circle/ProgressCircle.types.js
10692
- var e76 = [
10693
- "s",
10694
- "m",
10695
- "l"
10696
- ];
10697
- var t46 = ["white", "black"];
10698
-
10699
- // node_modules/@adobe/spectrum-wc-core/dist/components/progress-circle/ProgressCircle.base.js
10700
- var u17;
10701
- var d13 = class e77 extends i12(i9, { validSizes: e76 }) {
10702
- constructor(...e119) {
10703
- super(...e119), this.label = "", this.progress = null, this.languageResolver = new i10(this);
10704
- }
10705
- static hasMeaningfulLightDomChildren(e119) {
10706
- for (let n36 of e119.childNodes) {
10707
- var t88;
10708
- if (n36.nodeType === Node.ELEMENT_NODE || n36.nodeType === Node.TEXT_NODE && (t88 = n36.textContent) != null && t88.trim()) return true;
10709
- }
10710
- return false;
10711
- }
10712
- hasAccessibleName() {
10713
- return !!(this.label || this.getAttribute("aria-label") || this.getAttribute("aria-labelledby"));
10714
- }
10715
- static clampProgress(e119) {
10716
- return Number.isFinite(e119) ? Math.min(100, Math.max(0, e119)) : 0;
10717
- }
10718
- formatProgress() {
10719
- var e119;
10720
- return new Intl.NumberFormat(this.languageResolver.language, {
10721
- style: "percent",
10722
- unitDisplay: "narrow"
10723
- }).format(((e119 = this.progress) == null ? 0 : e119) / 100);
10724
- }
10725
- warnDeprecatedLightDomChildren() {
10726
- r9(this, e77.hasMeaningfulLightDomChildren(this), `<${this.localName}> no longer has a default slot. Light DOM children are not rendered and are not used for an accessible name. Use the "label" attribute or property, or "aria-label" / "aria-labelledby" on the host instead.`, "https://spectrum-web-components.adobe.com/?path=/docs/components-progress-circle--docs", { level: "deprecation" });
10727
- }
10728
- willUpdate(t88) {
10729
- if (t88.has("progress") && this.progress !== null) {
10730
- let t89 = e77.clampProgress(this.progress);
10731
- t89 !== this.progress && (this.progress = t89);
10732
- }
10733
- super.willUpdate(t88);
10734
- }
10735
- firstUpdated(e119) {
10736
- super.firstUpdated(e119), this.setAttribute("role", "progressbar");
10737
- }
10738
- updated(t88) {
10739
- if (super.updated(t88), t88.has("progress") && (this.progress !== null && this.progress >= 0 ? (this.setAttribute("aria-valuemin", "0"), this.setAttribute("aria-valuemax", "100"), this.setAttribute("aria-valuenow", String(this.progress)), this.setAttribute("aria-valuetext", this.formatProgress())) : (this.removeAttribute("aria-valuemin"), this.removeAttribute("aria-valuemax"), this.removeAttribute("aria-valuenow"), this.removeAttribute("aria-valuetext"))), this.progress !== null && t88.has(e27) && this.setAttribute("aria-valuetext", this.formatProgress()), t88.has("label") && (this.label.length ? this.setAttribute("aria-label", this.label) : t88.get("label") === this.getAttribute("aria-label") && this.removeAttribute("aria-label")), t88.has("label") && !this.hasAccessibleName() && (this.setAttribute("aria-label", e77.DEFAULT_LABEL), r9(this, true, `<${this.localName}> requires an accessible name. A default label of "${e77.DEFAULT_LABEL}" has been applied, but a more specific label should be provided via:`, "https://spectrum-web-components.adobe.com/?path=/docs/components-progress-circle--docs", {
10740
- type: "accessibility",
10741
- issues: [
10742
- 'value supplied to the "label" attribute, which will be displayed visually as part of the element, or',
10743
- 'value supplied to the "aria-label" attribute, which will only be provided to screen readers, or',
10744
- 'an element ID reference supplied to the "aria-labelledby" attribute, which will be provided by screen readers and will need to be managed manually by the parent application.'
10745
- ]
10746
- })), t88.has("staticColor") && this.staticColor !== void 0) {
10747
- let e119 = this.constructor;
10748
- n10(this, {
10749
- prop: "static-color",
10750
- value: this.staticColor,
10751
- valid: e119.STATIC_COLORS,
10752
- url: "https://spectrum-web-components.adobe.com/?path=/docs/components-progress-circle--docs"
10753
- });
10754
- }
10755
- t14() && this.warnDeprecatedLightDomChildren();
10756
- }
10757
- };
10758
- u17 = d13, u17.DEFAULT_LABEL = "Loading", e24([n({
10759
- type: String,
10760
- reflect: true,
10761
- attribute: "static-color"
10762
- })], d13.prototype, "staticColor", void 0), e24([n({ type: String })], d13.prototype, "label", void 0), e24([n({
10763
- type: Number,
10764
- reflect: true
10765
- })], d13.prototype, "progress", void 0);
10766
-
10767
- // node_modules/@adobe/spectrum-wc/dist/components/progress-circle/ProgressCircle.js
10768
- var l15;
10769
- var u18 = class extends d13 {
10770
- static get styles() {
10771
- return [t45];
10772
- }
10773
- computeDashOffset() {
10774
- if (this.progress !== null) return this.progress === 0 ? 98 : 100 - this.progress;
10775
- }
10776
- render() {
10777
- let e119 = this.size === "s" ? 2 : this.size === "l" ? 6 : 4, t88 = `calc(50% - ${e119 / 2}px)`;
10778
- return b`
10779
- <div
10780
- class=${e3({
10781
- "swc-ProgressCircle": true,
10782
- "swc-ProgressCircle--indeterminate": this.progress === null,
10783
- [`swc-ProgressCircle--static${e14(this.staticColor)}`]: this.staticColor !== void 0
10784
- })}
10785
- >
10786
- <svg aria-hidden="true" fill="none" width="100%" height="100%">
10787
- <circle
10788
- cx="50%"
10789
- cy="50%"
10790
- r=${`calc(50% - ${e119}px)`}
10791
- stroke-width=${e119}
10792
- />
10793
- <circle
10794
- cx="50%"
10795
- cy="50%"
10796
- class="swc-ProgressCircle-track"
10797
- r=${t88}
10798
- />
10799
- <circle
10800
- cx="50%"
10801
- cy="50%"
10802
- r=${t88}
10803
- class="swc-ProgressCircle-fill"
10804
- pathLength="100"
10805
- stroke-dasharray="100 200"
10806
- stroke-dashoffset=${o2(this.computeDashOffset())}
10807
- stroke-linecap="round"
10808
- />
10809
- </svg>
10810
- </div>
10811
- `;
10812
- }
10813
- };
10814
- l15 = u18, l15.STATIC_COLORS = t46, e12([n({
10815
- reflect: true,
10816
- attribute: "static-color"
10817
- })], u18.prototype, "staticColor", void 0);
10818
-
10819
- // node_modules/@adobe/spectrum-wc/dist/components/progress-circle/swc-progress-circle.js
10820
- e25("swc-progress-circle", u18);
10821
-
10822
- // node_modules/@adobe/spectrum-wc-icons/dist/AlertTriangle.js
10823
- function e78() {
10824
- return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path fill="var(--swc-icon-color, currentColor)" d="M10 15.123a.9.9 0 0 1-.627-.228.956.956 0 0 1 0-1.285.87.87 0 0 1 .626-.234c.237-.01.466.08.633.247a.86.86 0 0 1 .242.627.88.88 0 0 1-.228.639.86.86 0 0 1-.647.234M10 11.75a.75.75 0 0 1-.75-.75V7a.75.75 0 0 1 1.5 0v4a.75.75 0 0 1-.75.75"/><path fill="var(--swc-icon-color, currentColor)" d="M16.733 18H3.267c-.8 0-1.523-.41-1.933-1.098s-.427-1.518-.046-2.222L8.02 2.232a2.248 2.248 0 0 1 3.958 0l6.733 12.448c.381.704.364 1.535-.046 2.222S17.534 18 16.733 18M10 2.553a.73.73 0 0 0-.66.392L2.607 15.393a.74.74 0 0 0 .016.74.74.74 0 0 0 .644.367h13.466a.74.74 0 0 0 .644-.366.74.74 0 0 0 .016-.741L10.66 2.945a.73.73 0 0 0-.66-.392"/></svg>';
10825
- }
10826
-
10827
- // node_modules/@adobe/spectrum-wc-icons/dist/swc-icon-alert-triangle.js
10828
- var o50 = class extends a10 {
10829
- static get styles() {
10830
- return [t40];
10831
- }
10832
- render() {
10833
- return b`
10834
- <span class="swc-Icon">${o16(e78())}</span>
10835
- `;
10836
- }
10837
- };
10838
- e25("swc-icon-alert-triangle", o50);
10839
-
10840
- // node_modules/@adobe/spectrum-wc-icons/dist/UserFollowing.js
10841
- function e79() {
10842
- return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path fill="var(--swc-icon-color, currentColor)" d="M15 10.5a4.5 4.5 0 1 0 0 9 4.5 4.5 0 0 0 0-9m2.4 3.35L15.09 17a.623.623 0 0 1-.968.048l-1.439-1.599a.625.625 0 0 1 .93-.836l.924 1.028 1.855-2.53a.625.625 0 1 1 1.007.74M2.274 18.752a.75.75 0 0 1-.733-.91c.596-2.73 3.313-5.025 6.608-5.58a.75.75 0 0 1 .249 1.48c-2.706.455-4.923 2.273-5.391 4.42a.75.75 0 0 1-.733.59m7.726-7.9c-2.485 0-4.507-2.153-4.507-4.8s2.022-4.8 4.507-4.8 4.507 2.153 4.507 4.8-2.022 4.8-4.507 4.8m0-8.1c-1.658 0-3.007 1.48-3.007 3.3s1.349 3.3 3.007 3.3 3.007-1.48 3.007-3.3-1.349-3.3-3.007-3.3"/></svg>';
10843
- }
10844
-
10845
- // node_modules/@adobe/spectrum-wc-icons/dist/swc-icon-user-following.js
10846
- var o51 = class extends a10 {
10847
- static get styles() {
10848
- return [t40];
10849
- }
10850
- render() {
10851
- return b`
10852
- <span class="swc-Icon">${o16(e79())}</span>
10853
- `;
10854
- }
10855
- };
10856
- e25("swc-icon-user-following", o51);
10857
-
10858
- // src/app/follow.ts
10859
- var lights = {
10860
- connecting: ["info", (owner) => `Connecting to ${owner}`],
10861
- connected: ["positive", (owner) => `Following ${owner}`],
10862
- reconnecting: ["notice", (owner) => `Reconnecting to ${owner}`],
10863
- unlinked: ["negative", (owner) => `Unlinked from ${owner}`],
10864
- failed: ["negative", (owner) => `Can\u2019t reach ${owner}`]
10865
- };
10866
- function followLight(state3) {
10867
- const [variant, text2] = lights[state3.link];
10868
- return { variant, text: text2(state3.owner) };
10869
- }
10870
- function followPage(state3) {
10871
- if (!state3) return null;
10872
- const { owner } = state3;
10873
- if (state3.link === "connecting")
10874
- return {
10875
- kind: "connecting",
10876
- title: `Connecting to ${owner}\u2026`,
10877
- body: `This device follows ${owner}. Its agent shows here once it\u2019s connected.`
10878
- };
10879
- if (state3.link === "unlinked")
10880
- return {
10881
- kind: "unlinked",
10882
- title: `${owner} unlinked this device`,
10883
- body: `To follow it again, open a new link from ${owner}.`
10884
- };
10885
- if (state3.link === "failed")
10886
- return {
10887
- kind: "failed",
10888
- title: `Can\u2019t follow ${owner}`,
10889
- body: state3.error ?? `The link to ${owner} failed.`
10890
- };
10891
- if (state3.access.view) return null;
10892
- const where2 = state3.name ? `next to ${state3.name}` : "for this device";
10893
- return {
10894
- kind: "waiting",
10895
- title: `Waiting for ${owner} to allow this device`,
10896
- body: `On ${owner}, choose Allow ${where2} in Network \u203A Linked devices.`
10897
- };
10898
- }
10899
- function list(items, last) {
10900
- if (items.length < 2) return items.join("");
10901
- return `${items.slice(0, -1).join(", ")} ${last} ${items.at(-1)}`;
10902
- }
10903
- function followCan(state3) {
10904
- const allowed = ["watch the agent"];
10905
- const missing = [];
10906
- (state3.access.control ? allowed : missing).push("send prompts");
10907
- (state3.access.terminal ? allowed : missing).push("open terminals");
10908
- const can = `This device can ${list(allowed, "and")}.`;
10909
- return missing.length ? `${can} To ${list(missing, "or")}, allow it on ${state3.owner}.` : can;
10910
- }
10911
- function following(model) {
10912
- const state3 = model?.follow?.state();
10913
- return state3 && !followPage(state3) ? state3 : null;
10914
- }
10915
- function watchOnly(model) {
10916
- const state3 = following(model);
10917
- if (!state3 || state3.access.control) return "";
10918
- return `${state3.owner} lets this device watch only. To send prompts, allow Control for it on ${state3.owner}.`;
10919
- }
10920
- function terminalsAllowed(model) {
10921
- const state3 = model?.follow?.state();
10922
- return !state3 || !!state3.access.terminal;
10923
- }
10924
- var SliccFollow = class extends ModelElement {
10925
- static properties = {
10926
- ...ModelElement.properties,
10927
- page: { type: Boolean, reflect: true },
10928
- compact: { type: Boolean, reflect: true },
10929
- busy: { state: true },
10930
- error: { state: true }
10931
- };
10932
- constructor() {
10933
- super();
10934
- this.page = false;
10935
- this.compact = false;
10936
- this.busy = "";
10937
- this.error = "";
10938
- }
10939
- static styles = [
10940
- shared,
10941
- i`
10942
- :host {
10943
- display: inline-block;
10944
- }
10945
- :host([page]) {
10946
- display: block;
10947
- max-width: 480px;
10948
- }
10949
- .chip swc-status-light {
10950
- align-self: center;
10951
- }
10952
- :host([compact]) .chip .text {
10953
- display: none;
10954
- }
10955
- .panel {
10956
- display: grid;
10957
- gap: var(--swc-spacing-200);
10958
- width: calc(var(--swc-spacing-400) * 11);
10959
- max-width: 100%;
10960
- padding: var(--swc-spacing-300);
10961
- box-sizing: border-box;
10962
- font-size: var(--swc-font-size-100);
10963
- color: var(--swc-neutral-content-color-default);
10964
- }
10965
- h2 {
10966
- margin: 0;
10967
- font-size: var(--swc-font-size-300);
10968
- font-weight: var(--swc-bold-font-weight);
10969
- line-height: var(--swc-heading-line-height);
10970
- color: var(--swc-heading-color);
10971
- }
10972
- .page h2 {
10973
- font-size: var(--swc-font-size-500);
10974
- }
10975
- .page > p {
10976
- font-size: var(--swc-font-size-200);
10977
- }
10978
- .panel h2 {
10979
- font-size: var(--swc-font-size-100);
10980
- }
10981
- p {
10982
- margin: 0;
10983
- }
10984
- .muted {
10985
- color: var(--swc-neutral-subdued-content-color-default);
10986
- }
10987
- .page {
10988
- display: grid;
10989
- gap: var(--swc-spacing-300);
10990
- justify-items: center;
10991
- text-align: center;
10992
- }
10993
- .actions {
10994
- display: flex;
10995
- flex-wrap: wrap;
10996
- justify-content: center;
10997
- gap: var(--swc-spacing-200);
10998
- }
10999
- .panel .actions {
11000
- justify-content: flex-start;
11001
- }
11002
- .error {
11003
- display: flex;
11004
- align-items: flex-start;
11005
- gap: var(--swc-spacing-75);
11006
- color: var(--swc-negative-content-color-default);
11007
- --swc-icon-color: var(--swc-negative-content-color-default);
11008
- }
11009
- `
11010
- ];
11011
- subscribe(model) {
11012
- const port = model.follow;
11013
- return port ? [port.on("follow", () => this.requestUpdate())] : [];
11014
- }
11015
- async leave() {
11016
- const port = this.model?.follow;
11017
- if (!port || this.busy) return;
11018
- const state3 = port.state();
11019
- if (state3.link !== "unlinked") {
11020
- const ok2 = await confirm({
11021
- title: `Stop following ${state3.owner}?`,
11022
- body: `This device forgets the link. To follow ${state3.owner} again, open a new link from it.`,
11023
- action: "Leave",
11024
- variant: "confirmation"
11025
- });
11026
- if (!ok2) return;
11027
- }
11028
- await this.#run("leave", () => port.leave());
11029
- }
11030
- async retry() {
11031
- const port = this.model?.follow;
11032
- if (!port?.retry || this.busy) return;
11033
- await this.#run("retry", () => port.retry?.());
10900
+ #droppable(agent) {
10901
+ return agent.kind === "scoop" && Boolean(this.model?.agent.drop) && !watchOnly(this.model);
11034
10902
  }
11035
- async #run(busy, task) {
11036
- this.busy = busy;
11037
- this.error = "";
10903
+ #deletable(agent) {
10904
+ return agent.kind === "cone" && !agent.frozen && Boolean(this.model?.agent.freeze) && !watchOnly(this.model);
10905
+ }
10906
+ async #deleteCone(agent, trigger2) {
10907
+ if (!await deleteCone(this.model, agent, trigger2)) return;
10908
+ await this.updateComplete;
10909
+ this.focus();
10910
+ }
10911
+ async #drop(agent, trigger2) {
10912
+ const port = this.model?.agent;
10913
+ if (!port?.drop) return;
10914
+ const ok2 = await confirm({
10915
+ title: `Drop scoop ${agent.name}?`,
10916
+ body: "It stops, and its working folder is deleted. Its conversation and reports are kept. You can\u2019t undo this.",
10917
+ action: "Drop",
10918
+ variant: "destructive",
10919
+ trigger: trigger2
10920
+ });
10921
+ if (!ok2 || watchOnly(this.model)) return;
10922
+ const { [agent.id]: _9, ...rest } = this.errors;
10923
+ this.errors = rest;
11038
10924
  try {
11039
- await task();
10925
+ await port.drop(agent.id);
11040
10926
  } catch (error) {
11041
- this.error = error instanceof Error ? error.message : String(error);
11042
- } finally {
11043
- this.busy = "";
10927
+ const message = error instanceof Error ? error.message : String(error);
10928
+ this.errors = { ...this.errors, [agent.id]: `Couldn\u2019t drop ${agent.name}: ${message}` };
10929
+ return;
11044
10930
  }
10931
+ const current = port.active();
10932
+ const stale = current === agent.id || !port.list().some((candidate) => candidate.id === current);
10933
+ if (stale && agent.parentId) port.select(agent.parentId);
10934
+ await this.updateComplete;
10935
+ this.focus();
11045
10936
  }
11046
- #error() {
11047
- return this.error ? b`<p class="error" role="alert" data-error><swc-icon-alert-triangle size="s" aria-hidden="true"></swc-icon-alert-triangle><span>${this.error}</span></p>` : A;
10937
+ #dropButton(agent) {
10938
+ if (!this.#droppable(agent)) return A;
10939
+ const id = `drop-${agent.id}`;
10940
+ const label = `Drop scoop ${agent.name}`;
10941
+ return b`<swc-action-button
10942
+ id=${id}
10943
+ class="drop"
10944
+ size="l"
10945
+ quiet
10946
+ tabindex="-1"
10947
+ data-action="drop"
10948
+ accessible-label=${label}
10949
+ @click=${(event2) => {
10950
+ event2.stopPropagation();
10951
+ void this.#drop(agent, event2.currentTarget);
10952
+ }}
10953
+ ><swc-icon-close slot="icon"></swc-icon-close></swc-action-button
10954
+ ><swc-tooltip for=${id} placement="start">${label}</swc-tooltip>`;
11048
10955
  }
11049
- #leaveButton() {
11050
- return b`<swc-button size="m" variant="secondary" fill-style="outline" data-action="leave" ?pending=${this.busy === "leave"} ?disabled=${!!this.busy && this.busy !== "leave"} @click=${() => this.leave()}>Leave</swc-button>`;
10956
+ #deleteButton(agent) {
10957
+ if (!this.#deletable(agent)) return A;
10958
+ const id = `delete-${agent.id}`;
10959
+ const label = `Delete cone ${coneLabel(this.model, agent)}`;
10960
+ return b`<swc-action-button
10961
+ id=${id}
10962
+ class="drop"
10963
+ size="l"
10964
+ quiet
10965
+ tabindex="-1"
10966
+ data-action="delete-cone"
10967
+ accessible-label=${label}
10968
+ @click=${(event2) => {
10969
+ event2.stopPropagation();
10970
+ void this.#deleteCone(agent, event2.currentTarget);
10971
+ }}
10972
+ ><swc-icon-delete slot="icon"></swc-icon-delete></swc-action-button
10973
+ ><swc-tooltip for=${id} placement="start">${label}</swc-tooltip>`;
11051
10974
  }
11052
- #page(page) {
11053
- return b`<div class="page" data-follow-page=${page.kind}>
11054
- ${page.kind === "connecting" || page.kind === "waiting" ? b`<swc-progress-circle size="m" indeterminate label=${page.kind === "waiting" ? "Waiting" : "Connecting"} aria-hidden="true"></swc-progress-circle>` : A}
11055
- <h2 aria-live="polite">${page.title}</h2>
11056
- <p class="muted">${page.body}</p>
11057
- ${this.#error()}
11058
- <div class="actions">
11059
- ${page.kind === "failed" && this.model?.follow?.retry ? b`<swc-button size="m" variant="accent" data-action="retry" ?pending=${this.busy === "retry"} ?disabled=${!!this.busy && this.busy !== "retry"} @click=${() => this.retry()}>Try again</swc-button>` : A}
11060
- ${this.#leaveButton()}
11061
- </div>
11062
- </div>`;
10975
+ #row(agent, active) {
10976
+ const selected = agent.id === active;
10977
+ const error = this.errors[agent.id];
10978
+ const model = this.model;
10979
+ const title = agent.kind === "cone" ? agentTitle(model, agent) : null;
10980
+ const label = `${coneLabel(model, agent)}: ${statusLabel[agent.status]}, ${percent(agent.contextFill)} context${agent.unread ? `, ${agent.unread} unread` : ""}${error ? `. ${error}` : ""}`;
10981
+ return b`<li
10982
+ role="option"
10983
+ class=${agent.kind}
10984
+ data-id=${agent.id}
10985
+ aria-selected=${selected ? "true" : "false"}
10986
+ aria-label=${label}
10987
+ tabindex=${selected ? "0" : "-1"}
10988
+ aria-keyshortcuts=${this.#droppable(agent) || this.#deletable(agent) ? "Delete" : A}
10989
+ title=${label}
10990
+ @click=${() => this.#select(agent.id)}
10991
+ >
10992
+ <span class="name">${agent.name}</span>
10993
+ ${title === null ? A : b`<span class="title">${title || untitled}</span>`}
10994
+ ${agent.unread ? b`<swc-badge class="unread" size="s" variant="accent">${agent.unread}</swc-badge>` : A}
10995
+ <span class="fill">${percent(agent.contextFill)}</span>
10996
+ ${statusLight(agent.status)}
10997
+ ${this.#dropButton(agent)}
10998
+ ${this.#deleteButton(agent)}
10999
+ ${error ? b`<span class="error">${error}</span>` : A}
11000
+ </li>`;
11063
11001
  }
11064
11002
  render() {
11065
- const state3 = this.model?.follow?.state();
11066
- if (!state3) return A;
11067
- const page = followPage(state3);
11068
- if (this.page) return page ? this.#page(page) : A;
11069
- const light = followLight(state3);
11070
- return b`<swc-action-button id="chip" class="chip" size="s" quiet data-follow=${state3.link} accessible-label=${light.text}>
11071
- ${this.compact ? b`<swc-icon-user-following slot="icon" size="s" aria-hidden="true"></swc-icon-user-following>` : A}
11072
- <swc-status-light size="s" variant=${light.variant}><span class="text">${light.text}</span></swc-status-light>
11073
- </swc-action-button>
11074
- <swc-tooltip for="chip" placement="bottom">${light.text}</swc-tooltip>
11075
- <swc-popover for="chip" placement="bottom-end" accessible-label=${light.text}>
11076
- <div class="panel">
11077
- <h2>${light.text}</h2>
11078
- ${state3.link === "reconnecting" ? b`<p class="muted" data-reconnecting>The link to ${state3.owner} dropped. The conversation may be out of date until it’s back${state3.access.control ? ", and sending waits until then" : ""}.</p>` : A}
11079
- <p data-can>${followCan(state3)}</p>
11080
- ${this.#error()}
11081
- <div class="actions">${this.#leaveButton()}</div>
11082
- </div>
11083
- </swc-popover>`;
11003
+ const agents = ordered(this.model?.agent.list() ?? []);
11004
+ const active = this.model?.agent.active() ?? "";
11005
+ const errors = Object.values(this.errors);
11006
+ return b`<ul role="listbox" aria-label="Cones and scoops" @keydown=${this.#keydown}>
11007
+ ${agents.map((agent) => this.#row(agent, active))}
11008
+ </ul>
11009
+ <div class="sr" role="status">${errors.at(-1) ?? ""}</div>`;
11010
+ }
11011
+ };
11012
+
11013
+ // node_modules/lit-html/directives/keyed.js
11014
+ var i17 = e2(class extends i3 {
11015
+ constructor() {
11016
+ super(...arguments), this.key = A;
11017
+ }
11018
+ render(r39, t88) {
11019
+ return this.key = r39, t88;
11020
+ }
11021
+ update(r39, [t88, e119]) {
11022
+ return t88 !== this.key && (p(r39), this.key = t88), e119;
11023
+ }
11024
+ });
11025
+
11026
+ // node_modules/lit-html/static.js
11027
+ var a12 = /* @__PURE__ */ Symbol.for("");
11028
+ var o51 = (t88) => {
11029
+ if (t88?.r === a12) return t88?._$litStatic$;
11030
+ };
11031
+ var s9 = (t88) => ({ _$litStatic$: t88, r: a12 });
11032
+ var l15 = /* @__PURE__ */ new Map();
11033
+ var n28 = (t88) => (r39, ...e119) => {
11034
+ const a22 = e119.length;
11035
+ let s19, i25;
11036
+ const n36 = [], u27 = [];
11037
+ let c27, $6 = 0, f11 = false;
11038
+ for (; $6 < a22; ) {
11039
+ for (c27 = r39[$6]; $6 < a22 && void 0 !== (i25 = e119[$6], s19 = o51(i25)); ) c27 += s19 + r39[++$6], f11 = true;
11040
+ $6 !== a22 && u27.push(i25), n36.push(c27), $6++;
11041
+ }
11042
+ if ($6 === a22 && n36.push(r39[a22]), f11) {
11043
+ const t89 = n36.join("$$lit$$");
11044
+ void 0 === (r39 = l15.get(t89)) && (n36.raw = n36, l15.set(t89, r39 = n36)), e119 = u27;
11045
+ }
11046
+ return t88(r39, ...e119);
11047
+ };
11048
+ var u18 = n28(b);
11049
+ var c17 = n28(w);
11050
+ var $2 = n28(T);
11051
+
11052
+ // src/app/dips.ts
11053
+ var dipType = "application/x-slicc-sprinkle";
11054
+ var Dips = class extends Emitter {
11055
+ key = "slicc-ui.dips";
11056
+ #out = /* @__PURE__ */ new Set();
11057
+ #storage = null;
11058
+ load(storage) {
11059
+ this.#storage = storage;
11060
+ try {
11061
+ const saved = JSON.parse(storage?.getItem(this.key) ?? "[]");
11062
+ this.#out = new Set(Array.isArray(saved) ? saved.filter((id) => typeof id === "string") : []);
11063
+ } catch {
11064
+ this.#out = /* @__PURE__ */ new Set();
11065
+ }
11066
+ this.emit("change", this.list());
11067
+ }
11068
+ list() {
11069
+ return [...this.#out];
11070
+ }
11071
+ has(id) {
11072
+ return this.#out.has(id);
11073
+ }
11074
+ detach(id) {
11075
+ if (this.#out.has(id)) return;
11076
+ this.#out.add(id);
11077
+ this.#storage?.setItem(this.key, JSON.stringify(this.list()));
11078
+ this.emit("change", this.list());
11084
11079
  }
11085
11080
  };
11081
+ function dipsOf(node) {
11082
+ let current = node;
11083
+ while (current) {
11084
+ const found = current.dips;
11085
+ if (found instanceof Dips) return found;
11086
+ current = current.parentNode ?? current.host ?? null;
11087
+ }
11088
+ return null;
11089
+ }
11086
11090
 
11087
11091
  // src/app/fonts.ts
11088
11092
  var adobeClean = [
@@ -13839,13 +13843,13 @@ function resolve(panels, raw2, reachable2, cone) {
13839
13843
  return found?.id ?? null;
13840
13844
  }
13841
13845
  function state(info) {
13842
- const shown3 = info.active ? "active" : info.visible ? "shown" : info.open ? "open" : "closed";
13843
- return info.busy ? `${shown3} \xB7 busy: ${info.busy}` : shown3;
13846
+ const shown4 = info.active ? "active" : info.visible ? "shown" : info.open ? "open" : "closed";
13847
+ return info.busy ? `${shown4} \xB7 busy: ${info.busy}` : shown4;
13844
13848
  }
13845
13849
  function table(rows) {
13846
13850
  const lines = [["ID", "TITLE", "STATE"], ...rows.map((row) => [row.id, row.title, state(row)])];
13847
13851
  const widths = [0, 1].map((column) => Math.max(...lines.map((line) => line[column].length)));
13848
- return lines.map(([id, title, shown3]) => `${id.padEnd(widths[0])} ${title.padEnd(widths[1])} ${shown3}`).join("\n");
13852
+ return lines.map(([id, title, shown4]) => `${id.padEnd(widths[0])} ${title.padEnd(widths[1])} ${shown4}`).join("\n");
13849
13853
  }
13850
13854
  var done = (result, note = "") => result.code === 0 ? { stdout: `${result.message}${note}
13851
13855
  `, stderr: "", code: 0 } : { stdout: "", stderr: `panel: ${result.message}
@@ -14101,6 +14105,17 @@ function settled(element2) {
14101
14105
  requestAnimationFrame(frame);
14102
14106
  });
14103
14107
  }
14108
+ function shown2() {
14109
+ if (!document.hidden) return Promise.resolve();
14110
+ return new Promise((resolve2) => {
14111
+ const seen = () => {
14112
+ if (document.hidden) return;
14113
+ document.removeEventListener("visibilitychange", seen);
14114
+ resolve2();
14115
+ };
14116
+ document.addEventListener("visibilitychange", seen);
14117
+ });
14118
+ }
14104
14119
  var ended = { write() {
14105
14120
  }, resize() {
14106
14121
  }, close() {
@@ -14128,6 +14143,9 @@ var KeptSession = class {
14128
14143
  }) : this.#start(size4);
14129
14144
  return session.then((live) => this.#handle(live, sink));
14130
14145
  }
14146
+ replay(write) {
14147
+ for (const chunk of this.#log) write(chunk);
14148
+ }
14131
14149
  dispose() {
14132
14150
  this.#sink = null;
14133
14151
  this.#log = [];
@@ -14306,9 +14324,12 @@ var SliccTerminalPanel = class extends ThemedElement {
14306
14324
  const backend = keep(model.terminals, info.id);
14307
14325
  terminal.backend = {
14308
14326
  open: async (sink) => {
14309
- await this.#placed(info.id, terminal);
14327
+ const hidden = await this.#placed(info.id, terminal);
14310
14328
  terminal.fit();
14311
- return backend.open(sink, { cols: terminal.cols, rows: terminal.rows });
14329
+ const cols = terminal.cols;
14330
+ const session = await backend.open(sink, { cols, rows: terminal.rows });
14331
+ if (hidden) void this.#relayout(terminal, backend, cols);
14332
+ return session;
14312
14333
  }
14313
14334
  };
14314
14335
  terminal.addEventListener("exit", () => model.terminals.close(info.id));
@@ -14329,7 +14350,25 @@ var SliccTerminalPanel = class extends ThemedElement {
14329
14350
  #placed(id, screen) {
14330
14351
  const host4 = this.getRootNode().host;
14331
14352
  const panel = host4?.localName === "slicc-dock" ? host4.api.getPanel(terminalPanel(id)) : void 0;
14332
- if (!panel) return Promise.resolve();
14353
+ if (!panel) return Promise.resolve(false);
14354
+ if (!document.hidden) return this.#seen(panel, screen).then(() => false);
14355
+ if (laid(screen.getBoundingClientRect())) return Promise.resolve(true);
14356
+ return new Promise((resolve2) => {
14357
+ const done2 = (hidden) => {
14358
+ watch.dispose();
14359
+ document.removeEventListener("visibilitychange", visible2);
14360
+ resolve2(hidden);
14361
+ };
14362
+ const watch = panel.api.onDidDimensionsChange((size4) => {
14363
+ if (laid(size4)) done2(true);
14364
+ });
14365
+ const visible2 = () => {
14366
+ if (!document.hidden) done2(false);
14367
+ };
14368
+ document.addEventListener("visibilitychange", visible2);
14369
+ }).then((hidden) => hidden || this.#seen(panel, screen).then(() => false));
14370
+ }
14371
+ #seen(panel, screen) {
14333
14372
  const sized = laid(panel.api) ? Promise.resolve() : new Promise((resolve2) => {
14334
14373
  const watch = panel.api.onDidDimensionsChange((size4) => {
14335
14374
  if (!laid(size4)) return;
@@ -14339,6 +14378,14 @@ var SliccTerminalPanel = class extends ThemedElement {
14339
14378
  });
14340
14379
  return sized.then(() => settled(screen));
14341
14380
  }
14381
+ async #relayout(screen, backend, cols) {
14382
+ await shown2();
14383
+ await settled(screen);
14384
+ screen.fit();
14385
+ if (screen.cols === cols) return;
14386
+ screen.redraw("\x1Bc");
14387
+ backend.replay((data) => screen.redraw(data));
14388
+ }
14342
14389
  #request() {
14343
14390
  this.dispatchEvent(new CustomEvent("new-terminal", { bubbles: true, composed: true }));
14344
14391
  }
@@ -20665,7 +20712,7 @@ function part(entry, handlers, showThinking) {
20665
20712
  case "delegation":
20666
20713
  return delegation(entry, handlers);
20667
20714
  case "sprinkle":
20668
- return b`<slicc-sprinkle inline .model=${handlers.model} sprinkle=${entry.sprinkle}></slicc-sprinkle>`;
20715
+ return b`<slicc-sprinkle inline ?readonly=${handlers.readOnly} .model=${handlers.model} sprinkle=${entry.sprinkle}></slicc-sprinkle>`;
20669
20716
  case "link":
20670
20717
  return host2(entry.url) ? A : b`<div class="link-text">${entry.title}</div>`;
20671
20718
  default:
@@ -22006,8 +22053,8 @@ var SliccUpdates = class extends ModelElement {
22006
22053
  #checked(at) {
22007
22054
  if (at === null) return b`<span>Not checked yet</span>`;
22008
22055
  const date = new Date(at);
22009
- const shown3 = date.toLocaleString("en-GB", { dateStyle: "medium", timeStyle: "short" });
22010
- return b`<span>Checked <time datetime=${date.toISOString()}>${shown3}</time></span>`;
22056
+ const shown4 = date.toLocaleString("en-GB", { dateStyle: "medium", timeStyle: "short" });
22057
+ return b`<span>Checked <time datetime=${date.toISOString()}>${shown4}</time></span>`;
22011
22058
  }
22012
22059
  #item(item2) {
22013
22060
  const [variant, state3] = states[item2.state];
@@ -22072,14 +22119,14 @@ var SliccUpdates = class extends ModelElement {
22072
22119
  #package(item2, all2, act2) {
22073
22120
  const light = packageLight(item2);
22074
22121
  const busy = this.busy.get(item2.id);
22075
- const shown3 = busy ? [busy] : act2 ? item2.actions : [];
22122
+ const shown4 = busy ? [busy] : act2 ? item2.actions : [];
22076
22123
  const error = this.problems.get(item2.id) ?? item2.error;
22077
22124
  return b`<li data-id=${item2.id} data-state=${item2.state}>
22078
22125
  <div class="name">
22079
22126
  <h3 title=${item2.package}>${item2.label}</h3>
22080
22127
  ${light ? b`<swc-status-light size="s" variant=${light[0]}>${light[1]}</swc-status-light>` : A}
22081
22128
  </div>
22082
- <div class="buttons">${shown3.map(
22129
+ <div class="buttons">${shown4.map(
22083
22130
  (action) => b`<swc-button
22084
22131
  size="s"
22085
22132
  variant="secondary"
@@ -22150,7 +22197,7 @@ var SliccUpdates = class extends ModelElement {
22150
22197
  // src/app/app.ts
22151
22198
  function railIcon(icon) {
22152
22199
  if (icon.startsWith("swc-icon-")) {
22153
- return u16`<${s9(icon)} slot="icon"></${s9(icon)}>`;
22200
+ return u18`<${s9(icon)} slot="icon"></${s9(icon)}>`;
22154
22201
  }
22155
22202
  return b`<slicc-lucide slot="icon" name=${icon}></slicc-lucide>`;
22156
22203
  }
@@ -22814,7 +22861,7 @@ var SliccApp = class extends ThemedElement {
22814
22861
  const driven = item2.id === "browser" && !!this.model?.browser.list().some((tab) => tab.controlled);
22815
22862
  const visible2 = shown(this.dock, item2.id);
22816
22863
  const label = `${visible2 ? `${item2.title}, shown` : `Open ${item2.title}`}${changes2 ? `, ${changeCount(changes2)}` : driven ? ", a tab is in use" : ""}`;
22817
- const button = u16`<swc-action-button id=${`rail-${item2.id}`} class=${visible2 ? "selected" : ""} quiet size="m" accessible-label=${label} data-surface=${item2.id} data-cone=${o2(item2.cone)} ?data-visible=${visible2} @click=${() => this.show(item2.id)}>${railIcon(item2.icon)}</swc-action-button>`;
22864
+ const button = u18`<swc-action-button id=${`rail-${item2.id}`} class=${visible2 ? "selected" : ""} quiet size="m" accessible-label=${label} data-surface=${item2.id} data-cone=${o2(item2.cone)} ?data-visible=${visible2} @click=${() => this.show(item2.id)}>${railIcon(item2.icon)}</swc-action-button>`;
22818
22865
  const tooltip = b`<swc-tooltip for=${`rail-${item2.id}`} placement=${{ left: "end", right: "start", bottom: "top" }[side]}>${item2.title}</swc-tooltip>`;
22819
22866
  return changes2 ? b`<span class="badged">${button}<swc-badge size="s" variant="neutral" aria-hidden="true">${changes2}</swc-badge></span>${tooltip}` : driven ? b`<span class="badged">${button}<span class="dot" data-driven aria-hidden="true"></span></span>${tooltip}` : b`${button}${tooltip}`;
22820
22867
  }
@@ -22826,20 +22873,20 @@ var SliccApp = class extends ThemedElement {
22826
22873
  if (!items.length) return A;
22827
22874
  const changes2 = items.some((item2) => item2.id === "changes") ? this.#changes() : 0;
22828
22875
  const label = changes2 ? `More panels, ${changeCount(changes2)}` : "More panels";
22829
- const menu = u16`<sp-action-menu quiet size="m" label=${label} placement="top-end" @change=${(event2) => this.show(event2.target.value)}>
22876
+ const menu = u18`<sp-action-menu quiet size="m" label=${label} placement="top-end" @change=${(event2) => this.show(event2.target.value)}>
22830
22877
  <swc-icon-more slot="icon"></swc-icon-more>
22831
- ${items.map((item2) => u16`<sp-menu-item value=${item2.id}>${railIcon(item2.icon)}${item2.title}</sp-menu-item>`)}
22878
+ ${items.map((item2) => u18`<sp-menu-item value=${item2.id}>${railIcon(item2.icon)}${item2.title}</sp-menu-item>`)}
22832
22879
  </sp-action-menu>`;
22833
22880
  return changes2 ? b`<span class="badged">${menu}<swc-badge size="s" variant="neutral" aria-hidden="true">${changes2}</swc-badge></span>` : menu;
22834
22881
  }
22835
22882
  #rail(items, side) {
22836
22883
  const primary = side === "bottom" ? items.filter((item2) => phoneRail.includes(item2.id)) : items;
22837
22884
  const fit = primary.length < items.length ? Math.min(primary.length, railCapacity(this.#width, Infinity)) : railCapacity(this.#width, items.length);
22838
- const shown3 = side === "bottom" ? primary.slice(0, fit) : items;
22839
- const grouped = new Set(shown3.map((item2) => item2.cone).filter(Boolean)).size > 1;
22840
- return b`<nav class=${`rail ${side}`} aria-label=${`Panels, ${side}`} @dragover=${this.#railOver} @dragleave=${this.#railLeave} @drop=${this.#railDrop}>${shown3.map(
22841
- (item2, index) => b`${grouped && index && shown3[index - 1].cone !== item2.cone ? b`<span class="cones" aria-hidden="true"></span>` : A}${this.#railButton(item2, side)}`
22842
- )}${this.#more(items.filter((item2) => !shown3.includes(item2)))}</nav>`;
22885
+ const shown4 = side === "bottom" ? primary.slice(0, fit) : items;
22886
+ const grouped = new Set(shown4.map((item2) => item2.cone).filter(Boolean)).size > 1;
22887
+ return b`<nav class=${`rail ${side}`} aria-label=${`Panels, ${side}`} @dragover=${this.#railOver} @dragleave=${this.#railLeave} @drop=${this.#railDrop}>${shown4.map(
22888
+ (item2, index) => b`${grouped && index && shown4[index - 1].cone !== item2.cone ? b`<span class="cones" aria-hidden="true"></span>` : A}${this.#railButton(item2, side)}`
22889
+ )}${this.#more(items.filter((item2) => !shown4.includes(item2)))}</nav>`;
22843
22890
  }
22844
22891
  #rails() {
22845
22892
  const dock = this.renderRoot.querySelector("slicc-dock");
@@ -22889,7 +22936,10 @@ var SliccApp = class extends ThemedElement {
22889
22936
  }
22890
22937
  #deletable() {
22891
22938
  const cone = this.model?.agent.list().find((agent) => agent.id === this.#cone());
22892
- return Boolean(cone && !cone.frozen && this.model?.agent.freeze);
22939
+ return Boolean(cone && !cone.frozen && this.model?.agent.freeze && !watchOnly(this.model));
22940
+ }
22941
+ #creatable() {
22942
+ return Boolean(this.model?.agent.createCone) && !watchOnly(this.model);
22893
22943
  }
22894
22944
  #cone() {
22895
22945
  const agent = this.#active();
@@ -22932,6 +22982,7 @@ var SliccApp = class extends ThemedElement {
22932
22982
  action: "Create",
22933
22983
  trigger: trigger2,
22934
22984
  submit: async (name) => {
22985
+ if (watchOnly(this.model)) return;
22935
22986
  created = await create3(name);
22936
22987
  }
22937
22988
  });
@@ -23010,8 +23061,8 @@ var SliccApp = class extends ThemedElement {
23010
23061
  cones.map((agent) => agent.id).join(" "),
23011
23062
  b`<sp-picker size="s" label="Agent" value=${this.#cone()} @change=${this.#pick}>
23012
23063
  ${cones.map((agent) => b`<sp-menu-item value=${agent.id}>${agent.name}<span slot="description">${agentTitle(this.model, agent) || untitled}</span></sp-menu-item>`)}
23013
- ${this.model?.agent.createCone ? b`<sp-menu-divider></sp-menu-divider><sp-menu-item value=${newCone} data-action="new-cone"><swc-icon-add slot="icon"></swc-icon-add>New cone</sp-menu-item>` : A}
23014
- ${this.#deletable() ? b`${this.model?.agent.createCone ? A : b`<sp-menu-divider></sp-menu-divider>`}<sp-menu-item value=${deleteActiveCone} data-action="delete-cone"><swc-icon-delete slot="icon"></swc-icon-delete>Delete cone</sp-menu-item>` : A}
23064
+ ${this.#creatable() ? b`<sp-menu-divider></sp-menu-divider><sp-menu-item value=${newCone} data-action="new-cone"><swc-icon-add slot="icon"></swc-icon-add>New cone</sp-menu-item>` : A}
23065
+ ${this.#deletable() ? b`${this.#creatable() ? A : b`<sp-menu-divider></sp-menu-divider>`}<sp-menu-item value=${deleteActiveCone} data-action="delete-cone"><swc-icon-delete slot="icon"></swc-icon-delete>Delete cone</sp-menu-item>` : A}
23015
23066
  ${this.#offers("agents") ? b`<sp-menu-divider></sp-menu-divider><sp-menu-item value=${allAgents}>Show all agents</sp-menu-item>` : A}
23016
23067
  </sp-picker>`
23017
23068
  ) : A}
@@ -24351,6 +24402,7 @@ var SliccBrowser = class extends ModelElement {
24351
24402
  this.requestUpdate();
24352
24403
  }),
24353
24404
  ...model.network ? [model.network.on("network", () => this.requestUpdate())] : [],
24405
+ ...model.follow ? [model.follow.on("follow", () => this.requestUpdate())] : [],
24354
24406
  () => clearInterval(timer),
24355
24407
  () => resize.disconnect(),
24356
24408
  () => document.removeEventListener("visibilitychange", visibility),
@@ -24503,7 +24555,7 @@ var SliccBrowser = class extends ModelElement {
24503
24555
  return tab.agentId ? `${agentName(this.model, tab.agentId)} is using this tab` : "In use";
24504
24556
  }
24505
24557
  #stopButton(tab, refocus, justified = false) {
24506
- if (!tab.agentId) return A;
24558
+ if (!tab.agentId || watchOnly(this.model)) return A;
24507
24559
  const agentId = tab.agentId;
24508
24560
  return b`<swc-button size="s" variant="secondary" ?justified=${justified} data-action="stop-agent" @click=${() => this.#stop(agentId, refocus)}>Stop ${agentName(this.model, agentId)}</swc-button>`;
24509
24561
  }
@@ -25637,7 +25689,7 @@ var SliccChat = class extends ThemedElement {
25637
25689
  if (agent.frozen) {
25638
25690
  return b`<swc-badge size="s" variant="informative" subtle>Frozen</swc-badge>
25639
25691
  <span class="frozen">Read only</span>
25640
- <swc-button size="s" variant="secondary" fill-style="outline" data-action="thaw" @click=${() => model.agent.thaw(agent.id)}>Thaw</swc-button>
25692
+ ${watchOnly(model) ? A : b`<swc-button size="s" variant="secondary" fill-style="outline" data-action="thaw" @click=${() => model.agent.thaw(agent.id)}>Thaw</swc-button>`}
25641
25693
  ${meter}`;
25642
25694
  }
25643
25695
  if (watchOnly(model)) {
@@ -26679,7 +26731,7 @@ var fieldStyles = i`
26679
26731
  outline-offset: var(--swc-focus-ring-gap);
26680
26732
  }
26681
26733
  `;
26682
- function shown2(element2, style = getComputedStyle(element2)) {
26734
+ function shown3(element2, style = getComputedStyle(element2)) {
26683
26735
  return !element2.hidden && !element2.inert && style.display !== "none";
26684
26736
  }
26685
26737
  function disabled(element2) {
@@ -26709,10 +26761,10 @@ function tabbables(root2, stop, out = []) {
26709
26761
  continue;
26710
26762
  }
26711
26763
  const style = getComputedStyle(child);
26712
- if (!shown2(child, style)) continue;
26764
+ if (!shown3(child, style)) continue;
26713
26765
  if (child.localName === "details" && !child.open) {
26714
26766
  const summary = child.querySelector(":scope > summary");
26715
- if (summary && shown2(summary) && getComputedStyle(summary).visibility !== "hidden" && !(summary.hasAttribute("tabindex") && summary.tabIndex < 0))
26767
+ if (summary && shown3(summary) && getComputedStyle(summary).visibility !== "hidden" && !(summary.hasAttribute("tabindex") && summary.tabIndex < 0))
26716
26768
  out.push(summary);
26717
26769
  continue;
26718
26770
  }
@@ -28097,8 +28149,8 @@ var SliccMemory = class extends ModelElement {
28097
28149
  const scopes = this.#scopes;
28098
28150
  const scope = this.scope;
28099
28151
  const option2 = (item2) => b`<sp-menu-item value=${item2.id}>${item2.label}</sp-menu-item>`;
28100
- const shown3 = visible(all2, scope, this.tag, this.query);
28101
- return b`<div class="bar"><span>${shown3.length} of ${all2.filter((memory) => memory.scope === scope).length} memories</span><span class="spacer"></span>
28152
+ const shown4 = visible(all2, scope, this.tag, this.query);
28153
+ return b`<div class="bar"><span>${shown4.length} of ${all2.filter((memory) => memory.scope === scope).length} memories</span><span class="spacer"></span>
28102
28154
  <swc-action-button size="s" quiet @click=${() => this.editing = "new"}><swc-icon-add slot="icon"></swc-icon-add>Remember</swc-action-button>
28103
28155
  </div>
28104
28156
  <div class="tools">
@@ -28120,7 +28172,7 @@ var SliccMemory = class extends ModelElement {
28120
28172
  </div>
28121
28173
  <div class="list">
28122
28174
  ${this.editing === "new" ? b`<div class="row">${this.#form({ scope })}</div>` : A}
28123
- ${shown3.length ? sections(shown3).map(
28175
+ ${shown4.length ? sections(shown4).map(
28124
28176
  ([section, items]) => b`<h3>${section}</h3>${items.map((memory) => this.#row(memory))}`
28125
28177
  ) : b`<div class="note">${all2.length ? "No memories match." : "No memories yet."}</div>`}
28126
28178
  </div>`;
@@ -29465,8 +29517,8 @@ var SliccSecrets = class extends ThemedElement {
29465
29517
  const before = entries[entries.length - 1]?.seq;
29466
29518
  const page = await vault.audit(before);
29467
29519
  if (this.model?.vault !== vault || !this.isConnected) return;
29468
- const shown3 = merged(vault.list()?.audit ?? [], this.older);
29469
- if (shown3[shown3.length - 1]?.seq !== before) return;
29520
+ const shown4 = merged(vault.list()?.audit ?? [], this.older);
29521
+ if (shown4[shown4.length - 1]?.seq !== before) return;
29470
29522
  this.older = merged(this.older, page.audit);
29471
29523
  this.more = page.more;
29472
29524
  } catch (error) {
@@ -29648,7 +29700,7 @@ var SliccSecrets = class extends ThemedElement {
29648
29700
  </li>`;
29649
29701
  }
29650
29702
  #audit(vault, list5, entries, devices) {
29651
- const shown3 = this.reveals ? entries.filter((entry) => entry.type === "materialize") : entries;
29703
+ const shown4 = this.reveals ? entries.filter((entry) => entry.type === "materialize") : entries;
29652
29704
  const more = this.more ?? list5.auditMore;
29653
29705
  return b`<div class="audit-head">
29654
29706
  <h3 id="secrets-audit">Activity</h3>
@@ -29656,7 +29708,7 @@ var SliccSecrets = class extends ThemedElement {
29656
29708
  this.reveals = event2.target.checked;
29657
29709
  }}>Only reveals to programs</sp-switch>
29658
29710
  </div>
29659
- ${shown3.length ? b`<ol class="audit" aria-labelledby="secrets-audit">${shown3.map((entry) => this.#entry(entry, devices))}</ol>` : b`<p class="muted" data-audit-empty>${this.reveals ? more ? "No reveals in the activity loaded so far." : "No program has been given a secret." : "Nothing has used a secret yet."}</p>`}
29711
+ ${shown4.length ? b`<ol class="audit" aria-labelledby="secrets-audit">${shown4.map((entry) => this.#entry(entry, devices))}</ol>` : b`<p class="muted" data-audit-empty>${this.reveals ? more ? "No reveals in the activity loaded so far." : "No program has been given a secret." : "Nothing has used a secret yet."}</p>`}
29660
29712
  ${more ? b`<div class="row"><swc-button size="s" variant="secondary" fill-style="outline" data-action="older" ?pending=${this.loading} @click=${() => this.showOlder(vault, entries)}>Show older</swc-button></div>` : A}`;
29661
29713
  }
29662
29714
  #feedback() {
@@ -30306,17 +30358,20 @@ var sprinkleMethods = /* @__PURE__ */ new Set([
30306
30358
  "setState"
30307
30359
  ]);
30308
30360
  var grip = w`<svg class="grip" viewBox="0 0 8 14" width="8" height="14" aria-hidden="true">${[2, 7, 12].flatMap((y10) => [2, 6].map((x7) => w`<circle cx=${x7} cy=${y10} r="1.25"></circle>`))}</svg>`;
30361
+ var plainId = (id) => id.replace(/^cone:/, "");
30309
30362
  var SliccSprinkle = class extends ThemedElement {
30310
30363
  static properties = {
30311
30364
  ...ThemedElement.properties,
30312
30365
  sprinkle: {},
30313
30366
  inline: { type: Boolean, reflect: true },
30367
+ readonly: { type: Boolean, reflect: true },
30314
30368
  height: { state: true }
30315
30369
  };
30316
30370
  constructor() {
30317
30371
  super();
30318
30372
  this.sprinkle = "";
30319
30373
  this.inline = false;
30374
+ this.readonly = false;
30320
30375
  this.height = 160;
30321
30376
  }
30322
30377
  static styles = i`
@@ -30380,6 +30435,30 @@ var SliccSprinkle = class extends ThemedElement {
30380
30435
  color: var(--spectrum-neutral-subdued-content-color-default);
30381
30436
  font-size: var(--spectrum-font-size-75);
30382
30437
  }
30438
+ .view-only {
30439
+ color: var(--spectrum-neutral-subdued-content-color-default);
30440
+ white-space: nowrap;
30441
+ overflow: hidden;
30442
+ text-overflow: ellipsis;
30443
+ padding-inline-end: 4px;
30444
+ }
30445
+ .panel {
30446
+ display: flex;
30447
+ flex-direction: column;
30448
+ height: 100%;
30449
+ }
30450
+ .panel iframe {
30451
+ flex: 1;
30452
+ min-height: 0;
30453
+ }
30454
+ .bar {
30455
+ display: flex;
30456
+ align-items: center;
30457
+ height: 28px;
30458
+ padding: 0 12px;
30459
+ border-bottom: 1px solid var(--spectrum-gray-200);
30460
+ font-size: var(--spectrum-font-size-75);
30461
+ }
30383
30462
  .note {
30384
30463
  padding: 24px;
30385
30464
  color: var(--spectrum-neutral-subdued-content-color-default);
@@ -30391,6 +30470,7 @@ var SliccSprinkle = class extends ThemedElement {
30391
30470
  const source = event2.source;
30392
30471
  const data = event2.data ?? {};
30393
30472
  if (data.type === "slicc-lick") {
30473
+ if (this.#readOnly()) return;
30394
30474
  this.model?.sprinkles.send(this.sprinkle, {
30395
30475
  action: data.action,
30396
30476
  data: data.data,
@@ -30408,10 +30488,32 @@ var SliccSprinkle = class extends ThemedElement {
30408
30488
  await this.#call(source, data);
30409
30489
  }
30410
30490
  };
30491
+ #readOnly() {
30492
+ return this.readonly || this.#frozen() || !!watchOnly(this.model);
30493
+ }
30494
+ #seen = /* @__PURE__ */ new Set();
30495
+ #frozen() {
30496
+ const owner = this.#data?.agentId;
30497
+ const port = this.model?.agent;
30498
+ if (!port || !owner) return false;
30499
+ const id = plainId(owner);
30500
+ const agents = port.list();
30501
+ const live = agents.find((agent) => plainId(agent.id) === id);
30502
+ if (live) {
30503
+ this.#seen.add(id);
30504
+ return !!live.frozen;
30505
+ }
30506
+ if (port.frozen().some((row) => !row.live && plainId(row.id) === id)) return true;
30507
+ return agents.length > 0 && this.#seen.has(id);
30508
+ }
30411
30509
  async #call(source, data) {
30412
30510
  const port = this.model?.sprinkles;
30413
30511
  if (!port?.call || typeof data.method !== "string" || !sprinkleMethods.has(data.method)) return;
30414
30512
  const method = data.method;
30513
+ if (method === "setState" && this.#readOnly()) {
30514
+ source.postMessage({ type: "slicc-result", id: data.id, error: "read-only" }, "*");
30515
+ return;
30516
+ }
30415
30517
  const args2 = Array.isArray(data.args) ? data.args : [];
30416
30518
  if (method === "setState") this.#held.value = args2[0] ?? null;
30417
30519
  try {
@@ -30464,7 +30566,8 @@ var SliccSprinkle = class extends ThemedElement {
30464
30566
  ...super.subscribe(model),
30465
30567
  () => globalThis.removeEventListener("message", this.#message),
30466
30568
  model.sprinkles.on("sprinkles", () => this.requestUpdate()),
30467
- this.#dips.on("change", () => this.requestUpdate())
30569
+ this.#dips.on("change", () => this.requestUpdate()),
30570
+ ...model.follow ? [model.follow.on("follow", () => this.requestUpdate())] : []
30468
30571
  ];
30469
30572
  }
30470
30573
  #drag = (event2) => {
@@ -30510,18 +30613,22 @@ ${data.html}`;
30510
30613
  const bridged = !!this.model?.sprinkles.call;
30511
30614
  if (bridged && !this.#held.ready) return b``;
30512
30615
  const state3 = bridged ? this.#held : void 0;
30616
+ const watch = !!watchOnly(this.model);
30617
+ const caption = watch ? b`<span class="view-only" data-view-only>View only on this device</span>` : A;
30513
30618
  const style = `color-scheme:${this.color};${this.inline ? `height:${this.height}px;` : ""}`;
30514
30619
  const frame = b`${i17(
30515
30620
  this.#mounts,
30516
- b`<iframe title=${data.title} sandbox="allow-scripts" style=${style} .srcdoc=${this.#document(data, state3)}></iframe>`
30621
+ b`<iframe title=${data.title} sandbox="allow-scripts" ?inert=${watch} style=${style} .srcdoc=${this.#document(data, state3)}></iframe>`
30517
30622
  )}`;
30518
- if (!this.inline) return frame;
30623
+ if (!this.inline)
30624
+ return watch ? b`<div class="panel"><div class="bar">${caption}</div>${frame}</div>` : frame;
30519
30625
  return b`<div class="handle" draggable="true" title="Drag into the dock or a rail to open as a panel" @dragstart=${this.#drag}>
30520
30626
  ${grip}
30521
30627
  <span class="name">${data.title}</span>
30522
30628
  <sp-action-button size="xs" quiet label=${`Open ${data.title} as a panel`} title="Open as a panel" @click=${() => this.#send("detach-sprinkle", data.id)}>
30523
30629
  <swc-icon-open-in slot="icon"></swc-icon-open-in>
30524
30630
  </sp-action-button>
30631
+ ${caption}
30525
30632
  </div>
30526
30633
  <div class="frame">${frame}</div>`;
30527
30634
  }
@@ -30779,10 +30886,10 @@ var SliccValueRequest = class extends ThemedElement {
30779
30886
  if (!vault || !request2) return A;
30780
30887
  const locked = !!vault.status()?.locked;
30781
30888
  const rest = queue.length - 1;
30782
- const shown3 = this.problem?.id === request2.id ? this.problem : null;
30783
- const problem = shown3?.text ?? "";
30784
- const name = this.#aria("name", shown3);
30785
- const field = this.#aria("value", shown3);
30889
+ const shown4 = this.problem?.id === request2.id ? this.problem : null;
30890
+ const problem = shown4?.text ?? "";
30891
+ const name = this.#aria("name", shown4);
30892
+ const field = this.#aria("value", shown4);
30786
30893
  return i17(
30787
30894
  request2.id,
30788
30895
  b`<dialog role="alertdialog" aria-labelledby="title" aria-describedby="asked" data-request=${request2.id} @cancel=${(event2) => {