@solongate/proxy 0.67.0 → 0.69.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/dist/index.js +233 -123
- package/dist/tui/index.js +203 -93
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7019,13 +7019,13 @@ var init_hooks = __esm({
|
|
|
7019
7019
|
});
|
|
7020
7020
|
|
|
7021
7021
|
// src/tui/panels/Live.tsx
|
|
7022
|
-
import { Box as Box2, Text as Text2 } from "ink";
|
|
7023
|
-
import { closeSync, openSync, readSync, statSync } from "fs";
|
|
7022
|
+
import { Box as Box2, Text as Text2, useInput } from "ink";
|
|
7023
|
+
import { closeSync, mkdirSync as mkdirSync3, openSync, readSync, statSync, writeFileSync as writeFileSync3 } from "fs";
|
|
7024
7024
|
import { homedir as homedir3 } from "os";
|
|
7025
|
-
import { join as join5 } from "path";
|
|
7025
|
+
import { dirname, join as join5 } from "path";
|
|
7026
7026
|
import { useCallback as useCallback2, useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
|
|
7027
7027
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
7028
|
-
function tailLines(file, maxBytes =
|
|
7028
|
+
function tailLines(file, maxBytes = 131072) {
|
|
7029
7029
|
try {
|
|
7030
7030
|
const size = statSync(file).size;
|
|
7031
7031
|
const start = Math.max(0, size - maxBytes);
|
|
@@ -7040,6 +7040,9 @@ function tailLines(file, maxBytes = 65536) {
|
|
|
7040
7040
|
return [];
|
|
7041
7041
|
}
|
|
7042
7042
|
}
|
|
7043
|
+
function oscCopy(text) {
|
|
7044
|
+
process.stdout.write(`\x1B]52;c;${Buffer.from(text, "utf-8").toString("base64")}\x07`);
|
|
7045
|
+
}
|
|
7043
7046
|
function cloudItem(e) {
|
|
7044
7047
|
return {
|
|
7045
7048
|
id: "c:" + e.id,
|
|
@@ -7049,7 +7052,11 @@ function cloudItem(e) {
|
|
|
7049
7052
|
permission: (e.permission ?? "").slice(0, 4),
|
|
7050
7053
|
detail: (e.arguments_summary ? JSON.stringify(e.arguments_summary) : e.reason ?? "").replace(/\s+/g, " "),
|
|
7051
7054
|
dlp: !!e.dlp_matches?.length,
|
|
7052
|
-
source: "cloud"
|
|
7055
|
+
source: "cloud",
|
|
7056
|
+
session: e.session_id ?? void 0,
|
|
7057
|
+
agent: e.agent_name ?? void 0,
|
|
7058
|
+
evalMs: e.evaluation_time_ms ?? void 0,
|
|
7059
|
+
rule: e.matched_rule_id ?? void 0
|
|
7053
7060
|
};
|
|
7054
7061
|
}
|
|
7055
7062
|
function ColumnChart({ series, hot, height, width: width2, color, hotColor = theme.bad }) {
|
|
@@ -7068,7 +7075,7 @@ function ColumnChart({ series, hot, height, width: width2, color, hotColor = the
|
|
|
7068
7075
|
else if (frac >= (r - 0.5) / height) ch = "\u2584";
|
|
7069
7076
|
else if (r === 1) ch = "\u2581";
|
|
7070
7077
|
else ch = " ";
|
|
7071
|
-
const c2 = r === 1 && v === 0 ?
|
|
7078
|
+
const c2 = r === 1 && v === 0 ? DIM_FLOOR : hotPad?.[i] ? hotColor : color;
|
|
7072
7079
|
const last = segs[segs.length - 1];
|
|
7073
7080
|
if (last && last.color === c2) last.text += ch;
|
|
7074
7081
|
else segs.push({ text: ch, color: c2 });
|
|
@@ -7084,7 +7091,7 @@ function HBar({ label, value, max, width: width2, color }) {
|
|
|
7084
7091
|
return /* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
|
|
7085
7092
|
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: label.padEnd(10) }),
|
|
7086
7093
|
/* @__PURE__ */ jsx2(Text2, { color, children: "\u2588".repeat(Math.min(width2, filled)) }),
|
|
7087
|
-
/* @__PURE__ */ jsx2(Text2, { color:
|
|
7094
|
+
/* @__PURE__ */ jsx2(Text2, { color: DIM_FLOOR, children: "\u2591".repeat(Math.max(0, width2 - filled)) }),
|
|
7088
7095
|
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: " " + value })
|
|
7089
7096
|
] });
|
|
7090
7097
|
}
|
|
@@ -7109,6 +7116,9 @@ function LivePanel({ active: active2 }) {
|
|
|
7109
7116
|
const [localOn, setLocalOn] = useState2(null);
|
|
7110
7117
|
const [ring, setRing] = useState2(null);
|
|
7111
7118
|
const [log6, setLog] = useState2([]);
|
|
7119
|
+
const [filter, setFilter] = useState2("all");
|
|
7120
|
+
const [scroll, setScroll] = useState2(0);
|
|
7121
|
+
const [toast, setToast] = useState2(null);
|
|
7112
7122
|
const seenRef = useRef2(/* @__PURE__ */ new Set());
|
|
7113
7123
|
const lastLocalTs = useRef2(0);
|
|
7114
7124
|
const pausedUntil = useRef2(0);
|
|
@@ -7146,10 +7156,14 @@ function LivePanel({ active: active2 }) {
|
|
|
7146
7156
|
at,
|
|
7147
7157
|
tool: j.tool ?? "?",
|
|
7148
7158
|
decision: j.decision ?? "ALLOW",
|
|
7149
|
-
permission: "",
|
|
7159
|
+
permission: (j.permission ?? "").slice(0, 4),
|
|
7150
7160
|
detail: (j.arguments ? JSON.stringify(j.arguments) : j.reason ?? "").replace(/\s+/g, " "),
|
|
7151
7161
|
dlp: !!j.dlp,
|
|
7152
|
-
source: "local"
|
|
7162
|
+
source: "local",
|
|
7163
|
+
session: j.session_id,
|
|
7164
|
+
agent: j.agent_name,
|
|
7165
|
+
evalMs: j.evaluation_time_ms,
|
|
7166
|
+
rule: j.matched_rule_id
|
|
7153
7167
|
});
|
|
7154
7168
|
} catch {
|
|
7155
7169
|
}
|
|
@@ -7158,9 +7172,7 @@ function LivePanel({ active: active2 }) {
|
|
|
7158
7172
|
lastLocalTs.current = fresh[fresh.length - 1].at;
|
|
7159
7173
|
setLocalBuf((prev) => [...prev, ...fresh].slice(-400));
|
|
7160
7174
|
const denies = fresh.filter((f) => f.decision !== "ALLOW").length;
|
|
7161
|
-
if (
|
|
7162
|
-
pushLog(`local +${fresh.length} calls${denies ? ` \xB7 ${denies} DENIED` : ""}`, denies ? "bad" : "warn");
|
|
7163
|
-
}
|
|
7175
|
+
if (fresh.length < 10) pushLog(`local +${fresh.length} calls${denies ? ` \xB7 ${denies} DENIED` : ""}`, denies ? "bad" : "warn");
|
|
7164
7176
|
}
|
|
7165
7177
|
const ringLines = tailLines(RING, 8192).slice(-30);
|
|
7166
7178
|
if (ringLines.length) {
|
|
@@ -7197,9 +7209,7 @@ function LivePanel({ active: active2 }) {
|
|
|
7197
7209
|
const fresh = fd.entries.filter((e) => !seenRef.current.has(e.id));
|
|
7198
7210
|
const firstLoad = seenRef.current.size === 0 && fresh.length > 1;
|
|
7199
7211
|
for (const e of fresh) seenRef.current.add(e.id);
|
|
7200
|
-
if (fresh.length)
|
|
7201
|
-
setCloudBuf((prev) => [...prev, ...fresh.map(cloudItem).sort((a, b) => a.at - b.at)].slice(-400));
|
|
7202
|
-
}
|
|
7212
|
+
if (fresh.length) setCloudBuf((prev) => [...prev, ...fresh.map(cloudItem).sort((a, b) => a.at - b.at)].slice(-400));
|
|
7203
7213
|
const denies = fresh.filter((e) => e.decision !== "ALLOW").length;
|
|
7204
7214
|
if (firstLoad) pushLog(`cloud link up \xB7 api ${ms}ms \xB7 ${fresh.length} calls`);
|
|
7205
7215
|
else pushLog(`api ${ms}ms \xB7 +${fresh.length} cloud${denies ? ` \xB7 ${denies} DENIED` : ""}`, denies ? "bad" : fresh.length ? "warn" : "ok");
|
|
@@ -7239,16 +7249,20 @@ function LivePanel({ active: active2 }) {
|
|
|
7239
7249
|
}, [active2, pollFeed, pollMedium, pollSlow]);
|
|
7240
7250
|
const sessions = useLoader(() => api.agents.live({ limit: 30, includeDeactivated: true }));
|
|
7241
7251
|
const insights = useLoader(() => api.stats.securityInsights(7));
|
|
7252
|
+
const guard = useLoader(() => api.settings.getGuardStatus());
|
|
7242
7253
|
usePoll(() => {
|
|
7243
7254
|
if (!paused()) sessions.reload();
|
|
7244
7255
|
}, 1e4, active2);
|
|
7245
7256
|
usePoll(() => {
|
|
7246
7257
|
if (!paused()) insights.reload();
|
|
7247
7258
|
}, 3e4, active2);
|
|
7259
|
+
usePoll(() => {
|
|
7260
|
+
if (!paused()) guard.reload();
|
|
7261
|
+
}, 6e4, active2);
|
|
7248
7262
|
const [tick, setTick] = useState2(0);
|
|
7249
7263
|
useEffect2(() => {
|
|
7250
7264
|
if (!active2) return;
|
|
7251
|
-
const t = setInterval(() => setTick((n) => n + 1),
|
|
7265
|
+
const t = setInterval(() => setTick((n) => n + 1), 500);
|
|
7252
7266
|
return () => clearInterval(t);
|
|
7253
7267
|
}, [active2]);
|
|
7254
7268
|
const startRef = useRef2(Date.now());
|
|
@@ -7256,19 +7270,34 @@ function LivePanel({ active: active2 }) {
|
|
|
7256
7270
|
const rows = process.stdout.rows ?? 30;
|
|
7257
7271
|
const ins = insights.data ?? {};
|
|
7258
7272
|
const spin = SPIN[tick % SPIN.length];
|
|
7273
|
+
const nowMs = Date.now();
|
|
7274
|
+
const mergedAll = [...cloudBuf, ...localBuf].sort((a, b) => a.at - b.at);
|
|
7275
|
+
const filtered = filter === "all" ? mergedAll : mergedAll.filter((e) => e.source === filter);
|
|
7276
|
+
const visible = filtered.slice(-STREAM_KEEP);
|
|
7259
7277
|
const points = tsData?.timeseries ?? [];
|
|
7260
|
-
const
|
|
7261
|
-
const
|
|
7278
|
+
const minuteCounts = new Array(60).fill(0);
|
|
7279
|
+
const minuteHot = new Array(60).fill(false);
|
|
7280
|
+
for (const e of mergedAll) {
|
|
7281
|
+
const idx = 59 - Math.floor((nowMs - e.at) / 6e4);
|
|
7282
|
+
if (idx >= 0 && idx < 60) {
|
|
7283
|
+
minuteCounts[idx]++;
|
|
7284
|
+
if (e.decision !== "ALLOW") minuteHot[idx] = true;
|
|
7285
|
+
}
|
|
7286
|
+
}
|
|
7287
|
+
const localTraffic = localOn === true && minuteCounts.some((c2) => c2 > 0);
|
|
7288
|
+
const traffic = localTraffic ? minuteCounts : points.map((p) => p.total);
|
|
7289
|
+
const trafficHot = localTraffic ? minuteHot : points.map((p) => p.denied > 0);
|
|
7290
|
+
const trafficLabel = localTraffic ? "calls/min \xB7 60m \xB7 local+cloud" : "24h \xB7 cloud";
|
|
7262
7291
|
const rl = ins.layers?.rateLimit;
|
|
7263
7292
|
const dl = ins.layers?.dlp;
|
|
7264
|
-
const
|
|
7293
|
+
const gh = ins.layers?.ghost;
|
|
7294
|
+
const minuteNow = minuteCounts[59] ?? 0;
|
|
7265
7295
|
const dlpBars = (ins.dlpByPattern ?? []).slice(0, 2);
|
|
7266
7296
|
const maxDlpBar = dlpBars[0]?.count ?? 1;
|
|
7267
|
-
const
|
|
7268
|
-
const denials = merged.filter((e) => e.decision !== "ALLOW");
|
|
7297
|
+
const denials = mergedAll.filter((e) => e.decision !== "ALLOW");
|
|
7269
7298
|
const lastDeny = denials[denials.length - 1];
|
|
7270
7299
|
const toolCounts = /* @__PURE__ */ new Map();
|
|
7271
|
-
for (const e of
|
|
7300
|
+
for (const e of mergedAll) toolCounts.set(e.tool, (toolCounts.get(e.tool) ?? 0) + 1);
|
|
7272
7301
|
const topTools = [...toolCounts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 3);
|
|
7273
7302
|
const latNow = lat[lat.length - 1] ?? 0;
|
|
7274
7303
|
const sortedLat = [...lat].sort((a, b) => a - b);
|
|
@@ -7277,20 +7306,65 @@ function LivePanel({ active: active2 }) {
|
|
|
7277
7306
|
const backingOff = Date.now() < pausedUntil.current;
|
|
7278
7307
|
const sess = (sessions.data?.agents ?? []).slice().sort((a, b) => Date.parse(b.last_seen_at) - Date.parse(a.last_seen_at));
|
|
7279
7308
|
const sessCounts = sessions.data?.counts;
|
|
7309
|
+
const localSess = /* @__PURE__ */ new Map();
|
|
7310
|
+
for (const e of localBuf) {
|
|
7311
|
+
if (!e.session) continue;
|
|
7312
|
+
const cur = localSess.get(e.session) ?? { agent: e.agent ?? "local agent", calls: 0, denies: 0, lastAt: 0 };
|
|
7313
|
+
cur.calls++;
|
|
7314
|
+
if (e.decision !== "ALLOW") cur.denies++;
|
|
7315
|
+
cur.lastAt = Math.max(cur.lastAt, e.at);
|
|
7316
|
+
if (e.agent) cur.agent = e.agent;
|
|
7317
|
+
localSess.set(e.session, cur);
|
|
7318
|
+
}
|
|
7319
|
+
const localSessList = [...localSess.entries()].sort((a, b) => b[1].lastAt - a[1].lastAt);
|
|
7280
7320
|
const chartH = rows >= 36 ? 6 : 4;
|
|
7281
|
-
const colH = rows >= 32 ?
|
|
7282
|
-
const streamRows = Math.max(4, rows -
|
|
7283
|
-
const tail = merged.slice(-streamRows);
|
|
7321
|
+
const colH = rows >= 32 ? 7 : 5;
|
|
7322
|
+
const streamRows = Math.max(4, rows - 5 - (1 + chartH) - colH);
|
|
7284
7323
|
const innerW = cols - 2;
|
|
7285
7324
|
const leftW = Math.floor(innerW * 0.55);
|
|
7286
7325
|
const rightW = innerW - leftW - 2;
|
|
7287
7326
|
const colW = Math.max(20, Math.floor((innerW - 4) / 3));
|
|
7327
|
+
const maxScroll = Math.max(0, visible.length - streamRows);
|
|
7328
|
+
const clampedScroll = Math.min(scroll, maxScroll);
|
|
7329
|
+
const start = Math.max(0, visible.length - streamRows - clampedScroll);
|
|
7330
|
+
const windowed = visible.slice(start, start + streamRows);
|
|
7331
|
+
useInput(
|
|
7332
|
+
(input, key) => {
|
|
7333
|
+
if (input === "f") {
|
|
7334
|
+
setFilter((f) => FILTERS[(FILTERS.indexOf(f) + 1) % FILTERS.length]);
|
|
7335
|
+
setScroll(0);
|
|
7336
|
+
} else if (key.upArrow) setScroll((n) => Math.min(maxScroll, n + 1));
|
|
7337
|
+
else if (key.downArrow) setScroll((n) => Math.max(0, n - 1));
|
|
7338
|
+
else if (key.pageUp) setScroll((n) => Math.min(maxScroll, n + streamRows));
|
|
7339
|
+
else if (key.pageDown) setScroll((n) => Math.max(0, n - streamRows));
|
|
7340
|
+
else if (input === "c") {
|
|
7341
|
+
const dump = visible.map(
|
|
7342
|
+
(e) => `[${new Date(e.at).toISOString()}] ${e.source.toUpperCase().padEnd(5)} ${e.decision.padEnd(6)} ${e.tool.padEnd(16)} ${e.permission.padEnd(5)} ${e.evalMs != null ? String(e.evalMs).padStart(5) + "ms " : " "}${(e.agent ?? "-").padEnd(14)} ${e.session ? e.session.slice(0, 8) : "- "} ${e.detail}`
|
|
7343
|
+
).join("\n");
|
|
7344
|
+
try {
|
|
7345
|
+
mkdirSync3(dirname(DUMP), { recursive: true });
|
|
7346
|
+
writeFileSync3(DUMP, dump + "\n");
|
|
7347
|
+
} catch {
|
|
7348
|
+
}
|
|
7349
|
+
oscCopy(dump);
|
|
7350
|
+
setToast({ msg: `copied ${visible.length} lines \u2192 clipboard + ${DUMP}`, until: Date.now() + 4e3 });
|
|
7351
|
+
}
|
|
7352
|
+
},
|
|
7353
|
+
{ isActive: active2 }
|
|
7354
|
+
);
|
|
7288
7355
|
const sessionDot = (st) => st === "active" ? { ch: "\u25CF", color: theme.ok } : st === "idle" ? { ch: "\u25CC", color: theme.warn } : { ch: "\u25CB", color: theme.dim };
|
|
7356
|
+
if (s === null && localOn === null) {
|
|
7357
|
+
return /* @__PURE__ */ jsxs2(Text2, { color: theme.dim, children: [
|
|
7358
|
+
spin,
|
|
7359
|
+
" connecting\u2026"
|
|
7360
|
+
] });
|
|
7361
|
+
}
|
|
7289
7362
|
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", paddingX: 1, children: [
|
|
7290
7363
|
/* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
|
|
7291
7364
|
/* @__PURE__ */ jsx2(Text2, { backgroundColor: "#1432A0", color: "#AAC8FA", bold: true, children: " SOLONGATE LIVE " }),
|
|
7292
|
-
/* @__PURE__ */ jsx2(Text2, { backgroundColor: BG, color: "#82AAF0", children: ` ${spin} up ${fmtUp(
|
|
7293
|
-
backingOff ? /* @__PURE__ */ jsx2(Text2, { backgroundColor: "#3d2a12", color: "#ffb454", bold: true, children: " RATE LIMITED \xB7 backing off " }) : lastDeny ? /* @__PURE__ */ jsx2(Text2, { backgroundColor: "#3d1220", color: "#ff6b6b", bold: true, children: ` \u26A0 ${hhmmss(lastDeny.at)} ${lastDeny.tool} DENIED ` }) : /* @__PURE__ */ jsx2(Text2, { backgroundColor: BG, color: "#4f6db8", children: " \u2713 clean " })
|
|
7365
|
+
/* @__PURE__ */ jsx2(Text2, { backgroundColor: BG, color: "#82AAF0", children: ` ${spin} up ${fmtUp(nowMs - startRef.current)} \xB7 ${hhmmss(nowMs)} \xB7 api ${latNow}ms ` }),
|
|
7366
|
+
backingOff ? /* @__PURE__ */ jsx2(Text2, { backgroundColor: "#3d2a12", color: "#ffb454", bold: true, children: " RATE LIMITED \xB7 backing off " }) : lastDeny ? /* @__PURE__ */ jsx2(Text2, { backgroundColor: "#3d1220", color: "#ff6b6b", bold: true, children: ` \u26A0 ${hhmmss(lastDeny.at)} ${lastDeny.tool} DENIED ` }) : /* @__PURE__ */ jsx2(Text2, { backgroundColor: BG, color: "#4f6db8", children: " \u2713 clean " }),
|
|
7367
|
+
toast && nowMs < toast.until ? /* @__PURE__ */ jsx2(Text2, { backgroundColor: "#123d1f", color: "#7bd88f", bold: true, children: ` ${toast.msg} ` }) : null
|
|
7294
7368
|
] }),
|
|
7295
7369
|
/* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
|
|
7296
7370
|
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: "\u2502 calls " }),
|
|
@@ -7300,18 +7374,22 @@ function LivePanel({ active: active2 }) {
|
|
|
7300
7374
|
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: " \u2502 deny " }),
|
|
7301
7375
|
/* @__PURE__ */ jsx2(Text2, { color: theme.bad, bold: true, children: s ? s.denied : "\xB7\xB7" }),
|
|
7302
7376
|
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: " \u2502 local " }),
|
|
7303
|
-
localOn ? /* @__PURE__ */ jsx2(Text2, { color: theme.ok, children: "\u2713
|
|
7304
|
-
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: " \u2502
|
|
7377
|
+
localOn ? /* @__PURE__ */ jsx2(Text2, { color: theme.ok, children: "\u2713" }) : /* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: "off" }),
|
|
7378
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: " \u2502 rl " }),
|
|
7305
7379
|
/* @__PURE__ */ jsx2(Text2, { color: rl?.mode === "block" ? theme.ok : rl?.mode === "detect" ? theme.warn : theme.dim, children: rl?.mode ?? "?" }),
|
|
7306
7380
|
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: " \u2502 dlp " }),
|
|
7307
7381
|
/* @__PURE__ */ jsx2(Text2, { color: dl?.mode === "block" ? theme.ok : dl?.mode === "detect" ? theme.warn : theme.dim, children: dl?.mode ?? "?" }),
|
|
7308
|
-
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: " \u2502
|
|
7309
|
-
/* @__PURE__ */ jsx2(Text2, { color:
|
|
7382
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: " \u2502 ghost " }),
|
|
7383
|
+
/* @__PURE__ */ jsx2(Text2, { color: gh?.mode === "on" ? theme.ok : theme.dim, children: gh?.mode ?? "?" }),
|
|
7384
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: " \u2502 sess " }),
|
|
7385
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.accent, children: `${localSessList.length}loc ${sessCounts?.active ?? 0}\u25B2${sessCounts?.idle ?? 0}\u25CC` }),
|
|
7386
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: " \u2502 hooks " }),
|
|
7387
|
+
/* @__PURE__ */ jsx2(Text2, { color: guard.data?.up_to_date ? theme.ok : theme.warn, children: guard.data ? `v${guard.data.installed ?? "?"}${guard.data.up_to_date ? "" : "\u2192v" + guard.data.latest} ${guard.data.device_count}dev` : "\xB7" }),
|
|
7310
7388
|
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: " \u2502" })
|
|
7311
7389
|
] }),
|
|
7312
|
-
/* @__PURE__ */ jsxs2(Box2, { children: [
|
|
7390
|
+
/* @__PURE__ */ jsxs2(Box2, { height: 1 + chartH, children: [
|
|
7313
7391
|
/* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", width: leftW, marginRight: 2, children: [
|
|
7314
|
-
/* @__PURE__ */ jsx2(PaneTitle, { label: "TRAFFIC", extra:
|
|
7392
|
+
/* @__PURE__ */ jsx2(PaneTitle, { label: "TRAFFIC", extra: `${trafficLabel} \xB7 peak ${Math.max(0, ...traffic)} \xB7 red = denials`, width: leftW }),
|
|
7315
7393
|
/* @__PURE__ */ jsx2(ColumnChart, { series: traffic, hot: trafficHot, height: chartH, width: leftW, color: theme.accent })
|
|
7316
7394
|
] }),
|
|
7317
7395
|
/* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", width: rightW, children: [
|
|
@@ -7319,45 +7397,61 @@ function LivePanel({ active: active2 }) {
|
|
|
7319
7397
|
/* @__PURE__ */ jsx2(ColumnChart, { series: lat, hot: lat.map((v) => v > latHotAt), height: chartH, width: rightW, color: "#82AAF0", hotColor: "#ffb454" })
|
|
7320
7398
|
] })
|
|
7321
7399
|
] }),
|
|
7322
|
-
/* @__PURE__ */ jsxs2(Box2, { children: [
|
|
7323
|
-
/* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", width: colW, marginRight: 2, children: [
|
|
7400
|
+
/* @__PURE__ */ jsxs2(Box2, { height: colH, children: [
|
|
7401
|
+
/* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", width: colW, marginRight: 2, overflow: "hidden", children: [
|
|
7324
7402
|
/* @__PURE__ */ jsx2(PaneTitle, { label: "LAYERS", width: colW }),
|
|
7325
7403
|
/* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
|
|
7326
7404
|
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: "RATELIMIT ".padEnd(10) }),
|
|
7327
7405
|
/* @__PURE__ */ jsx2(Text2, { color: rl?.mode === "block" ? theme.ok : rl?.mode === "detect" ? theme.warn : theme.dim, children: (rl?.mode ?? "?").padEnd(7) }),
|
|
7328
|
-
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: rl?.perMinute ? `${minuteNow}/${rl.perMinute}
|
|
7406
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: rl?.perMinute ? `${minuteNow}/${rl.perMinute}m ${rl.perHour || "\u2014"}h ${rl.perDay || "\u2014"}d` : "no limits set" })
|
|
7329
7407
|
] }),
|
|
7330
|
-
rl?.perMinute ? /* @__PURE__ */ jsx2(HBar, { label: "load", value: minuteNow, max: rl.perMinute, width: Math.max(6, colW - 16), color: minuteNow > rl.perMinute ? theme.bad : theme.accent }) : null,
|
|
7408
|
+
rl?.perMinute ? /* @__PURE__ */ jsx2(HBar, { label: "load/min", value: minuteNow, max: rl.perMinute, width: Math.max(6, colW - 16), color: minuteNow > rl.perMinute ? theme.bad : theme.accent }) : null,
|
|
7331
7409
|
/* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
|
|
7332
7410
|
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: "DLP".padEnd(10) }),
|
|
7333
7411
|
/* @__PURE__ */ jsx2(Text2, { color: dl?.mode === "block" ? theme.ok : dl?.mode === "detect" ? theme.warn : theme.dim, children: (dl?.mode ?? "?").padEnd(7) }),
|
|
7334
|
-
/* @__PURE__ */
|
|
7335
|
-
(dl?.patterns ?? []).length,
|
|
7336
|
-
" patterns armed"
|
|
7337
|
-
] })
|
|
7412
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: `${(dl?.patterns ?? []).length} builtin \xB7 ${(dl?.custom ?? []).length} custom` })
|
|
7338
7413
|
] }),
|
|
7339
|
-
dlpBars.length ? dlpBars.map((d) => /* @__PURE__ */ jsx2(HBar, { label: truncate2(d.pattern, 10), value: d.count, max: maxDlpBar, width: Math.max(6, colW - 16), color: theme.bad }, d.pattern)) : /* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: "hits
|
|
7340
|
-
|
|
7414
|
+
dlpBars.length ? dlpBars.map((d) => /* @__PURE__ */ jsx2(HBar, { label: truncate2(d.pattern, 10), value: d.count, max: maxDlpBar, width: Math.max(6, colW - 16), color: theme.bad }, d.pattern)) : /* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: " no dlp hits in last 7 days" }),
|
|
7415
|
+
/* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
|
|
7341
7416
|
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: "GUARD".padEnd(10) }),
|
|
7342
|
-
/* @__PURE__ */
|
|
7343
|
-
|
|
7344
|
-
|
|
7417
|
+
ring ? /* @__PURE__ */ jsxs2(Text2, { color: theme.ok, children: [
|
|
7418
|
+
"local \u2713 ",
|
|
7419
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: `eval avg ${ring.avgMs}ms` })
|
|
7420
|
+
] }) : /* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: "no local ring in cwd" })
|
|
7421
|
+
] })
|
|
7345
7422
|
] }),
|
|
7346
|
-
/* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", width: colW, marginRight: 2, children: [
|
|
7347
|
-
/* @__PURE__ */ jsx2(PaneTitle, { label: "SESSIONS", extra:
|
|
7348
|
-
|
|
7349
|
-
|
|
7350
|
-
|
|
7351
|
-
|
|
7352
|
-
|
|
7353
|
-
|
|
7354
|
-
|
|
7423
|
+
/* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", width: colW, marginRight: 2, overflow: "hidden", children: [
|
|
7424
|
+
/* @__PURE__ */ jsx2(PaneTitle, { label: "SESSIONS", extra: `${localSessList.length} local \xB7 ${sessCounts?.active ?? 0} cloud`, width: colW }),
|
|
7425
|
+
localSessList.length === 0 && sess.length === 0 ? /* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: "scanning\u2026" }) : null,
|
|
7426
|
+
localSessList.slice(0, Math.max(1, colH - 2)).map(([id, v]) => {
|
|
7427
|
+
const freshDot = nowMs - v.lastAt < 9e4;
|
|
7428
|
+
const isMe = ring?.session === id;
|
|
7429
|
+
return /* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
|
|
7430
|
+
/* @__PURE__ */ jsxs2(Text2, { color: freshDot ? theme.ok : theme.dim, children: [
|
|
7431
|
+
freshDot ? "\u25CF" : "\u25CB",
|
|
7432
|
+
" "
|
|
7433
|
+
] }),
|
|
7434
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.ok, children: "LOC " }),
|
|
7435
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.accentBright, bold: isMe, children: truncate2(isMe ? "this machine" : v.agent, 12).padEnd(13) }),
|
|
7436
|
+
/* @__PURE__ */ jsxs2(Text2, { children: [
|
|
7437
|
+
String(v.calls).padStart(4),
|
|
7438
|
+
"c "
|
|
7439
|
+
] }),
|
|
7440
|
+
/* @__PURE__ */ jsxs2(Text2, { color: v.denies ? theme.bad : theme.dim, children: [
|
|
7441
|
+
String(v.denies).padStart(3),
|
|
7442
|
+
"d "
|
|
7443
|
+
] }),
|
|
7444
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: ago(v.lastAt) })
|
|
7445
|
+
] }, id);
|
|
7446
|
+
}),
|
|
7447
|
+
sess.slice(0, Math.max(0, colH - 1 - Math.min(localSessList.length, Math.max(1, colH - 2)))).map((a) => {
|
|
7355
7448
|
const dot = sessionDot(a.status);
|
|
7356
7449
|
return /* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
|
|
7357
7450
|
/* @__PURE__ */ jsxs2(Text2, { color: dot.color, children: [
|
|
7358
7451
|
dot.ch,
|
|
7359
7452
|
" "
|
|
7360
7453
|
] }),
|
|
7454
|
+
/* @__PURE__ */ jsx2(Text2, { color: "#4f6db8", children: "CLD " }),
|
|
7361
7455
|
/* @__PURE__ */ jsx2(Text2, { color: theme.accent, children: truncate2(a.agent_name ?? a.session_id, 12).padEnd(13) }),
|
|
7362
7456
|
/* @__PURE__ */ jsxs2(Text2, { children: [
|
|
7363
7457
|
String(a.total_calls).padStart(4),
|
|
@@ -7367,12 +7461,12 @@ function LivePanel({ active: active2 }) {
|
|
|
7367
7461
|
String(a.denied_calls).padStart(3),
|
|
7368
7462
|
"d "
|
|
7369
7463
|
] }),
|
|
7370
|
-
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: ago(a.last_seen_at) })
|
|
7464
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: `t${a.trust_score} ` + ago(a.last_seen_at) })
|
|
7371
7465
|
] }, a.session_id);
|
|
7372
7466
|
})
|
|
7373
7467
|
] }),
|
|
7374
|
-
/* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", width: colW, children: [
|
|
7375
|
-
/* @__PURE__ */ jsx2(PaneTitle, { label: "EVENT LOG", extra: "
|
|
7468
|
+
/* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", width: colW, overflow: "hidden", children: [
|
|
7469
|
+
/* @__PURE__ */ jsx2(PaneTitle, { label: "EVENT LOG", extra: "system heartbeat", width: colW }),
|
|
7376
7470
|
log6.slice(-(colH - 1)).map((l, i) => /* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
|
|
7377
7471
|
/* @__PURE__ */ jsxs2(Text2, { color: theme.dim, children: [
|
|
7378
7472
|
hhmmss(l.ts),
|
|
@@ -7383,37 +7477,49 @@ function LivePanel({ active: active2 }) {
|
|
|
7383
7477
|
] }, l.ts + ":" + i))
|
|
7384
7478
|
] })
|
|
7385
7479
|
] }),
|
|
7386
|
-
/* @__PURE__ */ jsx2(
|
|
7387
|
-
|
|
7388
|
-
|
|
7389
|
-
|
|
7390
|
-
|
|
7391
|
-
|
|
7392
|
-
|
|
7393
|
-
|
|
7394
|
-
|
|
7395
|
-
|
|
7396
|
-
|
|
7397
|
-
"
|
|
7398
|
-
|
|
7399
|
-
|
|
7400
|
-
|
|
7401
|
-
|
|
7402
|
-
|
|
7403
|
-
/* @__PURE__ */
|
|
7404
|
-
|
|
7405
|
-
|
|
7406
|
-
|
|
7407
|
-
|
|
7408
|
-
|
|
7480
|
+
/* @__PURE__ */ jsx2(
|
|
7481
|
+
PaneTitle,
|
|
7482
|
+
{
|
|
7483
|
+
label: "TOOL STREAM",
|
|
7484
|
+
extra: `last ${STREAM_KEEP} \xB7 filter ${filter}${clampedScroll > 0 ? ` \xB7 \u25B2${clampedScroll} scrolled` : " \xB7 following"} \xB7 f filter \xB7 \u2191\u2193 scroll \xB7 c copy`,
|
|
7485
|
+
width: innerW
|
|
7486
|
+
}
|
|
7487
|
+
),
|
|
7488
|
+
/* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", height: streamRows, overflow: "hidden", children: [
|
|
7489
|
+
localOn === false ? /* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
|
|
7490
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.warn, children: "local logs off" }),
|
|
7491
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: " \u2014 enable: dashboard \u2192 Settings \u2192 Local logs \xB7 hooks write ~/.solongate/local-logs \xB7 view: `solongate logs-server`" })
|
|
7492
|
+
] }) : null,
|
|
7493
|
+
windowed.length === 0 ? /* @__PURE__ */ jsxs2(Text2, { color: theme.dim, children: [
|
|
7494
|
+
spin,
|
|
7495
|
+
" awaiting traffic\u2026"
|
|
7496
|
+
] }) : null,
|
|
7497
|
+
windowed.map((e) => /* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
|
|
7498
|
+
/* @__PURE__ */ jsxs2(Text2, { color: theme.dim, children: [
|
|
7499
|
+
"[",
|
|
7500
|
+
hhmmss(e.at),
|
|
7501
|
+
" "
|
|
7502
|
+
] }),
|
|
7503
|
+
/* @__PURE__ */ jsx2(Text2, { color: e.source === "local" ? theme.ok : "#4f6db8", children: e.source === "local" ? "LOC" : "CLD" }),
|
|
7504
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: "] " }),
|
|
7505
|
+
/* @__PURE__ */ jsx2(Text2, { color: decisionColor(e.decision), bold: e.decision !== "ALLOW", children: e.decision.padEnd(6) }),
|
|
7506
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.accent, children: truncate2(e.tool, 12).padEnd(13) }),
|
|
7507
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: e.permission.padEnd(5) }),
|
|
7508
|
+
/* @__PURE__ */ jsx2(Text2, { color: e.evalMs != null && e.evalMs > 500 ? theme.warn : theme.dim, children: (e.evalMs != null ? `${e.evalMs}ms` : "\u2014").padEnd(7) }),
|
|
7509
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: truncate2(e.agent ?? "-", 11).padEnd(12) }),
|
|
7510
|
+
e.dlp ? /* @__PURE__ */ jsx2(Text2, { color: theme.bad, children: "DLP! " }) : null,
|
|
7511
|
+
e.rule && e.decision !== "ALLOW" ? /* @__PURE__ */ jsx2(Text2, { color: theme.bad, children: truncate2(e.rule, 14) + " " }) : null,
|
|
7512
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: e.detail })
|
|
7513
|
+
] }, e.id))
|
|
7514
|
+
] }),
|
|
7409
7515
|
/* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
|
|
7410
7516
|
/* @__PURE__ */ jsx2(Text2, { backgroundColor: BG, color: "#82AAF0", bold: true, children: " LIVE " }),
|
|
7411
|
-
/* @__PURE__ */ jsx2(Text2, { backgroundColor: "#0b1530", color: "#4f6db8", children: ` local ${localOn ? "on" : "off"} \xB7 top ${topTools.map(([t, c2]) => `${t}\xD7${c2}`).join(" ") || "\u2014"}
|
|
7412
|
-
/* @__PURE__ */ jsx2(Text2, { backgroundColor: BG, color: "#82AAF0", children: " esc menu \xB7 q quit " })
|
|
7517
|
+
/* @__PURE__ */ jsx2(Text2, { backgroundColor: "#0b1530", color: "#4f6db8", children: ` local ${localOn ? "on" : "off"} \xB7 ${localBuf.length} loc/${cloudBuf.length} cld buffered \xB7 top ${topTools.map(([t, c2]) => `${t}\xD7${c2}`).join(" ") || "\u2014"} ` }),
|
|
7518
|
+
/* @__PURE__ */ jsx2(Text2, { backgroundColor: BG, color: "#82AAF0", children: " f filter \xB7 \u2191\u2193 scroll \xB7 c copy \xB7 esc menu \xB7 q quit " })
|
|
7413
7519
|
] })
|
|
7414
7520
|
] });
|
|
7415
7521
|
}
|
|
7416
|
-
var SPIN, BG, LOCAL_LOG, RING, hhmmss, fmtUp;
|
|
7522
|
+
var SPIN, BG, DIM_FLOOR, LOCAL_LOG, RING, DUMP, STREAM_KEEP, hhmmss, fmtUp, FILTERS;
|
|
7417
7523
|
var init_Live = __esm({
|
|
7418
7524
|
"src/tui/panels/Live.tsx"() {
|
|
7419
7525
|
"use strict";
|
|
@@ -7422,8 +7528,11 @@ var init_Live = __esm({
|
|
|
7422
7528
|
init_theme();
|
|
7423
7529
|
SPIN = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
7424
7530
|
BG = "#12234f";
|
|
7531
|
+
DIM_FLOOR = "#233457";
|
|
7425
7532
|
LOCAL_LOG = join5(homedir3(), ".solongate", "local-logs", "solongate-audit.jsonl");
|
|
7426
7533
|
RING = join5(process.cwd(), ".solongate", ".eval-ring.jsonl");
|
|
7534
|
+
DUMP = join5(homedir3(), ".solongate", "live-stream.log");
|
|
7535
|
+
STREAM_KEEP = 100;
|
|
7427
7536
|
hhmmss = (ts) => {
|
|
7428
7537
|
const d = new Date(ts);
|
|
7429
7538
|
return Number.isNaN(d.getTime()) ? "--:--:--" : d.toTimeString().slice(0, 8);
|
|
@@ -7433,11 +7542,12 @@ var init_Live = __esm({
|
|
|
7433
7542
|
const p = (n) => String(n).padStart(2, "0");
|
|
7434
7543
|
return `${p(Math.floor(s / 3600))}:${p(Math.floor(s % 3600 / 60))}:${p(s % 60)}`;
|
|
7435
7544
|
};
|
|
7545
|
+
FILTERS = ["all", "local", "cloud"];
|
|
7436
7546
|
}
|
|
7437
7547
|
});
|
|
7438
7548
|
|
|
7439
7549
|
// src/tui/panels/Policies.tsx
|
|
7440
|
-
import { Box as Box3, Text as Text3, useInput } from "ink";
|
|
7550
|
+
import { Box as Box3, Text as Text3, useInput as useInput2 } from "ink";
|
|
7441
7551
|
import TextInput from "ink-text-input";
|
|
7442
7552
|
import { useEffect as useEffect3, useState as useState3 } from "react";
|
|
7443
7553
|
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
@@ -7507,7 +7617,7 @@ function PoliciesPanel({ focused }) {
|
|
|
7507
7617
|
setDirty(false);
|
|
7508
7618
|
setStatus("discarded");
|
|
7509
7619
|
};
|
|
7510
|
-
|
|
7620
|
+
useInput2(
|
|
7511
7621
|
(input, key) => {
|
|
7512
7622
|
if (view === "list") {
|
|
7513
7623
|
if (key.upArrow) setPi((n) => Math.max(0, n - 1));
|
|
@@ -7682,7 +7792,7 @@ var init_Policies = __esm({
|
|
|
7682
7792
|
});
|
|
7683
7793
|
|
|
7684
7794
|
// src/tui/panels/RateLimit.tsx
|
|
7685
|
-
import { Box as Box4, Text as Text4, useInput as
|
|
7795
|
+
import { Box as Box4, Text as Text4, useInput as useInput3 } from "ink";
|
|
7686
7796
|
import { useEffect as useEffect4, useState as useState4 } from "react";
|
|
7687
7797
|
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
7688
7798
|
function ColoredSpark({ values, limit, width: width2 = 60 }) {
|
|
@@ -7730,7 +7840,7 @@ function RateLimitPanel({ focused }) {
|
|
|
7730
7840
|
setStatus("\u2717 " + (e instanceof Error ? e.message : String(e)));
|
|
7731
7841
|
}
|
|
7732
7842
|
};
|
|
7733
|
-
|
|
7843
|
+
useInput3(
|
|
7734
7844
|
(input, key) => {
|
|
7735
7845
|
const step = key.shift ? 10 : 1;
|
|
7736
7846
|
if (key.upArrow) setFi((n) => (n - 1 + FIELDS2.length) % FIELDS2.length);
|
|
@@ -7822,7 +7932,7 @@ var init_RateLimit = __esm({
|
|
|
7822
7932
|
});
|
|
7823
7933
|
|
|
7824
7934
|
// src/tui/panels/Dlp.tsx
|
|
7825
|
-
import { Box as Box5, Text as Text5, useInput as
|
|
7935
|
+
import { Box as Box5, Text as Text5, useInput as useInput4 } from "ink";
|
|
7826
7936
|
import TextInput2 from "ink-text-input";
|
|
7827
7937
|
import { useEffect as useEffect5, useState as useState5 } from "react";
|
|
7828
7938
|
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
@@ -7866,7 +7976,7 @@ function DlpPanel({ focused }) {
|
|
|
7866
7976
|
};
|
|
7867
7977
|
const customCount = dlp?.custom.length ?? 0;
|
|
7868
7978
|
const total = available.length + customCount;
|
|
7869
|
-
|
|
7979
|
+
useInput4(
|
|
7870
7980
|
(input, key) => {
|
|
7871
7981
|
if (!dlp) return;
|
|
7872
7982
|
if (key.upArrow) setSel((n) => Math.max(0, n - 1));
|
|
@@ -8048,7 +8158,7 @@ var init_Stats = __esm({
|
|
|
8048
8158
|
});
|
|
8049
8159
|
|
|
8050
8160
|
// src/tui/panels/Audit.tsx
|
|
8051
|
-
import { Box as Box7, Text as Text7, useInput as
|
|
8161
|
+
import { Box as Box7, Text as Text7, useInput as useInput5 } from "ink";
|
|
8052
8162
|
import TextInput3 from "ink-text-input";
|
|
8053
8163
|
import { useState as useState6 } from "react";
|
|
8054
8164
|
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
@@ -8077,7 +8187,7 @@ function AuditPanel({ active: active2, focused }) {
|
|
|
8077
8187
|
() => view === "detail" && current?.session_id ? api.audit.list({ session_id: current.session_id, limit: 40 }) : Promise.resolve(null),
|
|
8078
8188
|
[view, current?.session_id]
|
|
8079
8189
|
);
|
|
8080
|
-
|
|
8190
|
+
useInput5(
|
|
8081
8191
|
(input, key) => {
|
|
8082
8192
|
if (view === "detail") {
|
|
8083
8193
|
if (key.leftArrow || key.escape) setView("list");
|
|
@@ -8227,7 +8337,7 @@ var init_Audit = __esm({
|
|
|
8227
8337
|
});
|
|
8228
8338
|
|
|
8229
8339
|
// src/tui/App.tsx
|
|
8230
|
-
import { Box as Box8, Text as Text8, useApp, useInput as
|
|
8340
|
+
import { Box as Box8, Text as Text8, useApp, useInput as useInput6 } from "ink";
|
|
8231
8341
|
import { useState as useState7 } from "react";
|
|
8232
8342
|
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
8233
8343
|
function LiveHint() {
|
|
@@ -8259,7 +8369,7 @@ function App() {
|
|
|
8259
8369
|
const { exit } = useApp();
|
|
8260
8370
|
const [section, setSection] = useState7(0);
|
|
8261
8371
|
const [focus, setFocus] = useState7("nav");
|
|
8262
|
-
|
|
8372
|
+
useInput6((input, key) => {
|
|
8263
8373
|
if (focus === "nav") {
|
|
8264
8374
|
if (key.upArrow) setSection((n) => (n - 1 + SECTIONS.length) % SECTIONS.length);
|
|
8265
8375
|
else if (key.downArrow) setSection((n) => (n + 1) % SECTIONS.length);
|
|
@@ -9094,8 +9204,8 @@ __export(global_install_exports, {
|
|
|
9094
9204
|
runGlobalRestore: () => runGlobalRestore,
|
|
9095
9205
|
unlockProtected: () => unlockProtected
|
|
9096
9206
|
});
|
|
9097
|
-
import { readFileSync as readFileSync6, writeFileSync as
|
|
9098
|
-
import { resolve as resolve4, join as join6, dirname } from "path";
|
|
9207
|
+
import { readFileSync as readFileSync6, writeFileSync as writeFileSync4, existsSync as existsSync4, mkdirSync as mkdirSync4 } from "fs";
|
|
9208
|
+
import { resolve as resolve4, join as join6, dirname as dirname2 } from "path";
|
|
9099
9209
|
import { homedir as homedir4 } from "os";
|
|
9100
9210
|
import { fileURLToPath } from "url";
|
|
9101
9211
|
import { createInterface } from "readline";
|
|
@@ -9207,13 +9317,13 @@ function runGlobalRestore() {
|
|
|
9207
9317
|
unlockProtected();
|
|
9208
9318
|
removeClaudeShim();
|
|
9209
9319
|
if (existsSync4(p.backupPath)) {
|
|
9210
|
-
|
|
9320
|
+
writeFileSync4(p.settingsPath, readFileSync6(p.backupPath, "utf-8"));
|
|
9211
9321
|
console.log(` Restored ${p.settingsPath} from backup.`);
|
|
9212
9322
|
} else if (existsSync4(p.settingsPath)) {
|
|
9213
9323
|
try {
|
|
9214
9324
|
const s = JSON.parse(readFileSync6(p.settingsPath, "utf-8"));
|
|
9215
9325
|
delete s.hooks;
|
|
9216
|
-
|
|
9326
|
+
writeFileSync4(p.settingsPath, JSON.stringify(s, null, 2) + "\n");
|
|
9217
9327
|
console.log(` Removed SolonGate hooks from ${p.settingsPath}.`);
|
|
9218
9328
|
} catch {
|
|
9219
9329
|
}
|
|
@@ -9257,8 +9367,8 @@ function writeShimBlock(file, block) {
|
|
|
9257
9367
|
if (content.length && !content.endsWith("\n")) content += "\n";
|
|
9258
9368
|
content += block + "\n";
|
|
9259
9369
|
}
|
|
9260
|
-
|
|
9261
|
-
|
|
9370
|
+
mkdirSync4(dirname2(file), { recursive: true });
|
|
9371
|
+
writeFileSync4(file, content);
|
|
9262
9372
|
}
|
|
9263
9373
|
function installClaudeShim(shieldPath) {
|
|
9264
9374
|
const real = resolveRealClaude();
|
|
@@ -9315,22 +9425,22 @@ async function runGlobalInstall(opts = {}) {
|
|
|
9315
9425
|
process.exit(1);
|
|
9316
9426
|
}
|
|
9317
9427
|
const apiUrl = opts.apiUrl || process.env["SOLONGATE_API_URL"] || "https://api.solongate.com";
|
|
9318
|
-
|
|
9319
|
-
|
|
9428
|
+
mkdirSync4(p.hooksDir, { recursive: true });
|
|
9429
|
+
mkdirSync4(p.claudeDir, { recursive: true });
|
|
9320
9430
|
unlockProtected();
|
|
9321
|
-
|
|
9322
|
-
|
|
9323
|
-
|
|
9324
|
-
|
|
9431
|
+
writeFileSync4(join6(p.hooksDir, "guard.mjs"), readGuard());
|
|
9432
|
+
writeFileSync4(join6(p.hooksDir, "audit.mjs"), readHook("audit.mjs"));
|
|
9433
|
+
writeFileSync4(join6(p.hooksDir, "stop.mjs"), readHook("stop.mjs"));
|
|
9434
|
+
writeFileSync4(join6(p.hooksDir, "shield.mjs"), readHook("shield.mjs"));
|
|
9325
9435
|
console.log(` Installed hooks \u2192 ${p.hooksDir}`);
|
|
9326
9436
|
removeClaudeShim();
|
|
9327
|
-
|
|
9437
|
+
writeFileSync4(p.configPath, JSON.stringify({ apiKey, apiUrl }, null, 2) + "\n");
|
|
9328
9438
|
console.log(` Wrote ${p.configPath}`);
|
|
9329
9439
|
let existing = {};
|
|
9330
9440
|
if (existsSync4(p.settingsPath)) {
|
|
9331
9441
|
const raw = readFileSync6(p.settingsPath, "utf-8");
|
|
9332
9442
|
if (!existsSync4(p.backupPath)) {
|
|
9333
|
-
|
|
9443
|
+
writeFileSync4(p.backupPath, raw);
|
|
9334
9444
|
console.log(` Backed up existing settings \u2192 ${p.backupPath}`);
|
|
9335
9445
|
}
|
|
9336
9446
|
try {
|
|
@@ -9351,7 +9461,7 @@ async function runGlobalInstall(opts = {}) {
|
|
|
9351
9461
|
Stop: [{ matcher: "", hooks: [{ type: "command", command: `"${nodeBin}" "${stopAbs}" claude-code "Claude Code"` }] }]
|
|
9352
9462
|
}
|
|
9353
9463
|
};
|
|
9354
|
-
|
|
9464
|
+
writeFileSync4(p.settingsPath, JSON.stringify(merged, null, 2) + "\n");
|
|
9355
9465
|
console.log(` Registered global hooks \u2192 ${p.settingsPath}`);
|
|
9356
9466
|
if (process.env["SOLONGATE_OS_LOCK"] === "1") {
|
|
9357
9467
|
lockProtected();
|
|
@@ -9365,7 +9475,7 @@ var __dirname, HOOKS_DIR, SHIM_BEGIN, SHIM_END;
|
|
|
9365
9475
|
var init_global_install = __esm({
|
|
9366
9476
|
"src/global-install.ts"() {
|
|
9367
9477
|
"use strict";
|
|
9368
|
-
__dirname =
|
|
9478
|
+
__dirname = dirname2(fileURLToPath(import.meta.url));
|
|
9369
9479
|
HOOKS_DIR = resolve4(__dirname, "..", "hooks");
|
|
9370
9480
|
SHIM_BEGIN = "# >>> SolonGate shield (auto secret redaction) >>>";
|
|
9371
9481
|
SHIM_END = "# <<< SolonGate shield <<<";
|
|
@@ -10015,7 +10125,7 @@ var init_logs_server = __esm({
|
|
|
10015
10125
|
|
|
10016
10126
|
// src/inject.ts
|
|
10017
10127
|
var inject_exports = {};
|
|
10018
|
-
import { readFileSync as readFileSync9, writeFileSync as
|
|
10128
|
+
import { readFileSync as readFileSync9, writeFileSync as writeFileSync5, existsSync as existsSync6, copyFileSync } from "fs";
|
|
10019
10129
|
import { resolve as resolve7 } from "path";
|
|
10020
10130
|
import { execSync } from "child_process";
|
|
10021
10131
|
function parseInjectArgs(argv) {
|
|
@@ -10323,7 +10433,7 @@ async function main2() {
|
|
|
10323
10433
|
log3("");
|
|
10324
10434
|
log3(` Backup: ${backupPath}`);
|
|
10325
10435
|
}
|
|
10326
|
-
|
|
10436
|
+
writeFileSync5(entryFile, result.modified);
|
|
10327
10437
|
log3("");
|
|
10328
10438
|
log3(" \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510");
|
|
10329
10439
|
log3(" \u2502 SolonGate SDK injected successfully! \u2502");
|
|
@@ -10352,7 +10462,7 @@ var init_inject = __esm({
|
|
|
10352
10462
|
|
|
10353
10463
|
// src/create.ts
|
|
10354
10464
|
var create_exports = {};
|
|
10355
|
-
import { mkdirSync as
|
|
10465
|
+
import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync6, existsSync as existsSync7 } from "fs";
|
|
10356
10466
|
import { resolve as resolve8, join as join8 } from "path";
|
|
10357
10467
|
import { execSync as execSync2 } from "child_process";
|
|
10358
10468
|
function withSpinner(message, fn) {
|
|
@@ -10432,7 +10542,7 @@ EXAMPLES
|
|
|
10432
10542
|
`);
|
|
10433
10543
|
}
|
|
10434
10544
|
function createProject(dir, name, _policy) {
|
|
10435
|
-
|
|
10545
|
+
writeFileSync6(
|
|
10436
10546
|
join8(dir, "package.json"),
|
|
10437
10547
|
JSON.stringify(
|
|
10438
10548
|
{
|
|
@@ -10462,7 +10572,7 @@ function createProject(dir, name, _policy) {
|
|
|
10462
10572
|
2
|
|
10463
10573
|
) + "\n"
|
|
10464
10574
|
);
|
|
10465
|
-
|
|
10575
|
+
writeFileSync6(
|
|
10466
10576
|
join8(dir, "tsconfig.json"),
|
|
10467
10577
|
JSON.stringify(
|
|
10468
10578
|
{
|
|
@@ -10483,8 +10593,8 @@ function createProject(dir, name, _policy) {
|
|
|
10483
10593
|
2
|
|
10484
10594
|
) + "\n"
|
|
10485
10595
|
);
|
|
10486
|
-
|
|
10487
|
-
|
|
10596
|
+
mkdirSync5(join8(dir, "src"), { recursive: true });
|
|
10597
|
+
writeFileSync6(
|
|
10488
10598
|
join8(dir, "src", "index.ts"),
|
|
10489
10599
|
`#!/usr/bin/env node
|
|
10490
10600
|
|
|
@@ -10526,7 +10636,7 @@ console.log('');
|
|
|
10526
10636
|
console.log('Press Ctrl+C to stop.');
|
|
10527
10637
|
`
|
|
10528
10638
|
);
|
|
10529
|
-
|
|
10639
|
+
writeFileSync6(
|
|
10530
10640
|
join8(dir, ".mcp.json"),
|
|
10531
10641
|
JSON.stringify(
|
|
10532
10642
|
{
|
|
@@ -10544,12 +10654,12 @@ console.log('Press Ctrl+C to stop.');
|
|
|
10544
10654
|
2
|
|
10545
10655
|
) + "\n"
|
|
10546
10656
|
);
|
|
10547
|
-
|
|
10657
|
+
writeFileSync6(
|
|
10548
10658
|
join8(dir, ".env"),
|
|
10549
10659
|
`SOLONGATE_API_KEY=sg_live_YOUR_KEY_HERE
|
|
10550
10660
|
`
|
|
10551
10661
|
);
|
|
10552
|
-
|
|
10662
|
+
writeFileSync6(
|
|
10553
10663
|
join8(dir, ".gitignore"),
|
|
10554
10664
|
`node_modules/
|
|
10555
10665
|
dist/
|
|
@@ -10569,7 +10679,7 @@ async function main3() {
|
|
|
10569
10679
|
process.exit(1);
|
|
10570
10680
|
}
|
|
10571
10681
|
withSpinner(`Setting up ${opts.name}...`, () => {
|
|
10572
|
-
|
|
10682
|
+
mkdirSync5(dir, { recursive: true });
|
|
10573
10683
|
createProject(dir, opts.name, opts.policy);
|
|
10574
10684
|
});
|
|
10575
10685
|
if (!opts.noInstall) {
|
|
@@ -10643,7 +10753,7 @@ var init_create = __esm({
|
|
|
10643
10753
|
|
|
10644
10754
|
// src/pull-push.ts
|
|
10645
10755
|
var pull_push_exports = {};
|
|
10646
|
-
import { readFileSync as readFileSync10, writeFileSync as
|
|
10756
|
+
import { readFileSync as readFileSync10, writeFileSync as writeFileSync7, existsSync as existsSync8 } from "fs";
|
|
10647
10757
|
import { resolve as resolve9 } from "path";
|
|
10648
10758
|
function loadEnv() {
|
|
10649
10759
|
if (process.env.SOLONGATE_API_KEY) return;
|
|
@@ -10838,7 +10948,7 @@ async function pull(apiKey, file, policyId) {
|
|
|
10838
10948
|
const policy = await fetchCloudPolicy(apiKey, API_URL, policyId);
|
|
10839
10949
|
const { id: _id, ...policyWithoutId } = policy;
|
|
10840
10950
|
const json = JSON.stringify(policyWithoutId, null, 2) + "\n";
|
|
10841
|
-
|
|
10951
|
+
writeFileSync7(file, json, "utf-8");
|
|
10842
10952
|
log5("");
|
|
10843
10953
|
log5(green2(" Saved to: ") + file);
|
|
10844
10954
|
log5(` ${dim2("Name:")} ${policy.name}`);
|