@solongate/proxy 0.82.33 → 0.82.34

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
@@ -8918,34 +8918,29 @@ function DryRunPanel({ focused }) {
8918
8918
  }
8919
8919
  }
8920
8920
  }
8921
- const headerRows = 3;
8921
+ const headerRows = 5;
8922
8922
  const budget = Math.max(3, rows - headerRows);
8923
8923
  const maxOff = Math.max(0, lines.length - budget);
8924
8924
  const start = Math.min(off, maxOff);
8925
8925
  const win = lines.slice(start, start + budget);
8926
8926
  const above = start;
8927
8927
  const below = Math.max(0, lines.length - (start + budget));
8928
- const sampleLabel = `${SAMPLES[si]}${res?.sampled != null ? ` (ran ${res.sampled})` : ""}`;
8929
8928
  return /* @__PURE__ */ jsx3(DataView, { loading: list6.loading && !list6.data, error: list6.error, children: /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", children: [
8930
- /* @__PURE__ */ jsxs3(Box3, { children: [
8931
- /* @__PURE__ */ jsx3(Text3, { bold: true, color: theme.accentBright, children: "Policy Dry Run" }),
8932
- /* @__PURE__ */ jsxs3(Text3, { color: theme.dim, children: [
8933
- " ",
8934
- truncate2(selected?.name ?? "no policy", 26)
8935
- ] }),
8936
- /* @__PURE__ */ jsxs3(Text3, { color: theme.dim, children: [
8937
- " mode: ",
8938
- selected?.mode ?? "-"
8939
- ] }),
8940
- /* @__PURE__ */ jsxs3(Text3, { color: theme.dim, children: [
8941
- " sample: ",
8942
- sampleLabel
8943
- ] })
8929
+ /* @__PURE__ */ jsx3(Text3, { bold: true, color: theme.accentBright, children: "Policy Dry Run" }),
8930
+ /* @__PURE__ */ jsxs3(Text3, { wrap: "truncate", children: [
8931
+ /* @__PURE__ */ jsx3(Text3, { color: theme.dim, children: " policy " }),
8932
+ /* @__PURE__ */ jsx3(Text3, { color: theme.accent, children: "\u2039 " + truncate2(selected?.name ?? "none", 30) + " \u203A" }),
8933
+ /* @__PURE__ */ jsx3(Text3, { color: theme.dim, children: ` ${policies.length ? pi + 1 : 0}/${policies.length} press p \xB7 mode ${selected?.mode ?? "-"}` })
8944
8934
  ] }),
8945
- /* @__PURE__ */ jsx3(Text3, { color: theme.dim, wrap: "truncate", children: focused ? `\u2191\u2193 scroll \xB7 p policy \xB7 n sample \xB7 r re-run${above ? ` \xB7 \u25B2${above}` : ""}${below ? ` \xB7 \u25BC${below}` : ""}` : "press \u2192 to open" }),
8935
+ /* @__PURE__ */ jsxs3(Text3, { wrap: "truncate", children: [
8936
+ /* @__PURE__ */ jsx3(Text3, { color: theme.dim, children: " logs " }),
8937
+ /* @__PURE__ */ jsx3(Text3, { color: theme.accent, children: "\u2039 " + String(SAMPLES[si]) + " \u203A" }),
8938
+ /* @__PURE__ */ jsx3(Text3, { color: theme.dim, children: ` press n${res?.sampled != null ? ` replayed ${res.sampled} of your most recent logs` : ""}` })
8939
+ ] }),
8940
+ /* @__PURE__ */ jsx3(Text3, { color: theme.dim, wrap: "truncate", children: focused ? `\u2191\u2193 scroll \xB7 p policy \xB7 n logs \xB7 r re-run${above ? ` \xB7 \u25B2${above}` : ""}${below ? ` \xB7 \u25BC${below}` : ""}` : "press \u2192 to open" }),
8946
8941
  running ? /* @__PURE__ */ jsx3(Text3, { color: theme.warn, children: "replaying recent traffic\u2026" }) : null,
8947
8942
  err2 ? /* @__PURE__ */ jsx3(Text3, { color: theme.bad, wrap: "truncate", children: "\u2717 " + err2 }) : null,
8948
- !running && !err2 && !res ? /* @__PURE__ */ jsx3(Text3, { color: theme.dim, children: "no result yet \u2014 press r to run" }) : null,
8943
+ !running && !err2 && !res ? /* @__PURE__ */ jsx3(Text3, { color: theme.dim, children: "no result yet, press r to run" }) : null,
8949
8944
  /* @__PURE__ */ jsx3(Box3, { marginTop: 1, flexDirection: "column", children: win })
8950
8945
  ] }) });
8951
8946
  }
@@ -8963,6 +8958,31 @@ var init_DryRun = __esm({
8963
8958
  }
8964
8959
  });
8965
8960
 
