@solongate/proxy 0.76.0 → 0.77.0

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
@@ -7036,7 +7036,7 @@ import { closeSync, openSync, readSync, statSync } from "fs";
7036
7036
  import { homedir as homedir3 } from "os";
7037
7037
  import { join as join5 } from "path";
7038
7038
  import { useCallback as useCallback2, useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
7039
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
7039
+ import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
7040
7040
  function tailLines(file, maxBytes = 131072) {
7041
7041
  try {
7042
7042
  const size = statSync(file).size;
@@ -7414,7 +7414,7 @@ function LivePanel({ active: active2 }) {
7414
7414
  const q = search.trim().toLowerCase();
7415
7415
  const matches = (e) => !q || `${e.tool} ${e.agent ?? ""} ${e.decision} ${e.permission} ${e.rule ?? ""} ${e.detail}`.toLowerCase().includes(q);
7416
7416
  const filtered = (filter === "all" ? mergedAll : mergedAll.filter((e) => filter === "local" ? isLoc(e) : !isLoc(e))).filter(matches);
7417
- const visibleDesc = filtered.slice(-STREAM_KEEP).reverse();
7417
+ const visibleDesc = filtered.slice().reverse();
7418
7418
  const chartH = rows >= 36 ? 6 : 4;
7419
7419
  const colH = rows >= 32 ? 7 : 5;
7420
7420
  const streamRows = Math.max(4, rows - 5 - (1 + chartH) - colH);
@@ -7423,9 +7423,10 @@ function LivePanel({ active: active2 }) {
7423
7423
  const rightW = innerW - leftW - 2;
7424
7424
  const colW = Math.max(20, Math.floor((innerW - 4) / 3));
7425
7425
  const pickable = combinedSess.slice(0, colH - 1);
7426
- const maxScroll = Math.max(0, visibleDesc.length - streamRows);
7426
+ const streamBodyRows = Math.max(3, streamRows - 1);
7427
+ const maxScroll = Math.max(0, visibleDesc.length - streamBodyRows);
7427
7428
  const clampedScroll = Math.min(scroll, maxScroll);
7428
- const windowed = visibleDesc.slice(clampedScroll, clampedScroll + streamRows);
7429
+ const windowed = visibleDesc.slice(clampedScroll, clampedScroll + streamBodyRows);
7429
7430
  const detailEntries = detail ? (() => {
7430
7431
  const seen = /* @__PURE__ */ new Set();
7431
7432
  const all = [];
@@ -7484,30 +7485,31 @@ function LivePanel({ active: active2 }) {
7484
7485
  },
7485
7486
  { isActive: active2 && !editingSearch }
7486
7487
  );
7487
- const searchRow = editingSearch ? /* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
7488
- /* @__PURE__ */ jsx2(Text2, { color: theme.warn, children: "search: " }),
7489
- /* @__PURE__ */ jsx2(
7490
- TextInput,
7491
- {
7492
- value: search,
7493
- onChange: (v) => {
7494
- if (v.endsWith("/")) {
7495
- setEditingSearch(false);
7496
- return;
7497
- }
7498
- setSearch(v);
7499
- setScroll(0);
7500
- setDetailScroll(0);
7501
- },
7502
- onSubmit: () => setEditingSearch(false)
7503
- }
7504
- ),
7505
- /* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: " (enter/\u200B/ done \xB7 empty = clear)" })
7506
- ] }) : search ? /* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
7507
- /* @__PURE__ */ jsx2(Text2, { color: theme.warn, children: "search: " }),
7508
- /* @__PURE__ */ jsx2(Text2, { color: theme.accentBright, bold: true, children: search }),
7509
- /* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: ` ${filtered.length} match \xB7 / edit` })
7510
- ] }) : null;
7488
+ const searchRow = /* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
7489
+ /* @__PURE__ */ jsx2(Text2, { color: editingSearch ? theme.warn : theme.dim, bold: editingSearch, children: editingSearch ? "\u2315 search: " : "\u2315 search: " }),
7490
+ editingSearch ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
7491
+ /* @__PURE__ */ jsx2(
7492
+ TextInput,
7493
+ {
7494
+ value: search,
7495
+ onChange: (v) => {
7496
+ if (v.endsWith("/")) {
7497
+ setEditingSearch(false);
7498
+ return;
7499
+ }
7500
+ setSearch(v);
7501
+ setScroll(0);
7502
+ setDetailScroll(0);
7503
+ },
7504
+ onSubmit: () => setEditingSearch(false)
7505
+ }
7506
+ ),
7507
+ /* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: ` ${filtered.length} match \xB7 enter/\u200B/ done \xB7 empty clears` })
7508
+ ] }) : search ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
7509
+ /* @__PURE__ */ jsx2(Text2, { color: theme.accentBright, bold: true, children: search }),
7510
+ /* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: ` ${filtered.length} match \xB7 press / to edit \xB7 type to clear` })
7511
+ ] }) : /* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: "press / to filter the stream by tool, agent, command\u2026" })
7512
+ ] });
7511
7513
  const sessionDot = (st) => st === "active" ? { ch: "\u25CF", color: theme.ok } : st === "idle" ? { ch: "\u25CC", color: theme.warn } : { ch: "\u25CB", color: theme.dim };
7512
7514
  void sessionDot;
7513
7515
  if (s === null && localOn === null) {
@@ -7539,9 +7541,10 @@ function LivePanel({ active: active2 }) {
7539
7541
  const first = d[d.length - 1]?.at;
7540
7542
  const last = d[0]?.at;
7541
7543
  const tlRows = Math.max(4, rows - 10);
7542
- const maxD = Math.max(0, d.length - tlRows);
7544
+ const tlBody = Math.max(3, tlRows - 1);
7545
+ const maxD = Math.max(0, d.length - tlBody);
7543
7546
  const dScroll = Math.min(detailScroll, maxD);
7544
- const tl = d.slice(dScroll, dScroll + tlRows);
7547
+ const tl = d.slice(dScroll, dScroll + tlBody);
7545
7548
  return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", paddingX: 1, children: [
7546
7549
  titleBar,
7547
7550
  /* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
@@ -7690,11 +7693,11 @@ function LivePanel({ active: active2 }) {
7690
7693
  PaneTitle,
7691
7694
  {
7692
7695
  label: "TOOL STREAM",
7693
- extra: `newest first \xB7 last ${STREAM_KEEP} \xB7 filter ${filter}${clampedScroll > 0 ? ` \xB7 \u25BC${clampedScroll} older` : ""} \xB7 f filter \xB7 / search \xB7 \u2191\u2193 scroll \xB7 s sessions`,
7696
+ extra: `${visibleDesc.length} entries${q ? " matched" : ""} \xB7 newest first \xB7 filter ${filter}${clampedScroll > 0 ? ` \xB7 \u25BC${clampedScroll} older` : ""} \xB7 f \xB7 / \xB7 \u2191\u2193 \xB7 s`,
7694
7697
  width: innerW
7695
7698
  }
7696
7699
  ),
7697
- /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", height: searchRow ? streamRows - 1 : streamRows, overflow: "hidden", children: [
7700
+ /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", height: streamRows, overflow: "hidden", children: [
7698
7701
  searchRow,
7699
7702
  localOn === false ? /* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
7700
7703
  /* @__PURE__ */ jsx2(Text2, { color: theme.warn, children: "local logs off" }),
@@ -7713,7 +7716,7 @@ function LivePanel({ active: active2 }) {
7713
7716
  ] })
7714
7717
  ] });
7715
7718
  }
