@solongate/proxy 0.59.4 → 0.60.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.
Files changed (40) hide show
  1. package/dist/api-client/agents.d.ts +10 -0
  2. package/dist/api-client/audit.d.ts +22 -0
  3. package/dist/api-client/client.d.ts +39 -0
  4. package/dist/api-client/index.d.ts +18 -0
  5. package/dist/api-client/policies.d.ts +82 -0
  6. package/dist/api-client/settings.d.ts +22 -0
  7. package/dist/api-client/stats.d.ts +9 -0
  8. package/dist/api-client/types.d.ts +224 -0
  9. package/dist/audit/index.js +0 -1
  10. package/dist/commands/agents.d.ts +4 -0
  11. package/dist/commands/args.d.ts +15 -0
  12. package/dist/commands/audit.d.ts +1 -0
  13. package/dist/commands/dlp.d.ts +1 -0
  14. package/dist/commands/format.d.ts +22 -0
  15. package/dist/commands/index.d.ts +7 -0
  16. package/dist/commands/index.js +938 -0
  17. package/dist/commands/policy.d.ts +1 -0
  18. package/dist/commands/ratelimit.d.ts +1 -0
  19. package/dist/commands/stats.d.ts +1 -0
  20. package/dist/index.js +2059 -348
  21. package/dist/inject.js +4 -4
  22. package/dist/lib.js +3 -31
  23. package/dist/proxy.d.ts +0 -7
  24. package/dist/pull-push.js +2 -1
  25. package/dist/tui/App.d.ts +1 -0
  26. package/dist/tui/components.d.ts +40 -0
  27. package/dist/tui/hooks.d.ts +13 -0
  28. package/dist/tui/index.d.ts +1 -0
  29. package/dist/tui/index.js +881 -0
  30. package/dist/tui/panels/Agents.d.ts +3 -0
  31. package/dist/tui/panels/Audit.d.ts +4 -0
  32. package/dist/tui/panels/Dlp.d.ts +4 -0
  33. package/dist/tui/panels/Policies.d.ts +4 -0
  34. package/dist/tui/panels/RateLimit.d.ts +4 -0
  35. package/dist/tui/panels/Stats.d.ts +3 -0
  36. package/dist/tui/theme.d.ts +16 -0
  37. package/hooks/audit.mjs +23 -4
  38. package/hooks/guard.bundled.mjs +46 -35
  39. package/hooks/guard.mjs +16 -2
  40. package/package.json +7 -2
@@ -0,0 +1,3 @@
1
+ export declare function AgentsPanel({ active }: {
2
+ active: boolean;
3
+ }): JSX.Element;
@@ -0,0 +1,4 @@
1
+ export declare function AuditPanel({ active, focused }: {
2
+ active: boolean;
3
+ focused: boolean;
4
+ }): JSX.Element;
@@ -0,0 +1,4 @@
1
+ export declare function DlpPanel({ focused }: {
2
+ active: boolean;
3
+ focused: boolean;
4
+ }): JSX.Element;
@@ -0,0 +1,4 @@
1
+ export declare function PoliciesPanel({ focused }: {
2
+ active: boolean;
3
+ focused: boolean;
4
+ }): JSX.Element;
@@ -0,0 +1,4 @@
1
+ export declare function RateLimitPanel({ focused }: {
2
+ active: boolean;
3
+ focused: boolean;
4
+ }): JSX.Element;
@@ -0,0 +1,3 @@
1
+ export declare function StatsPanel({ active }: {
2
+ active: boolean;
3
+ }): JSX.Element;
@@ -0,0 +1,16 @@
1
+ /** Shared colors + small helpers for the Ink TUI. */
2
+ export declare const theme: {
3
+ readonly accent: "cyan";
4
+ readonly accentBright: "#5a8ce6";
5
+ readonly ok: "green";
6
+ readonly warn: "yellow";
7
+ readonly bad: "red";
8
+ readonly dim: "gray";
9
+ };
10
+ /** Ink `color` for a decision string. */
11
+ export declare function decisionColor(decision: string): string;
12
+ /** Ink `color` for a layer/agent mode/status. */
13
+ export declare function modeColor(m: string): string;
14
+ export declare function sparkline(values: number[], width?: number): string;
15
+ export declare function truncate(s: string, n: number): string;
16
+ export declare function ago(ts: string | number): string;
package/hooks/audit.mjs CHANGED
@@ -11,7 +11,7 @@ import { homedir } from 'node:os';
11
11
  // Bump on every audit.mjs change. The cloud serves the newest version; the guard