8961
+ // src/tui/nav.ts
8962
+ function requestSection(label) {
8963
+ pending = label;
8964
+ for (const fn of subs) fn();
8965
+ }
8966
+ function takePendingSection() {
8967
+ const p = pending;
8968
+ pending = null;
8969
+ return p;
8970
+ }
8971
+ function onSectionRequest(fn) {
8972
+ subs.add(fn);
8973
+ return () => {
8974
+ subs.delete(fn);
8975
+ };
8976
+ }
8977
+ var pending, subs;
8978
+ var init_nav = __esm({
8979
+ "src/tui/nav.ts"() {
8980
+ "use strict";
8981
+ pending = null;
8982
+ subs = /* @__PURE__ */ new Set();
8983
+ }
8984
+ });
8985
+
8966
8986
  // src/tui/panels/Policies.tsx
8967
8987
  import { Box as Box4, Text as Text4, useInput as useInput3 } from "ink";
8968
8988
  import TextInput2 from "ink-text-input";
@@ -9104,7 +9124,7 @@ function PoliciesPanel({ focused }) {
9104
9124
  } else if (input === "D") {
9105
9125
  if (selected) {
9106
9126
  requestDryRun(selected.id);
9107
- setStatus('Sent to Dry Run - open the "Dry Run" section in the left nav for the full report.');
9127
+ requestSection("Dry Run");
9108
9128
  }
9109
9129
  } else if (input === "s") void save();
9110
9130
  else if (input === "x") discard();
