@solongate/proxy 0.81.28 → 0.81.30

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
@@ -8920,13 +8920,14 @@ function AuditPanel({ active: active2, focused }) {
8920
8920
  const [confirm, setConfirm] = useState6(null);
8921
8921
  const [msg, setMsg] = useState6(null);
8922
8922
  const [showHelp, setShowHelp] = useState6(false);
8923
+ const [frozen, setFrozen] = useState6(false);
8923
8924
  const toTop = () => setSel(0);
8924
8925
  const statsQ = useLoader(() => source === "cloud" ? api.stats.get() : Promise.resolve(null), [source]);
8925
8926
  const tsQ = useLoader(() => source === "cloud" ? api.stats.timeseries({ period: "24h" }) : Promise.resolve(null), [source]);
8926
8927
  usePoll(() => {
8927
8928
  statsQ.reloadQuiet();
8928
8929
  tsQ.reloadQuiet();
8929
- }, 15e3, active2 && source === "cloud");
8930
+ }, 15e3, active2 && source === "cloud" && !frozen);
8930
8931
  const query = {
8931
8932
  filter: DECISIONS[di],
8932
8933
  signal: SIGNALS[gi],
@@ -8941,9 +8942,9 @@ function AuditPanel({ active: active2, focused }) {
8941
8942
  () => source === "cloud" ? api.audit.list(query) : Promise.resolve(null),
8942
8943
  [source, di, gi, tool, agent, search, sessFilter, page]
8943
8944
  );
8944
- usePoll(cloudQ.reloadQuiet, 6e3, active2 && source === "cloud" && view === "logs" && !editing && page === 0);
8945
+ usePoll(cloudQ.reloadQuiet, 6e3, active2 && source === "cloud" && view === "logs" && !editing && page === 0 && !frozen);
8945
8946
  const localQ = useLoader(() => source === "local" ? Promise.resolve(loadLocalRows()) : Promise.resolve(null), [source]);
8946
- usePoll(localQ.reloadQuiet, 6e3, active2 && source === "local" && view === "logs" && !editing && page === 0);
8947
+ usePoll(localQ.reloadQuiet, 6e3, active2 && source === "local" && view === "logs" && !editing && page === 0 && !frozen);
8947
8948
  const q = search.trim().toLowerCase();
8948
8949
  const localFiltered = (localQ.data ?? []).filter((r) => {
8949
8950
  if (DECISIONS[di] && r.decision !== DECISIONS[di]) return false;
@@ -8970,7 +8971,7 @@ function AuditPanel({ active: active2, focused }) {
8970
8971
  () => source === "cloud" ? api.agents.live({ limit: 100, includeDeactivated: true }) : Promise.resolve(null),
8971
8972
  [source]
8972
8973
  );
8973
- usePoll(agentsQ.reloadQuiet, 8e3, active2 && source === "cloud" && view === "sessions");
8974
+ usePoll(agentsQ.reloadQuiet, 8e3, active2 && source === "cloud" && view === "sessions" && !frozen);
8974
8975
  let sessions = [];
8975
8976
  if (source === "cloud") {
8976
8977
  sessions = (agentsQ.data?.agents ?? []).map((a) => ({
@@ -9048,6 +9049,11 @@ function AuditPanel({ active: active2, focused }) {
9048
9049
  };
9049
9050
  useInput5(
9050
9051
  (input, key) => {
9052
+ if (input === " ") {
9053
+ setFrozen((f) => !f);
9054
+ return;
9055
+ }
9056
+ if (frozen) return;
9051
9057
  if (showHelp) {
9052
9058
  setShowHelp(false);
9053
9059
  return;
@@ -9200,22 +9206,29 @@ function AuditPanel({ active: active2, focused }) {
9200
9206
  LOCAL_LOG
9201
9207
  ] })
9202
9208
  ] });
9209
+ const copyBanner = frozen ? /* @__PURE__ */ jsx6(Text6, { backgroundColor: "#123d1f", color: "#7bd88f", bold: true, wrap: "truncate", children: " \u23F5 COPY MODE \u2014 screen frozen, select & copy freely \xB7 space resume " }) : null;
9203
9210
  const srcChip = /* @__PURE__ */ jsxs6(Text6, { children: [
9204
9211
  /* @__PURE__ */ jsx6(Text6, { color: theme.dim, children: "src:" }),
9205
9212
  /* @__PURE__ */ jsx6(Text6, { color: source === "local" ? theme.ok : "#4f6db8", bold: true, children: source }),
9206
9213
  /* @__PURE__ */ jsx6(Text6, { color: theme.dim, children: " (s) " })
9207
9214
  ] });
9208
9215
  if (showHelp) {
9216
+ const colOf = (groups) => /* @__PURE__ */ jsx6(Box6, { flexDirection: "column", width: "50%", paddingRight: 2, children: groups.map(([group, keys]) => /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", marginBottom: 1, children: [
9217
+ /* @__PURE__ */ jsx6(Text6, { bold: true, color: theme.accent, children: group }),
9218
+ keys.map(([k, desc]) => /* @__PURE__ */ jsxs6(Text6, { wrap: "truncate", children: [
9219
+ /* @__PURE__ */ jsx6(Text6, { color: theme.accentBright, children: (" " + k).padEnd(19) }),
9220
+ /* @__PURE__ */ jsx6(Text6, { color: theme.dim, children: desc })
9221
+ ] }, k))
9222
+ ] }, group)) });
9209
9223
  return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
9210
- /* @__PURE__ */ jsx6(Text6, { bold: true, color: theme.accentBright, children: "AUDIT \u2014 all keys" }),
9211
- AUDIT_HELP.map(([group, keys]) => /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", marginTop: 1, children: [
9212
- /* @__PURE__ */ jsx6(Text6, { bold: true, color: theme.accent, children: group }),
9213
- keys.map(([k, desc]) => /* @__PURE__ */ jsxs6(Text6, { wrap: "truncate", children: [
9214
- /* @__PURE__ */ jsx6(Text6, { color: theme.accentBright, children: (" " + k).padEnd(20) }),
9215
- /* @__PURE__ */ jsx6(Text6, { color: theme.dim, children: desc })
9216
- ] }, k))
9217
- ] }, group)),
9218
- /* @__PURE__ */ jsx6(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx6(Text6, { color: theme.dim, children: "press any key to close" }) })
9224
+ /* @__PURE__ */ jsxs6(Text6, { bold: true, color: theme.accentBright, children: [
9225
+ "AUDIT \u2014 all keys ",
9226
+ /* @__PURE__ */ jsx6(Text6, { color: theme.dim, children: "\xB7 press any key to close" })
9227
+ ] }),
9228
+ /* @__PURE__ */ jsxs6(Box6, { marginTop: 1, children: [
9229
+ colOf(AUDIT_HELP.slice(0, 1)),
9230
+ colOf(AUDIT_HELP.slice(1))
9231
+ ] })
9219
9232
  ] });
