@ai-ecoverse/slicc-spectrum 1.60.2 → 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 +8 -3
- package/dist/slicc-dummy.js +438 -11
- package/dist/slicc-dummy.js.map +4 -4
- package/dist/slicc-ui.js +1201 -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
|
}
|
|
@@ -13816,37 +13816,37 @@ function coneOf(agents, id) {
|
|
|
13816
13816
|
}
|
|
13817
13817
|
return agent?.kind === "cone" ? agent.id : null;
|
|
13818
13818
|
}
|
|
13819
|
-
function resolve(panels, raw2,
|
|
13819
|
+
function resolve(panels, raw2, reachable2, cone) {
|
|
13820
13820
|
if (/^(file|diff):./.test(raw2)) return raw2;
|
|
13821
13821
|
if (raw2 === "chat") {
|
|
13822
13822
|
const agent = cone === void 0 ? panels.active() : cone;
|
|
13823
|
-
return
|
|
13823
|
+
return reachable2.some((info) => info.id === `chat:${agent}`) ? `chat:${agent}` : null;
|
|
13824
13824
|
}
|
|
13825
13825
|
if (raw2 === "terminal") {
|
|
13826
|
-
const terminals =
|
|
13826
|
+
const terminals = reachable2.filter((info) => info.kind === "terminal");
|
|
13827
13827
|
const picked = terminals.find((info) => info.active) ?? terminals.filter((info) => info.open).at(-1) ?? terminals.at(-1);
|
|
13828
13828
|
return picked?.id ?? null;
|
|
13829
13829
|
}
|
|
13830
|
-
if (
|
|
13830
|
+
if (reachable2.some((info) => info.id === raw2)) return raw2;
|
|
13831
13831
|
const name = raw2.startsWith("sprinkle:") ? raw2.slice(9) : raw2;
|
|
13832
|
-
const sprinkles =
|
|
13832
|
+
const sprinkles = reachable2.filter((info) => info.kind === "sprinkle");
|
|
13833
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);
|
|
13834
13834
|
return found?.id ?? null;
|
|
13835
13835
|
}
|
|
13836
13836
|
function state(info) {
|
|
13837
|
-
const
|
|
13838
|
-
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;
|
|
13839
13839
|
}
|
|
13840
13840
|
function table(rows) {
|
|
13841
13841
|
const lines = [["ID", "TITLE", "STATE"], ...rows.map((row) => [row.id, row.title, state(row)])];
|
|
13842
13842
|
const widths = [0, 1].map((column) => Math.max(...lines.map((line) => line[column].length)));
|
|
13843
|
-
return lines.map(([id, title,
|
|
13843
|
+
return lines.map(([id, title, shown3]) => `${id.padEnd(widths[0])} ${title.padEnd(widths[1])} ${shown3}`).join("\n");
|
|
13844
13844
|
}
|
|
13845
13845
|
var done = (result, note = "") => result.code === 0 ? { stdout: `${result.message}${note}
|
|
13846
13846
|
`, stderr: "", code: 0 } : { stdout: "", stderr: `panel: ${result.message}
|
|
13847
13847
|
`, code: result.code };
|
|
13848
13848
|
function act(scope, parsed) {
|
|
13849
|
-
const { panels, reachable, cone } = scope;
|
|
13849
|
+
const { panels, reachable: reachable2, cone } = scope;
|
|
13850
13850
|
if (parsed.verb === "reset") {
|
|
13851
13851
|
const recent = scope.agent ? panels.recentClose() : null;
|
|
13852
13852
|
if (recent)
|
|
@@ -13856,11 +13856,11 @@ function act(scope, parsed) {
|
|
|
13856
13856
|
return done(panels.reset());
|
|
13857
13857
|
}
|
|
13858
13858
|
const raw2 = parsed.id;
|
|
13859
|
-
const id = resolve(panels, raw2,
|
|
13859
|
+
const id = resolve(panels, raw2, reachable2, cone);
|
|
13860
13860
|
if (!id) return done(unknown(raw2));
|
|
13861
13861
|
let place3 = parsed.place;
|
|
13862
13862
|
if (typeof place3 === "object") {
|
|
13863
|
-
const ref = resolve(panels, place3.ref,
|
|
13863
|
+
const ref = resolve(panels, place3.ref, reachable2, cone);
|
|
13864
13864
|
if (!ref) return done(unknown(place3.ref));
|
|
13865
13865
|
place3 = { ...place3, ref };
|
|
13866
13866
|
}
|
|
@@ -13895,12 +13895,12 @@ ${help}`, code: 2 };
|
|
|
13895
13895
|
const agents = panels.agents();
|
|
13896
13896
|
const scoped2 = caller.agentId !== null || !!caller.cone;
|
|
13897
13897
|
const cone = scoped2 ? caller.cone ?? coneOf(agents, caller.agentId) : void 0;
|
|
13898
|
-
const
|
|
13898
|
+
const reachable2 = panels.list().filter(
|
|
13899
13899
|
(info) => !scoped2 || info.agent === null || !!cone && coneOf(agents, info.agent) === cone
|
|
13900
13900
|
);
|
|
13901
13901
|
if (parsed.verb !== "list")
|
|
13902
|
-
return act({ panels, agent: caller.agentId !== null, cone, reachable }, parsed);
|
|
13903
|
-
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);
|
|
13904
13904
|
return { stdout: `${body4}
|
|
13905
13905
|
`, stderr: "", code: 0 };
|
|
13906
13906
|
}
|
|
@@ -20681,12 +20681,12 @@ function user(message) {
|
|
|
20681
20681
|
const tag3 = delivered === "steer" || delivered === "follow-up" ? deliveries[delivered] : null;
|
|
20682
20682
|
const agent = message.origin === "agent";
|
|
20683
20683
|
const name = message.from ?? "an agent";
|
|
20684
|
-
const
|
|
20684
|
+
const who2 = agent ? name : message.from ? `From ${message.from}` : "You";
|
|
20685
20685
|
const label = agent ? `Request from ${name}` : message.from ? `Message from ${message.from}` : "Your message";
|
|
20686
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"}>
|
|
20687
20687
|
<div class="bubble">
|
|
20688
20688
|
<div class="meta">
|
|
20689
|
-
<span class="who">${
|
|
20689
|
+
<span class="who">${who2}</span><span>${time(message.createdAt)}</span>
|
|
20690
20690
|
${agent ? b`<swc-badge class="origin" size="s" variant="indigo">Agent</swc-badge>` : A}
|
|
20691
20691
|
${tag3 ? b`<swc-badge class="tag" size="s" variant=${delivered === "steer" ? "notice" : "informative"} subtle>${tag3}</swc-badge>` : A}
|
|
20692
20692
|
</div>
|
|
@@ -21945,8 +21945,8 @@ var SliccUpdates = class extends ModelElement {
|
|
|
21945
21945
|
#checked(at) {
|
|
21946
21946
|
if (at === null) return b`<span>Not checked yet</span>`;
|
|
21947
21947
|
const date = new Date(at);
|
|
21948
|
-
const
|
|
21949
|
-
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>`;
|
|
21950
21950
|
}
|
|
21951
21951
|
#item(item2) {
|
|
21952
21952
|
const [variant, state3] = states[item2.state];
|
|
@@ -22011,14 +22011,14 @@ var SliccUpdates = class extends ModelElement {
|
|
|
22011
22011
|
#package(item2, all2, act2) {
|
|
22012
22012
|
const light = packageLight(item2);
|
|
22013
22013
|
const busy = this.busy.get(item2.id);
|
|
22014
|
-
const
|
|
22014
|
+
const shown3 = busy ? [busy] : act2 ? item2.actions : [];
|
|
22015
22015
|
const error = this.problems.get(item2.id) ?? item2.error;
|
|
22016
22016
|
return b`<li data-id=${item2.id} data-state=${item2.state}>
|
|
22017
22017
|
<div class="name">
|
|
22018
22018
|
<h3 title=${item2.package}>${item2.label}</h3>
|
|
22019
22019
|
${light ? b`<swc-status-light size="s" variant=${light[0]}>${light[1]}</swc-status-light>` : A}
|
|
22020
22020
|
</div>
|
|
22021
|
-
<div class="buttons">${
|
|
22021
|
+
<div class="buttons">${shown3.map(
|
|
22022
22022
|
(action) => b`<swc-button
|
|
22023
22023
|
size="s"
|
|
22024
22024
|
variant="secondary"
|
|
@@ -22035,7 +22035,7 @@ var SliccUpdates = class extends ModelElement {
|
|
|
22035
22035
|
(warning) => b`<span><swc-icon-alert-triangle size="s" aria-hidden="true"></swc-icon-alert-triangle>${warning}</span>`
|
|
22036
22036
|
)}</p>` : A}
|
|
22037
22037
|
${item2.commands.length ? b`<p class="commands"><span class="hidden">Commands: </span>${item2.commands.map(
|
|
22038
|
-
(
|
|
22038
|
+
(command3) => b`<code>${command3}</code>`
|
|
22039
22039
|
)}</p>` : A}
|
|
22040
22040
|
${this.#packageProgress(item2)}
|
|
22041
22041
|
${error ? b`<div class="error" role="alert" data-error>
|
|
@@ -22716,9 +22716,9 @@ var SliccApp = class extends ThemedElement {
|
|
|
22716
22716
|
if (!model) return [];
|
|
22717
22717
|
const selected = this.#cone();
|
|
22718
22718
|
const cones = model.agent.list().filter((agent) => agent.kind === "cone");
|
|
22719
|
-
const
|
|
22720
|
-
const order = [selected, ...cones.map((cone) => cone.id), ...
|
|
22721
|
-
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) => {
|
|
22722
22722
|
const cone = cones.find((agent) => agent.id === sprinkle.agentId && agent.id !== selected);
|
|
22723
22723
|
return cone ? { ...sprinkle, title: `${cone.name} / ${sprinkle.title}` } : sprinkle;
|
|
22724
22724
|
}).sort((a22, b13) => order.indexOf(a22.agentId) - order.indexOf(b13.agentId));
|
|
@@ -22774,11 +22774,11 @@ var SliccApp = class extends ThemedElement {
|
|
|
22774
22774
|
#rail(items, side) {
|
|
22775
22775
|
const primary = side === "bottom" ? items.filter((item2) => phoneRail.includes(item2.id)) : items;
|
|
22776
22776
|
const fit = primary.length < items.length ? Math.min(primary.length, railCapacity(this.#width, Infinity)) : railCapacity(this.#width, items.length);
|
|
22777
|
-
const
|
|
22778
|
-
const grouped = new Set(
|
|
22779
|
-
return b`<nav class=${`rail ${side}`} aria-label=${`Panels, ${side}`} @dragover=${this.#railOver} @dragleave=${this.#railLeave} @drop=${this.#railDrop}>${
|
|
22780
|
-
(item2, index) => b`${grouped && index &&
|
|
22781
|
-
)}${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>`;
|
|
22782
22782
|
}
|
|
22783
22783
|
#rails() {
|
|
22784
22784
|
const dock = this.renderRoot.querySelector("slicc-dock");
|
|
@@ -23021,6 +23021,202 @@ function sudo(approval) {
|
|
|
23021
23021
|
const as = approval.target && approval.target !== "root" ? `-u ${approval.target} ` : "";
|
|
23022
23022
|
return `sudo ${as}${approval.command}`;
|
|
23023
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
|
+
}
|
|
23024
23220
|
function waiting(model, now) {
|
|
23025
23221
|
return [...model?.approvals?.list() ?? []].filter((approval) => approval.expiresAt > now).sort((a22, b13) => a22.createdAt - b13.createdAt);
|
|
23026
23222
|
}
|
|
@@ -23086,6 +23282,27 @@ var SliccApprovals = class extends ModelElement {
|
|
|
23086
23282
|
margin-block-start: var(--swc-spacing-300);
|
|
23087
23283
|
font-variant-numeric: tabular-nums;
|
|
23088
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
|
+
}
|
|
23089
23306
|
.problem {
|
|
23090
23307
|
display: flex;
|
|
23091
23308
|
align-items: flex-start;
|
|
@@ -23140,6 +23357,7 @@ var SliccApprovals = class extends ModelElement {
|
|
|
23140
23357
|
async decide(approval, decision) {
|
|
23141
23358
|
const port = this.model?.approvals;
|
|
23142
23359
|
if (!port?.decide || this.busy || decision !== "deny" && !this.#armed) return;
|
|
23360
|
+
if (decision === "always" && secretRules(approval)) return;
|
|
23143
23361
|
this.busy = decision;
|
|
23144
23362
|
this.failure = null;
|
|
23145
23363
|
this.#pending.add(approval.id);
|
|
@@ -23161,15 +23379,15 @@ var SliccApprovals = class extends ModelElement {
|
|
|
23161
23379
|
}
|
|
23162
23380
|
willUpdate(changed) {
|
|
23163
23381
|
super.willUpdate(changed);
|
|
23164
|
-
const
|
|
23382
|
+
const list5 = this.#current();
|
|
23165
23383
|
const showing = this.#showing;
|
|
23166
23384
|
if (showing && this.#pending.has(showing.id)) return;
|
|
23167
|
-
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)) {
|
|
23168
23386
|
const reason = this.#ended.get(showing.id) ?? (showing.expiresAt <= this.now ? "expired" : "answered");
|
|
23169
23387
|
if (reason !== "withdrawn") this.gone = { approval: showing, reason: gone(reason) };
|
|
23170
23388
|
}
|
|
23171
23389
|
if (this.gone) return;
|
|
23172
|
-
const next =
|
|
23390
|
+
const next = list5[0] ?? null;
|
|
23173
23391
|
if (next?.id === showing?.id) return;
|
|
23174
23392
|
this.#showing = next;
|
|
23175
23393
|
clearTimeout(this.#arming);
|
|
@@ -23240,10 +23458,12 @@ var SliccApprovals = class extends ModelElement {
|
|
|
23240
23458
|
);
|
|
23241
23459
|
}
|
|
23242
23460
|
const held = this.#showing && this.#pending.has(this.#showing.id) ? this.#showing : null;
|
|
23243
|
-
const
|
|
23244
|
-
const [approval, ...rest] = held ? [held, ...
|
|
23461
|
+
const list5 = this.#current();
|
|
23462
|
+
const [approval, ...rest] = held ? [held, ...list5.filter(({ id }) => id !== held.id)] : list5;
|
|
23245
23463
|
if (!approval) return A;
|
|
23246
23464
|
const failure2 = this.failure?.id === approval.id ? this.failure.message : "";
|
|
23465
|
+
const rules = secretRules(approval);
|
|
23466
|
+
const always = approval.always && !rules;
|
|
23247
23467
|
return this.#dialog(
|
|
23248
23468
|
approval,
|
|
23249
23469
|
approval.id,
|
|
@@ -23251,12 +23471,13 @@ var SliccApprovals = class extends ModelElement {
|
|
|
23251
23471
|
<h2 id="title" slot="heading">Allow sudo?</h2>
|
|
23252
23472
|
${this.#request(approval)}
|
|
23253
23473
|
${approval.cwd ? b`<p class="cwd">In ${approval.cwd}</p>` : A}
|
|
23254
|
-
${
|
|
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}
|
|
23255
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}
|
|
23256
23477
|
<p class="timer" data-timer>Denied automatically in ${countdown(approval.expiresAt - this.now)}.</p>
|
|
23257
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}
|
|
23258
23479
|
${this.#button(approval, "deny", "Deny", "secondary")}
|
|
23259
|
-
${
|
|
23480
|
+
${always ? this.#button(approval, "always", "Always allow", "secondary") : A}
|
|
23260
23481
|
${this.#button(approval, "once", "Allow once", "accent")}
|
|
23261
23482
|
</sp-alert-dialog>`
|
|
23262
23483
|
);
|
|
@@ -24168,9 +24389,9 @@ var SliccBrowser = class extends ModelElement {
|
|
|
24168
24389
|
if (visible2 && tab && !this.#ticker)
|
|
24169
24390
|
this.#ticker = setInterval(() => this.requestUpdate(), 1e3);
|
|
24170
24391
|
if (!(visible2 && tab)) this.#still();
|
|
24171
|
-
const
|
|
24172
|
-
const count =
|
|
24173
|
-
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;
|
|
24174
24395
|
this.#count = count;
|
|
24175
24396
|
}
|
|
24176
24397
|
#still() {
|
|
@@ -25064,18 +25285,18 @@ function failedTurns(messages, messageId) {
|
|
|
25064
25285
|
}
|
|
25065
25286
|
return ids;
|
|
25066
25287
|
}
|
|
25067
|
-
var
|
|
25288
|
+
var touched2 = false;
|
|
25068
25289
|
document.addEventListener(
|
|
25069
25290
|
"pointerdown",
|
|
25070
25291
|
(event2) => {
|
|
25071
|
-
|
|
25292
|
+
touched2 = event2.pointerType !== "mouse";
|
|
25072
25293
|
},
|
|
25073
25294
|
true
|
|
25074
25295
|
);
|
|
25075
25296
|
document.addEventListener(
|
|
25076
25297
|
"keydown",
|
|
25077
25298
|
() => {
|
|
25078
|
-
|
|
25299
|
+
touched2 = false;
|
|
25079
25300
|
},
|
|
25080
25301
|
true
|
|
25081
25302
|
);
|
|
@@ -25251,7 +25472,7 @@ var SliccChat = class extends ThemedElement {
|
|
|
25251
25472
|
this.#observe();
|
|
25252
25473
|
}
|
|
25253
25474
|
focus() {
|
|
25254
|
-
if (!
|
|
25475
|
+
if (!touched2 && globalThis.matchMedia("(pointer: fine)").matches)
|
|
25255
25476
|
this.focusOn("slicc-composer", ".log");
|
|
25256
25477
|
else this.focusOn(".log");
|
|
25257
25478
|
}
|
|
@@ -26257,7 +26478,7 @@ e25("swc-icon-clock", o84);
|
|
|
26257
26478
|
// src/app/composer.ts
|
|
26258
26479
|
var limit = 25 * 1024 * 1024;
|
|
26259
26480
|
function available(model) {
|
|
26260
|
-
return commands2.filter((
|
|
26481
|
+
return commands2.filter((command3) => command3.available?.(model) ?? true);
|
|
26261
26482
|
}
|
|
26262
26483
|
var commands2 = [
|
|
26263
26484
|
{
|
|
@@ -26336,8 +26557,8 @@ function trigger(text2, caret) {
|
|
|
26336
26557
|
const argument = before.match(/^\/(\w+)\s+(\S*)$/);
|
|
26337
26558
|
if (argument)
|
|
26338
26559
|
return { kind: "argument", start: before.length - argument[2].length, query: argument[2] };
|
|
26339
|
-
const
|
|
26340
|
-
if (
|
|
26560
|
+
const command3 = before.match(/^\/([\w:-]*)$/);
|
|
26561
|
+
if (command3) return { kind: "command", start: 0, query: command3[1] };
|
|
26341
26562
|
const mention = before.match(/(^|\s)@([\w./-]*)$/);
|
|
26342
26563
|
if (mention)
|
|
26343
26564
|
return { kind: "mention", start: before.length - mention[2].length - 1, query: mention[2] };
|
|
@@ -26644,14 +26865,14 @@ var SliccComposer = class extends ModelElement {
|
|
|
26644
26865
|
const text2 = this.value.trim();
|
|
26645
26866
|
const attachments = this.attachments.filter((attachment2) => !attachment2.error);
|
|
26646
26867
|
if (!model || !text2 && attachments.length === 0 || this.#held()) return;
|
|
26647
|
-
const
|
|
26648
|
-
const known =
|
|
26868
|
+
const command3 = text2.match(/^\/(\w+)(?:\s+(.*))?$/);
|
|
26869
|
+
const known = command3 && available(model).find((candidate) => candidate.name === command3[1]);
|
|
26649
26870
|
this.value = "";
|
|
26650
26871
|
this.attachments = [];
|
|
26651
26872
|
this.popup = null;
|
|
26652
26873
|
this.#history = -1;
|
|
26653
26874
|
if (known) {
|
|
26654
|
-
known.run(model, this.#agent, (
|
|
26875
|
+
known.run(model, this.#agent, (command3[2] ?? "").trim());
|
|
26655
26876
|
return;
|
|
26656
26877
|
}
|
|
26657
26878
|
const busy = this.#busy();
|
|
@@ -26739,22 +26960,22 @@ var SliccComposer = class extends ModelElement {
|
|
|
26739
26960
|
const model = this.model;
|
|
26740
26961
|
if (kind === "command") {
|
|
26741
26962
|
const usable = available(model);
|
|
26742
|
-
const builtins = usable.map((
|
|
26743
|
-
value:
|
|
26744
|
-
label: `/${
|
|
26745
|
-
detail:
|
|
26963
|
+
const builtins = usable.map((command3) => ({
|
|
26964
|
+
value: command3.name,
|
|
26965
|
+
label: `/${command3.name}`,
|
|
26966
|
+
detail: command3.detail
|
|
26746
26967
|
}));
|
|
26747
|
-
const own4 = model.agent.commands(this.#agent).filter((
|
|
26748
|
-
value:
|
|
26749
|
-
label: `/${
|
|
26750
|
-
detail:
|
|
26751
|
-
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"
|
|
26752
26973
|
})).sort((a22, b13) => a22.group === b13.group ? 0 : a22.group === "Prompts" ? -1 : 1);
|
|
26753
26974
|
return filter([...builtins, ...own4], query, Number.POSITIVE_INFINITY);
|
|
26754
26975
|
}
|
|
26755
26976
|
if (kind === "argument") {
|
|
26756
26977
|
const name = this.value.match(/^\/(\w+)/)?.[1];
|
|
26757
|
-
return filter(commands2.find((
|
|
26978
|
+
return filter(commands2.find((command3) => command3.name === name)?.args?.(model) ?? [], query);
|
|
26758
26979
|
}
|
|
26759
26980
|
const files = this.#paths.map((path) => ({
|
|
26760
26981
|
value: path,
|
|
@@ -26774,7 +26995,7 @@ var SliccComposer = class extends ModelElement {
|
|
|
26774
26995
|
if (this.popup?.kind === "file" || this.popup?.kind === "secret") return;
|
|
26775
26996
|
const found = trigger(this.value, area.selectionStart ?? this.value.length);
|
|
26776
26997
|
const name = this.value.match(/^\/(\w+)/)?.[1];
|
|
26777
|
-
const takes = commands2.some((
|
|
26998
|
+
const takes = commands2.some((command3) => command3.name === name && command3.args);
|
|
26778
26999
|
this.popup = found && (found.kind !== "argument" || takes) ? { ...found, items: this.#choices(found.kind, found.query), index: 0 } : null;
|
|
26779
27000
|
}
|
|
26780
27001
|
openPopup(kind) {
|
|
@@ -27368,8 +27589,8 @@ var SliccMemory = class extends ModelElement {
|
|
|
27368
27589
|
const scopes = this.#scopes;
|
|
27369
27590
|
const scope = this.scope;
|
|
27370
27591
|
const option2 = (item2) => b`<sp-menu-item value=${item2.id}>${item2.label}</sp-menu-item>`;
|
|
27371
|
-
const
|
|
27372
|
-
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>
|
|
27373
27594
|
<swc-action-button size="s" quiet @click=${() => this.editing = "new"}><swc-icon-add slot="icon"></swc-icon-add>Remember</swc-action-button>
|
|
27374
27595
|
</div>
|
|
27375
27596
|
<div class="tools">
|
|
@@ -27391,7 +27612,7 @@ var SliccMemory = class extends ModelElement {
|
|
|
27391
27612
|
</div>
|
|
27392
27613
|
<div class="list">
|
|
27393
27614
|
${this.editing === "new" ? b`<div class="row">${this.#form({ scope })}</div>` : A}
|
|
27394
|
-
${
|
|
27615
|
+
${shown3.length ? sections(shown3).map(
|
|
27395
27616
|
([section, items]) => b`<h3>${section}</h3>${items.map((memory) => this.#row(memory))}`
|
|
27396
27617
|
) : b`<div class="note">${all2.length ? "No memories match." : "No memories yet."}</div>`}
|
|
27397
27618
|
</div>`;
|
|
@@ -27699,10 +27920,10 @@ var SliccMonitor = class extends ModelElement {
|
|
|
27699
27920
|
const surface2 = surfaces2[section.id];
|
|
27700
27921
|
const rows = section.rows.length > 0;
|
|
27701
27922
|
const open = rows && (this.expanded[section.id] ?? flag !== null);
|
|
27702
|
-
const
|
|
27923
|
+
const list5 = `rows-${section.id}`;
|
|
27703
27924
|
return b`<li class="section" data-id=${section.id} data-open=${open ? "" : A}>
|
|
27704
27925
|
<div class="line">
|
|
27705
|
-
${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=${() => {
|
|
27706
27927
|
this.expanded = { ...this.expanded, [section.id]: !open };
|
|
27707
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>`}
|
|
27708
27929
|
${flag ? b`<swc-badge size="s" variant=${flag.variant} subtle>${flag.text}</swc-badge>` : A}
|
|
@@ -27711,7 +27932,7 @@ var SliccMonitor = class extends ModelElement {
|
|
|
27711
27932
|
>Open</swc-action-button
|
|
27712
27933
|
>` : A}
|
|
27713
27934
|
</div>
|
|
27714
|
-
${open ? b`<ul class="rows" id=${
|
|
27935
|
+
${open ? b`<ul class="rows" id=${list5} aria-label=${section.label}>${c(
|
|
27715
27936
|
section.rows,
|
|
27716
27937
|
(row, i25) => row.id ?? i25,
|
|
27717
27938
|
(row) => this.#row(row)
|
|
@@ -27918,6 +28139,748 @@ var SliccNotices = class extends ModelElement {
|
|
|
27918
28139
|
}
|
|
27919
28140
|
};
|
|
27920
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
|
+
|
|
27921
28884
|
// src/app/settings.ts
|
|
27922
28885
|
var accountStatus = {
|
|
27923
28886
|
connected: ["positive", "Connected"],
|
|
@@ -28275,6 +29238,7 @@ var SliccSettings = class extends ModelElement {
|
|
|
28275
29238
|
<div class="accounts">${providers.map((account) => this.#account(account))}</div>
|
|
28276
29239
|
${servers.length ? b`<h2>MCP servers</h2>
|
|
28277
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}
|
|
28278
29242
|
</div>`;
|
|
28279
29243
|
}
|
|
28280
29244
|
};
|
|
@@ -31070,14 +32034,14 @@ var RegexSource = class {
|
|
|
31070
32034
|
return CAPTURING_REGEX_SOURCE.test(regexSource);
|
|
31071
32035
|
}
|
|
31072
32036
|
static replaceCaptures(regexSource, captureSource, captureIndices) {
|
|
31073
|
-
return regexSource.replace(CAPTURING_REGEX_SOURCE, (match, index, commandIndex,
|
|
32037
|
+
return regexSource.replace(CAPTURING_REGEX_SOURCE, (match, index, commandIndex, command3) => {
|
|
31074
32038
|
let capture = captureIndices[parseInt(index || commandIndex, 10)];
|
|
31075
32039
|
if (capture) {
|
|
31076
32040
|
let result = captureSource.substring(capture.start, capture.end);
|
|
31077
32041
|
while (result[0] === ".") {
|
|
31078
32042
|
result = result.substring(1);
|
|
31079
32043
|
}
|
|
31080
|
-
switch (
|
|
32044
|
+
switch (command3) {
|
|
31081
32045
|
case "downcase":
|
|
31082
32046
|
return result.toLowerCase();
|
|
31083
32047
|
case "upcase":
|
|
@@ -32091,8 +33055,8 @@ var IncludeOnlyRule = class extends Rule {
|
|
|
32091
33055
|
}
|
|
32092
33056
|
}
|
|
32093
33057
|
collectPatterns(grammar2, out) {
|
|
32094
|
-
for (const
|
|
32095
|
-
const rule = grammar2.getRule(
|
|
33058
|
+
for (const pattern2 of this.patterns) {
|
|
33059
|
+
const rule = grammar2.getRule(pattern2);
|
|
32096
33060
|
rule.collectPatterns(grammar2, out);
|
|
32097
33061
|
}
|
|
32098
33062
|
}
|
|
@@ -32159,8 +33123,8 @@ var BeginEndRule = class extends Rule {
|
|
|
32159
33123
|
_getCachedCompiledPatterns(grammar2, endRegexSource) {
|
|
32160
33124
|
if (!this._cachedCompiledPatterns) {
|
|
32161
33125
|
this._cachedCompiledPatterns = new RegExpSourceList();
|
|
32162
|
-
for (const
|
|
32163
|
-
const rule = grammar2.getRule(
|
|
33126
|
+
for (const pattern2 of this.patterns) {
|
|
33127
|
+
const rule = grammar2.getRule(pattern2);
|
|
32164
33128
|
rule.collectPatterns(grammar2, this._cachedCompiledPatterns);
|
|
32165
33129
|
}
|
|
32166
33130
|
if (this.applyEndPatternLast) {
|
|
@@ -32232,8 +33196,8 @@ var BeginWhileRule = class extends Rule {
|
|
|
32232
33196
|
_getCachedCompiledPatterns(grammar2) {
|
|
32233
33197
|
if (!this._cachedCompiledPatterns) {
|
|
32234
33198
|
this._cachedCompiledPatterns = new RegExpSourceList();
|
|
32235
|
-
for (const
|
|
32236
|
-
const rule = grammar2.getRule(
|
|
33199
|
+
for (const pattern2 of this.patterns) {
|
|
33200
|
+
const rule = grammar2.getRule(pattern2);
|
|
32237
33201
|
rule.collectPatterns(grammar2, this._cachedCompiledPatterns);
|
|
32238
33202
|
}
|
|
32239
33203
|
}
|
|
@@ -32354,14 +33318,14 @@ var RuleFactory = class _RuleFactory {
|
|
|
32354
33318
|
let r39 = [];
|
|
32355
33319
|
if (patterns) {
|
|
32356
33320
|
for (let i25 = 0, len = patterns.length; i25 < len; i25++) {
|
|
32357
|
-
const
|
|
33321
|
+
const pattern2 = patterns[i25];
|
|
32358
33322
|
let ruleId = -1;
|
|
32359
|
-
if (
|
|
32360
|
-
const reference2 = parseInclude(
|
|
33323
|
+
if (pattern2.include) {
|
|
33324
|
+
const reference2 = parseInclude(pattern2.include);
|
|
32361
33325
|
switch (reference2.kind) {
|
|
32362
33326
|
case 0:
|
|
32363
33327
|
case 1:
|
|
32364
|
-
ruleId = _RuleFactory.getCompiledRuleId(repository[
|
|
33328
|
+
ruleId = _RuleFactory.getCompiledRuleId(repository[pattern2.include], helper, repository);
|
|
32365
33329
|
break;
|
|
32366
33330
|
case 2:
|
|
32367
33331
|
let localIncludedRule = repository[reference2.ruleName];
|
|
@@ -32390,7 +33354,7 @@ var RuleFactory = class _RuleFactory {
|
|
|
32390
33354
|
break;
|
|
32391
33355
|
}
|
|
32392
33356
|
} else {
|
|
32393
|
-
ruleId = _RuleFactory.getCompiledRuleId(
|
|
33357
|
+
ruleId = _RuleFactory.getCompiledRuleId(pattern2, helper, repository);
|
|
32394
33358
|
}
|
|
32395
33359
|
if (ruleId !== -1) {
|
|
32396
33360
|
const rule = helper.getRule(ruleId);
|
|
@@ -37233,13 +38197,13 @@ function splitTokens(tokens, breakpoints) {
|
|
|
37233
38197
|
});
|
|
37234
38198
|
});
|
|
37235
38199
|
}
|
|
37236
|
-
function flatTokenVariants(
|
|
38200
|
+
function flatTokenVariants(merged2, variantsOrder, cssVariablePrefix, defaultColor, colorsRendering = "css-vars") {
|
|
37237
38201
|
const token2 = {
|
|
37238
|
-
content:
|
|
37239
|
-
explanation:
|
|
37240
|
-
offset:
|
|
38202
|
+
content: merged2.content,
|
|
38203
|
+
explanation: merged2.explanation,
|
|
38204
|
+
offset: merged2.offset
|
|
37241
38205
|
};
|
|
37242
|
-
const styles = variantsOrder.map((t88) => getTokenStyleObject(
|
|
38206
|
+
const styles = variantsOrder.map((t88) => getTokenStyleObject(merged2.variants[t88]));
|
|
37243
38207
|
const styleKeys = new Set(styles.flatMap((t88) => Object.keys(t88)));
|
|
37244
38208
|
const mergedStyles = {};
|
|
37245
38209
|
const varKey = (idx, key2) => {
|
|
@@ -39349,25 +40313,25 @@ var namedCaptureDelim = r35`\(\?<(?![=!])(?<captureName>[^>]+)>`;
|
|
|
39349
40313
|
var captureDelim = r35`${namedCaptureDelim}|(?<unnamed>\()(?!\?)`;
|
|
39350
40314
|
var token = new RegExp(r35`${namedCaptureDelim}|${recursiveToken}|\(\?|\\?.`, "gsu");
|
|
39351
40315
|
var overlappingRecursionMsg = "Cannot use multiple overlapping recursions";
|
|
39352
|
-
function recursion(
|
|
40316
|
+
function recursion(pattern2, data) {
|
|
39353
40317
|
const { hiddenCaptures, mode } = {
|
|
39354
40318
|
hiddenCaptures: [],
|
|
39355
40319
|
mode: "plugin",
|
|
39356
40320
|
...data
|
|
39357
40321
|
};
|
|
39358
40322
|
let captureTransfers = data?.captureTransfers ?? /* @__PURE__ */ new Map();
|
|
39359
|
-
if (!new RegExp(recursiveToken, "su").test(
|
|
40323
|
+
if (!new RegExp(recursiveToken, "su").test(pattern2)) {
|
|
39360
40324
|
return {
|
|
39361
|
-
pattern,
|
|
40325
|
+
pattern: pattern2,
|
|
39362
40326
|
captureTransfers,
|
|
39363
40327
|
hiddenCaptures
|
|
39364
40328
|
};
|
|
39365
40329
|
}
|
|
39366
|
-
if (mode === "plugin" && hasUnescaped(
|
|
40330
|
+
if (mode === "plugin" && hasUnescaped(pattern2, r35`\(\?\(DEFINE\)`, Context.DEFAULT)) {
|
|
39367
40331
|
throw new Error("DEFINE groups cannot be used with recursion");
|
|
39368
40332
|
}
|
|
39369
40333
|
const addedHiddenCaptures = [];
|
|
39370
|
-
const hasNumberedBackref = hasUnescaped(
|
|
40334
|
+
const hasNumberedBackref = hasUnescaped(pattern2, r35`\\[1-9]`, Context.DEFAULT);
|
|
39371
40335
|
const groupContentsStartPos = /* @__PURE__ */ new Map();
|
|
39372
40336
|
const openGroups = [];
|
|
39373
40337
|
let hasRecursed = false;
|
|
@@ -39375,7 +40339,7 @@ function recursion(pattern, data) {
|
|
|
39375
40339
|
let numCapturesPassed = 0;
|
|
39376
40340
|
let match;
|
|
39377
40341
|
token.lastIndex = 0;
|
|
39378
|
-
while (match = token.exec(
|
|
40342
|
+
while (match = token.exec(pattern2)) {
|
|
39379
40343
|
const { 0: m15, groups: { captureName, rDepth, gRNameOrNum, gRDepth } } = match;
|
|
39380
40344
|
if (m15 === "[") {
|
|
39381
40345
|
numCharClassesOpen++;
|
|
@@ -39392,13 +40356,13 @@ function recursion(pattern, data) {
|
|
|
39392
40356
|
`${mode === "external" ? "Backrefs" : "Numbered backrefs"} cannot be used with global recursion`
|
|
39393
40357
|
);
|
|
39394
40358
|
}
|
|
39395
|
-
const left =
|
|
39396
|
-
const right =
|
|
40359
|
+
const left = pattern2.slice(0, match.index);
|
|
40360
|
+
const right = pattern2.slice(token.lastIndex);
|
|
39397
40361
|
if (hasUnescaped(right, recursiveToken, Context.DEFAULT)) {
|
|
39398
40362
|
throw new Error(overlappingRecursionMsg);
|
|
39399
40363
|
}
|
|
39400
40364
|
const reps = +rDepth - 1;
|
|
39401
|
-
|
|
40365
|
+
pattern2 = makeRecursive(
|
|
39402
40366
|
left,
|
|
39403
40367
|
right,
|
|
39404
40368
|
reps,
|
|
@@ -39432,7 +40396,7 @@ function recursion(pattern, data) {
|
|
|
39432
40396
|
throw new Error(r35`Recursive \g cannot be used outside the referenced group "${mode === "external" ? gRNameOrNum : r35`\g<${gRNameOrNum}&R=${gRDepth}>`}"`);
|
|
39433
40397
|
}
|
|
39434
40398
|
const startPos = groupContentsStartPos.get(gRNameOrNum);
|
|
39435
|
-
const groupContents = getGroupContents(
|
|
40399
|
+
const groupContents = getGroupContents(pattern2, startPos);
|
|
39436
40400
|
if (hasNumberedBackref && hasUnescaped(groupContents, r35`${namedCaptureDelim}|\((?!\?)`, Context.DEFAULT)) {
|
|
39437
40401
|
throw new Error(
|
|
39438
40402
|
// When used in `external` mode by transpilers other than Regex+, backrefs might have
|
|
@@ -39440,11 +40404,11 @@ function recursion(pattern, data) {
|
|
|
39440
40404
|
`${mode === "external" ? "Backrefs" : "Numbered backrefs"} cannot be used with recursion of capturing groups`
|
|
39441
40405
|
);
|
|
39442
40406
|
}
|
|
39443
|
-
const groupContentsLeft =
|
|
40407
|
+
const groupContentsLeft = pattern2.slice(startPos, match.index);
|
|
39444
40408
|
const groupContentsRight = groupContents.slice(groupContentsLeft.length + m15.length);
|
|
39445
40409
|
const numAddedHiddenCapturesPreExpansion = addedHiddenCaptures.length;
|
|
39446
40410
|
const reps = +gRDepth - 1;
|
|
39447
|
-
const
|
|
40411
|
+
const expansion2 = makeRecursive(
|
|
39448
40412
|
groupContentsLeft,
|
|
39449
40413
|
groupContentsRight,
|
|
39450
40414
|
reps,
|
|
@@ -39461,10 +40425,10 @@ function recursion(pattern, data) {
|
|
|
39461
40425
|
numAddedHiddenCapturesPreExpansion,
|
|
39462
40426
|
numCapturesPassed
|
|
39463
40427
|
);
|
|
39464
|
-
const pre =
|
|
39465
|
-
const post =
|
|
39466
|
-
|
|
39467
|
-
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;
|
|
39468
40432
|
openGroups.forEach((g7) => g7.hasRecursedWithin = true);
|
|
39469
40433
|
hasRecursed = true;
|
|
39470
40434
|
} else if (captureName) {
|
|
@@ -39491,7 +40455,7 @@ function recursion(pattern, data) {
|
|
|
39491
40455
|
}
|
|
39492
40456
|
hiddenCaptures.push(...addedHiddenCaptures);
|
|
39493
40457
|
return {
|
|
39494
|
-
pattern,
|
|
40458
|
+
pattern: pattern2,
|
|
39495
40459
|
captureTransfers,
|
|
39496
40460
|
hiddenCaptures
|
|
39497
40461
|
};
|
|
@@ -39522,14 +40486,14 @@ function makeRecursive(left, right, reps, isSubpattern, hiddenCaptures, addedHid
|
|
|
39522
40486
|
];
|
|
39523
40487
|
return `${left}${repeatWithDepth(`(?:${left}`, "forward", ...rest)}(?:)${repeatWithDepth(`${right})`, "backward", ...rest)}${right}`;
|
|
39524
40488
|
}
|
|
39525
|
-
function repeatWithDepth(
|
|
40489
|
+
function repeatWithDepth(pattern2, direction, reps, namesInRecursed, hiddenCaptures, addedHiddenCaptures, numCapturesPassed) {
|
|
39526
40490
|
const startNum = 2;
|
|
39527
40491
|
const getDepthNum = (i25) => direction === "forward" ? i25 + startNum : reps - i25 + startNum - 1;
|
|
39528
40492
|
let result = "";
|
|
39529
40493
|
for (let i25 = 0; i25 < reps; i25++) {
|
|
39530
40494
|
const depthNum = getDepthNum(i25);
|
|
39531
40495
|
result += replaceUnescaped(
|
|
39532
|
-
|
|
40496
|
+
pattern2,
|
|
39533
40497
|
r35`${captureDelim}|\\k<(?<backref>[^>]+)>`,
|
|
39534
40498
|
({ 0: m15, groups: { captureName, unnamed, backref } }) => {
|
|
39535
40499
|
if (backref && namesInRecursed && !namesInRecursed.has(backref)) {
|
|
@@ -40612,8 +41576,8 @@ function isLoneGLookaround(node, options) {
|
|
|
40612
41576
|
function isValidJsGroupName(name) {
|
|
40613
41577
|
return /^[$_\p{IDS}][$\u200C\u200D\p{IDC}]*$/u.test(name);
|
|
40614
41578
|
}
|
|
40615
|
-
function parseFragment(
|
|
40616
|
-
const ast = J2(
|
|
41579
|
+
function parseFragment(pattern2, options) {
|
|
41580
|
+
const ast = J2(pattern2, {
|
|
40617
41581
|
...options,
|
|
40618
41582
|
// Providing a custom set of Unicode property names avoids converting some JS Unicode
|
|
40619
41583
|
// properties (ex: `\p{Alpha}`) to Onig POSIX classes
|
|
@@ -41209,13 +42173,13 @@ var EmulatedRegExp = class _EmulatedRegExp extends RegExp {
|
|
|
41209
42173
|
@param {EmulatedRegExp} pattern
|
|
41210
42174
|
@param {string} [flags]
|
|
41211
42175
|
*/
|
|
41212
|
-
constructor(
|
|
42176
|
+
constructor(pattern2, flags, options) {
|
|
41213
42177
|
const lazyCompile = !!options?.lazyCompile;
|
|
41214
|
-
if (
|
|
42178
|
+
if (pattern2 instanceof RegExp) {
|
|
41215
42179
|
if (options) {
|
|
41216
42180
|
throw new Error("Cannot provide options when copying a regexp");
|
|
41217
42181
|
}
|
|
41218
|
-
const re3 =
|
|
42182
|
+
const re3 = pattern2;
|
|
41219
42183
|
super(re3, flags);
|
|
41220
42184
|
this.#pattern = re3.source;
|
|
41221
42185
|
if (re3 instanceof _EmulatedRegExp) {
|
|
@@ -41231,8 +42195,8 @@ var EmulatedRegExp = class _EmulatedRegExp extends RegExp {
|
|
|
41231
42195
|
transfers: [],
|
|
41232
42196
|
...options
|
|
41233
42197
|
};
|
|
41234
|
-
super(lazyCompile ? "" :
|
|
41235
|
-
this.#pattern =
|
|
42198
|
+
super(lazyCompile ? "" : pattern2, flags);
|
|
42199
|
+
this.#pattern = pattern2;
|
|
41236
42200
|
this.#captureMap = createCaptureMap(opts.hiddenCaptures, opts.transfers);
|
|
41237
42201
|
this.#strategy = opts.strategy;
|
|
41238
42202
|
this.rawOptions = options ?? {};
|
|
@@ -41358,13 +42322,13 @@ function createCaptureMap(hiddenCaptures, transfers) {
|
|
|
41358
42322
|
}
|
|
41359
42323
|
return captureMap;
|
|
41360
42324
|
}
|
|
41361
|
-
function createNameMap(
|
|
42325
|
+
function createNameMap(pattern2) {
|
|
41362
42326
|
const re3 = /(?<capture>\((?:\?<(?![=!])(?<name>[^>]+)>|(?!\?)))|\\?./gsu;
|
|
41363
42327
|
const map = /* @__PURE__ */ new Map();
|
|
41364
42328
|
let numCharClassesOpen = 0;
|
|
41365
42329
|
let numCaptures = 0;
|
|
41366
42330
|
let match;
|
|
41367
|
-
while (match = re3.exec(
|
|
42331
|
+
while (match = re3.exec(pattern2)) {
|
|
41368
42332
|
const { 0: m15, groups: { capture, name } } = match;
|
|
41369
42333
|
if (m15 === "[") {
|
|
41370
42334
|
numCharClassesOpen++;
|
|
@@ -41381,16 +42345,16 @@ function createNameMap(pattern) {
|
|
|
41381
42345
|
}
|
|
41382
42346
|
return map;
|
|
41383
42347
|
}
|
|
41384
|
-
function toRegExp(
|
|
41385
|
-
const d22 = toRegExpDetails(
|
|
42348
|
+
function toRegExp(pattern2, options) {
|
|
42349
|
+
const d22 = toRegExpDetails(pattern2, options);
|
|
41386
42350
|
if (d22.options) {
|
|
41387
42351
|
return new EmulatedRegExp(d22.pattern, d22.flags, d22.options);
|
|
41388
42352
|
}
|
|
41389
42353
|
return new RegExp(d22.pattern, d22.flags);
|
|
41390
42354
|
}
|
|
41391
|
-
function toRegExpDetails(
|
|
42355
|
+
function toRegExpDetails(pattern2, options) {
|
|
41392
42356
|
const opts = getOptions(options);
|
|
41393
|
-
const onigurumaAst = J2(
|
|
42357
|
+
const onigurumaAst = J2(pattern2, {
|
|
41394
42358
|
flags: opts.flags,
|
|
41395
42359
|
normalizeUnknownPropertyNames: true,
|
|
41396
42360
|
rules: {
|
|
@@ -41443,8 +42407,8 @@ function toRegExpDetails(pattern, options) {
|
|
|
41443
42407
|
}
|
|
41444
42408
|
|
|
41445
42409
|
// node_modules/@shikijs/engine-javascript/dist/engine-compile.mjs
|
|
41446
|
-
function defaultJavaScriptRegexConstructor(
|
|
41447
|
-
return toRegExp(
|
|
42410
|
+
function defaultJavaScriptRegexConstructor(pattern2, options) {
|
|
42411
|
+
return toRegExp(pattern2, {
|
|
41448
42412
|
global: true,
|
|
41449
42413
|
hasIndices: true,
|
|
41450
42414
|
lazyCompileLength: 3e3,
|
|
@@ -41464,7 +42428,7 @@ function createJavaScriptRegexEngine(options = {}) {
|
|
|
41464
42428
|
cache: /* @__PURE__ */ new Map(),
|
|
41465
42429
|
...options
|
|
41466
42430
|
};
|
|
41467
|
-
_options.regexConstructor ||= (
|
|
42431
|
+
_options.regexConstructor ||= (pattern2) => defaultJavaScriptRegexConstructor(pattern2, { target: _options.target });
|
|
41468
42432
|
return {
|
|
41469
42433
|
createScanner(patterns) {
|
|
41470
42434
|
return new JavaScriptScanner(patterns, _options);
|
|
@@ -42794,8 +43758,8 @@ var InteractionManager = class {
|
|
|
42794
43758
|
const indexes = this.getLineIndex(point.lineNumber, point.side);
|
|
42795
43759
|
if (indexes == null) return;
|
|
42796
43760
|
const lineIndex = this.mode === "diff" ? `${indexes[0]},${indexes[1]}` : `${indexes[0]}`;
|
|
42797
|
-
const
|
|
42798
|
-
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) {
|
|
42799
43763
|
if (!(element2 instanceof HTMLElement)) continue;
|
|
42800
43764
|
const target = this.resolvePointerTarget(getElementPath(element2));
|
|
42801
43765
|
if (!isLinePointerTarget(target)) continue;
|
|
@@ -44047,6 +45011,7 @@ var EXTENSION_TO_FILE_FORMAT = {
|
|
|
44047
45011
|
mli: "ocaml",
|
|
44048
45012
|
mll: "ocaml",
|
|
44049
45013
|
mly: "ocaml",
|
|
45014
|
+
odin: "odin",
|
|
44050
45015
|
pas: "pascal",
|
|
44051
45016
|
p: "pascal",
|
|
44052
45017
|
pl: "prolog",
|
|
@@ -44079,6 +45044,17 @@ var EXTENSION_TO_FILE_FORMAT = {
|
|
|
44079
45044
|
py: "python",
|
|
44080
45045
|
pyw: "python",
|
|
44081
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",
|
|
44082
45058
|
qml: "qml",
|
|
44083
45059
|
qmldir: "qmldir",
|
|
44084
45060
|
qss: "qss",
|
|
@@ -44189,16 +45165,22 @@ var EXTENSION_TO_FILE_FORMAT = {
|
|
|
44189
45165
|
sty: "tex"
|
|
44190
45166
|
};
|
|
44191
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) {
|
|
44192
45174
|
if (CUSTOM_EXTENSION_TO_FILE_FORMAT.has(fileName)) return CUSTOM_EXTENSION_TO_FILE_FORMAT.get(fileName) ?? "text";
|
|
44193
|
-
if (EXTENSION_TO_FILE_FORMAT
|
|
45175
|
+
if (Object.hasOwn(EXTENSION_TO_FILE_FORMAT, fileName)) return EXTENSION_TO_FILE_FORMAT[fileName] ?? null;
|
|
44194
45176
|
const compoundMatch = fileName.match(/\.([^/\\]+\.[^/\\]+)$/);
|
|
44195
45177
|
if (compoundMatch != null) {
|
|
44196
45178
|
if (CUSTOM_EXTENSION_TO_FILE_FORMAT.has(compoundMatch[1])) return CUSTOM_EXTENSION_TO_FILE_FORMAT.get(compoundMatch[1]) ?? "text";
|
|
44197
|
-
if (EXTENSION_TO_FILE_FORMAT
|
|
45179
|
+
if (Object.hasOwn(EXTENSION_TO_FILE_FORMAT, compoundMatch[1])) return EXTENSION_TO_FILE_FORMAT[compoundMatch[1]] ?? "text";
|
|
44198
45180
|
}
|
|
44199
45181
|
const simpleMatch = fileName.match(/\.([^.]+)$/)?.[1] ?? "";
|
|
44200
45182
|
if (CUSTOM_EXTENSION_TO_FILE_FORMAT.has(simpleMatch)) return CUSTOM_EXTENSION_TO_FILE_FORMAT.get(simpleMatch) ?? "text";
|
|
44201
|
-
return EXTENSION_TO_FILE_FORMAT[simpleMatch] ?? "text";
|
|
45183
|
+
return Object.hasOwn(EXTENSION_TO_FILE_FORMAT, simpleMatch) ? EXTENSION_TO_FILE_FORMAT[simpleMatch] ?? "text" : null;
|
|
44202
45184
|
}
|
|
44203
45185
|
|
|
44204
45186
|
// node_modules/@pierre/diffs/dist/utils/getHighlighterOptions.js
|
|
@@ -44564,8 +45546,8 @@ function normalizeThemeColors(theme3) {
|
|
|
44564
45546
|
function fill(colors, key2, value) {
|
|
44565
45547
|
if (value != null && value !== "") colors[key2] = value;
|
|
44566
45548
|
}
|
|
44567
|
-
function firstColor(...
|
|
44568
|
-
for (const candidate of
|
|
45549
|
+
function firstColor(...candidates2) {
|
|
45550
|
+
for (const candidate of candidates2) if (candidate != null && candidate !== "") return candidate;
|
|
44569
45551
|
}
|
|
44570
45552
|
function matchesSurface(color, surface2) {
|
|
44571
45553
|
return surface2 != null && color.toLowerCase() === surface2.toLowerCase();
|
|
@@ -45671,6 +46653,12 @@ function isStyleNode(element2) {
|
|
|
45671
46653
|
return typeof tagName === "string" && tagName.toLowerCase() === "style";
|
|
45672
46654
|
}
|
|
45673
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
|
+
|
|
45674
46662
|
// node_modules/@pierre/diffs/dist/utils/editSessionAnnotations.js
|
|
45675
46663
|
function adoptEditSessionAnnotations(annotations, getName, previousSession) {
|
|
45676
46664
|
const slotNames = /* @__PURE__ */ new Map();
|
|
@@ -45762,10 +46750,31 @@ function createHostThemeStyleNode() {
|
|
|
45762
46750
|
return node;
|
|
45763
46751
|
}
|
|
45764
46752
|
|
|
45765
|
-
// node_modules/@pierre/diffs/dist/
|
|
45766
|
-
var
|
|
45767
|
-
|
|
45768
|
-
|
|
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);
|
|
45769
46778
|
}
|
|
45770
46779
|
|
|
45771
46780
|
// node_modules/@pierre/diffs/dist/components/web-components.js
|
|
@@ -46417,6 +47426,7 @@ var File = class {
|
|
|
46417
47426
|
const tokenizeMaxLength = this.options.tokenizeMaxLength ?? 1e5;
|
|
46418
47427
|
if (this.fileRenderer.getOrCreateLineCache(file).length > tokenizeMaxLength) return;
|
|
46419
47428
|
await workerManager.primeFileHighlightCache(file).catch((error) => {
|
|
47429
|
+
if (isHandledWorkerPoolError(error)) return;
|
|
46420
47430
|
console.error(error);
|
|
46421
47431
|
});
|
|
46422
47432
|
}
|
|
@@ -49288,13 +50298,13 @@ function getChangeIterationRanges(state3, content, diffStyle) {
|
|
|
49288
50298
|
}
|
|
49289
50299
|
if (iterationRanges.length === 0) return iterationRanges;
|
|
49290
50300
|
iterationRanges.sort((a22, b13) => a22[0] - b13[0]);
|
|
49291
|
-
const
|
|
50301
|
+
const merged2 = [iterationRanges[0]];
|
|
49292
50302
|
for (const [start, end] of iterationRanges.slice(1)) {
|
|
49293
|
-
const last =
|
|
50303
|
+
const last = merged2[merged2.length - 1];
|
|
49294
50304
|
if (start <= last[1]) last[1] = Math.max(last[1], end);
|
|
49295
|
-
else
|
|
50305
|
+
else merged2.push([start, end]);
|
|
49296
50306
|
}
|
|
49297
|
-
return
|
|
50307
|
+
return merged2;
|
|
49298
50308
|
}
|
|
49299
50309
|
function getChangeLineData({ hunkIndex, hunk, collapsedAfter, collapsedBefore, diffStyle, index, unifiedLineIndex, splitLineIndex, additionLineIndex, deletionLineIndex, additionLineNumber, deletionLineNumber, content, isLastContent, unifiedCount, splitCount }) {
|
|
49300
50310
|
const unifiedDeletionLineIndex = index < content.deletions ? unifiedLineIndex + index : void 0;
|
|
@@ -50491,7 +51501,7 @@ var DiffHunksRenderer = class {
|
|
|
50491
51501
|
* row set without a line-count change — the host must escalate to a full
|
|
50492
51502
|
* re-render instead of its cheap refresh path.
|
|
50493
51503
|
*/
|
|
50494
|
-
updateRenderCache(dirtyLines, themeType, lineCountChangeInFlight = false) {
|
|
51504
|
+
updateRenderCache(dirtyLines, themeType, lineCountChangeInFlight = false, changedDocumentLines, documentLineCount) {
|
|
50495
51505
|
this.pendingStructuralRows = void 0;
|
|
50496
51506
|
const { renderCache } = this;
|
|
50497
51507
|
if (renderCache == null) return false;
|
|
@@ -50502,13 +51512,27 @@ var DiffHunksRenderer = class {
|
|
|
50502
51512
|
const pendingStructuralRows = this.pendingStructuralRows = lineCountChangeInFlight ? /* @__PURE__ */ new Map() : void 0;
|
|
50503
51513
|
const changedAdditionLines = [];
|
|
50504
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
|
+
}
|
|
50505
51529
|
for (const [line, tokens] of dirtyLines) {
|
|
50506
51530
|
const prevProps = hastLines[line]?.properties ?? {};
|
|
50507
51531
|
const lineText = tokens.map((a22) => a22[2]).join("");
|
|
50508
51532
|
const canSyncDiffLine = line < diff.additionLines.length;
|
|
50509
51533
|
const prevLine = canSyncDiffLine ? diff.additionLines[line] ?? "" : "";
|
|
50510
51534
|
const prevText = cleanLastNewline(prevLine);
|
|
50511
|
-
if (pendingStructuralRows == null && canSyncDiffLine) {
|
|
51535
|
+
if (pendingStructuralRows == null && canSyncDiffLine && changedDocumentLines?.has(line) !== true) {
|
|
50512
51536
|
diff.additionLines[line] = applyLineTextWithNewline(prevLine, lineText);
|
|
50513
51537
|
if (prevText !== lineText) {
|
|
50514
51538
|
changedAdditionLines.push(line);
|
|
@@ -51502,6 +52526,9 @@ function realignAdditionHastLines(previousLines, nextLines, hastLines, textDocum
|
|
|
51502
52526
|
for (let index = prefix; index < nextLines.length; index++) realigned[index] ??= createPlainAdditionLineElement(index, textDocument.getLineText(index));
|
|
51503
52527
|
return realigned;
|
|
51504
52528
|
}
|
|
52529
|
+
function canAppendFinalDocumentRow(additionLines, documentLineCount) {
|
|
52530
|
+
return documentLineCount === additionLines.length + 1 && additionLines.at(-1)?.endsWith("\n") === true;
|
|
52531
|
+
}
|
|
51505
52532
|
function createPlainAdditionLineElement(lineIndex, lineText, unifiedLineIndex = lineIndex, splitLineIndex = lineIndex) {
|
|
51506
52533
|
return {
|
|
51507
52534
|
type: "element",
|
|
@@ -51604,6 +52631,7 @@ function getDiffHunksRendererOptions(options) {
|
|
|
51604
52631
|
hunkSeparators: typeof options?.hunkSeparators === "function" ? "custom" : options?.hunkSeparators,
|
|
51605
52632
|
expandUnchanged: options?.expandUnchanged,
|
|
51606
52633
|
loadDiffFiles: options?.loadDiffFiles,
|
|
52634
|
+
parseDiffOptions: options?.parseDiffOptions,
|
|
51607
52635
|
collapsedContextThreshold: options?.collapsedContextThreshold,
|
|
51608
52636
|
lineDiffType: options?.lineDiffType,
|
|
51609
52637
|
maxLineDiffLength: options?.maxLineDiffLength,
|
|
@@ -52596,7 +53624,7 @@ var FileDiff = class {
|
|
|
52596
53624
|
this.detachAdditionLines();
|
|
52597
53625
|
this.hunksRenderer.beginEditSession(editSessionDiff);
|
|
52598
53626
|
const { shouldRefreshDiffsView, lineCountChangeInFlight } = options;
|
|
52599
|
-
if (this.hunksRenderer.updateRenderCache(dirtyLines, themeType, lineCountChangeInFlight)) {
|
|
53627
|
+
if (this.hunksRenderer.updateRenderCache(dirtyLines, themeType, lineCountChangeInFlight, options.changedDocumentLines, options.documentLineCount)) {
|
|
52600
53628
|
if (this.refreshViewTimeout != null) {
|
|
52601
53629
|
clearTimeout(this.refreshViewTimeout);
|
|
52602
53630
|
this.refreshViewTimeout = void 0;
|
|
@@ -52743,6 +53771,7 @@ var FileDiff = class {
|
|
|
52743
53771
|
const tokenizeMaxLength = this.options.tokenizeMaxLength ?? 1e5;
|
|
52744
53772
|
if (Math.max(fileDiff.additionLines.length, fileDiff.deletionLines.length) > tokenizeMaxLength) return;
|
|
52745
53773
|
await workerManager.primeDiffHighlightCache(fileDiff).catch((error) => {
|
|
53774
|
+
if (isHandledWorkerPoolError(error)) return;
|
|
52746
53775
|
console.error(error);
|
|
52747
53776
|
});
|
|
52748
53777
|
}
|
|
@@ -54240,9 +55269,9 @@ function disableTextSelection(rootNode = document) {
|
|
|
54240
55269
|
}
|
|
54241
55270
|
function getDockviewTheme(element2) {
|
|
54242
55271
|
function toClassList(element3) {
|
|
54243
|
-
const
|
|
54244
|
-
for (let i25 = 0; i25 < element3.classList.length; i25++)
|
|
54245
|
-
return
|
|
55272
|
+
const list5 = [];
|
|
55273
|
+
for (let i25 = 0; i25 < element3.classList.length; i25++) list5.push(element3.classList.item(i25));
|
|
55274
|
+
return list5;
|
|
54246
55275
|
}
|
|
54247
55276
|
let theme3 = void 0;
|
|
54248
55277
|
let parent = element2;
|
|
@@ -55446,7 +56475,7 @@ var BranchNode = class BranchNode2 extends CompositeDisposable {
|
|
|
55446
56475
|
if (child instanceof BranchNode2) child.proportionalLayout = value;
|
|
55447
56476
|
});
|
|
55448
56477
|
}
|
|
55449
|
-
constructor(orientation, proportionalLayout, styles, size4, orthogonalSize,
|
|
56478
|
+
constructor(orientation, proportionalLayout, styles, size4, orthogonalSize, disabled2, margin, childDescriptors) {
|
|
55450
56479
|
super();
|
|
55451
56480
|
this.orientation = orientation;
|
|
55452
56481
|
this.styles = styles;
|
|
@@ -55489,7 +56518,7 @@ var BranchNode = class BranchNode2 extends CompositeDisposable {
|
|
|
55489
56518
|
});
|
|
55490
56519
|
this.splitview.layout(this.size, this.orthogonalSize);
|
|
55491
56520
|
}
|
|
55492
|
-
this.disabled =
|
|
56521
|
+
this.disabled = disabled2;
|
|
55493
56522
|
this.addDisposables(this._onDidChange, this._onDidVisibilityChange, this.splitview.onDidSashEnd(() => {
|
|
55494
56523
|
this._onDidChange.fire({});
|
|
55495
56524
|
}));
|
|
@@ -65093,9 +66122,9 @@ var ENTERPRISE_MODULE_NAMES = /* @__PURE__ */ new Set([
|
|
|
65093
66122
|
var _warnedMissingModule = /* @__PURE__ */ new Set();
|
|
65094
66123
|
function missingModuleMessage(moduleName, reason) {
|
|
65095
66124
|
const reasons = reason === void 0 ? [] : [].concat(reason);
|
|
65096
|
-
const
|
|
66125
|
+
const quoted2 = reasons.map((r39) => `\`${r39}\``).join(", ");
|
|
65097
66126
|
const requires = reasons.length > 1 ? "require" : "requires";
|
|
65098
|
-
const needed = reasons.length ? `${
|
|
66127
|
+
const needed = reasons.length ? `${quoted2} ${requires} the "${moduleName}" module` : `The "${moduleName}" module is required`;
|
|
65099
66128
|
if (ENTERPRISE_MODULE_NAMES.has(moduleName)) return `dockview: ${needed}, which ships in dockview-enterprise.
|
|
65100
66129
|
|
|
65101
66130
|
npm install dockview-enterprise
|
|
@@ -65695,9 +66724,9 @@ var RootDropTargetService = class {
|
|
|
65695
66724
|
}
|
|
65696
66725
|
setOptions(options) {
|
|
65697
66726
|
if ("dndEdges" in options) {
|
|
65698
|
-
const
|
|
65699
|
-
this._html5Target.disabled =
|
|
65700
|
-
this._pointerTarget.disabled =
|
|
66727
|
+
const disabled2 = typeof options.dndEdges === "boolean" && options.dndEdges === false;
|
|
66728
|
+
this._html5Target.disabled = disabled2;
|
|
66729
|
+
this._pointerTarget.disabled = disabled2;
|
|
65701
66730
|
}
|
|
65702
66731
|
if ("dndEdges" in options || "dockToEdgeGroups" in options) {
|
|
65703
66732
|
const model = resolveRootOverlayModel({
|
|
@@ -66076,16 +67105,16 @@ var nextContextMenuItemId = () => `dv-ctx-menu-item-${_nextId++}`;
|
|
|
66076
67105
|
function isItemConfig(item2) {
|
|
66077
67106
|
return typeof item2 === "object";
|
|
66078
67107
|
}
|
|
66079
|
-
function buildItem(label, close, action,
|
|
67108
|
+
function buildItem(label, close, action, disabled2) {
|
|
66080
67109
|
const el = document.createElement("div");
|
|
66081
67110
|
el.className = "dv-context-menu-item";
|
|
66082
67111
|
el.setAttribute("role", "menuitem");
|
|
66083
|
-
if (
|
|
67112
|
+
if (disabled2) {
|
|
66084
67113
|
el.classList.add("dv-context-menu-item--disabled");
|
|
66085
67114
|
el.setAttribute("aria-disabled", "true");
|
|
66086
67115
|
}
|
|
66087
67116
|
el.textContent = label;
|
|
66088
|
-
if (!
|
|
67117
|
+
if (!disabled2) el.addEventListener("click", () => {
|
|
66089
67118
|
action();
|
|
66090
67119
|
close();
|
|
66091
67120
|
});
|
|
@@ -71287,9 +72316,9 @@ var getBaseFileName = (path) => {
|
|
|
71287
72316
|
};
|
|
71288
72317
|
var getExtensionCandidates = (fileName) => {
|
|
71289
72318
|
const segments = fileName.toLowerCase().split(".");
|
|
71290
|
-
const
|
|
71291
|
-
for (let index = 1; index < segments.length; index += 1)
|
|
71292
|
-
return
|
|
72319
|
+
const candidates2 = [];
|
|
72320
|
+
for (let index = 1; index < segments.length; index += 1) candidates2.push(segments.slice(index).join("."));
|
|
72321
|
+
return candidates2;
|
|
71293
72322
|
};
|
|
71294
72323
|
function remapEntryToIcon(entry, remappedFrom) {
|
|
71295
72324
|
if (typeof entry === "string") return {
|
|
@@ -77442,8 +78471,8 @@ function getFileTreeRowAriaLabel(row) {
|
|
|
77442
78471
|
if (flattenedSegments == null || flattenedSegments.length === 0) return row.name;
|
|
77443
78472
|
return flattenedSegments.map((segment2) => segment2.name).join(" / ");
|
|
77444
78473
|
}
|
|
77445
|
-
function computeStickyRowsFromCandidates(
|
|
77446
|
-
return
|
|
78474
|
+
function computeStickyRowsFromCandidates(candidates2, scrollTop, itemHeight, totalRowCount) {
|
|
78475
|
+
return candidates2.map((candidate, slotDepth) => {
|
|
77447
78476
|
const defaultTop = slotDepth * itemHeight;
|
|
77448
78477
|
const nextBoundaryIndex = candidate.subtreeEndIndex + 1;
|
|
77449
78478
|
if (nextBoundaryIndex >= totalRowCount) return {
|
|
@@ -77490,9 +78519,9 @@ function getPointElement(rootNode, clientX, clientY) {
|
|
|
77490
78519
|
return element2 instanceof HTMLElement ? element2 : null;
|
|
77491
78520
|
}
|
|
77492
78521
|
function getShadowPointElementByGeometry(rootNode, clientX, clientY) {
|
|
77493
|
-
const
|
|
77494
|
-
for (let index =
|
|
77495
|
-
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];
|
|
77496
78525
|
const rect = candidate.getBoundingClientRect();
|
|
77497
78526
|
if (clientX >= rect.left && clientX <= rect.right && clientY >= rect.top && clientY <= rect.bottom) return candidate;
|
|
77498
78527
|
}
|
|
@@ -80010,6 +81039,8 @@ var elements = {
|
|
|
80010
81039
|
"slicc-network": SliccNetwork,
|
|
80011
81040
|
"slicc-notices": SliccNotices,
|
|
80012
81041
|
"slicc-approvals": SliccApprovals,
|
|
81042
|
+
"slicc-secrets": SliccSecrets,
|
|
81043
|
+
"slicc-vault-button": SliccVaultButton,
|
|
80013
81044
|
"slicc-confirm": SliccConfirm,
|
|
80014
81045
|
"slicc-prompt": SliccPrompt,
|
|
80015
81046
|
"slicc-app": SliccApp
|
|
@@ -80046,7 +81077,9 @@ export {
|
|
|
80046
81077
|
SliccNetwork,
|
|
80047
81078
|
SliccNotices,
|
|
80048
81079
|
SliccPrompt,
|
|
81080
|
+
SliccSecrets,
|
|
80049
81081
|
SliccUpdates,
|
|
81082
|
+
SliccVaultButton,
|
|
80050
81083
|
confirm,
|
|
80051
81084
|
define2 as define,
|
|
80052
81085
|
grammarBase,
|