@solongate/proxy 0.81.43 → 0.81.45
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/dist/index.js +130 -10
- package/dist/tui/index.js +130 -10
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7534,6 +7534,7 @@ function LivePanel({ active: active2 }) {
|
|
|
7534
7534
|
const [detailScroll, setDetailScroll] = useState2(0);
|
|
7535
7535
|
const [inspect, setInspect] = useState2(null);
|
|
7536
7536
|
const [inspectScroll, setInspectScroll] = useState2(0);
|
|
7537
|
+
const [layersScroll, setLayersScroll] = useState2(0);
|
|
7537
7538
|
const inspectFromRef = useRef2("stream");
|
|
7538
7539
|
const seenRef = useRef2(/* @__PURE__ */ new Set());
|
|
7539
7540
|
const lastLocalTs = useRef2(0);
|
|
@@ -7706,20 +7707,45 @@ function LivePanel({ active: active2 }) {
|
|
|
7706
7707
|
}, [active2, frozen]);
|
|
7707
7708
|
const startRef = useRef2(Date.now());
|
|
7708
7709
|
const lastNotifyAt = useRef2(0);
|
|
7710
|
+
const toastQueue = useRef2(/* @__PURE__ */ new Map());
|
|
7711
|
+
const toastTimer = useRef2(null);
|
|
7712
|
+
const TOAST_RANK = { "DLP hit": 0, "Call denied": 1, "Rate-limit burst": 2 };
|
|
7713
|
+
const flushToasts = useCallback2(function flush() {
|
|
7714
|
+
toastTimer.current = null;
|
|
7715
|
+
const q2 = toastQueue.current;
|
|
7716
|
+
if (!q2.size) return;
|
|
7717
|
+
const wait = 3e3 - (Date.now() - lastNotifyAt.current);
|
|
7718
|
+
if (wait > 0) {
|
|
7719
|
+
toastTimer.current = setTimeout(flush, wait);
|
|
7720
|
+
return;
|
|
7721
|
+
}
|
|
7722
|
+
lastNotifyAt.current = Date.now();
|
|
7723
|
+
const items = [...q2.entries()].sort((a, b) => (TOAST_RANK[a[0]] ?? 9) - (TOAST_RANK[b[0]] ?? 9));
|
|
7724
|
+
q2.clear();
|
|
7725
|
+
try {
|
|
7726
|
+
process.stdout.write("\x07");
|
|
7727
|
+
} catch {
|
|
7728
|
+
}
|
|
7729
|
+
const total = items.reduce((n, [, v]) => n + v.count, 0);
|
|
7730
|
+
if (items.length === 1 && total === 1) desktopNotify(items[0][0], items[0][1].msg);
|
|
7731
|
+
else desktopNotify("Security alerts", items.map(([t, v]) => `${v.count}\xD7 ${t}`).join(" \xB7 "));
|
|
7732
|
+
}, []);
|
|
7733
|
+
useEffect2(
|
|
7734
|
+
() => () => {
|
|
7735
|
+
if (toastTimer.current) clearTimeout(toastTimer.current);
|
|
7736
|
+
},
|
|
7737
|
+
[]
|
|
7738
|
+
);
|
|
7709
7739
|
const fireAlert = useCallback2(
|
|
7710
7740
|
(id, title, msg, level = "warn", desktop = true) => {
|
|
7711
7741
|
pushLog(`${level === "bad" ? "\u26D4" : "\u23F8"} ${msg}`, level);
|
|
7712
7742
|
setAlerts((a) => [...a.filter((x) => x.id !== id), { id, msg, level, until: Date.now() + 15e3 }].slice(-4));
|
|
7713
7743
|
if (!desktop || !CONFIG.notifications) return;
|
|
7714
|
-
|
|
7715
|
-
|
|
7716
|
-
|
|
7717
|
-
process.stdout.write("\x07");
|
|
7718
|
-
} catch {
|
|
7719
|
-
}
|
|
7720
|
-
desktopNotify(title, msg);
|
|
7744
|
+
const cur = toastQueue.current.get(title);
|
|
7745
|
+
toastQueue.current.set(title, { count: (cur?.count ?? 0) + 1, msg: cur?.msg ?? msg });
|
|
7746
|
+
if (!toastTimer.current) toastTimer.current = setTimeout(flushToasts, 400);
|
|
7721
7747
|
},
|
|
7722
|
-
[pushLog]
|
|
7748
|
+
[pushLog, flushToasts]
|
|
7723
7749
|
);
|
|
7724
7750
|
useEffect2(() => {
|
|
7725
7751
|
if (!active2) return;
|
|
@@ -7908,6 +7934,14 @@ function LivePanel({ active: active2 }) {
|
|
|
7908
7934
|
else if (key.pageDown) setInspectScroll((n) => n + 10);
|
|
7909
7935
|
return;
|
|
7910
7936
|
}
|
|
7937
|
+
if (mode === "layers") {
|
|
7938
|
+
if (key.leftArrow || input === "l") setMode("stream");
|
|
7939
|
+
else if (key.upArrow) setLayersScroll((n) => Math.max(0, n - 1));
|
|
7940
|
+
else if (key.downArrow) setLayersScroll((n) => n + 1);
|
|
7941
|
+
else if (key.pageUp) setLayersScroll((n) => Math.max(0, n - 10));
|
|
7942
|
+
else if (key.pageDown) setLayersScroll((n) => n + 10);
|
|
7943
|
+
return;
|
|
7944
|
+
}
|
|
7911
7945
|
if (mode === "detail") {
|
|
7912
7946
|
const maxD = Math.max(0, detailEntries.length - 1);
|
|
7913
7947
|
if (key.leftArrow) {
|
|
@@ -7957,6 +7991,9 @@ function LivePanel({ active: active2 }) {
|
|
|
7957
7991
|
} else if (input === "s") {
|
|
7958
7992
|
setPickIdx(0);
|
|
7959
7993
|
setMode("pick");
|
|
7994
|
+
} else if (input === "l") {
|
|
7995
|
+
setLayersScroll(0);
|
|
7996
|
+
setMode("layers");
|
|
7960
7997
|
} else if (input === "w") void doAction("whitelist");
|
|
7961
7998
|
else if (input === "b") void doAction("block");
|
|
7962
7999
|
else if (input === "d") toggleSignal("deny");
|
|
@@ -8076,6 +8113,87 @@ function LivePanel({ active: active2 }) {
|
|
|
8076
8113
|
] })
|
|
8077
8114
|
] });
|
|
8078
8115
|
}
|
|
8116
|
+
if (mode === "layers") {
|
|
8117
|
+
const modeColor4 = (m) => m === "block" || m === "on" ? theme.ok : m === "detect" ? theme.warn : theme.dim;
|
|
8118
|
+
const barW = Math.max(10, Math.min(40, innerW - 30));
|
|
8119
|
+
const burstsInBuf = mergedAll.filter((e) => e.burst).length;
|
|
8120
|
+
const dlpInBuf = mergedAll.filter((e) => e.dlp).length;
|
|
8121
|
+
const allHits = ins.dlpByPattern ?? [];
|
|
8122
|
+
const maxHit = allHits[0]?.count ?? 1;
|
|
8123
|
+
const L = [];
|
|
8124
|
+
const push2 = (el) => L.push(/* @__PURE__ */ jsx2(Box2, { children: el }, L.length));
|
|
8125
|
+
const blank = () => push2(/* @__PURE__ */ jsx2(Text2, { children: " " }));
|
|
8126
|
+
const section = (label, m, note) => push2(
|
|
8127
|
+
/* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
|
|
8128
|
+
/* @__PURE__ */ jsxs2(Text2, { bold: true, color: theme.accentBright, children: [
|
|
8129
|
+
"\u258E",
|
|
8130
|
+
label.padEnd(10)
|
|
8131
|
+
] }),
|
|
8132
|
+
/* @__PURE__ */ jsx2(Text2, { bold: true, color: modeColor4(m), children: (m ?? "?").padEnd(8) }),
|
|
8133
|
+
note ? /* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: note }) : null
|
|
8134
|
+
] })
|
|
8135
|
+
);
|
|
8136
|
+
const kv = (k, v) => push2(
|
|
8137
|
+
/* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
|
|
8138
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: (" " + k).padEnd(16) }),
|
|
8139
|
+
v
|
|
8140
|
+
] })
|
|
8141
|
+
);
|
|
8142
|
+
section("RATELIMIT", rl?.mode, rl?.mode === "block" ? "over-limit calls are DENIED" : rl?.mode === "detect" ? "over-limit calls are observed & flagged rl:yes" : "no limit enforcement");
|
|
8143
|
+
kv("limits", /* @__PURE__ */ jsx2(Text2, { children: rl?.perMinute || rl?.perHour || rl?.perDay ? `${rl?.perMinute || "\u2014"}/min \xB7 ${rl?.perHour || "\u2014"}/hour \xB7 ${rl?.perDay || "\u2014"}/day` : "none configured" }));
|
|
8144
|
+
kv("load now", /* @__PURE__ */ jsx2(Text2, { children: `${minuteNow} calls in the last 60s` }));
|
|
8145
|
+
if (rl?.perMinute) push2(/* @__PURE__ */ jsx2(HBar, { label: " load/min", value: minuteNow, max: rl.perMinute, width: barW, color: minuteNow > rl.perMinute ? theme.bad : theme.accent }));
|
|
8146
|
+
kv("bursts", /* @__PURE__ */ jsx2(Text2, { color: burstsInBuf ? theme.warn : theme.dim, children: `${burstsInBuf} flagged in the live buffer` }));
|
|
8147
|
+
blank();
|
|
8148
|
+
section("DLP", dl?.mode, dl?.mode === "block" ? "secrets in arguments are DENIED + redacted" : dl?.mode === "detect" ? "secrets observed & flagged dlp:yes, output redacted" : "no secret scanning");
|
|
8149
|
+
kv("hits", /* @__PURE__ */ jsx2(Text2, { color: dlpInBuf ? theme.bad : theme.dim, children: `${dlpInBuf} flagged in the live buffer` }));
|
|
8150
|
+
const builtin = dl?.patterns ?? [];
|
|
8151
|
+
kv("builtin", /* @__PURE__ */ jsx2(Text2, { children: builtin.length ? `${builtin.length} patterns enabled` : "none enabled" }));
|
|
8152
|
+
for (const line of wrapLines(builtin.join(" \xB7 "), Math.max(20, innerW - 18))) push2(/* @__PURE__ */ jsx2(Text2, { wrap: "truncate", color: theme.dim, children: " " + line }));
|
|
8153
|
+
const custom = dl?.custom ?? [];
|
|
8154
|
+
kv("custom", /* @__PURE__ */ jsx2(Text2, { children: custom.length ? `${custom.length} patterns` : "none" }));
|
|
8155
|
+
for (const c2 of custom)
|
|
8156
|
+
push2(
|
|
8157
|
+
/* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
|
|
8158
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: " " }),
|
|
8159
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.accent, children: truncate2(c2.name ?? "custom", 24).padEnd(25) }),
|
|
8160
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: truncate2(c2.re ?? "", Math.max(10, innerW - 44)) })
|
|
8161
|
+
] })
|
|
8162
|
+
);
|
|
8163
|
+
kv("pattern hits", /* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: allHits.length ? "last 7 days" : "none in the last 7 days" }));
|
|
8164
|
+
for (const h of allHits) push2(/* @__PURE__ */ jsx2(HBar, { label: " " + truncate2(h.pattern, 10), value: h.count, max: maxHit, width: barW, color: theme.bad }));
|
|
8165
|
+
blank();
|
|
8166
|
+
section("GHOST", gh?.mode, gh?.mode === "on" ? "matching paths are hidden from agents" : "no hidden paths");
|
|
8167
|
+
const ghostPats = gh?.patterns ?? [];
|
|
8168
|
+
kv("patterns", /* @__PURE__ */ jsx2(Text2, { children: ghostPats.length ? `${ghostPats.length}` : "none" }));
|
|
8169
|
+
for (const line of wrapLines(ghostPats.join(" \xB7 "), Math.max(20, innerW - 18))) push2(/* @__PURE__ */ jsx2(Text2, { wrap: "truncate", color: theme.dim, children: " " + line }));
|
|
8170
|
+
blank();
|
|
8171
|
+
section("GUARD", guard.data ? guard.data.up_to_date ? "ok" : "stale" : "?", "the PreToolUse hook enforcing all of the above");
|
|
8172
|
+
kv(
|
|
8173
|
+
"hooks",
|
|
8174
|
+
guard.data ? /* @__PURE__ */ jsx2(Text2, { color: guard.data.up_to_date ? theme.ok : theme.warn, children: `v${guard.data.installed ?? "?"}${guard.data.up_to_date ? " (latest)" : ` \u2192 v${guard.data.latest} available`} \xB7 ${guard.data.device_count} device${guard.data.device_count === 1 ? "" : "s"}` }) : /* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: "loading\u2026" })
|
|
8175
|
+
);
|
|
8176
|
+
kv("local eval", ring ? /* @__PURE__ */ jsx2(Text2, { color: theme.ok, children: `avg ${ring.avgMs}ms over ${ring.count} recent calls` }) : /* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: "no local ring in cwd" }));
|
|
8177
|
+
const bodyRows = Math.max(4, rows - 5);
|
|
8178
|
+
const maxLScroll = Math.max(0, L.length - bodyRows);
|
|
8179
|
+
const lOff = Math.min(layersScroll, maxLScroll);
|
|
8180
|
+
const win = L.slice(lOff, lOff + bodyRows);
|
|
8181
|
+
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", paddingX: 1, children: [
|
|
8182
|
+
titleBar,
|
|
8183
|
+
/* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
|
|
8184
|
+
/* @__PURE__ */ jsx2(Text2, { backgroundColor: BG, color: "white", bold: true, children: " LAYERS " }),
|
|
8185
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: " security layers, limits and patterns \xB7 insights window: last 7 days" }),
|
|
8186
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: " \u2190 back" })
|
|
8187
|
+
] }),
|
|
8188
|
+
/* @__PURE__ */ jsx2(PaneTitle, { label: "LAYERS", extra: `${insights.data ? "" : spin + " loading \xB7 "}${maxLScroll ? `\u25BC${maxLScroll - lOff} more \xB7 \u2191\u2193 scroll \xB7 ` : ""}l or \u2190 back`, width: innerW }),
|
|
8189
|
+
/* @__PURE__ */ jsx2(Box2, { flexDirection: "column", height: bodyRows, overflow: "hidden", children: win }),
|
|
8190
|
+
/* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
|
|
8191
|
+
/* @__PURE__ */ jsx2(Text2, { backgroundColor: BG, color: "white", bold: true, children: " LAYERS " }),
|
|
8192
|
+
/* @__PURE__ */ jsx2(Text2, { backgroundColor: "#0b1530", color: "white", children: " rate limit \xB7 dlp \xB7 ghost \xB7 guard " }),
|
|
8193
|
+
/* @__PURE__ */ jsx2(Text2, { backgroundColor: BG, color: "white", children: " \u2191\u2193 scroll \xB7 ? all keys \xB7 \u2190 back \xB7 esc menu " })
|
|
8194
|
+
] })
|
|
8195
|
+
] });
|
|
8196
|
+
}
|
|
8079
8197
|
if (mode === "detail" && detail) {
|
|
8080
8198
|
const d = detailEntries;
|
|
8081
8199
|
const allow = d.filter((e) => e.decision === "ALLOW").length;
|
|
@@ -8195,7 +8313,7 @@ function LivePanel({ active: active2 }) {
|
|
|
8195
8313
|
] }),
|
|
8196
8314
|
/* @__PURE__ */ jsxs2(Box2, { height: colH, children: [
|
|
8197
8315
|
/* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", width: colW, marginRight: 2, overflow: "hidden", children: [
|
|
8198
|
-
/* @__PURE__ */ jsx2(PaneTitle, { label: "LAYERS", width: colW }),
|
|
8316
|
+
/* @__PURE__ */ jsx2(PaneTitle, { label: "LAYERS", extra: "l = inspect", width: colW }),
|
|
8199
8317
|
/* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
|
|
8200
8318
|
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: "RATELIMIT ".padEnd(10) }),
|
|
8201
8319
|
/* @__PURE__ */ jsx2(Text2, { color: rl?.mode === "block" ? theme.ok : rl?.mode === "detect" ? theme.warn : theme.dim, children: (rl?.mode ?? "?").padEnd(7) }),
|
|
@@ -8228,7 +8346,8 @@ function LivePanel({ active: active2 }) {
|
|
|
8228
8346
|
" "
|
|
8229
8347
|
] }),
|
|
8230
8348
|
/* @__PURE__ */ jsx2(Text2, { color: st.color, children: st.label.padEnd(7) }),
|
|
8231
|
-
/* @__PURE__ */ jsx2(Text2, { color: theme.accentBright, children: truncate2(r.isMe ?
|
|
8349
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.accentBright, children: truncate2(r.agent, r.isMe ? 9 : 12).padEnd(r.isMe ? 10 : 13) }),
|
|
8350
|
+
r.isMe ? /* @__PURE__ */ jsx2(Text2, { color: theme.ok, children: "me " }) : null,
|
|
8232
8351
|
/* @__PURE__ */ jsxs2(Text2, { children: [
|
|
8233
8352
|
String(r.calls).padStart(4),
|
|
8234
8353
|
"c "
|
|
@@ -8323,6 +8442,7 @@ var init_Live = __esm({
|
|
|
8323
8442
|
["f", "source filter: all \u2192 local \u2192 cloud"],
|
|
8324
8443
|
["/", "live search (tool, agent, command\u2026) \xB7 enter done"],
|
|
8325
8444
|
["s", "session picker"],
|
|
8445
|
+
["l", "layers detail (rate limit \xB7 dlp \xB7 ghost \xB7 guard)"],
|
|
8326
8446
|
["e", "export visible rows \u2192 ~/.solongate/live-export.jsonl"],
|
|
8327
8447
|
["space", "copy mode: freeze screen for mouse selection"],
|
|
8328
8448
|
["esc", "back to menu"],
|
package/dist/tui/index.js
CHANGED
|
@@ -920,6 +920,7 @@ var LIVE_HELP = [
|
|
|
920
920
|
["f", "source filter: all \u2192 local \u2192 cloud"],
|
|
921
921
|
["/", "live search (tool, agent, command\u2026) \xB7 enter done"],
|
|
922
922
|
["s", "session picker"],
|
|
923
|
+
["l", "layers detail (rate limit \xB7 dlp \xB7 ghost \xB7 guard)"],
|
|
923
924
|
["e", "export visible rows \u2192 ~/.solongate/live-export.jsonl"],
|
|
924
925
|
["space", "copy mode: freeze screen for mouse selection"],
|
|
925
926
|
["esc", "back to menu"],
|
|
@@ -970,6 +971,7 @@ function LivePanel({ active: active2 }) {
|
|
|
970
971
|
const [detailScroll, setDetailScroll] = useState2(0);
|
|
971
972
|
const [inspect, setInspect] = useState2(null);
|
|
972
973
|
const [inspectScroll, setInspectScroll] = useState2(0);
|
|
974
|
+
const [layersScroll, setLayersScroll] = useState2(0);
|
|
973
975
|
const inspectFromRef = useRef2("stream");
|
|
974
976
|
const seenRef = useRef2(/* @__PURE__ */ new Set());
|
|
975
977
|
const lastLocalTs = useRef2(0);
|
|
@@ -1142,20 +1144,45 @@ function LivePanel({ active: active2 }) {
|
|
|
1142
1144
|
}, [active2, frozen]);
|
|
1143
1145
|
const startRef = useRef2(Date.now());
|
|
1144
1146
|
const lastNotifyAt = useRef2(0);
|
|
1147
|
+
const toastQueue = useRef2(/* @__PURE__ */ new Map());
|
|
1148
|
+
const toastTimer = useRef2(null);
|
|
1149
|
+
const TOAST_RANK = { "DLP hit": 0, "Call denied": 1, "Rate-limit burst": 2 };
|
|
1150
|
+
const flushToasts = useCallback2(function flush() {
|
|
1151
|
+
toastTimer.current = null;
|
|
1152
|
+
const q2 = toastQueue.current;
|
|
1153
|
+
if (!q2.size) return;
|
|
1154
|
+
const wait = 3e3 - (Date.now() - lastNotifyAt.current);
|
|
1155
|
+
if (wait > 0) {
|
|
1156
|
+
toastTimer.current = setTimeout(flush, wait);
|
|
1157
|
+
return;
|
|
1158
|
+
}
|
|
1159
|
+
lastNotifyAt.current = Date.now();
|
|
1160
|
+
const items = [...q2.entries()].sort((a, b) => (TOAST_RANK[a[0]] ?? 9) - (TOAST_RANK[b[0]] ?? 9));
|
|
1161
|
+
q2.clear();
|
|
1162
|
+
try {
|
|
1163
|
+
process.stdout.write("\x07");
|
|
1164
|
+
} catch {
|
|
1165
|
+
}
|
|
1166
|
+
const total = items.reduce((n, [, v]) => n + v.count, 0);
|
|
1167
|
+
if (items.length === 1 && total === 1) desktopNotify(items[0][0], items[0][1].msg);
|
|
1168
|
+
else desktopNotify("Security alerts", items.map(([t, v]) => `${v.count}\xD7 ${t}`).join(" \xB7 "));
|
|
1169
|
+
}, []);
|
|
1170
|
+
useEffect2(
|
|
1171
|
+
() => () => {
|
|
1172
|
+
if (toastTimer.current) clearTimeout(toastTimer.current);
|
|
1173
|
+
},
|
|
1174
|
+
[]
|
|
1175
|
+
);
|
|
1145
1176
|
const fireAlert = useCallback2(
|
|
1146
1177
|
(id, title, msg, level = "warn", desktop = true) => {
|
|
1147
1178
|
pushLog(`${level === "bad" ? "\u26D4" : "\u23F8"} ${msg}`, level);
|
|
1148
1179
|
setAlerts((a) => [...a.filter((x) => x.id !== id), { id, msg, level, until: Date.now() + 15e3 }].slice(-4));
|
|
1149
1180
|
if (!desktop || !CONFIG.notifications) return;
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
process.stdout.write("\x07");
|
|
1154
|
-
} catch {
|
|
1155
|
-
}
|
|
1156
|
-
desktopNotify(title, msg);
|
|
1181
|
+
const cur = toastQueue.current.get(title);
|
|
1182
|
+
toastQueue.current.set(title, { count: (cur?.count ?? 0) + 1, msg: cur?.msg ?? msg });
|
|
1183
|
+
if (!toastTimer.current) toastTimer.current = setTimeout(flushToasts, 400);
|
|
1157
1184
|
},
|
|
1158
|
-
[pushLog]
|
|
1185
|
+
[pushLog, flushToasts]
|
|
1159
1186
|
);
|
|
1160
1187
|
useEffect2(() => {
|
|
1161
1188
|
if (!active2) return;
|
|
@@ -1344,6 +1371,14 @@ function LivePanel({ active: active2 }) {
|
|
|
1344
1371
|
else if (key.pageDown) setInspectScroll((n) => n + 10);
|
|
1345
1372
|
return;
|
|
1346
1373
|
}
|
|
1374
|
+
if (mode === "layers") {
|
|
1375
|
+
if (key.leftArrow || input === "l") setMode("stream");
|
|
1376
|
+
else if (key.upArrow) setLayersScroll((n) => Math.max(0, n - 1));
|
|
1377
|
+
else if (key.downArrow) setLayersScroll((n) => n + 1);
|
|
1378
|
+
else if (key.pageUp) setLayersScroll((n) => Math.max(0, n - 10));
|
|
1379
|
+
else if (key.pageDown) setLayersScroll((n) => n + 10);
|
|
1380
|
+
return;
|
|
1381
|
+
}
|
|
1347
1382
|
if (mode === "detail") {
|
|
1348
1383
|
const maxD = Math.max(0, detailEntries.length - 1);
|
|
1349
1384
|
if (key.leftArrow) {
|
|
@@ -1393,6 +1428,9 @@ function LivePanel({ active: active2 }) {
|
|
|
1393
1428
|
} else if (input === "s") {
|
|
1394
1429
|
setPickIdx(0);
|
|
1395
1430
|
setMode("pick");
|
|
1431
|
+
} else if (input === "l") {
|
|
1432
|
+
setLayersScroll(0);
|
|
1433
|
+
setMode("layers");
|
|
1396
1434
|
} else if (input === "w") void doAction("whitelist");
|
|
1397
1435
|
else if (input === "b") void doAction("block");
|
|
1398
1436
|
else if (input === "d") toggleSignal("deny");
|
|
@@ -1512,6 +1550,87 @@ function LivePanel({ active: active2 }) {
|
|
|
1512
1550
|
] })
|
|
1513
1551
|
] });
|
|
1514
1552
|
}
|
|
1553
|
+
if (mode === "layers") {
|
|
1554
|
+
const modeColor2 = (m) => m === "block" || m === "on" ? theme.ok : m === "detect" ? theme.warn : theme.dim;
|
|
1555
|
+
const barW = Math.max(10, Math.min(40, innerW - 30));
|
|
1556
|
+
const burstsInBuf = mergedAll.filter((e) => e.burst).length;
|
|
1557
|
+
const dlpInBuf = mergedAll.filter((e) => e.dlp).length;
|
|
1558
|
+
const allHits = ins.dlpByPattern ?? [];
|
|
1559
|
+
const maxHit = allHits[0]?.count ?? 1;
|
|
1560
|
+
const L = [];
|
|
1561
|
+
const push = (el) => L.push(/* @__PURE__ */ jsx2(Box2, { children: el }, L.length));
|
|
1562
|
+
const blank = () => push(/* @__PURE__ */ jsx2(Text2, { children: " " }));
|
|
1563
|
+
const section = (label, m, note) => push(
|
|
1564
|
+
/* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
|
|
1565
|
+
/* @__PURE__ */ jsxs2(Text2, { bold: true, color: theme.accentBright, children: [
|
|
1566
|
+
"\u258E",
|
|
1567
|
+
label.padEnd(10)
|
|
1568
|
+
] }),
|
|
1569
|
+
/* @__PURE__ */ jsx2(Text2, { bold: true, color: modeColor2(m), children: (m ?? "?").padEnd(8) }),
|
|
1570
|
+
note ? /* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: note }) : null
|
|
1571
|
+
] })
|
|
1572
|
+
);
|
|
1573
|
+
const kv = (k, v) => push(
|
|
1574
|
+
/* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
|
|
1575
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: (" " + k).padEnd(16) }),
|
|
1576
|
+
v
|
|
1577
|
+
] })
|
|
1578
|
+
);
|
|
1579
|
+
section("RATELIMIT", rl?.mode, rl?.mode === "block" ? "over-limit calls are DENIED" : rl?.mode === "detect" ? "over-limit calls are observed & flagged rl:yes" : "no limit enforcement");
|
|
1580
|
+
kv("limits", /* @__PURE__ */ jsx2(Text2, { children: rl?.perMinute || rl?.perHour || rl?.perDay ? `${rl?.perMinute || "\u2014"}/min \xB7 ${rl?.perHour || "\u2014"}/hour \xB7 ${rl?.perDay || "\u2014"}/day` : "none configured" }));
|
|
1581
|
+
kv("load now", /* @__PURE__ */ jsx2(Text2, { children: `${minuteNow} calls in the last 60s` }));
|
|
1582
|
+
if (rl?.perMinute) push(/* @__PURE__ */ jsx2(HBar, { label: " load/min", value: minuteNow, max: rl.perMinute, width: barW, color: minuteNow > rl.perMinute ? theme.bad : theme.accent }));
|
|
1583
|
+
kv("bursts", /* @__PURE__ */ jsx2(Text2, { color: burstsInBuf ? theme.warn : theme.dim, children: `${burstsInBuf} flagged in the live buffer` }));
|
|
1584
|
+
blank();
|
|
1585
|
+
section("DLP", dl?.mode, dl?.mode === "block" ? "secrets in arguments are DENIED + redacted" : dl?.mode === "detect" ? "secrets observed & flagged dlp:yes, output redacted" : "no secret scanning");
|
|
1586
|
+
kv("hits", /* @__PURE__ */ jsx2(Text2, { color: dlpInBuf ? theme.bad : theme.dim, children: `${dlpInBuf} flagged in the live buffer` }));
|
|
1587
|
+
const builtin = dl?.patterns ?? [];
|
|
1588
|
+
kv("builtin", /* @__PURE__ */ jsx2(Text2, { children: builtin.length ? `${builtin.length} patterns enabled` : "none enabled" }));
|
|
1589
|
+
for (const line of wrapLines(builtin.join(" \xB7 "), Math.max(20, innerW - 18))) push(/* @__PURE__ */ jsx2(Text2, { wrap: "truncate", color: theme.dim, children: " " + line }));
|
|
1590
|
+
const custom = dl?.custom ?? [];
|
|
1591
|
+
kv("custom", /* @__PURE__ */ jsx2(Text2, { children: custom.length ? `${custom.length} patterns` : "none" }));
|
|
1592
|
+
for (const c2 of custom)
|
|
1593
|
+
push(
|
|
1594
|
+
/* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
|
|
1595
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: " " }),
|
|
1596
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.accent, children: truncate(c2.name ?? "custom", 24).padEnd(25) }),
|
|
1597
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: truncate(c2.re ?? "", Math.max(10, innerW - 44)) })
|
|
1598
|
+
] })
|
|
1599
|
+
);
|
|
1600
|
+
kv("pattern hits", /* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: allHits.length ? "last 7 days" : "none in the last 7 days" }));
|
|
1601
|
+
for (const h of allHits) push(/* @__PURE__ */ jsx2(HBar, { label: " " + truncate(h.pattern, 10), value: h.count, max: maxHit, width: barW, color: theme.bad }));
|
|
1602
|
+
blank();
|
|
1603
|
+
section("GHOST", gh?.mode, gh?.mode === "on" ? "matching paths are hidden from agents" : "no hidden paths");
|
|
1604
|
+
const ghostPats = gh?.patterns ?? [];
|
|
1605
|
+
kv("patterns", /* @__PURE__ */ jsx2(Text2, { children: ghostPats.length ? `${ghostPats.length}` : "none" }));
|
|
1606
|
+
for (const line of wrapLines(ghostPats.join(" \xB7 "), Math.max(20, innerW - 18))) push(/* @__PURE__ */ jsx2(Text2, { wrap: "truncate", color: theme.dim, children: " " + line }));
|
|
1607
|
+
blank();
|
|
1608
|
+
section("GUARD", guard.data ? guard.data.up_to_date ? "ok" : "stale" : "?", "the PreToolUse hook enforcing all of the above");
|
|
1609
|
+
kv(
|
|
1610
|
+
"hooks",
|
|
1611
|
+
guard.data ? /* @__PURE__ */ jsx2(Text2, { color: guard.data.up_to_date ? theme.ok : theme.warn, children: `v${guard.data.installed ?? "?"}${guard.data.up_to_date ? " (latest)" : ` \u2192 v${guard.data.latest} available`} \xB7 ${guard.data.device_count} device${guard.data.device_count === 1 ? "" : "s"}` }) : /* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: "loading\u2026" })
|
|
1612
|
+
);
|
|
1613
|
+
kv("local eval", ring ? /* @__PURE__ */ jsx2(Text2, { color: theme.ok, children: `avg ${ring.avgMs}ms over ${ring.count} recent calls` }) : /* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: "no local ring in cwd" }));
|
|
1614
|
+
const bodyRows = Math.max(4, rows - 5);
|
|
1615
|
+
const maxLScroll = Math.max(0, L.length - bodyRows);
|
|
1616
|
+
const lOff = Math.min(layersScroll, maxLScroll);
|
|
1617
|
+
const win = L.slice(lOff, lOff + bodyRows);
|
|
1618
|
+
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", paddingX: 1, children: [
|
|
1619
|
+
titleBar,
|
|
1620
|
+
/* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
|
|
1621
|
+
/* @__PURE__ */ jsx2(Text2, { backgroundColor: BG, color: "white", bold: true, children: " LAYERS " }),
|
|
1622
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: " security layers, limits and patterns \xB7 insights window: last 7 days" }),
|
|
1623
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: " \u2190 back" })
|
|
1624
|
+
] }),
|
|
1625
|
+
/* @__PURE__ */ jsx2(PaneTitle, { label: "LAYERS", extra: `${insights.data ? "" : spin + " loading \xB7 "}${maxLScroll ? `\u25BC${maxLScroll - lOff} more \xB7 \u2191\u2193 scroll \xB7 ` : ""}l or \u2190 back`, width: innerW }),
|
|
1626
|
+
/* @__PURE__ */ jsx2(Box2, { flexDirection: "column", height: bodyRows, overflow: "hidden", children: win }),
|
|
1627
|
+
/* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
|
|
1628
|
+
/* @__PURE__ */ jsx2(Text2, { backgroundColor: BG, color: "white", bold: true, children: " LAYERS " }),
|
|
1629
|
+
/* @__PURE__ */ jsx2(Text2, { backgroundColor: "#0b1530", color: "white", children: " rate limit \xB7 dlp \xB7 ghost \xB7 guard " }),
|
|
1630
|
+
/* @__PURE__ */ jsx2(Text2, { backgroundColor: BG, color: "white", children: " \u2191\u2193 scroll \xB7 ? all keys \xB7 \u2190 back \xB7 esc menu " })
|
|
1631
|
+
] })
|
|
1632
|
+
] });
|
|
1633
|
+
}
|
|
1515
1634
|
if (mode === "detail" && detail) {
|
|
1516
1635
|
const d = detailEntries;
|
|
1517
1636
|
const allow = d.filter((e) => e.decision === "ALLOW").length;
|
|
@@ -1631,7 +1750,7 @@ function LivePanel({ active: active2 }) {
|
|
|
1631
1750
|
] }),
|
|
1632
1751
|
/* @__PURE__ */ jsxs2(Box2, { height: colH, children: [
|
|
1633
1752
|
/* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", width: colW, marginRight: 2, overflow: "hidden", children: [
|
|
1634
|
-
/* @__PURE__ */ jsx2(PaneTitle, { label: "LAYERS", width: colW }),
|
|
1753
|
+
/* @__PURE__ */ jsx2(PaneTitle, { label: "LAYERS", extra: "l = inspect", width: colW }),
|
|
1635
1754
|
/* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
|
|
1636
1755
|
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: "RATELIMIT ".padEnd(10) }),
|
|
1637
1756
|
/* @__PURE__ */ jsx2(Text2, { color: rl?.mode === "block" ? theme.ok : rl?.mode === "detect" ? theme.warn : theme.dim, children: (rl?.mode ?? "?").padEnd(7) }),
|
|
@@ -1664,7 +1783,8 @@ function LivePanel({ active: active2 }) {
|
|
|
1664
1783
|
" "
|
|
1665
1784
|
] }),
|
|
1666
1785
|
/* @__PURE__ */ jsx2(Text2, { color: st.color, children: st.label.padEnd(7) }),
|
|
1667
|
-
/* @__PURE__ */ jsx2(Text2, { color: theme.accentBright, children: truncate(r.isMe ?
|
|
1786
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.accentBright, children: truncate(r.agent, r.isMe ? 9 : 12).padEnd(r.isMe ? 10 : 13) }),
|
|
1787
|
+
r.isMe ? /* @__PURE__ */ jsx2(Text2, { color: theme.ok, children: "me " }) : null,
|
|
1668
1788
|
/* @__PURE__ */ jsxs2(Text2, { children: [
|
|
1669
1789
|
String(r.calls).padStart(4),
|
|
1670
1790
|
"c "
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solongate/proxy",
|
|
3
|
-
"version": "0.81.
|
|
3
|
+
"version": "0.81.45",
|
|
4
4
|
"description": "AI tool security proxy: protect any AI tool server with customizable policies, path/command constraints, rate limiting, and audit logging. No code changes required.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|