@solongate/proxy 0.81.24 → 0.81.26
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/api-client/audit.d.ts +13 -0
- package/dist/commands/index.js +8 -0
- package/dist/index.js +253 -256
- package/dist/tui/hooks.d.ts +3 -0
- package/dist/tui/index.js +209 -201
- package/dist/tui/local-log.d.ts +4 -0
- package/package.json +1 -1
- package/dist/tui/panels/Agents.d.ts +0 -4
- package/dist/tui/panels/Stats.d.ts +0 -3
package/dist/index.js
CHANGED
|
@@ -6814,7 +6814,7 @@ function DataView({
|
|
|
6814
6814
|
"\u2717 ",
|
|
6815
6815
|
error
|
|
6816
6816
|
] });
|
|
6817
|
-
if (loading) return /* @__PURE__ */ jsx(Text, { color: theme.
|
|
6817
|
+
if (loading) return /* @__PURE__ */ jsx(Text, { color: theme.warn, children: "\u27F3 loading\u2026" });
|
|
6818
6818
|
if (empty) return /* @__PURE__ */ jsx(Text, { color: theme.dim, children: emptyText ?? "No data." });
|
|
6819
6819
|
return /* @__PURE__ */ jsx(Fragment, { children });
|
|
6820
6820
|
}
|
|
@@ -6845,7 +6845,7 @@ var init_components = __esm({
|
|
|
6845
6845
|
});
|
|
6846
6846
|
|
|
6847
6847
|
// src/tui/local-log.ts
|
|
6848
|
-
import { closeSync, openSync, readSync, statSync } from "fs";
|
|
6848
|
+
import { closeSync, openSync, readFileSync as readFileSync6, readSync, statSync, writeFileSync as writeFileSync3 } from "fs";
|
|
6849
6849
|
import { homedir as homedir4 } from "os";
|
|
6850
6850
|
import { join as join6 } from "path";
|
|
6851
6851
|
function tailLines(file, maxBytes = 131072) {
|
|
@@ -6863,6 +6863,39 @@ function tailLines(file, maxBytes = 131072) {
|
|
|
6863
6863
|
return [];
|
|
6864
6864
|
}
|
|
6865
6865
|
}
|
|
6866
|
+
function deleteLocalEntry(at, tool, session) {
|
|
6867
|
+
try {
|
|
6868
|
+
const lines = readFileSync6(LOCAL_LOG, "utf-8").split("\n");
|
|
6869
|
+
let removed = 0;
|
|
6870
|
+
const kept = lines.filter((line) => {
|
|
6871
|
+
if (!line.trim()) return false;
|
|
6872
|
+
if (removed) return true;
|
|
6873
|
+
try {
|
|
6874
|
+
const j = JSON.parse(line);
|
|
6875
|
+
const hit = Date.parse(j.ts ?? "") === at && (j.tool ?? "?") === tool && (!session || j.session_id === session);
|
|
6876
|
+
if (hit) {
|
|
6877
|
+
removed++;
|
|
6878
|
+
return false;
|
|
6879
|
+
}
|
|
6880
|
+
} catch {
|
|
6881
|
+
}
|
|
6882
|
+
return true;
|
|
6883
|
+
});
|
|
6884
|
+
if (removed) writeFileSync3(LOCAL_LOG, kept.length ? kept.join("\n") + "\n" : "");
|
|
6885
|
+
return removed;
|
|
6886
|
+
} catch {
|
|
6887
|
+
return 0;
|
|
6888
|
+
}
|
|
6889
|
+
}
|
|
6890
|
+
function clearLocalLog() {
|
|
6891
|
+
try {
|
|
6892
|
+
const n = readFileSync6(LOCAL_LOG, "utf-8").split("\n").filter(Boolean).length;
|
|
6893
|
+
writeFileSync3(LOCAL_LOG, "");
|
|
6894
|
+
return n;
|
|
6895
|
+
} catch {
|
|
6896
|
+
return 0;
|
|
6897
|
+
}
|
|
6898
|
+
}
|
|
6866
6899
|
function parseLocalLines(lines) {
|
|
6867
6900
|
const out2 = [];
|
|
6868
6901
|
for (const line of lines) {
|
|
@@ -7062,11 +7095,19 @@ var audit_exports = {};
|
|
|
7062
7095
|
__export(audit_exports, {
|
|
7063
7096
|
block: () => block,
|
|
7064
7097
|
list: () => list2,
|
|
7098
|
+
remove: () => remove2,
|
|
7099
|
+
removeAll: () => removeAll,
|
|
7065
7100
|
whitelist: () => whitelist
|
|
7066
7101
|
});
|
|
7067
7102
|
function list2(query = {}) {
|
|
7068
7103
|
return request("GET", "/audit-logs", { query });
|
|
7069
7104
|
}
|
|
7105
|
+
function remove2(ids) {
|
|
7106
|
+
return request("DELETE", "/audit-logs", { body: { ids } });
|
|
7107
|
+
}
|
|
7108
|
+
function removeAll() {
|
|
7109
|
+
return request("DELETE", "/audit-logs", { body: { scope: "logs" } });
|
|
7110
|
+
}
|
|
7070
7111
|
function whitelist(id, scope = "exact") {
|
|
7071
7112
|
return request("POST", `/audit-logs/${encodeURIComponent(id)}/whitelist`, { body: { scope } });
|
|
7072
7113
|
}
|
|
@@ -7203,6 +7244,7 @@ function useLoader(fn, deps = []) {
|
|
|
7203
7244
|
const [loading, setLoading] = useState(true);
|
|
7204
7245
|
const [nonce, setNonce] = useState(0);
|
|
7205
7246
|
const alive = useRef(true);
|
|
7247
|
+
const quiet = useRef(false);
|
|
7206
7248
|
const fnRef = useRef(fn);
|
|
7207
7249
|
fnRef.current = fn;
|
|
7208
7250
|
useEffect(() => {
|
|
@@ -7212,7 +7254,8 @@ function useLoader(fn, deps = []) {
|
|
|
7212
7254
|
};
|
|
7213
7255
|
}, []);
|
|
7214
7256
|
useEffect(() => {
|
|
7215
|
-
setLoading(true);
|
|
7257
|
+
if (!quiet.current) setLoading(true);
|
|
7258
|
+
quiet.current = false;
|
|
7216
7259
|
fnRef.current().then((d) => {
|
|
7217
7260
|
if (!alive.current) return;
|
|
7218
7261
|
setData(d);
|
|
@@ -7225,7 +7268,11 @@ function useLoader(fn, deps = []) {
|
|
|
7225
7268
|
});
|
|
7226
7269
|
}, [nonce, ...deps]);
|
|
7227
7270
|
const reload = useCallback(() => setNonce((n) => n + 1), []);
|
|
7228
|
-
|
|
7271
|
+
const reloadQuiet = useCallback(() => {
|
|
7272
|
+
quiet.current = true;
|
|
7273
|
+
setNonce((n) => n + 1);
|
|
7274
|
+
}, []);
|
|
7275
|
+
return { data, error, loading, reload, reloadQuiet };
|
|
7229
7276
|
}
|
|
7230
7277
|
function usePoll(reload, intervalMs, enabled = true) {
|
|
7231
7278
|
useEffect(() => {
|
|
@@ -7261,7 +7308,7 @@ var init_hooks = __esm({
|
|
|
7261
7308
|
// src/tui/panels/Live.tsx
|
|
7262
7309
|
import { Box as Box2, Text as Text2, useInput } from "ink";
|
|
7263
7310
|
import TextInput from "ink-text-input";
|
|
7264
|
-
import { mkdirSync as mkdirSync3, writeFileSync as
|
|
7311
|
+
import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
7265
7312
|
import { homedir as homedir5 } from "os";
|
|
7266
7313
|
import { join as join7 } from "path";
|
|
7267
7314
|
import { useCallback as useCallback2, useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
|
|
@@ -7529,13 +7576,13 @@ function LivePanel({ active: active2 }) {
|
|
|
7529
7576
|
const insights = useLoader(() => api.stats.securityInsights(7));
|
|
7530
7577
|
const guard = useLoader(() => api.settings.getGuardStatus());
|
|
7531
7578
|
usePoll(() => {
|
|
7532
|
-
if (!paused()) sessions.
|
|
7579
|
+
if (!paused()) sessions.reloadQuiet();
|
|
7533
7580
|
}, 8e3, active2);
|
|
7534
7581
|
usePoll(() => {
|
|
7535
|
-
if (!paused()) insights.
|
|
7582
|
+
if (!paused()) insights.reloadQuiet();
|
|
7536
7583
|
}, 2e4, active2);
|
|
7537
7584
|
usePoll(() => {
|
|
7538
|
-
if (!paused()) guard.
|
|
7585
|
+
if (!paused()) guard.reloadQuiet();
|
|
7539
7586
|
}, 6e4, active2);
|
|
7540
7587
|
useEffect2(() => {
|
|
7541
7588
|
if (!detail) return;
|
|
@@ -7812,7 +7859,7 @@ function LivePanel({ active: active2 }) {
|
|
|
7812
7859
|
const file = join7(homedir5(), ".solongate", "live-export.jsonl");
|
|
7813
7860
|
try {
|
|
7814
7861
|
mkdirSync3(join7(homedir5(), ".solongate"), { recursive: true });
|
|
7815
|
-
|
|
7862
|
+
writeFileSync4(file, visibleDesc.map((x) => JSON.stringify(x)).join("\n") + "\n");
|
|
7816
7863
|
setActionMsg({ text: `\u2713 exported ${visibleDesc.length} lines \u2192 ${file}`, level: "ok", until: Date.now() + 6e3 });
|
|
7817
7864
|
} catch (err2) {
|
|
7818
7865
|
setActionMsg({ text: "\u2717 export failed: " + (err2 instanceof Error ? err2.message : String(err2)), level: "bad", until: Date.now() + 6e3 });
|
|
@@ -8867,12 +8914,14 @@ function AuditPanel({ active: active2, focused }) {
|
|
|
8867
8914
|
const [si, setSi] = useState6(0);
|
|
8868
8915
|
const [sessSearch, setSessSearch] = useState6("");
|
|
8869
8916
|
const [sessSel, setSessSel] = useState6(0);
|
|
8917
|
+
const [confirm, setConfirm] = useState6(null);
|
|
8918
|
+
const [msg, setMsg] = useState6(null);
|
|
8870
8919
|
const toTop = () => setSel(0);
|
|
8871
8920
|
const statsQ = useLoader(() => source === "cloud" ? api.stats.get() : Promise.resolve(null), [source]);
|
|
8872
8921
|
const tsQ = useLoader(() => source === "cloud" ? api.stats.timeseries({ period: "24h" }) : Promise.resolve(null), [source]);
|
|
8873
8922
|
usePoll(() => {
|
|
8874
|
-
statsQ.
|
|
8875
|
-
tsQ.
|
|
8923
|
+
statsQ.reloadQuiet();
|
|
8924
|
+
tsQ.reloadQuiet();
|
|
8876
8925
|
}, 15e3, active2 && source === "cloud");
|
|
8877
8926
|
const query = {
|
|
8878
8927
|
filter: DECISIONS[di],
|
|
@@ -8888,9 +8937,9 @@ function AuditPanel({ active: active2, focused }) {
|
|
|
8888
8937
|
() => source === "cloud" ? api.audit.list(query) : Promise.resolve(null),
|
|
8889
8938
|
[source, di, gi, tool, agent, search, sessFilter, page]
|
|
8890
8939
|
);
|
|
8891
|
-
usePoll(cloudQ.
|
|
8940
|
+
usePoll(cloudQ.reloadQuiet, 6e3, active2 && source === "cloud" && view === "logs" && !editing && page === 0);
|
|
8892
8941
|
const localQ = useLoader(() => source === "local" ? Promise.resolve(loadLocalRows()) : Promise.resolve(null), [source]);
|
|
8893
|
-
usePoll(localQ.
|
|
8942
|
+
usePoll(localQ.reloadQuiet, 6e3, active2 && source === "local" && view === "logs" && !editing && page === 0);
|
|
8894
8943
|
let pageRows = [];
|
|
8895
8944
|
let total = 0;
|
|
8896
8945
|
if (source === "cloud") {
|
|
@@ -8918,7 +8967,7 @@ function AuditPanel({ active: active2, focused }) {
|
|
|
8918
8967
|
() => source === "cloud" ? api.agents.live({ limit: 100, includeDeactivated: true }) : Promise.resolve(null),
|
|
8919
8968
|
[source]
|
|
8920
8969
|
);
|
|
8921
|
-
usePoll(agentsQ.
|
|
8970
|
+
usePoll(agentsQ.reloadQuiet, 8e3, active2 && source === "cloud" && view === "sessions");
|
|
8922
8971
|
let sessions = [];
|
|
8923
8972
|
if (source === "cloud") {
|
|
8924
8973
|
sessions = (agentsQ.data?.agents ?? []).map((a) => ({
|
|
@@ -8952,6 +9001,31 @@ function AuditPanel({ active: active2, focused }) {
|
|
|
8952
9001
|
() => view === "detail" && current?.session && source === "cloud" ? api.audit.list({ session_id: current.session, limit: 40 }) : Promise.resolve(null),
|
|
8953
9002
|
[view, current?.session, source]
|
|
8954
9003
|
);
|
|
9004
|
+
const logsLoading = (source === "cloud" ? cloudQ.loading : localQ.loading) && !editing;
|
|
9005
|
+
const sessLoading = source === "cloud" ? agentsQ.loading : localQ.loading;
|
|
9006
|
+
const doDelete = (kind) => {
|
|
9007
|
+
setMsg({ text: "deleting\u2026", level: "ok" });
|
|
9008
|
+
const run12 = async () => {
|
|
9009
|
+
if (source === "cloud") {
|
|
9010
|
+
if (kind === "one") {
|
|
9011
|
+
if (!current) throw new Error("nothing selected");
|
|
9012
|
+
await api.audit.remove([current.id]);
|
|
9013
|
+
} else {
|
|
9014
|
+
await api.audit.removeAll();
|
|
9015
|
+
}
|
|
9016
|
+
cloudQ.reload();
|
|
9017
|
+
statsQ.reloadQuiet();
|
|
9018
|
+
} else {
|
|
9019
|
+
const n = kind === "one" && current ? deleteLocalEntry(current.at, current.tool, current.session) : kind === "all" ? clearLocalLog() : 0;
|
|
9020
|
+
if (!n) throw new Error("entry not found in the local file");
|
|
9021
|
+
localQ.reload();
|
|
9022
|
+
}
|
|
9023
|
+
};
|
|
9024
|
+
run12().then(() => {
|
|
9025
|
+
setMsg({ text: kind === "one" ? "\u2713 entry deleted" : `\u2713 ALL ${source} logs deleted`, level: "ok" });
|
|
9026
|
+
toTop();
|
|
9027
|
+
}).catch((e) => setMsg({ text: "\u2717 " + (e instanceof Error ? e.message : String(e)), level: "bad" }));
|
|
9028
|
+
};
|
|
8955
9029
|
useInput5(
|
|
8956
9030
|
(input, key) => {
|
|
8957
9031
|
if (view === "detail") {
|
|
@@ -8962,6 +9036,11 @@ function AuditPanel({ active: active2, focused }) {
|
|
|
8962
9036
|
else if (key.pageDown) setDetailScroll((n) => n + 10);
|
|
8963
9037
|
return;
|
|
8964
9038
|
}
|
|
9039
|
+
if (view === "logs" ? logsLoading : sessLoading) return;
|
|
9040
|
+
if (confirm && input !== "x" && input !== "X") {
|
|
9041
|
+
setConfirm(null);
|
|
9042
|
+
setMsg(null);
|
|
9043
|
+
}
|
|
8965
9044
|
if (input === "s") {
|
|
8966
9045
|
setSource((s) => s === "cloud" ? "local" : "cloud");
|
|
8967
9046
|
setPage(0);
|
|
@@ -8978,7 +9057,7 @@ function AuditPanel({ active: active2, focused }) {
|
|
|
8978
9057
|
else if (key.downArrow) setSessSel((n) => Math.min(sessionsFiltered.length - 1, n + 1));
|
|
8979
9058
|
else if (key.pageUp) setSessSel((n) => Math.max(0, n - 10));
|
|
8980
9059
|
else if (key.pageDown) setSessSel((n) => Math.min(sessionsFiltered.length - 1, n + 10));
|
|
8981
|
-
else if (key.return
|
|
9060
|
+
else if (key.return) {
|
|
8982
9061
|
if (currentSess) {
|
|
8983
9062
|
setSessFilter(currentSess.id);
|
|
8984
9063
|
setPage(0);
|
|
@@ -9000,17 +9079,17 @@ function AuditPanel({ active: active2, focused }) {
|
|
|
9000
9079
|
else if (key.downArrow) setSel((n) => Math.min(pageRows.length - 1, n + 1));
|
|
9001
9080
|
else if (key.pageUp) setSel((n) => Math.max(0, n - 10));
|
|
9002
9081
|
else if (key.pageDown) setSel((n) => Math.min(pageRows.length - 1, n + 10));
|
|
9003
|
-
else if (key.return
|
|
9082
|
+
else if (key.return) {
|
|
9004
9083
|
if (current) {
|
|
9005
9084
|
setDetailScroll(0);
|
|
9006
9085
|
setView("detail");
|
|
9007
9086
|
}
|
|
9008
|
-
} else if (
|
|
9087
|
+
} else if (key.rightArrow) {
|
|
9009
9088
|
if (page < pages - 1) {
|
|
9010
9089
|
setPage(page + 1);
|
|
9011
9090
|
toTop();
|
|
9012
9091
|
}
|
|
9013
|
-
} else if (
|
|
9092
|
+
} else if (key.leftArrow) {
|
|
9014
9093
|
if (page > 0) {
|
|
9015
9094
|
setPage(page - 1);
|
|
9016
9095
|
toTop();
|
|
@@ -9023,6 +9102,23 @@ function AuditPanel({ active: active2, focused }) {
|
|
|
9023
9102
|
setGi((n) => (n + 1) % SIGNALS.length);
|
|
9024
9103
|
setPage(0);
|
|
9025
9104
|
toTop();
|
|
9105
|
+
} else if (input === "x") {
|
|
9106
|
+
if (!current) return;
|
|
9107
|
+
if (confirm?.kind !== "one" || confirm.key !== current.id) {
|
|
9108
|
+
setConfirm({ kind: "one", key: current.id });
|
|
9109
|
+
setMsg({ text: `delete ${current.decision} ${current.tool} (${ago(current.at)} ago)? press x again`, level: "bad" });
|
|
9110
|
+
return;
|
|
9111
|
+
}
|
|
9112
|
+
setConfirm(null);
|
|
9113
|
+
doDelete("one");
|
|
9114
|
+
} else if (input === "X") {
|
|
9115
|
+
if (confirm?.kind !== "all") {
|
|
9116
|
+
setConfirm({ kind: "all", key: "all" });
|
|
9117
|
+
setMsg({ text: `DELETE ALL ${source} logs (${total} entries)? press X again`, level: "bad" });
|
|
9118
|
+
return;
|
|
9119
|
+
}
|
|
9120
|
+
setConfirm(null);
|
|
9121
|
+
doDelete("all");
|
|
9026
9122
|
} else if (input === "t") setEditing("tool");
|
|
9027
9123
|
else if (input === "n") setEditing("agent");
|
|
9028
9124
|
else if (input === "/") setEditing("search");
|
|
@@ -9149,8 +9245,7 @@ function AuditPanel({ active: active2, focused }) {
|
|
|
9149
9245
|
const selC = Math.min(sessSel, Math.max(0, sessionsFiltered.length - 1));
|
|
9150
9246
|
const start2 = Math.min(Math.max(0, selC - Math.floor((listRows2 - 1) / 2)), Math.max(0, sessionsFiltered.length - listRows2));
|
|
9151
9247
|
const win = sessionsFiltered.slice(start2, start2 + listRows2);
|
|
9152
|
-
|
|
9153
|
-
return /* @__PURE__ */ jsx6(DataView, { loading: loading2, error: source === "cloud" ? agentsQ.error : localQ.error, children: /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
9248
|
+
return /* @__PURE__ */ jsx6(DataView, { loading: sessLoading, error: source === "cloud" ? agentsQ.error : localQ.error, children: /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
9154
9249
|
strip,
|
|
9155
9250
|
/* @__PURE__ */ jsxs6(Box6, { children: [
|
|
9156
9251
|
srcChip,
|
|
@@ -9213,15 +9308,14 @@ function AuditPanel({ active: active2, focused }) {
|
|
|
9213
9308
|
] }) : null
|
|
9214
9309
|
] }) });
|
|
9215
9310
|
}
|
|
9216
|
-
const headerRows = 6 + (editing && editing !== "sess-search" ? 1 : 0);
|
|
9311
|
+
const headerRows = 6 + (editing && editing !== "sess-search" ? 1 : 0) + (msg ? 1 : 0);
|
|
9217
9312
|
const listRows = Math.max(4, rows - headerRows);
|
|
9218
9313
|
const selClamped = Math.min(sel, Math.max(0, pageRows.length - 1));
|
|
9219
9314
|
const maxStart = Math.max(0, pageRows.length - listRows);
|
|
9220
9315
|
const start = Math.min(Math.max(0, selClamped - Math.floor((listRows - 1) / 2)), maxStart);
|
|
9221
9316
|
const windowed = pageRows.slice(start, start + listRows);
|
|
9222
9317
|
const reasonW = Math.min(60, Math.max(12, cols - 67));
|
|
9223
|
-
|
|
9224
|
-
return /* @__PURE__ */ jsx6(DataView, { loading, error: source === "cloud" ? cloudQ.error : localQ.error, children: /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
9318
|
+
return /* @__PURE__ */ jsx6(DataView, { loading: logsLoading, error: source === "cloud" ? cloudQ.error : localQ.error, children: /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
9225
9319
|
strip,
|
|
9226
9320
|
/* @__PURE__ */ jsxs6(Box6, { children: [
|
|
9227
9321
|
srcChip,
|
|
@@ -9234,7 +9328,8 @@ function AuditPanel({ active: active2, focused }) {
|
|
|
9234
9328
|
chip("search", search || "\xB7", !!search),
|
|
9235
9329
|
sessFilter ? chip("sess", sessFilter.slice(0, 8), true) : null
|
|
9236
9330
|
] }),
|
|
9237
|
-
/* @__PURE__ */ jsx6(Text6, { color: theme.dim, wrap: "truncate", children: focused ? "\u2191\u2193 select \xB7 enter full entry \xB7
|
|
9331
|
+
/* @__PURE__ */ jsx6(Text6, { color: theme.dim, wrap: "truncate", children: focused ? "\u2191\u2193 select \xB7 enter full entry \xB7 \u2190\u2192 page \xB7 f dec \xB7 g sig \xB7 t tool \xB7 n agent \xB7 / search \xB7 x del \xB7 X del ALL \xB7 s source \xB7 v sessions \xB7 c clear" : "press \u2192 to browse" }),
|
|
9332
|
+
msg ? /* @__PURE__ */ jsx6(Text6, { color: msg.level === "bad" ? theme.bad : theme.ok, children: truncate2(msg.text, cols) }) : null,
|
|
9238
9333
|
editing && editing !== "sess-search" ? /* @__PURE__ */ jsxs6(Box6, { children: [
|
|
9239
9334
|
/* @__PURE__ */ jsxs6(Text6, { color: theme.warn, children: [
|
|
9240
9335
|
editing,
|
|
@@ -9332,107 +9427,11 @@ var init_Audit = __esm({
|
|
|
9332
9427
|
}
|
|
9333
9428
|
});
|
|
9334
9429
|
|
|
9335
|
-
// src/tui/panels/Agents.tsx
|
|
9336
|
-
import { Box as Box7, Text as Text7, useInput as useInput6 } from "ink";
|
|
9337
|
-
import { useState as useState7 } from "react";
|
|
9338
|
-
import { Fragment as Fragment5, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
9339
|
-
function Bar({ label, value, max = 100, width: width2 = 16, color = theme.accent }) {
|
|
9340
|
-
const filled = max > 0 ? Math.round(Math.min(value, max) / max * width2) : 0;
|
|
9341
|
-
return /* @__PURE__ */ jsxs7(Text7, { wrap: "truncate", children: [
|
|
9342
|
-
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: label.padEnd(9) }),
|
|
9343
|
-
/* @__PURE__ */ jsx7(Text7, { color, children: "\u2588".repeat(filled) }),
|
|
9344
|
-
/* @__PURE__ */ jsx7(Text7, { color: "#233457", children: "\u2591".repeat(Math.max(0, width2 - filled)) }),
|
|
9345
|
-
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: " " + value })
|
|
9346
|
-
] });
|
|
9347
|
-
}
|
|
9348
|
-
function AgentsPanel({ focused }) {
|
|
9349
|
-
const live2 = useLoader(() => api.agents.live({ limit: 30, includeDeactivated: true }));
|
|
9350
|
-
usePoll(live2.reload, 6e3, focused ? false : true);
|
|
9351
|
-
const [sel, setSel] = useState7(0);
|
|
9352
|
-
const agents = (live2.data?.agents ?? []).filter((a) => a.agent_id);
|
|
9353
|
-
const selected = agents[Math.min(sel, Math.max(0, agents.length - 1))];
|
|
9354
|
-
const detail = useLoader(() => selected?.agent_id ? api.agents.get(selected.agent_id) : Promise.resolve(null), [selected?.agent_id]);
|
|
9355
|
-
useInput6(
|
|
9356
|
-
(_input, key) => {
|
|
9357
|
-
if (key.upArrow) setSel((n) => Math.max(0, n - 1));
|
|
9358
|
-
else if (key.downArrow) setSel((n) => Math.min(agents.length - 1, n + 1));
|
|
9359
|
-
},
|
|
9360
|
-
{ isActive: focused }
|
|
9361
|
-
);
|
|
9362
|
-
const d = detail.data;
|
|
9363
|
-
const base = d?.baseline;
|
|
9364
|
-
const radar = base?.radar;
|
|
9365
|
-
const anomalies2 = d?.anomalies ?? [];
|
|
9366
|
-
const tmap = d?.trust_map;
|
|
9367
|
-
const tools = tmap?.tools ?? [];
|
|
9368
|
-
const resources = tmap?.resources ?? [];
|
|
9369
|
-
const listW = 30;
|
|
9370
|
-
return /* @__PURE__ */ jsx7(DataView, { loading: live2.loading && !live2.data, error: live2.error, empty: !!live2.data && agents.length === 0, emptyText: "No identified agents yet.", children: /* @__PURE__ */ jsxs7(Box7, { children: [
|
|
9371
|
-
/* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", width: listW, marginRight: 2, overflow: "hidden", children: [
|
|
9372
|
-
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: focused ? "\u2191\u2193 select agent" : "press \u2192 to browse" }),
|
|
9373
|
-
agents.slice(0, 16).map((a, i) => /* @__PURE__ */ jsxs7(Text7, { wrap: "truncate", backgroundColor: focused && i === sel ? "#1c2f63" : void 0, bold: i === sel, children: [
|
|
9374
|
-
/* @__PURE__ */ jsxs7(Text7, { color: statusColor(a.status), children: [
|
|
9375
|
-
a.status === "active" ? "\u25CF" : a.status === "idle" ? "\u25D0" : "\u25CB",
|
|
9376
|
-
" "
|
|
9377
|
-
] }),
|
|
9378
|
-
/* @__PURE__ */ jsx7(Text7, { color: theme.accent, children: truncate2(a.agent_name ?? a.agent_id ?? "?", 16).padEnd(17) }),
|
|
9379
|
-
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: `t${a.trust_score}` })
|
|
9380
|
-
] }, a.session_id))
|
|
9381
|
-
] }),
|
|
9382
|
-
/* @__PURE__ */ jsx7(Box7, { flexDirection: "column", flexGrow: 1, overflow: "hidden", children: !selected ? /* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "select an agent" }) : detail.loading && !d ? /* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "loading profile\u2026" }) : !d ? /* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "no profile (agent has no calls yet)" }) : /* @__PURE__ */ jsxs7(Fragment5, { children: [
|
|
9383
|
-
/* @__PURE__ */ jsxs7(Box7, { children: [
|
|
9384
|
-
/* @__PURE__ */ jsx7(Text7, { bold: true, color: theme.accentBright, children: truncate2(selected.agent_name ?? selected.agent_id ?? "?", 22) }),
|
|
9385
|
-
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: ` trust ${base?.trustScore ?? "\u2014"}/100 \xB7 ${base?.character ?? ""}` })
|
|
9386
|
-
] }),
|
|
9387
|
-
base?.characterBlurb ? /* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: truncate2(String(base.characterBlurb), 70) }) : null,
|
|
9388
|
-
radar ? /* @__PURE__ */ jsxs7(Box7, { marginTop: 1, flexDirection: "column", children: [
|
|
9389
|
-
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "Behaviour radar (0\u2013100)" }),
|
|
9390
|
-
/* @__PURE__ */ jsx7(Bar, { label: "read", value: Math.round((radar.read ?? 0) * 100) }),
|
|
9391
|
-
/* @__PURE__ */ jsx7(Bar, { label: "write", value: Math.round((radar.write ?? 0) * 100), color: theme.warn }),
|
|
9392
|
-
/* @__PURE__ */ jsx7(Bar, { label: "execute", value: Math.round((radar.execute ?? 0) * 100), color: theme.warn }),
|
|
9393
|
-
/* @__PURE__ */ jsx7(Bar, { label: "network", value: Math.round((radar.network ?? 0) * 100) }),
|
|
9394
|
-
/* @__PURE__ */ jsx7(Bar, { label: "complian.", value: Math.round((radar.compliance ?? 0) * 100), color: theme.ok })
|
|
9395
|
-
] }) : null,
|
|
9396
|
-
/* @__PURE__ */ jsxs7(Box7, { marginTop: 1, flexDirection: "column", children: [
|
|
9397
|
-
/* @__PURE__ */ jsxs7(Text7, { color: theme.dim, children: [
|
|
9398
|
-
"Anomalies ",
|
|
9399
|
-
anomalies2.length ? `(${anomalies2.length})` : ""
|
|
9400
|
-
] }),
|
|
9401
|
-
anomalies2.length === 0 ? /* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: " none" }) : anomalies2.slice(0, 4).map((an, i) => /* @__PURE__ */ jsxs7(Text7, { wrap: "truncate", children: [
|
|
9402
|
-
/* @__PURE__ */ jsx7(Text7, { color: sevColor(String(an.severity)), children: ` ${String(an.severity).toUpperCase().slice(0, 4).padEnd(5)}` }),
|
|
9403
|
-
/* @__PURE__ */ jsx7(Text7, { color: theme.accent, children: String(an.kind).padEnd(12) }),
|
|
9404
|
-
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: truncate2(String(an.description ?? ""), 44) })
|
|
9405
|
-
] }, i))
|
|
9406
|
-
] }),
|
|
9407
|
-
/* @__PURE__ */ jsxs7(Box7, { marginTop: 1, flexDirection: "column", children: [
|
|
9408
|
-
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "Trust map \xB7 top tools" }),
|
|
9409
|
-
tools.slice(0, 4).map((t, i) => /* @__PURE__ */ jsxs7(Text7, { wrap: "truncate", children: [
|
|
9410
|
-
/* @__PURE__ */ jsx7(Text7, { color: t.anomalous ? theme.bad : theme.accent, children: ` ${truncate2(String(t.name), 16).padEnd(17)}` }),
|
|
9411
|
-
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: `${t.count}\xD7 ${t.permission ?? ""}` })
|
|
9412
|
-
] }, i)),
|
|
9413
|
-
resources.slice(0, 3).map((r, i) => /* @__PURE__ */ jsx7(Text7, { 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))
|
|
9414
|
-
] })
|
|
9415
|
-
] }) })
|
|
9416
|
-
] }) });
|
|
9417
|
-
}
|
|
9418
|
-
var statusColor, sevColor;
|
|
9419
|
-
var init_Agents = __esm({
|
|
9420
|
-
"src/tui/panels/Agents.tsx"() {
|
|
9421
|
-
"use strict";
|
|
9422
|
-
init_api_client();
|
|
9423
|
-
init_components();
|
|
9424
|
-
init_hooks();
|
|
9425
|
-
init_theme();
|
|
9426
|
-
statusColor = (s) => s === "active" ? theme.ok : s === "idle" ? theme.warn : theme.dim;
|
|
9427
|
-
sevColor = (s) => s === "high" ? theme.bad : s === "medium" ? theme.warn : theme.dim;
|
|
9428
|
-
}
|
|
9429
|
-
});
|
|
9430
|
-
|
|
9431
9430
|
// src/tui/panels/Settings.tsx
|
|
9432
|
-
import { Box as
|
|
9431
|
+
import { Box as Box7, Text as Text7, useInput as useInput6 } from "ink";
|
|
9433
9432
|
import TextInput5 from "ink-text-input";
|
|
9434
|
-
import { useState as
|
|
9435
|
-
import { jsx as
|
|
9433
|
+
import { useState as useState7 } from "react";
|
|
9434
|
+
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
9436
9435
|
function alertBodyFor(channel) {
|
|
9437
9436
|
const c2 = channel.trim();
|
|
9438
9437
|
const base = { name: "dataroom alert", threshold: 5, windowSeconds: 60, signal: "any" };
|
|
@@ -9443,12 +9442,12 @@ function alertBodyFor(channel) {
|
|
|
9443
9442
|
function SettingsPanel({ active: active2, focused }) {
|
|
9444
9443
|
void active2;
|
|
9445
9444
|
const { cols, rows } = usePanelSize();
|
|
9446
|
-
const [sel, setSel] =
|
|
9447
|
-
const [editing, setEditing] =
|
|
9448
|
-
const [input, setInput] =
|
|
9449
|
-
const [confirmDel, setConfirmDel] =
|
|
9450
|
-
const [msg, setMsg] =
|
|
9451
|
-
const [busy, setBusy] =
|
|
9445
|
+
const [sel, setSel] = useState7(0);
|
|
9446
|
+
const [editing, setEditing] = useState7(null);
|
|
9447
|
+
const [input, setInput] = useState7("");
|
|
9448
|
+
const [confirmDel, setConfirmDel] = useState7(null);
|
|
9449
|
+
const [msg, setMsg] = useState7(null);
|
|
9450
|
+
const [busy, setBusy] = useState7(false);
|
|
9452
9451
|
const localQ = useLoader(() => api.settings.getLocalLogs());
|
|
9453
9452
|
const whQ = useLoader(() => api.settings.getWebhooks());
|
|
9454
9453
|
const alertQ = useLoader(() => api.settings.getAlerts());
|
|
@@ -9518,7 +9517,7 @@ function SettingsPanel({ active: active2, focused }) {
|
|
|
9518
9517
|
run12("alert rule added", () => api.settings.createAlert(alertBodyFor(v)), alertQ.reload);
|
|
9519
9518
|
}
|
|
9520
9519
|
};
|
|
9521
|
-
|
|
9520
|
+
useInput6(
|
|
9522
9521
|
(inp, key) => {
|
|
9523
9522
|
setMsg(null);
|
|
9524
9523
|
if (key.upArrow) {
|
|
@@ -9557,7 +9556,7 @@ function SettingsPanel({ active: active2, focused }) {
|
|
|
9557
9556
|
const loading = localQ.loading && !localQ.data || whQ.loading && !whQ.data || alertQ.loading && !alertQ.data;
|
|
9558
9557
|
const error = localQ.error ?? whQ.error ?? alertQ.error;
|
|
9559
9558
|
const mark = (r) => keyOf(r) === keyOf(cur) && focused ? "\u25B8 " : " ";
|
|
9560
|
-
const onOff = (on) => on ? /* @__PURE__ */
|
|
9559
|
+
const onOff = (on) => on ? /* @__PURE__ */ jsx7(Text7, { color: theme.ok, children: "on " }) : /* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "off" });
|
|
9561
9560
|
const chanOf = (rule) => [...(rule.slackUrls ?? []).map((u) => "slack " + u), ...rule.emails ?? [], ...(rule.telegram ?? []).map((t) => "tg " + t)].join(", ") || "\u2014";
|
|
9562
9561
|
const listBudget = Math.max(4, rows - 8);
|
|
9563
9562
|
const start = Math.min(Math.max(0, selClamped - Math.floor(listBudget / 2)), Math.max(0, rowsAll.length - listBudget));
|
|
@@ -9565,68 +9564,68 @@ function SettingsPanel({ active: active2, focused }) {
|
|
|
9565
9564
|
const i = rowsAll.findIndex((x) => keyOf(x) === keyOf(r));
|
|
9566
9565
|
return i >= start && i < start + listBudget;
|
|
9567
9566
|
};
|
|
9568
|
-
return /* @__PURE__ */
|
|
9569
|
-
/* @__PURE__ */
|
|
9570
|
-
editing ? /* @__PURE__ */
|
|
9571
|
-
/* @__PURE__ */
|
|
9572
|
-
/* @__PURE__ */
|
|
9573
|
-
] }) : msg ? /* @__PURE__ */
|
|
9574
|
-
inWindow(rowsAll[0]) || inWindow(rowsAll[1]) ? /* @__PURE__ */
|
|
9575
|
-
/* @__PURE__ */
|
|
9567
|
+
return /* @__PURE__ */ jsx7(DataView, { loading, error, children: /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
9568
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: focused ? "\u2191\u2193 move \xB7 enter/space toggle-edit-add \xB7 e events \xB7 d delete \xB7 r refresh" : "press \u2192 to configure" }),
|
|
9569
|
+
editing ? /* @__PURE__ */ jsxs7(Box7, { children: [
|
|
9570
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.warn, children: editing === "path" ? "local log path: " : editing === "wh-url" ? "webhook url: " : "channel (slack url / email / telegram id): " }),
|
|
9571
|
+
/* @__PURE__ */ jsx7(TextInput5, { value: input, onChange: setInput, onSubmit: submitInput })
|
|
9572
|
+
] }) : msg ? /* @__PURE__ */ jsx7(Text7, { color: msg.level === "bad" ? theme.bad : theme.ok, children: truncate2(msg.text, cols) }) : /* @__PURE__ */ jsx7(Text7, { children: " " }),
|
|
9573
|
+
inWindow(rowsAll[0]) || inWindow(rowsAll[1]) ? /* @__PURE__ */ jsxs7(Box7, { marginTop: 1, flexDirection: "column", children: [
|
|
9574
|
+
/* @__PURE__ */ jsxs7(Text7, { bold: true, color: theme.accentBright, children: [
|
|
9576
9575
|
"LOCAL LOGS ",
|
|
9577
|
-
/* @__PURE__ */
|
|
9576
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "\u2014 hooks mirror every decision to a file on the agent machine" })
|
|
9578
9577
|
] }),
|
|
9579
|
-
/* @__PURE__ */
|
|
9580
|
-
/* @__PURE__ */
|
|
9581
|
-
/* @__PURE__ */
|
|
9578
|
+
/* @__PURE__ */ jsxs7(Text7, { wrap: "truncate", children: [
|
|
9579
|
+
/* @__PURE__ */ jsx7(Text7, { color: keyOf(cur) === "ll-enabled" && focused ? theme.accentBright : theme.dim, children: mark(rowsAll[0]) }),
|
|
9580
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "enabled ".padEnd(10) }),
|
|
9582
9581
|
onOff(!!local?.enabled),
|
|
9583
|
-
/* @__PURE__ */
|
|
9582
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: " enter toggles" })
|
|
9584
9583
|
] }),
|
|
9585
|
-
/* @__PURE__ */
|
|
9586
|
-
/* @__PURE__ */
|
|
9587
|
-
/* @__PURE__ */
|
|
9588
|
-
local?.path ? /* @__PURE__ */
|
|
9584
|
+
/* @__PURE__ */ jsxs7(Text7, { wrap: "truncate", children: [
|
|
9585
|
+
/* @__PURE__ */ jsx7(Text7, { color: keyOf(cur) === "ll-path" && focused ? theme.accentBright : theme.dim, children: mark(rowsAll[1]) }),
|
|
9586
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "path ".padEnd(10) }),
|
|
9587
|
+
local?.path ? /* @__PURE__ */ jsx7(Text7, { color: theme.accent, children: truncate2(local.path, cols - 14) }) : /* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "not set \u2014 enter to edit" })
|
|
9589
9588
|
] })
|
|
9590
9589
|
] }) : null,
|
|
9591
|
-
/* @__PURE__ */
|
|
9592
|
-
/* @__PURE__ */
|
|
9590
|
+
/* @__PURE__ */ jsxs7(Box7, { marginTop: 1, flexDirection: "column", children: [
|
|
9591
|
+
/* @__PURE__ */ jsxs7(Text7, { bold: true, color: theme.accentBright, children: [
|
|
9593
9592
|
"WEBHOOKS ",
|
|
9594
|
-
/* @__PURE__ */
|
|
9593
|
+
/* @__PURE__ */ jsxs7(Text7, { color: theme.dim, children: [
|
|
9595
9594
|
"\u2014 POST every matching event to your endpoint (",
|
|
9596
9595
|
webhooks.length,
|
|
9597
9596
|
")"
|
|
9598
9597
|
] })
|
|
9599
9598
|
] }),
|
|
9600
|
-
webhooks.filter((wh) => inWindow({ kind: "wh", wh })).map((wh) => /* @__PURE__ */
|
|
9601
|
-
/* @__PURE__ */
|
|
9599
|
+
webhooks.filter((wh) => inWindow({ kind: "wh", wh })).map((wh) => /* @__PURE__ */ jsxs7(Text7, { wrap: "truncate", children: [
|
|
9600
|
+
/* @__PURE__ */ jsx7(Text7, { color: keyOf(cur) === "wh:" + wh.id && focused ? theme.accentBright : theme.dim, children: mark({ kind: "wh", wh }) }),
|
|
9602
9601
|
onOff(wh.enabled),
|
|
9603
|
-
/* @__PURE__ */
|
|
9604
|
-
/* @__PURE__ */
|
|
9602
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.warn, children: (" " + wh.events).padEnd(9) }),
|
|
9603
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.accent, children: truncate2(wh.url, cols - 16) })
|
|
9605
9604
|
] }, wh.id)),
|
|
9606
|
-
inWindow(rowsAll.find((r) => r.kind === "wh-add")) ? /* @__PURE__ */
|
|
9607
|
-
/* @__PURE__ */
|
|
9608
|
-
/* @__PURE__ */
|
|
9605
|
+
inWindow(rowsAll.find((r) => r.kind === "wh-add")) ? /* @__PURE__ */ jsxs7(Text7, { children: [
|
|
9606
|
+
/* @__PURE__ */ jsx7(Text7, { color: cur.kind === "wh-add" && focused ? theme.accentBright : theme.dim, children: mark({ kind: "wh-add" }) }),
|
|
9607
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "+ add webhook (enter)" })
|
|
9609
9608
|
] }) : null
|
|
9610
9609
|
] }),
|
|
9611
|
-
/* @__PURE__ */
|
|
9612
|
-
/* @__PURE__ */
|
|
9610
|
+
/* @__PURE__ */ jsxs7(Box7, { marginTop: 1, flexDirection: "column", children: [
|
|
9611
|
+
/* @__PURE__ */ jsxs7(Text7, { bold: true, color: theme.accentBright, children: [
|
|
9613
9612
|
"ALERTS ",
|
|
9614
|
-
/* @__PURE__ */
|
|
9613
|
+
/* @__PURE__ */ jsxs7(Text7, { color: theme.dim, children: [
|
|
9615
9614
|
"\u2014 notify on a signal spike (",
|
|
9616
9615
|
alerts.length,
|
|
9617
9616
|
")"
|
|
9618
9617
|
] })
|
|
9619
9618
|
] }),
|
|
9620
|
-
alerts.filter((rule) => inWindow({ kind: "alert", rule })).map((rule) => /* @__PURE__ */
|
|
9621
|
-
/* @__PURE__ */
|
|
9619
|
+
alerts.filter((rule) => inWindow({ kind: "alert", rule })).map((rule) => /* @__PURE__ */ jsxs7(Text7, { wrap: "truncate", children: [
|
|
9620
|
+
/* @__PURE__ */ jsx7(Text7, { color: keyOf(cur) === "alert:" + rule.id && focused ? theme.accentBright : theme.dim, children: mark({ kind: "alert", rule }) }),
|
|
9622
9621
|
onOff(rule.enabled),
|
|
9623
|
-
/* @__PURE__ */
|
|
9624
|
-
/* @__PURE__ */
|
|
9625
|
-
/* @__PURE__ */
|
|
9622
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.warn, children: (" " + rule.signal).padEnd(11) }),
|
|
9623
|
+
/* @__PURE__ */ jsx7(Text7, { children: `\u2265${rule.threshold}/${rule.windowSeconds}s ` }),
|
|
9624
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.accent, children: truncate2(chanOf(rule), cols - 26) })
|
|
9626
9625
|
] }, rule.id)),
|
|
9627
|
-
inWindow(rowsAll[rowsAll.length - 1]) ? /* @__PURE__ */
|
|
9628
|
-
/* @__PURE__ */
|
|
9629
|
-
/* @__PURE__ */
|
|
9626
|
+
inWindow(rowsAll[rowsAll.length - 1]) ? /* @__PURE__ */ jsxs7(Text7, { children: [
|
|
9627
|
+
/* @__PURE__ */ jsx7(Text7, { color: cur.kind === "alert-add" && focused ? theme.accentBright : theme.dim, children: mark({ kind: "alert-add" }) }),
|
|
9628
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "+ add alert (enter \u2014 one channel: slack url, email or telegram chat id)" })
|
|
9630
9629
|
] }) : null
|
|
9631
9630
|
] })
|
|
9632
9631
|
] }) });
|
|
@@ -9644,17 +9643,17 @@ var init_Settings = __esm({
|
|
|
9644
9643
|
});
|
|
9645
9644
|
|
|
9646
9645
|
// src/tui/App.tsx
|
|
9647
|
-
import { Box as
|
|
9648
|
-
import { useState as
|
|
9649
|
-
import { jsx as
|
|
9646
|
+
import { Box as Box8, Text as Text8, useApp, useInput as useInput7 } from "ink";
|
|
9647
|
+
import { useState as useState8 } from "react";
|
|
9648
|
+
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
9650
9649
|
function LiveHint() {
|
|
9651
|
-
return /* @__PURE__ */
|
|
9652
|
-
/* @__PURE__ */
|
|
9653
|
-
/* @__PURE__ */
|
|
9654
|
-
/* @__PURE__ */
|
|
9655
|
-
/* @__PURE__ */
|
|
9650
|
+
return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
|
|
9651
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.accentBright, bold: true, children: "\u25B6 REALTIME CONSOLE" }),
|
|
9652
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: "Fullscreen live monitor \u2014 streaming tool calls, active charts," }),
|
|
9653
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: "counters, DLP hits and denial alerts. Updates every 2s." }),
|
|
9654
|
+
/* @__PURE__ */ jsx8(Box8, { marginTop: 1, children: /* @__PURE__ */ jsxs8(Text8, { children: [
|
|
9656
9655
|
"press ",
|
|
9657
|
-
/* @__PURE__ */
|
|
9656
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.accent, children: "enter" }),
|
|
9658
9657
|
" to go live"
|
|
9659
9658
|
] }) })
|
|
9660
9659
|
] });
|
|
@@ -9662,22 +9661,22 @@ function LiveHint() {
|
|
|
9662
9661
|
function Banner({ cols }) {
|
|
9663
9662
|
const wide = cols >= 82;
|
|
9664
9663
|
if (!wide) {
|
|
9665
|
-
return /* @__PURE__ */
|
|
9666
|
-
/* @__PURE__ */
|
|
9667
|
-
/* @__PURE__ */
|
|
9664
|
+
return /* @__PURE__ */ jsxs8(Box8, { children: [
|
|
9665
|
+
/* @__PURE__ */ jsx8(Text8, { bold: true, color: theme.accentBright, children: "SolonGate" }),
|
|
9666
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: " \u2014 security control center" })
|
|
9668
9667
|
] });
|
|
9669
9668
|
}
|
|
9670
|
-
return /* @__PURE__ */
|
|
9671
|
-
BANNER_FULL.map((line, i) => /* @__PURE__ */
|
|
9672
|
-
/* @__PURE__ */
|
|
9669
|
+
return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
|
|
9670
|
+
BANNER_FULL.map((line, i) => /* @__PURE__ */ jsx8(Text8, { bold: true, color: BANNER_HEX[i], children: line }, i)),
|
|
9671
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: " security control center \xB7 manage policies, rate limits, DLP & more" })
|
|
9673
9672
|
] });
|
|
9674
9673
|
}
|
|
9675
9674
|
function App() {
|
|
9676
9675
|
const { exit } = useApp();
|
|
9677
|
-
const [section, setSection] =
|
|
9678
|
-
const [focus, setFocus] =
|
|
9679
|
-
const [help, setHelp] =
|
|
9680
|
-
|
|
9676
|
+
const [section, setSection] = useState8(0);
|
|
9677
|
+
const [focus, setFocus] = useState8("nav");
|
|
9678
|
+
const [help, setHelp] = useState8(false);
|
|
9679
|
+
useInput7((input, key) => {
|
|
9681
9680
|
if (help) {
|
|
9682
9681
|
setHelp(false);
|
|
9683
9682
|
return;
|
|
@@ -9698,31 +9697,31 @@ function App() {
|
|
|
9698
9697
|
});
|
|
9699
9698
|
const { cols, rows } = useTermSize();
|
|
9700
9699
|
const current = SECTIONS[section];
|
|
9701
|
-
if (help) return /* @__PURE__ */
|
|
9700
|
+
if (help) return /* @__PURE__ */ jsx8(HelpOverlay, { cols, rows });
|
|
9702
9701
|
if (current.label === "Live" && focus === "panel") {
|
|
9703
|
-
return /* @__PURE__ */
|
|
9702
|
+
return /* @__PURE__ */ jsx8(Box8, { flexDirection: "column", width: cols, height: rows, children: /* @__PURE__ */ jsx8(LivePanel, { active: true, focused: true }) });
|
|
9704
9703
|
}
|
|
9705
9704
|
const Panel = current.Panel;
|
|
9706
|
-
return /* @__PURE__ */
|
|
9707
|
-
/* @__PURE__ */
|
|
9708
|
-
/* @__PURE__ */
|
|
9709
|
-
/* @__PURE__ */
|
|
9710
|
-
/* @__PURE__ */
|
|
9705
|
+
return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", width: cols, height: rows, paddingX: 1, paddingTop: 1, children: [
|
|
9706
|
+
/* @__PURE__ */ jsx8(Banner, { cols }),
|
|
9707
|
+
/* @__PURE__ */ jsxs8(Box8, { marginTop: 1, flexGrow: 1, children: [
|
|
9708
|
+
/* @__PURE__ */ jsx8(Box8, { flexDirection: "column", width: 16, borderStyle: "round", borderColor: focus === "nav" ? theme.accent : "gray", paddingX: 1, children: SECTIONS.map((s, i) => /* @__PURE__ */ jsx8(Text8, { color: i === section ? theme.accentBright : void 0, bold: i === section, children: (i === section ? "\u25B8 " : " ") + s.label }, s.label)) }),
|
|
9709
|
+
/* @__PURE__ */ jsx8(Box8, { flexGrow: 1, borderStyle: "round", borderColor: focus === "panel" ? theme.accent : "gray", paddingX: 1, paddingY: 0, children: /* @__PURE__ */ jsx8(Panel, { active: focus === "panel" || current.label !== "Live", focused: focus === "panel" }) })
|
|
9711
9710
|
] }),
|
|
9712
|
-
/* @__PURE__ */
|
|
9711
|
+
/* @__PURE__ */ jsx8(Box8, { children: focus === "nav" ? /* @__PURE__ */ jsx8(KeyHints, { hints: [["\u2191\u2193", "section"], ["\u2192/enter", "open"], ["?", "help"], ["q", "quit"]] }) : /* @__PURE__ */ jsx8(KeyHints, { hints: [["\u2190/esc", "back"], ["\u2191\u2193", "in-panel"], ["space/s", "act"]] }) })
|
|
9713
9712
|
] });
|
|
9714
9713
|
}
|
|
9715
9714
|
function HelpOverlay({ cols, rows }) {
|
|
9716
|
-
return /* @__PURE__ */
|
|
9717
|
-
/* @__PURE__ */
|
|
9718
|
-
/* @__PURE__ */
|
|
9719
|
-
/* @__PURE__ */
|
|
9720
|
-
keys.map(([k, desc]) => /* @__PURE__ */
|
|
9721
|
-
/* @__PURE__ */
|
|
9722
|
-
/* @__PURE__ */
|
|
9715
|
+
return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", width: cols, height: rows, paddingX: 2, paddingTop: 1, children: [
|
|
9716
|
+
/* @__PURE__ */ jsx8(Text8, { bold: true, color: theme.accentBright, children: "SolonGate \u2014 keyboard shortcuts" }),
|
|
9717
|
+
/* @__PURE__ */ jsx8(Box8, { marginTop: 1, flexDirection: "column", children: HELP.map(([group, keys]) => /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", marginBottom: 1, children: [
|
|
9718
|
+
/* @__PURE__ */ jsx8(Text8, { bold: true, color: theme.accent, children: group }),
|
|
9719
|
+
keys.map(([k, desc]) => /* @__PURE__ */ jsxs8(Text8, { children: [
|
|
9720
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.accentBright, children: (" " + k).padEnd(16) }),
|
|
9721
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: desc })
|
|
9723
9722
|
] }, k))
|
|
9724
9723
|
] }, group)) }),
|
|
9725
|
-
/* @__PURE__ */
|
|
9724
|
+
/* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: "press any key to close" })
|
|
9726
9725
|
] });
|
|
9727
9726
|
}
|
|
9728
9727
|
var SECTIONS, BANNER_HEX, HELP;
|
|
@@ -9737,12 +9736,10 @@ var init_App = __esm({
|
|
|
9737
9736
|
init_RateLimit();
|
|
9738
9737
|
init_Dlp();
|
|
9739
9738
|
init_Audit();
|
|
9740
|
-
init_Agents();
|
|
9741
9739
|
init_Settings();
|
|
9742
9740
|
init_hooks();
|
|
9743
9741
|
SECTIONS = [
|
|
9744
9742
|
{ label: "Live", Panel: LiveHint },
|
|
9745
|
-
{ label: "Agents", Panel: AgentsPanel },
|
|
9746
9743
|
{ label: "Policies", Panel: PoliciesPanel },
|
|
9747
9744
|
{ label: "Rate Limit", Panel: RateLimitPanel },
|
|
9748
9745
|
{ label: "DLP", Panel: DlpPanel },
|
|
@@ -9755,7 +9752,7 @@ var init_App = __esm({
|
|
|
9755
9752
|
["Live", [["\u2191\u2193", "select a stream row"], ["enter", "full entry content"], ["w", "whitelist the selected DENY"], ["b", "block the selected ALLOW"], ["d / x / r", "filter denies / dlp / rate-limit"], ["f", "local / cloud filter"], ["/", "search"], ["s", "sessions (\u2191\u2193 pick, enter open)"], ["space", "copy mode (freeze)"]]],
|
|
9756
9753
|
["Policies", [["\u2191\u2193", "browse / select"], ["a", "activate (pin) selected policy"], ["x", "deactivate \u2014 no active policy"], ["enter", "open rules \u2192 open a rule"], ["space", "toggle a rule on/off"], ["e", "flip effect"], ["n", "new rule"], ["d", "delete rule"], ["m", "flip mode"], ["D", "dry-run the draft"], ["s", "save"], ["x", "discard"]]],
|
|
9757
9754
|
["Rate limit / DLP", [["\u2191\u2193", "field / pattern"], ["\u2190\u2192", "adjust (shift = \xB110)"], ["space", "toggle pattern"], ["m", "mode"], ["a / d", "add / remove custom"], ["g", "ghost mode"], ["P", "self-protection"], ["s", "save"]]],
|
|
9758
|
-
["Audit", [["v", "logs \u2194 sessions"], ["s", "source: cloud \u2194 local"], ["
|
|
9755
|
+
["Audit", [["v", "logs \u2194 sessions"], ["s", "source: cloud \u2194 local"], ["\u2190 \u2192", "prev / next page (500 each)"], ["\u2191\u2193", "select (list scrolls)"], ["enter", "full entry / session logs"], ["f / g", "decision / signal filter"], ["t / n / /", "tool / agent / search"], ["x / X", "delete entry / ALL (press twice)"], ["c", "clear filters"]]],
|
|
9759
9756
|
["Settings", [["\u2191\u2193", "move"], ["enter / space", "toggle \xB7 edit \xB7 add"], ["e", "webhook events"], ["d d", "delete"], ["r", "refresh"]]]
|
|
9760
9757
|
];
|
|
9761
9758
|
}
|
|
@@ -9767,7 +9764,7 @@ __export(tui_exports, {
|
|
|
9767
9764
|
launchTui: () => launchTui
|
|
9768
9765
|
});
|
|
9769
9766
|
import { render } from "ink";
|
|
9770
|
-
import { jsx as
|
|
9767
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
9771
9768
|
async function launchTui() {
|
|
9772
9769
|
if (!process.stdout.isTTY || !process.stdin.isTTY) {
|
|
9773
9770
|
process.stderr.write(
|
|
@@ -9781,7 +9778,7 @@ async function launchTui() {
|
|
|
9781
9778
|
}
|
|
9782
9779
|
process.stdout.write("\x1B[?1049h\x1B[H");
|
|
9783
9780
|
try {
|
|
9784
|
-
const { waitUntilExit } = render(/* @__PURE__ */
|
|
9781
|
+
const { waitUntilExit } = render(/* @__PURE__ */ jsx9(App, {}));
|
|
9785
9782
|
await waitUntilExit();
|
|
9786
9783
|
} finally {
|
|
9787
9784
|
process.stdout.write("\x1B[?1049l");
|
|
@@ -9893,7 +9890,7 @@ var init_args = __esm({
|
|
|
9893
9890
|
});
|
|
9894
9891
|
|
|
9895
9892
|
// src/commands/policy.ts
|
|
9896
|
-
import { readFileSync as
|
|
9893
|
+
import { readFileSync as readFileSync7 } from "fs";
|
|
9897
9894
|
async function run(argv) {
|
|
9898
9895
|
const { positionals, flags } = parse(argv);
|
|
9899
9896
|
const sub = positionals[0];
|
|
@@ -10068,7 +10065,7 @@ function printRules(rules) {
|
|
|
10068
10065
|
}
|
|
10069
10066
|
async function resolveRules(target) {
|
|
10070
10067
|
if (target.endsWith(".json")) {
|
|
10071
|
-
const parsed = JSON.parse(
|
|
10068
|
+
const parsed = JSON.parse(readFileSync7(target, "utf-8"));
|
|
10072
10069
|
return parsed.rules ?? [];
|
|
10073
10070
|
}
|
|
10074
10071
|
const p = await api.policies.get(target);
|
|
@@ -10432,7 +10429,7 @@ async function runAgents(argv) {
|
|
|
10432
10429
|
table(
|
|
10433
10430
|
["STATUS", "AGENT", "CALLS", "DENY", "DLP", "TRUST", "CHARACTER"],
|
|
10434
10431
|
res.agents.map((a) => [
|
|
10435
|
-
|
|
10432
|
+
statusColor(a.status),
|
|
10436
10433
|
cyan(truncate3(a.agent_name ?? a.agent_id ?? a.session_id, 20)),
|
|
10437
10434
|
String(a.total_calls),
|
|
10438
10435
|
a.denied_calls ? red(String(a.denied_calls)) : dim("0"),
|
|
@@ -10451,7 +10448,7 @@ async function runAgent(argv) {
|
|
|
10451
10448
|
const a = await api.agents.get(id);
|
|
10452
10449
|
if (json) return printJson(a), 0;
|
|
10453
10450
|
err("");
|
|
10454
|
-
err(` ${bold(a.agent_id)} status: ${
|
|
10451
|
+
err(` ${bold(a.agent_id)} status: ${statusColor(String(a.status))}`);
|
|
10455
10452
|
const base = a.baseline;
|
|
10456
10453
|
if (base) {
|
|
10457
10454
|
err(` ${dim(base.character ?? "")} trust ${bold(String(base.trustScore ?? "\u2014"))}/100 deny-rate ${(Number(base.denyRate ?? 0) * 100).toFixed(0)}%`);
|
|
@@ -10471,14 +10468,14 @@ async function runAgent(argv) {
|
|
|
10471
10468
|
}
|
|
10472
10469
|
return 0;
|
|
10473
10470
|
}
|
|
10474
|
-
var
|
|
10471
|
+
var statusColor;
|
|
10475
10472
|
var init_agents2 = __esm({
|
|
10476
10473
|
"src/commands/agents.ts"() {
|
|
10477
10474
|
"use strict";
|
|
10478
10475
|
init_api_client();
|
|
10479
10476
|
init_args();
|
|
10480
10477
|
init_format();
|
|
10481
|
-
|
|
10478
|
+
statusColor = (s) => s === "active" ? green(s) : s === "idle" ? yellow(s) : dim(s);
|
|
10482
10479
|
}
|
|
10483
10480
|
});
|
|
10484
10481
|
|
|
@@ -10961,7 +10958,7 @@ __export(global_install_exports, {
|
|
|
10961
10958
|
runGlobalRestore: () => runGlobalRestore,
|
|
10962
10959
|
unlockProtected: () => unlockProtected
|
|
10963
10960
|
});
|
|
10964
|
-
import { readFileSync as
|
|
10961
|
+
import { readFileSync as readFileSync8, writeFileSync as writeFileSync5, existsSync as existsSync6, mkdirSync as mkdirSync4 } from "fs";
|
|
10965
10962
|
import { resolve as resolve4, join as join10, dirname } from "path";
|
|
10966
10963
|
import { homedir as homedir8 } from "os";
|
|
10967
10964
|
import { fileURLToPath } from "url";
|
|
@@ -11056,11 +11053,11 @@ function globalPaths() {
|
|
|
11056
11053
|
};
|
|
11057
11054
|
}
|
|
11058
11055
|
function readHook(filename) {
|
|
11059
|
-
return
|
|
11056
|
+
return readFileSync8(join10(HOOKS_DIR, filename), "utf-8");
|
|
11060
11057
|
}
|
|
11061
11058
|
function readGuard() {
|
|
11062
11059
|
const bundled = join10(HOOKS_DIR, "guard.bundled.mjs");
|
|
11063
|
-
return existsSync6(bundled) ?
|
|
11060
|
+
return existsSync6(bundled) ? readFileSync8(bundled, "utf-8") : readHook("guard.mjs");
|
|
11064
11061
|
}
|
|
11065
11062
|
function ask(question) {
|
|
11066
11063
|
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
@@ -11074,13 +11071,13 @@ function runGlobalRestore() {
|
|
|
11074
11071
|
unlockProtected();
|
|
11075
11072
|
removeClaudeShim();
|
|
11076
11073
|
if (existsSync6(p.backupPath)) {
|
|
11077
|
-
|
|
11074
|
+
writeFileSync5(p.settingsPath, readFileSync8(p.backupPath, "utf-8"));
|
|
11078
11075
|
console.log(` Restored ${p.settingsPath} from backup.`);
|
|
11079
11076
|
} else if (existsSync6(p.settingsPath)) {
|
|
11080
11077
|
try {
|
|
11081
|
-
const s = JSON.parse(
|
|
11078
|
+
const s = JSON.parse(readFileSync8(p.settingsPath, "utf-8"));
|
|
11082
11079
|
delete s.hooks;
|
|
11083
|
-
|
|
11080
|
+
writeFileSync5(p.settingsPath, JSON.stringify(s, null, 2) + "\n");
|
|
11084
11081
|
console.log(` Removed SolonGate hooks from ${p.settingsPath}.`);
|
|
11085
11082
|
} catch {
|
|
11086
11083
|
}
|
|
@@ -11118,14 +11115,14 @@ function shimTargets() {
|
|
|
11118
11115
|
}
|
|
11119
11116
|
function writeShimBlock(file, block2) {
|
|
11120
11117
|
const re = new RegExp(escapeRe(SHIM_BEGIN) + "[\\s\\S]*?" + escapeRe(SHIM_END) + "\\r?\\n?", "g");
|
|
11121
|
-
let content = existsSync6(file) ?
|
|
11118
|
+
let content = existsSync6(file) ? readFileSync8(file, "utf-8") : "";
|
|
11122
11119
|
content = content.replace(re, "");
|
|
11123
11120
|
if (block2) {
|
|
11124
11121
|
if (content.length && !content.endsWith("\n")) content += "\n";
|
|
11125
11122
|
content += block2 + "\n";
|
|
11126
11123
|
}
|
|
11127
11124
|
mkdirSync4(dirname(file), { recursive: true });
|
|
11128
|
-
|
|
11125
|
+
writeFileSync5(file, content);
|
|
11129
11126
|
}
|
|
11130
11127
|
function installClaudeShim(shieldPath) {
|
|
11131
11128
|
const real = resolveRealClaude();
|
|
@@ -11163,7 +11160,7 @@ async function runGlobalInstall(opts = {}) {
|
|
|
11163
11160
|
let apiKey = opts.apiKey || process.env["SOLONGATE_API_KEY"] || "";
|
|
11164
11161
|
if (!apiKey || apiKey === "sg_live_your_key_here") {
|
|
11165
11162
|
try {
|
|
11166
|
-
const cfg = JSON.parse(
|
|
11163
|
+
const cfg = JSON.parse(readFileSync8(p.configPath, "utf-8"));
|
|
11167
11164
|
if (cfg && typeof cfg.apiKey === "string") apiKey = cfg.apiKey;
|
|
11168
11165
|
} catch {
|
|
11169
11166
|
}
|
|
@@ -11179,19 +11176,19 @@ async function runGlobalInstall(opts = {}) {
|
|
|
11179
11176
|
mkdirSync4(p.hooksDir, { recursive: true });
|
|
11180
11177
|
mkdirSync4(p.claudeDir, { recursive: true });
|
|
11181
11178
|
unlockProtected();
|
|
11182
|
-
|
|
11183
|
-
|
|
11184
|
-
|
|
11185
|
-
|
|
11179
|
+
writeFileSync5(join10(p.hooksDir, "guard.mjs"), readGuard());
|
|
11180
|
+
writeFileSync5(join10(p.hooksDir, "audit.mjs"), readHook("audit.mjs"));
|
|
11181
|
+
writeFileSync5(join10(p.hooksDir, "stop.mjs"), readHook("stop.mjs"));
|
|
11182
|
+
writeFileSync5(join10(p.hooksDir, "shield.mjs"), readHook("shield.mjs"));
|
|
11186
11183
|
console.log(` Installed hooks \u2192 ${p.hooksDir}`);
|
|
11187
11184
|
installClaudeShim(join10(p.hooksDir, "shield.mjs"));
|
|
11188
|
-
|
|
11185
|
+
writeFileSync5(p.configPath, JSON.stringify({ apiKey, apiUrl }, null, 2) + "\n");
|
|
11189
11186
|
console.log(` Wrote ${p.configPath}`);
|
|
11190
11187
|
let existing = {};
|
|
11191
11188
|
if (existsSync6(p.settingsPath)) {
|
|
11192
|
-
const raw =
|
|
11189
|
+
const raw = readFileSync8(p.settingsPath, "utf-8");
|
|
11193
11190
|
if (!existsSync6(p.backupPath)) {
|
|
11194
|
-
|
|
11191
|
+
writeFileSync5(p.backupPath, raw);
|
|
11195
11192
|
console.log(` Backed up existing settings \u2192 ${p.backupPath}`);
|
|
11196
11193
|
}
|
|
11197
11194
|
try {
|
|
@@ -11214,7 +11211,7 @@ async function runGlobalInstall(opts = {}) {
|
|
|
11214
11211
|
Stop: [{ matcher: "", hooks: [{ type: "command", command: hookCmd(stopAbs) }] }]
|
|
11215
11212
|
}
|
|
11216
11213
|
};
|
|
11217
|
-
|
|
11214
|
+
writeFileSync5(p.settingsPath, JSON.stringify(merged, null, 2) + "\n");
|
|
11218
11215
|
console.log(` Registered global hooks \u2192 ${p.settingsPath}`);
|
|
11219
11216
|
if (process.env["SOLONGATE_OS_LOCK"] === "1") {
|
|
11220
11217
|
lockProtected();
|
|
@@ -11394,7 +11391,7 @@ import { createServer, request as httpRequest } from "http";
|
|
|
11394
11391
|
import { request as httpsRequest } from "https";
|
|
11395
11392
|
import { spawn as spawn3 } from "child_process";
|
|
11396
11393
|
import { URL as URL2 } from "url";
|
|
11397
|
-
import { readFileSync as
|
|
11394
|
+
import { readFileSync as readFileSync9, existsSync as existsSync7, readdirSync, statSync as statSync4 } from "fs";
|
|
11398
11395
|
import { resolve as resolve5 } from "path";
|
|
11399
11396
|
import { homedir as homedir9 } from "os";
|
|
11400
11397
|
function findCacheFile() {
|
|
@@ -11424,7 +11421,7 @@ function loadCfg() {
|
|
|
11424
11421
|
try {
|
|
11425
11422
|
const f = findCacheFile();
|
|
11426
11423
|
if (f && existsSync7(f)) {
|
|
11427
|
-
const c2 = JSON.parse(
|
|
11424
|
+
const c2 = JSON.parse(readFileSync9(f, "utf-8"));
|
|
11428
11425
|
const d = c2?.security?.dlpRedact;
|
|
11429
11426
|
const g = c2?.security?.ghost;
|
|
11430
11427
|
const ghost = g && Array.isArray(g.patterns) ? g.patterns : [];
|
|
@@ -11712,7 +11709,7 @@ __export(logs_server_exports, {
|
|
|
11712
11709
|
runLogsServer: () => runLogsServer
|
|
11713
11710
|
});
|
|
11714
11711
|
import { createServer as createServer2 } from "http";
|
|
11715
|
-
import { readFileSync as
|
|
11712
|
+
import { readFileSync as readFileSync10, statSync as statSync5 } from "fs";
|
|
11716
11713
|
import { resolve as resolve6, join as join11, isAbsolute } from "path";
|
|
11717
11714
|
import { homedir as homedir10 } from "os";
|
|
11718
11715
|
import { readdirSync as readdirSync2 } from "fs";
|
|
@@ -11739,7 +11736,7 @@ async function findLogDir() {
|
|
|
11739
11736
|
const files = readdirSync2(base).filter((f) => f.startsWith(".policy-cache-") && f.endsWith(".json"));
|
|
11740
11737
|
for (const f of files) {
|
|
11741
11738
|
try {
|
|
11742
|
-
const c2 = JSON.parse(
|
|
11739
|
+
const c2 = JSON.parse(readFileSync10(join11(base, f), "utf-8"));
|
|
11743
11740
|
const p = c2?.security?.localLogs?.path;
|
|
11744
11741
|
if (typeof p === "string" && p.trim()) return { dir: resolveLocalLogDir(p), configured: p };
|
|
11745
11742
|
} catch {
|
|
@@ -11748,7 +11745,7 @@ async function findLogDir() {
|
|
|
11748
11745
|
} catch {
|
|
11749
11746
|
}
|
|
11750
11747
|
try {
|
|
11751
|
-
const cfgRaw =
|
|
11748
|
+
const cfgRaw = readFileSync10(join11(base, "cloud-guard.json"), "utf-8");
|
|
11752
11749
|
const { apiKey, apiUrl } = JSON.parse(cfgRaw);
|
|
11753
11750
|
if (apiKey) {
|
|
11754
11751
|
const url = `${apiUrl || "https://api.solongate.com"}/api/v1/policies/active`;
|
|
@@ -11838,7 +11835,7 @@ async function runLogsServer() {
|
|
|
11838
11835
|
return;
|
|
11839
11836
|
}
|
|
11840
11837
|
try {
|
|
11841
|
-
const text =
|
|
11838
|
+
const text = readFileSync10(info.file, "utf-8");
|
|
11842
11839
|
res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8", "Last-Modified": lastMod, "X-Solongate-Exists": "1" });
|
|
11843
11840
|
res.end(text);
|
|
11844
11841
|
} catch {
|
|
@@ -11890,7 +11887,7 @@ var init_logs_server = __esm({
|
|
|
11890
11887
|
|
|
11891
11888
|
// src/inject.ts
|
|
11892
11889
|
var inject_exports = {};
|
|
11893
|
-
import { readFileSync as
|
|
11890
|
+
import { readFileSync as readFileSync11, writeFileSync as writeFileSync6, existsSync as existsSync8, copyFileSync } from "fs";
|
|
11894
11891
|
import { resolve as resolve7 } from "path";
|
|
11895
11892
|
import { execSync } from "child_process";
|
|
11896
11893
|
function parseInjectArgs(argv) {
|
|
@@ -11950,7 +11947,7 @@ WHAT IT DOES
|
|
|
11950
11947
|
function detectProject() {
|
|
11951
11948
|
if (!existsSync8(resolve7("package.json"))) return false;
|
|
11952
11949
|
try {
|
|
11953
|
-
const pkg = JSON.parse(
|
|
11950
|
+
const pkg = JSON.parse(readFileSync11(resolve7("package.json"), "utf-8"));
|
|
11954
11951
|
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
11955
11952
|
return !!(allDeps["@modelcontextprotocol/sdk"] || allDeps["@modelcontextprotocol/server"]);
|
|
11956
11953
|
} catch {
|
|
@@ -11959,7 +11956,7 @@ function detectProject() {
|
|
|
11959
11956
|
}
|
|
11960
11957
|
function findTsEntryFile() {
|
|
11961
11958
|
try {
|
|
11962
|
-
const pkg = JSON.parse(
|
|
11959
|
+
const pkg = JSON.parse(readFileSync11(resolve7("package.json"), "utf-8"));
|
|
11963
11960
|
if (pkg.bin) {
|
|
11964
11961
|
const binPath = typeof pkg.bin === "string" ? pkg.bin : Object.values(pkg.bin)[0];
|
|
11965
11962
|
if (typeof binPath === "string") {
|
|
@@ -11986,7 +11983,7 @@ function findTsEntryFile() {
|
|
|
11986
11983
|
const full = resolve7(c2);
|
|
11987
11984
|
if (existsSync8(full)) {
|
|
11988
11985
|
try {
|
|
11989
|
-
const content =
|
|
11986
|
+
const content = readFileSync11(full, "utf-8");
|
|
11990
11987
|
if (content.includes("McpServer") || content.includes("McpServer")) {
|
|
11991
11988
|
return full;
|
|
11992
11989
|
}
|
|
@@ -12006,7 +12003,7 @@ function detectPackageManager() {
|
|
|
12006
12003
|
}
|
|
12007
12004
|
function installSdk() {
|
|
12008
12005
|
try {
|
|
12009
|
-
const pkg = JSON.parse(
|
|
12006
|
+
const pkg = JSON.parse(readFileSync11(resolve7("package.json"), "utf-8"));
|
|
12010
12007
|
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
12011
12008
|
if (allDeps["@solongate/proxy"]) {
|
|
12012
12009
|
log3(" @solongate/proxy already installed");
|
|
@@ -12027,7 +12024,7 @@ function installSdk() {
|
|
|
12027
12024
|
}
|
|
12028
12025
|
}
|
|
12029
12026
|
function injectTypeScript(filePath) {
|
|
12030
|
-
const original =
|
|
12027
|
+
const original = readFileSync11(filePath, "utf-8");
|
|
12031
12028
|
const changes = [];
|
|
12032
12029
|
let modified = original;
|
|
12033
12030
|
if (modified.includes("SecureMcpServer")) {
|
|
@@ -12198,7 +12195,7 @@ async function main2() {
|
|
|
12198
12195
|
log3("");
|
|
12199
12196
|
log3(` Backup: ${backupPath}`);
|
|
12200
12197
|
}
|
|
12201
|
-
|
|
12198
|
+
writeFileSync6(entryFile, result.modified);
|
|
12202
12199
|
log3("");
|
|
12203
12200
|
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");
|
|
12204
12201
|
log3(" \u2502 SolonGate SDK injected successfully! \u2502");
|
|
@@ -12227,7 +12224,7 @@ var init_inject = __esm({
|
|
|
12227
12224
|
|
|
12228
12225
|
// src/create.ts
|
|
12229
12226
|
var create_exports = {};
|
|
12230
|
-
import { mkdirSync as mkdirSync5, writeFileSync as
|
|
12227
|
+
import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync7, existsSync as existsSync9 } from "fs";
|
|
12231
12228
|
import { resolve as resolve8, join as join12 } from "path";
|
|
12232
12229
|
import { execSync as execSync2 } from "child_process";
|
|
12233
12230
|
function withSpinner(message, fn) {
|
|
@@ -12307,7 +12304,7 @@ EXAMPLES
|
|
|
12307
12304
|
`);
|
|
12308
12305
|
}
|
|
12309
12306
|
function createProject(dir, name, _policy) {
|
|
12310
|
-
|
|
12307
|
+
writeFileSync7(
|
|
12311
12308
|
join12(dir, "package.json"),
|
|
12312
12309
|
JSON.stringify(
|
|
12313
12310
|
{
|
|
@@ -12337,7 +12334,7 @@ function createProject(dir, name, _policy) {
|
|
|
12337
12334
|
2
|
|
12338
12335
|
) + "\n"
|
|
12339
12336
|
);
|
|
12340
|
-
|
|
12337
|
+
writeFileSync7(
|
|
12341
12338
|
join12(dir, "tsconfig.json"),
|
|
12342
12339
|
JSON.stringify(
|
|
12343
12340
|
{
|
|
@@ -12359,7 +12356,7 @@ function createProject(dir, name, _policy) {
|
|
|
12359
12356
|
) + "\n"
|
|
12360
12357
|
);
|
|
12361
12358
|
mkdirSync5(join12(dir, "src"), { recursive: true });
|
|
12362
|
-
|
|
12359
|
+
writeFileSync7(
|
|
12363
12360
|
join12(dir, "src", "index.ts"),
|
|
12364
12361
|
`#!/usr/bin/env node
|
|
12365
12362
|
|
|
@@ -12401,7 +12398,7 @@ console.log('');
|
|
|
12401
12398
|
console.log('Press Ctrl+C to stop.');
|
|
12402
12399
|
`
|
|
12403
12400
|
);
|
|
12404
|
-
|
|
12401
|
+
writeFileSync7(
|
|
12405
12402
|
join12(dir, ".mcp.json"),
|
|
12406
12403
|
JSON.stringify(
|
|
12407
12404
|
{
|
|
@@ -12419,12 +12416,12 @@ console.log('Press Ctrl+C to stop.');
|
|
|
12419
12416
|
2
|
|
12420
12417
|
) + "\n"
|
|
12421
12418
|
);
|
|
12422
|
-
|
|
12419
|
+
writeFileSync7(
|
|
12423
12420
|
join12(dir, ".env"),
|
|
12424
12421
|
`SOLONGATE_API_KEY=sg_live_YOUR_KEY_HERE
|
|
12425
12422
|
`
|
|
12426
12423
|
);
|
|
12427
|
-
|
|
12424
|
+
writeFileSync7(
|
|
12428
12425
|
join12(dir, ".gitignore"),
|
|
12429
12426
|
`node_modules/
|
|
12430
12427
|
dist/
|
|
@@ -12518,14 +12515,14 @@ var init_create = __esm({
|
|
|
12518
12515
|
|
|
12519
12516
|
// src/pull-push.ts
|
|
12520
12517
|
var pull_push_exports = {};
|
|
12521
|
-
import { readFileSync as
|
|
12518
|
+
import { readFileSync as readFileSync12, writeFileSync as writeFileSync8, existsSync as existsSync10 } from "fs";
|
|
12522
12519
|
import { resolve as resolve9 } from "path";
|
|
12523
12520
|
function loadEnv() {
|
|
12524
12521
|
if (process.env.SOLONGATE_API_KEY) return;
|
|
12525
12522
|
const envPath = resolve9(".env");
|
|
12526
12523
|
if (!existsSync10(envPath)) return;
|
|
12527
12524
|
try {
|
|
12528
|
-
const content =
|
|
12525
|
+
const content = readFileSync12(envPath, "utf-8");
|
|
12529
12526
|
for (const line of content.split("\n")) {
|
|
12530
12527
|
const trimmed = line.trim();
|
|
12531
12528
|
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
@@ -12713,7 +12710,7 @@ async function pull(apiKey, file, policyId) {
|
|
|
12713
12710
|
const policy = await fetchCloudPolicy(apiKey, API_URL, policyId);
|
|
12714
12711
|
const { id: _id, ...policyWithoutId } = policy;
|
|
12715
12712
|
const json = JSON.stringify(policyWithoutId, null, 2) + "\n";
|
|
12716
|
-
|
|
12713
|
+
writeFileSync8(file, json, "utf-8");
|
|
12717
12714
|
log5("");
|
|
12718
12715
|
log5(green2(" Saved to: ") + file);
|
|
12719
12716
|
log5(` ${dim2("Name:")} ${policy.name}`);
|
|
@@ -12742,7 +12739,7 @@ async function push(apiKey, file, policyId) {
|
|
|
12742
12739
|
log5(" solongate-proxy list");
|
|
12743
12740
|
process.exit(1);
|
|
12744
12741
|
}
|
|
12745
|
-
const content =
|
|
12742
|
+
const content = readFileSync12(file, "utf-8");
|
|
12746
12743
|
let policy;
|
|
12747
12744
|
try {
|
|
12748
12745
|
policy = JSON.parse(content);
|