@solongate/proxy 0.72.0 → 0.73.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 +195 -212
- package/dist/tui/index.js +165 -182
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7030,12 +7030,11 @@ var init_hooks = __esm({
|
|
|
7030
7030
|
|
|
7031
7031
|
// src/tui/panels/Live.tsx
|
|
7032
7032
|
import { Box as Box2, Text as Text2, useInput } from "ink";
|
|
7033
|
-
import {
|
|
7034
|
-
import { closeSync, mkdirSync as mkdirSync3, openSync, readSync, statSync, writeFileSync as writeFileSync3 } from "fs";
|
|
7033
|
+
import { closeSync, openSync, readSync, statSync } from "fs";
|
|
7035
7034
|
import { homedir as homedir3 } from "os";
|
|
7036
|
-
import {
|
|
7035
|
+
import { join as join5 } from "path";
|
|
7037
7036
|
import { useCallback as useCallback2, useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
|
|
7038
|
-
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
7037
|
+
import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
7039
7038
|
function tailLines(file, maxBytes = 131072) {
|
|
7040
7039
|
try {
|
|
7041
7040
|
const size = statSync(file).size;
|
|
@@ -7051,22 +7050,6 @@ function tailLines(file, maxBytes = 131072) {
|
|
|
7051
7050
|
return [];
|
|
7052
7051
|
}
|
|
7053
7052
|
}
|
|
7054
|
-
function copyToClipboard(text) {
|
|
7055
|
-
const tools = [
|
|
7056
|
-
["wl-copy", []],
|
|
7057
|
-
["xclip", ["-selection", "clipboard"]],
|
|
7058
|
-
["xsel", ["--clipboard", "--input"]]
|
|
7059
|
-
];
|
|
7060
|
-
for (const [cmd, args] of tools) {
|
|
7061
|
-
try {
|
|
7062
|
-
const r = spawnSync(cmd, args, { input: text, timeout: 2e3 });
|
|
7063
|
-
if (r.status === 0) return cmd;
|
|
7064
|
-
} catch {
|
|
7065
|
-
}
|
|
7066
|
-
}
|
|
7067
|
-
process.stdout.write(`\x1B]52;c;${Buffer.from(text, "utf-8").toString("base64")}\x07`);
|
|
7068
|
-
return null;
|
|
7069
|
-
}
|
|
7070
7053
|
function cloudItem(e) {
|
|
7071
7054
|
return {
|
|
7072
7055
|
id: "c:" + e.id,
|
|
@@ -7076,6 +7059,7 @@ function cloudItem(e) {
|
|
|
7076
7059
|
permission: (e.permission ?? "").slice(0, 4),
|
|
7077
7060
|
detail: (e.arguments_summary ? JSON.stringify(e.arguments_summary) : e.reason ?? "").replace(/\s+/g, " "),
|
|
7078
7061
|
dlp: !!e.dlp_matches?.length,
|
|
7062
|
+
burst: !!e.rate_limit_burst,
|
|
7079
7063
|
source: "cloud",
|
|
7080
7064
|
session: e.session_id ?? void 0,
|
|
7081
7065
|
agent: e.agent_name ?? void 0,
|
|
@@ -7131,6 +7115,12 @@ function PaneTitle({ label, extra, width: width2 }) {
|
|
|
7131
7115
|
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: tail + "\u2500".repeat(Math.max(0, width2 - used)) })
|
|
7132
7116
|
] });
|
|
7133
7117
|
}
|
|
7118
|
+
function Stat({ label, value, color }) {
|
|
7119
|
+
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", marginRight: 3, children: [
|
|
7120
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: label }),
|
|
7121
|
+
/* @__PURE__ */ jsx2(Text2, { bold: true, color, children: String(value) })
|
|
7122
|
+
] });
|
|
7123
|
+
}
|
|
7134
7124
|
function StreamLine({ e, loc }) {
|
|
7135
7125
|
return /* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
|
|
7136
7126
|
/* @__PURE__ */ jsxs2(Text2, { color: theme.dim, children: [
|
|
@@ -7146,6 +7136,7 @@ function StreamLine({ e, loc }) {
|
|
|
7146
7136
|
/* @__PURE__ */ jsx2(Text2, { color: e.evalMs != null && e.evalMs > 500 ? theme.warn : theme.dim, children: (e.evalMs != null ? `${e.evalMs}ms` : "\u2014").padEnd(7) }),
|
|
7147
7137
|
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: truncate2(e.agent ?? "-", 11).padEnd(12) }),
|
|
7148
7138
|
e.dlp ? /* @__PURE__ */ jsx2(Text2, { color: theme.bad, children: "DLP! " }) : null,
|
|
7139
|
+
e.burst ? /* @__PURE__ */ jsx2(Text2, { color: theme.warn, children: "BURST " }) : null,
|
|
7149
7140
|
e.rule && e.decision !== "ALLOW" ? /* @__PURE__ */ jsx2(Text2, { color: theme.bad, children: truncate2(e.rule, 14) + " " }) : null,
|
|
7150
7141
|
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: e.detail })
|
|
7151
7142
|
] });
|
|
@@ -7161,12 +7152,11 @@ function LivePanel({ active: active2 }) {
|
|
|
7161
7152
|
const [log6, setLog] = useState2([]);
|
|
7162
7153
|
const [filter, setFilter] = useState2("all");
|
|
7163
7154
|
const [scroll, setScroll] = useState2(0);
|
|
7164
|
-
const [toast, setToast] = useState2(null);
|
|
7165
7155
|
const [mode, setMode] = useState2("stream");
|
|
7156
|
+
const [sessFilter, setSessFilter] = useState2("all");
|
|
7166
7157
|
const [pickIdx, setPickIdx] = useState2(0);
|
|
7167
|
-
const [detail, setDetail] = useState2(null);
|
|
7168
7158
|
const [detailCloud, setDetailCloud] = useState2([]);
|
|
7169
|
-
const [
|
|
7159
|
+
const [tlScroll, setTlScroll] = useState2(0);
|
|
7170
7160
|
const seenRef = useRef2(/* @__PURE__ */ new Set());
|
|
7171
7161
|
const lastLocalTs = useRef2(0);
|
|
7172
7162
|
const pausedUntil = useRef2(0);
|
|
@@ -7211,6 +7201,7 @@ function LivePanel({ active: active2 }) {
|
|
|
7211
7201
|
permission: (j.permission ?? "").slice(0, 4),
|
|
7212
7202
|
detail: (j.arguments ? JSON.stringify(j.arguments) : j.reason ?? "").replace(/\s+/g, " "),
|
|
7213
7203
|
dlp: !!j.dlp,
|
|
7204
|
+
burst: !!j.rate_limit_burst,
|
|
7214
7205
|
source: "local",
|
|
7215
7206
|
session: j.session_id,
|
|
7216
7207
|
agent: j.agent_name,
|
|
@@ -7315,19 +7306,6 @@ function LivePanel({ active: active2 }) {
|
|
|
7315
7306
|
usePoll(() => {
|
|
7316
7307
|
if (!paused()) guard.reload();
|
|
7317
7308
|
}, 6e4, active2);
|
|
7318
|
-
useEffect2(() => {
|
|
7319
|
-
if (!detail) return;
|
|
7320
|
-
setDetailCloud([]);
|
|
7321
|
-
setDetailScroll(0);
|
|
7322
|
-
let alive = true;
|
|
7323
|
-
api.audit.list({ session_id: detail.id, limit: 100 }).then((r) => {
|
|
7324
|
-
if (alive) setDetailCloud(r.entries.map(cloudItem));
|
|
7325
|
-
}).catch(() => {
|
|
7326
|
-
});
|
|
7327
|
-
return () => {
|
|
7328
|
-
alive = false;
|
|
7329
|
-
};
|
|
7330
|
-
}, [detail]);
|
|
7331
7309
|
const [tick, setTick] = useState2(0);
|
|
7332
7310
|
useEffect2(() => {
|
|
7333
7311
|
if (!active2 || frozen) return;
|
|
@@ -7347,67 +7325,68 @@ function LivePanel({ active: active2 }) {
|
|
|
7347
7325
|
}
|
|
7348
7326
|
const cloudDeduped = cloudBuf.filter((e) => !localKeys.has(`${e.tool}|${e.decision}|${Math.round(e.at / 6e4)}`));
|
|
7349
7327
|
const mergedAll = [...cloudDeduped, ...localBuf].sort((a, b) => a.at - b.at);
|
|
7350
|
-
const points = tsData?.timeseries ?? [];
|
|
7351
|
-
const nowMin = Math.floor(nowMs / 6e4);
|
|
7352
|
-
const minuteCounts = new Array(60).fill(0);
|
|
7353
|
-
const minuteHot = new Array(60).fill(false);
|
|
7354
|
-
for (const e of mergedAll) {
|
|
7355
|
-
const idx = 59 - (nowMin - Math.floor(e.at / 6e4));
|
|
7356
|
-
if (idx >= 0 && idx < 60) {
|
|
7357
|
-
minuteCounts[idx]++;
|
|
7358
|
-
if (e.decision !== "ALLOW") minuteHot[idx] = true;
|
|
7359
|
-
}
|
|
7360
|
-
}
|
|
7361
|
-
const localTraffic = localOn === true && minuteCounts.some((c2) => c2 > 0);
|
|
7362
|
-
const traffic = localTraffic ? minuteCounts : points.map((p) => p.total);
|
|
7363
|
-
const trafficHot = localTraffic ? minuteHot : points.map((p) => p.denied > 0);
|
|
7364
|
-
const trafficLabel = localTraffic ? "calls/min \xB7 60m \xB7 local+cloud" : "24h \xB7 cloud";
|
|
7365
|
-
const rl = ins.layers?.rateLimit;
|
|
7366
|
-
const dl = ins.layers?.dlp;
|
|
7367
|
-
const gh = ins.layers?.ghost;
|
|
7368
|
-
const minuteNow = minuteCounts[59] ?? 0;
|
|
7369
|
-
const dlpBars = (ins.dlpByPattern ?? []).slice(0, 2);
|
|
7370
|
-
const maxDlpBar = dlpBars[0]?.count ?? 1;
|
|
7371
|
-
const denialsAll = mergedAll.filter((e) => e.decision !== "ALLOW");
|
|
7372
|
-
const lastDeny = denialsAll[denialsAll.length - 1];
|
|
7373
|
-
const toolCounts = /* @__PURE__ */ new Map();
|
|
7374
|
-
for (const e of mergedAll) toolCounts.set(e.tool, (toolCounts.get(e.tool) ?? 0) + 1);
|
|
7375
|
-
const topTools = [...toolCounts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 3);
|
|
7376
|
-
const latNow = lat[lat.length - 1] ?? 0;
|
|
7377
|
-
const sortedLat = [...lat].sort((a, b) => a - b);
|
|
7378
|
-
const latMed = sortedLat.length ? sortedLat[Math.floor(sortedLat.length / 2)] : 0;
|
|
7379
|
-
const latHotAt = Math.max(2e3, latMed * 2.5);
|
|
7380
|
-
const backingOff = Date.now() < pausedUntil.current;
|
|
7381
|
-
const sess = (sessions.data?.agents ?? []).slice().sort((a, b) => Date.parse(b.last_seen_at) - Date.parse(a.last_seen_at));
|
|
7382
|
-
const sessCounts = sessions.data?.counts;
|
|
7383
7328
|
const localSess = /* @__PURE__ */ new Map();
|
|
7384
7329
|
for (const e of localBuf) {
|
|
7385
7330
|
if (!e.session) continue;
|
|
7386
|
-
const cur = localSess.get(e.session) ?? { agent: e.agent ?? "local agent", calls: 0, denies: 0, lastAt: 0 };
|
|
7331
|
+
const cur = localSess.get(e.session) ?? { agent: e.agent ?? "local agent", calls: 0, denies: 0, dlp: 0, lastAt: 0 };
|
|
7387
7332
|
cur.calls++;
|
|
7388
7333
|
if (e.decision !== "ALLOW") cur.denies++;
|
|
7334
|
+
if (e.dlp) cur.dlp++;
|
|
7389
7335
|
cur.lastAt = Math.max(cur.lastAt, e.at);
|
|
7390
7336
|
if (e.agent) cur.agent = e.agent;
|
|
7391
7337
|
localSess.set(e.session, cur);
|
|
7392
7338
|
}
|
|
7393
|
-
const
|
|
7394
|
-
...[...localSess.entries()].sort((a, b) => b[1].lastAt - a[1].lastAt).map(([id, v]) => ({ source: "local", id, agent: v.agent, calls: v.calls, denies: v.denies, lastAt: v.lastAt, isMe: ring?.session === id })),
|
|
7395
|
-
...
|
|
7339
|
+
const combinedSessAll = [
|
|
7340
|
+
...[...localSess.entries()].sort((a, b) => b[1].lastAt - a[1].lastAt).map(([id, v]) => ({ source: "local", id, agent: v.agent, calls: v.calls, denies: v.denies, dlp: v.dlp, lastAt: v.lastAt, isMe: ring?.session === id })),
|
|
7341
|
+
...(sessions.data?.agents ?? []).filter((a) => !localSess.has(a.session_id)).sort((a, b) => Date.parse(b.last_seen_at) - Date.parse(a.last_seen_at)).map((a) => ({
|
|
7396
7342
|
source: "cloud",
|
|
7397
7343
|
id: a.session_id,
|
|
7398
7344
|
agent: a.agent_name ?? a.session_id,
|
|
7399
7345
|
calls: a.total_calls,
|
|
7400
7346
|
denies: a.denied_calls,
|
|
7347
|
+
dlp: a.dlp_events,
|
|
7401
7348
|
lastAt: Date.parse(a.last_seen_at),
|
|
7402
7349
|
trust: a.trust_score,
|
|
7403
7350
|
isMe: false
|
|
7404
7351
|
}))
|
|
7405
7352
|
];
|
|
7353
|
+
const combinedSess = sessFilter === "all" ? combinedSessAll : combinedSessAll.filter((r) => sessStatus(r.lastAt, nowMs) === sessFilter);
|
|
7406
7354
|
const localSessIds = new Set(localSess.keys());
|
|
7407
7355
|
if (ring?.session) localSessIds.add(ring.session);
|
|
7408
7356
|
const isLoc = (e) => e.source === "local" || !!e.session && localSessIds.has(e.session);
|
|
7409
7357
|
const filtered = filter === "all" ? mergedAll : mergedAll.filter((e) => filter === "local" ? isLoc(e) : !isLoc(e));
|
|
7410
7358
|
const visibleDesc = filtered.slice(-STREAM_KEEP).reverse();
|
|
7359
|
+
const points = tsData?.timeseries ?? [];
|
|
7360
|
+
const nowSlot = Math.floor(nowMs / 1e4);
|
|
7361
|
+
const slotCounts = new Array(60).fill(0);
|
|
7362
|
+
const slotHot = new Array(60).fill(false);
|
|
7363
|
+
for (const e of mergedAll) {
|
|
7364
|
+
const idx = 59 - (nowSlot - Math.floor(e.at / 1e4));
|
|
7365
|
+
if (idx >= 0 && idx < 60) {
|
|
7366
|
+
slotCounts[idx]++;
|
|
7367
|
+
if (e.decision !== "ALLOW") slotHot[idx] = true;
|
|
7368
|
+
}
|
|
7369
|
+
}
|
|
7370
|
+
const localTraffic = localOn === true && slotCounts.some((c2) => c2 > 0);
|
|
7371
|
+
const traffic = localTraffic ? slotCounts : points.map((p) => p.total);
|
|
7372
|
+
const trafficHot = localTraffic ? slotHot : points.map((p) => p.denied > 0);
|
|
7373
|
+
const trafficLabel = localTraffic ? "calls/10s \xB7 last 10m" : "24h \xB7 cloud";
|
|
7374
|
+
const rl = ins.layers?.rateLimit;
|
|
7375
|
+
const dl = ins.layers?.dlp;
|
|
7376
|
+
const gh = ins.layers?.ghost;
|
|
7377
|
+
const minuteNow = mergedAll.filter((e) => nowMs - e.at < 6e4).length;
|
|
7378
|
+
const dlpBars = (ins.dlpByPattern ?? []).slice(0, 2);
|
|
7379
|
+
const maxDlpBar = dlpBars[0]?.count ?? 1;
|
|
7380
|
+
const denialsAll = mergedAll.filter((e) => e.decision !== "ALLOW");
|
|
7381
|
+
const lastDeny = denialsAll[denialsAll.length - 1];
|
|
7382
|
+
const toolCounts = /* @__PURE__ */ new Map();
|
|
7383
|
+
for (const e of mergedAll) toolCounts.set(e.tool, (toolCounts.get(e.tool) ?? 0) + 1);
|
|
7384
|
+
const topTools = [...toolCounts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 3);
|
|
7385
|
+
const latNow = lat[lat.length - 1] ?? 0;
|
|
7386
|
+
const sortedLat = [...lat].sort((a, b) => a - b);
|
|
7387
|
+
const latMed = sortedLat.length ? sortedLat[Math.floor(sortedLat.length / 2)] : 0;
|
|
7388
|
+
const latHotAt = Math.max(2e3, latMed * 2.5);
|
|
7389
|
+
const backingOff = Date.now() < pausedUntil.current;
|
|
7411
7390
|
const chartH = rows >= 36 ? 6 : 4;
|
|
7412
7391
|
const colH = rows >= 32 ? 7 : 5;
|
|
7413
7392
|
const streamRows = Math.max(4, rows - 5 - (1 + chartH) - colH);
|
|
@@ -7415,14 +7394,25 @@ function LivePanel({ active: active2 }) {
|
|
|
7415
7394
|
const leftW = Math.floor(innerW * 0.55);
|
|
7416
7395
|
const rightW = innerW - leftW - 2;
|
|
7417
7396
|
const colW = Math.max(20, Math.floor((innerW - 4) / 3));
|
|
7418
|
-
const pickable = combinedSess.slice(0, colH - 1);
|
|
7419
7397
|
const maxScroll = Math.max(0, visibleDesc.length - streamRows);
|
|
7420
7398
|
const clampedScroll = Math.min(scroll, maxScroll);
|
|
7421
7399
|
const windowed = visibleDesc.slice(clampedScroll, clampedScroll + streamRows);
|
|
7422
|
-
const
|
|
7400
|
+
const selIdx = Math.min(pickIdx, Math.max(0, combinedSess.length - 1));
|
|
7401
|
+
const selected = combinedSess[selIdx];
|
|
7402
|
+
useEffect2(() => {
|
|
7403
|
+
if (mode !== "sessions" || !selected?.id) return;
|
|
7404
|
+
setTlScroll(0);
|
|
7405
|
+
const t = setTimeout(() => {
|
|
7406
|
+
api.audit.list({ session_id: selected.id, limit: 100 }).then((r) => {
|
|
7407
|
+
if (!frozenRef.current) setDetailCloud(r.entries.map(cloudItem));
|
|
7408
|
+
}).catch(() => setDetailCloud([]));
|
|
7409
|
+
}, 400);
|
|
7410
|
+
return () => clearTimeout(t);
|
|
7411
|
+
}, [mode, selected?.id]);
|
|
7412
|
+
const detailEntries = selected ? (() => {
|
|
7423
7413
|
const seen = /* @__PURE__ */ new Set();
|
|
7424
7414
|
const all = [];
|
|
7425
|
-
for (const e of [...detailCloud, ...mergedAll.filter((x) => x.session ===
|
|
7415
|
+
for (const e of [...detailCloud, ...mergedAll.filter((x) => x.session === selected.id)]) {
|
|
7426
7416
|
const key = `${e.at}:${e.tool}:${e.decision}`;
|
|
7427
7417
|
if (seen.has(key)) continue;
|
|
7428
7418
|
seen.add(key);
|
|
@@ -7432,63 +7422,37 @@ function LivePanel({ active: active2 }) {
|
|
|
7432
7422
|
})() : [];
|
|
7433
7423
|
useInput(
|
|
7434
7424
|
(input, key) => {
|
|
7435
|
-
if (mode === "detail") {
|
|
7436
|
-
const maxD = Math.max(0, detailEntries.length - (rows - 10));
|
|
7437
|
-
if (key.leftArrow) {
|
|
7438
|
-
setMode("stream");
|
|
7439
|
-
setDetail(null);
|
|
7440
|
-
} else if (key.upArrow) setDetailScroll((n) => Math.max(0, n - 1));
|
|
7441
|
-
else if (key.downArrow) setDetailScroll((n) => Math.min(maxD, n + 1));
|
|
7442
|
-
else if (key.pageUp) setDetailScroll((n) => Math.max(0, n - 10));
|
|
7443
|
-
else if (key.pageDown) setDetailScroll((n) => Math.min(maxD, n + 10));
|
|
7444
|
-
return;
|
|
7445
|
-
}
|
|
7446
|
-
if (mode === "pick") {
|
|
7447
|
-
if (key.upArrow) setPickIdx((n) => Math.max(0, n - 1));
|
|
7448
|
-
else if (key.downArrow) setPickIdx((n) => Math.min(pickable.length - 1, n + 1));
|
|
7449
|
-
else if (key.return) {
|
|
7450
|
-
const row = pickable[pickIdx];
|
|
7451
|
-
if (row) {
|
|
7452
|
-
setDetail(row);
|
|
7453
|
-
setMode("detail");
|
|
7454
|
-
}
|
|
7455
|
-
} else if (input === "s" || key.leftArrow) setMode("stream");
|
|
7456
|
-
return;
|
|
7457
|
-
}
|
|
7458
7425
|
if (input === " ") {
|
|
7459
7426
|
setFrozen((f) => !f);
|
|
7460
7427
|
return;
|
|
7461
7428
|
}
|
|
7462
7429
|
if (frozen) return;
|
|
7430
|
+
if (mode === "sessions") {
|
|
7431
|
+
if (key.leftArrow) {
|
|
7432
|
+
setMode("stream");
|
|
7433
|
+
setDetailCloud([]);
|
|
7434
|
+
} else if (key.upArrow) setPickIdx((n) => Math.max(0, n - 1));
|
|
7435
|
+
else if (key.downArrow) setPickIdx((n) => Math.min(combinedSess.length - 1, n + 1));
|
|
7436
|
+
else if (input === "f") {
|
|
7437
|
+
setSessFilter((f) => SESS_FILTERS[(SESS_FILTERS.indexOf(f) + 1) % SESS_FILTERS.length]);
|
|
7438
|
+
setPickIdx(0);
|
|
7439
|
+
} else if (key.pageUp) setTlScroll((n) => Math.max(0, n - 10));
|
|
7440
|
+
else if (key.pageDown) setTlScroll((n) => n + 10);
|
|
7441
|
+
return;
|
|
7442
|
+
}
|
|
7463
7443
|
if (input === "f") {
|
|
7464
7444
|
setFilter((f) => FILTERS[(FILTERS.indexOf(f) + 1) % FILTERS.length]);
|
|
7465
7445
|
setScroll(0);
|
|
7466
7446
|
} else if (input === "s") {
|
|
7467
7447
|
setPickIdx(0);
|
|
7468
|
-
setMode("
|
|
7448
|
+
setMode("sessions");
|
|
7469
7449
|
} else if (key.downArrow) setScroll((n) => Math.min(maxScroll, n + 1));
|
|
7470
7450
|
else if (key.upArrow) setScroll((n) => Math.max(0, n - 1));
|
|
7471
7451
|
else if (key.pageDown) setScroll((n) => Math.min(maxScroll, n + streamRows));
|
|
7472
7452
|
else if (key.pageUp) setScroll((n) => Math.max(0, n - streamRows));
|
|
7473
|
-
else if (input === "c") {
|
|
7474
|
-
const dump = visibleDesc.map(
|
|
7475
|
-
(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}`
|
|
7476
|
-
).join("\n");
|
|
7477
|
-
try {
|
|
7478
|
-
mkdirSync3(dirname(DUMP), { recursive: true });
|
|
7479
|
-
writeFileSync3(DUMP, dump + "\n");
|
|
7480
|
-
} catch {
|
|
7481
|
-
}
|
|
7482
|
-
const via = copyToClipboard(dump);
|
|
7483
|
-
setToast(
|
|
7484
|
-
via ? { msg: `\u2713 ${visibleDesc.length} lines in clipboard (${via})`, until: Date.now() + 4e3 } : { msg: "\u2717 no clipboard tool \u2014 install wl-clipboard or xclip", until: Date.now() + 6e3 }
|
|
7485
|
-
);
|
|
7486
|
-
}
|
|
7487
7453
|
},
|
|
7488
7454
|
{ isActive: active2 }
|
|
7489
7455
|
);
|
|
7490
|
-
const sessionDot = (st) => st === "active" ? { ch: "\u25CF", color: theme.ok } : st === "idle" ? { ch: "\u25CC", color: theme.warn } : { ch: "\u25CB", color: theme.dim };
|
|
7491
|
-
void sessionDot;
|
|
7492
7456
|
if (s === null && localOn === null) {
|
|
7493
7457
|
return /* @__PURE__ */ jsxs2(Text2, { color: theme.dim, children: [
|
|
7494
7458
|
spin,
|
|
@@ -7498,72 +7462,91 @@ function LivePanel({ active: active2 }) {
|
|
|
7498
7462
|
const titleBar = /* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
|
|
7499
7463
|
/* @__PURE__ */ jsx2(Text2, { backgroundColor: "#1432A0", color: "#AAC8FA", bold: true, children: " SOLONGATE LIVE " }),
|
|
7500
7464
|
/* @__PURE__ */ jsx2(Text2, { backgroundColor: BG, color: "#82AAF0", children: ` ${spin} up ${fmtUp(nowMs - startRef.current)} \xB7 ${hhmmss(nowMs)} \xB7 api ${latNow}ms ` }),
|
|
7501
|
-
frozen ? /* @__PURE__ */ jsx2(Text2, { backgroundColor: "#123d1f", color: "#7bd88f", bold: true, children: " \u23F5 COPY MODE \u2014 screen frozen, select & copy freely \xB7 space resume " }) : 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 " })
|
|
7502
|
-
toast && nowMs < toast.until ? /* @__PURE__ */ jsx2(Text2, { backgroundColor: "#123d1f", color: "#7bd88f", bold: true, children: ` ${toast.msg} ` }) : null
|
|
7465
|
+
frozen ? /* @__PURE__ */ jsx2(Text2, { backgroundColor: "#123d1f", color: "#7bd88f", bold: true, children: " \u23F5 COPY MODE \u2014 screen frozen, select & copy freely \xB7 space resume " }) : 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 " })
|
|
7503
7466
|
] });
|
|
7504
|
-
if (mode === "
|
|
7467
|
+
if (mode === "sessions") {
|
|
7468
|
+
const listW = Math.min(44, Math.floor(innerW * 0.38));
|
|
7469
|
+
const detailW = innerW - listW - 2;
|
|
7470
|
+
const bodyH = rows - 4;
|
|
7471
|
+
const listRows = bodyH - 1;
|
|
7505
7472
|
const d = detailEntries;
|
|
7506
7473
|
const allow = d.filter((e) => e.decision === "ALLOW").length;
|
|
7507
7474
|
const deny = d.length - allow;
|
|
7508
7475
|
const dlpN = d.filter((e) => e.dlp).length;
|
|
7476
|
+
const burstN = d.filter((e) => e.burst).length;
|
|
7509
7477
|
const evals = d.filter((e) => e.evalMs != null).map((e) => e.evalMs);
|
|
7510
7478
|
const evalAvg = evals.length ? Math.round(evals.reduce((a, b) => a + b, 0) / evals.length) : null;
|
|
7511
7479
|
const tCounts = /* @__PURE__ */ new Map();
|
|
7512
|
-
const
|
|
7513
|
-
|
|
7514
|
-
tCounts.set(e.tool, (tCounts.get(e.tool) ?? 0) + 1);
|
|
7515
|
-
if (e.permission) pCounts.set(e.permission, (pCounts.get(e.permission) ?? 0) + 1);
|
|
7516
|
-
}
|
|
7517
|
-
const top = [...tCounts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 6);
|
|
7518
|
-
const perms = [...pCounts.entries()].sort((a, b) => b[1] - a[1]);
|
|
7480
|
+
for (const e of d) tCounts.set(e.tool, (tCounts.get(e.tool) ?? 0) + 1);
|
|
7481
|
+
const top = [...tCounts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 5);
|
|
7519
7482
|
const first = d[d.length - 1]?.at;
|
|
7520
7483
|
const last = d[0]?.at;
|
|
7521
|
-
const tlRows = Math.max(
|
|
7522
|
-
const
|
|
7523
|
-
const
|
|
7524
|
-
const tl = d.slice(
|
|
7484
|
+
const tlRows = Math.max(3, bodyH - 8);
|
|
7485
|
+
const maxTl = Math.max(0, d.length - tlRows);
|
|
7486
|
+
const tScroll = Math.min(tlScroll, maxTl);
|
|
7487
|
+
const tl = d.slice(tScroll, tScroll + tlRows);
|
|
7525
7488
|
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", paddingX: 1, children: [
|
|
7526
7489
|
titleBar,
|
|
7527
|
-
/* @__PURE__ */
|
|
7528
|
-
|
|
7529
|
-
/* @__PURE__ */
|
|
7530
|
-
|
|
7531
|
-
|
|
7532
|
-
|
|
7533
|
-
|
|
7534
|
-
|
|
7535
|
-
|
|
7536
|
-
|
|
7537
|
-
|
|
7538
|
-
|
|
7539
|
-
|
|
7540
|
-
|
|
7541
|
-
|
|
7542
|
-
|
|
7543
|
-
|
|
7544
|
-
|
|
7545
|
-
|
|
7546
|
-
|
|
7547
|
-
|
|
7548
|
-
|
|
7549
|
-
|
|
7550
|
-
|
|
7551
|
-
|
|
7552
|
-
|
|
7553
|
-
|
|
7554
|
-
|
|
7555
|
-
|
|
7556
|
-
|
|
7557
|
-
|
|
7558
|
-
|
|
7559
|
-
|
|
7560
|
-
|
|
7561
|
-
|
|
7490
|
+
/* @__PURE__ */ jsx2(PaneTitle, { label: "SESSIONS", extra: `${combinedSess.length} shown \xB7 filter ${sessFilter} (f) \xB7 \u2191\u2193 select \xB7 PgUp/Dn timeline \xB7 \u2190 back`, width: innerW }),
|
|
7491
|
+
/* @__PURE__ */ jsxs2(Box2, { height: bodyH, children: [
|
|
7492
|
+
/* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", width: listW, marginRight: 2, overflow: "hidden", children: [
|
|
7493
|
+
combinedSess.length === 0 ? /* @__PURE__ */ jsxs2(Text2, { color: theme.dim, children: [
|
|
7494
|
+
"no sessions",
|
|
7495
|
+
sessFilter !== "all" ? ` (${sessFilter})` : ""
|
|
7496
|
+
] }) : null,
|
|
7497
|
+
combinedSess.slice(0, listRows).map((r, i) => {
|
|
7498
|
+
const st = sessStatus(r.lastAt, nowMs);
|
|
7499
|
+
const dot = st === "active" ? { ch: "\u25CF", color: theme.ok } : st === "idle" ? { ch: "\u25CC", color: theme.warn } : { ch: "\u25CB", color: theme.dim };
|
|
7500
|
+
const sel = i === selIdx;
|
|
7501
|
+
return /* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", backgroundColor: sel ? "#1c2f63" : void 0, bold: sel, children: [
|
|
7502
|
+
/* @__PURE__ */ jsxs2(Text2, { color: sel ? theme.accentBright : dot.color, children: [
|
|
7503
|
+
sel ? "\u25B8" : dot.ch,
|
|
7504
|
+
" "
|
|
7505
|
+
] }),
|
|
7506
|
+
/* @__PURE__ */ jsx2(Text2, { color: r.source === "local" ? theme.ok : "#4f6db8", children: r.source === "local" ? "LOC " : "CLD " }),
|
|
7507
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.accentBright, children: truncate2(r.isMe ? "this machine" : r.agent, 13).padEnd(14) }),
|
|
7508
|
+
/* @__PURE__ */ jsxs2(Text2, { children: [
|
|
7509
|
+
String(r.calls).padStart(4),
|
|
7510
|
+
"c "
|
|
7511
|
+
] }),
|
|
7512
|
+
/* @__PURE__ */ jsxs2(Text2, { color: r.denies ? theme.bad : theme.dim, children: [
|
|
7513
|
+
String(r.denies).padStart(3),
|
|
7514
|
+
"d "
|
|
7515
|
+
] }),
|
|
7516
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: ago(r.lastAt) })
|
|
7517
|
+
] }, r.id);
|
|
7518
|
+
})
|
|
7519
|
+
] }),
|
|
7520
|
+
/* @__PURE__ */ jsx2(Box2, { flexDirection: "column", width: detailW, overflow: "hidden", children: !selected ? /* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: "select a session to see its run timeline" }) : /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
7521
|
+
/* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
|
|
7522
|
+
/* @__PURE__ */ jsx2(Text2, { color: sessStatus(selected.lastAt, nowMs) === "active" ? theme.ok : theme.dim, children: sessStatus(selected.lastAt, nowMs) === "active" ? "\u25CF " : "\u25CB " }),
|
|
7523
|
+
/* @__PURE__ */ jsx2(Text2, { bold: true, children: truncate2(selected.isMe ? selected.agent + " (this machine)" : selected.agent, 30) }),
|
|
7524
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: " " + selected.id })
|
|
7525
|
+
] }),
|
|
7526
|
+
/* @__PURE__ */ jsxs2(Box2, { marginTop: 1, children: [
|
|
7527
|
+
/* @__PURE__ */ jsx2(Stat, { label: "Total", value: d.length }),
|
|
7528
|
+
/* @__PURE__ */ jsx2(Stat, { label: "Allowed", value: allow, color: theme.ok }),
|
|
7529
|
+
/* @__PURE__ */ jsx2(Stat, { label: "Denied", value: deny, color: deny ? theme.bad : void 0 }),
|
|
7530
|
+
/* @__PURE__ */ jsx2(Stat, { label: "DLP", value: dlpN, color: dlpN ? theme.bad : void 0 }),
|
|
7531
|
+
/* @__PURE__ */ jsx2(Stat, { label: "Rate limit", value: burstN, color: burstN ? theme.warn : void 0 }),
|
|
7532
|
+
/* @__PURE__ */ jsx2(Stat, { label: "Avg eval", value: evalAvg != null ? `${evalAvg}ms` : "\u2014" }),
|
|
7533
|
+
selected.trust != null ? /* @__PURE__ */ jsx2(Stat, { label: "Trust", value: `${selected.trust}/100`, color: theme.accent }) : null
|
|
7534
|
+
] }),
|
|
7535
|
+
/* @__PURE__ */ jsx2(Text2, { wrap: "truncate", color: theme.dim, children: `first ${first ? `${hhmmss(first)} (${ago(first)} ago)` : "\u2014"} \xB7 last ${last ? `${hhmmss(last)} (${ago(last)} ago)` : "\u2014"} \xB7 tools ${top.map(([t, c2]) => `${t}\xD7${c2}`).join(" ") || "\u2014"}` }),
|
|
7536
|
+
/* @__PURE__ */ jsx2(PaneTitle, { label: "TIMELINE", extra: `${d.length} events \xB7 newest first${tScroll ? ` \xB7 \u25BC${tScroll}` : ""}`, width: detailW }),
|
|
7537
|
+
/* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", overflow: "hidden", flexGrow: 1, children: [
|
|
7538
|
+
tl.length === 0 ? /* @__PURE__ */ jsxs2(Text2, { color: theme.dim, children: [
|
|
7539
|
+
spin,
|
|
7540
|
+
" loading history\u2026"
|
|
7541
|
+
] }) : null,
|
|
7542
|
+
tl.map((e) => /* @__PURE__ */ jsx2(StreamLine, { e, loc: isLoc(e) }, e.id))
|
|
7543
|
+
] })
|
|
7544
|
+
] }) })
|
|
7562
7545
|
] }),
|
|
7563
7546
|
/* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
|
|
7564
|
-
/* @__PURE__ */ jsx2(Text2, { backgroundColor: BG, color: "#82AAF0", bold: true, children: "
|
|
7565
|
-
/* @__PURE__ */ jsx2(Text2, { backgroundColor: "#0b1530", color: "#4f6db8", children: ` ${
|
|
7566
|
-
/* @__PURE__ */ jsx2(Text2, { backgroundColor: BG, color: "#82AAF0", children: " \u2191\u2193
|
|
7547
|
+
/* @__PURE__ */ jsx2(Text2, { backgroundColor: BG, color: "#82AAF0", bold: true, children: " SESSIONS " }),
|
|
7548
|
+
/* @__PURE__ */ jsx2(Text2, { backgroundColor: "#0b1530", color: "#4f6db8", children: ` ${combinedSess.length} sessions \xB7 space copy-mode ` }),
|
|
7549
|
+
/* @__PURE__ */ jsx2(Text2, { backgroundColor: BG, color: "#82AAF0", children: " \u2191\u2193 select \xB7 f status \xB7 \u2190 back \xB7 esc menu " })
|
|
7567
7550
|
] })
|
|
7568
7551
|
] });
|
|
7569
7552
|
}
|
|
@@ -7585,7 +7568,7 @@ function LivePanel({ active: active2 }) {
|
|
|
7585
7568
|
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: " \u2502 ghost " }),
|
|
7586
7569
|
/* @__PURE__ */ jsx2(Text2, { color: gh?.mode === "on" ? theme.ok : theme.dim, children: gh?.mode ?? "?" }),
|
|
7587
7570
|
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: " \u2502 sess " }),
|
|
7588
|
-
/* @__PURE__ */ jsx2(Text2, { color: theme.accent, children:
|
|
7571
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.accent, children: String(combinedSessAll.length) }),
|
|
7589
7572
|
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: " \u2502 hooks " }),
|
|
7590
7573
|
/* @__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" }),
|
|
7591
7574
|
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: " \u2502" })
|
|
@@ -7624,14 +7607,13 @@ function LivePanel({ active: active2 }) {
|
|
|
7624
7607
|
] })
|
|
7625
7608
|
] }),
|
|
7626
7609
|
/* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", width: colW, marginRight: 2, overflow: "hidden", children: [
|
|
7627
|
-
/* @__PURE__ */ jsx2(PaneTitle, { label: "SESSIONS", extra:
|
|
7628
|
-
|
|
7629
|
-
|
|
7630
|
-
const
|
|
7631
|
-
|
|
7632
|
-
|
|
7633
|
-
|
|
7634
|
-
sel ? "\u25B8" : freshDot ? "\u25CF" : "\u25CB",
|
|
7610
|
+
/* @__PURE__ */ jsx2(PaneTitle, { label: "SESSIONS", extra: "press s to inspect", width: colW }),
|
|
7611
|
+
combinedSessAll.slice(0, colH - 1).map((r) => {
|
|
7612
|
+
const st = sessStatus(r.lastAt, nowMs);
|
|
7613
|
+
const dot = st === "active" ? { ch: "\u25CF", color: theme.ok } : st === "idle" ? { ch: "\u25CC", color: theme.warn } : { ch: "\u25CB", color: theme.dim };
|
|
7614
|
+
return /* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", bold: r.isMe, children: [
|
|
7615
|
+
/* @__PURE__ */ jsxs2(Text2, { color: dot.color, children: [
|
|
7616
|
+
dot.ch,
|
|
7635
7617
|
" "
|
|
7636
7618
|
] }),
|
|
7637
7619
|
/* @__PURE__ */ jsx2(Text2, { color: r.source === "local" ? theme.ok : "#4f6db8", children: r.source === "local" ? "LOC " : "CLD " }),
|
|
@@ -7644,7 +7626,7 @@ function LivePanel({ active: active2 }) {
|
|
|
7644
7626
|
String(r.denies).padStart(3),
|
|
7645
7627
|
"d "
|
|
7646
7628
|
] }),
|
|
7647
|
-
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children:
|
|
7629
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: ago(r.lastAt) })
|
|
7648
7630
|
] }, r.id);
|
|
7649
7631
|
})
|
|
7650
7632
|
] }),
|
|
@@ -7664,7 +7646,7 @@ function LivePanel({ active: active2 }) {
|
|
|
7664
7646
|
PaneTitle,
|
|
7665
7647
|
{
|
|
7666
7648
|
label: "TOOL STREAM",
|
|
7667
|
-
extra: `newest first \xB7 last ${STREAM_KEEP} \xB7 filter ${filter}${clampedScroll > 0 ? ` \xB7 \u25BC${clampedScroll} older` : ""} \xB7 f filter \xB7 \u2191\u2193 scroll \xB7
|
|
7649
|
+
extra: `newest first \xB7 last ${STREAM_KEEP} \xB7 filter ${filter}${clampedScroll > 0 ? ` \xB7 \u25BC${clampedScroll} older` : ""} \xB7 f filter \xB7 \u2191\u2193 scroll \xB7 s sessions`,
|
|
7668
7650
|
width: innerW
|
|
7669
7651
|
}
|
|
7670
7652
|
),
|
|
@@ -7681,12 +7663,12 @@ function LivePanel({ active: active2 }) {
|
|
|
7681
7663
|
] }),
|
|
7682
7664
|
/* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
|
|
7683
7665
|
/* @__PURE__ */ jsx2(Text2, { backgroundColor: BG, color: "#82AAF0", bold: true, children: " LIVE " }),
|
|
7684
|
-
/* @__PURE__ */ jsx2(Text2, { backgroundColor: "#0b1530", color: "#4f6db8", children: ` local ${localOn ? "on" : "off"} \xB7 ${localBuf.length} loc/${
|
|
7685
|
-
/* @__PURE__ */ jsx2(Text2, { backgroundColor: BG, color: "#82AAF0", children: " space copy-mode \xB7 f filter \xB7 s sessions \xB7
|
|
7666
|
+
/* @__PURE__ */ jsx2(Text2, { backgroundColor: "#0b1530", color: "#4f6db8", children: ` local ${localOn ? "on" : "off"} \xB7 ${localBuf.length} loc/${cloudDeduped.length} cld \xB7 top ${topTools.map(([t, c2]) => `${t}\xD7${c2}`).join(" ") || "\u2014"} ` }),
|
|
7667
|
+
/* @__PURE__ */ jsx2(Text2, { backgroundColor: BG, color: "#82AAF0", children: " space copy-mode \xB7 f filter \xB7 s sessions \xB7 esc menu \xB7 q quit " })
|
|
7686
7668
|
] })
|
|
7687
7669
|
] });
|
|
7688
7670
|
}
|
|
7689
|
-
var SPIN, BG, DIM_FLOOR, LOCAL_LOG, RING,
|
|
7671
|
+
var SPIN, BG, DIM_FLOOR, LOCAL_LOG, RING, STREAM_KEEP, hhmmss, fmtUp, FILTERS, SESS_FILTERS, sessStatus;
|
|
7690
7672
|
var init_Live = __esm({
|
|
7691
7673
|
"src/tui/panels/Live.tsx"() {
|
|
7692
7674
|
"use strict";
|
|
@@ -7698,7 +7680,6 @@ var init_Live = __esm({
|
|
|
7698
7680
|
DIM_FLOOR = "#233457";
|
|
7699
7681
|
LOCAL_LOG = join5(homedir3(), ".solongate", "local-logs", "solongate-audit.jsonl");
|
|
7700
7682
|
RING = join5(process.cwd(), ".solongate", ".eval-ring.jsonl");
|
|
7701
|
-
DUMP = join5(homedir3(), ".solongate", "live-stream.log");
|
|
7702
7683
|
STREAM_KEEP = 100;
|
|
7703
7684
|
hhmmss = (ts) => {
|
|
7704
7685
|
const d = new Date(ts);
|
|
@@ -7710,6 +7691,8 @@ var init_Live = __esm({
|
|
|
7710
7691
|
return `${p(Math.floor(s / 3600))}:${p(Math.floor(s % 3600 / 60))}:${p(s % 60)}`;
|
|
7711
7692
|
};
|
|
7712
7693
|
FILTERS = ["all", "local", "cloud"];
|
|
7694
|
+
SESS_FILTERS = ["all", "active", "idle", "ended"];
|
|
7695
|
+
sessStatus = (lastAt, now) => now - lastAt < 9e4 ? "active" : now - lastAt < 3e5 ? "idle" : "ended";
|
|
7713
7696
|
}
|
|
7714
7697
|
});
|
|
7715
7698
|
|
|
@@ -9371,8 +9354,8 @@ __export(global_install_exports, {
|
|
|
9371
9354
|
runGlobalRestore: () => runGlobalRestore,
|
|
9372
9355
|
unlockProtected: () => unlockProtected
|
|
9373
9356
|
});
|
|
9374
|
-
import { readFileSync as readFileSync6, writeFileSync as
|
|
9375
|
-
import { resolve as resolve4, join as join6, dirname
|
|
9357
|
+
import { readFileSync as readFileSync6, writeFileSync as writeFileSync3, existsSync as existsSync4, mkdirSync as mkdirSync3 } from "fs";
|
|
9358
|
+
import { resolve as resolve4, join as join6, dirname } from "path";
|
|
9376
9359
|
import { homedir as homedir4 } from "os";
|
|
9377
9360
|
import { fileURLToPath } from "url";
|
|
9378
9361
|
import { createInterface } from "readline";
|
|
@@ -9484,13 +9467,13 @@ function runGlobalRestore() {
|
|
|
9484
9467
|
unlockProtected();
|
|
9485
9468
|
removeClaudeShim();
|
|
9486
9469
|
if (existsSync4(p.backupPath)) {
|
|
9487
|
-
|
|
9470
|
+
writeFileSync3(p.settingsPath, readFileSync6(p.backupPath, "utf-8"));
|
|
9488
9471
|
console.log(` Restored ${p.settingsPath} from backup.`);
|
|
9489
9472
|
} else if (existsSync4(p.settingsPath)) {
|
|
9490
9473
|
try {
|
|
9491
9474
|
const s = JSON.parse(readFileSync6(p.settingsPath, "utf-8"));
|
|
9492
9475
|
delete s.hooks;
|
|
9493
|
-
|
|
9476
|
+
writeFileSync3(p.settingsPath, JSON.stringify(s, null, 2) + "\n");
|
|
9494
9477
|
console.log(` Removed SolonGate hooks from ${p.settingsPath}.`);
|
|
9495
9478
|
} catch {
|
|
9496
9479
|
}
|
|
@@ -9534,8 +9517,8 @@ function writeShimBlock(file, block) {
|
|
|
9534
9517
|
if (content.length && !content.endsWith("\n")) content += "\n";
|
|
9535
9518
|
content += block + "\n";
|
|
9536
9519
|
}
|
|
9537
|
-
|
|
9538
|
-
|
|
9520
|
+
mkdirSync3(dirname(file), { recursive: true });
|
|
9521
|
+
writeFileSync3(file, content);
|
|
9539
9522
|
}
|
|
9540
9523
|
function installClaudeShim(shieldPath) {
|
|
9541
9524
|
const real = resolveRealClaude();
|
|
@@ -9592,22 +9575,22 @@ async function runGlobalInstall(opts = {}) {
|
|
|
9592
9575
|
process.exit(1);
|
|
9593
9576
|
}
|
|
9594
9577
|
const apiUrl = opts.apiUrl || process.env["SOLONGATE_API_URL"] || "https://api.solongate.com";
|
|
9595
|
-
|
|
9596
|
-
|
|
9578
|
+
mkdirSync3(p.hooksDir, { recursive: true });
|
|
9579
|
+
mkdirSync3(p.claudeDir, { recursive: true });
|
|
9597
9580
|
unlockProtected();
|
|
9598
|
-
|
|
9599
|
-
|
|
9600
|
-
|
|
9601
|
-
|
|
9581
|
+
writeFileSync3(join6(p.hooksDir, "guard.mjs"), readGuard());
|
|
9582
|
+
writeFileSync3(join6(p.hooksDir, "audit.mjs"), readHook("audit.mjs"));
|
|
9583
|
+
writeFileSync3(join6(p.hooksDir, "stop.mjs"), readHook("stop.mjs"));
|
|
9584
|
+
writeFileSync3(join6(p.hooksDir, "shield.mjs"), readHook("shield.mjs"));
|
|
9602
9585
|
console.log(` Installed hooks \u2192 ${p.hooksDir}`);
|
|
9603
9586
|
removeClaudeShim();
|
|
9604
|
-
|
|
9587
|
+
writeFileSync3(p.configPath, JSON.stringify({ apiKey, apiUrl }, null, 2) + "\n");
|
|
9605
9588
|
console.log(` Wrote ${p.configPath}`);
|
|
9606
9589
|
let existing = {};
|
|
9607
9590
|
if (existsSync4(p.settingsPath)) {
|
|
9608
9591
|
const raw = readFileSync6(p.settingsPath, "utf-8");
|
|
9609
9592
|
if (!existsSync4(p.backupPath)) {
|
|
9610
|
-
|
|
9593
|
+
writeFileSync3(p.backupPath, raw);
|
|
9611
9594
|
console.log(` Backed up existing settings \u2192 ${p.backupPath}`);
|
|
9612
9595
|
}
|
|
9613
9596
|
try {
|
|
@@ -9628,7 +9611,7 @@ async function runGlobalInstall(opts = {}) {
|
|
|
9628
9611
|
Stop: [{ matcher: "", hooks: [{ type: "command", command: `"${nodeBin}" "${stopAbs}" claude-code "Claude Code"` }] }]
|
|
9629
9612
|
}
|
|
9630
9613
|
};
|
|
9631
|
-
|
|
9614
|
+
writeFileSync3(p.settingsPath, JSON.stringify(merged, null, 2) + "\n");
|
|
9632
9615
|
console.log(` Registered global hooks \u2192 ${p.settingsPath}`);
|
|
9633
9616
|
if (process.env["SOLONGATE_OS_LOCK"] === "1") {
|
|
9634
9617
|
lockProtected();
|
|
@@ -9642,7 +9625,7 @@ var __dirname, HOOKS_DIR, SHIM_BEGIN, SHIM_END;
|
|
|
9642
9625
|
var init_global_install = __esm({
|
|
9643
9626
|
"src/global-install.ts"() {
|
|
9644
9627
|
"use strict";
|
|
9645
|
-
__dirname =
|
|
9628
|
+
__dirname = dirname(fileURLToPath(import.meta.url));
|
|
9646
9629
|
HOOKS_DIR = resolve4(__dirname, "..", "hooks");
|
|
9647
9630
|
SHIM_BEGIN = "# >>> SolonGate shield (auto secret redaction) >>>";
|
|
9648
9631
|
SHIM_END = "# <<< SolonGate shield <<<";
|
|
@@ -10292,7 +10275,7 @@ var init_logs_server = __esm({
|
|
|
10292
10275
|
|
|
10293
10276
|
// src/inject.ts
|
|
10294
10277
|
var inject_exports = {};
|
|
10295
|
-
import { readFileSync as readFileSync9, writeFileSync as
|
|
10278
|
+
import { readFileSync as readFileSync9, writeFileSync as writeFileSync4, existsSync as existsSync6, copyFileSync } from "fs";
|
|
10296
10279
|
import { resolve as resolve7 } from "path";
|
|
10297
10280
|
import { execSync } from "child_process";
|
|
10298
10281
|
function parseInjectArgs(argv) {
|
|
@@ -10600,7 +10583,7 @@ async function main2() {
|
|
|
10600
10583
|
log3("");
|
|
10601
10584
|
log3(` Backup: ${backupPath}`);
|
|
10602
10585
|
}
|
|
10603
|
-
|
|
10586
|
+
writeFileSync4(entryFile, result.modified);
|
|
10604
10587
|
log3("");
|
|
10605
10588
|
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");
|
|
10606
10589
|
log3(" \u2502 SolonGate SDK injected successfully! \u2502");
|
|
@@ -10629,7 +10612,7 @@ var init_inject = __esm({
|
|
|
10629
10612
|
|
|
10630
10613
|
// src/create.ts
|
|
10631
10614
|
var create_exports = {};
|
|
10632
|
-
import { mkdirSync as
|
|
10615
|
+
import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync5, existsSync as existsSync7 } from "fs";
|
|
10633
10616
|
import { resolve as resolve8, join as join8 } from "path";
|
|
10634
10617
|
import { execSync as execSync2 } from "child_process";
|
|
10635
10618
|
function withSpinner(message, fn) {
|
|
@@ -10709,7 +10692,7 @@ EXAMPLES
|
|
|
10709
10692
|
`);
|
|
10710
10693
|
}
|
|
10711
10694
|
function createProject(dir, name, _policy) {
|
|
10712
|
-
|
|
10695
|
+
writeFileSync5(
|
|
10713
10696
|
join8(dir, "package.json"),
|
|
10714
10697
|
JSON.stringify(
|
|
10715
10698
|
{
|
|
@@ -10739,7 +10722,7 @@ function createProject(dir, name, _policy) {
|
|
|
10739
10722
|
2
|
|
10740
10723
|
) + "\n"
|
|
10741
10724
|
);
|
|
10742
|
-
|
|
10725
|
+
writeFileSync5(
|
|
10743
10726
|
join8(dir, "tsconfig.json"),
|
|
10744
10727
|
JSON.stringify(
|
|
10745
10728
|
{
|
|
@@ -10760,8 +10743,8 @@ function createProject(dir, name, _policy) {
|
|
|
10760
10743
|
2
|
|
10761
10744
|
) + "\n"
|
|
10762
10745
|
);
|
|
10763
|
-
|
|
10764
|
-
|
|
10746
|
+
mkdirSync4(join8(dir, "src"), { recursive: true });
|
|
10747
|
+
writeFileSync5(
|
|
10765
10748
|
join8(dir, "src", "index.ts"),
|
|
10766
10749
|
`#!/usr/bin/env node
|
|
10767
10750
|
|
|
@@ -10803,7 +10786,7 @@ console.log('');
|
|
|
10803
10786
|
console.log('Press Ctrl+C to stop.');
|
|
10804
10787
|
`
|
|
10805
10788
|
);
|
|
10806
|
-
|
|
10789
|
+
writeFileSync5(
|
|
10807
10790
|
join8(dir, ".mcp.json"),
|
|
10808
10791
|
JSON.stringify(
|
|
10809
10792
|
{
|
|
@@ -10821,12 +10804,12 @@ console.log('Press Ctrl+C to stop.');
|
|
|
10821
10804
|
2
|
|
10822
10805
|
) + "\n"
|
|
10823
10806
|
);
|
|
10824
|
-
|
|
10807
|
+
writeFileSync5(
|
|
10825
10808
|
join8(dir, ".env"),
|
|
10826
10809
|
`SOLONGATE_API_KEY=sg_live_YOUR_KEY_HERE
|
|
10827
10810
|
`
|
|
10828
10811
|
);
|
|
10829
|
-
|
|
10812
|
+
writeFileSync5(
|
|
10830
10813
|
join8(dir, ".gitignore"),
|
|
10831
10814
|
`node_modules/
|
|
10832
10815
|
dist/
|
|
@@ -10846,7 +10829,7 @@ async function main3() {
|
|
|
10846
10829
|
process.exit(1);
|
|
10847
10830
|
}
|
|
10848
10831
|
withSpinner(`Setting up ${opts.name}...`, () => {
|
|
10849
|
-
|
|
10832
|
+
mkdirSync4(dir, { recursive: true });
|
|
10850
10833
|
createProject(dir, opts.name, opts.policy);
|
|
10851
10834
|
});
|
|
10852
10835
|
if (!opts.noInstall) {
|
|
@@ -10920,7 +10903,7 @@ var init_create = __esm({
|
|
|
10920
10903
|
|
|
10921
10904
|
// src/pull-push.ts
|
|
10922
10905
|
var pull_push_exports = {};
|
|
10923
|
-
import { readFileSync as readFileSync10, writeFileSync as
|
|
10906
|
+
import { readFileSync as readFileSync10, writeFileSync as writeFileSync6, existsSync as existsSync8 } from "fs";
|
|
10924
10907
|
import { resolve as resolve9 } from "path";
|
|
10925
10908
|
function loadEnv() {
|
|
10926
10909
|
if (process.env.SOLONGATE_API_KEY) return;
|
|
@@ -11115,7 +11098,7 @@ async function pull(apiKey, file, policyId) {
|
|
|
11115
11098
|
const policy = await fetchCloudPolicy(apiKey, API_URL, policyId);
|
|
11116
11099
|
const { id: _id, ...policyWithoutId } = policy;
|
|
11117
11100
|
const json = JSON.stringify(policyWithoutId, null, 2) + "\n";
|
|
11118
|
-
|
|
11101
|
+
writeFileSync6(file, json, "utf-8");
|
|
11119
11102
|
log5("");
|
|
11120
11103
|
log5(green2(" Saved to: ") + file);
|
|
11121
11104
|
log5(` ${dim2("Name:")} ${policy.name}`);
|