@solongate/proxy 0.34.0 → 0.35.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.
package/dist/index.js CHANGED
@@ -274,6 +274,9 @@ function parseArgs(argv) {
274
274
  aiJudgeApiKey = process.env.GROQ_API_KEY;
275
275
  }
276
276
  }
277
+ if (aiJudgeApiKey && (aiJudgeApiKey.includes("your_") || aiJudgeApiKey.includes("_here") || aiJudgeApiKey.length < 10)) {
278
+ aiJudgeApiKey = void 0;
279
+ }
277
280
  const aiJudge = aiJudgeEnabled ? {
278
281
  enabled: true,
279
282
  model: aiJudgeModel,
@@ -533,7 +536,7 @@ function isAlreadyProtected(server) {
533
536
  }
534
537
  return false;
535
538
  }
536
- function wrapServer(serverName, server, policy, agentName) {
539
+ function wrapServer(serverName, server, policy, agentName, aiJudge) {
537
540
  const env = { ...server.env ?? {} };
538
541
  env.SOLONGATE_API_KEY = "${SOLONGATE_API_KEY}";
539
542
  const proxyArgs = ["-y", "@solongate/proxy@latest"];
@@ -543,6 +546,9 @@ function wrapServer(serverName, server, policy, agentName) {
543
546
  if (agentName) {
544
547
  proxyArgs.push("--agent-name", agentName);
545
548
  }
549
+ if (aiJudge) {
550
+ proxyArgs.push("--ai-judge");
551
+ }
546
552
  proxyArgs.push("--verbose", "--", server.command, ...server.args ?? []);
547
553
  return {
548
554
  command: "npx",
@@ -563,7 +569,8 @@ function parseInitArgs(argv) {
563
569
  const args = argv.slice(2);
564
570
  const options = {
565
571
  all: false,
566
- tools: []
572
+ tools: [],
573
+ aiJudge: false
567
574
  };
568
575
  for (let i = 0; i < args.length; i++) {
569
576
  switch (args[i]) {
@@ -588,6 +595,9 @@ function parseInitArgs(argv) {
588
595
  case "--openclaw":
589
596
  options.tools.push("openclaw");
590
597
  break;
598
+ case "--ai-judge":
599
+ options.aiJudge = true;
600
+ break;
591
601
  case "--help":
592
602
  case "-h":
593
603
  printHelp();
@@ -615,8 +625,13 @@ AI TOOL HOOKS (default: all)
615
625
  --gemini Install hooks for Gemini CLI
616
626
  --openclaw Install hooks for OpenClaw
617
627
 
628
+ SECURITY LAYERS
629
+ --ai-judge Enable AI Judge (semantic intent analysis via LLM)
630
+ Requires GROQ_API_KEY in .env (free at https://console.groq.com/keys)
631
+
618
632
  EXAMPLES
619
633
  npx @solongate/proxy init --all # Protect everything, all tools
634
+ npx @solongate/proxy init --all --ai-judge # With AI Judge enabled
620
635
  npx @solongate/proxy init --all --claude-code --gemini # Only Claude Code + Gemini hooks
621
636
  npx @solongate/proxy init --all --policy policy.json # With custom policy
622
637
  `;
@@ -1046,7 +1061,7 @@ async function main() {
1046
1061
  const newConfig = { mcpServers: {} };
1047
1062
  for (const name of serverNames) {
1048
1063
  if (toProtect.includes(name)) {
1049
- newConfig.mcpServers[name] = wrapServer(name, config.mcpServers[name], policyValue);
1064
+ newConfig.mcpServers[name] = wrapServer(name, config.mcpServers[name], policyValue, void 0, options.aiJudge);
1050
1065
  } else {
1051
1066
  newConfig.mcpServers[name] = config.mcpServers[name];
1052
1067
  }
@@ -5671,6 +5686,12 @@ CRITICAL: Only DENY access to files EXPLICITLY in the protected_files list. "cat
5671
5686
 
5672
5687
  Respond with ONLY valid JSON, no markdown, no explanation outside the JSON:
5673
5688
  {"decision": "ALLOW" or "DENY", "reason": "brief one-line explanation", "confidence": 0.0 to 1.0}`;
5689
+ var AuthError = class extends Error {
5690
+ constructor(message) {
5691
+ super(message);
5692
+ this.name = "AuthError";
5693
+ }
5694
+ };
5674
5695
  var AiJudge = class _AiJudge {
5675
5696
  config;
5676
5697
  protectedFiles;
@@ -5727,6 +5748,13 @@ var AiJudge = class _AiJudge {
5727
5748
  this.consecutiveFailures++;
5728
5749
  this.lastFailureTime = Date.now();
5729
5750
  const message = err instanceof Error ? err.message : String(err);
5751
+ if (err instanceof AuthError) {
5752
+ return {
5753
+ decision: "ALLOW",
5754
+ reason: `AI Judge auth error (skipping): ${message.slice(0, 100)}`,
5755
+ confidence: 0.5
5756
+ };
5757
+ }
5730
5758
  return {
5731
5759
  decision: "DENY",
5732
5760
  reason: `AI Judge error (fail-closed): ${message.slice(0, 100)}`,
@@ -5808,6 +5836,9 @@ var AiJudge = class _AiJudge {
5808
5836
  });
5809
5837
  if (!res.ok) {
5810
5838
  const errBody = await res.text().catch(() => "");
5839
+ if (res.status === 401 || res.status === 403) {
5840
+ throw new AuthError(`LLM auth failed (${res.status}): ${errBody.slice(0, 200)}`);
5841
+ }
5811
5842
  throw new Error(`LLM endpoint returned ${res.status}: ${errBody.slice(0, 200)}`);
5812
5843
  }
5813
5844
  const data = await res.json();
@@ -6048,6 +6079,9 @@ var SolonGateProxy = class {
6048
6079
  if (match) groqKey = match[1].trim();
6049
6080
  }
6050
6081
  if (!groqKey) groqKey = process.env.GROQ_API_KEY;
6082
+ if (groqKey && (groqKey.includes("your_") || groqKey.includes("_here") || groqKey.length < 10)) {
6083
+ groqKey = void 0;
6084
+ }
6051
6085
  if (groqKey) {
6052
6086
  this.config.aiJudge = {
6053
6087
  enabled: true,
package/dist/init.js CHANGED
@@ -117,7 +117,7 @@ function isAlreadyProtected(server) {
117
117
  }
118
118
  return false;
119
119
  }
120
- function wrapServer(serverName, server, policy, agentName) {
120
+ function wrapServer(serverName, server, policy, agentName, aiJudge) {
121
121
  const env = { ...server.env ?? {} };
122
122
  env.SOLONGATE_API_KEY = "${SOLONGATE_API_KEY}";
123
123
  const proxyArgs = ["-y", "@solongate/proxy@latest"];
@@ -127,6 +127,9 @@ function wrapServer(serverName, server, policy, agentName) {
127
127
  if (agentName) {
128
128
  proxyArgs.push("--agent-name", agentName);
129
129
  }
130
+ if (aiJudge) {
131
+ proxyArgs.push("--ai-judge");
132
+ }
130
133
  proxyArgs.push("--verbose", "--", server.command, ...server.args ?? []);
131
134
  return {
132
135
  command: "npx",
@@ -147,7 +150,8 @@ function parseInitArgs(argv) {
147
150
  const args = argv.slice(2);
148
151
  const options = {
149
152
  all: false,
150
- tools: []
153
+ tools: [],
154
+ aiJudge: false
151
155
  };
152
156
  for (let i = 0; i < args.length; i++) {
153
157
  switch (args[i]) {
@@ -172,6 +176,9 @@ function parseInitArgs(argv) {
172
176
  case "--openclaw":
173
177
  options.tools.push("openclaw");
174
178
  break;
179
+ case "--ai-judge":
180
+ options.aiJudge = true;
181
+ break;
175
182
  case "--help":
176
183
  case "-h":
177
184
  printHelp();
@@ -199,8 +206,13 @@ AI TOOL HOOKS (default: all)
199
206
  --gemini Install hooks for Gemini CLI
200
207
  --openclaw Install hooks for OpenClaw
201
208
 
209
+ SECURITY LAYERS
210
+ --ai-judge Enable AI Judge (semantic intent analysis via LLM)
211
+ Requires GROQ_API_KEY in .env (free at https://console.groq.com/keys)
212
+
202
213
  EXAMPLES
203
214
  npx @solongate/proxy init --all # Protect everything, all tools
215
+ npx @solongate/proxy init --all --ai-judge # With AI Judge enabled
204
216
  npx @solongate/proxy init --all --claude-code --gemini # Only Claude Code + Gemini hooks
205
217
  npx @solongate/proxy init --all --policy policy.json # With custom policy
206
218
  `;
@@ -632,7 +644,7 @@ async function main() {
632
644
  const newConfig = { mcpServers: {} };
633
645
  for (const name of serverNames) {
634
646
  if (toProtect.includes(name)) {
635
- newConfig.mcpServers[name] = wrapServer(name, config.mcpServers[name], policyValue);
647
+ newConfig.mcpServers[name] = wrapServer(name, config.mcpServers[name], policyValue, void 0, options.aiJudge);
636
648
  } else {
637
649
  newConfig.mcpServers[name] = config.mcpServers[name];
638
650
  }
package/dist/lib.js CHANGED
@@ -3973,6 +3973,12 @@ CRITICAL: Only DENY access to files EXPLICITLY in the protected_files list. "cat
3973
3973
 
3974
3974
  Respond with ONLY valid JSON, no markdown, no explanation outside the JSON:
3975
3975
  {"decision": "ALLOW" or "DENY", "reason": "brief one-line explanation", "confidence": 0.0 to 1.0}`;
3976
+ var AuthError = class extends Error {
3977
+ constructor(message) {
3978
+ super(message);
3979
+ this.name = "AuthError";
3980
+ }
3981
+ };
3976
3982
  var AiJudge = class _AiJudge {
3977
3983
  config;
3978
3984
  protectedFiles;
@@ -4029,6 +4035,13 @@ var AiJudge = class _AiJudge {
4029
4035
  this.consecutiveFailures++;
4030
4036
  this.lastFailureTime = Date.now();
4031
4037
  const message = err instanceof Error ? err.message : String(err);
4038
+ if (err instanceof AuthError) {
4039
+ return {
4040
+ decision: "ALLOW",
4041
+ reason: `AI Judge auth error (skipping): ${message.slice(0, 100)}`,
4042
+ confidence: 0.5
4043
+ };
4044
+ }
4032
4045
  return {
4033
4046
  decision: "DENY",
4034
4047
  reason: `AI Judge error (fail-closed): ${message.slice(0, 100)}`,
@@ -4110,6 +4123,9 @@ var AiJudge = class _AiJudge {
4110
4123
  });
4111
4124
  if (!res.ok) {
4112
4125
  const errBody = await res.text().catch(() => "");
4126
+ if (res.status === 401 || res.status === 403) {
4127
+ throw new AuthError(`LLM auth failed (${res.status}): ${errBody.slice(0, 200)}`);
4128
+ }
4113
4129
  throw new Error(`LLM endpoint returned ${res.status}: ${errBody.slice(0, 200)}`);
4114
4130
  }
4115
4131
  const data = await res.json();
@@ -4350,6 +4366,9 @@ var SolonGateProxy = class {
4350
4366
  if (match) groqKey = match[1].trim();
4351
4367
  }
4352
4368
  if (!groqKey) groqKey = process.env.GROQ_API_KEY;
4369
+ if (groqKey && (groqKey.includes("your_") || groqKey.includes("_here") || groqKey.length < 10)) {
4370
+ groqKey = void 0;
4371
+ }
4353
4372
  if (groqKey) {
4354
4373
  this.config.aiJudge = {
4355
4374
  enabled: true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solongate/proxy",
3
- "version": "0.34.0",
3
+ "version": "0.35.0",
4
4
  "description": "AI tool security proxy — protect any AI tool server with customizable policies, path/command constraints, rate limiting, and audit logging. Zero code changes required.",
5
5
  "type": "module",
6
6
  "bin": {