@solongate/proxy 0.72.0 → 0.74.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 +46 -80
- package/dist/tui/index.js +16 -50
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7030,10 +7030,9 @@ var init_hooks = __esm({
|
|
|
7030
7030
|
|
|
7031
7031
|
// src/tui/panels/Live.tsx
|
|
7032
7032
|
import { Box as Box2, Text as Text2, useInput } from "ink";
|
|
7033
|
-
import {
|
|
7034
|
-
import { closeSync, mkdirSync as mkdirSync3, openSync, readSync, statSync, writeFileSync as writeFileSync3 } from "fs";
|
|
7033
|
+
import { closeSync, openSync, readSync, statSync } from "fs";
|
|
7035
7034
|
import { homedir as homedir3 } from "os";
|
|
7036
|
-
import {
|
|
7035
|
+
import { join as join5 } from "path";
|
|
7037
7036
|
import { useCallback as useCallback2, useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
|
|
7038
7037
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
7039
7038
|
function tailLines(file, maxBytes = 131072) {
|
|
@@ -7051,22 +7050,6 @@ function tailLines(file, maxBytes = 131072) {
|
|
|
7051
7050
|
return [];
|
|
7052
7051
|
}
|
|
7053
7052
|
}
|
|
7054
|
-
function copyToClipboard(text) {
|
|
7055
|
-
const tools = [
|
|
7056
|
-
["wl-copy", []],
|
|
7057
|
-
["xclip", ["-selection", "clipboard"]],
|
|
7058
|
-
["xsel", ["--clipboard", "--input"]]
|
|
7059
|
-
];
|
|
7060
|
-
for (const [cmd, args] of tools) {
|
|
7061
|
-
try {
|
|
7062
|
-
const r = spawnSync(cmd, args, { input: text, timeout: 2e3 });
|
|
7063
|
-
if (r.status === 0) return cmd;
|
|
7064
|
-
} catch {
|
|
7065
|
-
}
|
|
7066
|
-
}
|
|
7067
|
-
process.stdout.write(`\x1B]52;c;${Buffer.from(text, "utf-8").toString("base64")}\x07`);
|
|
7068
|
-
return null;
|
|
7069
|
-
}
|
|
7070
7053
|
function cloudItem(e) {
|
|
7071
7054
|
return {
|
|
7072
7055
|
id: "c:" + e.id,
|
|
@@ -7161,7 +7144,6 @@ function LivePanel({ active: active2 }) {
|
|
|
7161
7144
|
const [log6, setLog] = useState2([]);
|
|
7162
7145
|
const [filter, setFilter] = useState2("all");
|
|
7163
7146
|
const [scroll, setScroll] = useState2(0);
|
|
7164
|
-
const [toast, setToast] = useState2(null);
|
|
7165
7147
|
const [mode, setMode] = useState2("stream");
|
|
7166
7148
|
const [pickIdx, setPickIdx] = useState2(0);
|
|
7167
7149
|
const [detail, setDetail] = useState2(null);
|
|
@@ -7348,24 +7330,24 @@ function LivePanel({ active: active2 }) {
|
|
|
7348
7330
|
const cloudDeduped = cloudBuf.filter((e) => !localKeys.has(`${e.tool}|${e.decision}|${Math.round(e.at / 6e4)}`));
|
|
7349
7331
|
const mergedAll = [...cloudDeduped, ...localBuf].sort((a, b) => a.at - b.at);
|
|
7350
7332
|
const points = tsData?.timeseries ?? [];
|
|
7351
|
-
const
|
|
7352
|
-
const
|
|
7353
|
-
const
|
|
7333
|
+
const nowSlot = Math.floor(nowMs / 1e4);
|
|
7334
|
+
const slotCounts = new Array(60).fill(0);
|
|
7335
|
+
const slotHot = new Array(60).fill(false);
|
|
7354
7336
|
for (const e of mergedAll) {
|
|
7355
|
-
const idx = 59 - (
|
|
7337
|
+
const idx = 59 - (nowSlot - Math.floor(e.at / 1e4));
|
|
7356
7338
|
if (idx >= 0 && idx < 60) {
|
|
7357
|
-
|
|
7358
|
-
if (e.decision !== "ALLOW")
|
|
7339
|
+
slotCounts[idx]++;
|
|
7340
|
+
if (e.decision !== "ALLOW") slotHot[idx] = true;
|
|
7359
7341
|
}
|
|
7360
7342
|
}
|
|
7361
|
-
const localTraffic = localOn === true &&
|
|
7362
|
-
const traffic = localTraffic ?
|
|
7363
|
-
const trafficHot = localTraffic ?
|
|
7364
|
-
const trafficLabel = localTraffic ? "calls/
|
|
7343
|
+
const localTraffic = localOn === true && slotCounts.some((c2) => c2 > 0);
|
|
7344
|
+
const traffic = localTraffic ? slotCounts : points.map((p) => p.total);
|
|
7345
|
+
const trafficHot = localTraffic ? slotHot : points.map((p) => p.denied > 0);
|
|
7346
|
+
const trafficLabel = localTraffic ? "calls/10s \xB7 last 10m" : "24h \xB7 cloud";
|
|
7365
7347
|
const rl = ins.layers?.rateLimit;
|
|
7366
7348
|
const dl = ins.layers?.dlp;
|
|
7367
7349
|
const gh = ins.layers?.ghost;
|
|
7368
|
-
const minuteNow =
|
|
7350
|
+
const minuteNow = mergedAll.filter((e) => nowMs - e.at < 6e4).length;
|
|
7369
7351
|
const dlpBars = (ins.dlpByPattern ?? []).slice(0, 2);
|
|
7370
7352
|
const maxDlpBar = dlpBars[0]?.count ?? 1;
|
|
7371
7353
|
const denialsAll = mergedAll.filter((e) => e.decision !== "ALLOW");
|
|
@@ -7470,20 +7452,6 @@ function LivePanel({ active: active2 }) {
|
|
|
7470
7452
|
else if (key.upArrow) setScroll((n) => Math.max(0, n - 1));
|
|
7471
7453
|
else if (key.pageDown) setScroll((n) => Math.min(maxScroll, n + streamRows));
|
|
7472
7454
|
else if (key.pageUp) setScroll((n) => Math.max(0, n - streamRows));
|
|
7473
|
-
else if (input === "c") {
|
|
7474
|
-
const dump = visibleDesc.map(
|
|
7475
|
-
(e) => `[${new Date(e.at).toISOString()}] ${e.source.toUpperCase().padEnd(5)} ${e.decision.padEnd(6)} ${e.tool.padEnd(16)} ${e.permission.padEnd(5)} ${e.evalMs != null ? String(e.evalMs).padStart(5) + "ms " : " "}${(e.agent ?? "-").padEnd(14)} ${e.session ? e.session.slice(0, 8) : "- "} ${e.detail}`
|
|
7476
|
-
).join("\n");
|
|
7477
|
-
try {
|
|
7478
|
-
mkdirSync3(dirname(DUMP), { recursive: true });
|
|
7479
|
-
writeFileSync3(DUMP, dump + "\n");
|
|
7480
|
-
} catch {
|
|
7481
|
-
}
|
|
7482
|
-
const via = copyToClipboard(dump);
|
|
7483
|
-
setToast(
|
|
7484
|
-
via ? { msg: `\u2713 ${visibleDesc.length} lines in clipboard (${via})`, until: Date.now() + 4e3 } : { msg: "\u2717 no clipboard tool \u2014 install wl-clipboard or xclip", until: Date.now() + 6e3 }
|
|
7485
|
-
);
|
|
7486
|
-
}
|
|
7487
7455
|
},
|
|
7488
7456
|
{ isActive: active2 }
|
|
7489
7457
|
);
|
|
@@ -7498,8 +7466,7 @@ function LivePanel({ active: active2 }) {
|
|
|
7498
7466
|
const titleBar = /* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
|
|
7499
7467
|
/* @__PURE__ */ jsx2(Text2, { backgroundColor: "#1432A0", color: "#AAC8FA", bold: true, children: " SOLONGATE LIVE " }),
|
|
7500
7468
|
/* @__PURE__ */ jsx2(Text2, { backgroundColor: BG, color: "#82AAF0", children: ` ${spin} up ${fmtUp(nowMs - startRef.current)} \xB7 ${hhmmss(nowMs)} \xB7 api ${latNow}ms ` }),
|
|
7501
|
-
frozen ? /* @__PURE__ */ jsx2(Text2, { backgroundColor: "#123d1f", color: "#7bd88f", bold: true, children: " \u23F5 COPY MODE \u2014 screen frozen, select & copy freely \xB7 space resume " }) : backingOff ? /* @__PURE__ */ jsx2(Text2, { backgroundColor: "#3d2a12", color: "#ffb454", bold: true, children: " RATE LIMITED \xB7 backing off " }) : lastDeny ? /* @__PURE__ */ jsx2(Text2, { backgroundColor: "#3d1220", color: "#ff6b6b", bold: true, children: ` \u26A0 ${hhmmss(lastDeny.at)} ${lastDeny.tool} DENIED ` }) : /* @__PURE__ */ jsx2(Text2, { backgroundColor: BG, color: "#4f6db8", children: " \u2713 clean " })
|
|
7502
|
-
toast && nowMs < toast.until ? /* @__PURE__ */ jsx2(Text2, { backgroundColor: "#123d1f", color: "#7bd88f", bold: true, children: ` ${toast.msg} ` }) : null
|
|
7469
|
+
frozen ? /* @__PURE__ */ jsx2(Text2, { backgroundColor: "#123d1f", color: "#7bd88f", bold: true, children: " \u23F5 COPY MODE \u2014 screen frozen, select & copy freely \xB7 space resume " }) : backingOff ? /* @__PURE__ */ jsx2(Text2, { backgroundColor: "#3d2a12", color: "#ffb454", bold: true, children: " RATE LIMITED \xB7 backing off " }) : lastDeny ? /* @__PURE__ */ jsx2(Text2, { backgroundColor: "#3d1220", color: "#ff6b6b", bold: true, children: ` \u26A0 ${hhmmss(lastDeny.at)} ${lastDeny.tool} DENIED ` }) : /* @__PURE__ */ jsx2(Text2, { backgroundColor: BG, color: "#4f6db8", children: " \u2713 clean " })
|
|
7503
7470
|
] });
|
|
7504
7471
|
if (mode === "detail" && detail) {
|
|
7505
7472
|
const d = detailEntries;
|
|
@@ -7664,7 +7631,7 @@ function LivePanel({ active: active2 }) {
|
|
|
7664
7631
|
PaneTitle,
|
|
7665
7632
|
{
|
|
7666
7633
|
label: "TOOL STREAM",
|
|
7667
|
-
extra: `newest first \xB7 last ${STREAM_KEEP} \xB7 filter ${filter}${clampedScroll > 0 ? ` \xB7 \u25BC${clampedScroll} older` : ""} \xB7 f filter \xB7 \u2191\u2193 scroll \xB7
|
|
7634
|
+
extra: `newest first \xB7 last ${STREAM_KEEP} \xB7 filter ${filter}${clampedScroll > 0 ? ` \xB7 \u25BC${clampedScroll} older` : ""} \xB7 f filter \xB7 \u2191\u2193 scroll \xB7 s sessions`,
|
|
7668
7635
|
width: innerW
|
|
7669
7636
|
}
|
|
7670
7637
|
),
|
|
@@ -7682,11 +7649,11 @@ function LivePanel({ active: active2 }) {
|
|
|
7682
7649
|
/* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
|
|
7683
7650
|
/* @__PURE__ */ jsx2(Text2, { backgroundColor: BG, color: "#82AAF0", bold: true, children: " LIVE " }),
|
|
7684
7651
|
/* @__PURE__ */ jsx2(Text2, { backgroundColor: "#0b1530", color: "#4f6db8", children: ` local ${localOn ? "on" : "off"} \xB7 ${localBuf.length} loc/${cloudBuf.length} cld \xB7 top ${topTools.map(([t, c2]) => `${t}\xD7${c2}`).join(" ") || "\u2014"} ` }),
|
|
7685
|
-
/* @__PURE__ */ jsx2(Text2, { backgroundColor: BG, color: "#82AAF0", children: " space copy-mode \xB7 f filter \xB7 s sessions \xB7
|
|
7652
|
+
/* @__PURE__ */ jsx2(Text2, { backgroundColor: BG, color: "#82AAF0", children: " space copy-mode \xB7 f filter \xB7 s sessions \xB7 esc menu \xB7 q quit " })
|
|
7686
7653
|
] })
|
|
7687
7654
|
] });
|
|
7688
7655
|
}
|
|
7689
|
-
var SPIN, BG, DIM_FLOOR, LOCAL_LOG, RING,
|
|
7656
|
+
var SPIN, BG, DIM_FLOOR, LOCAL_LOG, RING, STREAM_KEEP, hhmmss, fmtUp, FILTERS;
|
|
7690
7657
|
var init_Live = __esm({
|
|
7691
7658
|
"src/tui/panels/Live.tsx"() {
|
|
7692
7659
|
"use strict";
|
|
@@ -7698,7 +7665,6 @@ var init_Live = __esm({
|
|
|
7698
7665
|
DIM_FLOOR = "#233457";
|
|
7699
7666
|
LOCAL_LOG = join5(homedir3(), ".solongate", "local-logs", "solongate-audit.jsonl");
|
|
7700
7667
|
RING = join5(process.cwd(), ".solongate", ".eval-ring.jsonl");
|
|
7701
|
-
DUMP = join5(homedir3(), ".solongate", "live-stream.log");
|
|
7702
7668
|
STREAM_KEEP = 100;
|
|
7703
7669
|
hhmmss = (ts) => {
|
|
7704
7670
|
const d = new Date(ts);
|
|
@@ -9371,8 +9337,8 @@ __export(global_install_exports, {
|
|
|
9371
9337
|
runGlobalRestore: () => runGlobalRestore,
|
|
9372
9338
|
unlockProtected: () => unlockProtected
|
|
9373
9339
|
});
|
|
9374
|
-
import { readFileSync as readFileSync6, writeFileSync as
|
|
9375
|
-
import { resolve as resolve4, join as join6, dirname
|
|
9340
|
+
import { readFileSync as readFileSync6, writeFileSync as writeFileSync3, existsSync as existsSync4, mkdirSync as mkdirSync3 } from "fs";
|
|
9341
|
+
import { resolve as resolve4, join as join6, dirname } from "path";
|
|
9376
9342
|
import { homedir as homedir4 } from "os";
|
|
9377
9343
|
import { fileURLToPath } from "url";
|
|
9378
9344
|
import { createInterface } from "readline";
|
|
@@ -9484,13 +9450,13 @@ function runGlobalRestore() {
|
|
|
9484
9450
|
unlockProtected();
|
|
9485
9451
|
removeClaudeShim();
|
|
9486
9452
|
if (existsSync4(p.backupPath)) {
|
|
9487
|
-
|
|
9453
|
+
writeFileSync3(p.settingsPath, readFileSync6(p.backupPath, "utf-8"));
|
|
9488
9454
|
console.log(` Restored ${p.settingsPath} from backup.`);
|
|
9489
9455
|
} else if (existsSync4(p.settingsPath)) {
|
|
9490
9456
|
try {
|
|
9491
9457
|
const s = JSON.parse(readFileSync6(p.settingsPath, "utf-8"));
|
|
9492
9458
|
delete s.hooks;
|
|
9493
|
-
|
|
9459
|
+
writeFileSync3(p.settingsPath, JSON.stringify(s, null, 2) + "\n");
|
|
9494
9460
|
console.log(` Removed SolonGate hooks from ${p.settingsPath}.`);
|
|
9495
9461
|
} catch {
|
|
9496
9462
|
}
|
|
@@ -9534,8 +9500,8 @@ function writeShimBlock(file, block) {
|
|
|
9534
9500
|
if (content.length && !content.endsWith("\n")) content += "\n";
|
|
9535
9501
|
content += block + "\n";
|
|
9536
9502
|
}
|
|
9537
|
-
|
|
9538
|
-
|
|
9503
|
+
mkdirSync3(dirname(file), { recursive: true });
|
|
9504
|
+
writeFileSync3(file, content);
|
|
9539
9505
|
}
|
|
9540
9506
|
function installClaudeShim(shieldPath) {
|
|
9541
9507
|
const real = resolveRealClaude();
|
|
@@ -9592,22 +9558,22 @@ async function runGlobalInstall(opts = {}) {
|
|
|
9592
9558
|
process.exit(1);
|
|
9593
9559
|
}
|
|
9594
9560
|
const apiUrl = opts.apiUrl || process.env["SOLONGATE_API_URL"] || "https://api.solongate.com";
|
|
9595
|
-
|
|
9596
|
-
|
|
9561
|
+
mkdirSync3(p.hooksDir, { recursive: true });
|
|
9562
|
+
mkdirSync3(p.claudeDir, { recursive: true });
|
|
9597
9563
|
unlockProtected();
|
|
9598
|
-
|
|
9599
|
-
|
|
9600
|
-
|
|
9601
|
-
|
|
9564
|
+
writeFileSync3(join6(p.hooksDir, "guard.mjs"), readGuard());
|
|
9565
|
+
writeFileSync3(join6(p.hooksDir, "audit.mjs"), readHook("audit.mjs"));
|
|
9566
|
+
writeFileSync3(join6(p.hooksDir, "stop.mjs"), readHook("stop.mjs"));
|
|
9567
|
+
writeFileSync3(join6(p.hooksDir, "shield.mjs"), readHook("shield.mjs"));
|
|
9602
9568
|
console.log(` Installed hooks \u2192 ${p.hooksDir}`);
|
|
9603
9569
|
removeClaudeShim();
|
|
9604
|
-
|
|
9570
|
+
writeFileSync3(p.configPath, JSON.stringify({ apiKey, apiUrl }, null, 2) + "\n");
|
|
9605
9571
|
console.log(` Wrote ${p.configPath}`);
|
|
9606
9572
|
let existing = {};
|
|
9607
9573
|
if (existsSync4(p.settingsPath)) {
|
|
9608
9574
|
const raw = readFileSync6(p.settingsPath, "utf-8");
|
|
9609
9575
|
if (!existsSync4(p.backupPath)) {
|
|
9610
|
-
|
|
9576
|
+
writeFileSync3(p.backupPath, raw);
|
|
9611
9577
|
console.log(` Backed up existing settings \u2192 ${p.backupPath}`);
|
|
9612
9578
|
}
|
|
9613
9579
|
try {
|
|
@@ -9628,7 +9594,7 @@ async function runGlobalInstall(opts = {}) {
|
|
|
9628
9594
|
Stop: [{ matcher: "", hooks: [{ type: "command", command: `"${nodeBin}" "${stopAbs}" claude-code "Claude Code"` }] }]
|
|
9629
9595
|
}
|
|
9630
9596
|
};
|
|
9631
|
-
|
|
9597
|
+
writeFileSync3(p.settingsPath, JSON.stringify(merged, null, 2) + "\n");
|
|
9632
9598
|
console.log(` Registered global hooks \u2192 ${p.settingsPath}`);
|
|
9633
9599
|
if (process.env["SOLONGATE_OS_LOCK"] === "1") {
|
|
9634
9600
|
lockProtected();
|
|
@@ -9642,7 +9608,7 @@ var __dirname, HOOKS_DIR, SHIM_BEGIN, SHIM_END;
|
|
|
9642
9608
|
var init_global_install = __esm({
|
|
9643
9609
|
"src/global-install.ts"() {
|
|
9644
9610
|
"use strict";
|
|
9645
|
-
__dirname =
|
|
9611
|
+
__dirname = dirname(fileURLToPath(import.meta.url));
|
|
9646
9612
|
HOOKS_DIR = resolve4(__dirname, "..", "hooks");
|
|
9647
9613
|
SHIM_BEGIN = "# >>> SolonGate shield (auto secret redaction) >>>";
|
|
9648
9614
|
SHIM_END = "# <<< SolonGate shield <<<";
|
|
@@ -10292,7 +10258,7 @@ var init_logs_server = __esm({
|
|
|
10292
10258
|
|
|
10293
10259
|
// src/inject.ts
|
|
10294
10260
|
var inject_exports = {};
|
|
10295
|
-
import { readFileSync as readFileSync9, writeFileSync as
|
|
10261
|
+
import { readFileSync as readFileSync9, writeFileSync as writeFileSync4, existsSync as existsSync6, copyFileSync } from "fs";
|
|
10296
10262
|
import { resolve as resolve7 } from "path";
|
|
10297
10263
|
import { execSync } from "child_process";
|
|
10298
10264
|
function parseInjectArgs(argv) {
|
|
@@ -10600,7 +10566,7 @@ async function main2() {
|
|
|
10600
10566
|
log3("");
|
|
10601
10567
|
log3(` Backup: ${backupPath}`);
|
|
10602
10568
|
}
|
|
10603
|
-
|
|
10569
|
+
writeFileSync4(entryFile, result.modified);
|
|
10604
10570
|
log3("");
|
|
10605
10571
|
log3(" \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510");
|
|
10606
10572
|
log3(" \u2502 SolonGate SDK injected successfully! \u2502");
|
|
@@ -10629,7 +10595,7 @@ var init_inject = __esm({
|
|
|
10629
10595
|
|
|
10630
10596
|
// src/create.ts
|
|
10631
10597
|
var create_exports = {};
|
|
10632
|
-
import { mkdirSync as
|
|
10598
|
+
import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync5, existsSync as existsSync7 } from "fs";
|
|
10633
10599
|
import { resolve as resolve8, join as join8 } from "path";
|
|
10634
10600
|
import { execSync as execSync2 } from "child_process";
|
|
10635
10601
|
function withSpinner(message, fn) {
|
|
@@ -10709,7 +10675,7 @@ EXAMPLES
|
|
|
10709
10675
|
`);
|
|
10710
10676
|
}
|
|
10711
10677
|
function createProject(dir, name, _policy) {
|
|
10712
|
-
|
|
10678
|
+
writeFileSync5(
|
|
10713
10679
|
join8(dir, "package.json"),
|
|
10714
10680
|
JSON.stringify(
|
|
10715
10681
|
{
|
|
@@ -10739,7 +10705,7 @@ function createProject(dir, name, _policy) {
|
|
|
10739
10705
|
2
|
|
10740
10706
|
) + "\n"
|
|
10741
10707
|
);
|
|
10742
|
-
|
|
10708
|
+
writeFileSync5(
|
|
10743
10709
|
join8(dir, "tsconfig.json"),
|
|
10744
10710
|
JSON.stringify(
|
|
10745
10711
|
{
|
|
@@ -10760,8 +10726,8 @@ function createProject(dir, name, _policy) {
|
|
|
10760
10726
|
2
|
|
10761
10727
|
) + "\n"
|
|
10762
10728
|
);
|
|
10763
|
-
|
|
10764
|
-
|
|
10729
|
+
mkdirSync4(join8(dir, "src"), { recursive: true });
|
|
10730
|
+
writeFileSync5(
|
|
10765
10731
|
join8(dir, "src", "index.ts"),
|
|
10766
10732
|
`#!/usr/bin/env node
|
|
10767
10733
|
|
|
@@ -10803,7 +10769,7 @@ console.log('');
|
|
|
10803
10769
|
console.log('Press Ctrl+C to stop.');
|
|
10804
10770
|
`
|
|
10805
10771
|
);
|
|
10806
|
-
|
|
10772
|
+
writeFileSync5(
|
|
10807
10773
|
join8(dir, ".mcp.json"),
|
|
10808
10774
|
JSON.stringify(
|
|
10809
10775
|
{
|
|
@@ -10821,12 +10787,12 @@ console.log('Press Ctrl+C to stop.');
|
|
|
10821
10787
|
2
|
|
10822
10788
|
) + "\n"
|
|
10823
10789
|
);
|
|
10824
|
-
|
|
10790
|
+
writeFileSync5(
|
|
10825
10791
|
join8(dir, ".env"),
|
|
10826
10792
|
`SOLONGATE_API_KEY=sg_live_YOUR_KEY_HERE
|
|
10827
10793
|
`
|
|
10828
10794
|
);
|
|
10829
|
-
|
|
10795
|
+
writeFileSync5(
|
|
10830
10796
|
join8(dir, ".gitignore"),
|
|
10831
10797
|
`node_modules/
|
|
10832
10798
|
dist/
|
|
@@ -10846,7 +10812,7 @@ async function main3() {
|
|
|
10846
10812
|
process.exit(1);
|
|
10847
10813
|
}
|
|
10848
10814
|
withSpinner(`Setting up ${opts.name}...`, () => {
|
|
10849
|
-
|
|
10815
|
+
mkdirSync4(dir, { recursive: true });
|
|
10850
10816
|
createProject(dir, opts.name, opts.policy);
|
|
10851
10817
|
});
|
|
10852
10818
|
if (!opts.noInstall) {
|
|
@@ -10920,7 +10886,7 @@ var init_create = __esm({
|
|
|
10920
10886
|
|
|
10921
10887
|
// src/pull-push.ts
|
|
10922
10888
|
var pull_push_exports = {};
|
|
10923
|
-
import { readFileSync as readFileSync10, writeFileSync as
|
|
10889
|
+
import { readFileSync as readFileSync10, writeFileSync as writeFileSync6, existsSync as existsSync8 } from "fs";
|
|
10924
10890
|
import { resolve as resolve9 } from "path";
|
|
10925
10891
|
function loadEnv() {
|
|
10926
10892
|
if (process.env.SOLONGATE_API_KEY) return;
|
|
@@ -11115,7 +11081,7 @@ async function pull(apiKey, file, policyId) {
|
|
|
11115
11081
|
const policy = await fetchCloudPolicy(apiKey, API_URL, policyId);
|
|
11116
11082
|
const { id: _id, ...policyWithoutId } = policy;
|
|
11117
11083
|
const json = JSON.stringify(policyWithoutId, null, 2) + "\n";
|
|
11118
|
-
|
|
11084
|
+
writeFileSync6(file, json, "utf-8");
|
|
11119
11085
|
log5("");
|
|
11120
11086
|
log5(green2(" Saved to: ") + file);
|
|
11121
11087
|
log5(` ${dim2("Name:")} ${policy.name}`);
|
package/dist/tui/index.js
CHANGED
|
@@ -126,10 +126,9 @@ function KeyHints({ hints }) {
|
|
|
126
126
|
|
|
127
127
|
// src/tui/panels/Live.tsx
|
|
128
128
|
import { Box as Box2, Text as Text2, useInput } from "ink";
|
|
129
|
-
import {
|
|
130
|
-
import { closeSync, mkdirSync, openSync, readSync, statSync, writeFileSync } from "fs";
|
|
129
|
+
import { closeSync, openSync, readSync, statSync } from "fs";
|
|
131
130
|
import { homedir as homedir2 } from "os";
|
|
132
|
-
import {
|
|
131
|
+
import { join as join2 } from "path";
|
|
133
132
|
import { useCallback as useCallback2, useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
|
|
134
133
|
|
|
135
134
|
// src/api-client/client.ts
|
|
@@ -450,7 +449,6 @@ var BG = "#12234f";
|
|
|
450
449
|
var DIM_FLOOR = "#233457";
|
|
451
450
|
var LOCAL_LOG = join2(homedir2(), ".solongate", "local-logs", "solongate-audit.jsonl");
|
|
452
451
|
var RING = join2(process.cwd(), ".solongate", ".eval-ring.jsonl");
|
|
453
|
-
var DUMP = join2(homedir2(), ".solongate", "live-stream.log");
|
|
454
452
|
var STREAM_KEEP = 100;
|
|
455
453
|
var hhmmss = (ts) => {
|
|
456
454
|
const d = new Date(ts);
|
|
@@ -476,22 +474,6 @@ function tailLines(file, maxBytes = 131072) {
|
|
|
476
474
|
return [];
|
|
477
475
|
}
|
|
478
476
|
}
|
|
479
|
-
function copyToClipboard(text) {
|
|
480
|
-
const tools = [
|
|
481
|
-
["wl-copy", []],
|
|
482
|
-
["xclip", ["-selection", "clipboard"]],
|
|
483
|
-
["xsel", ["--clipboard", "--input"]]
|
|
484
|
-
];
|
|
485
|
-
for (const [cmd, args] of tools) {
|
|
486
|
-
try {
|
|
487
|
-
const r = spawnSync(cmd, args, { input: text, timeout: 2e3 });
|
|
488
|
-
if (r.status === 0) return cmd;
|
|
489
|
-
} catch {
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
process.stdout.write(`\x1B]52;c;${Buffer.from(text, "utf-8").toString("base64")}\x07`);
|
|
493
|
-
return null;
|
|
494
|
-
}
|
|
495
477
|
function cloudItem(e) {
|
|
496
478
|
return {
|
|
497
479
|
id: "c:" + e.id,
|
|
@@ -587,7 +569,6 @@ function LivePanel({ active: active2 }) {
|
|
|
587
569
|
const [log, setLog] = useState2([]);
|
|
588
570
|
const [filter, setFilter] = useState2("all");
|
|
589
571
|
const [scroll, setScroll] = useState2(0);
|
|
590
|
-
const [toast, setToast] = useState2(null);
|
|
591
572
|
const [mode, setMode] = useState2("stream");
|
|
592
573
|
const [pickIdx, setPickIdx] = useState2(0);
|
|
593
574
|
const [detail, setDetail] = useState2(null);
|
|
@@ -774,24 +755,24 @@ function LivePanel({ active: active2 }) {
|
|
|
774
755
|
const cloudDeduped = cloudBuf.filter((e) => !localKeys.has(`${e.tool}|${e.decision}|${Math.round(e.at / 6e4)}`));
|
|
775
756
|
const mergedAll = [...cloudDeduped, ...localBuf].sort((a, b) => a.at - b.at);
|
|
776
757
|
const points = tsData?.timeseries ?? [];
|
|
777
|
-
const
|
|
778
|
-
const
|
|
779
|
-
const
|
|
758
|
+
const nowSlot = Math.floor(nowMs / 1e4);
|
|
759
|
+
const slotCounts = new Array(60).fill(0);
|
|
760
|
+
const slotHot = new Array(60).fill(false);
|
|
780
761
|
for (const e of mergedAll) {
|
|
781
|
-
const idx = 59 - (
|
|
762
|
+
const idx = 59 - (nowSlot - Math.floor(e.at / 1e4));
|
|
782
763
|
if (idx >= 0 && idx < 60) {
|
|
783
|
-
|
|
784
|
-
if (e.decision !== "ALLOW")
|
|
764
|
+
slotCounts[idx]++;
|
|
765
|
+
if (e.decision !== "ALLOW") slotHot[idx] = true;
|
|
785
766
|
}
|
|
786
767
|
}
|
|
787
|
-
const localTraffic = localOn === true &&
|
|
788
|
-
const traffic = localTraffic ?
|
|
789
|
-
const trafficHot = localTraffic ?
|
|
790
|
-
const trafficLabel = localTraffic ? "calls/
|
|
768
|
+
const localTraffic = localOn === true && slotCounts.some((c2) => c2 > 0);
|
|
769
|
+
const traffic = localTraffic ? slotCounts : points.map((p) => p.total);
|
|
770
|
+
const trafficHot = localTraffic ? slotHot : points.map((p) => p.denied > 0);
|
|
771
|
+
const trafficLabel = localTraffic ? "calls/10s \xB7 last 10m" : "24h \xB7 cloud";
|
|
791
772
|
const rl = ins.layers?.rateLimit;
|
|
792
773
|
const dl = ins.layers?.dlp;
|
|
793
774
|
const gh = ins.layers?.ghost;
|
|
794
|
-
const minuteNow =
|
|
775
|
+
const minuteNow = mergedAll.filter((e) => nowMs - e.at < 6e4).length;
|
|
795
776
|
const dlpBars = (ins.dlpByPattern ?? []).slice(0, 2);
|
|
796
777
|
const maxDlpBar = dlpBars[0]?.count ?? 1;
|
|
797
778
|
const denialsAll = mergedAll.filter((e) => e.decision !== "ALLOW");
|
|
@@ -896,20 +877,6 @@ function LivePanel({ active: active2 }) {
|
|
|
896
877
|
else if (key.upArrow) setScroll((n) => Math.max(0, n - 1));
|
|
897
878
|
else if (key.pageDown) setScroll((n) => Math.min(maxScroll, n + streamRows));
|
|
898
879
|
else if (key.pageUp) setScroll((n) => Math.max(0, n - streamRows));
|
|
899
|
-
else if (input === "c") {
|
|
900
|
-
const dump = visibleDesc.map(
|
|
901
|
-
(e) => `[${new Date(e.at).toISOString()}] ${e.source.toUpperCase().padEnd(5)} ${e.decision.padEnd(6)} ${e.tool.padEnd(16)} ${e.permission.padEnd(5)} ${e.evalMs != null ? String(e.evalMs).padStart(5) + "ms " : " "}${(e.agent ?? "-").padEnd(14)} ${e.session ? e.session.slice(0, 8) : "- "} ${e.detail}`
|
|
902
|
-
).join("\n");
|
|
903
|
-
try {
|
|
904
|
-
mkdirSync(dirname(DUMP), { recursive: true });
|
|
905
|
-
writeFileSync(DUMP, dump + "\n");
|
|
906
|
-
} catch {
|
|
907
|
-
}
|
|
908
|
-
const via = copyToClipboard(dump);
|
|
909
|
-
setToast(
|
|
910
|
-
via ? { msg: `\u2713 ${visibleDesc.length} lines in clipboard (${via})`, until: Date.now() + 4e3 } : { msg: "\u2717 no clipboard tool \u2014 install wl-clipboard or xclip", until: Date.now() + 6e3 }
|
|
911
|
-
);
|
|
912
|
-
}
|
|
913
880
|
},
|
|
914
881
|
{ isActive: active2 }
|
|
915
882
|
);
|
|
@@ -924,8 +891,7 @@ function LivePanel({ active: active2 }) {
|
|
|
924
891
|
const titleBar = /* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
|
|
925
892
|
/* @__PURE__ */ jsx2(Text2, { backgroundColor: "#1432A0", color: "#AAC8FA", bold: true, children: " SOLONGATE LIVE " }),
|
|
926
893
|
/* @__PURE__ */ jsx2(Text2, { backgroundColor: BG, color: "#82AAF0", children: ` ${spin} up ${fmtUp(nowMs - startRef.current)} \xB7 ${hhmmss(nowMs)} \xB7 api ${latNow}ms ` }),
|
|
927
|
-
frozen ? /* @__PURE__ */ jsx2(Text2, { backgroundColor: "#123d1f", color: "#7bd88f", bold: true, children: " \u23F5 COPY MODE \u2014 screen frozen, select & copy freely \xB7 space resume " }) : backingOff ? /* @__PURE__ */ jsx2(Text2, { backgroundColor: "#3d2a12", color: "#ffb454", bold: true, children: " RATE LIMITED \xB7 backing off " }) : lastDeny ? /* @__PURE__ */ jsx2(Text2, { backgroundColor: "#3d1220", color: "#ff6b6b", bold: true, children: ` \u26A0 ${hhmmss(lastDeny.at)} ${lastDeny.tool} DENIED ` }) : /* @__PURE__ */ jsx2(Text2, { backgroundColor: BG, color: "#4f6db8", children: " \u2713 clean " })
|
|
928
|
-
toast && nowMs < toast.until ? /* @__PURE__ */ jsx2(Text2, { backgroundColor: "#123d1f", color: "#7bd88f", bold: true, children: ` ${toast.msg} ` }) : null
|
|
894
|
+
frozen ? /* @__PURE__ */ jsx2(Text2, { backgroundColor: "#123d1f", color: "#7bd88f", bold: true, children: " \u23F5 COPY MODE \u2014 screen frozen, select & copy freely \xB7 space resume " }) : backingOff ? /* @__PURE__ */ jsx2(Text2, { backgroundColor: "#3d2a12", color: "#ffb454", bold: true, children: " RATE LIMITED \xB7 backing off " }) : lastDeny ? /* @__PURE__ */ jsx2(Text2, { backgroundColor: "#3d1220", color: "#ff6b6b", bold: true, children: ` \u26A0 ${hhmmss(lastDeny.at)} ${lastDeny.tool} DENIED ` }) : /* @__PURE__ */ jsx2(Text2, { backgroundColor: BG, color: "#4f6db8", children: " \u2713 clean " })
|
|
929
895
|
] });
|
|
930
896
|
if (mode === "detail" && detail) {
|
|
931
897
|
const d = detailEntries;
|
|
@@ -1090,7 +1056,7 @@ function LivePanel({ active: active2 }) {
|
|
|
1090
1056
|
PaneTitle,
|
|
1091
1057
|
{
|
|
1092
1058
|
label: "TOOL STREAM",
|
|
1093
|
-
extra: `newest first \xB7 last ${STREAM_KEEP} \xB7 filter ${filter}${clampedScroll > 0 ? ` \xB7 \u25BC${clampedScroll} older` : ""} \xB7 f filter \xB7 \u2191\u2193 scroll \xB7
|
|
1059
|
+
extra: `newest first \xB7 last ${STREAM_KEEP} \xB7 filter ${filter}${clampedScroll > 0 ? ` \xB7 \u25BC${clampedScroll} older` : ""} \xB7 f filter \xB7 \u2191\u2193 scroll \xB7 s sessions`,
|
|
1094
1060
|
width: innerW
|
|
1095
1061
|
}
|
|
1096
1062
|
),
|
|
@@ -1108,7 +1074,7 @@ function LivePanel({ active: active2 }) {
|
|
|
1108
1074
|
/* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
|
|
1109
1075
|
/* @__PURE__ */ jsx2(Text2, { backgroundColor: BG, color: "#82AAF0", bold: true, children: " LIVE " }),
|
|
1110
1076
|
/* @__PURE__ */ jsx2(Text2, { backgroundColor: "#0b1530", color: "#4f6db8", children: ` local ${localOn ? "on" : "off"} \xB7 ${localBuf.length} loc/${cloudBuf.length} cld \xB7 top ${topTools.map(([t, c2]) => `${t}\xD7${c2}`).join(" ") || "\u2014"} ` }),
|
|
1111
|
-
/* @__PURE__ */ jsx2(Text2, { backgroundColor: BG, color: "#82AAF0", children: " space copy-mode \xB7 f filter \xB7 s sessions \xB7
|
|
1077
|
+
/* @__PURE__ */ jsx2(Text2, { backgroundColor: BG, color: "#82AAF0", children: " space copy-mode \xB7 f filter \xB7 s sessions \xB7 esc menu \xB7 q quit " })
|
|
1112
1078
|
] })
|
|
1113
1079
|
] });
|
|
1114
1080
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solongate/proxy",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.74.0",
|
|
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": {
|