@kya-os/agentshield-nextjs 0.1.41 → 0.1.42

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 (79) hide show
  1. package/dist/.tsbuildinfo +1 -0
  2. package/dist/api-client.d.mts +145 -0
  3. package/dist/api-client.d.ts +145 -0
  4. package/dist/api-client.js +130 -0
  5. package/dist/api-client.js.map +1 -0
  6. package/dist/api-client.mjs +126 -0
  7. package/dist/api-client.mjs.map +1 -0
  8. package/dist/api-middleware.d.mts +118 -0
  9. package/dist/api-middleware.d.ts +118 -0
  10. package/dist/api-middleware.js +295 -0
  11. package/dist/api-middleware.js.map +1 -0
  12. package/dist/api-middleware.mjs +292 -0
  13. package/dist/api-middleware.mjs.map +1 -0
  14. package/dist/create-middleware.d.mts +2 -1
  15. package/dist/create-middleware.d.ts +2 -1
  16. package/dist/create-middleware.js +474 -200
  17. package/dist/create-middleware.js.map +1 -1
  18. package/dist/create-middleware.mjs +454 -200
  19. package/dist/create-middleware.mjs.map +1 -1
  20. package/dist/edge/index.d.mts +110 -0
  21. package/dist/edge/index.d.ts +110 -0
  22. package/dist/edge/index.js +253 -0
  23. package/dist/edge/index.js.map +1 -0
  24. package/dist/edge/index.mjs +251 -0
  25. package/dist/edge/index.mjs.map +1 -0
  26. package/dist/edge-detector-wrapper.d.mts +6 -15
  27. package/dist/edge-detector-wrapper.d.ts +6 -15
  28. package/dist/edge-detector-wrapper.js +314 -95
  29. package/dist/edge-detector-wrapper.js.map +1 -1
  30. package/dist/edge-detector-wrapper.mjs +294 -95
  31. package/dist/edge-detector-wrapper.mjs.map +1 -1
  32. package/dist/edge-runtime-loader.d.mts +1 -1
  33. package/dist/edge-runtime-loader.d.ts +1 -1
  34. package/dist/edge-runtime-loader.js +10 -25
  35. package/dist/edge-runtime-loader.js.map +1 -1
  36. package/dist/edge-runtime-loader.mjs +11 -23
  37. package/dist/edge-runtime-loader.mjs.map +1 -1
  38. package/dist/edge-wasm-middleware.js +2 -1
  39. package/dist/edge-wasm-middleware.js.map +1 -1
  40. package/dist/edge-wasm-middleware.mjs +2 -1
  41. package/dist/edge-wasm-middleware.mjs.map +1 -1
  42. package/dist/enhanced-middleware.d.mts +153 -0
  43. package/dist/enhanced-middleware.d.ts +153 -0
  44. package/dist/enhanced-middleware.js +1074 -0
  45. package/dist/enhanced-middleware.js.map +1 -0
  46. package/dist/enhanced-middleware.mjs +1072 -0
  47. package/dist/enhanced-middleware.mjs.map +1 -0
  48. package/dist/index.d.mts +8 -153
  49. package/dist/index.d.ts +8 -153
  50. package/dist/index.js +821 -233
  51. package/dist/index.js.map +1 -1
  52. package/dist/index.mjs +797 -234
  53. package/dist/index.mjs.map +1 -1
  54. package/dist/middleware.d.mts +2 -1
  55. package/dist/middleware.d.ts +2 -1
  56. package/dist/middleware.js +474 -200
  57. package/dist/middleware.js.map +1 -1
  58. package/dist/middleware.mjs +454 -200
  59. package/dist/middleware.mjs.map +1 -1
  60. package/dist/session-tracker.d.mts +1 -1
  61. package/dist/session-tracker.d.ts +1 -1
  62. package/dist/session-tracker.js.map +1 -1
  63. package/dist/session-tracker.mjs.map +1 -1
  64. package/dist/signature-verifier.d.mts +1 -0
  65. package/dist/signature-verifier.d.ts +1 -0
  66. package/dist/signature-verifier.js +204 -44
  67. package/dist/signature-verifier.js.map +1 -1
  68. package/dist/signature-verifier.mjs +184 -44
  69. package/dist/signature-verifier.mjs.map +1 -1
  70. package/dist/{types-BJTEUa4T.d.mts → types-DVmy9NE3.d.mts} +19 -2
  71. package/dist/{types-BJTEUa4T.d.ts → types-DVmy9NE3.d.ts} +19 -2
  72. package/dist/wasm-middleware.js +15 -6
  73. package/dist/wasm-middleware.js.map +1 -1
  74. package/dist/wasm-middleware.mjs +15 -6
  75. package/dist/wasm-middleware.mjs.map +1 -1
  76. package/package.json +27 -6
  77. package/wasm/agentshield_wasm.js +209 -152
  78. package/wasm/agentshield_wasm_bg.wasm +0 -0
  79. package/wasm/package.json +30 -0
@@ -1,21 +1,151 @@
1
1
  'use strict';
2
2
 
3
3
  var server = require('next/server');
4
+ var ed25519 = require('@noble/ed25519');
5
+ var sha2 = require('@noble/hashes/sha2');
6
+ var agentshieldShared = require('@kya-os/agentshield-shared');
4
7
 
5
- // src/middleware.ts
8
+ function _interopNamespace(e) {
9
+ if (e && e.__esModule) return e;
10
+ var n = Object.create(null);
11
+ if (e) {
12
+ Object.keys(e).forEach(function (k) {
13
+ if (k !== 'default') {
14
+ var d = Object.getOwnPropertyDescriptor(e, k);
15
+ Object.defineProperty(n, k, d.get ? d : {
16
+ enumerable: true,
17
+ get: function () { return e[k]; }
18
+ });
19
+ }
20
+ });
21
+ }
22
+ n.default = e;
23
+ return Object.freeze(n);
24
+ }
25
+
26
+ var ed25519__namespace = /*#__PURE__*/_interopNamespace(ed25519);
6
27
 