@@ -9257,6 +9277,7 @@ var init_Policies = __esm({
9257
9277
  "use strict";
9258
9278
  init_api_client();
9259
9279
  init_DryRun();
9280
+ init_nav();
9260
9281
  init_components();
9261
9282
  init_hooks();
9262
9283
  init_theme();
@@ -11308,6 +11329,18 @@ function App() {
11308
11329
  const [viewNonce, setViewNonce] = useState9(0);
11309
11330
  const [section, setSection] = useState9(accounts.length === 0 ? SETTINGS_SECTION : 0);
11310
11331
  const [focus, setFocus] = useState9("nav");
11332
+ useEffect8(
11333
+ () => onSectionRequest(() => {
11334
+ const label = takePendingSection();
11335
+ if (!label) return;
11336
+ const idx = SECTIONS.findIndex((s) => s.label === label);
11337
+ if (idx >= 0) {
11338
+ setSection(idx);
11339
+ setFocus("panel");
11340
+ }
11341
+ }),
11342
+ []
11343
+ );
11311
11344
  const [help, setHelp] = useState9(false);
11312
11345
  const [update2, setUpdate] = useState9({ kind: "idle" });
11313
11346
  useEffect8(() => {
@@ -11445,6 +11478,7 @@ var init_App = __esm({
11445
11478
  init_DryRun();
11446
11479
  init_Settings();
11447
11480
  init_hooks();
11481
+ init_nav();
11448
11482
  init_client();
11449
11483
  init_api_client();
11450
11484
  init_self_update();
package/dist/tui/index.js CHANGED
@@ -2030,38 +2030,52 @@ function DryRunPanel({ focused }) {
2030
2030
  }
2031
2031
  }
2032
2032
  }
2033
- const headerRows = 3;
2033
+ const headerRows = 5;
2034
2034
  const budget = Math.max(3, rows - headerRows);
2035
2035
  const maxOff = Math.max(0, lines.length - budget);
2036
2036
  const start = Math.min(off, maxOff);
2037
2037
  const win = lines.slice(start, start + budget);
2038
2038
  const above = start;
2039
2039
  const below = Math.max(0, lines.length - (start + budget));
2040
- const sampleLabel = `${SAMPLES[si]}${res?.sampled != null ? ` (ran ${res.sampled})` : ""}`;
2041
2040
  return /* @__PURE__ */ jsx3(DataView, { loading: list5.loading && !list5.data, error: list5.error, children: /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", children: [
2042
- /* @__PURE__ */ jsxs3(Box3, { children: [
2043
- /* @__PURE__ */ jsx3(Text3, { bold: true, color: theme.accentBright, children: "Policy Dry Run" }),
2044
- /* @__PURE__ */ jsxs3(Text3, { color: theme.dim, children: [
2045
- " ",
2046
- truncate(selected?.name ?? "no policy", 26)
2047
- ] }),
2048
- /* @__PURE__ */ jsxs3(Text3, { color: theme.dim, children: [
2049
- " mode: ",
2050
- selected?.mode ?? "-"
2051
- ] }),
2052
- /* @__PURE__ */ jsxs3(Text3, { color: theme.dim, children: [
2053
- " sample: ",
2054
- sampleLabel
2055
- ] })
2041
+ /* @__PURE__ */ jsx3(Text3, { bold: true, color: theme.accentBright, children: "Policy Dry Run" }),
2042
+ /* @__PURE__ */ jsxs3(Text3, { wrap: "truncate", children: [
2043
+ /* @__PURE__ */ jsx3(Text3, { color: theme.dim, children: " policy " }),
2044
+ /* @__PURE__ */ jsx3(Text3, { color: theme.accent, children: "\u2039 " + truncate(selected?.name ?? "none", 30) + " \u203A" }),
2045
+ /* @__PURE__ */ jsx3(Text3, { color: theme.dim, children: ` ${policies.length ? pi + 1 : 0}/${policies.length} press p \xB7 mode ${selected?.mode ?? "-"}` })
2056
2046
  ] }),
2057
- /* @__PURE__ */ jsx3(Text3, { color: theme.dim, wrap: "truncate", children: focused ? `\u2191\u2193 scroll \xB7 p policy \xB7 n sample \xB7 r re-run${above ? ` \xB7 \u25B2${above}` : ""}${below ? ` \xB7 \u25BC${below}` : ""}` : "press \u2192 to open" }),
2047
+ /* @__PURE__ */ jsxs3(Text3, { wrap: "truncate", children: [
2048
+ /* @__PURE__ */ jsx3(Text3, { color: theme.dim, children: " logs " }),
2049
+ /* @__PURE__ */ jsx3(Text3, { color: theme.accent, children: "\u2039 " + String(SAMPLES[si]) + " \u203A" }),
2050
+ /* @__PURE__ */ jsx3(Text3, { color: theme.dim, children: ` press n${res?.sampled != null ? ` replayed ${res.sampled} of your most recent logs` : ""}` })
2051
+ ] }),
2052
+ /* @__PURE__ */ jsx3(Text3, { color: theme.dim, wrap: "truncate", children: focused ? `\u2191\u2193 scroll \xB7 p policy \xB7 n logs \xB7 r re-run${above ? ` \xB7 \u25B2${above}` : ""}${below ? ` \xB7 \u25BC${below}` : ""}` : "press \u2192 to open" }),
2058
2053
  running ? /* @__PURE__ */ jsx3(Text3, { color: theme.warn, children: "replaying recent traffic\u2026" }) : null,
2059
2054
  err ? /* @__PURE__ */ jsx3(Text3, { color: theme.bad, wrap: "truncate", children: "\u2717 " + err }) : null,
2060
- !running && !err && !res ? /* @__PURE__ */ jsx3(Text3, { color: theme.dim, children: "no result yet \u2014 press r to run" }) : null,
2055
+ !running && !err && !res ? /* @__PURE__ */ jsx3(Text3, { color: theme.dim, children: "no result yet, press r to run" }) : null,
2061
2056
  /* @__PURE__ */ jsx3(Box3, { marginTop: 1, flexDirection: "column", children: win })
2062
2057
  ] }) });
2063
2058
  }
2064
2059
 
2060
+ // src/tui/nav.ts
2061
+ var pending = null;
2062
+ var subs = /* @__PURE__ */ new Set();
2063
+ function requestSection(label) {
2064
+ pending = label;
2065
+ for (const fn of subs) fn();
2066
+ }
2067
+ function takePendingSection() {
2068
+ const p = pending;
2069
+ pending = null;
2070
+ return p;
2071
+ }
2072
+ function onSectionRequest(fn) {
2073
+ subs.add(fn);
2074
+ return () => {
2075
+ subs.delete(fn);
2076
+ };
2077
+ }
2078
+
2065
2079
  // src/tui/panels/Policies.tsx
2066
2080
  import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
2067
2081
  var constr = (r, g, side) => (r[g]?.[side] ?? []).join(", ");
@@ -2221,7 +2235,7 @@ function PoliciesPanel({ focused }) {
2221
2235
  } else if (input === "D") {
2222
2236
  if (selected) {
2223
2237
  requestDryRun(selected.id);
2224
- setStatus('Sent to Dry Run - open the "Dry Run" section in the left nav for the full report.');
2238
+ requestSection("Dry Run");
2225
2239
  }
2226
2240
  } else if (input === "s") void save();
2227
2241
  else if (input === "x") discard();
@@ -4533,6 +4547,18 @@ function App() {
4533
4547
  const [viewNonce, setViewNonce] = useState9(0);
4534
4548
  const [section, setSection] = useState9(accounts.length === 0 ? SETTINGS_SECTION : 0);
4535
4549
  const [focus, setFocus] = useState9("nav");
4550
+ useEffect8(
4551
+ () => onSectionRequest(() => {
4552
+ const label = takePendingSection();
4553
+ if (!label) return;
4554
+ const idx = SECTIONS.findIndex((s) => s.label === label);
4555
+ if (idx >= 0) {
4556
+ setSection(idx);
4557
+ setFocus("panel");
4558
+ }
4559
+ }),
4560
+ []
4561
+ );
4536
4562
  const [help, setHelp] = useState9(false);
4537
4563
  const [update2, setUpdate] = useState9({ kind: "idle" });
4538
4564
  useEffect8(() => {
@@ -0,0 +1,6 @@
1
+ /** Ask the shell to switch to (and focus) the section with this label. */
2
+ export declare function requestSection(label: string): void;
3
+ /** Consume the pending request (returns null when there is none). */
4
+ export declare function takePendingSection(): string | null;
5
+ /** Subscribe to requests. Returns an unsubscribe function. */
6
+ export declare function onSectionRequest(fn: () => void): () => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solongate/proxy",
3
- "version": "0.82.33",
3
+ "version": "0.82.34",
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": {