@kya-os/agentshield-nextjs 0.2.13 → 0.3.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.
Files changed (73) hide show
  1. package/dist/api-client.d.mts +6 -1
  2. package/dist/api-client.d.ts +6 -1
  3. package/dist/api-client.js.map +1 -1
  4. package/dist/api-client.mjs.map +1 -1
  5. package/dist/api-middleware.d.mts +13 -0
  6. package/dist/api-middleware.d.ts +13 -0
  7. package/dist/api-middleware.js +149 -19
  8. package/dist/api-middleware.js.map +1 -1
  9. package/dist/api-middleware.mjs +149 -19
  10. package/dist/api-middleware.mjs.map +1 -1
  11. package/dist/create-middleware.js +565 -487
  12. package/dist/create-middleware.js.map +1 -1
  13. package/dist/create-middleware.mjs +565 -487
  14. package/dist/create-middleware.mjs.map +1 -1
  15. package/dist/edge/index.js +69 -46
  16. package/dist/edge/index.js.map +1 -1
  17. package/dist/edge/index.mjs +69 -46
  18. package/dist/edge/index.mjs.map +1 -1
  19. package/dist/edge-detector-wrapper.js +9 -1
  20. package/dist/edge-detector-wrapper.js.map +1 -1
  21. package/dist/edge-detector-wrapper.mjs +9 -1
  22. package/dist/edge-detector-wrapper.mjs.map +1 -1
  23. package/dist/edge-runtime-loader.d.mts +1 -0
  24. package/dist/edge-runtime-loader.d.ts +1 -0
  25. package/dist/edge-runtime-loader.js +19 -3
  26. package/dist/edge-runtime-loader.js.map +1 -1
  27. package/dist/edge-runtime-loader.mjs +19 -3
  28. package/dist/edge-runtime-loader.mjs.map +1 -1
  29. package/dist/edge-wasm-middleware.d.mts +1 -0
  30. package/dist/edge-wasm-middleware.d.ts +1 -0
  31. package/dist/edge-wasm-middleware.js +10 -2
  32. package/dist/edge-wasm-middleware.js.map +1 -1
  33. package/dist/edge-wasm-middleware.mjs +11 -3
  34. package/dist/edge-wasm-middleware.mjs.map +1 -1
  35. package/dist/enhanced-middleware.js +48 -20
  36. package/dist/enhanced-middleware.js.map +1 -1
  37. package/dist/enhanced-middleware.mjs +49 -21
  38. package/dist/enhanced-middleware.mjs.map +1 -1
  39. package/dist/index.d.mts +1 -1
  40. package/dist/index.d.ts +1 -1
  41. package/dist/index.js +263 -102
  42. package/dist/index.js.map +1 -1
  43. package/dist/index.mjs +264 -103
  44. package/dist/index.mjs.map +1 -1
  45. package/dist/middleware.js +565 -487
  46. package/dist/middleware.js.map +1 -1
  47. package/dist/middleware.mjs +565 -487
  48. package/dist/middleware.mjs.map +1 -1
  49. package/dist/policy.d.mts +16 -4
  50. package/dist/policy.d.ts +16 -4
  51. package/dist/policy.js +14 -10
  52. package/dist/policy.js.map +1 -1
  53. package/dist/policy.mjs +14 -10
  54. package/dist/policy.mjs.map +1 -1
  55. package/dist/session-tracker.js +13 -19
  56. package/dist/session-tracker.js.map +1 -1
  57. package/dist/session-tracker.mjs +13 -19
  58. package/dist/session-tracker.mjs.map +1 -1
  59. package/dist/signature-verifier.js +9 -1
  60. package/dist/signature-verifier.js.map +1 -1
  61. package/dist/signature-verifier.mjs +9 -1
  62. package/dist/signature-verifier.mjs.map +1 -1
  63. package/dist/wasm-middleware.d.mts +1 -0
  64. package/dist/wasm-middleware.d.ts +1 -0
  65. package/dist/wasm-middleware.js +15 -15
  66. package/dist/wasm-middleware.js.map +1 -1
  67. package/dist/wasm-middleware.mjs +15 -15
  68. package/dist/wasm-middleware.mjs.map +1 -1
  69. package/package.json +3 -3
  70. package/wasm/agentshield_wasm.d.ts +379 -21
  71. package/wasm/agentshield_wasm.js +1409 -506
  72. package/wasm/agentshield_wasm_bg.wasm +0 -0
  73. package/dist/.tsbuildinfo +0 -1
@@ -1,9 +1,9 @@
1
1
  'use strict';
2
2
 
3
+ var agentshieldShared = require('@kya-os/agentshield-shared');
3
4
  var server = require('next/server');
4
5
  var ed25519 = require('@noble/ed25519');
5
6
  var sha2_js = require('@noble/hashes/sha2.js');
6
- var agentshieldShared = require('@kya-os/agentshield-shared');
7
7
 