7
- // src/signature-verifier.ts
28
+ // src/middleware.ts
29
+ ed25519__namespace.etc.sha512Sync = (...m) => sha2.sha512(ed25519__namespace.etc.concatBytes(...m));
8
30
  var KNOWN_KEYS = {
9
31
  chatgpt: [
10
32
  {
11
33
  kid: "otMqcjr17mGyruktGvJU8oojQTSMHlVm7uO-lrcqbdg",
12
34
  // ChatGPT's current Ed25519 public key (base64)
35
+ // Source: https://chatgpt.com/.well-known/http-message-signatures-directory
13
36
  publicKey: "7F_3jDlxaquwh291MiACkcS3Opq88NksyHiakzS-Y1g",
14
- validFrom: (/* @__PURE__ */ new Date("2025-01-01")).getTime() / 1e3,
15
- validUntil: (/* @__PURE__ */ new Date("2025-04-11")).getTime() / 1e3
37
+ validFrom: 1735689600,
38
+ // Jan 1, 2025 (from OpenAI's nbf)
39
+ // Extended expiration as fallback safety - API fetch should provide fresh keys
40
+ // Check OpenAI's well-known endpoint for actual expiration dates
41
+ validUntil: 1799625600
42
+ // Jan 1, 2027 (extended for fallback safety)
16
43
  }
17
44
  ]
18
45
  };
46
+ var keyCache = /* @__PURE__ */ new Map();
47
+ var CACHE_TTL_MS = 5 * 60 * 1e3;
48
+ var CACHE_MAX_SIZE = 100;
49
+ function getApiBaseUrl() {
50
+ if (typeof window !== "undefined") {
51
+ return "/api/internal";
52
+ }
53
+ const baseUrl2 = process.env.NEXT_PUBLIC_APP_URL || process.env.NEXT_PUBLIC_API_URL || process.env.API_URL || (process.env.VERCEL_URL ? `https://${process.env.VERCEL_URL}` : null);
54
+ if (baseUrl2) {
55
+ return baseUrl2.replace(/\/$/, "") + "/api/internal";
56
+ }
57
+ if (process.env.NODE_ENV !== "production") {
58
+ console.warn(
59
+ "[Signature] No base URL configured for server-side fetch. Using localhost fallback."
60
+ );
61
+ return "http://localhost:3000/api/internal";
62
+ }
63
+ console.error(
64
+ "[Signature] CRITICAL: No base URL configured for server-side fetch in production!"
65
+ );
66
+ return "/api/internal";
67
+ }
68
+ function cleanupExpiredCache() {
69
+ const now = Date.now();
70
+ const entriesToDelete = [];
71
+ for (const [agent, cached] of keyCache.entries()) {
72
+ if (now - cached.cachedAt > CACHE_TTL_MS) {
73
+ entriesToDelete.push(agent);
74
+ }
75
+ }
76
+ for (const agent of entriesToDelete) {
77
+ keyCache.delete(agent);
78
+ }
79
+ if (keyCache.size > CACHE_MAX_SIZE) {
80
+ const entries = Array.from(keyCache.entries()).map(([agent, cached]) => ({
81
+ agent,
82
+ cachedAt: cached.cachedAt
83
+ }));
84
+ entries.sort((a, b) => a.cachedAt - b.cachedAt);
85
+ const toRemove = entries.slice(0, keyCache.size - CACHE_MAX_SIZE);
86
+ for (const entry of toRemove) {
87
+ keyCache.delete(entry.agent);
88
+ }
89
+ }
90
+ }
91
+ async function fetchKeysFromApi(agent) {
92
+ if (keyCache.size > CACHE_MAX_SIZE) {
93
+ cleanupExpiredCache();
94
+ }
95
+ const cached = keyCache.get(agent);
96
+ if (cached && Date.now() - cached.cachedAt < CACHE_TTL_MS) {
97
+ return cached.keys;
98
+ }
99
+ if (typeof fetch === "undefined") {
100
+ console.warn("[Signature] fetch() not available in this environment");
101
+ return null;
102
+ }
103
+ try {
104
+ const apiBaseUrl = getApiBaseUrl();
105
+ const url = `${apiBaseUrl}/signature-keys?agent=${encodeURIComponent(agent)}`;
106
+ const response = await fetch(url, {
107
+ method: "GET",
108
+ headers: {
109
+ "Content-Type": "application/json"
110
+ },
111
+ // 5 second timeout
112
+ signal: AbortSignal.timeout(5e3)
113
+ });
114
+ if (!response.ok) {
115
+ console.warn(`[Signature] Failed to fetch keys from API: ${response.status}`);
116
+ return null;
117
+ }
118
+ const data = await response.json();
119
+ if (!data.keys || !Array.isArray(data.keys) || data.keys.length === 0) {
120
+ console.warn(`[Signature] No keys returned from API for agent: ${agent}`);
121
+ return null;
122
+ }
123
+ keyCache.set(agent, {
124
+ keys: data.keys,
125
+ cachedAt: Date.now()
126
+ });
127
+ return data.keys;
128
+ } catch (error) {
129
+ console.warn("[Signature] Error fetching keys from API, using fallback", {
130
+ error: error instanceof Error ? error.message : "Unknown error",
131
+ agent
132
+ });
133
+ return null;
134
+ }
135
+ }
136
+ function isValidAgent(agent) {
137
+ return agent in KNOWN_KEYS;
138
+ }
139
+ async function getKeysForAgent(agent) {
140
+ const apiKeys = await fetchKeysFromApi(agent);
141
+ if (apiKeys && apiKeys.length > 0) {
142
+ return apiKeys;
143
+ }
144
+ if (isValidAgent(agent)) {
145
+ return KNOWN_KEYS[agent];
146
+ }
147
+ return [];
148
+ }
19
149
  function parseSignatureInput(signatureInput) {
20
150
  try {
21
151
  const match = signatureInput.match(/sig1=\((.*?)\);(.+)/);
@@ -51,21 +181,29 @@ function buildSignatureBase(method, path, headers, signedHeaders) {
51
181
  case "@authority":
52
182
  value = headers["host"] || headers["Host"] || "";
53
183
  break;
54
- default:
55
- const key = Object.keys(headers).find(
56
- (k) => k.toLowerCase() === headerName.toLowerCase()
57
- );
184
+ default: {
185
+ const key = Object.keys(headers).find((k) => k.toLowerCase() === headerName.toLowerCase());
58
186
  value = key ? headers[key] || "" : "";
59
187
  break;
188
+ }
60
189
  }
61
190
  components.push(`"${headerName}": ${value}`);
62
191
  }
63
192
  return components.join("\n");
64
193
  }
