@solongate/proxy 0.81.87 → 0.81.89
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 +87 -92
- package/dist/tui/index.js +82 -87
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9087,16 +9087,8 @@ var init_Policies = __esm({
|
|
|
9087
9087
|
import { Box as Box4, Text as Text4, useInput as useInput3 } from "ink";
|
|
9088
9088
|
import { useEffect as useEffect4, useState as useState4 } from "react";
|
|
9089
9089
|
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
9090
|
-
function ColoredSpark({ values, limit, width: width2 = 60 }) {
|
|
9091
|
-
const v = values.length > width2 ? values.slice(values.length - width2) : values;
|
|
9092
|
-
const max = Math.max(1, ...v);
|
|
9093
|
-
return /* @__PURE__ */ jsx4(Text4, { children: v.map((n, i) => {
|
|
9094
|
-
const ch = BLOCKS[Math.min(BLOCKS.length - 1, Math.round(n / max * (BLOCKS.length - 1)))];
|
|
9095
|
-
const over = limit > 0 && n > limit;
|
|
9096
|
-
return /* @__PURE__ */ jsx4(Text4, { color: over ? theme.bad : theme.accent, children: ch }, i);
|
|
9097
|
-
}) });
|
|
9098
|
-
}
|
|
9099
9090
|
function RateLimitPanel({ focused }) {
|
|
9091
|
+
const { cols, rows } = usePanelSize();
|
|
9100
9092
|
const layersQ = useLoader(() => api.settings.getSecurityLayers());
|
|
9101
9093
|
const historyQ = useLoader(() => api.settings.getRateLimitHistory());
|
|
9102
9094
|
const insightsQ = useLoader(() => api.stats.securityInsights(7));
|
|
@@ -9110,12 +9102,8 @@ function RateLimitPanel({ focused }) {
|
|
|
9110
9102
|
const adjust = (dir, step) => {
|
|
9111
9103
|
if (!draft) return;
|
|
9112
9104
|
const field = FIELDS2[fi];
|
|
9113
|
-
if (field === "mode") {
|
|
9114
|
-
|
|
9115
|
-
setDraft({ ...draft, mode: MODES[idx] });
|
|
9116
|
-
} else {
|
|
9117
|
-
setDraft({ ...draft, [field]: Math.max(0, draft[field] + dir * step) });
|
|
9118
|
-
}
|
|
9105
|
+
if (field === "mode") setDraft({ ...draft, mode: MODES[(MODES.indexOf(draft.mode) + dir + MODES.length) % MODES.length] });
|
|
9106
|
+
else setDraft({ ...draft, [field]: Math.max(0, draft[field] + dir * step) });
|
|
9119
9107
|
setDirty(true);
|
|
9120
9108
|
setStatus(null);
|
|
9121
9109
|
};
|
|
@@ -9128,6 +9116,7 @@ function RateLimitPanel({ focused }) {
|
|
|
9128
9116
|
setDirty(false);
|
|
9129
9117
|
setStatus("\u2713 Saved");
|
|
9130
9118
|
historyQ.reload();
|
|
9119
|
+
insightsQ.reload();
|
|
9131
9120
|
} catch (e) {
|
|
9132
9121
|
setStatus("\u2717 " + (e instanceof Error ? e.message : String(e)));
|
|
9133
9122
|
}
|
|
@@ -9144,86 +9133,89 @@ function RateLimitPanel({ focused }) {
|
|
|
9144
9133
|
{ isActive: focused }
|
|
9145
9134
|
);
|
|
9146
9135
|
const history = (historyQ.data?.history ?? []).slice().sort((a, b) => b.ts - a.ts);
|
|
9147
|
-
const
|
|
9148
|
-
const
|
|
9149
|
-
const
|
|
9150
|
-
|
|
9151
|
-
|
|
9152
|
-
|
|
9153
|
-
|
|
9154
|
-
|
|
9155
|
-
|
|
9156
|
-
|
|
9157
|
-
|
|
9158
|
-
|
|
9159
|
-
|
|
9160
|
-
|
|
9161
|
-
|
|
9162
|
-
|
|
9163
|
-
|
|
9164
|
-
|
|
9165
|
-
return /* @__PURE__ */ jsxs4(Box4, { marginTop: 1, children: [
|
|
9166
|
-
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: "load " }),
|
|
9167
|
-
/* @__PURE__ */ jsx4(Text4, { color: col, children: "\u2588".repeat(filled) }),
|
|
9168
|
-
/* @__PURE__ */ jsx4(Text4, { color: "#233457", children: "\u2591".repeat(Math.max(0, width2 - filled)) }),
|
|
9169
|
-
/* @__PURE__ */ jsx4(Text4, { color: col, children: ` ${now}/${draft.perMinute} ` }),
|
|
9170
|
-
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: `(${pct}% this min)` })
|
|
9171
|
-
] });
|
|
9172
|
-
})() : null,
|
|
9173
|
-
dirty || status ? /* @__PURE__ */ jsxs4(Box4, { marginTop: 1, children: [
|
|
9174
|
-
dirty ? /* @__PURE__ */ jsx4(Text4, { color: theme.warn, children: "\u25CF unsaved \u2014 press s to apply " }) : null,
|
|
9175
|
-
status ? /* @__PURE__ */ jsx4(Text4, { color: status.startsWith("\u2717") ? theme.bad : theme.ok, children: status }) : null
|
|
9176
|
-
] }) : null,
|
|
9177
|
-
/* @__PURE__ */ jsxs4(Box4, { marginTop: 1, flexDirection: "column", children: [
|
|
9178
|
-
/* @__PURE__ */ jsxs4(Box4, { children: [
|
|
9179
|
-
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: "Activity " }),
|
|
9180
|
-
bursts > 0 ? /* @__PURE__ */ jsxs4(Text4, { color: theme.bad, children: [
|
|
9181
|
-
bursts,
|
|
9182
|
-
" burst min"
|
|
9183
|
-
] }) : /* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: "no bursts" }),
|
|
9184
|
-
insightsQ.loading && !insightsQ.data ? /* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: " \u2026" }) : null
|
|
9136
|
+
const lastChange = history[0];
|
|
9137
|
+
const peaks = insightsQ.data?.["peaks"] ?? { minute: 0, hour: 0, day: 0 };
|
|
9138
|
+
const anomalies2 = (insightsQ.data?.["anomalies"] ?? []).slice().sort((a, b) => new Date(b.minute).getTime() - new Date(a.minute).getTime());
|
|
9139
|
+
return /* @__PURE__ */ jsx4(DataView, { loading: layersQ.loading && !draft, error: layersQ.error, children: draft ? (() => {
|
|
9140
|
+
const lim = draft.perMinute;
|
|
9141
|
+
const now = insightsQ.data ? insightsQ.data["activity"]?.minute?.slice(-1)[0]?.count ?? 0 : 0;
|
|
9142
|
+
const loadPct = lim > 0 ? Math.min(100, Math.round(now / lim * 100)) : 0;
|
|
9143
|
+
const last24h = (insightsQ.data?.["activity"]?.hour ?? []).reduce((s, b) => s + b.count, 0);
|
|
9144
|
+
const hasLoad = lim > 0;
|
|
9145
|
+
const fixed = 1 + 4 + (hasLoad ? 1 : 0) + 5 + 1 + 1 + 1 + 1 + (dirty || status ? 1 : 0) + 1;
|
|
9146
|
+
const burstBudget = Math.max(1, rows - fixed);
|
|
9147
|
+
const shown = anomalies2.slice(0, burstBudget);
|
|
9148
|
+
const bw = Math.max(10, cols - 30);
|
|
9149
|
+
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", height: rows, overflow: "hidden", children: [
|
|
9150
|
+
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, wrap: "truncate", children: focused ? "\u2191\u2193 field \xB7 \u2190\u2192 \xB11 \xB7 shift+\u2190\u2192 \xB110 \xB7 s save" : "press \u2192 to edit" }),
|
|
9151
|
+
/* @__PURE__ */ jsxs4(FieldRow, { label: "Mode", active: focused && fi === 0, children: [
|
|
9152
|
+
/* @__PURE__ */ jsx4(Text4, { color: modeColor(draft.mode), bold: true, children: draft.mode }),
|
|
9153
|
+
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: draft.mode === "off" ? " no limit" : draft.mode === "detect" ? " flag bursts, never block" : " DENY calls over the limit" })
|
|
9185
9154
|
] }),
|
|
9186
|
-
/* @__PURE__ */
|
|
9187
|
-
|
|
9188
|
-
|
|
9155
|
+
/* @__PURE__ */ jsx4(FieldRow, { label: "Per minute", active: focused && fi === 1, children: /* @__PURE__ */ jsx4(Text4, { bold: true, children: draft.perMinute || "off" }) }),
|
|
9156
|
+
/* @__PURE__ */ jsx4(FieldRow, { label: "Per hour", active: focused && fi === 2, children: /* @__PURE__ */ jsx4(Text4, { bold: true, children: draft.perHour || "off" }) }),
|
|
9157
|
+
/* @__PURE__ */ jsx4(FieldRow, { label: "Per day", active: focused && fi === 3, children: /* @__PURE__ */ jsx4(Text4, { bold: true, children: draft.perDay || "off" }) }),
|
|
9158
|
+
hasLoad ? /* @__PURE__ */ jsxs4(Text4, { wrap: "truncate", children: [
|
|
9159
|
+
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: "load now".padEnd(13) }),
|
|
9160
|
+
/* @__PURE__ */ jsx4(Text4, { color: loadPct >= 100 ? theme.bad : loadPct >= 80 ? theme.warn : theme.ok, children: "\u2588".repeat(Math.min(18, Math.round(now / lim * 18))) }),
|
|
9161
|
+
/* @__PURE__ */ jsx4(Text4, { color: "#233457", children: "\u2591".repeat(Math.max(0, 18 - Math.round(now / lim * 18))) }),
|
|
9162
|
+
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: ` ${now}/${lim} this minute (${loadPct}%)` })
|
|
9163
|
+
] }) : null,
|
|
9164
|
+
/* @__PURE__ */ jsxs4(Text4, { color: theme.accentBright, bold: true, wrap: "truncate", children: [
|
|
9165
|
+
"Busiest 7d",
|
|
9166
|
+
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: " most calls in one window vs your limit" })
|
|
9189
9167
|
] }),
|
|
9190
|
-
/* @__PURE__ */
|
|
9191
|
-
|
|
9192
|
-
|
|
9193
|
-
|
|
9194
|
-
|
|
9195
|
-
|
|
9196
|
-
|
|
9197
|
-
|
|
9198
|
-
|
|
9168
|
+
/* @__PURE__ */ jsx4(BusiestRow, { label: "minute", peak: peaks.minute, limit: draft.perMinute }),
|
|
9169
|
+
/* @__PURE__ */ jsx4(BusiestRow, { label: "hour", peak: peaks.hour, limit: draft.perHour }),
|
|
9170
|
+
/* @__PURE__ */ jsx4(BusiestRow, { label: "day", peak: peaks.day, limit: draft.perDay }),
|
|
9171
|
+
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, wrap: "truncate", children: `activity`.padEnd(11) + ` last 24h \xB7 ${last24h} calls \xB7 busiest hour ${peaks.hour}/hr` }),
|
|
9172
|
+
/* @__PURE__ */ jsxs4(Box4, { marginTop: 1, flexDirection: "column", children: [
|
|
9173
|
+
/* @__PURE__ */ jsxs4(Text4, { color: theme.accentBright, bold: true, wrap: "truncate", children: [
|
|
9174
|
+
`Recent bursts 7d${anomalies2.length ? ` (${anomalies2.length})` : ""}`,
|
|
9175
|
+
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: " over the per-minute limit \xB7 Bypassed = detect (not blocked)" })
|
|
9176
|
+
] }),
|
|
9177
|
+
anomalies2.length === 0 ? /* @__PURE__ */ jsxs4(Text4, { color: theme.dim, children: [
|
|
9178
|
+
" ",
|
|
9179
|
+
insightsQ.loading ? "loading\u2026" : "no bursts in the last 7 days"
|
|
9180
|
+
] }) : /* @__PURE__ */ jsx4(
|
|
9181
|
+
Table,
|
|
9182
|
+
{
|
|
9183
|
+
columns: [{ header: "WHEN", width: 13 }, { header: "RESULT", width: 9 }, { header: "CALLS", width: 7 }, { header: "AGENT", width: Math.max(8, bw - 29) }],
|
|
9184
|
+
rows: shown.map((a) => [
|
|
9185
|
+
{ value: when(new Date(a.minute).getTime()), dim: true },
|
|
9186
|
+
{ value: a.blocked ? "Blocked" : "Bypassed", color: a.blocked ? theme.bad : theme.warn },
|
|
9187
|
+
{ value: `${a.count}/${a.limit}`, color: theme.warn },
|
|
9188
|
+
{ value: truncate2(a.agent, Math.max(8, bw - 29)), dim: true }
|
|
9189
|
+
])
|
|
9190
|
+
}
|
|
9191
|
+
)
|
|
9199
9192
|
] }),
|
|
9200
|
-
|
|
9201
|
-
|
|
9202
|
-
{
|
|
9203
|
-
|
|
9204
|
-
|
|
9205
|
-
|
|
9206
|
-
|
|
9207
|
-
|
|
9208
|
-
|
|
9209
|
-
|
|
9210
|
-
|
|
9211
|
-
|
|
9212
|
-
|
|
9213
|
-
|
|
9214
|
-
|
|
9215
|
-
|
|
9216
|
-
|
|
9217
|
-
|
|
9218
|
-
] }) : null });
|
|
9193
|
+
/* @__PURE__ */ jsxs4(Text4, { wrap: "truncate", children: [
|
|
9194
|
+
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: "limit now " }),
|
|
9195
|
+
/* @__PURE__ */ jsx4(Text4, { children: lim > 0 ? `${lim}/min` : "no per-minute limit" }),
|
|
9196
|
+
lastChange ? /* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: ` \xB7 changed ${when(lastChange.ts)}` }) : null,
|
|
9197
|
+
dirty ? /* @__PURE__ */ jsx4(Text4, { color: theme.warn, children: " \u25CF unsaved (s)" }) : null,
|
|
9198
|
+
status ? /* @__PURE__ */ jsx4(Text4, { color: status.startsWith("\u2717") ? theme.bad : theme.ok, children: " " + status }) : null
|
|
9199
|
+
] })
|
|
9200
|
+
] });
|
|
9201
|
+
})() : null });
|
|
9202
|
+
}
|
|
9203
|
+
function BusiestRow({ label, peak, limit }) {
|
|
9204
|
+
const ctx = limit > 0 ? peak > limit ? `over ${limit}` : peak === limit ? `at limit ${limit}` : `limit ${limit}` : "no limit set";
|
|
9205
|
+
const hot = limit > 0 && peak > limit;
|
|
9206
|
+
return /* @__PURE__ */ jsxs4(Text4, { wrap: "truncate", children: [
|
|
9207
|
+
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: (" " + label).padEnd(11) }),
|
|
9208
|
+
/* @__PURE__ */ jsx4(Text4, { color: hot ? theme.bad : void 0, bold: hot, children: String(peak).padStart(4) + " calls" }),
|
|
9209
|
+
/* @__PURE__ */ jsx4(Text4, { color: hot ? theme.bad : theme.dim, children: " \xB7 " + ctx })
|
|
9210
|
+
] });
|
|
9219
9211
|
}
|
|
9220
9212
|
function FieldRow({ label, active: active2, children }) {
|
|
9221
|
-
return /* @__PURE__ */ jsxs4(
|
|
9222
|
-
/* @__PURE__ */ jsx4(Text4, { color: active2 ? theme.accentBright : void 0, children: (active2 ? "\u25B8 " : " ") + label.padEnd(
|
|
9213
|
+
return /* @__PURE__ */ jsxs4(Text4, { wrap: "truncate", children: [
|
|
9214
|
+
/* @__PURE__ */ jsx4(Text4, { color: active2 ? theme.accentBright : void 0, children: (active2 ? "\u25B8 " : " ") + label.padEnd(11) }),
|
|
9223
9215
|
children
|
|
9224
9216
|
] });
|
|
9225
9217
|
}
|
|
9226
|
-
var MODES, FIELDS2,
|
|
9218
|
+
var MODES, FIELDS2, when;
|
|
9227
9219
|
var init_RateLimit = __esm({
|
|
9228
9220
|
"src/tui/panels/RateLimit.tsx"() {
|
|
9229
9221
|
"use strict";
|
|
@@ -9233,7 +9225,10 @@ var init_RateLimit = __esm({
|
|
|
9233
9225
|
init_theme();
|
|
9234
9226
|
MODES = ["off", "detect", "block"];
|
|
9235
9227
|
FIELDS2 = ["mode", "perMinute", "perHour", "perDay"];
|
|
9236
|
-
|
|
9228
|
+
when = (ms) => {
|
|
9229
|
+
const d = new Date(ms);
|
|
9230
|
+
return Number.isNaN(d.getTime()) ? "\u2014" : d.toLocaleDateString([], { month: "short", day: "numeric" }) + " " + d.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", hour12: false });
|
|
9231
|
+
};
|
|
9237
9232
|
}
|
|
9238
9233
|
});
|
|
9239
9234
|
|
|
@@ -11211,10 +11206,10 @@ function truncate3(s, n) {
|
|
|
11211
11206
|
function sparkline(values) {
|
|
11212
11207
|
if (values.length === 0) return "";
|
|
11213
11208
|
const max = Math.max(...values, 0);
|
|
11214
|
-
if (max === 0) return
|
|
11215
|
-
return values.map((v) =>
|
|
11209
|
+
if (max === 0) return BLOCKS[0].repeat(values.length);
|
|
11210
|
+
return values.map((v) => BLOCKS[Math.min(BLOCKS.length - 1, Math.round(v / max * (BLOCKS.length - 1)))]).join("");
|
|
11216
11211
|
}
|
|
11217
|
-
var out, err, dim, bold, green, red, yellow, cyan, ANSI, width,
|
|
11212
|
+
var out, err, dim, bold, green, red, yellow, cyan, ANSI, width, BLOCKS;
|
|
11218
11213
|
var init_format = __esm({
|
|
11219
11214
|
"src/commands/format.ts"() {
|
|
11220
11215
|
"use strict";
|
|
@@ -11229,7 +11224,7 @@ var init_format = __esm({
|
|
|
11229
11224
|
cyan = (s) => `${c.cyan}${s}${c.reset}`;
|
|
11230
11225
|
ANSI = /\x1b\[[0-9;]*m/g;
|
|
11231
11226
|
width = (s) => s.replace(ANSI, "").length;
|
|
11232
|
-
|
|
11227
|
+
BLOCKS = ["\u2581", "\u2582", "\u2583", "\u2584", "\u2585", "\u2586", "\u2587", "\u2588"];
|
|
11233
11228
|
}
|
|
11234
11229
|
});
|
|
11235
11230
|
|
package/dist/tui/index.js
CHANGED
|
@@ -2176,17 +2176,12 @@ import { useEffect as useEffect4, useState as useState4 } from "react";
|
|
|
2176
2176
|
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
2177
2177
|
var MODES = ["off", "detect", "block"];
|
|
2178
2178
|
var FIELDS2 = ["mode", "perMinute", "perHour", "perDay"];
|
|
2179
|
-
var
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
return /* @__PURE__ */ jsx4(Text4, { children: v.map((n, i) => {
|
|
2184
|
-
const ch = BLOCKS[Math.min(BLOCKS.length - 1, Math.round(n / max * (BLOCKS.length - 1)))];
|
|
2185
|
-
const over = limit > 0 && n > limit;
|
|
2186
|
-
return /* @__PURE__ */ jsx4(Text4, { color: over ? theme.bad : theme.accent, children: ch }, i);
|
|
2187
|
-
}) });
|
|
2188
|
-
}
|
|
2179
|
+
var when = (ms) => {
|
|
2180
|
+
const d = new Date(ms);
|
|
2181
|
+
return Number.isNaN(d.getTime()) ? "\u2014" : d.toLocaleDateString([], { month: "short", day: "numeric" }) + " " + d.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", hour12: false });
|
|
2182
|
+
};
|
|
2189
2183
|
function RateLimitPanel({ focused }) {
|
|
2184
|
+
const { cols, rows } = usePanelSize();
|
|
2190
2185
|
const layersQ = useLoader(() => api.settings.getSecurityLayers());
|
|
2191
2186
|
const historyQ = useLoader(() => api.settings.getRateLimitHistory());
|
|
2192
2187
|
const insightsQ = useLoader(() => api.stats.securityInsights(7));
|
|
@@ -2200,12 +2195,8 @@ function RateLimitPanel({ focused }) {
|
|
|
2200
2195
|
const adjust = (dir, step) => {
|
|
2201
2196
|
if (!draft) return;
|
|
2202
2197
|
const field = FIELDS2[fi];
|
|
2203
|
-
if (field === "mode") {
|
|
2204
|
-
|
|
2205
|
-
setDraft({ ...draft, mode: MODES[idx] });
|
|
2206
|
-
} else {
|
|
2207
|
-
setDraft({ ...draft, [field]: Math.max(0, draft[field] + dir * step) });
|
|
2208
|
-
}
|
|
2198
|
+
if (field === "mode") setDraft({ ...draft, mode: MODES[(MODES.indexOf(draft.mode) + dir + MODES.length) % MODES.length] });
|
|
2199
|
+
else setDraft({ ...draft, [field]: Math.max(0, draft[field] + dir * step) });
|
|
2209
2200
|
setDirty(true);
|
|
2210
2201
|
setStatus(null);
|
|
2211
2202
|
};
|
|
@@ -2218,6 +2209,7 @@ function RateLimitPanel({ focused }) {
|
|
|
2218
2209
|
setDirty(false);
|
|
2219
2210
|
setStatus("\u2713 Saved");
|
|
2220
2211
|
historyQ.reload();
|
|
2212
|
+
insightsQ.reload();
|
|
2221
2213
|
} catch (e) {
|
|
2222
2214
|
setStatus("\u2717 " + (e instanceof Error ? e.message : String(e)));
|
|
2223
2215
|
}
|
|
@@ -2234,82 +2226,85 @@ function RateLimitPanel({ focused }) {
|
|
|
2234
2226
|
{ isActive: focused }
|
|
2235
2227
|
);
|
|
2236
2228
|
const history = (historyQ.data?.history ?? []).slice().sort((a, b) => b.ts - a.ts);
|
|
2237
|
-
const
|
|
2238
|
-
const
|
|
2239
|
-
const
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
return /* @__PURE__ */ jsxs4(Box4, { marginTop: 1, children: [
|
|
2256
|
-
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: "load " }),
|
|
2257
|
-
/* @__PURE__ */ jsx4(Text4, { color: col, children: "\u2588".repeat(filled) }),
|
|
2258
|
-
/* @__PURE__ */ jsx4(Text4, { color: "#233457", children: "\u2591".repeat(Math.max(0, width - filled)) }),
|
|
2259
|
-
/* @__PURE__ */ jsx4(Text4, { color: col, children: ` ${now}/${draft.perMinute} ` }),
|
|
2260
|
-
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: `(${pct}% this min)` })
|
|
2261
|
-
] });
|
|
2262
|
-
})() : null,
|
|
2263
|
-
dirty || status ? /* @__PURE__ */ jsxs4(Box4, { marginTop: 1, children: [
|
|
2264
|
-
dirty ? /* @__PURE__ */ jsx4(Text4, { color: theme.warn, children: "\u25CF unsaved \u2014 press s to apply " }) : null,
|
|
2265
|
-
status ? /* @__PURE__ */ jsx4(Text4, { color: status.startsWith("\u2717") ? theme.bad : theme.ok, children: status }) : null
|
|
2266
|
-
] }) : null,
|
|
2267
|
-
/* @__PURE__ */ jsxs4(Box4, { marginTop: 1, flexDirection: "column", children: [
|
|
2268
|
-
/* @__PURE__ */ jsxs4(Box4, { children: [
|
|
2269
|
-
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: "Activity " }),
|
|
2270
|
-
bursts > 0 ? /* @__PURE__ */ jsxs4(Text4, { color: theme.bad, children: [
|
|
2271
|
-
bursts,
|
|
2272
|
-
" burst min"
|
|
2273
|
-
] }) : /* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: "no bursts" }),
|
|
2274
|
-
insightsQ.loading && !insightsQ.data ? /* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: " \u2026" }) : null
|
|
2229
|
+
const lastChange = history[0];
|
|
2230
|
+
const peaks = insightsQ.data?.["peaks"] ?? { minute: 0, hour: 0, day: 0 };
|
|
2231
|
+
const anomalies2 = (insightsQ.data?.["anomalies"] ?? []).slice().sort((a, b) => new Date(b.minute).getTime() - new Date(a.minute).getTime());
|
|
2232
|
+
return /* @__PURE__ */ jsx4(DataView, { loading: layersQ.loading && !draft, error: layersQ.error, children: draft ? (() => {
|
|
2233
|
+
const lim = draft.perMinute;
|
|
2234
|
+
const now = insightsQ.data ? insightsQ.data["activity"]?.minute?.slice(-1)[0]?.count ?? 0 : 0;
|
|
2235
|
+
const loadPct = lim > 0 ? Math.min(100, Math.round(now / lim * 100)) : 0;
|
|
2236
|
+
const last24h = (insightsQ.data?.["activity"]?.hour ?? []).reduce((s, b) => s + b.count, 0);
|
|
2237
|
+
const hasLoad = lim > 0;
|
|
2238
|
+
const fixed = 1 + 4 + (hasLoad ? 1 : 0) + 5 + 1 + 1 + 1 + 1 + (dirty || status ? 1 : 0) + 1;
|
|
2239
|
+
const burstBudget = Math.max(1, rows - fixed);
|
|
2240
|
+
const shown = anomalies2.slice(0, burstBudget);
|
|
2241
|
+
const bw = Math.max(10, cols - 30);
|
|
2242
|
+
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", height: rows, overflow: "hidden", children: [
|
|
2243
|
+
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, wrap: "truncate", children: focused ? "\u2191\u2193 field \xB7 \u2190\u2192 \xB11 \xB7 shift+\u2190\u2192 \xB110 \xB7 s save" : "press \u2192 to edit" }),
|
|
2244
|
+
/* @__PURE__ */ jsxs4(FieldRow, { label: "Mode", active: focused && fi === 0, children: [
|
|
2245
|
+
/* @__PURE__ */ jsx4(Text4, { color: modeColor(draft.mode), bold: true, children: draft.mode }),
|
|
2246
|
+
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: draft.mode === "off" ? " no limit" : draft.mode === "detect" ? " flag bursts, never block" : " DENY calls over the limit" })
|
|
2275
2247
|
] }),
|
|
2276
|
-
/* @__PURE__ */
|
|
2277
|
-
|
|
2278
|
-
|
|
2248
|
+
/* @__PURE__ */ jsx4(FieldRow, { label: "Per minute", active: focused && fi === 1, children: /* @__PURE__ */ jsx4(Text4, { bold: true, children: draft.perMinute || "off" }) }),
|
|
2249
|
+
/* @__PURE__ */ jsx4(FieldRow, { label: "Per hour", active: focused && fi === 2, children: /* @__PURE__ */ jsx4(Text4, { bold: true, children: draft.perHour || "off" }) }),
|
|
2250
|
+
/* @__PURE__ */ jsx4(FieldRow, { label: "Per day", active: focused && fi === 3, children: /* @__PURE__ */ jsx4(Text4, { bold: true, children: draft.perDay || "off" }) }),
|
|
2251
|
+
hasLoad ? /* @__PURE__ */ jsxs4(Text4, { wrap: "truncate", children: [
|
|
2252
|
+
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: "load now".padEnd(13) }),
|
|
2253
|
+
/* @__PURE__ */ jsx4(Text4, { color: loadPct >= 100 ? theme.bad : loadPct >= 80 ? theme.warn : theme.ok, children: "\u2588".repeat(Math.min(18, Math.round(now / lim * 18))) }),
|
|
2254
|
+
/* @__PURE__ */ jsx4(Text4, { color: "#233457", children: "\u2591".repeat(Math.max(0, 18 - Math.round(now / lim * 18))) }),
|
|
2255
|
+
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: ` ${now}/${lim} this minute (${loadPct}%)` })
|
|
2256
|
+
] }) : null,
|
|
2257
|
+
/* @__PURE__ */ jsxs4(Text4, { color: theme.accentBright, bold: true, wrap: "truncate", children: [
|
|
2258
|
+
"Busiest 7d",
|
|
2259
|
+
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: " most calls in one window vs your limit" })
|
|
2279
2260
|
] }),
|
|
2280
|
-
/* @__PURE__ */
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2261
|
+
/* @__PURE__ */ jsx4(BusiestRow, { label: "minute", peak: peaks.minute, limit: draft.perMinute }),
|
|
2262
|
+
/* @__PURE__ */ jsx4(BusiestRow, { label: "hour", peak: peaks.hour, limit: draft.perHour }),
|
|
2263
|
+
/* @__PURE__ */ jsx4(BusiestRow, { label: "day", peak: peaks.day, limit: draft.perDay }),
|
|
2264
|
+
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, wrap: "truncate", children: `activity`.padEnd(11) + ` last 24h \xB7 ${last24h} calls \xB7 busiest hour ${peaks.hour}/hr` }),
|
|
2265
|
+
/* @__PURE__ */ jsxs4(Box4, { marginTop: 1, flexDirection: "column", children: [
|
|
2266
|
+
/* @__PURE__ */ jsxs4(Text4, { color: theme.accentBright, bold: true, wrap: "truncate", children: [
|
|
2267
|
+
`Recent bursts 7d${anomalies2.length ? ` (${anomalies2.length})` : ""}`,
|
|
2268
|
+
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: " over the per-minute limit \xB7 Bypassed = detect (not blocked)" })
|
|
2269
|
+
] }),
|
|
2270
|
+
anomalies2.length === 0 ? /* @__PURE__ */ jsxs4(Text4, { color: theme.dim, children: [
|
|
2271
|
+
" ",
|
|
2272
|
+
insightsQ.loading ? "loading\u2026" : "no bursts in the last 7 days"
|
|
2273
|
+
] }) : /* @__PURE__ */ jsx4(
|
|
2274
|
+
Table,
|
|
2275
|
+
{
|
|
2276
|
+
columns: [{ header: "WHEN", width: 13 }, { header: "RESULT", width: 9 }, { header: "CALLS", width: 7 }, { header: "AGENT", width: Math.max(8, bw - 29) }],
|
|
2277
|
+
rows: shown.map((a) => [
|
|
2278
|
+
{ value: when(new Date(a.minute).getTime()), dim: true },
|
|
2279
|
+
{ value: a.blocked ? "Blocked" : "Bypassed", color: a.blocked ? theme.bad : theme.warn },
|
|
2280
|
+
{ value: `${a.count}/${a.limit}`, color: theme.warn },
|
|
2281
|
+
{ value: truncate(a.agent, Math.max(8, bw - 29)), dim: true }
|
|
2282
|
+
])
|
|
2283
|
+
}
|
|
2284
|
+
)
|
|
2289
2285
|
] }),
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
{
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
] }) : null });
|
|
2286
|
+
/* @__PURE__ */ jsxs4(Text4, { wrap: "truncate", children: [
|
|
2287
|
+
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: "limit now " }),
|
|
2288
|
+
/* @__PURE__ */ jsx4(Text4, { children: lim > 0 ? `${lim}/min` : "no per-minute limit" }),
|
|
2289
|
+
lastChange ? /* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: ` \xB7 changed ${when(lastChange.ts)}` }) : null,
|
|
2290
|
+
dirty ? /* @__PURE__ */ jsx4(Text4, { color: theme.warn, children: " \u25CF unsaved (s)" }) : null,
|
|
2291
|
+
status ? /* @__PURE__ */ jsx4(Text4, { color: status.startsWith("\u2717") ? theme.bad : theme.ok, children: " " + status }) : null
|
|
2292
|
+
] })
|
|
2293
|
+
] });
|
|
2294
|
+
})() : null });
|
|
2295
|
+
}
|
|
2296
|
+
function BusiestRow({ label, peak, limit }) {
|
|
2297
|
+
const ctx = limit > 0 ? peak > limit ? `over ${limit}` : peak === limit ? `at limit ${limit}` : `limit ${limit}` : "no limit set";
|
|
2298
|
+
const hot = limit > 0 && peak > limit;
|
|
2299
|
+
return /* @__PURE__ */ jsxs4(Text4, { wrap: "truncate", children: [
|
|
2300
|
+
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: (" " + label).padEnd(11) }),
|
|
2301
|
+
/* @__PURE__ */ jsx4(Text4, { color: hot ? theme.bad : void 0, bold: hot, children: String(peak).padStart(4) + " calls" }),
|
|
2302
|
+
/* @__PURE__ */ jsx4(Text4, { color: hot ? theme.bad : theme.dim, children: " \xB7 " + ctx })
|
|
2303
|
+
] });
|
|
2309
2304
|
}
|
|
2310
2305
|
function FieldRow({ label, active: active2, children }) {
|
|
2311
|
-
return /* @__PURE__ */ jsxs4(
|
|
2312
|
-
/* @__PURE__ */ jsx4(Text4, { color: active2 ? theme.accentBright : void 0, children: (active2 ? "\u25B8 " : " ") + label.padEnd(
|
|
2306
|
+
return /* @__PURE__ */ jsxs4(Text4, { wrap: "truncate", children: [
|
|
2307
|
+
/* @__PURE__ */ jsx4(Text4, { color: active2 ? theme.accentBright : void 0, children: (active2 ? "\u25B8 " : " ") + label.padEnd(11) }),
|
|
2313
2308
|
children
|
|
2314
2309
|
] });
|
|
2315
2310
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solongate/proxy",
|
|
3
|
-
"version": "0.81.
|
|
3
|
+
"version": "0.81.89",
|
|
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": {
|