@solongate/proxy 0.81.28 → 0.81.29

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,6 +9206,7 @@ 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 }),
@@ -9225,11 +9232,12 @@ function AuditPanel({ active: active2, focused }) {
9225
9232
  const argLines = current.args ? wrapLines(prettyJson(current.args), bodyW) : ["(no arguments recorded)"];
9226
9233
  const sessionRows = current.session ? Math.min(4, sessionCalls.length) + 2 : 1;
9227
9234
  const reasonShown = reasonLines.slice(0, 4);
9228
- const argBudget = Math.max(3, rows - 2 - 5 - reasonShown.length - 1 - sessionRows - 1);
9235
+ const argBudget = Math.max(3, rows - 2 - 5 - reasonShown.length - 1 - sessionRows - 1 - (frozen ? 1 : 0));
9229
9236
  const maxScroll = Math.max(0, argLines.length - argBudget);
9230
9237
  const off = Math.min(detailScroll, maxScroll);
9231
9238
  const argWin = argLines.slice(off, off + argBudget);
9232
9239
  return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
9240
+ copyBanner,
9233
9241
  /* @__PURE__ */ jsxs6(Box6, { children: [
9234
9242
  /* @__PURE__ */ jsx6(Text6, { color: decisionColor(current.decision), bold: true, children: current.decision }),
9235
9243
  /* @__PURE__ */ jsx6(Text6, { color: theme.accent, children: " " + current.tool }),
@@ -9288,8 +9296,9 @@ function AuditPanel({ active: active2, focused }) {
9288
9296
  const selC = Math.min(sessSel, Math.max(0, sessionsFiltered.length - 1));
9289
9297
  const start2 = Math.min(Math.max(0, selC - Math.floor((listRows2 - 1) / 2)), Math.max(0, sessionsFiltered.length - listRows2));
9290
9298
  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: [
9299
+ return /* @__PURE__ */ jsx6(DataView, { loading: sessLoading && !frozen, error: source === "cloud" ? agentsQ.error : localQ.error, children: /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
9292
9300
  strip,
9301
+ copyBanner,
9293
9302
  /* @__PURE__ */ jsxs6(Box6, { children: [
9294
9303
  srcChip,
9295
9304
  /* @__PURE__ */ jsx6(Text6, { color: theme.accentBright, bold: true, children: "SESSIONS" }),
@@ -9351,15 +9360,16 @@ function AuditPanel({ active: active2, focused }) {
9351
9360
  ] }) : null
9352
9361
  ] }) });
9353
9362
  }
9354
- const headerRows = 6 + (editing && editing !== "sess-search" ? 1 : 0) + (msg ? 1 : 0);
9363
+ const headerRows = 6 + (editing && editing !== "sess-search" ? 1 : 0) + (msg ? 1 : 0) + (frozen ? 1 : 0);
9355
9364
  const listRows = Math.max(4, rows - headerRows);
9356
9365
  const selClamped = Math.min(sel, Math.max(0, pageRows.length - 1));
9357
9366
  const maxStart = Math.max(0, pageRows.length - listRows);
9358
9367
  const start = Math.min(Math.max(0, selClamped - Math.floor((listRows - 1) / 2)), maxStart);
9359
9368
  const windowed = pageRows.slice(start, start + listRows);
9360
9369
  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: [
9370
+ return /* @__PURE__ */ jsx6(DataView, { loading: logsLoading && !frozen, error: source === "cloud" ? cloudQ.error : localQ.error, children: /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
9362
9371
  strip,
9372
+ copyBanner,
9363
9373
  /* @__PURE__ */ jsxs6(Box6, { children: [
9364
9374
  srcChip,
9365
9375
  /* @__PURE__ */ jsx6(Text6, { color: theme.accentBright, bold: true, children: "LOGS" }),
@@ -9494,6 +9504,7 @@ var init_Audit = __esm({
9494
9504
  [
9495
9505
  ["v", "switch logs \u2194 sessions"],
9496
9506
  ["s", "switch source cloud \u2194 local file"],
9507
+ ["space", "copy mode: freeze screen for mouse selection"],
9497
9508
  ["?", "this help \xB7 any key closes"],
9498
9509
  ["esc", "back to the menu"]
9499
9510
  ]
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,6 +2610,7 @@ 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 }),
@@ -2628,11 +2636,12 @@ function AuditPanel({ active: active2, focused }) {
2628
2636
  const argLines = current.args ? wrapLines(prettyJson(current.args), bodyW) : ["(no arguments recorded)"];
2629
2637
  const sessionRows = current.session ? Math.min(4, sessionCalls.length) + 2 : 1;
2630
2638
  const reasonShown = reasonLines.slice(0, 4);
2631
- const argBudget = Math.max(3, rows - 2 - 5 - reasonShown.length - 1 - sessionRows - 1);
2639
+ const argBudget = Math.max(3, rows - 2 - 5 - reasonShown.length - 1 - sessionRows - 1 - (frozen ? 1 : 0));
2632
2640
  const maxScroll = Math.max(0, argLines.length - argBudget);
2633
2641
  const off = Math.min(detailScroll, maxScroll);
2634
2642
  const argWin = argLines.slice(off, off + argBudget);
2635
2643
  return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
2644
+ copyBanner,
2636
2645
  /* @__PURE__ */ jsxs6(Box6, { children: [
2637
2646
  /* @__PURE__ */ jsx6(Text6, { color: decisionColor(current.decision), bold: true, children: current.decision }),
2638
2647
  /* @__PURE__ */ jsx6(Text6, { color: theme.accent, children: " " + current.tool }),
@@ -2691,8 +2700,9 @@ function AuditPanel({ active: active2, focused }) {
2691
2700
  const selC = Math.min(sessSel, Math.max(0, sessionsFiltered.length - 1));
2692
2701
  const start2 = Math.min(Math.max(0, selC - Math.floor((listRows2 - 1) / 2)), Math.max(0, sessionsFiltered.length - listRows2));
2693
2702
  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: [
2703
+ return /* @__PURE__ */ jsx6(DataView, { loading: sessLoading && !frozen, error: source === "cloud" ? agentsQ.error : localQ.error, children: /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
2695
2704
  strip,
2705
+ copyBanner,
2696
2706
  /* @__PURE__ */ jsxs6(Box6, { children: [
2697
2707
  srcChip,
2698
2708
  /* @__PURE__ */ jsx6(Text6, { color: theme.accentBright, bold: true, children: "SESSIONS" }),
@@ -2754,15 +2764,16 @@ function AuditPanel({ active: active2, focused }) {
2754
2764
  ] }) : null
2755
2765
  ] }) });
2756
2766
  }
2757
- const headerRows = 6 + (editing && editing !== "sess-search" ? 1 : 0) + (msg ? 1 : 0);
2767
+ const headerRows = 6 + (editing && editing !== "sess-search" ? 1 : 0) + (msg ? 1 : 0) + (frozen ? 1 : 0);
2758
2768
  const listRows = Math.max(4, rows - headerRows);
2759
2769
  const selClamped = Math.min(sel, Math.max(0, pageRows.length - 1));
2760
2770
  const maxStart = Math.max(0, pageRows.length - listRows);
2761
2771
  const start = Math.min(Math.max(0, selClamped - Math.floor((listRows - 1) / 2)), maxStart);
2762
2772
  const windowed = pageRows.slice(start, start + listRows);
2763
2773
  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: [
2774
+ return /* @__PURE__ */ jsx6(DataView, { loading: logsLoading && !frozen, error: source === "cloud" ? cloudQ.error : localQ.error, children: /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
2765
2775
  strip,
2776
+ copyBanner,
2766
2777
  /* @__PURE__ */ jsxs6(Box6, { children: [
2767
2778
  srcChip,
2768
2779
  /* @__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.29",
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": {