@solongate/proxy 0.81.96 → 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 CHANGED
@@ -9111,9 +9111,8 @@ 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 [fi, setFi] = useState4(0);
9114
+ const [sel, setSel] = useState4(0);
9115
9115
  const [status, setStatus] = useState4(null);
9116
- const [burstOff, setBurstOff] = useState4(0);
9117
9116
  useEffect4(() => {
9118
9117
  if (layersQ.data && !dirty) setDraft({ ...layersQ.data.layers.rateLimit });
9119
9118
  }, [layersQ.data]);
@@ -9125,7 +9124,7 @@ function RateLimitPanel({ focused }) {
9125
9124
  insightsQ.reloadQuiet();
9126
9125
  }, 1e4);
9127
9126
  const adjust = (dir, step) => {
9128
- if (!draft) return;
9127
+ if (!draft || fi < 0) return;
9129
9128
  const field = FIELDS2[fi];
9130
9129
  if (field === "mode") setDraft({ ...draft, mode: MODES[(MODES.indexOf(draft.mode) + dir + MODES.length) % MODES.length] });
9131
9130
  else setDraft({ ...draft, [field]: Math.max(0, draft[field] + dir * step) });
@@ -9156,14 +9155,19 @@ function RateLimitPanel({ focused }) {
9156
9155
  const fixed = 1 + 4 + (showExtras ? (hasLoad ? 1 : 0) + 5 : 0) + 1 + 1 + 1 + 1;
9157
9156
  const burstBudget = Math.max(1, rows - fixed);
9158
9157
  const maxOff = Math.max(0, anomalies2.length - burstBudget);
9159
- const off = Math.min(burstOff, maxOff);
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);
9160
9164
  useInput3(
9161
9165
  (input, key) => {
9162
9166
  const step = key.shift ? 10 : 1;
9163
- if (key.pageDown) setBurstOff((o) => Math.min(o + burstBudget, maxOff));
9164
- else if (key.pageUp) setBurstOff((o) => Math.max(0, o - burstBudget));
9165
- else if (key.upArrow) setFi((n) => (n - 1 + FIELDS2.length) % FIELDS2.length);
9166
- else if (key.downArrow) setFi((n) => (n + 1) % FIELDS2.length);
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));
9167
9171
  else if (key.leftArrow) adjust(-1, step);
9168
9172
  else if (key.rightArrow) adjust(1, step);
9169
9173
  else if (input === "s") void save();
@@ -9184,7 +9188,7 @@ function RateLimitPanel({ focused }) {
9184
9188
  const shown = anomalies2.slice(off, off + burstBudget);
9185
9189
  const bw = Math.max(10, cols - 30);
9186
9190
  return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", height: rows, overflow: "hidden", children: [
9187
- /* @__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 \xB7 ^R refresh${maxOff > 0 ? " \xB7 PgUp/PgDn bursts" : ""}` : "press \u2192 to edit" }),
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" }),
9188
9192
  /* @__PURE__ */ jsxs4(FieldRow, { label: "Mode", active: focused && fi === 0, children: [
9189
9193
  /* @__PURE__ */ jsx4(Text4, { color: modeColor(draft.mode), bold: true, children: draft.mode }),
9190
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" })
@@ -9220,13 +9224,16 @@ function RateLimitPanel({ focused }) {
9220
9224
  ] }) : /* @__PURE__ */ jsx4(
9221
9225
  Table,
9222
9226
  {
9223
- columns: [{ header: "WHEN", width: 13 }, { header: "RESULT", width: 9 }, { header: "CALLS", width: 7 }, { header: "AGENT", width: Math.max(8, bw - 29) }],
9224
- rows: shown.map((a) => [
9225
- { value: when(new Date(a.minute).getTime()), dim: true },
9226
- { value: a.blocked ? "Blocked" : "Bypassed", color: a.blocked ? theme.bad : theme.warn },
9227
- { value: `${a.count}/${a.limit}`, color: theme.warn },
9228
- { value: truncate2(a.agent, Math.max(8, bw - 29)), dim: true }
9229
- ])
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
+ })
9230
9237
  }
9231
9238
  )
9232
9239
  ] }),
