@solongate/proxy 0.82.34 → 0.82.36
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 +65 -30
- package/dist/tui/index.js +64 -29
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -8800,6 +8800,7 @@ var init_Live = __esm({
|
|
|
8800
8800
|
|
|
8801
8801
|
// src/tui/panels/DryRun.tsx
|
|
8802
8802
|
import { Box as Box3, Text as Text3, useInput as useInput2 } from "ink";
|
|
8803
|
+
import TextInput2 from "ink-text-input";
|
|
8803
8804
|
import { useEffect as useEffect3, useState as useState3 } from "react";
|
|
8804
8805
|
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
8805
8806
|
function requestDryRun(policyId) {
|
|
@@ -8809,21 +8810,24 @@ function DryRunPanel({ focused }) {
|
|
|
8809
8810
|
const list6 = useLoader(() => api.policies.list());
|
|
8810
8811
|
const policies = list6.data?.policies ?? [];
|
|
8811
8812
|
const [pi, setPi] = useState3(0);
|
|
8812
|
-
const [
|
|
8813
|
+
const [limit, setLimit] = useState3(DEFAULT_LIMIT);
|
|
8814
|
+
const [editLogs, setEditLogs] = useState3(null);
|
|
8815
|
+
const statsQ = useLoader(() => api.stats.get());
|
|
8816
|
+
const totalLogs = statsQ.data?.total_calls ?? null;
|
|
8813
8817
|
const [res, setRes] = useState3(null);
|
|
8814
8818
|
const [running, setRunning] = useState3(false);
|
|
8815
8819
|
const [err2, setErr] = useState3(null);
|
|
8816
8820
|
const [off, setOff] = useState3(0);
|
|
8817
8821
|
const { cols, rows } = usePanelSize();
|
|
8818
8822
|
const selected = policies[Math.min(pi, Math.max(0, policies.length - 1))];
|
|
8819
|
-
function run10(policyIdx = pi,
|
|
8823
|
+
function run10(policyIdx = pi, lim = limit) {
|
|
8820
8824
|
const p = policies[policyIdx];
|
|
8821
8825
|
if (!p) return;
|
|
8822
8826
|
setRunning(true);
|
|
8823
8827
|
setErr(null);
|
|
8824
8828
|
setRes(null);
|
|
8825
8829
|
setOff(0);
|
|
8826
|
-
api.policies.backtest({ rules: p.rules ?? [], mode: p.mode, limit:
|
|
8830
|
+
api.policies.backtest({ rules: p.rules ?? [], mode: p.mode, limit: lim }).then((r) => setRes(r)).catch((e) => setErr(e instanceof Error ? e.message : String(e))).finally(() => setRunning(false));
|
|
8827
8831
|
}
|
|
8828
8832
|
useEffect3(() => {
|
|
8829
8833
|
if (policies.length === 0 || res || running || err2) return;
|
|
@@ -8834,22 +8838,28 @@ function DryRunPanel({ focused }) {
|
|
|
8834
8838
|
pendingPolicyId = null;
|
|
8835
8839
|
}
|
|
8836
8840
|
setPi(idx);
|
|
8837
|
-
run10(idx,
|
|
8841
|
+
run10(idx, limit);
|
|
8838
8842
|
}, [policies.length]);
|
|
8839
8843
|
useInput2((input, key) => {
|
|
8840
|
-
if (!focused) return;
|
|
8844
|
+
if (!focused || editLogs !== null) return;
|
|
8841
8845
|
if (key.upArrow) setOff((n) => Math.max(0, n - 1));
|
|
8842
8846
|
else if (key.downArrow) setOff((n) => n + 1);
|
|
8843
|
-
else if (input === "p") {
|
|
8847
|
+
else if (input === "p" || input === "P") {
|
|
8844
8848
|
const n = policies.length ? (pi + 1) % policies.length : 0;
|
|
8845
8849
|
setPi(n);
|
|
8846
|
-
run10(n,
|
|
8847
|
-
} else if (input === "n") {
|
|
8848
|
-
|
|
8849
|
-
|
|
8850
|
-
run10(pi, n);
|
|
8851
|
-
} else if (input === "r") run10(pi, si);
|
|
8850
|
+
run10(n, limit);
|
|
8851
|
+
} else if (input === "n" || input === "N") {
|
|
8852
|
+
setEditLogs(String(limit));
|
|
8853
|
+
} else if (input === "r" || input === "R") run10(pi, limit);
|
|
8852
8854
|
});
|
|
8855
|
+
function commitLogs(raw) {
|
|
8856
|
+
const cap = Math.min(MAX_LIMIT, totalLogs && totalLogs > 0 ? totalLogs : MAX_LIMIT);
|
|
8857
|
+
const parsed = parseInt(raw.replace(/[^0-9]/g, ""), 10);
|
|
8858
|
+
const next = Number.isFinite(parsed) && parsed > 0 ? Math.min(parsed, cap) : limit;
|
|
8859
|
+
setEditLogs(null);
|
|
8860
|
+
setLimit(next);
|
|
8861
|
+
run10(pi, next);
|
|
8862
|
+
}
|
|
8853
8863
|
const w = Math.max(40, cols);
|
|
8854
8864
|
const lines = [];
|
|
8855
8865
|
const head = (t) => lines.push(/* @__PURE__ */ jsx3(Text3, { bold: true, color: theme.accentBright, children: t }, `h${lines.length}`));
|
|
@@ -8932,10 +8942,15 @@ function DryRunPanel({ focused }) {
|
|
|
8932
8942
|
/* @__PURE__ */ jsx3(Text3, { color: theme.accent, children: "\u2039 " + truncate2(selected?.name ?? "none", 30) + " \u203A" }),
|
|
8933
8943
|
/* @__PURE__ */ jsx3(Text3, { color: theme.dim, children: ` ${policies.length ? pi + 1 : 0}/${policies.length} press p \xB7 mode ${selected?.mode ?? "-"}` })
|
|
8934
8944
|
] }),
|
|
8935
|
-
/* @__PURE__ */ jsxs3(
|
|
8945
|
+
editLogs !== null ? /* @__PURE__ */ jsxs3(Box3, { children: [
|
|
8936
8946
|
/* @__PURE__ */ jsx3(Text3, { color: theme.dim, children: " logs " }),
|
|
8937
|
-
/* @__PURE__ */ jsx3(Text3, { color: theme.
|
|
8938
|
-
/* @__PURE__ */ jsx3(
|
|
8947
|
+
/* @__PURE__ */ jsx3(Text3, { color: theme.warn, children: "how many recent logs to replay: " }),
|
|
8948
|
+
/* @__PURE__ */ jsx3(TextInput2, { value: editLogs, onChange: setEditLogs, onSubmit: commitLogs }),
|
|
8949
|
+
/* @__PURE__ */ jsx3(Text3, { color: theme.dim, children: ` (max ${Math.min(MAX_LIMIT, totalLogs && totalLogs > 0 ? totalLogs : MAX_LIMIT)})` })
|
|
8950
|
+
] }) : /* @__PURE__ */ jsxs3(Text3, { wrap: "truncate", children: [
|
|
8951
|
+
/* @__PURE__ */ jsx3(Text3, { color: theme.dim, children: " logs " }),
|
|
8952
|
+
/* @__PURE__ */ jsx3(Text3, { color: theme.accent, children: "\u2039 " + String(limit) + " \u203A" }),
|
|
8953
|
+
/* @__PURE__ */ jsx3(Text3, { color: theme.dim, children: ` press n to type a number max ${Math.min(MAX_LIMIT, totalLogs && totalLogs > 0 ? totalLogs : MAX_LIMIT)}${res?.sampled != null ? ` replayed ${res.sampled}` : ""}` })
|
|
8939
8954
|
] }),
|
|
8940
8955
|
/* @__PURE__ */ jsx3(Text3, { color: theme.dim, wrap: "truncate", children: focused ? `\u2191\u2193 scroll \xB7 p policy \xB7 n logs \xB7 r re-run${above ? ` \xB7 \u25B2${above}` : ""}${below ? ` \xB7 \u25BC${below}` : ""}` : "press \u2192 to open" }),
|
|
8941
8956
|
running ? /* @__PURE__ */ jsx3(Text3, { color: theme.warn, children: "replaying recent traffic\u2026" }) : null,
|
|
@@ -8944,7 +8959,7 @@ function DryRunPanel({ focused }) {
|
|
|
8944
8959
|
/* @__PURE__ */ jsx3(Box3, { marginTop: 1, flexDirection: "column", children: win })
|
|
8945
8960
|
] }) });
|
|
8946
8961
|
}
|
|
8947
|
-
var
|
|
8962
|
+
var DEFAULT_LIMIT, MAX_LIMIT, pendingPolicyId, pct;
|
|
8948
8963
|
var init_DryRun = __esm({
|
|
8949
8964
|
"src/tui/panels/DryRun.tsx"() {
|
|
8950
8965
|
"use strict";
|
|
@@ -8952,7 +8967,8 @@ var init_DryRun = __esm({
|
|
|
8952
8967
|
init_components();
|
|
8953
8968
|
init_hooks();
|
|
8954
8969
|
init_theme();
|
|
8955
|
-
|
|
8970
|
+
DEFAULT_LIMIT = 1e3;
|
|
8971
|
+
MAX_LIMIT = 5e3;
|
|
8956
8972
|
pendingPolicyId = null;
|
|
8957
8973
|
pct = (n, d) => d ? (n / d * 100).toFixed(1) + "%" : "0%";
|
|
8958
8974
|
}
|
|
@@ -8985,7 +9001,7 @@ var init_nav = __esm({
|
|
|
8985
9001
|
|
|
8986
9002
|
// src/tui/panels/Policies.tsx
|
|
8987
9003
|
import { Box as Box4, Text as Text4, useInput as useInput3 } from "ink";
|
|
8988
|
-
import
|
|
9004
|
+
import TextInput3 from "ink-text-input";
|
|
8989
9005
|
import { useEffect as useEffect4, useState as useState4 } from "react";
|
|
8990
9006
|
import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
8991
9007
|
function ruleSummary(r) {
|
|
@@ -9048,7 +9064,7 @@ function PoliciesPanel({ focused }) {
|
|
|
9048
9064
|
});
|
|
9049
9065
|
setRules(res.rules);
|
|
9050
9066
|
setDirty(false);
|
|
9051
|
-
setStatus("\u2713 Saved
|
|
9067
|
+
setStatus("\u2713 Saved");
|
|
9052
9068
|
list6.reload();
|
|
9053
9069
|
} catch (e) {
|
|
9054
9070
|
setStatus("\u2717 " + (e instanceof Error ? e.message : String(e)));
|
|
@@ -9062,8 +9078,20 @@ function PoliciesPanel({ focused }) {
|
|
|
9062
9078
|
setDirty(false);
|
|
9063
9079
|
setStatus("discarded");
|
|
9064
9080
|
};
|
|
9081
|
+
const [creating, setCreating] = useState4(null);
|
|
9082
|
+
function commitNewPolicy(name) {
|
|
9083
|
+
const n = name.trim();
|
|
9084
|
+
setCreating(null);
|
|
9085
|
+
if (!n) return;
|
|
9086
|
+
setStatus("Creating\u2026");
|
|
9087
|
+
void api.policies.create({ id: `policy-${Date.now()}`, name: n, rules: [], mode: "denylist" }).then(() => {
|
|
9088
|
+
setStatus(`\u2713 created "${n}" - open it and press n to add rules`);
|
|
9089
|
+
list6.reload();
|
|
9090
|
+
}).catch((e) => setStatus("\u2717 " + (e instanceof Error ? e.message : String(e))));
|
|
9091
|
+
}
|
|
9065
9092
|
useInput3(
|
|
9066
9093
|
(input, key) => {
|
|
9094
|
+
if (creating !== null) return;
|
|
9067
9095
|
if (key.ctrl && input === "r" && !editing) {
|
|
9068
9096
|
list6.reload();
|
|
9069
9097
|
activeQ.reload();
|
|
@@ -9085,6 +9113,9 @@ function PoliciesPanel({ focused }) {
|
|
|
9085
9113
|
activeQ.reload();
|
|
9086
9114
|
}).catch((e) => setStatus("\u2717 " + (e instanceof Error ? e.message : String(e))));
|
|
9087
9115
|
}
|
|
9116
|
+
} else if (input === "n" || input === "N") {
|
|
9117
|
+
setStatus(null);
|
|
9118
|
+
setCreating("");
|
|
9088
9119
|
} else if (input === "x") {
|
|
9089
9120
|
setStatus("Deactivating\u2026");
|
|
9090
9121
|
void api.policies.setActive(null).then(() => {
|
|
@@ -9152,7 +9183,7 @@ function PoliciesPanel({ focused }) {
|
|
|
9152
9183
|
);
|
|
9153
9184
|
if (view === "list") {
|
|
9154
9185
|
const activeName = activeId ? policies.find((p) => p.id === activeId)?.name ?? activeId : null;
|
|
9155
|
-
const lHead = 3 + (status ? 1 : 0);
|
|
9186
|
+
const lHead = 3 + (status ? 1 : 0) + (creating !== null ? 1 : 0);
|
|
9156
9187
|
const lBudget = Math.max(3, panelRows - lHead);
|
|
9157
9188
|
const lStart = Math.min(Math.max(0, pi - Math.floor(lBudget / 2)), Math.max(0, policies.length - lBudget));
|
|
9158
9189
|
const lWin = policies.slice(lStart, lStart + lBudget);
|
|
@@ -9169,7 +9200,11 @@ function PoliciesPanel({ focused }) {
|
|
|
9169
9200
|
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: activeBy ? ` (${activeBy})` : "" })
|
|
9170
9201
|
] }) : /* @__PURE__ */ jsx4(Text4, { color: theme.bad, bold: true, children: "\u25CB NONE \u2014 nothing enforced, grants refused" })
|
|
9171
9202
|
] }),
|
|
9172
|
-
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, wrap: "truncate", children: focused ? `\u2191\u2193 select \xB7 enter open \xB7 a activate \xB7 x deactivate \xB7 ^R refresh${lAbove ? ` \xB7 \u25B2${lAbove}` : ""}${lBelow ? ` \xB7 \u25BC${lBelow}` : ""}` : "press \u2192 to browse" }),
|
|
9203
|
+
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, wrap: "truncate", children: focused ? `\u2191\u2193 select \xB7 enter open \xB7 n new policy \xB7 a activate \xB7 x deactivate \xB7 ^R refresh${lAbove ? ` \xB7 \u25B2${lAbove}` : ""}${lBelow ? ` \xB7 \u25BC${lBelow}` : ""}` : "press \u2192 to browse" }),
|
|
9204
|
+
creating !== null ? /* @__PURE__ */ jsxs4(Box4, { children: [
|
|
9205
|
+
/* @__PURE__ */ jsx4(Text4, { color: theme.warn, children: "new policy name: " }),
|
|
9206
|
+
/* @__PURE__ */ jsx4(TextInput3, { value: creating, onChange: setCreating, onSubmit: commitNewPolicy })
|
|
9207
|
+
] }) : null,
|
|
9173
9208
|
/* @__PURE__ */ jsx4(Box4, { marginTop: 1, flexDirection: "column", children: lWin.map((p, wi) => {
|
|
9174
9209
|
const i = lStart + wi;
|
|
9175
9210
|
return /* @__PURE__ */ jsxs4(Text4, { color: i === pi ? theme.accentBright : void 0, bold: i === pi, children: [
|
|
@@ -9249,7 +9284,7 @@ function PoliciesPanel({ focused }) {
|
|
|
9249
9284
|
return /* @__PURE__ */ jsxs4(Box4, { children: [
|
|
9250
9285
|
/* @__PURE__ */ jsx4(Text4, { color: active2 ? theme.accentBright : void 0, children: (active2 ? "\u25B8 " : " ") + f.label.padEnd(13) }),
|
|
9251
9286
|
active2 && editing && f.kind === "text" ? /* @__PURE__ */ jsx4(
|
|
9252
|
-
|
|
9287
|
+
TextInput3,
|
|
9253
9288
|
{
|
|
9254
9289
|
value: editVal,
|
|
9255
9290
|
onChange: setEditVal,
|
|
@@ -9487,7 +9522,7 @@ var init_RateLimit = __esm({
|
|
|
9487
9522
|
|
|
9488
9523
|
// src/tui/panels/Dlp.tsx
|
|
9489
9524
|
import { Box as Box6, Text as Text6, useInput as useInput5 } from "ink";
|
|
9490
|
-
import
|
|
9525
|
+
import TextInput4 from "ink-text-input";
|
|
9491
9526
|
import { useEffect as useEffect6, useState as useState6 } from "react";
|
|
9492
9527
|
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
9493
9528
|
function DlpPanel({ focused }) {
|
|
@@ -9667,7 +9702,7 @@ function DlpPanel({ focused }) {
|
|
|
9667
9702
|
adding ? /* @__PURE__ */ jsx6(Box6, { flexDirection: "column", children: /* @__PURE__ */ jsxs6(Box6, { children: [
|
|
9668
9703
|
/* @__PURE__ */ jsx6(Text6, { color: theme.warn, children: adding === "name" ? "new pattern name: " : adding === "re" ? `pattern for "${newName}" (glob, * = any chars, e.g. sk-* AKIA*): ` : "ghost path to hide (glob, * = any chars, e.g. */.env *.pem): " }),
|
|
9669
9704
|
/* @__PURE__ */ jsx6(
|
|
9670
|
-
|
|
9705
|
+
TextInput4,
|
|
9671
9706
|
{
|
|
9672
9707
|
value: input,
|
|
9673
9708
|
onChange: setInput,
|
|
@@ -9711,7 +9746,7 @@ var init_Dlp = __esm({
|
|
|
9711
9746
|
|
|
9712
9747
|
// src/tui/panels/Audit.tsx
|
|
9713
9748
|
import { Box as Box7, Text as Text7, useInput as useInput6 } from "ink";
|
|
9714
|
-
import
|
|
9749
|
+
import TextInput5 from "ink-text-input";
|
|
9715
9750
|
import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync8 } from "fs";
|
|
9716
9751
|
import { homedir as homedir8 } from "os";
|
|
9717
9752
|
import { join as join10 } from "path";
|
|
@@ -10150,7 +10185,7 @@ function AuditPanel({ active: active2, focused }) {
|
|
|
10150
10185
|
editing === "sess-search" ? /* @__PURE__ */ jsxs7(Box7, { children: [
|
|
10151
10186
|
/* @__PURE__ */ jsx7(Text7, { color: theme.warn, children: "search: " }),
|
|
10152
10187
|
/* @__PURE__ */ jsx7(
|
|
10153
|
-
|
|
10188
|
+
TextInput5,
|
|
10154
10189
|
{
|
|
10155
10190
|
value: sessSearch,
|
|
10156
10191
|
onChange: (v) => {
|
|
@@ -10228,7 +10263,7 @@ function AuditPanel({ active: active2, focused }) {
|
|
|
10228
10263
|
": "
|
|
10229
10264
|
] }),
|
|
10230
10265
|
/* @__PURE__ */ jsx7(
|
|
10231
|
-
|
|
10266
|
+
TextInput5,
|
|
10232
10267
|
{
|
|
10233
10268
|
value: editing === "tool" ? tool : editing === "agent" ? agent : search,
|
|
10234
10269
|
onChange: (v) => {
|
|
@@ -10652,7 +10687,7 @@ var init_global_install = __esm({
|
|
|
10652
10687
|
|
|
10653
10688
|
// src/tui/panels/Settings.tsx
|
|
10654
10689
|
import { Box as Box8, Text as Text8, useInput as useInput7 } from "ink";
|
|
10655
|
-
import
|
|
10690
|
+
import TextInput6 from "ink-text-input";
|
|
10656
10691
|
import { useEffect as useEffect7, useRef as useRef3, useState as useState8 } from "react";
|
|
10657
10692
|
import { Fragment as Fragment5, jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
10658
10693
|
function SettingsPanel({
|
|
@@ -11076,7 +11111,7 @@ function SettingsPanel({
|
|
|
11076
11111
|
/* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: "\u2191\u2193 field \xB7 \u2190\u2192 change \xB7 e edit target \xB7 enter save \xB7 esc cancel" }),
|
|
11077
11112
|
editing === "alert-target" ? /* @__PURE__ */ jsxs8(Box8, { marginTop: 1, children: [
|
|
11078
11113
|
/* @__PURE__ */ jsx8(Text8, { color: theme.warn, children: editor.channel === "email" ? "e-mail address: " : "telegram chat id (from @userinfobot): " }),
|
|
11079
|
-
/* @__PURE__ */ jsx8(
|
|
11114
|
+
/* @__PURE__ */ jsx8(TextInput6, { value: input, onChange: setInput, onSubmit: submitInput })
|
|
11080
11115
|
] }) : msg ? /* @__PURE__ */ jsx8(Text8, { color: msg.level === "bad" ? theme.bad : theme.ok, children: truncate2(msg.text, cols) }) : /* @__PURE__ */ jsx8(Text8, { children: " " }),
|
|
11081
11116
|
/* @__PURE__ */ jsxs8(Box8, { marginTop: 1, flexDirection: "column", children: [
|
|
11082
11117
|
fieldRow(0, "target", editor.target ? /* @__PURE__ */ jsx8(Text8, { color: theme.accent, children: truncate2(editor.target, cols - 16) }) : /* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: "empty \u2014 press e" }), "press e to edit"),
|
|
@@ -11256,7 +11291,7 @@ function SettingsPanel({
|
|
|
11256
11291
|
/* @__PURE__ */ jsx8(Text8, { wrap: "truncate", color: theme.dim, children: focused ? `\u2191\u2193 move \xB7 enter act \xB7 m toggle \xB7 t test \xB7 e edit \xB7 x remove \xB7 d delete \xB7 n add${moreAbove ? ` \xB7 \u25B2${moreAbove}` : ""}${moreBelow ? ` \xB7 \u25BC${moreBelow}` : ""}` : "press \u2192 to configure" }),
|
|
11257
11292
|
editing ? /* @__PURE__ */ jsxs8(Box8, { children: [
|
|
11258
11293
|
/* @__PURE__ */ jsx8(Text8, { color: theme.warn, children: editing === "path" ? "local log path: " : "webhook url: " }),
|
|
11259
|
-
/* @__PURE__ */ jsx8(
|
|
11294
|
+
/* @__PURE__ */ jsx8(TextInput6, { value: input, onChange: setInput, onSubmit: submitInput })
|
|
11260
11295
|
] }) : msg ? /* @__PURE__ */ jsx8(Text8, { wrap: "truncate", color: msg.level === "bad" ? theme.bad : theme.ok, children: truncate2(msg.text, cols) }) : login?.msg ? /* @__PURE__ */ jsx8(Text8, { wrap: "truncate", color: login.phase === "error" ? theme.bad : theme.ok, children: login.msg }) : /* @__PURE__ */ jsx8(Text8, { children: " " }),
|
|
11261
11296
|
/* @__PURE__ */ jsx8(Box8, { flexDirection: "column", height: budget, overflow: "hidden", children: win })
|
|
11262
11297
|
] }) });
|
package/dist/tui/index.js
CHANGED
|
@@ -1904,14 +1904,16 @@ function LivePanel({ active: active2 }) {
|
|
|
1904
1904
|
|
|
1905
1905
|
// src/tui/panels/Policies.tsx
|
|
1906
1906
|
import { Box as Box4, Text as Text4, useInput as useInput3 } from "ink";
|
|
1907
|
-
import
|
|
1907
|
+
import TextInput3 from "ink-text-input";
|
|
1908
1908
|
import { useEffect as useEffect4, useState as useState4 } from "react";
|
|
1909
1909
|
|
|
1910
1910
|
// src/tui/panels/DryRun.tsx
|
|
1911
1911
|
import { Box as Box3, Text as Text3, useInput as useInput2 } from "ink";
|
|
1912
|
+
import TextInput2 from "ink-text-input";
|
|
1912
1913
|
import { useEffect as useEffect3, useState as useState3 } from "react";
|
|
1913
1914
|
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1914
|
-
var
|
|
1915
|
+
var DEFAULT_LIMIT = 1e3;
|
|
1916
|
+
var MAX_LIMIT = 5e3;
|
|
1915
1917
|
var pendingPolicyId = null;
|
|
1916
1918
|
function requestDryRun(policyId) {
|
|
1917
1919
|
pendingPolicyId = policyId;
|
|
@@ -1921,21 +1923,24 @@ function DryRunPanel({ focused }) {
|
|
|
1921
1923
|
const list5 = useLoader(() => api.policies.list());
|
|
1922
1924
|
const policies = list5.data?.policies ?? [];
|
|
1923
1925
|
const [pi, setPi] = useState3(0);
|
|
1924
|
-
const [
|
|
1926
|
+
const [limit, setLimit] = useState3(DEFAULT_LIMIT);
|
|
1927
|
+
const [editLogs, setEditLogs] = useState3(null);
|
|
1928
|
+
const statsQ = useLoader(() => api.stats.get());
|
|
1929
|
+
const totalLogs = statsQ.data?.total_calls ?? null;
|
|
1925
1930
|
const [res, setRes] = useState3(null);
|
|
1926
1931
|
const [running, setRunning] = useState3(false);
|
|
1927
1932
|
const [err, setErr] = useState3(null);
|
|
1928
1933
|
const [off, setOff] = useState3(0);
|
|
1929
1934
|
const { cols, rows } = usePanelSize();
|
|
1930
1935
|
const selected = policies[Math.min(pi, Math.max(0, policies.length - 1))];
|
|
1931
|
-
function run(policyIdx = pi,
|
|
1936
|
+
function run(policyIdx = pi, lim = limit) {
|
|
1932
1937
|
const p = policies[policyIdx];
|
|
1933
1938
|
if (!p) return;
|
|
1934
1939
|
setRunning(true);
|
|
1935
1940
|
setErr(null);
|
|
1936
1941
|
setRes(null);
|
|
1937
1942
|
setOff(0);
|
|
1938
|
-
api.policies.backtest({ rules: p.rules ?? [], mode: p.mode, limit:
|
|
1943
|
+
api.policies.backtest({ rules: p.rules ?? [], mode: p.mode, limit: lim }).then((r) => setRes(r)).catch((e) => setErr(e instanceof Error ? e.message : String(e))).finally(() => setRunning(false));
|
|
1939
1944
|
}
|
|
1940
1945
|
useEffect3(() => {
|
|
1941
1946
|
if (policies.length === 0 || res || running || err) return;
|
|
@@ -1946,22 +1951,28 @@ function DryRunPanel({ focused }) {
|
|
|
1946
1951
|
pendingPolicyId = null;
|
|
1947
1952
|
}
|
|
1948
1953
|
setPi(idx);
|
|
1949
|
-
run(idx,
|
|
1954
|
+
run(idx, limit);
|
|
1950
1955
|
}, [policies.length]);
|
|
1951
1956
|
useInput2((input, key) => {
|
|
1952
|
-
if (!focused) return;
|
|
1957
|
+
if (!focused || editLogs !== null) return;
|
|
1953
1958
|
if (key.upArrow) setOff((n) => Math.max(0, n - 1));
|
|
1954
1959
|
else if (key.downArrow) setOff((n) => n + 1);
|
|
1955
|
-
else if (input === "p") {
|
|
1960
|
+
else if (input === "p" || input === "P") {
|
|
1956
1961
|
const n = policies.length ? (pi + 1) % policies.length : 0;
|
|
1957
1962
|
setPi(n);
|
|
1958
|
-
run(n,
|
|
1959
|
-
} else if (input === "n") {
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
run(pi, n);
|
|
1963
|
-
} else if (input === "r") run(pi, si);
|
|
1963
|
+
run(n, limit);
|
|
1964
|
+
} else if (input === "n" || input === "N") {
|
|
1965
|
+
setEditLogs(String(limit));
|
|
1966
|
+
} else if (input === "r" || input === "R") run(pi, limit);
|
|
1964
1967
|
});
|
|
1968
|
+
function commitLogs(raw) {
|
|
1969
|
+
const cap = Math.min(MAX_LIMIT, totalLogs && totalLogs > 0 ? totalLogs : MAX_LIMIT);
|
|
1970
|
+
const parsed = parseInt(raw.replace(/[^0-9]/g, ""), 10);
|
|
1971
|
+
const next = Number.isFinite(parsed) && parsed > 0 ? Math.min(parsed, cap) : limit;
|
|
1972
|
+
setEditLogs(null);
|
|
1973
|
+
setLimit(next);
|
|
1974
|
+
run(pi, next);
|
|
1975
|
+
}
|
|
1965
1976
|
const w = Math.max(40, cols);
|
|
1966
1977
|
const lines = [];
|
|
1967
1978
|
const head = (t) => lines.push(/* @__PURE__ */ jsx3(Text3, { bold: true, color: theme.accentBright, children: t }, `h${lines.length}`));
|
|
@@ -2044,10 +2055,15 @@ function DryRunPanel({ focused }) {
|
|
|
2044
2055
|
/* @__PURE__ */ jsx3(Text3, { color: theme.accent, children: "\u2039 " + truncate(selected?.name ?? "none", 30) + " \u203A" }),
|
|
2045
2056
|
/* @__PURE__ */ jsx3(Text3, { color: theme.dim, children: ` ${policies.length ? pi + 1 : 0}/${policies.length} press p \xB7 mode ${selected?.mode ?? "-"}` })
|
|
2046
2057
|
] }),
|
|
2047
|
-
/* @__PURE__ */ jsxs3(
|
|
2058
|
+
editLogs !== null ? /* @__PURE__ */ jsxs3(Box3, { children: [
|
|
2048
2059
|
/* @__PURE__ */ jsx3(Text3, { color: theme.dim, children: " logs " }),
|
|
2049
|
-
/* @__PURE__ */ jsx3(Text3, { color: theme.
|
|
2050
|
-
/* @__PURE__ */ jsx3(
|
|
2060
|
+
/* @__PURE__ */ jsx3(Text3, { color: theme.warn, children: "how many recent logs to replay: " }),
|
|
2061
|
+
/* @__PURE__ */ jsx3(TextInput2, { value: editLogs, onChange: setEditLogs, onSubmit: commitLogs }),
|
|
2062
|
+
/* @__PURE__ */ jsx3(Text3, { color: theme.dim, children: ` (max ${Math.min(MAX_LIMIT, totalLogs && totalLogs > 0 ? totalLogs : MAX_LIMIT)})` })
|
|
2063
|
+
] }) : /* @__PURE__ */ jsxs3(Text3, { wrap: "truncate", children: [
|
|
2064
|
+
/* @__PURE__ */ jsx3(Text3, { color: theme.dim, children: " logs " }),
|
|
2065
|
+
/* @__PURE__ */ jsx3(Text3, { color: theme.accent, children: "\u2039 " + String(limit) + " \u203A" }),
|
|
2066
|
+
/* @__PURE__ */ jsx3(Text3, { color: theme.dim, children: ` press n to type a number max ${Math.min(MAX_LIMIT, totalLogs && totalLogs > 0 ? totalLogs : MAX_LIMIT)}${res?.sampled != null ? ` replayed ${res.sampled}` : ""}` })
|
|
2051
2067
|
] }),
|
|
2052
2068
|
/* @__PURE__ */ jsx3(Text3, { color: theme.dim, wrap: "truncate", children: focused ? `\u2191\u2193 scroll \xB7 p policy \xB7 n logs \xB7 r re-run${above ? ` \xB7 \u25B2${above}` : ""}${below ? ` \xB7 \u25BC${below}` : ""}` : "press \u2192 to open" }),
|
|
2053
2069
|
running ? /* @__PURE__ */ jsx3(Text3, { color: theme.warn, children: "replaying recent traffic\u2026" }) : null,
|
|
@@ -2159,7 +2175,7 @@ function PoliciesPanel({ focused }) {
|
|
|
2159
2175
|
});
|
|
2160
2176
|
setRules(res.rules);
|
|
2161
2177
|
setDirty(false);
|
|
2162
|
-
setStatus("\u2713 Saved
|
|
2178
|
+
setStatus("\u2713 Saved");
|
|
2163
2179
|
list5.reload();
|
|
2164
2180
|
} catch (e) {
|
|
2165
2181
|
setStatus("\u2717 " + (e instanceof Error ? e.message : String(e)));
|
|
@@ -2173,8 +2189,20 @@ function PoliciesPanel({ focused }) {
|
|
|
2173
2189
|
setDirty(false);
|
|
2174
2190
|
setStatus("discarded");
|
|
2175
2191
|
};
|
|
2192
|
+
const [creating, setCreating] = useState4(null);
|
|
2193
|
+
function commitNewPolicy(name) {
|
|
2194
|
+
const n = name.trim();
|
|
2195
|
+
setCreating(null);
|
|
2196
|
+
if (!n) return;
|
|
2197
|
+
setStatus("Creating\u2026");
|
|
2198
|
+
void api.policies.create({ id: `policy-${Date.now()}`, name: n, rules: [], mode: "denylist" }).then(() => {
|
|
2199
|
+
setStatus(`\u2713 created "${n}" - open it and press n to add rules`);
|
|
2200
|
+
list5.reload();
|
|
2201
|
+
}).catch((e) => setStatus("\u2717 " + (e instanceof Error ? e.message : String(e))));
|
|
2202
|
+
}
|
|
2176
2203
|
useInput3(
|
|
2177
2204
|
(input, key) => {
|
|
2205
|
+
if (creating !== null) return;
|
|
2178
2206
|
if (key.ctrl && input === "r" && !editing) {
|
|
2179
2207
|
list5.reload();
|
|
2180
2208
|
activeQ.reload();
|
|
@@ -2196,6 +2224,9 @@ function PoliciesPanel({ focused }) {
|
|
|
2196
2224
|
activeQ.reload();
|
|
2197
2225
|
}).catch((e) => setStatus("\u2717 " + (e instanceof Error ? e.message : String(e))));
|
|
2198
2226
|
}
|
|
2227
|
+
} else if (input === "n" || input === "N") {
|
|
2228
|
+
setStatus(null);
|
|
2229
|
+
setCreating("");
|
|
2199
2230
|
} else if (input === "x") {
|
|
2200
2231
|
setStatus("Deactivating\u2026");
|
|
2201
2232
|
void api.policies.setActive(null).then(() => {
|
|
@@ -2263,7 +2294,7 @@ function PoliciesPanel({ focused }) {
|
|
|
2263
2294
|
);
|
|
2264
2295
|
if (view === "list") {
|
|
2265
2296
|
const activeName = activeId ? policies.find((p) => p.id === activeId)?.name ?? activeId : null;
|
|
2266
|
-
const lHead = 3 + (status ? 1 : 0);
|
|
2297
|
+
const lHead = 3 + (status ? 1 : 0) + (creating !== null ? 1 : 0);
|
|
2267
2298
|
const lBudget = Math.max(3, panelRows - lHead);
|
|
2268
2299
|
const lStart = Math.min(Math.max(0, pi - Math.floor(lBudget / 2)), Math.max(0, policies.length - lBudget));
|
|
2269
2300
|
const lWin = policies.slice(lStart, lStart + lBudget);
|
|
@@ -2280,7 +2311,11 @@ function PoliciesPanel({ focused }) {
|
|
|
2280
2311
|
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: activeBy ? ` (${activeBy})` : "" })
|
|
2281
2312
|
] }) : /* @__PURE__ */ jsx4(Text4, { color: theme.bad, bold: true, children: "\u25CB NONE \u2014 nothing enforced, grants refused" })
|
|
2282
2313
|
] }),
|
|
2283
|
-
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, wrap: "truncate", children: focused ? `\u2191\u2193 select \xB7 enter open \xB7 a activate \xB7 x deactivate \xB7 ^R refresh${lAbove ? ` \xB7 \u25B2${lAbove}` : ""}${lBelow ? ` \xB7 \u25BC${lBelow}` : ""}` : "press \u2192 to browse" }),
|
|
2314
|
+
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, wrap: "truncate", children: focused ? `\u2191\u2193 select \xB7 enter open \xB7 n new policy \xB7 a activate \xB7 x deactivate \xB7 ^R refresh${lAbove ? ` \xB7 \u25B2${lAbove}` : ""}${lBelow ? ` \xB7 \u25BC${lBelow}` : ""}` : "press \u2192 to browse" }),
|
|
2315
|
+
creating !== null ? /* @__PURE__ */ jsxs4(Box4, { children: [
|
|
2316
|
+
/* @__PURE__ */ jsx4(Text4, { color: theme.warn, children: "new policy name: " }),
|
|
2317
|
+
/* @__PURE__ */ jsx4(TextInput3, { value: creating, onChange: setCreating, onSubmit: commitNewPolicy })
|
|
2318
|
+
] }) : null,
|
|
2284
2319
|
/* @__PURE__ */ jsx4(Box4, { marginTop: 1, flexDirection: "column", children: lWin.map((p, wi) => {
|
|
2285
2320
|
const i = lStart + wi;
|
|
2286
2321
|
return /* @__PURE__ */ jsxs4(Text4, { color: i === pi ? theme.accentBright : void 0, bold: i === pi, children: [
|
|
@@ -2360,7 +2395,7 @@ function PoliciesPanel({ focused }) {
|
|
|
2360
2395
|
return /* @__PURE__ */ jsxs4(Box4, { children: [
|
|
2361
2396
|
/* @__PURE__ */ jsx4(Text4, { color: active2 ? theme.accentBright : void 0, children: (active2 ? "\u25B8 " : " ") + f.label.padEnd(13) }),
|
|
2362
2397
|
active2 && editing && f.kind === "text" ? /* @__PURE__ */ jsx4(
|
|
2363
|
-
|
|
2398
|
+
TextInput3,
|
|
2364
2399
|
{
|
|
2365
2400
|
value: editVal,
|
|
2366
2401
|
onChange: setEditVal,
|
|
@@ -2555,7 +2590,7 @@ function FieldRow({ label, active: active2, children }) {
|
|
|
2555
2590
|
|
|
2556
2591
|
// src/tui/panels/Dlp.tsx
|
|
2557
2592
|
import { Box as Box6, Text as Text6, useInput as useInput5 } from "ink";
|
|
2558
|
-
import
|
|
2593
|
+
import TextInput4 from "ink-text-input";
|
|
2559
2594
|
import { useEffect as useEffect6, useState as useState6 } from "react";
|
|
2560
2595
|
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
2561
2596
|
var MODES2 = ["off", "detect", "block"];
|
|
@@ -2736,7 +2771,7 @@ function DlpPanel({ focused }) {
|
|
|
2736
2771
|
adding ? /* @__PURE__ */ jsx6(Box6, { flexDirection: "column", children: /* @__PURE__ */ jsxs6(Box6, { children: [
|
|
2737
2772
|
/* @__PURE__ */ jsx6(Text6, { color: theme.warn, children: adding === "name" ? "new pattern name: " : adding === "re" ? `pattern for "${newName}" (glob, * = any chars, e.g. sk-* AKIA*): ` : "ghost path to hide (glob, * = any chars, e.g. */.env *.pem): " }),
|
|
2738
2773
|
/* @__PURE__ */ jsx6(
|
|
2739
|
-
|
|
2774
|
+
TextInput4,
|
|
2740
2775
|
{
|
|
2741
2776
|
value: input,
|
|
2742
2777
|
onChange: setInput,
|
|
@@ -2769,7 +2804,7 @@ function DlpPanel({ focused }) {
|
|
|
2769
2804
|
|
|
2770
2805
|
// src/tui/panels/Audit.tsx
|
|
2771
2806
|
import { Box as Box7, Text as Text7, useInput as useInput6 } from "ink";
|
|
2772
|
-
import
|
|
2807
|
+
import TextInput5 from "ink-text-input";
|
|
2773
2808
|
import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
2774
2809
|
import { homedir as homedir5 } from "os";
|
|
2775
2810
|
import { join as join5 } from "path";
|
|
@@ -3291,7 +3326,7 @@ function AuditPanel({ active: active2, focused }) {
|
|
|
3291
3326
|
editing === "sess-search" ? /* @__PURE__ */ jsxs7(Box7, { children: [
|
|
3292
3327
|
/* @__PURE__ */ jsx7(Text7, { color: theme.warn, children: "search: " }),
|
|
3293
3328
|
/* @__PURE__ */ jsx7(
|
|
3294
|
-
|
|
3329
|
+
TextInput5,
|
|
3295
3330
|
{
|
|
3296
3331
|
value: sessSearch,
|
|
3297
3332
|
onChange: (v) => {
|
|
@@ -3369,7 +3404,7 @@ function AuditPanel({ active: active2, focused }) {
|
|
|
3369
3404
|
": "
|
|
3370
3405
|
] }),
|
|
3371
3406
|
/* @__PURE__ */ jsx7(
|
|
3372
|
-
|
|
3407
|
+
TextInput5,
|
|
3373
3408
|
{
|
|
3374
3409
|
value: editing === "tool" ? tool : editing === "agent" ? agent : search,
|
|
3375
3410
|
onChange: (v) => {
|
|
@@ -3393,7 +3428,7 @@ function AuditPanel({ active: active2, focused }) {
|
|
|
3393
3428
|
|
|
3394
3429
|
// src/tui/panels/Settings.tsx
|
|
3395
3430
|
import { Box as Box8, Text as Text8, useInput as useInput7 } from "ink";
|
|
3396
|
-
import
|
|
3431
|
+
import TextInput6 from "ink-text-input";
|
|
3397
3432
|
import { useEffect as useEffect7, useRef as useRef3, useState as useState8 } from "react";
|
|
3398
3433
|
|
|
3399
3434
|
// src/global-install.ts
|
|
@@ -4316,7 +4351,7 @@ function SettingsPanel({
|
|
|
4316
4351
|
/* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: "\u2191\u2193 field \xB7 \u2190\u2192 change \xB7 e edit target \xB7 enter save \xB7 esc cancel" }),
|
|
4317
4352
|
editing === "alert-target" ? /* @__PURE__ */ jsxs8(Box8, { marginTop: 1, children: [
|
|
4318
4353
|
/* @__PURE__ */ jsx8(Text8, { color: theme.warn, children: editor.channel === "email" ? "e-mail address: " : "telegram chat id (from @userinfobot): " }),
|
|
4319
|
-
/* @__PURE__ */ jsx8(
|
|
4354
|
+
/* @__PURE__ */ jsx8(TextInput6, { value: input, onChange: setInput, onSubmit: submitInput })
|
|
4320
4355
|
] }) : msg ? /* @__PURE__ */ jsx8(Text8, { color: msg.level === "bad" ? theme.bad : theme.ok, children: truncate(msg.text, cols) }) : /* @__PURE__ */ jsx8(Text8, { children: " " }),
|
|
4321
4356
|
/* @__PURE__ */ jsxs8(Box8, { marginTop: 1, flexDirection: "column", children: [
|
|
4322
4357
|
fieldRow(0, "target", editor.target ? /* @__PURE__ */ jsx8(Text8, { color: theme.accent, children: truncate(editor.target, cols - 16) }) : /* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: "empty \u2014 press e" }), "press e to edit"),
|
|
@@ -4496,7 +4531,7 @@ function SettingsPanel({
|
|
|
4496
4531
|
/* @__PURE__ */ jsx8(Text8, { wrap: "truncate", color: theme.dim, children: focused ? `\u2191\u2193 move \xB7 enter act \xB7 m toggle \xB7 t test \xB7 e edit \xB7 x remove \xB7 d delete \xB7 n add${moreAbove ? ` \xB7 \u25B2${moreAbove}` : ""}${moreBelow ? ` \xB7 \u25BC${moreBelow}` : ""}` : "press \u2192 to configure" }),
|
|
4497
4532
|
editing ? /* @__PURE__ */ jsxs8(Box8, { children: [
|
|
4498
4533
|
/* @__PURE__ */ jsx8(Text8, { color: theme.warn, children: editing === "path" ? "local log path: " : "webhook url: " }),
|
|
4499
|
-
/* @__PURE__ */ jsx8(
|
|
4534
|
+
/* @__PURE__ */ jsx8(TextInput6, { value: input, onChange: setInput, onSubmit: submitInput })
|
|
4500
4535
|
] }) : msg ? /* @__PURE__ */ jsx8(Text8, { wrap: "truncate", color: msg.level === "bad" ? theme.bad : theme.ok, children: truncate(msg.text, cols) }) : login?.msg ? /* @__PURE__ */ jsx8(Text8, { wrap: "truncate", color: login.phase === "error" ? theme.bad : theme.ok, children: login.msg }) : /* @__PURE__ */ jsx8(Text8, { children: " " }),
|
|
4501
4536
|
/* @__PURE__ */ jsx8(Box8, { flexDirection: "column", height: budget, overflow: "hidden", children: win })
|
|
4502
4537
|
] }) });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solongate/proxy",
|
|
3
|
-
"version": "0.82.
|
|
3
|
+
"version": "0.82.36",
|
|
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": {
|