12
12
  // hook installs it on its next run (no re-login needed). See guard.mjs
13
13
  // fetchAndInstallHook / maybeSelfUpdate.
14
- const HOOK_VERSION = 14;
14
+ const HOOK_VERSION = 15;
15
15
 
16
16
  function loadEnvKey(dir) {
17
17
  try {
@@ -46,20 +46,39 @@ function loadGlobalCloudConfig() {
46
46
  // instead of a stale-TTL zero. Returns null when no matching measurement exists —
47
47
  // an unknown eval time must be stored as null, not a fake 0 that drags averages.
48
48
  function readLastEvalMs(toolName, sessionId) {
49
+ // Prefer the ring: average the recent same-session eval records. When several
50
+ // tool calls run in PARALLEL they all land here within a moment, so each one
51
+ // reports the burst's arithmetic-mean eval time instead of a blank (the single
52
+ // .last-eval flag would be overwritten / half-read under that concurrency). A
53
+ // lone sequential call has only itself in the window → it reports its own time.
54
+ try {
55
+ const ring = resolve('.solongate', '.eval-ring.jsonl');
56
+ if (existsSync(ring)) {
57
+ const now = Date.now();
58
+ const recent = [];
59
+ for (const line of readFileSync(ring, 'utf-8').split('\n')) {
60
+ if (!line) continue;
61
+ let r; try { r = JSON.parse(line); } catch { continue; }
62
+ if (!r || typeof r.ms !== 'number' || typeof r.ts !== 'number') continue;
63
+ if (now - r.ts > 2500) continue; // recent burst only
64
+ if (r.session && sessionId && r.session !== sessionId) continue;
65
+ recent.push(r.ms);
66
+ }
67
+ if (recent.length) return Math.max(0, Math.round(recent.reduce((a, b) => a + b, 0) / recent.length));
68
+ }
69
+ } catch {}
70
+ // Fallback: the single-value flag (original behavior).
49
71
  try {
50
72
  const p = resolve('.solongate', '.last-eval');
51
73
  if (!existsSync(p)) return null;
52
74
  const c = JSON.parse(readFileSync(p, 'utf-8'));
53
75
  if (!c || typeof c.ms !== 'number' || typeof c.ts !== 'number') return null;
54
76
  if (typeof c.tool === 'string') {
55
- // New flag format: match this invocation (tool + session when both known);
56
- // 2h ceiling only guards against a truly abandoned flag file.
57
77
  if (c.tool !== toolName) return null;
58
78
  if (c.session && sessionId && c.session !== sessionId) return null;
59
79
  if (Date.now() - c.ts > 2 * 3600 * 1000) return null;
60
80
  return Math.max(0, Math.round(c.ms));
61
81
  }
62
- // Legacy flag (no tool info): keep the old conservative 30s freshness rule.
63
82
  if (Date.now() - c.ts < 30000) return Math.max(0, Math.round(c.ms));
64
83
  return null;
65
84
  } catch { return null; }
@@ -34,9 +34,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
34
34
  mod
35
35
  ));
36
36
 
37
- // node_modules/.pnpm/@open-policy-agent+opa-wasm@1.10.0/node_modules/@open-policy-agent/opa-wasm/src/builtins/json.js
37
+ // ../../node_modules/.pnpm/@open-policy-agent+opa-wasm@1.10.0/node_modules/@open-policy-agent/opa-wasm/src/builtins/json.js
38
38
  var require_json = __commonJS({
39
- "node_modules/.pnpm/@open-policy-agent+opa-wasm@1.10.0/node_modules/@open-policy-agent/opa-wasm/src/builtins/json.js"(exports, module) {
39
+ "../../node_modules/.pnpm/@open-policy-agent+opa-wasm@1.10.0/node_modules/@open-policy-agent/opa-wasm/src/builtins/json.js"(exports, module) {
40
40
  function isValidJSON(str) {
41
41
  if (typeof str !== "string") {
42
42
  return;
@@ -57,9 +57,9 @@ var require_json = __commonJS({
57
57
  }
58
58
  });
59
59
 
60
- // node_modules/.pnpm/sprintf-js@1.1.3/node_modules/sprintf-js/src/sprintf.js
60
+ // ../../node_modules/.pnpm/sprintf-js@1.1.3/node_modules/sprintf-js/src/sprintf.js
61
61
  var require_sprintf = __commonJS({
62
- "node_modules/.pnpm/sprintf-js@1.1.3/node_modules/sprintf-js/src/sprintf.js"(exports) {
62
+ "../../node_modules/.pnpm/sprintf-js@1.1.3/node_modules/sprintf-js/src/sprintf.js"(exports) {
63
63
  !function() {
64
64
  "use strict";
65
65
  var re = {
@@ -260,26 +260,26 @@ var require_sprintf = __commonJS({
260
260
  }
261
261
  });
262
262
 
263
- // node_modules/.pnpm/@open-policy-agent+opa-wasm@1.10.0/node_modules/@open-policy-agent/opa-wasm/src/builtins/strings.js
263
+ // ../../node_modules/.pnpm/@open-policy-agent+opa-wasm@1.10.0/node_modules/@open-policy-agent/opa-wasm/src/builtins/strings.js
264
264
  var require_strings = __commonJS({
265
- "node_modules/.pnpm/@open-policy-agent+opa-wasm@1.10.0/node_modules/@open-policy-agent/opa-wasm/src/builtins/strings.js"(exports, module) {
265
+ "../../node_modules/.pnpm/@open-policy-agent+opa-wasm@1.10.0/node_modules/@open-policy-agent/opa-wasm/src/builtins/strings.js"(exports, module) {
266
266
  var vsprintf = require_sprintf().vsprintf;
267
267
  var sprintf = (s, values) => vsprintf(s, values);
268
268
  module.exports = { sprintf };
269
269
  }
270
270
  });
271
271
 
272
- // node_modules/.pnpm/@open-policy-agent+opa-wasm@1.10.0/node_modules/@open-policy-agent/opa-wasm/src/builtins/regex.js
272
+ // ../../node_modules/.pnpm/@open-policy-agent+opa-wasm@1.10.0/node_modules/@open-policy-agent/opa-wasm/src/builtins/regex.js
273
273
  var require_regex = __commonJS({
274
- "node_modules/.pnpm/@open-policy-agent+opa-wasm@1.10.0/node_modules/@open-policy-agent/opa-wasm/src/builtins/regex.js"(exports, module) {
274
+ "../../node_modules/.pnpm/@open-policy-agent+opa-wasm@1.10.0/node_modules/@open-policy-agent/opa-wasm/src/builtins/regex.js"(exports, module) {
275
275
  var regexSplit = (pattern, s) => s.split(RegExp(pattern));
276
276
  module.exports = { "regex.split": regexSplit };
277
277
  }
278
278
  });
279
279
 
280
- // node_modules/.pnpm/yaml@1.10.3/node_modules/yaml/dist/PlainValue-516d5bc2.js
280
+ // ../../node_modules/.pnpm/yaml@1.10.3/node_modules/yaml/dist/PlainValue-516d5bc2.js
281
281
  var require_PlainValue_516d5bc2 = __commonJS({
282
- "node_modules/.pnpm/yaml@1.10.3/node_modules/yaml/dist/PlainValue-516d5bc2.js"(exports) {
282
+ "../../node_modules/.pnpm/yaml@1.10.3/node_modules/yaml/dist/PlainValue-516d5bc2.js"(exports) {
283
283
  "use strict";
284
284
  var Char = {
285
285
  ANCHOR: "&",
@@ -1042,9 +1042,9 @@ ${ctx}
1042
1042
  }
1043
1043
  });
1044
1044
 
1045
- // node_modules/.pnpm/yaml@1.10.3/node_modules/yaml/dist/parse-cst.js
1045
+ // ../../node_modules/.pnpm/yaml@1.10.3/node_modules/yaml/dist/parse-cst.js
1046
1046
  var require_parse_cst = __commonJS({
1047
- "node_modules/.pnpm/yaml@1.10.3/node_modules/yaml/dist/parse-cst.js"(exports) {
1047
+ "../../node_modules/.pnpm/yaml@1.10.3/node_modules/yaml/dist/parse-cst.js"(exports) {
1048
1048
  "use strict";
1049
1049
  var PlainValue = require_PlainValue_516d5bc2();
1050
1050
  var BlankLine = class extends PlainValue.Node {
@@ -2535,9 +2535,9 @@ var require_parse_cst = __commonJS({
2535
2535
  }
2536
2536
  });
2537
2537
 
2538
- // node_modules/.pnpm/yaml@1.10.3/node_modules/yaml/dist/resolveSeq-95613e94.js
2538
+ // ../../node_modules/.pnpm/yaml@1.10.3/node_modules/yaml/dist/resolveSeq-95613e94.js
2539
2539
  var require_resolveSeq_95613e94 = __commonJS({
2540
- "node_modules/.pnpm/yaml@1.10.3/node_modules/yaml/dist/resolveSeq-95613e94.js"(exports) {
2540
+ "../../node_modules/.pnpm/yaml@1.10.3/node_modules/yaml/dist/resolveSeq-95613e94.js"(exports) {
2541
2541
  "use strict";
2542
2542
  var PlainValue = require_PlainValue_516d5bc2();
2543
2543
  function addCommentBefore(str, indent, comment) {
@@ -4512,9 +4512,9 @@ ${ca}` : ca;
4512
4512
  }
4513
4513
  });
4514
4514
 
4515
- // node_modules/.pnpm/yaml@1.10.3/node_modules/yaml/dist/warnings-793925ce.js
4515
+ // ../../node_modules/.pnpm/yaml@1.10.3/node_modules/yaml/dist/warnings-793925ce.js
4516
4516
  var require_warnings_793925ce = __commonJS({
4517
- "node_modules/.pnpm/yaml@1.10.3/node_modules/yaml/dist/warnings-793925ce.js"(exports) {
4517
+ "../../node_modules/.pnpm/yaml@1.10.3/node_modules/yaml/dist/warnings-793925ce.js"(exports) {
4518
4518
  "use strict";
4519
4519
  var PlainValue = require_PlainValue_516d5bc2();
4520
4520
  var resolveSeq = require_resolveSeq_95613e94();
@@ -4879,9 +4879,9 @@ ${pair.comment}` : item.comment;
4879
4879
  }
4880
4880
  });
4881
4881
 
4882
- // node_modules/.pnpm/yaml@1.10.3/node_modules/yaml/dist/Schema-bcc6c2d7.js
4882
+ // ../../node_modules/.pnpm/yaml@1.10.3/node_modules/yaml/dist/Schema-bcc6c2d7.js
4883
4883
  var require_Schema_bcc6c2d7 = __commonJS({
4884
- "node_modules/.pnpm/yaml@1.10.3/node_modules/yaml/dist/Schema-bcc6c2d7.js"(exports) {
4884
+ "../../node_modules/.pnpm/yaml@1.10.3/node_modules/yaml/dist/Schema-bcc6c2d7.js"(exports) {
4885
4885
  "use strict";
4886
4886
  var PlainValue = require_PlainValue_516d5bc2();
4887
4887
  var resolveSeq = require_resolveSeq_95613e94();
@@ -5345,9 +5345,9 @@ var require_Schema_bcc6c2d7 = __commonJS({
5345
5345
  }
5346
5346
  });
5347
5347
 
5348
- // node_modules/.pnpm/yaml@1.10.3/node_modules/yaml/dist/Document-a8d0fbf9.js
5348
+ // ../../node_modules/.pnpm/yaml@1.10.3/node_modules/yaml/dist/Document-a8d0fbf9.js
5349
5349
  var require_Document_a8d0fbf9 = __commonJS({
5350
- "node_modules/.pnpm/yaml@1.10.3/node_modules/yaml/dist/Document-a8d0fbf9.js"(exports) {
5350
+ "../../node_modules/.pnpm/yaml@1.10.3/node_modules/yaml/dist/Document-a8d0fbf9.js"(exports) {
5351
5351
  "use strict";
5352
5352
  var PlainValue = require_PlainValue_516d5bc2();
5353
5353
  var resolveSeq = require_resolveSeq_95613e94();
@@ -6028,9 +6028,9 @@ ${cbNode.commentBefore}` : cb;
6028
6028
  }
6029
6029
  });
6030
6030
 
6031
- // node_modules/.pnpm/yaml@1.10.3/node_modules/yaml/dist/index.js
6031
+ // ../../node_modules/.pnpm/yaml@1.10.3/node_modules/yaml/dist/index.js
6032
6032
  var require_dist = __commonJS({
6033
- "node_modules/.pnpm/yaml@1.10.3/node_modules/yaml/dist/index.js"(exports) {
6033
+ "../../node_modules/.pnpm/yaml@1.10.3/node_modules/yaml/dist/index.js"(exports) {
6034
6034
  "use strict";
6035
6035
  var parseCst = require_parse_cst();
6036
6036
  var Document$1 = require_Document_a8d0fbf9();
@@ -6099,16 +6099,16 @@ var require_dist = __commonJS({
6099
6099
  }
6100
6100
  });
6101
6101
 
6102
- // node_modules/.pnpm/yaml@1.10.3/node_modules/yaml/index.js
6102
+ // ../../node_modules/.pnpm/yaml@1.10.3/node_modules/yaml/index.js
6103
6103
  var require_yaml = __commonJS({
6104
- "node_modules/.pnpm/yaml@1.10.3/node_modules/yaml/index.js"(exports, module) {
6104
+ "../../node_modules/.pnpm/yaml@1.10.3/node_modules/yaml/index.js"(exports, module) {
6105
6105
  module.exports = require_dist().YAML;
6106
6106
  }
6107
6107
  });
6108
6108
 
6109
- // node_modules/.pnpm/@open-policy-agent+opa-wasm@1.10.0/node_modules/@open-policy-agent/opa-wasm/src/builtins/yaml.js
6109
+ // ../../node_modules/.pnpm/@open-policy-agent+opa-wasm@1.10.0/node_modules/@open-policy-agent/opa-wasm/src/builtins/yaml.js
6110
6110
  var require_yaml2 = __commonJS({
6111
- "node_modules/.pnpm/@open-policy-agent+opa-wasm@1.10.0/node_modules/@open-policy-agent/opa-wasm/src/builtins/yaml.js"(exports, module) {
6111
+ "../../node_modules/.pnpm/@open-policy-agent+opa-wasm@1.10.0/node_modules/@open-policy-agent/opa-wasm/src/builtins/yaml.js"(exports, module) {
6112
6112
  var yaml = require_yaml();
6113
6113
  var errors = /* @__PURE__ */ new Set([
6114
6114
  "YAMLReferenceError",
@@ -6143,9 +6143,9 @@ var require_yaml2 = __commonJS({
6143
6143
  }
6144
6144
  });
6145
6145
 
6146
- // node_modules/.pnpm/@open-policy-agent+opa-wasm@1.10.0/node_modules/@open-policy-agent/opa-wasm/src/builtins/index.js
6146
+ // ../../node_modules/.pnpm/@open-policy-agent+opa-wasm@1.10.0/node_modules/@open-policy-agent/opa-wasm/src/builtins/index.js
6147
6147
  var require_builtins = __commonJS({
6148
- "node_modules/.pnpm/@open-policy-agent+opa-wasm@1.10.0/node_modules/@open-policy-agent/opa-wasm/src/builtins/index.js"(exports, module) {
6148
+ "../../node_modules/.pnpm/@open-policy-agent+opa-wasm@1.10.0/node_modules/@open-policy-agent/opa-wasm/src/builtins/index.js"(exports, module) {
6149
6149
  var json = require_json();
6150
6150
  var strings = require_strings();
6151
6151
  var regex = require_regex();
@@ -6159,9 +6159,9 @@ var require_builtins = __commonJS({
6159
6159
  }
6160
6160
  });
6161
6161
 
6162
- // node_modules/.pnpm/@open-policy-agent+opa-wasm@1.10.0/node_modules/@open-policy-agent/opa-wasm/src/opa.js
6162
+ // ../../node_modules/.pnpm/@open-policy-agent+opa-wasm@1.10.0/node_modules/@open-policy-agent/opa-wasm/src/opa.js
6163
6163
  var require_opa = __commonJS({
6164
- "node_modules/.pnpm/@open-policy-agent+opa-wasm@1.10.0/node_modules/@open-policy-agent/opa-wasm/src/opa.js"(exports, module) {
6164
+ "../../node_modules/.pnpm/@open-policy-agent+opa-wasm@1.10.0/node_modules/@open-policy-agent/opa-wasm/src/opa.js"(exports, module) {
6165
6165
  var builtIns = require_builtins();
6166
6166
  function stringDecoder(mem) {
6167
6167
  return function(addr) {
@@ -6514,7 +6514,7 @@ var require_opa = __commonJS({
6514
6514
  }
6515
6515
  });
6516
6516
 
6517
- // node_modules/.pnpm/@open-policy-agent+opa-wasm@1.10.0/node_modules/@open-policy-agent/opa-wasm/src/index.mjs
6517
+ // ../../node_modules/.pnpm/@open-policy-agent+opa-wasm@1.10.0/node_modules/@open-policy-agent/opa-wasm/src/index.mjs
6518
6518
  var src_exports = {};
6519
6519
  __export(src_exports, {
6520
6520
  default: () => src_default,
@@ -6522,21 +6522,21 @@ __export(src_exports, {
6522
6522
  });
6523
6523
  var import_opa, loadPolicy, src_default;
6524
6524
  var init_src = __esm({
6525
- "node_modules/.pnpm/@open-policy-agent+opa-wasm@1.10.0/node_modules/@open-policy-agent/opa-wasm/src/index.mjs"() {
6525
+ "../../node_modules/.pnpm/@open-policy-agent+opa-wasm@1.10.0/node_modules/@open-policy-agent/opa-wasm/src/index.mjs"() {
6526
6526
  import_opa = __toESM(require_opa(), 1);
6527
6527
  loadPolicy = import_opa.default.loadPolicy;
6528
6528
  src_default = import_opa.default;
6529
6529
  }
6530
6530
  });
6531
6531
 
6532
- // packages/proxy/hooks/guard.mjs
6532
+ // hooks/guard.mjs
6533
6533
  import { readFileSync, existsSync, statSync, writeFileSync, mkdirSync, chmodSync, renameSync, appendFileSync } from "node:fs";
6534
6534
  import { spawn } from "node:child_process";
6535
6535
  import { resolve, join, dirname, isAbsolute } from "node:path";
6536
6536
  import { homedir } from "node:os";
6537
6537
  import { gunzipSync } from "node:zlib";
6538
6538
  import { createHash } from "node:crypto";
6539
- var HOOK_VERSION = 33;
6539
+ var HOOK_VERSION = 34;
6540
6540
  function localLogsOnly(security) {
6541
6541
  const l = security && security.localLogs;
6542
6542
  return !!(l && l.enabled && typeof l.path === "string" && l.path.trim());
@@ -7850,7 +7850,18 @@ process.stdin.on("end", async () => {
7850
7850
  try {
7851
7851
  const _fd = resolve(".solongate");
7852
7852
  mkdirSync(_fd, { recursive: true });
7853
- writeFileSync(join(_fd, ".last-eval"), JSON.stringify({ ms: Date.now() - _evalStart, ts: Date.now(), tool: toolName, session: data.session_id || "" }));
7853
+ const _rec = { ms: Date.now() - _evalStart, ts: Date.now(), tool: toolName, session: data.session_id || "" };
7854
+ writeFileSync(join(_fd, ".last-eval"), JSON.stringify(_rec));
7855
+ try {
7856
+ const ring = join(_fd, ".eval-ring.jsonl");
7857
+ appendFileSync(ring, JSON.stringify(_rec) + "\n");
7858
+ try {
7859
+ if (statSync(ring).size > 16384)
7860
+ writeFileSync(ring, readFileSync(ring, "utf-8").split("\n").filter(Boolean).slice(-50).join("\n") + "\n");
7861
+ } catch {
7862
+ }
7863
+ } catch {
7864
+ }
7854
7865
  } catch {
7855
7866
  }
7856
7867
  if (reason) {
package/hooks/guard.mjs CHANGED
@@ -32,7 +32,7 @@ import { createHash } from 'node:crypto';
32
32
  // the installed hook self-updates when the cloud version is higher (see
33
33
  // maybeSelfUpdate). This is what makes guard fixes propagate without a manual
34
34
  // reinstall — the same trust model as the OPA WASM this hook already runs.
35
- const HOOK_VERSION = 33;
35
+ const HOOK_VERSION = 34;
36
36
 
37
37
  // True when local log storage is ON. In that mode logs are kept LOCAL ONLY and
38
38
  // nothing is sent to the cloud audit log.
@@ -1661,7 +1661,21 @@ process.stdin.on('end', async () => {
1661
1661
  // ALLOW path and can't time the guard itself, so it reads this file back.
1662
1662
  // Keyed by tool + session so the audit hook can match THIS invocation even
1663
1663
  // when the tool itself runs for minutes (a bare timestamp TTL lost those).
1664
- try { const _fd = resolve('.solongate'); mkdirSync(_fd, { recursive: true }); writeFileSync(join(_fd, '.last-eval'), JSON.stringify({ ms: Date.now() - _evalStart, ts: Date.now(), tool: toolName, session: data.session_id || '' })); } catch {}
1664
+ try {
1665
+ const _fd = resolve('.solongate'); mkdirSync(_fd, { recursive: true });
1666
+ const _rec = { ms: Date.now() - _evalStart, ts: Date.now(), tool: toolName, session: data.session_id || '' };
1667
+ writeFileSync(join(_fd, '.last-eval'), JSON.stringify(_rec));
1668
+ // Also append to a short ring. When many tool calls run in PARALLEL they all
1669
+ // race on the single .last-eval above (overwrite / torn read → blank eval
1670
+ // time in the log). appendFileSync lines are atomic, so the PostToolUse
1671
+ // audit hook can recover a value by averaging the recent same-session
1672
+ // records — a parallel burst then shares one arithmetic-mean eval time.
1673
+ try {
1674
+ const ring = join(_fd, '.eval-ring.jsonl');
1675
+ appendFileSync(ring, JSON.stringify(_rec) + '\n');
1676
+ try { if (statSync(ring).size > 16384) writeFileSync(ring, readFileSync(ring, 'utf-8').split('\n').filter(Boolean).slice(-50).join('\n') + '\n'); } catch {}
1677
+ } catch {}
1678
+ } catch {}
1665
1679
 
1666
1680
  // Only log DENY decisions from guard hook.
1667
1681
  // ALLOW decisions are logged by the audit hook (PostToolUse) to avoid double-counting.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solongate/proxy",
3
- "version": "0.59.4",
3
+ "version": "0.60.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": {
@@ -60,12 +60,17 @@
60
60
  },
61
61
  "dependencies": {
62
62
  "@modelcontextprotocol/sdk": "^1.26.0",
63
+ "ink": "^5.0.1",
64
+ "ink-spinner": "^5.0.0",
65
+ "ink-text-input": "^6.0.0",
66
+ "react": "^18.3.1",
63
67
  "zod": "^3.25.0"
64
68
  },
65
69
  "devDependencies": {
66
70
  "@open-policy-agent/opa-wasm": "^1.10.0",
67
- "chalk": "^5.3.0",
68
71
  "@solongate/tsconfig": "workspace:*",
72
+ "@types/react": "^18.3.12",
73
+ "chalk": "^5.3.0",
69
74
  "esbuild": "^0.19.12",
70
75
  "tsup": "^8.3.0",
71
76
  "tsx": "^4.19.0",