@solongate/proxy 0.81.42 → 0.81.44
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 +111 -66
- package/dist/tui/index.js +58 -13
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7537,6 +7537,7 @@ function LivePanel({ active: active2 }) {
|
|
|
7537
7537
|
const inspectFromRef = useRef2("stream");
|
|
7538
7538
|
const seenRef = useRef2(/* @__PURE__ */ new Set());
|
|
7539
7539
|
const lastLocalTs = useRef2(0);
|
|
7540
|
+
const localSeq = useRef2(0);
|
|
7540
7541
|
const pausedUntil = useRef2(0);
|
|
7541
7542
|
const sessRef = useRef2([]);
|
|
7542
7543
|
const mergedRef = useRef2([]);
|
|
@@ -7582,7 +7583,7 @@ function LivePanel({ active: active2 }) {
|
|
|
7582
7583
|
const at = Date.parse(j.ts ?? "");
|
|
7583
7584
|
if (!Number.isFinite(at) || at <= lastLocalTs.current) continue;
|
|
7584
7585
|
fresh.push({
|
|
7585
|
-
id: "l:" + at + ":" + (j.tool ?? "")
|
|
7586
|
+
id: "l:" + at + ":" + (j.tool ?? "") + ":" + localSeq.current++,
|
|
7586
7587
|
at,
|
|
7587
7588
|
tool: j.tool ?? "?",
|
|
7588
7589
|
decision: j.decision ?? "ALLOW",
|
|
@@ -7705,20 +7706,45 @@ function LivePanel({ active: active2 }) {
|
|
|
7705
7706
|
}, [active2, frozen]);
|
|
7706
7707
|
const startRef = useRef2(Date.now());
|
|
7707
7708
|
const lastNotifyAt = useRef2(0);
|
|
7709
|
+
const toastQueue = useRef2(/* @__PURE__ */ new Map());
|
|
7710
|
+
const toastTimer = useRef2(null);
|
|
7711
|
+
const TOAST_RANK = { "DLP hit": 0, "Call denied": 1, "Rate-limit burst": 2 };
|
|
7712
|
+
const flushToasts = useCallback2(function flush() {
|
|
7713
|
+
toastTimer.current = null;
|
|
7714
|
+
const q2 = toastQueue.current;
|
|
7715
|
+
if (!q2.size) return;
|
|
7716
|
+
const wait = 3e3 - (Date.now() - lastNotifyAt.current);
|
|
7717
|
+
if (wait > 0) {
|
|
7718
|
+
toastTimer.current = setTimeout(flush, wait);
|
|
7719
|
+
return;
|
|
7720
|
+
}
|
|
7721
|
+
lastNotifyAt.current = Date.now();
|
|
7722
|
+
const items = [...q2.entries()].sort((a, b) => (TOAST_RANK[a[0]] ?? 9) - (TOAST_RANK[b[0]] ?? 9));
|
|
7723
|
+
q2.clear();
|
|
7724
|
+
try {
|
|
7725
|
+
process.stdout.write("\x07");
|
|
7726
|
+
} catch {
|
|
7727
|
+
}
|
|
7728
|
+
const total = items.reduce((n, [, v]) => n + v.count, 0);
|
|
7729
|
+
if (items.length === 1 && total === 1) desktopNotify(items[0][0], items[0][1].msg);
|
|
7730
|
+
else desktopNotify("Security alerts", items.map(([t, v]) => `${v.count}\xD7 ${t}`).join(" \xB7 "));
|
|
7731
|
+
}, []);
|
|
7732
|
+
useEffect2(
|
|
7733
|
+
() => () => {
|
|
7734
|
+
if (toastTimer.current) clearTimeout(toastTimer.current);
|
|
7735
|
+
},
|
|
7736
|
+
[]
|
|
7737
|
+
);
|
|
7708
7738
|
const fireAlert = useCallback2(
|
|
7709
|
-
(id, title, msg, level = "warn") => {
|
|
7739
|
+
(id, title, msg, level = "warn", desktop = true) => {
|
|
7710
7740
|
pushLog(`${level === "bad" ? "\u26D4" : "\u23F8"} ${msg}`, level);
|
|
7711
7741
|
setAlerts((a) => [...a.filter((x) => x.id !== id), { id, msg, level, until: Date.now() + 15e3 }].slice(-4));
|
|
7712
|
-
if (!CONFIG.notifications) return;
|
|
7713
|
-
|
|
7714
|
-
|
|
7715
|
-
|
|
7716
|
-
process.stdout.write("\x07");
|
|
7717
|
-
} catch {
|
|
7718
|
-
}
|
|
7719
|
-
desktopNotify(title, msg);
|
|
7742
|
+
if (!desktop || !CONFIG.notifications) return;
|
|
7743
|
+
const cur = toastQueue.current.get(title);
|
|
7744
|
+
toastQueue.current.set(title, { count: (cur?.count ?? 0) + 1, msg: cur?.msg ?? msg });
|
|
7745
|
+
if (!toastTimer.current) toastTimer.current = setTimeout(flushToasts, 400);
|
|
7720
7746
|
},
|
|
7721
|
-
[pushLog]
|
|
7747
|
+
[pushLog, flushToasts]
|
|
7722
7748
|
);
|
|
7723
7749
|
useEffect2(() => {
|
|
7724
7750
|
if (!active2) return;
|
|
@@ -7726,7 +7752,7 @@ function LivePanel({ active: active2 }) {
|
|
|
7726
7752
|
const prev = prevStatus.current.get(r.id);
|
|
7727
7753
|
if (prev && prev === "active" && r.status === "idle") {
|
|
7728
7754
|
const name = r.isMe ? `${r.agent} (this machine)` : r.agent;
|
|
7729
|
-
fireAlert("idle:" + r.id, "Agent idle", `${name} went IDLE, no tool call for 60s`, "warn");
|
|
7755
|
+
fireAlert("idle:" + r.id, "Agent idle", `${name} went IDLE, no tool call for 60s`, "warn", false);
|
|
7730
7756
|
}
|
|
7731
7757
|
prevStatus.current.set(r.id, r.status);
|
|
7732
7758
|
}
|
|
@@ -10150,6 +10176,9 @@ var tui_exports = {};
|
|
|
10150
10176
|
__export(tui_exports, {
|
|
10151
10177
|
launchTui: () => launchTui
|
|
10152
10178
|
});
|
|
10179
|
+
import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync6 } from "fs";
|
|
10180
|
+
import { homedir as homedir7 } from "os";
|
|
10181
|
+
import { join as join9 } from "path";
|
|
10153
10182
|
import { render } from "ink";
|
|
10154
10183
|
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
10155
10184
|
async function launchTui() {
|
|
@@ -10160,10 +10189,26 @@ async function launchTui() {
|
|
|
10160
10189
|
return;
|
|
10161
10190
|
}
|
|
10162
10191
|
process.stdout.write("\x1B[?1049h\x1B[H");
|
|
10192
|
+
const debugLog = join9(homedir7(), ".solongate", "dataroom-debug.log");
|
|
10193
|
+
const saved = { log: console.log, warn: console.warn, error: console.error, info: console.info, debug: console.debug };
|
|
10194
|
+
const toFile = (level) => (...args) => {
|
|
10195
|
+
try {
|
|
10196
|
+
mkdirSync6(join9(homedir7(), ".solongate"), { recursive: true });
|
|
10197
|
+
appendFileSync2(debugLog, `${(/* @__PURE__ */ new Date()).toISOString()} [${level}] ${args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ")}
|
|
10198
|
+
`);
|
|
10199
|
+
} catch {
|
|
10200
|
+
}
|
|
10201
|
+
};
|
|
10202
|
+
console.log = toFile("log");
|
|
10203
|
+
console.warn = toFile("warn");
|
|
10204
|
+
console.error = toFile("error");
|
|
10205
|
+
console.info = toFile("info");
|
|
10206
|
+
console.debug = toFile("debug");
|
|
10163
10207
|
try {
|
|
10164
|
-
const { waitUntilExit } = render(/* @__PURE__ */ jsx10(App, {}));
|
|
10208
|
+
const { waitUntilExit } = render(/* @__PURE__ */ jsx10(App, {}), { patchConsole: false });
|
|
10165
10209
|
await waitUntilExit();
|
|
10166
10210
|
} finally {
|
|
10211
|
+
Object.assign(console, saved);
|
|
10167
10212
|
process.stdout.write("\x1B[?1049l");
|
|
10168
10213
|
}
|
|
10169
10214
|
}
|
|
@@ -10863,8 +10908,8 @@ var init_agents2 = __esm({
|
|
|
10863
10908
|
|
|
10864
10909
|
// src/commands/doctor.ts
|
|
10865
10910
|
import { existsSync as existsSync4, statSync as statSync2 } from "fs";
|
|
10866
|
-
import { homedir as
|
|
10867
|
-
import { join as
|
|
10911
|
+
import { homedir as homedir8 } from "os";
|
|
10912
|
+
import { join as join10 } from "path";
|
|
10868
10913
|
async function run6(argv) {
|
|
10869
10914
|
const { flags } = parse(argv);
|
|
10870
10915
|
const json = flagBool(flags, "json");
|
|
@@ -10924,14 +10969,14 @@ var init_doctor = __esm({
|
|
|
10924
10969
|
init_api_client();
|
|
10925
10970
|
init_format();
|
|
10926
10971
|
init_args();
|
|
10927
|
-
LOCAL_LOG2 =
|
|
10972
|
+
LOCAL_LOG2 = join10(homedir8(), ".solongate", "local-logs", "solongate-audit.jsonl");
|
|
10928
10973
|
}
|
|
10929
10974
|
});
|
|
10930
10975
|
|
|
10931
10976
|
// src/commands/watch.ts
|
|
10932
10977
|
import { closeSync as closeSync2, existsSync as existsSync5, openSync as openSync2, readSync as readSync2, statSync as statSync3 } from "fs";
|
|
10933
|
-
import { homedir as
|
|
10934
|
-
import { join as
|
|
10978
|
+
import { homedir as homedir9 } from "os";
|
|
10979
|
+
import { join as join11 } from "path";
|
|
10935
10980
|
function tailLocal(file, maxBytes = 131072) {
|
|
10936
10981
|
try {
|
|
10937
10982
|
const size = statSync3(file).size;
|
|
@@ -11038,7 +11083,7 @@ var init_watch = __esm({
|
|
|
11038
11083
|
init_cli_utils();
|
|
11039
11084
|
init_args();
|
|
11040
11085
|
init_format();
|
|
11041
|
-
LOCAL_LOG3 =
|
|
11086
|
+
LOCAL_LOG3 = join11(homedir9(), ".solongate", "local-logs", "solongate-audit.jsonl");
|
|
11042
11087
|
trunc = (s, n) => s.length <= n ? s : s.slice(0, n - 1) + "\u2026";
|
|
11043
11088
|
time = (ms) => new Date(ms).toTimeString().slice(0, 8);
|
|
11044
11089
|
}
|
|
@@ -11329,9 +11374,9 @@ var init_commands = __esm({
|
|
|
11329
11374
|
});
|
|
11330
11375
|
|
|
11331
11376
|
// src/global-install.ts
|
|
11332
|
-
import { readFileSync as readFileSync8, writeFileSync as writeFileSync7, existsSync as existsSync6, mkdirSync as
|
|
11333
|
-
import { resolve as resolve4, join as
|
|
11334
|
-
import { homedir as
|
|
11377
|
+
import { readFileSync as readFileSync8, writeFileSync as writeFileSync7, existsSync as existsSync6, mkdirSync as mkdirSync7 } from "fs";
|
|
11378
|
+
import { resolve as resolve4, join as join12, dirname } from "path";
|
|
11379
|
+
import { homedir as homedir10 } from "os";
|
|
11335
11380
|
import { fileURLToPath } from "url";
|
|
11336
11381
|
import { createInterface } from "readline";
|
|
11337
11382
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
@@ -11394,10 +11439,10 @@ function unlockFile(file) {
|
|
|
11394
11439
|
function protectedTargets() {
|
|
11395
11440
|
const p = globalPaths();
|
|
11396
11441
|
return [
|
|
11397
|
-
|
|
11398
|
-
|
|
11399
|
-
|
|
11400
|
-
|
|
11442
|
+
join12(p.hooksDir, "guard.mjs"),
|
|
11443
|
+
join12(p.hooksDir, "audit.mjs"),
|
|
11444
|
+
join12(p.hooksDir, "stop.mjs"),
|
|
11445
|
+
join12(p.hooksDir, "shield.mjs"),
|
|
11401
11446
|
p.configPath,
|
|
11402
11447
|
p.settingsPath
|
|
11403
11448
|
];
|
|
@@ -11409,25 +11454,25 @@ function unlockProtected() {
|
|
|
11409
11454
|
for (const f of protectedTargets()) unlockFile(f);
|
|
11410
11455
|
}
|
|
11411
11456
|
function globalPaths() {
|
|
11412
|
-
const home =
|
|
11413
|
-
const sgDir =
|
|
11414
|
-
const hooksDir =
|
|
11415
|
-
const claudeDir =
|
|
11457
|
+
const home = homedir10();
|
|
11458
|
+
const sgDir = join12(home, ".solongate");
|
|
11459
|
+
const hooksDir = join12(sgDir, "hooks");
|
|
11460
|
+
const claudeDir = join12(home, ".claude");
|
|
11416
11461
|
return {
|
|
11417
11462
|
home,
|
|
11418
11463
|
sgDir,
|
|
11419
11464
|
hooksDir,
|
|
11420
11465
|
claudeDir,
|
|
11421
|
-
settingsPath:
|
|
11422
|
-
backupPath:
|
|
11423
|
-
configPath:
|
|
11466
|
+
settingsPath: join12(claudeDir, "settings.json"),
|
|
11467
|
+
backupPath: join12(claudeDir, "settings.solongate.bak"),
|
|
11468
|
+
configPath: join12(sgDir, "cloud-guard.json")
|
|
11424
11469
|
};
|
|
11425
11470
|
}
|
|
11426
11471
|
function readHook(filename) {
|
|
11427
|
-
return readFileSync8(
|
|
11472
|
+
return readFileSync8(join12(HOOKS_DIR, filename), "utf-8");
|
|
11428
11473
|
}
|
|
11429
11474
|
function readGuard() {
|
|
11430
|
-
const bundled =
|
|
11475
|
+
const bundled = join12(HOOKS_DIR, "guard.bundled.mjs");
|
|
11431
11476
|
return existsSync6(bundled) ? readFileSync8(bundled, "utf-8") : readHook("guard.mjs");
|
|
11432
11477
|
}
|
|
11433
11478
|
function ask(question) {
|
|
@@ -11462,7 +11507,7 @@ function shimTargets() {
|
|
|
11462
11507
|
return [];
|
|
11463
11508
|
}
|
|
11464
11509
|
}
|
|
11465
|
-
return [".bashrc", ".zshrc", ".profile"].map((f) =>
|
|
11510
|
+
return [".bashrc", ".zshrc", ".profile"].map((f) => join12(homedir10(), f)).filter((f) => existsSync6(f));
|
|
11466
11511
|
}
|
|
11467
11512
|
function writeShimBlock(file, block2) {
|
|
11468
11513
|
const re = new RegExp(escapeRe(SHIM_BEGIN) + "[\\s\\S]*?" + escapeRe(SHIM_END) + "\\r?\\n?", "g");
|
|
@@ -11472,7 +11517,7 @@ function writeShimBlock(file, block2) {
|
|
|
11472
11517
|
if (content.length && !content.endsWith("\n")) content += "\n";
|
|
11473
11518
|
content += block2 + "\n";
|
|
11474
11519
|
}
|
|
11475
|
-
|
|
11520
|
+
mkdirSync7(dirname(file), { recursive: true });
|
|
11476
11521
|
writeFileSync7(file, content);
|
|
11477
11522
|
}
|
|
11478
11523
|
function installClaudeShim(shieldPath) {
|
|
@@ -11516,15 +11561,15 @@ async function runGlobalInstall(opts = {}) {
|
|
|
11516
11561
|
process.exit(1);
|
|
11517
11562
|
}
|
|
11518
11563
|
const apiUrl = opts.apiUrl || process.env["SOLONGATE_API_URL"] || "https://api.solongate.com";
|
|
11519
|
-
|
|
11520
|
-
|
|
11564
|
+
mkdirSync7(p.hooksDir, { recursive: true });
|
|
11565
|
+
mkdirSync7(p.claudeDir, { recursive: true });
|
|
11521
11566
|
unlockProtected();
|
|
11522
|
-
writeFileSync7(
|
|
11523
|
-
writeFileSync7(
|
|
11524
|
-
writeFileSync7(
|
|
11525
|
-
writeFileSync7(
|
|
11567
|
+
writeFileSync7(join12(p.hooksDir, "guard.mjs"), readGuard());
|
|
11568
|
+
writeFileSync7(join12(p.hooksDir, "audit.mjs"), readHook("audit.mjs"));
|
|
11569
|
+
writeFileSync7(join12(p.hooksDir, "stop.mjs"), readHook("stop.mjs"));
|
|
11570
|
+
writeFileSync7(join12(p.hooksDir, "shield.mjs"), readHook("shield.mjs"));
|
|
11526
11571
|
console.log(` Installed hooks \u2192 ${p.hooksDir}`);
|
|
11527
|
-
installClaudeShim(
|
|
11572
|
+
installClaudeShim(join12(p.hooksDir, "shield.mjs"));
|
|
11528
11573
|
writeFileSync7(p.configPath, JSON.stringify({ apiKey, apiUrl }, null, 2) + "\n");
|
|
11529
11574
|
console.log(` Wrote ${p.configPath}`);
|
|
11530
11575
|
let existing = {};
|
|
@@ -11540,9 +11585,9 @@ async function runGlobalInstall(opts = {}) {
|
|
|
11540
11585
|
existing = {};
|
|
11541
11586
|
}
|
|
11542
11587
|
}
|
|
11543
|
-
const guardAbs =
|
|
11544
|
-
const auditAbs =
|
|
11545
|
-
const stopAbs =
|
|
11588
|
+
const guardAbs = join12(p.hooksDir, "guard.mjs").replace(/\\/g, "/");
|
|
11589
|
+
const auditAbs = join12(p.hooksDir, "audit.mjs").replace(/\\/g, "/");
|
|
11590
|
+
const stopAbs = join12(p.hooksDir, "stop.mjs").replace(/\\/g, "/");
|
|
11546
11591
|
const nodeBin = process.execPath.replace(/\\/g, "/");
|
|
11547
11592
|
const call = process.platform === "win32" ? "& " : "";
|
|
11548
11593
|
const hookCmd = (script) => `${call}"${nodeBin}" "${script}" claude-code "Claude Code"`;
|
|
@@ -11734,9 +11779,9 @@ import { spawn as spawn4 } from "child_process";
|
|
|
11734
11779
|
import { URL as URL2 } from "url";
|
|
11735
11780
|
import { readFileSync as readFileSync9, existsSync as existsSync7, readdirSync, statSync as statSync4 } from "fs";
|
|
11736
11781
|
import { resolve as resolve5 } from "path";
|
|
11737
|
-
import { homedir as
|
|
11782
|
+
import { homedir as homedir11 } from "os";
|
|
11738
11783
|
function findCacheFile() {
|
|
11739
|
-
const dir = resolve5(
|
|
11784
|
+
const dir = resolve5(homedir11(), ".solongate");
|
|
11740
11785
|
const envSel = process.env.SOLONGATE_AGENT_ID;
|
|
11741
11786
|
if (envSel) {
|
|
11742
11787
|
const f = resolve5(dir, ".policy-cache-" + envSel.replace(/[^a-zA-Z0-9_-]/g, "_") + ".json");
|
|
@@ -12051,8 +12096,8 @@ __export(logs_server_exports, {
|
|
|
12051
12096
|
});
|
|
12052
12097
|
import { createServer as createServer2 } from "http";
|
|
12053
12098
|
import { readFileSync as readFileSync10, statSync as statSync5 } from "fs";
|
|
12054
|
-
import { resolve as resolve6, join as
|
|
12055
|
-
import { homedir as
|
|
12099
|
+
import { resolve as resolve6, join as join13, isAbsolute } from "path";
|
|
12100
|
+
import { homedir as homedir12 } from "os";
|
|
12056
12101
|
import { readdirSync as readdirSync2 } from "fs";
|
|
12057
12102
|
function allowedOrigins() {
|
|
12058
12103
|
const base = [
|
|
@@ -12069,15 +12114,15 @@ function resolveLocalLogDir(rawPath) {
|
|
|
12069
12114
|
const dir = String(rawPath || "").trim().replace(/[\\/]+$/, "");
|
|
12070
12115
|
if (!dir) return null;
|
|
12071
12116
|
if (isAbsolute(dir)) return dir;
|
|
12072
|
-
return resolve6(
|
|
12117
|
+
return resolve6(homedir12(), ".solongate", "local-logs");
|
|
12073
12118
|
}
|
|
12074
12119
|
async function findLogDir() {
|
|
12075
|
-
const base = resolve6(
|
|
12120
|
+
const base = resolve6(homedir12(), ".solongate");
|
|
12076
12121
|
try {
|
|
12077
12122
|
const files = readdirSync2(base).filter((f) => f.startsWith(".policy-cache-") && f.endsWith(".json"));
|
|
12078
12123
|
for (const f of files) {
|
|
12079
12124
|
try {
|
|
12080
|
-
const c2 = JSON.parse(readFileSync10(
|
|
12125
|
+
const c2 = JSON.parse(readFileSync10(join13(base, f), "utf-8"));
|
|
12081
12126
|
const p = c2?.security?.localLogs?.path;
|
|
12082
12127
|
if (typeof p === "string" && p.trim()) return { dir: resolveLocalLogDir(p), configured: p };
|
|
12083
12128
|
} catch {
|
|
@@ -12086,7 +12131,7 @@ async function findLogDir() {
|
|
|
12086
12131
|
} catch {
|
|
12087
12132
|
}
|
|
12088
12133
|
try {
|
|
12089
|
-
const cfgRaw = readFileSync10(
|
|
12134
|
+
const cfgRaw = readFileSync10(join13(base, "cloud-guard.json"), "utf-8");
|
|
12090
12135
|
const { apiKey, apiUrl } = JSON.parse(cfgRaw);
|
|
12091
12136
|
if (apiKey) {
|
|
12092
12137
|
const url = `${apiUrl || "https://api.solongate.com"}/api/v1/policies/active`;
|
|
@@ -12115,7 +12160,7 @@ function setCors(req, res) {
|
|
|
12115
12160
|
}
|
|
12116
12161
|
function fileInfo(dir) {
|
|
12117
12162
|
if (!dir) return { file: null, exists: false, size: 0, mtimeMs: 0 };
|
|
12118
|
-
const file =
|
|
12163
|
+
const file = join13(dir, LOG_FILENAME);
|
|
12119
12164
|
try {
|
|
12120
12165
|
const st = statSync5(file);
|
|
12121
12166
|
return { file, exists: true, size: st.size, mtimeMs: st.mtimeMs };
|
|
@@ -12565,8 +12610,8 @@ var init_inject = __esm({
|
|
|
12565
12610
|
|
|
12566
12611
|
// src/create.ts
|
|
12567
12612
|
var create_exports = {};
|
|
12568
|
-
import { mkdirSync as
|
|
12569
|
-
import { resolve as resolve8, join as
|
|
12613
|
+
import { mkdirSync as mkdirSync8, writeFileSync as writeFileSync9, existsSync as existsSync9 } from "fs";
|
|
12614
|
+
import { resolve as resolve8, join as join14 } from "path";
|
|
12570
12615
|
import { execSync as execSync2 } from "child_process";
|
|
12571
12616
|
function withSpinner(message, fn) {
|
|
12572
12617
|
const frames = ["\u28FE", "\u28FD", "\u28FB", "\u28BF", "\u287F", "\u28DF", "\u28EF", "\u28F7"];
|
|
@@ -12646,7 +12691,7 @@ EXAMPLES
|
|
|
12646
12691
|
}
|
|
12647
12692
|
function createProject(dir, name, _policy) {
|
|
12648
12693
|
writeFileSync9(
|
|
12649
|
-
|
|
12694
|
+
join14(dir, "package.json"),
|
|
12650
12695
|
JSON.stringify(
|
|
12651
12696
|
{
|
|
12652
12697
|
name,
|
|
@@ -12676,7 +12721,7 @@ function createProject(dir, name, _policy) {
|
|
|
12676
12721
|
) + "\n"
|
|
12677
12722
|
);
|
|
12678
12723
|
writeFileSync9(
|
|
12679
|
-
|
|
12724
|
+
join14(dir, "tsconfig.json"),
|
|
12680
12725
|
JSON.stringify(
|
|
12681
12726
|
{
|
|
12682
12727
|
compilerOptions: {
|
|
@@ -12696,9 +12741,9 @@ function createProject(dir, name, _policy) {
|
|
|
12696
12741
|
2
|
|
12697
12742
|
) + "\n"
|
|
12698
12743
|
);
|
|
12699
|
-
|
|
12744
|
+
mkdirSync8(join14(dir, "src"), { recursive: true });
|
|
12700
12745
|
writeFileSync9(
|
|
12701
|
-
|
|
12746
|
+
join14(dir, "src", "index.ts"),
|
|
12702
12747
|
`#!/usr/bin/env node
|
|
12703
12748
|
|
|
12704
12749
|
console.log = (...args: unknown[]) => {
|
|
@@ -12740,7 +12785,7 @@ console.log('Press Ctrl+C to stop.');
|
|
|
12740
12785
|
`
|
|
12741
12786
|
);
|
|
12742
12787
|
writeFileSync9(
|
|
12743
|
-
|
|
12788
|
+
join14(dir, ".mcp.json"),
|
|
12744
12789
|
JSON.stringify(
|
|
12745
12790
|
{
|
|
12746
12791
|
mcpServers: {
|
|
@@ -12758,12 +12803,12 @@ console.log('Press Ctrl+C to stop.');
|
|
|
12758
12803
|
) + "\n"
|
|
12759
12804
|
);
|
|
12760
12805
|
writeFileSync9(
|
|
12761
|
-
|
|
12806
|
+
join14(dir, ".env"),
|
|
12762
12807
|
`SOLONGATE_API_KEY=sg_live_YOUR_KEY_HERE
|
|
12763
12808
|
`
|
|
12764
12809
|
);
|
|
12765
12810
|
writeFileSync9(
|
|
12766
|
-
|
|
12811
|
+
join14(dir, ".gitignore"),
|
|
12767
12812
|
`node_modules/
|
|
12768
12813
|
dist/
|
|
12769
12814
|
*.solongate-backup
|
|
@@ -12782,7 +12827,7 @@ async function main3() {
|
|
|
12782
12827
|
process.exit(1);
|
|
12783
12828
|
}
|
|
12784
12829
|
withSpinner(`Setting up ${opts.name}...`, () => {
|
|
12785
|
-
|
|
12830
|
+
mkdirSync8(dir, { recursive: true });
|
|
12786
12831
|
createProject(dir, opts.name, opts.policy);
|
|
12787
12832
|
});
|
|
12788
12833
|
if (!opts.noInstall) {
|
package/dist/tui/index.js
CHANGED
|
@@ -5,6 +5,9 @@ var __export = (target, all) => {
|
|
|
5
5
|
};
|
|
6
6
|
|
|
7
7
|
// src/tui/index.tsx
|
|
8
|
+
import { appendFileSync, mkdirSync as mkdirSync4 } from "fs";
|
|
9
|
+
import { homedir as homedir6 } from "os";
|
|
10
|
+
import { join as join6 } from "path";
|
|
8
11
|
import { render } from "ink";
|
|
9
12
|
|
|
10
13
|
// src/tui/App.tsx
|
|
@@ -970,6 +973,7 @@ function LivePanel({ active: active2 }) {
|
|
|
970
973
|
const inspectFromRef = useRef2("stream");
|
|
971
974
|
const seenRef = useRef2(/* @__PURE__ */ new Set());
|
|
972
975
|
const lastLocalTs = useRef2(0);
|
|
976
|
+
const localSeq = useRef2(0);
|
|
973
977
|
const pausedUntil = useRef2(0);
|
|
974
978
|
const sessRef = useRef2([]);
|
|
975
979
|
const mergedRef = useRef2([]);
|
|
@@ -1015,7 +1019,7 @@ function LivePanel({ active: active2 }) {
|
|
|
1015
1019
|
const at = Date.parse(j.ts ?? "");
|
|
1016
1020
|
if (!Number.isFinite(at) || at <= lastLocalTs.current) continue;
|
|
1017
1021
|
fresh.push({
|
|
1018
|
-
id: "l:" + at + ":" + (j.tool ?? "")
|
|
1022
|
+
id: "l:" + at + ":" + (j.tool ?? "") + ":" + localSeq.current++,
|
|
1019
1023
|
at,
|
|
1020
1024
|
tool: j.tool ?? "?",
|
|
1021
1025
|
decision: j.decision ?? "ALLOW",
|
|
@@ -1138,20 +1142,45 @@ function LivePanel({ active: active2 }) {
|
|
|
1138
1142
|
}, [active2, frozen]);
|
|
1139
1143
|
const startRef = useRef2(Date.now());
|
|
1140
1144
|
const lastNotifyAt = useRef2(0);
|
|
1145
|
+
const toastQueue = useRef2(/* @__PURE__ */ new Map());
|
|
1146
|
+
const toastTimer = useRef2(null);
|
|
1147
|
+
const TOAST_RANK = { "DLP hit": 0, "Call denied": 1, "Rate-limit burst": 2 };
|
|
1148
|
+
const flushToasts = useCallback2(function flush() {
|
|
1149
|
+
toastTimer.current = null;
|
|
1150
|
+
const q2 = toastQueue.current;
|
|
1151
|
+
if (!q2.size) return;
|
|
1152
|
+
const wait = 3e3 - (Date.now() - lastNotifyAt.current);
|
|
1153
|
+
if (wait > 0) {
|
|
1154
|
+
toastTimer.current = setTimeout(flush, wait);
|
|
1155
|
+
return;
|
|
1156
|
+
}
|
|
1157
|
+
lastNotifyAt.current = Date.now();
|
|
1158
|
+
const items = [...q2.entries()].sort((a, b) => (TOAST_RANK[a[0]] ?? 9) - (TOAST_RANK[b[0]] ?? 9));
|
|
1159
|
+
q2.clear();
|
|
1160
|
+
try {
|
|
1161
|
+
process.stdout.write("\x07");
|
|
1162
|
+
} catch {
|
|
1163
|
+
}
|
|
1164
|
+
const total = items.reduce((n, [, v]) => n + v.count, 0);
|
|
1165
|
+
if (items.length === 1 && total === 1) desktopNotify(items[0][0], items[0][1].msg);
|
|
1166
|
+
else desktopNotify("Security alerts", items.map(([t, v]) => `${v.count}\xD7 ${t}`).join(" \xB7 "));
|
|
1167
|
+
}, []);
|
|
1168
|
+
useEffect2(
|
|
1169
|
+
() => () => {
|
|
1170
|
+
if (toastTimer.current) clearTimeout(toastTimer.current);
|
|
1171
|
+
},
|
|
1172
|
+
[]
|
|
1173
|
+
);
|
|
1141
1174
|
const fireAlert = useCallback2(
|
|
1142
|
-
(id, title, msg, level = "warn") => {
|
|
1175
|
+
(id, title, msg, level = "warn", desktop = true) => {
|
|
1143
1176
|
pushLog(`${level === "bad" ? "\u26D4" : "\u23F8"} ${msg}`, level);
|
|
1144
1177
|
setAlerts((a) => [...a.filter((x) => x.id !== id), { id, msg, level, until: Date.now() + 15e3 }].slice(-4));
|
|
1145
|
-
if (!CONFIG.notifications) return;
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
process.stdout.write("\x07");
|
|
1150
|
-
} catch {
|
|
1151
|
-
}
|
|
1152
|
-
desktopNotify(title, msg);
|
|
1178
|
+
if (!desktop || !CONFIG.notifications) return;
|
|
1179
|
+
const cur = toastQueue.current.get(title);
|
|
1180
|
+
toastQueue.current.set(title, { count: (cur?.count ?? 0) + 1, msg: cur?.msg ?? msg });
|
|
1181
|
+
if (!toastTimer.current) toastTimer.current = setTimeout(flushToasts, 400);
|
|
1153
1182
|
},
|
|
1154
|
-
[pushLog]
|
|
1183
|
+
[pushLog, flushToasts]
|
|
1155
1184
|
);
|
|
1156
1185
|
useEffect2(() => {
|
|
1157
1186
|
if (!active2) return;
|
|
@@ -1159,7 +1188,7 @@ function LivePanel({ active: active2 }) {
|
|
|
1159
1188
|
const prev = prevStatus.current.get(r.id);
|
|
1160
1189
|
if (prev && prev === "active" && r.status === "idle") {
|
|
1161
1190
|
const name = r.isMe ? `${r.agent} (this machine)` : r.agent;
|
|
1162
|
-
fireAlert("idle:" + r.id, "Agent idle", `${name} went IDLE, no tool call for 60s`, "warn");
|
|
1191
|
+
fireAlert("idle:" + r.id, "Agent idle", `${name} went IDLE, no tool call for 60s`, "warn", false);
|
|
1163
1192
|
}
|
|
1164
1193
|
prevStatus.current.set(r.id, r.status);
|
|
1165
1194
|
}
|
|
@@ -3436,10 +3465,26 @@ async function launchTui() {
|
|
|
3436
3465
|
return;
|
|
3437
3466
|
}
|
|
3438
3467
|
process.stdout.write("\x1B[?1049h\x1B[H");
|
|
3468
|
+
const debugLog = join6(homedir6(), ".solongate", "dataroom-debug.log");
|
|
3469
|
+
const saved = { log: console.log, warn: console.warn, error: console.error, info: console.info, debug: console.debug };
|
|
3470
|
+
const toFile = (level) => (...args) => {
|
|
3471
|
+
try {
|
|
3472
|
+
mkdirSync4(join6(homedir6(), ".solongate"), { recursive: true });
|
|
3473
|
+
appendFileSync(debugLog, `${(/* @__PURE__ */ new Date()).toISOString()} [${level}] ${args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ")}
|
|
3474
|
+
`);
|
|
3475
|
+
} catch {
|
|
3476
|
+
}
|
|
3477
|
+
};
|
|
3478
|
+
console.log = toFile("log");
|
|
3479
|
+
console.warn = toFile("warn");
|
|
3480
|
+
console.error = toFile("error");
|
|
3481
|
+
console.info = toFile("info");
|
|
3482
|
+
console.debug = toFile("debug");
|
|
3439
3483
|
try {
|
|
3440
|
-
const { waitUntilExit } = render(/* @__PURE__ */ jsx10(App, {}));
|
|
3484
|
+
const { waitUntilExit } = render(/* @__PURE__ */ jsx10(App, {}), { patchConsole: false });
|
|
3441
3485
|
await waitUntilExit();
|
|
3442
3486
|
} finally {
|
|
3487
|
+
Object.assign(console, saved);
|
|
3443
3488
|
process.stdout.write("\x1B[?1049l");
|
|
3444
3489
|
}
|
|
3445
3490
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solongate/proxy",
|
|
3
|
-
"version": "0.81.
|
|
3
|
+
"version": "0.81.44",
|
|
4
4
|
"description": "AI tool security proxy: protect any AI tool server with customizable policies, path/command constraints, rate limiting, and audit logging. No code changes required.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|