@ai-ecoverse/slicc-spectrum 1.91.0 → 1.94.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -5
- package/dist/chunk-RYA3OPGE.js +1885 -0
- package/dist/chunk-RYA3OPGE.js.map +7 -0
- package/dist/slicc-dummy.js +133 -1600
- package/dist/slicc-dummy.js.map +4 -4
- package/dist/slicc-kernel-model.js +1 -1
- package/dist/slicc-ui.js +760 -74
- package/dist/slicc-ui.js.map +4 -4
- package/dist/types/app/approvals.d.ts +1 -1
- package/dist/types/app/chat.d.ts +2 -1
- package/dist/types/app/confirm.d.ts +4 -3
- package/dist/types/app/freezer-import.d.ts +1 -1
- package/dist/types/app/guests.d.ts +1 -1
- package/dist/types/app/secrets.d.ts +18 -2
- package/dist/types/app/settings.d.ts +25 -1
- package/dist/types/app/sign-in.d.ts +12 -0
- package/dist/types/app/value-request.d.ts +1 -1
- package/dist/types/dummy/index.d.ts +1 -1
- package/dist/types/dummy/providers.d.ts +4 -0
- package/dist/types/dummy/settings.d.ts +6 -3
- package/dist/types/dummy/vault.d.ts +6 -2
- package/dist/types/dummy.d.ts +2 -1
- package/dist/types/model/types.d.ts +58 -2
- package/package.json +1 -1
- package/dist/chunk-VRFAMBWK.js +0 -118
- package/dist/chunk-VRFAMBWK.js.map +0 -7
package/dist/slicc-ui.js
CHANGED
|
@@ -9349,7 +9349,7 @@ function themeOf(node) {
|
|
|
9349
9349
|
}
|
|
9350
9350
|
return document.querySelector("slicc-app")?.shadowRoot?.querySelector("sp-theme") ?? document.body;
|
|
9351
9351
|
}
|
|
9352
|
-
var
|
|
9352
|
+
var dialogFrame = i`
|
|
9353
9353
|
dialog {
|
|
9354
9354
|
box-sizing: border-box;
|
|
9355
9355
|
max-inline-size: calc(100vw - 2 * var(--swc-spacing-300));
|
|
@@ -9369,6 +9369,13 @@ var dialogStyles = i`
|
|
|
9369
9369
|
color-mix(in srgb, var(--swc-overlay-color) calc(var(--swc-overlay-opacity-dark) * 100%), transparent)
|
|
9370
9370
|
);
|
|
9371
9371
|
}
|
|
9372
|
+
@media (forced-colors: active) {
|
|
9373
|
+
dialog {
|
|
9374
|
+
outline: solid;
|
|
9375
|
+
}
|
|
9376
|
+
}
|
|
9377
|
+
`;
|
|
9378
|
+
var alertStyles = i`
|
|
9372
9379
|
sp-alert-dialog {
|
|
9373
9380
|
--mod-alert-dialog-min-width: min(
|
|
9374
9381
|
var(--swc-alert-dialog-minimum-width),
|
|
@@ -9390,9 +9397,6 @@ var dialogStyles = i`
|
|
|
9390
9397
|
}
|
|
9391
9398
|
}
|
|
9392
9399
|
@media (forced-colors: active) {
|
|
9393
|
-
dialog {
|
|
9394
|
-
outline: solid;
|
|
9395
|
-
}
|
|
9396
9400
|
sp-alert-dialog {
|
|
9397
9401
|
border: none;
|
|
9398
9402
|
}
|
|
@@ -9409,6 +9413,7 @@ var dialogStyles = i`
|
|
|
9409
9413
|
margin-block-end: var(--swc-spacing-75);
|
|
9410
9414
|
}
|
|
9411
9415
|
`;
|
|
9416
|
+
var dialogStyles = [dialogFrame, alertStyles];
|
|
9412
9417
|
var SliccConfirm = class extends i2 {
|
|
9413
9418
|
static properties = { heading: {}, body: {}, action: {}, variant: {}, cancel: {} };
|
|
9414
9419
|
trigger = null;
|
|
@@ -22649,6 +22654,34 @@ function markdown(text2) {
|
|
|
22649
22654
|
return b`${parse(text2).map(render)}`;
|
|
22650
22655
|
}
|
|
22651
22656
|
|
|
22657
|
+
// src/app/sign-in.ts
|
|
22658
|
+
var continuing = "Continue in the sign-in window that opened.";
|
|
22659
|
+
var closed = "Closed the sign-in window? Cancel, then Log in again.";
|
|
22660
|
+
var signInWait = { closedAfter: 2e4 };
|
|
22661
|
+
function signInText(waited) {
|
|
22662
|
+
return waited ? closed : continuing;
|
|
22663
|
+
}
|
|
22664
|
+
var SignInWaits = class {
|
|
22665
|
+
#since = /* @__PURE__ */ new Map();
|
|
22666
|
+
#update;
|
|
22667
|
+
constructor(update) {
|
|
22668
|
+
this.#update = update;
|
|
22669
|
+
}
|
|
22670
|
+
waited(key2) {
|
|
22671
|
+
const now = Date.now();
|
|
22672
|
+
const since3 = this.#since.get(key2);
|
|
22673
|
+
if (since3 === void 0) {
|
|
22674
|
+
this.#since.set(key2, now);
|
|
22675
|
+
setTimeout(this.#update, signInWait.closedAfter);
|
|
22676
|
+
return false;
|
|
22677
|
+
}
|
|
22678
|
+
return now - since3 >= signInWait.closedAfter;
|
|
22679
|
+
}
|
|
22680
|
+
done(key2) {
|
|
22681
|
+
this.#since.delete(key2);
|
|
22682
|
+
}
|
|
22683
|
+
};
|
|
22684
|
+
|
|
22652
22685
|
// src/app/messages.ts
|
|
22653
22686
|
var lickLabels = {
|
|
22654
22687
|
webhook: ["Webhook", "informative"],
|
|
@@ -22843,8 +22876,6 @@ function actionLabel(action, handlers, messageId) {
|
|
|
22843
22876
|
return count2 > 1 ? `Drop ${count2} failed turns` : actionLabels[action];
|
|
22844
22877
|
}
|
|
22845
22878
|
var signedIn = "Signed in. Retry to send it again.";
|
|
22846
|
-
var continuing = "Continue in the sign-in window that opened.";
|
|
22847
|
-
var closed = "Closed the sign-in window? Cancel, then Log in again.";
|
|
22848
22879
|
function stopSigningIn(event2, handlers, account, id) {
|
|
22849
22880
|
const main2 = event2.currentTarget.nextElementSibling;
|
|
22850
22881
|
main2.focus();
|
|
@@ -22863,7 +22894,7 @@ function errorCard(item2, handlers) {
|
|
|
22863
22894
|
const login = fix === "login" && item2.account && !handlers.readOnly ? handlers.login?.(item2.account, id) : void 0;
|
|
22864
22895
|
const resolved = login?.state === "connected";
|
|
22865
22896
|
const signing = login?.state === "signing-in" && login.window;
|
|
22866
|
-
const text2 = resolved ? signedIn : signing ? login.waited
|
|
22897
|
+
const text2 = resolved ? signedIn : signing ? signInText(login.waited) : item2.text;
|
|
22867
22898
|
const title = resolved && login.provider ? `Signed in to ${login.provider} again.` : item2.title;
|
|
22868
22899
|
const failure2 = login?.state === "idle" ? login.error : void 0;
|
|
22869
22900
|
return b`<div class="error-card" role=${resolved ? A : "alert"} aria-atomic=${resolved ? A : "false"} data-id=${id || A} data-login=${login?.state ?? A}>
|
|
@@ -24701,7 +24732,7 @@ document.addEventListener(
|
|
|
24701
24732
|
},
|
|
24702
24733
|
true
|
|
24703
24734
|
);
|
|
24704
|
-
var SliccChat = class
|
|
24735
|
+
var SliccChat = class extends ThemedElement {
|
|
24705
24736
|
static properties = {
|
|
24706
24737
|
...ThemedElement.properties,
|
|
24707
24738
|
agent: {},
|
|
@@ -25125,19 +25156,14 @@ var SliccChat = class _SliccChat extends ThemedElement {
|
|
|
25125
25156
|
if (!restored) return;
|
|
25126
25157
|
this.renderRoot.querySelector("slicc-composer")?.restore(latest ? { text: latest.text, attachments: latest.attachments } : restored);
|
|
25127
25158
|
}
|
|
25128
|
-
static closedAfter
|
|
25129
|
-
|
|
25130
|
-
#signing = /* @__PURE__ */ new Map();
|
|
25131
|
-
#waited(key2) {
|
|
25132
|
-
const now = Date.now();
|
|
25133
|
-
const since3 = this.#signing.get(key2);
|
|
25134
|
-
if (since3 === void 0) {
|
|
25135
|
-
this.#signing.set(key2, now);
|
|
25136
|
-
setTimeout(() => this.requestUpdate(), _SliccChat.closedAfter);
|
|
25137
|
-
return false;
|
|
25138
|
-
}
|
|
25139
|
-
return now - since3 >= _SliccChat.closedAfter;
|
|
25159
|
+
static get closedAfter() {
|
|
25160
|
+
return signInWait.closedAfter;
|
|
25140
25161
|
}
|
|
25162
|
+
static set closedAfter(after) {
|
|
25163
|
+
signInWait.closedAfter = after;
|
|
25164
|
+
}
|
|
25165
|
+
#logins = /* @__PURE__ */ new Map();
|
|
25166
|
+
#waits = new SignInWaits(() => this.requestUpdate());
|
|
25141
25167
|
#loginState(accountId, messageId) {
|
|
25142
25168
|
const settings = this.model.settings;
|
|
25143
25169
|
const account = settings.accounts().find((candidate) => candidate.id === accountId);
|
|
@@ -25146,8 +25172,8 @@ var SliccChat = class _SliccChat extends ThemedElement {
|
|
|
25146
25172
|
const window2 = account?.auth === "oauth";
|
|
25147
25173
|
const key2 = `${messageId}:${accountId}`;
|
|
25148
25174
|
if (account?.status === "signing-in" || local2?.pending)
|
|
25149
|
-
return { state: "signing-in", cancel, window: window2, waited: window2 && this.#waited(key2) };
|
|
25150
|
-
this.#
|
|
25175
|
+
return { state: "signing-in", cancel, window: window2, waited: window2 && this.#waits.waited(key2) };
|
|
25176
|
+
this.#waits.done(key2);
|
|
25151
25177
|
if (account?.status === "connected") return { state: "connected", provider: account.provider };
|
|
25152
25178
|
return { state: "idle", error: local2?.error };
|
|
25153
25179
|
}
|
|
@@ -25988,13 +26014,13 @@ var SliccFileView = class extends ThemedElement {
|
|
|
25988
26014
|
async save() {
|
|
25989
26015
|
const model = this.model;
|
|
25990
26016
|
if (!model || this.draft === null) return;
|
|
25991
|
-
const
|
|
26017
|
+
const draft2 = this.draft;
|
|
25992
26018
|
this.saving = true;
|
|
25993
26019
|
try {
|
|
25994
|
-
await model.files.write(this.path,
|
|
25995
|
-
this.text =
|
|
26020
|
+
await model.files.write(this.path, draft2);
|
|
26021
|
+
this.text = draft2;
|
|
25996
26022
|
this.missing = false;
|
|
25997
|
-
if (this.draft ===
|
|
26023
|
+
if (this.draft === draft2) this.draft = null;
|
|
25998
26024
|
} finally {
|
|
25999
26025
|
this.saving = false;
|
|
26000
26026
|
}
|
|
@@ -31336,8 +31362,8 @@ var Panels = class {
|
|
|
31336
31362
|
};
|
|
31337
31363
|
}
|
|
31338
31364
|
find(id) {
|
|
31339
|
-
const
|
|
31340
|
-
if (
|
|
31365
|
+
const listed2 = this.list().find((info) => info.id === id);
|
|
31366
|
+
if (listed2) return listed2;
|
|
31341
31367
|
const document2 = id.match(/^(file|diff):(.+)$/);
|
|
31342
31368
|
if (!document2) return void 0;
|
|
31343
31369
|
return this.#state({
|
|
@@ -39792,7 +39818,8 @@ var fieldStyles = i`
|
|
|
39792
39818
|
font-size: var(--swc-font-size-75);
|
|
39793
39819
|
color: var(--swc-neutral-subdued-content-color-default);
|
|
39794
39820
|
}
|
|
39795
|
-
.field input:not([type='checkbox'])
|
|
39821
|
+
.field input:not([type='checkbox']),
|
|
39822
|
+
.field select {
|
|
39796
39823
|
box-sizing: border-box;
|
|
39797
39824
|
inline-size: 100%;
|
|
39798
39825
|
font: inherit;
|
|
@@ -39803,7 +39830,8 @@ var fieldStyles = i`
|
|
|
39803
39830
|
background: var(--swc-background-layer-2-color);
|
|
39804
39831
|
color: inherit;
|
|
39805
39832
|
}
|
|
39806
|
-
.field input[aria-invalid='true']
|
|
39833
|
+
.field input[aria-invalid='true'],
|
|
39834
|
+
.field select[aria-invalid='true'] {
|
|
39807
39835
|
border-color: var(--swc-negative-border-color-default);
|
|
39808
39836
|
}
|
|
39809
39837
|
.field input[type='file'] {
|
|
@@ -39820,6 +39848,7 @@ var fieldStyles = i`
|
|
|
39820
39848
|
color: inherit;
|
|
39821
39849
|
}
|
|
39822
39850
|
.field input:focus-visible,
|
|
39851
|
+
.field select:focus-visible,
|
|
39823
39852
|
input[type='checkbox']:focus-visible {
|
|
39824
39853
|
outline: var(--swc-focus-indicator-thickness) solid var(--swc-focus-indicator-color);
|
|
39825
39854
|
outline-offset: var(--swc-focus-ring-gap);
|
|
@@ -40419,7 +40448,7 @@ var SliccComposer = class extends ThemedElement {
|
|
|
40419
40448
|
clearValues(this.renderRoot);
|
|
40420
40449
|
const held = [
|
|
40421
40450
|
this.attachments,
|
|
40422
|
-
...[...this.#drafts.values()].map((
|
|
40451
|
+
...[...this.#drafts.values()].map((draft2) => draft2.attachments)
|
|
40423
40452
|
];
|
|
40424
40453
|
if (held.flat().some((attachment2) => attachment2.url?.startsWith("blob:")))
|
|
40425
40454
|
this.#abandon = setTimeout(() => {
|
|
@@ -40475,10 +40504,10 @@ var SliccComposer = class extends ThemedElement {
|
|
|
40475
40504
|
#switch(id) {
|
|
40476
40505
|
if (this.#agent)
|
|
40477
40506
|
this.#drafts.set(this.#agent, { value: this.value, attachments: this.attachments });
|
|
40478
|
-
const
|
|
40507
|
+
const draft2 = this.#drafts.get(id);
|
|
40479
40508
|
this.#agent = id;
|
|
40480
|
-
this.value =
|
|
40481
|
-
this.attachments =
|
|
40509
|
+
this.value = draft2?.value ?? "";
|
|
40510
|
+
this.attachments = draft2?.attachments ?? [];
|
|
40482
40511
|
this.popup = null;
|
|
40483
40512
|
this.#history = -1;
|
|
40484
40513
|
}
|
|
@@ -40531,8 +40560,8 @@ var SliccComposer = class extends ThemedElement {
|
|
|
40531
40560
|
this.failure = null;
|
|
40532
40561
|
this.#history = -1;
|
|
40533
40562
|
model.agent.send(this.#agent, text2).catch((error) => {
|
|
40534
|
-
const
|
|
40535
|
-
this.value =
|
|
40563
|
+
const draft2 = this.value.trim();
|
|
40564
|
+
this.value = draft2 && draft2 !== text2 ? `${text2}
|
|
40536
40565
|
${this.value}` : text2;
|
|
40537
40566
|
this.failure = error instanceof Error ? error.message : String(error);
|
|
40538
40567
|
});
|
|
@@ -40857,8 +40886,8 @@ ${this.value}` : text2;
|
|
|
40857
40886
|
}
|
|
40858
40887
|
async #paste(event2) {
|
|
40859
40888
|
const data = event2.clipboardData;
|
|
40860
|
-
const
|
|
40861
|
-
const files =
|
|
40889
|
+
const listed2 = [...data?.files ?? []];
|
|
40890
|
+
const files = listed2.length ? listed2 : [...data?.items ?? []].flatMap((item2) => {
|
|
40862
40891
|
const file = item2.kind === "file" ? item2.getAsFile() : null;
|
|
40863
40892
|
return file ? [file] : [];
|
|
40864
40893
|
});
|
|
@@ -41836,7 +41865,28 @@ function changes(entry, devices) {
|
|
|
41836
41865
|
return entry.changes.map((change) => [change.kind, changeLine(change, devices)]);
|
|
41837
41866
|
return (entry.widened ?? []).map((change) => [change.kind, widening(change, devices)]);
|
|
41838
41867
|
}
|
|
41839
|
-
|
|
41868
|
+
var listed = (items, one2) => items.map((item2, index) => b`${index ? ", " : ""}${one2(item2)}`);
|
|
41869
|
+
function endpointsLine(entry, named2 = (provider) => provider) {
|
|
41870
|
+
const parts2 = [];
|
|
41871
|
+
if (entry.purged?.length)
|
|
41872
|
+
parts2.push(
|
|
41873
|
+
b`<span class="part" data-part="purged">Removed custom model URLs an agent set, automatically: ${listed(entry.purged, (item2) => b`${named2(item2.provider)} at <code>${item2.host ?? item2.url}</code>`)}. Only you can set a model URL now, in Settings › Accounts</span>`
|
|
41874
|
+
);
|
|
41875
|
+
if (entry.adopted?.length)
|
|
41876
|
+
parts2.push(
|
|
41877
|
+
b`<span class="part" data-part="adopted">Kept the MCP servers your tokens use, automatically: ${listed(entry.adopted, (item2) => b`${item2.server} at <code>${item2.host}</code>`)}</span>`
|
|
41878
|
+
);
|
|
41879
|
+
if (entry.pinned)
|
|
41880
|
+
parts2.push(
|
|
41881
|
+
b`<span class="part" data-part="pinned"><code>${entry.pinned.name ?? entry.pinned.server}</code> pinned to <code>${entry.pinned.host}</code> automatically, on first use</span>`
|
|
41882
|
+
);
|
|
41883
|
+
if (entry.unpinned)
|
|
41884
|
+
parts2.push(
|
|
41885
|
+
b`<span class="part" data-part="unpinned"><code>${entry.unpinned.name ?? entry.unpinned.server}</code> unpinned from <code>${entry.unpinned.host}</code>; the next use pins it again</span>`
|
|
41886
|
+
);
|
|
41887
|
+
return b`${parts2.map((part2, index) => b`${index ? ". " : ""}${part2}`)}`;
|
|
41888
|
+
}
|
|
41889
|
+
function auditLine(entry, devices, named2) {
|
|
41840
41890
|
switch (entry.type) {
|
|
41841
41891
|
case "inject":
|
|
41842
41892
|
case "forward":
|
|
@@ -41852,7 +41902,7 @@ function auditLine(entry, devices) {
|
|
|
41852
41902
|
case "restore":
|
|
41853
41903
|
return b`Restored`;
|
|
41854
41904
|
case "endpoints":
|
|
41855
|
-
return
|
|
41905
|
+
return endpointsLine(entry, named2);
|
|
41856
41906
|
case "refresh":
|
|
41857
41907
|
return entry.grant ? b`Refreshed automatically with the sign-in <code>${entry.grant}</code>` : b`Refreshed automatically`;
|
|
41858
41908
|
default:
|
|
@@ -41909,6 +41959,9 @@ var SliccSecrets = class extends ThemedElement {
|
|
|
41909
41959
|
failure: { state: true },
|
|
41910
41960
|
form: { state: true },
|
|
41911
41961
|
busy: { state: true },
|
|
41962
|
+
unpinning: { state: true },
|
|
41963
|
+
unpinned: { state: true },
|
|
41964
|
+
unpinFailure: { state: true },
|
|
41912
41965
|
problem: { state: true },
|
|
41913
41966
|
invalid: { state: true },
|
|
41914
41967
|
said: { state: true },
|
|
@@ -41931,6 +41984,9 @@ var SliccSecrets = class extends ThemedElement {
|
|
|
41931
41984
|
this.failure = null;
|
|
41932
41985
|
this.form = null;
|
|
41933
41986
|
this.busy = false;
|
|
41987
|
+
this.unpinning = null;
|
|
41988
|
+
this.unpinned = /* @__PURE__ */ new Set();
|
|
41989
|
+
this.unpinFailure = null;
|
|
41934
41990
|
this.problem = null;
|
|
41935
41991
|
this.invalid = null;
|
|
41936
41992
|
this.said = null;
|
|
@@ -42193,6 +42249,13 @@ var SliccSecrets = class extends ThemedElement {
|
|
|
42193
42249
|
.audit .hint {
|
|
42194
42250
|
display: block;
|
|
42195
42251
|
}
|
|
42252
|
+
.audit .unpin {
|
|
42253
|
+
display: flex;
|
|
42254
|
+
flex-wrap: wrap;
|
|
42255
|
+
align-items: center;
|
|
42256
|
+
gap: var(--swc-spacing-200);
|
|
42257
|
+
margin-top: var(--swc-spacing-100);
|
|
42258
|
+
}
|
|
42196
42259
|
.row {
|
|
42197
42260
|
display: flex;
|
|
42198
42261
|
flex-wrap: wrap;
|
|
@@ -42254,6 +42317,9 @@ var SliccSecrets = class extends ThemedElement {
|
|
|
42254
42317
|
this.failure = null;
|
|
42255
42318
|
this.form = null;
|
|
42256
42319
|
this.busy = false;
|
|
42320
|
+
this.unpinning = null;
|
|
42321
|
+
this.unpinned = /* @__PURE__ */ new Set();
|
|
42322
|
+
this.unpinFailure = null;
|
|
42257
42323
|
this.problem = null;
|
|
42258
42324
|
this.invalid = null;
|
|
42259
42325
|
this.said = null;
|
|
@@ -42738,12 +42804,42 @@ var SliccSecrets = class extends ThemedElement {
|
|
|
42738
42804
|
${refused2.map((item2) => b`<li data-refused-secret=${item2.secret}><span><code>${item2.secret}</code> to ${ruleLine(item2.rule)}</span><span class="muted">${item2.reason}</span></li>`)}
|
|
42739
42805
|
</ul>`;
|
|
42740
42806
|
}
|
|
42741
|
-
#
|
|
42807
|
+
#provider(id) {
|
|
42808
|
+
const settings = this.model?.settings;
|
|
42809
|
+
const option2 = settings?.providers?.().find((item2) => item2.id === id);
|
|
42810
|
+
const account = settings?.accounts().find((item2) => item2.id === id);
|
|
42811
|
+
return option2?.name ?? account?.provider ?? id;
|
|
42812
|
+
}
|
|
42813
|
+
#unpin(vault, entry, all2) {
|
|
42814
|
+
const name = entry.pinned?.name;
|
|
42815
|
+
if (!name || !vault.unpin) return A;
|
|
42816
|
+
const key2 = `unpin:${entry.seq}`;
|
|
42817
|
+
const undone = all2.some(
|
|
42818
|
+
(later) => later.type === "endpoints" && later.seq > entry.seq && later.unpinned?.name === name
|
|
42819
|
+
);
|
|
42820
|
+
if (undone || this.unpinned.has(key2)) return A;
|
|
42821
|
+
const busy = this.unpinning === key2;
|
|
42822
|
+
return b`<span class="unpin"><swc-button size="s" variant="secondary" fill-style="outline" data-action="unpin" ?pending=${busy} ?disabled=${!!vault.status()?.locked} @click=${() => this.#unpinNow(vault, name, key2)}>Unpin</swc-button>${this.unpinFailure?.key === key2 ? b`<span class="warning" role="alert" data-error="unpin">${this.unpinFailure.message}</span>` : A}</span>`;
|
|
42823
|
+
}
|
|
42824
|
+
async #unpinNow(vault, name, key2) {
|
|
42825
|
+
if (this.unpinning) return;
|
|
42826
|
+
this.unpinning = key2;
|
|
42827
|
+
this.unpinFailure = null;
|
|
42828
|
+
try {
|
|
42829
|
+
await vault.unpin?.([name]);
|
|
42830
|
+
if (this.#mine(vault)) this.unpinned = /* @__PURE__ */ new Set([...this.unpinned, key2]);
|
|
42831
|
+
} catch (error) {
|
|
42832
|
+
if (this.#mine(vault)) this.unpinFailure = { key: key2, message: failureText(error) };
|
|
42833
|
+
} finally {
|
|
42834
|
+
if (this.#mine(vault)) this.unpinning = null;
|
|
42835
|
+
}
|
|
42836
|
+
}
|
|
42837
|
+
#entry(entry, devices, vault, all2 = []) {
|
|
42742
42838
|
const date = new Date(entry.at);
|
|
42743
42839
|
const name = entry.type === "policy" || entry.type === "endpoints" ? null : entry.name;
|
|
42744
42840
|
return b`<li data-seq=${entry.seq} data-type=${entry.type}>
|
|
42745
42841
|
<time datetime=${date.toISOString()} title=${date.toLocaleString("en-GB", { dateStyle: "medium", timeStyle: "short" })}>${since(entry.at)}</time>
|
|
42746
|
-
<span class="what">${name ? b`<code>${name}</code> · ` : A}${auditLine(entry, devices)}${entry.type === "policy" || entry.type === "refresh" || entry.type === "endpoints" ? A : b` <span class="by">by ${who(entry)}</span>`}</span>
|
|
42842
|
+
<span class="what">${name ? b`<code>${name}</code> · ` : A}${auditLine(entry, devices, (provider) => this.#provider(provider))}${entry.type === "policy" || entry.type === "refresh" || entry.type === "endpoints" ? A : b` <span class="by">by ${who(entry)}</span>`}${entry.type === "endpoints" && vault ? this.#unpin(vault, entry, all2) : A}</span>
|
|
42747
42843
|
</li>`;
|
|
42748
42844
|
}
|
|
42749
42845
|
#audit(vault, list5, entries, devices) {
|
|
@@ -42755,7 +42851,7 @@ var SliccSecrets = class extends ThemedElement {
|
|
|
42755
42851
|
this.reveals = event2.target.checked;
|
|
42756
42852
|
}}>Only reveals to programs</sp-switch>
|
|
42757
42853
|
</div>
|
|
42758
|
-
${shown4.length ? b`<ol class="audit" aria-labelledby="secrets-audit">${shown4.map((entry) => this.#entry(entry, devices))}</ol>` : b`<p class="muted" data-audit-empty>${this.reveals ? more ? "No reveals in the activity loaded so far." : "No program has been given a secret." : "Nothing has used a secret yet."}</p>`}
|
|
42854
|
+
${shown4.length ? b`<ol class="audit" aria-labelledby="secrets-audit">${shown4.map((entry) => this.#entry(entry, devices, vault, entries))}</ol>` : b`<p class="muted" data-audit-empty>${this.reveals ? more ? "No reveals in the activity loaded so far." : "No program has been given a secret." : "Nothing has used a secret yet."}</p>`}
|
|
42759
42855
|
${more ? b`<div class="row"><swc-button size="s" variant="secondary" fill-style="outline" data-action="older" ?pending=${this.loading} @click=${() => this.showOlder(vault, entries)}>Show older</swc-button></div>` : A}`;
|
|
42760
42856
|
}
|
|
42761
42857
|
#feedback() {
|
|
@@ -42870,6 +42966,7 @@ function recordKind(account) {
|
|
|
42870
42966
|
return account.group === "mcp" ? "mcp" : "model";
|
|
42871
42967
|
}
|
|
42872
42968
|
function recordName(account) {
|
|
42969
|
+
if (account.vaultName) return account.vaultName;
|
|
42873
42970
|
if (account.group === "mcp") return `MCP_${upper(serverOf(account))}_TOKEN`;
|
|
42874
42971
|
return envNames[account.id] ?? `${upper(account.id)}_API_KEY`;
|
|
42875
42972
|
}
|
|
@@ -42884,6 +42981,48 @@ var accountStatus = {
|
|
|
42884
42981
|
"needs-sign-in": ["neutral", "Needs sign-in"],
|
|
42885
42982
|
"sign-in-expired": ["notice", "Sign-in expired"]
|
|
42886
42983
|
};
|
|
42984
|
+
var authHints = {
|
|
42985
|
+
"api-key": "API key",
|
|
42986
|
+
oauth: "Sign in",
|
|
42987
|
+
fields: "Endpoint and key",
|
|
42988
|
+
local: "On this device"
|
|
42989
|
+
};
|
|
42990
|
+
var listOrder = {
|
|
42991
|
+
connected: 0,
|
|
42992
|
+
expired: 1,
|
|
42993
|
+
"signing-in": 2,
|
|
42994
|
+
disconnected: 3
|
|
42995
|
+
};
|
|
42996
|
+
var corsNotice = {
|
|
42997
|
+
short: "Needs the SLICC extension or CLI",
|
|
42998
|
+
long: "Needs the SLICC extension or CLI, because the browser blocks direct requests to it."
|
|
42999
|
+
};
|
|
43000
|
+
var removeBodies = {
|
|
43001
|
+
oauth: "Its sign-in is deleted from the vault. Models from it stop working.",
|
|
43002
|
+
local: "Models from it stop working."
|
|
43003
|
+
};
|
|
43004
|
+
function draft(option2) {
|
|
43005
|
+
return {
|
|
43006
|
+
id: option2.id,
|
|
43007
|
+
provider: option2.name,
|
|
43008
|
+
identity: "",
|
|
43009
|
+
status: "disconnected",
|
|
43010
|
+
group: "providers",
|
|
43011
|
+
store: "vault",
|
|
43012
|
+
auth: option2.auth === "fields" ? "api-key" : option2.auth,
|
|
43013
|
+
fields: option2.fields,
|
|
43014
|
+
keyUrl: option2.keyUrl,
|
|
43015
|
+
needs: option2.needs,
|
|
43016
|
+
vaultName: option2.vaultName
|
|
43017
|
+
};
|
|
43018
|
+
}
|
|
43019
|
+
function matchProviders(options, query) {
|
|
43020
|
+
const words = query.trim().toLowerCase().split(/\s+/).filter(Boolean);
|
|
43021
|
+
return options.filter((option2) => {
|
|
43022
|
+
const text2 = `${option2.name} ${option2.id} ${option2.description ?? ""}`.toLowerCase();
|
|
43023
|
+
return words.every((word) => text2.includes(word));
|
|
43024
|
+
});
|
|
43025
|
+
}
|
|
42887
43026
|
var popup = (account) => account.group === "mcp" && account.auth === "oauth";
|
|
42888
43027
|
var secretNames = { "api-key": "API key", token: "token" };
|
|
42889
43028
|
var rejectedNames = { "api-key": "API key rejected", token: "Token rejected" };
|
|
@@ -42903,8 +43042,15 @@ var SliccSettings = class extends ThemedElement {
|
|
|
42903
43042
|
entering: { state: true },
|
|
42904
43043
|
failure: { state: true },
|
|
42905
43044
|
problem: { state: true },
|
|
42906
|
-
blocked: { state: true }
|
|
43045
|
+
blocked: { state: true },
|
|
43046
|
+
picking: { state: true },
|
|
43047
|
+
adding: { state: true },
|
|
43048
|
+
query: { state: true },
|
|
43049
|
+
filled: { state: true }
|
|
42907
43050
|
};
|
|
43051
|
+
#waits = new SignInWaits(() => this.requestUpdate());
|
|
43052
|
+
#landing = null;
|
|
43053
|
+
#bases = /* @__PURE__ */ new Map();
|
|
42908
43054
|
#scroll = new ViewScroll(this, "settings:scroll", { scroller: () => this, rows: "[data-id]" });
|
|
42909
43055
|
constructor() {
|
|
42910
43056
|
super();
|
|
@@ -42913,9 +43059,16 @@ var SliccSettings = class extends ThemedElement {
|
|
|
42913
43059
|
this.failure = null;
|
|
42914
43060
|
this.problem = null;
|
|
42915
43061
|
this.blocked = false;
|
|
43062
|
+
this.picking = false;
|
|
43063
|
+
this.adding = null;
|
|
43064
|
+
this.query = "";
|
|
43065
|
+
this.filled = /* @__PURE__ */ new Set();
|
|
42916
43066
|
}
|
|
42917
43067
|
static styles = [
|
|
42918
43068
|
fieldStyles,
|
|
43069
|
+
dialogFrame,
|
|
43070
|
+
searchCss,
|
|
43071
|
+
r(link_default),
|
|
42919
43072
|
i`
|
|
42920
43073
|
:host {
|
|
42921
43074
|
display: block;
|
|
@@ -43027,6 +43180,144 @@ var SliccSettings = class extends ThemedElement {
|
|
|
43027
43180
|
line-height: var(--swc-line-height-200);
|
|
43028
43181
|
--swc-icon-color: var(--swc-negative-content-color-default);
|
|
43029
43182
|
}
|
|
43183
|
+
.actions {
|
|
43184
|
+
display: flex;
|
|
43185
|
+
align-items: center;
|
|
43186
|
+
gap: var(--swc-spacing-75);
|
|
43187
|
+
}
|
|
43188
|
+
.notes {
|
|
43189
|
+
grid-column: 1 / -1;
|
|
43190
|
+
display: grid;
|
|
43191
|
+
gap: var(--swc-spacing-75);
|
|
43192
|
+
margin-block-start: calc(-1 * var(--swc-spacing-200));
|
|
43193
|
+
}
|
|
43194
|
+
.notice {
|
|
43195
|
+
display: flex;
|
|
43196
|
+
align-items: flex-start;
|
|
43197
|
+
gap: var(--swc-spacing-75);
|
|
43198
|
+
margin: 0;
|
|
43199
|
+
color: var(--swc-neutral-subdued-content-color-default);
|
|
43200
|
+
font-size: var(--swc-font-size-75);
|
|
43201
|
+
line-height: var(--swc-line-height-200);
|
|
43202
|
+
--swc-icon-color: var(--swc-notice-visual-color);
|
|
43203
|
+
}
|
|
43204
|
+
.notice swc-icon-alert-triangle {
|
|
43205
|
+
flex: none;
|
|
43206
|
+
margin-block-start: var(--swc-spacing-50);
|
|
43207
|
+
}
|
|
43208
|
+
.add {
|
|
43209
|
+
margin-block-start: var(--swc-spacing-200);
|
|
43210
|
+
margin-inline-start: calc(-1 * var(--swc-spacing-100));
|
|
43211
|
+
}
|
|
43212
|
+
dialog.picker {
|
|
43213
|
+
inline-size: min(520px, calc(100vw - 2 * var(--swc-spacing-300)));
|
|
43214
|
+
}
|
|
43215
|
+
.picker .head {
|
|
43216
|
+
display: flex;
|
|
43217
|
+
align-items: center;
|
|
43218
|
+
justify-content: space-between;
|
|
43219
|
+
gap: var(--swc-spacing-200);
|
|
43220
|
+
padding: var(--swc-spacing-400) var(--swc-spacing-300) var(--swc-spacing-200) var(--swc-spacing-500);
|
|
43221
|
+
}
|
|
43222
|
+
.picker h2 {
|
|
43223
|
+
margin: 0;
|
|
43224
|
+
font-size: var(--swc-heading-size-s);
|
|
43225
|
+
overflow-wrap: anywhere;
|
|
43226
|
+
}
|
|
43227
|
+
.picker .find {
|
|
43228
|
+
display: flex;
|
|
43229
|
+
padding: var(--swc-spacing-100) var(--swc-spacing-500) var(--swc-spacing-200);
|
|
43230
|
+
}
|
|
43231
|
+
.picker .results {
|
|
43232
|
+
block-size: min(400px, calc(100dvh - 280px));
|
|
43233
|
+
overflow-y: auto;
|
|
43234
|
+
overscroll-behavior: contain;
|
|
43235
|
+
padding: var(--swc-spacing-75) var(--swc-spacing-400);
|
|
43236
|
+
border-block: var(--swc-border-width-100) solid var(--swc-gray-200);
|
|
43237
|
+
}
|
|
43238
|
+
.options {
|
|
43239
|
+
display: grid;
|
|
43240
|
+
gap: var(--swc-spacing-50);
|
|
43241
|
+
}
|
|
43242
|
+
.option {
|
|
43243
|
+
display: grid;
|
|
43244
|
+
grid-template-columns: minmax(0, 1fr) max-content;
|
|
43245
|
+
align-items: baseline;
|
|
43246
|
+
gap: var(--swc-spacing-50) var(--swc-spacing-300);
|
|
43247
|
+
padding: var(--swc-spacing-100) var(--swc-spacing-100);
|
|
43248
|
+
border-radius: var(--swc-corner-radius-medium-default);
|
|
43249
|
+
cursor: pointer;
|
|
43250
|
+
}
|
|
43251
|
+
.option:hover,
|
|
43252
|
+
.option:focus {
|
|
43253
|
+
background: var(--swc-gray-200);
|
|
43254
|
+
}
|
|
43255
|
+
.option:focus {
|
|
43256
|
+
outline: none;
|
|
43257
|
+
}
|
|
43258
|
+
.option:focus-visible {
|
|
43259
|
+
outline: var(--swc-focus-indicator-thickness) solid var(--swc-focus-indicator-color);
|
|
43260
|
+
outline-offset: calc(-1 * var(--swc-focus-indicator-thickness));
|
|
43261
|
+
}
|
|
43262
|
+
.option[aria-disabled='true'] {
|
|
43263
|
+
cursor: default;
|
|
43264
|
+
}
|
|
43265
|
+
.option[aria-disabled='true']:hover {
|
|
43266
|
+
background: none;
|
|
43267
|
+
}
|
|
43268
|
+
.option .name {
|
|
43269
|
+
font-weight: var(--swc-bold-font-weight);
|
|
43270
|
+
overflow-wrap: anywhere;
|
|
43271
|
+
}
|
|
43272
|
+
.option[aria-disabled='true'] .name {
|
|
43273
|
+
color: var(--swc-neutral-subdued-content-color-default);
|
|
43274
|
+
}
|
|
43275
|
+
.option .tag {
|
|
43276
|
+
justify-self: end;
|
|
43277
|
+
color: var(--swc-neutral-subdued-content-color-default);
|
|
43278
|
+
font-size: var(--swc-font-size-75);
|
|
43279
|
+
}
|
|
43280
|
+
.added {
|
|
43281
|
+
display: inline-flex;
|
|
43282
|
+
align-items: center;
|
|
43283
|
+
gap: var(--swc-spacing-50);
|
|
43284
|
+
}
|
|
43285
|
+
.option .description,
|
|
43286
|
+
.option .notice {
|
|
43287
|
+
grid-column: 1 / -1;
|
|
43288
|
+
}
|
|
43289
|
+
.option .description,
|
|
43290
|
+
.lead,
|
|
43291
|
+
.empty {
|
|
43292
|
+
margin: 0;
|
|
43293
|
+
color: var(--swc-neutral-subdued-content-color-default);
|
|
43294
|
+
}
|
|
43295
|
+
.empty {
|
|
43296
|
+
padding: var(--swc-spacing-200) var(--swc-spacing-100);
|
|
43297
|
+
overflow-wrap: anywhere;
|
|
43298
|
+
}
|
|
43299
|
+
.picker .end {
|
|
43300
|
+
justify-content: flex-end;
|
|
43301
|
+
padding: var(--swc-spacing-300) var(--swc-spacing-500) var(--swc-spacing-400);
|
|
43302
|
+
}
|
|
43303
|
+
.step {
|
|
43304
|
+
display: grid;
|
|
43305
|
+
gap: var(--swc-spacing-200);
|
|
43306
|
+
padding: var(--swc-spacing-100) var(--swc-spacing-500) var(--swc-spacing-500);
|
|
43307
|
+
}
|
|
43308
|
+
.step .key.stacked {
|
|
43309
|
+
max-width: none;
|
|
43310
|
+
}
|
|
43311
|
+
.step sp-textfield {
|
|
43312
|
+
inline-size: 100%;
|
|
43313
|
+
}
|
|
43314
|
+
.step .buttons {
|
|
43315
|
+
margin-block-start: var(--swc-spacing-200);
|
|
43316
|
+
}
|
|
43317
|
+
.get-key {
|
|
43318
|
+
justify-self: start;
|
|
43319
|
+
font-size: var(--swc-font-size-75);
|
|
43320
|
+
}
|
|
43030
43321
|
@container (max-width: 480px) {
|
|
43031
43322
|
.page {
|
|
43032
43323
|
padding-inline: var(--swc-spacing-300);
|
|
@@ -43057,7 +43348,8 @@ var SliccSettings = class extends ThemedElement {
|
|
|
43057
43348
|
.state {
|
|
43058
43349
|
grid-area: state;
|
|
43059
43350
|
}
|
|
43060
|
-
.account swc-button
|
|
43351
|
+
.account swc-button,
|
|
43352
|
+
.account .actions {
|
|
43061
43353
|
grid-area: action;
|
|
43062
43354
|
}
|
|
43063
43355
|
.key sp-textfield {
|
|
@@ -43077,6 +43369,7 @@ var SliccSettings = class extends ThemedElement {
|
|
|
43077
43369
|
...super.subscribe(model),
|
|
43078
43370
|
model.settings.on("settings", settle2),
|
|
43079
43371
|
model.settings.on("accounts", settle2),
|
|
43372
|
+
model.settings.on("providers", update),
|
|
43080
43373
|
...model.vault ? [model.vault.on("status", update)] : []
|
|
43081
43374
|
];
|
|
43082
43375
|
}
|
|
@@ -43123,6 +43416,7 @@ var SliccSettings = class extends ThemedElement {
|
|
|
43123
43416
|
try {
|
|
43124
43417
|
await (fields ? settings?.connect(id, secret, fields) : secret === void 0 ? settings?.connect(id) : settings?.connect(id, secret));
|
|
43125
43418
|
if (this.entering === id) this.entering = null;
|
|
43419
|
+
if (this.adding?.id === id && this.#added(id)?.status === "connected") this.#finish(id);
|
|
43126
43420
|
} catch (error) {
|
|
43127
43421
|
if (!this.#cancelled.has(id)) this.failure = { id, message: error.message };
|
|
43128
43422
|
} finally {
|
|
@@ -43158,13 +43452,88 @@ var SliccSettings = class extends ThemedElement {
|
|
|
43158
43452
|
this.#busy(id, false);
|
|
43159
43453
|
return;
|
|
43160
43454
|
}
|
|
43161
|
-
await this
|
|
43455
|
+
await this.#connectBases(account, void 0, fields, vault);
|
|
43456
|
+
}
|
|
43457
|
+
#baseOf(value) {
|
|
43458
|
+
const trimmed = value?.trim() ?? "";
|
|
43459
|
+
try {
|
|
43460
|
+
return new URL(trimmed).protocol === "https:" ? trimmed : void 0;
|
|
43461
|
+
} catch {
|
|
43462
|
+
return void 0;
|
|
43463
|
+
}
|
|
43464
|
+
}
|
|
43465
|
+
#oldBase(account, field) {
|
|
43466
|
+
return this.#baseOf(field.value) ?? this.#bases.get(`${account.id} ${field.name}`);
|
|
43467
|
+
}
|
|
43468
|
+
#baseChanges(account, fields) {
|
|
43469
|
+
return (account.fields ?? []).filter((field) => field.customBase).map((field) => ({
|
|
43470
|
+
field: field.name,
|
|
43471
|
+
url: this.#baseOf(fields?.[field.name]),
|
|
43472
|
+
old: this.#oldBase(account, field)
|
|
43473
|
+
})).filter((change) => change.url !== change.old);
|
|
43474
|
+
}
|
|
43475
|
+
#modelChange(name, changes2, from, to) {
|
|
43476
|
+
const entries = (key2) => changes2.flatMap((change) => change[key2] ? [{ name, url: change[key2] }] : []);
|
|
43477
|
+
const remove2 = entries(from);
|
|
43478
|
+
const add = entries(to);
|
|
43479
|
+
if (!remove2.length && !add.length) return null;
|
|
43480
|
+
return {
|
|
43481
|
+
...remove2.length ? { remove: { model: remove2 } } : {},
|
|
43482
|
+
...add.length ? { add: { model: add } } : {}
|
|
43483
|
+
};
|
|
43484
|
+
}
|
|
43485
|
+
async #connectBases(account, secret, fields, vault = null) {
|
|
43486
|
+
const model = this.model;
|
|
43487
|
+
const live = vault?.endpoints ? vault : null;
|
|
43488
|
+
const { id } = account;
|
|
43489
|
+
const name = recordName(account);
|
|
43490
|
+
const changes2 = this.#baseChanges(account, fields);
|
|
43491
|
+
const forward = live ? this.#modelChange(name, changes2, "old", "url") : null;
|
|
43492
|
+
if (forward) {
|
|
43493
|
+
this.#busy(id, true);
|
|
43494
|
+
try {
|
|
43495
|
+
await live?.endpoints?.(forward);
|
|
43496
|
+
} catch (error) {
|
|
43497
|
+
this.#busy(id, false);
|
|
43498
|
+
const field = changes2.find((change) => change.url) ?? changes2[0];
|
|
43499
|
+
if (this.model === model) this.#refuse(id, field.field, failureText(error));
|
|
43500
|
+
return;
|
|
43501
|
+
}
|
|
43502
|
+
if (this.model !== model) {
|
|
43503
|
+
this.#busy(id, false);
|
|
43504
|
+
return;
|
|
43505
|
+
}
|
|
43506
|
+
}
|
|
43507
|
+
await this.connect(id, secret, fields);
|
|
43508
|
+
if (this.failure?.id === id) {
|
|
43509
|
+
this.#placeFailure(account, fields);
|
|
43510
|
+
const back = forward ? this.#modelChange(name, changes2, "url", "old") : null;
|
|
43511
|
+
if (back) await live?.endpoints?.(back).catch(() => {
|
|
43512
|
+
});
|
|
43513
|
+
return;
|
|
43514
|
+
}
|
|
43515
|
+
for (const change of changes2) {
|
|
43516
|
+
const key2 = `${id} ${change.field}`;
|
|
43517
|
+
if (change.url) this.#bases.set(key2, change.url);
|
|
43518
|
+
else this.#bases.delete(key2);
|
|
43519
|
+
}
|
|
43520
|
+
}
|
|
43521
|
+
#placeFailure(account, fields) {
|
|
43522
|
+
const message = this.failure.message;
|
|
43523
|
+
const field = (account.fields ?? []).find(
|
|
43524
|
+
(candidate) => candidate.customBase && !!fields?.[candidate.name] && [candidate.name, candidate.label, "https", "url", "port", "userinfo"].some(
|
|
43525
|
+
(word) => new RegExp(`\\b${word.replace(/[^a-z0-9 ]/gi, "\\$&")}\\b`, "i").test(message)
|
|
43526
|
+
)
|
|
43527
|
+
);
|
|
43528
|
+
if (!field) return;
|
|
43529
|
+
this.failure = null;
|
|
43530
|
+
this.#refuse(account.id, field.name, message);
|
|
43162
43531
|
}
|
|
43163
43532
|
#refuse(id, field, message) {
|
|
43164
43533
|
this.problem = { id, field, message };
|
|
43165
43534
|
void this.updateComplete.then(
|
|
43166
43535
|
() => this.renderRoot.querySelector(
|
|
43167
|
-
field === "value" ? ".key input[data-field=value]" : `.key
|
|
43536
|
+
field === "value" ? ".key input[data-field=value]" : `.key [data-account-field="${field}"]`
|
|
43168
43537
|
)?.focus()
|
|
43169
43538
|
);
|
|
43170
43539
|
}
|
|
@@ -43172,25 +43541,35 @@ var SliccSettings = class extends ThemedElement {
|
|
|
43172
43541
|
if (!account.fields?.length) return void 0;
|
|
43173
43542
|
const values = {};
|
|
43174
43543
|
for (const field of account.fields) {
|
|
43175
|
-
const input = form.querySelector(
|
|
43176
|
-
`input[data-account-field="${field.name}"]`
|
|
43177
|
-
);
|
|
43544
|
+
const input = form.querySelector(`[data-account-field="${field.name}"]`);
|
|
43178
43545
|
const value = input.value.trim();
|
|
43179
43546
|
if (value) values[field.name] = value;
|
|
43180
|
-
else if (field.required) {
|
|
43547
|
+
else if (field.required && field.options?.length !== 0) {
|
|
43181
43548
|
this.#refuse(account.id, field.name, `${field.label} can\u2019t be empty`);
|
|
43182
43549
|
return null;
|
|
43183
43550
|
}
|
|
43184
43551
|
}
|
|
43185
43552
|
return values;
|
|
43186
43553
|
}
|
|
43554
|
+
#added(id) {
|
|
43555
|
+
return this.model?.settings.accounts().find((account) => account.id === id);
|
|
43556
|
+
}
|
|
43557
|
+
#offered() {
|
|
43558
|
+
return this.model?.settings.providers?.() ?? null;
|
|
43559
|
+
}
|
|
43187
43560
|
#start(account) {
|
|
43188
43561
|
if (account.auth !== "api-key") {
|
|
43189
43562
|
void this.connect(account.id);
|
|
43190
43563
|
return;
|
|
43191
43564
|
}
|
|
43565
|
+
this.#enter(account);
|
|
43566
|
+
}
|
|
43567
|
+
#enter(account) {
|
|
43192
43568
|
this.failure = null;
|
|
43193
43569
|
this.problem = null;
|
|
43570
|
+
this.filled = new Set(
|
|
43571
|
+
(account.fields ?? []).filter((field) => field.options || field.value?.trim()).map((field) => field.name)
|
|
43572
|
+
);
|
|
43194
43573
|
this.entering = account.id;
|
|
43195
43574
|
void this.updateComplete.then(() => this.focusOn(".key sp-textfield", ".key input"));
|
|
43196
43575
|
}
|
|
@@ -43198,6 +43577,7 @@ var SliccSettings = class extends ThemedElement {
|
|
|
43198
43577
|
event2.preventDefault();
|
|
43199
43578
|
const form = event2.currentTarget;
|
|
43200
43579
|
this.problem = null;
|
|
43580
|
+
this.filled = new Set([...this.filled].filter((name) => name !== "value"));
|
|
43201
43581
|
if (this.#vault(account)) {
|
|
43202
43582
|
const value = take(form.querySelector("input[data-field=value]"));
|
|
43203
43583
|
const fields2 = this.#fields(form, account);
|
|
@@ -43208,7 +43588,7 @@ var SliccSettings = class extends ThemedElement {
|
|
|
43208
43588
|
const secret = field.value.trim();
|
|
43209
43589
|
field.value = "";
|
|
43210
43590
|
const fields = this.#fields(form, account);
|
|
43211
|
-
if (secret && fields !== null) void this
|
|
43591
|
+
if (secret && fields !== null) void this.#connectBases(account, secret, fields);
|
|
43212
43592
|
}
|
|
43213
43593
|
#submitOnEnter(event2) {
|
|
43214
43594
|
const target2 = event2.target;
|
|
@@ -43219,7 +43599,7 @@ var SliccSettings = class extends ThemedElement {
|
|
|
43219
43599
|
#send(event2) {
|
|
43220
43600
|
event2.currentTarget.closest("form")?.requestSubmit();
|
|
43221
43601
|
}
|
|
43222
|
-
#
|
|
43602
|
+
#enterKey(event2) {
|
|
43223
43603
|
if (event2.key === "Enter") this.#send(event2);
|
|
43224
43604
|
}
|
|
43225
43605
|
#cancel() {
|
|
@@ -43244,17 +43624,64 @@ var SliccSettings = class extends ThemedElement {
|
|
|
43244
43624
|
}
|
|
43245
43625
|
#extra(account) {
|
|
43246
43626
|
return (account.fields ?? []).map(
|
|
43247
|
-
(field) => b`<label class="field"
|
|
43627
|
+
(field) => b`<label class="field">
|
|
43628
|
+
<span>${field.label}</span>${this.#control(account, field)}
|
|
43629
|
+
</label>
|
|
43630
|
+
${field.help ? b`<p class="hint" id=${`help-${field.name}`}>${field.help}</p>` : A}
|
|
43631
|
+
${this.#problem(account, field.name)}`
|
|
43632
|
+
);
|
|
43633
|
+
}
|
|
43634
|
+
#describedBy(account, field) {
|
|
43635
|
+
const problem = this.#described(account, field.name);
|
|
43636
|
+
const ids = [problem === A ? "" : problem, field.help ? `help-${field.name}` : ""];
|
|
43637
|
+
return ids.filter(Boolean).join(" ") || A;
|
|
43638
|
+
}
|
|
43639
|
+
#control(account, field) {
|
|
43640
|
+
if (field.options) {
|
|
43641
|
+
const chosen = field.value ?? field.options[0]?.value;
|
|
43642
|
+
return b`<select
|
|
43643
|
+
data-account-field=${field.name}
|
|
43644
|
+
?disabled=${!field.options.length}
|
|
43645
|
+
aria-required=${field.required ? "true" : A}
|
|
43646
|
+
aria-invalid=${this.#invalid(account, field.name)}
|
|
43647
|
+
aria-describedby=${this.#describedBy(account, field)}
|
|
43648
|
+
>
|
|
43649
|
+
${field.options.map((option2) => b`<option value=${option2.value} ?selected=${option2.value === chosen}>${option2.label}</option>`)}
|
|
43650
|
+
</select>`;
|
|
43651
|
+
}
|
|
43652
|
+
return b`<input
|
|
43248
43653
|
type="text"
|
|
43249
43654
|
autocomplete="off"
|
|
43250
43655
|
spellcheck="false"
|
|
43251
43656
|
data-account-field=${field.name}
|
|
43657
|
+
value=${field.value ?? A}
|
|
43658
|
+
placeholder=${field.placeholder ?? A}
|
|
43252
43659
|
aria-required=${field.required ? "true" : A}
|
|
43253
43660
|
aria-invalid=${this.#invalid(account, field.name)}
|
|
43254
|
-
aria-describedby=${this.#
|
|
43255
|
-
|
|
43256
|
-
|
|
43257
|
-
|
|
43661
|
+
aria-describedby=${this.#describedBy(account, field)}
|
|
43662
|
+
/>`;
|
|
43663
|
+
}
|
|
43664
|
+
#getKey(account) {
|
|
43665
|
+
if (!account.keyUrl) return A;
|
|
43666
|
+
return b`<a class="swc-Link get-key" href=${account.keyUrl} target="_blank" rel="noopener noreferrer" data-action="get-key">Get a key</a>`;
|
|
43667
|
+
}
|
|
43668
|
+
#leave(account) {
|
|
43669
|
+
const adding = this.adding?.id === account.id;
|
|
43670
|
+
return b`<swc-button size="m" variant="secondary" data-action=${adding ? "back" : "cancel"} @click=${() => adding ? this.#back() : this.#cancel()}>${adding ? "Back" : "Cancel"}</swc-button>`;
|
|
43671
|
+
}
|
|
43672
|
+
#saveLabel(account) {
|
|
43673
|
+
return this.adding?.id === account.id ? "Connect" : "Save";
|
|
43674
|
+
}
|
|
43675
|
+
#ready(account) {
|
|
43676
|
+
if (!this.#offered()) return true;
|
|
43677
|
+
const required = (account.fields ?? []).filter((field) => field.required);
|
|
43678
|
+
return ["value", ...required.map((field) => field.name)].every((name) => this.filled.has(name));
|
|
43679
|
+
}
|
|
43680
|
+
#fill(event2) {
|
|
43681
|
+
const input = event2.target;
|
|
43682
|
+
const name = input.dataset.accountField ?? "value";
|
|
43683
|
+
const rest = [...this.filled].filter((candidate) => candidate !== name);
|
|
43684
|
+
this.filled = new Set(input.value.trim() ? [...rest, name] : rest);
|
|
43258
43685
|
}
|
|
43259
43686
|
#unlock(vault) {
|
|
43260
43687
|
return b`<div class="locked" data-locked>
|
|
@@ -43274,7 +43701,7 @@ var SliccSettings = class extends ThemedElement {
|
|
|
43274
43701
|
const busy = this.pending.has(account.id);
|
|
43275
43702
|
const locked = !!vault.status()?.locked;
|
|
43276
43703
|
const name = secretNames[account.secret ?? "api-key"];
|
|
43277
|
-
return b`<form class="key stacked" data-id=${account.id} data-store="vault" @submit=${(event2) => this.#submit(event2, account)} @keydown=${(event2) => this.#submitOnEnter(event2)}>
|
|
43704
|
+
return b`<form class="key stacked" data-id=${account.id} data-store="vault" @submit=${(event2) => this.#submit(event2, account)} @keydown=${(event2) => this.#submitOnEnter(event2)} @input=${(event2) => this.#fill(event2)}>
|
|
43278
43705
|
<label class="field"><span>${account.provider} ${name}</span><input
|
|
43279
43706
|
type="password"
|
|
43280
43707
|
autocomplete="off"
|
|
@@ -43285,11 +43712,12 @@ var SliccSettings = class extends ThemedElement {
|
|
|
43285
43712
|
aria-describedby=${this.#described(account, "value")}
|
|
43286
43713
|
/></label>
|
|
43287
43714
|
${this.#problem(account, "value")}
|
|
43288
|
-
${this.#extra(account)}
|
|
43289
43715
|
${locked ? this.#unlock(vault) : b`<p class="hint">Saved in the vault</p>`}
|
|
43716
|
+
${this.#getKey(account)}
|
|
43717
|
+
${this.#extra(account)}
|
|
43290
43718
|
<div class="buttons">
|
|
43291
|
-
<swc-button size="m" variant="accent" data-action="save" ?pending=${busy} ?disabled=${locked} @click=${(event2) => this.#send(event2)}
|
|
43292
|
-
|
|
43719
|
+
<swc-button size="m" variant="accent" data-action="save" ?pending=${busy} ?disabled=${locked || !busy && !this.#ready(account)} @click=${(event2) => this.#send(event2)}>${this.#saveLabel(account)}</swc-button>
|
|
43720
|
+
${this.#leave(account)}
|
|
43293
43721
|
</div>
|
|
43294
43722
|
</form>`;
|
|
43295
43723
|
}
|
|
@@ -43298,23 +43726,24 @@ var SliccSettings = class extends ThemedElement {
|
|
|
43298
43726
|
const vault = this.#vault(account);
|
|
43299
43727
|
if (vault) return this.#kept(account, vault);
|
|
43300
43728
|
const busy = this.pending.has(account.id);
|
|
43301
|
-
const extra = account.fields?.length;
|
|
43302
|
-
return b`<form class=${extra ? "key stacked" : "key"} data-id=${account.id} @submit=${(event2) => this.#submit(event2, account)} @keydown=${(event2) => this.#submitOnEnter(event2)}>
|
|
43729
|
+
const extra = account.fields?.length || account.keyUrl;
|
|
43730
|
+
return b`<form class=${extra ? "key stacked" : "key"} data-id=${account.id} @submit=${(event2) => this.#submit(event2, account)} @keydown=${(event2) => this.#submitOnEnter(event2)} @input=${(event2) => this.#fill(event2)}>
|
|
43303
43731
|
<sp-textfield
|
|
43304
43732
|
size="m"
|
|
43305
43733
|
type="password"
|
|
43306
43734
|
autocomplete="off"
|
|
43307
43735
|
label=${`${account.provider} ${secretNames[account.secret ?? "api-key"]}`}
|
|
43308
43736
|
placeholder=${`Paste the ${secretNames[account.secret ?? "api-key"]}`}
|
|
43309
|
-
@keydown=${(event2) => this.#
|
|
43737
|
+
@keydown=${(event2) => this.#enterKey(event2)}
|
|
43310
43738
|
></sp-textfield>
|
|
43739
|
+
${this.#getKey(account)}
|
|
43311
43740
|
${extra ? this.#extra(account) : A}
|
|
43312
|
-
${extra ? b`<div class="buttons">${this.#buttons(busy)}</div>` : this.#buttons(busy)}
|
|
43741
|
+
${extra ? b`<div class="buttons">${this.#buttons(account, busy)}</div>` : this.#buttons(account, busy)}
|
|
43313
43742
|
</form>`;
|
|
43314
43743
|
}
|
|
43315
|
-
#buttons(busy) {
|
|
43316
|
-
return b`<swc-button size="m" variant="accent" data-action="save" ?pending=${busy} @click=${(event2) => this.#send(event2)}
|
|
43317
|
-
|
|
43744
|
+
#buttons(account, busy) {
|
|
43745
|
+
return b`<swc-button size="m" variant="accent" data-action="save" ?pending=${busy} ?disabled=${!busy && !this.#ready(account)} @click=${(event2) => this.#send(event2)}>${this.#saveLabel(account)}</swc-button>
|
|
43746
|
+
${this.#leave(account)}`;
|
|
43318
43747
|
}
|
|
43319
43748
|
#inVault(account) {
|
|
43320
43749
|
const vault = this.model?.vault;
|
|
@@ -43366,7 +43795,8 @@ var SliccSettings = class extends ThemedElement {
|
|
|
43366
43795
|
get busyReason() {
|
|
43367
43796
|
const accounts = this.model?.settings.accounts() ?? [];
|
|
43368
43797
|
if (accounts.some((account) => this.#signingIn(account))) return "signing in";
|
|
43369
|
-
|
|
43798
|
+
if (this.entering !== null) return "a key is being entered";
|
|
43799
|
+
return this.picking ? "a provider is being added" : null;
|
|
43370
43800
|
}
|
|
43371
43801
|
#signingIn(account) {
|
|
43372
43802
|
return account.status === "signing-in" || account.auth !== "api-key" && account.status !== "connected" && this.pending.has(account.id);
|
|
@@ -43423,10 +43853,266 @@ var SliccSettings = class extends ThemedElement {
|
|
|
43423
43853
|
<span class="provider">${account.provider}</span>
|
|
43424
43854
|
<span class="identity">${account.identity}${this.#inVault(account) ? b`<span class="kept" data-store="vault">${account.identity ? " \xB7 " : ""}${kept2(account)}</span>` : A}</span>
|
|
43425
43855
|
<swc-status-light class="state" variant=${variant}>${label}</swc-status-light>
|
|
43426
|
-
${this.#action(account)}
|
|
43856
|
+
${this.#removable(account) ? b`<div class="actions">${this.#action(account)}${this.#removeButton(account)}</div>` : this.#action(account)}
|
|
43427
43857
|
</div>
|
|
43428
|
-
${this.#
|
|
43429
|
-
${failure2}`;
|
|
43858
|
+
${this.#offered() ? this.#rowNotes(account) : A}
|
|
43859
|
+
${this.adding?.id === account.id ? A : b`${this.#key(account)}${failure2}`}`;
|
|
43860
|
+
}
|
|
43861
|
+
#removable(account) {
|
|
43862
|
+
return !!this.#offered() && !!this.model?.settings.remove && account.group !== "mcp";
|
|
43863
|
+
}
|
|
43864
|
+
#removeButton(account) {
|
|
43865
|
+
const id = `remove-${account.id}`;
|
|
43866
|
+
const label = `Remove ${account.provider}`;
|
|
43867
|
+
return b`<swc-action-button
|
|
43868
|
+
id=${id}
|
|
43869
|
+
size="m"
|
|
43870
|
+
quiet
|
|
43871
|
+
data-action="remove-account"
|
|
43872
|
+
accessible-label=${label}
|
|
43873
|
+
?disabled=${this.pending.has(account.id)}
|
|
43874
|
+
@click=${() => this.#remove(account)}
|
|
43875
|
+
><swc-icon-delete slot="icon"></swc-icon-delete></swc-action-button
|
|
43876
|
+
><swc-tooltip for=${id} placement="top">${label}</swc-tooltip>`;
|
|
43877
|
+
}
|
|
43878
|
+
async #remove(account) {
|
|
43879
|
+
const model = this.model;
|
|
43880
|
+
const body4 = removeBodies[account.auth ?? ""] ?? "Its key is deleted from the vault. Models from it stop working.";
|
|
43881
|
+
const title = `Remove ${account.provider}?`;
|
|
43882
|
+
if (!await confirm({ title, body: body4, action: "Remove" })) return;
|
|
43883
|
+
if (this.model !== model) return;
|
|
43884
|
+
clearValues(this.renderRoot);
|
|
43885
|
+
if (this.entering === account.id) this.entering = null;
|
|
43886
|
+
const vault = model.vault;
|
|
43887
|
+
const keyed = account.store === "vault" && account.auth === "api-key" && !!vault?.remove;
|
|
43888
|
+
if (keyed && !await this.#forget(account, vault)) return;
|
|
43889
|
+
if (this.model !== model) return;
|
|
43890
|
+
this.#busy(account.id, true);
|
|
43891
|
+
this.failure = null;
|
|
43892
|
+
try {
|
|
43893
|
+
await model.settings.remove?.(account.id);
|
|
43894
|
+
} catch (error) {
|
|
43895
|
+
if (this.model === model) this.failure = { id: account.id, message: failureText(error) };
|
|
43896
|
+
return;
|
|
43897
|
+
} finally {
|
|
43898
|
+
this.#busy(account.id, false);
|
|
43899
|
+
}
|
|
43900
|
+
this.focusOn("[data-action=add-provider]");
|
|
43901
|
+
for (const field of account.fields ?? []) this.#bases.delete(`${account.id} ${field.name}`);
|
|
43902
|
+
}
|
|
43903
|
+
#notice(needs, size4 = "long") {
|
|
43904
|
+
if (needs !== "cors-free-transport") return A;
|
|
43905
|
+
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>`;
|
|
43906
|
+
}
|
|
43907
|
+
#signingNote(account) {
|
|
43908
|
+
const key2 = `settings:${account.id}`;
|
|
43909
|
+
if (account.auth !== "oauth" || !this.#signingIn(account)) {
|
|
43910
|
+
this.#waits.done(key2);
|
|
43911
|
+
return A;
|
|
43912
|
+
}
|
|
43913
|
+
return b`<p class="hint" role="status" data-signing>${signInText(this.#waits.waited(key2))}</p>`;
|
|
43914
|
+
}
|
|
43915
|
+
#rowNotes(account) {
|
|
43916
|
+
const notice = this.#notice(account.needs);
|
|
43917
|
+
const signing = this.adding?.id === account.id ? A : this.#signingNote(account);
|
|
43918
|
+
if (notice === A && signing === A) return A;
|
|
43919
|
+
return b`<div class="notes">${notice}${signing}</div>`;
|
|
43920
|
+
}
|
|
43921
|
+
#openPicker() {
|
|
43922
|
+
this.query = "";
|
|
43923
|
+
this.adding = null;
|
|
43924
|
+
this.picking = true;
|
|
43925
|
+
}
|
|
43926
|
+
updated(changed) {
|
|
43927
|
+
super.updated(changed);
|
|
43928
|
+
const dialog = this.#dialog;
|
|
43929
|
+
if (!changed.has("picking") || !dialog || dialog.open) return;
|
|
43930
|
+
dialog.showModal();
|
|
43931
|
+
const field = this.renderRoot.querySelector("sp-search");
|
|
43932
|
+
void field.updateComplete.then(() => field.focus());
|
|
43933
|
+
}
|
|
43934
|
+
get #dialog() {
|
|
43935
|
+
return this.renderRoot.querySelector("dialog.picker");
|
|
43936
|
+
}
|
|
43937
|
+
#closePicker() {
|
|
43938
|
+
this.#dialog?.close();
|
|
43939
|
+
}
|
|
43940
|
+
#closed() {
|
|
43941
|
+
const id = this.adding?.id;
|
|
43942
|
+
if (id !== void 0 && this.entering === id) {
|
|
43943
|
+
clearValues(this.renderRoot);
|
|
43944
|
+
this.entering = null;
|
|
43945
|
+
this.problem = null;
|
|
43946
|
+
}
|
|
43947
|
+
if (id !== void 0 && this.failure?.id === id) this.failure = null;
|
|
43948
|
+
this.picking = false;
|
|
43949
|
+
this.adding = null;
|
|
43950
|
+
this.query = "";
|
|
43951
|
+
const landing = this.#landing;
|
|
43952
|
+
this.#landing = null;
|
|
43953
|
+
void this.updateComplete.then(() => {
|
|
43954
|
+
const root2 = this.renderRoot;
|
|
43955
|
+
const row = landing ? root2.querySelector(`.account[data-id="${CSS.escape(landing)}"] swc-button`) : null;
|
|
43956
|
+
(row ?? root2.querySelector("[data-action=add-provider]"))?.focus();
|
|
43957
|
+
});
|
|
43958
|
+
}
|
|
43959
|
+
#finish(id) {
|
|
43960
|
+
this.#landing = id;
|
|
43961
|
+
this.#closePicker();
|
|
43962
|
+
}
|
|
43963
|
+
#choose(option2) {
|
|
43964
|
+
if (this.#added(option2.id)) return;
|
|
43965
|
+
this.adding = option2;
|
|
43966
|
+
this.failure = null;
|
|
43967
|
+
if (option2.auth === "api-key" || option2.auth === "fields") {
|
|
43968
|
+
this.#enter(draft(option2));
|
|
43969
|
+
return;
|
|
43970
|
+
}
|
|
43971
|
+
void this.updateComplete.then(
|
|
43972
|
+
() => this.focusOn("[data-step] [data-action=sign-in]", "[data-step] [data-action=connect]")
|
|
43973
|
+
);
|
|
43974
|
+
}
|
|
43975
|
+
#back() {
|
|
43976
|
+
const id = this.adding.id;
|
|
43977
|
+
clearValues(this.renderRoot);
|
|
43978
|
+
if (this.entering === id) this.entering = null;
|
|
43979
|
+
if (this.failure?.id === id) this.failure = null;
|
|
43980
|
+
this.problem = null;
|
|
43981
|
+
this.adding = null;
|
|
43982
|
+
void this.updateComplete.then(
|
|
43983
|
+
() => this.renderRoot.querySelector(`.option[data-provider="${CSS.escape(id)}"]`)?.focus()
|
|
43984
|
+
);
|
|
43985
|
+
}
|
|
43986
|
+
#options() {
|
|
43987
|
+
return [...this.renderRoot.querySelectorAll(".option")];
|
|
43988
|
+
}
|
|
43989
|
+
#pickerKey(event2) {
|
|
43990
|
+
if (event2.key !== "Escape") return;
|
|
43991
|
+
event2.preventDefault();
|
|
43992
|
+
this.#closePicker();
|
|
43993
|
+
}
|
|
43994
|
+
#searchKey(event2) {
|
|
43995
|
+
if (event2.key === "ArrowDown") {
|
|
43996
|
+
event2.preventDefault();
|
|
43997
|
+
this.#options()[0]?.focus();
|
|
43998
|
+
return;
|
|
43999
|
+
}
|
|
44000
|
+
if (event2.key !== "Enter") return;
|
|
44001
|
+
event2.preventDefault();
|
|
44002
|
+
const first2 = matchProviders(this.#offered() ?? [], this.query).find(
|
|
44003
|
+
(option2) => !this.#added(option2.id)
|
|
44004
|
+
);
|
|
44005
|
+
if (first2) this.#choose(first2);
|
|
44006
|
+
}
|
|
44007
|
+
#optionKey(event2, option2) {
|
|
44008
|
+
const options = this.#options();
|
|
44009
|
+
const at = options.indexOf(event2.currentTarget);
|
|
44010
|
+
const moves = {
|
|
44011
|
+
ArrowDown: Math.min(at + 1, options.length - 1),
|
|
44012
|
+
ArrowUp: at - 1,
|
|
44013
|
+
Home: 0,
|
|
44014
|
+
End: options.length - 1
|
|
44015
|
+
};
|
|
44016
|
+
const typed3 = event2.key.length === 1 && !event2.ctrlKey && !event2.metaKey && !event2.altKey;
|
|
44017
|
+
if (event2.key in moves) {
|
|
44018
|
+
const to = moves[event2.key];
|
|
44019
|
+
if (to < 0) this.focusOn("sp-search");
|
|
44020
|
+
else options[to].focus();
|
|
44021
|
+
} else if (event2.key === "Enter" || event2.key === " ") this.#choose(option2);
|
|
44022
|
+
else if (typed3 || event2.key === "Backspace") {
|
|
44023
|
+
this.query = typed3 ? this.query + event2.key : this.query.slice(0, -1);
|
|
44024
|
+
this.focusOn("sp-search");
|
|
44025
|
+
} else return;
|
|
44026
|
+
event2.preventDefault();
|
|
44027
|
+
}
|
|
44028
|
+
#option(option2) {
|
|
44029
|
+
const added = !!this.#added(option2.id);
|
|
44030
|
+
return b`<div
|
|
44031
|
+
class="option"
|
|
44032
|
+
role="option"
|
|
44033
|
+
tabindex="-1"
|
|
44034
|
+
data-provider=${option2.id}
|
|
44035
|
+
data-auth=${option2.auth}
|
|
44036
|
+
aria-disabled=${added ? "true" : "false"}
|
|
44037
|
+
@click=${() => this.#choose(option2)}
|
|
44038
|
+
@keydown=${(event2) => this.#optionKey(event2, option2)}
|
|
44039
|
+
>
|
|
44040
|
+
<span class="name">${option2.name}</span>
|
|
44041
|
+
<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>
|
|
44042
|
+
${option2.description ? b`<span class="description">${option2.description}</span>` : A}
|
|
44043
|
+
${this.#notice(option2.needs, "short")}
|
|
44044
|
+
</div>`;
|
|
44045
|
+
}
|
|
44046
|
+
#pickStep(offered) {
|
|
44047
|
+
const matches2 = matchProviders(offered, this.query);
|
|
44048
|
+
return b`<div class="find">${search({
|
|
44049
|
+
label: "Search providers",
|
|
44050
|
+
value: this.query,
|
|
44051
|
+
input: (value) => {
|
|
44052
|
+
this.query = value;
|
|
44053
|
+
},
|
|
44054
|
+
keydown: (event2) => this.#searchKey(event2)
|
|
44055
|
+
})}</div>
|
|
44056
|
+
<div class="results">${matches2.length ? b`<div class="options" role="listbox" aria-label="Providers">${matches2.map((option2) => this.#option(option2))}</div>` : b`<p class="empty" role="status">No provider matches “${this.query.trim()}”.</p>`}</div>
|
|
44057
|
+
<div class="buttons end">
|
|
44058
|
+
<swc-button size="m" variant="secondary" data-action="close" @click=${() => this.#closePicker()}>Cancel</swc-button>
|
|
44059
|
+
</div>`;
|
|
44060
|
+
}
|
|
44061
|
+
#signInStep(account) {
|
|
44062
|
+
const signing = this.#signingIn(account);
|
|
44063
|
+
const cancel = signing && !!this.model?.settings.cancel;
|
|
44064
|
+
return b`<p class="hint">Sign in to ${account.provider} in a new window.</p>
|
|
44065
|
+
${signing ? this.#signingNote(account) : A}
|
|
44066
|
+
<div class="buttons">
|
|
44067
|
+
${cancel ? b`<swc-button size="m" variant="secondary" data-action="cancel-sign-in" @click=${() => this.#stopSigningIn(account)}>Cancel</swc-button>` : A}
|
|
44068
|
+
<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>
|
|
44069
|
+
${signing ? A : this.#leave(account)}
|
|
44070
|
+
</div>`;
|
|
44071
|
+
}
|
|
44072
|
+
#localStep(account) {
|
|
44073
|
+
return b`<p class="hint">SLICC connects to ${account.provider} on this device.</p>
|
|
44074
|
+
<div class="buttons">
|
|
44075
|
+
<swc-button size="m" variant="accent" data-action="connect" ?pending=${this.pending.has(account.id)} @click=${() => this.connect(account.id)}>Connect</swc-button>
|
|
44076
|
+
${this.#leave(account)}
|
|
44077
|
+
</div>`;
|
|
44078
|
+
}
|
|
44079
|
+
#connectStep(option2) {
|
|
44080
|
+
const account = this.#added(option2.id) ?? draft(option2);
|
|
44081
|
+
const step = option2.auth === "oauth" ? this.#signInStep(account) : option2.auth === "local" ? this.#localStep(account) : this.#key(account);
|
|
44082
|
+
return b`<div class="step" data-step=${option2.auth} data-provider=${option2.id}>
|
|
44083
|
+
${option2.description ? b`<p class="lead">${option2.description}</p>` : A}
|
|
44084
|
+
${this.#notice(option2.needs)}
|
|
44085
|
+
${step}
|
|
44086
|
+
${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}
|
|
44087
|
+
</div>`;
|
|
44088
|
+
}
|
|
44089
|
+
#picker(offered) {
|
|
44090
|
+
if (!this.picking) return A;
|
|
44091
|
+
const adding = this.adding;
|
|
44092
|
+
return b`<dialog class="picker" aria-labelledby="picker-title" data-picker=${adding ? "connect" : "pick"} @keydown=${(event2) => this.#pickerKey(event2)} @close=${() => this.#closed()}>
|
|
44093
|
+
<div class="head">
|
|
44094
|
+
<h2 id="picker-title">${adding ? `Add ${adding.name}` : "Add a provider"}</h2>
|
|
44095
|
+
<swc-close-button size="m" data-action="close" accessible-label="Close" @click=${() => this.#closePicker()}></swc-close-button>
|
|
44096
|
+
</div>
|
|
44097
|
+
${adding ? this.#connectStep(adding) : this.#pickStep(offered)}
|
|
44098
|
+
</dialog>`;
|
|
44099
|
+
}
|
|
44100
|
+
#providerList(accounts) {
|
|
44101
|
+
const offered = this.#offered();
|
|
44102
|
+
if (!offered)
|
|
44103
|
+
return b`<div class="accounts">${accounts.map((account) => this.#account(account))}</div>`;
|
|
44104
|
+
const sorted = [...accounts].sort((a23, b13) => listOrder[a23.status] - listOrder[b13.status]);
|
|
44105
|
+
return b`<div class="accounts" data-group="providers">${c(
|
|
44106
|
+
sorted,
|
|
44107
|
+
(account) => account.id,
|
|
44108
|
+
(account) => this.#account(account)
|
|
44109
|
+
)}</div>
|
|
44110
|
+
<div class="add">
|
|
44111
|
+
<swc-action-button size="m" quiet data-action="add-provider" @click=${() => this.#openPicker()}>
|
|
44112
|
+
<swc-icon-add slot="icon"></swc-icon-add>Add a provider
|
|
44113
|
+
</swc-action-button>
|
|
44114
|
+
</div>
|
|
44115
|
+
${this.#picker(offered)}`;
|
|
43430
44116
|
}
|
|
43431
44117
|
render() {
|
|
43432
44118
|
const settings = this.model?.settings;
|
|
@@ -43482,7 +44168,7 @@ var SliccSettings = class extends ThemedElement {
|
|
|
43482
44168
|
</div>
|
|
43483
44169
|
</div>
|
|
43484
44170
|
<h2 data-section="accounts">Accounts</h2>
|
|
43485
|
-
|
|
44171
|
+
${this.#providerList(providers)}
|
|
43486
44172
|
${servers.length ? b`<h2>MCP servers</h2>
|
|
43487
44173
|
<div class="accounts" data-group="mcp">${servers.map((account) => this.#account(account))}</div>` : A}
|
|
43488
44174
|
${this.model?.vault ? b`<slicc-secrets .model=${this.model}></slicc-secrets>` : A}
|