@ai-ecoverse/slicc-spectrum 2.3.1 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/slicc-ui.js CHANGED
@@ -10403,10 +10403,10 @@ function parseAnsi(text4, streaming = false) {
10403
10403
  const runs = [];
10404
10404
  let style2 = plain;
10405
10405
  let start2 = 0;
10406
- const push2 = (end) => {
10407
- if (end <= start2) return;
10406
+ const push2 = (end2) => {
10407
+ if (end2 <= start2) return;
10408
10408
  const last = runs.at(-1);
10409
- const piece = text4.slice(start2, end);
10409
+ const piece = text4.slice(start2, end2);
10410
10410
  if (last?.style === style2) last.text += piece;
10411
10411
  else runs.push({ text: piece, style: style2 });
10412
10412
  };
@@ -10536,53 +10536,30 @@ function ansi(text4, streaming = false, surface2) {
10536
10536
  }
10537
10537
 
10538
10538
  // src/app/command.ts
10539
- var toShow = "Show the full command to allow it.";
10540
10539
  var toScroll = "Scroll to the end of the command to allow it.";
10541
- var clampCss = i`
10542
- .command [data-clamp] {
10543
- display: block;
10544
- max-block-size: 4lh;
10545
- overflow: hidden;
10546
- }
10547
- .full-command .chevron {
10548
- transition: transform var(--swc-animation-duration-100) var(--swc-animation-ease-out);
10549
- }
10550
- .full-command[data-shown] .chevron {
10551
- transform: rotate(180deg);
10552
- }
10553
- @media (prefers-reduced-motion: reduce) {
10554
- .full-command .chevron {
10555
- transition: none;
10556
- }
10540
+ var endCss = i`
10541
+ .command .end {
10542
+ display: inline-block;
10543
+ inline-size: 0;
10544
+ block-size: 0;
10557
10545
  }
10558
10546
  `;
10559
- var Cuts = class {
10560
- #cuts = /* @__PURE__ */ new Map();
10561
- #root;
10562
- #changed;
10563
- #observer = new ResizeObserver(() => this.measure());
10564
- constructor(root, changed2) {
10565
- this.#root = root;
10566
- this.#changed = changed2;
10567
- }
10568
- get(id) {
10569
- return this.#cuts.get(id);
10570
- }
10571
- measure() {
10572
- let changed2 = false;
10573
- for (const command2 of this.#root().querySelectorAll(".command [data-clamp]")) {
10574
- this.#observer.observe(command2);
10575
- const id = command2.dataset.clamp;
10576
- const cut = command2.clientHeight ? command2.scrollHeight > command2.clientHeight + 1 : void 0;
10577
- if (this.#cuts.get(id) === cut) continue;
10578
- changed2 = true;
10579
- if (cut === void 0) this.#cuts.delete(id);
10580
- else this.#cuts.set(id, cut);
10581
- }
10582
- if (changed2) this.#changed();
10547
+ var end = (id) => b`<span class="end" data-end=${id}></span>`;
10548
+ var Watched = class {
10549
+ #observer;
10550
+ #targets = /* @__PURE__ */ new Set();
10551
+ constructor(observer) {
10552
+ this.#observer = observer;
10553
+ }
10554
+ sync(targets) {
10555
+ const next = new Set(targets);
10556
+ for (const target of this.#targets) if (!next.has(target)) this.#observer.unobserve(target);
10557
+ for (const target of next) if (!this.#targets.has(target)) this.#observer.observe(target);
10558
+ this.#targets = next;
10583
10559
  }
10584
10560
  disconnect() {
10585
10561
  this.#observer.disconnect();
10562
+ this.#targets.clear();
10586
10563
  }
10587
10564
  };
10588
10565
  var Ends = class {
@@ -10622,16 +10599,62 @@ var Ends = class {
10622
10599
  this.#seen.delete(id);
10623
10600
  this.#looked.delete(id);
10624
10601
  }
10602
+ #watched = new Watched(this.#observer);
10625
10603
  observe() {
10626
- for (const end of this.#root().querySelectorAll("[data-end]"))
10627
- this.#observer.observe(end);
10604
+ this.#watched.sync(this.#root().querySelectorAll("[data-end]"));
10628
10605
  }
10629
10606
  disconnect() {
10630
- this.#observer.disconnect();
10607
+ this.#watched.disconnect();
10631
10608
  }
10632
10609
  };
10633
- function fullCommand(shown6, toggle) {
10634
- return b`<swc-action-button size="s" quiet class="full-command" data-action="full-command" data-shown=${shown6 ? "" : A} aria-expanded=${shown6 ? "true" : "false"} @click=${toggle}><swc-icon-chevron-down slot="icon" class="chevron" aria-hidden="true"></swc-icon-chevron-down>${shown6 ? "Hide the full command" : "Show the full command"}</swc-action-button>`;
10610
+ var Arming = class {
10611
+ #ms;
10612
+ #changed = 0;
10613
+ #pressed = 0;
10614
+ #layout = "";
10615
+ constructor(ms) {
10616
+ this.#ms = ms;
10617
+ }
10618
+ arm() {
10619
+ this.#changed = performance.now();
10620
+ }
10621
+ press = () => {
10622
+ this.#pressed = performance.now();
10623
+ };
10624
+ settled(at = performance.now()) {
10625
+ return at - this.#changed >= this.#ms();
10626
+ }
10627
+ counts(event2) {
10628
+ return this.settled(event2.detail ? this.#pressed : performance.now());
10629
+ }
10630
+ watch(layout2) {
10631
+ if (layout2 === this.#layout) return;
10632
+ this.#layout = layout2;
10633
+ this.arm();
10634
+ }
10635
+ forget() {
10636
+ this.#layout = "";
10637
+ }
10638
+ };
10639
+ function layout(buttons, head = [], frame) {
10640
+ const box = frame?.getBoundingClientRect();
10641
+ const x5 = box ? box.left - frame.scrollLeft : 0;
10642
+ const y8 = box ? box.top - frame.scrollTop : 0;
10643
+ return JSON.stringify([
10644
+ ...head,
10645
+ box ? [box.left, box.top].map(Math.round) : null,
10646
+ buttons.map((button) => {
10647
+ const { left, top, width, height } = button.getBoundingClientRect();
10648
+ return [
10649
+ button.closest("[data-id]")?.dataset.id ?? null,
10650
+ button.dataset.action,
10651
+ button.textContent,
10652
+ button.hasAttribute("disabled"),
10653
+ button.hasAttribute("pending"),
10654
+ ...width || height ? [left - x5, top - y8, width, height].map(Math.round) : []
10655
+ ];
10656
+ })
10657
+ ]);
10635
10658
  }
10636
10659
 
10637
10660
  // node_modules/@adobe/spectrum-wc/dist/components/ui-icons/ui-icons.types.js
@@ -14484,13 +14507,13 @@ function decodeNamedCharacterReference(value) {
14484
14507
 
14485
14508
  // node_modules/micromark-util-chunked/index.js
14486
14509
  function splice(list6, start2, remove2, items) {
14487
- const end = list6.length;
14510
+ const end2 = list6.length;
14488
14511
  let chunkStart = 0;
14489
14512
  let parameters;
14490
14513
  if (start2 < 0) {
14491
- start2 = -start2 > end ? 0 : end + start2;
14514
+ start2 = -start2 > end2 ? 0 : end2 + start2;
14492
14515
  } else {
14493
- start2 = start2 > end ? end : start2;
14516
+ start2 = start2 > end2 ? end2 : start2;
14494
14517
  }
14495
14518
  remove2 = remove2 > 0 ? remove2 : 0;
14496
14519
  if (items.length < 1e4) {
@@ -15044,11 +15067,11 @@ function resolveAllAttention(events, context) {
15044
15067
  const start2 = {
15045
15068
  ...events[open][1].end
15046
15069
  };
15047
- const end = {
15070
+ const end2 = {
15048
15071
  ...events[index2][1].start
15049
15072
  };
15050
15073
  movePoint(start2, -use);
15051
- movePoint(end, use);
15074
+ movePoint(end2, use);
15052
15075
  const openingSequence = {
15053
15076
  type: use > 1 ? "strongSequence" : "emphasisSequence",
15054
15077
  start: start2,
@@ -15061,7 +15084,7 @@ function resolveAllAttention(events, context) {
15061
15084
  start: {
15062
15085
  ...events[index2][1].start
15063
15086
  },
15064
- end
15087
+ end: end2
15065
15088
  };
15066
15089
  const text4 = {
15067
15090
  type: use > 1 ? "strongText" : "emphasisText",
@@ -15825,8 +15848,8 @@ var SpliceBuffer = class {
15825
15848
  * @returns {Array<T>}
15826
15849
  * Array of items.
15827
15850
  */
15828
- slice(start2, end) {
15829
- const stop = end === null || end === void 0 ? Number.POSITIVE_INFINITY : end;
15851
+ slice(start2, end2) {
15852
+ const stop = end2 === null || end2 === void 0 ? Number.POSITIVE_INFINITY : end2;
15830
15853
  if (stop < this.left.length) {
15831
15854
  return this.left.slice(start2, stop);
15832
15855
  }
@@ -17123,7 +17146,7 @@ function tokenizeHtmlText(effects, ok4, nok) {
17123
17146
  return comment(code3);
17124
17147
  }
17125
17148
  function commentEnd(code3) {
17126
- return code3 === 62 ? end(code3) : code3 === 45 ? commentClose(code3) : comment(code3);
17149
+ return code3 === 62 ? end2(code3) : code3 === 45 ? commentClose(code3) : comment(code3);
17127
17150
  }
17128
17151
  function cdataOpenInside(code3) {
17129
17152
  const value = "CDATA[";
@@ -17157,7 +17180,7 @@ function tokenizeHtmlText(effects, ok4, nok) {
17157
17180
  }
17158
17181
  function cdataEnd(code3) {
17159
17182
  if (code3 === 62) {
17160
- return end(code3);
17183
+ return end2(code3);
17161
17184
  }
17162
17185
  if (code3 === 93) {
17163
17186
  effects.consume(code3);
@@ -17167,7 +17190,7 @@ function tokenizeHtmlText(effects, ok4, nok) {
17167
17190
  }
17168
17191
  function declaration(code3) {
17169
17192
  if (code3 === null || code3 === 62) {
17170
- return end(code3);
17193
+ return end2(code3);
17171
17194
  }
17172
17195
  if (markdownLineEnding(code3)) {
17173
17196
  returnState = declaration;
@@ -17192,7 +17215,7 @@ function tokenizeHtmlText(effects, ok4, nok) {
17192
17215
  return instruction;
17193
17216
  }
17194
17217
  function instructionClose(code3) {
17195
- return code3 === 62 ? end(code3) : instruction(code3);
17218
+ return code3 === 62 ? end2(code3) : instruction(code3);
17196
17219
  }
17197
17220
  function tagCloseStart(code3) {
17198
17221
  if (asciiAlpha(code3)) {
@@ -17217,7 +17240,7 @@ function tokenizeHtmlText(effects, ok4, nok) {
17217
17240
  effects.consume(code3);
17218
17241
  return tagCloseBetween;
17219
17242
  }
17220
- return end(code3);
17243
+ return end2(code3);
17221
17244
  }
17222
17245
  function tagOpen(code3) {
17223
17246
  if (code3 === 45 || asciiAlphanumeric(code3)) {
@@ -17232,7 +17255,7 @@ function tokenizeHtmlText(effects, ok4, nok) {
17232
17255
  function tagOpenBetween(code3) {
17233
17256
  if (code3 === 47) {
17234
17257
  effects.consume(code3);
17235
- return end;
17258
+ return end2;
17236
17259
  }
17237
17260
  if (code3 === 58 || code3 === 95 || asciiAlpha(code3)) {
17238
17261
  effects.consume(code3);
@@ -17246,7 +17269,7 @@ function tokenizeHtmlText(effects, ok4, nok) {
17246
17269
  effects.consume(code3);
17247
17270
  return tagOpenBetween;
17248
17271
  }
17249
- return end(code3);
17272
+ return end2(code3);
17250
17273
  }
17251
17274
  function tagOpenAttributeName(code3) {
17252
17275
  if (code3 === 45 || code3 === 46 || code3 === 58 || code3 === 95 || asciiAlphanumeric(code3)) {
@@ -17322,7 +17345,7 @@ function tokenizeHtmlText(effects, ok4, nok) {
17322
17345
  }
17323
17346
  return nok(code3);
17324
17347
  }
17325
- function end(code3) {
17348
+ function end2(code3) {
17326
17349
  if (code3 === 62) {
17327
17350
  effects.consume(code3);
17328
17351
  effects.exit("htmlTextData");
@@ -18538,7 +18561,7 @@ function preprocess() {
18538
18561
  let start2 = true;
18539
18562
  let atCarriageReturn;
18540
18563
  return preprocessor;
18541
- function preprocessor(value, encoding, end) {
18564
+ function preprocessor(value, encoding, end2) {
18542
18565
  value = buffer + (typeof value === "string" ? value.toString() : new TextDecoder(encoding || void 0).decode(value));
18543
18566
  const chunks = [];
18544
18567
  let startPosition = 0;
@@ -18597,7 +18620,7 @@ function preprocess() {
18597
18620
  }
18598
18621
  startPosition = endPosition + 1;
18599
18622
  }
18600
- if (end) {
18623
+ if (end2) {
18601
18624
  if (atCarriageReturn) {
18602
18625
  chunks.push(-5);
18603
18626
  }
@@ -18850,7 +18873,7 @@ function compiler(options2) {
18850
18873
  }
18851
18874
  }
18852
18875
  function prepareList(events, start2) {
18853
- const end = events.length - 1;
18876
+ const end2 = events.length - 1;
18854
18877
  let index2 = start2 - 1;
18855
18878
  let containerBalance = -1;
18856
18879
  let listSpread = false;
@@ -18859,7 +18882,7 @@ function compiler(options2) {
18859
18882
  let firstBlankLineIndex;
18860
18883
  let atMarker;
18861
18884
  const insertions = [];
18862
- while (++index2 <= end) {
18885
+ while (++index2 <= end2) {
18863
18886
  const event2 = events[index2];
18864
18887
  switch (event2[1].type) {
18865
18888
  case "listUnordered":
@@ -20896,8 +20919,8 @@ function flushCell(map, context, range2, rowKind, rowEnd, previousCell) {
20896
20919
  map.add(range2[2], 0, [["enter", valueToken, context]]);
20897
20920
  if (rowKind !== 2) {
20898
20921
  const start2 = context.events[range2[2]];
20899
- const end = context.events[range2[3]];
20900
- start2[1].end = Object.assign({}, end[1].end);
20922
+ const end2 = context.events[range2[3]];
20923
+ start2[1].end = Object.assign({}, end2[1].end);
20901
20924
  start2[1].type = "chunkText";
20902
20925
  start2[1].contentType = "text";
20903
20926
  if (range2[3] > range2[2] + 1) {
@@ -21711,19 +21734,19 @@ var InteractionManager = class {
21711
21734
  lineNumber: range2.start,
21712
21735
  side: range2.side
21713
21736
  };
21714
- const end = {
21737
+ const end2 = {
21715
21738
  lineNumber: range2.end,
21716
21739
  side: range2.endSide ?? range2.side
21717
21740
  };
21718
21741
  const startIndex = this.selectionPointRowIndex(start2);
21719
- const endIndex = this.selectionPointRowIndex(end);
21742
+ const endIndex = this.selectionPointRowIndex(end2);
21720
21743
  if (startIndex == null || endIndex == null) return;
21721
21744
  return startIndex > endIndex ? {
21722
- top: end,
21745
+ top: end2,
21723
21746
  bottom: start2
21724
21747
  } : {
21725
21748
  top: start2,
21726
- bottom: end
21749
+ bottom: end2
21727
21750
  };
21728
21751
  }
21729
21752
  selectionPointRowIndex(point3) {
@@ -22040,10 +22063,10 @@ var InteractionManager = class {
22040
22063
  buildSelectedLineRange(anchor, current) {
22041
22064
  return this.buildSelectionRange(anchor.lineNumber, current.lineNumber, anchor.side, current.side);
22042
22065
  }
22043
- buildSelectionRange(start2, end, side, endSide) {
22066
+ buildSelectionRange(start2, end2, side, endSide) {
22044
22067
  return {
22045
22068
  start: start2,
22046
- end,
22069
+ end: end2,
22047
22070
  ...side != null ? { side } : {},
22048
22071
  ...side !== endSide && endSide != null ? { endSide } : {}
22049
22072
  };
@@ -23383,8 +23406,8 @@ function linesFromFileContents(contents) {
23383
23406
  const offsets = computeLineOffsets(contents);
23384
23407
  return Array.from({ length: offsets.length }, (_7, i26) => {
23385
23408
  const start2 = offsets[i26];
23386
- const end = offsets[i26 + 1] ?? contents.length;
23387
- return contents.slice(start2, end);
23409
+ const end2 = offsets[i26 + 1] ?? contents.length;
23410
+ return contents.slice(start2, end2);
23388
23411
  });
23389
23412
  }
23390
23413
 
@@ -25957,12 +25980,12 @@ function getLoadedFileCacheKey(oldFile, newFile) {
25957
25980
 
25958
25981
  // node_modules/@pierre/diffs/dist/utils/cleanLastNewline.js
25959
25982
  function cleanLastNewline(contents) {
25960
- let end = contents.length;
25961
- if (contents.charCodeAt(end - 1) === 10) {
25962
- end--;
25963
- if (contents.charCodeAt(end - 1) === 13) end--;
25983
+ let end2 = contents.length;
25984
+ if (contents.charCodeAt(end2 - 1) === 10) {
25985
+ end2--;
25986
+ if (contents.charCodeAt(end2 - 1) === 13) end2--;
25964
25987
  }
25965
- return contents.slice(0, end);
25988
+ return contents.slice(0, end2);
25966
25989
  }
25967
25990
 
25968
25991
  // node_modules/@pierre/diffs/dist/utils/detachString.js
@@ -27747,12 +27770,12 @@ function getNearestRenderableAdditionLine({ fileDiff, lineNumber, direction, exp
27747
27770
  }
27748
27771
  if (lineNumber >= modeledEnd) return lineNumber;
27749
27772
  if (direction === "down") {
27750
- for (const [start2, end] of ranges2) if (end > lineNumber) return Math.max(start2, lineNumber);
27773
+ for (const [start2, end2] of ranges2) if (end2 > lineNumber) return Math.max(start2, lineNumber);
27751
27774
  return;
27752
27775
  }
27753
27776
  for (let index2 = ranges2.length - 1; index2 >= 0; index2--) {
27754
- const [start2, end] = ranges2[index2];
27755
- if (start2 <= lineNumber) return Math.min(end - 1, lineNumber);
27777
+ const [start2, end2] = ranges2[index2];
27778
+ if (start2 <= lineNumber) return Math.min(end2 - 1, lineNumber);
27756
27779
  }
27757
27780
  }
27758
27781
 
@@ -28116,20 +28139,20 @@ function getContextLineIterationBounds(state2, count2, diffStyle) {
28116
28139
  const ranges2 = [];
28117
28140
  function pushRange(currentCount) {
28118
28141
  const start3 = Math.max(0, state2.viewportStart - currentCount);
28119
- const end2 = Math.min(count2, state2.viewportEnd - currentCount);
28120
- if (end2 > start3) ranges2.push([start3, end2]);
28142
+ const end3 = Math.min(count2, state2.viewportEnd - currentCount);
28143
+ if (end3 > start3) ranges2.push([start3, end3]);
28121
28144
  }
28122
28145
  if (diffStyle !== "split") pushRange(state2.unifiedCount);
28123
28146
  if (diffStyle !== "unified") pushRange(state2.splitCount);
28124
28147
  if (ranges2.length === 0) return [0, 0];
28125
28148
  let start2 = ranges2[0][0];
28126
- let end = ranges2[0][1];
28149
+ let end2 = ranges2[0][1];
28127
28150
  for (let index2 = 1; index2 < ranges2.length; index2++) {
28128
28151
  const range2 = ranges2[index2];
28129
28152
  start2 = Math.min(start2, range2[0]);
28130
- end = Math.max(end, range2[1]);
28153
+ end2 = Math.max(end2, range2[1]);
28131
28154
  }
28132
- return [start2, end];
28155
+ return [start2, end2];
28133
28156
  }
28134
28157
  function walkContextLines(state2, count2, diffStyle, callback, onSkippedStart, shouldBreak) {
28135
28158
  const [startIndex, endIndex] = getContextLineIterationBounds(state2, count2, diffStyle);
@@ -28169,8 +28192,8 @@ function getChangeIterationRanges(state2, content3, diffStyle) {
28169
28192
  }
28170
28193
  function pushRange(range2, kind) {
28171
28194
  if (range2 == null) return;
28172
- const [start2, end] = mapRangeToIteration(range2, kind);
28173
- if (end > start2) iterationRanges.push([start2, end]);
28195
+ const [start2, end2] = mapRangeToIteration(range2, kind);
28196
+ if (end2 > start2) iterationRanges.push([start2, end2]);
28174
28197
  }
28175
28198
  if (useUnified) {
28176
28199
  pushRange(getVisibleRange(state2.unifiedCount, content3.deletions), "deletions");
@@ -28183,10 +28206,10 @@ function getChangeIterationRanges(state2, content3, diffStyle) {
28183
28206
  if (iterationRanges.length === 0) return iterationRanges;
28184
28207
  iterationRanges.sort((a20, b10) => a20[0] - b10[0]);
28185
28208
  const merged2 = [iterationRanges[0]];
28186
- for (const [start2, end] of iterationRanges.slice(1)) {
28209
+ for (const [start2, end2] of iterationRanges.slice(1)) {
28187
28210
  const last = merged2[merged2.length - 1];
28188
- if (start2 <= last[1]) last[1] = Math.max(last[1], end);
28189
- else merged2.push([start2, end]);
28211
+ if (start2 <= last[1]) last[1] = Math.max(last[1], end2);
28212
+ else merged2.push([start2, end2]);
28190
28213
  }
28191
28214
  return merged2;
28192
28215
  }
@@ -28651,8 +28674,8 @@ function getAffectedHunkIndexes(diff, changedAdditionLineIndexes) {
28651
28674
  }
28652
28675
  function findHunkIndexForAdditionLine(diff, line) {
28653
28676
  for (const [hunkIndex, hunk] of diff.hunks.entries()) {
28654
- const end = hunk.additionLineIndex + hunk.additionCount;
28655
- if (line >= hunk.additionLineIndex && line < end) return hunkIndex;
28677
+ const end2 = hunk.additionLineIndex + hunk.additionCount;
28678
+ if (line >= hunk.additionLineIndex && line < end2) return hunkIndex;
28656
28679
  }
28657
28680
  }
28658
28681
  function reparseHunkRegion(diff, hunkIndex, parseDiffOptions) {
@@ -28904,10 +28927,10 @@ function rebuildExpansionFromAnchors(diff, anchors) {
28904
28927
  if (gapEnd <= gapStart) return;
28905
28928
  let fromStart = 0;
28906
28929
  let fromEnd = 0;
28907
- for (const [start2, end] of anchors) {
28908
- if (end <= gapStart || start2 >= gapEnd) continue;
28909
- if (start2 <= gapStart) fromStart = Math.max(fromStart, Math.min(end, gapEnd) - gapStart);
28910
- if (end >= gapEnd) fromEnd = Math.max(fromEnd, gapEnd - Math.max(start2, gapStart));
28930
+ for (const [start2, end2] of anchors) {
28931
+ if (end2 <= gapStart || start2 >= gapEnd) continue;
28932
+ if (start2 <= gapStart) fromStart = Math.max(fromStart, Math.min(end2, gapEnd) - gapStart);
28933
+ if (end2 >= gapEnd) fromEnd = Math.max(fromEnd, gapEnd - Math.max(start2, gapStart));
28911
28934
  }
28912
28935
  if (fromStart > 0 || fromEnd > 0) rebuilt.set(key, {
28913
28936
  fromStart,
@@ -32778,8 +32801,8 @@ var closing = /^[\s>]*(`{3,}|~{3,})[ \t]*$/;
32778
32801
  function sealed(source) {
32779
32802
  const lines = source.split("\n");
32780
32803
  const open = lines[0].match(opening)[1];
32781
- const end = lines.length > 1 ? lines.at(-1).match(closing)?.[1] : void 0;
32782
- return !!end && end[0] === open[0] && end.length >= open.length;
32804
+ const end2 = lines.length > 1 ? lines.at(-1).match(closing)?.[1] : void 0;
32805
+ return !!end2 && end2[0] === open[0] && end2.length >= open.length;
32783
32806
  }
32784
32807
  function seal(nodes, source) {
32785
32808
  for (const node2 of nodes) {
@@ -33991,10 +34014,10 @@ function show(turn) {
33991
34014
  ].find((candidate) => candidate.dataset.place === turn.dataset.id);
33992
34015
  const log = place4?.closest(".log");
33993
34016
  if (!log) return;
33994
- const end = Number.parseFloat(getComputedStyle(log).scrollPaddingBlockEnd) || 0;
34017
+ const end2 = Number.parseFloat(getComputedStyle(log).scrollPaddingBlockEnd) || 0;
33995
34018
  const at = place4.getBoundingClientRect().top - log.getBoundingClientRect().top;
33996
34019
  log.scrollTo({
33997
- top: log.scrollTop + at - log.clientHeight + end,
34020
+ top: log.scrollTop + at - log.clientHeight + end2,
33998
34021
  behavior: still() ? "auto" : "smooth"
33999
34022
  });
34000
34023
  }
@@ -34007,16 +34030,19 @@ function spokenLeft(left, at) {
34007
34030
  return left <= 6e4 ? "Less than a minute left" : `Expires at ${deadline(at)}`;
34008
34031
  }
34009
34032
  function decide(message, handlers, settled4) {
34010
- const commands3 = settled4 || !message.body ? void 0 : handlers.commands;
34011
- const full = commands3?.has(message.id) ?? true;
34012
- const cut = commands3?.cut(message.id);
34013
- const toggle = commands3 && (full || cut) ? fullCommand(full, () => commands3.toggle(message.id)) : A;
34014
- const actions2 = b`${commands3 && !full && cut ? b`<p class="allow-hint" data-allow-hint>${toShow}</p>` : A}<div class="decide">
34015
- ${toggle}
34016
- <swc-button size="s" variant="secondary" fill-style="outline" data-action="deny" ?disabled=${handlers.readOnly} @click=${() => handlers.resolve(message.id, "dismissed")}>Deny</swc-button>
34017
- ${full || cut === false ? b`<swc-button size="s" variant="accent" data-action="allow" ?disabled=${handlers.readOnly} @click=${() => handlers.resolve(message.id, "confirmed")}>Allow</swc-button>` : A}
34033
+ const { id, body: body2 } = message;
34034
+ const commands3 = settled4 ? void 0 : handlers.commands;
34035
+ const gated = !!body2 && !!commands3;
34036
+ const whole = !gated || !!commands3?.seen(id);
34037
+ const choose = (event2, state2) => {
34038
+ if (commands3?.armed(event2) === false || state2 === "confirmed" && !whole) return;
34039
+ handlers.resolve(id, state2);
34040
+ };
34041
+ const actions2 = b`<div class="decide">
34042
+ <swc-button size="s" variant="secondary" fill-style="outline" data-action="deny" ?disabled=${handlers.readOnly} @click=${(event2) => choose(event2, "dismissed")}>Deny</swc-button>
34043
+ <swc-button size="s" variant="accent" data-action="allow" ?disabled=${handlers.readOnly || !whole} @click=${(event2) => choose(event2, "confirmed")}>Allow</swc-button>
34018
34044
  </div>`;
34019
- const command2 = message.body ? b`<pre class="command"><span class="lines" data-clamp=${full ? A : message.id}>${message.body}</span></pre>` : A;
34045
+ const command2 = body2 ? b`<pre class="command"><span class="lines">${body2}${gated ? end(id) : A}</span></pre>` : A;
34020
34046
  return { actions: actions2, command: command2 };
34021
34047
  }
34022
34048
  function decision(message, handlers) {
@@ -34811,14 +34837,6 @@ var messageCss = i`
34811
34837
  justify-content: flex-end;
34812
34838
  padding: 0;
34813
34839
  }
34814
- .decide .full-command {
34815
- margin-inline-end: auto;
34816
- }
34817
- .decision .allow-hint {
34818
- margin: 0;
34819
- color: var(--swc-neutral-subdued-content-color-default);
34820
- font-size: var(--swc-font-size-75);
34821
- }
34822
34840
  .question.decision .options {
34823
34841
  display: flex;
34824
34842
  flex-wrap: wrap;
@@ -35113,10 +35131,44 @@ var SliccVaultButton = class extends i2 {
35113
35131
  }
35114
35132
  }
35115
35133
  };
35134
+ function valueConfig(doc, theme3) {
35135
+ const lang = doc.documentElement.lang;
35136
+ return {
35137
+ theme: theme3,
35138
+ dir: doc.documentElement.dir === "rtl" ? "rtl" : "ltr",
35139
+ ...lang ? { lang } : {}
35140
+ };
35141
+ }
35142
+ function enters(vault) {
35143
+ return !!(vault?.enter && vault.valueFrame);
35144
+ }
35145
+ function ours(detail, request2, open) {
35146
+ if (request2 !== open) return false;
35147
+ return !("request" in detail) || detail.request === void 0 || detail.request === request2;
35148
+ }
35149
+ function drop(vault, request2) {
35150
+ void vault?.cancel?.(request2).catch(() => {
35151
+ });
35152
+ }
35153
+ function goneText(state2) {
35154
+ return state2 === "expired" ? "The vault\u2019s field timed out. Try again." : "The vault\u2019s field closed. Try again.";
35155
+ }
35156
+ function valueField(vault, request2, config, on2) {
35157
+ return b`<div class="value-field" data-value-frame><slicc-vault-value .vault=${vault} .request=${request2} .config=${config} @vault-value=${(event2) => on2(event2.detail, request2)}></slicc-vault-value></div>`;
35158
+ }
35116
35159
  var frameHeight = 480;
35117
35160
  var frameInset = 4;
35118
35161
  var between = (value, most) => typeof value === "number" && Number.isFinite(value) ? Math.min(Math.max(value, 0), most) : 0;
35119
- var picked = ["event", "request", "state", "code", "message"];
35162
+ var picked = [
35163
+ "event",
35164
+ "request",
35165
+ "state",
35166
+ "code",
35167
+ "message",
35168
+ "name",
35169
+ "placeholder",
35170
+ "record"
35171
+ ];
35120
35172
  function pick(event2) {
35121
35173
  const fields = event2;
35122
35174
  return Object.fromEntries(
@@ -35130,6 +35182,7 @@ var SliccVaultValue = class extends i2 {
35130
35182
  config: { attribute: false }
35131
35183
  };
35132
35184
  #frame = null;
35185
+ #focusing = false;
35133
35186
  #off = null;
35134
35187
  #ready = false;
35135
35188
  #sent = "";
@@ -35164,7 +35217,8 @@ var SliccVaultValue = class extends i2 {
35164
35217
  this.#drop();
35165
35218
  }
35166
35219
  focus() {
35167
- this.#frame?.post({ type: "slicc-vault", v: 1, op: "focus" });
35220
+ this.#focusing = !this.#ready;
35221
+ if (this.#ready) this.#frame?.post({ type: "slicc-vault", v: 1, op: "focus" });
35168
35222
  }
35169
35223
  updated(changed2) {
35170
35224
  if (changed2.has("vault") || changed2.has("request")) this.#drop();
@@ -35205,6 +35259,7 @@ var SliccVaultValue = class extends i2 {
35205
35259
  if (event2.event === "ready") {
35206
35260
  this.#ready = true;
35207
35261
  this.#send();
35262
+ if (this.#focusing) this.focus();
35208
35263
  } else if (event2.event === "size") {
35209
35264
  const inset = between(event2.inset, frameInset);
35210
35265
  element2.style.blockSize = `${between(event2.height, frameHeight)}px`;
@@ -35584,6 +35639,8 @@ var SliccComposer = class extends ThemedElement {
35584
35639
  sharing: { state: true },
35585
35640
  secretError: { state: true },
35586
35641
  secretField: { state: true },
35642
+ secretName: { state: true },
35643
+ entry: { state: true },
35587
35644
  failure: { state: true },
35588
35645
  reattach: { state: true },
35589
35646
  agent: {}
@@ -35617,6 +35674,8 @@ var SliccComposer = class extends ThemedElement {
35617
35674
  this.sharing = false;
35618
35675
  this.secretError = null;
35619
35676
  this.secretField = null;
35677
+ this.secretName = "";
35678
+ this.entry = null;
35620
35679
  this.failure = null;
35621
35680
  this.reattach = null;
35622
35681
  this.agent = "";
@@ -35903,6 +35962,9 @@ var SliccComposer = class extends ThemedElement {
35903
35962
  flex-wrap: wrap;
35904
35963
  gap: var(--swc-spacing-100);
35905
35964
  }
35965
+ .secret .value-field {
35966
+ min-inline-size: min(22rem, 70vw);
35967
+ }
35906
35968
  .secret-error {
35907
35969
  display: flex;
35908
35970
  align-items: flex-start;
@@ -35921,7 +35983,11 @@ var SliccComposer = class extends ThemedElement {
35921
35983
  ];
35922
35984
  willUpdate(changed2) {
35923
35985
  super.willUpdate(changed2);
35924
- if (changed2.has("popup") && this.popup?.kind !== "secret") clearValues(this.renderRoot);
35986
+ if (changed2.has("popup") && this.popup?.kind !== "secret") {
35987
+ clearValues(this.renderRoot);
35988
+ this.#leave();
35989
+ this.secretName = "";
35990
+ }
35925
35991
  if (changed2.has("agent") && this.agent && this.model && this.agent !== this.#agent) {
35926
35992
  this.#switch(this.agent);
35927
35993
  }
@@ -35951,6 +36017,7 @@ var SliccComposer = class extends ThemedElement {
35951
36017
  globalThis.removeEventListener("blur", this.#release);
35952
36018
  globalThis.removeEventListener("pointerdown", this.#outside, true);
35953
36019
  clearValues(this.renderRoot);
36020
+ this.#leave();
35954
36021
  const kept3 = this.#waiting.draft?.attachments;
35955
36022
  const held2 = [
35956
36023
  this.attachments === kept3 ? [] : this.attachments,
@@ -36205,6 +36272,88 @@ ${this.value}` : text4;
36205
36272
  ];
36206
36273
  this.popup = null;
36207
36274
  }
36275
+ #clean(name) {
36276
+ return name.trim().toUpperCase().replace(/[^A-Z0-9_]/g, "_");
36277
+ }
36278
+ #exists(vault, name) {
36279
+ return !!vault?.list()?.secrets.some(
36280
+ (secret) => secret.name === name && secret.kind === "secret" && secret.state !== "removed"
36281
+ );
36282
+ }
36283
+ #attach(name) {
36284
+ this.#refuse(null);
36285
+ this.attachments = [
36286
+ ...this.attachments,
36287
+ { id: this.#id(), name, kind: "secret", mimeType: "application/octet-stream", size: 0 }
36288
+ ];
36289
+ this.popup = null;
36290
+ }
36291
+ #leave() {
36292
+ const entry = this.entry;
36293
+ if (!entry) return;
36294
+ this.entry = null;
36295
+ drop(entry.vault, entry.request);
36296
+ }
36297
+ async enterSecret(name, replace2 = false) {
36298
+ const vault = this.model?.vault;
36299
+ const clean = this.#clean(name);
36300
+ if (this.sharing) return;
36301
+ const bad = clean ? nameProblem(clean) : "Enter a name";
36302
+ if (bad) {
36303
+ this.#refuse(bad, "name", true);
36304
+ return;
36305
+ }
36306
+ if (!replace2 && this.#exists(vault, clean)) {
36307
+ this.#attach(clean);
36308
+ return;
36309
+ }
36310
+ const agent = this.#agent;
36311
+ const mine2 = () => this.#agent === agent && this.model?.vault === vault;
36312
+ this.sharing = true;
36313
+ try {
36314
+ if (replace2) {
36315
+ const sure = await confirm({
36316
+ title: `Replace ${clean}?`,
36317
+ body: "A secret with this name exists. Sharing replaces its value, and its placeholder stays.",
36318
+ action: "Replace",
36319
+ variant: "confirmation"
36320
+ });
36321
+ if (!sure || !mine2()) return;
36322
+ }
36323
+ const { request: request2 } = await vault.enter({
36324
+ name: clean,
36325
+ ...replace2 ? { replace: true } : {}
36326
+ });
36327
+ if (!mine2() || this.popup?.kind !== "secret") {
36328
+ drop(vault, request2);
36329
+ return;
36330
+ }
36331
+ this.#refuse(null);
36332
+ this.entry = { request: request2, name: clean, vault };
36333
+ void this.updateComplete.then(
36334
+ () => this.renderRoot.querySelector("slicc-vault-value")?.focus()
36335
+ );
36336
+ } catch (error) {
36337
+ if (mine2()) this.#refuse(failureText(error), fieldOf(error, "name"), true);
36338
+ } finally {
36339
+ this.sharing = false;
36340
+ }
36341
+ }
36342
+ #entered(detail, request2) {
36343
+ const entry = this.entry;
36344
+ if (!entry || !ours(detail, request2, entry.request)) return;
36345
+ if (detail.event === "error") {
36346
+ this.#refuse(detail.message);
36347
+ return;
36348
+ }
36349
+ if (detail.event === "escape") {
36350
+ this.closeSecret();
36351
+ return;
36352
+ }
36353
+ this.entry = null;
36354
+ if (detail.event === "done") this.#attach(entry.name);
36355
+ else this.#refuse(goneText(detail.state));
36356
+ }
36208
36357
  #refuse(text4, field3 = null, focus = false) {
36209
36358
  this.secretError = text4;
36210
36359
  this.secretField = text4 ? field3 : null;
@@ -36298,6 +36447,7 @@ ${this.value}` : text4;
36298
36447
  }
36299
36448
  closeSecret() {
36300
36449
  clearValues(this.renderRoot);
36450
+ this.#leave();
36301
36451
  this.popup = null;
36302
36452
  }
36303
36453
  openPopup(kind) {
@@ -36529,9 +36679,11 @@ ${this.value}` : text4;
36529
36679
  #popup() {
36530
36680
  const popup2 = this.popup;
36531
36681
  if (!popup2) return A;
36682
+ if (popup2.kind === "secret" && this.#framed())
36683
+ return this.#entering(this.model?.vault);
36532
36684
  if (popup2.kind === "secret") {
36533
36685
  const vault = this.model?.vault;
36534
- const valued = !!vault?.put && !blocked(vault);
36686
+ const valued = !!vault?.put && !vault.enter && !blocked(vault);
36535
36687
  const waiting3 = vault?.put ? blocked(vault) : null;
36536
36688
  if (!valued) clearValues(this.renderRoot);
36537
36689
  const submit = (event2) => {
@@ -36592,6 +36744,50 @@ ${this.value}` : text4;
36592
36744
  ) : b`<div class="empty">Nothing matches.</div>`}
36593
36745
  </div>`;
36594
36746
  }
36747
+ #framed() {
36748
+ const vault = this.model?.vault;
36749
+ return enters(vault) && (!!this.entry || !away(vault));
36750
+ }
36751
+ #entering(vault) {
36752
+ const entry = this.entry;
36753
+ const close = (event2) => {
36754
+ if (event2.key === "Escape") this.closeSecret();
36755
+ };
36756
+ const cancel = b`<swc-button size="s" variant="secondary" fill-style="outline" data-action="cancel-secret" ?disabled=${this.sharing} @click=${() => this.closeSecret()}>Cancel</swc-button>`;
36757
+ const error = this.secretError ? b`<span class="secret-error" role="alert" id="secret-error" data-error><swc-icon-alert-triangle size="s" aria-hidden="true"></swc-icon-alert-triangle><span>${this.secretError}</span></span>` : A;
36758
+ if (entry)
36759
+ return b`<form class="popup secret" data-vault="on" data-entry @submit=${(event2) => event2.preventDefault()} @keydown=${close}>
36760
+ <strong>Share a secret</strong>
36761
+ <span class="lead">Type the value of <code>${entry.name}</code> in the vault’s own field. The agent only sees its name.</span>
36762
+ ${valueField(vault, entry.request, valueConfig(this.ownerDocument, this.color), (detail, request2) => this.#entered(detail, request2))}
36763
+ ${error}
36764
+ <span class="buttons">
36765
+ <swc-button size="s" variant="secondary" fill-style="outline" data-action="back-secret" @click=${() => this.#leave()}>Back</swc-button>
36766
+ ${cancel}
36767
+ </span>
36768
+ </form>`;
36769
+ const name = this.#clean(this.secretName);
36770
+ const exists = !!name && this.#exists(vault, name);
36771
+ const bad = this.secretField === "name" ? "true" : A;
36772
+ const submit = (event2) => {
36773
+ event2.preventDefault();
36774
+ void this.enterSecret(this.secretName);
36775
+ };
36776
+ return b`<form class="popup secret" data-vault="on" @submit=${submit} @keydown=${close} @input=${(event2) => {
36777
+ this.secretField = null;
36778
+ this.secretName = event2.target.value;
36779
+ }}>
36780
+ <strong>Share a secret</strong>
36781
+ <span class="lead">${exists ? b`<code>${name}</code> is in the vault. Share it as it is, or replace its value first.` : "You type the value in the vault\u2019s own field next; the agent only sees its name."}</span>
36782
+ <label class="field"><span>Name</span><input name="name" placeholder="API_TOKEN" autocomplete="off" spellcheck="false" .value=${this.secretName} aria-invalid=${bad} aria-describedby=${this.secretField === "name" ? "secret-error" : A} /></label>
36783
+ ${error}
36784
+ <span class="buttons">
36785
+ <swc-button size="s" variant="accent" data-action="share-secret" ?pending=${this.sharing} @click=${(event2) => event2.currentTarget.closest("form")?.requestSubmit()}>Share</swc-button>
36786
+ ${exists ? b`<swc-button size="s" variant="secondary" fill-style="outline" data-action="replace-secret" ?disabled=${this.sharing} @click=${() => void this.enterSecret(this.secretName, true)}>Replace value</swc-button>` : A}
36787
+ ${cancel}
36788
+ </span>
36789
+ </form>`;
36790
+ }
36595
36791
  #hold() {
36596
36792
  const hold2 = this.model?.agent.hold?.();
36597
36793
  if (!hold2) return A;
@@ -36884,8 +37080,8 @@ var ModelFilter = class {
36884
37080
  }
36885
37081
  if (event2.key.trim().length !== 1 || event2.ctrlKey || event2.metaKey || event2.altKey) return;
36886
37082
  search3.focus();
36887
- const end = search3.focusElement.value.length;
36888
- search3.focusElement.setSelectionRange(end, end);
37083
+ const end2 = search3.focusElement.value.length;
37084
+ search3.focusElement.setSelectionRange(end2, end2);
36889
37085
  }
36890
37086
  };
36891
37087
  #key = (event2) => {
@@ -37228,14 +37424,28 @@ function pendingAsks(messages) {
37228
37424
  );
37229
37425
  });
37230
37426
  }
37231
- function into(card2, dock2) {
37232
- const box = card2.getBoundingClientRect();
37427
+ function into(card2, dock2, target) {
37233
37428
  const view = dock2.getBoundingClientRect();
37234
37429
  const start2 = view.top + (Number.parseFloat(getComputedStyle(dock2).scrollPaddingBlockStart) || 0);
37430
+ const fits2 = card2.getBoundingClientRect().height <= view.bottom - start2;
37431
+ const box = (fits2 ? card2 : target).getBoundingClientRect();
37235
37432
  if (box.top < start2) dock2.scrollTop -= start2 - box.top;
37236
37433
  else if (box.bottom > view.bottom)
37237
37434
  dock2.scrollTop += Math.min(box.bottom - view.bottom, box.top - start2);
37238
37435
  }
37436
+ function lift(turn, dock2, raised) {
37437
+ const decide2 = turn.querySelector(".decide");
37438
+ if (!decide2) return raised;
37439
+ const style2 = getComputedStyle(dock2);
37440
+ const view = dock2.getBoundingClientRect();
37441
+ const start2 = view.top + (Number.parseFloat(style2.scrollPaddingBlockStart) || 0);
37442
+ const end2 = view.bottom - (Number.parseFloat(style2.scrollPaddingBlockEnd) || 0);
37443
+ const top = (turn.querySelector(".command") ?? turn).getBoundingClientRect().top;
37444
+ const need = decide2.getBoundingClientRect().bottom - end2;
37445
+ const base = dock2.scrollTop - raised;
37446
+ dock2.scrollTop = base + (need <= top - start2 ? raised + Math.max(0, need) : 0);
37447
+ return dock2.scrollTop - base;
37448
+ }
37239
37449
  var place = (id) => b`<div class="ask-place" data-place=${id} aria-hidden="true"></div>`;
37240
37450
  function dock(entries, messages, seat) {
37241
37451
  const docked = new Map(seat ? [] : pendingAsks(messages));
@@ -37358,7 +37568,7 @@ var SliccChat = class _SliccChat extends ThemedElement {
37358
37568
  fade,
37359
37569
  markdownCss,
37360
37570
  messageCss,
37361
- clampCss,
37571
+ endCss,
37362
37572
  r(link_default),
37363
37573
  signInCss,
37364
37574
  i`
@@ -37618,8 +37828,14 @@ var SliccChat = class _SliccChat extends ThemedElement {
37618
37828
  #licks = new ViewSet(this, "chat:licks");
37619
37829
  #runs = new ViewSet(this, "chat:runs");
37620
37830
  #details = /* @__PURE__ */ new Set();
37621
- #commands = new ViewSet(this, "chat:commands");
37622
- #cuts = new Cuts(
37831
+ arming = 500;
37832
+ #arming = new Arming(() => this.arming);
37833
+ #moves = new Watched(new ResizeObserver(() => this.#settle()));
37834
+ #moved = () => this.#settle();
37835
+ #lifted = "";
37836
+ #lifting = "";
37837
+ #raised = 0;
37838
+ #ends = new Ends(
37623
37839
  () => this.renderRoot,
37624
37840
  () => this.requestUpdate()
37625
37841
  );
@@ -37634,12 +37850,8 @@ var SliccChat = class _SliccChat extends ThemedElement {
37634
37850
  }
37635
37851
  },
37636
37852
  commands: {
37637
- cut: (id) => this.#cuts.get(id),
37638
- has: (id) => this.#commands.has(id),
37639
- toggle: (id) => {
37640
- this.#commands.toggle(id);
37641
- void this.updateComplete.then(() => this.#reach(id));
37642
- }
37853
+ seen: (id) => this.#ends.has(id),
37854
+ armed: (event2) => this.#arming.counts(event2)
37643
37855
  },
37644
37856
  color: "light",
37645
37857
  model: null,
@@ -37718,27 +37930,52 @@ var SliccChat = class _SliccChat extends ThemedElement {
37718
37930
  const target = event2.target;
37719
37931
  this.#held = target.closest(".decision-turn[data-pending]")?.dataset.id ?? "";
37720
37932
  const card2 = target.closest(".ask");
37721
- if (card2) into(card2, card2.closest(".asks"));
37933
+ if (card2) into(card2, card2.closest(".asks"), target);
37722
37934
  };
37723
37935
  #more = () => {
37724
37936
  const dock2 = this.renderRoot.querySelector(".asks");
37725
37937
  if (!dock2) return;
37726
- const end = Number.parseFloat(getComputedStyle(dock2).paddingBlockEnd) || 0;
37938
+ const end2 = Number.parseFloat(getComputedStyle(dock2).paddingBlockEnd) || 0;
37727
37939
  dock2.toggleAttribute(
37728
37940
  "data-more",
37729
- dock2.scrollHeight - dock2.scrollTop - dock2.clientHeight > end + 1
37941
+ dock2.scrollHeight - dock2.scrollTop - dock2.clientHeight > end2 + 1
37730
37942
  );
37731
37943
  };
37732
- #reach(id) {
37944
+ #settle() {
37945
+ this.#lift();
37733
37946
  const dock2 = this.renderRoot.querySelector(".asks");
37734
- const turn = [...dock2?.querySelectorAll(".decision-turn") ?? []].find(
37735
- (candidate) => candidate.dataset.id === id
37947
+ const buttons = [...this.renderRoot.querySelectorAll(".asks .decide swc-button")];
37948
+ this.#arming.watch(layout(buttons, [], dock2));
37949
+ }
37950
+ #lift() {
37951
+ const dock2 = this.renderRoot.querySelector(".asks");
37952
+ const turn = [...dock2?.querySelectorAll(".ask .decision-turn") ?? []].at(-1);
37953
+ const id = turn?.dataset.id ?? "";
37954
+ if (id !== this.#lifted) {
37955
+ this.#lifting = id;
37956
+ this.#raised = 0;
37957
+ }
37958
+ this.#lifted = id;
37959
+ if (!this.#lifting || !dock2 || !turn || dock2.hasAttribute("data-open")) return;
37960
+ const raised = lift(turn, dock2, this.#raised);
37961
+ if (raised !== this.#raised) this.#arming.arm();
37962
+ this.#raised = raised;
37963
+ }
37964
+ #stay = () => {
37965
+ this.#lifting = "";
37966
+ };
37967
+ #press = () => {
37968
+ this.#stay();
37969
+ this.#arming.press();
37970
+ };
37971
+ #guard() {
37972
+ this.#ends.observe();
37973
+ this.#moves.sync(
37974
+ this.renderRoot.querySelectorAll(
37975
+ "header, slicc-notices, .asks, .asks .decision, .asks .decide swc-button"
37976
+ )
37736
37977
  );
37737
- if (!dock2 || !turn) return;
37738
- const style2 = getComputedStyle(dock2);
37739
- const room = dock2.clientHeight - (Number.parseFloat(style2.scrollPaddingBlockStart) || 0) - (Number.parseFloat(style2.scrollPaddingBlockEnd) || 0);
37740
- const target = turn.offsetHeight <= room ? turn : turn.querySelector(".decide");
37741
- target?.scrollIntoView({ block: "nearest" });
37978
+ this.#settle();
37742
37979
  }
37743
37980
  #refocus() {
37744
37981
  if (!this.#held || this.renderRoot.activeElement) return;
@@ -37847,11 +38084,11 @@ var SliccChat = class _SliccChat extends ThemedElement {
37847
38084
  #bottom() {
37848
38085
  return this.#gap() <= this.#slack();
37849
38086
  }
37850
- #pin(end = true) {
38087
+ #pin(end2 = true) {
37851
38088
  if (!this.#stuck) return;
37852
38089
  const log = this.#log();
37853
38090
  const card2 = log.querySelector("swc-conversation-thread")?.lastElementChild ?? null;
37854
- const held2 = !end && card2 !== null && card2 === this.#card;
38091
+ const held2 = !end2 && card2 !== null && card2 === this.#card;
37855
38092
  this.#card = card2;
37856
38093
  log.scrollTop = held2 ? this.#head(log, card2) : log.scrollHeight;
37857
38094
  this.#last = log.scrollTop;
@@ -37936,15 +38173,21 @@ var SliccChat = class _SliccChat extends ThemedElement {
37936
38173
  this.#probed = null;
37937
38174
  globalThis.addEventListener("pointerup", this.#release, true);
37938
38175
  globalThis.addEventListener("pointercancel", this.#release, true);
38176
+ globalThis.addEventListener("resize", this.#moved);
37939
38177
  if (this.hasUpdated) this.#observe();
37940
38178
  }
37941
38179
  disconnectedCallback() {
37942
38180
  super.disconnectedCallback();
37943
38181
  globalThis.removeEventListener("pointerup", this.#release, true);
37944
38182
  globalThis.removeEventListener("pointercancel", this.#release, true);
38183
+ globalThis.removeEventListener("resize", this.#moved);
37945
38184
  this.#resize.disconnect();
37946
38185
  this.#fit.disconnect();
37947
- this.#cuts.disconnect();
38186
+ this.#ends.disconnect();
38187
+ this.#moves.disconnect();
38188
+ this.#lifted = "";
38189
+ this.#lifting = "";
38190
+ this.#arming.forget();
37948
38191
  this.#fitted = void 0;
37949
38192
  clearInterval(this.#tick);
37950
38193
  this.#tick = void 0;
@@ -37973,7 +38216,7 @@ var SliccChat = class _SliccChat extends ThemedElement {
37973
38216
  const asks = [...this.renderRoot.querySelectorAll(".ask-list .decision-turn")];
37974
38217
  for (const turn of asks) turn.tabIndex = 0;
37975
38218
  this.#more();
37976
- this.#cuts.measure();
38219
+ this.#guard();
37977
38220
  }
37978
38221
  #timed() {
37979
38222
  const model = this.model;
@@ -38192,7 +38435,7 @@ var SliccChat = class _SliccChat extends ThemedElement {
38192
38435
  this.#all = !open;
38193
38436
  this.requestUpdate();
38194
38437
  };
38195
- return b`<section class="asks" aria-label="Waiting for you" ?data-open=${open} @scroll=${this.#more}><div class="column">
38438
+ return b`<section class="asks" aria-label="Waiting for you" ?data-open=${open} @scroll=${this.#more} @pointerdown=${this.#press} @wheel=${this.#stay} @touchstart=${this.#stay} @keydown=${this.#stay} @focusin=${this.#stay}><div class="column">
38196
38439
  ${older.length ? b`<div class="waiting"><swc-action-button size="s" quiet data-action="show-waiting" aria-expanded=${open ? "true" : "false"} @click=${toggle}><swc-icon-chevron-down slot="icon"></swc-icon-chevron-down>${asks.length} waiting</swc-action-button>${timed.length ? askTimer(Math.min(...timed)) : A}</div>` : A}
38197
38440
  <div class="ask-list" aria-live="polite">${c(
38198
38441
  asks,
@@ -39536,13 +39779,19 @@ function importProfile(options2) {
39536
39779
 
39537
39780
  // src/app/names.ts
39538
39781
  var untitled = "No messages yet";
39782
+ var earlier = "Earlier messages";
39783
+ var unnamed = "Untitled chat";
39539
39784
  function short(text4, max2 = 60) {
39540
39785
  return text4.length > max2 ? `${text4.slice(0, max2 - 1).trimEnd()}\u2026` : text4;
39541
39786
  }
39542
39787
  function agentTitle(model, agent) {
39543
39788
  if (agent.title !== void 0) return agent.title.trim();
39544
- const first2 = model.agent.messages(agent.id).find((message) => message.role === "user");
39545
- return first2?.role === "user" ? first2.text.trim().split("\n")[0].trim() : "";
39789
+ const messages = model.agent.messages(agent.id);
39790
+ const first2 = messages.find((message) => message.role === "user");
39791
+ const line = first2?.role === "user" ? first2.text.trim().split("\n")[0].trim() : "";
39792
+ if (line) return line;
39793
+ if (model.agent.hasOlder?.(agent.id)) return earlier;
39794
+ return messages.length ? unnamed : "";
39546
39795
  }
39547
39796
  function twinned(name, id, rows2) {
39548
39797
  return rows2.some((row) => row.id !== id && row.name === name);
@@ -48231,11 +48480,11 @@ var UpdateVisibility = class {
48231
48480
  constructor(ready) {
48232
48481
  this.#boot = !ready;
48233
48482
  }
48234
- change(port, layout = false) {
48483
+ change(port, layout2 = false) {
48235
48484
  const failed2 = new Set(
48236
48485
  port.list().filter((item2) => item2.state === "failed").map((item2) => item2.id)
48237
48486
  );
48238
- const open = (this.#initial || layout) && this.#boot || [...failed2].some((id) => !this.#failed.has(id));
48487
+ const open = (this.#initial || layout2) && this.#boot || [...failed2].some((id) => !this.#failed.has(id));
48239
48488
  this.#initial = false;
48240
48489
  this.#failed = failed2;
48241
48490
  if (this.#boot && port.ready() && failed2.size === 0) {
@@ -49113,6 +49362,9 @@ var SliccApp = class extends ThemedElement {
49113
49362
  flex-direction: column;
49114
49363
  height: 100%;
49115
49364
  }
49365
+ .shell slicc-live {
49366
+ flex: none;
49367
+ }
49116
49368
  .shell[data-alone] header > :not(.brand),
49117
49369
  .shell[data-alone] main,
49118
49370
  .shell[data-alone] .rail.bottom {
@@ -49433,10 +49685,10 @@ var SliccApp = class extends ThemedElement {
49433
49685
  const model = this.model;
49434
49686
  if (!model) return;
49435
49687
  this.panels.quietly(() => {
49436
- const layout = this.#started !== this.screen;
49437
- if (layout) this.#start(model);
49688
+ const layout2 = this.#started !== this.screen;
49689
+ if (layout2) this.#start(model);
49438
49690
  else if (changed2.has("model")) this.#rebind(model);
49439
- this.#updates(layout);
49691
+ this.#updates(layout2);
49440
49692
  this.#retitle();
49441
49693
  });
49442
49694
  }
@@ -49446,14 +49698,14 @@ var SliccApp = class extends ThemedElement {
49446
49698
  if (panel && panel.title !== sprinkle.title) panel.api.setTitle(sprinkle.title);
49447
49699
  }
49448
49700
  }
49449
- #updates(layout) {
49701
+ #updates(layout2) {
49450
49702
  const port = this.model?.updates;
49451
49703
  if (port !== this.#updatesPort) {
49452
49704
  this.#updatesPort = port;
49453
49705
  this.#updatesVisibility = port ? new UpdateVisibility(port.ready()) : null;
49454
49706
  }
49455
49707
  if (!port || !this.#offers("updates")) return;
49456
- const change = this.#updatesVisibility?.change(port, layout);
49708
+ const change = this.#updatesVisibility?.change(port, layout2);
49457
49709
  if (change === "open") {
49458
49710
  const restored = this.dock.api.getPanel("updates");
49459
49711
  if (restored) this.dock.reveal("updates");
@@ -49537,8 +49789,8 @@ var SliccApp = class extends ThemedElement {
49537
49789
  this.#saving = true;
49538
49790
  this.#save();
49539
49791
  }
49540
- #offered(layout, factories) {
49541
- return Object.values(layout?.panels ?? {}).every(
49792
+ #offered(layout2, factories) {
49793
+ return Object.values(layout2?.panels ?? {}).every(
49542
49794
  (panel) => (panel.contentComponent ?? "") in factories
49543
49795
  );
49544
49796
  }
@@ -49945,6 +50197,7 @@ var SliccApp = class extends ThemedElement {
49945
50197
  ) : A}
49946
50198
  ${this.#headerButton("theme", color2 === "dark" ? "Switch to light theme" : "Switch to dark theme", b`<swc-icon-contrast slot="icon"></swc-icon-contrast>`, () => this.toggleColor())}
49947
50199
  </header>
50200
+ ${this.model?.live ? b`<slicc-live .model=${this.model} ?compact=${this.screen === "phone"}></slicc-live>` : A}
49948
50201
  ${lonely ? b`<div class="alone" role="status" data-tabs="alone"><p>${alone2}</p></div>` : A}
49949
50202
  ${paused && !lonely ? b`<div class="alone" data-follow=${paused.kind}><slicc-follow page .model=${this.model}></slicc-follow></div>` : A}
49950
50203
  <main>
@@ -50234,6 +50487,7 @@ var SliccSecrets = class extends ThemedElement {
50234
50487
  problem: { state: true },
50235
50488
  invalid: { state: true },
50236
50489
  said: { state: true },
50490
+ entry: { state: true },
50237
50491
  acting: { state: true },
50238
50492
  importKind: { state: true },
50239
50493
  candidates: { state: true },
@@ -50264,6 +50518,7 @@ var SliccSecrets = class extends ThemedElement {
50264
50518
  this.candidates = null;
50265
50519
  this.picked = /* @__PURE__ */ new Set();
50266
50520
  this.again = false;
50521
+ this.entry = null;
50267
50522
  }
50268
50523
  static styles = [
50269
50524
  fieldStyles,
@@ -50572,6 +50827,7 @@ var SliccSecrets = class extends ThemedElement {
50572
50827
  super.disconnectedCallback();
50573
50828
  clearTimeout(this.#tick);
50574
50829
  clearValues(this.renderRoot);
50830
+ this.#leave();
50575
50831
  this.older = [];
50576
50832
  this.more = null;
50577
50833
  }
@@ -50585,6 +50841,7 @@ var SliccSecrets = class extends ThemedElement {
50585
50841
  this.loading = false;
50586
50842
  this.popup = null;
50587
50843
  this.failure = null;
50844
+ this.#leave();
50588
50845
  this.form = null;
50589
50846
  this.busy = false;
50590
50847
  this.unpinning = null;
@@ -50647,6 +50904,7 @@ var SliccSecrets = class extends ThemedElement {
50647
50904
  open(form) {
50648
50905
  if (form && this.busy) return;
50649
50906
  clearValues(this.renderRoot);
50907
+ this.#leave();
50650
50908
  this.form = form;
50651
50909
  this.problem = null;
50652
50910
  this.invalid = null;
@@ -50655,6 +50913,88 @@ var SliccSecrets = class extends ThemedElement {
50655
50913
  this.again = false;
50656
50914
  if (form?.kind === "import") this.importKind = "bundle";
50657
50915
  if (form) void this.updateComplete.then(() => this.#focus());
50916
+ const vault = this.model?.vault;
50917
+ if (form?.kind === "replace" && enters(vault))
50918
+ void this.#begin(vault, form, form.name, true);
50919
+ }
50920
+ #leave() {
50921
+ const entry = this.entry;
50922
+ if (!entry) return;
50923
+ this.entry = null;
50924
+ drop(entry.vault, entry.request);
50925
+ }
50926
+ async #begin(vault, form, name, replace2) {
50927
+ const options2 = form.kind === "replace" ? form.options : void 0;
50928
+ this.busy = true;
50929
+ try {
50930
+ const { request: request2 } = await vault.enter({
50931
+ name,
50932
+ ...options2?.kind ? { kind: options2.kind } : {},
50933
+ ...options2?.provider ? { provider: options2.provider } : {},
50934
+ ...options2?.server ? { server: options2.server } : {},
50935
+ ...replace2 ? { replace: true } : {}
50936
+ });
50937
+ if (!this.#mine(vault, form)) {
50938
+ drop(vault, request2);
50939
+ return;
50940
+ }
50941
+ this.#refuse(null);
50942
+ this.entry = { request: request2, form, vault, name };
50943
+ void this.updateComplete.then(
50944
+ () => this.renderRoot.querySelector("[data-form] slicc-vault-value")?.focus()
50945
+ );
50946
+ } catch (error) {
50947
+ if (this.#mine(vault, form)) this.#refuse(failureText(error), fieldOf(error, "name"), true);
50948
+ } finally {
50949
+ if (this.model?.vault === vault) this.busy = false;
50950
+ }
50951
+ }
50952
+ async next(vault) {
50953
+ const form = this.form;
50954
+ if (this.busy) return;
50955
+ const name = this.#field("name").value.trim();
50956
+ const bad = nameProblem(name);
50957
+ if (bad) {
50958
+ this.#refuse(bad, "name", true);
50959
+ return;
50960
+ }
50961
+ const exists = !!vault.list()?.secrets.some(
50962
+ (secret) => secret.name === name && secret.kind === "secret" && secret.state !== "removed"
50963
+ );
50964
+ if (exists) {
50965
+ this.busy = true;
50966
+ const sure = await confirm({
50967
+ title: `Replace ${name}?`,
50968
+ body: "A secret with this name exists. Saving replaces its value, and its placeholder stays.",
50969
+ action: "Replace",
50970
+ variant: "confirmation"
50971
+ });
50972
+ if (this.model?.vault === vault) this.busy = false;
50973
+ if (!sure || !this.#mine(vault, form)) return;
50974
+ }
50975
+ await this.#begin(vault, form, name, exists);
50976
+ }
50977
+ #entered(detail, request2) {
50978
+ const entry = this.entry;
50979
+ if (!entry || !ours(detail, request2, entry.request)) return;
50980
+ if (detail.event === "error") {
50981
+ this.#refuse(detail.message);
50982
+ return;
50983
+ }
50984
+ if (detail.event === "escape") {
50985
+ this.open(null);
50986
+ return;
50987
+ }
50988
+ this.entry = null;
50989
+ if (detail.event === "gone") {
50990
+ this.#refuse(goneText(detail.state));
50991
+ return;
50992
+ }
50993
+ this.form = null;
50994
+ this.said = {
50995
+ kind: "saved",
50996
+ name: (detail.state === "sealed" ? detail.name : void 0) ?? entry.name
50997
+ };
50658
50998
  }
50659
50999
  #refuse(text4, field3 = null, focus = false) {
50660
51000
  this.problem = text4;
@@ -50918,7 +51258,33 @@ var SliccSecrets = class extends ThemedElement {
50918
51258
  #locked(locked) {
50919
51259
  return locked ? b`<div class="locked"><p class="muted" data-locked>Unlock the vault first</p>${this.#button({ intent: { kind: "unlock" }, label: "Unlock", size: "s", variant: "accent" }, "unlock")}</div>` : A;
50920
51260
  }
51261
+ #entryForm(vault, form) {
51262
+ const add = form.kind === "add";
51263
+ const entry = this.entry?.form === form ? this.entry : null;
51264
+ const next = () => this.next(vault);
51265
+ const keys = (event2) => {
51266
+ if (event2.key === "Escape") {
51267
+ event2.preventDefault();
51268
+ this.open(null);
51269
+ } else if (event2.key === "Enter" && event2.target.localName === "input") {
51270
+ event2.preventDefault();
51271
+ void next();
51272
+ }
51273
+ };
51274
+ const name = form.kind === "replace" ? form.name : "";
51275
+ return b`<div class="form" data-form=${form.kind} data-entry=${entry ? "" : A} @input=${() => this.#typed()} @keydown=${keys}>
51276
+ <strong>${add ? "Add a secret" : b`Replace the value of <code>${name}</code>`}</strong>
51277
+ ${add && !entry ? b`<label class="field"><span>Name</span><input type="text" autocomplete="off" spellcheck="false" autocapitalize="characters" data-field="name" placeholder="API_TOKEN" aria-invalid=${this.#bad("name")} aria-describedby=${this.#described("name")} @input=${(event2) => this.#upper(event2)} /></label>` : A}
51278
+ ${entry ? b`<p class="muted">Type the value in the vault’s own field. It never passes through this page.</p>${valueField(vault, entry.request, valueConfig(this.ownerDocument, this.color), (detail, request2) => this.#entered(detail, request2))}` : add ? b`<p class="muted">You type the value in the vault’s own field next.</p>` : b`<p class="muted" data-opening>${this.busy ? "Opening the vault\u2019s field\u2026" : ""}</p>`}
51279
+ ${this.problem ? this.#error(this.problem, "form") : A}
51280
+ <div class="buttons">
51281
+ ${add && !entry ? b`<swc-button size="m" variant="accent" data-action="enter-value" ?pending=${this.busy} @click=${next}>Next</swc-button>` : A}
51282
+ <swc-button size="m" variant="secondary" fill-style="outline" data-action="cancel" @click=${() => this.open(null)}>Cancel</swc-button>
51283
+ </div>
51284
+ </div>`;
51285
+ }
50921
51286
  #valueForm(vault, form, locked) {
51287
+ if (enters(vault)) return this.#entryForm(vault, form);
50922
51288
  const save = () => this.save(vault);
50923
51289
  const add = form.kind === "add";
50924
51290
  return b`<div class="form" data-form=${form.kind} @input=${() => this.#typed()} @keydown=${(event2) => this.#enter(event2, save, locked)}>
@@ -51251,6 +51617,45 @@ function trayAsking(approval) {
51251
51617
  return `${name} wants a new join URL. Linked devices move to it, and the old one stops working.`;
51252
51618
  return `${name} wants to unlink ${approval.device?.name ?? "a device"} from this seven.`;
51253
51619
  }
51620
+ var captureActs = {
51621
+ "screen:still": ["take a picture of your screen", "take pictures of your screen"],
51622
+ "screen:video": ["record your screen", "record your screen"],
51623
+ "camera:still": ["take a photo with your camera", "take photos with your camera"],
51624
+ "camera:video": ["record your camera", "record your camera"],
51625
+ "microphone:audio": ["record your microphone", "record your microphone"]
51626
+ };
51627
+ function captureAct(detail) {
51628
+ const fallback = `capture your ${detail.what}`;
51629
+ return captureActs[`${detail.what}:${detail.mode}`] ?? [fallback, fallback];
51630
+ }
51631
+ function captureLine(approval) {
51632
+ const { detail } = approval;
51633
+ const [act2] = captureAct(detail);
51634
+ const device = detail.device ? ` (${detail.device})` : "";
51635
+ const still2 = detail.mode === "still";
51636
+ const span = detail.seconds ? ` for up to ${detail.seconds} ${detail.seconds === 1 ? "second" : "seconds"}` : " until it\u2019s stopped";
51637
+ const audio = [
51638
+ detail.system ? "system audio" : "",
51639
+ detail.microphone && detail.what !== "microphone" ? "microphone" : ""
51640
+ ].filter(Boolean);
51641
+ const extra = still2 || !audio.length ? "" : `, with your ${audio.join(" and ")}`;
51642
+ const line = `${act2}${device}${still2 ? "" : span}${extra}`;
51643
+ return `${line[0].toUpperCase()}${line.slice(1)} \xB7 ${detail.program}`;
51644
+ }
51645
+ function captureAsking(approval) {
51646
+ return `${approval.agentName ?? "This cone"} wants to use your ${approval.detail.what} for ${approval.requester.name}:`;
51647
+ }
51648
+ function captureWaiting(approval) {
51649
+ return `${approval.agentName ?? "This cone"} wants to use your ${approval.detail.what} for ${approval.requester.name}, which waits for the owner's approval.`;
51650
+ }
51651
+ function captureAlwaysHint(approval) {
51652
+ const [, acts] = captureAct(approval.detail);
51653
+ const picker = approval.detail.what === "screen" ? " You still choose what to share each time." : "";
51654
+ return `Always allow lets ${approval.agentName ?? "this cone"} ${acts} for ${approval.requester.name} without asking again.${picker}`;
51655
+ }
51656
+ function clickWhere(approval) {
51657
+ return approval.device ? `Click in seven\u2019s tab on ${approval.device.name}.` : "Click in seven\u2019s tab.";
51658
+ }
51254
51659
  function secretTitle(approval) {
51255
51660
  return approval.mode === "reveal" ? `Reveal ${approval.name} to a program?` : `Enter a value for ${approval.name}?`;
51256
51661
  }
@@ -51276,7 +51681,8 @@ function secretWaiting(approval) {
51276
51681
  function approved(approval) {
51277
51682
  if (approval.kind === "sudo") return sudo(approval);
51278
51683
  if (approval.kind === "secret") return processLine(approval);
51279
- if (approval.kind === "guest-message" || approval.kind === "tray") return "";
51684
+ if (approval.kind === "guest-message" || approval.kind === "tray" || approval.kind === "click" || approval.kind === "capture")
51685
+ return "";
51280
51686
  if (approval.summary.trim()) return approval.summary;
51281
51687
  return approval.args?.trim() ? `${approval.tool}
51282
51688
  ${approval.args}` : "";
@@ -51285,6 +51691,7 @@ function truncated(approval) {
51285
51691
  return approval.kind === "guest-tool" && !approval.summary.trim() && !!approval.argsTruncated;
51286
51692
  }
51287
51693
  function hintOf(approval) {
51694
+ if (approval.kind === "capture") return captureAlwaysHint(approval);
51288
51695
  return approval.kind === "sudo" ? commandText(alwaysHint(approval), false) : guestAlwaysHint(approval);
51289
51696
  }
51290
51697
  var tooLong = "This request is too long to show in full, so it can\u2019t be allowed.";
@@ -51296,13 +51703,18 @@ var levels2 = {
51296
51703
  2: { name: "permissions", label: "Changes permissions." },
51297
51704
  3: { name: "harm", label: "Could harm the system." }
51298
51705
  };
51706
+ var captureLevels = {
51707
+ 1: { name: "routine", label: "Routine capture." },
51708
+ 2: { name: "permissions", label: "Records what you share." },
51709
+ 3: { name: "harm", label: "Could expose something private." }
51710
+ };
51299
51711
  var fits = (aligned) => aligned === void 0 ? "" : aligned ? " It fits what you asked for." : " It isn\u2019t clear it serves what you asked for.";
51300
51712
  function leveled(approval) {
51301
51713
  const level = approval.verdict?.level;
51302
51714
  return level === 1 || level === 2 || level === 3 ? level : null;
51303
51715
  }
51304
51716
  function offersAlways(approval) {
51305
- return approval.kind !== "tray" && approval.kind !== "secret" && approval.always && (approval.kind !== "sudo" || leveled(approval) !== null);
51717
+ return approval.kind !== "tray" && approval.kind !== "secret" && approval.kind !== "click" && approval.always && (approval.kind !== "sudo" || leveled(approval) !== null);
51306
51718
  }
51307
51719
  function verdictNote(approval) {
51308
51720
  if (approval.kind !== "sudo" || offersAlways(approval)) return "";
@@ -51320,7 +51732,7 @@ function judged(approval) {
51320
51732
  const { verdict, judging, verdictError } = approval;
51321
51733
  const level = leveled(approval);
51322
51734
  if (verdict && level) {
51323
- const { name, label } = levels2[level];
51735
+ const { name, label } = (approval.kind === "capture" ? captureLevels : levels2)[level];
51324
51736
  return b`<div class="judged" data-verdict=${name} data-level=${level}>${level === 3 ? b`<swc-icon-alert-triangle size="s" aria-hidden="true"></swc-icon-alert-triangle>` : A}<p><strong>${label}</strong>${verdict.reason ? b` ${shown5(verdict.reason)}` : ""}${fits(verdict.aligned)}</p></div>`;
51325
51737
  }
51326
51738
  if (judging) return b`<div class="judged" data-verdict="checking"><p>Checking…</p></div>`;
@@ -51358,6 +51770,16 @@ var titles = {
51358
51770
  ask: "",
51359
51771
  elsewhere: "Answered elsewhere",
51360
51772
  expired: "Secret request timed out"
51773
+ },
51774
+ click: {
51775
+ ask: "",
51776
+ elsewhere: "Answered elsewhere",
51777
+ expired: "Click request timed out"
51778
+ },
51779
+ capture: {
51780
+ ask: "Allow a guest\u2019s capture?",
51781
+ elsewhere: "Answered elsewhere",
51782
+ expired: "Capture request timed out"
51361
51783
  }
51362
51784
  };
51363
51785
  var approvalKinds = Object.freeze(
@@ -51366,11 +51788,31 @@ var approvalKinds = Object.freeze(
51366
51788
  function title(approval) {
51367
51789
  if (approval.kind === "tray") return trayTitle(approval);
51368
51790
  if (approval.kind === "secret") return secretTitle(approval);
51791
+ if (approval.kind === "click") return approval.title;
51369
51792
  return titles[approval.kind].ask;
51370
51793
  }
51371
51794
  var toAnswer = "Scroll to the end of the command to answer it.";
51795
+ function extras(approval) {
51796
+ if (approval.kind === "secret")
51797
+ return [
51798
+ approval.mode,
51799
+ approval.name,
51800
+ approval.reveal,
51801
+ approval.prompt ?? "",
51802
+ approval.requester
51803
+ ];
51804
+ if (approval.kind === "click")
51805
+ return [approval.title, approval.body, approval.action, approval.here, approval.device ?? null];
51806
+ if (approval.kind === "capture") return [approval.detail, approval.requester];
51807
+ return [];
51808
+ }
51809
+ function answerable(approval, decision2) {
51810
+ if (decision2 === "deny") return true;
51811
+ if (approval.kind === "secret") return false;
51812
+ return approval.kind !== "click" || approval.here;
51813
+ }
51372
51814
  function identity(approval) {
51373
- const extra = approval.kind === "secret" ? [approval.mode, approval.name, approval.reveal, approval.prompt ?? "", approval.requester] : [];
51815
+ const extra = extras(approval);
51374
51816
  return JSON.stringify([approval.kind, approval.createdAt, approved(approval), ...extra]);
51375
51817
  }
51376
51818
  function gone(reason) {
@@ -51386,10 +51828,9 @@ var SliccApprovals = class extends ModelElement {
51386
51828
  frameError: { state: true }
51387
51829
  };
51388
51830
  arming = 500;
51389
- #changed = 0;
51390
- #pressed = 0;
51391
- #layout = "";
51392
- #moves = new ResizeObserver(() => this.#settle());
51831
+ #arming = new Arming(() => this.arming);
51832
+ #moves = new Watched(new ResizeObserver(() => this.#settle()));
51833
+ #moved = () => this.#settle();
51393
51834
  #showing = null;
51394
51835
  #pending = /* @__PURE__ */ new Set();
51395
51836
  #done = /* @__PURE__ */ new Set();
@@ -51416,6 +51857,7 @@ var SliccApprovals = class extends ModelElement {
51416
51857
  static styles = [
51417
51858
  dialogStyles,
51418
51859
  controlStyles,
51860
+ endCss,
51419
51861
  i`
51420
51862
  :host {
51421
51863
  display: contents;
@@ -51437,17 +51879,12 @@ var SliccApprovals = class extends ModelElement {
51437
51879
  white-space: pre-wrap;
51438
51880
  overflow-wrap: anywhere;
51439
51881
  }
51440
- .command .lines:not([data-clamp]) {
51882
+ .command .lines {
51441
51883
  display: block;
51442
51884
  max-block-size: min(16lh, 50dvh);
51443
51885
  overflow: auto;
51444
51886
  overscroll-behavior: contain;
51445
51887
  }
51446
- .command .end {
51447
- display: inline-block;
51448
- inline-size: 0;
51449
- block-size: 0;
51450
- }
51451
51888
  .guest {
51452
51889
  margin-block-start: var(--swc-spacing-200);
51453
51890
  padding: var(--swc-spacing-200) var(--swc-spacing-300);
@@ -51476,6 +51913,11 @@ var SliccApprovals = class extends ModelElement {
51476
51913
  .cwd {
51477
51914
  overflow-wrap: anywhere;
51478
51915
  }
51916
+ .where {
51917
+ margin-block-start: var(--swc-spacing-200);
51918
+ font-weight: var(--swc-bold-font-weight);
51919
+ overflow-wrap: anywhere;
51920
+ }
51479
51921
  .timer {
51480
51922
  margin-block-start: var(--swc-spacing-300);
51481
51923
  font-variant-numeric: tabular-nums;
@@ -51625,11 +52067,16 @@ var SliccApprovals = class extends ModelElement {
51625
52067
  })
51626
52068
  ];
51627
52069
  }
52070
+ connectedCallback() {
52071
+ super.connectedCallback();
52072
+ globalThis.addEventListener("resize", this.#moved);
52073
+ }
51628
52074
  disconnectedCallback() {
51629
52075
  super.disconnectedCallback();
52076
+ globalThis.removeEventListener("resize", this.#moved);
51630
52077
  this.#tick(false);
51631
52078
  this.#showing = null;
51632
- this.#layout = "";
52079
+ this.#arming.forget();
51633
52080
  this.#moves.disconnect();
51634
52081
  this.#ends.disconnect();
51635
52082
  }
@@ -51643,7 +52090,7 @@ var SliccApprovals = class extends ModelElement {
51643
52090
  async decide(approval, decision2) {
51644
52091
  const port = this.model?.approvals;
51645
52092
  const { id } = approval;
51646
- if (!port?.decide || this.busy || this.gone || this.#showing?.id !== id || this.#done.has(id) || this.#closed.has(id) || approval.kind === "secret" && decision2 !== "deny" || decision2 !== "deny" && (!this.#settled(performance.now()) || !this.#whole(approval)))
52093
+ if (!port?.decide || this.busy || this.gone || this.#showing?.id !== id || this.#done.has(id) || this.#closed.has(id) || !answerable(approval, decision2) || decision2 !== "deny" && (!this.#arming.settled() || !this.#whole(approval)))
51647
52094
  return;
51648
52095
  const live = port.list().find(({ id: id2 }) => id2 === approval.id);
51649
52096
  if (decision2 === "always" && !(live && offersAlways(live))) return;
@@ -51699,34 +52146,15 @@ var SliccApprovals = class extends ModelElement {
51699
52146
  if (next?.id === showing?.id) return;
51700
52147
  this.frameError = null;
51701
52148
  this.#showing = next;
51702
- this.#changed = performance.now();
51703
- }
51704
- #settled(at) {
51705
- return at - this.#changed >= this.arming;
52149
+ this.#arming.arm();
51706
52150
  }
51707
52151
  #settle() {
51708
52152
  const dialog = this.renderRoot.querySelector("dialog");
51709
52153
  const buttons = [...this.renderRoot.querySelectorAll("[slot=button]")];
51710
- const layout = JSON.stringify([
51711
- dialog?.dataset.approval,
51712
- dialog?.dataset.gone,
51713
- buttons.map((button) => {
51714
- const { left, top, width, height } = button.getBoundingClientRect();
51715
- return [
51716
- button.dataset.action,
51717
- button.textContent,
51718
- button.hasAttribute("disabled"),
51719
- button.hasAttribute("pending"),
51720
- ...[left, top, width, height].map(Math.round)
51721
- ];
51722
- })
51723
- ]);
51724
- if (layout === this.#layout) return;
51725
- this.#layout = layout;
51726
- this.#changed = performance.now();
52154
+ this.#arming.watch(layout(buttons, [dialog?.dataset.approval, dialog?.dataset.gone]));
51727
52155
  }
51728
52156
  #click(event2, approval, decision2) {
51729
- if (!this.#settled(event2.detail ? this.#pressed : performance.now())) return;
52157
+ if (!this.#arming.counts(event2)) return;
51730
52158
  void this.decide(approval, decision2);
51731
52159
  }
51732
52160
  updated(changed2) {
@@ -51735,9 +52163,7 @@ var SliccApprovals = class extends ModelElement {
51735
52163
  this.#tick(this.isConnected && all2.length > 0);
51736
52164
  this.#ends.observe();
51737
52165
  const dialog = this.renderRoot.querySelector("dialog");
51738
- if (dialog)
51739
- for (const box of dialog.querySelectorAll("sp-alert-dialog, [slot=button]"))
51740
- this.#moves.observe(box);
52166
+ this.#moves.sync(dialog?.querySelectorAll("sp-alert-dialog, [slot=button]") ?? []);
51741
52167
  this.#settle();
51742
52168
  const key = dialog ? `${dialog.dataset.approval}:${this.#generation.get(dialog.dataset.approval)}:${dialog.dataset.gone ?? ""}:${dialog.hasAttribute("data-rejected")}` : "";
51743
52169
  if (key === this.#shown) return;
@@ -51776,12 +52202,7 @@ var SliccApprovals = class extends ModelElement {
51776
52202
  #config() {
51777
52203
  const doc = this.ownerDocument;
51778
52204
  const dark = doc.defaultView?.matchMedia?.("(prefers-color-scheme: dark)").matches ?? false;
51779
- const lang = doc.documentElement.lang;
51780
- return {
51781
- theme: resolveColor(this.model?.settings?.get().color ?? "system", dark),
51782
- dir: doc.documentElement.dir === "rtl" ? "rtl" : "ltr",
51783
- ...lang ? { lang } : {}
51784
- };
52205
+ return valueConfig(doc, resolveColor(this.model?.settings?.get().color ?? "system", dark));
51785
52206
  }
51786
52207
  #frame(approval) {
51787
52208
  const vault = this.model?.vault;
@@ -51820,7 +52241,7 @@ var SliccApprovals = class extends ModelElement {
51820
52241
  #dialog(approval, key, content3) {
51821
52242
  return i23(
51822
52243
  key,
51823
- b`<dialog role="alertdialog" aria-labelledby="title" aria-describedby="asking" data-approval=${approval.id} data-kind=${approval.kind} data-requester=${approval.requester.kind} data-gone=${this.gone?.reason ?? A} data-rejected=${!this.gone && this.failure?.id === approval.id ? "" : A} @pointerdown=${() => this.#pressed = performance.now()} @cancel=${(event2) => this.#cancel(event2, approval)}>${content3}</dialog>`
52244
+ b`<dialog role="alertdialog" aria-labelledby="title" aria-describedby="asking" data-approval=${approval.id} data-kind=${approval.kind} data-requester=${approval.requester.kind} data-gone=${this.gone?.reason ?? A} data-rejected=${!this.gone && this.failure?.id === approval.id ? "" : A} @pointerdown=${this.#arming.press} @cancel=${(event2) => this.#cancel(event2, approval)}>${content3}</dialog>`
51824
52245
  );
51825
52246
  }
51826
52247
  #whole(approval) {
@@ -51836,10 +52257,16 @@ var SliccApprovals = class extends ModelElement {
51836
52257
  const text4 = approved(approval);
51837
52258
  if (!text4) return b`<p class="hint" data-id="no-details">This request has no details.</p>`;
51838
52259
  const command2 = approval.kind === "sudo" || approval.kind === "secret";
51839
- return b`<pre class="command" data-command=${command2 ? "" : A} data-summary=${command2 ? A : ""}><span class="lines">${command2 ? commandText(text4) : text4}${pending ? b`<span class="end" data-end=${id}></span>` : A}</span></pre>`;
52260
+ return b`<pre class="command" data-command=${command2 ? "" : A} data-summary=${command2 ? A : ""}><span class="lines">${command2 ? commandText(text4) : text4}${pending ? end(id) : A}</span></pre>`;
51840
52261
  }
51841
52262
  #request(approval, pending = false) {
51842
52263
  if (approval.kind === "tray") return b`<p id="asking">${trayAsking(approval)}</p>`;
52264
+ if (approval.kind === "click")
52265
+ return b`<p id="asking">${commandText(approval.body, false)}</p>
52266
+ ${approval.here ? A : b`<p class="where" data-where>${commandText(clickWhere(approval), false)}</p>`}`;
52267
+ if (approval.kind === "capture")
52268
+ return b`<p id="asking">${commandText(captureAsking(approval), false)}</p>
52269
+ <div class="guest" data-capture>${commandText(captureLine(approval), false)}</div>`;
51843
52270
  if (approval.kind === "sudo")
51844
52271
  return b`<p id="asking">${commandText(asking2(approval), false)}:</p>
51845
52272
  ${this.#command(approval, pending)}`;
@@ -51858,16 +52285,18 @@ var SliccApprovals = class extends ModelElement {
51858
52285
  ${files.length ? b`<ul class="files" data-attachments>${files.map((file) => b`<li>${file.name} · ${file.mimeType} · ${size3(file.size)}</li>`)}</ul>` : A}`;
51859
52286
  }
51860
52287
  #notes(approval, gate, always) {
51861
- if (approval.kind === "tray" || approval.kind === "secret") return A;
52288
+ if (approval.kind === "tray" || approval.kind === "secret" || approval.kind === "click")
52289
+ return A;
51862
52290
  const note = verdictNote(approval);
51863
52291
  return b`<div class="notes" data-notes><div class="judge" aria-live="polite">${judged(approval)}${note ? b`<p class="hint" data-verdict-note>${note}</p>` : A}</div>${gate ? b`<p class="hint" data-allow-hint>${gate}</p>` : A}${always ? b`<p class="hint" data-always-hint>${hintOf(approval)}</p>` : A}</div>`;
51864
52292
  }
51865
52293
  #actions(approval, rejected, always) {
51866
52294
  if (rejected)
51867
52295
  return b`<swc-button slot="button" variant="secondary" fill-style="outline" data-action="close" @click=${() => this.#dismiss(approval)}>Close</swc-button>`;
51868
- return b`${this.#button(approval, "deny", "Deny", "secondary")}
52296
+ const click = approval.kind === "click";
52297
+ return b`${this.#button(approval, "deny", click ? "Cancel" : "Deny", "secondary")}
51869
52298
  ${always ? this.#button(approval, "always", inCwd(approval) ? "Always allow in this directory" : "Always allow", "secondary") : A}
51870
- ${approval.kind === "secret" ? A : this.#button(approval, "once", "Allow once", "accent")}`;
52299
+ ${answerable(approval, "once") ? this.#button(approval, "once", click ? approval.action : "Allow once", "accent") : A}`;
51871
52300
  }
51872
52301
  render() {
51873
52302
  if (this.gone) {
@@ -51878,7 +52307,7 @@ var SliccApprovals = class extends ModelElement {
51878
52307
  b`<sp-alert-dialog variant="information" data-approval-kind=${approval2.kind}>
51879
52308
  <h2 id="title" slot="heading">${titles[approval2.kind][reason]}</h2>
51880
52309
  ${this.#request(approval2)}
51881
- ${reason === "expired" ? b`<p class="timer" data-timer>Denied because nobody answered in time.</p>` : A}
52310
+ ${reason === "expired" ? b`<p class="timer" data-timer>${approval2.kind === "click" ? "Cancelled because nobody clicked in time." : "Denied because nobody answered in time."}</p>` : A}
51882
52311
  <swc-button slot="button" variant="secondary" fill-style="outline" data-action="close" @click=${() => this.close()}>Close</swc-button>
51883
52312
  </sp-alert-dialog>`
51884
52313
  );
@@ -51893,13 +52322,13 @@ var SliccApprovals = class extends ModelElement {
51893
52322
  return this.#dialog(
51894
52323
  approval,
51895
52324
  `${approval.id}:${this.#generation.get(approval.id)}`,
51896
- b`<sp-alert-dialog variant="warning" data-approval-kind=${approval.kind}>
52325
+ b`<sp-alert-dialog variant=${approval.kind === "click" ? "information" : "warning"} data-approval-kind=${approval.kind}>
51897
52326
  <h2 id="title" slot="heading">${commandText(title(approval), false)}</h2>
51898
52327
  ${this.#request(approval, true)}
51899
52328
  ${approval.kind === "sudo" && approval.cwd ? b`<p class="cwd">In ${commandText(approval.cwd, false)}</p>` : A}
51900
52329
  ${this.#notes(approval, gate, always)}
51901
52330
  ${approval.kind === "secret" && !failure3 ? this.#frame(approval) : A}
51902
- ${failure3 ? b`<p class="problem" role="alert" data-error><swc-icon-alert-triangle size="s" aria-hidden="true"></swc-icon-alert-triangle><span>${failure3}</span></p>` : b`<p class="timer" data-timer>Denied automatically in ${countdown(approval.expiresAt - this.now)}.</p>`}
52331
+ ${failure3 ? b`<p class="problem" role="alert" data-error><swc-icon-alert-triangle size="s" aria-hidden="true"></swc-icon-alert-triangle><span>${failure3}</span></p>` : b`<p class="timer" data-timer>${approval.kind === "click" ? "Cancelled" : "Denied"} automatically in ${countdown(approval.expiresAt - this.now)}.</p>`}
51903
52332
  <p class="more" data-more=${rest.length ? "" : A}>${rest.length === 1 ? "1 more request is waiting." : rest.length ? `${rest.length} more requests are waiting.` : ""}</p>
51904
52333
  ${this.#actions(approval, !!failure3, always)}
51905
52334
  </sp-alert-dialog>`
@@ -53634,6 +54063,116 @@ var SliccDiffPanel = class extends ThemedElement {
53634
54063
  }
53635
54064
  };
53636
54065
 
54066
+ // src/app/live.ts
54067
+ function elapsed(ms) {
54068
+ const seconds = Math.max(0, Math.floor(ms / 1e3));
54069
+ return `${Math.floor(seconds / 60)}:${String(seconds % 60).padStart(2, "0")}`;
54070
+ }
54071
+ function liveLine(item2, now) {
54072
+ return [item2.label, item2.what, item2.asker, elapsed(now - item2.since)].filter(Boolean).join(" \xB7 ");
54073
+ }
54074
+ var SliccLive = class extends ModelElement {
54075
+ static properties = {
54076
+ ...ModelElement.properties,
54077
+ compact: { type: Boolean, reflect: true },
54078
+ now: { state: true }
54079
+ };
54080
+ #timer = null;
54081
+ constructor() {
54082
+ super();
54083
+ this.compact = false;
54084
+ this.now = Date.now();
54085
+ }
54086
+ static styles = i`
54087
+ :host {
54088
+ display: block;
54089
+ }
54090
+ .live {
54091
+ display: flex;
54092
+ flex-direction: column;
54093
+ gap: var(--swc-spacing-50);
54094
+ padding: var(--swc-spacing-75) var(--swc-spacing-200);
54095
+ border-bottom: var(--swc-border-width-100) solid var(--swc-gray-200);
54096
+ background: var(--swc-background-layer-1-color);
54097
+ font-size: var(--swc-font-size-75);
54098
+ color: var(--swc-neutral-content-color-default);
54099
+ }
54100
+ .chip {
54101
+ display: flex;
54102
+ align-items: center;
54103
+ gap: var(--swc-spacing-100);
54104
+ min-width: 0;
54105
+ }
54106
+ .dot {
54107
+ flex: none;
54108
+ inline-size: var(--swc-spacing-100);
54109
+ block-size: var(--swc-spacing-100);
54110
+ border-radius: 50%;
54111
+ background: var(--swc-negative-visual-color);
54112
+ }
54113
+ .text {
54114
+ flex: 0 1 auto;
54115
+ min-width: 0;
54116
+ overflow: hidden;
54117
+ white-space: nowrap;
54118
+ text-overflow: ellipsis;
54119
+ font-variant-numeric: tabular-nums;
54120
+ }
54121
+ .label {
54122
+ font-weight: var(--swc-bold-font-weight);
54123
+ }
54124
+ :host([compact]) .detail {
54125
+ display: none;
54126
+ }
54127
+ swc-action-button {
54128
+ flex: none;
54129
+ }
54130
+ `;
54131
+ subscribe(model) {
54132
+ return model.live ? [
54133
+ model.live.on("items", () => {
54134
+ this.now = Date.now();
54135
+ this.requestUpdate();
54136
+ })
54137
+ ] : [];
54138
+ }
54139
+ disconnectedCallback() {
54140
+ super.disconnectedCallback();
54141
+ this.#tick(false);
54142
+ }
54143
+ #items() {
54144
+ return this.model?.live?.items() ?? [];
54145
+ }
54146
+ #tick(on2) {
54147
+ if (on2 && !this.#timer) this.#timer = setInterval(() => this.now = Date.now(), 1e3);
54148
+ if (!on2 && this.#timer) {
54149
+ clearInterval(this.#timer);
54150
+ this.#timer = null;
54151
+ }
54152
+ }
54153
+ updated(changed2) {
54154
+ super.updated(changed2);
54155
+ this.#tick(this.isConnected && this.#items().length > 0);
54156
+ }
54157
+ #chip(item2) {
54158
+ const rest = liveLine({ ...item2, label: "" }, this.now);
54159
+ return b`<div class="chip" role="listitem" data-id=${item2.id} data-kind=${item2.kind}>
54160
+ <span class="dot" aria-hidden="true"></span>
54161
+ <span class="text" title=${liveLine(item2, this.now)}><span class="label">${item2.label}</span><span class="detail"> · ${rest}</span></span>
54162
+ <swc-action-button size="s" quiet data-action="live-act" accessible-label=${`${item2.action.label}: ${item2.label}`} @click=${() => this.model?.live?.act(item2.id)}>${item2.action.label}</swc-action-button>
54163
+ </div>`;
54164
+ }
54165
+ render() {
54166
+ const items = this.#items();
54167
+ if (!items.length) return A;
54168
+ return b`<div class="live" role="list" aria-label="Live now" data-surface="live">${c(
54169
+ items,
54170
+ (item2) => item2.id,
54171
+ (item2) => this.#chip(item2)
54172
+ )}</div>`;
54173
+ }
54174
+ };
54175
+
53637
54176
  // src/app/lucide.ts
53638
54177
  var library = null;
53639
54178
  function load2() {
@@ -54458,6 +54997,25 @@ var SliccNotices = class extends ModelElement {
54458
54997
  <p>It waits for the owner's answer. Denied automatically at ${deadline(approval.expiresAt)}.</p>
54459
54998
  </div>
54460
54999
  </div>`;
55000
+ if (approval.kind === "click")
55001
+ return b`<div class="notice" role="status" data-approval-notice=${approval.id} data-approval-kind="click" data-tone="warning">
55002
+ <swc-icon-alert-triangle></swc-icon-alert-triangle>
55003
+ <div class="text">
55004
+ <span class="title">${commandText(approval.title, false)}</span>
55005
+ <p>${commandText(approval.body, false)}</p>
55006
+ <p>${commandText(clickWhere(approval), false)} Cancelled automatically at ${deadline(approval.expiresAt)}.</p>
55007
+ </div>
55008
+ </div>`;
55009
+ if (approval.kind === "capture")
55010
+ return b`<div class="notice" role="status" data-approval-notice=${approval.id} data-approval-kind="capture" data-tone="warning">
55011
+ <swc-icon-alert-triangle></swc-icon-alert-triangle>
55012
+ <div class="text">
55013
+ <span class="title">Waiting for approval of a guest’s capture</span>
55014
+ <p>${commandText(captureWaiting(approval), false)}</p>
55015
+ <p>${commandText(captureLine(approval), false)}</p>
55016
+ <p>Denied automatically at ${deadline(approval.expiresAt)}.</p>
55017
+ </div>
55018
+ </div>`;
54461
55019
  if (approval.kind !== "sudo")
54462
55020
  return b`<div class="notice" role="status" data-approval-notice=${approval.id} data-approval-kind=${approval.kind} data-tone="warning">
54463
55021
  <swc-icon-alert-triangle></swc-icon-alert-triangle>
@@ -54661,6 +55219,7 @@ var SliccSettings = class extends ThemedElement {
54661
55219
  ...ThemedElement.properties,
54662
55220
  pending: { state: true },
54663
55221
  entering: { state: true },
55222
+ keyEntry: { state: true },
54664
55223
  failure: { state: true },
54665
55224
  problem: { state: true },
54666
55225
  blocked: { state: true },
@@ -54677,6 +55236,8 @@ var SliccSettings = class extends ThemedElement {
54677
55236
  refusals: { state: true },
54678
55237
  removing: { state: true }
54679
55238
  };
55239
+ #auto = null;
55240
+ #wants = null;
54680
55241
  #waits = new SignInWaits(() => this.requestUpdate());
54681
55242
  #copies = new SignInCopies(() => this.requestUpdate());
54682
55243
  #modelFilter = new ModelFilter(this);
@@ -54692,6 +55253,7 @@ var SliccSettings = class extends ThemedElement {
54692
55253
  super();
54693
55254
  this.pending = /* @__PURE__ */ new Set();
54694
55255
  this.entering = null;
55256
+ this.keyEntry = null;
54695
55257
  this.failure = null;
54696
55258
  this.problem = null;
54697
55259
  this.blocked = false;
@@ -54805,6 +55367,17 @@ var SliccSettings = class extends ThemedElement {
54805
55367
  .field sp-picker {
54806
55368
  width: 100%;
54807
55369
  }
55370
+ .entry-fields {
55371
+ display: grid;
55372
+ gap: var(--swc-spacing-200);
55373
+ }
55374
+ .entry-fields[hidden] {
55375
+ display: none;
55376
+ }
55377
+ .entry-label {
55378
+ font-size: var(--swc-font-size-75);
55379
+ color: var(--swc-neutral-subdued-content-color-default);
55380
+ }
54808
55381
  .field sp-field-label {
54809
55382
  margin: 0;
54810
55383
  padding-block: 0;
@@ -54841,7 +55414,8 @@ var SliccSettings = class extends ThemedElement {
54841
55414
  .switched {
54842
55415
  grid-column: 2;
54843
55416
  }
54844
- .developer {
55417
+ .developer,
55418
+ .capture {
54845
55419
  display: grid;
54846
55420
  gap: var(--swc-spacing-75);
54847
55421
  padding-block: var(--swc-spacing-75);
@@ -54852,7 +55426,8 @@ var SliccSettings = class extends ThemedElement {
54852
55426
  gap: var(--swc-spacing-100);
54853
55427
  }
54854
55428
  .developer .hint,
54855
- .developer .failure {
55429
+ .developer .failure,
55430
+ .capture .hint {
54856
55431
  margin: 0;
54857
55432
  line-height: var(--swc-line-height-200);
54858
55433
  }
@@ -55104,7 +55679,8 @@ var SliccSettings = class extends ThemedElement {
55104
55679
  settle3();
55105
55680
  }),
55106
55681
  model.settings.on("providers", update),
55107
- ...model.vault ? [model.vault.on("status", update), model.vault.on("list", update)] : []
55682
+ ...model.vault ? [model.vault.on("status", update), model.vault.on("list", update)] : [],
55683
+ ...model.switches ? [model.switches.on("switches", update)] : []
55108
55684
  ];
55109
55685
  }
55110
55686
  focus() {
@@ -55173,6 +55749,27 @@ var SliccSettings = class extends ThemedElement {
55173
55749
  </div>
55174
55750
  </div>`;
55175
55751
  }
55752
+ #switches() {
55753
+ const port = this.model?.switches;
55754
+ const list6 = port?.list() ?? [];
55755
+ if (!port || !list6.length) return A;
55756
+ return b`<h2 data-section="switches">Capture and devices</h2>
55757
+ <div class="rows">
55758
+ <div class="row">
55759
+ <span class="label">Allow</span>
55760
+ <div class="capture">
55761
+ <div class="switches" data-surface="switches">
55762
+ ${c(
55763
+ list6,
55764
+ (item2) => item2.key,
55765
+ (item2) => b`<sp-switch .checked=${l(item2.on)} data-id=${item2.key} @change=${(event2) => port.set(item2.key, this.#checked(event2))}>${item2.label}</sp-switch>`
55766
+ )}
55767
+ </div>
55768
+ <p class="hint">Programs can capture only what’s on here. Turning one off stops what’s live under it.</p>
55769
+ </div>
55770
+ </div>
55771
+ </div>`;
55772
+ }
55176
55773
  #cancelled = /* @__PURE__ */ new Set();
55177
55774
  #busy(id, on2) {
55178
55775
  const rest = [...this.pending].filter((candidate) => candidate !== id);
@@ -55197,7 +55794,7 @@ var SliccSettings = class extends ThemedElement {
55197
55794
  #vault(account) {
55198
55795
  const vault = this.model?.vault;
55199
55796
  const keyed2 = account.auth === "api-key" || dual(account);
55200
- return keyed2 && account.store === "vault" && vault?.put ? vault : null;
55797
+ return keyed2 && account.store === "vault" && vault && (vault.put || enters(vault)) ? vault : null;
55201
55798
  }
55202
55799
  async keep(account, value, fields) {
55203
55800
  const model = this.model;
@@ -55219,15 +55816,7 @@ var SliccSettings = class extends ThemedElement {
55219
55816
  try {
55220
55817
  if (keyed2) await vault.put?.(recordName(account), value, void 0, options2);
55221
55818
  else if (settings) await vault.settings?.(recordName(account), "model", settings);
55222
- if (url) {
55223
- const server = serverOf(account);
55224
- const old = registrations2()[server];
55225
- await vault.endpoints?.({
55226
- ...old && old !== url ? { remove: { mcp: [{ server, url: old }] } } : {},
55227
- add: { mcp: [{ server, url }] }
55228
- });
55229
- register(server, url);
55230
- }
55819
+ if (url) await this.#endpoint(account, vault, url);
55231
55820
  } catch (error) {
55232
55821
  this.#busy(id, false);
55233
55822
  if (this.model === model) this.#refused(account, failureText(error), keyed2);
@@ -55243,6 +55832,114 @@ var SliccSettings = class extends ThemedElement {
55243
55832
  await vault.settings?.(recordName(account), "model", before ?? {}).catch(() => {
55244
55833
  });
55245
55834
  }
55835
+ async #endpoint(account, vault, url) {
55836
+ const server = serverOf(account);
55837
+ const old = registrations2()[server];
55838
+ await vault.endpoints?.({
55839
+ ...old && old !== url ? { remove: { mcp: [{ server, url: old }] } } : {},
55840
+ add: { mcp: [{ server, url }] }
55841
+ });
55842
+ register(server, url);
55843
+ }
55844
+ #held(account) {
55845
+ const name = recordName(account);
55846
+ const kind = recordKind(account);
55847
+ return !!this.model?.vault?.list()?.secrets.some(
55848
+ (secret) => secret.name === name && secret.kind === kind && secret.state !== "removed"
55849
+ );
55850
+ }
55851
+ async #startKey(account, fields) {
55852
+ const model = this.model;
55853
+ const vault = this.#vault(account);
55854
+ const { id } = account;
55855
+ const name = recordName(account);
55856
+ const settings = this.#settingsOf(account, fields);
55857
+ const options2 = account.group === "mcp" ? { name, kind: "mcp", server: serverOf(account) } : { name, kind: "model", provider: account.id, ...settings ? { settings } : {} };
55858
+ if (this.#held(account)) options2.replace = true;
55859
+ this.#busy(id, true);
55860
+ this.failure = null;
55861
+ this.problem = null;
55862
+ try {
55863
+ const { request: request2 } = await vault.enter(options2);
55864
+ if (this.model !== model || this.entering !== id) {
55865
+ drop(vault, request2);
55866
+ return;
55867
+ }
55868
+ this.keyEntry = { id, request: request2, fields, vault };
55869
+ void this.updateComplete.then(
55870
+ () => this.renderRoot.querySelector("[data-entry] slicc-vault-value")?.focus()
55871
+ );
55872
+ } catch (error) {
55873
+ if (this.model === model) this.#refused(account, failureText(error), true);
55874
+ } finally {
55875
+ this.#busy(id, false);
55876
+ }
55877
+ }
55878
+ async #nextKey(event2, account) {
55879
+ event2.preventDefault();
55880
+ if (account.blocked || this.pending.has(account.id)) return;
55881
+ const form = event2.currentTarget.closest("form");
55882
+ const fields = this.#fields(form, account);
55883
+ if (fields === null) return;
55884
+ const url = this.#mcpUrl(account);
55885
+ const model = this.model;
55886
+ if (url && !await this.#confirmUrl(url)) return;
55887
+ if (this.model !== model || this.entering !== account.id) return;
55888
+ if (away(this.#vault(account))) return;
55889
+ await this.#startKey(account, fields);
55890
+ }
55891
+ async #keyed(account, detail, request2) {
55892
+ const entry = this.keyEntry;
55893
+ if (!entry || entry.id !== account.id || !ours(detail, request2, entry.request)) return;
55894
+ const { id } = account;
55895
+ if (detail.event === "error") {
55896
+ this.#refuse(id, "value", detail.message);
55897
+ return;
55898
+ }
55899
+ if (detail.event === "escape") {
55900
+ this.#leaveKey(account);
55901
+ return;
55902
+ }
55903
+ this.keyEntry = null;
55904
+ if (detail.event === "gone") {
55905
+ this.#refuse(id, "value", goneText(detail.state));
55906
+ return;
55907
+ }
55908
+ const model = this.model;
55909
+ const vault = this.#vault(account);
55910
+ const url = this.#mcpUrl(account);
55911
+ this.#busy(id, true);
55912
+ if (url) {
55913
+ try {
55914
+ await this.#endpoint(account, vault, url);
55915
+ } catch (error) {
55916
+ this.#busy(id, false);
55917
+ if (this.model === model) this.#refused(account, failureText(error), false);
55918
+ return;
55919
+ }
55920
+ }
55921
+ if (this.model !== model || this.entering !== id) {
55922
+ this.#busy(id, false);
55923
+ return;
55924
+ }
55925
+ await this.#connectBases(account, void 0, entry.fields, vault);
55926
+ }
55927
+ #leaveKey(account) {
55928
+ this.#dropKey();
55929
+ if (this.#auto === account.id) {
55930
+ if (this.adding?.id === account.id) this.#back();
55931
+ else this.#cancel();
55932
+ }
55933
+ }
55934
+ #unmounted() {
55935
+ if (this.keyEntry && !this.renderRoot.querySelector("form.key[data-entry]")) this.#dropKey();
55936
+ }
55937
+ #dropKey() {
55938
+ const entry = this.keyEntry;
55939
+ if (!entry) return;
55940
+ this.keyEntry = null;
55941
+ drop(entry.vault, entry.request);
55942
+ }
55246
55943
  #settingsOf(account, fields) {
55247
55944
  const settable = (account.fields ?? []).filter((field3) => field3.vaultSetting);
55248
55945
  if (account.group === "mcp" || !settable.length) return void 0;
@@ -55623,7 +56320,40 @@ var SliccSettings = class extends ThemedElement {
55623
56320
  </div>
55624
56321
  ${this.blocked ? b`<div class="problem" role="alert" data-popup="blocked"><swc-icon-alert-triangle size="s" aria-hidden="true"></swc-icon-alert-triangle><span>The browser blocked the vault window. Allow pop-ups for this site, then try again.</span></div>` : A}`;
55625
56322
  }
56323
+ #entryKept(account, vault) {
56324
+ const { id } = account;
56325
+ const busy = this.pending.has(id);
56326
+ const name = secretNames[account.secret ?? "api-key"];
56327
+ const entry = this.keyEntry?.id === id ? this.keyEntry : null;
56328
+ const fields = account.fields ?? [];
56329
+ const waiting3 = away(vault);
56330
+ if (!entry && !waiting3 && !fields.length && !this.#mcpUrl(account) && this.#auto !== id && !busy)
56331
+ this.#wants = account;
56332
+ const required = fields.filter((field3) => field3.required && !field3.options);
56333
+ const ready = !waiting3 && !account.blocked && required.every((field3) => !this.#offered() || this.filled.has(field3.name));
56334
+ const optional = this.#keyOptional(account);
56335
+ const hint2 = entry ? "Type it in the vault\u2019s own field. It never passes through this page." : waiting3 ? "Waiting for the vault" : busy ? "Opening the vault\u2019s field\u2026" : `You type the ${name} in the vault\u2019s own field next.${optional ? " Or save these settings and keep the key you have." : ""}`;
56336
+ return b`<form class="key stacked" data-id=${id} data-store="vault" data-entry=${entry ? "" : A} @submit=${(event2) => void this.#nextKey(event2, account)} @keydown=${(event2) => this.#submitOnEnter(event2)} @input=${(event2) => this.#fill(event2)}>
56337
+ <span class="entry-label">${account.provider} ${name}</span>
56338
+ ${entry ? valueField(vault, entry.request, valueConfig(this.ownerDocument, this.color), (detail, request2) => void this.#keyed(account, detail, request2)) : A}
56339
+ ${this.#problem(account, "value")}
56340
+ <p class="hint">${hint2}</p>
56341
+ ${this.#getKey(account)}
56342
+ <div class="entry-fields" ?hidden=${!!entry}>${this.#extra(account)}</div>
56343
+ <div class="buttons">
56344
+ ${entry ? b`<swc-button size="m" variant="secondary" data-action="back-key" @click=${() => this.#leaveKey(account)}>Back</swc-button>` : b`<swc-button size="m" variant="accent" data-action="enter-key" ?pending=${busy} ?disabled=${!busy && !ready} @click=${(event2) => void this.#nextKey(event2, account)}>Next</swc-button>
56345
+ ${optional ? b`<swc-button size="m" variant="secondary" data-action="save" ?disabled=${busy || !ready} @click=${(event2) => this.#keepSettings(event2, account)}>Save settings</swc-button>` : A}
56346
+ ${this.#leave(account)}`}
56347
+ </div>
56348
+ </form>`;
56349
+ }
56350
+ #keepSettings(event2, account) {
56351
+ const form = event2.currentTarget.closest("form");
56352
+ const fields = this.#fields(form, account);
56353
+ if (fields !== null && !this.pending.has(account.id)) void this.keep(account, "", fields);
56354
+ }
55626
56355
  #kept(account, vault) {
56356
+ if (enters(vault)) return this.#entryKept(account, vault);
55627
56357
  const busy = this.pending.has(account.id);
55628
56358
  const locked = !!vault.status()?.locked;
55629
56359
  const name = secretNames[account.secret ?? "api-key"];
@@ -56135,8 +56865,25 @@ var SliccSettings = class extends ThemedElement {
56135
56865
  this.adding = null;
56136
56866
  this.picking = true;
56137
56867
  }
56868
+ disconnectedCallback() {
56869
+ super.disconnectedCallback();
56870
+ this.#dropKey();
56871
+ }
56872
+ willUpdate(changed2) {
56873
+ super.willUpdate(changed2);
56874
+ const entry = this.keyEntry;
56875
+ if (entry && (this.entering !== entry.id || entry.vault !== this.model?.vault)) this.#dropKey();
56876
+ if (this.entering === null) this.#auto = null;
56877
+ }
56138
56878
  updated(changed2) {
56139
56879
  super.updated(changed2);
56880
+ if (this.keyEntry) void this.updateComplete.then(() => this.#unmounted());
56881
+ const wants = this.#wants;
56882
+ this.#wants = null;
56883
+ if (wants && this.#auto !== wants.id) {
56884
+ this.#auto = wants.id;
56885
+ void this.#startKey(wants, void 0);
56886
+ }
56140
56887
  const dialog = this.#dialog;
56141
56888
  if (!changed2.has("picking") || !dialog || dialog.open) return;
56142
56889
  dialog.showModal();
@@ -56388,6 +57135,7 @@ var SliccSettings = class extends ThemedElement {
56388
57135
  </div>
56389
57136
  ${this.#developerRow()}
56390
57137
  </div>
57138
+ ${this.#switches()}
56391
57139
  <h2 data-section="accounts">Accounts</h2>
56392
57140
  ${this.#providerList(providers)}
56393
57141
  ${this.#serverList(servers)}
@@ -56445,9 +57193,9 @@ function args(value, start2) {
56445
57193
  function branch(value, side) {
56446
57194
  const at = value.indexOf("light-dark(");
56447
57195
  if (at < 0) return value;
56448
- const [parts3, end] = args(value, at + "light-dark(".length);
57196
+ const [parts3, end2] = args(value, at + "light-dark(".length);
56449
57197
  const picked2 = branch((parts3[side] ?? "").trim(), side);
56450
- return value.slice(0, at) + picked2 + branch(value.slice(end + 1), side);
57198
+ return value.slice(0, at) + picked2 + branch(value.slice(end2 + 1), side);
56451
57199
  }
56452
57200
  function frameTokens(found) {
56453
57201
  const entries = [...found];
@@ -59035,20 +59783,20 @@ var Splitview = class {
59035
59783
  this.distributeEmptySpace();
59036
59784
  this.layoutViews();
59037
59785
  };
59038
- const end = () => {
59786
+ const end2 = () => {
59039
59787
  for (const item2 of this.viewItems) item2.enabled = true;
59040
59788
  iframes.release();
59041
59789
  this.saveProportions();
59042
59790
  doc.removeEventListener("pointermove", onPointerMove);
59043
- doc.removeEventListener("pointerup", end);
59044
- doc.removeEventListener("pointercancel", end);
59045
- doc.removeEventListener("contextmenu", end);
59791
+ doc.removeEventListener("pointerup", end2);
59792
+ doc.removeEventListener("pointercancel", end2);
59793
+ doc.removeEventListener("contextmenu", end2);
59046
59794
  this._onDidSashEnd.fire(void 0);
59047
59795
  };
59048
59796
  doc.addEventListener("pointermove", onPointerMove);
59049
- doc.addEventListener("pointerup", end);
59050
- doc.addEventListener("pointercancel", end);
59051
- doc.addEventListener("contextmenu", end);
59797
+ doc.addEventListener("pointerup", end2);
59798
+ doc.addEventListener("pointercancel", end2);
59799
+ doc.addEventListener("contextmenu", end2);
59052
59800
  };
59053
59801
  sash.addEventListener("pointerdown", onPointerStart);
59054
59802
  const sashItem = {
@@ -64848,12 +65596,12 @@ var TabReorderController = class extends CompositeDisposable {
64848
65596
  commitPointerReorder(event2) {
64849
65597
  const animState = this._animState;
64850
65598
  if ((animState === null || animState === void 0 ? void 0 : animState.currentInsertionIndex) == null) return;
64851
- const drop = this.resolveTabDrop(animState);
65599
+ const drop2 = this.resolveTabDrop(animState);
64852
65600
  this._animState = null;
64853
65601
  this.clearWrapDropIndicator();
64854
65602
  this.uncollapseSourceTab(animState.sourceTabId);
64855
- if (!drop) return;
64856
- this.host.fireDrop(_objectSpread2({ event: event2 }, drop));
65603
+ if (!drop2) return;
65604
+ this.host.fireDrop(_objectSpread2({ event: event2 }, drop2));
64857
65605
  }
64858
65606
  /**
64859
65607
  * Shared body of the dragover entry point. Refreshes stale anim state
@@ -65897,19 +66645,19 @@ var Tabs = class extends CompositeDisposable {
65897
66645
  this._commitGroupMove(animState.sourceTabGroupId, animState.currentInsertionIndex);
65898
66646
  return;
65899
66647
  }
65900
- const drop = this._reorder.resolveTabDrop(animState);
66648
+ const drop2 = this._reorder.resolveTabDrop(animState);
65901
66649
  this._reorder.uncollapseSourceTab(animState.sourceTabId);
65902
- if (!drop) {
66650
+ if (!drop2) {
65903
66651
  this.resetTabTransforms();
65904
66652
  return;
65905
66653
  }
65906
66654
  const sourceIndex = animState.sourceIndex;
65907
66655
  const firstPositions = this.snapshotTabPositions();
65908
66656
  this.resetTabTransforms();
65909
- this._onDrop.fire(_objectSpread2({ event: event2 }, drop));
66657
+ this._onDrop.fire(_objectSpread2({ event: event2 }, drop2));
65910
66658
  this.runFlipAnimation(firstPositions, animState.sourceTabId, sourceIndex === -1, {
65911
- from: Math.min(sourceIndex, drop.index),
65912
- to: Math.max(sourceIndex, drop.index)
66659
+ from: Math.min(sourceIndex, drop2.index),
66660
+ to: Math.max(sourceIndex, drop2.index)
65913
66661
  });
65914
66662
  }, true), Disposable.from(() => {
65915
66663
  var _this$_voidContainerL2;
@@ -69118,7 +69866,7 @@ var Overlay = class Overlay2 extends CompositeDisposable {
69118
69866
  captureTarget.setPointerCapture(pointerId);
69119
69867
  } catch (_unused) {
69120
69868
  }
69121
- const end = () => {
69869
+ const end2 = () => {
69122
69870
  toggleClass(this._element, "dv-resize-container-dragging", false);
69123
69871
  this._dragMove.value = Disposable.NONE;
69124
69872
  this._onDidChangeEnd.fire();
@@ -69186,7 +69934,7 @@ var Overlay = class Overlay2 extends CompositeDisposable {
69186
69934
  hasMoved = true;
69187
69935
  this._onDidStartMoving.fire();
69188
69936
  }
69189
- }), addDisposableListener(globalThis.window, "pointerup", end), addDisposableListener(globalThis.window, "pointercancel", end));
69937
+ }), addDisposableListener(globalThis.window, "pointerup", end2), addDisposableListener(globalThis.window, "pointercancel", end2));
69190
69938
  };
69191
69939
  this.addDisposables(addDisposableListener(dragTarget, "pointerdown", (event2) => {
69192
69940
  if (event2.defaultPrevented) {
@@ -69218,7 +69966,7 @@ var Overlay = class Overlay2 extends CompositeDisposable {
69218
69966
  resizeHandleElement.setPointerCapture(pointerId);
69219
69967
  } catch (_unused3) {
69220
69968
  }
69221
- const end = () => {
69969
+ const end2 = () => {
69222
69970
  move.dispose();
69223
69971
  this._onDidChangeEnd.fire();
69224
69972
  };
@@ -69310,7 +70058,7 @@ var Overlay = class Overlay2 extends CompositeDisposable {
69310
70058
  resizeHandleElement.releasePointerCapture(pointerId);
69311
70059
  } catch (_unused4) {
69312
70060
  }
69313
- } }, addDisposableListener(globalThis.window, "pointerup", end), addDisposableListener(globalThis.window, "pointercancel", end));
70061
+ } }, addDisposableListener(globalThis.window, "pointerup", end2), addDisposableListener(globalThis.window, "pointercancel", end2));
69314
70062
  }));
69315
70063
  }
69316
70064
  getMinimumWidth(width) {
@@ -75361,10 +76109,10 @@ var SliccDock = class extends HTMLElement {
75361
76109
  toJSON() {
75362
76110
  return this.api.toJSON();
75363
76111
  }
75364
- restore(layout) {
75365
- if (!layout) return false;
76112
+ restore(layout2) {
76113
+ if (!layout2) return false;
75366
76114
  try {
75367
- this.api.fromJSON(layout);
76115
+ this.api.fromJSON(layout2);
75368
76116
  return this.api.panels.length > 0;
75369
76117
  } catch {
75370
76118
  this.api.clear();
@@ -78282,12 +79030,12 @@ function getVisibleRowContext(state2, index2) {
78282
79030
  subtreeEndIndex: getVisibleRowSubtreeEndIndex(state2, selected.cursor, selected.index, totalVisibleCount)
78283
79031
  };
78284
79032
  }
78285
- function getVisibleSlice(state2, start2, end) {
79033
+ function getVisibleSlice(state2, start2, end2) {
78286
79034
  const instrumentation = state2.instrumentation;
78287
79035
  const totalVisibleCount = getVisibleCount(state2);
78288
- if (totalVisibleCount <= 0 || end < start2) return [];
79036
+ if (totalVisibleCount <= 0 || end2 < start2) return [];
78289
79037
  const normalizedStart = Math.max(0, Math.min(start2, totalVisibleCount - 1));
78290
- const normalizedEnd = Math.max(normalizedStart, Math.min(end, totalVisibleCount - 1));
79038
+ const normalizedEnd = Math.max(normalizedStart, Math.min(end2, totalVisibleCount - 1));
78291
79039
  if (instrumentation == null) {
78292
79040
  if (normalizedStart === 0) return collectVisibleRowsDFS(state2, normalizedEnd + 1);
78293
79041
  const rows3 = [];
@@ -78905,8 +79653,8 @@ var PathStore = class PathStore2 {
78905
79653
  getVisibleCount() {
78906
79654
  return withBenchmarkPhase(this.#state.instrumentation, "store.getVisibleCount", () => getVisibleCount(this.#state));
78907
79655
  }
78908
- getVisibleSlice(start2, end) {
78909
- return withBenchmarkPhase(this.#state.instrumentation, "store.getVisibleSlice", () => getVisibleSlice(this.#state, start2, end));
79656
+ getVisibleSlice(start2, end2) {
79657
+ return withBenchmarkPhase(this.#state.instrumentation, "store.getVisibleSlice", () => getVisibleSlice(this.#state, start2, end2));
78910
79658
  }
78911
79659
  getVisibleRowContext(index2) {
78912
79660
  return withBenchmarkPhase(this.#state.instrumentation, "store.getVisibleRowContext", () => getVisibleRowContext(this.#state, index2));
@@ -79969,10 +80717,10 @@ var FileTreeController = class FileTreeController2 {
79969
80717
  getVisibleCount() {
79970
80718
  return this.#visibleCount;
79971
80719
  }
79972
- getVisibleRows(start2, end) {
79973
- if (end < start2 || this.#visibleCount === 0) return [];
80720
+ getVisibleRows(start2, end2) {
80721
+ if (end2 < start2 || this.#visibleCount === 0) return [];
79974
80722
  const boundedStart = Math.max(0, start2);
79975
- const boundedEnd = Math.min(this.#visibleCount - 1, end);
80723
+ const boundedEnd = Math.min(this.#visibleCount - 1, end2);
79976
80724
  if (boundedEnd < boundedStart) return [];
79977
80725
  const boundedLength = boundedEnd - boundedStart + 1;
79978
80726
  if (this.#searchVisibleIndices == null && !this.#hasFullProjection && boundedEnd >= this.#projectionPaths.length && boundedLength <= CONTEXT_VISIBLE_ROW_RANGE_LIMIT) {
@@ -84276,8 +85024,8 @@ var FileTree = class {
84276
85024
  getVisibleCount() {
84277
85025
  return this.#controller.getVisibleCount();
84278
85026
  }
84279
- getVisibleRows(start2, end) {
84280
- return this.#controller.getVisibleRows(start2, end);
85027
+ getVisibleRows(start2, end2) {
85028
+ return this.#controller.getVisibleRows(start2, end2);
84281
85029
  }
84282
85030
  getSelectedPaths() {
84283
85031
  return this.#controller.getSelectedPaths();
@@ -85003,6 +85751,7 @@ function defineFileTree() {
85003
85751
  }
85004
85752
 
85005
85753
  // src/ui.ts
85754
+ var valueEntry = true;
85006
85755
  var elements = {
85007
85756
  "slicc-agents": SliccAgents,
85008
85757
  "slicc-chat": SliccChat,
@@ -85022,6 +85771,7 @@ var elements = {
85022
85771
  "slicc-sprinkle": SliccSprinkle,
85023
85772
  "slicc-lucide": SliccLucide,
85024
85773
  "slicc-tray": SliccTray,
85774
+ "slicc-live": SliccLive,
85025
85775
  "slicc-follow": SliccFollow,
85026
85776
  "slicc-updates": SliccUpdates,
85027
85777
  "slicc-network": SliccNetwork,
@@ -85067,6 +85817,7 @@ export {
85067
85817
  SliccFollow,
85068
85818
  SliccFreezerImport,
85069
85819
  SliccGuestInvite,
85820
+ SliccLive,
85070
85821
  SliccNetwork,
85071
85822
  SliccNotices,
85072
85823
  SliccPrompt,
@@ -85082,7 +85833,8 @@ export {
85082
85833
  panelCommand,
85083
85834
  prompt,
85084
85835
  resolveColor,
85085
- surfaces2 as surfaces
85836
+ surfaces2 as surfaces,
85837
+ valueEntry
85086
85838
  };
85087
85839
  /*! Bundled license information:
85088
85840