package/dist/tui/index.js CHANGED
@@ -2199,9 +2199,8 @@ 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 [fi, setFi] = useState4(0);
2202
+ const [sel, setSel] = useState4(0);
2203
2203
  const [status, setStatus] = useState4(null);
2204
- const [burstOff, setBurstOff] = useState4(0);
2205
2204
  useEffect4(() => {
2206
2205
  if (layersQ.data && !dirty) setDraft({ ...layersQ.data.layers.rateLimit });
2207
2206
  }, [layersQ.data]);
@@ -2213,7 +2212,7 @@ function RateLimitPanel({ focused }) {
2213
2212
  insightsQ.reloadQuiet();
2214
2213
  }, 1e4);
2215
2214
  const adjust = (dir, step) => {
2216
- if (!draft) return;
2215
+ if (!draft || fi < 0) return;
2217
2216
  const field = FIELDS2[fi];
2218
2217
  if (field === "mode") setDraft({ ...draft, mode: MODES[(MODES.indexOf(draft.mode) + dir + MODES.length) % MODES.length] });
2219
2218
  else setDraft({ ...draft, [field]: Math.max(0, draft[field] + dir * step) });
@@ -2244,14 +2243,19 @@ function RateLimitPanel({ focused }) {
2244
2243
  const fixed = 1 + 4 + (showExtras ? (hasLoad ? 1 : 0) + 5 : 0) + 1 + 1 + 1 + 1;
2245
2244
  const burstBudget = Math.max(1, rows - fixed);
2246
2245
  const maxOff = Math.max(0, anomalies2.length - burstBudget);
2247
- const off = Math.min(burstOff, maxOff);
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);
2248
2252
  useInput3(
2249
2253
  (input, key) => {
2250
2254
  const step = key.shift ? 10 : 1;
2251
- if (key.pageDown) setBurstOff((o) => Math.min(o + burstBudget, maxOff));
2252
- else if (key.pageUp) setBurstOff((o) => Math.max(0, o - burstBudget));
2253
- else if (key.upArrow) setFi((n) => (n - 1 + FIELDS2.length) % FIELDS2.length);
2254
- else if (key.downArrow) setFi((n) => (n + 1) % FIELDS2.length);
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));
2255
2259
  else if (key.leftArrow) adjust(-1, step);
2256
2260
  else if (key.rightArrow) adjust(1, step);
2257
2261
  else if (input === "s") void save();
@@ -2272,7 +2276,7 @@ function RateLimitPanel({ focused }) {
2272
2276
  const shown = anomalies2.slice(off, off + burstBudget);
2273
2277
  const bw = Math.max(10, cols - 30);
2274
2278
  return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", height: rows, overflow: "hidden", children: [
2275
- /* @__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 \xB7 ^R refresh${maxOff > 0 ? " \xB7 PgUp/PgDn bursts" : ""}` : "press \u2192 to edit" }),
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" }),
2276
2280
  /* @__PURE__ */ jsxs4(FieldRow, { label: "Mode", active: focused && fi === 0, children: [
2277
2281
  /* @__PURE__ */ jsx4(Text4, { color: modeColor(draft.mode), bold: true, children: draft.mode }),
2278
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" })
@@ -2308,13 +2312,16 @@ function RateLimitPanel({ focused }) {
2308
2312
  ] }) : /* @__PURE__ */ jsx4(
2309
2313
  Table,
2310
2314
  {
2311
- columns: [{ header: "WHEN", width: 13 }, { header: "RESULT", width: 9 }, { header: "CALLS", width: 7 }, { header: "AGENT", width: Math.max(8, bw - 29) }],
2312
- rows: shown.map((a) => [
2313
- { value: when(new Date(a.minute).getTime()), dim: true },
2314
- { value: a.blocked ? "Blocked" : "Bypassed", color: a.blocked ? theme.bad : theme.warn },
2315
- { value: `${a.count}/${a.limit}`, color: theme.warn },
2316
- { value: truncate(a.agent, Math.max(8, bw - 29)), dim: true }
2317
- ])
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
+ })
2318
2325
  }
2319
2326
  )
2320
2327
  ] }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solongate/proxy",
3
- "version": "0.81.96",
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": {