@ai-ecoverse/slicc-spectrum 1.94.2 → 1.96.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.
@@ -6,7 +6,7 @@ import {
6
6
  DummySettings,
7
7
  clock,
8
8
  dummySettingsKey
9
- } from "./chunk-2R4DLSKG.js";
9
+ } from "./chunk-CVMI4FSY.js";
10
10
  import {
11
11
  Emitter
12
12
  } from "./chunk-T5NHW4KC.js";
package/dist/slicc-ui.js CHANGED
@@ -30183,28 +30183,56 @@ function decision(message, handlers, pile) {
30183
30183
  </div>
30184
30184
  </swc-conversation-turn>`;
30185
30185
  }
30186
+ var scoopWords = {
30187
+ completed: "finished",
30188
+ failed: "failed",
30189
+ stopped: "stopped"
30190
+ };
30191
+ var scoopBracket = /^\[(?:scoop |@)[^\]\n]* (completed|failed|stopped)\][^\S\n]*(?:\n|$)/;
30192
+ function scoopLine(message) {
30193
+ const icon = lickIcons[message.channel];
30194
+ const [label] = lickLabels[message.channel];
30195
+ const bracket = message.channel === "scoop-notify" && scoopBracket.exec(message.text);
30196
+ if (!bracket) return [message.text, false, icon, label];
30197
+ const name = message.title.replace(/\s*\([^)]*\)$/, "");
30198
+ const word = scoopWords[bracket[1]];
30199
+ if (bracket[1] === "completed") return [`Scoop ${name} ${word}`, false, icon, label];
30200
+ return [`Scoop ${name} ${word}`, true, "\u274C", `Scoop ${word}`];
30201
+ }
30202
+ function lickBody(message) {
30203
+ return message.channel === "scoop-notify" ? (message.body ?? "").replace(scoopBracket, "").trim() : message.body;
30204
+ }
30205
+ function lickContent(message, body4, handlers) {
30206
+ const scoop = message.channel === "scoop-notify";
30207
+ const report = message.report;
30208
+ if (!scoop && !report) return b`<pre class="output">${body4}</pre>`;
30209
+ const shown4 = !body4 ? A : scoop ? b`<div class="text">${markdown(body4)}</div>` : b`<pre class="output">${body4}</pre>`;
30210
+ return b`<div class="report">${shown4}${report ? b`<swc-button size="s" variant="secondary" fill-style="outline" data-action="open-report" @click=${() => handlers.open(report)}>Open the report</swc-button>` : A}</div>`;
30211
+ }
30186
30212
  function lick(message, handlers, stamp = true, pile = flatPile) {
30187
30213
  if (pendingApproval(message)) return decision(message, handlers, pile);
30188
- const [label] = lickLabels[message.channel];
30214
+ const [line, failed2, icon, label] = scoopLine(message);
30215
+ const severity = message.severity ?? (failed2 ? "error" : void 0);
30189
30216
  const outcome = message.state === "confirmed" ? "Allowed" : message.state === "dismissed" ? "Denied" : "";
30190
- const head2 = b`${message.severity ? b`<span class="sr">${severities[message.severity].prefix}</span>` : A}
30217
+ const head2 = b`${severity ? b`<span class="sr">${severities[severity].prefix}</span>` : A}
30191
30218
  ${outcome ? b`<span class="sr">${outcome}. </span>` : A}
30192
- <span class="text">${message.text}</span>
30219
+ <span class="text" data-summary=${message.summary ? "" : A}>${message.summary || line}</span>
30193
30220
  ${message.count && message.count > 1 ? b`<span class="times" title="Coalesced events">×${message.count}</span>` : A}`;
30194
30221
  const outcomeIcon = message.state === "confirmed" ? "\u{1F44D}" : message.state === "dismissed" ? "\u{1F44E}" : "";
30195
- const reaction = b`<span class="reactions"><span class="reaction" title=${label} aria-hidden="true">${lickIcons[message.channel]}</span>${outcomeIcon ? b`<span class="reaction" title=${outcome} aria-hidden="true">${outcomeIcon}</span>` : A}</span>`;
30196
- const name = `${message.severity ? severities[message.severity].prefix : ""}${label} event`;
30197
- const byline2 = b`<div class="meta">${message.severity ? b`<span class="severity-icon">${severities[message.severity].icon}</span>` : A}<span class="who">${message.title}</span>${stamp ? when(message.createdAt) : unseen(message.createdAt)}</div>`;
30198
- if (!message.body) {
30222
+ const reaction = b`<span class="reactions"><span class="reaction" title=${label} aria-hidden="true">${icon}</span>${outcomeIcon ? b`<span class="reaction" title=${outcome} aria-hidden="true">${outcomeIcon}</span>` : A}</span>`;
30223
+ const name = `${severity ? severities[severity].prefix : ""}${label} event`;
30224
+ const byline2 = b`<div class="meta">${severity ? b`<span class="severity-icon">${severities[severity].icon}</span>` : A}<span class="who">${message.title}</span>${stamp ? when(message.createdAt) : unseen(message.createdAt)}</div>`;
30225
+ const body4 = lickBody(message);
30226
+ if (!body4 && !message.report) {
30199
30227
  return outside(
30200
30228
  name,
30201
30229
  byline2,
30202
- b`<div class="lick-frame"><div class="lick" data-id=${message.id} data-channel=${message.channel} data-severity=${message.severity ?? A}><div class="lick-head">${head2}</div></div>${reaction}</div>`
30230
+ b`<div class="lick-frame"><div class="lick" data-id=${message.id} data-channel=${message.channel} data-severity=${severity ?? A}><div class="lick-head">${head2}</div></div>${reaction}</div>`
30203
30231
  );
30204
30232
  }
30205
- const details = b`<details class="lick" data-id=${message.id} data-channel=${message.channel} data-severity=${message.severity ?? A} ?open=${handlers.licks?.has(message.id) ?? false} @toggle=${handlers.licks?.details(message.id) ?? A}>
30233
+ const details = b`<details class="lick" data-id=${message.id} data-channel=${message.channel} data-severity=${severity ?? A} ?open=${handlers.licks?.has(message.id) ?? false} @toggle=${handlers.licks?.details(message.id) ?? A}>
30206
30234
  <summary class="lick-head">${head2}<swc-icon-chevron-right class="chevron" size="s" aria-hidden="true"></swc-icon-chevron-right></summary>
30207
- <pre class="output">${message.body}</pre>
30235
+ ${lickContent(message, body4, handlers)}
30208
30236
  </details>`;
30209
30237
  return outside(name, byline2, b`<div class="lick-frame">${details}${reaction}</div>`);
30210
30238
  }
@@ -30395,16 +30423,35 @@ var messageCss = i`
30395
30423
  details[open] > summary .chevron {
30396
30424
  transform: rotate(90deg);
30397
30425
  }
30398
- .lick .text,
30426
+ .lick-head .text,
30399
30427
  .runs .label {
30400
30428
  min-inline-size: 0;
30401
30429
  overflow: hidden;
30402
30430
  text-overflow: ellipsis;
30403
30431
  white-space: nowrap;
30404
30432
  }
30405
- .lick .text {
30433
+ .lick-head .text {
30406
30434
  flex: 1;
30407
30435
  }
30436
+ .lick-head .text[data-summary] {
30437
+ white-space: normal;
30438
+ }
30439
+ .lick .report {
30440
+ display: flex;
30441
+ flex-direction: column;
30442
+ align-items: flex-start;
30443
+ gap: var(--swc-spacing-200);
30444
+ padding: var(--swc-spacing-75) var(--swc-spacing-200) var(--swc-spacing-200);
30445
+ overflow-wrap: anywhere;
30446
+ }
30447
+ .lick .report .heading {
30448
+ font-size: inherit;
30449
+ }
30450
+ .lick .report > .text {
30451
+ align-self: stretch;
30452
+ max-block-size: calc(var(--swc-spacing-1000) * 4);
30453
+ overflow: auto;
30454
+ }
30408
30455
  swc-system-message > slicc-tool-runs + slicc-tool-runs {
30409
30456
  margin-block-start: var(--swc-spacing-75);
30410
30457
  }
@@ -49643,7 +49690,8 @@ var accountStatus = {
49643
49690
  "signing-in": ["info", "Signing in\u2026"],
49644
49691
  rejected: ["notice", "Rejected"],
49645
49692
  "needs-sign-in": ["neutral", "Needs sign-in"],
49646
- "sign-in-expired": ["notice", "Sign-in expired"]
49693
+ "sign-in-expired": ["notice", "Sign-in expired"],
49694
+ unreachable: ["notice", "Unreachable"]
49647
49695
  };
49648
49696
  var authHints = {
49649
49697
  "api-key": "API key",
@@ -49677,6 +49725,7 @@ function draft(option2) {
49677
49725
  fields: option2.fields,
49678
49726
  keyUrl: option2.keyUrl,
49679
49727
  needs: option2.needs,
49728
+ blocked: option2.blocked,
49680
49729
  vaultName: option2.vaultName
49681
49730
  };
49682
49731
  }
@@ -49687,6 +49736,23 @@ function matchProviders(options2, query) {
49687
49736
  return words.every((word) => text5.includes(word));
49688
49737
  });
49689
49738
  }
49739
+ var mcpRegistrations = "slicc-spectrum.mcp-endpoints";
49740
+ function registrations2() {
49741
+ try {
49742
+ return JSON.parse(globalThis.localStorage.getItem(mcpRegistrations) ?? "{}") ?? {};
49743
+ } catch {
49744
+ return {};
49745
+ }
49746
+ }
49747
+ function register(server, url) {
49748
+ const all3 = registrations2();
49749
+ if (url) all3[server] = url;
49750
+ else delete all3[server];
49751
+ try {
49752
+ globalThis.localStorage.setItem(mcpRegistrations, JSON.stringify(all3));
49753
+ } catch {
49754
+ }
49755
+ }
49690
49756
  var popup = (account) => account.group === "mcp" && account.auth === "oauth";
49691
49757
  var start = (options2, value) => options2.some((option2) => option2.value === value) ? value : options2[0]?.value ?? "";
49692
49758
  var nothingToChoose = "Nothing to choose from yet. You can connect without it.";
@@ -49716,6 +49782,7 @@ var SliccSettings = class extends ThemedElement {
49716
49782
  };
49717
49783
  #waits = new SignInWaits(() => this.requestUpdate());
49718
49784
  #landing = null;
49785
+ #away = false;
49719
49786
  #bases = /* @__PURE__ */ new Map();
49720
49787
  #scroll = new ViewScroll(this, "settings:scroll", { scroller: () => this, rows: "[data-id]" });
49721
49788
  constructor() {
@@ -49954,6 +50021,10 @@ var SliccSettings = class extends ThemedElement {
49954
50021
  .option[aria-disabled='true'] .name {
49955
50022
  color: var(--swc-neutral-subdued-content-color-default);
49956
50023
  }
50024
+ .option[data-blocked] .name,
50025
+ .option[data-blocked] .description {
50026
+ color: var(--swc-disabled-content-color);
50027
+ }
49957
50028
  .option .tag {
49958
50029
  justify-self: end;
49959
50030
  color: var(--swc-neutral-subdued-content-color-default);
@@ -50052,7 +50123,7 @@ var SliccSettings = class extends ThemedElement {
50052
50123
  model.settings.on("settings", settle2),
50053
50124
  model.settings.on("accounts", settle2),
50054
50125
  model.settings.on("providers", update),
50055
- ...model.vault ? [model.vault.on("status", update)] : []
50126
+ ...model.vault ? [model.vault.on("status", update), model.vault.on("list", update)] : []
50056
50127
  ];
50057
50128
  }
50058
50129
  focus() {
@@ -50123,8 +50194,18 @@ var SliccSettings = class extends ThemedElement {
50123
50194
  const options2 = account.group === "mcp" ? { kind: "mcp", server: serverOf(account) } : { kind: "model", provider: account.id };
50124
50195
  this.#busy(id, true);
50125
50196
  this.failure = null;
50197
+ const url = this.#mcpUrl(account);
50126
50198
  try {
50127
50199
  await vault.put?.(recordName(account), value, void 0, options2);
50200
+ if (url) {
50201
+ const server = serverOf(account);
50202
+ const old = registrations2()[server];
50203
+ await vault.endpoints?.({
50204
+ ...old && old !== url ? { remove: { mcp: [{ server, url: old }] } } : {},
50205
+ add: { mcp: [{ server, url }] }
50206
+ });
50207
+ register(server, url);
50208
+ }
50128
50209
  } catch (error) {
50129
50210
  this.#busy(id, false);
50130
50211
  if (this.model === model) this.#refuse(id, "value", failureText(error));
@@ -50261,9 +50342,15 @@ var SliccSettings = class extends ThemedElement {
50261
50342
  }
50262
50343
  #submit(event2, account) {
50263
50344
  event2.preventDefault();
50345
+ if (account.blocked) return;
50264
50346
  const form = event2.currentTarget;
50265
50347
  this.problem = null;
50266
50348
  this.filled = new Set([...this.filled].filter((name) => name !== "value"));
50349
+ const url = this.#mcpUrl(account);
50350
+ if (this.#vault(account) && url) {
50351
+ void this.#confirmSubmit(form, account, url);
50352
+ return;
50353
+ }
50267
50354
  if (this.#vault(account)) {
50268
50355
  const value = take(form.querySelector("input[data-field=value]"));
50269
50356
  const fields2 = this.#fields(form, account);
@@ -50276,6 +50363,67 @@ var SliccSettings = class extends ThemedElement {
50276
50363
  const fields = this.#fields(form, account);
50277
50364
  if (secret && fields !== null) void this.#connectBases(account, secret, fields);
50278
50365
  }
50366
+ async #confirmSubmit(form, account, url) {
50367
+ const input = form.querySelector("input[data-field=value]");
50368
+ const problem = valueProblem(input.value);
50369
+ if (problem) return this.#refuse(account.id, "value", problem);
50370
+ const fields = this.#fields(form, account);
50371
+ if (fields === null || this.pending.has(account.id)) return;
50372
+ const model = this.model;
50373
+ if (!await this.#confirmUrl(url)) return;
50374
+ if (!input.isConnected || this.model !== model) return;
50375
+ await this.keep(account, take(input), fields);
50376
+ }
50377
+ #confirmUrl(url) {
50378
+ return confirm({
50379
+ title: `Connect to ${url}?`,
50380
+ body: `SLICC sends this token only to ${url}.`,
50381
+ action: "Connect",
50382
+ variant: "confirmation"
50383
+ });
50384
+ }
50385
+ #mcpUrl(account) {
50386
+ if (account.group !== "mcp" || !this.model?.vault?.endpoints) return null;
50387
+ return this.#baseOf(account.url) ?? null;
50388
+ }
50389
+ #pinned(account) {
50390
+ const server = serverOf(account);
50391
+ return this.model?.vault?.list()?.secrets.find(
50392
+ (secret) => secret.kind === "mcp" && secret.server === server && secret.state !== "removed" && secret.pinned
50393
+ )?.url;
50394
+ }
50395
+ #moved(account) {
50396
+ const url = this.#mcpUrl(account);
50397
+ const old = registrations2()[serverOf(account)] ?? this.#pinned(account);
50398
+ return url && old && old !== url ? url : null;
50399
+ }
50400
+ async #reconnectMcp(account, url) {
50401
+ const model = this.model;
50402
+ const server = serverOf(account);
50403
+ const old = registrations2()[server];
50404
+ if (!await this.#confirmUrl(url)) return;
50405
+ if (this.model !== model) return;
50406
+ this.#busy(account.id, true);
50407
+ this.failure = null;
50408
+ try {
50409
+ await model.vault?.endpoints?.({
50410
+ ...old ? { remove: { mcp: [{ server, url: old }] } } : {},
50411
+ add: { mcp: [{ server, url }] }
50412
+ });
50413
+ register(server, url);
50414
+ } catch (error) {
50415
+ if (this.model === model) this.failure = { id: account.id, message: failureText(error) };
50416
+ return;
50417
+ } finally {
50418
+ this.#busy(account.id, false);
50419
+ }
50420
+ if (this.model === model) await this.connect(account.id);
50421
+ }
50422
+ #movedNote(account) {
50423
+ const url = this.#moved(account);
50424
+ if (!url) return A;
50425
+ return b`<div class="notes"><p class="notice" data-notice="moved"><swc-icon-alert-triangle size="s" aria-hidden="true"></swc-icon-alert-triangle><span>The server moved to ${url}. Reconnect to send the token there.</span></p></div>`;
50426
+ }
50279
50427
  #submitOnEnter(event2) {
50280
50428
  const target2 = event2.target;
50281
50429
  if (event2.key !== "Enter" || target2.localName !== "input") return;
@@ -50369,6 +50517,7 @@ var SliccSettings = class extends ThemedElement {
50369
50517
  return this.adding?.id === account.id ? "Connect" : "Save";
50370
50518
  }
50371
50519
  #ready(account) {
50520
+ if (account.blocked) return false;
50372
50521
  if (!this.#offered()) return true;
50373
50522
  const required = (account.fields ?? []).filter((field) => field.required && !field.options);
50374
50523
  return ["value", ...required.map((field) => field.name)].every((name) => this.filled.has(name));
@@ -50474,8 +50623,16 @@ var SliccSettings = class extends ThemedElement {
50474
50623
  if (!await confirm({ title, body: body4, action: "Disconnect", variant: "confirmation" })) return;
50475
50624
  clearValues(this.renderRoot);
50476
50625
  if (this.model !== model) return;
50626
+ const server = serverOf(account);
50627
+ const pinned = !!this.#pinned(account);
50628
+ const url = account.group === "mcp" ? registrations2()[server] ?? (pinned ? null : this.#mcpUrl(account)) : null;
50477
50629
  if (stored && !await this.#forget(account, stored)) return;
50478
- if (this.model === model) model?.settings.disconnect(account.id);
50630
+ if (this.model !== model) return;
50631
+ model?.settings.disconnect(account.id);
50632
+ if (!url || !stored?.endpoints) return;
50633
+ await stored.endpoints({ remove: { mcp: [{ server, url }] } }).then(() => register(server, void 0)).catch((error) => {
50634
+ if (this.model === model) this.failure = { id: account.id, message: failureText(error) };
50635
+ });
50479
50636
  }
50480
50637
  async #forget(account, vault) {
50481
50638
  this.#busy(account.id, true);
@@ -50533,12 +50690,13 @@ var SliccSettings = class extends ThemedElement {
50533
50690
  data-action="connect"
50534
50691
  accessible-label=${popup(account) ? `Sign in to ${account.provider}` : `${label} ${account.provider}`}
50535
50692
  ?pending=${busy}
50536
- ?disabled=${entering}
50693
+ ?disabled=${entering || !!account.blocked}
50537
50694
  @click=${() => this.#start(account)}
50538
50695
  >${label}</swc-button>`;
50539
50696
  }
50540
50697
  #status(account) {
50541
50698
  if (this.#signingIn(account)) return "signing-in";
50699
+ if (account.status === "connected" && account.blocked) return "unreachable";
50542
50700
  if (account.status === "expired" && account.auth === "api-key") return "rejected";
50543
50701
  if (popup(account) && account.status === "disconnected") return "needs-sign-in";
50544
50702
  if (popup(account) && account.status === "expired") return "sign-in-expired";
@@ -50556,11 +50714,27 @@ var SliccSettings = class extends ThemedElement {
50556
50714
  <span class="provider">${account.provider}</span>
50557
50715
  <span class="identity">${account.identity}${this.#inVault(account) ? b`<span class="kept" data-store="vault">${account.identity ? " \xB7 " : ""}${kept2(account)}</span>` : A}</span>
50558
50716
  <swc-status-light class="state" variant=${variant}>${label}</swc-status-light>
50559
- ${this.#removable(account) ? b`<div class="actions">${this.#action(account)}${this.#removeButton(account)}</div>` : this.#action(account)}
50717
+ ${this.#actions(account)}
50560
50718
  </div>
50561
50719
  ${this.#offered() ? this.#rowNotes(account) : A}
50720
+ ${this.#movedNote(account)}
50562
50721
  ${this.adding?.id === account.id ? A : b`${this.#key(account)}${failure2}`}`;
50563
50722
  }
50723
+ #actions(account) {
50724
+ const moved2 = account.status === "connected" ? this.#moved(account) : null;
50725
+ if (moved2)
50726
+ return b`<div class="actions"><swc-button
50727
+ size="m"
50728
+ variant="accent"
50729
+ data-action="reconnect-mcp"
50730
+ accessible-label=${`Reconnect ${account.provider}`}
50731
+ ?pending=${this.pending.has(account.id)}
50732
+ @click=${() => this.#reconnectMcp(account, moved2)}
50733
+ >Reconnect</swc-button>${this.#action(account)}</div>`;
50734
+ if (this.#removable(account))
50735
+ return b`<div class="actions">${this.#action(account)}${this.#removeButton(account)}</div>`;
50736
+ return this.#action(account);
50737
+ }
50564
50738
  #removable(account) {
50565
50739
  return !!this.#offered() && !!this.model?.settings.remove && account.group !== "mcp";
50566
50740
  }
@@ -50578,6 +50752,14 @@ var SliccSettings = class extends ThemedElement {
50578
50752
  ><swc-icon-delete slot="icon"></swc-icon-delete></swc-action-button
50579
50753
  ><swc-tooltip for=${id} placement="top">${label}</swc-tooltip>`;
50580
50754
  }
50755
+ async #closeTip(id) {
50756
+ const tip = this.renderRoot.querySelector(
50757
+ `swc-tooltip[for="${CSS.escape(id)}"]`
50758
+ );
50759
+ if (!tip) return;
50760
+ tip.open = false;
50761
+ await tip.updateComplete;
50762
+ }
50581
50763
  async #remove(account) {
50582
50764
  const model = this.model;
50583
50765
  const body4 = removeBodies[account.auth ?? ""] ?? "Its key is deleted from the vault. Models from it stop working.";
@@ -50590,6 +50772,7 @@ var SliccSettings = class extends ThemedElement {
50590
50772
  const keyed = account.store === "vault" && account.auth === "api-key" && !!vault?.remove;
50591
50773
  if (keyed && !await this.#forget(account, vault)) return;
50592
50774
  if (this.model !== model) return;
50775
+ await this.#closeTip(`remove-${account.id}`);
50593
50776
  this.#busy(account.id, true);
50594
50777
  this.failure = null;
50595
50778
  try {
@@ -50603,9 +50786,25 @@ var SliccSettings = class extends ThemedElement {
50603
50786
  this.focusOn("[data-action=add-provider]");
50604
50787
  for (const field of account.fields ?? []) this.#bases.delete(`${account.id} ${field.name}`);
50605
50788
  }
50606
- #notice(needs, size4 = "long") {
50789
+ #notice(row, size4 = "long") {
50790
+ const needs = row.blocked;
50607
50791
  if (needs !== "cors-free-transport") return A;
50608
- return b`<p class="notice" data-notice=${needs}><swc-icon-alert-triangle size="s" aria-hidden="true"></swc-icon-alert-triangle><span>${corsNotice[size4]}</span></p>`;
50792
+ return b`<p class="notice" data-notice=${needs} data-blocked><swc-icon-alert-triangle size="s" aria-hidden="true"></swc-icon-alert-triangle><span>${corsNotice[size4]} <a class="swc-Link" href="#network" data-action="setup-network" aria-label="Set up the SLICC extension or CLI" @click=${(event2) => this.#setUp(event2)}>Set up</a></span></p>`;
50793
+ }
50794
+ #setUp(event2) {
50795
+ event2.preventDefault();
50796
+ event2.stopPropagation();
50797
+ if (this.picking) {
50798
+ this.#away = true;
50799
+ this.#closePicker();
50800
+ }
50801
+ this.dispatchEvent(
50802
+ new CustomEvent("show-surface", {
50803
+ detail: { id: "network", section: "whole" },
50804
+ bubbles: true,
50805
+ composed: true
50806
+ })
50807
+ );
50609
50808
  }
50610
50809
  #signingNote(account) {
50611
50810
  const key2 = `settings:${account.id}`;
@@ -50616,7 +50815,7 @@ var SliccSettings = class extends ThemedElement {
50616
50815
  return b`<p class="hint" role="status" data-signing>${signInText(this.#waits.waited(key2))}</p>`;
50617
50816
  }
50618
50817
  #rowNotes(account) {
50619
- const notice = this.#notice(account.needs);
50818
+ const notice = this.#notice(account);
50620
50819
  const signing = this.adding?.id === account.id ? A : this.#signingNote(account);
50621
50820
  if (notice === A && signing === A) return A;
50622
50821
  return b`<div class="notes">${notice}${signing}</div>`;
@@ -50653,6 +50852,9 @@ var SliccSettings = class extends ThemedElement {
50653
50852
  this.query = "";
50654
50853
  const landing = this.#landing;
50655
50854
  this.#landing = null;
50855
+ const away2 = this.#away;
50856
+ this.#away = false;
50857
+ if (away2) return;
50656
50858
  void this.updateComplete.then(() => {
50657
50859
  const root2 = this.renderRoot;
50658
50860
  const row = landing ? root2.querySelector(`.account[data-id="${CSS.escape(landing)}"] swc-button`) : null;
@@ -50664,7 +50866,7 @@ var SliccSettings = class extends ThemedElement {
50664
50866
  this.#closePicker();
50665
50867
  }
50666
50868
  #choose(option2) {
50667
- if (this.#added(option2.id)) return;
50869
+ if (option2.blocked || this.#added(option2.id)) return;
50668
50870
  this.adding = option2;
50669
50871
  this.failure = null;
50670
50872
  if (option2.auth === "api-key" || option2.auth === "fields") {
@@ -50703,11 +50905,13 @@ var SliccSettings = class extends ThemedElement {
50703
50905
  if (event2.key !== "Enter") return;
50704
50906
  event2.preventDefault();
50705
50907
  const first2 = matchProviders(this.#offered() ?? [], this.query).find(
50706
- (option2) => !this.#added(option2.id)
50908
+ (option2) => !option2.blocked && !this.#added(option2.id)
50707
50909
  );
50708
50910
  if (first2) this.#choose(first2);
50709
50911
  }
50710
50912
  #optionKey(event2, option2) {
50913
+ const inner = event2.target !== event2.currentTarget;
50914
+ if (inner && (event2.key === "Enter" || event2.key === " ")) return;
50711
50915
  const options2 = this.#options();
50712
50916
  const at = options2.indexOf(event2.currentTarget);
50713
50917
  const moves = {
@@ -50736,14 +50940,15 @@ var SliccSettings = class extends ThemedElement {
50736
50940
  tabindex="-1"
50737
50941
  data-provider=${option2.id}
50738
50942
  data-auth=${option2.auth}
50739
- aria-disabled=${added ? "true" : "false"}
50943
+ ?data-blocked=${!!option2.blocked}
50944
+ aria-disabled=${added || option2.blocked ? "true" : "false"}
50740
50945
  @click=${() => this.#choose(option2)}
50741
50946
  @keydown=${(event2) => this.#optionKey(event2, option2)}
50742
50947
  >
50743
50948
  <span class="name">${option2.name}</span>
50744
50949
  <span class="tag">${added ? b`<span class="added" data-added><swc-icon-checkmark size="s" aria-hidden="true"></swc-icon-checkmark>Added</span>` : authHints[option2.auth]}</span>
50745
50950
  ${option2.description ? b`<span class="description">${option2.description}</span>` : A}
50746
- ${this.#notice(option2.needs, "short")}
50951
+ ${this.#notice(option2, "short")}
50747
50952
  </div>`;
50748
50953
  }
50749
50954
  #pickStep(offered) {
@@ -50768,23 +50973,24 @@ var SliccSettings = class extends ThemedElement {
50768
50973
  ${signing ? this.#signingNote(account) : A}
50769
50974
  <div class="buttons">
50770
50975
  ${cancel ? b`<swc-button size="m" variant="secondary" data-action="cancel-sign-in" @click=${() => this.#stopSigningIn(account)}>Cancel</swc-button>` : A}
50771
- <swc-button size="m" variant="accent" data-action="sign-in" ?pending=${signing} @click=${() => this.connect(account.id)}>${signing ? "Signing in\u2026" : "Sign in"}</swc-button>
50976
+ <swc-button size="m" variant="accent" data-action="sign-in" ?pending=${signing} ?disabled=${!!account.blocked} @click=${() => this.connect(account.id)}>${signing ? "Signing in\u2026" : "Sign in"}</swc-button>
50772
50977
  ${signing ? A : this.#leave(account)}
50773
50978
  </div>`;
50774
50979
  }
50775
50980
  #localStep(account) {
50776
50981
  return b`<p class="hint">SLICC connects to ${account.provider} on this device.</p>
50777
50982
  <div class="buttons">
50778
- <swc-button size="m" variant="accent" data-action="connect" ?pending=${this.pending.has(account.id)} @click=${() => this.connect(account.id)}>Connect</swc-button>
50983
+ <swc-button size="m" variant="accent" data-action="connect" ?pending=${this.pending.has(account.id)} ?disabled=${!!account.blocked} @click=${() => this.connect(account.id)}>Connect</swc-button>
50779
50984
  ${this.#leave(account)}
50780
50985
  </div>`;
50781
50986
  }
50782
- #connectStep(option2) {
50987
+ #connectStep(adding) {
50988
+ const option2 = this.#offered()?.find((candidate) => candidate.id === adding.id) ?? adding;
50783
50989
  const account = this.#added(option2.id) ?? draft(option2);
50784
50990
  const step = option2.auth === "oauth" ? this.#signInStep(account) : option2.auth === "local" ? this.#localStep(account) : this.#key(account);
50785
50991
  return b`<div class="step" data-step=${option2.auth} data-provider=${option2.id}>
50786
50992
  ${option2.description ? b`<p class="lead">${option2.description}</p>` : A}
50787
- ${this.#notice(option2.needs)}
50993
+ ${this.#notice(option2)}
50788
50994
  ${step}
50789
50995
  ${this.failure?.id === option2.id ? b`<div class="failure" role="alert"><swc-icon-alert-triangle size="s" aria-hidden="true"></swc-icon-alert-triangle><span>${this.failure.message}</span></div>` : A}
50790
50996
  </div>`;