194
+ function base64ToBytes(base64) {
195
+ let standardBase64 = base64.replace(/-/g, "+").replace(/_/g, "/");
196
+ const padding = standardBase64.length % 4;
197
+ if (padding) {
198
+ standardBase64 += "=".repeat(4 - padding);
199
+ }
200
+ const binaryString = atob(standardBase64);
201
+ return Uint8Array.from(binaryString, (c) => c.charCodeAt(0));
202
+ }
65
203
  async function verifyEd25519Signature(publicKeyBase64, signatureBase64, message) {
66
204
  try {
67
- const publicKeyBytes = Uint8Array.from(atob(publicKeyBase64), (c) => c.charCodeAt(0));
68
- const signatureBytes = Uint8Array.from(atob(signatureBase64), (c) => c.charCodeAt(0));
205
+ const publicKeyBytes = base64ToBytes(publicKeyBase64);
206
+ const signatureBytes = base64ToBytes(signatureBase64);
69
207
  const messageBytes = new TextEncoder().encode(message);
70
208
  if (publicKeyBytes.length !== 32) {
71
209
  console.error("[Signature] Invalid public key length:", publicKeyBytes.length);
@@ -75,34 +213,36 @@ async function verifyEd25519Signature(publicKeyBase64, signatureBase64, message)
75
213
  console.error("[Signature] Invalid signature length:", signatureBytes.length);
76
214
  return false;
77
215
  }
78
- const publicKey = await crypto.subtle.importKey(
79
- "raw",
80
- publicKeyBytes,
81
- {
82
- name: "Ed25519",
83
- namedCurve: "Ed25519"
84
- },
85
- false,
86
- ["verify"]
87
- );
88
- const isValid = await crypto.subtle.verify(
89
- "Ed25519",
90
- publicKey,
91
- signatureBytes,
92
- messageBytes
93
- );
94
- return isValid;
95
- } catch (error) {
96
- console.error("[Signature] Ed25519 verification failed:", error);
97
- if (typeof window === "undefined") {
98
- try {
99
- console.warn("[Signature] Ed25519 not supported in this environment");
100
- return false;
101
- } catch {
102
- return false;
103
- }
216
+ return ed25519__namespace.verify(signatureBytes, messageBytes, publicKeyBytes);
217
+ } catch (nobleError) {
218
+ console.warn("[Signature] @noble/ed25519 failed, trying Web Crypto fallback:", nobleError);
219
+ try {
220
+ const publicKeyBytes = base64ToBytes(publicKeyBase64);
221
+ const signatureBytes = base64ToBytes(signatureBase64);
222
+ const messageBytes = new TextEncoder().encode(message);
223
+ const publicKey = await crypto.subtle.importKey(
224
+ "raw",
225
+ publicKeyBytes.buffer,
226
+ {
227
+ name: "Ed25519",
228
+ namedCurve: "Ed25519"
229
+ },
230
+ false,
231
+ ["verify"]
232
+ );
233
+ return await crypto.subtle.verify(
234
+ "Ed25519",
235
+ publicKey,
236
+ signatureBytes.buffer,
237
+ messageBytes
238
+ );
239
+ } catch (cryptoError) {
240
+ console.error("[Signature] Both @noble/ed25519 and Web Crypto failed:", {
241
+ nobleError: nobleError instanceof Error ? nobleError.message : "Unknown",
242
+ cryptoError: cryptoError instanceof Error ? cryptoError.message : "Unknown"
243
+ });
244
+ return false;
104
245
  }
105
- return false;
106
246
  }
107
247
  }
108
248
  async function verifyAgentSignature(method, path, headers) {
@@ -147,12 +287,12 @@ async function verifyAgentSignature(method, path, headers) {
147
287
  }
148
288
  }
149
289
  let agent;
150
- let knownKeys;
290
+ let agentKey;
151
291
  if (signatureAgent === '"https://chatgpt.com"' || signatureAgent?.includes("chatgpt.com")) {
152
292
  agent = "ChatGPT";
153
- knownKeys = KNOWN_KEYS.chatgpt;
293
+ agentKey = "chatgpt";
154
294
  }
155
- if (!agent || !knownKeys) {
295
+ if (!agent || !agentKey) {
156
296
  return {
157
297
  isValid: false,
158
298
  confidence: 0,
@@ -160,6 +300,15 @@ async function verifyAgentSignature(method, path, headers) {
160
300
  verificationMethod: "none"
161
301
  };
162
302
  }
303
+ const knownKeys = await getKeysForAgent(agentKey);
304
+ if (knownKeys.length === 0) {
305
+ return {
306
+ isValid: false,
307
+ confidence: 0,
308
+ reason: "No keys available for agent",
309
+ verificationMethod: "none"
310
+ };
311
+ }
163
312
  const key = knownKeys.find((k) => k.kid === parsed.keyid);
164
313
  if (!key) {
165
314
  return {
@@ -186,11 +335,7 @@ async function verifyAgentSignature(method, path, headers) {
186
335
  if (signatureValue.endsWith(":")) {
187
336
  signatureValue = signatureValue.slice(0, -1);
188
337
  }
189
- const isValid = await verifyEd25519Signature(
190
- key.publicKey,
191
- signatureValue,
192
- signatureBase
193
- );
338
+ const isValid = await verifyEd25519Signature(key.publicKey, signatureValue, signatureBase);
194
339
  if (isValid) {
195
340
  return {
196
341
  isValid: true,
@@ -214,27 +359,27 @@ function hasSignatureHeaders(headers) {
214
359
  }
215
360
  function isChatGPTSignature(headers) {
216
361
  const signatureAgent = headers["signature-agent"] || headers["Signature-Agent"];
217
- return signatureAgent === '"https://chatgpt.com"' || (signatureAgent?.includes("chatgpt.com") || false);
362
+ if (!signatureAgent) {
363
+ return false;
364
+ }
365
+ const agentUrlStr = signatureAgent.replace(/^"+|"+$/g, "");
366
+ if (agentUrlStr === "https://chatgpt.com") {
367
+ return true;
368
+ }
369
+ try {
370
+ const agentUrl = new URL(agentUrlStr);
371
+ const allowedHosts = ["chatgpt.com", "www.chatgpt.com"];
372
+ return allowedHosts.includes(agentUrl.host);
373
+ } catch {
374
+ return false;
375
+ }
218
376
  }
219
-
220
- // src/edge-detector-wrapper.ts
221
- var AI_AGENT_PATTERNS = [
222
- { pattern: /chatgpt-user/i, type: "chatgpt", name: "ChatGPT" },
223
- { pattern: /claude-web/i, type: "claude", name: "Claude" },
224
- { pattern: /perplexitybot/i, type: "perplexity", name: "Perplexity" },
225
- { pattern: /perplexity-user/i, type: "perplexity", name: "Perplexity" },
226
- { pattern: /perplexity-ai/i, type: "perplexity", name: "Perplexity" },
227
- { pattern: /perplexity/i, type: "perplexity", name: "Perplexity" },
228
- // Fallback
229
- { pattern: /bingbot/i, type: "bing", name: "Bing AI" },
230
- { pattern: /anthropic-ai/i, type: "anthropic", name: "Anthropic" }
231
- ];
232
- var CLOUD_PROVIDERS = {
233
- aws: ["54.", "52.", "35.", "18.", "3."],
234
- gcp: ["35.", "34.", "104.", "107.", "108."],
235
- azure: ["13.", "20.", "40.", "52.", "104."]
236
- };
377
+ var rules = agentshieldShared.loadRulesSync();
237
378
  var EdgeAgentDetector = class {
379
+ rules;
380
+ constructor() {
381
+ this.rules = rules;
382
+ }
238
383
  async analyze(input) {
239
384
  const reasons = [];
240
385
  let detectedAgent;
@@ -253,7 +398,7 @@ var EdgeAgentDetector = class {
253
398
  headers
254
399
  );
255
400
  if (signatureResult.isValid) {
256
- confidence = signatureResult.confidence;
401
+ confidence = signatureResult.confidence * 100;
257
402
  reasons.push(`verified_signature:${signatureResult.agent?.toLowerCase() || "unknown"}`);
258
403
  if (signatureResult.agent) {
259
404
  detectedAgent = {
@@ -266,7 +411,13 @@ var EdgeAgentDetector = class {
266
411
  reasons.push(`keyid:${signatureResult.keyid}`);
267
412
  }
268
413
  } else {
269
- confidence = Math.max(confidence, 0.3);
414
+ console.warn("[EdgeAgentDetector] Signature verification failed:", {
415
+ reason: signatureResult.reason,
416
+ agent: signatureResult.agent,
417
+ hasSignatureAgent: !!headers["signature-agent"] || !!headers["Signature-Agent"],
418
+ signatureAgentValue: headers["signature-agent"] || headers["Signature-Agent"]
419
+ });
420
+ confidence = Math.max(confidence, 30);
270
421
  reasons.push("invalid_signature");
271
422
  if (signatureResult.reason) {
272
423
  reasons.push(`signature_error:${signatureResult.reason}`);
@@ -278,68 +429,133 @@ var EdgeAgentDetector = class {
278
429
  }
279
430
  } catch (error) {
280
431
  console.error("[EdgeAgentDetector] Signature verification error:", error);
281
- confidence = Math.max(confidence, 0.2);
432
+ confidence = Math.max(confidence, 20);
282
433
  reasons.push("signature_verification_error");
283
434
  }
284
435
  }
285
436
  const userAgent = input.userAgent || input.headers?.["user-agent"] || "";
286
437
  if (userAgent) {
287
- for (const { pattern, type, name } of AI_AGENT_PATTERNS) {
288
- if (pattern.test(userAgent)) {
289
- const highConfidenceAgents = [
290
- "chatgpt",
291
- "claude",
292
- "perplexity",
293
- "anthropic"
294
- ];
295
- const patternConfidence = highConfidenceAgents.includes(type) ? 0.85 : 0.5;
296
- confidence = Math.max(confidence, patternConfidence);
297
- reasons.push(`known_pattern:${type}`);
438
+ const userAgentEntries = Object.entries(this.rules.rules.userAgents);
439
+ const genericKeys = ["generic_bot", "dev_tools", "automation_tools"];
440
+ const sortedEntries = userAgentEntries.sort((a, b) => {
441
+ const aIsGeneric = genericKeys.includes(a[0]);
442
+ const bIsGeneric = genericKeys.includes(b[0]);
443
+ if (aIsGeneric && !bIsGeneric) return 1;
444
+ if (!aIsGeneric && bIsGeneric) return -1;
445
+ return 0;
446
+ });
447
+ for (const [agentKey, agentRule] of sortedEntries) {
448
+ const rule = agentRule;
449
+ const matched = rule.patterns.some((pattern) => {
450
+ const regex = new RegExp(pattern, "i");
451
+ return regex.test(userAgent);
452
+ });
453
+ if (matched) {
454
+ const agentType = this.getAgentType(agentKey);
455
+ const agentName = this.getAgentName(agentKey);
456
+ confidence = Math.max(confidence, rule.confidence * 100);
457
+ reasons.push(`known_pattern:${agentType}`);
298
458
  if (!detectedAgent) {
299
- detectedAgent = { type, name };
459
+ detectedAgent = { type: agentType, name: agentName };
300
460
  verificationMethod = "pattern";
301
461
  }
302
462
  break;
303
463
  }
304
464
  }
305
465
  }
306
- const aiHeaders = [
307
- "openai-conversation-id",
308
- "openai-ephemeral-user-id",
309
- "anthropic-client-id",
310
- "x-goog-api-client",
311
- "x-ms-copilot-id"
312
- ];
313
- const foundAiHeaders = aiHeaders.filter(
314
- (header) => normalizedHeaders[header]
466
+ const suspiciousHeaders = this.rules.rules.headers.suspicious;
467
+ const foundAiHeaders = suspiciousHeaders.filter(
468
+ (headerRule) => normalizedHeaders[headerRule.name.toLowerCase()]
315
469
  );
316
470
  if (foundAiHeaders.length > 0) {
317
- confidence = Math.max(confidence, 0.6);
471
+ const maxConfidence = Math.max(...foundAiHeaders.map((h) => h.confidence * 100));
472
+ confidence = Math.max(confidence, maxConfidence);
318
473
  reasons.push(`ai_headers:${foundAiHeaders.length}`);
319
474
  }
320
475
  const ip = input.ip || input.ipAddress;
321
476
  if (ip && !normalizedHeaders["x-forwarded-for"] && !normalizedHeaders["x-real-ip"]) {
322
- for (const [provider, prefixes] of Object.entries(CLOUD_PROVIDERS)) {
323
- if (prefixes.some((prefix) => ip.startsWith(prefix))) {
324
- confidence = Math.max(confidence, 0.4);
477
+ const ipRanges = "providers" in this.rules.rules.ipRanges ? this.rules.rules.ipRanges.providers : this.rules.rules.ipRanges;
478
+ for (const [provider, ipRule] of Object.entries(ipRanges)) {
479
+ if (!ipRule || typeof ipRule !== "object" || !("ranges" in ipRule) || !Array.isArray(ipRule.ranges))
480
+ continue;
481
+ const matched = ipRule.ranges.some((range) => {
482
+ const prefix = range.split("/")[0];
483
+ const prefixParts = prefix.split(".");
484
+ const ipParts = ip.split(".");
485
+ for (let i = 0; i < Math.min(prefixParts.length - 1, 2); i++) {
486
+ if (prefixParts[i] !== ipParts[i] && prefixParts[i] !== "0") {
487
+ return false;
488
+ }
489
+ }
490
+ return true;
491
+ });
492
+ if (matched) {
493
+ const rule = ipRule;
494
+ confidence = Math.max(confidence, rule.confidence * 40);
325
495
  reasons.push(`cloud_provider:${provider}`);
326
496
  break;
327
497
  }
328
498
  }
329
499
  }
330
- if (reasons.length > 2 && confidence < 1) {
331
- confidence = Math.min(confidence * 1.2, 0.95);
500
+ if (reasons.length > 2 && confidence < 100) {
501
+ confidence = Math.min(confidence * 1.2, 95);
332
502
  }
503
+ confidence = Math.min(Math.max(confidence, 0), 100);
333
504
  return {
334
- isAgent: confidence > 0.3,
505
+ isAgent: confidence > 30,
506
+ // Updated to 0-100 scale (was 0.3)
335
507
  confidence,
508
+ detectionClass: confidence > 30 && detectedAgent ? { type: "AiAgent", agentType: detectedAgent.name } : confidence > 30 ? { type: "Unknown" } : { type: "Human" },
509
+ signals: [],
510
+ // Will be populated by enhanced detection engine in future tasks
336
511
  ...detectedAgent && { detectedAgent },
337
512
  reasons,
338
- ...verificationMethod && { verificationMethod },
339
- forgeabilityRisk: verificationMethod === "signature" ? "low" : confidence > 0.8 ? "medium" : "high",
513
+ ...verificationMethod && {
514
+ verificationMethod
515
+ },
516
+ forgeabilityRisk: verificationMethod === "signature" ? "low" : confidence > 80 ? "medium" : "high",
517
+ // Updated to 0-100 scale
340
518
  timestamp: /* @__PURE__ */ new Date()
341
519
  };
342
520
  }
521
+ /**
522
+ * Get agent type from rule key
523
+ */
524
+ getAgentType(agentKey) {
525
+ const typeMap = {
526
+ openai_gptbot: "openai",
527
+ anthropic_claude: "anthropic",
528
+ perplexity_bot: "perplexity",
529
+ google_ai: "google",
530
+ microsoft_ai: "microsoft",
531
+ meta_ai: "meta",
532
+ cohere_bot: "cohere",
533
+ huggingface_bot: "huggingface",
534
+ generic_bot: "generic",
535
+ dev_tools: "dev",
536
+ automation_tools: "automation"
537
+ };
538
+ return typeMap[agentKey] || agentKey;
539
+ }
540
+ /**
541
+ * Get agent name from rule key
542
+ */
543
+ getAgentName(agentKey) {
544
+ const nameMap = {
545
+ openai_gptbot: "ChatGPT/GPTBot",
546
+ anthropic_claude: "Claude",
547
+ perplexity_bot: "Perplexity",
548
+ google_ai: "Google AI",
549
+ microsoft_ai: "Microsoft Copilot",
550
+ meta_ai: "Meta AI",
551
+ cohere_bot: "Cohere",
552
+ huggingface_bot: "HuggingFace",
553
+ generic_bot: "Generic Bot",
554
+ dev_tools: "Development Tool",
555
+ automation_tools: "Automation Tool"
556
+ };
557
+ return nameMap[agentKey] || agentKey;
558
+ }
343
559
  };
344
560
  var EdgeAgentDetectorWrapper = class {
345
561
  detector;
@@ -410,26 +626,31 @@ async function initWasm() {
410
626
  throw new Error(`Failed to fetch WASM: ${response2.status}`);
411
627
  }
412
628
  const streamResponse = response2.clone();
413
- const { instance } = await WebAssembly.instantiateStreaming(
414
- streamResponse,
415
- {
416
- wbg: {
417
- __wbg_log_1d3ae13c3d5e6b8e: (ptr, len) => {
418
- console.log("WASM:", ptr, len);
419
- },
420
- __wbindgen_throw: (ptr, len) => {
421
- throw new Error(`WASM Error at ${ptr}, length ${len}`);
629
+ const { instance } = await WebAssembly.instantiateStreaming(streamResponse, {
630
+ wbg: {
631
+ __wbg_log_1d3ae13c3d5e6b8e: (ptr, len) => {
632
+ if (process.env.NODE_ENV !== "production") {
633
+ console.debug("WASM:", ptr, len);
422
634
  }
635
+ },
636
+ __wbindgen_throw: (ptr, len) => {
637
+ throw new Error(`WASM Error at ${ptr}, length ${len}`);
423
638
  }
424
639
  }
425
- );
640
+ });
426
641
  wasmInstance = instance;
427
642
  wasmExports = instance.exports;
428
- console.log("[AgentShield] \u2705 WASM module initialized with streaming");
643
+ if (process.env.NODE_ENV !== "production") {
644
+ console.debug("[AgentShield] \u2705 WASM module initialized with streaming");
645
+ }
429
646
  return;
430
647
  } catch (streamError) {
431
648
  if (!controller.signal.aborted) {
432
- console.log("[AgentShield] Streaming compilation failed, falling back to standard compilation");
649
+ if (process.env.NODE_ENV !== "production") {
650
+ console.debug(
651
+ "[AgentShield] Streaming compilation failed, falling back to standard compilation"
652
+ );
653
+ }
433
654
  } else {
434
655
  throw streamError;
435
656
  }
@@ -445,7 +666,9 @@ async function initWasm() {
445
666
  const imports = {
446
667
  wbg: {
447
668
  __wbg_log_1d3ae13c3d5e6b8e: (ptr, len) => {
448
- console.log("WASM:", ptr, len);
669
+ if (process.env.NODE_ENV !== "production") {
670
+ console.debug("WASM:", ptr, len);
671
+ }
449
672
  },
450
673
  __wbindgen_throw: (ptr, len) => {
451
674
  throw new Error(`WASM Error at ${ptr}, length ${len}`);
@@ -454,12 +677,20 @@ async function initWasm() {
454
677
  };
455
678
  wasmInstance = await WebAssembly.instantiate(compiledModule, imports);
456
679
  wasmExports = wasmInstance.exports;
457
- console.log("[AgentShield] \u2705 WASM module initialized via fallback");
680
+ if (process.env.NODE_ENV !== "production") {
681
+ console.debug("[AgentShield] \u2705 WASM module initialized via fallback");
682
+ }
458
683
  } catch (fetchError) {
459
- if (fetchError.name === "AbortError") {
460
- console.warn("[AgentShield] WASM fetch timed out after 3 seconds - using pattern detection");
684
+ const error = fetchError;
685
+ if (error.name === "AbortError") {
686
+ console.warn(
687
+ "[AgentShield] WASM fetch timed out after 3 seconds - using pattern detection"
688
+ );
461
689
  } else {
462
- console.warn("[AgentShield] Failed to fetch WASM file:", fetchError.message);
690
+ console.warn(
691
+ "[AgentShield] Failed to fetch WASM file:",
692
+ error.message || "Unknown error"
693
+ );
463
694
  }
464
695
  wasmExports = null;
465
696
  }
@@ -520,30 +751,16 @@ async function isWasmAvailable() {
520
751
  return false;
521
752
  }
522
753
  }
523
-
524
- // src/edge-detector-with-wasm.ts
525
- var AI_AGENT_PATTERNS2 = [
526
- { pattern: /chatgpt-user/i, type: "chatgpt", name: "ChatGPT" },
527
- { pattern: /claude-web/i, type: "claude", name: "Claude" },
528
- { pattern: /perplexitybot/i, type: "perplexity", name: "Perplexity" },
529
- { pattern: /perplexity-user/i, type: "perplexity", name: "Perplexity" },
530
- { pattern: /perplexity-ai/i, type: "perplexity", name: "Perplexity" },
531
- { pattern: /perplexity/i, type: "perplexity", name: "Perplexity" },
532
- { pattern: /bingbot/i, type: "bing", name: "Bing AI" },
533
- { pattern: /anthropic-ai/i, type: "anthropic", name: "Anthropic" }
534
- ];
535
- var CLOUD_PROVIDERS2 = {
536
- aws: ["54.", "52.", "35.", "18.", "3."],
537
- gcp: ["35.", "34.", "104.", "107.", "108."],
538
- azure: ["13.", "20.", "40.", "52.", "104."]
539
- };
754
+ var rules2 = agentshieldShared.loadRulesSync();
540
755
  var EdgeAgentDetectorWithWasm = class {
541
756
  constructor(enableWasm = true) {
542
757
  this.enableWasm = enableWasm;
758
+ this.rules = rules2;
543
759
  }
544
760
  wasmEnabled = false;
545
761
  initPromise = null;
546
762
  baseUrl = null;
763
+ rules;
547
764
  /**
548
765
  * Set the base URL for WASM loading in Edge Runtime
549
766
  */
@@ -566,11 +783,14 @@ var EdgeAgentDetectorWithWasm = class {
566
783
  this.initPromise = (async () => {
567
784
  try {
568
785
  const wasmAvailable = await isWasmAvailable();
569
- this.wasmEnabled = wasmAvailable;
570
- if (this.wasmEnabled) {
571
- console.log("[AgentShield] WASM detection enabled");
786
+ if (wasmAvailable) {
787
+ if (this.baseUrl) {
788
+ setWasmBaseUrl(this.baseUrl);
789
+ }
790
+ await initWasm();
791
+ this.wasmEnabled = true;
572
792
  } else {
573
- console.log("[AgentShield] WASM not available, using pattern detection");
793
+ this.wasmEnabled = false;
574
794
  }
575
795
  } catch (error) {
576
796
  console.error("[AgentShield] Failed to initialize WASM:", error);
@@ -595,69 +815,84 @@ var EdgeAgentDetectorWithWasm = class {
595
815
  const signaturePresent = !!(normalizedHeaders["signature"] || normalizedHeaders["signature-input"]);
596
816
  const signatureAgent = normalizedHeaders["signature-agent"];
597
817
  if (signatureAgent?.includes("chatgpt.com")) {
598
- confidence = 0.85;
818
+ confidence = 85;
599
819
  reasons.push("signature_agent:chatgpt");
600
820
  detectedAgent = { type: "chatgpt", name: "ChatGPT" };
601
821
  verificationMethod = "signature";
602
822
  } else if (signaturePresent) {
603
- confidence = Math.max(confidence, 0.4);
823
+ confidence = Math.max(confidence, 40);
604
824
  reasons.push("signature_present");
605
825
  }
606
826
  const userAgent = input.userAgent || input.headers?.["user-agent"] || "";
607
827
  if (userAgent) {
608
- for (const { pattern, type, name } of AI_AGENT_PATTERNS2) {
609
- if (pattern.test(userAgent)) {
610
- const highConfidenceAgents = [
611
- "chatgpt",
612
- "claude",
613
- "perplexity",
614
- "anthropic"
615
- ];
616
- const patternConfidence = highConfidenceAgents.includes(type) ? 0.85 : 0.5;
617
- confidence = Math.max(confidence, patternConfidence);
618
- reasons.push(`known_pattern:${type}`);
828
+ for (const [agentKey, agentRule] of Object.entries(this.rules.rules.userAgents)) {
829
+ const matched = agentRule.patterns.some((pattern) => {
830
+ const regex = new RegExp(pattern, "i");
831
+ return regex.test(userAgent);
832
+ });
833
+ if (matched) {
834
+ const agentType = this.getAgentType(agentKey);
835
+ const agentName = this.getAgentName(agentKey);
836
+ confidence = Math.max(confidence, Math.round(agentRule.confidence * 0.85 * 100));
837
+ reasons.push(`known_pattern:${agentType}`);
619
838
  if (!detectedAgent) {
620
- detectedAgent = { type, name };
839
+ detectedAgent = { type: agentType, name: agentName };
621
840
  verificationMethod = "pattern";
622
841
  }
623
842
  break;
624
843
  }
625
844
  }
626
845
  }
627
- const aiHeaders = [
628
- "openai-conversation-id",
629
- "openai-ephemeral-user-id",
630
- "anthropic-client-id",
631
- "x-goog-api-client",
632
- "x-ms-copilot-id"
633
- ];
634
- const foundAiHeaders = aiHeaders.filter(
635
- (header) => normalizedHeaders[header]
846
+ const suspiciousHeaders = this.rules.rules.headers.suspicious;
847
+ const foundAiHeaders = suspiciousHeaders.filter(
848
+ (headerRule) => normalizedHeaders[headerRule.name.toLowerCase()]
636
849
  );
637
850
  if (foundAiHeaders.length > 0) {
638
- confidence = Math.max(confidence, 0.6);
851
+ const maxConfidence = Math.max(...foundAiHeaders.map((h) => h.confidence));
852
+ confidence = Math.max(confidence, maxConfidence);
639
853
  reasons.push(`ai_headers:${foundAiHeaders.length}`);
640
854
  }
641
855
  const ip = input.ip || input.ipAddress;
642
856
  if (ip && !normalizedHeaders["x-forwarded-for"] && !normalizedHeaders["x-real-ip"]) {
643
- for (const [provider, prefixes] of Object.entries(CLOUD_PROVIDERS2)) {
644
- if (prefixes.some((prefix) => ip.startsWith(prefix))) {
645
- confidence = Math.max(confidence, 0.4);
857
+ const ipRanges = "providers" in this.rules.rules.ipRanges ? this.rules.rules.ipRanges.providers : this.rules.rules.ipRanges;
858
+ for (const [provider, ipRule] of Object.entries(ipRanges)) {
859
+ if (!ipRule || typeof ipRule !== "object" || !("ranges" in ipRule) || !Array.isArray(ipRule.ranges))
860
+ continue;
861
+ const matched = ipRule.ranges.some((range) => {
862
+ const prefix = range.split("/")[0];
863
+ const prefixParts = prefix.split(".");
864
+ const ipParts = ip.split(".");
865
+ for (let i = 0; i < Math.min(prefixParts.length - 1, 2); i++) {
866
+ if (prefixParts[i] !== ipParts[i] && prefixParts[i] !== "0") {
867
+ return false;
868
+ }
869
+ }
870
+ return true;
871
+ });
872
+ if (matched) {
873
+ confidence = Math.max(confidence, Math.round(ipRule.confidence * 0.4 * 100));
646
874
  reasons.push(`cloud_provider:${provider}`);
647
875
  break;
648
876
  }
649
877
  }
650
878
  }
651
879
  if (reasons.length > 2) {
652
- confidence = Math.min(confidence * 1.2, 0.95);
880
+ confidence = Math.min(Math.round(confidence * 1.2), 95);
653
881
  }
882
+ confidence = Math.min(Math.max(confidence, 0), 100);
654
883
  return {
655
- isAgent: confidence > 0.3,
884
+ isAgent: confidence > 30,
885
+ // 30% threshold
656
886
  confidence,
887
+ detectionClass: confidence > 30 && detectedAgent ? { type: "AiAgent", agentType: detectedAgent.name } : confidence > 30 ? { type: "Unknown" } : { type: "Human" },
888
+ signals: [],
889
+ // Will be populated by enhanced detection engine in future tasks
657
890
  ...detectedAgent && { detectedAgent },
658
891
  reasons,
659
- ...verificationMethod && { verificationMethod },
660
- forgeabilityRisk: confidence > 0.8 ? "medium" : "high",
892
+ ...verificationMethod && {
893
+ verificationMethod: agentshieldShared.mapVerificationMethod(verificationMethod)
894
+ },
895
+ forgeabilityRisk: confidence > 80 ? "medium" : "high",
661
896
  timestamp: /* @__PURE__ */ new Date()
662
897
  };
663
898
  }
@@ -674,15 +909,17 @@ var EdgeAgentDetectorWithWasm = class {
674
909
  input.ip || input.ipAddress
675
910
  );
676
911
  if (wasmResult) {
677
- console.log("[AgentShield] Using WASM detection result");
678
912
  const detectedAgent = wasmResult.agent ? this.mapAgentName(wasmResult.agent) : void 0;
679
913
  return {
680
914
  isAgent: wasmResult.isAgent,
681
915
  confidence: wasmResult.confidence,
916
+ detectionClass: wasmResult.isAgent && detectedAgent ? { type: "AiAgent", agentType: detectedAgent.name } : wasmResult.isAgent ? { type: "Unknown" } : { type: "Human" },
917
+ signals: [],
918
+ // Will be populated by enhanced detection engine in future tasks
682
919
  ...detectedAgent && { detectedAgent },
683
920
  reasons: [`wasm:${wasmResult.verificationMethod}`],
684
- verificationMethod: wasmResult.verificationMethod,
685
- forgeabilityRisk: wasmResult.verificationMethod === "signature" ? "low" : wasmResult.confidence > 0.9 ? "medium" : "high",
921
+ verificationMethod: agentshieldShared.mapVerificationMethod(wasmResult.verificationMethod),
922
+ forgeabilityRisk: wasmResult.verificationMethod === "signature" ? "low" : wasmResult.confidence > 90 ? "medium" : "high",
686
923
  timestamp: /* @__PURE__ */ new Date()
687
924
  };
688
925
  }
@@ -691,15 +928,50 @@ var EdgeAgentDetectorWithWasm = class {
691
928
  }
692
929
  }
693
930
  const patternResult = await this.patternDetection(input);
694
- if (this.wasmEnabled && patternResult.confidence >= 0.85) {
695
- patternResult.confidence = Math.min(0.95, patternResult.confidence + 0.1);
931
+ if (this.wasmEnabled && patternResult.confidence >= 85) {
932
+ patternResult.confidence = Math.min(95, patternResult.confidence + 10);
696
933
  patternResult.reasons.push("wasm_enhanced");
697
- if (!patternResult.verificationMethod) {
698
- patternResult.verificationMethod = "wasm-enhanced";
699
- }
700
934
  }
701
935
  return patternResult;
702
936
  }
937
+ /**
938
+ * Get agent type from rule key
939
+ */
940
+ getAgentType(agentKey) {
941
+ const typeMap = {
942
+ openai_gptbot: "openai",
943
+ anthropic_claude: "anthropic",
944
+ perplexity_bot: "perplexity",
945
+ google_ai: "google",
946
+ microsoft_ai: "microsoft",
947
+ meta_ai: "meta",
948
+ cohere_bot: "cohere",
949
+ huggingface_bot: "huggingface",
950
+ generic_bot: "generic",
951
+ dev_tools: "dev",
952
+ automation_tools: "automation"
953
+ };
954
+ return typeMap[agentKey] || agentKey;
955
+ }
956
+ /**
957
+ * Get agent name from rule key
958
+ */
959
+ getAgentName(agentKey) {
960
+ const nameMap = {
961
+ openai_gptbot: "ChatGPT/GPTBot",
962
+ anthropic_claude: "Claude",
963
+ perplexity_bot: "Perplexity",
964
+ google_ai: "Google AI",
965
+ microsoft_ai: "Microsoft Copilot",
966
+ meta_ai: "Meta AI",
967
+ cohere_bot: "Cohere",
968
+ huggingface_bot: "HuggingFace",
969
+ generic_bot: "Generic Bot",
970
+ dev_tools: "Development Tool",
971
+ automation_tools: "Automation Tool"
972
+ };
973
+ return nameMap[agentKey] || agentKey;
974
+ }
703
975
  /**
704
976
  * Map agent names from WASM to consistent format
705
977
  */
@@ -880,7 +1152,9 @@ function createAgentShieldMiddleware(config = {}) {
880
1152
  }) : null;
881
1153
  if (config.events) {
882
1154
  Object.entries(config.events).forEach(([event, handler]) => {
883
- detector.on(event, handler);
1155
+ if (handler) {
1156
+ detector.on(event, handler);
1157
+ }
884
1158
  });
885
1159
  }
886
1160
  const {
@@ -912,19 +1186,22 @@ function createAgentShieldMiddleware(config = {}) {
912
1186
  const response2 = server.NextResponse.next();
913
1187
  response2.headers.set("x-agentshield-detected", "true");
914
1188
  response2.headers.set("x-agentshield-agent", existingSession.agent);
915
- response2.headers.set(
916
- "x-agentshield-confidence",
917
- existingSession.confidence.toString()
918
- );
1189
+ response2.headers.set("x-agentshield-confidence", existingSession.confidence.toString());
919
1190
  response2.headers.set("x-agentshield-session", "continued");
920
1191
  response2.headers.set("x-agentshield-session-id", existingSession.id);
921
1192
  request.agentShield = {
922
1193
  result: {
923
1194
  isAgent: true,
924
1195
  confidence: existingSession.confidence,
925
- detectedAgent: { name: existingSession.agent },
1196
+ detectionClass: { type: "AiAgent" },
1197
+ detectedAgent: {
1198
+ type: "ai_agent",
1199
+ name: existingSession.agent
1200
+ },
926
1201
  timestamp: /* @__PURE__ */ new Date(),
927
- verificationMethod: "session"
1202
+ verificationMethod: "behavioral",
1203
+ reasons: ["Session continued"],
1204
+ signals: []
928
1205
  },
929
1206
  session: existingSession,
930
1207
  skipped: false
@@ -954,7 +1231,7 @@ function createAgentShieldMiddleware(config = {}) {
954
1231
  timestamp: /* @__PURE__ */ new Date()
955
1232
  };
956
1233
  const result = await detector.analyze(context);
957
- if (result.isAgent && result.confidence >= (config.confidenceThreshold ?? 0.7)) {
1234
+ if (result.isAgent && result.confidence >= (config.confidenceThreshold ?? 70)) {
958
1235
  if (onDetection) {
959
1236
  const customResponse = await onDetection(request, result);
960
1237
  if (customResponse) {
@@ -973,11 +1250,9 @@ function createAgentShieldMiddleware(config = {}) {
973
1250
  { status: blockedResponse.status }
974
1251
  );
975
1252
  if (blockedResponse.headers) {
976
- Object.entries(blockedResponse.headers).forEach(
977
- ([key, value]) => {
978
- response2.headers.set(key, value);
979
- }
980
- );
1253
+ Object.entries(blockedResponse.headers).forEach(([key, value]) => {
1254
+ response2.headers.set(key, value);
1255
+ });
981
1256
  }
982
1257
  detector.emit("agent.blocked", result, context);
983
1258
  return response2;
@@ -987,17 +1262,19 @@ function createAgentShieldMiddleware(config = {}) {
987
1262
  case "rewrite":
988
1263
  return server.NextResponse.rewrite(new URL(rewriteUrl, request.url));
989
1264
  case "log":
990
- console.warn("AgentShield: Agent detected", {
991
- ipAddress: context.ipAddress,
992
- userAgent: context.userAgent,
993
- confidence: result.confidence,
994
- reasons: result.reasons,
995
- pathname: request.nextUrl.pathname
996
- });
1265
+ if (process.env.NODE_ENV !== "production") {
1266
+ console.debug("AgentShield: Agent detected", {
1267
+ ipAddress: context.ipAddress,
1268
+ userAgent: context.userAgent,
1269
+ confidence: result.confidence,
1270
+ reasons: result.reasons,
1271
+ pathname: request.nextUrl.pathname
1272
+ });
1273
+ }
997
1274
  break;
998
1275
  case "allow":
999
1276
  default:
1000
- if (result.isAgent && result.confidence >= (config.confidenceThreshold ?? 0.7)) {
1277
+ if (result.isAgent && result.confidence >= (config.confidenceThreshold ?? 70)) {
1001
1278
  detector.emit("agent.allowed", result, context);
1002
1279
  }
1003
1280
  break;
@@ -1009,14 +1286,11 @@ function createAgentShieldMiddleware(config = {}) {
1009
1286
  };
1010
1287
  let response = server.NextResponse.next();
1011
1288
  response.headers.set("x-agentshield-detected", result.isAgent.toString());
1012
- response.headers.set(
1013
- "x-agentshield-confidence",
1014
- result.confidence.toString()
1015
- );
1289
+ response.headers.set("x-agentshield-confidence", result.confidence.toString());
1016
1290
  if (result.detectedAgent?.name) {
1017
1291
  response.headers.set("x-agentshield-agent", result.detectedAgent.name);
1018
1292
  }
1019
- if (sessionTracker && result.isAgent && result.confidence >= (config.confidenceThreshold ?? 0.7)) {
1293
+ if (sessionTracker && result.isAgent && result.confidence >= (config.confidenceThreshold ?? 70)) {
1020
1294
  response = await sessionTracker.track(request, response, result);
1021
1295
  response.headers.set("x-agentshield-session", "new");
1022
1296
  detector.emit("agent.session.started", result, context);