7716
- var SPIN, BG, DIM_FLOOR, LOCAL_LOG, RING, STREAM_KEEP, hhmmss, fmtUp, FILTERS, sessStatus, STATUS_STYLE;
7719
+ var SPIN, BG, DIM_FLOOR, LOCAL_LOG, RING, hhmmss, fmtUp, FILTERS, sessStatus, STATUS_STYLE;
7717
7720
  var init_Live = __esm({
7718
7721
  "src/tui/panels/Live.tsx"() {
7719
7722
  "use strict";
@@ -7725,7 +7728,6 @@ var init_Live = __esm({
7725
7728
  DIM_FLOOR = "#233457";
7726
7729
  LOCAL_LOG = join5(homedir3(), ".solongate", "local-logs", "solongate-audit.jsonl");
7727
7730
  RING = join5(process.cwd(), ".solongate", ".eval-ring.jsonl");
7728
- STREAM_KEEP = 100;
7729
7731
  hhmmss = (ts) => {
7730
7732
  const d = new Date(ts);
7731
7733
  return Number.isNaN(d.getTime()) ? "--:--:--" : d.toTimeString().slice(0, 8);
package/dist/tui/index.js CHANGED
@@ -445,13 +445,12 @@ function usePoll(reload, intervalMs, enabled = true) {
445
445
  }
446
446
 
447
447
  // src/tui/panels/Live.tsx
448
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
448
+ import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
449
449
  var SPIN = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
450
450
  var BG = "#12234f";
451
451
  var DIM_FLOOR = "#233457";
452
452
  var LOCAL_LOG = join2(homedir2(), ".solongate", "local-logs", "solongate-audit.jsonl");
453
453
  var RING = join2(process.cwd(), ".solongate", ".eval-ring.jsonl");
454
- var STREAM_KEEP = 100;
455
454
  var hhmmss = (ts) => {
456
455
  const d = new Date(ts);
457
456
  return Number.isNaN(d.getTime()) ? "--:--:--" : d.toTimeString().slice(0, 8);
@@ -845,7 +844,7 @@ function LivePanel({ active: active2 }) {
845
844
  const q = search.trim().toLowerCase();
846
845
  const matches = (e) => !q || `${e.tool} ${e.agent ?? ""} ${e.decision} ${e.permission} ${e.rule ?? ""} ${e.detail}`.toLowerCase().includes(q);
847
846
  const filtered = (filter === "all" ? mergedAll : mergedAll.filter((e) => filter === "local" ? isLoc(e) : !isLoc(e))).filter(matches);
848
- const visibleDesc = filtered.slice(-STREAM_KEEP).reverse();
847
+ const visibleDesc = filtered.slice().reverse();
849
848
  const chartH = rows >= 36 ? 6 : 4;
850
849
  const colH = rows >= 32 ? 7 : 5;
851
850
  const streamRows = Math.max(4, rows - 5 - (1 + chartH) - colH);
@@ -854,9 +853,10 @@ function LivePanel({ active: active2 }) {
854
853
  const rightW = innerW - leftW - 2;
855
854
  const colW = Math.max(20, Math.floor((innerW - 4) / 3));
856
855
  const pickable = combinedSess.slice(0, colH - 1);
857
- const maxScroll = Math.max(0, visibleDesc.length - streamRows);
856
+ const streamBodyRows = Math.max(3, streamRows - 1);
857
+ const maxScroll = Math.max(0, visibleDesc.length - streamBodyRows);
858
858
  const clampedScroll = Math.min(scroll, maxScroll);
859
- const windowed = visibleDesc.slice(clampedScroll, clampedScroll + streamRows);
859
+ const windowed = visibleDesc.slice(clampedScroll, clampedScroll + streamBodyRows);
860
860
  const detailEntries = detail ? (() => {
861
861
  const seen = /* @__PURE__ */ new Set();
862
862
  const all = [];
@@ -915,30 +915,31 @@ function LivePanel({ active: active2 }) {
915
915
  },
916
916
  { isActive: active2 && !editingSearch }
917
917
  );
918
- const searchRow = editingSearch ? /* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
919
- /* @__PURE__ */ jsx2(Text2, { color: theme.warn, children: "search: " }),
920
- /* @__PURE__ */ jsx2(
921
- TextInput,
922
- {
923
- value: search,
924
- onChange: (v) => {
925
- if (v.endsWith("/")) {
926
- setEditingSearch(false);
927
- return;
928
- }
929
- setSearch(v);
930
- setScroll(0);
931
- setDetailScroll(0);
932
- },
933
- onSubmit: () => setEditingSearch(false)
934
- }
935
- ),
936
- /* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: " (enter/\u200B/ done \xB7 empty = clear)" })
937
- ] }) : search ? /* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
938
- /* @__PURE__ */ jsx2(Text2, { color: theme.warn, children: "search: " }),
939
- /* @__PURE__ */ jsx2(Text2, { color: theme.accentBright, bold: true, children: search }),
940
- /* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: ` ${filtered.length} match \xB7 / edit` })
941
- ] }) : null;
918
+ const searchRow = /* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
919
+ /* @__PURE__ */ jsx2(Text2, { color: editingSearch ? theme.warn : theme.dim, bold: editingSearch, children: editingSearch ? "\u2315 search: " : "\u2315 search: " }),
920
+ editingSearch ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
921
+ /* @__PURE__ */ jsx2(
922
+ TextInput,
923
+ {
924
+ value: search,
925
+ onChange: (v) => {
926
+ if (v.endsWith("/")) {
927
+ setEditingSearch(false);
928
+ return;
929
+ }
930
+ setSearch(v);
931
+ setScroll(0);
932
+ setDetailScroll(0);
933
+ },
934
+ onSubmit: () => setEditingSearch(false)
935
+ }
936
+ ),
937
+ /* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: ` ${filtered.length} match \xB7 enter/\u200B/ done \xB7 empty clears` })
938
+ ] }) : search ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
939
+ /* @__PURE__ */ jsx2(Text2, { color: theme.accentBright, bold: true, children: search }),
940
+ /* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: ` ${filtered.length} match \xB7 press / to edit \xB7 type to clear` })
941
+ ] }) : /* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: "press / to filter the stream by tool, agent, command\u2026" })
942
+ ] });
942
943
  const sessionDot = (st) => st === "active" ? { ch: "\u25CF", color: theme.ok } : st === "idle" ? { ch: "\u25CC", color: theme.warn } : { ch: "\u25CB", color: theme.dim };
943
944
  void sessionDot;
944
945
  if (s === null && localOn === null) {
@@ -970,9 +971,10 @@ function LivePanel({ active: active2 }) {
970
971
  const first = d[d.length - 1]?.at;
971
972
  const last = d[0]?.at;
972
973
  const tlRows = Math.max(4, rows - 10);
973
- const maxD = Math.max(0, d.length - tlRows);
974
+ const tlBody = Math.max(3, tlRows - 1);
975
+ const maxD = Math.max(0, d.length - tlBody);
974
976
  const dScroll = Math.min(detailScroll, maxD);
975
- const tl = d.slice(dScroll, dScroll + tlRows);
977
+ const tl = d.slice(dScroll, dScroll + tlBody);
976
978
  return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", paddingX: 1, children: [
977
979
  titleBar,
978
980
  /* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
@@ -1121,11 +1123,11 @@ function LivePanel({ active: active2 }) {
1121
1123
  PaneTitle,
1122
1124
  {
1123
1125
  label: "TOOL STREAM",
1124
- extra: `newest first \xB7 last ${STREAM_KEEP} \xB7 filter ${filter}${clampedScroll > 0 ? ` \xB7 \u25BC${clampedScroll} older` : ""} \xB7 f filter \xB7 / search \xB7 \u2191\u2193 scroll \xB7 s sessions`,
1126
+ extra: `${visibleDesc.length} entries${q ? " matched" : ""} \xB7 newest first \xB7 filter ${filter}${clampedScroll > 0 ? ` \xB7 \u25BC${clampedScroll} older` : ""} \xB7 f \xB7 / \xB7 \u2191\u2193 \xB7 s`,
1125
1127
  width: innerW
1126
1128
  }
1127
1129
  ),
1128
- /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", height: searchRow ? streamRows - 1 : streamRows, overflow: "hidden", children: [
1130
+ /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", height: streamRows, overflow: "hidden", children: [
1129
1131
  searchRow,
1130
1132
  localOn === false ? /* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
1131
1133
  /* @__PURE__ */ jsx2(Text2, { color: theme.warn, children: "local logs off" }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solongate/proxy",
3
- "version": "0.76.0",
3
+ "version": "0.77.0",
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": {