@solongate/proxy 0.81.38 → 0.81.40
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/README.md +4 -10
- package/dist/index.js +33 -67
- package/dist/login.js +0 -1
- package/dist/tui/index.js +28 -14
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
> **Don't `npm i` this.** There's nothing to import. Run the two commands below to pair your machine:
|
|
4
4
|
> ```bash
|
|
5
|
-
>
|
|
6
|
-
>
|
|
5
|
+
> npm i -g @solongate/proxy
|
|
6
|
+
> solongate
|
|
7
7
|
> ```
|
|
8
8
|
|
|
9
9
|
**Security for AI agents.** SolonGate checks every action an AI agent takes. Each tool call (shell command, file read or write, network request) is allowed, blocked, or logged before it runs, based on a policy you control. No code changes.
|
|
@@ -24,8 +24,8 @@ SolonGate is fully managed. There is nothing to host: pair your machine with one
|
|
|
24
24
|
Pair the machine and turn on the guard. There are no API keys to copy. First fetch SolonGate, then log in:
|
|
25
25
|
|
|
26
26
|
```bash
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
npm i -g @solongate/proxy
|
|
28
|
+
solongate
|
|
29
29
|
```
|
|
30
30
|
|
|
31
31
|
This opens your browser to authorize the device. Approve it from your signed-in dashboard and SolonGate installs a global guard hook that intercepts every tool call from every AI session on the machine and checks it against your active policy.
|
|
@@ -60,12 +60,6 @@ Prefer to keep everything local? In **Settings**, turn on **Local log storage**
|
|
|
60
60
|
|
|
61
61
|
Set a threshold in **Settings** and SolonGate notifies you by Telegram, email, or webhook when blocks spike.
|
|
62
62
|
|
|
63
|
-
## Uninstall
|
|
64
|
-
|
|
65
|
-
```bash
|
|
66
|
-
npx @solongate/proxy logout
|
|
67
|
-
```
|
|
68
|
-
|
|
69
63
|
## Why SolonGate?
|
|
70
64
|
|
|
71
65
|
AI agents get direct access to your system: shell, file system, databases, network. SolonGate sits between the agent and the action, enforcing your policy on every tool call before it runs, and recording every decision for audit.
|
package/dist/index.js
CHANGED
|
@@ -271,7 +271,7 @@ function parseArgs(argv) {
|
|
|
271
271
|
}
|
|
272
272
|
if (!apiKey) {
|
|
273
273
|
throw new Error(
|
|
274
|
-
"Not logged in. Run this once to get started:\n\n
|
|
274
|
+
"Not logged in. Run this once to get started:\n\n solongate login\n"
|
|
275
275
|
);
|
|
276
276
|
}
|
|
277
277
|
if (!apiKey.startsWith("sg_live_") && !apiKey.startsWith("sg_test_")) {
|
|
@@ -327,7 +327,7 @@ function parseArgs(argv) {
|
|
|
327
327
|
}
|
|
328
328
|
if (upstreamArgs.length === 0) {
|
|
329
329
|
throw new Error(
|
|
330
|
-
"No upstream server command provided.\n\nIf you just want to get started, run:\n
|
|
330
|
+
"No upstream server command provided.\n\nIf you just want to get started, run:\n solongate login\n"
|
|
331
331
|
);
|
|
332
332
|
}
|
|
333
333
|
const [command, ...commandArgs] = upstreamArgs;
|
|
@@ -7815,9 +7815,12 @@ function LivePanel({ active: active2 }) {
|
|
|
7815
7815
|
const signalOk = (e) => signal === "none" ? true : signal === "deny" ? e.decision !== "ALLOW" : signal === "dlp" ? e.dlp : e.burst;
|
|
7816
7816
|
const filtered = (filter === "all" ? mergedAll : mergedAll.filter((e) => filter === "local" ? isLoc(e) : !isLoc(e))).filter(matches).filter(signalOk);
|
|
7817
7817
|
const visibleDesc = filtered.slice().reverse();
|
|
7818
|
+
const activeAlert = alerts.filter((a) => nowMs < a.until).slice(-1)[0];
|
|
7819
|
+
const activeAction = actionMsg && nowMs < actionMsg.until ? actionMsg : null;
|
|
7820
|
+
const bannerRows = (activeAlert ? 1 : 0) + (activeAction ? 1 : 0);
|
|
7818
7821
|
const chartH = rows >= 36 ? 6 : 4;
|
|
7819
7822
|
const colH = rows >= 32 ? 7 : 5;
|
|
7820
|
-
const streamRows = Math.max(4, rows - 5 - (1 + chartH) - colH);
|
|
7823
|
+
const streamRows = Math.max(4, rows - 5 - (1 + chartH) - colH - bannerRows);
|
|
7821
7824
|
const innerW = cols - 2;
|
|
7822
7825
|
const leftW = Math.floor(innerW * 0.55);
|
|
7823
7826
|
const rightW = innerW - leftW - 2;
|
|
@@ -8165,18 +8168,17 @@ function LivePanel({ active: active2 }) {
|
|
|
8165
8168
|
/* @__PURE__ */ jsx2(Text2, { color: guard.data?.up_to_date ? theme.ok : theme.warn, children: guard.data ? `v${guard.data.installed ?? "?"}${guard.data.up_to_date ? "" : "\u2192v" + guard.data.latest} ${guard.data.device_count}dev` : "\xB7" }),
|
|
8166
8169
|
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: " \u2502" })
|
|
8167
8170
|
] }),
|
|
8168
|
-
|
|
8171
|
+
activeAlert ? /* @__PURE__ */ jsx2(
|
|
8169
8172
|
Text2,
|
|
8170
8173
|
{
|
|
8171
8174
|
wrap: "truncate",
|
|
8172
|
-
backgroundColor:
|
|
8173
|
-
color:
|
|
8175
|
+
backgroundColor: activeAlert.level === "bad" ? "#3d1220" : "#3d2a12",
|
|
8176
|
+
color: activeAlert.level === "bad" ? "#ff6b6b" : "#ffb454",
|
|
8174
8177
|
bold: true,
|
|
8175
|
-
children: ` ${
|
|
8176
|
-
}
|
|
8177
|
-
|
|
8178
|
-
)),
|
|
8179
|
-
actionMsg && nowMs < actionMsg.until ? /* @__PURE__ */ jsx2(Text2, { wrap: "truncate", backgroundColor: actionMsg.level === "bad" ? "#3d1220" : "#123d1f", color: actionMsg.level === "bad" ? "#ff6b6b" : "#7bd88f", bold: true, children: ` ${truncate2(actionMsg.text, innerW - 4)} ` }) : null,
|
|
8178
|
+
children: ` ${activeAlert.level === "bad" ? "\u26D4 ALERT" : "\u23F8 IDLE"} \xB7 ${truncate2(activeAlert.msg, innerW - 14)} `
|
|
8179
|
+
}
|
|
8180
|
+
) : null,
|
|
8181
|
+
activeAction ? /* @__PURE__ */ jsx2(Text2, { wrap: "truncate", backgroundColor: activeAction.level === "bad" ? "#3d1220" : "#123d1f", color: activeAction.level === "bad" ? "#ff6b6b" : "#7bd88f", bold: true, children: ` ${truncate2(activeAction.text, innerW - 4)} ` }) : null,
|
|
8180
8182
|
/* @__PURE__ */ jsxs2(Box2, { height: 1 + chartH, children: [
|
|
8181
8183
|
/* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", width: leftW, marginRight: 2, children: [
|
|
8182
8184
|
/* @__PURE__ */ jsx2(PaneTitle, { label: "TRAFFIC", extra: `${trafficLabel} \xB7 peak ${Math.max(0, ...traffic)} \xB7 red = denials`, width: leftW }),
|
|
@@ -10034,6 +10036,8 @@ function App() {
|
|
|
10034
10036
|
if (accounts.length < 2) return;
|
|
10035
10037
|
viewAccount(accounts[(acctIdx + 1) % accounts.length]);
|
|
10036
10038
|
};
|
|
10039
|
+
const locked = accounts.length === 0;
|
|
10040
|
+
const effectiveSection = locked ? ACCOUNTS_SECTION : section;
|
|
10037
10041
|
useInput8((input, key) => {
|
|
10038
10042
|
if (help) {
|
|
10039
10043
|
setHelp(false);
|
|
@@ -10043,6 +10047,12 @@ function App() {
|
|
|
10043
10047
|
setHelp(true);
|
|
10044
10048
|
return;
|
|
10045
10049
|
}
|
|
10050
|
+
if (locked) {
|
|
10051
|
+
if (key.rightArrow || key.return || key.tab) setFocus("panel");
|
|
10052
|
+
else if (key.escape) setFocus("nav");
|
|
10053
|
+
else if (input === "q" && focus === "nav") exit();
|
|
10054
|
+
return;
|
|
10055
|
+
}
|
|
10046
10056
|
if (focus === "nav") {
|
|
10047
10057
|
if (key.upArrow) setSection((n) => (n - 1 + SECTIONS.length) % SECTIONS.length);
|
|
10048
10058
|
else if (key.downArrow) setSection((n) => (n + 1) % SECTIONS.length);
|
|
@@ -10055,7 +10065,7 @@ function App() {
|
|
|
10055
10065
|
}
|
|
10056
10066
|
});
|
|
10057
10067
|
const { cols, rows } = useTermSize();
|
|
10058
|
-
const current = SECTIONS[
|
|
10068
|
+
const current = SECTIONS[effectiveSection];
|
|
10059
10069
|
if (help) return /* @__PURE__ */ jsx9(HelpOverlay, { cols, rows });
|
|
10060
10070
|
if (current.label === "Live" && focus === "panel") {
|
|
10061
10071
|
return /* @__PURE__ */ jsx9(Box9, { flexDirection: "column", width: cols, height: rows, children: /* @__PURE__ */ jsx9(LivePanel, { active: true, focused: true }, viewNonce) });
|
|
@@ -10066,14 +10076,18 @@ function App() {
|
|
|
10066
10076
|
/* @__PURE__ */ jsx9(Banner, { cols }),
|
|
10067
10077
|
/* @__PURE__ */ jsxs9(Text9, { wrap: "truncate", children: [
|
|
10068
10078
|
/* @__PURE__ */ jsx9(Text9, { color: theme.dim, children: "account: " }),
|
|
10069
|
-
/* @__PURE__ */ jsx9(Text9, { color: theme.accentBright, bold: true, children: acctLabel }),
|
|
10070
|
-
accounts.length > 1 ? /* @__PURE__ */ jsx9(Text9, { color: theme.dim, children: ` (${acctIdx + 1}/${accounts.length} \xB7 a switch \xB7 Accounts to manage)` }) :
|
|
10079
|
+
/* @__PURE__ */ jsx9(Text9, { color: locked ? theme.warn : theme.accentBright, bold: true, children: acctLabel }),
|
|
10080
|
+
locked ? /* @__PURE__ */ jsx9(Text9, { color: theme.dim, children: " \xB7 log in from Accounts to unlock the dataroom" }) : accounts.length > 1 ? /* @__PURE__ */ jsx9(Text9, { color: theme.dim, children: ` (${acctIdx + 1}/${accounts.length} \xB7 a switch \xB7 Accounts to manage)` }) : /* @__PURE__ */ jsx9(Text9, { color: theme.dim, children: " \xB7 Accounts to add another" })
|
|
10071
10081
|
] }),
|
|
10072
10082
|
/* @__PURE__ */ jsxs9(Box9, { marginTop: 1, flexGrow: 1, children: [
|
|
10073
|
-
/* @__PURE__ */ jsx9(Box9, { flexDirection: "column", width: 16, borderStyle: "round", borderColor: focus === "nav" ? theme.accent : "gray", paddingX: 1, children: SECTIONS.map((s, i) =>
|
|
10083
|
+
/* @__PURE__ */ jsx9(Box9, { flexDirection: "column", width: 16, borderStyle: "round", borderColor: focus === "nav" ? theme.accent : "gray", paddingX: 1, children: SECTIONS.map((s, i) => {
|
|
10084
|
+
const isCur = i === effectiveSection;
|
|
10085
|
+
const disabled = locked && s.label !== "Accounts";
|
|
10086
|
+
return /* @__PURE__ */ jsx9(Text9, { color: isCur ? theme.accentBright : disabled ? theme.dim : void 0, bold: isCur, dimColor: disabled, children: (isCur ? "\u25B8 " : disabled ? "\u2298 " : " ") + s.label }, s.label);
|
|
10087
|
+
}) }),
|
|
10074
10088
|
/* @__PURE__ */ jsx9(Box9, { flexGrow: 1, borderStyle: "round", borderColor: focus === "panel" ? theme.accent : "gray", paddingX: 1, paddingY: 0, children: panelBody })
|
|
10075
10089
|
] }, viewNonce),
|
|
10076
|
-
/* @__PURE__ */ jsx9(Box9, { children: focus === "nav" ? /* @__PURE__ */ jsx9(KeyHints, { hints: [["\u2191\u2193", "section"], ["\u2192/enter", "open"], ...accounts.length > 1 ? [["a", "account"]] : [], ["?", "help"], ["q", "quit"]] }) : /* @__PURE__ */ jsx9(KeyHints, { hints: [["\u2190/esc", "back"], ["\u2191\u2193", "in-panel"], ["space/s", "act"]] }) })
|
|
10090
|
+
/* @__PURE__ */ jsx9(Box9, { children: locked ? /* @__PURE__ */ jsx9(KeyHints, { hints: [["\u2192/enter", "open Accounts"], ["n", "log in"], ["q", "quit"]] }) : focus === "nav" ? /* @__PURE__ */ jsx9(KeyHints, { hints: [["\u2191\u2193", "section"], ["\u2192/enter", "open"], ...accounts.length > 1 ? [["a", "account"]] : [], ["?", "help"], ["q", "quit"]] }) : /* @__PURE__ */ jsx9(KeyHints, { hints: [["\u2190/esc", "back"], ["\u2191\u2193", "in-panel"], ["space/s", "act"]] }) })
|
|
10077
10091
|
] });
|
|
10078
10092
|
}
|
|
10079
10093
|
function HelpOverlay({ cols, rows }) {
|
|
@@ -11312,17 +11326,6 @@ var init_commands = __esm({
|
|
|
11312
11326
|
});
|
|
11313
11327
|
|
|
11314
11328
|
// src/global-install.ts
|
|
11315
|
-
var global_install_exports = {};
|
|
11316
|
-
__export(global_install_exports, {
|
|
11317
|
-
globalPaths: () => globalPaths,
|
|
11318
|
-
installClaudeShim: () => installClaudeShim,
|
|
11319
|
-
installGlobalWithKey: () => installGlobalWithKey,
|
|
11320
|
-
lockProtected: () => lockProtected,
|
|
11321
|
-
removeClaudeShim: () => removeClaudeShim,
|
|
11322
|
-
runGlobalInstall: () => runGlobalInstall,
|
|
11323
|
-
runGlobalRestore: () => runGlobalRestore,
|
|
11324
|
-
unlockProtected: () => unlockProtected
|
|
11325
|
-
});
|
|
11326
11329
|
import { readFileSync as readFileSync8, writeFileSync as writeFileSync7, existsSync as existsSync6, mkdirSync as mkdirSync6 } from "fs";
|
|
11327
11330
|
import { resolve as resolve4, join as join11, dirname } from "path";
|
|
11328
11331
|
import { homedir as homedir9 } from "os";
|
|
@@ -11431,26 +11434,6 @@ function ask(question) {
|
|
|
11431
11434
|
res(a.trim());
|
|
11432
11435
|
}));
|
|
11433
11436
|
}
|
|
11434
|
-
function runGlobalRestore() {
|
|
11435
|
-
const p = globalPaths();
|
|
11436
|
-
unlockProtected();
|
|
11437
|
-
removeClaudeShim();
|
|
11438
|
-
if (existsSync6(p.backupPath)) {
|
|
11439
|
-
writeFileSync7(p.settingsPath, readFileSync8(p.backupPath, "utf-8"));
|
|
11440
|
-
console.log(` Restored ${p.settingsPath} from backup.`);
|
|
11441
|
-
} else if (existsSync6(p.settingsPath)) {
|
|
11442
|
-
try {
|
|
11443
|
-
const s = JSON.parse(readFileSync8(p.settingsPath, "utf-8"));
|
|
11444
|
-
delete s.hooks;
|
|
11445
|
-
writeFileSync7(p.settingsPath, JSON.stringify(s, null, 2) + "\n");
|
|
11446
|
-
console.log(` Removed SolonGate hooks from ${p.settingsPath}.`);
|
|
11447
|
-
} catch {
|
|
11448
|
-
}
|
|
11449
|
-
} else {
|
|
11450
|
-
console.log(" Nothing to restore \u2014 no global Claude Code settings found.");
|
|
11451
|
-
}
|
|
11452
|
-
console.log(" Global SolonGate enforcement uninstalled. Restart Claude Code.");
|
|
11453
|
-
}
|
|
11454
11437
|
function escapeRe(s) {
|
|
11455
11438
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
11456
11439
|
}
|
|
@@ -11512,14 +11495,6 @@ ${SHIM_END}`;
|
|
|
11512
11495
|
}
|
|
11513
11496
|
}
|
|
11514
11497
|
}
|
|
11515
|
-
function removeClaudeShim() {
|
|
11516
|
-
for (const file of shimTargets()) {
|
|
11517
|
-
try {
|
|
11518
|
-
writeShimBlock(file, null);
|
|
11519
|
-
} catch {
|
|
11520
|
-
}
|
|
11521
|
-
}
|
|
11522
|
-
}
|
|
11523
11498
|
async function runGlobalInstall(opts = {}) {
|
|
11524
11499
|
const p = globalPaths();
|
|
11525
11500
|
let apiKey = opts.apiKey || process.env["SOLONGATE_API_KEY"] || "";
|
|
@@ -11583,9 +11558,6 @@ async function runGlobalInstall(opts = {}) {
|
|
|
11583
11558
|
console.log(" Locked protection files (OS-level read-only/immutable).");
|
|
11584
11559
|
}
|
|
11585
11560
|
}
|
|
11586
|
-
async function installGlobalWithKey(apiKey, apiUrl) {
|
|
11587
|
-
await runGlobalInstall({ apiKey, apiUrl });
|
|
11588
|
-
}
|
|
11589
11561
|
var __dirname, HOOKS_DIR, SHIM_BEGIN, SHIM_END;
|
|
11590
11562
|
var init_global_install = __esm({
|
|
11591
11563
|
"src/global-install.ts"() {
|
|
@@ -11721,7 +11693,6 @@ async function main() {
|
|
|
11721
11693
|
console.log(" \u2502 Every Claude Code session on this machine is \u2502");
|
|
11722
11694
|
console.log(" \u2502 now guarded by your cloud policy (OPA WASM). \u2502");
|
|
11723
11695
|
console.log(" \u2502 \u2502");
|
|
11724
|
-
console.log(" \u2502 Undo: npx @solongate/proxy logout \u2502");
|
|
11725
11696
|
console.log(" \u2502 Manage policy: https://dashboard.solongate.com \u2502");
|
|
11726
11697
|
console.log(" \u2502 Restart Claude Code to apply. \u2502");
|
|
11727
11698
|
console.log(" \u2514\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\u2500\u2500\u2500\u2518");
|
|
@@ -16222,7 +16193,7 @@ ${msg.content.text}`;
|
|
|
16222
16193
|
|
|
16223
16194
|
// src/index.ts
|
|
16224
16195
|
init_cli_utils();
|
|
16225
|
-
var CLI_SUBCOMMANDS = /* @__PURE__ */ new Set(["login", "
|
|
16196
|
+
var CLI_SUBCOMMANDS = /* @__PURE__ */ new Set(["login", "shield", "create", "inject", "pull", "push", "list", "ls", "logs-server", "local-logs", "policy", "ratelimit", "dlp", "stats", "audit", "agents", "agent", "doctor", "watch", "keys", "mcp", "alerts", "webhooks", "dataroom"]);
|
|
16226
16197
|
var IS_HUMAN_CLI = process.argv.length <= 2 || CLI_SUBCOMMANDS.has(process.argv[2] ?? "");
|
|
16227
16198
|
if (!IS_HUMAN_CLI) {
|
|
16228
16199
|
console.log = (...args) => {
|
|
@@ -16244,14 +16215,14 @@ function printWelcome() {
|
|
|
16244
16215
|
console.log("");
|
|
16245
16216
|
console.log(" Get started with one command:");
|
|
16246
16217
|
console.log("");
|
|
16247
|
-
console.log(` ${c.cyan}
|
|
16218
|
+
console.log(` ${c.cyan}solongate login${c.reset}`);
|
|
16248
16219
|
console.log("");
|
|
16249
16220
|
console.log(` ${c.dim}This pairs your device and protects every Claude Code session${c.reset}`);
|
|
16250
16221
|
console.log(` ${c.dim}on this machine with your cloud policy. Manage it at${c.reset}`);
|
|
16251
16222
|
console.log(` ${c.cyan}https://dashboard.solongate.com${c.reset}`);
|
|
16252
16223
|
console.log("");
|
|
16253
16224
|
console.log(` ${c.dim}Using local log storage? Show it live in the dashboard with${c.reset}`);
|
|
16254
|
-
console.log(` ${c.cyan}
|
|
16225
|
+
console.log(` ${c.cyan}solongate logs-server${c.reset}`);
|
|
16255
16226
|
console.log("");
|
|
16256
16227
|
}
|
|
16257
16228
|
async function main5() {
|
|
@@ -16280,11 +16251,6 @@ async function main5() {
|
|
|
16280
16251
|
await Promise.resolve().then(() => (init_login(), login_exports));
|
|
16281
16252
|
return;
|
|
16282
16253
|
}
|
|
16283
|
-
if (subcommand === "logout") {
|
|
16284
|
-
const { runGlobalRestore: runGlobalRestore2 } = await Promise.resolve().then(() => (init_global_install(), global_install_exports));
|
|
16285
|
-
runGlobalRestore2();
|
|
16286
|
-
return;
|
|
16287
|
-
}
|
|
16288
16254
|
if (subcommand === "shield") {
|
|
16289
16255
|
const { runShield: runShield2 } = await Promise.resolve().then(() => (init_shield(), shield_exports));
|
|
16290
16256
|
await runShield2();
|
package/dist/login.js
CHANGED
|
@@ -410,7 +410,6 @@ async function main() {
|
|
|
410
410
|
console.log(" \u2502 Every Claude Code session on this machine is \u2502");
|
|
411
411
|
console.log(" \u2502 now guarded by your cloud policy (OPA WASM). \u2502");
|
|
412
412
|
console.log(" \u2502 \u2502");
|
|
413
|
-
console.log(" \u2502 Undo: npx @solongate/proxy logout \u2502");
|
|
414
413
|
console.log(" \u2502 Manage policy: https://dashboard.solongate.com \u2502");
|
|
415
414
|
console.log(" \u2502 Restart Claude Code to apply. \u2502");
|
|
416
415
|
console.log(" \u2514\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\u2500\u2500\u2500\u2518");
|
package/dist/tui/index.js
CHANGED
|
@@ -1248,9 +1248,12 @@ function LivePanel({ active: active2 }) {
|
|
|
1248
1248
|
const signalOk = (e) => signal === "none" ? true : signal === "deny" ? e.decision !== "ALLOW" : signal === "dlp" ? e.dlp : e.burst;
|
|
1249
1249
|
const filtered = (filter === "all" ? mergedAll : mergedAll.filter((e) => filter === "local" ? isLoc(e) : !isLoc(e))).filter(matches).filter(signalOk);
|
|
1250
1250
|
const visibleDesc = filtered.slice().reverse();
|
|
1251
|
+
const activeAlert = alerts.filter((a) => nowMs < a.until).slice(-1)[0];
|
|
1252
|
+
const activeAction = actionMsg && nowMs < actionMsg.until ? actionMsg : null;
|
|
1253
|
+
const bannerRows = (activeAlert ? 1 : 0) + (activeAction ? 1 : 0);
|
|
1251
1254
|
const chartH = rows >= 36 ? 6 : 4;
|
|
1252
1255
|
const colH = rows >= 32 ? 7 : 5;
|
|
1253
|
-
const streamRows = Math.max(4, rows - 5 - (1 + chartH) - colH);
|
|
1256
|
+
const streamRows = Math.max(4, rows - 5 - (1 + chartH) - colH - bannerRows);
|
|
1254
1257
|
const innerW = cols - 2;
|
|
1255
1258
|
const leftW = Math.floor(innerW * 0.55);
|
|
1256
1259
|
const rightW = innerW - leftW - 2;
|
|
@@ -1598,18 +1601,17 @@ function LivePanel({ active: active2 }) {
|
|
|
1598
1601
|
/* @__PURE__ */ jsx2(Text2, { color: guard.data?.up_to_date ? theme.ok : theme.warn, children: guard.data ? `v${guard.data.installed ?? "?"}${guard.data.up_to_date ? "" : "\u2192v" + guard.data.latest} ${guard.data.device_count}dev` : "\xB7" }),
|
|
1599
1602
|
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: " \u2502" })
|
|
1600
1603
|
] }),
|
|
1601
|
-
|
|
1604
|
+
activeAlert ? /* @__PURE__ */ jsx2(
|
|
1602
1605
|
Text2,
|
|
1603
1606
|
{
|
|
1604
1607
|
wrap: "truncate",
|
|
1605
|
-
backgroundColor:
|
|
1606
|
-
color:
|
|
1608
|
+
backgroundColor: activeAlert.level === "bad" ? "#3d1220" : "#3d2a12",
|
|
1609
|
+
color: activeAlert.level === "bad" ? "#ff6b6b" : "#ffb454",
|
|
1607
1610
|
bold: true,
|
|
1608
|
-
children: ` ${
|
|
1609
|
-
}
|
|
1610
|
-
|
|
1611
|
-
)),
|
|
1612
|
-
actionMsg && nowMs < actionMsg.until ? /* @__PURE__ */ jsx2(Text2, { wrap: "truncate", backgroundColor: actionMsg.level === "bad" ? "#3d1220" : "#123d1f", color: actionMsg.level === "bad" ? "#ff6b6b" : "#7bd88f", bold: true, children: ` ${truncate(actionMsg.text, innerW - 4)} ` }) : null,
|
|
1611
|
+
children: ` ${activeAlert.level === "bad" ? "\u26D4 ALERT" : "\u23F8 IDLE"} \xB7 ${truncate(activeAlert.msg, innerW - 14)} `
|
|
1612
|
+
}
|
|
1613
|
+
) : null,
|
|
1614
|
+
activeAction ? /* @__PURE__ */ jsx2(Text2, { wrap: "truncate", backgroundColor: activeAction.level === "bad" ? "#3d1220" : "#123d1f", color: activeAction.level === "bad" ? "#ff6b6b" : "#7bd88f", bold: true, children: ` ${truncate(activeAction.text, innerW - 4)} ` }) : null,
|
|
1613
1615
|
/* @__PURE__ */ jsxs2(Box2, { height: 1 + chartH, children: [
|
|
1614
1616
|
/* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", width: leftW, marginRight: 2, children: [
|
|
1615
1617
|
/* @__PURE__ */ jsx2(PaneTitle, { label: "TRAFFIC", extra: `${trafficLabel} \xB7 peak ${Math.max(0, ...traffic)} \xB7 red = denials`, width: leftW }),
|
|
@@ -3344,6 +3346,8 @@ function App() {
|
|
|
3344
3346
|
if (accounts.length < 2) return;
|
|
3345
3347
|
viewAccount(accounts[(acctIdx + 1) % accounts.length]);
|
|
3346
3348
|
};
|
|
3349
|
+
const locked = accounts.length === 0;
|
|
3350
|
+
const effectiveSection = locked ? ACCOUNTS_SECTION : section;
|
|
3347
3351
|
useInput8((input, key) => {
|
|
3348
3352
|
if (help) {
|
|
3349
3353
|
setHelp(false);
|
|
@@ -3353,6 +3357,12 @@ function App() {
|
|
|
3353
3357
|
setHelp(true);
|
|
3354
3358
|
return;
|
|
3355
3359
|
}
|
|
3360
|
+
if (locked) {
|
|
3361
|
+
if (key.rightArrow || key.return || key.tab) setFocus("panel");
|
|
3362
|
+
else if (key.escape) setFocus("nav");
|
|
3363
|
+
else if (input === "q" && focus === "nav") exit();
|
|
3364
|
+
return;
|
|
3365
|
+
}
|
|
3356
3366
|
if (focus === "nav") {
|
|
3357
3367
|
if (key.upArrow) setSection((n) => (n - 1 + SECTIONS.length) % SECTIONS.length);
|
|
3358
3368
|
else if (key.downArrow) setSection((n) => (n + 1) % SECTIONS.length);
|
|
@@ -3365,7 +3375,7 @@ function App() {
|
|
|
3365
3375
|
}
|
|
3366
3376
|
});
|
|
3367
3377
|
const { cols, rows } = useTermSize();
|
|
3368
|
-
const current = SECTIONS[
|
|
3378
|
+
const current = SECTIONS[effectiveSection];
|
|
3369
3379
|
if (help) return /* @__PURE__ */ jsx9(HelpOverlay, { cols, rows });
|
|
3370
3380
|
if (current.label === "Live" && focus === "panel") {
|
|
3371
3381
|
return /* @__PURE__ */ jsx9(Box9, { flexDirection: "column", width: cols, height: rows, children: /* @__PURE__ */ jsx9(LivePanel, { active: true, focused: true }, viewNonce) });
|
|
@@ -3376,14 +3386,18 @@ function App() {
|
|
|
3376
3386
|
/* @__PURE__ */ jsx9(Banner, { cols }),
|
|
3377
3387
|
/* @__PURE__ */ jsxs9(Text9, { wrap: "truncate", children: [
|
|
3378
3388
|
/* @__PURE__ */ jsx9(Text9, { color: theme.dim, children: "account: " }),
|
|
3379
|
-
/* @__PURE__ */ jsx9(Text9, { color: theme.accentBright, bold: true, children: acctLabel }),
|
|
3380
|
-
accounts.length > 1 ? /* @__PURE__ */ jsx9(Text9, { color: theme.dim, children: ` (${acctIdx + 1}/${accounts.length} \xB7 a switch \xB7 Accounts to manage)` }) :
|
|
3389
|
+
/* @__PURE__ */ jsx9(Text9, { color: locked ? theme.warn : theme.accentBright, bold: true, children: acctLabel }),
|
|
3390
|
+
locked ? /* @__PURE__ */ jsx9(Text9, { color: theme.dim, children: " \xB7 log in from Accounts to unlock the dataroom" }) : accounts.length > 1 ? /* @__PURE__ */ jsx9(Text9, { color: theme.dim, children: ` (${acctIdx + 1}/${accounts.length} \xB7 a switch \xB7 Accounts to manage)` }) : /* @__PURE__ */ jsx9(Text9, { color: theme.dim, children: " \xB7 Accounts to add another" })
|
|
3381
3391
|
] }),
|
|
3382
3392
|
/* @__PURE__ */ jsxs9(Box9, { marginTop: 1, flexGrow: 1, children: [
|
|
3383
|
-
/* @__PURE__ */ jsx9(Box9, { flexDirection: "column", width: 16, borderStyle: "round", borderColor: focus === "nav" ? theme.accent : "gray", paddingX: 1, children: SECTIONS.map((s, i) =>
|
|
3393
|
+
/* @__PURE__ */ jsx9(Box9, { flexDirection: "column", width: 16, borderStyle: "round", borderColor: focus === "nav" ? theme.accent : "gray", paddingX: 1, children: SECTIONS.map((s, i) => {
|
|
3394
|
+
const isCur = i === effectiveSection;
|
|
3395
|
+
const disabled = locked && s.label !== "Accounts";
|
|
3396
|
+
return /* @__PURE__ */ jsx9(Text9, { color: isCur ? theme.accentBright : disabled ? theme.dim : void 0, bold: isCur, dimColor: disabled, children: (isCur ? "\u25B8 " : disabled ? "\u2298 " : " ") + s.label }, s.label);
|
|
3397
|
+
}) }),
|
|
3384
3398
|
/* @__PURE__ */ jsx9(Box9, { flexGrow: 1, borderStyle: "round", borderColor: focus === "panel" ? theme.accent : "gray", paddingX: 1, paddingY: 0, children: panelBody })
|
|
3385
3399
|
] }, viewNonce),
|
|
3386
|
-
/* @__PURE__ */ jsx9(Box9, { children: focus === "nav" ? /* @__PURE__ */ jsx9(KeyHints, { hints: [["\u2191\u2193", "section"], ["\u2192/enter", "open"], ...accounts.length > 1 ? [["a", "account"]] : [], ["?", "help"], ["q", "quit"]] }) : /* @__PURE__ */ jsx9(KeyHints, { hints: [["\u2190/esc", "back"], ["\u2191\u2193", "in-panel"], ["space/s", "act"]] }) })
|
|
3400
|
+
/* @__PURE__ */ jsx9(Box9, { children: locked ? /* @__PURE__ */ jsx9(KeyHints, { hints: [["\u2192/enter", "open Accounts"], ["n", "log in"], ["q", "quit"]] }) : focus === "nav" ? /* @__PURE__ */ jsx9(KeyHints, { hints: [["\u2191\u2193", "section"], ["\u2192/enter", "open"], ...accounts.length > 1 ? [["a", "account"]] : [], ["?", "help"], ["q", "quit"]] }) : /* @__PURE__ */ jsx9(KeyHints, { hints: [["\u2190/esc", "back"], ["\u2191\u2193", "in-panel"], ["space/s", "act"]] }) })
|
|
3387
3401
|
] });
|
|
3388
3402
|
}
|
|
3389
3403
|
var HELP = [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solongate/proxy",
|
|
3
|
-
"version": "0.81.
|
|
3
|
+
"version": "0.81.40",
|
|
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": {
|