@solongate/proxy 0.29.0 → 0.29.1

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/hooks/audit.mjs CHANGED
@@ -61,7 +61,8 @@ process.stdin.on('end', async () => {
61
61
  writeFileSync(join(flagDir, '.last-tool-call'), Date.now().toString());
62
62
  } catch {}
63
63
 
64
- await fetch(`${API_URL}/api/v1/audit-logs`, {
64
+ // Fire-and-forget: don't block tool execution waiting for API response
65
+ fetch(`${API_URL}/api/v1/audit-logs`, {
65
66
  method: 'POST',
66
67
  headers: {
67
68
  'Authorization': `Bearer ${API_KEY}`,
@@ -78,9 +79,10 @@ process.stdin.on('end', async () => {
78
79
  agent_name: AGENT_NAME,
79
80
  }),
80
81
  signal: AbortSignal.timeout(5000),
81
- });
82
+ }).catch(() => {}).finally(() => process.exit(0));
83
+ // Exit after short delay if fetch hangs on DNS/connect
84
+ setTimeout(() => process.exit(0), 3000);
82
85
  } catch {
83
- // Silent
86
+ process.exit(0);
84
87
  }
85
- process.exit(0);
86
88
  });
package/hooks/guard.mjs CHANGED
@@ -909,19 +909,34 @@ process.stdin.on('end', async () => {
909
909
  }
910
910
  }
911
911
 
912
- // ── Fetch PI config from Cloud ──
912
+ // ── Fetch PI config from Cloud (cached for 60s to avoid per-call latency) ──
913
913
  let piCfg = { piEnabled: true, piThreshold: 0.5, piMode: 'block', piWhitelist: [], piToolConfig: {}, piCustomPatterns: [], piWebhookUrl: null };
914
914
  if (API_KEY && API_KEY.startsWith('sg_live_')) {
915
+ const cacheFile = join(resolve('.solongate'), '.pi-config-cache.json');
916
+ let usedCache = false;
915
917
  try {
916
- const cfgRes = await fetch(API_URL + '/api/v1/project-config', {
917
- headers: { 'Authorization': 'Bearer ' + API_KEY },
918
- signal: AbortSignal.timeout(3000),
919
- });
920
- if (cfgRes.ok) {
921
- const cfg = await cfgRes.json();
922
- piCfg = { ...piCfg, ...cfg };
918
+ if (existsSync(cacheFile)) {
919
+ const cached = JSON.parse(readFileSync(cacheFile, 'utf-8'));
920
+ if (cached._ts && Date.now() - cached._ts < 60000) {
921
+ const { _ts, ...rest } = cached;
922
+ piCfg = { ...piCfg, ...rest };
923
+ usedCache = true;
924
+ }
923
925
  }
924
- } catch {} // Fallback: defaults (safe)
926
+ } catch {}
927
+ if (!usedCache) {
928
+ try {
929
+ const cfgRes = await fetch(API_URL + '/api/v1/project-config', {
930
+ headers: { 'Authorization': 'Bearer ' + API_KEY },
931
+ signal: AbortSignal.timeout(3000),
932
+ });
933
+ if (cfgRes.ok) {
934
+ const cfg = await cfgRes.json();
935
+ piCfg = { ...piCfg, ...cfg };
936
+ try { writeFileSync(cacheFile, JSON.stringify({ ...cfg, _ts: Date.now() })); } catch {}
937
+ }
938
+ } catch {} // Fallback: defaults (safe)
939
+ }
925
940
  }
926
941
 
927
942
  // ── Per-tool config: check if PI scanning is disabled for this tool ──
@@ -1078,8 +1093,23 @@ process.stdin.on('end', async () => {
1078
1093
  let aiJudgeEndpoint = 'https://api.groq.com/openai';
1079
1094
  let aiJudgeTimeout = 5000;
1080
1095
 
1081
- // Check cloud config for AI Judge settings
1096
+ // Check cloud config for AI Judge settings (cached for 60s)
1082
1097
  if (API_KEY && API_KEY.startsWith('sg_live_')) {
1098
+ const ajCacheFile = join(resolve('.solongate'), '.aj-config-cache.json');
1099
+ let ajCached = false;
1100
+ try {
1101
+ if (existsSync(ajCacheFile)) {
1102
+ const cached = JSON.parse(readFileSync(ajCacheFile, 'utf-8'));
1103
+ if (cached._ts && Date.now() - cached._ts < 60000) {
1104
+ aiJudgeEnabled = Boolean(cached.enabled);
1105
+ if (cached.model) aiJudgeModel = cached.model;
1106
+ if (cached.endpoint) aiJudgeEndpoint = cached.endpoint;
1107
+ if (cached.timeoutMs) aiJudgeTimeout = cached.timeoutMs;
1108
+ ajCached = true;
1109
+ }
1110
+ }
1111
+ } catch {}
1112
+ if (!ajCached) {
1083
1113
  try {
1084
1114
  const cfgRes = await fetch(API_URL + '/api/v1/project-config/ai-judge', {
1085
1115
  headers: { 'Authorization': 'Bearer ' + API_KEY },
@@ -1091,8 +1121,10 @@ process.stdin.on('end', async () => {
1091
1121
  if (cfg.model) aiJudgeModel = cfg.model;
1092
1122
  if (cfg.endpoint) aiJudgeEndpoint = cfg.endpoint;
1093
1123
  if (cfg.timeoutMs) aiJudgeTimeout = cfg.timeoutMs;
1124
+ try { writeFileSync(ajCacheFile, JSON.stringify({ ...cfg, _ts: Date.now() })); } catch {}
1094
1125
  }
1095
1126
  } catch {}
1127
+ }
1096
1128
  }
1097
1129
 
1098
1130
  if (aiJudgeEnabled && GROQ_KEY) {
package/hooks/stop.mjs CHANGED
@@ -49,8 +49,8 @@ process.stdin.on('end', async () => {
49
49
  process.exit(0);
50
50
  }
51
51
 
52
- // No tool calls → log 1 ALLOW for the text-only response
53
- await fetch(`${API_URL}/api/v1/audit-logs`, {
52
+ // No tool calls → log 1 ALLOW for the text-only response (fire-and-forget)
53
+ fetch(`${API_URL}/api/v1/audit-logs`, {
54
54
  method: 'POST',
55
55
  headers: {
56
56
  'Authorization': `Bearer ${API_KEY}`,
@@ -67,9 +67,9 @@ process.stdin.on('end', async () => {
67
67
  agent_name: AGENT_NAME,
68
68
  }),
69
69
  signal: AbortSignal.timeout(5000),
70
- });
70
+ }).catch(() => {}).finally(() => process.exit(0));
71
+ setTimeout(() => process.exit(0), 3000);
71
72
  } catch {
72
- // Silent
73
+ process.exit(0);
73
74
  }
74
- process.exit(0);
75
75
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solongate/proxy",
3
- "version": "0.29.0",
3
+ "version": "0.29.1",
4
4
  "description": "MCP security proxy — protect any MCP server with customizable policies, path/command constraints, rate limiting, and audit logging. Zero code changes required.",
5
5
  "type": "module",
6
6
  "bin": {