@ai-ecoverse/slicc-spectrum 1.65.2 → 1.66.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 +2 -2
- package/dist/{chunk-ZS4XIKFR.js → chunk-2PKRU2CL.js} +2 -2
- package/dist/{chunk-ZS4XIKFR.js.map → chunk-2PKRU2CL.js.map} +2 -2
- package/dist/slicc-dummy.js +51 -11
- package/dist/slicc-dummy.js.map +3 -3
- package/dist/slicc-kernel-model.js +1 -1
- package/dist/slicc-ui.js +330 -34
- package/dist/slicc-ui.js.map +4 -4
- package/dist/types/app/records.d.ts +5 -0
- package/dist/types/app/secrets.d.ts +4 -1
- package/dist/types/app/settings.d.ts +17 -4
- package/dist/types/dummy/index.d.ts +4 -2
- package/dist/types/dummy/vault.d.ts +5 -3
- package/dist/types/model/types.d.ts +17 -2
- package/package.json +3 -3
package/dist/slicc-ui.js
CHANGED
|
@@ -28772,6 +28772,20 @@ function asking2(request2) {
|
|
|
28772
28772
|
if (request2.kind === "unseal") return b`${by} asks to remove the ${request2.provider} sign-in`;
|
|
28773
28773
|
return request2.name ? b`${by} asks for <code>${request2.name}</code>` : b`${by} asks for a value`;
|
|
28774
28774
|
}
|
|
28775
|
+
var accountLights = {
|
|
28776
|
+
connected: ["positive", "Active"],
|
|
28777
|
+
expired: ["notice", "Expired"],
|
|
28778
|
+
"signing-in": ["info", "Signing in"],
|
|
28779
|
+
disconnected: ["neutral", "Not connected"]
|
|
28780
|
+
};
|
|
28781
|
+
function putOptions(secret) {
|
|
28782
|
+
if (secret.kind === "model") return { kind: "model", provider: secret.provider };
|
|
28783
|
+
if (secret.kind === "mcp") return { kind: "mcp", server: secret.server };
|
|
28784
|
+
return void 0;
|
|
28785
|
+
}
|
|
28786
|
+
function agentUse(secret) {
|
|
28787
|
+
return secret.kind === "model" || secret.kind === "mcp" && secret.rules.length === 0;
|
|
28788
|
+
}
|
|
28775
28789
|
function byName(a22, b13) {
|
|
28776
28790
|
return a22.name < b13.name ? -1 : a22.name > b13.name ? 1 : 0;
|
|
28777
28791
|
}
|
|
@@ -29263,7 +29277,8 @@ var SliccSecrets = class extends ThemedElement {
|
|
|
29263
29277
|
model.vault.on("availability", update),
|
|
29264
29278
|
model.vault.on("list", () => this.#listed(model.vault))
|
|
29265
29279
|
] : [],
|
|
29266
|
-
...model.network ? [model.network.on("network", update)] : []
|
|
29280
|
+
...model.network ? [model.network.on("network", update)] : [],
|
|
29281
|
+
model.settings.on("accounts", update)
|
|
29267
29282
|
];
|
|
29268
29283
|
}
|
|
29269
29284
|
#button(config, action) {
|
|
@@ -29349,7 +29364,7 @@ var SliccSecrets = class extends ThemedElement {
|
|
|
29349
29364
|
}
|
|
29350
29365
|
this.busy = true;
|
|
29351
29366
|
try {
|
|
29352
|
-
await vault.put?.(name, value);
|
|
29367
|
+
await vault.put?.(name, value, void 0, form.kind === "replace" ? form.options : void 0);
|
|
29353
29368
|
if (!this.#mine(vault, form)) return;
|
|
29354
29369
|
this.form = null;
|
|
29355
29370
|
this.said = { kind: "saved", name };
|
|
@@ -29629,8 +29644,21 @@ var SliccSecrets = class extends ThemedElement {
|
|
|
29629
29644
|
</div>
|
|
29630
29645
|
</div>`;
|
|
29631
29646
|
}
|
|
29647
|
+
#reach(secret, gone3) {
|
|
29648
|
+
if (agentUse(secret)) {
|
|
29649
|
+
const use = secret.kind === "model" ? `Model requests to ${this.#providerName(secret.provider ?? "")}, by the agent` : `Requests to the MCP server ${secret.server}, by the agent`;
|
|
29650
|
+
return b`<dt>Used for</dt><dd data-used-for>${use}</dd>`;
|
|
29651
|
+
}
|
|
29652
|
+
const rules = secret.rules.length ? secret.rules.map((rule, index) => b`${index ? b`<br />` : A}${ruleLine(rule)}`) : "Nowhere yet: no rule names it";
|
|
29653
|
+
return b`<dt>${gone3 ? "Was sent to" : "Sent to"}</dt><dd data-rules>${rules}</dd>`;
|
|
29654
|
+
}
|
|
29655
|
+
#account(secret) {
|
|
29656
|
+
const id = secret.kind === "mcp" ? `mcp:${secret.server}` : secret.provider;
|
|
29657
|
+
return this.model?.settings.accounts().find((account) => account.id === id);
|
|
29658
|
+
}
|
|
29632
29659
|
#state(secret) {
|
|
29633
|
-
const
|
|
29660
|
+
const account = agentUse(secret) ? this.#account(secret) : void 0;
|
|
29661
|
+
const [variant, label] = secret.state === "removed" ? ["neutral", "Removed"] : secret.expiresAt !== void 0 && secret.expiresAt <= Date.now() ? ["notice", "Expired"] : account ? accountLights[account.status] : secret.state === "inert" && !agentUse(secret) ? ["neutral", "No rule yet"] : ["positive", "Active"];
|
|
29634
29662
|
return b`<swc-status-light size="s" variant=${variant}>${label}</swc-status-light>`;
|
|
29635
29663
|
}
|
|
29636
29664
|
#controls(vault, secret) {
|
|
@@ -29641,15 +29669,18 @@ var SliccSecrets = class extends ThemedElement {
|
|
|
29641
29669
|
const replace = vault.put && replaceable(secret);
|
|
29642
29670
|
if (!replace && !vault.remove) return A;
|
|
29643
29671
|
return b`<div class="buttons">
|
|
29644
|
-
${replace ? b`<swc-button size="s" variant="secondary" data-action="replace" @click=${() => this.open({ kind: "replace", name })}>Replace value</swc-button>` : A}
|
|
29672
|
+
${replace ? b`<swc-button size="s" variant="secondary" data-action="replace" @click=${() => this.open({ kind: "replace", name, options: putOptions(secret) })}>Replace value</swc-button>` : A}
|
|
29645
29673
|
${vault.remove ? b`<swc-button size="s" variant="secondary" fill-style="outline" data-action="remove" ?pending=${this.acting.has(`remove:${name}`)} @click=${(event2) => this.removeSecret(vault, secret, event2.currentTarget)}>Remove</swc-button>` : A}
|
|
29646
29674
|
</div>`;
|
|
29647
29675
|
}
|
|
29676
|
+
#providerName(id) {
|
|
29677
|
+
return this.model?.settings.accounts().find((account) => account.id === id)?.provider ?? id;
|
|
29678
|
+
}
|
|
29648
29679
|
#secret(vault, secret, entries, devices, more, locked) {
|
|
29649
29680
|
const kind = kinds[secret.kind];
|
|
29650
29681
|
const reveal = revealed(secret.name, entries, Date.now(), more);
|
|
29651
29682
|
const exec = execLine(secret.exec, secret.execArgv);
|
|
29652
|
-
const
|
|
29683
|
+
const gone3 = secret.state === "removed";
|
|
29653
29684
|
const form = this.#offline ? null : this.form;
|
|
29654
29685
|
return b`<li class="secret" data-secret=${secret.name} data-state=${secret.state}>
|
|
29655
29686
|
<div class="name">
|
|
@@ -29659,17 +29690,18 @@ var SliccSecrets = class extends ThemedElement {
|
|
|
29659
29690
|
</div>
|
|
29660
29691
|
${this.#controls(vault, secret)}
|
|
29661
29692
|
<dl>
|
|
29662
|
-
|
|
29663
|
-
|
|
29664
|
-
${secret.exits ? b`<dt>${gone2 ? "Left through" : "Leaves through"}</dt><dd data-exits>${secret.exits.length ? list4(secret.exits.map((exit) => exitLabel(exit, devices))) : "No exit"}</dd>` : A}
|
|
29693
|
+
${this.#reach(secret, gone3)}
|
|
29694
|
+
${secret.exits ? b`<dt>${gone3 ? "Left through" : "Leaves through"}</dt><dd data-exits>${secret.exits.length ? list4(secret.exits.map((exit) => exitLabel(exit, devices))) : "No exit"}</dd>` : A}
|
|
29665
29695
|
${exec || reveal ? b`<dt>Programs</dt><dd data-exec>${exec}${exec && reveal ? b`<br />` : A}${reveal}</dd>` : A}
|
|
29696
|
+
${secret.kind === "model" && secret.provider ? b`<dt>Provider</dt><dd data-provider>${this.#providerName(secret.provider)}</dd>` : A}
|
|
29697
|
+
${secret.kind === "mcp" && secret.server ? b`<dt>Server</dt><dd data-server>${secret.server}</dd>` : A}
|
|
29666
29698
|
<dt>From</dt>
|
|
29667
29699
|
<dd data-source>${sourceLine(secret, devices)}</dd>
|
|
29668
29700
|
${secret.usedAt ? b`<dt>Last used</dt><dd data-used>${since(secret.usedAt)}</dd>` : A}
|
|
29669
29701
|
${secret.expiresAt ? b`<dt>Expires</dt><dd data-expires>${until(secret.expiresAt)}</dd>` : A}
|
|
29670
29702
|
${secret.removedAt ? b`<dt>Removed</dt><dd>${since(secret.removedAt)}</dd>` : A}
|
|
29671
29703
|
</dl>
|
|
29672
|
-
${form?.kind === "replace" && form.name === secret.name ? this.#valueForm(vault, form, locked) : A}
|
|
29704
|
+
${form?.kind === "replace" && form.name === secret.name && (form.options?.kind ?? "secret") === (putOptions(secret)?.kind ?? "secret") ? this.#valueForm(vault, form, locked) : A}
|
|
29673
29705
|
</li>`;
|
|
29674
29706
|
}
|
|
29675
29707
|
#secrets(vault, list5, entries, devices, locked) {
|
|
@@ -29790,6 +29822,43 @@ var SliccSecrets = class extends ThemedElement {
|
|
|
29790
29822
|
}
|
|
29791
29823
|
};
|
|
29792
29824
|
|
|
29825
|
+
// src/app/records.ts
|
|
29826
|
+
var envNames = {
|
|
29827
|
+
anthropic: "ANTHROPIC_API_KEY",
|
|
29828
|
+
openai: "OPENAI_API_KEY",
|
|
29829
|
+
azure: "AZURE_OPENAI_API_KEY",
|
|
29830
|
+
"azure-openai": "AZURE_OPENAI_API_KEY",
|
|
29831
|
+
"azure-openai-responses": "AZURE_OPENAI_API_KEY",
|
|
29832
|
+
google: "GEMINI_API_KEY",
|
|
29833
|
+
gemini: "GEMINI_API_KEY",
|
|
29834
|
+
"google-vertex": "GOOGLE_CLOUD_API_KEY",
|
|
29835
|
+
"amazon-bedrock": "AWS_BEARER_TOKEN_BEDROCK",
|
|
29836
|
+
mistral: "MISTRAL_API_KEY",
|
|
29837
|
+
groq: "GROQ_API_KEY",
|
|
29838
|
+
cerebras: "CEREBRAS_API_KEY",
|
|
29839
|
+
xai: "XAI_API_KEY",
|
|
29840
|
+
openrouter: "OPENROUTER_API_KEY",
|
|
29841
|
+
"vercel-ai-gateway": "AI_GATEWAY_API_KEY",
|
|
29842
|
+
deepseek: "DEEPSEEK_API_KEY",
|
|
29843
|
+
zai: "ZAI_API_KEY",
|
|
29844
|
+
moonshotai: "MOONSHOT_API_KEY",
|
|
29845
|
+
fireworks: "FIREWORKS_API_KEY",
|
|
29846
|
+
together: "TOGETHER_API_KEY",
|
|
29847
|
+
huggingface: "HF_TOKEN",
|
|
29848
|
+
"github-copilot": "COPILOT_GITHUB_TOKEN"
|
|
29849
|
+
};
|
|
29850
|
+
var upper = (text2) => text2.toUpperCase().replace(/[^A-Z0-9]/g, "_");
|
|
29851
|
+
function serverOf(account) {
|
|
29852
|
+
return account.id.replace(/^mcp:/, "");
|
|
29853
|
+
}
|
|
29854
|
+
function recordKind(account) {
|
|
29855
|
+
return account.group === "mcp" ? "mcp" : "model";
|
|
29856
|
+
}
|
|
29857
|
+
function recordName(account) {
|
|
29858
|
+
if (account.group === "mcp") return `MCP_${upper(serverOf(account))}_TOKEN`;
|
|
29859
|
+
return envNames[account.id] ?? `${upper(account.id)}_API_KEY`;
|
|
29860
|
+
}
|
|
29861
|
+
|
|
29793
29862
|
// src/app/settings.ts
|
|
29794
29863
|
var accountStatus = {
|
|
29795
29864
|
connected: ["positive", "Connected"],
|
|
@@ -29803,20 +29872,34 @@ var accountStatus = {
|
|
|
29803
29872
|
var popup = (account) => account.group === "mcp" && account.auth === "oauth";
|
|
29804
29873
|
var secretNames = { "api-key": "API key", token: "token" };
|
|
29805
29874
|
var rejectedNames = { "api-key": "API key rejected", token: "Token rejected" };
|
|
29806
|
-
var
|
|
29875
|
+
var keptNames = { "api-key": "Key kept in the vault", token: "Token kept in the vault" };
|
|
29876
|
+
var kept2 = (account) => account.auth === "api-key" ? keptNames[account.secret ?? "api-key"] : "Kept in the vault";
|
|
29877
|
+
async function gone2(vault, name, kind) {
|
|
29878
|
+
try {
|
|
29879
|
+
await vault.remove?.(name, kind);
|
|
29880
|
+
} catch (error) {
|
|
29881
|
+
if (!isVaultFailure(error) || error.code !== "ENOENT") throw error;
|
|
29882
|
+
}
|
|
29883
|
+
}
|
|
29884
|
+
var SliccSettings = class extends ThemedElement {
|
|
29807
29885
|
static properties = {
|
|
29808
|
-
...
|
|
29886
|
+
...ThemedElement.properties,
|
|
29809
29887
|
pending: { state: true },
|
|
29810
29888
|
entering: { state: true },
|
|
29811
|
-
failure: { state: true }
|
|
29889
|
+
failure: { state: true },
|
|
29890
|
+
problem: { state: true },
|
|
29891
|
+
blocked: { state: true }
|
|
29812
29892
|
};
|
|
29813
29893
|
constructor() {
|
|
29814
29894
|
super();
|
|
29815
29895
|
this.pending = /* @__PURE__ */ new Set();
|
|
29816
29896
|
this.entering = null;
|
|
29817
29897
|
this.failure = null;
|
|
29898
|
+
this.problem = null;
|
|
29899
|
+
this.blocked = false;
|
|
29818
29900
|
}
|
|
29819
29901
|
static styles = [
|
|
29902
|
+
fieldStyles,
|
|
29820
29903
|
i`
|
|
29821
29904
|
:host {
|
|
29822
29905
|
display: block;
|
|
@@ -29898,7 +29981,25 @@ var SliccSettings = class extends ModelElement {
|
|
|
29898
29981
|
.key sp-textfield {
|
|
29899
29982
|
flex: 1 1 auto;
|
|
29900
29983
|
}
|
|
29901
|
-
.
|
|
29984
|
+
.key.stacked {
|
|
29985
|
+
display: grid;
|
|
29986
|
+
gap: var(--swc-spacing-200);
|
|
29987
|
+
max-width: 420px;
|
|
29988
|
+
}
|
|
29989
|
+
.buttons,
|
|
29990
|
+
.locked {
|
|
29991
|
+
display: flex;
|
|
29992
|
+
flex-wrap: wrap;
|
|
29993
|
+
align-items: center;
|
|
29994
|
+
gap: var(--swc-spacing-100);
|
|
29995
|
+
}
|
|
29996
|
+
.hint {
|
|
29997
|
+
margin: 0;
|
|
29998
|
+
color: var(--swc-neutral-subdued-content-color-default);
|
|
29999
|
+
font-size: var(--swc-font-size-75);
|
|
30000
|
+
}
|
|
30001
|
+
.failure,
|
|
30002
|
+
.problem {
|
|
29902
30003
|
display: flex;
|
|
29903
30004
|
align-items: flex-start;
|
|
29904
30005
|
gap: var(--swc-spacing-100);
|
|
@@ -29945,7 +30046,12 @@ var SliccSettings = class extends ModelElement {
|
|
|
29945
30046
|
];
|
|
29946
30047
|
subscribe(model) {
|
|
29947
30048
|
const update = () => this.requestUpdate();
|
|
29948
|
-
return [
|
|
30049
|
+
return [
|
|
30050
|
+
...super.subscribe(model),
|
|
30051
|
+
model.settings.on("settings", update),
|
|
30052
|
+
model.settings.on("accounts", update),
|
|
30053
|
+
...model.vault ? [model.vault.on("status", update)] : []
|
|
30054
|
+
];
|
|
29949
30055
|
}
|
|
29950
30056
|
focus() {
|
|
29951
30057
|
this.focusOn("sp-picker");
|
|
@@ -29960,19 +30066,78 @@ var SliccSettings = class extends ModelElement {
|
|
|
29960
30066
|
return event2.target.checked;
|
|
29961
30067
|
}
|
|
29962
30068
|
#cancelled = /* @__PURE__ */ new Set();
|
|
29963
|
-
|
|
29964
|
-
|
|
30069
|
+
#busy(id, on) {
|
|
30070
|
+
const rest = [...this.pending].filter((candidate) => candidate !== id);
|
|
30071
|
+
this.pending = new Set(on ? [...rest, id] : rest);
|
|
30072
|
+
}
|
|
30073
|
+
async connect(id, secret, fields) {
|
|
30074
|
+
this.#busy(id, true);
|
|
29965
30075
|
this.failure = null;
|
|
29966
30076
|
this.#cancelled.delete(id);
|
|
30077
|
+
const settings = this.model?.settings;
|
|
29967
30078
|
try {
|
|
29968
|
-
await
|
|
30079
|
+
await (fields ? settings?.connect(id, secret, fields) : secret === void 0 ? settings?.connect(id) : settings?.connect(id, secret));
|
|
29969
30080
|
if (this.entering === id) this.entering = null;
|
|
29970
30081
|
} catch (error) {
|
|
29971
30082
|
if (!this.#cancelled.has(id)) this.failure = { id, message: error.message };
|
|
29972
30083
|
} finally {
|
|
29973
30084
|
this.#cancelled.delete(id);
|
|
29974
|
-
this
|
|
30085
|
+
this.#busy(id, false);
|
|
30086
|
+
}
|
|
30087
|
+
}
|
|
30088
|
+
#vault(account) {
|
|
30089
|
+
const vault = this.model?.vault;
|
|
30090
|
+
return account.auth === "api-key" && account.store === "vault" && vault?.put ? vault : null;
|
|
30091
|
+
}
|
|
30092
|
+
async keep(account, value, fields) {
|
|
30093
|
+
const model = this.model;
|
|
30094
|
+
const vault = this.#vault(account);
|
|
30095
|
+
const { id } = account;
|
|
30096
|
+
const problem = valueProblem(value);
|
|
30097
|
+
if (problem) {
|
|
30098
|
+
this.#refuse(id, "value", problem);
|
|
30099
|
+
return;
|
|
30100
|
+
}
|
|
30101
|
+
if (vault.status()?.locked) return;
|
|
30102
|
+
const options = account.group === "mcp" ? { kind: "mcp", server: serverOf(account) } : { kind: "model", provider: account.id };
|
|
30103
|
+
this.#busy(id, true);
|
|
30104
|
+
this.failure = null;
|
|
30105
|
+
try {
|
|
30106
|
+
await vault.put?.(recordName(account), value, void 0, options);
|
|
30107
|
+
} catch (error) {
|
|
30108
|
+
this.#busy(id, false);
|
|
30109
|
+
if (this.model === model) this.#refuse(id, "value", failureText(error));
|
|
30110
|
+
return;
|
|
30111
|
+
}
|
|
30112
|
+
if (this.model !== model || this.entering !== id) {
|
|
30113
|
+
this.#busy(id, false);
|
|
30114
|
+
return;
|
|
29975
30115
|
}
|
|
30116
|
+
await this.connect(id, void 0, fields);
|
|
30117
|
+
}
|
|
30118
|
+
#refuse(id, field, message) {
|
|
30119
|
+
this.problem = { id, field, message };
|
|
30120
|
+
void this.updateComplete.then(
|
|
30121
|
+
() => this.renderRoot.querySelector(
|
|
30122
|
+
field === "value" ? ".key input[data-field=value]" : `.key input[data-account-field="${field}"]`
|
|
30123
|
+
)?.focus()
|
|
30124
|
+
);
|
|
30125
|
+
}
|
|
30126
|
+
#fields(form, account) {
|
|
30127
|
+
if (!account.fields?.length) return void 0;
|
|
30128
|
+
const values = {};
|
|
30129
|
+
for (const field of account.fields) {
|
|
30130
|
+
const input = form.querySelector(
|
|
30131
|
+
`input[data-account-field="${field.name}"]`
|
|
30132
|
+
);
|
|
30133
|
+
const value = input.value.trim();
|
|
30134
|
+
if (value) values[field.name] = value;
|
|
30135
|
+
else if (field.required) {
|
|
30136
|
+
this.#refuse(account.id, field.name, `${field.label} can\u2019t be empty`);
|
|
30137
|
+
return null;
|
|
30138
|
+
}
|
|
30139
|
+
}
|
|
30140
|
+
return values;
|
|
29976
30141
|
}
|
|
29977
30142
|
#start(account) {
|
|
29978
30143
|
if (account.auth !== "api-key") {
|
|
@@ -29980,17 +30145,31 @@ var SliccSettings = class extends ModelElement {
|
|
|
29980
30145
|
return;
|
|
29981
30146
|
}
|
|
29982
30147
|
this.failure = null;
|
|
30148
|
+
this.problem = null;
|
|
29983
30149
|
this.entering = account.id;
|
|
29984
|
-
void this.updateComplete.then(() => this.focusOn(".key sp-textfield"));
|
|
30150
|
+
void this.updateComplete.then(() => this.focusOn(".key sp-textfield", ".key input"));
|
|
29985
30151
|
}
|
|
29986
|
-
#submit(event2,
|
|
30152
|
+
#submit(event2, account) {
|
|
29987
30153
|
event2.preventDefault();
|
|
29988
|
-
const
|
|
29989
|
-
|
|
29990
|
-
)
|
|
30154
|
+
const form = event2.currentTarget;
|
|
30155
|
+
this.problem = null;
|
|
30156
|
+
if (this.#vault(account)) {
|
|
30157
|
+
const value = take(form.querySelector("input[data-field=value]"));
|
|
30158
|
+
const fields2 = this.#fields(form, account);
|
|
30159
|
+
if (fields2 !== null && !this.pending.has(account.id)) void this.keep(account, value, fields2);
|
|
30160
|
+
return;
|
|
30161
|
+
}
|
|
30162
|
+
const field = form.querySelector("sp-textfield");
|
|
29991
30163
|
const secret = field.value.trim();
|
|
29992
30164
|
field.value = "";
|
|
29993
|
-
|
|
30165
|
+
const fields = this.#fields(form, account);
|
|
30166
|
+
if (secret && fields !== null) void this.connect(account.id, secret, fields);
|
|
30167
|
+
}
|
|
30168
|
+
#submitOnEnter(event2) {
|
|
30169
|
+
const target = event2.target;
|
|
30170
|
+
if (event2.key !== "Enter" || target.localName !== "input") return;
|
|
30171
|
+
event2.preventDefault();
|
|
30172
|
+
this.#send(event2);
|
|
29994
30173
|
}
|
|
29995
30174
|
#send(event2) {
|
|
29996
30175
|
event2.currentTarget.closest("form")?.requestSubmit();
|
|
@@ -29999,13 +30178,83 @@ var SliccSettings = class extends ModelElement {
|
|
|
29999
30178
|
if (event2.key === "Enter") this.#send(event2);
|
|
30000
30179
|
}
|
|
30001
30180
|
#cancel() {
|
|
30181
|
+
clearValues(this.renderRoot);
|
|
30002
30182
|
this.entering = null;
|
|
30003
30183
|
this.failure = null;
|
|
30184
|
+
this.problem = null;
|
|
30185
|
+
}
|
|
30186
|
+
#problem(account, field) {
|
|
30187
|
+
const problem = this.problem;
|
|
30188
|
+
if (problem?.id !== account.id || problem.field !== field) return A;
|
|
30189
|
+
return b`<div class="problem" id="key-problem" role="alert">
|
|
30190
|
+
<swc-icon-alert-triangle size="s" aria-hidden="true"></swc-icon-alert-triangle>
|
|
30191
|
+
<span>${problem.message}</span>
|
|
30192
|
+
</div>`;
|
|
30193
|
+
}
|
|
30194
|
+
#described(account, field) {
|
|
30195
|
+
return this.problem?.id === account.id && this.problem.field === field ? "key-problem" : A;
|
|
30196
|
+
}
|
|
30197
|
+
#invalid(account, field) {
|
|
30198
|
+
return this.#described(account, field) === A ? A : "true";
|
|
30199
|
+
}
|
|
30200
|
+
#extra(account) {
|
|
30201
|
+
return (account.fields ?? []).map(
|
|
30202
|
+
(field) => b`<label class="field"><span>${field.label}</span><input
|
|
30203
|
+
type="text"
|
|
30204
|
+
autocomplete="off"
|
|
30205
|
+
spellcheck="false"
|
|
30206
|
+
data-account-field=${field.name}
|
|
30207
|
+
aria-required=${field.required ? "true" : A}
|
|
30208
|
+
aria-invalid=${this.#invalid(account, field.name)}
|
|
30209
|
+
aria-describedby=${this.#described(account, field.name)}
|
|
30210
|
+
/></label>
|
|
30211
|
+
${this.#problem(account, field.name)}`
|
|
30212
|
+
);
|
|
30213
|
+
}
|
|
30214
|
+
#unlock(vault) {
|
|
30215
|
+
return b`<div class="locked" data-locked>
|
|
30216
|
+
<span>Unlock the vault first</span>
|
|
30217
|
+
<slicc-vault-button
|
|
30218
|
+
data-action="unlock"
|
|
30219
|
+
.vault=${vault}
|
|
30220
|
+
.config=${{ intent: { kind: "unlock" }, label: "Unlock", size: "m", variant: "accent", theme: this.color }}
|
|
30221
|
+
@vault-popup=${(event2) => {
|
|
30222
|
+
this.blocked = event2.detail.state === "blocked";
|
|
30223
|
+
}}
|
|
30224
|
+
></slicc-vault-button>
|
|
30225
|
+
</div>
|
|
30226
|
+
${this.blocked ? b`<div class="problem" role="alert" data-popup="blocked"><swc-icon-alert-triangle size="s" aria-hidden="true"></swc-icon-alert-triangle><span>The browser blocked the vault window. Allow pop-ups for this site, then try again.</span></div>` : A}`;
|
|
30227
|
+
}
|
|
30228
|
+
#kept(account, vault) {
|
|
30229
|
+
const busy = this.pending.has(account.id);
|
|
30230
|
+
const locked = !!vault.status()?.locked;
|
|
30231
|
+
const name = secretNames[account.secret ?? "api-key"];
|
|
30232
|
+
return b`<form class="key stacked" data-id=${account.id} data-store="vault" @submit=${(event2) => this.#submit(event2, account)} @keydown=${(event2) => this.#submitOnEnter(event2)}>
|
|
30233
|
+
<label class="field"><span>${account.provider} ${name}</span><input
|
|
30234
|
+
type="password"
|
|
30235
|
+
autocomplete="off"
|
|
30236
|
+
spellcheck="false"
|
|
30237
|
+
data-field="value"
|
|
30238
|
+
placeholder=${`Paste the ${name}`}
|
|
30239
|
+
aria-invalid=${this.#invalid(account, "value")}
|
|
30240
|
+
aria-describedby=${this.#described(account, "value")}
|
|
30241
|
+
/></label>
|
|
30242
|
+
${this.#problem(account, "value")}
|
|
30243
|
+
${this.#extra(account)}
|
|
30244
|
+
${locked ? this.#unlock(vault) : b`<p class="hint">Saved in the vault</p>`}
|
|
30245
|
+
<div class="buttons">
|
|
30246
|
+
<swc-button size="m" variant="accent" data-action="save" ?pending=${busy} ?disabled=${locked} @click=${(event2) => this.#send(event2)}>Save</swc-button>
|
|
30247
|
+
<swc-button size="m" variant="secondary" data-action="cancel" @click=${() => this.#cancel()}>Cancel</swc-button>
|
|
30248
|
+
</div>
|
|
30249
|
+
</form>`;
|
|
30004
30250
|
}
|
|
30005
30251
|
#key(account) {
|
|
30006
30252
|
if (this.entering !== account.id) return A;
|
|
30253
|
+
const vault = this.#vault(account);
|
|
30254
|
+
if (vault) return this.#kept(account, vault);
|
|
30007
30255
|
const busy = this.pending.has(account.id);
|
|
30008
|
-
|
|
30256
|
+
const extra = account.fields?.length;
|
|
30257
|
+
return b`<form class=${extra ? "key stacked" : "key"} data-id=${account.id} @submit=${(event2) => this.#submit(event2, account)} @keydown=${(event2) => this.#submitOnEnter(event2)}>
|
|
30009
30258
|
<sp-textfield
|
|
30010
30259
|
size="m"
|
|
30011
30260
|
type="password"
|
|
@@ -30014,15 +30263,61 @@ var SliccSettings = class extends ModelElement {
|
|
|
30014
30263
|
placeholder=${`Paste the ${secretNames[account.secret ?? "api-key"]}`}
|
|
30015
30264
|
@keydown=${(event2) => this.#enter(event2)}
|
|
30016
30265
|
></sp-textfield>
|
|
30017
|
-
|
|
30018
|
-
|
|
30266
|
+
${extra ? this.#extra(account) : A}
|
|
30267
|
+
${extra ? b`<div class="buttons">${this.#buttons(busy)}</div>` : this.#buttons(busy)}
|
|
30019
30268
|
</form>`;
|
|
30020
30269
|
}
|
|
30270
|
+
#buttons(busy) {
|
|
30271
|
+
return b`<swc-button size="m" variant="accent" data-action="save" ?pending=${busy} @click=${(event2) => this.#send(event2)}>Save</swc-button>
|
|
30272
|
+
<swc-button size="m" variant="secondary" data-action="cancel" @click=${() => this.#cancel()}>Cancel</swc-button>`;
|
|
30273
|
+
}
|
|
30274
|
+
#inVault(account) {
|
|
30275
|
+
const vault = this.model?.vault;
|
|
30276
|
+
if (account.store !== "vault" || account.status !== "connected" || !vault) return false;
|
|
30277
|
+
return account.auth !== "api-key" || !!vault.put;
|
|
30278
|
+
}
|
|
30279
|
+
#records(account, vault) {
|
|
30280
|
+
if (account.auth === "api-key") return [[recordName(account), recordKind(account)]];
|
|
30281
|
+
const server = serverOf(account);
|
|
30282
|
+
const names = (vault.list()?.secrets ?? []).filter(
|
|
30283
|
+
(secret) => secret.kind === "mcp" && secret.server === server && secret.state !== "removed"
|
|
30284
|
+
).map((secret) => secret.name);
|
|
30285
|
+
const tokens = names.length ? names : [`${upper(server)}_ACCESS_TOKEN`];
|
|
30286
|
+
return tokens.flatMap(
|
|
30287
|
+
(name) => [
|
|
30288
|
+
[name, "mcp"],
|
|
30289
|
+
[`${name}_GRANT`, "grant"]
|
|
30290
|
+
]
|
|
30291
|
+
);
|
|
30292
|
+
}
|
|
30021
30293
|
async #disconnect(account) {
|
|
30022
|
-
const
|
|
30294
|
+
const model = this.model;
|
|
30295
|
+
const vault = model?.vault;
|
|
30296
|
+
const vaulted = account.store === "vault" && !!vault?.remove;
|
|
30297
|
+
const key2 = vaulted && account.auth === "api-key";
|
|
30298
|
+
const signIn = vaulted && account.auth !== "api-key" && account.group === "mcp";
|
|
30299
|
+
const stored = key2 || signIn ? vault : void 0;
|
|
30300
|
+
const body4 = `Agents can\u2019t use ${account.provider} until you connect it again.${key2 ? " You can restore its key from Removed in Secrets for 30 days." : ""}`;
|
|
30023
30301
|
const title = `Disconnect ${account.provider}?`;
|
|
30024
|
-
if (await confirm({ title, body: body4, action: "Disconnect", variant: "confirmation" }))
|
|
30025
|
-
|
|
30302
|
+
if (!await confirm({ title, body: body4, action: "Disconnect", variant: "confirmation" })) return;
|
|
30303
|
+
clearValues(this.renderRoot);
|
|
30304
|
+
if (this.model !== model) return;
|
|
30305
|
+
if (stored && !await this.#forget(account, stored)) return;
|
|
30306
|
+
if (this.model === model) model?.settings.disconnect(account.id);
|
|
30307
|
+
}
|
|
30308
|
+
async #forget(account, vault) {
|
|
30309
|
+
this.#busy(account.id, true);
|
|
30310
|
+
this.failure = null;
|
|
30311
|
+
try {
|
|
30312
|
+
for (const [name, kind] of this.#records(account, vault)) await gone2(vault, name, kind);
|
|
30313
|
+
return true;
|
|
30314
|
+
} catch (error) {
|
|
30315
|
+
if (this.model?.vault === vault)
|
|
30316
|
+
this.failure = { id: account.id, message: failureText(error) };
|
|
30317
|
+
return false;
|
|
30318
|
+
} finally {
|
|
30319
|
+
this.#busy(account.id, false);
|
|
30320
|
+
}
|
|
30026
30321
|
}
|
|
30027
30322
|
#stopSigningIn(account) {
|
|
30028
30323
|
this.#cancelled.add(account.id);
|
|
@@ -30052,6 +30347,7 @@ var SliccSettings = class extends ModelElement {
|
|
|
30052
30347
|
variant="secondary"
|
|
30053
30348
|
data-action="disconnect"
|
|
30054
30349
|
accessible-label=${`Disconnect ${account.provider}`}
|
|
30350
|
+
?pending=${this.pending.has(account.id)}
|
|
30055
30351
|
@click=${() => this.#disconnect(account)}
|
|
30056
30352
|
>Disconnect</swc-button>`;
|
|
30057
30353
|
}
|
|
@@ -30085,7 +30381,7 @@ var SliccSettings = class extends ModelElement {
|
|
|
30085
30381
|
</div>` : A;
|
|
30086
30382
|
return b`<div class="account" data-id=${account.id}>
|
|
30087
30383
|
<span class="provider">${account.provider}</span>
|
|
30088
|
-
<span class="identity">${account.identity}</span>
|
|
30384
|
+
<span class="identity">${account.identity}${this.#inVault(account) ? b`<span class="kept" data-store="vault">${account.identity ? " \xB7 " : ""}${kept2(account)}</span>` : A}</span>
|
|
30089
30385
|
<swc-status-light class="state" variant=${variant}>${label}</swc-status-light>
|
|
30090
30386
|
${this.#action(account)}
|
|
30091
30387
|
</div>
|
|
@@ -41934,12 +42230,12 @@ function getIgnoreCaseMatchChars(char) {
|
|
|
41934
42230
|
}
|
|
41935
42231
|
const set = /* @__PURE__ */ new Set();
|
|
41936
42232
|
const lower2 = char.toLowerCase();
|
|
41937
|
-
const
|
|
42233
|
+
const upper2 = lower2.toUpperCase();
|
|
41938
42234
|
const title = LowerToTitleCaseMap.get(lower2);
|
|
41939
42235
|
const altLower = LowerToAlternativeLowerCaseMap.get(lower2);
|
|
41940
42236
|
const altUpper = LowerToAlternativeUpperCaseMap.get(lower2);
|
|
41941
|
-
if ([...
|
|
41942
|
-
set.add(
|
|
42237
|
+
if ([...upper2].length === 1) {
|
|
42238
|
+
set.add(upper2);
|
|
41943
42239
|
}
|
|
41944
42240
|
altUpper && set.add(altUpper);
|
|
41945
42241
|
title && set.add(title);
|