@solongate/proxy 0.80.0 → 0.81.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 +333 -139
- package/dist/tui/config.d.ts +6 -0
- package/dist/tui/index.js +230 -55
- package/dist/tui/panels/Agents.d.ts +4 -0
- package/dist/tui/theme.d.ts +2 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6702,6 +6702,34 @@ var init_client = __esm({
|
|
|
6702
6702
|
}
|
|
6703
6703
|
});
|
|
6704
6704
|
|
|
6705
|
+
// src/tui/config.ts
|
|
6706
|
+
import { readFileSync as readFileSync5 } from "fs";
|
|
6707
|
+
import { homedir as homedir3 } from "os";
|
|
6708
|
+
import { join as join5 } from "path";
|
|
6709
|
+
function loadConfig() {
|
|
6710
|
+
if (cached2) return cached2;
|
|
6711
|
+
const defaults = { notifications: true };
|
|
6712
|
+
try {
|
|
6713
|
+
const raw = readFileSync5(join5(homedir3(), ".solongate", "tui-config.json"), "utf-8");
|
|
6714
|
+
const j = JSON.parse(raw);
|
|
6715
|
+
cached2 = {
|
|
6716
|
+
notifications: j.notifications !== false,
|
|
6717
|
+
accent: typeof j.accent === "string" ? j.accent : void 0,
|
|
6718
|
+
pollMs: typeof j.pollMs === "number" ? j.pollMs : void 0
|
|
6719
|
+
};
|
|
6720
|
+
} catch {
|
|
6721
|
+
cached2 = defaults;
|
|
6722
|
+
}
|
|
6723
|
+
return cached2;
|
|
6724
|
+
}
|
|
6725
|
+
var cached2;
|
|
6726
|
+
var init_config2 = __esm({
|
|
6727
|
+
"src/tui/config.ts"() {
|
|
6728
|
+
"use strict";
|
|
6729
|
+
cached2 = null;
|
|
6730
|
+
}
|
|
6731
|
+
});
|
|
6732
|
+
|
|
6705
6733
|
// src/tui/theme.ts
|
|
6706
6734
|
function decisionColor(decision) {
|
|
6707
6735
|
const d = (decision || "").toUpperCase();
|
|
@@ -6735,13 +6763,15 @@ function ago(ts) {
|
|
|
6735
6763
|
if (s < 86400) return `${Math.floor(s / 3600)}h`;
|
|
6736
6764
|
return `${Math.floor(s / 86400)}d`;
|
|
6737
6765
|
}
|
|
6738
|
-
var theme, BLOCKS;
|
|
6766
|
+
var accent, theme, BLOCKS;
|
|
6739
6767
|
var init_theme = __esm({
|
|
6740
6768
|
"src/tui/theme.ts"() {
|
|
6741
6769
|
"use strict";
|
|
6770
|
+
init_config2();
|
|
6771
|
+
accent = loadConfig().accent;
|
|
6742
6772
|
theme = {
|
|
6743
|
-
accent: "cyan",
|
|
6744
|
-
accentBright: "#5a8ce6",
|
|
6773
|
+
accent: accent || "cyan",
|
|
6774
|
+
accentBright: accent || "#5a8ce6",
|
|
6745
6775
|
ok: "green",
|
|
6746
6776
|
warn: "yellow",
|
|
6747
6777
|
bad: "red",
|
|
@@ -7108,9 +7138,9 @@ var init_hooks = __esm({
|
|
|
7108
7138
|
import { Box as Box2, Text as Text2, useInput } from "ink";
|
|
7109
7139
|
import TextInput from "ink-text-input";
|
|
7110
7140
|
import { spawn } from "child_process";
|
|
7111
|
-
import { closeSync, openSync, readSync, statSync } from "fs";
|
|
7112
|
-
import { homedir as
|
|
7113
|
-
import { join as
|
|
7141
|
+
import { closeSync, mkdirSync as mkdirSync3, openSync, readSync, statSync, writeFileSync as writeFileSync3 } from "fs";
|
|
7142
|
+
import { homedir as homedir4 } from "os";
|
|
7143
|
+
import { join as join6 } from "path";
|
|
7114
7144
|
import { useCallback as useCallback2, useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
|
|
7115
7145
|
import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
7116
7146
|
function tailLines(file, maxBytes = 131072) {
|
|
@@ -7420,6 +7450,7 @@ function LivePanel({ active: active2 }) {
|
|
|
7420
7450
|
(id, title, msg, level = "warn") => {
|
|
7421
7451
|
pushLog(`${level === "bad" ? "\u26D4" : "\u23F8"} ${msg}`, level);
|
|
7422
7452
|
setAlerts((a) => [...a.filter((x) => x.id !== id), { id, msg, level, until: Date.now() + 15e3 }].slice(-4));
|
|
7453
|
+
if (!CONFIG.notifications) return;
|
|
7423
7454
|
try {
|
|
7424
7455
|
process.stdout.write("\x07");
|
|
7425
7456
|
} catch {
|
|
@@ -7647,7 +7678,16 @@ function LivePanel({ active: active2 }) {
|
|
|
7647
7678
|
else if (input === "d") toggleSignal("deny");
|
|
7648
7679
|
else if (input === "x") toggleSignal("dlp");
|
|
7649
7680
|
else if (input === "r") toggleSignal("ratelimit");
|
|
7650
|
-
else if (
|
|
7681
|
+
else if (input === "e") {
|
|
7682
|
+
const file = join6(homedir4(), ".solongate", "live-export.jsonl");
|
|
7683
|
+
try {
|
|
7684
|
+
mkdirSync3(join6(homedir4(), ".solongate"), { recursive: true });
|
|
7685
|
+
writeFileSync3(file, visibleDesc.map((x) => JSON.stringify(x)).join("\n") + "\n");
|
|
7686
|
+
setActionMsg({ text: `\u2713 exported ${visibleDesc.length} lines \u2192 ${file}`, level: "ok", until: Date.now() + 6e3 });
|
|
7687
|
+
} catch (err2) {
|
|
7688
|
+
setActionMsg({ text: "\u2717 export failed: " + (err2 instanceof Error ? err2.message : String(err2)), level: "bad", until: Date.now() + 6e3 });
|
|
7689
|
+
}
|
|
7690
|
+
} else if (key.downArrow) setSel((n) => Math.min(visibleDesc.length - 1, n + 1));
|
|
7651
7691
|
else if (key.upArrow) setSel((n) => Math.max(0, n - 1));
|
|
7652
7692
|
else if (key.pageDown) setSel((n) => Math.min(visibleDesc.length - 1, n + streamBodyRows));
|
|
7653
7693
|
else if (key.pageUp) setSel((n) => Math.max(0, n - streamBodyRows));
|
|
@@ -7896,18 +7936,20 @@ function LivePanel({ active: active2 }) {
|
|
|
7896
7936
|
] })
|
|
7897
7937
|
] });
|
|
7898
7938
|
}
|
|
7899
|
-
var SPIN, BG, DIM_FLOOR, LOCAL_LOG, RING, hhmmss, fmtUp, FILTERS, sessStatus, STATUS_STYLE;
|
|
7939
|
+
var CONFIG, SPIN, BG, DIM_FLOOR, LOCAL_LOG, RING, hhmmss, fmtUp, FILTERS, sessStatus, STATUS_STYLE;
|
|
7900
7940
|
var init_Live = __esm({
|
|
7901
7941
|
"src/tui/panels/Live.tsx"() {
|
|
7902
7942
|
"use strict";
|
|
7903
7943
|
init_api_client();
|
|
7944
|
+
init_config2();
|
|
7904
7945
|
init_hooks();
|
|
7905
7946
|
init_theme();
|
|
7947
|
+
CONFIG = loadConfig();
|
|
7906
7948
|
SPIN = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
7907
7949
|
BG = "#12234f";
|
|
7908
7950
|
DIM_FLOOR = "#233457";
|
|
7909
|
-
LOCAL_LOG =
|
|
7910
|
-
RING =
|
|
7951
|
+
LOCAL_LOG = join6(homedir4(), ".solongate", "local-logs", "solongate-audit.jsonl");
|
|
7952
|
+
RING = join6(process.cwd(), ".solongate", ".eval-ring.jsonl");
|
|
7911
7953
|
hhmmss = (ts) => {
|
|
7912
7954
|
const d = new Date(ts);
|
|
7913
7955
|
return Number.isNaN(d.getTime()) ? "--:--:--" : d.toTimeString().slice(0, 8);
|
|
@@ -7931,7 +7973,7 @@ var init_Live = __esm({
|
|
|
7931
7973
|
import { Box as Box3, Text as Text3, useInput as useInput2 } from "ink";
|
|
7932
7974
|
import TextInput2 from "ink-text-input";
|
|
7933
7975
|
import { useEffect as useEffect3, useState as useState3 } from "react";
|
|
7934
|
-
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
7976
|
+
import { Fragment as Fragment3, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
7935
7977
|
function ruleSummary(r) {
|
|
7936
7978
|
const bits = [];
|
|
7937
7979
|
for (const [g, tag] of [["commandConstraints", "cmd"], ["pathConstraints", "path"], ["filenameConstraints", "file"], ["urlConstraints", "url"]]) {
|
|
@@ -7961,6 +8003,11 @@ function PoliciesPanel({ focused }) {
|
|
|
7961
8003
|
() => view === "versions" && selected ? api.policies.versions(selected.id, { limit: 50 }) : Promise.resolve(null),
|
|
7962
8004
|
[view, selected?.id]
|
|
7963
8005
|
);
|
|
8006
|
+
const diffVer = versionsQ.data?.versions[vi]?.version;
|
|
8007
|
+
const diffQ = useLoader(
|
|
8008
|
+
() => view === "versions" && selected && diffVer !== void 0 ? api.policies.get(selected.id, diffVer) : Promise.resolve(null),
|
|
8009
|
+
[view, selected?.id, diffVer]
|
|
8010
|
+
);
|
|
7964
8011
|
useEffect3(() => {
|
|
7965
8012
|
if (detail.data) {
|
|
7966
8013
|
setRules(detail.data.rules);
|
|
@@ -8164,6 +8211,23 @@ function PoliciesPanel({ focused }) {
|
|
|
8164
8211
|
])
|
|
8165
8212
|
}
|
|
8166
8213
|
) }),
|
|
8214
|
+
/* @__PURE__ */ jsxs3(Box3, { marginTop: 1, flexDirection: "column", children: [
|
|
8215
|
+
/* @__PURE__ */ jsx3(Text3, { color: theme.dim, children: `Diff v${diffVer ?? "?"} vs current draft` }),
|
|
8216
|
+
(() => {
|
|
8217
|
+
const old = diffQ.data?.rules ?? [];
|
|
8218
|
+
const cur = rules;
|
|
8219
|
+
const oldIds = new Set(old.map((r) => r.id));
|
|
8220
|
+
const curIds = new Set(cur.map((r) => r.id));
|
|
8221
|
+
const added = cur.filter((r) => !oldIds.has(r.id));
|
|
8222
|
+
const removed = old.filter((r) => !curIds.has(r.id));
|
|
8223
|
+
if (diffQ.loading && !diffQ.data) return /* @__PURE__ */ jsx3(Text3, { color: theme.dim, children: " loading\u2026" });
|
|
8224
|
+
if (!added.length && !removed.length) return /* @__PURE__ */ jsx3(Text3, { color: theme.dim, children: " identical rule set" });
|
|
8225
|
+
return /* @__PURE__ */ jsxs3(Fragment3, { children: [
|
|
8226
|
+
added.slice(0, 4).map((r) => /* @__PURE__ */ jsx3(Text3, { wrap: "truncate", color: theme.ok, children: ` + ${r.effect} ${truncate2(r.toolPattern, 18)} ${truncate2(r.description || r.id, 30)}` }, "a" + r.id)),
|
|
8227
|
+
removed.slice(0, 4).map((r) => /* @__PURE__ */ jsx3(Text3, { wrap: "truncate", color: theme.bad, children: ` - ${r.effect} ${truncate2(r.toolPattern, 18)} ${truncate2(r.description || r.id, 30)}` }, "r" + r.id))
|
|
8228
|
+
] });
|
|
8229
|
+
})()
|
|
8230
|
+
] }),
|
|
8167
8231
|
status ? /* @__PURE__ */ jsx3(Text3, { color: status.startsWith("\u2717") ? theme.bad : theme.ok, children: status }) : null
|
|
8168
8232
|
] }) });
|
|
8169
8233
|
}
|
|
@@ -8308,6 +8372,20 @@ function RateLimitPanel({ focused }) {
|
|
|
8308
8372
|
/* @__PURE__ */ jsx4(FieldRow, { label: "Per hour", active: focused && fi === 2, children: /* @__PURE__ */ jsx4(Text4, { bold: true, children: draft.perHour === 0 ? "off" : draft.perHour }) }),
|
|
8309
8373
|
/* @__PURE__ */ jsx4(FieldRow, { label: "Per day", active: focused && fi === 3, children: /* @__PURE__ */ jsx4(Text4, { bold: true, children: draft.perDay === 0 ? "off" : draft.perDay }) })
|
|
8310
8374
|
] }),
|
|
8375
|
+
draft.perMinute > 0 ? (() => {
|
|
8376
|
+
const now = minuteSeries.slice(-1)[0] ?? 0;
|
|
8377
|
+
const pct = Math.min(100, Math.round(now / draft.perMinute * 100));
|
|
8378
|
+
const width2 = 30;
|
|
8379
|
+
const filled = Math.min(width2, Math.round(now / draft.perMinute * width2));
|
|
8380
|
+
const col = pct >= 100 ? theme.bad : pct >= 80 ? theme.warn : theme.ok;
|
|
8381
|
+
return /* @__PURE__ */ jsxs4(Box4, { marginTop: 1, children: [
|
|
8382
|
+
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: "load " }),
|
|
8383
|
+
/* @__PURE__ */ jsx4(Text4, { color: col, children: "\u2588".repeat(filled) }),
|
|
8384
|
+
/* @__PURE__ */ jsx4(Text4, { color: "#233457", children: "\u2591".repeat(Math.max(0, width2 - filled)) }),
|
|
8385
|
+
/* @__PURE__ */ jsx4(Text4, { color: col, children: ` ${now}/${draft.perMinute} ` }),
|
|
8386
|
+
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: `(${pct}% this min)` })
|
|
8387
|
+
] });
|
|
8388
|
+
})() : null,
|
|
8311
8389
|
dirty || status ? /* @__PURE__ */ jsxs4(Box4, { marginTop: 1, children: [
|
|
8312
8390
|
dirty ? /* @__PURE__ */ jsx4(Text4, { color: theme.warn, children: "\u25CF unsaved \u2014 press s to apply " }) : null,
|
|
8313
8391
|
status ? /* @__PURE__ */ jsx4(Text4, { color: status.startsWith("\u2717") ? theme.bad : theme.ok, children: status }) : null
|
|
@@ -8532,10 +8610,27 @@ function DlpPanel({ focused }) {
|
|
|
8532
8610
|
}
|
|
8533
8611
|
)
|
|
8534
8612
|
] }) : null,
|
|
8613
|
+
adding === "re" ? /* @__PURE__ */ jsx5(RegexTest, { re: newRe }) : null,
|
|
8535
8614
|
status ? /* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx5(Text5, { color: status.startsWith("\u2717") ? theme.bad : theme.ok, children: status }) }) : null
|
|
8536
8615
|
] }) : null });
|
|
8537
8616
|
}
|
|
8538
|
-
|
|
8617
|
+
function RegexTest({ re }) {
|
|
8618
|
+
if (!re.trim()) return /* @__PURE__ */ jsx5(Text5, { color: theme.dim, children: " regex: type a pattern\u2026" });
|
|
8619
|
+
let rx = null;
|
|
8620
|
+
let err2 = "";
|
|
8621
|
+
try {
|
|
8622
|
+
rx = new RegExp(re);
|
|
8623
|
+
} catch (e) {
|
|
8624
|
+
err2 = e instanceof Error ? e.message : String(e);
|
|
8625
|
+
}
|
|
8626
|
+
if (!rx) return /* @__PURE__ */ jsx5(Text5, { color: theme.bad, children: ` \u2717 invalid: ${err2.slice(0, 50)}` });
|
|
8627
|
+
const hits = SAMPLES.filter((s) => rx.test(s));
|
|
8628
|
+
return /* @__PURE__ */ jsxs5(Text5, { wrap: "truncate", children: [
|
|
8629
|
+
/* @__PURE__ */ jsx5(Text5, { color: theme.ok, children: " \u2713 valid" }),
|
|
8630
|
+
/* @__PURE__ */ jsx5(Text5, { color: theme.dim, children: hits.length ? ` matches ${hits.length}/${SAMPLES.length} samples: ${hits.map((h) => h.slice(0, 8)).join(", ")}` : " (no sample match \u2014 will only catch your custom secrets)" })
|
|
8631
|
+
] });
|
|
8632
|
+
}
|
|
8633
|
+
var MODES2, SAMPLES;
|
|
8539
8634
|
var init_Dlp = __esm({
|
|
8540
8635
|
"src/tui/panels/Dlp.tsx"() {
|
|
8541
8636
|
"use strict";
|
|
@@ -8544,6 +8639,7 @@ var init_Dlp = __esm({
|
|
|
8544
8639
|
init_hooks();
|
|
8545
8640
|
init_theme();
|
|
8546
8641
|
MODES2 = ["off", "detect", "block"];
|
|
8642
|
+
SAMPLES = ["AKIA1234567890ABCD00", "sk-ant-api03-xxxxxxxx", "ghp_16chars0000000000000000000000000000", "password=hunter2", "Bearer eyJhbGciOi"];
|
|
8547
8643
|
}
|
|
8548
8644
|
});
|
|
8549
8645
|
|
|
@@ -8839,18 +8935,114 @@ var init_Audit = __esm({
|
|
|
8839
8935
|
}
|
|
8840
8936
|
});
|
|
8841
8937
|
|
|
8842
|
-
// src/tui/
|
|
8843
|
-
import { Box as Box8, Text as Text8,
|
|
8938
|
+
// src/tui/panels/Agents.tsx
|
|
8939
|
+
import { Box as Box8, Text as Text8, useInput as useInput6 } from "ink";
|
|
8844
8940
|
import { useState as useState7 } from "react";
|
|
8845
|
-
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
8941
|
+
import { Fragment as Fragment4, jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
8942
|
+
function Bar({ label, value, max = 100, width: width2 = 16, color = theme.accent }) {
|
|
8943
|
+
const filled = max > 0 ? Math.round(Math.min(value, max) / max * width2) : 0;
|
|
8944
|
+
return /* @__PURE__ */ jsxs8(Text8, { wrap: "truncate", children: [
|
|
8945
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: label.padEnd(9) }),
|
|
8946
|
+
/* @__PURE__ */ jsx8(Text8, { color, children: "\u2588".repeat(filled) }),
|
|
8947
|
+
/* @__PURE__ */ jsx8(Text8, { color: "#233457", children: "\u2591".repeat(Math.max(0, width2 - filled)) }),
|
|
8948
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: " " + value })
|
|
8949
|
+
] });
|
|
8950
|
+
}
|
|
8951
|
+
function AgentsPanel({ focused }) {
|
|
8952
|
+
const live2 = useLoader(() => api.agents.live({ limit: 30, includeDeactivated: true }));
|
|
8953
|
+
usePoll(live2.reload, 6e3, focused ? false : true);
|
|
8954
|
+
const [sel, setSel] = useState7(0);
|
|
8955
|
+
const agents = (live2.data?.agents ?? []).filter((a) => a.agent_id);
|
|
8956
|
+
const selected = agents[Math.min(sel, Math.max(0, agents.length - 1))];
|
|
8957
|
+
const detail = useLoader(() => selected?.agent_id ? api.agents.get(selected.agent_id) : Promise.resolve(null), [selected?.agent_id]);
|
|
8958
|
+
useInput6(
|
|
8959
|
+
(_input, key) => {
|
|
8960
|
+
if (key.upArrow) setSel((n) => Math.max(0, n - 1));
|
|
8961
|
+
else if (key.downArrow) setSel((n) => Math.min(agents.length - 1, n + 1));
|
|
8962
|
+
},
|
|
8963
|
+
{ isActive: focused }
|
|
8964
|
+
);
|
|
8965
|
+
const d = detail.data;
|
|
8966
|
+
const base = d?.baseline;
|
|
8967
|
+
const radar = base?.radar;
|
|
8968
|
+
const anomalies2 = d?.anomalies ?? [];
|
|
8969
|
+
const tmap = d?.trust_map;
|
|
8970
|
+
const tools = tmap?.tools ?? [];
|
|
8971
|
+
const resources = tmap?.resources ?? [];
|
|
8972
|
+
const listW = 30;
|
|
8973
|
+
return /* @__PURE__ */ jsx8(DataView, { loading: live2.loading && !live2.data, error: live2.error, empty: !!live2.data && agents.length === 0, emptyText: "No identified agents yet.", children: /* @__PURE__ */ jsxs8(Box8, { children: [
|
|
8974
|
+
/* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", width: listW, marginRight: 2, overflow: "hidden", children: [
|
|
8975
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: focused ? "\u2191\u2193 select agent" : "press \u2192 to browse" }),
|
|
8976
|
+
agents.slice(0, 16).map((a, i) => /* @__PURE__ */ jsxs8(Text8, { wrap: "truncate", backgroundColor: focused && i === sel ? "#1c2f63" : void 0, bold: i === sel, children: [
|
|
8977
|
+
/* @__PURE__ */ jsxs8(Text8, { color: statusColor(a.status), children: [
|
|
8978
|
+
a.status === "active" ? "\u25CF" : a.status === "idle" ? "\u25D0" : "\u25CB",
|
|
8979
|
+
" "
|
|
8980
|
+
] }),
|
|
8981
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.accent, children: truncate2(a.agent_name ?? a.agent_id ?? "?", 16).padEnd(17) }),
|
|
8982
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: `t${a.trust_score}` })
|
|
8983
|
+
] }, a.session_id))
|
|
8984
|
+
] }),
|
|
8985
|
+
/* @__PURE__ */ jsx8(Box8, { flexDirection: "column", flexGrow: 1, overflow: "hidden", children: !selected ? /* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: "select an agent" }) : detail.loading && !d ? /* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: "loading profile\u2026" }) : !d ? /* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: "no profile (agent has no calls yet)" }) : /* @__PURE__ */ jsxs8(Fragment4, { children: [
|
|
8986
|
+
/* @__PURE__ */ jsxs8(Box8, { children: [
|
|
8987
|
+
/* @__PURE__ */ jsx8(Text8, { bold: true, color: theme.accentBright, children: truncate2(selected.agent_name ?? selected.agent_id ?? "?", 22) }),
|
|
8988
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: ` trust ${base?.trustScore ?? "\u2014"}/100 \xB7 ${base?.character ?? ""}` })
|
|
8989
|
+
] }),
|
|
8990
|
+
base?.characterBlurb ? /* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: truncate2(String(base.characterBlurb), 70) }) : null,
|
|
8991
|
+
radar ? /* @__PURE__ */ jsxs8(Box8, { marginTop: 1, flexDirection: "column", children: [
|
|
8992
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: "Behaviour radar (0\u2013100)" }),
|
|
8993
|
+
/* @__PURE__ */ jsx8(Bar, { label: "read", value: Math.round((radar.read ?? 0) * 100) }),
|
|
8994
|
+
/* @__PURE__ */ jsx8(Bar, { label: "write", value: Math.round((radar.write ?? 0) * 100), color: theme.warn }),
|
|
8995
|
+
/* @__PURE__ */ jsx8(Bar, { label: "execute", value: Math.round((radar.execute ?? 0) * 100), color: theme.warn }),
|
|
8996
|
+
/* @__PURE__ */ jsx8(Bar, { label: "network", value: Math.round((radar.network ?? 0) * 100) }),
|
|
8997
|
+
/* @__PURE__ */ jsx8(Bar, { label: "complian.", value: Math.round((radar.compliance ?? 0) * 100), color: theme.ok })
|
|
8998
|
+
] }) : null,
|
|
8999
|
+
/* @__PURE__ */ jsxs8(Box8, { marginTop: 1, flexDirection: "column", children: [
|
|
9000
|
+
/* @__PURE__ */ jsxs8(Text8, { color: theme.dim, children: [
|
|
9001
|
+
"Anomalies ",
|
|
9002
|
+
anomalies2.length ? `(${anomalies2.length})` : ""
|
|
9003
|
+
] }),
|
|
9004
|
+
anomalies2.length === 0 ? /* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: " none" }) : anomalies2.slice(0, 4).map((an, i) => /* @__PURE__ */ jsxs8(Text8, { wrap: "truncate", children: [
|
|
9005
|
+
/* @__PURE__ */ jsx8(Text8, { color: sevColor(String(an.severity)), children: ` ${String(an.severity).toUpperCase().slice(0, 4).padEnd(5)}` }),
|
|
9006
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.accent, children: String(an.kind).padEnd(12) }),
|
|
9007
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: truncate2(String(an.description ?? ""), 44) })
|
|
9008
|
+
] }, i))
|
|
9009
|
+
] }),
|
|
9010
|
+
/* @__PURE__ */ jsxs8(Box8, { marginTop: 1, flexDirection: "column", children: [
|
|
9011
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: "Trust map \xB7 top tools" }),
|
|
9012
|
+
tools.slice(0, 4).map((t, i) => /* @__PURE__ */ jsxs8(Text8, { wrap: "truncate", children: [
|
|
9013
|
+
/* @__PURE__ */ jsx8(Text8, { color: t.anomalous ? theme.bad : theme.accent, children: ` ${truncate2(String(t.name), 16).padEnd(17)}` }),
|
|
9014
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: `${t.count}\xD7 ${t.permission ?? ""}` })
|
|
9015
|
+
] }, i)),
|
|
9016
|
+
resources.slice(0, 3).map((r, i) => /* @__PURE__ */ jsx8(Text8, { wrap: "truncate", color: r.anomalous ? theme.bad : theme.dim, children: ` ${r.type === "domain" ? "\u{1F310}" : "\u{1F4C1}"} ${truncate2(String(r.value), 40)} ${r.count}\xD7` }, "r" + i))
|
|
9017
|
+
] })
|
|
9018
|
+
] }) })
|
|
9019
|
+
] }) });
|
|
9020
|
+
}
|
|
9021
|
+
var statusColor, sevColor;
|
|
9022
|
+
var init_Agents = __esm({
|
|
9023
|
+
"src/tui/panels/Agents.tsx"() {
|
|
9024
|
+
"use strict";
|
|
9025
|
+
init_api_client();
|
|
9026
|
+
init_components();
|
|
9027
|
+
init_hooks();
|
|
9028
|
+
init_theme();
|
|
9029
|
+
statusColor = (s) => s === "active" ? theme.ok : s === "idle" ? theme.warn : theme.dim;
|
|
9030
|
+
sevColor = (s) => s === "high" ? theme.bad : s === "medium" ? theme.warn : theme.dim;
|
|
9031
|
+
}
|
|
9032
|
+
});
|
|
9033
|
+
|
|
9034
|
+
// src/tui/App.tsx
|
|
9035
|
+
import { Box as Box9, Text as Text9, useApp, useInput as useInput7 } from "ink";
|
|
9036
|
+
import { useState as useState8 } from "react";
|
|
9037
|
+
import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
8846
9038
|
function LiveHint() {
|
|
8847
|
-
return /* @__PURE__ */
|
|
8848
|
-
/* @__PURE__ */
|
|
8849
|
-
/* @__PURE__ */
|
|
8850
|
-
/* @__PURE__ */
|
|
8851
|
-
/* @__PURE__ */
|
|
9039
|
+
return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
|
|
9040
|
+
/* @__PURE__ */ jsx9(Text9, { color: theme.accentBright, bold: true, children: "\u25B6 REALTIME CONSOLE" }),
|
|
9041
|
+
/* @__PURE__ */ jsx9(Text9, { color: theme.dim, children: "Fullscreen live monitor \u2014 streaming tool calls, active charts," }),
|
|
9042
|
+
/* @__PURE__ */ jsx9(Text9, { color: theme.dim, children: "counters, DLP hits and denial alerts. Updates every 2s." }),
|
|
9043
|
+
/* @__PURE__ */ jsx9(Box9, { marginTop: 1, children: /* @__PURE__ */ jsxs9(Text9, { children: [
|
|
8852
9044
|
"press ",
|
|
8853
|
-
/* @__PURE__ */
|
|
9045
|
+
/* @__PURE__ */ jsx9(Text9, { color: theme.accent, children: "enter" }),
|
|
8854
9046
|
" to go live"
|
|
8855
9047
|
] }) })
|
|
8856
9048
|
] });
|
|
@@ -8858,22 +9050,22 @@ function LiveHint() {
|
|
|
8858
9050
|
function Banner() {
|
|
8859
9051
|
const wide = (process.stdout.columns ?? 80) >= 82;
|
|
8860
9052
|
if (!wide) {
|
|
8861
|
-
return /* @__PURE__ */
|
|
8862
|
-
/* @__PURE__ */
|
|
8863
|
-
/* @__PURE__ */
|
|
9053
|
+
return /* @__PURE__ */ jsxs9(Box9, { children: [
|
|
9054
|
+
/* @__PURE__ */ jsx9(Text9, { bold: true, color: theme.accentBright, children: "SolonGate" }),
|
|
9055
|
+
/* @__PURE__ */ jsx9(Text9, { color: theme.dim, children: " \u2014 security control center" })
|
|
8864
9056
|
] });
|
|
8865
9057
|
}
|
|
8866
|
-
return /* @__PURE__ */
|
|
8867
|
-
BANNER_FULL.map((line, i) => /* @__PURE__ */
|
|
8868
|
-
/* @__PURE__ */
|
|
9058
|
+
return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
|
|
9059
|
+
BANNER_FULL.map((line, i) => /* @__PURE__ */ jsx9(Text9, { bold: true, color: BANNER_HEX[i], children: line }, i)),
|
|
9060
|
+
/* @__PURE__ */ jsx9(Text9, { color: theme.dim, children: " security control center \xB7 manage policies, rate limits, DLP & more" })
|
|
8869
9061
|
] });
|
|
8870
9062
|
}
|
|
8871
9063
|
function App() {
|
|
8872
9064
|
const { exit } = useApp();
|
|
8873
|
-
const [section, setSection] =
|
|
8874
|
-
const [focus, setFocus] =
|
|
8875
|
-
const [help, setHelp] =
|
|
8876
|
-
|
|
9065
|
+
const [section, setSection] = useState8(0);
|
|
9066
|
+
const [focus, setFocus] = useState8("nav");
|
|
9067
|
+
const [help, setHelp] = useState8(false);
|
|
9068
|
+
useInput7((input, key) => {
|
|
8877
9069
|
if (help) {
|
|
8878
9070
|
setHelp(false);
|
|
8879
9071
|
return;
|
|
@@ -8895,31 +9087,31 @@ function App() {
|
|
|
8895
9087
|
const cols = process.stdout.columns ?? 100;
|
|
8896
9088
|
const rows = process.stdout.rows ?? 30;
|
|
8897
9089
|
const current = SECTIONS[section];
|
|
8898
|
-
if (help) return /* @__PURE__ */
|
|
9090
|
+
if (help) return /* @__PURE__ */ jsx9(HelpOverlay, { cols, rows });
|
|
8899
9091
|
if (current.label === "Live" && focus === "panel") {
|
|
8900
|
-
return /* @__PURE__ */
|
|
9092
|
+
return /* @__PURE__ */ jsx9(Box9, { flexDirection: "column", width: cols, height: rows, children: /* @__PURE__ */ jsx9(LivePanel, { active: true, focused: true }) });
|
|
8901
9093
|
}
|
|
8902
9094
|
const Panel = current.Panel;
|
|
8903
|
-
return /* @__PURE__ */
|
|
8904
|
-
/* @__PURE__ */
|
|
8905
|
-
/* @__PURE__ */
|
|
8906
|
-
/* @__PURE__ */
|
|
8907
|
-
/* @__PURE__ */
|
|
9095
|
+
return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", width: cols, height: rows, paddingX: 1, paddingTop: 1, children: [
|
|
9096
|
+
/* @__PURE__ */ jsx9(Banner, {}),
|
|
9097
|
+
/* @__PURE__ */ jsxs9(Box9, { marginTop: 1, flexGrow: 1, children: [
|
|
9098
|
+
/* @__PURE__ */ jsx9(Box9, { flexDirection: "column", width: 16, borderStyle: "round", borderColor: focus === "nav" ? theme.accent : "gray", paddingX: 1, children: SECTIONS.map((s, i) => /* @__PURE__ */ jsx9(Text9, { color: i === section ? theme.accentBright : void 0, bold: i === section, children: (i === section ? "\u25B8 " : " ") + s.label }, s.label)) }),
|
|
9099
|
+
/* @__PURE__ */ jsx9(Box9, { flexGrow: 1, borderStyle: "round", borderColor: focus === "panel" ? theme.accent : "gray", paddingX: 1, paddingY: 0, children: /* @__PURE__ */ jsx9(Panel, { active: focus === "panel" || current.label !== "Live", focused: focus === "panel" }) })
|
|
8908
9100
|
] }),
|
|
8909
|
-
/* @__PURE__ */
|
|
9101
|
+
/* @__PURE__ */ jsx9(Box9, { children: focus === "nav" ? /* @__PURE__ */ jsx9(KeyHints, { hints: [["\u2191\u2193", "section"], ["\u2192/enter", "open"], ["?", "help"], ["q", "quit"]] }) : /* @__PURE__ */ jsx9(KeyHints, { hints: [["\u2190/esc", "back"], ["\u2191\u2193", "in-panel"], ["space/s", "act"]] }) })
|
|
8910
9102
|
] });
|
|
8911
9103
|
}
|
|
8912
9104
|
function HelpOverlay({ cols, rows }) {
|
|
8913
|
-
return /* @__PURE__ */
|
|
8914
|
-
/* @__PURE__ */
|
|
8915
|
-
/* @__PURE__ */
|
|
8916
|
-
/* @__PURE__ */
|
|
8917
|
-
keys.map(([k, desc]) => /* @__PURE__ */
|
|
8918
|
-
/* @__PURE__ */
|
|
8919
|
-
/* @__PURE__ */
|
|
9105
|
+
return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", width: cols, height: rows, paddingX: 2, paddingTop: 1, children: [
|
|
9106
|
+
/* @__PURE__ */ jsx9(Text9, { bold: true, color: theme.accentBright, children: "SolonGate \u2014 keyboard shortcuts" }),
|
|
9107
|
+
/* @__PURE__ */ jsx9(Box9, { marginTop: 1, flexDirection: "column", children: HELP.map(([group, keys]) => /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", marginBottom: 1, children: [
|
|
9108
|
+
/* @__PURE__ */ jsx9(Text9, { bold: true, color: theme.accent, children: group }),
|
|
9109
|
+
keys.map(([k, desc]) => /* @__PURE__ */ jsxs9(Text9, { children: [
|
|
9110
|
+
/* @__PURE__ */ jsx9(Text9, { color: theme.accentBright, children: (" " + k).padEnd(16) }),
|
|
9111
|
+
/* @__PURE__ */ jsx9(Text9, { color: theme.dim, children: desc })
|
|
8920
9112
|
] }, k))
|
|
8921
9113
|
] }, group)) }),
|
|
8922
|
-
/* @__PURE__ */
|
|
9114
|
+
/* @__PURE__ */ jsx9(Text9, { color: theme.dim, children: "press any key to close" })
|
|
8923
9115
|
] });
|
|
8924
9116
|
}
|
|
8925
9117
|
var SECTIONS, BANNER_HEX, HELP;
|
|
@@ -8935,8 +9127,10 @@ var init_App = __esm({
|
|
|
8935
9127
|
init_Dlp();
|
|
8936
9128
|
init_Stats();
|
|
8937
9129
|
init_Audit();
|
|
9130
|
+
init_Agents();
|
|
8938
9131
|
SECTIONS = [
|
|
8939
9132
|
{ label: "Live", Panel: LiveHint },
|
|
9133
|
+
{ label: "Agents", Panel: AgentsPanel },
|
|
8940
9134
|
{ label: "Policies", Panel: PoliciesPanel },
|
|
8941
9135
|
{ label: "Rate Limit", Panel: RateLimitPanel },
|
|
8942
9136
|
{ label: "DLP", Panel: DlpPanel },
|
|
@@ -8959,7 +9153,7 @@ __export(tui_exports, {
|
|
|
8959
9153
|
launchTui: () => launchTui
|
|
8960
9154
|
});
|
|
8961
9155
|
import { render } from "ink";
|
|
8962
|
-
import { jsx as
|
|
9156
|
+
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
8963
9157
|
async function launchTui() {
|
|
8964
9158
|
if (!process.stdout.isTTY || !process.stdin.isTTY) {
|
|
8965
9159
|
process.stderr.write(
|
|
@@ -8973,7 +9167,7 @@ async function launchTui() {
|
|
|
8973
9167
|
}
|
|
8974
9168
|
process.stdout.write("\x1B[?1049h\x1B[H");
|
|
8975
9169
|
try {
|
|
8976
|
-
const { waitUntilExit } = render(/* @__PURE__ */
|
|
9170
|
+
const { waitUntilExit } = render(/* @__PURE__ */ jsx10(App, {}));
|
|
8977
9171
|
await waitUntilExit();
|
|
8978
9172
|
} finally {
|
|
8979
9173
|
process.stdout.write("\x1B[?1049l");
|
|
@@ -9085,7 +9279,7 @@ var init_args = __esm({
|
|
|
9085
9279
|
});
|
|
9086
9280
|
|
|
9087
9281
|
// src/commands/policy.ts
|
|
9088
|
-
import { readFileSync as
|
|
9282
|
+
import { readFileSync as readFileSync6 } from "fs";
|
|
9089
9283
|
async function run(argv) {
|
|
9090
9284
|
const { positionals, flags } = parse(argv);
|
|
9091
9285
|
const sub = positionals[0];
|
|
@@ -9260,7 +9454,7 @@ function printRules(rules) {
|
|
|
9260
9454
|
}
|
|
9261
9455
|
async function resolveRules(target) {
|
|
9262
9456
|
if (target.endsWith(".json")) {
|
|
9263
|
-
const parsed = JSON.parse(
|
|
9457
|
+
const parsed = JSON.parse(readFileSync6(target, "utf-8"));
|
|
9264
9458
|
return parsed.rules ?? [];
|
|
9265
9459
|
}
|
|
9266
9460
|
const p = await api.policies.get(target);
|
|
@@ -9624,7 +9818,7 @@ async function runAgents(argv) {
|
|
|
9624
9818
|
table(
|
|
9625
9819
|
["STATUS", "AGENT", "CALLS", "DENY", "DLP", "TRUST", "CHARACTER"],
|
|
9626
9820
|
res.agents.map((a) => [
|
|
9627
|
-
|
|
9821
|
+
statusColor2(a.status),
|
|
9628
9822
|
cyan(truncate3(a.agent_name ?? a.agent_id ?? a.session_id, 20)),
|
|
9629
9823
|
String(a.total_calls),
|
|
9630
9824
|
a.denied_calls ? red(String(a.denied_calls)) : dim("0"),
|
|
@@ -9643,7 +9837,7 @@ async function runAgent(argv) {
|
|
|
9643
9837
|
const a = await api.agents.get(id);
|
|
9644
9838
|
if (json) return printJson(a), 0;
|
|
9645
9839
|
err("");
|
|
9646
|
-
err(` ${bold(a.agent_id)} status: ${
|
|
9840
|
+
err(` ${bold(a.agent_id)} status: ${statusColor2(String(a.status))}`);
|
|
9647
9841
|
const base = a.baseline;
|
|
9648
9842
|
if (base) {
|
|
9649
9843
|
err(` ${dim(base.character ?? "")} trust ${bold(String(base.trustScore ?? "\u2014"))}/100 deny-rate ${(Number(base.denyRate ?? 0) * 100).toFixed(0)}%`);
|
|
@@ -9663,21 +9857,21 @@ async function runAgent(argv) {
|
|
|
9663
9857
|
}
|
|
9664
9858
|
return 0;
|
|
9665
9859
|
}
|
|
9666
|
-
var
|
|
9860
|
+
var statusColor2;
|
|
9667
9861
|
var init_agents2 = __esm({
|
|
9668
9862
|
"src/commands/agents.ts"() {
|
|
9669
9863
|
"use strict";
|
|
9670
9864
|
init_api_client();
|
|
9671
9865
|
init_args();
|
|
9672
9866
|
init_format();
|
|
9673
|
-
|
|
9867
|
+
statusColor2 = (s) => s === "active" ? green(s) : s === "idle" ? yellow(s) : dim(s);
|
|
9674
9868
|
}
|
|
9675
9869
|
});
|
|
9676
9870
|
|
|
9677
9871
|
// src/commands/doctor.ts
|
|
9678
9872
|
import { existsSync as existsSync4, statSync as statSync2 } from "fs";
|
|
9679
|
-
import { homedir as
|
|
9680
|
-
import { join as
|
|
9873
|
+
import { homedir as homedir5 } from "os";
|
|
9874
|
+
import { join as join7 } from "path";
|
|
9681
9875
|
async function run6(argv) {
|
|
9682
9876
|
const { flags } = parse(argv);
|
|
9683
9877
|
const json = flagBool(flags, "json");
|
|
@@ -9737,14 +9931,14 @@ var init_doctor = __esm({
|
|
|
9737
9931
|
init_api_client();
|
|
9738
9932
|
init_format();
|
|
9739
9933
|
init_args();
|
|
9740
|
-
LOCAL_LOG2 =
|
|
9934
|
+
LOCAL_LOG2 = join7(homedir5(), ".solongate", "local-logs", "solongate-audit.jsonl");
|
|
9741
9935
|
}
|
|
9742
9936
|
});
|
|
9743
9937
|
|
|
9744
9938
|
// src/commands/watch.ts
|
|
9745
9939
|
import { closeSync as closeSync2, existsSync as existsSync5, openSync as openSync2, readSync as readSync2, statSync as statSync3 } from "fs";
|
|
9746
|
-
import { homedir as
|
|
9747
|
-
import { join as
|
|
9940
|
+
import { homedir as homedir6 } from "os";
|
|
9941
|
+
import { join as join8 } from "path";
|
|
9748
9942
|
function tailLocal(file, maxBytes = 131072) {
|
|
9749
9943
|
try {
|
|
9750
9944
|
const size = statSync3(file).size;
|
|
@@ -9851,7 +10045,7 @@ var init_watch = __esm({
|
|
|
9851
10045
|
init_cli_utils();
|
|
9852
10046
|
init_args();
|
|
9853
10047
|
init_format();
|
|
9854
|
-
LOCAL_LOG3 =
|
|
10048
|
+
LOCAL_LOG3 = join8(homedir6(), ".solongate", "local-logs", "solongate-audit.jsonl");
|
|
9855
10049
|
trunc = (s, n) => s.length <= n ? s : s.slice(0, n - 1) + "\u2026";
|
|
9856
10050
|
time = (ms) => new Date(ms).toTimeString().slice(0, 8);
|
|
9857
10051
|
}
|
|
@@ -10153,9 +10347,9 @@ __export(global_install_exports, {
|
|
|
10153
10347
|
runGlobalRestore: () => runGlobalRestore,
|
|
10154
10348
|
unlockProtected: () => unlockProtected
|
|
10155
10349
|
});
|
|
10156
|
-
import { readFileSync as
|
|
10157
|
-
import { resolve as resolve4, join as
|
|
10158
|
-
import { homedir as
|
|
10350
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync4, existsSync as existsSync6, mkdirSync as mkdirSync4 } from "fs";
|
|
10351
|
+
import { resolve as resolve4, join as join9, dirname } from "path";
|
|
10352
|
+
import { homedir as homedir7 } from "os";
|
|
10159
10353
|
import { fileURLToPath } from "url";
|
|
10160
10354
|
import { createInterface } from "readline";
|
|
10161
10355
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
@@ -10218,10 +10412,10 @@ function unlockFile(file) {
|
|
|
10218
10412
|
function protectedTargets() {
|
|
10219
10413
|
const p = globalPaths();
|
|
10220
10414
|
return [
|
|
10221
|
-
|
|
10222
|
-
|
|
10223
|
-
|
|
10224
|
-
|
|
10415
|
+
join9(p.hooksDir, "guard.mjs"),
|
|
10416
|
+
join9(p.hooksDir, "audit.mjs"),
|
|
10417
|
+
join9(p.hooksDir, "stop.mjs"),
|
|
10418
|
+
join9(p.hooksDir, "shield.mjs"),
|
|
10225
10419
|
p.configPath,
|
|
10226
10420
|
p.settingsPath
|
|
10227
10421
|
];
|
|
@@ -10233,26 +10427,26 @@ function unlockProtected() {
|
|
|
10233
10427
|
for (const f of protectedTargets()) unlockFile(f);
|
|
10234
10428
|
}
|
|
10235
10429
|
function globalPaths() {
|
|
10236
|
-
const home =
|
|
10237
|
-
const sgDir =
|
|
10238
|
-
const hooksDir =
|
|
10239
|
-
const claudeDir =
|
|
10430
|
+
const home = homedir7();
|
|
10431
|
+
const sgDir = join9(home, ".solongate");
|
|
10432
|
+
const hooksDir = join9(sgDir, "hooks");
|
|
10433
|
+
const claudeDir = join9(home, ".claude");
|
|
10240
10434
|
return {
|
|
10241
10435
|
home,
|
|
10242
10436
|
sgDir,
|
|
10243
10437
|
hooksDir,
|
|
10244
10438
|
claudeDir,
|
|
10245
|
-
settingsPath:
|
|
10246
|
-
backupPath:
|
|
10247
|
-
configPath:
|
|
10439
|
+
settingsPath: join9(claudeDir, "settings.json"),
|
|
10440
|
+
backupPath: join9(claudeDir, "settings.solongate.bak"),
|
|
10441
|
+
configPath: join9(sgDir, "cloud-guard.json")
|
|
10248
10442
|
};
|
|
10249
10443
|
}
|
|
10250
10444
|
function readHook(filename) {
|
|
10251
|
-
return
|
|
10445
|
+
return readFileSync7(join9(HOOKS_DIR, filename), "utf-8");
|
|
10252
10446
|
}
|
|
10253
10447
|
function readGuard() {
|
|
10254
|
-
const bundled =
|
|
10255
|
-
return existsSync6(bundled) ?
|
|
10448
|
+
const bundled = join9(HOOKS_DIR, "guard.bundled.mjs");
|
|
10449
|
+
return existsSync6(bundled) ? readFileSync7(bundled, "utf-8") : readHook("guard.mjs");
|
|
10256
10450
|
}
|
|
10257
10451
|
function ask(question) {
|
|
10258
10452
|
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
@@ -10266,13 +10460,13 @@ function runGlobalRestore() {
|
|
|
10266
10460
|
unlockProtected();
|
|
10267
10461
|
removeClaudeShim();
|
|
10268
10462
|
if (existsSync6(p.backupPath)) {
|
|
10269
|
-
|
|
10463
|
+
writeFileSync4(p.settingsPath, readFileSync7(p.backupPath, "utf-8"));
|
|
10270
10464
|
console.log(` Restored ${p.settingsPath} from backup.`);
|
|
10271
10465
|
} else if (existsSync6(p.settingsPath)) {
|
|
10272
10466
|
try {
|
|
10273
|
-
const s = JSON.parse(
|
|
10467
|
+
const s = JSON.parse(readFileSync7(p.settingsPath, "utf-8"));
|
|
10274
10468
|
delete s.hooks;
|
|
10275
|
-
|
|
10469
|
+
writeFileSync4(p.settingsPath, JSON.stringify(s, null, 2) + "\n");
|
|
10276
10470
|
console.log(` Removed SolonGate hooks from ${p.settingsPath}.`);
|
|
10277
10471
|
} catch {
|
|
10278
10472
|
}
|
|
@@ -10306,18 +10500,18 @@ function shimTargets() {
|
|
|
10306
10500
|
return [];
|
|
10307
10501
|
}
|
|
10308
10502
|
}
|
|
10309
|
-
return [".bashrc", ".zshrc", ".profile"].map((f) =>
|
|
10503
|
+
return [".bashrc", ".zshrc", ".profile"].map((f) => join9(homedir7(), f)).filter((f) => existsSync6(f));
|
|
10310
10504
|
}
|
|
10311
10505
|
function writeShimBlock(file, block2) {
|
|
10312
10506
|
const re = new RegExp(escapeRe(SHIM_BEGIN) + "[\\s\\S]*?" + escapeRe(SHIM_END) + "\\r?\\n?", "g");
|
|
10313
|
-
let content = existsSync6(file) ?
|
|
10507
|
+
let content = existsSync6(file) ? readFileSync7(file, "utf-8") : "";
|
|
10314
10508
|
content = content.replace(re, "");
|
|
10315
10509
|
if (block2) {
|
|
10316
10510
|
if (content.length && !content.endsWith("\n")) content += "\n";
|
|
10317
10511
|
content += block2 + "\n";
|
|
10318
10512
|
}
|
|
10319
|
-
|
|
10320
|
-
|
|
10513
|
+
mkdirSync4(dirname(file), { recursive: true });
|
|
10514
|
+
writeFileSync4(file, content);
|
|
10321
10515
|
}
|
|
10322
10516
|
function installClaudeShim(shieldPath) {
|
|
10323
10517
|
const real = resolveRealClaude();
|
|
@@ -10361,7 +10555,7 @@ async function runGlobalInstall(opts = {}) {
|
|
|
10361
10555
|
let apiKey = opts.apiKey || process.env["SOLONGATE_API_KEY"] || "";
|
|
10362
10556
|
if (!apiKey || apiKey === "sg_live_your_key_here") {
|
|
10363
10557
|
try {
|
|
10364
|
-
const cfg = JSON.parse(
|
|
10558
|
+
const cfg = JSON.parse(readFileSync7(p.configPath, "utf-8"));
|
|
10365
10559
|
if (cfg && typeof cfg.apiKey === "string") apiKey = cfg.apiKey;
|
|
10366
10560
|
} catch {
|
|
10367
10561
|
}
|
|
@@ -10374,22 +10568,22 @@ async function runGlobalInstall(opts = {}) {
|
|
|
10374
10568
|
process.exit(1);
|
|
10375
10569
|
}
|
|
10376
10570
|
const apiUrl = opts.apiUrl || process.env["SOLONGATE_API_URL"] || "https://api.solongate.com";
|
|
10377
|
-
|
|
10378
|
-
|
|
10571
|
+
mkdirSync4(p.hooksDir, { recursive: true });
|
|
10572
|
+
mkdirSync4(p.claudeDir, { recursive: true });
|
|
10379
10573
|
unlockProtected();
|
|
10380
|
-
|
|
10381
|
-
|
|
10382
|
-
|
|
10383
|
-
|
|
10574
|
+
writeFileSync4(join9(p.hooksDir, "guard.mjs"), readGuard());
|
|
10575
|
+
writeFileSync4(join9(p.hooksDir, "audit.mjs"), readHook("audit.mjs"));
|
|
10576
|
+
writeFileSync4(join9(p.hooksDir, "stop.mjs"), readHook("stop.mjs"));
|
|
10577
|
+
writeFileSync4(join9(p.hooksDir, "shield.mjs"), readHook("shield.mjs"));
|
|
10384
10578
|
console.log(` Installed hooks \u2192 ${p.hooksDir}`);
|
|
10385
10579
|
removeClaudeShim();
|
|
10386
|
-
|
|
10580
|
+
writeFileSync4(p.configPath, JSON.stringify({ apiKey, apiUrl }, null, 2) + "\n");
|
|
10387
10581
|
console.log(` Wrote ${p.configPath}`);
|
|
10388
10582
|
let existing = {};
|
|
10389
10583
|
if (existsSync6(p.settingsPath)) {
|
|
10390
|
-
const raw =
|
|
10584
|
+
const raw = readFileSync7(p.settingsPath, "utf-8");
|
|
10391
10585
|
if (!existsSync6(p.backupPath)) {
|
|
10392
|
-
|
|
10586
|
+
writeFileSync4(p.backupPath, raw);
|
|
10393
10587
|
console.log(` Backed up existing settings \u2192 ${p.backupPath}`);
|
|
10394
10588
|
}
|
|
10395
10589
|
try {
|
|
@@ -10398,9 +10592,9 @@ async function runGlobalInstall(opts = {}) {
|
|
|
10398
10592
|
existing = {};
|
|
10399
10593
|
}
|
|
10400
10594
|
}
|
|
10401
|
-
const guardAbs =
|
|
10402
|
-
const auditAbs =
|
|
10403
|
-
const stopAbs =
|
|
10595
|
+
const guardAbs = join9(p.hooksDir, "guard.mjs").replace(/\\/g, "/");
|
|
10596
|
+
const auditAbs = join9(p.hooksDir, "audit.mjs").replace(/\\/g, "/");
|
|
10597
|
+
const stopAbs = join9(p.hooksDir, "stop.mjs").replace(/\\/g, "/");
|
|
10404
10598
|
const nodeBin = process.execPath.replace(/\\/g, "/");
|
|
10405
10599
|
const merged = {
|
|
10406
10600
|
...existing,
|
|
@@ -10410,7 +10604,7 @@ async function runGlobalInstall(opts = {}) {
|
|
|
10410
10604
|
Stop: [{ matcher: "", hooks: [{ type: "command", command: `"${nodeBin}" "${stopAbs}" claude-code "Claude Code"` }] }]
|
|
10411
10605
|
}
|
|
10412
10606
|
};
|
|
10413
|
-
|
|
10607
|
+
writeFileSync4(p.settingsPath, JSON.stringify(merged, null, 2) + "\n");
|
|
10414
10608
|
console.log(` Registered global hooks \u2192 ${p.settingsPath}`);
|
|
10415
10609
|
if (process.env["SOLONGATE_OS_LOCK"] === "1") {
|
|
10416
10610
|
lockProtected();
|
|
@@ -10590,11 +10784,11 @@ import { createServer, request as httpRequest } from "http";
|
|
|
10590
10784
|
import { request as httpsRequest } from "https";
|
|
10591
10785
|
import { spawn as spawn3 } from "child_process";
|
|
10592
10786
|
import { URL as URL2 } from "url";
|
|
10593
|
-
import { readFileSync as
|
|
10787
|
+
import { readFileSync as readFileSync8, existsSync as existsSync7, readdirSync, statSync as statSync4 } from "fs";
|
|
10594
10788
|
import { resolve as resolve5 } from "path";
|
|
10595
|
-
import { homedir as
|
|
10789
|
+
import { homedir as homedir8 } from "os";
|
|
10596
10790
|
function findCacheFile() {
|
|
10597
|
-
const dir = resolve5(
|
|
10791
|
+
const dir = resolve5(homedir8(), ".solongate");
|
|
10598
10792
|
const envSel = process.env.SOLONGATE_AGENT_ID;
|
|
10599
10793
|
if (envSel) {
|
|
10600
10794
|
const f = resolve5(dir, ".policy-cache-" + envSel.replace(/[^a-zA-Z0-9_-]/g, "_") + ".json");
|
|
@@ -10620,7 +10814,7 @@ function loadCfg() {
|
|
|
10620
10814
|
try {
|
|
10621
10815
|
const f = findCacheFile();
|
|
10622
10816
|
if (f && existsSync7(f)) {
|
|
10623
|
-
const c2 = JSON.parse(
|
|
10817
|
+
const c2 = JSON.parse(readFileSync8(f, "utf-8"));
|
|
10624
10818
|
const d = c2?.security?.dlpRedact;
|
|
10625
10819
|
const g = c2?.security?.ghost;
|
|
10626
10820
|
const ghost = g && Array.isArray(g.patterns) ? g.patterns : [];
|
|
@@ -10896,9 +11090,9 @@ __export(logs_server_exports, {
|
|
|
10896
11090
|
runLogsServer: () => runLogsServer
|
|
10897
11091
|
});
|
|
10898
11092
|
import { createServer as createServer2 } from "http";
|
|
10899
|
-
import { readFileSync as
|
|
10900
|
-
import { resolve as resolve6, join as
|
|
10901
|
-
import { homedir as
|
|
11093
|
+
import { readFileSync as readFileSync9, statSync as statSync5 } from "fs";
|
|
11094
|
+
import { resolve as resolve6, join as join10, isAbsolute } from "path";
|
|
11095
|
+
import { homedir as homedir9 } from "os";
|
|
10902
11096
|
import { readdirSync as readdirSync2 } from "fs";
|
|
10903
11097
|
function allowedOrigins() {
|
|
10904
11098
|
const base = [
|
|
@@ -10915,15 +11109,15 @@ function resolveLocalLogDir(rawPath) {
|
|
|
10915
11109
|
const dir = String(rawPath || "").trim().replace(/[\\/]+$/, "");
|
|
10916
11110
|
if (!dir) return null;
|
|
10917
11111
|
if (isAbsolute(dir)) return dir;
|
|
10918
|
-
return resolve6(
|
|
11112
|
+
return resolve6(homedir9(), ".solongate", "local-logs");
|
|
10919
11113
|
}
|
|
10920
11114
|
async function findLogDir() {
|
|
10921
|
-
const base = resolve6(
|
|
11115
|
+
const base = resolve6(homedir9(), ".solongate");
|
|
10922
11116
|
try {
|
|
10923
11117
|
const files = readdirSync2(base).filter((f) => f.startsWith(".policy-cache-") && f.endsWith(".json"));
|
|
10924
11118
|
for (const f of files) {
|
|
10925
11119
|
try {
|
|
10926
|
-
const c2 = JSON.parse(
|
|
11120
|
+
const c2 = JSON.parse(readFileSync9(join10(base, f), "utf-8"));
|
|
10927
11121
|
const p = c2?.security?.localLogs?.path;
|
|
10928
11122
|
if (typeof p === "string" && p.trim()) return { dir: resolveLocalLogDir(p), configured: p };
|
|
10929
11123
|
} catch {
|
|
@@ -10932,7 +11126,7 @@ async function findLogDir() {
|
|
|
10932
11126
|
} catch {
|
|
10933
11127
|
}
|
|
10934
11128
|
try {
|
|
10935
|
-
const cfgRaw =
|
|
11129
|
+
const cfgRaw = readFileSync9(join10(base, "cloud-guard.json"), "utf-8");
|
|
10936
11130
|
const { apiKey, apiUrl } = JSON.parse(cfgRaw);
|
|
10937
11131
|
if (apiKey) {
|
|
10938
11132
|
const url = `${apiUrl || "https://api.solongate.com"}/api/v1/policies/active`;
|
|
@@ -10961,7 +11155,7 @@ function setCors(req, res) {
|
|
|
10961
11155
|
}
|
|
10962
11156
|
function fileInfo(dir) {
|
|
10963
11157
|
if (!dir) return { file: null, exists: false, size: 0, mtimeMs: 0 };
|
|
10964
|
-
const file =
|
|
11158
|
+
const file = join10(dir, LOG_FILENAME);
|
|
10965
11159
|
try {
|
|
10966
11160
|
const st = statSync5(file);
|
|
10967
11161
|
return { file, exists: true, size: st.size, mtimeMs: st.mtimeMs };
|
|
@@ -11022,7 +11216,7 @@ async function runLogsServer() {
|
|
|
11022
11216
|
return;
|
|
11023
11217
|
}
|
|
11024
11218
|
try {
|
|
11025
|
-
const text =
|
|
11219
|
+
const text = readFileSync9(info.file, "utf-8");
|
|
11026
11220
|
res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8", "Last-Modified": lastMod, "X-Solongate-Exists": "1" });
|
|
11027
11221
|
res.end(text);
|
|
11028
11222
|
} catch {
|
|
@@ -11074,7 +11268,7 @@ var init_logs_server = __esm({
|
|
|
11074
11268
|
|
|
11075
11269
|
// src/inject.ts
|
|
11076
11270
|
var inject_exports = {};
|
|
11077
|
-
import { readFileSync as
|
|
11271
|
+
import { readFileSync as readFileSync10, writeFileSync as writeFileSync5, existsSync as existsSync8, copyFileSync } from "fs";
|
|
11078
11272
|
import { resolve as resolve7 } from "path";
|
|
11079
11273
|
import { execSync } from "child_process";
|
|
11080
11274
|
function parseInjectArgs(argv) {
|
|
@@ -11134,7 +11328,7 @@ WHAT IT DOES
|
|
|
11134
11328
|
function detectProject() {
|
|
11135
11329
|
if (!existsSync8(resolve7("package.json"))) return false;
|
|
11136
11330
|
try {
|
|
11137
|
-
const pkg = JSON.parse(
|
|
11331
|
+
const pkg = JSON.parse(readFileSync10(resolve7("package.json"), "utf-8"));
|
|
11138
11332
|
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
11139
11333
|
return !!(allDeps["@modelcontextprotocol/sdk"] || allDeps["@modelcontextprotocol/server"]);
|
|
11140
11334
|
} catch {
|
|
@@ -11143,7 +11337,7 @@ function detectProject() {
|
|
|
11143
11337
|
}
|
|
11144
11338
|
function findTsEntryFile() {
|
|
11145
11339
|
try {
|
|
11146
|
-
const pkg = JSON.parse(
|
|
11340
|
+
const pkg = JSON.parse(readFileSync10(resolve7("package.json"), "utf-8"));
|
|
11147
11341
|
if (pkg.bin) {
|
|
11148
11342
|
const binPath = typeof pkg.bin === "string" ? pkg.bin : Object.values(pkg.bin)[0];
|
|
11149
11343
|
if (typeof binPath === "string") {
|
|
@@ -11170,7 +11364,7 @@ function findTsEntryFile() {
|
|
|
11170
11364
|
const full = resolve7(c2);
|
|
11171
11365
|
if (existsSync8(full)) {
|
|
11172
11366
|
try {
|
|
11173
|
-
const content =
|
|
11367
|
+
const content = readFileSync10(full, "utf-8");
|
|
11174
11368
|
if (content.includes("McpServer") || content.includes("McpServer")) {
|
|
11175
11369
|
return full;
|
|
11176
11370
|
}
|
|
@@ -11190,7 +11384,7 @@ function detectPackageManager() {
|
|
|
11190
11384
|
}
|
|
11191
11385
|
function installSdk() {
|
|
11192
11386
|
try {
|
|
11193
|
-
const pkg = JSON.parse(
|
|
11387
|
+
const pkg = JSON.parse(readFileSync10(resolve7("package.json"), "utf-8"));
|
|
11194
11388
|
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
11195
11389
|
if (allDeps["@solongate/proxy"]) {
|
|
11196
11390
|
log3(" @solongate/proxy already installed");
|
|
@@ -11211,7 +11405,7 @@ function installSdk() {
|
|
|
11211
11405
|
}
|
|
11212
11406
|
}
|
|
11213
11407
|
function injectTypeScript(filePath) {
|
|
11214
|
-
const original =
|
|
11408
|
+
const original = readFileSync10(filePath, "utf-8");
|
|
11215
11409
|
const changes = [];
|
|
11216
11410
|
let modified = original;
|
|
11217
11411
|
if (modified.includes("SecureMcpServer")) {
|
|
@@ -11382,7 +11576,7 @@ async function main2() {
|
|
|
11382
11576
|
log3("");
|
|
11383
11577
|
log3(` Backup: ${backupPath}`);
|
|
11384
11578
|
}
|
|
11385
|
-
|
|
11579
|
+
writeFileSync5(entryFile, result.modified);
|
|
11386
11580
|
log3("");
|
|
11387
11581
|
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");
|
|
11388
11582
|
log3(" \u2502 SolonGate SDK injected successfully! \u2502");
|
|
@@ -11411,8 +11605,8 @@ var init_inject = __esm({
|
|
|
11411
11605
|
|
|
11412
11606
|
// src/create.ts
|
|
11413
11607
|
var create_exports = {};
|
|
11414
|
-
import { mkdirSync as
|
|
11415
|
-
import { resolve as resolve8, join as
|
|
11608
|
+
import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync6, existsSync as existsSync9 } from "fs";
|
|
11609
|
+
import { resolve as resolve8, join as join11 } from "path";
|
|
11416
11610
|
import { execSync as execSync2 } from "child_process";
|
|
11417
11611
|
function withSpinner(message, fn) {
|
|
11418
11612
|
const frames = ["\u28FE", "\u28FD", "\u28FB", "\u28BF", "\u287F", "\u28DF", "\u28EF", "\u28F7"];
|
|
@@ -11491,8 +11685,8 @@ EXAMPLES
|
|
|
11491
11685
|
`);
|
|
11492
11686
|
}
|
|
11493
11687
|
function createProject(dir, name, _policy) {
|
|
11494
|
-
|
|
11495
|
-
|
|
11688
|
+
writeFileSync6(
|
|
11689
|
+
join11(dir, "package.json"),
|
|
11496
11690
|
JSON.stringify(
|
|
11497
11691
|
{
|
|
11498
11692
|
name,
|
|
@@ -11521,8 +11715,8 @@ function createProject(dir, name, _policy) {
|
|
|
11521
11715
|
2
|
|
11522
11716
|
) + "\n"
|
|
11523
11717
|
);
|
|
11524
|
-
|
|
11525
|
-
|
|
11718
|
+
writeFileSync6(
|
|
11719
|
+
join11(dir, "tsconfig.json"),
|
|
11526
11720
|
JSON.stringify(
|
|
11527
11721
|
{
|
|
11528
11722
|
compilerOptions: {
|
|
@@ -11542,9 +11736,9 @@ function createProject(dir, name, _policy) {
|
|
|
11542
11736
|
2
|
|
11543
11737
|
) + "\n"
|
|
11544
11738
|
);
|
|
11545
|
-
|
|
11546
|
-
|
|
11547
|
-
|
|
11739
|
+
mkdirSync5(join11(dir, "src"), { recursive: true });
|
|
11740
|
+
writeFileSync6(
|
|
11741
|
+
join11(dir, "src", "index.ts"),
|
|
11548
11742
|
`#!/usr/bin/env node
|
|
11549
11743
|
|
|
11550
11744
|
console.log = (...args: unknown[]) => {
|
|
@@ -11585,8 +11779,8 @@ console.log('');
|
|
|
11585
11779
|
console.log('Press Ctrl+C to stop.');
|
|
11586
11780
|
`
|
|
11587
11781
|
);
|
|
11588
|
-
|
|
11589
|
-
|
|
11782
|
+
writeFileSync6(
|
|
11783
|
+
join11(dir, ".mcp.json"),
|
|
11590
11784
|
JSON.stringify(
|
|
11591
11785
|
{
|
|
11592
11786
|
mcpServers: {
|
|
@@ -11603,13 +11797,13 @@ console.log('Press Ctrl+C to stop.');
|
|
|
11603
11797
|
2
|
|
11604
11798
|
) + "\n"
|
|
11605
11799
|
);
|
|
11606
|
-
|
|
11607
|
-
|
|
11800
|
+
writeFileSync6(
|
|
11801
|
+
join11(dir, ".env"),
|
|
11608
11802
|
`SOLONGATE_API_KEY=sg_live_YOUR_KEY_HERE
|
|
11609
11803
|
`
|
|
11610
11804
|
);
|
|
11611
|
-
|
|
11612
|
-
|
|
11805
|
+
writeFileSync6(
|
|
11806
|
+
join11(dir, ".gitignore"),
|
|
11613
11807
|
`node_modules/
|
|
11614
11808
|
dist/
|
|
11615
11809
|
*.solongate-backup
|
|
@@ -11628,7 +11822,7 @@ async function main3() {
|
|
|
11628
11822
|
process.exit(1);
|
|
11629
11823
|
}
|
|
11630
11824
|
withSpinner(`Setting up ${opts.name}...`, () => {
|
|
11631
|
-
|
|
11825
|
+
mkdirSync5(dir, { recursive: true });
|
|
11632
11826
|
createProject(dir, opts.name, opts.policy);
|
|
11633
11827
|
});
|
|
11634
11828
|
if (!opts.noInstall) {
|
|
@@ -11702,14 +11896,14 @@ var init_create = __esm({
|
|
|
11702
11896
|
|
|
11703
11897
|
// src/pull-push.ts
|
|
11704
11898
|
var pull_push_exports = {};
|
|
11705
|
-
import { readFileSync as
|
|
11899
|
+
import { readFileSync as readFileSync11, writeFileSync as writeFileSync7, existsSync as existsSync10 } from "fs";
|
|
11706
11900
|
import { resolve as resolve9 } from "path";
|
|
11707
11901
|
function loadEnv() {
|
|
11708
11902
|
if (process.env.SOLONGATE_API_KEY) return;
|
|
11709
11903
|
const envPath = resolve9(".env");
|
|
11710
11904
|
if (!existsSync10(envPath)) return;
|
|
11711
11905
|
try {
|
|
11712
|
-
const content =
|
|
11906
|
+
const content = readFileSync11(envPath, "utf-8");
|
|
11713
11907
|
for (const line of content.split("\n")) {
|
|
11714
11908
|
const trimmed = line.trim();
|
|
11715
11909
|
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
@@ -11897,7 +12091,7 @@ async function pull(apiKey, file, policyId) {
|
|
|
11897
12091
|
const policy = await fetchCloudPolicy(apiKey, API_URL, policyId);
|
|
11898
12092
|
const { id: _id, ...policyWithoutId } = policy;
|
|
11899
12093
|
const json = JSON.stringify(policyWithoutId, null, 2) + "\n";
|
|
11900
|
-
|
|
12094
|
+
writeFileSync7(file, json, "utf-8");
|
|
11901
12095
|
log5("");
|
|
11902
12096
|
log5(green2(" Saved to: ") + file);
|
|
11903
12097
|
log5(` ${dim2("Name:")} ${policy.name}`);
|
|
@@ -11926,7 +12120,7 @@ async function push(apiKey, file, policyId) {
|
|
|
11926
12120
|
log5(" solongate-proxy list");
|
|
11927
12121
|
process.exit(1);
|
|
11928
12122
|
}
|
|
11929
|
-
const content =
|
|
12123
|
+
const content = readFileSync11(file, "utf-8");
|
|
11930
12124
|
let policy;
|
|
11931
12125
|
try {
|
|
11932
12126
|
policy = JSON.parse(content);
|