@ai-ecoverse/slicc-spectrum 1.92.0 → 1.93.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 +10 -3
- package/dist/chunk-RYA3OPGE.js +1885 -0
- package/dist/chunk-RYA3OPGE.js.map +7 -0
- package/dist/slicc-dummy.js +103 -1616
- package/dist/slicc-dummy.js.map +4 -4
- package/dist/slicc-kernel-model.js +1 -1
- package/dist/slicc-ui.js +656 -55
- 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/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 +4 -2
- package/dist/types/dummy/vault.d.ts +4 -2
- package/dist/types/dummy.d.ts +1 -0
- package/dist/types/model/types.d.ts +37 -0
- package/package.json +1 -1
- package/dist/chunk-3CM23WFV.js +0 -122
- package/dist/chunk-3CM23WFV.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
|
-
|
|
25131
|
-
|
|
25132
|
-
|
|
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;
|
|
25161
|
+
}
|
|
25162
|
+
static set closedAfter(after) {
|
|
25163
|
+
signInWait.closedAfter = after;
|
|
25140
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
|
}
|
|
@@ -40422,7 +40448,7 @@ var SliccComposer = class extends ThemedElement {
|
|
|
40422
40448
|
clearValues(this.renderRoot);
|
|
40423
40449
|
const held = [
|
|
40424
40450
|
this.attachments,
|
|
40425
|
-
...[...this.#drafts.values()].map((
|
|
40451
|
+
...[...this.#drafts.values()].map((draft2) => draft2.attachments)
|
|
40426
40452
|
];
|
|
40427
40453
|
if (held.flat().some((attachment2) => attachment2.url?.startsWith("blob:")))
|
|
40428
40454
|
this.#abandon = setTimeout(() => {
|
|
@@ -40478,10 +40504,10 @@ var SliccComposer = class extends ThemedElement {
|
|
|
40478
40504
|
#switch(id) {
|
|
40479
40505
|
if (this.#agent)
|
|
40480
40506
|
this.#drafts.set(this.#agent, { value: this.value, attachments: this.attachments });
|
|
40481
|
-
const
|
|
40507
|
+
const draft2 = this.#drafts.get(id);
|
|
40482
40508
|
this.#agent = id;
|
|
40483
|
-
this.value =
|
|
40484
|
-
this.attachments =
|
|
40509
|
+
this.value = draft2?.value ?? "";
|
|
40510
|
+
this.attachments = draft2?.attachments ?? [];
|
|
40485
40511
|
this.popup = null;
|
|
40486
40512
|
this.#history = -1;
|
|
40487
40513
|
}
|
|
@@ -40534,8 +40560,8 @@ var SliccComposer = class extends ThemedElement {
|
|
|
40534
40560
|
this.failure = null;
|
|
40535
40561
|
this.#history = -1;
|
|
40536
40562
|
model.agent.send(this.#agent, text2).catch((error) => {
|
|
40537
|
-
const
|
|
40538
|
-
this.value =
|
|
40563
|
+
const draft2 = this.value.trim();
|
|
40564
|
+
this.value = draft2 && draft2 !== text2 ? `${text2}
|
|
40539
40565
|
${this.value}` : text2;
|
|
40540
40566
|
this.failure = error instanceof Error ? error.message : String(error);
|
|
40541
40567
|
});
|
|
@@ -42873,6 +42899,7 @@ function recordKind(account) {
|
|
|
42873
42899
|
return account.group === "mcp" ? "mcp" : "model";
|
|
42874
42900
|
}
|
|
42875
42901
|
function recordName(account) {
|
|
42902
|
+
if (account.vaultName) return account.vaultName;
|
|
42876
42903
|
if (account.group === "mcp") return `MCP_${upper(serverOf(account))}_TOKEN`;
|
|
42877
42904
|
return envNames[account.id] ?? `${upper(account.id)}_API_KEY`;
|
|
42878
42905
|
}
|
|
@@ -42887,6 +42914,48 @@ var accountStatus = {
|
|
|
42887
42914
|
"needs-sign-in": ["neutral", "Needs sign-in"],
|
|
42888
42915
|
"sign-in-expired": ["notice", "Sign-in expired"]
|
|
42889
42916
|
};
|
|
42917
|
+
var authHints = {
|
|
42918
|
+
"api-key": "API key",
|
|
42919
|
+
oauth: "Sign in",
|
|
42920
|
+
fields: "Endpoint and key",
|
|
42921
|
+
local: "On this device"
|
|
42922
|
+
};
|
|
42923
|
+
var listOrder = {
|
|
42924
|
+
connected: 0,
|
|
42925
|
+
expired: 1,
|
|
42926
|
+
"signing-in": 2,
|
|
42927
|
+
disconnected: 3
|
|
42928
|
+
};
|
|
42929
|
+
var corsNotice = {
|
|
42930
|
+
short: "Needs the SLICC extension or CLI",
|
|
42931
|
+
long: "Needs the SLICC extension or CLI, because the browser blocks direct requests to it."
|
|
42932
|
+
};
|
|
42933
|
+
var removeBodies = {
|
|
42934
|
+
oauth: "Its sign-in is deleted from the vault. Models from it stop working.",
|
|
42935
|
+
local: "Models from it stop working."
|
|
42936
|
+
};
|
|
42937
|
+
function draft(option2) {
|
|
42938
|
+
return {
|
|
42939
|
+
id: option2.id,
|
|
42940
|
+
provider: option2.name,
|
|
42941
|
+
identity: "",
|
|
42942
|
+
status: "disconnected",
|
|
42943
|
+
group: "providers",
|
|
42944
|
+
store: "vault",
|
|
42945
|
+
auth: option2.auth === "fields" ? "api-key" : option2.auth,
|
|
42946
|
+
fields: option2.fields,
|
|
42947
|
+
keyUrl: option2.keyUrl,
|
|
42948
|
+
needs: option2.needs,
|
|
42949
|
+
vaultName: option2.vaultName
|
|
42950
|
+
};
|
|
42951
|
+
}
|
|
42952
|
+
function matchProviders(options, query) {
|
|
42953
|
+
const words = query.trim().toLowerCase().split(/\s+/).filter(Boolean);
|
|
42954
|
+
return options.filter((option2) => {
|
|
42955
|
+
const text2 = `${option2.name} ${option2.id} ${option2.description ?? ""}`.toLowerCase();
|
|
42956
|
+
return words.every((word) => text2.includes(word));
|
|
42957
|
+
});
|
|
42958
|
+
}
|
|
42890
42959
|
var popup = (account) => account.group === "mcp" && account.auth === "oauth";
|
|
42891
42960
|
var secretNames = { "api-key": "API key", token: "token" };
|
|
42892
42961
|
var rejectedNames = { "api-key": "API key rejected", token: "Token rejected" };
|
|
@@ -42906,8 +42975,15 @@ var SliccSettings = class extends ThemedElement {
|
|
|
42906
42975
|
entering: { state: true },
|
|
42907
42976
|
failure: { state: true },
|
|
42908
42977
|
problem: { state: true },
|
|
42909
|
-
blocked: { state: true }
|
|
42978
|
+
blocked: { state: true },
|
|
42979
|
+
picking: { state: true },
|
|
42980
|
+
adding: { state: true },
|
|
42981
|
+
query: { state: true },
|
|
42982
|
+
filled: { state: true }
|
|
42910
42983
|
};
|
|
42984
|
+
#waits = new SignInWaits(() => this.requestUpdate());
|
|
42985
|
+
#landing = null;
|
|
42986
|
+
#bases = /* @__PURE__ */ new Map();
|
|
42911
42987
|
#scroll = new ViewScroll(this, "settings:scroll", { scroller: () => this, rows: "[data-id]" });
|
|
42912
42988
|
constructor() {
|
|
42913
42989
|
super();
|
|
@@ -42916,9 +42992,16 @@ var SliccSettings = class extends ThemedElement {
|
|
|
42916
42992
|
this.failure = null;
|
|
42917
42993
|
this.problem = null;
|
|
42918
42994
|
this.blocked = false;
|
|
42995
|
+
this.picking = false;
|
|
42996
|
+
this.adding = null;
|
|
42997
|
+
this.query = "";
|
|
42998
|
+
this.filled = /* @__PURE__ */ new Set();
|
|
42919
42999
|
}
|
|
42920
43000
|
static styles = [
|
|
42921
43001
|
fieldStyles,
|
|
43002
|
+
dialogFrame,
|
|
43003
|
+
searchCss,
|
|
43004
|
+
r(link_default),
|
|
42922
43005
|
i`
|
|
42923
43006
|
:host {
|
|
42924
43007
|
display: block;
|
|
@@ -43030,6 +43113,144 @@ var SliccSettings = class extends ThemedElement {
|
|
|
43030
43113
|
line-height: var(--swc-line-height-200);
|
|
43031
43114
|
--swc-icon-color: var(--swc-negative-content-color-default);
|
|
43032
43115
|
}
|
|
43116
|
+
.actions {
|
|
43117
|
+
display: flex;
|
|
43118
|
+
align-items: center;
|
|
43119
|
+
gap: var(--swc-spacing-75);
|
|
43120
|
+
}
|
|
43121
|
+
.notes {
|
|
43122
|
+
grid-column: 1 / -1;
|
|
43123
|
+
display: grid;
|
|
43124
|
+
gap: var(--swc-spacing-75);
|
|
43125
|
+
margin-block-start: calc(-1 * var(--swc-spacing-200));
|
|
43126
|
+
}
|
|
43127
|
+
.notice {
|
|
43128
|
+
display: flex;
|
|
43129
|
+
align-items: flex-start;
|
|
43130
|
+
gap: var(--swc-spacing-75);
|
|
43131
|
+
margin: 0;
|
|
43132
|
+
color: var(--swc-neutral-subdued-content-color-default);
|
|
43133
|
+
font-size: var(--swc-font-size-75);
|
|
43134
|
+
line-height: var(--swc-line-height-200);
|
|
43135
|
+
--swc-icon-color: var(--swc-notice-visual-color);
|
|
43136
|
+
}
|
|
43137
|
+
.notice swc-icon-alert-triangle {
|
|
43138
|
+
flex: none;
|
|
43139
|
+
margin-block-start: var(--swc-spacing-50);
|
|
43140
|
+
}
|
|
43141
|
+
.add {
|
|
43142
|
+
margin-block-start: var(--swc-spacing-200);
|
|
43143
|
+
margin-inline-start: calc(-1 * var(--swc-spacing-100));
|
|
43144
|
+
}
|
|
43145
|
+
dialog.picker {
|
|
43146
|
+
inline-size: min(520px, calc(100vw - 2 * var(--swc-spacing-300)));
|
|
43147
|
+
}
|
|
43148
|
+
.picker .head {
|
|
43149
|
+
display: flex;
|
|
43150
|
+
align-items: center;
|
|
43151
|
+
justify-content: space-between;
|
|
43152
|
+
gap: var(--swc-spacing-200);
|
|
43153
|
+
padding: var(--swc-spacing-400) var(--swc-spacing-300) var(--swc-spacing-200) var(--swc-spacing-500);
|
|
43154
|
+
}
|
|
43155
|
+
.picker h2 {
|
|
43156
|
+
margin: 0;
|
|
43157
|
+
font-size: var(--swc-heading-size-s);
|
|
43158
|
+
overflow-wrap: anywhere;
|
|
43159
|
+
}
|
|
43160
|
+
.picker .find {
|
|
43161
|
+
display: flex;
|
|
43162
|
+
padding: var(--swc-spacing-100) var(--swc-spacing-500) var(--swc-spacing-200);
|
|
43163
|
+
}
|
|
43164
|
+
.picker .results {
|
|
43165
|
+
block-size: min(400px, calc(100dvh - 280px));
|
|
43166
|
+
overflow-y: auto;
|
|
43167
|
+
overscroll-behavior: contain;
|
|
43168
|
+
padding: var(--swc-spacing-75) var(--swc-spacing-400);
|
|
43169
|
+
border-block: var(--swc-border-width-100) solid var(--swc-gray-200);
|
|
43170
|
+
}
|
|
43171
|
+
.options {
|
|
43172
|
+
display: grid;
|
|
43173
|
+
gap: var(--swc-spacing-50);
|
|
43174
|
+
}
|
|
43175
|
+
.option {
|
|
43176
|
+
display: grid;
|
|
43177
|
+
grid-template-columns: minmax(0, 1fr) max-content;
|
|
43178
|
+
align-items: baseline;
|
|
43179
|
+
gap: var(--swc-spacing-50) var(--swc-spacing-300);
|
|
43180
|
+
padding: var(--swc-spacing-100) var(--swc-spacing-100);
|
|
43181
|
+
border-radius: var(--swc-corner-radius-medium-default);
|
|
43182
|
+
cursor: pointer;
|
|
43183
|
+
}
|
|
43184
|
+
.option:hover,
|
|
43185
|
+
.option:focus {
|
|
43186
|
+
background: var(--swc-gray-200);
|
|
43187
|
+
}
|
|
43188
|
+
.option:focus {
|
|
43189
|
+
outline: none;
|
|
43190
|
+
}
|
|
43191
|
+
.option:focus-visible {
|
|
43192
|
+
outline: var(--swc-focus-indicator-thickness) solid var(--swc-focus-indicator-color);
|
|
43193
|
+
outline-offset: calc(-1 * var(--swc-focus-indicator-thickness));
|
|
43194
|
+
}
|
|
43195
|
+
.option[aria-disabled='true'] {
|
|
43196
|
+
cursor: default;
|
|
43197
|
+
}
|
|
43198
|
+
.option[aria-disabled='true']:hover {
|
|
43199
|
+
background: none;
|
|
43200
|
+
}
|
|
43201
|
+
.option .name {
|
|
43202
|
+
font-weight: var(--swc-bold-font-weight);
|
|
43203
|
+
overflow-wrap: anywhere;
|
|
43204
|
+
}
|
|
43205
|
+
.option[aria-disabled='true'] .name {
|
|
43206
|
+
color: var(--swc-neutral-subdued-content-color-default);
|
|
43207
|
+
}
|
|
43208
|
+
.option .tag {
|
|
43209
|
+
justify-self: end;
|
|
43210
|
+
color: var(--swc-neutral-subdued-content-color-default);
|
|
43211
|
+
font-size: var(--swc-font-size-75);
|
|
43212
|
+
}
|
|
43213
|
+
.added {
|
|
43214
|
+
display: inline-flex;
|
|
43215
|
+
align-items: center;
|
|
43216
|
+
gap: var(--swc-spacing-50);
|
|
43217
|
+
}
|
|
43218
|
+
.option .description,
|
|
43219
|
+
.option .notice {
|
|
43220
|
+
grid-column: 1 / -1;
|
|
43221
|
+
}
|
|
43222
|
+
.option .description,
|
|
43223
|
+
.lead,
|
|
43224
|
+
.empty {
|
|
43225
|
+
margin: 0;
|
|
43226
|
+
color: var(--swc-neutral-subdued-content-color-default);
|
|
43227
|
+
}
|
|
43228
|
+
.empty {
|
|
43229
|
+
padding: var(--swc-spacing-200) var(--swc-spacing-100);
|
|
43230
|
+
overflow-wrap: anywhere;
|
|
43231
|
+
}
|
|
43232
|
+
.picker .end {
|
|
43233
|
+
justify-content: flex-end;
|
|
43234
|
+
padding: var(--swc-spacing-300) var(--swc-spacing-500) var(--swc-spacing-400);
|
|
43235
|
+
}
|
|
43236
|
+
.step {
|
|
43237
|
+
display: grid;
|
|
43238
|
+
gap: var(--swc-spacing-200);
|
|
43239
|
+
padding: var(--swc-spacing-100) var(--swc-spacing-500) var(--swc-spacing-500);
|
|
43240
|
+
}
|
|
43241
|
+
.step .key.stacked {
|
|
43242
|
+
max-width: none;
|
|
43243
|
+
}
|
|
43244
|
+
.step sp-textfield {
|
|
43245
|
+
inline-size: 100%;
|
|
43246
|
+
}
|
|
43247
|
+
.step .buttons {
|
|
43248
|
+
margin-block-start: var(--swc-spacing-200);
|
|
43249
|
+
}
|
|
43250
|
+
.get-key {
|
|
43251
|
+
justify-self: start;
|
|
43252
|
+
font-size: var(--swc-font-size-75);
|
|
43253
|
+
}
|
|
43033
43254
|
@container (max-width: 480px) {
|
|
43034
43255
|
.page {
|
|
43035
43256
|
padding-inline: var(--swc-spacing-300);
|
|
@@ -43060,7 +43281,8 @@ var SliccSettings = class extends ThemedElement {
|
|
|
43060
43281
|
.state {
|
|
43061
43282
|
grid-area: state;
|
|
43062
43283
|
}
|
|
43063
|
-
.account swc-button
|
|
43284
|
+
.account swc-button,
|
|
43285
|
+
.account .actions {
|
|
43064
43286
|
grid-area: action;
|
|
43065
43287
|
}
|
|
43066
43288
|
.key sp-textfield {
|
|
@@ -43080,6 +43302,7 @@ var SliccSettings = class extends ThemedElement {
|
|
|
43080
43302
|
...super.subscribe(model),
|
|
43081
43303
|
model.settings.on("settings", settle2),
|
|
43082
43304
|
model.settings.on("accounts", settle2),
|
|
43305
|
+
model.settings.on("providers", update),
|
|
43083
43306
|
...model.vault ? [model.vault.on("status", update)] : []
|
|
43084
43307
|
];
|
|
43085
43308
|
}
|
|
@@ -43126,6 +43349,7 @@ var SliccSettings = class extends ThemedElement {
|
|
|
43126
43349
|
try {
|
|
43127
43350
|
await (fields ? settings?.connect(id, secret, fields) : secret === void 0 ? settings?.connect(id) : settings?.connect(id, secret));
|
|
43128
43351
|
if (this.entering === id) this.entering = null;
|
|
43352
|
+
if (this.adding?.id === id && this.#added(id)?.status === "connected") this.#finish(id);
|
|
43129
43353
|
} catch (error) {
|
|
43130
43354
|
if (!this.#cancelled.has(id)) this.failure = { id, message: error.message };
|
|
43131
43355
|
} finally {
|
|
@@ -43161,7 +43385,82 @@ var SliccSettings = class extends ThemedElement {
|
|
|
43161
43385
|
this.#busy(id, false);
|
|
43162
43386
|
return;
|
|
43163
43387
|
}
|
|
43164
|
-
await this
|
|
43388
|
+
await this.#connectBases(account, void 0, fields, vault);
|
|
43389
|
+
}
|
|
43390
|
+
#baseOf(value) {
|
|
43391
|
+
const trimmed = value?.trim() ?? "";
|
|
43392
|
+
try {
|
|
43393
|
+
return new URL(trimmed).protocol === "https:" ? trimmed : void 0;
|
|
43394
|
+
} catch {
|
|
43395
|
+
return void 0;
|
|
43396
|
+
}
|
|
43397
|
+
}
|
|
43398
|
+
#oldBase(account, field) {
|
|
43399
|
+
return this.#baseOf(field.value) ?? this.#bases.get(`${account.id} ${field.name}`);
|
|
43400
|
+
}
|
|
43401
|
+
#baseChanges(account, fields) {
|
|
43402
|
+
return (account.fields ?? []).filter((field) => field.customBase).map((field) => ({
|
|
43403
|
+
field: field.name,
|
|
43404
|
+
url: this.#baseOf(fields?.[field.name]),
|
|
43405
|
+
old: this.#oldBase(account, field)
|
|
43406
|
+
})).filter((change) => change.url !== change.old);
|
|
43407
|
+
}
|
|
43408
|
+
#modelChange(name, changes2, from, to) {
|
|
43409
|
+
const entries = (key2) => changes2.flatMap((change) => change[key2] ? [{ name, url: change[key2] }] : []);
|
|
43410
|
+
const remove2 = entries(from);
|
|
43411
|
+
const add = entries(to);
|
|
43412
|
+
if (!remove2.length && !add.length) return null;
|
|
43413
|
+
return {
|
|
43414
|
+
...remove2.length ? { remove: { model: remove2 } } : {},
|
|
43415
|
+
...add.length ? { add: { model: add } } : {}
|
|
43416
|
+
};
|
|
43417
|
+
}
|
|
43418
|
+
async #connectBases(account, secret, fields, vault = null) {
|
|
43419
|
+
const model = this.model;
|
|
43420
|
+
const live = vault?.endpoints ? vault : null;
|
|
43421
|
+
const { id } = account;
|
|
43422
|
+
const name = recordName(account);
|
|
43423
|
+
const changes2 = this.#baseChanges(account, fields);
|
|
43424
|
+
const forward = live ? this.#modelChange(name, changes2, "old", "url") : null;
|
|
43425
|
+
if (forward) {
|
|
43426
|
+
this.#busy(id, true);
|
|
43427
|
+
try {
|
|
43428
|
+
await live?.endpoints?.(forward);
|
|
43429
|
+
} catch (error) {
|
|
43430
|
+
this.#busy(id, false);
|
|
43431
|
+
const field = changes2.find((change) => change.url) ?? changes2[0];
|
|
43432
|
+
if (this.model === model) this.#refuse(id, field.field, failureText(error));
|
|
43433
|
+
return;
|
|
43434
|
+
}
|
|
43435
|
+
if (this.model !== model) {
|
|
43436
|
+
this.#busy(id, false);
|
|
43437
|
+
return;
|
|
43438
|
+
}
|
|
43439
|
+
}
|
|
43440
|
+
await this.connect(id, secret, fields);
|
|
43441
|
+
if (this.failure?.id === id) {
|
|
43442
|
+
this.#placeFailure(account, fields);
|
|
43443
|
+
const back = forward ? this.#modelChange(name, changes2, "url", "old") : null;
|
|
43444
|
+
if (back) await live?.endpoints?.(back).catch(() => {
|
|
43445
|
+
});
|
|
43446
|
+
return;
|
|
43447
|
+
}
|
|
43448
|
+
for (const change of changes2) {
|
|
43449
|
+
const key2 = `${id} ${change.field}`;
|
|
43450
|
+
if (change.url) this.#bases.set(key2, change.url);
|
|
43451
|
+
else this.#bases.delete(key2);
|
|
43452
|
+
}
|
|
43453
|
+
}
|
|
43454
|
+
#placeFailure(account, fields) {
|
|
43455
|
+
const message = this.failure.message;
|
|
43456
|
+
const field = (account.fields ?? []).find(
|
|
43457
|
+
(candidate) => candidate.customBase && !!fields?.[candidate.name] && [candidate.name, candidate.label, "https", "url", "port", "userinfo"].some(
|
|
43458
|
+
(word) => new RegExp(`\\b${word.replace(/[^a-z0-9 ]/gi, "\\$&")}\\b`, "i").test(message)
|
|
43459
|
+
)
|
|
43460
|
+
);
|
|
43461
|
+
if (!field) return;
|
|
43462
|
+
this.failure = null;
|
|
43463
|
+
this.#refuse(account.id, field.name, message);
|
|
43165
43464
|
}
|
|
43166
43465
|
#refuse(id, field, message) {
|
|
43167
43466
|
this.problem = { id, field, message };
|
|
@@ -43185,13 +43484,25 @@ var SliccSettings = class extends ThemedElement {
|
|
|
43185
43484
|
}
|
|
43186
43485
|
return values;
|
|
43187
43486
|
}
|
|
43487
|
+
#added(id) {
|
|
43488
|
+
return this.model?.settings.accounts().find((account) => account.id === id);
|
|
43489
|
+
}
|
|
43490
|
+
#offered() {
|
|
43491
|
+
return this.model?.settings.providers?.() ?? null;
|
|
43492
|
+
}
|
|
43188
43493
|
#start(account) {
|
|
43189
43494
|
if (account.auth !== "api-key") {
|
|
43190
43495
|
void this.connect(account.id);
|
|
43191
43496
|
return;
|
|
43192
43497
|
}
|
|
43498
|
+
this.#enter(account);
|
|
43499
|
+
}
|
|
43500
|
+
#enter(account) {
|
|
43193
43501
|
this.failure = null;
|
|
43194
43502
|
this.problem = null;
|
|
43503
|
+
this.filled = new Set(
|
|
43504
|
+
(account.fields ?? []).filter((field) => field.options || field.value?.trim()).map((field) => field.name)
|
|
43505
|
+
);
|
|
43195
43506
|
this.entering = account.id;
|
|
43196
43507
|
void this.updateComplete.then(() => this.focusOn(".key sp-textfield", ".key input"));
|
|
43197
43508
|
}
|
|
@@ -43199,6 +43510,7 @@ var SliccSettings = class extends ThemedElement {
|
|
|
43199
43510
|
event2.preventDefault();
|
|
43200
43511
|
const form = event2.currentTarget;
|
|
43201
43512
|
this.problem = null;
|
|
43513
|
+
this.filled = new Set([...this.filled].filter((name) => name !== "value"));
|
|
43202
43514
|
if (this.#vault(account)) {
|
|
43203
43515
|
const value = take(form.querySelector("input[data-field=value]"));
|
|
43204
43516
|
const fields2 = this.#fields(form, account);
|
|
@@ -43209,7 +43521,7 @@ var SliccSettings = class extends ThemedElement {
|
|
|
43209
43521
|
const secret = field.value.trim();
|
|
43210
43522
|
field.value = "";
|
|
43211
43523
|
const fields = this.#fields(form, account);
|
|
43212
|
-
if (secret && fields !== null) void this
|
|
43524
|
+
if (secret && fields !== null) void this.#connectBases(account, secret, fields);
|
|
43213
43525
|
}
|
|
43214
43526
|
#submitOnEnter(event2) {
|
|
43215
43527
|
const target2 = event2.target;
|
|
@@ -43220,7 +43532,7 @@ var SliccSettings = class extends ThemedElement {
|
|
|
43220
43532
|
#send(event2) {
|
|
43221
43533
|
event2.currentTarget.closest("form")?.requestSubmit();
|
|
43222
43534
|
}
|
|
43223
|
-
#
|
|
43535
|
+
#enterKey(event2) {
|
|
43224
43536
|
if (event2.key === "Enter") this.#send(event2);
|
|
43225
43537
|
}
|
|
43226
43538
|
#cancel() {
|
|
@@ -43248,9 +43560,15 @@ var SliccSettings = class extends ThemedElement {
|
|
|
43248
43560
|
(field) => b`<label class="field">
|
|
43249
43561
|
<span>${field.label}</span>${this.#control(account, field)}
|
|
43250
43562
|
</label>
|
|
43563
|
+
${field.help ? b`<p class="hint" id=${`help-${field.name}`}>${field.help}</p>` : A}
|
|
43251
43564
|
${this.#problem(account, field.name)}`
|
|
43252
43565
|
);
|
|
43253
43566
|
}
|
|
43567
|
+
#describedBy(account, field) {
|
|
43568
|
+
const problem = this.#described(account, field.name);
|
|
43569
|
+
const ids = [problem === A ? "" : problem, field.help ? `help-${field.name}` : ""];
|
|
43570
|
+
return ids.filter(Boolean).join(" ") || A;
|
|
43571
|
+
}
|
|
43254
43572
|
#control(account, field) {
|
|
43255
43573
|
if (field.options) {
|
|
43256
43574
|
const chosen = field.value ?? field.options[0]?.value;
|
|
@@ -43259,7 +43577,7 @@ var SliccSettings = class extends ThemedElement {
|
|
|
43259
43577
|
?disabled=${!field.options.length}
|
|
43260
43578
|
aria-required=${field.required ? "true" : A}
|
|
43261
43579
|
aria-invalid=${this.#invalid(account, field.name)}
|
|
43262
|
-
aria-describedby=${this.#
|
|
43580
|
+
aria-describedby=${this.#describedBy(account, field)}
|
|
43263
43581
|
>
|
|
43264
43582
|
${field.options.map((option2) => b`<option value=${option2.value} ?selected=${option2.value === chosen}>${option2.label}</option>`)}
|
|
43265
43583
|
</select>`;
|
|
@@ -43269,11 +43587,35 @@ var SliccSettings = class extends ThemedElement {
|
|
|
43269
43587
|
autocomplete="off"
|
|
43270
43588
|
spellcheck="false"
|
|
43271
43589
|
data-account-field=${field.name}
|
|
43590
|
+
value=${field.value ?? A}
|
|
43591
|
+
placeholder=${field.placeholder ?? A}
|
|
43272
43592
|
aria-required=${field.required ? "true" : A}
|
|
43273
43593
|
aria-invalid=${this.#invalid(account, field.name)}
|
|
43274
|
-
aria-describedby=${this.#
|
|
43594
|
+
aria-describedby=${this.#describedBy(account, field)}
|
|
43275
43595
|
/>`;
|
|
43276
43596
|
}
|
|
43597
|
+
#getKey(account) {
|
|
43598
|
+
if (!account.keyUrl) return A;
|
|
43599
|
+
return b`<a class="swc-Link get-key" href=${account.keyUrl} target="_blank" rel="noopener noreferrer" data-action="get-key">Get a key</a>`;
|
|
43600
|
+
}
|
|
43601
|
+
#leave(account) {
|
|
43602
|
+
const adding = this.adding?.id === account.id;
|
|
43603
|
+
return b`<swc-button size="m" variant="secondary" data-action=${adding ? "back" : "cancel"} @click=${() => adding ? this.#back() : this.#cancel()}>${adding ? "Back" : "Cancel"}</swc-button>`;
|
|
43604
|
+
}
|
|
43605
|
+
#saveLabel(account) {
|
|
43606
|
+
return this.adding?.id === account.id ? "Connect" : "Save";
|
|
43607
|
+
}
|
|
43608
|
+
#ready(account) {
|
|
43609
|
+
if (!this.#offered()) return true;
|
|
43610
|
+
const required = (account.fields ?? []).filter((field) => field.required);
|
|
43611
|
+
return ["value", ...required.map((field) => field.name)].every((name) => this.filled.has(name));
|
|
43612
|
+
}
|
|
43613
|
+
#fill(event2) {
|
|
43614
|
+
const input = event2.target;
|
|
43615
|
+
const name = input.dataset.accountField ?? "value";
|
|
43616
|
+
const rest = [...this.filled].filter((candidate) => candidate !== name);
|
|
43617
|
+
this.filled = new Set(input.value.trim() ? [...rest, name] : rest);
|
|
43618
|
+
}
|
|
43277
43619
|
#unlock(vault) {
|
|
43278
43620
|
return b`<div class="locked" data-locked>
|
|
43279
43621
|
<span>Unlock the vault first</span>
|
|
@@ -43292,7 +43634,7 @@ var SliccSettings = class extends ThemedElement {
|
|
|
43292
43634
|
const busy = this.pending.has(account.id);
|
|
43293
43635
|
const locked = !!vault.status()?.locked;
|
|
43294
43636
|
const name = secretNames[account.secret ?? "api-key"];
|
|
43295
|
-
return b`<form class="key stacked" data-id=${account.id} data-store="vault" @submit=${(event2) => this.#submit(event2, account)} @keydown=${(event2) => this.#submitOnEnter(event2)}>
|
|
43637
|
+
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)}>
|
|
43296
43638
|
<label class="field"><span>${account.provider} ${name}</span><input
|
|
43297
43639
|
type="password"
|
|
43298
43640
|
autocomplete="off"
|
|
@@ -43303,11 +43645,12 @@ var SliccSettings = class extends ThemedElement {
|
|
|
43303
43645
|
aria-describedby=${this.#described(account, "value")}
|
|
43304
43646
|
/></label>
|
|
43305
43647
|
${this.#problem(account, "value")}
|
|
43306
|
-
${this.#extra(account)}
|
|
43307
43648
|
${locked ? this.#unlock(vault) : b`<p class="hint">Saved in the vault</p>`}
|
|
43649
|
+
${this.#getKey(account)}
|
|
43650
|
+
${this.#extra(account)}
|
|
43308
43651
|
<div class="buttons">
|
|
43309
|
-
<swc-button size="m" variant="accent" data-action="save" ?pending=${busy} ?disabled=${locked} @click=${(event2) => this.#send(event2)}
|
|
43310
|
-
|
|
43652
|
+
<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>
|
|
43653
|
+
${this.#leave(account)}
|
|
43311
43654
|
</div>
|
|
43312
43655
|
</form>`;
|
|
43313
43656
|
}
|
|
@@ -43316,23 +43659,24 @@ var SliccSettings = class extends ThemedElement {
|
|
|
43316
43659
|
const vault = this.#vault(account);
|
|
43317
43660
|
if (vault) return this.#kept(account, vault);
|
|
43318
43661
|
const busy = this.pending.has(account.id);
|
|
43319
|
-
const extra = account.fields?.length;
|
|
43320
|
-
return b`<form class=${extra ? "key stacked" : "key"} data-id=${account.id} @submit=${(event2) => this.#submit(event2, account)} @keydown=${(event2) => this.#submitOnEnter(event2)}>
|
|
43662
|
+
const extra = account.fields?.length || account.keyUrl;
|
|
43663
|
+
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)}>
|
|
43321
43664
|
<sp-textfield
|
|
43322
43665
|
size="m"
|
|
43323
43666
|
type="password"
|
|
43324
43667
|
autocomplete="off"
|
|
43325
43668
|
label=${`${account.provider} ${secretNames[account.secret ?? "api-key"]}`}
|
|
43326
43669
|
placeholder=${`Paste the ${secretNames[account.secret ?? "api-key"]}`}
|
|
43327
|
-
@keydown=${(event2) => this.#
|
|
43670
|
+
@keydown=${(event2) => this.#enterKey(event2)}
|
|
43328
43671
|
></sp-textfield>
|
|
43672
|
+
${this.#getKey(account)}
|
|
43329
43673
|
${extra ? this.#extra(account) : A}
|
|
43330
|
-
${extra ? b`<div class="buttons">${this.#buttons(busy)}</div>` : this.#buttons(busy)}
|
|
43674
|
+
${extra ? b`<div class="buttons">${this.#buttons(account, busy)}</div>` : this.#buttons(account, busy)}
|
|
43331
43675
|
</form>`;
|
|
43332
43676
|
}
|
|
43333
|
-
#buttons(busy) {
|
|
43334
|
-
return b`<swc-button size="m" variant="accent" data-action="save" ?pending=${busy} @click=${(event2) => this.#send(event2)}
|
|
43335
|
-
|
|
43677
|
+
#buttons(account, busy) {
|
|
43678
|
+
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>
|
|
43679
|
+
${this.#leave(account)}`;
|
|
43336
43680
|
}
|
|
43337
43681
|
#inVault(account) {
|
|
43338
43682
|
const vault = this.model?.vault;
|
|
@@ -43384,7 +43728,8 @@ var SliccSettings = class extends ThemedElement {
|
|
|
43384
43728
|
get busyReason() {
|
|
43385
43729
|
const accounts = this.model?.settings.accounts() ?? [];
|
|
43386
43730
|
if (accounts.some((account) => this.#signingIn(account))) return "signing in";
|
|
43387
|
-
|
|
43731
|
+
if (this.entering !== null) return "a key is being entered";
|
|
43732
|
+
return this.picking ? "a provider is being added" : null;
|
|
43388
43733
|
}
|
|
43389
43734
|
#signingIn(account) {
|
|
43390
43735
|
return account.status === "signing-in" || account.auth !== "api-key" && account.status !== "connected" && this.pending.has(account.id);
|
|
@@ -43441,10 +43786,266 @@ var SliccSettings = class extends ThemedElement {
|
|
|
43441
43786
|
<span class="provider">${account.provider}</span>
|
|
43442
43787
|
<span class="identity">${account.identity}${this.#inVault(account) ? b`<span class="kept" data-store="vault">${account.identity ? " \xB7 " : ""}${kept2(account)}</span>` : A}</span>
|
|
43443
43788
|
<swc-status-light class="state" variant=${variant}>${label}</swc-status-light>
|
|
43444
|
-
${this.#action(account)}
|
|
43789
|
+
${this.#removable(account) ? b`<div class="actions">${this.#action(account)}${this.#removeButton(account)}</div>` : this.#action(account)}
|
|
43445
43790
|
</div>
|
|
43446
|
-
${this.#
|
|
43447
|
-
${failure2}`;
|
|
43791
|
+
${this.#offered() ? this.#rowNotes(account) : A}
|
|
43792
|
+
${this.adding?.id === account.id ? A : b`${this.#key(account)}${failure2}`}`;
|
|
43793
|
+
}
|
|
43794
|
+
#removable(account) {
|
|
43795
|
+
return !!this.#offered() && !!this.model?.settings.remove && account.group !== "mcp";
|
|
43796
|
+
}
|
|
43797
|
+
#removeButton(account) {
|
|
43798
|
+
const id = `remove-${account.id}`;
|
|
43799
|
+
const label = `Remove ${account.provider}`;
|
|
43800
|
+
return b`<swc-action-button
|
|
43801
|
+
id=${id}
|
|
43802
|
+
size="m"
|
|
43803
|
+
quiet
|
|
43804
|
+
data-action="remove-account"
|
|
43805
|
+
accessible-label=${label}
|
|
43806
|
+
?disabled=${this.pending.has(account.id)}
|
|
43807
|
+
@click=${() => this.#remove(account)}
|
|
43808
|
+
><swc-icon-delete slot="icon"></swc-icon-delete></swc-action-button
|
|
43809
|
+
><swc-tooltip for=${id} placement="top">${label}</swc-tooltip>`;
|
|
43810
|
+
}
|
|
43811
|
+
async #remove(account) {
|
|
43812
|
+
const model = this.model;
|
|
43813
|
+
const body4 = removeBodies[account.auth ?? ""] ?? "Its key is deleted from the vault. Models from it stop working.";
|
|
43814
|
+
const title = `Remove ${account.provider}?`;
|
|
43815
|
+
if (!await confirm({ title, body: body4, action: "Remove" })) return;
|
|
43816
|
+
if (this.model !== model) return;
|
|
43817
|
+
clearValues(this.renderRoot);
|
|
43818
|
+
if (this.entering === account.id) this.entering = null;
|
|
43819
|
+
const vault = model.vault;
|
|
43820
|
+
const keyed = account.store === "vault" && account.auth === "api-key" && !!vault?.remove;
|
|
43821
|
+
if (keyed && !await this.#forget(account, vault)) return;
|
|
43822
|
+
if (this.model !== model) return;
|
|
43823
|
+
this.#busy(account.id, true);
|
|
43824
|
+
this.failure = null;
|
|
43825
|
+
try {
|
|
43826
|
+
await model.settings.remove?.(account.id);
|
|
43827
|
+
} catch (error) {
|
|
43828
|
+
if (this.model === model) this.failure = { id: account.id, message: failureText(error) };
|
|
43829
|
+
return;
|
|
43830
|
+
} finally {
|
|
43831
|
+
this.#busy(account.id, false);
|
|
43832
|
+
}
|
|
43833
|
+
this.focusOn("[data-action=add-provider]");
|
|
43834
|
+
for (const field of account.fields ?? []) this.#bases.delete(`${account.id} ${field.name}`);
|
|
43835
|
+
}
|
|
43836
|
+
#notice(needs, size4 = "long") {
|
|
43837
|
+
if (needs !== "cors-free-transport") return A;
|
|
43838
|
+
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>`;
|
|
43839
|
+
}
|
|
43840
|
+
#signingNote(account) {
|
|
43841
|
+
const key2 = `settings:${account.id}`;
|
|
43842
|
+
if (account.auth !== "oauth" || !this.#signingIn(account)) {
|
|
43843
|
+
this.#waits.done(key2);
|
|
43844
|
+
return A;
|
|
43845
|
+
}
|
|
43846
|
+
return b`<p class="hint" role="status" data-signing>${signInText(this.#waits.waited(key2))}</p>`;
|
|
43847
|
+
}
|
|
43848
|
+
#rowNotes(account) {
|
|
43849
|
+
const notice = this.#notice(account.needs);
|
|
43850
|
+
const signing = this.adding?.id === account.id ? A : this.#signingNote(account);
|
|
43851
|
+
if (notice === A && signing === A) return A;
|
|
43852
|
+
return b`<div class="notes">${notice}${signing}</div>`;
|
|
43853
|
+
}
|
|
43854
|
+
#openPicker() {
|
|
43855
|
+
this.query = "";
|
|
43856
|
+
this.adding = null;
|
|
43857
|
+
this.picking = true;
|
|
43858
|
+
}
|
|
43859
|
+
updated(changed) {
|
|
43860
|
+
super.updated(changed);
|
|
43861
|
+
const dialog = this.#dialog;
|
|
43862
|
+
if (!changed.has("picking") || !dialog || dialog.open) return;
|
|
43863
|
+
dialog.showModal();
|
|
43864
|
+
const field = this.renderRoot.querySelector("sp-search");
|
|
43865
|
+
void field.updateComplete.then(() => field.focus());
|
|
43866
|
+
}
|
|
43867
|
+
get #dialog() {
|
|
43868
|
+
return this.renderRoot.querySelector("dialog.picker");
|
|
43869
|
+
}
|
|
43870
|
+
#closePicker() {
|
|
43871
|
+
this.#dialog?.close();
|
|
43872
|
+
}
|
|
43873
|
+
#closed() {
|
|
43874
|
+
const id = this.adding?.id;
|
|
43875
|
+
if (id !== void 0 && this.entering === id) {
|
|
43876
|
+
clearValues(this.renderRoot);
|
|
43877
|
+
this.entering = null;
|
|
43878
|
+
this.problem = null;
|
|
43879
|
+
}
|
|
43880
|
+
if (id !== void 0 && this.failure?.id === id) this.failure = null;
|
|
43881
|
+
this.picking = false;
|
|
43882
|
+
this.adding = null;
|
|
43883
|
+
this.query = "";
|
|
43884
|
+
const landing = this.#landing;
|
|
43885
|
+
this.#landing = null;
|
|
43886
|
+
void this.updateComplete.then(() => {
|
|
43887
|
+
const root2 = this.renderRoot;
|
|
43888
|
+
const row = landing ? root2.querySelector(`.account[data-id="${CSS.escape(landing)}"] swc-button`) : null;
|
|
43889
|
+
(row ?? root2.querySelector("[data-action=add-provider]"))?.focus();
|
|
43890
|
+
});
|
|
43891
|
+
}
|
|
43892
|
+
#finish(id) {
|
|
43893
|
+
this.#landing = id;
|
|
43894
|
+
this.#closePicker();
|
|
43895
|
+
}
|
|
43896
|
+
#choose(option2) {
|
|
43897
|
+
if (this.#added(option2.id)) return;
|
|
43898
|
+
this.adding = option2;
|
|
43899
|
+
this.failure = null;
|
|
43900
|
+
if (option2.auth === "api-key" || option2.auth === "fields") {
|
|
43901
|
+
this.#enter(draft(option2));
|
|
43902
|
+
return;
|
|
43903
|
+
}
|
|
43904
|
+
void this.updateComplete.then(
|
|
43905
|
+
() => this.focusOn("[data-step] [data-action=sign-in]", "[data-step] [data-action=connect]")
|
|
43906
|
+
);
|
|
43907
|
+
}
|
|
43908
|
+
#back() {
|
|
43909
|
+
const id = this.adding.id;
|
|
43910
|
+
clearValues(this.renderRoot);
|
|
43911
|
+
if (this.entering === id) this.entering = null;
|
|
43912
|
+
if (this.failure?.id === id) this.failure = null;
|
|
43913
|
+
this.problem = null;
|
|
43914
|
+
this.adding = null;
|
|
43915
|
+
void this.updateComplete.then(
|
|
43916
|
+
() => this.renderRoot.querySelector(`.option[data-provider="${CSS.escape(id)}"]`)?.focus()
|
|
43917
|
+
);
|
|
43918
|
+
}
|
|
43919
|
+
#options() {
|
|
43920
|
+
return [...this.renderRoot.querySelectorAll(".option")];
|
|
43921
|
+
}
|
|
43922
|
+
#pickerKey(event2) {
|
|
43923
|
+
if (event2.key !== "Escape") return;
|
|
43924
|
+
event2.preventDefault();
|
|
43925
|
+
this.#closePicker();
|
|
43926
|
+
}
|
|
43927
|
+
#searchKey(event2) {
|
|
43928
|
+
if (event2.key === "ArrowDown") {
|
|
43929
|
+
event2.preventDefault();
|
|
43930
|
+
this.#options()[0]?.focus();
|
|
43931
|
+
return;
|
|
43932
|
+
}
|
|
43933
|
+
if (event2.key !== "Enter") return;
|
|
43934
|
+
event2.preventDefault();
|
|
43935
|
+
const first2 = matchProviders(this.#offered() ?? [], this.query).find(
|
|
43936
|
+
(option2) => !this.#added(option2.id)
|
|
43937
|
+
);
|
|
43938
|
+
if (first2) this.#choose(first2);
|
|
43939
|
+
}
|
|
43940
|
+
#optionKey(event2, option2) {
|
|
43941
|
+
const options = this.#options();
|
|
43942
|
+
const at = options.indexOf(event2.currentTarget);
|
|
43943
|
+
const moves = {
|
|
43944
|
+
ArrowDown: Math.min(at + 1, options.length - 1),
|
|
43945
|
+
ArrowUp: at - 1,
|
|
43946
|
+
Home: 0,
|
|
43947
|
+
End: options.length - 1
|
|
43948
|
+
};
|
|
43949
|
+
const typed3 = event2.key.length === 1 && !event2.ctrlKey && !event2.metaKey && !event2.altKey;
|
|
43950
|
+
if (event2.key in moves) {
|
|
43951
|
+
const to = moves[event2.key];
|
|
43952
|
+
if (to < 0) this.focusOn("sp-search");
|
|
43953
|
+
else options[to].focus();
|
|
43954
|
+
} else if (event2.key === "Enter" || event2.key === " ") this.#choose(option2);
|
|
43955
|
+
else if (typed3 || event2.key === "Backspace") {
|
|
43956
|
+
this.query = typed3 ? this.query + event2.key : this.query.slice(0, -1);
|
|
43957
|
+
this.focusOn("sp-search");
|
|
43958
|
+
} else return;
|
|
43959
|
+
event2.preventDefault();
|
|
43960
|
+
}
|
|
43961
|
+
#option(option2) {
|
|
43962
|
+
const added = !!this.#added(option2.id);
|
|
43963
|
+
return b`<div
|
|
43964
|
+
class="option"
|
|
43965
|
+
role="option"
|
|
43966
|
+
tabindex="-1"
|
|
43967
|
+
data-provider=${option2.id}
|
|
43968
|
+
data-auth=${option2.auth}
|
|
43969
|
+
aria-disabled=${added ? "true" : "false"}
|
|
43970
|
+
@click=${() => this.#choose(option2)}
|
|
43971
|
+
@keydown=${(event2) => this.#optionKey(event2, option2)}
|
|
43972
|
+
>
|
|
43973
|
+
<span class="name">${option2.name}</span>
|
|
43974
|
+
<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>
|
|
43975
|
+
${option2.description ? b`<span class="description">${option2.description}</span>` : A}
|
|
43976
|
+
${this.#notice(option2.needs, "short")}
|
|
43977
|
+
</div>`;
|
|
43978
|
+
}
|
|
43979
|
+
#pickStep(offered) {
|
|
43980
|
+
const matches2 = matchProviders(offered, this.query);
|
|
43981
|
+
return b`<div class="find">${search({
|
|
43982
|
+
label: "Search providers",
|
|
43983
|
+
value: this.query,
|
|
43984
|
+
input: (value) => {
|
|
43985
|
+
this.query = value;
|
|
43986
|
+
},
|
|
43987
|
+
keydown: (event2) => this.#searchKey(event2)
|
|
43988
|
+
})}</div>
|
|
43989
|
+
<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>
|
|
43990
|
+
<div class="buttons end">
|
|
43991
|
+
<swc-button size="m" variant="secondary" data-action="close" @click=${() => this.#closePicker()}>Cancel</swc-button>
|
|
43992
|
+
</div>`;
|
|
43993
|
+
}
|
|
43994
|
+
#signInStep(account) {
|
|
43995
|
+
const signing = this.#signingIn(account);
|
|
43996
|
+
const cancel = signing && !!this.model?.settings.cancel;
|
|
43997
|
+
return b`<p class="hint">Sign in to ${account.provider} in a new window.</p>
|
|
43998
|
+
${signing ? this.#signingNote(account) : A}
|
|
43999
|
+
<div class="buttons">
|
|
44000
|
+
${cancel ? b`<swc-button size="m" variant="secondary" data-action="cancel-sign-in" @click=${() => this.#stopSigningIn(account)}>Cancel</swc-button>` : A}
|
|
44001
|
+
<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>
|
|
44002
|
+
${signing ? A : this.#leave(account)}
|
|
44003
|
+
</div>`;
|
|
44004
|
+
}
|
|
44005
|
+
#localStep(account) {
|
|
44006
|
+
return b`<p class="hint">SLICC connects to ${account.provider} on this device.</p>
|
|
44007
|
+
<div class="buttons">
|
|
44008
|
+
<swc-button size="m" variant="accent" data-action="connect" ?pending=${this.pending.has(account.id)} @click=${() => this.connect(account.id)}>Connect</swc-button>
|
|
44009
|
+
${this.#leave(account)}
|
|
44010
|
+
</div>`;
|
|
44011
|
+
}
|
|
44012
|
+
#connectStep(option2) {
|
|
44013
|
+
const account = this.#added(option2.id) ?? draft(option2);
|
|
44014
|
+
const step = option2.auth === "oauth" ? this.#signInStep(account) : option2.auth === "local" ? this.#localStep(account) : this.#key(account);
|
|
44015
|
+
return b`<div class="step" data-step=${option2.auth} data-provider=${option2.id}>
|
|
44016
|
+
${option2.description ? b`<p class="lead">${option2.description}</p>` : A}
|
|
44017
|
+
${this.#notice(option2.needs)}
|
|
44018
|
+
${step}
|
|
44019
|
+
${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}
|
|
44020
|
+
</div>`;
|
|
44021
|
+
}
|
|
44022
|
+
#picker(offered) {
|
|
44023
|
+
if (!this.picking) return A;
|
|
44024
|
+
const adding = this.adding;
|
|
44025
|
+
return b`<dialog class="picker" aria-labelledby="picker-title" data-picker=${adding ? "connect" : "pick"} @keydown=${(event2) => this.#pickerKey(event2)} @close=${() => this.#closed()}>
|
|
44026
|
+
<div class="head">
|
|
44027
|
+
<h2 id="picker-title">${adding ? `Add ${adding.name}` : "Add a provider"}</h2>
|
|
44028
|
+
<swc-close-button size="m" data-action="close" accessible-label="Close" @click=${() => this.#closePicker()}></swc-close-button>
|
|
44029
|
+
</div>
|
|
44030
|
+
${adding ? this.#connectStep(adding) : this.#pickStep(offered)}
|
|
44031
|
+
</dialog>`;
|
|
44032
|
+
}
|
|
44033
|
+
#providerList(accounts) {
|
|
44034
|
+
const offered = this.#offered();
|
|
44035
|
+
if (!offered)
|
|
44036
|
+
return b`<div class="accounts">${accounts.map((account) => this.#account(account))}</div>`;
|
|
44037
|
+
const sorted = [...accounts].sort((a23, b13) => listOrder[a23.status] - listOrder[b13.status]);
|
|
44038
|
+
return b`<div class="accounts" data-group="providers">${c(
|
|
44039
|
+
sorted,
|
|
44040
|
+
(account) => account.id,
|
|
44041
|
+
(account) => this.#account(account)
|
|
44042
|
+
)}</div>
|
|
44043
|
+
<div class="add">
|
|
44044
|
+
<swc-action-button size="m" quiet data-action="add-provider" @click=${() => this.#openPicker()}>
|
|
44045
|
+
<swc-icon-add slot="icon"></swc-icon-add>Add a provider
|
|
44046
|
+
</swc-action-button>
|
|
44047
|
+
</div>
|
|
44048
|
+
${this.#picker(offered)}`;
|
|
43448
44049
|
}
|
|
43449
44050
|
render() {
|
|
43450
44051
|
const settings = this.model?.settings;
|
|
@@ -43500,7 +44101,7 @@ var SliccSettings = class extends ThemedElement {
|
|
|
43500
44101
|
</div>
|
|
43501
44102
|
</div>
|
|
43502
44103
|
<h2 data-section="accounts">Accounts</h2>
|
|
43503
|
-
|
|
44104
|
+
${this.#providerList(providers)}
|
|
43504
44105
|
${servers.length ? b`<h2>MCP servers</h2>
|
|
43505
44106
|
<div class="accounts" data-group="mcp">${servers.map((account) => this.#account(account))}</div>` : A}
|
|
43506
44107
|
${this.model?.vault ? b`<slicc-secrets .model=${this.model}></slicc-secrets>` : A}
|