@solongate/proxy 0.81.95 → 0.81.97
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 +35 -21
- package/dist/tui/index.js +35 -21
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9111,7 +9111,7 @@ function RateLimitPanel({ focused }) {
|
|
|
9111
9111
|
const insightsQ = useLoader(() => api.stats.securityInsights(7));
|
|
9112
9112
|
const [draft, setDraft] = useState4(null);
|
|
9113
9113
|
const [dirty, setDirty] = useState4(false);
|
|
9114
|
-
const [
|
|
9114
|
+
const [sel, setSel] = useState4(0);
|
|
9115
9115
|
const [status, setStatus] = useState4(null);
|
|
9116
9116
|
useEffect4(() => {
|
|
9117
9117
|
if (layersQ.data && !dirty) setDraft({ ...layersQ.data.layers.rateLimit });
|
|
@@ -9124,7 +9124,7 @@ function RateLimitPanel({ focused }) {
|
|
|
9124
9124
|
insightsQ.reloadQuiet();
|
|
9125
9125
|
}, 1e4);
|
|
9126
9126
|
const adjust = (dir, step) => {
|
|
9127
|
-
if (!draft) return;
|
|
9127
|
+
if (!draft || fi < 0) return;
|
|
9128
9128
|
const field = FIELDS2[fi];
|
|
9129
9129
|
if (field === "mode") setDraft({ ...draft, mode: MODES[(MODES.indexOf(draft.mode) + dir + MODES.length) % MODES.length] });
|
|
9130
9130
|
else setDraft({ ...draft, [field]: Math.max(0, draft[field] + dir * step) });
|
|
@@ -9146,11 +9146,28 @@ function RateLimitPanel({ focused }) {
|
|
|
9146
9146
|
setStatus("\u2717 " + (e instanceof Error ? e.message : String(e)));
|
|
9147
9147
|
}
|
|
9148
9148
|
};
|
|
9149
|
+
const history = (historyQ.data?.history ?? []).slice().sort((a, b) => b.ts - a.ts);
|
|
9150
|
+
const lastChange = history[0];
|
|
9151
|
+
const peaks = insightsQ.data?.["peaks"] ?? { minute: 0, hour: 0, day: 0 };
|
|
9152
|
+
const anomalies2 = (insightsQ.data?.["anomalies"] ?? []).slice().sort((a, b) => b.count - a.count || new Date(b.minute).getTime() - new Date(a.minute).getTime());
|
|
9153
|
+
const hasLoad = (draft?.perMinute ?? 0) > 0;
|
|
9154
|
+
const showExtras = rows >= 20;
|
|
9155
|
+
const fixed = 1 + 4 + (showExtras ? (hasLoad ? 1 : 0) + 5 : 0) + 1 + 1 + 1 + 1;
|
|
9156
|
+
const burstBudget = Math.max(1, rows - fixed);
|
|
9157
|
+
const maxOff = Math.max(0, anomalies2.length - burstBudget);
|
|
9158
|
+
const total = 4 + anomalies2.length;
|
|
9159
|
+
const selC = Math.min(sel, Math.max(0, total - 1));
|
|
9160
|
+
const onField = selC < 4;
|
|
9161
|
+
const fi = onField ? selC : -1;
|
|
9162
|
+
const bcur = onField ? -1 : selC - 4;
|
|
9163
|
+
const off = bcur < 0 ? 0 : Math.min(Math.max(0, bcur - Math.floor(burstBudget / 2)), maxOff);
|
|
9149
9164
|
useInput3(
|
|
9150
9165
|
(input, key) => {
|
|
9151
9166
|
const step = key.shift ? 10 : 1;
|
|
9152
|
-
if (key.upArrow)
|
|
9153
|
-
else if (key.downArrow)
|
|
9167
|
+
if (key.upArrow) setSel((n) => Math.max(0, n - 1));
|
|
9168
|
+
else if (key.downArrow) setSel((n) => Math.min(total - 1, n + 1));
|
|
9169
|
+
else if (key.pageDown) setSel((n) => Math.min(total - 1, n + burstBudget));
|
|
9170
|
+
else if (key.pageUp) setSel((n) => Math.max(0, n - burstBudget));
|
|
9154
9171
|
else if (key.leftArrow) adjust(-1, step);
|
|
9155
9172
|
else if (key.rightArrow) adjust(1, step);
|
|
9156
9173
|
else if (input === "s") void save();
|
|
@@ -9163,23 +9180,15 @@ function RateLimitPanel({ focused }) {
|
|
|
9163
9180
|
},
|
|
9164
9181
|
{ isActive: focused }
|
|
9165
9182
|
);
|
|
9166
|
-
const history = (historyQ.data?.history ?? []).slice().sort((a, b) => b.ts - a.ts);
|
|
9167
|
-
const lastChange = history[0];
|
|
9168
|
-
const peaks = insightsQ.data?.["peaks"] ?? { minute: 0, hour: 0, day: 0 };
|
|
9169
|
-
const anomalies2 = (insightsQ.data?.["anomalies"] ?? []).slice().sort((a, b) => b.count - a.count || new Date(b.minute).getTime() - new Date(a.minute).getTime());
|
|
9170
9183
|
return /* @__PURE__ */ jsx4(DataView, { loading: layersQ.loading && !draft, error: layersQ.error, children: draft ? (() => {
|
|
9171
9184
|
const lim = draft.perMinute;
|
|
9172
9185
|
const now = insightsQ.data ? insightsQ.data["activity"]?.minute?.slice(-1)[0]?.count ?? 0 : 0;
|
|
9173
9186
|
const loadPct = lim > 0 ? Math.min(100, Math.round(now / lim * 100)) : 0;
|
|
9174
9187
|
const last24h = (insightsQ.data?.["activity"]?.hour ?? []).reduce((s, b) => s + b.count, 0);
|
|
9175
|
-
const
|
|
9176
|
-
const showExtras = rows >= 20;
|
|
9177
|
-
const fixed = 1 + 4 + (showExtras ? (hasLoad ? 1 : 0) + 5 : 0) + 1 + 1 + 1;
|
|
9178
|
-
const burstBudget = Math.max(1, rows - fixed);
|
|
9179
|
-
const shown = anomalies2.slice(0, burstBudget);
|
|
9188
|
+
const shown = anomalies2.slice(off, off + burstBudget);
|
|
9180
9189
|
const bw = Math.max(10, cols - 30);
|
|
9181
9190
|
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", height: rows, overflow: "hidden", children: [
|
|
9182
|
-
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, wrap: "truncate", children: focused ? "\u2191\u2193
|
|
9191
|
+
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, wrap: "truncate", children: focused ? "\u2191\u2193 move (fields + bursts) \xB7 \u2190\u2192 \xB11 \xB7 shift+\u2190\u2192 \xB110 \xB7 s save \xB7 ^R refresh" : "press \u2192 to edit" }),
|
|
9183
9192
|
/* @__PURE__ */ jsxs4(FieldRow, { label: "Mode", active: focused && fi === 0, children: [
|
|
9184
9193
|
/* @__PURE__ */ jsx4(Text4, { color: modeColor(draft.mode), bold: true, children: draft.mode }),
|
|
9185
9194
|
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: draft.mode === "off" ? " no limit" : draft.mode === "detect" ? " flag bursts, never block" : " DENY calls over the limit" })
|
|
@@ -9206,6 +9215,7 @@ function RateLimitPanel({ focused }) {
|
|
|
9206
9215
|
/* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
|
|
9207
9216
|
/* @__PURE__ */ jsxs4(Text4, { color: theme.accentBright, bold: true, wrap: "truncate", children: [
|
|
9208
9217
|
`Recent bursts 7d${anomalies2.length ? ` (${anomalies2.length})` : ""}`,
|
|
9218
|
+
maxOff > 0 ? /* @__PURE__ */ jsx4(Text4, { color: theme.warn, children: ` ${off + 1}-${Math.min(off + burstBudget, anomalies2.length)}/${anomalies2.length}` }) : null,
|
|
9209
9219
|
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: " over the per-minute limit \xB7 Bypassed = detect (not blocked)" })
|
|
9210
9220
|
] }),
|
|
9211
9221
|
anomalies2.length === 0 ? /* @__PURE__ */ jsxs4(Text4, { color: theme.dim, children: [
|
|
@@ -9214,16 +9224,20 @@ function RateLimitPanel({ focused }) {
|
|
|
9214
9224
|
] }) : /* @__PURE__ */ jsx4(
|
|
9215
9225
|
Table,
|
|
9216
9226
|
{
|
|
9217
|
-
columns: [{ header: "WHEN", width:
|
|
9218
|
-
rows: shown.map((a) =>
|
|
9219
|
-
|
|
9220
|
-
|
|
9221
|
-
|
|
9222
|
-
|
|
9223
|
-
|
|
9227
|
+
columns: [{ header: "WHEN", width: 15 }, { header: "RESULT", width: 9 }, { header: "CALLS", width: 7 }, { header: "AGENT", width: Math.max(8, bw - 31) }],
|
|
9228
|
+
rows: shown.map((a, i) => {
|
|
9229
|
+
const isSel = off + i === bcur;
|
|
9230
|
+
return [
|
|
9231
|
+
{ value: (isSel ? "\u25B8 " : " ") + when(new Date(a.minute).getTime()), color: isSel ? theme.accentBright : void 0, dim: !isSel },
|
|
9232
|
+
{ value: a.blocked ? "Blocked" : "Bypassed", color: a.blocked ? theme.bad : theme.warn },
|
|
9233
|
+
{ value: `${a.count}/${a.limit}`, color: theme.warn },
|
|
9234
|
+
{ value: truncate2(a.agent, Math.max(8, bw - 31)), dim: !isSel }
|
|
9235
|
+
];
|
|
9236
|
+
})
|
|
9224
9237
|
}
|
|
9225
9238
|
)
|
|
9226
9239
|
] }),
|
|
9240
|
+
/* @__PURE__ */ jsx4(Text4, { children: " " }),
|
|
9227
9241
|
/* @__PURE__ */ jsxs4(Text4, { wrap: "truncate", children: [
|
|
9228
9242
|
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: "limit now " }),
|
|
9229
9243
|
/* @__PURE__ */ jsx4(Text4, { children: lim > 0 ? `${lim}/min` : "no per-minute limit" }),
|
package/dist/tui/index.js
CHANGED
|
@@ -2199,7 +2199,7 @@ function RateLimitPanel({ focused }) {
|
|
|
2199
2199
|
const insightsQ = useLoader(() => api.stats.securityInsights(7));
|
|
2200
2200
|
const [draft, setDraft] = useState4(null);
|
|
2201
2201
|
const [dirty, setDirty] = useState4(false);
|
|
2202
|
-
const [
|
|
2202
|
+
const [sel, setSel] = useState4(0);
|
|
2203
2203
|
const [status, setStatus] = useState4(null);
|
|
2204
2204
|
useEffect4(() => {
|
|
2205
2205
|
if (layersQ.data && !dirty) setDraft({ ...layersQ.data.layers.rateLimit });
|
|
@@ -2212,7 +2212,7 @@ function RateLimitPanel({ focused }) {
|
|
|
2212
2212
|
insightsQ.reloadQuiet();
|
|
2213
2213
|
}, 1e4);
|
|
2214
2214
|
const adjust = (dir, step) => {
|
|
2215
|
-
if (!draft) return;
|
|
2215
|
+
if (!draft || fi < 0) return;
|
|
2216
2216
|
const field = FIELDS2[fi];
|
|
2217
2217
|
if (field === "mode") setDraft({ ...draft, mode: MODES[(MODES.indexOf(draft.mode) + dir + MODES.length) % MODES.length] });
|
|
2218
2218
|
else setDraft({ ...draft, [field]: Math.max(0, draft[field] + dir * step) });
|
|
@@ -2234,11 +2234,28 @@ function RateLimitPanel({ focused }) {
|
|
|
2234
2234
|
setStatus("\u2717 " + (e instanceof Error ? e.message : String(e)));
|
|
2235
2235
|
}
|
|
2236
2236
|
};
|
|
2237
|
+
const history = (historyQ.data?.history ?? []).slice().sort((a, b) => b.ts - a.ts);
|
|
2238
|
+
const lastChange = history[0];
|
|
2239
|
+
const peaks = insightsQ.data?.["peaks"] ?? { minute: 0, hour: 0, day: 0 };
|
|
2240
|
+
const anomalies2 = (insightsQ.data?.["anomalies"] ?? []).slice().sort((a, b) => b.count - a.count || new Date(b.minute).getTime() - new Date(a.minute).getTime());
|
|
2241
|
+
const hasLoad = (draft?.perMinute ?? 0) > 0;
|
|
2242
|
+
const showExtras = rows >= 20;
|
|
2243
|
+
const fixed = 1 + 4 + (showExtras ? (hasLoad ? 1 : 0) + 5 : 0) + 1 + 1 + 1 + 1;
|
|
2244
|
+
const burstBudget = Math.max(1, rows - fixed);
|
|
2245
|
+
const maxOff = Math.max(0, anomalies2.length - burstBudget);
|
|
2246
|
+
const total = 4 + anomalies2.length;
|
|
2247
|
+
const selC = Math.min(sel, Math.max(0, total - 1));
|
|
2248
|
+
const onField = selC < 4;
|
|
2249
|
+
const fi = onField ? selC : -1;
|
|
2250
|
+
const bcur = onField ? -1 : selC - 4;
|
|
2251
|
+
const off = bcur < 0 ? 0 : Math.min(Math.max(0, bcur - Math.floor(burstBudget / 2)), maxOff);
|
|
2237
2252
|
useInput3(
|
|
2238
2253
|
(input, key) => {
|
|
2239
2254
|
const step = key.shift ? 10 : 1;
|
|
2240
|
-
if (key.upArrow)
|
|
2241
|
-
else if (key.downArrow)
|
|
2255
|
+
if (key.upArrow) setSel((n) => Math.max(0, n - 1));
|
|
2256
|
+
else if (key.downArrow) setSel((n) => Math.min(total - 1, n + 1));
|
|
2257
|
+
else if (key.pageDown) setSel((n) => Math.min(total - 1, n + burstBudget));
|
|
2258
|
+
else if (key.pageUp) setSel((n) => Math.max(0, n - burstBudget));
|
|
2242
2259
|
else if (key.leftArrow) adjust(-1, step);
|
|
2243
2260
|
else if (key.rightArrow) adjust(1, step);
|
|
2244
2261
|
else if (input === "s") void save();
|
|
@@ -2251,23 +2268,15 @@ function RateLimitPanel({ focused }) {
|
|
|
2251
2268
|
},
|
|
2252
2269
|
{ isActive: focused }
|
|
2253
2270
|
);
|
|
2254
|
-
const history = (historyQ.data?.history ?? []).slice().sort((a, b) => b.ts - a.ts);
|
|
2255
|
-
const lastChange = history[0];
|
|
2256
|
-
const peaks = insightsQ.data?.["peaks"] ?? { minute: 0, hour: 0, day: 0 };
|
|
2257
|
-
const anomalies2 = (insightsQ.data?.["anomalies"] ?? []).slice().sort((a, b) => b.count - a.count || new Date(b.minute).getTime() - new Date(a.minute).getTime());
|
|
2258
2271
|
return /* @__PURE__ */ jsx4(DataView, { loading: layersQ.loading && !draft, error: layersQ.error, children: draft ? (() => {
|
|
2259
2272
|
const lim = draft.perMinute;
|
|
2260
2273
|
const now = insightsQ.data ? insightsQ.data["activity"]?.minute?.slice(-1)[0]?.count ?? 0 : 0;
|
|
2261
2274
|
const loadPct = lim > 0 ? Math.min(100, Math.round(now / lim * 100)) : 0;
|
|
2262
2275
|
const last24h = (insightsQ.data?.["activity"]?.hour ?? []).reduce((s, b) => s + b.count, 0);
|
|
2263
|
-
const
|
|
2264
|
-
const showExtras = rows >= 20;
|
|
2265
|
-
const fixed = 1 + 4 + (showExtras ? (hasLoad ? 1 : 0) + 5 : 0) + 1 + 1 + 1;
|
|
2266
|
-
const burstBudget = Math.max(1, rows - fixed);
|
|
2267
|
-
const shown = anomalies2.slice(0, burstBudget);
|
|
2276
|
+
const shown = anomalies2.slice(off, off + burstBudget);
|
|
2268
2277
|
const bw = Math.max(10, cols - 30);
|
|
2269
2278
|
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", height: rows, overflow: "hidden", children: [
|
|
2270
|
-
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, wrap: "truncate", children: focused ? "\u2191\u2193
|
|
2279
|
+
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, wrap: "truncate", children: focused ? "\u2191\u2193 move (fields + bursts) \xB7 \u2190\u2192 \xB11 \xB7 shift+\u2190\u2192 \xB110 \xB7 s save \xB7 ^R refresh" : "press \u2192 to edit" }),
|
|
2271
2280
|
/* @__PURE__ */ jsxs4(FieldRow, { label: "Mode", active: focused && fi === 0, children: [
|
|
2272
2281
|
/* @__PURE__ */ jsx4(Text4, { color: modeColor(draft.mode), bold: true, children: draft.mode }),
|
|
2273
2282
|
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: draft.mode === "off" ? " no limit" : draft.mode === "detect" ? " flag bursts, never block" : " DENY calls over the limit" })
|
|
@@ -2294,6 +2303,7 @@ function RateLimitPanel({ focused }) {
|
|
|
2294
2303
|
/* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
|
|
2295
2304
|
/* @__PURE__ */ jsxs4(Text4, { color: theme.accentBright, bold: true, wrap: "truncate", children: [
|
|
2296
2305
|
`Recent bursts 7d${anomalies2.length ? ` (${anomalies2.length})` : ""}`,
|
|
2306
|
+
maxOff > 0 ? /* @__PURE__ */ jsx4(Text4, { color: theme.warn, children: ` ${off + 1}-${Math.min(off + burstBudget, anomalies2.length)}/${anomalies2.length}` }) : null,
|
|
2297
2307
|
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: " over the per-minute limit \xB7 Bypassed = detect (not blocked)" })
|
|
2298
2308
|
] }),
|
|
2299
2309
|
anomalies2.length === 0 ? /* @__PURE__ */ jsxs4(Text4, { color: theme.dim, children: [
|
|
@@ -2302,16 +2312,20 @@ function RateLimitPanel({ focused }) {
|
|
|
2302
2312
|
] }) : /* @__PURE__ */ jsx4(
|
|
2303
2313
|
Table,
|
|
2304
2314
|
{
|
|
2305
|
-
columns: [{ header: "WHEN", width:
|
|
2306
|
-
rows: shown.map((a) =>
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2315
|
+
columns: [{ header: "WHEN", width: 15 }, { header: "RESULT", width: 9 }, { header: "CALLS", width: 7 }, { header: "AGENT", width: Math.max(8, bw - 31) }],
|
|
2316
|
+
rows: shown.map((a, i) => {
|
|
2317
|
+
const isSel = off + i === bcur;
|
|
2318
|
+
return [
|
|
2319
|
+
{ value: (isSel ? "\u25B8 " : " ") + when(new Date(a.minute).getTime()), color: isSel ? theme.accentBright : void 0, dim: !isSel },
|
|
2320
|
+
{ value: a.blocked ? "Blocked" : "Bypassed", color: a.blocked ? theme.bad : theme.warn },
|
|
2321
|
+
{ value: `${a.count}/${a.limit}`, color: theme.warn },
|
|
2322
|
+
{ value: truncate(a.agent, Math.max(8, bw - 31)), dim: !isSel }
|
|
2323
|
+
];
|
|
2324
|
+
})
|
|
2312
2325
|
}
|
|
2313
2326
|
)
|
|
2314
2327
|
] }),
|
|
2328
|
+
/* @__PURE__ */ jsx4(Text4, { children: " " }),
|
|
2315
2329
|
/* @__PURE__ */ jsxs4(Text4, { wrap: "truncate", children: [
|
|
2316
2330
|
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: "limit now " }),
|
|
2317
2331
|
/* @__PURE__ */ jsx4(Text4, { children: lim > 0 ? `${lim}/min` : "no per-minute limit" }),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solongate/proxy",
|
|
3
|
-
"version": "0.81.
|
|
3
|
+
"version": "0.81.97",
|
|
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": {
|