8
8
  function _interopNamespace(e) {
9
9
  if (e && e.__esModule) return e;
@@ -25,7 +25,455 @@ function _interopNamespace(e) {
25
25
 
26
26
  var ed25519__namespace = /*#__PURE__*/_interopNamespace(ed25519);
27
27
 
28
- // src/middleware.ts
28
+ var __defProp = Object.defineProperty;
29
+ var __getOwnPropNames = Object.getOwnPropertyNames;
30
+ var __esm = (fn, res) => function __init() {
31
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
32
+ };
33
+ var __export = (target, all) => {
34
+ for (var name in all)
35
+ __defProp(target, name, { get: all[name], enumerable: true });
36
+ };
37
+
38
+ // src/wasm-loader.ts
39
+ function setWasmBaseUrl(url) {
40
+ baseUrl = url;
41
+ }
42
+ function getWasmUrl() {
43
+ if (baseUrl) {
44
+ try {
45
+ const url = new URL(baseUrl);
46
+ return `${url.origin}${WASM_PATH}`;
47
+ } catch {
48
+ return WASM_PATH;
49
+ }
50
+ }
51
+ return WASM_PATH;
52
+ }
53
+ async function initWasm() {
54
+ if (wasmExports) return true;
55
+ if (initPromise) {
56
+ await initPromise;
57
+ return !!wasmExports;
58
+ }
59
+ initPromise = (async () => {
60
+ try {
61
+ const controller = new AbortController();
62
+ const timeout = setTimeout(() => controller.abort(), 3e3);
63
+ try {
64
+ const wasmUrl = getWasmUrl();
65
+ if (typeof WebAssembly.instantiateStreaming === "function") {
66
+ try {
67
+ const response2 = await fetch(wasmUrl, { signal: controller.signal });
68
+ clearTimeout(timeout);
69
+ if (!response2.ok) {
70
+ throw new Error(`Failed to fetch WASM: ${response2.status}`);
71
+ }
72
+ const streamResponse = response2.clone();
73
+ const { instance } = await WebAssembly.instantiateStreaming(streamResponse, {
74
+ wbg: {
75
+ __wbg_log_1d3ae13c3d5e6b8e: (ptr, len) => {
76
+ if (process.env.NODE_ENV !== "production") {
77
+ console.debug("WASM:", ptr, len);
78
+ }
79
+ },
80
+ __wbindgen_throw: (ptr, len) => {
81
+ throw new Error(`WASM Error at ${ptr}, length ${len}`);
82
+ }
83
+ }
84
+ });
85
+ wasmInstance = instance;
86
+ wasmExports = instance.exports;
87
+ if (process.env.NODE_ENV !== "production") {
88
+ console.debug("[AgentShield] \u2705 WASM module initialized with streaming");
89
+ }
90
+ return;
91
+ } catch (streamError) {
92
+ if (!controller.signal.aborted) {
93
+ if (process.env.NODE_ENV !== "production") {
94
+ console.debug(
95
+ "[AgentShield] Streaming compilation failed, falling back to standard compilation"
96
+ );
97
+ }
98
+ } else {
99
+ throw streamError;
100
+ }
101
+ }
102
+ }
103
+ const response = await fetch(wasmUrl, { signal: controller.signal });
104
+ clearTimeout(timeout);
105
+ if (!response.ok) {
106
+ throw new Error(`Failed to fetch WASM: ${response.status}`);
107
+ }
108
+ const wasmArrayBuffer = await response.arrayBuffer();
109
+ const compiledModule = await WebAssembly.compile(wasmArrayBuffer);
110
+ const imports = {
111
+ wbg: {
112
+ __wbg_log_1d3ae13c3d5e6b8e: (ptr, len) => {
113
+ if (process.env.NODE_ENV !== "production") {
114
+ console.debug("WASM:", ptr, len);
115
+ }
116
+ },
117
+ __wbindgen_throw: (ptr, len) => {
118
+ throw new Error(`WASM Error at ${ptr}, length ${len}`);
119
+ }
120
+ }
121
+ };
122
+ wasmInstance = await WebAssembly.instantiate(compiledModule, imports);
123
+ wasmExports = wasmInstance.exports;
124
+ if (process.env.NODE_ENV !== "production") {
125
+ console.debug("[AgentShield] \u2705 WASM module initialized via fallback");
126
+ }
127
+ } catch (fetchError) {
128
+ const error = fetchError;
129
+ if (error.name === "AbortError") {
130
+ console.warn(
131
+ "[AgentShield] WASM fetch timed out after 3 seconds - using pattern detection"
132
+ );
133
+ } else {
134
+ console.warn(
135
+ "[AgentShield] Failed to fetch WASM file:",
136
+ error.message || "Unknown error"
137
+ );
138
+ }
139
+ wasmExports = null;
140
+ }
141
+ } catch (error) {
142
+ console.error("[AgentShield] Failed to initialize WASM:", error);
143
+ wasmExports = null;
144
+ }
145
+ })();
146
+ await initPromise;
147
+ return !!wasmExports;
148
+ }
149
+ async function detectAgentWithWasm(_userAgent, _headers, _ipAddress) {
150
+ return null;
151
+ }
152
+ async function getWasmVersion() {
153
+ const initialized = await initWasm();
154
+ if (!initialized || !wasmExports) {
155
+ return null;
156
+ }
157
+ if (typeof wasmExports.version === "function") {
158
+ return wasmExports.version();
159
+ }
160
+ return "unknown";
161
+ }
162
+ async function isWasmAvailable() {
163
+ try {
164
+ const initialized = await initWasm();
165
+ if (!initialized) return false;
166
+ const version = await getWasmVersion();
167
+ return version !== null;
168
+ } catch {
169
+ return false;
170
+ }
171
+ }
172
+ var wasmInstance, wasmExports, initPromise, WASM_PATH, baseUrl;
173
+ var init_wasm_loader = __esm({
174
+ "src/wasm-loader.ts"() {
175
+ wasmInstance = null;
176
+ wasmExports = null;
177
+ initPromise = null;
178
+ WASM_PATH = "/wasm/agentshield_wasm_bg.wasm";
179
+ baseUrl = null;
180
+ }
181
+ });
182
+
183
+ // src/edge-detector-with-wasm.ts
184
+ var edge_detector_with_wasm_exports = {};
185
+ __export(edge_detector_with_wasm_exports, {
186
+ EdgeAgentDetectorWithWasm: () => EdgeAgentDetectorWithWasm,
187
+ EdgeAgentDetectorWrapperWithWasm: () => EdgeAgentDetectorWrapperWithWasm
188
+ });
189
+ var rules2, EdgeAgentDetectorWithWasm, EdgeAgentDetectorWrapperWithWasm;
190
+ var init_edge_detector_with_wasm = __esm({
191
+ "src/edge-detector-with-wasm.ts"() {
192
+ init_wasm_loader();
193
+ rules2 = agentshieldShared.loadRulesSync();
194
+ EdgeAgentDetectorWithWasm = class {
195
+ constructor(enableWasm = true) {
196
+ this.enableWasm = enableWasm;
197
+ this.rules = rules2;
198
+ }
199
+ wasmEnabled = false;
200
+ initPromise = null;
201
+ baseUrl = null;
202
+ rules;
203
+ /**
204
+ * Set the base URL for WASM loading in Edge Runtime
205
+ */
206
+ setBaseUrl(url) {
207
+ this.baseUrl = url;
208
+ setWasmBaseUrl(url);
209
+ }
210
+ /**
211
+ * Initialize the detector (including WASM if enabled)
212
+ */
213
+ async init() {
214
+ if (!this.enableWasm) {
215
+ this.wasmEnabled = false;
216
+ return;
217
+ }
218
+ if (this.initPromise) {
219
+ await this.initPromise;
220
+ return;
221
+ }
222
+ this.initPromise = (async () => {
223
+ try {
224
+ const wasmAvailable = await isWasmAvailable();
225
+ if (wasmAvailable) {
226
+ if (this.baseUrl) {
227
+ setWasmBaseUrl(this.baseUrl);
228
+ }
229
+ await initWasm();
230
+ this.wasmEnabled = true;
231
+ } else {
232
+ this.wasmEnabled = false;
233
+ }
234
+ } catch (error) {
235
+ console.error("[AgentShield] Failed to initialize WASM:", error);
236
+ this.wasmEnabled = false;
237
+ }
238
+ })();
239
+ await this.initPromise;
240
+ }
241
+ /**
242
+ * Pattern-based detection (fallback)
243
+ */
244
+ async patternDetection(input) {
245
+ const reasons = [];
246
+ let detectedAgent;
247
+ let verificationMethod;
248
+ let confidence = 0;
249
+ const headers = input.headers || {};
250
+ const normalizedHeaders = {};
251
+ for (const [key, value] of Object.entries(headers)) {
252
+ normalizedHeaders[key.toLowerCase()] = value;
253
+ }
254
+ const signaturePresent = !!(normalizedHeaders["signature"] || normalizedHeaders["signature-input"]);
255
+ const signatureAgent = normalizedHeaders["signature-agent"];
256
+ const isChatGPT = (() => {
257
+ try {
258
+ const url = new URL(signatureAgent?.replace(/^"|"$/g, "") || "");
259
+ return url.hostname === "chatgpt.com" || url.hostname.endsWith(".chatgpt.com");
260
+ } catch {
261
+ return false;
262
+ }
263
+ })();
264
+ if (isChatGPT) {
265
+ confidence = 85;
266
+ reasons.push("signature_agent:chatgpt");
267
+ detectedAgent = { type: "chatgpt", name: "ChatGPT" };
268
+ verificationMethod = "signature";
269
+ } else if (signaturePresent) {
270
+ confidence = Math.max(confidence, 40);
271
+ reasons.push("signature_present");
272
+ }
273
+ const userAgent = input.userAgent || input.headers?.["user-agent"] || "";
274
+ if (userAgent) {
275
+ for (const [agentKey, agentRule] of Object.entries(this.rules.rules.userAgents)) {
276
+ const matched = agentRule.patterns.some((pattern) => {
277
+ const regex = new RegExp(pattern, "i");
278
+ return regex.test(userAgent);
279
+ });
280
+ if (matched) {
281
+ const agentType = this.getAgentType(agentKey);
282
+ const agentName = this.getAgentName(agentKey);
283
+ confidence = Math.max(confidence, Math.round(agentRule.confidence * 0.85 * 100));
284
+ reasons.push(`known_pattern:${agentType}`);
285
+ if (!detectedAgent) {
286
+ detectedAgent = { type: agentType, name: agentName };
287
+ verificationMethod = "pattern";
288
+ }
289
+ break;
290
+ }
291
+ }
292
+ }
293
+ const suspiciousHeaders = this.rules.rules.headers.suspicious;
294
+ const foundAiHeaders = suspiciousHeaders.filter(
295
+ (headerRule) => normalizedHeaders[headerRule.name.toLowerCase()]
296
+ );
297
+ if (foundAiHeaders.length > 0) {
298
+ const maxConfidence = Math.max(...foundAiHeaders.map((h) => h.confidence));
299
+ confidence = Math.max(confidence, maxConfidence);
300
+ reasons.push(`ai_headers:${foundAiHeaders.length}`);
301
+ }
302
+ const ip = input.ip || input.ipAddress;
303
+ if (ip && !normalizedHeaders["x-forwarded-for"] && !normalizedHeaders["x-real-ip"]) {
304
+ const ipRanges = "providers" in this.rules.rules.ipRanges ? this.rules.rules.ipRanges.providers : this.rules.rules.ipRanges;
305
+ for (const [provider, ipRule] of Object.entries(ipRanges)) {
306
+ if (!ipRule || typeof ipRule !== "object" || !("ranges" in ipRule) || !Array.isArray(ipRule.ranges))
307
+ continue;
308
+ const matched = ipRule.ranges.some((range) => {
309
+ const prefix = range.split("/")[0];
310
+ const prefixParts = prefix.split(".");
311
+ const ipParts = ip.split(".");
312
+ for (let i = 0; i < Math.min(prefixParts.length - 1, 2); i++) {
313
+ if (prefixParts[i] !== ipParts[i] && prefixParts[i] !== "0") {
314
+ return false;
315
+ }
316
+ }
317
+ return true;
318
+ });
319
+ if (matched) {
320
+ confidence = Math.max(confidence, Math.round(ipRule.confidence * 0.4 * 100));
321
+ reasons.push(`cloud_provider:${provider}`);
322
+ break;
323
+ }
324
+ }
325
+ }
326
+ if (reasons.length > 2) {
327
+ confidence = Math.min(Math.round(confidence * 1.2), 95);
328
+ }
329
+ confidence = Math.min(Math.max(confidence, 0), 100);
330
+ return {
331
+ isAgent: confidence > 30,
332
+ // 30% threshold
333
+ confidence,
334
+ detectionClass: confidence > 30 && detectedAgent ? { type: "AiAgent", agentType: detectedAgent.name } : confidence > 30 ? { type: "Unknown" } : { type: "Human" },
335
+ signals: [],
336
+ // Will be populated by enhanced detection engine in future tasks
337
+ ...detectedAgent && { detectedAgent },
338
+ reasons,
339
+ ...verificationMethod && {
340
+ verificationMethod: agentshieldShared.mapVerificationMethod(verificationMethod)
341
+ },
342
+ forgeabilityRisk: confidence > 80 ? "medium" : "high",
343
+ timestamp: /* @__PURE__ */ new Date()
344
+ };
345
+ }
346
+ /**
347
+ * Analyze request with WASM enhancement when available
348
+ */
349
+ async analyze(input) {
350
+ await this.init();
351
+ if (this.wasmEnabled) {
352
+ try {
353
+ const wasmResult = await detectAgentWithWasm(
354
+ input.userAgent || input.headers?.["user-agent"],
355
+ input.headers || {},
356
+ input.ip || input.ipAddress
357
+ );
358
+ if (wasmResult) {
359
+ const detectedAgent = wasmResult.agent ? this.mapAgentName(wasmResult.agent) : void 0;
360
+ return {
361
+ isAgent: wasmResult.isAgent,
362
+ confidence: wasmResult.confidence,
363
+ detectionClass: wasmResult.isAgent && detectedAgent ? { type: "AiAgent", agentType: detectedAgent.name } : wasmResult.isAgent ? { type: "Unknown" } : { type: "Human" },
364
+ signals: [],
365
+ // Will be populated by enhanced detection engine in future tasks
366
+ ...detectedAgent && { detectedAgent },
367
+ reasons: [`wasm:${wasmResult.verificationMethod}`],
368
+ verificationMethod: agentshieldShared.mapVerificationMethod(wasmResult.verificationMethod),
369
+ forgeabilityRisk: wasmResult.verificationMethod === "signature" ? "low" : wasmResult.confidence > 90 ? "medium" : "high",
370
+ timestamp: /* @__PURE__ */ new Date()
371
+ };
372
+ }
373
+ } catch (error) {
374
+ console.error("[AgentShield] WASM detection error:", error);
375
+ }
376
+ }
377
+ const patternResult = await this.patternDetection(input);
378
+ if (this.wasmEnabled && patternResult.confidence >= 85) {
379
+ patternResult.confidence = Math.min(95, patternResult.confidence + 10);
380
+ patternResult.reasons.push("wasm_enhanced");
381
+ }
382
+ return patternResult;
383
+ }
384
+ /**
385
+ * Get agent type from rule key
386
+ */
387
+ getAgentType(agentKey) {
388
+ const typeMap = {
389
+ openai_gptbot: "openai",
390
+ anthropic_claude: "anthropic",
391
+ perplexity_bot: "perplexity",
392
+ google_ai: "google",
393
+ microsoft_ai: "microsoft",
394
+ meta_ai: "meta",
395
+ cohere_bot: "cohere",
396
+ huggingface_bot: "huggingface",
397
+ generic_bot: "generic",
398
+ dev_tools: "dev",
399
+ automation_tools: "automation"
400
+ };
401
+ return typeMap[agentKey] || agentKey;
402
+ }
403
+ /**
404
+ * Get agent name from rule key
405
+ */
406
+ getAgentName(agentKey) {
407
+ const nameMap = {
408
+ openai_gptbot: "ChatGPT/GPTBot",
409
+ anthropic_claude: "Claude",
410
+ perplexity_bot: "Perplexity",
411
+ google_ai: "Google AI",
412
+ microsoft_ai: "Microsoft Copilot",
413
+ meta_ai: "Meta AI",
414
+ cohere_bot: "Cohere",
415
+ huggingface_bot: "HuggingFace",
416
+ generic_bot: "Generic Bot",
417
+ dev_tools: "Development Tool",
418
+ automation_tools: "Automation Tool"
419
+ };
420
+ return nameMap[agentKey] || agentKey;
421
+ }
422
+ /**
423
+ * Map agent names from WASM to consistent format
424
+ */
425
+ mapAgentName(agent) {
426
+ const lowerAgent = agent.toLowerCase();
427
+ if (lowerAgent.includes("chatgpt")) {
428
+ return { type: "chatgpt", name: "ChatGPT" };
429
+ } else if (lowerAgent.includes("claude")) {
430
+ return { type: "claude", name: "Claude" };
431
+ } else if (lowerAgent.includes("perplexity")) {
432
+ return { type: "perplexity", name: "Perplexity" };
433
+ } else if (lowerAgent.includes("bing")) {
434
+ return { type: "bing", name: "Bing AI" };
435
+ } else if (lowerAgent.includes("anthropic")) {
436
+ return { type: "anthropic", name: "Anthropic" };
437
+ }
438
+ return { type: "unknown", name: agent };
439
+ }
440
+ };
441
+ EdgeAgentDetectorWrapperWithWasm = class {
442
+ detector;
443
+ events = /* @__PURE__ */ new Map();
444
+ constructor(config) {
445
+ this.detector = new EdgeAgentDetectorWithWasm(config?.enableWasm ?? true);
446
+ if (config?.baseUrl) {
447
+ this.detector.setBaseUrl(config.baseUrl);
448
+ }
449
+ }
450
+ setBaseUrl(url) {
451
+ this.detector.setBaseUrl(url);
452
+ }
453
+ async analyze(input) {
454
+ const result = await this.detector.analyze(input);
455
+ if (result.isAgent && this.events.has("agent.detected")) {
456
+ const handlers = this.events.get("agent.detected") || [];
457
+ handlers.forEach((handler) => handler(result, input));
458
+ }
459
+ return result;
460
+ }
461
+ on(event, handler) {
462
+ if (!this.events.has(event)) {
463
+ this.events.set(event, []);
464
+ }
465
+ this.events.get(event).push(handler);
466
+ }
467
+ emit(event, ...args) {
468
+ const handlers = this.events.get(event) || [];
469
+ handlers.forEach((handler) => handler(...args));
470
+ }
471
+ async init() {
472
+ await this.detector.init();
473
+ }
474
+ };
475
+ }
476
+ });
29
477
  ed25519__namespace.etc.sha512Sync = (...m) => sha2_js.sha512(ed25519__namespace.etc.concatBytes(...m));
30
478
  var KNOWN_KEYS = {
31
479
  chatgpt: [
@@ -286,7 +734,15 @@ async function verifyAgentSignature(method, path, headers) {
286
734
  }
287
735
  let agent;
288
736
  let agentKey;
289
- if (signatureAgent === '"https://chatgpt.com"' || signatureAgent?.includes("chatgpt.com")) {
737
+ const isChatGPT = signatureAgent === '"https://chatgpt.com"' || (() => {
738
+ try {
739
+ const url = new URL(signatureAgent?.replace(/^"|"$/g, "") || "");
740
+ return url.hostname === "chatgpt.com" || url.hostname.endsWith(".chatgpt.com");
741
+ } catch {
742
+ return false;
743
+ }
744
+ })();
745
+ if (isChatGPT) {
290
746
  agent = "ChatGPT";
291
747
  agentKey = "chatgpt";
292
748
  }
@@ -583,462 +1039,46 @@ var EdgeAgentDetectorWrapper = class {
583
1039
  return;
584
1040
  }
585
1041
  };
586
-
587
- // src/wasm-loader.ts
588
- var wasmInstance = null;
589
- var wasmExports = null;
590
- var initPromise = null;
591
- var WASM_PATH = "/wasm/agentshield_wasm_bg.wasm";
592
- var baseUrl = null;
593
- function setWasmBaseUrl(url) {
594
- baseUrl = url;
595
- }
596
- function getWasmUrl() {
597
- if (baseUrl) {
1042
+ var EdgeSessionTracker = class {
1043
+ config;
1044
+ constructor(config) {
1045
+ this.config = {
1046
+ enabled: config.enabled,
1047
+ cookieName: config.cookieName || "__agentshield_session",
1048
+ cookieMaxAge: config.cookieMaxAge || 3600,
1049
+ // 1 hour default
1050
+ encryptionKey: config.encryptionKey || process.env.AGENTSHIELD_SECRET || "agentshield-default-key"
1051
+ };
1052
+ }
1053
+ /**
1054
+ * Track a new AI agent session
1055
+ */
1056
+ async track(_request, response, result) {
598
1057
  try {
599
- const url = new URL(baseUrl);
600
- return `${url.origin}${WASM_PATH}`;
601
- } catch {
602
- return WASM_PATH;
603
- }
604
- }
605
- return WASM_PATH;
606
- }
607
- async function initWasm() {
608
- if (wasmExports) return true;
609
- if (initPromise) {
610
- await initPromise;
611
- return !!wasmExports;
612
- }
613
- initPromise = (async () => {
614
- try {
615
- const controller = new AbortController();
616
- const timeout = setTimeout(() => controller.abort(), 3e3);
617
- try {
618
- const wasmUrl = getWasmUrl();
619
- if (typeof WebAssembly.instantiateStreaming === "function") {
620
- try {
621
- const response2 = await fetch(wasmUrl, { signal: controller.signal });
622
- clearTimeout(timeout);
623
- if (!response2.ok) {
624
- throw new Error(`Failed to fetch WASM: ${response2.status}`);
625
- }
626
- const streamResponse = response2.clone();
627
- const { instance } = await WebAssembly.instantiateStreaming(streamResponse, {
628
- wbg: {
629
- __wbg_log_1d3ae13c3d5e6b8e: (ptr, len) => {
630
- if (process.env.NODE_ENV !== "production") {
631
- console.debug("WASM:", ptr, len);
632
- }
633
- },
634
- __wbindgen_throw: (ptr, len) => {
635
- throw new Error(`WASM Error at ${ptr}, length ${len}`);
636
- }
637
- }
638
- });
639
- wasmInstance = instance;
640
- wasmExports = instance.exports;
641
- if (process.env.NODE_ENV !== "production") {
642
- console.debug("[AgentShield] \u2705 WASM module initialized with streaming");
643
- }
644
- return;
645
- } catch (streamError) {
646
- if (!controller.signal.aborted) {
647
- if (process.env.NODE_ENV !== "production") {
648
- console.debug(
649
- "[AgentShield] Streaming compilation failed, falling back to standard compilation"
650
- );
651
- }
652
- } else {
653
- throw streamError;
654
- }
655
- }
656
- }
657
- const response = await fetch(wasmUrl, { signal: controller.signal });
658
- clearTimeout(timeout);
659
- if (!response.ok) {
660
- throw new Error(`Failed to fetch WASM: ${response.status}`);
661
- }
662
- const wasmArrayBuffer = await response.arrayBuffer();
663
- const compiledModule = await WebAssembly.compile(wasmArrayBuffer);
664
- const imports = {
665
- wbg: {
666
- __wbg_log_1d3ae13c3d5e6b8e: (ptr, len) => {
667
- if (process.env.NODE_ENV !== "production") {
668
- console.debug("WASM:", ptr, len);
669
- }
670
- },
671
- __wbindgen_throw: (ptr, len) => {
672
- throw new Error(`WASM Error at ${ptr}, length ${len}`);
673
- }
674
- }
675
- };
676
- wasmInstance = await WebAssembly.instantiate(compiledModule, imports);
677
- wasmExports = wasmInstance.exports;
678
- if (process.env.NODE_ENV !== "production") {
679
- console.debug("[AgentShield] \u2705 WASM module initialized via fallback");
680
- }
681
- } catch (fetchError) {
682
- const error = fetchError;
683
- if (error.name === "AbortError") {
684
- console.warn(
685
- "[AgentShield] WASM fetch timed out after 3 seconds - using pattern detection"
686
- );
687
- } else {
688
- console.warn(
689
- "[AgentShield] Failed to fetch WASM file:",
690
- error.message || "Unknown error"
691
- );
692
- }
693
- wasmExports = null;
694
- }
695
- } catch (error) {
696
- console.error("[AgentShield] Failed to initialize WASM:", error);
697
- wasmExports = null;
698
- }
699
- })();
700
- await initPromise;
701
- return !!wasmExports;
702
- }
703
- async function detectAgentWithWasm(_userAgent, _headers, _ipAddress) {
704
- return null;
705
- }
706
- async function getWasmVersion() {
707
- const initialized = await initWasm();
708
- if (!initialized || !wasmExports) {
709
- return null;
710
- }
711
- if (typeof wasmExports.version === "function") {
712
- return wasmExports.version();
713
- }
714
- return "unknown";
715
- }
716
- async function isWasmAvailable() {
717
- try {
718
- const initialized = await initWasm();
719
- if (!initialized) return false;
720
- const version = await getWasmVersion();
721
- return version !== null;
722
- } catch {
723
- return false;
724
- }
725
- }
726
- var rules2 = agentshieldShared.loadRulesSync();
727
- var EdgeAgentDetectorWithWasm = class {
728
- constructor(enableWasm = true) {
729
- this.enableWasm = enableWasm;
730
- this.rules = rules2;
731
- }
732
- wasmEnabled = false;
733
- initPromise = null;
734
- baseUrl = null;
735
- rules;
736
- /**
737
- * Set the base URL for WASM loading in Edge Runtime
738
- */
739
- setBaseUrl(url) {
740
- this.baseUrl = url;
741
- setWasmBaseUrl(url);
742
- }
743
- /**
744
- * Initialize the detector (including WASM if enabled)
745
- */
746
- async init() {
747
- if (!this.enableWasm) {
748
- this.wasmEnabled = false;
749
- return;
750
- }
751
- if (this.initPromise) {
752
- await this.initPromise;
753
- return;
754
- }
755
- this.initPromise = (async () => {
756
- try {
757
- const wasmAvailable = await isWasmAvailable();
758
- if (wasmAvailable) {
759
- if (this.baseUrl) {
760
- setWasmBaseUrl(this.baseUrl);
761
- }
762
- await initWasm();
763
- this.wasmEnabled = true;
764
- } else {
765
- this.wasmEnabled = false;
766
- }
767
- } catch (error) {
768
- console.error("[AgentShield] Failed to initialize WASM:", error);
769
- this.wasmEnabled = false;
770
- }
771
- })();
772
- await this.initPromise;
773
- }
774
- /**
775
- * Pattern-based detection (fallback)
776
- */
777
- async patternDetection(input) {
778
- const reasons = [];
779
- let detectedAgent;
780
- let verificationMethod;
781
- let confidence = 0;
782
- const headers = input.headers || {};
783
- const normalizedHeaders = {};
784
- for (const [key, value] of Object.entries(headers)) {
785
- normalizedHeaders[key.toLowerCase()] = value;
786
- }
787
- const signaturePresent = !!(normalizedHeaders["signature"] || normalizedHeaders["signature-input"]);
788
- const signatureAgent = normalizedHeaders["signature-agent"];
789
- if (signatureAgent?.includes("chatgpt.com")) {
790
- confidence = 85;
791
- reasons.push("signature_agent:chatgpt");
792
- detectedAgent = { type: "chatgpt", name: "ChatGPT" };
793
- verificationMethod = "signature";
794
- } else if (signaturePresent) {
795
- confidence = Math.max(confidence, 40);
796
- reasons.push("signature_present");
797
- }
798
- const userAgent = input.userAgent || input.headers?.["user-agent"] || "";
799
- if (userAgent) {
800
- for (const [agentKey, agentRule] of Object.entries(this.rules.rules.userAgents)) {
801
- const matched = agentRule.patterns.some((pattern) => {
802
- const regex = new RegExp(pattern, "i");
803
- return regex.test(userAgent);
804
- });
805
- if (matched) {
806
- const agentType = this.getAgentType(agentKey);
807
- const agentName = this.getAgentName(agentKey);
808
- confidence = Math.max(confidence, Math.round(agentRule.confidence * 0.85 * 100));
809
- reasons.push(`known_pattern:${agentType}`);
810
- if (!detectedAgent) {
811
- detectedAgent = { type: agentType, name: agentName };
812
- verificationMethod = "pattern";
813
- }
814
- break;
815
- }
816
- }
817
- }
818
- const suspiciousHeaders = this.rules.rules.headers.suspicious;
819
- const foundAiHeaders = suspiciousHeaders.filter(
820
- (headerRule) => normalizedHeaders[headerRule.name.toLowerCase()]
821
- );
822
- if (foundAiHeaders.length > 0) {
823
- const maxConfidence = Math.max(...foundAiHeaders.map((h) => h.confidence));
824
- confidence = Math.max(confidence, maxConfidence);
825
- reasons.push(`ai_headers:${foundAiHeaders.length}`);
826
- }
827
- const ip = input.ip || input.ipAddress;
828
- if (ip && !normalizedHeaders["x-forwarded-for"] && !normalizedHeaders["x-real-ip"]) {
829
- const ipRanges = "providers" in this.rules.rules.ipRanges ? this.rules.rules.ipRanges.providers : this.rules.rules.ipRanges;
830
- for (const [provider, ipRule] of Object.entries(ipRanges)) {
831
- if (!ipRule || typeof ipRule !== "object" || !("ranges" in ipRule) || !Array.isArray(ipRule.ranges))
832
- continue;
833
- const matched = ipRule.ranges.some((range) => {
834
- const prefix = range.split("/")[0];
835
- const prefixParts = prefix.split(".");
836
- const ipParts = ip.split(".");
837
- for (let i = 0; i < Math.min(prefixParts.length - 1, 2); i++) {
838
- if (prefixParts[i] !== ipParts[i] && prefixParts[i] !== "0") {
839
- return false;
840
- }
841
- }
842
- return true;
843
- });
844
- if (matched) {
845
- confidence = Math.max(confidence, Math.round(ipRule.confidence * 0.4 * 100));
846
- reasons.push(`cloud_provider:${provider}`);
847
- break;
848
- }
849
- }
850
- }
851
- if (reasons.length > 2) {
852
- confidence = Math.min(Math.round(confidence * 1.2), 95);
853
- }
854
- confidence = Math.min(Math.max(confidence, 0), 100);
855
- return {
856
- isAgent: confidence > 30,
857
- // 30% threshold
858
- confidence,
859
- detectionClass: confidence > 30 && detectedAgent ? { type: "AiAgent", agentType: detectedAgent.name } : confidence > 30 ? { type: "Unknown" } : { type: "Human" },
860
- signals: [],
861
- // Will be populated by enhanced detection engine in future tasks
862
- ...detectedAgent && { detectedAgent },
863
- reasons,
864
- ...verificationMethod && {
865
- verificationMethod: agentshieldShared.mapVerificationMethod(verificationMethod)
866
- },
867
- forgeabilityRisk: confidence > 80 ? "medium" : "high",
868
- timestamp: /* @__PURE__ */ new Date()
869
- };
870
- }
871
- /**
872
- * Analyze request with WASM enhancement when available
873
- */
874
- async analyze(input) {
875
- await this.init();
876
- if (this.wasmEnabled) {
877
- try {
878
- const wasmResult = await detectAgentWithWasm(
879
- input.userAgent || input.headers?.["user-agent"],
880
- input.headers || {},
881
- input.ip || input.ipAddress
882
- );
883
- if (wasmResult) {
884
- const detectedAgent = wasmResult.agent ? this.mapAgentName(wasmResult.agent) : void 0;
885
- return {
886
- isAgent: wasmResult.isAgent,
887
- confidence: wasmResult.confidence,
888
- detectionClass: wasmResult.isAgent && detectedAgent ? { type: "AiAgent", agentType: detectedAgent.name } : wasmResult.isAgent ? { type: "Unknown" } : { type: "Human" },
889
- signals: [],
890
- // Will be populated by enhanced detection engine in future tasks
891
- ...detectedAgent && { detectedAgent },
892
- reasons: [`wasm:${wasmResult.verificationMethod}`],
893
- verificationMethod: agentshieldShared.mapVerificationMethod(wasmResult.verificationMethod),
894
- forgeabilityRisk: wasmResult.verificationMethod === "signature" ? "low" : wasmResult.confidence > 90 ? "medium" : "high",
895
- timestamp: /* @__PURE__ */ new Date()
896
- };
897
- }
898
- } catch (error) {
899
- console.error("[AgentShield] WASM detection error:", error);
900
- }
901
- }
902
- const patternResult = await this.patternDetection(input);
903
- if (this.wasmEnabled && patternResult.confidence >= 85) {
904
- patternResult.confidence = Math.min(95, patternResult.confidence + 10);
905
- patternResult.reasons.push("wasm_enhanced");
906
- }
907
- return patternResult;
908
- }
909
- /**
910
- * Get agent type from rule key
911
- */
912
- getAgentType(agentKey) {
913
- const typeMap = {
914
- openai_gptbot: "openai",
915
- anthropic_claude: "anthropic",
916
- perplexity_bot: "perplexity",
917
- google_ai: "google",
918
- microsoft_ai: "microsoft",
919
- meta_ai: "meta",
920
- cohere_bot: "cohere",
921
- huggingface_bot: "huggingface",
922
- generic_bot: "generic",
923
- dev_tools: "dev",
924
- automation_tools: "automation"
925
- };
926
- return typeMap[agentKey] || agentKey;
927
- }
928
- /**
929
- * Get agent name from rule key
930
- */
931
- getAgentName(agentKey) {
932
- const nameMap = {
933
- openai_gptbot: "ChatGPT/GPTBot",
934
- anthropic_claude: "Claude",
935
- perplexity_bot: "Perplexity",
936
- google_ai: "Google AI",
937
- microsoft_ai: "Microsoft Copilot",
938
- meta_ai: "Meta AI",
939
- cohere_bot: "Cohere",
940
- huggingface_bot: "HuggingFace",
941
- generic_bot: "Generic Bot",
942
- dev_tools: "Development Tool",
943
- automation_tools: "Automation Tool"
944
- };
945
- return nameMap[agentKey] || agentKey;
946
- }
947
- /**
948
- * Map agent names from WASM to consistent format
949
- */
950
- mapAgentName(agent) {
951
- const lowerAgent = agent.toLowerCase();
952
- if (lowerAgent.includes("chatgpt")) {
953
- return { type: "chatgpt", name: "ChatGPT" };
954
- } else if (lowerAgent.includes("claude")) {
955
- return { type: "claude", name: "Claude" };
956
- } else if (lowerAgent.includes("perplexity")) {
957
- return { type: "perplexity", name: "Perplexity" };
958
- } else if (lowerAgent.includes("bing")) {
959
- return { type: "bing", name: "Bing AI" };
960
- } else if (lowerAgent.includes("anthropic")) {
961
- return { type: "anthropic", name: "Anthropic" };
962
- }
963
- return { type: "unknown", name: agent };
964
- }
965
- };
966
- var EdgeAgentDetectorWrapperWithWasm = class {
967
- detector;
968
- events = /* @__PURE__ */ new Map();
969
- constructor(config) {
970
- this.detector = new EdgeAgentDetectorWithWasm(config?.enableWasm ?? true);
971
- if (config?.baseUrl) {
972
- this.detector.setBaseUrl(config.baseUrl);
973
- }
974
- }
975
- setBaseUrl(url) {
976
- this.detector.setBaseUrl(url);
977
- }
978
- async analyze(input) {
979
- const result = await this.detector.analyze(input);
980
- if (result.isAgent && this.events.has("agent.detected")) {
981
- const handlers = this.events.get("agent.detected") || [];
982
- handlers.forEach((handler) => handler(result, input));
983
- }
984
- return result;
985
- }
986
- on(event, handler) {
987
- if (!this.events.has(event)) {
988
- this.events.set(event, []);
989
- }
990
- this.events.get(event).push(handler);
991
- }
992
- emit(event, ...args) {
993
- const handlers = this.events.get(event) || [];
994
- handlers.forEach((handler) => handler(...args));
995
- }
996
- async init() {
997
- await this.detector.init();
998
- }
999
- };
1000
-
1001
- // src/session-tracker.ts
1002
- var EdgeSessionTracker = class {
1003
- config;
1004
- constructor(config) {
1005
- this.config = {
1006
- enabled: config.enabled,
1007
- cookieName: config.cookieName || "__agentshield_session",
1008
- cookieMaxAge: config.cookieMaxAge || 3600,
1009
- // 1 hour default
1010
- encryptionKey: config.encryptionKey || process.env.AGENTSHIELD_SECRET || "agentshield-default-key"
1011
- };
1012
- }
1013
- /**
1014
- * Track a new AI agent session
1015
- */
1016
- async track(_request, response, result) {
1017
- try {
1018
- if (!this.config.enabled || !result.isAgent) {
1019
- return response;
1020
- }
1021
- const sessionData = {
1022
- id: crypto.randomUUID(),
1023
- agent: result.detectedAgent?.name || "unknown",
1024
- confidence: result.confidence,
1025
- detectedAt: Date.now(),
1026
- expires: Date.now() + this.config.cookieMaxAge * 1e3
1027
- };
1028
- const encrypted = await this.encrypt(JSON.stringify(sessionData));
1029
- response.cookies.set(this.config.cookieName, encrypted, {
1030
- httpOnly: true,
1031
- secure: process.env.NODE_ENV === "production",
1032
- sameSite: "lax",
1033
- maxAge: this.config.cookieMaxAge,
1034
- path: "/"
1035
- });
1036
- return response;
1037
- } catch (error) {
1038
- if (process.env.DEBUG_AGENTSHIELD) {
1039
- console.warn("AgentShield: Failed to track session:", error);
1040
- }
1041
- return response;
1058
+ if (!this.config.enabled || !agentshieldShared.shouldEnforce(result)) {
1059
+ return response;
1060
+ }
1061
+ const sessionData = {
1062
+ id: crypto.randomUUID(),
1063
+ agent: result.detectedAgent?.name || "unknown",
1064
+ confidence: result.confidence,
1065
+ detectedAt: Date.now(),
1066
+ expires: Date.now() + this.config.cookieMaxAge * 1e3
1067
+ };
1068
+ const encrypted = await this.encrypt(JSON.stringify(sessionData));
1069
+ response.cookies.set(this.config.cookieName, encrypted, {
1070
+ httpOnly: true,
1071
+ secure: process.env.NODE_ENV === "production",
1072
+ sameSite: "lax",
1073
+ maxAge: this.config.cookieMaxAge,
1074
+ path: "/"
1075
+ });
1076
+ return response;
1077
+ } catch (error) {
1078
+ if (process.env.DEBUG_AGENTSHIELD) {
1079
+ console.warn("AgentShield: Failed to track session:", error);
1080
+ }
1081
+ return response;
1042
1082
  }
1043
1083
  }
1044
1084
  /**
@@ -1090,9 +1130,7 @@ var EdgeSessionTracker = class {
1090
1130
  for (let i = 0; i < encoded.length; i++) {
1091
1131
  obfuscated[i] = (encoded[i] || 0) ^ key.charCodeAt(i % key.length);
1092
1132
  }
1093
- return btoa(
1094
- Array.from(obfuscated, (byte) => String.fromCharCode(byte)).join("")
1095
- );
1133
+ return btoa(Array.from(obfuscated, (byte) => String.fromCharCode(byte)).join(""));
1096
1134
  } catch (error) {
1097
1135
  return btoa(data);
1098
1136
  }
@@ -1115,14 +1153,29 @@ var EdgeSessionTracker = class {
1115
1153
  }
1116
1154
  };
1117
1155
 
1118
- // src/middleware.ts
1156
+ // src/utils.ts
1157
+ function getClientIp(request) {
1158
+ const forwardedFor = request.headers.get("x-forwarded-for");
1159
+ if (forwardedFor) {
1160
+ const ip = forwardedFor.split(",")[0]?.trim();
1161
+ if (ip) return ip;
1162
+ }
1163
+ const realIp = request.headers.get("x-real-ip");
1164
+ if (realIp) return realIp;
1165
+ const cfIp = request.headers.get("cf-connecting-ip");
1166
+ if (cfIp) return cfIp;
1167
+ const clientIp = request.headers.get("x-client-ip");
1168
+ if (clientIp) return clientIp;
1169
+ return void 0;
1170
+ }
1119
1171
  function createAgentShieldMiddleware(config = {}) {
1120
- const detector = config.enableWasm ? new EdgeAgentDetectorWrapperWithWasm({ enableWasm: true }) : new EdgeAgentDetectorWrapper(config);
1172
+ let detector = config.enableWasm ? null : new EdgeAgentDetectorWrapper(config);
1173
+ let detectorInitPromise = null;
1121
1174
  const sessionTracker = config.sessionTracking?.enabled || config.enableWasm ? new EdgeSessionTracker({
1122
1175
  enabled: true,
1123
1176
  ...config.sessionTracking
1124
1177
  }) : null;
1125
- if (config.events) {
1178
+ if (detector && config.events) {
1126
1179
  Object.entries(config.events).forEach(([event, handler]) => {
1127
1180
  if (handler) {
1128
1181
  detector.on(event, handler);
@@ -1143,6 +1196,23 @@ function createAgentShieldMiddleware(config = {}) {
1143
1196
  } = config;
1144
1197
  return async (request) => {
1145
1198
  try {
1199
+ if (!detector) {
1200
+ if (!detectorInitPromise) {
1201
+ detectorInitPromise = (async () => {
1202
+ const { EdgeAgentDetectorWrapperWithWasm: EdgeAgentDetectorWrapperWithWasm2 } = await Promise.resolve().then(() => (init_edge_detector_with_wasm(), edge_detector_with_wasm_exports));
1203
+ detector = new EdgeAgentDetectorWrapperWithWasm2({ enableWasm: true });
1204
+ if (config.events) {
1205
+ Object.entries(config.events).forEach(([event, handler]) => {
1206
+ if (handler) {
1207
+ detector.on(event, handler);
1208
+ }
1209
+ });
1210
+ }
1211
+ })();
1212
+ }
1213
+ await detectorInitPromise;
1214
+ }
1215
+ const activeDetector = detector;
1146
1216
  const shouldSkip = skipPaths.some((pattern) => {
1147
1217
  if (typeof pattern === "string") {
1148
1218
  return request.nextUrl.pathname.startsWith(pattern);
@@ -1156,11 +1226,11 @@ function createAgentShieldMiddleware(config = {}) {
1156
1226
  const existingSession = sessionTracker ? await sessionTracker.check(request) : null;
1157
1227
  if (existingSession) {
1158
1228
  const response2 = server.NextResponse.next();
1159
- response2.headers.set("x-agentshield-detected", "true");
1160
- response2.headers.set("x-agentshield-agent", existingSession.agent);
1161
- response2.headers.set("x-agentshield-confidence", existingSession.confidence.toString());
1162
- response2.headers.set("x-agentshield-session", "continued");
1163
- response2.headers.set("x-agentshield-session-id", existingSession.id);
1229
+ response2.headers.set("kya-detected", "true");
1230
+ response2.headers.set("kya-agent", existingSession.agent);
1231
+ response2.headers.set("kya-confidence", existingSession.confidence.toString());
1232
+ response2.headers.set("kya-session", "continued");
1233
+ response2.headers.set("kya-session-id", existingSession.id);
1164
1234
  request.agentShield = {
1165
1235
  result: {
1166
1236
  isAgent: true,
@@ -1180,17 +1250,17 @@ function createAgentShieldMiddleware(config = {}) {
1180
1250
  };
1181
1251
  const context2 = {
1182
1252
  userAgent: request.headers.get("user-agent") || "",
1183
- ipAddress: (request.ip ?? request.headers.get("x-forwarded-for")) || "",
1253
+ ipAddress: getClientIp(request) || "",
1184
1254
  headers: Object.fromEntries(request.headers.entries()),
1185
1255
  url: request.url,
1186
1256
  method: request.method,
1187
1257
  timestamp: /* @__PURE__ */ new Date()
1188
1258
  };
1189
- detector.emit("agent.session.continued", existingSession, context2);
1259
+ activeDetector.emit("agent.session.continued", existingSession, context2);
1190
1260
  return response2;
1191
1261
  }
1192
1262
  const userAgent = request.headers.get("user-agent");
1193
- const ipAddress = request.ip ?? request.headers.get("x-forwarded-for");
1263
+ const ipAddress = getClientIp(request);
1194
1264
  const url = new URL(request.url);
1195
1265
  const pathWithQuery = url.pathname + url.search;
1196
1266
  const context = {
@@ -1202,15 +1272,19 @@ function createAgentShieldMiddleware(config = {}) {
1202
1272
  method: request.method,
1203
1273
  timestamp: /* @__PURE__ */ new Date()
1204
1274
  };
1205
- const result = await detector.analyze(context);
1206
- if (result.isAgent && result.confidence >= (config.confidenceThreshold ?? 70)) {
1275
+ const result = await activeDetector.analyze(context);
1276
+ const decision = agentshieldShared.evaluateEnforcement(result, {
1277
+ confidenceThreshold: config.confidenceThreshold,
1278
+ defaultAction: onAgentDetected
1279
+ });
1280
+ if (decision.shouldNotify) {
1207
1281
  if (onDetection) {
1208
1282
  const customResponse = await onDetection(request, result);
1209
1283
  if (customResponse) {
1210
1284
  return customResponse;
1211
1285
  }
1212
1286
  }
1213
- switch (onAgentDetected) {
1287
+ switch (decision.action) {
1214
1288
  case "block": {
1215
1289
  const response2 = server.NextResponse.json(
1216
1290
  {
@@ -1226,11 +1300,17 @@ function createAgentShieldMiddleware(config = {}) {
1226
1300
  response2.headers.set(key, value);
1227
1301
  });
1228
1302
  }
1229
- detector.emit("agent.blocked", result, context);
1303
+ activeDetector.emit("agent.blocked", result, context);
1230
1304
  return response2;
1231
1305
  }
1232
- case "redirect":
1233
- return server.NextResponse.redirect(new URL(redirectUrl, request.url));
1306
+ case "redirect": {
1307
+ const redirectTarget = new URL(redirectUrl, request.url);
1308
+ const agentName = result.detectedAgent?.name;
1309
+ if (agentName && !redirectTarget.searchParams.has("agent")) {
1310
+ redirectTarget.searchParams.set("agent", agentName.toLowerCase());
1311
+ }
1312
+ return server.NextResponse.redirect(redirectTarget);
1313
+ }
1234
1314
  case "rewrite":
1235
1315
  return server.NextResponse.rewrite(new URL(rewriteUrl, request.url));
1236
1316
  case "log":
@@ -1246,9 +1326,7 @@ function createAgentShieldMiddleware(config = {}) {
1246
1326
  break;
1247
1327
  case "allow":
1248
1328
  default:
1249
- if (result.isAgent && result.confidence >= (config.confidenceThreshold ?? 70)) {
1250
- detector.emit("agent.allowed", result, context);
1251
- }
1329
+ activeDetector.emit("agent.allowed", result, context);
1252
1330
  break;
1253
1331
  }
1254
1332
  }
@@ -1257,15 +1335,15 @@ function createAgentShieldMiddleware(config = {}) {
1257
1335
  skipped: false
1258
1336
  };
1259
1337
  let response = server.NextResponse.next();
1260
- response.headers.set("x-agentshield-detected", result.isAgent.toString());
1261
- response.headers.set("x-agentshield-confidence", result.confidence.toString());
1338
+ response.headers.set("kya-detected", result.isAgent.toString());
1339
+ response.headers.set("kya-confidence", result.confidence.toString());
1262
1340
  if (result.detectedAgent?.name) {
1263
- response.headers.set("x-agentshield-agent", result.detectedAgent.name);
1341
+ response.headers.set("kya-agent", result.detectedAgent.name);
1264
1342
  }
1265
- if (sessionTracker && result.isAgent && result.confidence >= (config.confidenceThreshold ?? 70)) {
1343
+ if (sessionTracker && decision.shouldNotify) {
1266
1344
  response = await sessionTracker.track(request, response, result);
1267
- response.headers.set("x-agentshield-session", "new");
1268
- detector.emit("agent.session.started", result, context);
1345
+ response.headers.set("kya-session", "new");
1346
+ activeDetector.emit("agent.session.started", result, context);
1269
1347
  }
1270
1348
  return response;
1271
1349
  } catch (error) {