@ai-ecoverse/slicc-spectrum 1.60.1 → 1.61.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 +9 -3
- package/dist/slicc-dummy.js +438 -11
- package/dist/slicc-dummy.js.map +4 -4
- package/dist/slicc-ui.js +1204 -168
- package/dist/slicc-ui.js.map +4 -4
- package/dist/types/app/approvals.d.ts +2 -0
- package/dist/types/app/secrets.d.ts +63 -0
- package/dist/types/app/vault.d.ts +36 -0
- package/dist/types/dummy/approvals.d.ts +1 -1
- package/dist/types/dummy/index.d.ts +4 -1
- package/dist/types/dummy/vault.d.ts +42 -0
- package/dist/types/dummy.d.ts +2 -0
- package/dist/types/model/types.d.ts +242 -0
- package/dist/types/ui.d.ts +3 -1
- package/package.json +3 -3
package/dist/slicc-ui.js
CHANGED
|
@@ -6304,10 +6304,10 @@ function getNearestOverflowAncestor(node) {
|
|
|
6304
6304
|
}
|
|
6305
6305
|
return getNearestOverflowAncestor(parentNode);
|
|
6306
6306
|
}
|
|
6307
|
-
function getOverflowAncestors(node,
|
|
6307
|
+
function getOverflowAncestors(node, list5, traverseIframes) {
|
|
6308
6308
|
var _node$ownerDocument2;
|
|
6309
|
-
if (
|
|
6310
|
-
|
|
6309
|
+
if (list5 === void 0) {
|
|
6310
|
+
list5 = [];
|
|
6311
6311
|
}
|
|
6312
6312
|
if (traverseIframes === void 0) {
|
|
6313
6313
|
traverseIframes = true;
|
|
@@ -6317,9 +6317,9 @@ function getOverflowAncestors(node, list4, traverseIframes) {
|
|
|
6317
6317
|
const win = getWindow(scrollableAncestor);
|
|
6318
6318
|
if (isBody) {
|
|
6319
6319
|
const frameElement = getFrameElement(win);
|
|
6320
|
-
return
|
|
6320
|
+
return list5.concat(win, win.visualViewport || [], isOverflowElement(scrollableAncestor) ? scrollableAncestor : [], frameElement && traverseIframes ? getOverflowAncestors(frameElement) : []);
|
|
6321
6321
|
} else {
|
|
6322
|
-
return
|
|
6322
|
+
return list5.concat(scrollableAncestor, getOverflowAncestors(scrollableAncestor, [], traverseIframes));
|
|
6323
6323
|
}
|
|
6324
6324
|
}
|
|
6325
6325
|
function getFrameElement(win) {
|
|
@@ -12300,7 +12300,7 @@ function remoteLight(status2) {
|
|
|
12300
12300
|
"linked devices are watching the agent."
|
|
12301
12301
|
)
|
|
12302
12302
|
].join(" ");
|
|
12303
|
-
const by = (
|
|
12303
|
+
const by = (list5) => list5.length === 1 ? list5[0].name : `${list5.length} linked devices`;
|
|
12304
12304
|
if (asking2.length) {
|
|
12305
12305
|
const text2 = asking2.length === 1 ? `${asking2[0].name} asks to follow` : `${asking2.length} devices ask to follow`;
|
|
12306
12306
|
return { mode: "ask", variant: "notice", text: text2, tooltip };
|
|
@@ -12908,8 +12908,8 @@ var SliccNetwork = class extends ModelElement {
|
|
|
12908
12908
|
}
|
|
12909
12909
|
const device = status2.links?.devices.find((item2) => item2.id === exit.id);
|
|
12910
12910
|
if (device?.state === "connected") return A;
|
|
12911
|
-
const
|
|
12912
|
-
return b`<div class="warning" data-exit="device" data-held><swc-icon-alert-triangle size="s" aria-hidden="true"></swc-icon-alert-triangle><div class="banner"><span>${
|
|
12911
|
+
const who2 = device ? `${device.name} is ${device.state}` : "The linked device isn\u2019t connected";
|
|
12912
|
+
return b`<div class="warning" data-exit="device" data-held><swc-icon-alert-triangle size="s" aria-hidden="true"></swc-icon-alert-triangle><div class="banner"><span>${who2}. Internet traffic waits until it’s connected.</span><div class="actions"><swc-button size="s" variant="secondary" fill-style="outline" data-action="exit-direct" ?pending=${this.busy === "exit"} ?disabled=${this.#waiting("exit")} @click=${() => this.#act("exit", () => port.setExit?.(null), "error")}>Send directly</swc-button></div></div></div>`;
|
|
12913
12913
|
}
|
|
12914
12914
|
#exitPicker(port, status2) {
|
|
12915
12915
|
const tailnet = status2.tailnet;
|
|
@@ -13694,8 +13694,8 @@ var Panels = class {
|
|
|
13694
13694
|
if (bad) return bad;
|
|
13695
13695
|
this.quietly(() => this.#host.open(id, focus, section));
|
|
13696
13696
|
if (place3) {
|
|
13697
|
-
const
|
|
13698
|
-
if (
|
|
13697
|
+
const moved2 = this.move(id, place3);
|
|
13698
|
+
if (moved2.code !== 0) return moved2;
|
|
13699
13699
|
}
|
|
13700
13700
|
return ok(`${focus ? "focused" : info.open ? "showed" : "opened"} ${id}`);
|
|
13701
13701
|
}
|
|
@@ -13752,9 +13752,12 @@ var help = `usage: panel <command>
|
|
|
13752
13752
|
close <id> close a panel
|
|
13753
13753
|
move <id> <place> move an open panel
|
|
13754
13754
|
reset restore the default layout
|
|
13755
|
+
tabs the tabs panel can reach (answered by the agent)
|
|
13755
13756
|
|
|
13756
13757
|
place: left | center | right, or --left | --right | --above | --below | --within <id>
|
|
13757
13758
|
open and focus also take --section <name>, e.g. panel open settings --section accounts
|
|
13759
|
+
--tab <tab> sends the command to that tab instead of the one showing your cone;
|
|
13760
|
+
see panel tabs
|
|
13758
13761
|
|
|
13759
13762
|
ids: the ones panel list shows, e.g. files, changes, terminal, monitor, settings,
|
|
13760
13763
|
chat (your cone's chat), chat:<agent>, terminal:<n>, sprinkle:<name>,
|
|
@@ -13813,37 +13816,37 @@ function coneOf(agents, id) {
|
|
|
13813
13816
|
}
|
|
13814
13817
|
return agent?.kind === "cone" ? agent.id : null;
|
|
13815
13818
|
}
|
|
13816
|
-
function resolve(panels, raw2,
|
|
13819
|
+
function resolve(panels, raw2, reachable2, cone) {
|
|
13817
13820
|
if (/^(file|diff):./.test(raw2)) return raw2;
|
|
13818
13821
|
if (raw2 === "chat") {
|
|
13819
13822
|
const agent = cone === void 0 ? panels.active() : cone;
|
|
13820
|
-
return
|
|
13823
|
+
return reachable2.some((info) => info.id === `chat:${agent}`) ? `chat:${agent}` : null;
|
|
13821
13824
|
}
|
|
13822
13825
|
if (raw2 === "terminal") {
|
|
13823
|
-
const terminals =
|
|
13826
|
+
const terminals = reachable2.filter((info) => info.kind === "terminal");
|
|
13824
13827
|
const picked = terminals.find((info) => info.active) ?? terminals.filter((info) => info.open).at(-1) ?? terminals.at(-1);
|
|
13825
13828
|
return picked?.id ?? null;
|
|
13826
13829
|
}
|
|
13827
|
-
if (
|
|
13830
|
+
if (reachable2.some((info) => info.id === raw2)) return raw2;
|
|
13828
13831
|
const name = raw2.startsWith("sprinkle:") ? raw2.slice(9) : raw2;
|
|
13829
|
-
const sprinkles =
|
|
13832
|
+
const sprinkles = reachable2.filter((info) => info.kind === "sprinkle");
|
|
13830
13833
|
const found = sprinkles.find((info) => info.id === `sprinkle:${name}`) ?? sprinkles.find((info) => cone && info.id === `sprinkle:${cone}/${name}`) ?? sprinkles.find((info) => info.id.split("/").at(-1) === name);
|
|
13831
13834
|
return found?.id ?? null;
|
|
13832
13835
|
}
|
|
13833
13836
|
function state(info) {
|
|
13834
|
-
const
|
|
13835
|
-
return info.busy ? `${
|
|
13837
|
+
const shown3 = info.active ? "active" : info.visible ? "shown" : info.open ? "open" : "closed";
|
|
13838
|
+
return info.busy ? `${shown3} \xB7 busy: ${info.busy}` : shown3;
|
|
13836
13839
|
}
|
|
13837
13840
|
function table(rows) {
|
|
13838
13841
|
const lines = [["ID", "TITLE", "STATE"], ...rows.map((row) => [row.id, row.title, state(row)])];
|
|
13839
13842
|
const widths = [0, 1].map((column) => Math.max(...lines.map((line) => line[column].length)));
|
|
13840
|
-
return lines.map(([id, title,
|
|
13843
|
+
return lines.map(([id, title, shown3]) => `${id.padEnd(widths[0])} ${title.padEnd(widths[1])} ${shown3}`).join("\n");
|
|
13841
13844
|
}
|
|
13842
13845
|
var done = (result, note = "") => result.code === 0 ? { stdout: `${result.message}${note}
|
|
13843
13846
|
`, stderr: "", code: 0 } : { stdout: "", stderr: `panel: ${result.message}
|
|
13844
13847
|
`, code: result.code };
|
|
13845
13848
|
function act(scope, parsed) {
|
|
13846
|
-
const { panels, reachable, cone } = scope;
|
|
13849
|
+
const { panels, reachable: reachable2, cone } = scope;
|
|
13847
13850
|
if (parsed.verb === "reset") {
|
|
13848
13851
|
const recent = scope.agent ? panels.recentClose() : null;
|
|
13849
13852
|
if (recent)
|
|
@@ -13853,11 +13856,11 @@ function act(scope, parsed) {
|
|
|
13853
13856
|
return done(panels.reset());
|
|
13854
13857
|
}
|
|
13855
13858
|
const raw2 = parsed.id;
|
|
13856
|
-
const id = resolve(panels, raw2,
|
|
13859
|
+
const id = resolve(panels, raw2, reachable2, cone);
|
|
13857
13860
|
if (!id) return done(unknown(raw2));
|
|
13858
13861
|
let place3 = parsed.place;
|
|
13859
13862
|
if (typeof place3 === "object") {
|
|
13860
|
-
const ref = resolve(panels, place3.ref,
|
|
13863
|
+
const ref = resolve(panels, place3.ref, reachable2, cone);
|
|
13861
13864
|
if (!ref) return done(unknown(place3.ref));
|
|
13862
13865
|
place3 = { ...place3, ref };
|
|
13863
13866
|
}
|
|
@@ -13892,12 +13895,12 @@ ${help}`, code: 2 };
|
|
|
13892
13895
|
const agents = panels.agents();
|
|
13893
13896
|
const scoped2 = caller.agentId !== null || !!caller.cone;
|
|
13894
13897
|
const cone = scoped2 ? caller.cone ?? coneOf(agents, caller.agentId) : void 0;
|
|
13895
|
-
const
|
|
13898
|
+
const reachable2 = panels.list().filter(
|
|
13896
13899
|
(info) => !scoped2 || info.agent === null || !!cone && coneOf(agents, info.agent) === cone
|
|
13897
13900
|
);
|
|
13898
13901
|
if (parsed.verb !== "list")
|
|
13899
|
-
return act({ panels, agent: caller.agentId !== null, cone, reachable }, parsed);
|
|
13900
|
-
const body4 = parsed.json ? JSON.stringify(
|
|
13902
|
+
return act({ panels, agent: caller.agentId !== null, cone, reachable: reachable2 }, parsed);
|
|
13903
|
+
const body4 = parsed.json ? JSON.stringify(reachable2, null, 2) : table(reachable2);
|
|
13901
13904
|
return { stdout: `${body4}
|
|
13902
13905
|
`, stderr: "", code: 0 };
|
|
13903
13906
|
}
|
|
@@ -20678,12 +20681,12 @@ function user(message) {
|
|
|
20678
20681
|
const tag3 = delivered === "steer" || delivered === "follow-up" ? deliveries[delivered] : null;
|
|
20679
20682
|
const agent = message.origin === "agent";
|
|
20680
20683
|
const name = message.from ?? "an agent";
|
|
20681
|
-
const
|
|
20684
|
+
const who2 = agent ? name : message.from ? `From ${message.from}` : "You";
|
|
20682
20685
|
const label = agent ? `Request from ${name}` : message.from ? `Message from ${message.from}` : "Your message";
|
|
20683
20686
|
return b`<swc-conversation-turn type="user" class="message user" accessible-label=${label} data-id=${message.id} data-mode=${message.mode ?? "send"} data-delivered=${delivered ?? "run"} data-origin=${message.origin ?? "user"}>
|
|
20684
20687
|
<div class="bubble">
|
|
20685
20688
|
<div class="meta">
|
|
20686
|
-
<span class="who">${
|
|
20689
|
+
<span class="who">${who2}</span><span>${time(message.createdAt)}</span>
|
|
20687
20690
|
${agent ? b`<swc-badge class="origin" size="s" variant="indigo">Agent</swc-badge>` : A}
|
|
20688
20691
|
${tag3 ? b`<swc-badge class="tag" size="s" variant=${delivered === "steer" ? "notice" : "informative"} subtle>${tag3}</swc-badge>` : A}
|
|
20689
20692
|
</div>
|
|
@@ -21942,8 +21945,8 @@ var SliccUpdates = class extends ModelElement {
|
|
|
21942
21945
|
#checked(at) {
|
|
21943
21946
|
if (at === null) return b`<span>Not checked yet</span>`;
|
|
21944
21947
|
const date = new Date(at);
|
|
21945
|
-
const
|
|
21946
|
-
return b`<span>Checked <time datetime=${date.toISOString()}>${
|
|
21948
|
+
const shown3 = date.toLocaleString("en-GB", { dateStyle: "medium", timeStyle: "short" });
|
|
21949
|
+
return b`<span>Checked <time datetime=${date.toISOString()}>${shown3}</time></span>`;
|
|
21947
21950
|
}
|
|
21948
21951
|
#item(item2) {
|
|
21949
21952
|
const [variant, state3] = states[item2.state];
|
|
@@ -22008,14 +22011,14 @@ var SliccUpdates = class extends ModelElement {
|
|
|
22008
22011
|
#package(item2, all2, act2) {
|
|
22009
22012
|
const light = packageLight(item2);
|
|
22010
22013
|
const busy = this.busy.get(item2.id);
|
|
22011
|
-
const
|
|
22014
|
+
const shown3 = busy ? [busy] : act2 ? item2.actions : [];
|
|
22012
22015
|
const error = this.problems.get(item2.id) ?? item2.error;
|
|
22013
22016
|
return b`<li data-id=${item2.id} data-state=${item2.state}>
|
|
22014
22017
|
<div class="name">
|
|
22015
22018
|
<h3 title=${item2.package}>${item2.label}</h3>
|
|
22016
22019
|
${light ? b`<swc-status-light size="s" variant=${light[0]}>${light[1]}</swc-status-light>` : A}
|
|
22017
22020
|
</div>
|
|
22018
|
-
<div class="buttons">${
|
|
22021
|
+
<div class="buttons">${shown3.map(
|
|
22019
22022
|
(action) => b`<swc-button
|
|
22020
22023
|
size="s"
|
|
22021
22024
|
variant="secondary"
|
|
@@ -22032,7 +22035,7 @@ var SliccUpdates = class extends ModelElement {
|
|
|
22032
22035
|
(warning) => b`<span><swc-icon-alert-triangle size="s" aria-hidden="true"></swc-icon-alert-triangle>${warning}</span>`
|
|
22033
22036
|
)}</p>` : A}
|
|
22034
22037
|
${item2.commands.length ? b`<p class="commands"><span class="hidden">Commands: </span>${item2.commands.map(
|
|
22035
|
-
(
|
|
22038
|
+
(command3) => b`<code>${command3}</code>`
|
|
22036
22039
|
)}</p>` : A}
|
|
22037
22040
|
${this.#packageProgress(item2)}
|
|
22038
22041
|
${error ? b`<div class="error" role="alert" data-error>
|
|
@@ -22713,9 +22716,9 @@ var SliccApp = class extends ThemedElement {
|
|
|
22713
22716
|
if (!model) return [];
|
|
22714
22717
|
const selected = this.#cone();
|
|
22715
22718
|
const cones = model.agent.list().filter((agent) => agent.kind === "cone");
|
|
22716
|
-
const
|
|
22717
|
-
const order = [selected, ...cones.map((cone) => cone.id), ...
|
|
22718
|
-
return
|
|
22719
|
+
const list5 = model.sprinkles.list();
|
|
22720
|
+
const order = [selected, ...cones.map((cone) => cone.id), ...list5.map((item2) => item2.agentId)];
|
|
22721
|
+
return list5.map((sprinkle) => {
|
|
22719
22722
|
const cone = cones.find((agent) => agent.id === sprinkle.agentId && agent.id !== selected);
|
|
22720
22723
|
return cone ? { ...sprinkle, title: `${cone.name} / ${sprinkle.title}` } : sprinkle;
|
|
22721
22724
|
}).sort((a22, b13) => order.indexOf(a22.agentId) - order.indexOf(b13.agentId));
|
|
@@ -22771,11 +22774,11 @@ var SliccApp = class extends ThemedElement {
|
|
|
22771
22774
|
#rail(items, side) {
|
|
22772
22775
|
const primary = side === "bottom" ? items.filter((item2) => phoneRail.includes(item2.id)) : items;
|
|
22773
22776
|
const fit = primary.length < items.length ? Math.min(primary.length, railCapacity(this.#width, Infinity)) : railCapacity(this.#width, items.length);
|
|
22774
|
-
const
|
|
22775
|
-
const grouped = new Set(
|
|
22776
|
-
return b`<nav class=${`rail ${side}`} aria-label=${`Panels, ${side}`} @dragover=${this.#railOver} @dragleave=${this.#railLeave} @drop=${this.#railDrop}>${
|
|
22777
|
-
(item2, index) => b`${grouped && index &&
|
|
22778
|
-
)}${this.#more(items.filter((item2) => !
|
|
22777
|
+
const shown3 = side === "bottom" ? primary.slice(0, fit) : items;
|
|
22778
|
+
const grouped = new Set(shown3.map((item2) => item2.cone).filter(Boolean)).size > 1;
|
|
22779
|
+
return b`<nav class=${`rail ${side}`} aria-label=${`Panels, ${side}`} @dragover=${this.#railOver} @dragleave=${this.#railLeave} @drop=${this.#railDrop}>${shown3.map(
|
|
22780
|
+
(item2, index) => b`${grouped && index && shown3[index - 1].cone !== item2.cone ? b`<span class="cones" aria-hidden="true"></span>` : A}${this.#railButton(item2, side)}`
|
|
22781
|
+
)}${this.#more(items.filter((item2) => !shown3.includes(item2)))}</nav>`;
|
|
22779
22782
|
}
|
|
22780
22783
|
#rails() {
|
|
22781
22784
|
const dock = this.renderRoot.querySelector("slicc-dock");
|
|
@@ -23018,6 +23021,202 @@ function sudo(approval) {
|
|
|
23018
23021
|
const as = approval.target && approval.target !== "root" ? `-u ${approval.target} ` : "";
|
|
23019
23022
|
return `sudo ${as}${approval.command}`;
|
|
23020
23023
|
}
|
|
23024
|
+
var rulePaths = ["/etc/fnox", "/etc/fnox/config.toml", "/etc/slicc/secrets-policy.toml"];
|
|
23025
|
+
var ruleParents = ["/", "/etc", "/etc/slicc"];
|
|
23026
|
+
function absolute(cwd, word) {
|
|
23027
|
+
const parts2 = [];
|
|
23028
|
+
for (const part2 of `${word.startsWith("/") ? "" : cwd}/${word}`.split("/")) {
|
|
23029
|
+
if (part2 === "..") parts2.pop();
|
|
23030
|
+
else if (part2 && part2 !== ".") parts2.push(part2);
|
|
23031
|
+
const alias = parts2.join("/").match(/^proc\/([^/]+)\/(?:task\/[^/]+\/)?(root|cwd)$/);
|
|
23032
|
+
if (alias?.[2] === "root") parts2.length = 0;
|
|
23033
|
+
else if (alias && /^(?:self|thread-self)$/.test(alias[1]))
|
|
23034
|
+
parts2.splice(0, parts2.length, ...cwd.split("/").filter(Boolean));
|
|
23035
|
+
}
|
|
23036
|
+
return `/${parts2.join("/")}`;
|
|
23037
|
+
}
|
|
23038
|
+
function pattern(path) {
|
|
23039
|
+
const source = path.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*\//g, "").replace(/\*\*/g, "").replace(/\*/g, "[^/]*").replace(/\?/g, "[^/]").replace(/\u0001/g, "(?:.*/)?").replace(/\u0002/g, ".*");
|
|
23040
|
+
return new RegExp(`^${source}$`);
|
|
23041
|
+
}
|
|
23042
|
+
var opaque = /^\/(?:proc\/[^/]+\/(?:task\/[^/]+\/)?(?:cwd|fd|map_files)|dev\/fd)(?:\/|$)/;
|
|
23043
|
+
var certain = (rules) => rules.startsWith("/") && !opaque.test(rules) && !rules.endsWith("\u2026");
|
|
23044
|
+
var readOnly = [
|
|
23045
|
+
"cat",
|
|
23046
|
+
"cd",
|
|
23047
|
+
"df",
|
|
23048
|
+
"diff",
|
|
23049
|
+
"du",
|
|
23050
|
+
"echo",
|
|
23051
|
+
"file",
|
|
23052
|
+
"grep",
|
|
23053
|
+
"head",
|
|
23054
|
+
"ls",
|
|
23055
|
+
"pwd",
|
|
23056
|
+
"readlink",
|
|
23057
|
+
"realpath",
|
|
23058
|
+
"stat",
|
|
23059
|
+
"tail",
|
|
23060
|
+
"tree",
|
|
23061
|
+
"wc"
|
|
23062
|
+
];
|
|
23063
|
+
function candidates(word) {
|
|
23064
|
+
if (word === "--") return [];
|
|
23065
|
+
if (word.startsWith("--")) return [word];
|
|
23066
|
+
if (!word.startsWith("-")) return [word];
|
|
23067
|
+
const slash = word.indexOf("/");
|
|
23068
|
+
const cluster2 = Array.from(word.slice(2), (_9, index) => word.slice(index + 2));
|
|
23069
|
+
return [...cluster2, ...slash > 2 ? [word.slice(slash)] : []];
|
|
23070
|
+
}
|
|
23071
|
+
function protects(path, whole) {
|
|
23072
|
+
const inside = (candidate) => candidate === "/etc/fnox" || candidate.startsWith("/etc/fnox/");
|
|
23073
|
+
if (opaque.test(path)) return true;
|
|
23074
|
+
if (/[[{$]/.test(path)) {
|
|
23075
|
+
const prefix = path.slice(0, path.search(/[*?[{$]/));
|
|
23076
|
+
return inside(prefix) || rulePaths.some((rule) => rule.startsWith(prefix));
|
|
23077
|
+
}
|
|
23078
|
+
if (!/[*?]/.test(path))
|
|
23079
|
+
return inside(path) || rulePaths.includes(path) || whole && ruleParents.includes(path);
|
|
23080
|
+
const glob = pattern(path);
|
|
23081
|
+
const top = path.split("/").slice(0, 3).join("/");
|
|
23082
|
+
return rulePaths.some((rule) => glob.test(rule)) || top !== path && pattern(top).test("/etc/fnox") || whole && ruleParents.some((parent) => glob.test(parent));
|
|
23083
|
+
}
|
|
23084
|
+
var command2 = (word) => word.split("/").pop() ?? "";
|
|
23085
|
+
var trusted = (word) => readOnly.includes(word.replace(/^\/(?:usr\/)?bin\/(?=[^/]+$)/, ""));
|
|
23086
|
+
var expansion = /\$\([^)]*\)?|\$\{[^}]*\}?|\$[\w@*#?$!-]*|`[^`]*`?/;
|
|
23087
|
+
function moved(cwds, word) {
|
|
23088
|
+
for (const cwd of [...cwds]) {
|
|
23089
|
+
const next = absolute(cwd, word);
|
|
23090
|
+
if (protects(next, false) || cwds.size >= 64) return next;
|
|
23091
|
+
cwds.add(next);
|
|
23092
|
+
}
|
|
23093
|
+
return null;
|
|
23094
|
+
}
|
|
23095
|
+
function touched(cwds, word, whole) {
|
|
23096
|
+
for (const candidate of candidates(word))
|
|
23097
|
+
for (const cwd of cwds) {
|
|
23098
|
+
const path = absolute(cwd, candidate);
|
|
23099
|
+
if (protects(path, whole)) return path;
|
|
23100
|
+
}
|
|
23101
|
+
return null;
|
|
23102
|
+
}
|
|
23103
|
+
function ansi(command3) {
|
|
23104
|
+
const escape2 = /\\(?:x([0-9a-fA-F]{1,2})|u([0-9a-fA-F]{1,4})|U([0-9a-fA-F]{1,8})|([0-7]{1,3})|([\s\S]))/g;
|
|
23105
|
+
return command3.replace(
|
|
23106
|
+
/\$'((?:[^'\\]|\\[\s\S])*)'/g,
|
|
23107
|
+
(_9, body4) => `'${body4.replace(escape2, (_match, hex, short2, long, octal, plain) => {
|
|
23108
|
+
if (octal) return String.fromCharCode(Number.parseInt(octal, 8));
|
|
23109
|
+
if (plain) return plain;
|
|
23110
|
+
return String.fromCodePoint(
|
|
23111
|
+
Math.min(Number.parseInt(hex ?? short2 ?? long, 16), 1114111)
|
|
23112
|
+
);
|
|
23113
|
+
}).replace(/'/g, "'\\''")}'`
|
|
23114
|
+
).replace(/\$"/g, '"');
|
|
23115
|
+
}
|
|
23116
|
+
function unglob(command3) {
|
|
23117
|
+
const chars = Array.from(command3);
|
|
23118
|
+
const close = /* @__PURE__ */ new Map();
|
|
23119
|
+
const open = [];
|
|
23120
|
+
for (const [index, char] of chars.entries()) {
|
|
23121
|
+
if (char === "(") open.push(index);
|
|
23122
|
+
else if (char === ")" && open.length) close.set(open.pop(), index);
|
|
23123
|
+
}
|
|
23124
|
+
const out = [];
|
|
23125
|
+
for (let index = 0; index < chars.length; index++) {
|
|
23126
|
+
const end = close.get(index);
|
|
23127
|
+
if (end !== void 0 && /^[?*+@!]$/.test(out.at(-1) ?? "")) {
|
|
23128
|
+
out[out.length - 1] = "*";
|
|
23129
|
+
index = end;
|
|
23130
|
+
} else out.push(chars[index]);
|
|
23131
|
+
}
|
|
23132
|
+
return out.join("");
|
|
23133
|
+
}
|
|
23134
|
+
var separators = /[;&|\n()`]/;
|
|
23135
|
+
function hide2(char) {
|
|
23136
|
+
return separators.test(char) ? String.fromCharCode(57344 + char.charCodeAt(0)) : char;
|
|
23137
|
+
}
|
|
23138
|
+
function unshield(segment2) {
|
|
23139
|
+
return segment2.replace(
|
|
23140
|
+
/[\ue000-\ue07f]/g,
|
|
23141
|
+
(char) => String.fromCharCode(char.charCodeAt(0) - 57344)
|
|
23142
|
+
);
|
|
23143
|
+
}
|
|
23144
|
+
function shield(text2) {
|
|
23145
|
+
let out = "";
|
|
23146
|
+
let quote = "";
|
|
23147
|
+
for (let index = 0; index < text2.length; index++) {
|
|
23148
|
+
const char = text2[index];
|
|
23149
|
+
if (quote === '"' && char === "\\") out += hide2(char) + hide2(text2[++index] ?? "");
|
|
23150
|
+
else if (quote) {
|
|
23151
|
+
out += char === quote ? char : hide2(char);
|
|
23152
|
+
if (char === quote) quote = "";
|
|
23153
|
+
} else if (char === "'" || char === '"') {
|
|
23154
|
+
quote = char;
|
|
23155
|
+
out += char;
|
|
23156
|
+
} else if (char === "\\") out += char + hide2(text2[++index] ?? "");
|
|
23157
|
+
else out += char;
|
|
23158
|
+
}
|
|
23159
|
+
return out;
|
|
23160
|
+
}
|
|
23161
|
+
function quoted(segment2) {
|
|
23162
|
+
const words = [];
|
|
23163
|
+
let word = "";
|
|
23164
|
+
let quote = "";
|
|
23165
|
+
for (let index = 0; index < segment2.length; index++) {
|
|
23166
|
+
const char = segment2[index];
|
|
23167
|
+
if (quote === '"' && char === "\\" && /["\\$`\n]/.test(segment2[index + 1] ?? ""))
|
|
23168
|
+
word += segment2[++index];
|
|
23169
|
+
else if (quote) {
|
|
23170
|
+
if (char === quote) quote = "";
|
|
23171
|
+
else word += char;
|
|
23172
|
+
} else if (char === "'" || char === '"') quote = char;
|
|
23173
|
+
else if (char === "\\") word += segment2[++index] ?? "";
|
|
23174
|
+
else if (/[\s<>=]/.test(char)) {
|
|
23175
|
+
words.push(word);
|
|
23176
|
+
word = "";
|
|
23177
|
+
} else word += char;
|
|
23178
|
+
}
|
|
23179
|
+
return [...words, word];
|
|
23180
|
+
}
|
|
23181
|
+
function commas(words) {
|
|
23182
|
+
return words.flatMap((word) => word.includes(",") ? [word, ...word.split(",")] : [word]).filter(Boolean);
|
|
23183
|
+
}
|
|
23184
|
+
function scan2(words, cwds, whole) {
|
|
23185
|
+
let cd = false;
|
|
23186
|
+
for (const [index, word] of words.entries()) {
|
|
23187
|
+
let hit = null;
|
|
23188
|
+
if (index === 0 || words[index - 1] === "-c") {
|
|
23189
|
+
cd = ["cd", "pushd"].includes(command2(word));
|
|
23190
|
+
hit = touched(cwds, word, whole);
|
|
23191
|
+
} else if (!cd) hit = touched(cwds, word, whole);
|
|
23192
|
+
else if (!word.startsWith("-")) {
|
|
23193
|
+
cd = false;
|
|
23194
|
+
hit = moved(cwds, word);
|
|
23195
|
+
}
|
|
23196
|
+
if (hit) return hit;
|
|
23197
|
+
}
|
|
23198
|
+
return null;
|
|
23199
|
+
}
|
|
23200
|
+
function secretRules(approval) {
|
|
23201
|
+
if (approval.command.length > 4096) return `${approval.command.slice(0, 40)}\u2026`;
|
|
23202
|
+
const start = absolute("/", approval.cwd ?? "/");
|
|
23203
|
+
if (protects(start, false)) return start;
|
|
23204
|
+
const cwds = /* @__PURE__ */ new Set([start]);
|
|
23205
|
+
const text2 = unglob(ansi(approval.command.replace(/\\\n/g, "")));
|
|
23206
|
+
const plain = text2.split(separators).map((segment2) => commas(segment2.split(/[\s<>=]+/).map((word) => word.replace(/['"\\]/g, ""))));
|
|
23207
|
+
const aware = shield(text2).split(separators).map((segment2) => commas(quoted(unshield(segment2))));
|
|
23208
|
+
const segments = JSON.stringify(aware) === JSON.stringify(plain) ? plain : [...plain, ...aware];
|
|
23209
|
+
const whole = segments.some((words) => words.length > 0 && !trusted(words[0]));
|
|
23210
|
+
for (const words of segments) {
|
|
23211
|
+
const hit = scan2(words, cwds, whole);
|
|
23212
|
+
if (hit) return hit;
|
|
23213
|
+
}
|
|
23214
|
+
const named = segments.flat().find((word) => !word.startsWith("/") && /fnox|secrets-policy/.test(word));
|
|
23215
|
+
if (named) return absolute([...cwds].pop() ?? start, named);
|
|
23216
|
+
const home2 = segments.flat().find((word) => /^~(?:[+-](?:\/|$)|.*\/\.\.(?:\/|$))/.test(word));
|
|
23217
|
+
if (home2) return home2;
|
|
23218
|
+
return segments.flat().some((word) => word.includes("$")) || text2.includes("`") ? text2.match(expansion)[0] : null;
|
|
23219
|
+
}
|
|
23021
23220
|
function waiting(model, now) {
|
|
23022
23221
|
return [...model?.approvals?.list() ?? []].filter((approval) => approval.expiresAt > now).sort((a22, b13) => a22.createdAt - b13.createdAt);
|
|
23023
23222
|
}
|
|
@@ -23083,6 +23282,27 @@ var SliccApprovals = class extends ModelElement {
|
|
|
23083
23282
|
margin-block-start: var(--swc-spacing-300);
|
|
23084
23283
|
font-variant-numeric: tabular-nums;
|
|
23085
23284
|
}
|
|
23285
|
+
.rules {
|
|
23286
|
+
display: flex;
|
|
23287
|
+
align-items: flex-start;
|
|
23288
|
+
gap: var(--swc-spacing-100);
|
|
23289
|
+
margin-block-start: var(--swc-spacing-200);
|
|
23290
|
+
padding: var(--swc-spacing-200) var(--swc-spacing-300);
|
|
23291
|
+
border-radius: var(--swc-corner-radius-medium-default);
|
|
23292
|
+
background: var(--swc-notice-subtle-background-color-default);
|
|
23293
|
+
--swc-icon-color: var(--swc-icon-color-notice);
|
|
23294
|
+
}
|
|
23295
|
+
.rules swc-icon-alert-triangle {
|
|
23296
|
+
flex: none;
|
|
23297
|
+
margin-block-start: 0.15em;
|
|
23298
|
+
}
|
|
23299
|
+
.rules p {
|
|
23300
|
+
margin: 0;
|
|
23301
|
+
}
|
|
23302
|
+
.rules code {
|
|
23303
|
+
font-family: var(--swc-code-font-family-stack);
|
|
23304
|
+
overflow-wrap: anywhere;
|
|
23305
|
+
}
|
|
23086
23306
|
.problem {
|
|
23087
23307
|
display: flex;
|
|
23088
23308
|
align-items: flex-start;
|
|
@@ -23137,6 +23357,7 @@ var SliccApprovals = class extends ModelElement {
|
|
|
23137
23357
|
async decide(approval, decision) {
|
|
23138
23358
|
const port = this.model?.approvals;
|
|
23139
23359
|
if (!port?.decide || this.busy || decision !== "deny" && !this.#armed) return;
|
|
23360
|
+
if (decision === "always" && secretRules(approval)) return;
|
|
23140
23361
|
this.busy = decision;
|
|
23141
23362
|
this.failure = null;
|
|
23142
23363
|
this.#pending.add(approval.id);
|
|
@@ -23158,15 +23379,15 @@ var SliccApprovals = class extends ModelElement {
|
|
|
23158
23379
|
}
|
|
23159
23380
|
willUpdate(changed) {
|
|
23160
23381
|
super.willUpdate(changed);
|
|
23161
|
-
const
|
|
23382
|
+
const list5 = this.#current();
|
|
23162
23383
|
const showing = this.#showing;
|
|
23163
23384
|
if (showing && this.#pending.has(showing.id)) return;
|
|
23164
|
-
if (showing && !this.gone && !this.#done.has(showing.id) && !
|
|
23385
|
+
if (showing && !this.gone && !this.#done.has(showing.id) && !list5.some((approval) => approval.id === showing.id)) {
|
|
23165
23386
|
const reason = this.#ended.get(showing.id) ?? (showing.expiresAt <= this.now ? "expired" : "answered");
|
|
23166
23387
|
if (reason !== "withdrawn") this.gone = { approval: showing, reason: gone(reason) };
|
|
23167
23388
|
}
|
|
23168
23389
|
if (this.gone) return;
|
|
23169
|
-
const next =
|
|
23390
|
+
const next = list5[0] ?? null;
|
|
23170
23391
|
if (next?.id === showing?.id) return;
|
|
23171
23392
|
this.#showing = next;
|
|
23172
23393
|
clearTimeout(this.#arming);
|
|
@@ -23237,10 +23458,12 @@ var SliccApprovals = class extends ModelElement {
|
|
|
23237
23458
|
);
|
|
23238
23459
|
}
|
|
23239
23460
|
const held = this.#showing && this.#pending.has(this.#showing.id) ? this.#showing : null;
|
|
23240
|
-
const
|
|
23241
|
-
const [approval, ...rest] = held ? [held, ...
|
|
23461
|
+
const list5 = this.#current();
|
|
23462
|
+
const [approval, ...rest] = held ? [held, ...list5.filter(({ id }) => id !== held.id)] : list5;
|
|
23242
23463
|
if (!approval) return A;
|
|
23243
23464
|
const failure2 = this.failure?.id === approval.id ? this.failure.message : "";
|
|
23465
|
+
const rules = secretRules(approval);
|
|
23466
|
+
const always = approval.always && !rules;
|
|
23244
23467
|
return this.#dialog(
|
|
23245
23468
|
approval,
|
|
23246
23469
|
approval.id,
|
|
@@ -23248,12 +23471,13 @@ var SliccApprovals = class extends ModelElement {
|
|
|
23248
23471
|
<h2 id="title" slot="heading">Allow sudo?</h2>
|
|
23249
23472
|
${this.#request(approval)}
|
|
23250
23473
|
${approval.cwd ? b`<p class="cwd">In ${approval.cwd}</p>` : A}
|
|
23251
|
-
${
|
|
23474
|
+
${rules ? b`<div class="rules" data-secret-rules=${rules}><swc-icon-alert-triangle size="s" aria-hidden="true"></swc-icon-alert-triangle><p>${certain(rules) ? b`<strong>This changes secret rules.</strong> It names <code>${rules}</code>, where SLICC keeps which secrets programs may use and where they may be sent.` : b`<strong>This may change secret rules.</strong> SLICC can't tell where <code>${rules}</code> leads, and it could reach the files where SLICC keeps which secrets programs may use and where they may be sent.`} Allow it only if you asked for this change.</p></div>` : A}
|
|
23475
|
+
${always ? b`<p class="hint">Always allow lets ${approval.requester.name} run exactly this command with sudo without asking again.</p>` : A}
|
|
23252
23476
|
${failure2 ? b`<p class="problem" role="alert" data-error><swc-icon-alert-triangle size="s" aria-hidden="true"></swc-icon-alert-triangle><span>${failure2}</span></p>` : A}
|
|
23253
23477
|
<p class="timer" data-timer>Denied automatically in ${countdown(approval.expiresAt - this.now)}.</p>
|
|
23254
23478
|
${rest.length ? b`<p class="more" data-more>${rest.length === 1 ? "1 more request is waiting." : `${rest.length} more requests are waiting.`}</p>` : A}
|
|
23255
23479
|
${this.#button(approval, "deny", "Deny", "secondary")}
|
|
23256
|
-
${
|
|
23480
|
+
${always ? this.#button(approval, "always", "Always allow", "secondary") : A}
|
|
23257
23481
|
${this.#button(approval, "once", "Allow once", "accent")}
|
|
23258
23482
|
</sp-alert-dialog>`
|
|
23259
23483
|
);
|
|
@@ -24165,9 +24389,9 @@ var SliccBrowser = class extends ModelElement {
|
|
|
24165
24389
|
if (visible2 && tab && !this.#ticker)
|
|
24166
24390
|
this.#ticker = setInterval(() => this.requestUpdate(), 1e3);
|
|
24167
24391
|
if (!(visible2 && tab)) this.#still();
|
|
24168
|
-
const
|
|
24169
|
-
const count =
|
|
24170
|
-
if (
|
|
24392
|
+
const list5 = this.renderRoot.querySelector(".actions:not(.last)");
|
|
24393
|
+
const count = list5?.childElementCount ?? 0;
|
|
24394
|
+
if (list5 && count !== this.#count) list5.scrollTop = list5.scrollHeight;
|
|
24171
24395
|
this.#count = count;
|
|
24172
24396
|
}
|
|
24173
24397
|
#still() {
|
|
@@ -25061,18 +25285,18 @@ function failedTurns(messages, messageId) {
|
|
|
25061
25285
|
}
|
|
25062
25286
|
return ids;
|
|
25063
25287
|
}
|
|
25064
|
-
var
|
|
25288
|
+
var touched2 = false;
|
|
25065
25289
|
document.addEventListener(
|
|
25066
25290
|
"pointerdown",
|
|
25067
25291
|
(event2) => {
|
|
25068
|
-
|
|
25292
|
+
touched2 = event2.pointerType !== "mouse";
|
|
25069
25293
|
},
|
|
25070
25294
|
true
|
|
25071
25295
|
);
|
|
25072
25296
|
document.addEventListener(
|
|
25073
25297
|
"keydown",
|
|
25074
25298
|
() => {
|
|
25075
|
-
|
|
25299
|
+
touched2 = false;
|
|
25076
25300
|
},
|
|
25077
25301
|
true
|
|
25078
25302
|
);
|
|
@@ -25248,7 +25472,7 @@ var SliccChat = class extends ThemedElement {
|
|
|
25248
25472
|
this.#observe();
|
|
25249
25473
|
}
|
|
25250
25474
|
focus() {
|
|
25251
|
-
if (!
|
|
25475
|
+
if (!touched2 && globalThis.matchMedia("(pointer: fine)").matches)
|
|
25252
25476
|
this.focusOn("slicc-composer", ".log");
|
|
25253
25477
|
else this.focusOn(".log");
|
|
25254
25478
|
}
|
|
@@ -26254,7 +26478,7 @@ e25("swc-icon-clock", o84);
|
|
|
26254
26478
|
// src/app/composer.ts
|
|
26255
26479
|
var limit = 25 * 1024 * 1024;
|
|
26256
26480
|
function available(model) {
|
|
26257
|
-
return commands2.filter((
|
|
26481
|
+
return commands2.filter((command3) => command3.available?.(model) ?? true);
|
|
26258
26482
|
}
|
|
26259
26483
|
var commands2 = [
|
|
26260
26484
|
{
|
|
@@ -26333,8 +26557,8 @@ function trigger(text2, caret) {
|
|
|
26333
26557
|
const argument = before.match(/^\/(\w+)\s+(\S*)$/);
|
|
26334
26558
|
if (argument)
|
|
26335
26559
|
return { kind: "argument", start: before.length - argument[2].length, query: argument[2] };
|
|
26336
|
-
const
|
|
26337
|
-
if (
|
|
26560
|
+
const command3 = before.match(/^\/([\w:-]*)$/);
|
|
26561
|
+
if (command3) return { kind: "command", start: 0, query: command3[1] };
|
|
26338
26562
|
const mention = before.match(/(^|\s)@([\w./-]*)$/);
|
|
26339
26563
|
if (mention)
|
|
26340
26564
|
return { kind: "mention", start: before.length - mention[2].length - 1, query: mention[2] };
|
|
@@ -26641,14 +26865,14 @@ var SliccComposer = class extends ModelElement {
|
|
|
26641
26865
|
const text2 = this.value.trim();
|
|
26642
26866
|
const attachments = this.attachments.filter((attachment2) => !attachment2.error);
|
|
26643
26867
|
if (!model || !text2 && attachments.length === 0 || this.#held()) return;
|
|
26644
|
-
const
|
|
26645
|
-
const known =
|
|
26868
|
+
const command3 = text2.match(/^\/(\w+)(?:\s+(.*))?$/);
|
|
26869
|
+
const known = command3 && available(model).find((candidate) => candidate.name === command3[1]);
|
|
26646
26870
|
this.value = "";
|
|
26647
26871
|
this.attachments = [];
|
|
26648
26872
|
this.popup = null;
|
|
26649
26873
|
this.#history = -1;
|
|
26650
26874
|
if (known) {
|
|
26651
|
-
known.run(model, this.#agent, (
|
|
26875
|
+
known.run(model, this.#agent, (command3[2] ?? "").trim());
|
|
26652
26876
|
return;
|
|
26653
26877
|
}
|
|
26654
26878
|
const busy = this.#busy();
|
|
@@ -26736,22 +26960,22 @@ var SliccComposer = class extends ModelElement {
|
|
|
26736
26960
|
const model = this.model;
|
|
26737
26961
|
if (kind === "command") {
|
|
26738
26962
|
const usable = available(model);
|
|
26739
|
-
const builtins = usable.map((
|
|
26740
|
-
value:
|
|
26741
|
-
label: `/${
|
|
26742
|
-
detail:
|
|
26963
|
+
const builtins = usable.map((command3) => ({
|
|
26964
|
+
value: command3.name,
|
|
26965
|
+
label: `/${command3.name}`,
|
|
26966
|
+
detail: command3.detail
|
|
26743
26967
|
}));
|
|
26744
|
-
const own4 = model.agent.commands(this.#agent).filter((
|
|
26745
|
-
value:
|
|
26746
|
-
label: `/${
|
|
26747
|
-
detail:
|
|
26748
|
-
group:
|
|
26968
|
+
const own4 = model.agent.commands(this.#agent).filter((command3) => !usable.some((builtin) => builtin.name === command3.name)).map((command3) => ({
|
|
26969
|
+
value: command3.name,
|
|
26970
|
+
label: `/${command3.name}`,
|
|
26971
|
+
detail: command3.description,
|
|
26972
|
+
group: command3.kind === "skill" ? "Skills" : "Prompts"
|
|
26749
26973
|
})).sort((a22, b13) => a22.group === b13.group ? 0 : a22.group === "Prompts" ? -1 : 1);
|
|
26750
26974
|
return filter([...builtins, ...own4], query, Number.POSITIVE_INFINITY);
|
|
26751
26975
|
}
|
|
26752
26976
|
if (kind === "argument") {
|
|
26753
26977
|
const name = this.value.match(/^\/(\w+)/)?.[1];
|
|
26754
|
-
return filter(commands2.find((
|
|
26978
|
+
return filter(commands2.find((command3) => command3.name === name)?.args?.(model) ?? [], query);
|
|
26755
26979
|
}
|
|
26756
26980
|
const files = this.#paths.map((path) => ({
|
|
26757
26981
|
value: path,
|
|
@@ -26771,7 +26995,7 @@ var SliccComposer = class extends ModelElement {
|
|
|
26771
26995
|
if (this.popup?.kind === "file" || this.popup?.kind === "secret") return;
|
|
26772
26996
|
const found = trigger(this.value, area.selectionStart ?? this.value.length);
|
|
26773
26997
|
const name = this.value.match(/^\/(\w+)/)?.[1];
|
|
26774
|
-
const takes = commands2.some((
|
|
26998
|
+
const takes = commands2.some((command3) => command3.name === name && command3.args);
|
|
26775
26999
|
this.popup = found && (found.kind !== "argument" || takes) ? { ...found, items: this.#choices(found.kind, found.query), index: 0 } : null;
|
|
26776
27000
|
}
|
|
26777
27001
|
openPopup(kind) {
|
|
@@ -27365,8 +27589,8 @@ var SliccMemory = class extends ModelElement {
|
|
|
27365
27589
|
const scopes = this.#scopes;
|
|
27366
27590
|
const scope = this.scope;
|
|
27367
27591
|
const option2 = (item2) => b`<sp-menu-item value=${item2.id}>${item2.label}</sp-menu-item>`;
|
|
27368
|
-
const
|
|
27369
|
-
return b`<div class="bar"><span>${
|
|
27592
|
+
const shown3 = visible(all2, scope, this.tag, this.query);
|
|
27593
|
+
return b`<div class="bar"><span>${shown3.length} of ${all2.filter((memory) => memory.scope === scope).length} memories</span><span class="spacer"></span>
|
|
27370
27594
|
<swc-action-button size="s" quiet @click=${() => this.editing = "new"}><swc-icon-add slot="icon"></swc-icon-add>Remember</swc-action-button>
|
|
27371
27595
|
</div>
|
|
27372
27596
|
<div class="tools">
|
|
@@ -27388,7 +27612,7 @@ var SliccMemory = class extends ModelElement {
|
|
|
27388
27612
|
</div>
|
|
27389
27613
|
<div class="list">
|
|
27390
27614
|
${this.editing === "new" ? b`<div class="row">${this.#form({ scope })}</div>` : A}
|
|
27391
|
-
${
|
|
27615
|
+
${shown3.length ? sections(shown3).map(
|
|
27392
27616
|
([section, items]) => b`<h3>${section}</h3>${items.map((memory) => this.#row(memory))}`
|
|
27393
27617
|
) : b`<div class="note">${all2.length ? "No memories match." : "No memories yet."}</div>`}
|
|
27394
27618
|
</div>`;
|
|
@@ -27696,10 +27920,10 @@ var SliccMonitor = class extends ModelElement {
|
|
|
27696
27920
|
const surface2 = surfaces2[section.id];
|
|
27697
27921
|
const rows = section.rows.length > 0;
|
|
27698
27922
|
const open = rows && (this.expanded[section.id] ?? flag !== null);
|
|
27699
|
-
const
|
|
27923
|
+
const list5 = `rows-${section.id}`;
|
|
27700
27924
|
return b`<li class="section" data-id=${section.id} data-open=${open ? "" : A}>
|
|
27701
27925
|
<div class="line">
|
|
27702
|
-
${rows ? b`<button class="toggle" aria-expanded=${open ? "true" : "false"} aria-controls=${open ?
|
|
27926
|
+
${rows ? b`<button class="toggle" aria-expanded=${open ? "true" : "false"} aria-controls=${open ? list5 : A} @click=${() => {
|
|
27703
27927
|
this.expanded = { ...this.expanded, [section.id]: !open };
|
|
27704
27928
|
}}><span class="chevron"><swc-icon-chevron-right size="s" aria-hidden="true"></swc-icon-chevron-right></span><span class="name">${section.label}</span></button>` : b`<span class="chevron"></span><span class="name">${section.label}</span>`}
|
|
27705
27929
|
${flag ? b`<swc-badge size="s" variant=${flag.variant} subtle>${flag.text}</swc-badge>` : A}
|
|
@@ -27708,7 +27932,7 @@ var SliccMonitor = class extends ModelElement {
|
|
|
27708
27932
|
>Open</swc-action-button
|
|
27709
27933
|
>` : A}
|
|
27710
27934
|
</div>
|
|
27711
|
-
${open ? b`<ul class="rows" id=${
|
|
27935
|
+
${open ? b`<ul class="rows" id=${list5} aria-label=${section.label}>${c(
|
|
27712
27936
|
section.rows,
|
|
27713
27937
|
(row, i25) => row.id ?? i25,
|
|
27714
27938
|
(row) => this.#row(row)
|
|
@@ -27915,6 +28139,748 @@ var SliccNotices = class extends ModelElement {
|
|
|
27915
28139
|
}
|
|
27916
28140
|
};
|
|
27917
28141
|
|
|
28142
|
+
// src/app/vault.ts
|
|
28143
|
+
var exitNames = {
|
|
28144
|
+
"vault-direct": "Straight from the vault",
|
|
28145
|
+
"local-proxy": "Local proxy",
|
|
28146
|
+
"cli-v": "Local SLICC, direct",
|
|
28147
|
+
tailscale: "Tailscale",
|
|
28148
|
+
"local-link": "Linked SLICC, through this page"
|
|
28149
|
+
};
|
|
28150
|
+
function devicesOf(model) {
|
|
28151
|
+
return model?.network?.status().links?.devices ?? [];
|
|
28152
|
+
}
|
|
28153
|
+
function deviceName2(id, devices) {
|
|
28154
|
+
return (devices.find((device) => device.id === id)?.name ?? id).replace(/^slicc\b/i, "SLICC");
|
|
28155
|
+
}
|
|
28156
|
+
function exitLabel(exit, devices) {
|
|
28157
|
+
if (exit.startsWith("device:")) return deviceName2(exit.slice("device:".length), devices);
|
|
28158
|
+
return exitNames[exit];
|
|
28159
|
+
}
|
|
28160
|
+
function list4(items) {
|
|
28161
|
+
if (items.length < 2) return items.join("");
|
|
28162
|
+
return `${items.slice(0, -1).join(", ")} and ${items[items.length - 1]}`;
|
|
28163
|
+
}
|
|
28164
|
+
function ruleLine(rule) {
|
|
28165
|
+
const methods = rule.methods.length ? rule.methods.join(" or ") : "any method";
|
|
28166
|
+
const paths = rule.paths.length ? rule.paths.join(" or ") : "any path";
|
|
28167
|
+
return `${rule.domain}, in ${rule.header}, ${methods}, ${paths}`;
|
|
28168
|
+
}
|
|
28169
|
+
function shellWord(word) {
|
|
28170
|
+
return /^[\w@%+=:,./-]+$/.test(word) ? word : `'${word.replace(/'/g, "'\\''")}'`;
|
|
28171
|
+
}
|
|
28172
|
+
function execLine(grant) {
|
|
28173
|
+
if (grant === false) return "Never revealed to programs";
|
|
28174
|
+
if (grant === true) return "Revealed to any program that asks";
|
|
28175
|
+
return `Revealed only to ${list4(grant.argv.map((argv) => argv.map(shellWord).join(" ")))}`;
|
|
28176
|
+
}
|
|
28177
|
+
function widening(change, devices) {
|
|
28178
|
+
switch (change.kind) {
|
|
28179
|
+
case "rule":
|
|
28180
|
+
return `${change.secret} may now be sent to ${ruleLine(change.rule)}`;
|
|
28181
|
+
case "methods":
|
|
28182
|
+
return `${change.secret} may now use ${list4(change.methods)} on ${change.domain}`;
|
|
28183
|
+
case "paths":
|
|
28184
|
+
return `${change.secret} may now reach ${list4(change.paths)} on ${change.domain}`;
|
|
28185
|
+
case "exec": {
|
|
28186
|
+
const line = execLine(change.grant);
|
|
28187
|
+
return `${change.secret}: ${line[0].toLowerCase()}${line.slice(1)}`;
|
|
28188
|
+
}
|
|
28189
|
+
case "exit":
|
|
28190
|
+
return `${change.secret} may now leave through ${exitLabel(change.exit, devices)}`;
|
|
28191
|
+
default:
|
|
28192
|
+
return `The limit ${change.field} rose from ${change.from} to ${change.to}`;
|
|
28193
|
+
}
|
|
28194
|
+
}
|
|
28195
|
+
function shown2(element2, style = getComputedStyle(element2)) {
|
|
28196
|
+
return !element2.hidden && !element2.inert && style.display !== "none";
|
|
28197
|
+
}
|
|
28198
|
+
function disabled(element2) {
|
|
28199
|
+
if (element2.matches(":disabled")) return true;
|
|
28200
|
+
if (!element2.matches("button, input, select, textarea")) return false;
|
|
28201
|
+
let fieldset = element2.closest("fieldset[disabled]");
|
|
28202
|
+
while (fieldset) {
|
|
28203
|
+
if (!fieldset.querySelector(":scope > legend")?.contains(element2)) return true;
|
|
28204
|
+
fieldset = fieldset.parentElement?.closest("fieldset[disabled]") ?? null;
|
|
28205
|
+
}
|
|
28206
|
+
return false;
|
|
28207
|
+
}
|
|
28208
|
+
function reachable(element2) {
|
|
28209
|
+
const radio = element2;
|
|
28210
|
+
if (radio.localName !== "input" || radio.type !== "radio" || !radio.name) return true;
|
|
28211
|
+
const root2 = radio.getRootNode();
|
|
28212
|
+
const group = Array.from(root2.querySelectorAll("input[type=radio]")).filter(
|
|
28213
|
+
(other) => other.name === radio.name && other.form === radio.form
|
|
28214
|
+
);
|
|
28215
|
+
const checked = group.find((other) => other.checked);
|
|
28216
|
+
return checked ? checked === radio : radio === group[0] || radio === group.at(-1);
|
|
28217
|
+
}
|
|
28218
|
+
function tabbables(root2, stop, out = []) {
|
|
28219
|
+
for (const child of Array.from(root2.children)) {
|
|
28220
|
+
if (child === stop) {
|
|
28221
|
+
out.push(null);
|
|
28222
|
+
continue;
|
|
28223
|
+
}
|
|
28224
|
+
const style = getComputedStyle(child);
|
|
28225
|
+
if (!shown2(child, style)) continue;
|
|
28226
|
+
if (child.localName === "details" && !child.open) {
|
|
28227
|
+
const summary = child.querySelector(":scope > summary");
|
|
28228
|
+
if (summary && shown2(summary) && getComputedStyle(summary).visibility !== "hidden" && !(summary.hasAttribute("tabindex") && summary.tabIndex < 0))
|
|
28229
|
+
out.push(summary);
|
|
28230
|
+
continue;
|
|
28231
|
+
}
|
|
28232
|
+
if (child.tabIndex >= 0 && !disabled(child) && style.visibility !== "hidden" && reachable(child))
|
|
28233
|
+
out.push(child);
|
|
28234
|
+
if (child.shadowRoot) tabbables(child.shadowRoot, stop, out);
|
|
28235
|
+
tabbables(child, stop, out);
|
|
28236
|
+
}
|
|
28237
|
+
return out;
|
|
28238
|
+
}
|
|
28239
|
+
function sequential(order) {
|
|
28240
|
+
const rank = (element2) => element2 && element2.tabIndex > 0 ? element2.tabIndex : Number.POSITIVE_INFINITY;
|
|
28241
|
+
return [...order].sort((a22, b13) => rank(a22) - rank(b13) || 0);
|
|
28242
|
+
}
|
|
28243
|
+
var SliccVaultButton = class extends i2 {
|
|
28244
|
+
static properties = {
|
|
28245
|
+
vault: { attribute: false },
|
|
28246
|
+
config: { attribute: false }
|
|
28247
|
+
};
|
|
28248
|
+
#button = null;
|
|
28249
|
+
#off = null;
|
|
28250
|
+
#ready = false;
|
|
28251
|
+
#sent = "";
|
|
28252
|
+
static styles = i`
|
|
28253
|
+
:host {
|
|
28254
|
+
display: inline-flex;
|
|
28255
|
+
vertical-align: middle;
|
|
28256
|
+
}
|
|
28257
|
+
iframe {
|
|
28258
|
+
border: 0;
|
|
28259
|
+
background: transparent;
|
|
28260
|
+
color-scheme: normal;
|
|
28261
|
+
}
|
|
28262
|
+
`;
|
|
28263
|
+
constructor() {
|
|
28264
|
+
super();
|
|
28265
|
+
this.vault = null;
|
|
28266
|
+
this.config = null;
|
|
28267
|
+
}
|
|
28268
|
+
connectedCallback() {
|
|
28269
|
+
super.connectedCallback();
|
|
28270
|
+
this.requestUpdate();
|
|
28271
|
+
}
|
|
28272
|
+
disconnectedCallback() {
|
|
28273
|
+
super.disconnectedCallback();
|
|
28274
|
+
this.#drop();
|
|
28275
|
+
}
|
|
28276
|
+
focus() {
|
|
28277
|
+
this.#button?.post({ type: "slicc-vault", v: 1, op: "focus" });
|
|
28278
|
+
}
|
|
28279
|
+
updated(changed) {
|
|
28280
|
+
if (changed.has("vault")) this.#drop();
|
|
28281
|
+
if (!this.#button && this.vault) this.#mount(this.vault);
|
|
28282
|
+
this.#send();
|
|
28283
|
+
}
|
|
28284
|
+
#mount(vault) {
|
|
28285
|
+
const button = vault.button();
|
|
28286
|
+
this.#button = button;
|
|
28287
|
+
this.#off = button.listen((event2) => this.#event(event2));
|
|
28288
|
+
this.renderRoot.append(button.element);
|
|
28289
|
+
}
|
|
28290
|
+
#drop() {
|
|
28291
|
+
this.#off?.();
|
|
28292
|
+
this.#button?.element.remove();
|
|
28293
|
+
this.#button = null;
|
|
28294
|
+
this.#off = null;
|
|
28295
|
+
this.#ready = false;
|
|
28296
|
+
this.#sent = "";
|
|
28297
|
+
}
|
|
28298
|
+
#send() {
|
|
28299
|
+
if (!(this.#ready && this.#button && this.config)) return;
|
|
28300
|
+
const sent = JSON.stringify(this.config);
|
|
28301
|
+
if (sent === this.#sent) return;
|
|
28302
|
+
this.#sent = sent;
|
|
28303
|
+
this.#button.post({ type: "slicc-vault", v: 1, op: "button", button: this.config });
|
|
28304
|
+
}
|
|
28305
|
+
#event(event2) {
|
|
28306
|
+
const element2 = this.#button?.element;
|
|
28307
|
+
if (event2.event === "ready") {
|
|
28308
|
+
this.#ready = true;
|
|
28309
|
+
this.#send();
|
|
28310
|
+
} else if (event2.event === "size") {
|
|
28311
|
+
element2.style.width = `${event2.width}px`;
|
|
28312
|
+
element2.style.height = `${event2.height}px`;
|
|
28313
|
+
element2.style.margin = `${-event2.inset}px`;
|
|
28314
|
+
} else if (event2.event === "label") {
|
|
28315
|
+
element2.title = event2.label;
|
|
28316
|
+
} else if (event2.event === "focus") {
|
|
28317
|
+
const order = sequential(tabbables(this.ownerDocument, this));
|
|
28318
|
+
const at = order.indexOf(null);
|
|
28319
|
+
order[event2.direction === "next" ? at + 1 : at - 1]?.focus();
|
|
28320
|
+
} else if (event2.event === "popup") {
|
|
28321
|
+
const { intent, state: state3, result } = event2;
|
|
28322
|
+
this.dispatchEvent(
|
|
28323
|
+
new CustomEvent("vault-popup", {
|
|
28324
|
+
detail: { intent, state: state3, ...result ? { result } : {} },
|
|
28325
|
+
bubbles: true,
|
|
28326
|
+
composed: true
|
|
28327
|
+
})
|
|
28328
|
+
);
|
|
28329
|
+
}
|
|
28330
|
+
}
|
|
28331
|
+
};
|
|
28332
|
+
|
|
28333
|
+
// src/app/secrets.ts
|
|
28334
|
+
var kinds = { secret: null, grant: "Sign-in", model: "Model key", mcp: "MCP server" };
|
|
28335
|
+
var lockModes = {
|
|
28336
|
+
auto: "Unlocks with this browser",
|
|
28337
|
+
passkey: "Unlocks with a passkey",
|
|
28338
|
+
passphrase: "Unlocks with a passphrase"
|
|
28339
|
+
};
|
|
28340
|
+
function until(at, now = Date.now()) {
|
|
28341
|
+
const minutes = Math.ceil((at - now) / 6e4);
|
|
28342
|
+
if (minutes <= 0) return "expired";
|
|
28343
|
+
if (minutes < 60) return `in ${minutes} min`;
|
|
28344
|
+
const hours = Math.round(minutes / 60);
|
|
28345
|
+
if (hours < 24) return `in ${hours} h`;
|
|
28346
|
+
const days = Math.round(hours / 24);
|
|
28347
|
+
return `in ${days} ${days === 1 ? "day" : "days"}`;
|
|
28348
|
+
}
|
|
28349
|
+
function who(entry) {
|
|
28350
|
+
if (entry.tag) return entry.tag;
|
|
28351
|
+
if (entry.uid === null) return "the vault";
|
|
28352
|
+
return entry.uid === 0 ? "root" : `uid ${entry.uid}`;
|
|
28353
|
+
}
|
|
28354
|
+
function sourceLine(secret, devices) {
|
|
28355
|
+
const on = secret.sourceDevice ? ` on ${deviceName2(secret.sourceDevice, devices)}` : "";
|
|
28356
|
+
const [kind, detail = ""] = secret.source.split(/:(.*)/s);
|
|
28357
|
+
if (kind === "popup") return `Entered in the vault${on}`;
|
|
28358
|
+
if (kind === "process") return `Saved by a program${on}`;
|
|
28359
|
+
if (kind === "import") return `Imported from ${detail}`;
|
|
28360
|
+
if (kind === "oauth") {
|
|
28361
|
+
const as = secret.account ? ` as ${secret.account}` : "";
|
|
28362
|
+
return `Signed in to ${secret.provider ?? detail}${as}`;
|
|
28363
|
+
}
|
|
28364
|
+
return `A jerk lease for ${detail.split("@")[0]}${on}`;
|
|
28365
|
+
}
|
|
28366
|
+
function startOfDay(now) {
|
|
28367
|
+
const date = new Date(now);
|
|
28368
|
+
date.setHours(0, 0, 0, 0);
|
|
28369
|
+
return date.getTime();
|
|
28370
|
+
}
|
|
28371
|
+
function revealed(name, entries, now = Date.now(), more = false) {
|
|
28372
|
+
const reveals = entries.filter(
|
|
28373
|
+
(entry) => entry.type === "materialize" && entry.name === name
|
|
28374
|
+
);
|
|
28375
|
+
if (!reveals.length) return null;
|
|
28376
|
+
const [last] = reveals;
|
|
28377
|
+
const start = startOfDay(now);
|
|
28378
|
+
const today = reveals.filter((entry) => entry.at >= start).length;
|
|
28379
|
+
const partial = more && (entries[entries.length - 1]?.at ?? 0) >= start;
|
|
28380
|
+
const when = today ? `${partial ? "at least " : ""}${today} ${today === 1 ? "time" : "times"} today` : since(last.at, now);
|
|
28381
|
+
return b`Revealed to programs ${when}, last by ${who(last)} with <code>${last.argv}</code>`;
|
|
28382
|
+
}
|
|
28383
|
+
function auditLine(entry, devices) {
|
|
28384
|
+
switch (entry.type) {
|
|
28385
|
+
case "inject":
|
|
28386
|
+
case "forward":
|
|
28387
|
+
return b`${entry.type === "inject" ? "Sent to" : "Forwarded to"} ${entry.domain}: <code>${entry.method} ${entry.path}</code>, through ${exitLabel(entry.exit, devices)}`;
|
|
28388
|
+
case "materialize":
|
|
28389
|
+
return b`Revealed to <code>${entry.argv}</code> in <code>${entry.cwd}</code>`;
|
|
28390
|
+
case "seal":
|
|
28391
|
+
return b`${entry.rotated ? "Value replaced" : "Value saved"}`;
|
|
28392
|
+
case "remove":
|
|
28393
|
+
return b`Removed`;
|
|
28394
|
+
case "restore":
|
|
28395
|
+
return b`Restored`;
|
|
28396
|
+
default: {
|
|
28397
|
+
const count = entry.widened.length;
|
|
28398
|
+
const widened = count ? `, widening ${count} ${count === 1 ? "rule" : "rules"}` : "";
|
|
28399
|
+
return b`<code>${entry.file}</code> ${entry.accepted ? `changed${widened}` : "changed and was refused"}${entry.warning ? b`. ${entry.warning}` : A}`;
|
|
28400
|
+
}
|
|
28401
|
+
}
|
|
28402
|
+
}
|
|
28403
|
+
function merged(...pages) {
|
|
28404
|
+
const bySeq = /* @__PURE__ */ new Map();
|
|
28405
|
+
for (const page of pages) for (const entry of page) bySeq.set(entry.seq, entry);
|
|
28406
|
+
return [...bySeq.values()].sort((a22, b13) => b13.seq - a22.seq);
|
|
28407
|
+
}
|
|
28408
|
+
function prompt2(text2) {
|
|
28409
|
+
return text2.length > 200 ? `${text2.slice(0, 199)}\u2026` : text2;
|
|
28410
|
+
}
|
|
28411
|
+
var SliccSecrets = class extends ThemedElement {
|
|
28412
|
+
static properties = {
|
|
28413
|
+
...ThemedElement.properties,
|
|
28414
|
+
older: { state: true },
|
|
28415
|
+
more: { state: true },
|
|
28416
|
+
loading: { state: true },
|
|
28417
|
+
reveals: { state: true },
|
|
28418
|
+
popup: { state: true },
|
|
28419
|
+
acking: { state: true },
|
|
28420
|
+
failure: { state: true }
|
|
28421
|
+
};
|
|
28422
|
+
#tick;
|
|
28423
|
+
constructor() {
|
|
28424
|
+
super();
|
|
28425
|
+
this.older = [];
|
|
28426
|
+
this.more = null;
|
|
28427
|
+
this.loading = false;
|
|
28428
|
+
this.reveals = false;
|
|
28429
|
+
this.popup = null;
|
|
28430
|
+
this.acking = /* @__PURE__ */ new Set();
|
|
28431
|
+
this.failure = null;
|
|
28432
|
+
}
|
|
28433
|
+
static styles = i`
|
|
28434
|
+
:host {
|
|
28435
|
+
display: block;
|
|
28436
|
+
container-type: inline-size;
|
|
28437
|
+
}
|
|
28438
|
+
h2 {
|
|
28439
|
+
font-size: var(--swc-heading-size-xs);
|
|
28440
|
+
font-weight: var(--swc-bold-font-weight);
|
|
28441
|
+
line-height: var(--swc-heading-line-height);
|
|
28442
|
+
color: var(--swc-heading-color);
|
|
28443
|
+
margin: 0;
|
|
28444
|
+
}
|
|
28445
|
+
h3 {
|
|
28446
|
+
font-size: var(--swc-font-size-100);
|
|
28447
|
+
font-weight: var(--swc-bold-font-weight);
|
|
28448
|
+
color: var(--swc-heading-color);
|
|
28449
|
+
margin: var(--swc-spacing-400) 0 var(--swc-spacing-100);
|
|
28450
|
+
}
|
|
28451
|
+
p {
|
|
28452
|
+
margin: var(--swc-spacing-100) 0;
|
|
28453
|
+
}
|
|
28454
|
+
ul,
|
|
28455
|
+
ol {
|
|
28456
|
+
list-style: none;
|
|
28457
|
+
margin: 0;
|
|
28458
|
+
padding: 0;
|
|
28459
|
+
}
|
|
28460
|
+
code {
|
|
28461
|
+
font-family: var(--swc-code-font-family, ui-monospace, monospace);
|
|
28462
|
+
font-size: 0.9em;
|
|
28463
|
+
overflow-wrap: anywhere;
|
|
28464
|
+
}
|
|
28465
|
+
.head {
|
|
28466
|
+
display: flex;
|
|
28467
|
+
flex-wrap: wrap;
|
|
28468
|
+
align-items: baseline;
|
|
28469
|
+
gap: var(--swc-spacing-200) var(--swc-spacing-300);
|
|
28470
|
+
margin: var(--swc-spacing-500) 0 var(--swc-spacing-200);
|
|
28471
|
+
}
|
|
28472
|
+
.head slicc-vault-button {
|
|
28473
|
+
align-self: center;
|
|
28474
|
+
margin-inline-start: auto;
|
|
28475
|
+
}
|
|
28476
|
+
.muted {
|
|
28477
|
+
color: var(--swc-neutral-subdued-content-color-default);
|
|
28478
|
+
}
|
|
28479
|
+
.box {
|
|
28480
|
+
display: grid;
|
|
28481
|
+
gap: var(--swc-spacing-100);
|
|
28482
|
+
padding: var(--swc-spacing-200) var(--swc-spacing-300);
|
|
28483
|
+
margin: var(--swc-spacing-200) 0;
|
|
28484
|
+
border-radius: var(--swc-corner-radius-100);
|
|
28485
|
+
border: var(--swc-border-width-100) solid var(--swc-gray-200);
|
|
28486
|
+
background: var(--swc-background-layer-1-color);
|
|
28487
|
+
}
|
|
28488
|
+
.box.notice {
|
|
28489
|
+
border-color: var(--swc-notice-visual-color);
|
|
28490
|
+
--swc-icon-color: var(--swc-notice-visual-color);
|
|
28491
|
+
}
|
|
28492
|
+
.box .title {
|
|
28493
|
+
display: flex;
|
|
28494
|
+
align-items: flex-start;
|
|
28495
|
+
gap: var(--swc-spacing-100);
|
|
28496
|
+
font-weight: var(--swc-bold-font-weight);
|
|
28497
|
+
}
|
|
28498
|
+
.box ul {
|
|
28499
|
+
list-style: disc;
|
|
28500
|
+
padding-inline-start: var(--swc-spacing-400);
|
|
28501
|
+
}
|
|
28502
|
+
.box .actions {
|
|
28503
|
+
display: flex;
|
|
28504
|
+
flex-wrap: wrap;
|
|
28505
|
+
align-items: center;
|
|
28506
|
+
gap: var(--swc-spacing-200);
|
|
28507
|
+
}
|
|
28508
|
+
.prompt {
|
|
28509
|
+
margin: 0;
|
|
28510
|
+
padding-inline-start: var(--swc-spacing-200);
|
|
28511
|
+
border-inline-start: var(--swc-border-width-200) solid var(--swc-gray-300);
|
|
28512
|
+
overflow-wrap: anywhere;
|
|
28513
|
+
}
|
|
28514
|
+
.said {
|
|
28515
|
+
white-space: pre-wrap;
|
|
28516
|
+
}
|
|
28517
|
+
.from {
|
|
28518
|
+
display: block;
|
|
28519
|
+
font-size: var(--swc-font-size-75);
|
|
28520
|
+
color: var(--swc-neutral-subdued-content-color-default);
|
|
28521
|
+
}
|
|
28522
|
+
.secrets {
|
|
28523
|
+
display: grid;
|
|
28524
|
+
gap: var(--swc-spacing-200);
|
|
28525
|
+
}
|
|
28526
|
+
.secret {
|
|
28527
|
+
display: grid;
|
|
28528
|
+
grid-template-columns: minmax(0, 1fr) max-content;
|
|
28529
|
+
gap: var(--swc-spacing-100) var(--swc-spacing-300);
|
|
28530
|
+
padding: var(--swc-spacing-200) 0;
|
|
28531
|
+
border-top: var(--swc-border-width-100) solid var(--swc-gray-200);
|
|
28532
|
+
}
|
|
28533
|
+
.secret:first-child {
|
|
28534
|
+
border-top: 0;
|
|
28535
|
+
}
|
|
28536
|
+
.name {
|
|
28537
|
+
display: flex;
|
|
28538
|
+
flex-wrap: wrap;
|
|
28539
|
+
align-items: baseline;
|
|
28540
|
+
gap: var(--swc-spacing-100) var(--swc-spacing-200);
|
|
28541
|
+
min-width: 0;
|
|
28542
|
+
}
|
|
28543
|
+
.name code {
|
|
28544
|
+
font-size: var(--swc-font-size-100);
|
|
28545
|
+
font-weight: var(--swc-bold-font-weight);
|
|
28546
|
+
}
|
|
28547
|
+
.secret slicc-vault-button {
|
|
28548
|
+
align-self: start;
|
|
28549
|
+
}
|
|
28550
|
+
.removed {
|
|
28551
|
+
margin-top: var(--swc-spacing-200);
|
|
28552
|
+
border-top: var(--swc-border-width-100) solid var(--swc-gray-200);
|
|
28553
|
+
padding-top: var(--swc-spacing-200);
|
|
28554
|
+
}
|
|
28555
|
+
.removed summary {
|
|
28556
|
+
cursor: pointer;
|
|
28557
|
+
font-size: var(--swc-font-size-75);
|
|
28558
|
+
color: var(--swc-neutral-subdued-content-color-default);
|
|
28559
|
+
}
|
|
28560
|
+
.removed .secret dl,
|
|
28561
|
+
.removed .secret .name code {
|
|
28562
|
+
color: var(--swc-neutral-subdued-content-color-default);
|
|
28563
|
+
}
|
|
28564
|
+
dl {
|
|
28565
|
+
grid-column: 1 / -1;
|
|
28566
|
+
display: grid;
|
|
28567
|
+
grid-template-columns: max-content minmax(0, 1fr);
|
|
28568
|
+
gap: var(--swc-spacing-50) var(--swc-spacing-300);
|
|
28569
|
+
margin: 0;
|
|
28570
|
+
font-size: var(--swc-font-size-75);
|
|
28571
|
+
line-height: var(--swc-line-height-200);
|
|
28572
|
+
}
|
|
28573
|
+
dt {
|
|
28574
|
+
color: var(--swc-neutral-subdued-content-color-default);
|
|
28575
|
+
}
|
|
28576
|
+
dd {
|
|
28577
|
+
margin: 0;
|
|
28578
|
+
min-width: 0;
|
|
28579
|
+
overflow-wrap: anywhere;
|
|
28580
|
+
}
|
|
28581
|
+
.audit-head {
|
|
28582
|
+
display: flex;
|
|
28583
|
+
flex-wrap: wrap;
|
|
28584
|
+
align-items: baseline;
|
|
28585
|
+
justify-content: space-between;
|
|
28586
|
+
gap: var(--swc-spacing-200);
|
|
28587
|
+
margin: var(--swc-spacing-400) 0 var(--swc-spacing-100);
|
|
28588
|
+
}
|
|
28589
|
+
.audit-head h3 {
|
|
28590
|
+
margin-block: 0;
|
|
28591
|
+
}
|
|
28592
|
+
.audit li {
|
|
28593
|
+
display: grid;
|
|
28594
|
+
grid-template-columns: 7em minmax(0, 1fr);
|
|
28595
|
+
gap: var(--swc-spacing-50) var(--swc-spacing-300);
|
|
28596
|
+
padding: var(--swc-spacing-100) 0;
|
|
28597
|
+
border-top: var(--swc-border-width-100) solid var(--swc-gray-200);
|
|
28598
|
+
font-size: var(--swc-font-size-75);
|
|
28599
|
+
line-height: var(--swc-line-height-200);
|
|
28600
|
+
}
|
|
28601
|
+
.audit time {
|
|
28602
|
+
color: var(--swc-neutral-subdued-content-color-default);
|
|
28603
|
+
}
|
|
28604
|
+
.audit .what {
|
|
28605
|
+
overflow-wrap: anywhere;
|
|
28606
|
+
}
|
|
28607
|
+
.audit .by {
|
|
28608
|
+
color: var(--swc-neutral-subdued-content-color-default);
|
|
28609
|
+
}
|
|
28610
|
+
.row {
|
|
28611
|
+
display: flex;
|
|
28612
|
+
flex-wrap: wrap;
|
|
28613
|
+
align-items: center;
|
|
28614
|
+
gap: var(--swc-spacing-200);
|
|
28615
|
+
margin-top: var(--swc-spacing-200);
|
|
28616
|
+
}
|
|
28617
|
+
.error {
|
|
28618
|
+
display: flex;
|
|
28619
|
+
align-items: flex-start;
|
|
28620
|
+
gap: var(--swc-spacing-100);
|
|
28621
|
+
color: var(--swc-negative-content-color-default);
|
|
28622
|
+
font-size: var(--swc-font-size-75);
|
|
28623
|
+
--swc-icon-color: var(--swc-negative-content-color-default);
|
|
28624
|
+
}
|
|
28625
|
+
@container (max-width: 480px) {
|
|
28626
|
+
.secret {
|
|
28627
|
+
grid-template-columns: minmax(0, 1fr);
|
|
28628
|
+
}
|
|
28629
|
+
.secret slicc-vault-button {
|
|
28630
|
+
order: 1;
|
|
28631
|
+
justify-self: start;
|
|
28632
|
+
}
|
|
28633
|
+
dl {
|
|
28634
|
+
grid-template-columns: minmax(0, 1fr);
|
|
28635
|
+
}
|
|
28636
|
+
dd {
|
|
28637
|
+
margin-bottom: var(--swc-spacing-75);
|
|
28638
|
+
}
|
|
28639
|
+
.audit li {
|
|
28640
|
+
grid-template-columns: minmax(0, 1fr);
|
|
28641
|
+
}
|
|
28642
|
+
}
|
|
28643
|
+
`;
|
|
28644
|
+
#pushed = [];
|
|
28645
|
+
disconnectedCallback() {
|
|
28646
|
+
super.disconnectedCallback();
|
|
28647
|
+
clearTimeout(this.#tick);
|
|
28648
|
+
this.older = [];
|
|
28649
|
+
this.more = null;
|
|
28650
|
+
this.#pushed = [];
|
|
28651
|
+
}
|
|
28652
|
+
willUpdate(changed) {
|
|
28653
|
+
super.willUpdate(changed);
|
|
28654
|
+
const before = changed.get("model");
|
|
28655
|
+
if (!changed.has("model") || before?.vault === this.model?.vault) return;
|
|
28656
|
+
this.older = [];
|
|
28657
|
+
this.more = null;
|
|
28658
|
+
this.loading = false;
|
|
28659
|
+
this.popup = null;
|
|
28660
|
+
this.acking = /* @__PURE__ */ new Set();
|
|
28661
|
+
this.failure = null;
|
|
28662
|
+
this.#pushed = [];
|
|
28663
|
+
}
|
|
28664
|
+
updated() {
|
|
28665
|
+
clearTimeout(this.#tick);
|
|
28666
|
+
if (!this.isConnected) return;
|
|
28667
|
+
const now = Date.now();
|
|
28668
|
+
const next = Math.min(
|
|
28669
|
+
now + 6e4,
|
|
28670
|
+
...(this.model?.vault?.list()?.secrets ?? []).map((secret) => secret.expiresAt ?? Number.POSITIVE_INFINITY).filter((at) => at > now)
|
|
28671
|
+
);
|
|
28672
|
+
this.#tick = setTimeout(() => this.requestUpdate(), next - now);
|
|
28673
|
+
}
|
|
28674
|
+
#listed(vault) {
|
|
28675
|
+
this.#pushed = [];
|
|
28676
|
+
const head2 = vault.list()?.audit ?? [];
|
|
28677
|
+
const last = head2[head2.length - 1];
|
|
28678
|
+
if (this.older.length && (!last || last.seq > this.older[0].seq + 1)) {
|
|
28679
|
+
this.older = [];
|
|
28680
|
+
this.more = null;
|
|
28681
|
+
}
|
|
28682
|
+
this.requestUpdate();
|
|
28683
|
+
}
|
|
28684
|
+
#noticed(notice) {
|
|
28685
|
+
this.#pushed = [...this.#pushed.filter((item2) => item2.id !== notice.id), notice];
|
|
28686
|
+
this.requestUpdate();
|
|
28687
|
+
}
|
|
28688
|
+
subscribe(model) {
|
|
28689
|
+
const update = () => this.requestUpdate();
|
|
28690
|
+
return [
|
|
28691
|
+
...super.subscribe(model),
|
|
28692
|
+
...model.vault ? [
|
|
28693
|
+
model.vault.on("status", update),
|
|
28694
|
+
model.vault.on("list", () => this.#listed(model.vault)),
|
|
28695
|
+
model.vault.on("notice", (notice) => this.#noticed(notice))
|
|
28696
|
+
] : [],
|
|
28697
|
+
...model.network ? [model.network.on("network", update)] : []
|
|
28698
|
+
];
|
|
28699
|
+
}
|
|
28700
|
+
#button(config) {
|
|
28701
|
+
const theme3 = this.color;
|
|
28702
|
+
return b`<slicc-vault-button
|
|
28703
|
+
.vault=${this.model?.vault}
|
|
28704
|
+
.config=${{ size: "m", variant: "secondary", ...config, theme: theme3 }}
|
|
28705
|
+
@vault-popup=${(event2) => this.#popup(event2.detail)}
|
|
28706
|
+
></slicc-vault-button>`;
|
|
28707
|
+
}
|
|
28708
|
+
#popup(detail) {
|
|
28709
|
+
this.popup = detail;
|
|
28710
|
+
}
|
|
28711
|
+
async showOlder(vault, entries) {
|
|
28712
|
+
this.loading = true;
|
|
28713
|
+
this.failure = null;
|
|
28714
|
+
try {
|
|
28715
|
+
const before = entries[entries.length - 1]?.seq;
|
|
28716
|
+
const page = await vault.audit(before);
|
|
28717
|
+
if (this.model?.vault !== vault || !this.isConnected) return;
|
|
28718
|
+
const shown3 = merged(vault.list()?.audit ?? [], this.older);
|
|
28719
|
+
if (shown3[shown3.length - 1]?.seq !== before) return;
|
|
28720
|
+
this.older = merged(this.older, page.audit);
|
|
28721
|
+
this.more = page.more;
|
|
28722
|
+
} catch (error) {
|
|
28723
|
+
if (this.model?.vault === vault && this.isConnected) this.failure = error.message;
|
|
28724
|
+
} finally {
|
|
28725
|
+
if (this.model?.vault === vault) this.loading = false;
|
|
28726
|
+
}
|
|
28727
|
+
}
|
|
28728
|
+
async acknowledge(vault, notice) {
|
|
28729
|
+
if (this.acking.has(notice.id)) return;
|
|
28730
|
+
this.acking = /* @__PURE__ */ new Set([...this.acking, notice.id]);
|
|
28731
|
+
this.failure = null;
|
|
28732
|
+
try {
|
|
28733
|
+
await vault.acknowledge(notice.id);
|
|
28734
|
+
if (this.model?.vault === vault)
|
|
28735
|
+
this.#pushed = this.#pushed.filter((item2) => item2.id !== notice.id);
|
|
28736
|
+
} catch (error) {
|
|
28737
|
+
if (this.model?.vault === vault && this.isConnected) this.failure = error.message;
|
|
28738
|
+
} finally {
|
|
28739
|
+
if (this.model?.vault === vault)
|
|
28740
|
+
this.acking = new Set([...this.acking].filter((id) => id !== notice.id));
|
|
28741
|
+
}
|
|
28742
|
+
}
|
|
28743
|
+
#request(request2) {
|
|
28744
|
+
const asker = who(request2);
|
|
28745
|
+
const what = request2.kind === "value" ? b`${asker} asks for <code>${request2.name}</code>` : request2.kind === "oauth" ? b`${asker} asks you to sign in to ${request2.provider}` : b`${asker} asks for a jerk lease for ${request2.provider}`;
|
|
28746
|
+
return b`<div class="box" data-request=${request2.id}>
|
|
28747
|
+
<span class="title">${what}</span>
|
|
28748
|
+
${request2.prompt ? b`<p class="prompt" data-prompt><span class="from">From the agent, not checked by SLICC:</span> <span class="said">${prompt2(request2.prompt)}</span></p>` : A}
|
|
28749
|
+
<div class="actions">
|
|
28750
|
+
${this.#button({ intent: { kind: "request", request: request2.id }, label: "Answer in the vault", variant: "accent" })}
|
|
28751
|
+
<span class="muted">Expires ${until(request2.expiresAt)}</span>
|
|
28752
|
+
</div>
|
|
28753
|
+
</div>`;
|
|
28754
|
+
}
|
|
28755
|
+
#notice(vault, notice, devices) {
|
|
28756
|
+
return b`<div class="box notice" role="alert" data-notice=${notice.id}>
|
|
28757
|
+
<span class="title"><swc-icon-alert-triangle size="s" aria-hidden="true"></swc-icon-alert-triangle><span>Rules widened in <code>${notice.file}</code> ${since(notice.at)}</span></span>
|
|
28758
|
+
<ul>${notice.widened.map((change) => b`<li>${widening(change, devices)}</li>`)}</ul>
|
|
28759
|
+
<span>If you didn’t mean this, change the file back with sudo.</span>
|
|
28760
|
+
<div class="actions"><swc-button size="s" variant="secondary" data-action="acknowledge" ?pending=${this.acking.has(notice.id)} @click=${() => this.acknowledge(vault, notice)}>Acknowledge</swc-button></div>
|
|
28761
|
+
</div>`;
|
|
28762
|
+
}
|
|
28763
|
+
#state(secret) {
|
|
28764
|
+
const [variant, label] = secret.state === "removed" ? ["neutral", "Removed"] : secret.expiresAt !== void 0 && secret.expiresAt <= Date.now() ? ["notice", "Expired"] : secret.state === "inert" ? ["neutral", "No rule yet"] : ["positive", "Active"];
|
|
28765
|
+
return b`<swc-status-light size="s" variant=${variant}>${label}</swc-status-light>`;
|
|
28766
|
+
}
|
|
28767
|
+
#action(secret) {
|
|
28768
|
+
if (secret.state === "removed")
|
|
28769
|
+
return this.#button({
|
|
28770
|
+
intent: { kind: "manage", name: secret.name },
|
|
28771
|
+
label: "Manage",
|
|
28772
|
+
size: "s"
|
|
28773
|
+
});
|
|
28774
|
+
if (secret.source.startsWith("oauth:"))
|
|
28775
|
+
return this.#button({
|
|
28776
|
+
intent: { kind: "signin", provider: secret.source.slice("oauth:".length) },
|
|
28777
|
+
label: "Sign in again",
|
|
28778
|
+
size: "s"
|
|
28779
|
+
});
|
|
28780
|
+
return this.#button({
|
|
28781
|
+
intent: { kind: "enter", name: secret.name },
|
|
28782
|
+
label: "Replace value",
|
|
28783
|
+
size: "s"
|
|
28784
|
+
});
|
|
28785
|
+
}
|
|
28786
|
+
#secret(secret, entries, devices, more) {
|
|
28787
|
+
const kind = kinds[secret.kind];
|
|
28788
|
+
const reveal = revealed(secret.name, entries, Date.now(), more);
|
|
28789
|
+
const gone2 = secret.state === "removed";
|
|
28790
|
+
return b`<li class="secret" data-secret=${secret.name} data-state=${secret.state}>
|
|
28791
|
+
<div class="name">
|
|
28792
|
+
<code>${secret.name}</code>
|
|
28793
|
+
${kind ? b`<swc-badge size="s" variant="neutral" subtle>${kind}</swc-badge>` : A}
|
|
28794
|
+
${this.#state(secret)}
|
|
28795
|
+
</div>
|
|
28796
|
+
${this.#action(secret)}
|
|
28797
|
+
<dl>
|
|
28798
|
+
<dt>${gone2 ? "Was sent to" : "Sent to"}</dt>
|
|
28799
|
+
<dd data-rules>${secret.rules.length ? secret.rules.map((rule, index) => b`${index ? b`<br />` : A}${ruleLine(rule)}`) : "Nowhere yet: no rule names it"}</dd>
|
|
28800
|
+
<dt>${gone2 ? "Left through" : "Leaves through"}</dt>
|
|
28801
|
+
<dd data-exits>${list4(secret.exits.map((exit) => exitLabel(exit, devices)))}</dd>
|
|
28802
|
+
<dt>Programs</dt>
|
|
28803
|
+
<dd data-exec>${execLine(secret.exec)}${reveal ? b`<br />${reveal}` : A}</dd>
|
|
28804
|
+
<dt>From</dt>
|
|
28805
|
+
<dd data-source>${sourceLine(secret, devices)}</dd>
|
|
28806
|
+
${secret.usedAt ? b`<dt>Last used</dt><dd data-used>${since(secret.usedAt)}</dd>` : A}
|
|
28807
|
+
${secret.expiresAt ? b`<dt>Expires</dt><dd data-expires>${until(secret.expiresAt)}</dd>` : A}
|
|
28808
|
+
${secret.removedAt ? b`<dt>Removed</dt><dd>${since(secret.removedAt)}</dd>` : A}
|
|
28809
|
+
</dl>
|
|
28810
|
+
</li>`;
|
|
28811
|
+
}
|
|
28812
|
+
#secrets(list5, entries, devices) {
|
|
28813
|
+
const more = this.more ?? list5.auditMore;
|
|
28814
|
+
const row = (secret) => this.#secret(secret, entries, devices, more);
|
|
28815
|
+
const live = list5.secrets.filter((secret) => secret.state !== "removed");
|
|
28816
|
+
const removed = list5.secrets.filter((secret) => secret.state === "removed");
|
|
28817
|
+
return b`${live.length ? b`<ul class="secrets" aria-labelledby="secrets">${live.map(row)}</ul>` : A}
|
|
28818
|
+
${removed.length ? b`<details class="removed" data-removed>
|
|
28819
|
+
<summary>Removed (${removed.length})</summary>
|
|
28820
|
+
<ul class="secrets">${removed.map(row)}</ul>
|
|
28821
|
+
</details>` : A}`;
|
|
28822
|
+
}
|
|
28823
|
+
#entry(entry, devices) {
|
|
28824
|
+
const date = new Date(entry.at);
|
|
28825
|
+
const name = entry.type === "policy" ? null : entry.name;
|
|
28826
|
+
return b`<li data-seq=${entry.seq} data-type=${entry.type}>
|
|
28827
|
+
<time datetime=${date.toISOString()} title=${date.toLocaleString("en-GB", { dateStyle: "medium", timeStyle: "short" })}>${since(entry.at)}</time>
|
|
28828
|
+
<span class="what">${name ? b`<code>${name}</code> · ` : A}${auditLine(entry, devices)}${entry.type === "policy" ? A : b` <span class="by">by ${who(entry)}</span>`}</span>
|
|
28829
|
+
</li>`;
|
|
28830
|
+
}
|
|
28831
|
+
#audit(vault, list5, entries, devices) {
|
|
28832
|
+
const shown3 = this.reveals ? entries.filter((entry) => entry.type === "materialize") : entries;
|
|
28833
|
+
const more = this.more ?? list5.auditMore;
|
|
28834
|
+
return b`<div class="audit-head">
|
|
28835
|
+
<h3 id="secrets-audit">Activity</h3>
|
|
28836
|
+
<sp-switch size="s" data-action="reveals" .checked=${this.reveals} @change=${(event2) => {
|
|
28837
|
+
this.reveals = event2.target.checked;
|
|
28838
|
+
}}>Only reveals to programs</sp-switch>
|
|
28839
|
+
</div>
|
|
28840
|
+
${shown3.length ? b`<ol class="audit" aria-labelledby="secrets-audit">${shown3.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>`}
|
|
28841
|
+
${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}`;
|
|
28842
|
+
}
|
|
28843
|
+
#feedback() {
|
|
28844
|
+
if (this.popup?.state === "blocked")
|
|
28845
|
+
return b`<div class="error" 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>`;
|
|
28846
|
+
if (this.popup?.state === "done" && this.popup.result)
|
|
28847
|
+
return b`<p role="status" data-popup="done">Saved <code>${this.popup.result.name}</code> in the vault.</p>`;
|
|
28848
|
+
return A;
|
|
28849
|
+
}
|
|
28850
|
+
render() {
|
|
28851
|
+
const vault = this.model?.vault;
|
|
28852
|
+
if (!vault) return A;
|
|
28853
|
+
const status2 = vault.status();
|
|
28854
|
+
const current = vault.list();
|
|
28855
|
+
const devices = devicesOf(this.model);
|
|
28856
|
+
const entries = merged(current?.audit ?? [], this.older);
|
|
28857
|
+
const listed = current?.notices ?? [];
|
|
28858
|
+
const notices = [
|
|
28859
|
+
...listed,
|
|
28860
|
+
...this.#pushed.filter((notice) => !listed.some((item2) => item2.id === notice.id))
|
|
28861
|
+
].filter((notice) => !notice.acknowledged);
|
|
28862
|
+
return b`<section aria-labelledby="secrets" data-vault=${status2 ? status2.locked ? "locked" : "unlocked" : "loading"}>
|
|
28863
|
+
<div class="head">
|
|
28864
|
+
<h2 id="secrets">Secrets</h2>
|
|
28865
|
+
${status2 ? b`<swc-status-light size="m" variant=${status2.locked ? "notice" : "positive"}>${status2.locked ? "Locked" : "Unlocked"}</swc-status-light><span class="muted">${lockModes[status2.lock]}</span>` : A}
|
|
28866
|
+
${status2?.locked ? this.#button({ intent: { kind: "unlock" }, label: "Unlock", variant: "accent" }) : this.#button({ intent: { kind: "manage" }, label: "Open the vault" })}
|
|
28867
|
+
</div>
|
|
28868
|
+
<p class="muted">Agents and programs use secrets by name. The values stay in the vault, so SLICC never sees or shows them.</p>
|
|
28869
|
+
${this.#feedback()}
|
|
28870
|
+
${this.failure ? b`<div class="error" role="alert" data-error="vault"><swc-icon-alert-triangle size="s" aria-hidden="true"></swc-icon-alert-triangle><span>${this.failure}</span></div>` : A}
|
|
28871
|
+
${status2?.waiting.length ? b`<h3>Waiting for you</h3>${status2.waiting.map((request2) => this.#request(request2))}` : A}
|
|
28872
|
+
${notices.map((notice) => this.#notice(vault, notice, devices))}
|
|
28873
|
+
${!current ? b`<p class="muted" data-loading>Loading secrets…</p>` : current.secrets.length ? this.#secrets(current, entries, devices) : b`<p data-empty>No secrets yet. When an agent or program needs one, it asks here, and you enter the value in the vault.</p>`}
|
|
28874
|
+
<p class="muted" data-policy>Rules live in <code>/etc/fnox/config.toml</code> and <code>/etc/slicc/secrets-policy.toml</code>. Change them with sudo; SLICC asks you before every change.</p>
|
|
28875
|
+
<div class="row">
|
|
28876
|
+
${this.#button({ intent: { kind: "import" }, label: "Import\u2026", size: "s" })}
|
|
28877
|
+
${this.#button({ intent: { kind: "export" }, label: "Export\u2026", size: "s" })}
|
|
28878
|
+
</div>
|
|
28879
|
+
${current ? this.#audit(vault, current, entries, devices) : A}
|
|
28880
|
+
</section>`;
|
|
28881
|
+
}
|
|
28882
|
+
};
|
|
28883
|
+
|
|
27918
28884
|
// src/app/settings.ts
|
|
27919
28885
|
var accountStatus = {
|
|
27920
28886
|
connected: ["positive", "Connected"],
|
|
@@ -28272,6 +29238,7 @@ var SliccSettings = class extends ModelElement {
|
|
|
28272
29238
|
<div class="accounts">${providers.map((account) => this.#account(account))}</div>
|
|
28273
29239
|
${servers.length ? b`<h2>MCP servers</h2>
|
|
28274
29240
|
<div class="accounts" data-group="mcp">${servers.map((account) => this.#account(account))}</div>` : A}
|
|
29241
|
+
${this.model?.vault ? b`<slicc-secrets .model=${this.model}></slicc-secrets>` : A}
|
|
28275
29242
|
</div>`;
|
|
28276
29243
|
}
|
|
28277
29244
|
};
|
|
@@ -31067,14 +32034,14 @@ var RegexSource = class {
|
|
|
31067
32034
|
return CAPTURING_REGEX_SOURCE.test(regexSource);
|
|
31068
32035
|
}
|
|
31069
32036
|
static replaceCaptures(regexSource, captureSource, captureIndices) {
|
|
31070
|
-
return regexSource.replace(CAPTURING_REGEX_SOURCE, (match, index, commandIndex,
|
|
32037
|
+
return regexSource.replace(CAPTURING_REGEX_SOURCE, (match, index, commandIndex, command3) => {
|
|
31071
32038
|
let capture = captureIndices[parseInt(index || commandIndex, 10)];
|
|
31072
32039
|
if (capture) {
|
|
31073
32040
|
let result = captureSource.substring(capture.start, capture.end);
|
|
31074
32041
|
while (result[0] === ".") {
|
|
31075
32042
|
result = result.substring(1);
|
|
31076
32043
|
}
|
|
31077
|
-
switch (
|
|
32044
|
+
switch (command3) {
|
|
31078
32045
|
case "downcase":
|
|
31079
32046
|
return result.toLowerCase();
|
|
31080
32047
|
case "upcase":
|
|
@@ -32088,8 +33055,8 @@ var IncludeOnlyRule = class extends Rule {
|
|
|
32088
33055
|
}
|
|
32089
33056
|
}
|
|
32090
33057
|
collectPatterns(grammar2, out) {
|
|
32091
|
-
for (const
|
|
32092
|
-
const rule = grammar2.getRule(
|
|
33058
|
+
for (const pattern2 of this.patterns) {
|
|
33059
|
+
const rule = grammar2.getRule(pattern2);
|
|
32093
33060
|
rule.collectPatterns(grammar2, out);
|
|
32094
33061
|
}
|
|
32095
33062
|
}
|
|
@@ -32156,8 +33123,8 @@ var BeginEndRule = class extends Rule {
|
|
|
32156
33123
|
_getCachedCompiledPatterns(grammar2, endRegexSource) {
|
|
32157
33124
|
if (!this._cachedCompiledPatterns) {
|
|
32158
33125
|
this._cachedCompiledPatterns = new RegExpSourceList();
|
|
32159
|
-
for (const
|
|
32160
|
-
const rule = grammar2.getRule(
|
|
33126
|
+
for (const pattern2 of this.patterns) {
|
|
33127
|
+
const rule = grammar2.getRule(pattern2);
|
|
32161
33128
|
rule.collectPatterns(grammar2, this._cachedCompiledPatterns);
|
|
32162
33129
|
}
|
|
32163
33130
|
if (this.applyEndPatternLast) {
|
|
@@ -32229,8 +33196,8 @@ var BeginWhileRule = class extends Rule {
|
|
|
32229
33196
|
_getCachedCompiledPatterns(grammar2) {
|
|
32230
33197
|
if (!this._cachedCompiledPatterns) {
|
|
32231
33198
|
this._cachedCompiledPatterns = new RegExpSourceList();
|
|
32232
|
-
for (const
|
|
32233
|
-
const rule = grammar2.getRule(
|
|
33199
|
+
for (const pattern2 of this.patterns) {
|
|
33200
|
+
const rule = grammar2.getRule(pattern2);
|
|
32234
33201
|
rule.collectPatterns(grammar2, this._cachedCompiledPatterns);
|
|
32235
33202
|
}
|
|
32236
33203
|
}
|
|
@@ -32351,14 +33318,14 @@ var RuleFactory = class _RuleFactory {
|
|
|
32351
33318
|
let r39 = [];
|
|
32352
33319
|
if (patterns) {
|
|
32353
33320
|
for (let i25 = 0, len = patterns.length; i25 < len; i25++) {
|
|
32354
|
-
const
|
|
33321
|
+
const pattern2 = patterns[i25];
|
|
32355
33322
|
let ruleId = -1;
|
|
32356
|
-
if (
|
|
32357
|
-
const reference2 = parseInclude(
|
|
33323
|
+
if (pattern2.include) {
|
|
33324
|
+
const reference2 = parseInclude(pattern2.include);
|
|
32358
33325
|
switch (reference2.kind) {
|
|
32359
33326
|
case 0:
|
|
32360
33327
|
case 1:
|
|
32361
|
-
ruleId = _RuleFactory.getCompiledRuleId(repository[
|
|
33328
|
+
ruleId = _RuleFactory.getCompiledRuleId(repository[pattern2.include], helper, repository);
|
|
32362
33329
|
break;
|
|
32363
33330
|
case 2:
|
|
32364
33331
|
let localIncludedRule = repository[reference2.ruleName];
|
|
@@ -32387,7 +33354,7 @@ var RuleFactory = class _RuleFactory {
|
|
|
32387
33354
|
break;
|
|
32388
33355
|
}
|
|
32389
33356
|
} else {
|
|
32390
|
-
ruleId = _RuleFactory.getCompiledRuleId(
|
|
33357
|
+
ruleId = _RuleFactory.getCompiledRuleId(pattern2, helper, repository);
|
|
32391
33358
|
}
|
|
32392
33359
|
if (ruleId !== -1) {
|
|
32393
33360
|
const rule = helper.getRule(ruleId);
|
|
@@ -37230,13 +38197,13 @@ function splitTokens(tokens, breakpoints) {
|
|
|
37230
38197
|
});
|
|
37231
38198
|
});
|
|
37232
38199
|
}
|
|
37233
|
-
function flatTokenVariants(
|
|
38200
|
+
function flatTokenVariants(merged2, variantsOrder, cssVariablePrefix, defaultColor, colorsRendering = "css-vars") {
|
|
37234
38201
|
const token2 = {
|
|
37235
|
-
content:
|
|
37236
|
-
explanation:
|
|
37237
|
-
offset:
|
|
38202
|
+
content: merged2.content,
|
|
38203
|
+
explanation: merged2.explanation,
|
|
38204
|
+
offset: merged2.offset
|
|
37238
38205
|
};
|
|
37239
|
-
const styles = variantsOrder.map((t88) => getTokenStyleObject(
|
|
38206
|
+
const styles = variantsOrder.map((t88) => getTokenStyleObject(merged2.variants[t88]));
|
|
37240
38207
|
const styleKeys = new Set(styles.flatMap((t88) => Object.keys(t88)));
|
|
37241
38208
|
const mergedStyles = {};
|
|
37242
38209
|
const varKey = (idx, key2) => {
|
|
@@ -39346,25 +40313,25 @@ var namedCaptureDelim = r35`\(\?<(?![=!])(?<captureName>[^>]+)>`;
|
|
|
39346
40313
|
var captureDelim = r35`${namedCaptureDelim}|(?<unnamed>\()(?!\?)`;
|
|
39347
40314
|
var token = new RegExp(r35`${namedCaptureDelim}|${recursiveToken}|\(\?|\\?.`, "gsu");
|
|
39348
40315
|
var overlappingRecursionMsg = "Cannot use multiple overlapping recursions";
|
|
39349
|
-
function recursion(
|
|
40316
|
+
function recursion(pattern2, data) {
|
|
39350
40317
|
const { hiddenCaptures, mode } = {
|
|
39351
40318
|
hiddenCaptures: [],
|
|
39352
40319
|
mode: "plugin",
|
|
39353
40320
|
...data
|
|
39354
40321
|
};
|
|
39355
40322
|
let captureTransfers = data?.captureTransfers ?? /* @__PURE__ */ new Map();
|
|
39356
|
-
if (!new RegExp(recursiveToken, "su").test(
|
|
40323
|
+
if (!new RegExp(recursiveToken, "su").test(pattern2)) {
|
|
39357
40324
|
return {
|
|
39358
|
-
pattern,
|
|
40325
|
+
pattern: pattern2,
|
|
39359
40326
|
captureTransfers,
|
|
39360
40327
|
hiddenCaptures
|
|
39361
40328
|
};
|
|
39362
40329
|
}
|
|
39363
|
-
if (mode === "plugin" && hasUnescaped(
|
|
40330
|
+
if (mode === "plugin" && hasUnescaped(pattern2, r35`\(\?\(DEFINE\)`, Context.DEFAULT)) {
|
|
39364
40331
|
throw new Error("DEFINE groups cannot be used with recursion");
|
|
39365
40332
|
}
|
|
39366
40333
|
const addedHiddenCaptures = [];
|
|
39367
|
-
const hasNumberedBackref = hasUnescaped(
|
|
40334
|
+
const hasNumberedBackref = hasUnescaped(pattern2, r35`\\[1-9]`, Context.DEFAULT);
|
|
39368
40335
|
const groupContentsStartPos = /* @__PURE__ */ new Map();
|
|
39369
40336
|
const openGroups = [];
|
|
39370
40337
|
let hasRecursed = false;
|
|
@@ -39372,7 +40339,7 @@ function recursion(pattern, data) {
|
|
|
39372
40339
|
let numCapturesPassed = 0;
|
|
39373
40340
|
let match;
|
|
39374
40341
|
token.lastIndex = 0;
|
|
39375
|
-
while (match = token.exec(
|
|
40342
|
+
while (match = token.exec(pattern2)) {
|
|
39376
40343
|
const { 0: m15, groups: { captureName, rDepth, gRNameOrNum, gRDepth } } = match;
|
|
39377
40344
|
if (m15 === "[") {
|
|
39378
40345
|
numCharClassesOpen++;
|
|
@@ -39389,13 +40356,13 @@ function recursion(pattern, data) {
|
|
|
39389
40356
|
`${mode === "external" ? "Backrefs" : "Numbered backrefs"} cannot be used with global recursion`
|
|
39390
40357
|
);
|
|
39391
40358
|
}
|
|
39392
|
-
const left =
|
|
39393
|
-
const right =
|
|
40359
|
+
const left = pattern2.slice(0, match.index);
|
|
40360
|
+
const right = pattern2.slice(token.lastIndex);
|
|
39394
40361
|
if (hasUnescaped(right, recursiveToken, Context.DEFAULT)) {
|
|
39395
40362
|
throw new Error(overlappingRecursionMsg);
|
|
39396
40363
|
}
|
|
39397
40364
|
const reps = +rDepth - 1;
|
|
39398
|
-
|
|
40365
|
+
pattern2 = makeRecursive(
|
|
39399
40366
|
left,
|
|
39400
40367
|
right,
|
|
39401
40368
|
reps,
|
|
@@ -39429,7 +40396,7 @@ function recursion(pattern, data) {
|
|
|
39429
40396
|
throw new Error(r35`Recursive \g cannot be used outside the referenced group "${mode === "external" ? gRNameOrNum : r35`\g<${gRNameOrNum}&R=${gRDepth}>`}"`);
|
|
39430
40397
|
}
|
|
39431
40398
|
const startPos = groupContentsStartPos.get(gRNameOrNum);
|
|
39432
|
-
const groupContents = getGroupContents(
|
|
40399
|
+
const groupContents = getGroupContents(pattern2, startPos);
|
|
39433
40400
|
if (hasNumberedBackref && hasUnescaped(groupContents, r35`${namedCaptureDelim}|\((?!\?)`, Context.DEFAULT)) {
|
|
39434
40401
|
throw new Error(
|
|
39435
40402
|
// When used in `external` mode by transpilers other than Regex+, backrefs might have
|
|
@@ -39437,11 +40404,11 @@ function recursion(pattern, data) {
|
|
|
39437
40404
|
`${mode === "external" ? "Backrefs" : "Numbered backrefs"} cannot be used with recursion of capturing groups`
|
|
39438
40405
|
);
|
|
39439
40406
|
}
|
|
39440
|
-
const groupContentsLeft =
|
|
40407
|
+
const groupContentsLeft = pattern2.slice(startPos, match.index);
|
|
39441
40408
|
const groupContentsRight = groupContents.slice(groupContentsLeft.length + m15.length);
|
|
39442
40409
|
const numAddedHiddenCapturesPreExpansion = addedHiddenCaptures.length;
|
|
39443
40410
|
const reps = +gRDepth - 1;
|
|
39444
|
-
const
|
|
40411
|
+
const expansion2 = makeRecursive(
|
|
39445
40412
|
groupContentsLeft,
|
|
39446
40413
|
groupContentsRight,
|
|
39447
40414
|
reps,
|
|
@@ -39458,10 +40425,10 @@ function recursion(pattern, data) {
|
|
|
39458
40425
|
numAddedHiddenCapturesPreExpansion,
|
|
39459
40426
|
numCapturesPassed
|
|
39460
40427
|
);
|
|
39461
|
-
const pre =
|
|
39462
|
-
const post =
|
|
39463
|
-
|
|
39464
|
-
token.lastIndex +=
|
|
40428
|
+
const pre = pattern2.slice(0, startPos);
|
|
40429
|
+
const post = pattern2.slice(startPos + groupContents.length);
|
|
40430
|
+
pattern2 = `${pre}${expansion2}${post}`;
|
|
40431
|
+
token.lastIndex += expansion2.length - m15.length - groupContentsLeft.length - groupContentsRight.length;
|
|
39465
40432
|
openGroups.forEach((g7) => g7.hasRecursedWithin = true);
|
|
39466
40433
|
hasRecursed = true;
|
|
39467
40434
|
} else if (captureName) {
|
|
@@ -39488,7 +40455,7 @@ function recursion(pattern, data) {
|
|
|
39488
40455
|
}
|
|
39489
40456
|
hiddenCaptures.push(...addedHiddenCaptures);
|
|
39490
40457
|
return {
|
|
39491
|
-
pattern,
|
|
40458
|
+
pattern: pattern2,
|
|
39492
40459
|
captureTransfers,
|
|
39493
40460
|
hiddenCaptures
|
|
39494
40461
|
};
|
|
@@ -39519,14 +40486,14 @@ function makeRecursive(left, right, reps, isSubpattern, hiddenCaptures, addedHid
|
|
|
39519
40486
|
];
|
|
39520
40487
|
return `${left}${repeatWithDepth(`(?:${left}`, "forward", ...rest)}(?:)${repeatWithDepth(`${right})`, "backward", ...rest)}${right}`;
|
|
39521
40488
|
}
|
|
39522
|
-
function repeatWithDepth(
|
|
40489
|
+
function repeatWithDepth(pattern2, direction, reps, namesInRecursed, hiddenCaptures, addedHiddenCaptures, numCapturesPassed) {
|
|
39523
40490
|
const startNum = 2;
|
|
39524
40491
|
const getDepthNum = (i25) => direction === "forward" ? i25 + startNum : reps - i25 + startNum - 1;
|
|
39525
40492
|
let result = "";
|
|
39526
40493
|
for (let i25 = 0; i25 < reps; i25++) {
|
|
39527
40494
|
const depthNum = getDepthNum(i25);
|
|
39528
40495
|
result += replaceUnescaped(
|
|
39529
|
-
|
|
40496
|
+
pattern2,
|
|
39530
40497
|
r35`${captureDelim}|\\k<(?<backref>[^>]+)>`,
|
|
39531
40498
|
({ 0: m15, groups: { captureName, unnamed, backref } }) => {
|
|
39532
40499
|
if (backref && namesInRecursed && !namesInRecursed.has(backref)) {
|
|
@@ -40609,8 +41576,8 @@ function isLoneGLookaround(node, options) {
|
|
|
40609
41576
|
function isValidJsGroupName(name) {
|
|
40610
41577
|
return /^[$_\p{IDS}][$\u200C\u200D\p{IDC}]*$/u.test(name);
|
|
40611
41578
|
}
|
|
40612
|
-
function parseFragment(
|
|
40613
|
-
const ast = J2(
|
|
41579
|
+
function parseFragment(pattern2, options) {
|
|
41580
|
+
const ast = J2(pattern2, {
|
|
40614
41581
|
...options,
|
|
40615
41582
|
// Providing a custom set of Unicode property names avoids converting some JS Unicode
|
|
40616
41583
|
// properties (ex: `\p{Alpha}`) to Onig POSIX classes
|
|
@@ -41206,13 +42173,13 @@ var EmulatedRegExp = class _EmulatedRegExp extends RegExp {
|
|
|
41206
42173
|
@param {EmulatedRegExp} pattern
|
|
41207
42174
|
@param {string} [flags]
|
|
41208
42175
|
*/
|
|
41209
|
-
constructor(
|
|
42176
|
+
constructor(pattern2, flags, options) {
|
|
41210
42177
|
const lazyCompile = !!options?.lazyCompile;
|
|
41211
|
-
if (
|
|
42178
|
+
if (pattern2 instanceof RegExp) {
|
|
41212
42179
|
if (options) {
|
|
41213
42180
|
throw new Error("Cannot provide options when copying a regexp");
|
|
41214
42181
|
}
|
|
41215
|
-
const re3 =
|
|
42182
|
+
const re3 = pattern2;
|
|
41216
42183
|
super(re3, flags);
|
|
41217
42184
|
this.#pattern = re3.source;
|
|
41218
42185
|
if (re3 instanceof _EmulatedRegExp) {
|
|
@@ -41228,8 +42195,8 @@ var EmulatedRegExp = class _EmulatedRegExp extends RegExp {
|
|
|
41228
42195
|
transfers: [],
|
|
41229
42196
|
...options
|
|
41230
42197
|
};
|
|
41231
|
-
super(lazyCompile ? "" :
|
|
41232
|
-
this.#pattern =
|
|
42198
|
+
super(lazyCompile ? "" : pattern2, flags);
|
|
42199
|
+
this.#pattern = pattern2;
|
|
41233
42200
|
this.#captureMap = createCaptureMap(opts.hiddenCaptures, opts.transfers);
|
|
41234
42201
|
this.#strategy = opts.strategy;
|
|
41235
42202
|
this.rawOptions = options ?? {};
|
|
@@ -41355,13 +42322,13 @@ function createCaptureMap(hiddenCaptures, transfers) {
|
|
|
41355
42322
|
}
|
|
41356
42323
|
return captureMap;
|
|
41357
42324
|
}
|
|
41358
|
-
function createNameMap(
|
|
42325
|
+
function createNameMap(pattern2) {
|
|
41359
42326
|
const re3 = /(?<capture>\((?:\?<(?![=!])(?<name>[^>]+)>|(?!\?)))|\\?./gsu;
|
|
41360
42327
|
const map = /* @__PURE__ */ new Map();
|
|
41361
42328
|
let numCharClassesOpen = 0;
|
|
41362
42329
|
let numCaptures = 0;
|
|
41363
42330
|
let match;
|
|
41364
|
-
while (match = re3.exec(
|
|
42331
|
+
while (match = re3.exec(pattern2)) {
|
|
41365
42332
|
const { 0: m15, groups: { capture, name } } = match;
|
|
41366
42333
|
if (m15 === "[") {
|
|
41367
42334
|
numCharClassesOpen++;
|
|
@@ -41378,16 +42345,16 @@ function createNameMap(pattern) {
|
|
|
41378
42345
|
}
|
|
41379
42346
|
return map;
|
|
41380
42347
|
}
|
|
41381
|
-
function toRegExp(
|
|
41382
|
-
const d22 = toRegExpDetails(
|
|
42348
|
+
function toRegExp(pattern2, options) {
|
|
42349
|
+
const d22 = toRegExpDetails(pattern2, options);
|
|
41383
42350
|
if (d22.options) {
|
|
41384
42351
|
return new EmulatedRegExp(d22.pattern, d22.flags, d22.options);
|
|
41385
42352
|
}
|
|
41386
42353
|
return new RegExp(d22.pattern, d22.flags);
|
|
41387
42354
|
}
|
|
41388
|
-
function toRegExpDetails(
|
|
42355
|
+
function toRegExpDetails(pattern2, options) {
|
|
41389
42356
|
const opts = getOptions(options);
|
|
41390
|
-
const onigurumaAst = J2(
|
|
42357
|
+
const onigurumaAst = J2(pattern2, {
|
|
41391
42358
|
flags: opts.flags,
|
|
41392
42359
|
normalizeUnknownPropertyNames: true,
|
|
41393
42360
|
rules: {
|
|
@@ -41440,8 +42407,8 @@ function toRegExpDetails(pattern, options) {
|
|
|
41440
42407
|
}
|
|
41441
42408
|
|
|
41442
42409
|
// node_modules/@shikijs/engine-javascript/dist/engine-compile.mjs
|
|
41443
|
-
function defaultJavaScriptRegexConstructor(
|
|
41444
|
-
return toRegExp(
|
|
42410
|
+
function defaultJavaScriptRegexConstructor(pattern2, options) {
|
|
42411
|
+
return toRegExp(pattern2, {
|
|
41445
42412
|
global: true,
|
|
41446
42413
|
hasIndices: true,
|
|
41447
42414
|
lazyCompileLength: 3e3,
|
|
@@ -41461,7 +42428,7 @@ function createJavaScriptRegexEngine(options = {}) {
|
|
|
41461
42428
|
cache: /* @__PURE__ */ new Map(),
|
|
41462
42429
|
...options
|
|
41463
42430
|
};
|
|
41464
|
-
_options.regexConstructor ||= (
|
|
42431
|
+
_options.regexConstructor ||= (pattern2) => defaultJavaScriptRegexConstructor(pattern2, { target: _options.target });
|
|
41465
42432
|
return {
|
|
41466
42433
|
createScanner(patterns) {
|
|
41467
42434
|
return new JavaScriptScanner(patterns, _options);
|
|
@@ -42791,8 +43758,8 @@ var InteractionManager = class {
|
|
|
42791
43758
|
const indexes = this.getLineIndex(point.lineNumber, point.side);
|
|
42792
43759
|
if (indexes == null) return;
|
|
42793
43760
|
const lineIndex = this.mode === "diff" ? `${indexes[0]},${indexes[1]}` : `${indexes[0]}`;
|
|
42794
|
-
const
|
|
42795
|
-
for (const element2 of
|
|
43761
|
+
const candidates2 = this.pre.querySelectorAll(`[data-column-number="${point.lineNumber}"][data-line-index="${lineIndex}"]`);
|
|
43762
|
+
for (const element2 of candidates2) {
|
|
42796
43763
|
if (!(element2 instanceof HTMLElement)) continue;
|
|
42797
43764
|
const target = this.resolvePointerTarget(getElementPath(element2));
|
|
42798
43765
|
if (!isLinePointerTarget(target)) continue;
|
|
@@ -44044,6 +45011,7 @@ var EXTENSION_TO_FILE_FORMAT = {
|
|
|
44044
45011
|
mli: "ocaml",
|
|
44045
45012
|
mll: "ocaml",
|
|
44046
45013
|
mly: "ocaml",
|
|
45014
|
+
odin: "odin",
|
|
44047
45015
|
pas: "pascal",
|
|
44048
45016
|
p: "pascal",
|
|
44049
45017
|
pl: "prolog",
|
|
@@ -44076,6 +45044,17 @@ var EXTENSION_TO_FILE_FORMAT = {
|
|
|
44076
45044
|
py: "python",
|
|
44077
45045
|
pyw: "python",
|
|
44078
45046
|
pyi: "python",
|
|
45047
|
+
BUCK: "python",
|
|
45048
|
+
BUILD: "python",
|
|
45049
|
+
PACKAGE: "python",
|
|
45050
|
+
WORKSPACE: "python",
|
|
45051
|
+
Tiltfile: "python",
|
|
45052
|
+
bazel: "python",
|
|
45053
|
+
bxl: "python",
|
|
45054
|
+
bzl: "python",
|
|
45055
|
+
bzlmod: "python",
|
|
45056
|
+
star: "python",
|
|
45057
|
+
sky: "python",
|
|
44079
45058
|
qml: "qml",
|
|
44080
45059
|
qmldir: "qmldir",
|
|
44081
45060
|
qss: "qss",
|
|
@@ -44186,16 +45165,22 @@ var EXTENSION_TO_FILE_FORMAT = {
|
|
|
44186
45165
|
sty: "tex"
|
|
44187
45166
|
};
|
|
44188
45167
|
function getFiletypeFromFileName(fileName) {
|
|
45168
|
+
const format = matchFiletypeFromName(fileName);
|
|
45169
|
+
if (format != null) return format;
|
|
45170
|
+
const baseName = fileName.split(/[/\\]/).pop() ?? fileName;
|
|
45171
|
+
return baseName === fileName ? "text" : matchFiletypeFromName(baseName) ?? "text";
|
|
45172
|
+
}
|
|
45173
|
+
function matchFiletypeFromName(fileName) {
|
|
44189
45174
|
if (CUSTOM_EXTENSION_TO_FILE_FORMAT.has(fileName)) return CUSTOM_EXTENSION_TO_FILE_FORMAT.get(fileName) ?? "text";
|
|
44190
|
-
if (EXTENSION_TO_FILE_FORMAT
|
|
45175
|
+
if (Object.hasOwn(EXTENSION_TO_FILE_FORMAT, fileName)) return EXTENSION_TO_FILE_FORMAT[fileName] ?? null;
|
|
44191
45176
|
const compoundMatch = fileName.match(/\.([^/\\]+\.[^/\\]+)$/);
|
|
44192
45177
|
if (compoundMatch != null) {
|
|
44193
45178
|
if (CUSTOM_EXTENSION_TO_FILE_FORMAT.has(compoundMatch[1])) return CUSTOM_EXTENSION_TO_FILE_FORMAT.get(compoundMatch[1]) ?? "text";
|
|
44194
|
-
if (EXTENSION_TO_FILE_FORMAT
|
|
45179
|
+
if (Object.hasOwn(EXTENSION_TO_FILE_FORMAT, compoundMatch[1])) return EXTENSION_TO_FILE_FORMAT[compoundMatch[1]] ?? "text";
|
|
44195
45180
|
}
|
|
44196
45181
|
const simpleMatch = fileName.match(/\.([^.]+)$/)?.[1] ?? "";
|
|
44197
45182
|
if (CUSTOM_EXTENSION_TO_FILE_FORMAT.has(simpleMatch)) return CUSTOM_EXTENSION_TO_FILE_FORMAT.get(simpleMatch) ?? "text";
|
|
44198
|
-
return EXTENSION_TO_FILE_FORMAT[simpleMatch] ?? "text";
|
|
45183
|
+
return Object.hasOwn(EXTENSION_TO_FILE_FORMAT, simpleMatch) ? EXTENSION_TO_FILE_FORMAT[simpleMatch] ?? "text" : null;
|
|
44199
45184
|
}
|
|
44200
45185
|
|
|
44201
45186
|
// node_modules/@pierre/diffs/dist/utils/getHighlighterOptions.js
|
|
@@ -44561,8 +45546,8 @@ function normalizeThemeColors(theme3) {
|
|
|
44561
45546
|
function fill(colors, key2, value) {
|
|
44562
45547
|
if (value != null && value !== "") colors[key2] = value;
|
|
44563
45548
|
}
|
|
44564
|
-
function firstColor(...
|
|
44565
|
-
for (const candidate of
|
|
45549
|
+
function firstColor(...candidates2) {
|
|
45550
|
+
for (const candidate of candidates2) if (candidate != null && candidate !== "") return candidate;
|
|
44566
45551
|
}
|
|
44567
45552
|
function matchesSurface(color, surface2) {
|
|
44568
45553
|
return surface2 != null && color.toLowerCase() === surface2.toLowerCase();
|
|
@@ -45668,6 +46653,12 @@ function isStyleNode(element2) {
|
|
|
45668
46653
|
return typeof tagName === "string" && tagName.toLowerCase() === "style";
|
|
45669
46654
|
}
|
|
45670
46655
|
|
|
46656
|
+
// node_modules/@pierre/diffs/dist/utils/platform.js
|
|
46657
|
+
var _isSafari = void 0;
|
|
46658
|
+
function isSafari() {
|
|
46659
|
+
return _isSafari ??= "safari" in window && "pushNotification" in window.safari || /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
|
46660
|
+
}
|
|
46661
|
+
|
|
45671
46662
|
// node_modules/@pierre/diffs/dist/utils/editSessionAnnotations.js
|
|
45672
46663
|
function adoptEditSessionAnnotations(annotations, getName, previousSession) {
|
|
45673
46664
|
const slotNames = /* @__PURE__ */ new Map();
|
|
@@ -45759,10 +46750,31 @@ function createHostThemeStyleNode() {
|
|
|
45759
46750
|
return node;
|
|
45760
46751
|
}
|
|
45761
46752
|
|
|
45762
|
-
// node_modules/@pierre/diffs/dist/
|
|
45763
|
-
var
|
|
45764
|
-
|
|
45765
|
-
|
|
46753
|
+
// node_modules/@pierre/diffs/dist/worker/errors.js
|
|
46754
|
+
var WorkerPoolTerminatedError = class extends Error {
|
|
46755
|
+
constructor() {
|
|
46756
|
+
super("WorkerPoolManager: operation canceled because the pool terminated");
|
|
46757
|
+
this.name = "WorkerPoolTerminatedError";
|
|
46758
|
+
}
|
|
46759
|
+
};
|
|
46760
|
+
var WorkerPoolTaskCanceledError = class extends Error {
|
|
46761
|
+
constructor() {
|
|
46762
|
+
super("WorkerPoolManager: operation canceled before the task completed");
|
|
46763
|
+
this.name = "WorkerPoolTaskCanceledError";
|
|
46764
|
+
}
|
|
46765
|
+
};
|
|
46766
|
+
var WorkerPoolWorkerError = class extends Error {
|
|
46767
|
+
constructor(message, options) {
|
|
46768
|
+
super(message, options);
|
|
46769
|
+
this.name = "WorkerPoolWorkerError";
|
|
46770
|
+
}
|
|
46771
|
+
};
|
|
46772
|
+
var reportedWorkerErrors = /* @__PURE__ */ new WeakSet();
|
|
46773
|
+
function isWorkerPoolCancellation(error) {
|
|
46774
|
+
return error instanceof WorkerPoolTerminatedError || error instanceof WorkerPoolTaskCanceledError;
|
|
46775
|
+
}
|
|
46776
|
+
function isHandledWorkerPoolError(error) {
|
|
46777
|
+
return isWorkerPoolCancellation(error) || error instanceof WorkerPoolWorkerError && reportedWorkerErrors.has(error);
|
|
45766
46778
|
}
|
|
45767
46779
|
|
|
45768
46780
|
// node_modules/@pierre/diffs/dist/components/web-components.js
|
|
@@ -46414,6 +47426,7 @@ var File = class {
|
|
|
46414
47426
|
const tokenizeMaxLength = this.options.tokenizeMaxLength ?? 1e5;
|
|
46415
47427
|
if (this.fileRenderer.getOrCreateLineCache(file).length > tokenizeMaxLength) return;
|
|
46416
47428
|
await workerManager.primeFileHighlightCache(file).catch((error) => {
|
|
47429
|
+
if (isHandledWorkerPoolError(error)) return;
|
|
46417
47430
|
console.error(error);
|
|
46418
47431
|
});
|
|
46419
47432
|
}
|
|
@@ -49285,13 +50298,13 @@ function getChangeIterationRanges(state3, content, diffStyle) {
|
|
|
49285
50298
|
}
|
|
49286
50299
|
if (iterationRanges.length === 0) return iterationRanges;
|
|
49287
50300
|
iterationRanges.sort((a22, b13) => a22[0] - b13[0]);
|
|
49288
|
-
const
|
|
50301
|
+
const merged2 = [iterationRanges[0]];
|
|
49289
50302
|
for (const [start, end] of iterationRanges.slice(1)) {
|
|
49290
|
-
const last =
|
|
50303
|
+
const last = merged2[merged2.length - 1];
|
|
49291
50304
|
if (start <= last[1]) last[1] = Math.max(last[1], end);
|
|
49292
|
-
else
|
|
50305
|
+
else merged2.push([start, end]);
|
|
49293
50306
|
}
|
|
49294
|
-
return
|
|
50307
|
+
return merged2;
|
|
49295
50308
|
}
|
|
49296
50309
|
function getChangeLineData({ hunkIndex, hunk, collapsedAfter, collapsedBefore, diffStyle, index, unifiedLineIndex, splitLineIndex, additionLineIndex, deletionLineIndex, additionLineNumber, deletionLineNumber, content, isLastContent, unifiedCount, splitCount }) {
|
|
49297
50310
|
const unifiedDeletionLineIndex = index < content.deletions ? unifiedLineIndex + index : void 0;
|
|
@@ -50488,7 +51501,7 @@ var DiffHunksRenderer = class {
|
|
|
50488
51501
|
* row set without a line-count change — the host must escalate to a full
|
|
50489
51502
|
* re-render instead of its cheap refresh path.
|
|
50490
51503
|
*/
|
|
50491
|
-
updateRenderCache(dirtyLines, themeType, lineCountChangeInFlight = false) {
|
|
51504
|
+
updateRenderCache(dirtyLines, themeType, lineCountChangeInFlight = false, changedDocumentLines, documentLineCount) {
|
|
50492
51505
|
this.pendingStructuralRows = void 0;
|
|
50493
51506
|
const { renderCache } = this;
|
|
50494
51507
|
if (renderCache == null) return false;
|
|
@@ -50499,13 +51512,27 @@ var DiffHunksRenderer = class {
|
|
|
50499
51512
|
const pendingStructuralRows = this.pendingStructuralRows = lineCountChangeInFlight ? /* @__PURE__ */ new Map() : void 0;
|
|
50500
51513
|
const changedAdditionLines = [];
|
|
50501
51514
|
const previousAdditionLines = /* @__PURE__ */ new Map();
|
|
51515
|
+
if (pendingStructuralRows == null && changedDocumentLines != null) {
|
|
51516
|
+
const additionLineCount = diff.additionLines.length;
|
|
51517
|
+
const canAppendFinalRow = canAppendFinalDocumentRow(diff.additionLines, documentLineCount);
|
|
51518
|
+
for (const [line, text2] of changedDocumentLines) {
|
|
51519
|
+
if (line < 0 || line > additionLineCount || line === additionLineCount && (text2 === "" || !canAppendFinalRow)) continue;
|
|
51520
|
+
const previous = diff.additionLines[line] ?? "";
|
|
51521
|
+
if (previous !== text2) {
|
|
51522
|
+
diff.additionLines[line] = text2;
|
|
51523
|
+
changedAdditionLines.push(line);
|
|
51524
|
+
previousAdditionLines.set(line, previous);
|
|
51525
|
+
if (!dirtyLines.has(line)) hastLines[line] = createPlainAdditionLineElement(line, cleanLastNewline(text2));
|
|
51526
|
+
}
|
|
51527
|
+
}
|
|
51528
|
+
}
|
|
50502
51529
|
for (const [line, tokens] of dirtyLines) {
|
|
50503
51530
|
const prevProps = hastLines[line]?.properties ?? {};
|
|
50504
51531
|
const lineText = tokens.map((a22) => a22[2]).join("");
|
|
50505
51532
|
const canSyncDiffLine = line < diff.additionLines.length;
|
|
50506
51533
|
const prevLine = canSyncDiffLine ? diff.additionLines[line] ?? "" : "";
|
|
50507
51534
|
const prevText = cleanLastNewline(prevLine);
|
|
50508
|
-
if (pendingStructuralRows == null && canSyncDiffLine) {
|
|
51535
|
+
if (pendingStructuralRows == null && canSyncDiffLine && changedDocumentLines?.has(line) !== true) {
|
|
50509
51536
|
diff.additionLines[line] = applyLineTextWithNewline(prevLine, lineText);
|
|
50510
51537
|
if (prevText !== lineText) {
|
|
50511
51538
|
changedAdditionLines.push(line);
|
|
@@ -51499,6 +52526,9 @@ function realignAdditionHastLines(previousLines, nextLines, hastLines, textDocum
|
|
|
51499
52526
|
for (let index = prefix; index < nextLines.length; index++) realigned[index] ??= createPlainAdditionLineElement(index, textDocument.getLineText(index));
|
|
51500
52527
|
return realigned;
|
|
51501
52528
|
}
|
|
52529
|
+
function canAppendFinalDocumentRow(additionLines, documentLineCount) {
|
|
52530
|
+
return documentLineCount === additionLines.length + 1 && additionLines.at(-1)?.endsWith("\n") === true;
|
|
52531
|
+
}
|
|
51502
52532
|
function createPlainAdditionLineElement(lineIndex, lineText, unifiedLineIndex = lineIndex, splitLineIndex = lineIndex) {
|
|
51503
52533
|
return {
|
|
51504
52534
|
type: "element",
|
|
@@ -51601,6 +52631,7 @@ function getDiffHunksRendererOptions(options) {
|
|
|
51601
52631
|
hunkSeparators: typeof options?.hunkSeparators === "function" ? "custom" : options?.hunkSeparators,
|
|
51602
52632
|
expandUnchanged: options?.expandUnchanged,
|
|
51603
52633
|
loadDiffFiles: options?.loadDiffFiles,
|
|
52634
|
+
parseDiffOptions: options?.parseDiffOptions,
|
|
51604
52635
|
collapsedContextThreshold: options?.collapsedContextThreshold,
|
|
51605
52636
|
lineDiffType: options?.lineDiffType,
|
|
51606
52637
|
maxLineDiffLength: options?.maxLineDiffLength,
|
|
@@ -52593,7 +53624,7 @@ var FileDiff = class {
|
|
|
52593
53624
|
this.detachAdditionLines();
|
|
52594
53625
|
this.hunksRenderer.beginEditSession(editSessionDiff);
|
|
52595
53626
|
const { shouldRefreshDiffsView, lineCountChangeInFlight } = options;
|
|
52596
|
-
if (this.hunksRenderer.updateRenderCache(dirtyLines, themeType, lineCountChangeInFlight)) {
|
|
53627
|
+
if (this.hunksRenderer.updateRenderCache(dirtyLines, themeType, lineCountChangeInFlight, options.changedDocumentLines, options.documentLineCount)) {
|
|
52597
53628
|
if (this.refreshViewTimeout != null) {
|
|
52598
53629
|
clearTimeout(this.refreshViewTimeout);
|
|
52599
53630
|
this.refreshViewTimeout = void 0;
|
|
@@ -52740,6 +53771,7 @@ var FileDiff = class {
|
|
|
52740
53771
|
const tokenizeMaxLength = this.options.tokenizeMaxLength ?? 1e5;
|
|
52741
53772
|
if (Math.max(fileDiff.additionLines.length, fileDiff.deletionLines.length) > tokenizeMaxLength) return;
|
|
52742
53773
|
await workerManager.primeDiffHighlightCache(fileDiff).catch((error) => {
|
|
53774
|
+
if (isHandledWorkerPoolError(error)) return;
|
|
52743
53775
|
console.error(error);
|
|
52744
53776
|
});
|
|
52745
53777
|
}
|
|
@@ -54237,9 +55269,9 @@ function disableTextSelection(rootNode = document) {
|
|
|
54237
55269
|
}
|
|
54238
55270
|
function getDockviewTheme(element2) {
|
|
54239
55271
|
function toClassList(element3) {
|
|
54240
|
-
const
|
|
54241
|
-
for (let i25 = 0; i25 < element3.classList.length; i25++)
|
|
54242
|
-
return
|
|
55272
|
+
const list5 = [];
|
|
55273
|
+
for (let i25 = 0; i25 < element3.classList.length; i25++) list5.push(element3.classList.item(i25));
|
|
55274
|
+
return list5;
|
|
54243
55275
|
}
|
|
54244
55276
|
let theme3 = void 0;
|
|
54245
55277
|
let parent = element2;
|
|
@@ -55443,7 +56475,7 @@ var BranchNode = class BranchNode2 extends CompositeDisposable {
|
|
|
55443
56475
|
if (child instanceof BranchNode2) child.proportionalLayout = value;
|
|
55444
56476
|
});
|
|
55445
56477
|
}
|
|
55446
|
-
constructor(orientation, proportionalLayout, styles, size4, orthogonalSize,
|
|
56478
|
+
constructor(orientation, proportionalLayout, styles, size4, orthogonalSize, disabled2, margin, childDescriptors) {
|
|
55447
56479
|
super();
|
|
55448
56480
|
this.orientation = orientation;
|
|
55449
56481
|
this.styles = styles;
|
|
@@ -55486,7 +56518,7 @@ var BranchNode = class BranchNode2 extends CompositeDisposable {
|
|
|
55486
56518
|
});
|
|
55487
56519
|
this.splitview.layout(this.size, this.orthogonalSize);
|
|
55488
56520
|
}
|
|
55489
|
-
this.disabled =
|
|
56521
|
+
this.disabled = disabled2;
|
|
55490
56522
|
this.addDisposables(this._onDidChange, this._onDidVisibilityChange, this.splitview.onDidSashEnd(() => {
|
|
55491
56523
|
this._onDidChange.fire({});
|
|
55492
56524
|
}));
|
|
@@ -65090,9 +66122,9 @@ var ENTERPRISE_MODULE_NAMES = /* @__PURE__ */ new Set([
|
|
|
65090
66122
|
var _warnedMissingModule = /* @__PURE__ */ new Set();
|
|
65091
66123
|
function missingModuleMessage(moduleName, reason) {
|
|
65092
66124
|
const reasons = reason === void 0 ? [] : [].concat(reason);
|
|
65093
|
-
const
|
|
66125
|
+
const quoted2 = reasons.map((r39) => `\`${r39}\``).join(", ");
|
|
65094
66126
|
const requires = reasons.length > 1 ? "require" : "requires";
|
|
65095
|
-
const needed = reasons.length ? `${
|
|
66127
|
+
const needed = reasons.length ? `${quoted2} ${requires} the "${moduleName}" module` : `The "${moduleName}" module is required`;
|
|
65096
66128
|
if (ENTERPRISE_MODULE_NAMES.has(moduleName)) return `dockview: ${needed}, which ships in dockview-enterprise.
|
|
65097
66129
|
|
|
65098
66130
|
npm install dockview-enterprise
|
|
@@ -65692,9 +66724,9 @@ var RootDropTargetService = class {
|
|
|
65692
66724
|
}
|
|
65693
66725
|
setOptions(options) {
|
|
65694
66726
|
if ("dndEdges" in options) {
|
|
65695
|
-
const
|
|
65696
|
-
this._html5Target.disabled =
|
|
65697
|
-
this._pointerTarget.disabled =
|
|
66727
|
+
const disabled2 = typeof options.dndEdges === "boolean" && options.dndEdges === false;
|
|
66728
|
+
this._html5Target.disabled = disabled2;
|
|
66729
|
+
this._pointerTarget.disabled = disabled2;
|
|
65698
66730
|
}
|
|
65699
66731
|
if ("dndEdges" in options || "dockToEdgeGroups" in options) {
|
|
65700
66732
|
const model = resolveRootOverlayModel({
|
|
@@ -66073,16 +67105,16 @@ var nextContextMenuItemId = () => `dv-ctx-menu-item-${_nextId++}`;
|
|
|
66073
67105
|
function isItemConfig(item2) {
|
|
66074
67106
|
return typeof item2 === "object";
|
|
66075
67107
|
}
|
|
66076
|
-
function buildItem(label, close, action,
|
|
67108
|
+
function buildItem(label, close, action, disabled2) {
|
|
66077
67109
|
const el = document.createElement("div");
|
|
66078
67110
|
el.className = "dv-context-menu-item";
|
|
66079
67111
|
el.setAttribute("role", "menuitem");
|
|
66080
|
-
if (
|
|
67112
|
+
if (disabled2) {
|
|
66081
67113
|
el.classList.add("dv-context-menu-item--disabled");
|
|
66082
67114
|
el.setAttribute("aria-disabled", "true");
|
|
66083
67115
|
}
|
|
66084
67116
|
el.textContent = label;
|
|
66085
|
-
if (!
|
|
67117
|
+
if (!disabled2) el.addEventListener("click", () => {
|
|
66086
67118
|
action();
|
|
66087
67119
|
close();
|
|
66088
67120
|
});
|
|
@@ -71284,9 +72316,9 @@ var getBaseFileName = (path) => {
|
|
|
71284
72316
|
};
|
|
71285
72317
|
var getExtensionCandidates = (fileName) => {
|
|
71286
72318
|
const segments = fileName.toLowerCase().split(".");
|
|
71287
|
-
const
|
|
71288
|
-
for (let index = 1; index < segments.length; index += 1)
|
|
71289
|
-
return
|
|
72319
|
+
const candidates2 = [];
|
|
72320
|
+
for (let index = 1; index < segments.length; index += 1) candidates2.push(segments.slice(index).join("."));
|
|
72321
|
+
return candidates2;
|
|
71290
72322
|
};
|
|
71291
72323
|
function remapEntryToIcon(entry, remappedFrom) {
|
|
71292
72324
|
if (typeof entry === "string") return {
|
|
@@ -77439,8 +78471,8 @@ function getFileTreeRowAriaLabel(row) {
|
|
|
77439
78471
|
if (flattenedSegments == null || flattenedSegments.length === 0) return row.name;
|
|
77440
78472
|
return flattenedSegments.map((segment2) => segment2.name).join(" / ");
|
|
77441
78473
|
}
|
|
77442
|
-
function computeStickyRowsFromCandidates(
|
|
77443
|
-
return
|
|
78474
|
+
function computeStickyRowsFromCandidates(candidates2, scrollTop, itemHeight, totalRowCount) {
|
|
78475
|
+
return candidates2.map((candidate, slotDepth) => {
|
|
77444
78476
|
const defaultTop = slotDepth * itemHeight;
|
|
77445
78477
|
const nextBoundaryIndex = candidate.subtreeEndIndex + 1;
|
|
77446
78478
|
if (nextBoundaryIndex >= totalRowCount) return {
|
|
@@ -77487,9 +78519,9 @@ function getPointElement(rootNode, clientX, clientY) {
|
|
|
77487
78519
|
return element2 instanceof HTMLElement ? element2 : null;
|
|
77488
78520
|
}
|
|
77489
78521
|
function getShadowPointElementByGeometry(rootNode, clientX, clientY) {
|
|
77490
|
-
const
|
|
77491
|
-
for (let index =
|
|
77492
|
-
const candidate =
|
|
78522
|
+
const candidates2 = Array.from(rootNode.querySelectorAll('[data-type="item"], [data-item-flattened-subitem]'));
|
|
78523
|
+
for (let index = candidates2.length - 1; index >= 0; index--) {
|
|
78524
|
+
const candidate = candidates2[index];
|
|
77493
78525
|
const rect = candidate.getBoundingClientRect();
|
|
77494
78526
|
if (clientX >= rect.left && clientX <= rect.right && clientY >= rect.top && clientY <= rect.bottom) return candidate;
|
|
77495
78527
|
}
|
|
@@ -80007,6 +81039,8 @@ var elements = {
|
|
|
80007
81039
|
"slicc-network": SliccNetwork,
|
|
80008
81040
|
"slicc-notices": SliccNotices,
|
|
80009
81041
|
"slicc-approvals": SliccApprovals,
|
|
81042
|
+
"slicc-secrets": SliccSecrets,
|
|
81043
|
+
"slicc-vault-button": SliccVaultButton,
|
|
80010
81044
|
"slicc-confirm": SliccConfirm,
|
|
80011
81045
|
"slicc-prompt": SliccPrompt,
|
|
80012
81046
|
"slicc-app": SliccApp
|
|
@@ -80043,7 +81077,9 @@ export {
|
|
|
80043
81077
|
SliccNetwork,
|
|
80044
81078
|
SliccNotices,
|
|
80045
81079
|
SliccPrompt,
|
|
81080
|
+
SliccSecrets,
|
|
80046
81081
|
SliccUpdates,
|
|
81082
|
+
SliccVaultButton,
|
|
80047
81083
|
confirm,
|
|
80048
81084
|
define2 as define,
|
|
80049
81085
|
grammarBase,
|