@ai-ecoverse/slicc-spectrum 1.110.0 → 1.111.1

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
@@ -8605,6 +8605,9 @@ function chatModels(options2) {
8605
8605
  function statusLight(status2) {
8606
8606
  return b`<swc-status-light size="s" variant=${statusVariant[status2]}>${statusLabel[status2]}</swc-status-light>`;
8607
8607
  }
8608
+ function statusDot(status2) {
8609
+ return b`<span class="dot" data-agent-status=${status2} data-variant=${statusVariant[status2]} role="img" aria-label=${statusLabel[status2]} title=${statusLabel[status2]}></span>`;
8610
+ }
8608
8611
  var shared = i`
8609
8612
  .dot {
8610
8613
  display: inline-block;
@@ -17944,14 +17947,14 @@ var resolver = {
17944
17947
  };
17945
17948
  var string = initializeFactory("string");
17946
17949
  var text = initializeFactory("text");
17947
- function initializeFactory(field2) {
17950
+ function initializeFactory(field3) {
17948
17951
  return {
17949
- resolveAll: createResolver(field2 === "text" ? resolveAllLineSuffixes : void 0),
17952
+ resolveAll: createResolver(field3 === "text" ? resolveAllLineSuffixes : void 0),
17950
17953
  tokenize: initializeText
17951
17954
  };
17952
17955
  function initializeText(effects) {
17953
17956
  const self2 = this;
17954
- const constructs2 = this.parser.constructs[field2];
17957
+ const constructs2 = this.parser.constructs[field3];
17955
17958
  const text4 = effects.attempt(constructs2, start2, notText);
17956
17959
  return start2;
17957
17960
  function start2(code3) {
@@ -25063,7 +25066,7 @@ var File = class {
25063
25066
  const sessionAnnotationsCurrent = editSessionAnnotations?.current;
25064
25067
  let acceptedFile;
25065
25068
  let failed2 = false;
25066
- let failure2;
25069
+ let failure3;
25067
25070
  if (editor == null) throw new Error("File.__completeEditSession: editor is required for completion");
25068
25071
  const completedFile = { ...editSessionFile };
25069
25072
  const event2 = {
@@ -25082,7 +25085,7 @@ var File = class {
25082
25085
  }
25083
25086
  } catch (error) {
25084
25087
  failed2 = true;
25085
- failure2 = error;
25088
+ failure3 = error;
25086
25089
  }
25087
25090
  const settledFile = installResult && acceptedFile != null ? acceptedFile : inputFile;
25088
25091
  const settledAnnotations = installResult && acceptedFile != null ? sessionAnnotationsCurrent ?? inputAnnotations : inputAnnotations;
@@ -25095,7 +25098,7 @@ var File = class {
25095
25098
  this.fileRenderer.endEditSession(settledFile);
25096
25099
  if (areFileTargetsEqual(this.getRenderedFile(), settledFile)) this.adoptRenderData(settledFile);
25097
25100
  if (installResult && this.fileContainer != null) this.rerender();
25098
- if (failed2) throw failure2;
25101
+ if (failed2) throw failure3;
25099
25102
  }
25100
25103
  applyDocumentChange(textDocument, newLineAnnotations) {
25101
25104
  const editSessionFile = this.editSession?.file;
@@ -31513,7 +31516,7 @@ var FileDiff = class {
31513
31516
  let acceptedOldFile = null;
31514
31517
  let acceptedNewFile = null;
31515
31518
  let failed2 = false;
31516
- let failure2;
31519
+ let failure3;
31517
31520
  if (editor == null) throw new Error("FileDiff.__completeEditSession: editor is required for completion");
31518
31521
  const completedDiff = cloneFileDiffMetadata(editSessionDiff);
31519
31522
  const newFile = {
@@ -31544,7 +31547,7 @@ var FileDiff = class {
31544
31547
  }
31545
31548
  } catch (error) {
31546
31549
  failed2 = true;
31547
- failure2 = error;
31550
+ failure3 = error;
31548
31551
  }
31549
31552
  if (installResult && acceptedDiff != null) {
31550
31553
  if (this.additionFile != null) {
@@ -31559,7 +31562,7 @@ var FileDiff = class {
31559
31562
  lineAnnotations: installResult && acceptedDiff != null ? sessionAnnotationsCurrent ?? inputAnnotations : inputAnnotations
31560
31563
  };
31561
31564
  if (installResult && this.fileContainer != null) this.rerender();
31562
- if (failed2) throw failure2;
31565
+ if (failed2) throw failure3;
31563
31566
  }
31564
31567
  /**
31565
31568
  * Run the session-end recompute: restore recompute-shaped hunks (a
@@ -33411,14 +33414,14 @@ function errorCard(item2, handlers) {
33411
33414
  const signing = login?.state === "signing-in" && login.window;
33412
33415
  const text4 = resolved ? signedIn : signing ? signInText(login.waited) : item2.text;
33413
33416
  const title2 = resolved && login.provider ? `Signed in to ${login.provider} again.` : item2.title;
33414
- const failure2 = login?.state === "idle" ? login.error : void 0;
33417
+ const failure3 = login?.state === "idle" ? login.error : void 0;
33415
33418
  return b`<div class="error-card" role=${resolved ? A : "alert"} aria-atomic=${resolved ? A : "false"} data-id=${id || A} data-login=${login?.state ?? A}>
33416
33419
  ${resolved ? b`<swc-icon-info-circle class="icon" size="s" aria-hidden="true"></swc-icon-info-circle>` : b`<swc-icon-alert-diamond class="icon" size="s" aria-hidden="true"></swc-icon-alert-diamond>`}
33417
33420
  ${resolved ? A : b`<span class="sr">Error: </span>`}<span class="lead">${title2}</span>
33418
33421
  ${text4 ? b`<span class="detail" role=${login ? "status" : A}>${text4}</span>` : A}
33419
33422
  ${fix ? b`<div class="fix" aria-live="off">${fixButton(fix, item2, handlers, login)}</div>` : A}
33420
33423
  ${signing ? signInDetails(item2.account, login.signIn, login.copied, (code3) => handlers.copySignIn?.(item2.account, id, code3), "s") : A}
33421
- ${failure2 ? b`<div class="help" data-error="login"><sp-help-text size="s" variant="negative" icon>${failure2}</sp-help-text><swc-action-button size="s" quiet data-action="settings" @click=${() => handlers.action("settings", item2.id, item2.account)}>Open settings</swc-action-button></div>` : A}
33424
+ ${failure3 ? b`<div class="help" data-error="login"><sp-help-text size="s" variant="negative" icon>${failure3}</sp-help-text><swc-action-button size="s" quiet data-action="settings" @click=${() => handlers.action("settings", item2.id, item2.account)}>Open settings</swc-action-button></div>` : A}
33422
33425
  </div>`;
33423
33426
  }
33424
33427
  function time(at) {
@@ -33620,8 +33623,8 @@ function question(item2, handlers) {
33620
33623
  } else {
33621
33624
  const submit = (event2) => {
33622
33625
  event2.preventDefault();
33623
- const field2 = event2.currentTarget.querySelector("input");
33624
- if (field2.value.trim()) answer(field2.value.trim());
33626
+ const field3 = event2.currentTarget.querySelector("input");
33627
+ if (field3.value.trim()) answer(field3.value.trim());
33625
33628
  };
33626
33629
  body2 = b`<form class="options" @submit=${submit}>
33627
33630
  <input class="input" type=${item2.kind === "email" ? "email" : item2.kind === "number" ? "number" : item2.kind === "date" ? "date" : "text"} aria-label=${item2.question} ?disabled=${handlers.readOnly} />
@@ -34891,8 +34894,8 @@ function failureText(error) {
34891
34894
  const text4 = isVaultFailure(error) ? codeTexts[error.code] : void 0;
34892
34895
  return text4 ?? (error instanceof Error ? error.message : "The vault did not answer");
34893
34896
  }
34894
- function fieldOf(error, field2) {
34895
- return isVaultFailure(error) && error.code === "EINVAL" ? field2 : null;
34897
+ function fieldOf(error, field3) {
34898
+ return isVaultFailure(error) && error.code === "EINVAL" ? field3 : null;
34896
34899
  }
34897
34900
  function away(vault) {
34898
34901
  const state2 = vault.availability?.() ?? (vault.status() ? "ready" : "waiting");
@@ -35814,12 +35817,12 @@ var SliccComposer = class extends ThemedElement {
35814
35817
  this.renderRoot.querySelector('.item[aria-selected="true"]')?.scrollIntoView({ block: "nearest" });
35815
35818
  }
35816
35819
  #wire() {
35817
- const field2 = this.#field;
35818
- void field2.updateComplete.then(() => {
35820
+ const field3 = this.#field;
35821
+ void field3.updateComplete.then(() => {
35819
35822
  const popover = this.renderRoot.querySelector("swc-popover");
35820
35823
  if (popover) {
35821
35824
  popover.triggerElement = null;
35822
- popover.triggerElement = field2.shadowRoot.querySelector(
35825
+ popover.triggerElement = field3.shadowRoot.querySelector(
35823
35826
  ".swc-PromptField-upload"
35824
35827
  );
35825
35828
  }
@@ -36030,16 +36033,16 @@ ${this.value}` : text4;
36030
36033
  text4 === null || text4 === void 0 ? { ...base, kind: "file", size: 0, error: "Could not read the file" } : { ...base, kind: "text", size: text4.length, text: text4 }
36031
36034
  ];
36032
36035
  }
36033
- async shareSecret(name, field2 = null) {
36036
+ async shareSecret(name, field3 = null) {
36034
36037
  const clean = name.trim().toUpperCase().replace(/[^A-Z0-9_]/g, "_");
36035
36038
  if (this.sharing) return;
36036
36039
  if (!clean) {
36037
- if (field2) this.#refuse("Enter a name", "name", true);
36040
+ if (field3) this.#refuse("Enter a name", "name", true);
36038
36041
  return;
36039
36042
  }
36040
- const value = field2 ? take(field2) : "";
36043
+ const value = field3 ? take(field3) : "";
36041
36044
  const vault = this.model?.vault;
36042
- if (field2 && vault?.put && !await this.#store(vault, clean, value)) return;
36045
+ if (field3 && vault?.put && !await this.#store(vault, clean, value)) return;
36043
36046
  this.#refuse(null);
36044
36047
  this.attachments = [
36045
36048
  ...this.attachments,
@@ -36053,12 +36056,12 @@ ${this.value}` : text4;
36053
36056
  ];
36054
36057
  this.popup = null;
36055
36058
  }
36056
- #refuse(text4, field2 = null, focus = false) {
36059
+ #refuse(text4, field3 = null, focus = false) {
36057
36060
  this.secretError = text4;
36058
- this.secretField = text4 ? field2 : null;
36059
- if (focus && text4 && field2)
36061
+ this.secretField = text4 ? field3 : null;
36062
+ if (focus && text4 && field3)
36060
36063
  void this.updateComplete.then(
36061
- () => this.renderRoot.querySelector(`form.secret input[name=${field2}]`)?.focus()
36064
+ () => this.renderRoot.querySelector(`form.secret input[name=${field3}]`)?.focus()
36062
36065
  );
36063
36066
  }
36064
36067
  async #store(vault, clean, value) {
@@ -37241,9 +37244,16 @@ var SliccChat = class _SliccChat extends ThemedElement {
37241
37244
  header swc-action-button {
37242
37245
  flex: none;
37243
37246
  }
37244
- header swc-status-light {
37247
+ header swc-status-light,
37248
+ header .dot {
37245
37249
  align-self: center;
37246
37250
  }
37251
+ @media (forced-colors: active) {
37252
+ header .dot[data-agent-status] {
37253
+ forced-color-adjust: none;
37254
+ background: CanvasText;
37255
+ }
37256
+ }
37247
37257
  header swc-meter {
37248
37258
  flex: 0 1 calc(var(--swc-spacing-400) * 6);
37249
37259
  min-width: calc(var(--swc-spacing-400) * 4.5);
@@ -37968,12 +37978,12 @@ var SliccChat = class _SliccChat extends ThemedElement {
37968
37978
  }
37969
37979
  if (watchOnly(model)) {
37970
37980
  const label = model.settings.models().find((option) => option.id === agent.model)?.label;
37971
- return b`${statusLight(agent.status)}
37981
+ return b`${statusDot(agent.status)}
37972
37982
  <span class="model" data-model>${label ?? agent.model}</span>
37973
37983
  ${meter}`;
37974
37984
  }
37975
37985
  const offered = chatModels(model.settings.models());
37976
- return b`${statusLight(agent.status)}
37986
+ return b`${statusDot(agent.status)}
37977
37987
  ${offered.length ? b`<sp-picker size="s" quiet label="Model" value=${agent.model} @change=${(event2) => model.agent.setModel(agent.id, event2.target.value)} @sp-opened=${this.#modelFilter.opened} @sp-closed=${this.#modelFilter.closed} @keydown=${this.#modelFilter.keys}>
37978
37988
  ${this.#modelFilter.items(offered)}
37979
37989
  </sp-picker>` : b`<swc-action-button size="s" quiet data-action="set-up-model" @click=${() => this.#action("settings")}>Set up a model</swc-action-button>`}
@@ -40512,9 +40522,6 @@ var SliccAgents = class extends ModelElement {
40512
40522
  font-size: var(--swc-font-size-75);
40513
40523
  color: var(--swc-neutral-subdued-content-color-default);
40514
40524
  }
40515
- .state {
40516
- color: var(--swc-neutral-content-color-default);
40517
- }
40518
40525
  .ribbon {
40519
40526
  grid-area: ribbon;
40520
40527
  display: flex;
@@ -40840,11 +40847,12 @@ var SliccAgents = class extends ModelElement {
40840
40847
  >
40841
40848
  ${this.#disclosure(agent, scoops, open)}
40842
40849
  <div class="head">
40843
- ${unread ? b`<span class="marker unread" data-status=${agent.status} aria-hidden="true">${unreadCount(unread)}</span>` : b`<span class="marker status" data-status=${agent.status} aria-hidden="true"></span>`}
40850
+ <span class="marker status" data-status=${agent.status} aria-hidden="true"></span>
40851
+ ${unread ? b`<span class="marker unread" data-status=${agent.status} aria-hidden="true">${unreadCount(unread)}</span>` : A}
40844
40852
  <span class="name">${agent.name}</span>
40845
40853
  </div>
40846
40854
  ${fillShown(agent.contextFill) ? b`<span class="fill" data-variant=${meterVariant2(agent.contextFill)}>${percent(agent.contextFill)}</span>` : A}
40847
- <span class="title"><span class="state">${statusLabel[agent.status]}</span> · ${title2 || untitled}</span>
40855
+ <span class="title">${title2 || untitled}</span>
40848
40856
  ${this.#ribbon(scoops)}
40849
40857
  ${this.#dropButton(agent, selected)}
40850
40858
  ${this.#deleteButton(agent, selected)}
@@ -41104,9 +41112,9 @@ var defaultGates = {
41104
41112
  messages: ["user", "agent", "cone", "scoop:*", "off"],
41105
41113
  tools: ["user", "agent", "scoop:*"]
41106
41114
  };
41107
- function gateChoice(field2, cone, gate) {
41115
+ function gateChoice(field3, cone, gate) {
41108
41116
  if (gate === "scoop:*")
41109
- return cone.scoops.flatMap((name) => gateChoice(field2, cone, `scoop:${name}`));
41117
+ return cone.scoops.flatMap((name) => gateChoice(field3, cone, `scoop:${name}`));
41110
41118
  if (gate.startsWith("scoop:")) {
41111
41119
  const name = gate.slice(6);
41112
41120
  return cone.scoops.includes(name) ? [{ value: gate, label: `${name} decides`, description: `The scoop ${name} decides.` }] : [];
@@ -41126,14 +41134,14 @@ function gateChoice(field2, cone, gate) {
41126
41134
  off: {
41127
41135
  value: "off",
41128
41136
  label: "No review",
41129
- description: field2 === "messages" ? "Messages go straight in as follow-ups." : "Tool calls run without review."
41137
+ description: field3 === "messages" ? "Messages go straight in as follow-ups." : "Tool calls run without review."
41130
41138
  }
41131
41139
  };
41132
41140
  return choices[gate] ? [choices[gate]] : [];
41133
41141
  }
41134
- function gateOptions(field2, cone, allowed = defaultGates[field2]) {
41135
- const options2 = allowed.flatMap((gate) => gateChoice(field2, cone, gate)).filter((option, index2, all2) => all2.findIndex(({ value }) => value === option.value) === index2);
41136
- return options2.length ? options2 : gateChoice(field2, cone, "user");
41142
+ function gateOptions(field3, cone, allowed = defaultGates[field3]) {
41143
+ const options2 = allowed.flatMap((gate) => gateChoice(field3, cone, gate)).filter((option, index2, all2) => all2.findIndex(({ value }) => value === option.value) === index2);
41144
+ return options2.length ? options2 : gateChoice(field3, cone, "user");
41137
41145
  }
41138
41146
  function defaultGate(options2) {
41139
41147
  return options2.some(({ value }) => value === "user") ? "user" : options2[0].value;
@@ -41278,11 +41286,11 @@ var SliccGuestInvite = class extends i2 {
41278
41286
  get #current() {
41279
41287
  return this.cones.find((cone) => cone.id === this.cone) ?? this.cones[0];
41280
41288
  }
41281
- #options(field2, cone) {
41282
- return gateOptions(field2, cone, this.port?.gates?.()[field2]);
41289
+ #options(field3, cone) {
41290
+ return gateOptions(field3, cone, this.port?.gates?.()[field3]);
41283
41291
  }
41284
- #keep(gate, field2, cone) {
41285
- const options2 = this.#options(field2, cone);
41292
+ #keep(gate, field3, cone) {
41293
+ const options2 = this.#options(field3, cone);
41286
41294
  return options2.some((option) => option.value === gate) ? gate : defaultGate(options2);
41287
41295
  }
41288
41296
  #settle() {
@@ -41354,18 +41362,18 @@ var SliccGuestInvite = class extends i2 {
41354
41362
  this.remove();
41355
41363
  if (this.trigger?.isConnected) this.trigger.focus();
41356
41364
  }
41357
- #gate(field2, title2, value) {
41358
- const options2 = this.#options(field2, this.#current);
41365
+ #gate(field3, title2, value) {
41366
+ const options2 = this.#options(field3, this.#current);
41359
41367
  const chosen = options2.find((option) => option.value === value);
41360
- const id = `guest-${field2}`;
41368
+ const id = `guest-${field3}`;
41361
41369
  return b`<div class="field">
41362
41370
  <sp-field-label for=${id} size="m">${title2}</sp-field-label>
41363
- <sp-picker id=${id} size="m" label=${title2} data-action=${`guest-${field2}`} .value=${l(value)} ?disabled=${this.pending} @change=${(event2) => {
41364
- this[field2] = this.#pick(event2);
41371
+ <sp-picker id=${id} size="m" label=${title2} data-action=${`guest-${field3}`} .value=${l(value)} ?disabled=${this.pending} @change=${(event2) => {
41372
+ this[field3] = this.#pick(event2);
41365
41373
  }}>
41366
41374
  ${options2.map((option) => b`<sp-menu-item value=${option.value}>${option.label}<span slot="description">${option.description}</span></sp-menu-item>`)}
41367
41375
  </sp-picker>
41368
- <sp-help-text size="m" data-help=${field2}>${chosen.description}</sp-help-text>
41376
+ <sp-help-text size="m" data-help=${field3}>${chosen.description}</sp-help-text>
41369
41377
  </div>`;
41370
41378
  }
41371
41379
  #form() {
@@ -42951,11 +42959,11 @@ var SliccNetwork = class extends ModelElement {
42951
42959
  }
42952
42960
  async #submitPair(event2, port) {
42953
42961
  event2.preventDefault();
42954
- const field2 = this.renderRoot.querySelector("#pair-url");
42955
- const url = field2.value.trim();
42962
+ const field3 = this.renderRoot.querySelector("#pair-url");
42963
+ const url = field3.value.trim();
42956
42964
  if (!url || this.pairBusy || !port.pairComputer) return;
42957
42965
  if (await this.#pairAct("pair", () => port.pairComputer?.(url))) {
42958
- field2.value = "";
42966
+ field3.value = "";
42959
42967
  this.pairFilled = false;
42960
42968
  }
42961
42969
  }
@@ -43024,11 +43032,11 @@ var SliccNetwork = class extends ModelElement {
43024
43032
  #submitKey(event2, port) {
43025
43033
  event2.preventDefault();
43026
43034
  if (this.busy) return;
43027
- const field2 = event2.currentTarget.querySelector(
43035
+ const field3 = event2.currentTarget.querySelector(
43028
43036
  "sp-textfield"
43029
43037
  );
43030
- const key = field2.value.trim();
43031
- field2.value = "";
43038
+ const key = field3.value.trim();
43039
+ field3.value = "";
43032
43040
  if (key) void this.#tailnet("key", () => port.submitAuthKey?.(key));
43033
43041
  }
43034
43042
  #sendKey(event2) {
@@ -50437,7 +50445,7 @@ var SliccApprovals = class extends ModelElement {
50437
50445
  const list6 = this.#current();
50438
50446
  const [approval, ...rest] = held2 ? [held2, ...list6.filter(({ id }) => id !== held2.id)] : list6;
50439
50447
  if (!approval) return A;
50440
- const failure2 = this.failure?.id === approval.id ? this.failure.message : "";
50448
+ const failure3 = this.failure?.id === approval.id ? this.failure.message : "";
50441
50449
  const verdict = rulesOf(approval);
50442
50450
  const rules = verdict.certain ?? verdict.maybe;
50443
50451
  const always = approval.kind !== "tray" && approval.always && !deniedSudo(approval) && !rules;
@@ -50453,10 +50461,10 @@ var SliccApprovals = class extends ModelElement {
50453
50461
  ${this.#verdict(approval)}
50454
50462
  ${rules ? b`<div class="rules" data-secret-rules=${rules}><swc-icon-alert-triangle size="s" aria-hidden="true"></swc-icon-alert-triangle><p>${verdict.certain ? b`<strong>This changes secret rules.</strong> It names <code>${commandText(rules, false)}</code>, where SLICC keeps which secrets programs may use and where they may be sent.` : b`<strong>This may change secret rules.</strong> SLICC can't tell where <code>${commandText(rules, false)}</code> leads, and it could reach the files where SLICC keeps which secrets programs may use and where they may be sent.`} Allow it only if you asked for this change.</p></div>` : A}
50455
50463
  ${hint2 ? b`<p class="hint">${hint2}</p>` : A}
50456
- ${!failure2 && gate ? b`<p class="hint" data-allow-hint>${gate}</p>` : A}
50457
- ${failure2 ? b`<p class="problem" role="alert" data-error><swc-icon-alert-triangle size="s" aria-hidden="true"></swc-icon-alert-triangle><span>${failure2}</span></p>` : b`<p class="timer" data-timer>Denied automatically in ${countdown(approval.expiresAt - this.now)}.</p>`}
50464
+ ${!failure3 && gate ? b`<p class="hint" data-allow-hint>${gate}</p>` : A}
50465
+ ${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>`}
50458
50466
  ${rest.length ? b`<p class="more" data-more>${rest.length === 1 ? "1 more request is waiting." : `${rest.length} more requests are waiting.`}</p>` : A}
50459
- ${this.#actions(approval, !!failure2, always)}
50467
+ ${this.#actions(approval, !!failure3, always)}
50460
50468
  </sp-alert-dialog>`
50461
50469
  );
50462
50470
  }
@@ -52683,15 +52691,15 @@ var SliccMemory = class extends ModelElement {
52683
52691
  }
52684
52692
  #save(memory) {
52685
52693
  const form = this.renderRoot.querySelector(".editor");
52686
- const field2 = (name) => form.querySelector(`[name=${name}]`).value.trim();
52687
- if (!field2("title")) return;
52688
- const tag3 = field2("tag");
52694
+ const field3 = (name) => form.querySelector(`[name=${name}]`).value.trim();
52695
+ if (!field3("title")) return;
52696
+ const tag3 = field3("tag");
52689
52697
  const saved = this.model?.memory.save({
52690
52698
  ...memory.id ? { id: memory.id } : {},
52691
52699
  scope: memory.scope,
52692
- section: field2("section") || "Notes",
52693
- title: field2("title"),
52694
- body: field2("body"),
52700
+ section: field3("section") || "Notes",
52701
+ title: field3("title"),
52702
+ body: field3("body"),
52695
52703
  tag: tag3 !== "none" ? tag3 : null
52696
52704
  });
52697
52705
  this.editing = null;
@@ -52968,13 +52976,13 @@ var SliccNotices = class extends ModelElement {
52968
52976
  }
52969
52977
  #notice(notice) {
52970
52978
  const pending = this.pending.get(notice.id);
52971
- const failure2 = this.failures.get(notice.id);
52979
+ const failure3 = this.failures.get(notice.id);
52972
52980
  return b`<div class="notice" role="status" data-notice=${notice.id} data-tone=${notice.tone}>
52973
52981
  ${notice.tone === "warning" ? b`<swc-icon-alert-triangle></swc-icon-alert-triangle>` : b`<swc-icon-info-circle></swc-icon-info-circle>`}
52974
52982
  <div class="text">
52975
52983
  <span class="title">${notice.title}</span>
52976
52984
  <p>${notice.body}</p>
52977
- ${failure2 ? b`<p class="problem" data-error><swc-icon-alert-triangle></swc-icon-alert-triangle><span>${failure2}</span></p>` : A}
52985
+ ${failure3 ? b`<p class="problem" data-error><swc-icon-alert-triangle></swc-icon-alert-triangle><span>${failure3}</span></p>` : A}
52978
52986
  ${notice.actions.length ? b`<div class="actions">${notice.actions.map(
52979
52987
  (action) => b`<swc-button size="s" variant="secondary" fill-style="outline" data-action=${action.id} ?pending=${pending === action.id} ?disabled=${!!pending && pending !== action.id} @click=${() => void this.act(notice.id, action.id)}>${action.label}</swc-button>`
52980
52988
  )}</div>` : A}
@@ -53674,19 +53682,19 @@ var SliccSecrets = class extends ThemedElement {
53674
53682
  if (form?.kind === "import") this.importKind = "bundle";
53675
53683
  if (form) void this.updateComplete.then(() => this.#focus());
53676
53684
  }
53677
- #refuse(text4, field2 = null, focus = false) {
53685
+ #refuse(text4, field3 = null, focus = false) {
53678
53686
  this.problem = text4;
53679
- this.invalid = text4 ? field2 : null;
53680
- if (focus && text4 && field2) void this.updateComplete.then(() => this.#field(field2)?.focus());
53687
+ this.invalid = text4 ? field3 : null;
53688
+ if (focus && text4 && field3) void this.updateComplete.then(() => this.#field(field3)?.focus());
53681
53689
  }
53682
53690
  #typed() {
53683
53691
  this.invalid = null;
53684
53692
  }
53685
- #bad(field2) {
53686
- return this.invalid === field2 ? "true" : A;
53693
+ #bad(field3) {
53694
+ return this.invalid === field3 ? "true" : A;
53687
53695
  }
53688
- #described(field2) {
53689
- return this.invalid === field2 ? "error-form" : A;
53696
+ #described(field3) {
53697
+ return this.invalid === field3 ? "error-form" : A;
53690
53698
  }
53691
53699
  #focus() {
53692
53700
  this.renderRoot.querySelector("[data-form] input, [data-form] sp-picker")?.focus();
@@ -53924,8 +53932,8 @@ var SliccSecrets = class extends ThemedElement {
53924
53932
  event2.preventDefault();
53925
53933
  if (!locked && !this.busy) void run();
53926
53934
  }
53927
- #value(label, field2 = "value") {
53928
- return b`<label class="field"><span>${label}</span><input type="password" autocomplete="off" spellcheck="false" data-field=${field2} aria-invalid=${this.#bad(field2)} aria-describedby=${this.#described(field2)} /></label>`;
53935
+ #value(label, field3 = "value") {
53936
+ return b`<label class="field"><span>${label}</span><input type="password" autocomplete="off" spellcheck="false" data-field=${field3} aria-invalid=${this.#bad(field3)} aria-describedby=${this.#described(field3)} /></label>`;
53929
53937
  }
53930
53938
  #actions(locked, label, action, run) {
53931
53939
  return b`<div class="buttons">
@@ -54979,13 +54987,13 @@ var SliccSettings = class extends ThemedElement {
54979
54987
  });
54980
54988
  }
54981
54989
  #settingsOf(account, fields) {
54982
- const settable = (account.fields ?? []).filter((field2) => field2.vaultSetting);
54990
+ const settable = (account.fields ?? []).filter((field3) => field3.vaultSetting);
54983
54991
  if (account.group === "mcp" || !settable.length) return void 0;
54984
54992
  return Object.fromEntries(
54985
- settable.flatMap((field2) => {
54986
- const value = fields?.[field2.name];
54987
- if (!value || field2.customBase && this.#baseOf(value)) return [];
54988
- return [[field2.vaultSetting, value]];
54993
+ settable.flatMap((field3) => {
54994
+ const value = fields?.[field3.name];
54995
+ if (!value || field3.customBase && this.#baseOf(value)) return [];
54996
+ return [[field3.vaultSetting, value]];
54989
54997
  })
54990
54998
  );
54991
54999
  }
@@ -54998,17 +55006,17 @@ var SliccSettings = class extends ThemedElement {
54998
55006
  #keyOptional(account) {
54999
55007
  const vault = this.#vault(account);
55000
55008
  const fields = account.fields ?? [];
55001
- if (!vault || !fields.some((field2) => field2.vaultSetting || field2.customBase)) return false;
55002
- if (fields.some((field2) => field2.vaultSetting) && !vault.settings) return false;
55009
+ if (!vault || !fields.some((field3) => field3.vaultSetting || field3.customBase)) return false;
55010
+ if (fields.some((field3) => field3.vaultSetting) && !vault.settings) return false;
55003
55011
  return !!this.#record(account);
55004
55012
  }
55005
55013
  #refused(account, message, keyed2) {
55006
- const field2 = (account.fields ?? []).find(
55014
+ const field3 = (account.fields ?? []).find(
55007
55015
  (candidate) => [candidate.vaultSetting, candidate.name, candidate.label].some(
55008
55016
  (word2) => word2 && words(message, word2)
55009
55017
  )
55010
55018
  );
55011
- if (field2) this.#refuse(account.id, field2.name, message);
55019
+ if (field3) this.#refuse(account.id, field3.name, message);
55012
55020
  else if (keyed2) this.#refuse(account.id, "value", message);
55013
55021
  else this.failure = { id: account.id, message };
55014
55022
  }
@@ -55020,14 +55028,14 @@ var SliccSettings = class extends ThemedElement {
55020
55028
  return void 0;
55021
55029
  }
55022
55030
  }
55023
- #oldBase(account, field2) {
55024
- return this.#baseOf(field2.value) ?? this.#bases.get(`${account.id} ${field2.name}`);
55031
+ #oldBase(account, field3) {
55032
+ return this.#baseOf(field3.value) ?? this.#bases.get(`${account.id} ${field3.name}`);
55025
55033
  }
55026
55034
  #baseChanges(account, fields) {
55027
- return (account.fields ?? []).filter((field2) => field2.customBase).map((field2) => ({
55028
- field: field2.name,
55029
- url: this.#baseOf(fields?.[field2.name]),
55030
- old: this.#oldBase(account, field2)
55035
+ return (account.fields ?? []).filter((field3) => field3.customBase).map((field3) => ({
55036
+ field: field3.name,
55037
+ url: this.#baseOf(fields?.[field3.name]),
55038
+ old: this.#oldBase(account, field3)
55031
55039
  })).filter((change) => change.url !== change.old);
55032
55040
  }
55033
55041
  #modelChange(name, changes2, from, to) {
@@ -55053,8 +55061,8 @@ var SliccSettings = class extends ThemedElement {
55053
55061
  await live?.endpoints?.(forward);
55054
55062
  } catch (error) {
55055
55063
  this.#busy(id, false);
55056
- const field2 = changes2.find((change) => change.url) ?? changes2[0];
55057
- if (this.model === model) this.#refuse(id, field2.field, failureText(error));
55064
+ const field3 = changes2.find((change) => change.url) ?? changes2[0];
55065
+ if (this.model === model) this.#refuse(id, field3.field, failureText(error));
55058
55066
  return;
55059
55067
  }
55060
55068
  if (this.model !== model) {
@@ -55078,35 +55086,35 @@ var SliccSettings = class extends ThemedElement {
55078
55086
  }
55079
55087
  #placeFailure(account, fields) {
55080
55088
  const message = this.failure.message;
55081
- const field2 = (account.fields ?? []).find(
55089
+ const field3 = (account.fields ?? []).find(
55082
55090
  (candidate) => candidate.customBase && !!fields?.[candidate.name] && [candidate.name, candidate.label, "https", "url", "port", "userinfo"].some(
55083
55091
  (word2) => words(message, word2)
55084
55092
  )
55085
55093
  );
55086
- if (!field2) return;
55094
+ if (!field3) return;
55087
55095
  this.failure = null;
55088
- this.#refuse(account.id, field2.name, message);
55096
+ this.#refuse(account.id, field3.name, message);
55089
55097
  }
55090
- #refuse(id, field2, message) {
55091
- this.problem = { id, field: field2, message };
55098
+ #refuse(id, field3, message) {
55099
+ this.problem = { id, field: field3, message };
55092
55100
  void this.updateComplete.then(
55093
55101
  () => this.renderRoot.querySelector(
55094
- field2 === "value" ? ".key input[data-field=value]" : `.key [data-account-field="${field2}"]`
55102
+ field3 === "value" ? ".key input[data-field=value]" : `.key [data-account-field="${field3}"]`
55095
55103
  )?.focus()
55096
55104
  );
55097
55105
  }
55098
55106
  #fields(form, account) {
55099
55107
  if (!account.fields?.length) return void 0;
55100
55108
  const values = {};
55101
- for (const field2 of account.fields) {
55102
- const input = form.querySelector(`[data-account-field="${field2.name}"]`);
55109
+ for (const field3 of account.fields) {
55110
+ const input = form.querySelector(`[data-account-field="${field3.name}"]`);
55103
55111
  const value = input.value.trim();
55104
- if (value) values[field2.name] = value;
55105
- else if (field2.required && field2.options?.length !== 0) {
55112
+ if (value) values[field3.name] = value;
55113
+ else if (field3.required && field3.options?.length !== 0) {
55106
55114
  this.#refuse(
55107
55115
  account.id,
55108
- field2.name,
55109
- field2.options ? `Select a ${field2.label.toLowerCase()}.` : `${field2.label} can\u2019t be empty`
55116
+ field3.name,
55117
+ field3.options ? `Select a ${field3.label.toLowerCase()}.` : `${field3.label} can\u2019t be empty`
55110
55118
  );
55111
55119
  return null;
55112
55120
  }
@@ -55149,7 +55157,7 @@ var SliccSettings = class extends ThemedElement {
55149
55157
  this.failure = null;
55150
55158
  this.problem = null;
55151
55159
  this.filled = new Set(
55152
- (account.fields ?? []).filter((field2) => field2.options || field2.value?.trim()).map((field2) => field2.name)
55160
+ (account.fields ?? []).filter((field3) => field3.options || field3.value?.trim()).map((field3) => field3.name)
55153
55161
  );
55154
55162
  this.entering = account.id;
55155
55163
  void this.updateComplete.then(() => this.focusOn(".key sp-textfield", ".key input"));
@@ -55171,9 +55179,9 @@ var SliccSettings = class extends ThemedElement {
55171
55179
  if (fields2 !== null && !this.pending.has(account.id)) void this.keep(account, value, fields2);
55172
55180
  return;
55173
55181
  }
55174
- const field2 = form.querySelector("sp-textfield");
55175
- const secret = field2.value.trim();
55176
- field2.value = "";
55182
+ const field3 = form.querySelector("sp-textfield");
55183
+ const secret = field3.value.trim();
55184
+ field3.value = "";
55177
55185
  const fields = this.#fields(form, account);
55178
55186
  if (secret && fields !== null) void this.#connectBases(account, secret, fields);
55179
55187
  }
@@ -55256,67 +55264,67 @@ var SliccSettings = class extends ThemedElement {
55256
55264
  this.failure = null;
55257
55265
  this.problem = null;
55258
55266
  }
55259
- #problem(account, field2, icon = true) {
55267
+ #problem(account, field3, icon = true) {
55260
55268
  const problem = this.problem;
55261
- if (problem?.id !== account.id || problem.field !== field2) return A;
55269
+ if (problem?.id !== account.id || problem.field !== field3) return A;
55262
55270
  return b`<div class="problem" id="key-problem" role="alert">
55263
55271
  ${icon ? b`<swc-icon-alert-triangle size="s" aria-hidden="true"></swc-icon-alert-triangle>` : A}
55264
55272
  <span>${problem.message}</span>
55265
55273
  </div>`;
55266
55274
  }
55267
- #described(account, field2) {
55268
- return this.problem?.id === account.id && this.problem.field === field2 ? "key-problem" : A;
55275
+ #described(account, field3) {
55276
+ return this.problem?.id === account.id && this.problem.field === field3 ? "key-problem" : A;
55269
55277
  }
55270
- #invalid(account, field2) {
55271
- return this.#described(account, field2) === A ? A : "true";
55278
+ #invalid(account, field3) {
55279
+ return this.#described(account, field3) === A ? A : "true";
55272
55280
  }
55273
55281
  #extra(account) {
55274
55282
  return (account.fields ?? []).map(
55275
- (field2) => field2.options ? b`<div class="field">
55276
- <sp-field-label for=${`field-${field2.name}`} size="m">${field2.label}</sp-field-label>${this.#control(account, field2)}
55277
- ${field2.options.length ? A : b`<p class="hint" data-empty=${field2.name}>${nothingToChoose}</p>`}
55278
- ${field2.help ? b`<p class="hint" id=${`help-${field2.name}`}>${field2.help}</p>` : A}
55279
- ${this.#problem(account, field2.name, false)}
55283
+ (field3) => field3.options ? b`<div class="field">
55284
+ <sp-field-label for=${`field-${field3.name}`} size="m">${field3.label}</sp-field-label>${this.#control(account, field3)}
55285
+ ${field3.options.length ? A : b`<p class="hint" data-empty=${field3.name}>${nothingToChoose}</p>`}
55286
+ ${field3.help ? b`<p class="hint" id=${`help-${field3.name}`}>${field3.help}</p>` : A}
55287
+ ${this.#problem(account, field3.name, false)}
55280
55288
  </div>` : b`<label class="field">
55281
- <span>${field2.label}</span>${this.#control(account, field2)}
55289
+ <span>${field3.label}</span>${this.#control(account, field3)}
55282
55290
  </label>
55283
- ${field2.help ? b`<p class="hint" id=${`help-${field2.name}`}>${field2.help}</p>` : A}
55284
- ${this.#problem(account, field2.name)}`
55291
+ ${field3.help ? b`<p class="hint" id=${`help-${field3.name}`}>${field3.help}</p>` : A}
55292
+ ${this.#problem(account, field3.name)}`
55285
55293
  );
55286
55294
  }
55287
- #describedBy(account, field2) {
55288
- const problem = this.#described(account, field2.name);
55289
- const ids = [problem === A ? "" : problem, field2.help ? `help-${field2.name}` : ""];
55295
+ #describedBy(account, field3) {
55296
+ const problem = this.#described(account, field3.name);
55297
+ const ids = [problem === A ? "" : problem, field3.help ? `help-${field3.name}` : ""];
55290
55298
  return ids.filter(Boolean).join(" ") || A;
55291
55299
  }
55292
- #control(account, field2) {
55293
- if (field2.options) {
55294
- const empty4 = !field2.options.length;
55295
- const described2 = this.problem?.id === account.id && this.problem.field === field2.name;
55300
+ #control(account, field3) {
55301
+ if (field3.options) {
55302
+ const empty4 = !field3.options.length;
55303
+ const described2 = this.problem?.id === account.id && this.problem.field === field3.name;
55296
55304
  return b`<sp-picker
55297
55305
  size="m"
55298
- data-account-field=${field2.name}
55299
- label=${empty4 ? "None available" : field2.label}
55300
- id=${`field-${field2.name}`}
55301
- value=${start(field2.options, field2.value)}
55306
+ data-account-field=${field3.name}
55307
+ label=${empty4 ? "None available" : field3.label}
55308
+ id=${`field-${field3.name}`}
55309
+ value=${start(field3.options, field3.value)}
55302
55310
  ?disabled=${empty4}
55303
55311
  ?invalid=${described2}
55304
- aria-required=${field2.required ? "true" : A}
55312
+ aria-required=${field3.required ? "true" : A}
55305
55313
  >
55306
- ${field2.options.map((option) => b`<sp-menu-item value=${option.value}>${option.label}</sp-menu-item>`)}
55307
- ${described2 || empty4 || field2.help ? b`<span slot="description" class="sr">${described2 ? this.problem?.message : empty4 ? nothingToChoose : field2.help}</span>` : A}
55314
+ ${field3.options.map((option) => b`<sp-menu-item value=${option.value}>${option.label}</sp-menu-item>`)}
55315
+ ${described2 || empty4 || field3.help ? b`<span slot="description" class="sr">${described2 ? this.problem?.message : empty4 ? nothingToChoose : field3.help}</span>` : A}
55308
55316
  </sp-picker>`;
55309
55317
  }
55310
55318
  return b`<input
55311
55319
  type="text"
55312
55320
  autocomplete="off"
55313
55321
  spellcheck="false"
55314
- data-account-field=${field2.name}
55315
- value=${field2.value ?? A}
55316
- placeholder=${field2.placeholder ?? A}
55317
- aria-required=${field2.required ? "true" : A}
55318
- aria-invalid=${this.#invalid(account, field2.name)}
55319
- aria-describedby=${this.#describedBy(account, field2)}
55322
+ data-account-field=${field3.name}
55323
+ value=${field3.value ?? A}
55324
+ placeholder=${field3.placeholder ?? A}
55325
+ aria-required=${field3.required ? "true" : A}
55326
+ aria-invalid=${this.#invalid(account, field3.name)}
55327
+ aria-describedby=${this.#describedBy(account, field3)}
55320
55328
  />`;
55321
55329
  }
55322
55330
  #getKey(account) {
@@ -55334,9 +55342,9 @@ var SliccSettings = class extends ThemedElement {
55334
55342
  #ready(account) {
55335
55343
  if (account.blocked) return false;
55336
55344
  if (!this.#offered()) return true;
55337
- const required = (account.fields ?? []).filter((field2) => field2.required && !field2.options);
55345
+ const required = (account.fields ?? []).filter((field3) => field3.required && !field3.options);
55338
55346
  const key = this.#keyOptional(account) ? [] : ["value"];
55339
- return [...key, ...required.map((field2) => field2.name)].every((name) => this.filled.has(name));
55347
+ return [...key, ...required.map((field3) => field3.name)].every((name) => this.filled.has(name));
55340
55348
  }
55341
55349
  #fill(event2) {
55342
55350
  const input = event2.target;
@@ -55530,7 +55538,7 @@ var SliccSettings = class extends ThemedElement {
55530
55538
  const status2 = this.#status(account);
55531
55539
  const [variant, generic] = accountStatus[status2];
55532
55540
  const label = status2 === "rejected" ? rejectedNames[account.secret ?? "api-key"] : generic;
55533
- const failure2 = this.failure?.id === account.id ? b`<div class="failure" role="alert">
55541
+ const failure3 = this.failure?.id === account.id ? b`<div class="failure" role="alert">
55534
55542
  <swc-icon-alert-triangle size="s" aria-hidden="true"></swc-icon-alert-triangle>
55535
55543
  <span>${this.failure.message}</span>
55536
55544
  </div>` : A;
@@ -55542,7 +55550,7 @@ var SliccSettings = class extends ThemedElement {
55542
55550
  </div>
55543
55551
  ${this.#rowNotes(account)}
55544
55552
  ${this.#movedNote(account)}
55545
- ${this.adding?.id === account.id ? A : b`${this.#key(account)}${this.#otherKey(account)}${failure2}`}`;
55553
+ ${this.adding?.id === account.id ? A : b`${this.#key(account)}${this.#otherKey(account)}${failure3}`}`;
55546
55554
  }
55547
55555
  #refusedNote(account) {
55548
55556
  if (account.state !== "refused") return A;
@@ -55624,7 +55632,7 @@ var SliccSettings = class extends ThemedElement {
55624
55632
  this.#busy(account.id, false);
55625
55633
  }
55626
55634
  this.focusOn("[data-action=add-provider]");
55627
- for (const field2 of account.fields ?? []) this.#bases.delete(`${account.id} ${field2.name}`);
55635
+ for (const field3 of account.fields ?? []) this.#bases.delete(`${account.id} ${field3.name}`);
55628
55636
  }
55629
55637
  #heldRecords(account, vault) {
55630
55638
  const server = serverOf(account);
@@ -55735,7 +55743,7 @@ var SliccSettings = class extends ThemedElement {
55735
55743
  event2.preventDefault();
55736
55744
  if (this.serverBusy) return;
55737
55745
  const form = event2.currentTarget;
55738
- const text4 = (field2) => form.querySelector(`[data-server-field=${field2}]`)?.value.trim();
55746
+ const text4 = (field3) => form.querySelector(`[data-server-field=${field3}]`)?.value.trim();
55739
55747
  const name = text4("name");
55740
55748
  const url = text4("url");
55741
55749
  const problem = this.#checkServer(name, url);
@@ -55764,21 +55772,21 @@ var SliccSettings = class extends ThemedElement {
55764
55772
  this.serverProblem = problem;
55765
55773
  if (problem.field !== "form") this.focusOn(`[data-server-field=${problem.field}]`);
55766
55774
  }
55767
- #serverNote(field2) {
55768
- if (this.serverProblem?.field !== field2) return A;
55769
- return b`<div class="problem" id=${`server-${field2}-problem`} role="alert" data-problem=${field2}>
55775
+ #serverNote(field3) {
55776
+ if (this.serverProblem?.field !== field3) return A;
55777
+ return b`<div class="problem" id=${`server-${field3}-problem`} role="alert" data-problem=${field3}>
55770
55778
  <swc-icon-alert-triangle size="s" aria-hidden="true"></swc-icon-alert-triangle>
55771
55779
  <span>${this.serverProblem.message}</span>
55772
55780
  </div>`;
55773
55781
  }
55774
- #serverInput(field2, type, help2) {
55775
- const invalid = this.serverProblem?.field === field2;
55776
- const problem = invalid ? `server-${field2}-problem ` : "";
55782
+ #serverInput(field3, type, help2) {
55783
+ const invalid = this.serverProblem?.field === field3;
55784
+ const problem = invalid ? `server-${field3}-problem ` : "";
55777
55785
  return b`<input
55778
55786
  type=${type}
55779
55787
  autocomplete="off"
55780
55788
  spellcheck="false"
55781
- data-server-field=${field2}
55789
+ data-server-field=${field3}
55782
55790
  aria-required="true"
55783
55791
  aria-invalid=${invalid ? "true" : A}
55784
55792
  aria-describedby=${`${problem}${help2}`}
@@ -55875,8 +55883,8 @@ var SliccSettings = class extends ThemedElement {
55875
55883
  const dialog = this.#dialog;
55876
55884
  if (!changed2.has("picking") || !dialog || dialog.open) return;
55877
55885
  dialog.showModal();
55878
- const field2 = this.renderRoot.querySelector("sp-search");
55879
- void field2.updateComplete.then(() => field2.focus());
55886
+ const field3 = this.renderRoot.querySelector("sp-search");
55887
+ void field3.updateComplete.then(() => field3.focus());
55880
55888
  }
55881
55889
  get #dialog() {
55882
55890
  return this.renderRoot.querySelector("dialog.picker");
@@ -56233,13 +56241,197 @@ var bridge = `(() => {
56233
56241
  face.load().then(size, () => {});
56234
56242
  }
56235
56243
  };
56244
+ const runs = new Map();
56236
56245
  addEventListener('message', (event) => {
56237
56246
  if (event.source !== parent) return;
56238
56247
  const message = event.data || {};
56239
56248
  if (message.type === 'slicc-icons') swap(message.icons);
56240
56249
  if (message.type === 'slicc-fonts') fonts(message.fonts);
56241
56250
  if (message.type === 'slicc-theme') document.documentElement.classList.toggle('theme-light', message.color === 'light');
56251
+ const run = runs.get(message.id);
56252
+ if (run && message.type === 'slicc-cgi-head') run.head(message);
56253
+ if (run && message.type === 'slicc-cgi-chunk') run.chunk(message);
56242
56254
  });
56255
+ const native = window.fetch;
56256
+ const tag = Math.random().toString(36).slice(2);
56257
+ let count = 0;
56258
+ const empty = new Set([101, 103, 204, 205, 304]);
56259
+ const moved = new Set([301, 302, 303, 307, 308]);
56260
+ const decode = (text) => Uint8Array.from(atob(text || ''), (char) => char.charCodeAt(0));
56261
+ const encode = (bytes) => {
56262
+ let text = '';
56263
+ for (let at = 0; at < bytes.length; at += 32768) text += String.fromCharCode(...bytes.subarray(at, at + 32768));
56264
+ return btoa(text);
56265
+ };
56266
+ const scope = (input) => {
56267
+ try {
56268
+ const href = input instanceof Request ? input.url : new URL(input, document.baseURI).href;
56269
+ const base = new URL('cgi-bin/', document.baseURI);
56270
+ return href.startsWith(base.href) ? base : null;
56271
+ } catch {
56272
+ return null;
56273
+ }
56274
+ };
56275
+ const send = (input, init, hops) => {
56276
+ const base = scope(input);
56277
+ if (!base) return native.call(window, input, init);
56278
+ let request;
56279
+ try {
56280
+ request = new Request(input, init);
56281
+ } catch (error) {
56282
+ return Promise.reject(error);
56283
+ }
56284
+ const payload = request.body ? request.arrayBuffer() : Promise.resolve(null);
56285
+ return payload.then((bytes) => exchange(request, base, bytes, hops));
56286
+ };
56287
+ const redirect = (request, payload, status, location, hops) => {
56288
+ if (request.redirect === 'error') throw new TypeError('fetch: the response redirects and redirect is error');
56289
+ if (hops >= 20) throw new TypeError('fetch: more than 20 redirects');
56290
+ const get = (status === 303 && request.method !== 'GET' && request.method !== 'HEAD') || ((status === 301 || status === 302) && request.method === 'POST');
56291
+ const headers = new Headers(request.headers);
56292
+ if (get) for (const name of ['content-encoding', 'content-language', 'content-location', 'content-type']) headers.delete(name);
56293
+ const init = { method: get ? 'GET' : request.method, headers, body: get ? null : payload, signal: request.signal, redirect: request.redirect };
56294
+ return send(new URL(location, request.url).href, init, hops + 1).then((response) => Object.defineProperty(response, 'redirected', { value: true }));
56295
+ };
56296
+ const exchange = (request, base, payload, hops) => new Promise((resolve, reject) => {
56297
+ const { signal } = request;
56298
+ if (signal.aborted) return reject(signal.reason);
56299
+ const id = tag + ':' + ++count;
56300
+ const url = new URL(request.url);
56301
+ const headers = new Headers(request.headers);
56302
+ if (!headers.has('accept')) headers.set('accept', '*/*');
56303
+ const language = navigator.languages.join(',') || navigator.language;
56304
+ if (language && !headers.has('accept-language')) headers.set('accept-language', language);
56305
+ let stream = null;
56306
+ const finish = () => {
56307
+ runs.delete(id);
56308
+ signal.removeEventListener('abort', abort);
56309
+ };
56310
+ const close = () => {
56311
+ finish();
56312
+ post({ type: 'slicc-cgi-close', id });
56313
+ };
56314
+ const abort = () => {
56315
+ close();
56316
+ reject(signal.reason);
56317
+ if (stream) stream.error(signal.reason);
56318
+ };
56319
+ signal.addEventListener('abort', abort);
56320
+ runs.set(id, {
56321
+ head(message) {
56322
+ if (typeof message.error === 'string') {
56323
+ finish();
56324
+ return reject(new TypeError(message.error));
56325
+ }
56326
+ const head = message.head;
56327
+ let response;
56328
+ let follow = false;
56329
+ try {
56330
+ const fields = new Headers(head.headers);
56331
+ follow = moved.has(head.status) && fields.has('location') && request.redirect !== 'manual';
56332
+ const drop = follow || request.method === 'HEAD' || empty.has(head.status);
56333
+ const body = drop ? null : new ReadableStream({
56334
+ start(controller) {
56335
+ const first = decode(head.body);
56336
+ if (first.length) controller.enqueue(first);
56337
+ if (head.done) controller.close();
56338
+ else stream = controller;
56339
+ },
56340
+ cancel() {
56341
+ if (runs.has(id)) close();
56342
+ },
56343
+ });
56344
+ response = new Response(body, { status: head.status, statusText: head.statusText, headers: fields });
56345
+ } catch (error) {
56346
+ close();
56347
+ return reject(new TypeError(error.message));
56348
+ }
56349
+ if (head.done) finish();
56350
+ url.hash = '';
56351
+ Object.defineProperty(response, 'url', { value: url.href });
56352
+ if (!follow) return resolve(response);
56353
+ try {
56354
+ resolve(redirect(request, payload, head.status, response.headers.get('location'), hops));
56355
+ } catch (error) {
56356
+ reject(error);
56357
+ }
56358
+ },
56359
+ chunk(message) {
56360
+ if (typeof message.error === 'string') {
56361
+ finish();
56362
+ if (stream) stream.error(new TypeError(message.error));
56363
+ return;
56364
+ }
56365
+ const bytes = decode(message.body);
56366
+ if (stream && bytes.length) stream.enqueue(bytes);
56367
+ if (!message.done) return;
56368
+ finish();
56369
+ if (stream) stream.close();
56370
+ },
56371
+ });
56372
+ post({
56373
+ type: 'slicc-cgi',
56374
+ id,
56375
+ request: {
56376
+ method: request.method,
56377
+ path: url.pathname.slice(base.pathname.length),
56378
+ query: url.search.slice(1),
56379
+ headers: [...headers],
56380
+ body: payload && payload.byteLength ? encode(new Uint8Array(payload)) : null,
56381
+ },
56382
+ });
56383
+ });
56384
+ window.fetch = function fetch(input, init) {
56385
+ return send(input, init, 0);
56386
+ };
56387
+ const formOf = (form, submitter) => {
56388
+ const own = (name) => !!submitter && submitter.hasAttribute('form' + name);
56389
+ return {
56390
+ action: (own('action') ? submitter.getAttribute('formaction') : form.getAttribute('action')) || '',
56391
+ method: own('method') ? submitter.formMethod : form.method,
56392
+ enctype: own('enctype') ? submitter.formEnctype : form.enctype,
56393
+ };
56394
+ };
56395
+ const submitted = (form, submitter) => {
56396
+ const { action, method, enctype } = formOf(form, submitter);
56397
+ if (!action || !scope(action)) return;
56398
+ const url = new URL(action, document.baseURI);
56399
+ const data = new FormData(form, submitter || null);
56400
+ const entries = [...data].map(([name, value]) => [name, typeof value === 'string' ? value : value.name]);
56401
+ const init = { method: method === 'post' ? 'POST' : 'GET', redirect: 'manual', headers: {} };
56402
+ if (init.method === 'GET') url.search = new URLSearchParams(entries).toString();
56403
+ else if (enctype === 'multipart/form-data') init.body = data;
56404
+ else if (enctype === 'text/plain') {
56405
+ init.body = entries.map(([name, value]) => name + '=' + value + '\\r\\n').join('');
56406
+ init.headers['content-type'] = 'text/plain';
56407
+ } else {
56408
+ init.body = new URLSearchParams(entries).toString();
56409
+ init.headers['content-type'] = 'application/x-www-form-urlencoded';
56410
+ }
56411
+ const tell = (detail) => form.dispatchEvent(new CustomEvent('slicc-cgi', { bubbles: true, cancelable: true, detail }));
56412
+ send(url.href, init, 0).then(
56413
+ (response) => {
56414
+ if (tell({ response }) && response.headers.has('location')) post({ type: 'slicc-reload' });
56415
+ },
56416
+ (error) => tell({ error }),
56417
+ );
56418
+ };
56419
+ const copies = new WeakSet();
56420
+ addEventListener('submit', (event) => {
56421
+ if (copies.has(event)) return;
56422
+ const form = event.composedPath()[0];
56423
+ if (!(form instanceof HTMLFormElement) || formOf(form, event.submitter).method === 'dialog') return;
56424
+ event.preventDefault();
56425
+ event.stopImmediatePropagation();
56426
+ const copy = new SubmitEvent('submit', { bubbles: true, cancelable: true, submitter: event.submitter });
56427
+ copies.add(copy);
56428
+ if (form.dispatchEvent(copy)) submitted(form, event.submitter);
56429
+ }, true);
56430
+ const submit = HTMLFormElement.prototype.submit;
56431
+ HTMLFormElement.prototype.submit = function () {
56432
+ if (formOf(this, null).method === 'dialog') return submit.call(this);
56433
+ submitted(this, null);
56434
+ };
56243
56435
  const size = () => {
56244
56436
  const style = getComputedStyle(document.body);
56245
56437
  post({ type: 'slicc-size', height: Math.ceil(document.body.offsetHeight + parseFloat(style.marginTop) + parseFloat(style.marginBottom)) });
@@ -56332,12 +56524,47 @@ async function frameFonts(files, base) {
56332
56524
  (font) => Boolean(font.data)
56333
56525
  );
56334
56526
  }
56527
+ var cgiMethods = /* @__PURE__ */ new Set([
56528
+ "cgi",
56529
+ "cgiRead",
56530
+ "cgiClose"
56531
+ ]);
56335
56532
  var sprinkleMethods = /* @__PURE__ */ new Set([
56336
56533
  "readFile",
56337
56534
  "exists",
56338
56535
  "getState",
56339
- "setState"
56536
+ "setState",
56537
+ ...cgiMethods
56340
56538
  ]);
56539
+ var field2 = (value) => typeof value === "string" ? value : "";
56540
+ function cgiRequest(value) {
56541
+ const given = value ?? {};
56542
+ const headers = (Array.isArray(given.headers) ? given.headers : []).filter(
56543
+ (pair) => Array.isArray(pair) && typeof pair[0] === "string" && typeof pair[1] === "string"
56544
+ ).map(([name, text4]) => [name, text4]);
56545
+ return {
56546
+ method: field2(given.method) || "GET",
56547
+ path: field2(given.path),
56548
+ query: field2(given.query),
56549
+ headers,
56550
+ body: field2(given.body) || null
56551
+ };
56552
+ }
56553
+ function cgiRefusal(status2, text4) {
56554
+ return {
56555
+ status: status2,
56556
+ statusText: status2 === 403 ? "Forbidden" : "Not Found",
56557
+ headers: [["Content-Type", "text/plain; charset=utf-8"]],
56558
+ body: btoa(`${text4}
56559
+ `),
56560
+ done: true,
56561
+ stream: null
56562
+ };
56563
+ }
56564
+ var cgiGuest = "A guest seat has no cgi-bin/.";
56565
+ var cgiReadOnly = "This sprinkle is read-only here, so its cgi-bin/ only answers GET and HEAD.";
56566
+ var cgiMissing = "This sprinkle has no cgi-bin/ here.";
56567
+ var failure2 = (error) => error instanceof Error ? error.message : String(error);
56341
56568
  var grip = w`<svg class="grip" viewBox="0 0 8 14" width="8" height="14" aria-hidden="true">${[2, 7, 12].flatMap((y8) => [2, 6].map((x5) => w`<circle cx=${x5} cy=${y8} r="1.25"></circle>`))}</svg>`;
56342
56569
  var plainId = (id) => id.replace(/^cone:/, "");
56343
56570
  var SliccSprinkle = class extends ThemedElement {
@@ -56477,8 +56704,75 @@ var SliccSprinkle = class extends ThemedElement {
56477
56704
  this.height = data.height;
56478
56705
  } else if (data.type === "slicc-call") {
56479
56706
  await this.#call(source, data);
56707
+ } else if (data.type === "slicc-cgi") {
56708
+ await this.#cgi(source, data);
56709
+ } else if (data.type === "slicc-cgi-close") {
56710
+ this.#close(data.id);
56711
+ } else if (data.type === "slicc-reload") {
56712
+ this.#reload();
56480
56713
  }
56481
56714
  };
56715
+ #runs = /* @__PURE__ */ new Map();
56716
+ #refusal(method) {
56717
+ if (this.model?.seat) return cgiRefusal(403, cgiGuest);
56718
+ const reading = ["GET", "HEAD"].includes(method.toUpperCase());
56719
+ if (!reading && this.#readOnly()) return cgiRefusal(403, cgiReadOnly);
56720
+ return void 0;
56721
+ }
56722
+ async #cgi(source, data) {
56723
+ if (typeof data.id !== "string") return;
56724
+ const id = data.id;
56725
+ const post2 = (message) => source.postMessage({ ...message, id }, "*");
56726
+ const request2 = cgiRequest(data.request);
56727
+ const port = this.model?.sprinkles;
56728
+ const call = port?.call?.bind(port);
56729
+ const refused3 = this.#refusal(request2.method);
56730
+ if (refused3 || !call)
56731
+ return post2({ type: "slicc-cgi-head", head: refused3 ?? cgiRefusal(404, cgiMissing) });
56732
+ const run = { call, sprinkle: this.sprinkle, stream: null, closed: false };
56733
+ this.#runs.set(id, run);
56734
+ let headed = false;
56735
+ try {
56736
+ const head = await call(run.sprinkle, "cgi", [request2]);
56737
+ let done2 = head.done || !head.stream;
56738
+ run.stream = done2 ? null : head.stream;
56739
+ if (run.closed) return this.#shut(run);
56740
+ headed = true;
56741
+ const { status: status2, statusText, headers, body: body2 } = head;
56742
+ post2({ type: "slicc-cgi-head", head: { status: status2, statusText, headers, body: body2, done: done2 } });
56743
+ while (!done2) {
56744
+ const chunk = await call(run.sprinkle, "cgiRead", [run.stream]);
56745
+ if (run.closed) return;
56746
+ done2 = chunk.done;
56747
+ post2({ type: "slicc-cgi-chunk", body: chunk.body, done: done2 });
56748
+ }
56749
+ } catch (error) {
56750
+ if (!run.closed)
56751
+ post2({ type: headed ? "slicc-cgi-chunk" : "slicc-cgi-head", error: failure2(error) });
56752
+ } finally {
56753
+ if (this.#runs.get(id) === run) this.#runs.delete(id);
56754
+ }
56755
+ }
56756
+ #close(id) {
56757
+ const run = typeof id === "string" ? this.#runs.get(id) : void 0;
56758
+ if (!run) return;
56759
+ this.#runs.delete(id);
56760
+ this.#shut(run);
56761
+ }
56762
+ #shut(run) {
56763
+ run.closed = true;
56764
+ if (run.stream) run.call(run.sprinkle, "cgiClose", [run.stream]).catch(() => void 0);
56765
+ }
56766
+ #closeAll() {
56767
+ for (const run of this.#runs.values()) this.#shut(run);
56768
+ this.#runs.clear();
56769
+ }
56770
+ #reload() {
56771
+ this.#closeAll();
56772
+ this.#frame = { key: "", doc: "" };
56773
+ this.#mounts++;
56774
+ this.requestUpdate();
56775
+ }
56482
56776
  #readOnly() {
56483
56777
  return this.readonly || !!this.model?.seat || this.#frozen() || !!watchOnly(this.model);
56484
56778
  }
@@ -56500,6 +56794,7 @@ var SliccSprinkle = class extends ThemedElement {
56500
56794
  async #call(source, data) {
56501
56795
  const port = this.model?.sprinkles;
56502
56796
  if (!port?.call || typeof data.method !== "string" || !sprinkleMethods.has(data.method)) return;
56797
+ if (cgiMethods.has(data.method)) return;
56503
56798
  const method = data.method;
56504
56799
  if (method === "setState" && this.#readOnly()) {
56505
56800
  source.postMessage({ type: "slicc-result", id: data.id, error: "read-only" }, "*");
@@ -56556,6 +56851,7 @@ var SliccSprinkle = class extends ThemedElement {
56556
56851
  return [
56557
56852
  ...super.subscribe(model),
56558
56853
  () => globalThis.removeEventListener("message", this.#message),
56854
+ () => this.#closeAll(),
56559
56855
  model.sprinkles.on("sprinkles", () => this.requestUpdate()),
56560
56856
  this.#dips.on("change", () => this.requestUpdate()),
56561
56857
  ...onWatch(model, () => this.requestUpdate())
@@ -56609,7 +56905,7 @@ ${data.html}`;
56609
56905
  const style2 = `color-scheme:${this.color};${this.inline ? `height:${this.height}px;` : ""}`;
56610
56906
  const frame = b`${i23(
56611
56907
  this.#mounts,
56612
- b`<iframe title=${data.title} sandbox="allow-scripts" ?inert=${watch2} style=${style2} .srcdoc=${this.#document(data, state2)}></iframe>`
56908
+ b`<iframe title=${data.title} sandbox="allow-scripts allow-forms" ?inert=${watch2} style=${style2} .srcdoc=${this.#document(data, state2)}></iframe>`
56613
56909
  )}`;
56614
56910
  if (!this.inline)
56615
56911
  return watch2 ? b`<div class="panel"><div class="bar">${caption2}</div>${frame}</div>` : frame;
@@ -56892,10 +57188,10 @@ var SliccValueRequest = class extends ThemedElement {
56892
57188
  const bad = nameProblem(name);
56893
57189
  const value = bad ? "" : take(this.#field("value"));
56894
57190
  const text4 = bad ?? valueProblem(value);
56895
- const field2 = bad ? "name" : "value";
56896
- this.problem = text4 ? { id: request2.id, text: text4, field: field2 } : null;
57191
+ const field3 = bad ? "name" : "value";
57192
+ this.problem = text4 ? { id: request2.id, text: text4, field: field3 } : null;
56897
57193
  if (text4) {
56898
- void this.updateComplete.then(() => this.#field(field2)?.focus());
57194
+ void this.updateComplete.then(() => this.#field(field3)?.focus());
56899
57195
  return;
56900
57196
  }
56901
57197
  this.busy = true;
@@ -56905,8 +57201,8 @@ var SliccValueRequest = class extends ThemedElement {
56905
57201
  this.#done.add(request2.id);
56906
57202
  } catch (error) {
56907
57203
  if (this.#mine(vault)) {
56908
- const field3 = fieldOf(error, "value");
56909
- this.problem = { id: request2.id, text: failureText(error), ...field3 ? { field: field3 } : {} };
57204
+ const field4 = fieldOf(error, "value");
57205
+ this.problem = { id: request2.id, text: failureText(error), ...field4 ? { field: field4 } : {} };
56910
57206
  }
56911
57207
  } finally {
56912
57208
  if (this.model?.vault === vault) this.busy = false;
@@ -56915,8 +57211,8 @@ var SliccValueRequest = class extends ThemedElement {
56915
57211
  #typed() {
56916
57212
  if (this.problem?.field) this.problem = { id: this.problem.id, text: this.problem.text };
56917
57213
  }
56918
- #aria(field2, problem) {
56919
- const bad = problem?.field === field2;
57214
+ #aria(field3, problem) {
57215
+ const bad = problem?.field === field3;
56920
57216
  return { invalid: bad ? "true" : A, described: bad ? "error-request" : A };
56921
57217
  }
56922
57218
  async cancelRequest(request2) {
@@ -56987,7 +57283,7 @@ var SliccValueRequest = class extends ThemedElement {
56987
57283
  const shown4 = this.problem?.id === request2.id ? this.problem : null;
56988
57284
  const problem = shown4?.text ?? "";
56989
57285
  const name = this.#aria("name", shown4);
56990
- const field2 = this.#aria("value", shown4);
57286
+ const field3 = this.#aria("value", shown4);
56991
57287
  return i23(
56992
57288
  request2.id,
56993
57289
  b`<dialog role="alertdialog" aria-labelledby="title" aria-describedby="asked" data-request=${request2.id} @cancel=${(event2) => {
@@ -57003,7 +57299,7 @@ var SliccValueRequest = class extends ThemedElement {
57003
57299
  const input = event2.currentTarget;
57004
57300
  input.value = input.value.toUpperCase();
57005
57301
  }} /></label>`}
57006
- <label class="field"><span>Value</span><input type="password" autocomplete="off" spellcheck="false" data-field="value" aria-invalid=${field2.invalid} aria-describedby=${field2.described} /></label>
57302
+ <label class="field"><span>Value</span><input type="password" autocomplete="off" spellcheck="false" data-field="value" aria-invalid=${field3.invalid} aria-describedby=${field3.described} /></label>
57007
57303
  </div>` : A}
57008
57304
  ${locked ? this.#unlock(vault) : A}
57009
57305
  ${problem ? b`<p class="problem" role="alert" id="error-request" data-error><swc-icon-alert-triangle size="s" aria-hidden="true"></swc-icon-alert-triangle><span>${problem}</span></p>` : A}
@@ -71102,10 +71398,10 @@ var ShellManager = class {
71102
71398
  this._shellElement.remove();
71103
71399
  }
71104
71400
  };
71105
- function logFailedPopout(failure2) {
71106
- if (failure2.error) console.error("dockview: failed to create popout.", failure2.error);
71107
- else if (failure2.reason === "blocked") console.error("dockview: failed to create popout. perhaps you need to allow pop-ups for this website");
71108
- else console.error(`dockview: failed to create popout (${failure2.reason}).`);
71401
+ function logFailedPopout(failure3) {
71402
+ if (failure3.error) console.error("dockview: failed to create popout.", failure3.error);
71403
+ else if (failure3.reason === "blocked") console.error("dockview: failed to create popout. perhaps you need to allow pop-ups for this website");
71404
+ else console.error(`dockview: failed to create popout (${failure3.reason}).`);
71109
71405
  }
71110
71406
  function buildTabGroupColorPalette(options2) {
71111
71407
  var _options$tabGroupColo;
@@ -71936,10 +72232,10 @@ var DockviewComponent = class extends BaseGrid {
71936
72232
  return false;
71937
72233
  }
71938
72234
  if (_window.isDisposed) {
71939
- const failure2 = _window.failure;
71940
- if (failure2 && !this.isDisposed) {
71941
- logFailedPopout(failure2);
71942
- this._onDidOpenPopoutWindowFail.fire(failure2);
72235
+ const failure3 = _window.failure;
72236
+ if (failure3 && !this.isDisposed) {
72237
+ logFailedPopout(failure3);
72238
+ this._onDidOpenPopoutWindowFail.fire(failure3);
71943
72239
  }
71944
72240
  return false;
71945
72241
  }
@@ -72132,10 +72428,10 @@ var DockviewComponent = class extends BaseGrid {
72132
72428
  * render nothing and later crash clear()/remove().
72133
72429
  */
72134
72430
  handleBlockedPopout(params) {
72135
- const { group, referenceGroup, options: options2, popoutWindowDisposable, failure: failure2 } = params;
72136
- logFailedPopout(failure2);
72431
+ const { group, referenceGroup, options: options2, popoutWindowDisposable, failure: failure3 } = params;
72432
+ logFailedPopout(failure3);
72137
72433
  popoutWindowDisposable.dispose();
72138
- this._onDidOpenPopoutWindowFail.fire(failure2);
72434
+ this._onDidOpenPopoutWindowFail.fire(failure3);
72139
72435
  if (options2 === null || options2 === void 0 ? void 0 : options2.overridePopoutGridview) {
72140
72436
  const blockedGridview = options2.overridePopoutGridview;
72141
72437
  const members = this.groups.filter((candidate) => blockedGridview.element.contains(candidate.element));