9220
9233
  }
9221
9234
  if (view === "detail" && current) {
@@ -9225,11 +9238,12 @@ function AuditPanel({ active: active2, focused }) {
9225
9238
  const argLines = current.args ? wrapLines(prettyJson(current.args), bodyW) : ["(no arguments recorded)"];
9226
9239
  const sessionRows = current.session ? Math.min(4, sessionCalls.length) + 2 : 1;
9227
9240
  const reasonShown = reasonLines.slice(0, 4);
9228
- const argBudget = Math.max(3, rows - 2 - 5 - reasonShown.length - 1 - sessionRows - 1);
9241
+ const argBudget = Math.max(3, rows - 2 - 5 - reasonShown.length - 1 - sessionRows - 1 - (frozen ? 1 : 0));
9229
9242
  const maxScroll = Math.max(0, argLines.length - argBudget);
9230
9243
  const off = Math.min(detailScroll, maxScroll);
9231
9244
  const argWin = argLines.slice(off, off + argBudget);
9232
9245
  return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
9246
+ copyBanner,
9233
9247
  /* @__PURE__ */ jsxs6(Box6, { children: [
9234
9248
  /* @__PURE__ */ jsx6(Text6, { color: decisionColor(current.decision), bold: true, children: current.decision }),
9235
9249
  /* @__PURE__ */ jsx6(Text6, { color: theme.accent, children: " " + current.tool }),
@@ -9288,8 +9302,9 @@ function AuditPanel({ active: active2, focused }) {
9288
9302
  const selC = Math.min(sessSel, Math.max(0, sessionsFiltered.length - 1));
9289
9303
  const start2 = Math.min(Math.max(0, selC - Math.floor((listRows2 - 1) / 2)), Math.max(0, sessionsFiltered.length - listRows2));
9290
9304
  const win = sessionsFiltered.slice(start2, start2 + listRows2);
9291
- return /* @__PURE__ */ jsx6(DataView, { loading: sessLoading, error: source === "cloud" ? agentsQ.error : localQ.error, children: /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
9305
+ return /* @__PURE__ */ jsx6(DataView, { loading: sessLoading && !frozen, error: source === "cloud" ? agentsQ.error : localQ.error, children: /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
9292
9306
  strip,
9307
+ copyBanner,
9293
9308
  /* @__PURE__ */ jsxs6(Box6, { children: [
9294
9309
  srcChip,
9295
9310
  /* @__PURE__ */ jsx6(Text6, { color: theme.accentBright, bold: true, children: "SESSIONS" }),
@@ -9351,15 +9366,16 @@ function AuditPanel({ active: active2, focused }) {
9351
9366
  ] }) : null
9352
9367
  ] }) });
9353
9368
  }
9354
- const headerRows = 6 + (editing && editing !== "sess-search" ? 1 : 0) + (msg ? 1 : 0);
9369
+ const headerRows = 6 + (editing && editing !== "sess-search" ? 1 : 0) + (msg ? 1 : 0) + (frozen ? 1 : 0);
9355
9370
  const listRows = Math.max(4, rows - headerRows);
9356
9371
  const selClamped = Math.min(sel, Math.max(0, pageRows.length - 1));
9357
9372
  const maxStart = Math.max(0, pageRows.length - listRows);
9358
9373
  const start = Math.min(Math.max(0, selClamped - Math.floor((listRows - 1) / 2)), maxStart);
9359
9374
  const windowed = pageRows.slice(start, start + listRows);
9360
9375
  const reasonW = Math.min(60, Math.max(12, cols - 67));
9361
- return /* @__PURE__ */ jsx6(DataView, { loading: logsLoading, error: source === "cloud" ? cloudQ.error : localQ.error, children: /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
9376
+ return /* @__PURE__ */ jsx6(DataView, { loading: logsLoading && !frozen, error: source === "cloud" ? cloudQ.error : localQ.error, children: /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
9362
9377
  strip,
9378
+ copyBanner,
9363
9379
  /* @__PURE__ */ jsxs6(Box6, { children: [
9364
9380
  srcChip,
9365
9381
  /* @__PURE__ */ jsx6(Text6, { color: theme.accentBright, bold: true, children: "LOGS" }),
@@ -9494,6 +9510,7 @@ var init_Audit = __esm({
9494
9510
  [
9495
9511
  ["v", "switch logs \u2194 sessions"],
9496
9512
  ["s", "switch source cloud \u2194 local file"],
9513
+ ["space", "copy mode: freeze screen for mouse selection"],
9497
9514
  ["?", "this help \xB7 any key closes"],
9498
9515
  ["esc", "back to the menu"]
9499
9516
  ]
package/dist/tui/index.js CHANGED
@@ -2291,6 +2291,7 @@ var AUDIT_HELP = [
2291
2291
  [
2292
2292
  ["v", "switch logs \u2194 sessions"],
2293
2293
  ["s", "switch source cloud \u2194 local file"],
2294
+ ["space", "copy mode: freeze screen for mouse selection"],
2294
2295
  ["?", "this help \xB7 any key closes"],
2295
2296
  ["esc", "back to the menu"]
2296
2297
  ]
@@ -2323,13 +2324,14 @@ function AuditPanel({ active: active2, focused }) {
2323
2324
  const [confirm, setConfirm] = useState6(null);
2324
2325
  const [msg, setMsg] = useState6(null);
2325
2326
  const [showHelp, setShowHelp] = useState6(false);
2327
+ const [frozen, setFrozen] = useState6(false);
2326
2328
  const toTop = () => setSel(0);
2327
2329
  const statsQ = useLoader(() => source === "cloud" ? api.stats.get() : Promise.resolve(null), [source]);
2328
2330
  const tsQ = useLoader(() => source === "cloud" ? api.stats.timeseries({ period: "24h" }) : Promise.resolve(null), [source]);
2329
2331
  usePoll(() => {
2330
2332
  statsQ.reloadQuiet();
2331
2333
  tsQ.reloadQuiet();
2332
- }, 15e3, active2 && source === "cloud");
2334
+ }, 15e3, active2 && source === "cloud" && !frozen);
2333
2335
  const query = {
2334
2336
  filter: DECISIONS[di],
2335
2337
  signal: SIGNALS[gi],
@@ -2344,9 +2346,9 @@ function AuditPanel({ active: active2, focused }) {
2344
2346
  () => source === "cloud" ? api.audit.list(query) : Promise.resolve(null),
2345
2347
  [source, di, gi, tool, agent, search, sessFilter, page]
2346
2348
  );
2347
- usePoll(cloudQ.reloadQuiet, 6e3, active2 && source === "cloud" && view === "logs" && !editing && page === 0);
2349
+ usePoll(cloudQ.reloadQuiet, 6e3, active2 && source === "cloud" && view === "logs" && !editing && page === 0 && !frozen);
2348
2350
  const localQ = useLoader(() => source === "local" ? Promise.resolve(loadLocalRows()) : Promise.resolve(null), [source]);
2349
- usePoll(localQ.reloadQuiet, 6e3, active2 && source === "local" && view === "logs" && !editing && page === 0);
2351
+ usePoll(localQ.reloadQuiet, 6e3, active2 && source === "local" && view === "logs" && !editing && page === 0 && !frozen);
2350
2352
  const q = search.trim().toLowerCase();
2351
2353
  const localFiltered = (localQ.data ?? []).filter((r) => {
2352
2354
  if (DECISIONS[di] && r.decision !== DECISIONS[di]) return false;
@@ -2373,7 +2375,7 @@ function AuditPanel({ active: active2, focused }) {
2373
2375
  () => source === "cloud" ? api.agents.live({ limit: 100, includeDeactivated: true }) : Promise.resolve(null),
2374
2376
  [source]
2375
2377
  );
2376
- usePoll(agentsQ.reloadQuiet, 8e3, active2 && source === "cloud" && view === "sessions");
2378
+ usePoll(agentsQ.reloadQuiet, 8e3, active2 && source === "cloud" && view === "sessions" && !frozen);
2377
2379
  let sessions = [];
2378
2380
  if (source === "cloud") {
2379
2381
  sessions = (agentsQ.data?.agents ?? []).map((a) => ({
@@ -2451,6 +2453,11 @@ function AuditPanel({ active: active2, focused }) {
2451
2453
  };
2452
2454
  useInput5(
2453
2455
  (input, key) => {
2456
+ if (input === " ") {
2457
+ setFrozen((f) => !f);
2458
+ return;
2459
+ }
2460
+ if (frozen) return;
2454
2461
  if (showHelp) {
2455
2462
  setShowHelp(false);
2456
2463
  return;
@@ -2603,22 +2610,29 @@ function AuditPanel({ active: active2, focused }) {
2603
2610
  LOCAL_LOG
2604
2611
  ] })
2605
2612
  ] });
2613
+ const copyBanner = frozen ? /* @__PURE__ */ jsx6(Text6, { backgroundColor: "#123d1f", color: "#7bd88f", bold: true, wrap: "truncate", children: " \u23F5 COPY MODE \u2014 screen frozen, select & copy freely \xB7 space resume " }) : null;
2606
2614
  const srcChip = /* @__PURE__ */ jsxs6(Text6, { children: [
2607
2615
  /* @__PURE__ */ jsx6(Text6, { color: theme.dim, children: "src:" }),
2608
2616
  /* @__PURE__ */ jsx6(Text6, { color: source === "local" ? theme.ok : "#4f6db8", bold: true, children: source }),
2609
2617
  /* @__PURE__ */ jsx6(Text6, { color: theme.dim, children: " (s) " })
2610
2618
  ] });
2611
2619
  if (showHelp) {
2620
+ const colOf = (groups) => /* @__PURE__ */ jsx6(Box6, { flexDirection: "column", width: "50%", paddingRight: 2, children: groups.map(([group, keys]) => /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", marginBottom: 1, children: [
2621
+ /* @__PURE__ */ jsx6(Text6, { bold: true, color: theme.accent, children: group }),
2622
+ keys.map(([k, desc]) => /* @__PURE__ */ jsxs6(Text6, { wrap: "truncate", children: [
2623
+ /* @__PURE__ */ jsx6(Text6, { color: theme.accentBright, children: (" " + k).padEnd(19) }),
2624
+ /* @__PURE__ */ jsx6(Text6, { color: theme.dim, children: desc })
2625
+ ] }, k))
2626
+ ] }, group)) });
2612
2627
  return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
2613
- /* @__PURE__ */ jsx6(Text6, { bold: true, color: theme.accentBright, children: "AUDIT \u2014 all keys" }),
2614
- AUDIT_HELP.map(([group, keys]) => /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", marginTop: 1, children: [
2615
- /* @__PURE__ */ jsx6(Text6, { bold: true, color: theme.accent, children: group }),
2616
- keys.map(([k, desc]) => /* @__PURE__ */ jsxs6(Text6, { wrap: "truncate", children: [
2617
- /* @__PURE__ */ jsx6(Text6, { color: theme.accentBright, children: (" " + k).padEnd(20) }),
2618
- /* @__PURE__ */ jsx6(Text6, { color: theme.dim, children: desc })
2619
- ] }, k))
2620
- ] }, group)),
2621
- /* @__PURE__ */ jsx6(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx6(Text6, { color: theme.dim, children: "press any key to close" }) })
2628
+ /* @__PURE__ */ jsxs6(Text6, { bold: true, color: theme.accentBright, children: [
2629
+ "AUDIT \u2014 all keys ",
2630
+ /* @__PURE__ */ jsx6(Text6, { color: theme.dim, children: "\xB7 press any key to close" })
2631
+ ] }),
2632
+ /* @__PURE__ */ jsxs6(Box6, { marginTop: 1, children: [
2633
+ colOf(AUDIT_HELP.slice(0, 1)),
2634
+ colOf(AUDIT_HELP.slice(1))
2635
+ ] })
2622
2636
  ] });
2623
2637
  }
2624
2638
  if (view === "detail" && current) {
@@ -2628,11 +2642,12 @@ function AuditPanel({ active: active2, focused }) {
2628
2642
  const argLines = current.args ? wrapLines(prettyJson(current.args), bodyW) : ["(no arguments recorded)"];
2629
2643
  const sessionRows = current.session ? Math.min(4, sessionCalls.length) + 2 : 1;
2630
2644
  const reasonShown = reasonLines.slice(0, 4);
2631
- const argBudget = Math.max(3, rows - 2 - 5 - reasonShown.length - 1 - sessionRows - 1);
2645
+ const argBudget = Math.max(3, rows - 2 - 5 - reasonShown.length - 1 - sessionRows - 1 - (frozen ? 1 : 0));
2632
2646
  const maxScroll = Math.max(0, argLines.length - argBudget);
2633
2647
  const off = Math.min(detailScroll, maxScroll);
2634
2648
  const argWin = argLines.slice(off, off + argBudget);
2635
2649
  return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
2650
+ copyBanner,
2636
2651
  /* @__PURE__ */ jsxs6(Box6, { children: [
2637
2652
  /* @__PURE__ */ jsx6(Text6, { color: decisionColor(current.decision), bold: true, children: current.decision }),
2638
2653
  /* @__PURE__ */ jsx6(Text6, { color: theme.accent, children: " " + current.tool }),
@@ -2691,8 +2706,9 @@ function AuditPanel({ active: active2, focused }) {
2691
2706
  const selC = Math.min(sessSel, Math.max(0, sessionsFiltered.length - 1));
2692
2707
  const start2 = Math.min(Math.max(0, selC - Math.floor((listRows2 - 1) / 2)), Math.max(0, sessionsFiltered.length - listRows2));
2693
2708
  const win = sessionsFiltered.slice(start2, start2 + listRows2);
2694
- return /* @__PURE__ */ jsx6(DataView, { loading: sessLoading, error: source === "cloud" ? agentsQ.error : localQ.error, children: /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
2709
+ return /* @__PURE__ */ jsx6(DataView, { loading: sessLoading && !frozen, error: source === "cloud" ? agentsQ.error : localQ.error, children: /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
2695
2710
  strip,
2711
+ copyBanner,
2696
2712
  /* @__PURE__ */ jsxs6(Box6, { children: [
2697
2713
  srcChip,
2698
2714
  /* @__PURE__ */ jsx6(Text6, { color: theme.accentBright, bold: true, children: "SESSIONS" }),
@@ -2754,15 +2770,16 @@ function AuditPanel({ active: active2, focused }) {
2754
2770
  ] }) : null
2755
2771
  ] }) });
2756
2772
  }
2757
- const headerRows = 6 + (editing && editing !== "sess-search" ? 1 : 0) + (msg ? 1 : 0);
2773
+ const headerRows = 6 + (editing && editing !== "sess-search" ? 1 : 0) + (msg ? 1 : 0) + (frozen ? 1 : 0);
2758
2774
  const listRows = Math.max(4, rows - headerRows);
2759
2775
  const selClamped = Math.min(sel, Math.max(0, pageRows.length - 1));
2760
2776
  const maxStart = Math.max(0, pageRows.length - listRows);
2761
2777
  const start = Math.min(Math.max(0, selClamped - Math.floor((listRows - 1) / 2)), maxStart);
2762
2778
  const windowed = pageRows.slice(start, start + listRows);
2763
2779
  const reasonW = Math.min(60, Math.max(12, cols - 67));
2764
- return /* @__PURE__ */ jsx6(DataView, { loading: logsLoading, error: source === "cloud" ? cloudQ.error : localQ.error, children: /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
2780
+ return /* @__PURE__ */ jsx6(DataView, { loading: logsLoading && !frozen, error: source === "cloud" ? cloudQ.error : localQ.error, children: /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
2765
2781
  strip,
2782
+ copyBanner,
2766
2783
  /* @__PURE__ */ jsxs6(Box6, { children: [
2767
2784
  srcChip,
2768
2785
  /* @__PURE__ */ jsx6(Text6, { color: theme.accentBright, bold: true, children: "LOGS" }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solongate/proxy",
3
- "version": "0.81.28",
3
+ "version": "0.81.30",
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": {