@solongate/proxy 0.66.0 → 0.66.1
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 +60 -17
- package/dist/tui/index.js +60 -17
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7079,20 +7079,33 @@ function LivePanel({ active: active2 }) {
|
|
|
7079
7079
|
const [buffer, setBuffer] = useState2([]);
|
|
7080
7080
|
const [log6, setLog] = useState2([]);
|
|
7081
7081
|
const seenRef = useRef2(/* @__PURE__ */ new Set());
|
|
7082
|
+
const pausedUntil = useRef2(0);
|
|
7082
7083
|
const pushLog = useCallback2((msg, level = "ok") => {
|
|
7083
7084
|
setLog((prev) => [...prev.slice(-59), { ts: Date.now(), msg, level }]);
|
|
7084
7085
|
}, []);
|
|
7085
|
-
const
|
|
7086
|
+
const onApiError = useCallback2(
|
|
7087
|
+
(e) => {
|
|
7088
|
+
const is429 = e instanceof ApiError && e.status === 429;
|
|
7089
|
+
if (is429 && Date.now() >= pausedUntil.current) {
|
|
7090
|
+
pausedUntil.current = Date.now() + 3e4;
|
|
7091
|
+
pushLog("rate limited by api \xB7 backing off 30s", "warn");
|
|
7092
|
+
} else if (!is429) {
|
|
7093
|
+
pushLog(`api error \xB7 ${truncate2(e instanceof Error ? e.message : String(e), 40)}`, "bad");
|
|
7094
|
+
}
|
|
7095
|
+
},
|
|
7096
|
+
[pushLog]
|
|
7097
|
+
);
|
|
7098
|
+
const paused = () => Date.now() < pausedUntil.current;
|
|
7099
|
+
const pollFeed = useCallback2(async () => {
|
|
7100
|
+
if (paused()) return;
|
|
7086
7101
|
const t0 = Date.now();
|
|
7087
7102
|
try {
|
|
7088
|
-
const
|
|
7103
|
+
const fd = await api.audit.list({ limit: 50 });
|
|
7089
7104
|
const ms = Date.now() - t0;
|
|
7090
|
-
|
|
7091
|
-
setTsData(td);
|
|
7092
|
-
setLat((l) => [...l.slice(-47), ms]);
|
|
7105
|
+
setLat((l) => [...l, ms].slice(-240));
|
|
7093
7106
|
const fresh = fd.entries.filter((e) => !seenRef.current.has(e.id));
|
|
7107
|
+
const firstLoad = seenRef.current.size === 0 && fresh.length > 1;
|
|
7094
7108
|
for (const e of fresh) seenRef.current.add(e.id);
|
|
7095
|
-
const firstLoad = seenRef.current.size === fresh.length && fresh.length > 1;
|
|
7096
7109
|
if (fresh.length) {
|
|
7097
7110
|
setBuffer((prev) => [...prev, ...fresh.sort((a, b) => Date.parse(a.created_at) - Date.parse(b.created_at))].slice(-400));
|
|
7098
7111
|
}
|
|
@@ -7105,19 +7118,47 @@ function LivePanel({ active: active2 }) {
|
|
|
7105
7118
|
denies || dlp ? "bad" : fresh.length ? "warn" : "ok"
|
|
7106
7119
|
);
|
|
7107
7120
|
} catch (e) {
|
|
7108
|
-
|
|
7121
|
+
onApiError(e);
|
|
7122
|
+
}
|
|
7123
|
+
}, [pushLog, onApiError]);
|
|
7124
|
+
const pollMedium = useCallback2(async () => {
|
|
7125
|
+
if (paused()) return;
|
|
7126
|
+
try {
|
|
7127
|
+
setS(await api.stats.get());
|
|
7128
|
+
} catch (e) {
|
|
7129
|
+
onApiError(e);
|
|
7130
|
+
}
|
|
7131
|
+
}, [onApiError]);
|
|
7132
|
+
const pollSlow = useCallback2(async () => {
|
|
7133
|
+
if (paused()) return;
|
|
7134
|
+
try {
|
|
7135
|
+
setTsData(await api.stats.timeseries({ period: "24h" }));
|
|
7136
|
+
} catch (e) {
|
|
7137
|
+
onApiError(e);
|
|
7109
7138
|
}
|
|
7110
|
-
}, [
|
|
7139
|
+
}, [onApiError]);
|
|
7111
7140
|
useEffect2(() => {
|
|
7112
7141
|
if (!active2) return;
|
|
7113
|
-
void
|
|
7114
|
-
|
|
7115
|
-
|
|
7116
|
-
|
|
7142
|
+
void pollFeed();
|
|
7143
|
+
void pollMedium();
|
|
7144
|
+
void pollSlow();
|
|
7145
|
+
const t1 = setInterval(() => void pollFeed(), 4e3);
|
|
7146
|
+
const t2 = setInterval(() => void pollMedium(), 1e4);
|
|
7147
|
+
const t3 = setInterval(() => void pollSlow(), 3e4);
|
|
7148
|
+
return () => {
|
|
7149
|
+
clearInterval(t1);
|
|
7150
|
+
clearInterval(t2);
|
|
7151
|
+
clearInterval(t3);
|
|
7152
|
+
};
|
|
7153
|
+
}, [active2, pollFeed, pollMedium, pollSlow]);
|
|
7117
7154
|
const sessions = useLoader(() => api.agents.live({ limit: 30, includeDeactivated: true }));
|
|
7118
7155
|
const insights = useLoader(() => api.stats.securityInsights(7));
|
|
7119
|
-
usePoll(
|
|
7120
|
-
|
|
7156
|
+
usePoll(() => {
|
|
7157
|
+
if (!paused()) sessions.reload();
|
|
7158
|
+
}, 1e4, active2);
|
|
7159
|
+
usePoll(() => {
|
|
7160
|
+
if (!paused()) insights.reload();
|
|
7161
|
+
}, 3e4, active2);
|
|
7121
7162
|
useEffect2(() => {
|
|
7122
7163
|
const c2 = sessions.data?.counts;
|
|
7123
7164
|
if (c2) pushLog(`sessions ${c2.active}\u25B2 ${c2.idle}\u25CC ${c2.deactivated}\u25CB`);
|
|
@@ -7156,6 +7197,8 @@ function LivePanel({ active: active2 }) {
|
|
|
7156
7197
|
const lastDeny = denials[denials.length - 1];
|
|
7157
7198
|
const latNow = lat[lat.length - 1] ?? 0;
|
|
7158
7199
|
const latAvg = lat.length ? Math.round(lat.reduce((a, b) => a + b, 0) / lat.length) : 0;
|
|
7200
|
+
const latHotAt = Math.max(1500, latAvg * 1.8);
|
|
7201
|
+
const backingOff = Date.now() < pausedUntil.current;
|
|
7159
7202
|
const sess = (sessions.data?.agents ?? []).slice().sort((a, b) => Date.parse(b.last_seen_at) - Date.parse(a.last_seen_at));
|
|
7160
7203
|
const sessCounts = sessions.data?.counts;
|
|
7161
7204
|
const chartH = rows >= 36 ? 6 : 4;
|
|
@@ -7171,7 +7214,7 @@ function LivePanel({ active: active2 }) {
|
|
|
7171
7214
|
/* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
|
|
7172
7215
|
/* @__PURE__ */ jsx2(Text2, { backgroundColor: "#1432A0", color: "#AAC8FA", bold: true, children: " \u26E8 SOLONGATE LIVE " }),
|
|
7173
7216
|
/* @__PURE__ */ jsx2(Text2, { backgroundColor: BG, color: "#82AAF0", children: ` ${spin} up ${fmtUp(Date.now() - startRef.current)} \xB7 ${hhmmss(Date.now())} \xB7 api ${latNow}ms ` }),
|
|
7174
|
-
lastDeny ? /* @__PURE__ */ jsx2(Text2, { backgroundColor: "#3d1220", color: "#ff6b6b", bold: true, children: ` \u26A0 ${hhmmss(lastDeny.created_at)} ${lastDeny.tool_name} DENIED ` }) : /* @__PURE__ */ jsx2(Text2, { backgroundColor: BG, color: "#4f6db8", children: " \u2713 clean " })
|
|
7217
|
+
backingOff ? /* @__PURE__ */ jsx2(Text2, { backgroundColor: "#3d2a12", color: "#ffb454", bold: true, children: " \u23F8 RATE LIMITED \xB7 backing off " }) : lastDeny ? /* @__PURE__ */ jsx2(Text2, { backgroundColor: "#3d1220", color: "#ff6b6b", bold: true, children: ` \u26A0 ${hhmmss(lastDeny.created_at)} ${lastDeny.tool_name} DENIED ` }) : /* @__PURE__ */ jsx2(Text2, { backgroundColor: BG, color: "#4f6db8", children: " \u2713 clean " })
|
|
7175
7218
|
] }),
|
|
7176
7219
|
/* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
|
|
7177
7220
|
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: "\u2502 calls " }),
|
|
@@ -7196,8 +7239,8 @@ function LivePanel({ active: active2 }) {
|
|
|
7196
7239
|
/* @__PURE__ */ jsx2(ColumnChart, { series: traffic, hot: trafficHot, height: chartH, width: leftW, color: theme.accent })
|
|
7197
7240
|
] }),
|
|
7198
7241
|
/* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", width: rightW, children: [
|
|
7199
|
-
/* @__PURE__ */ jsx2(PaneTitle, { label: "API LATENCY", extra: `live \xB7 now ${latNow}ms \xB7 avg ${latAvg}ms`, width: rightW }),
|
|
7200
|
-
/* @__PURE__ */ jsx2(ColumnChart, { series: lat, hot: lat.map((v) => v >
|
|
7242
|
+
/* @__PURE__ */ jsx2(PaneTitle, { label: "API LATENCY", extra: `live \xB7 now ${latNow}ms \xB7 avg ${latAvg}ms \xB7 red >${Math.round(latHotAt)}ms`, width: rightW }),
|
|
7243
|
+
/* @__PURE__ */ jsx2(ColumnChart, { series: lat, hot: lat.map((v) => v > latHotAt), height: chartH, width: rightW, color: "#82AAF0" })
|
|
7201
7244
|
] })
|
|
7202
7245
|
] }),
|
|
7203
7246
|
/* @__PURE__ */ jsxs2(Box2, { children: [
|
package/dist/tui/index.js
CHANGED
|
@@ -499,20 +499,33 @@ function LivePanel({ active: active2 }) {
|
|
|
499
499
|
const [buffer, setBuffer] = useState2([]);
|
|
500
500
|
const [log, setLog] = useState2([]);
|
|
501
501
|
const seenRef = useRef2(/* @__PURE__ */ new Set());
|
|
502
|
+
const pausedUntil = useRef2(0);
|
|
502
503
|
const pushLog = useCallback2((msg, level = "ok") => {
|
|
503
504
|
setLog((prev) => [...prev.slice(-59), { ts: Date.now(), msg, level }]);
|
|
504
505
|
}, []);
|
|
505
|
-
const
|
|
506
|
+
const onApiError = useCallback2(
|
|
507
|
+
(e) => {
|
|
508
|
+
const is429 = e instanceof ApiError && e.status === 429;
|
|
509
|
+
if (is429 && Date.now() >= pausedUntil.current) {
|
|
510
|
+
pausedUntil.current = Date.now() + 3e4;
|
|
511
|
+
pushLog("rate limited by api \xB7 backing off 30s", "warn");
|
|
512
|
+
} else if (!is429) {
|
|
513
|
+
pushLog(`api error \xB7 ${truncate(e instanceof Error ? e.message : String(e), 40)}`, "bad");
|
|
514
|
+
}
|
|
515
|
+
},
|
|
516
|
+
[pushLog]
|
|
517
|
+
);
|
|
518
|
+
const paused = () => Date.now() < pausedUntil.current;
|
|
519
|
+
const pollFeed = useCallback2(async () => {
|
|
520
|
+
if (paused()) return;
|
|
506
521
|
const t0 = Date.now();
|
|
507
522
|
try {
|
|
508
|
-
const
|
|
523
|
+
const fd = await api.audit.list({ limit: 50 });
|
|
509
524
|
const ms = Date.now() - t0;
|
|
510
|
-
|
|
511
|
-
setTsData(td);
|
|
512
|
-
setLat((l) => [...l.slice(-47), ms]);
|
|
525
|
+
setLat((l) => [...l, ms].slice(-240));
|
|
513
526
|
const fresh = fd.entries.filter((e) => !seenRef.current.has(e.id));
|
|
527
|
+
const firstLoad = seenRef.current.size === 0 && fresh.length > 1;
|
|
514
528
|
for (const e of fresh) seenRef.current.add(e.id);
|
|
515
|
-
const firstLoad = seenRef.current.size === fresh.length && fresh.length > 1;
|
|
516
529
|
if (fresh.length) {
|
|
517
530
|
setBuffer((prev) => [...prev, ...fresh.sort((a, b) => Date.parse(a.created_at) - Date.parse(b.created_at))].slice(-400));
|
|
518
531
|
}
|
|
@@ -525,19 +538,47 @@ function LivePanel({ active: active2 }) {
|
|
|
525
538
|
denies || dlp ? "bad" : fresh.length ? "warn" : "ok"
|
|
526
539
|
);
|
|
527
540
|
} catch (e) {
|
|
528
|
-
|
|
541
|
+
onApiError(e);
|
|
542
|
+
}
|
|
543
|
+
}, [pushLog, onApiError]);
|
|
544
|
+
const pollMedium = useCallback2(async () => {
|
|
545
|
+
if (paused()) return;
|
|
546
|
+
try {
|
|
547
|
+
setS(await api.stats.get());
|
|
548
|
+
} catch (e) {
|
|
549
|
+
onApiError(e);
|
|
550
|
+
}
|
|
551
|
+
}, [onApiError]);
|
|
552
|
+
const pollSlow = useCallback2(async () => {
|
|
553
|
+
if (paused()) return;
|
|
554
|
+
try {
|
|
555
|
+
setTsData(await api.stats.timeseries({ period: "24h" }));
|
|
556
|
+
} catch (e) {
|
|
557
|
+
onApiError(e);
|
|
529
558
|
}
|
|
530
|
-
}, [
|
|
559
|
+
}, [onApiError]);
|
|
531
560
|
useEffect2(() => {
|
|
532
561
|
if (!active2) return;
|
|
533
|
-
void
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
562
|
+
void pollFeed();
|
|
563
|
+
void pollMedium();
|
|
564
|
+
void pollSlow();
|
|
565
|
+
const t1 = setInterval(() => void pollFeed(), 4e3);
|
|
566
|
+
const t2 = setInterval(() => void pollMedium(), 1e4);
|
|
567
|
+
const t3 = setInterval(() => void pollSlow(), 3e4);
|
|
568
|
+
return () => {
|
|
569
|
+
clearInterval(t1);
|
|
570
|
+
clearInterval(t2);
|
|
571
|
+
clearInterval(t3);
|
|
572
|
+
};
|
|
573
|
+
}, [active2, pollFeed, pollMedium, pollSlow]);
|
|
537
574
|
const sessions = useLoader(() => api.agents.live({ limit: 30, includeDeactivated: true }));
|
|
538
575
|
const insights = useLoader(() => api.stats.securityInsights(7));
|
|
539
|
-
usePoll(
|
|
540
|
-
|
|
576
|
+
usePoll(() => {
|
|
577
|
+
if (!paused()) sessions.reload();
|
|
578
|
+
}, 1e4, active2);
|
|
579
|
+
usePoll(() => {
|
|
580
|
+
if (!paused()) insights.reload();
|
|
581
|
+
}, 3e4, active2);
|
|
541
582
|
useEffect2(() => {
|
|
542
583
|
const c2 = sessions.data?.counts;
|
|
543
584
|
if (c2) pushLog(`sessions ${c2.active}\u25B2 ${c2.idle}\u25CC ${c2.deactivated}\u25CB`);
|
|
@@ -576,6 +617,8 @@ function LivePanel({ active: active2 }) {
|
|
|
576
617
|
const lastDeny = denials[denials.length - 1];
|
|
577
618
|
const latNow = lat[lat.length - 1] ?? 0;
|
|
578
619
|
const latAvg = lat.length ? Math.round(lat.reduce((a, b) => a + b, 0) / lat.length) : 0;
|
|
620
|
+
const latHotAt = Math.max(1500, latAvg * 1.8);
|
|
621
|
+
const backingOff = Date.now() < pausedUntil.current;
|
|
579
622
|
const sess = (sessions.data?.agents ?? []).slice().sort((a, b) => Date.parse(b.last_seen_at) - Date.parse(a.last_seen_at));
|
|
580
623
|
const sessCounts = sessions.data?.counts;
|
|
581
624
|
const chartH = rows >= 36 ? 6 : 4;
|
|
@@ -591,7 +634,7 @@ function LivePanel({ active: active2 }) {
|
|
|
591
634
|
/* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
|
|
592
635
|
/* @__PURE__ */ jsx2(Text2, { backgroundColor: "#1432A0", color: "#AAC8FA", bold: true, children: " \u26E8 SOLONGATE LIVE " }),
|
|
593
636
|
/* @__PURE__ */ jsx2(Text2, { backgroundColor: BG, color: "#82AAF0", children: ` ${spin} up ${fmtUp(Date.now() - startRef.current)} \xB7 ${hhmmss(Date.now())} \xB7 api ${latNow}ms ` }),
|
|
594
|
-
lastDeny ? /* @__PURE__ */ jsx2(Text2, { backgroundColor: "#3d1220", color: "#ff6b6b", bold: true, children: ` \u26A0 ${hhmmss(lastDeny.created_at)} ${lastDeny.tool_name} DENIED ` }) : /* @__PURE__ */ jsx2(Text2, { backgroundColor: BG, color: "#4f6db8", children: " \u2713 clean " })
|
|
637
|
+
backingOff ? /* @__PURE__ */ jsx2(Text2, { backgroundColor: "#3d2a12", color: "#ffb454", bold: true, children: " \u23F8 RATE LIMITED \xB7 backing off " }) : lastDeny ? /* @__PURE__ */ jsx2(Text2, { backgroundColor: "#3d1220", color: "#ff6b6b", bold: true, children: ` \u26A0 ${hhmmss(lastDeny.created_at)} ${lastDeny.tool_name} DENIED ` }) : /* @__PURE__ */ jsx2(Text2, { backgroundColor: BG, color: "#4f6db8", children: " \u2713 clean " })
|
|
595
638
|
] }),
|
|
596
639
|
/* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
|
|
597
640
|
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: "\u2502 calls " }),
|
|
@@ -616,8 +659,8 @@ function LivePanel({ active: active2 }) {
|
|
|
616
659
|
/* @__PURE__ */ jsx2(ColumnChart, { series: traffic, hot: trafficHot, height: chartH, width: leftW, color: theme.accent })
|
|
617
660
|
] }),
|
|
618
661
|
/* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", width: rightW, children: [
|
|
619
|
-
/* @__PURE__ */ jsx2(PaneTitle, { label: "API LATENCY", extra: `live \xB7 now ${latNow}ms \xB7 avg ${latAvg}ms`, width: rightW }),
|
|
620
|
-
/* @__PURE__ */ jsx2(ColumnChart, { series: lat, hot: lat.map((v) => v >
|
|
662
|
+
/* @__PURE__ */ jsx2(PaneTitle, { label: "API LATENCY", extra: `live \xB7 now ${latNow}ms \xB7 avg ${latAvg}ms \xB7 red >${Math.round(latHotAt)}ms`, width: rightW }),
|
|
663
|
+
/* @__PURE__ */ jsx2(ColumnChart, { series: lat, hot: lat.map((v) => v > latHotAt), height: chartH, width: rightW, color: "#82AAF0" })
|
|
621
664
|
] })
|
|
622
665
|
] }),
|
|
623
666
|
/* @__PURE__ */ jsxs2(Box2, { children: [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solongate/proxy",
|
|
3
|
-
"version": "0.66.
|
|
3
|
+
"version": "0.66.1",
|
|
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": {
|