@apideck/agent-analytics 0.11.0 → 0.13.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.cjs CHANGED
@@ -1,901 +1,3 @@
1
- 'use strict';
2
-
3
- // src/bots.ts
4
- var AI_BOT_PATTERN = /ClaudeBot|Claude-User|Claude-SearchBot|Claude-Web|Anthropic|GPTBot|ChatGPT-User|OAI-SearchBot|PerplexityBot|Perplexity-User|Google-Extended|Google-CloudVertexBot|Google-Agent|GoogleAgent-Mariner|Gemini-Deep-Research|Applebot|cohere|Bytespider|CCBot|Amazonbot|Amzn-SearchBot|NovaAct|AzureAI-SearchBot|Meta-ExternalAgent|meta-externalfetcher|meta-webindexer|FacebookBot|DuckAssistBot|MistralAI-User|YouBot|AI2Bot|Diffbot|DeepSeek|PanguBot|Webzio-Extended|omgili|Timpibot|Grok|Manus-User|quillbot|MyCentralAIScraperBot|Cursor|Windsurf/i;
5
- var HTTP_CLIENT_PATTERN = /axios\/|curl\/|(?:^|[\s(])got(?:\/|[\s(])|\bcolly\b|Electron\/|node-fetch\/|python-requests\/|Go-http-client\/|okhttp\/|aiohttp\/|Deno\//i;
6
- function isAiBot(userAgent) {
7
- if (!userAgent) return false;
8
- return AI_BOT_PATTERN.test(userAgent);
9
- }
10
- function isHttpClient(userAgent) {
11
- if (!userAgent) return false;
12
- return HTTP_CLIENT_PATTERN.test(userAgent);
13
- }
14
- function parseBotName(userAgent) {
15
- if (!userAgent || typeof userAgent !== "string") return "Other";
16
- const s = userAgent.toLowerCase();
17
- if (s.includes("chatgpt-user") || s.includes("gptbot") || s.includes("oai-searchbot") || s.includes("openai"))
18
- return "ChatGPT";
19
- if (s.includes("claudebot") || s.includes("claude-user") || s.includes("claude-searchbot") || s.includes("claude-web") || s.includes("anthropic"))
20
- return "Claude";
21
- if (s.includes("perplexitybot") || s.includes("perplexity-user")) return "Perplexity";
22
- if (s.includes("ccbot")) return "Common Crawl";
23
- if (s.includes("google-extended") || s.includes("googlebot") || s.includes("google-cloudvertexbot") || s.includes("google-agent") || s.includes("googleagent-mariner") || s.includes("gemini-deep-research"))
24
- return "Google";
25
- if (s.includes("applebot")) return "Apple";
26
- if (s.includes("bingbot")) return "Bing";
27
- if (s.includes("bytespider")) return "Bytespider";
28
- if (s.includes("amazonbot") || s.includes("amzn-searchbot") || s.includes("novaact")) return "Amazon";
29
- if (s.includes("meta-externalagent") || s.includes("meta-externalfetcher") || s.includes("meta-webindexer") || s.includes("facebookbot"))
30
- return "Meta";
31
- if (s.includes("mistralai-user")) return "Mistral";
32
- if (s.includes("duckassistbot")) return "DuckDuckGo";
33
- if (s.includes("youbot")) return "You.com";
34
- if (s.includes("diffbot")) return "Diffbot";
35
- if (s.includes("ai2bot")) return "AI2";
36
- if (s.includes("cohere")) return "Cohere";
37
- if (s.includes("cursor")) return "Cursor";
38
- if (s.includes("windsurf")) return "Windsurf";
39
- if (s.includes("deepseek")) return "DeepSeek";
40
- if (s.includes("pangubot")) return "Huawei";
41
- if (s.includes("webzio") || s.includes("omgili")) return "Webz.io";
42
- if (s.includes("timpibot")) return "Timpi";
43
- if (s.includes("grok") || s.includes("xai-")) return "xAI";
44
- if (s.includes("manus-user")) return "Manus";
45
- if (s.includes("quillbot")) return "QuillBot";
46
- if (s.includes("azureai-searchbot")) return "Microsoft";
47
- if (s.includes("mycentralaiscraperbot")) return "MyCentralAI";
48
- if (s.includes("petalbot")) return "PetalBot";
49
- if (s.includes("ahrefsbot")) return "Ahrefs";
50
- if (s.includes("semrushbot")) return "Semrush";
51
- if (s.includes("mj12bot")) return "Majestic";
52
- if (s.includes("dotbot")) return "Moz";
53
- if (s.includes("rogerbot")) return "Moz";
54
- if (s.includes("screaming frog")) return "Screaming Frog";
55
- if (s.includes("sitebulb")) return "Sitebulb";
56
- if (s.includes("linkfluence")) return "Linkfluence";
57
- if (s.includes("dataforseo")) return "DataForSEO";
58
- if (s.includes("serpstatbot")) return "Serpstat";
59
- if (s.includes("uptimerobot")) return "UptimeRobot";
60
- if (s.includes("pingdom")) return "Pingdom";
61
- if (s.includes("statuscake")) return "StatusCake";
62
- if (s.includes("newrelicpinger")) return "New Relic";
63
- if (s.includes("datadogagent") || s.includes("datadog")) return "Datadog";
64
- if (s.includes("slackbot")) return "Slack";
65
- if (s.includes("twitterbot")) return "Twitter";
66
- if (s.includes("linkedinbot")) return "LinkedIn";
67
- if (s.includes("discordbot")) return "Discord";
68
- if (s.includes("telegrambot")) return "Telegram";
69
- if (s.includes("whatsapp")) return "WhatsApp";
70
- if (s.includes("linkupbot")) return "Linkup";
71
- if (s.includes("sogou")) return "Sogou";
72
- if (s.includes("yandexbot")) return "Yandex";
73
- if (s.includes("baiduspider")) return "Baidu";
74
- if (s.includes("facebookexternalhit")) return "Facebook";
75
- if (s.includes("com.apple.webkit")) return "Apple URL Preview";
76
- if (s.includes("ohdear")) return "Oh Dear";
77
- if (s.includes("scrapy")) return "Scrapy";
78
- if (s.includes("headlesschrome")) return "Headless Chrome";
79
- if (s.includes("phantomjs")) return "PhantomJS";
80
- if (s.includes("wget")) return "wget";
81
- if (s.includes("httpie")) return "HTTPie";
82
- if (s.includes("guzzlehttp")) return "Guzzle";
83
- if (s.includes("electron/")) return "Electron";
84
- if (/curl\//.test(s)) return "curl";
85
- if (/axios\//.test(s)) return "axios";
86
- if (/(?:^|[\s(])got(?:\/|[\s(])/.test(s)) return "got";
87
- if (/\bcolly\b/.test(s)) return "colly";
88
- if (/node-fetch\//.test(s)) return "node-fetch";
89
- if (/python-requests\//.test(s)) return "python-requests";
90
- if (/go-http-client\//.test(s)) return "Go http client";
91
- if (/okhttp\//.test(s)) return "OkHttp";
92
- if (/aiohttp\//.test(s)) return "aiohttp";
93
- if (/deno\//.test(s)) return "Deno";
94
- if (s.includes("mozilla") || s.includes("chrome") || s.includes("safari") || s.includes("firefox"))
95
- return "Browser";
96
- return "Other";
97
- }
98
- function firstUserAgentProduct(userAgent) {
99
- if (!userAgent || typeof userAgent !== "string") return "Other";
100
- const compatibleMatch = userAgent.match(/compatible;\s*([^/;\s]+)(?:\/[^\s;]*)?/i);
101
- if (compatibleMatch && compatibleMatch[1]) return compatibleMatch[1].trim();
102
- const first = userAgent.trim().split("/")[0]?.trim().split(/\s+/)[0]?.trim();
103
- return first || "Other";
104
- }
105
- function detectHeadless(req) {
106
- const signals = [];
107
- const ua = (req.headers.get("user-agent") || "").toLowerCase();
108
- const isBrowserUA = ua.includes("mozilla") || ua.includes("chrome") || ua.includes("safari") || ua.includes("firefox");
109
- if (!isBrowserUA) return { score: 0, signals: [], likely: false };
110
- if (!req.headers.get("accept-language")) {
111
- signals.push("missing-accept-language");
112
- }
113
- if (!req.headers.get("sec-fetch-mode")) {
114
- signals.push("missing-sec-fetch-mode");
115
- }
116
- const secChUa = req.headers.get("sec-ch-ua");
117
- if (!secChUa) {
118
- signals.push("missing-sec-ch-ua");
119
- } else if (secChUa.toLowerCase().includes("headlesschrome")) {
120
- signals.push("headless-chrome-hint");
121
- }
122
- const accept = req.headers.get("accept") || "";
123
- if (!accept || accept === "*/*") {
124
- signals.push("missing-or-bare-accept");
125
- }
126
- if ((req.headers.get("connection") || "").toLowerCase() === "close") {
127
- signals.push("connection-close");
128
- }
129
- const score = signals.length;
130
- return { score, signals, likely: score >= 2 };
131
- }
132
- function classifyAgent(userAgent) {
133
- const label = parseBotName(userAgent);
134
- const aiBot = isAiBot(userAgent);
135
- const httpClient = isHttpClient(userAgent);
136
- let kind;
137
- if (aiBot) kind = "declared-crawler";
138
- else if (httpClient) kind = "coding-agent-hint";
139
- else if (label === "Browser") kind = "browser";
140
- else kind = "other";
141
- return { kind, label, isAiBot: aiBot, codingAgentHint: httpClient };
142
- }
143
- function classifyRequest(req) {
144
- const userAgent = req.headers.get("user-agent") || "";
145
- const base = classifyAgent(userAgent);
146
- const headless = detectHeadless(req);
147
- let kind = base.kind;
148
- if (kind === "browser" && headless.likely) {
149
- kind = "headless-likely";
150
- }
151
- return { ...base, kind, headless };
152
- }
153
-
154
- // src/bot-ranges.ts
155
- var BOT_RANGES_CAPTURED_AT = "2026-08-02T00:00:00Z";
156
- var BOT_IP_RANGES = {
157
- ChatGPT: [
158
- "104.208.184.192/28",
159
- "104.208.184.208/28",
160
- "104.210.139.192/28",
161
- "104.210.139.224/28",
162
- "104.210.140.128/28",
163
- "128.85.198.32/28",
164
- "13.65.138.112/28",
165
- "13.65.138.96/28",
166
- "13.67.72.16/28",
167
- "13.70.107.160/28",
168
- "13.71.2.208/28",
169
- "13.76.115.224/28",
170
- "13.76.115.240/28",
171
- "13.76.116.80/28",
172
- "13.76.32.208/28",
173
- "13.83.167.128/28",
174
- "13.83.237.176/28",
175
- "132.196.82.48/28",
176
- "132.196.86.0/24",
177
- "134.149.233.80/28",
178
- "135.116.136.160/28",
179
- "135.13.64.240/28",
180
- "135.220.73.208/28",
181
- "135.220.73.240/28",
182
- "135.234.64.0/24",
183
- "135.237.131.208/28",
184
- "135.237.133.48/28",
185
- "137.135.191.176/28",
186
- "138.91.30.48/28",
187
- "138.91.46.96/28",
188
- "145.132.1.32/28",
189
- "145.132.136.96/28",
190
- "145.133.0.176/28",
191
- "158.158.5.32/28",
192
- "168.63.252.240/28",
193
- "172.162.248.64/28",
194
- "172.170.1.80/28",
195
- "172.170.225.0/28",
196
- "172.170.241.80/28",
197
- "172.170.8.208/28",
198
- "172.171.4.176/28",
199
- "172.175.152.224/28",
200
- "172.178.140.144/28",
201
- "172.178.141.112/28",
202
- "172.178.141.128/28",
203
- "172.182.193.224/28",
204
- "172.182.193.80/28",
205
- "172.182.194.144/28",
206
- "172.182.194.32/28",
207
- "172.182.195.48/28",
208
- "172.182.202.0/25",
209
- "172.182.204.0/24",
210
- "172.182.207.0/25",
211
- "172.182.209.208/28",
212
- "172.182.211.192/28",
213
- "172.182.213.192/28",
214
- "172.182.214.0/24",
215
- "172.182.215.0/24",
216
- "172.182.224.0/28",
217
- "172.183.143.224/28",
218
- "172.183.222.128/28",
219
- "172.192.112.208/28",
220
- "172.192.88.192/28",
221
- "172.192.97.32/28",
222
- "172.197.160.192/28",
223
- "172.197.161.208/28",
224
- "172.197.170.80/28",
225
- "172.197.203.16/28",
226
- "172.199.137.80/28",
227
- "172.202.102.112/28",
228
- "172.203.190.128/28",
229
- "172.204.27.16/28",
230
- "172.204.28.224/28",
231
- "172.204.96.32/28",
232
- "172.204.96.48/28",
233
- "172.204.96.80/28",
234
- "172.205.189.192/28",
235
- "172.207.1.32/28",
236
- "172.208.128.32/28",
237
- "172.208.128.48/28",
238
- "172.212.159.64/28",
239
- "172.212.172.160/28",
240
- "172.213.21.16/28",
241
- "172.215.215.32/28",
242
- "172.215.218.96/28",
243
- "191.233.1.112/28",
244
- "191.233.1.128/28",
245
- "191.233.194.32/28",
246
- "191.233.196.112/28",
247
- "191.233.199.160/28",
248
- "191.233.2.0/28",
249
- "191.235.66.16/28",
250
- "191.235.99.80/28",
251
- "191.237.249.64/28",
252
- "191.239.245.16/28",
253
- "20.102.212.144/28",
254
- "20.113.211.112/28",
255
- "20.113.225.112/28",
256
- "20.125.112.224/28",
257
- "20.125.144.144/28",
258
- "20.125.66.80/28",
259
- "20.14.99.96/28",
260
- "20.161.75.208/28",
261
- "20.168.18.32/28",
262
- "20.168.7.192/28",
263
- "20.168.7.240/28",
264
- "20.169.6.224/28",
265
- "20.169.7.48/28",
266
- "20.169.72.112/28",
267
- "20.169.73.176/28",
268
- "20.169.73.32/28",
269
- "20.169.73.64/28",
270
- "20.169.77.0/25",
271
- "20.169.78.112/28",
272
- "20.169.78.128/28",
273
- "20.169.78.144/28",
274
- "20.169.78.160/28",
275
- "20.169.78.176/28",
276
- "20.169.78.192/28",
277
- "20.169.78.208/28",
278
- "20.169.78.48/28",
279
- "20.169.78.64/28",
280
- "20.169.78.80/28",
281
- "20.169.78.96/28",
282
- "20.169.86.224/28",
283
- "20.169.86.240/28",
284
- "20.169.87.112/28",
285
- "20.17.108.96/28",
286
- "20.170.184.16/28",
287
- "20.170.184.32/28",
288
- "20.170.184.48/28",
289
- "20.170.184.64/28",
290
- "20.170.184.80/28",
291
- "20.171.123.64/28",
292
- "20.171.206.0/24",
293
- "20.171.207.0/24",
294
- "20.171.53.224/28",
295
- "20.172.29.32/28",
296
- "20.193.233.240/28",
297
- "20.193.50.32/28",
298
- "20.194.0.208/28",
299
- "20.194.1.0/28",
300
- "20.198.67.96/28",
301
- "20.199.211.160/28",
302
- "20.199.242.0/28",
303
- "20.200.212.240/28",
304
- "20.204.24.240/28",
305
- "20.210.154.128/28",
306
- "20.210.174.208/28",
307
- "20.210.211.192/28",
308
- "20.215.187.208/28",
309
- "20.215.188.192/28",
310
- "20.215.214.16/28",
311
- "20.215.219.128/28",
312
- "20.215.219.160/28",
313
- "20.215.219.208/28",
314
- "20.215.220.112/28",
315
- "20.215.220.128/28",
316
- "20.215.220.144/28",
317
- "20.215.220.160/28",
318
- "20.215.220.176/28",
319
- "20.215.220.192/28",
320
- "20.215.220.208/28",
321
- "20.215.220.64/28",
322
- "20.215.220.80/28",
323
- "20.215.220.96/28",
324
- "20.218.30.240/28",
325
- "20.219.71.192/28",
326
- "20.222.36.192/28",
327
- "20.226.32.80/28",
328
- "20.227.140.32/28",
329
- "20.228.106.176/28",
330
- "20.235.75.208/28",
331
- "20.235.87.224/28",
332
- "20.249.63.208/28",
333
- "20.25.151.224/28",
334
- "20.250.136.64/28",
335
- "20.250.136.80/28",
336
- "20.250.6.128/28",
337
- "20.27.94.128/28",
338
- "20.42.10.176/28",
339
- "20.45.178.144/28",
340
- "20.48.120.208/28",
341
- "20.52.125.160/28",
342
- "20.55.129.0/28",
343
- "20.55.229.144/28",
344
- "20.57.199.192/28",
345
- "20.63.180.96/28",
346
- "20.63.221.64/28",
347
- "20.79.59.112/28",
348
- "20.81.183.64/28",
349
- "20.83.243.176/28",
350
- "20.97.189.96/28",
351
- "23.102.140.144/28",
352
- "23.102.141.32/28",
353
- "23.98.142.176/28",
354
- "23.98.179.16/28",
355
- "23.98.186.176/28",
356
- "23.98.186.192/28",
357
- "23.98.186.64/28",
358
- "23.98.186.96/28",
359
- "4.151.119.48/28",
360
- "4.151.241.240/28",
361
- "4.151.71.176/28",
362
- "4.189.118.208/28",
363
- "4.189.119.48/28",
364
- "4.196.118.112/28",
365
- "4.197.115.112/28",
366
- "4.197.19.176/28",
367
- "4.197.22.112/28",
368
- "4.197.64.0/28",
369
- "4.197.64.16/28",
370
- "4.197.64.48/28",
371
- "4.197.64.64/28",
372
- "4.198.72.16/28",
373
- "4.198.96.112/28",
374
- "4.201.232.64/28",
375
- "4.201.232.80/28",
376
- "4.203.96.80/28",
377
- "4.205.128.176/28",
378
- "4.218.24.64/28",
379
- "4.226.200.16/28",
380
- "4.226.226.32/28",
381
- "4.227.36.0/25",
382
- "40.116.73.208/28",
383
- "40.122.235.112/28",
384
- "40.67.175.0/25",
385
- "40.67.183.160/28",
386
- "40.67.183.176/28",
387
- "40.78.161.48/28",
388
- "40.81.134.128/28",
389
- "40.81.134.144/28",
390
- "40.81.234.144/28",
391
- "40.81.67.96/28",
392
- "40.84.181.32/28",
393
- "40.84.221.208/28",
394
- "40.84.221.224/28",
395
- "40.90.214.16/28",
396
- "48.193.44.32/28",
397
- "48.221.184.112/28",
398
- "48.221.184.80/28",
399
- "48.221.184.96/28",
400
- "48.221.40.176/28",
401
- "51.107.70.192/28",
402
- "51.116.2.80/28",
403
- "51.116.221.96/28",
404
- "51.56.40.80/28",
405
- "51.57.0.96/28",
406
- "51.59.24.64/28",
407
- "51.59.24.80/28",
408
- "51.59.40.80/28",
409
- "51.59.40.96/28",
410
- "51.59.48.80/28",
411
- "51.59.48.96/28",
412
- "51.8.102.0/24",
413
- "51.8.155.112/28",
414
- "51.8.155.48/28",
415
- "51.8.155.64/28",
416
- "51.8.187.224/28",
417
- "52.148.129.32/28",
418
- "52.153.130.64/28",
419
- "52.154.22.48/28",
420
- "52.156.77.144/28",
421
- "52.159.227.32/28",
422
- "52.159.249.96/28",
423
- "52.161.49.224/28",
424
- "52.161.49.96/28",
425
- "52.165.212.16/28",
426
- "52.165.212.32/28",
427
- "52.165.212.48/28",
428
- "52.172.129.160/28",
429
- "52.172.251.112/28",
430
- "52.173.219.112/28",
431
- "52.173.219.96/28",
432
- "52.173.221.16/28",
433
- "52.173.221.176/28",
434
- "52.173.221.208/28",
435
- "52.173.234.16/28",
436
- "52.173.234.80/28",
437
- "52.173.235.80/28",
438
- "52.183.217.240/28",
439
- "52.187.246.128/28",
440
- "52.190.137.144/28",
441
- "52.190.137.16/28",
442
- "52.190.139.48/28",
443
- "52.190.142.64/28",
444
- "52.190.190.16/28",
445
- "52.225.75.208/28",
446
- "52.230.152.0/24",
447
- "52.230.163.32/28",
448
- "52.230.164.176/28",
449
- "52.231.30.48/28",
450
- "52.231.34.176/28",
451
- "52.231.39.144/28",
452
- "52.231.39.192/28",
453
- "52.231.49.48/28",
454
- "52.231.50.64/28",
455
- "52.236.94.144/28",
456
- "52.241.146.208/28",
457
- "52.242.132.224/28",
458
- "52.242.132.240/28",
459
- "52.242.245.208/28",
460
- "52.252.113.240/28",
461
- "52.255.109.112/28",
462
- "52.255.109.128/28",
463
- "52.255.109.144/28",
464
- "52.255.109.80/28",
465
- "52.255.109.96/28",
466
- "52.255.111.0/28",
467
- "52.255.111.112/28",
468
- "52.255.111.32/28",
469
- "52.255.111.48/28",
470
- "52.255.111.80/28",
471
- "57.154.174.112/28",
472
- "57.154.175.0/28",
473
- "57.154.187.32/28",
474
- "68.154.28.96/28",
475
- "68.218.30.112/28",
476
- "68.220.57.64/28",
477
- "68.221.67.192/28",
478
- "68.221.67.224/28",
479
- "68.221.67.240/28",
480
- "70.153.139.208/28",
481
- "70.153.189.192/28",
482
- "70.153.190.16/28",
483
- "70.153.76.16/28",
484
- "70.153.87.224/28",
485
- "70.156.144.64/28",
486
- "70.156.152.80/28",
487
- "70.156.152.96/28",
488
- "74.161.200.96/28",
489
- "74.224.217.64/28",
490
- "74.226.253.160/28",
491
- "74.249.86.176/28",
492
- "74.7.175.128/25",
493
- "74.7.227.0/25",
494
- "74.7.227.128/25",
495
- "74.7.228.0/25",
496
- "74.7.228.128/25",
497
- "74.7.229.0/25",
498
- "74.7.229.128/25",
499
- "74.7.230.0/25",
500
- "74.7.241.0/25",
501
- "74.7.241.128/25",
502
- "74.7.242.0/25",
503
- "74.7.242.128/25",
504
- "74.7.243.0/25",
505
- "74.7.243.128/25",
506
- "74.7.244.0/25",
507
- "74.7.35.112/28",
508
- "74.7.35.48/28",
509
- "74.7.36.64/28",
510
- "74.7.36.80/28",
511
- "74.7.36.96/28",
512
- "85.211.241.128/28",
513
- "9.129.0.0/17",
514
- "9.160.128.16/28",
515
- "9.160.128.32/28",
516
- "9.160.128.64/28",
517
- "9.160.163.128/28",
518
- "9.160.164.128/28",
519
- "9.160.34.144/28",
520
- "9.160.36.16/28",
521
- "9.160.96.16/28",
522
- "9.163.101.48/28",
523
- "9.205.25.128/28",
524
- "9.205.8.48/28",
525
- "9.223.181.208/28",
526
- "9.234.96.192/28",
527
- "9.234.97.128/28",
528
- "9.234.97.96/28",
529
- "9.235.40.32/28"
530
- ],
531
- Claude: [
532
- "136.107.176.208/32",
533
- "216.73.216.0/22",
534
- "34.11.34.31/32",
535
- "34.150.241.79/32",
536
- "34.162.191.81/32",
537
- "34.162.230.222/32",
538
- "34.162.244.71/32",
539
- "34.182.140.95/32",
540
- "34.182.161.143/32",
541
- "34.182.218.27/32",
542
- "34.182.220.85/32",
543
- "34.182.222.37/32",
544
- "34.182.225.167/32",
545
- "34.182.226.151/32",
546
- "34.182.226.221/32",
547
- "34.186.108.163/32",
548
- "34.85.172.162/32",
549
- "35.221.29.174/32",
550
- "35.245.175.129/32",
551
- "35.245.89.239/32"
552
- ],
553
- Perplexity: [
554
- "107.20.236.150/32",
555
- "18.210.92.235/32",
556
- "18.97.1.228/30",
557
- "18.97.9.96/29",
558
- "3.211.124.183/32",
559
- "3.222.232.239/32",
560
- "3.224.62.45/32",
561
- "3.231.139.107/32"
562
- ],
563
- Apple: [
564
- "17.22.237.0/24",
565
- "17.22.245.0/24",
566
- "17.22.253.0/24",
567
- "17.241.193.160/27",
568
- "17.241.200.160/27",
569
- "17.241.208.160/27",
570
- "17.241.219.0/24",
571
- "17.241.227.0/24",
572
- "17.241.75.0/24",
573
- "17.246.15.0/24",
574
- "17.246.19.0/24",
575
- "17.246.23.0/24"
576
- ]
577
- };
578
- var VERIFIABLE_VENDORS = Object.keys(BOT_IP_RANGES);
579
-
580
- // src/cidr.ts
581
- function ipv4ToInt(ip) {
582
- const parts = ip.split(".");
583
- if (parts.length !== 4) return null;
584
- let out = 0;
585
- for (const part of parts) {
586
- if (!/^\d{1,3}$/.test(part)) return null;
587
- if (part.length > 1 && part[0] === "0") return null;
588
- const n = Number(part);
589
- if (n > 255) return null;
590
- out = out << 8 | n;
591
- }
592
- return out >>> 0;
593
- }
594
- function ipv6ToBigInt(ip) {
595
- let text = ip;
596
- const zone = text.indexOf("%");
597
- if (zone !== -1) text = text.slice(0, zone);
598
- if (!text || text.indexOf(":") === -1) return null;
599
- let tail = null;
600
- const lastColon = text.lastIndexOf(":");
601
- const maybeV4 = text.slice(lastColon + 1);
602
- if (maybeV4.indexOf(".") !== -1) {
603
- tail = ipv4ToInt(maybeV4);
604
- if (tail === null) return null;
605
- text = text.slice(0, lastColon + 1) + "0:0";
606
- }
607
- const halves = text.split("::");
608
- if (halves.length > 2) return null;
609
- const head = halves[0] ? halves[0].split(":") : [];
610
- const rest = halves.length === 2 ? halves[1] ? halves[1].split(":") : [] : null;
611
- let groups;
612
- if (rest === null) {
613
- groups = head;
614
- if (groups.length !== 8) return null;
615
- } else {
616
- const fill = 8 - head.length - rest.length;
617
- if (fill < 0) return null;
618
- groups = [...head, ...Array(fill).fill("0"), ...rest];
619
- }
620
- let out = 0n;
621
- for (const g of groups) {
622
- if (!/^[0-9a-fA-F]{1,4}$/.test(g)) return null;
623
- out = out << 16n | BigInt(parseInt(g, 16));
624
- }
625
- if (tail !== null) out = out >> 32n << 32n | BigInt(tail >>> 0);
626
- return out;
627
- }
628
- function compileRanges(cidrs) {
629
- const v4 = [];
630
- const v6 = [];
631
- for (const cidr of cidrs) {
632
- const slash = cidr.lastIndexOf("/");
633
- if (slash === -1) continue;
634
- const addr = cidr.slice(0, slash);
635
- const bits = Number(cidr.slice(slash + 1));
636
- if (!Number.isInteger(bits) || bits < 0) continue;
637
- if (addr.indexOf(":") !== -1) {
638
- if (bits > 128) continue;
639
- const net = ipv6ToBigInt(addr);
640
- if (net === null) continue;
641
- v6.push({ net: bits === 0 ? 0n : net >> BigInt(128 - bits) << BigInt(128 - bits), bits });
642
- } else {
643
- if (bits > 32) continue;
644
- const net = ipv4ToInt(addr);
645
- if (net === null) continue;
646
- const mask = bits === 0 ? 0 : 4294967295 << 32 - bits >>> 0;
647
- v4.push({ net: (net & mask) >>> 0, mask });
648
- }
649
- }
650
- return { v4, v6 };
651
- }
652
- function ipInRanges(ip, ranges) {
653
- if (!ip) return false;
654
- const trimmed = ip.trim();
655
- if (!trimmed) return false;
656
- if (trimmed.indexOf(":") !== -1) {
657
- const value2 = ipv6ToBigInt(trimmed);
658
- if (value2 === null) return false;
659
- const V4_MAPPED_PREFIX = 0xffffn << 32n;
660
- if (value2 >> 32n === V4_MAPPED_PREFIX >> 32n) {
661
- const low = Number(value2 & 0xffffffffn) >>> 0;
662
- if (matchV4(low, ranges.v4)) return true;
663
- }
664
- for (const r of ranges.v6) {
665
- if (r.bits === 0) return true;
666
- if (value2 >> BigInt(128 - r.bits) << BigInt(128 - r.bits) === r.net) return true;
667
- }
668
- return false;
669
- }
670
- const value = ipv4ToInt(trimmed);
671
- if (value === null) return false;
672
- return matchV4(value, ranges.v4);
673
- }
674
- function matchV4(value, list) {
675
- for (const r of list) {
676
- if ((value & r.mask) >>> 0 === r.net) return true;
677
- }
678
- return false;
679
- }
680
- function ipInCidr(ip, cidr) {
681
- return ipInRanges(ip, compileRanges([cidr]));
682
- }
683
-
684
- // src/verify.ts
685
- var CLIENT_SIDE_AGENT_PATTERN = /claude-code|perplexity-user|cursor|windsurf|cline|aider/i;
686
- var SERVER_SIDE_CRAWLER_PATTERN = /ClaudeBot|Claude-SearchBot|GPTBot|OAI-SearchBot|ChatGPT-User|PerplexityBot|Applebot/i;
687
- var COMPILED = {};
688
- for (const vendor of VERIFIABLE_VENDORS) {
689
- COMPILED[vendor] = compileRanges(BOT_IP_RANGES[vendor] ?? []);
690
- }
691
- function verifiableVendors() {
692
- return VERIFIABLE_VENDORS;
693
- }
694
- function verifyBotIdentity(userAgent, ip) {
695
- const ua = userAgent ?? "";
696
- const claimed = parseBotName(userAgent);
697
- const ranges = COMPILED[claimed];
698
- if (!ranges) {
699
- const isKnownCrawler = claimed !== "Other" && claimed !== "Browser";
700
- return {
701
- verdict: isKnownCrawler ? "unverifiable" : "not-claimed",
702
- ...isKnownCrawler ? { reason: "no-published-ranges" } : {},
703
- claimed: isKnownCrawler ? claimed : null,
704
- verified: null
705
- };
706
- }
707
- if (CLIENT_SIDE_AGENT_PATTERN.test(ua) || !SERVER_SIDE_CRAWLER_PATTERN.test(ua)) {
708
- return {
709
- verdict: "unverifiable",
710
- reason: "client-side-agent",
711
- claimed,
712
- verified: null
713
- };
714
- }
715
- const trimmed = (ip ?? "").trim();
716
- if (!trimmed) {
717
- return { verdict: "unverifiable", reason: "no-client-ip", claimed, verified: null };
718
- }
719
- const inRange = ipInRanges(trimmed, ranges);
720
- return {
721
- verdict: inRange ? "verified" : "spoofed",
722
- claimed,
723
- verified: inRange
724
- };
725
- }
726
- function clientIpFromRequest(req) {
727
- const forwarded = req.headers.get("x-forwarded-for") || "";
728
- const first = forwarded.split(",")[0]?.trim();
729
- if (first) return first;
730
- return (req.headers.get("cf-connecting-ip") || req.headers.get("x-real-ip") || "").trim();
731
- }
732
- function verifyRequest(req) {
733
- return verifyBotIdentity(req.headers.get("user-agent"), clientIpFromRequest(req));
734
- }
735
-
736
- // src/hash.ts
737
- function hashId(input) {
738
- let h = 5381;
739
- for (let i = 0; i < input.length; i++) {
740
- h = (h << 5) + h + input.charCodeAt(i) & 4294967295;
741
- }
742
- return "anon_" + (h >>> 0).toString(16);
743
- }
744
-
745
- // src/track.ts
746
- async function trackVisit(req, opts) {
747
- const userAgent = req.headers.get("user-agent") || "";
748
- const onlyBots = opts.onlyBots ?? false;
749
- const skipBrowsers = opts.skipBrowsers ?? false;
750
- if (onlyBots && !isAiBot(userAgent)) return;
751
- if (skipBrowsers && !isAiBot(userAgent) && !isHttpClient(userAgent)) {
752
- if (!detectHeadless(req).likely) return;
753
- }
754
- let pathname = "/";
755
- let originFromUrl = "";
756
- try {
757
- const url = new URL(req.url);
758
- pathname = url.pathname;
759
- originFromUrl = url.origin;
760
- } catch {
761
- pathname = req.url || "/";
762
- }
763
- const origin = opts.origin ?? originFromUrl;
764
- const forwardedFor = req.headers.get("x-forwarded-for") || "";
765
- const ip = forwardedFor.split(",")[0]?.trim() ?? "";
766
- const referer = req.headers.get("referer");
767
- const country = opts.captureCountry ? req.headers.get("x-vercel-ip-country") || req.headers.get("cf-ipcountry") || req.headers.get("x-country-code") || null : null;
768
- const geo = opts.captureGeo ? extractGeo(req) : null;
769
- const classification = classifyRequest(req);
770
- const verification = opts.verifyIdentity ? verifyBotIdentity(userAgent, ip) : null;
771
- const event = {
772
- event: opts.eventName ?? "agent_visit",
773
- distinctId: hashId(`${ip}:${userAgent}`),
774
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
775
- properties: {
776
- $process_person_profile: false,
777
- $current_url: origin ? `${origin}${pathname}` : pathname,
778
- path: pathname,
779
- method: req.method,
780
- ...opts.captureCountry ? { country_code: country } : {},
781
- ...geo ?? {},
782
- ...opts.captureIp ? { client_ip: ip || null } : {},
783
- user_agent: userAgent,
784
- is_ai_bot: classification.isAiBot,
785
- bot_name: classification.label,
786
- ua_category: classification.kind,
787
- coding_agent_hint: classification.codingAgentHint,
788
- headless_score: classification.headless?.score ?? 0,
789
- headless_likely: classification.headless?.likely ?? false,
790
- ...verification ? {
791
- bot_verified: verification.verified,
792
- bot_verification: verification.verdict,
793
- ...verification.reason ? { bot_verification_reason: verification.reason } : {}
794
- } : {},
795
- referer,
796
- source: opts.source ?? null,
797
- ...opts.properties
798
- }
799
- };
800
- try {
801
- await opts.analytics.capture(event);
802
- } catch {
803
- }
804
- }
805
- function extractGeo(req) {
806
- const decode = (v) => {
807
- if (!v) return "";
808
- try {
809
- return decodeURIComponent(v);
810
- } catch {
811
- return v;
812
- }
813
- };
814
- const fields = [
815
- ["region", decode(req.headers.get("x-vercel-ip-country-region"))],
816
- ["city", decode(req.headers.get("x-vercel-ip-city"))],
817
- ["latitude", req.headers.get("x-vercel-ip-latitude") ?? ""],
818
- ["longitude", req.headers.get("x-vercel-ip-longitude") ?? ""],
819
- ["timezone", req.headers.get("x-vercel-ip-timezone") ?? ""]
820
- ];
821
- const out = {};
822
- for (const [k, v] of fields) if (v) out[k] = v;
823
- return out;
824
- }
825
-
826
- // src/adapters/posthog.ts
827
- function posthogAnalytics(config) {
828
- const hostRaw = config.host ?? "https://us.i.posthog.com";
829
- const base = (/^https?:\/\//.test(hostRaw) ? hostRaw : `https://${hostRaw}`).replace(/\/$/, "");
830
- const path = (config.path ?? "/i/v0/e/").replace(/^(?!\/)/, "/");
831
- const endpoint = `${base}${path}`;
832
- const fetchImpl = config.fetchImpl ?? fetch;
833
- return {
834
- async capture(event) {
835
- const payload = {
836
- api_key: config.apiKey,
837
- event: event.event,
838
- distinct_id: event.distinctId,
839
- timestamp: event.timestamp,
840
- properties: event.properties
841
- };
842
- await fetchImpl(endpoint, {
843
- method: "POST",
844
- headers: { "Content-Type": "application/json" },
845
- body: JSON.stringify(payload),
846
- keepalive: true
847
- });
848
- }
849
- };
850
- }
851
-
852
- // src/adapters/webhook.ts
853
- function webhookAnalytics(config) {
854
- const fetchImpl = config.fetchImpl ?? fetch;
855
- const transform = config.transform ?? ((e) => e);
856
- return {
857
- async capture(event) {
858
- await fetchImpl(config.url, {
859
- method: "POST",
860
- headers: {
861
- "Content-Type": "application/json",
862
- ...config.headers ?? {}
863
- },
864
- body: JSON.stringify(transform(event)),
865
- keepalive: true
866
- });
867
- }
868
- };
869
- }
870
-
871
- // src/adapters/custom.ts
872
- function customAnalytics(capture) {
873
- return { capture };
874
- }
875
-
876
- exports.AI_BOT_PATTERN = AI_BOT_PATTERN;
877
- exports.BOT_IP_RANGES = BOT_IP_RANGES;
878
- exports.BOT_RANGES_CAPTURED_AT = BOT_RANGES_CAPTURED_AT;
879
- exports.HTTP_CLIENT_PATTERN = HTTP_CLIENT_PATTERN;
880
- exports.VERIFIABLE_VENDORS = VERIFIABLE_VENDORS;
881
- exports.classifyAgent = classifyAgent;
882
- exports.classifyRequest = classifyRequest;
883
- exports.clientIpFromRequest = clientIpFromRequest;
884
- exports.compileRanges = compileRanges;
885
- exports.customAnalytics = customAnalytics;
886
- exports.detectHeadless = detectHeadless;
887
- exports.firstUserAgentProduct = firstUserAgentProduct;
888
- exports.hashId = hashId;
889
- exports.ipInCidr = ipInCidr;
890
- exports.ipInRanges = ipInRanges;
891
- exports.isAiBot = isAiBot;
892
- exports.isHttpClient = isHttpClient;
893
- exports.parseBotName = parseBotName;
894
- exports.posthogAnalytics = posthogAnalytics;
895
- exports.trackVisit = trackVisit;
896
- exports.verifiableVendors = verifiableVendors;
897
- exports.verifyBotIdentity = verifyBotIdentity;
898
- exports.verifyRequest = verifyRequest;
899
- exports.webhookAnalytics = webhookAnalytics;
900
- //# sourceMappingURL=index.cjs.map
1
+ 'use strict';var B=/ClaudeBot|Claude-User|Claude-SearchBot|Claude-Web|Anthropic|GPTBot|ChatGPT-User|OAI-SearchBot|PerplexityBot|Perplexity-User|Google-Extended|Google-CloudVertexBot|Google-Agent|GoogleAgent-Mariner|Gemini-Deep-Research|Applebot|cohere|Bytespider|CCBot|Amazonbot|Amzn-SearchBot|NovaAct|AzureAI-SearchBot|Meta-ExternalAgent|meta-externalfetcher|meta-webindexer|FacebookBot|DuckAssistBot|MistralAI-User|YouBot|AI2Bot|Diffbot|DeepSeek|PanguBot|Webzio-Extended|omgili|Timpibot|Grok|Manus-User|quillbot|MyCentralAIScraperBot|Cursor|Windsurf/i,S=/axios\/|curl\/|(?:^|[\s(])got(?:\/|[\s(])|\bcolly\b|Electron\/|node-fetch\/|python-requests\/|Go-http-client\/|okhttp\/|aiohttp\/|Deno\//i;function f(t){return t?B.test(t):false}function m(t){return t?S.test(t):false}function T(t){if(!t||typeof t!="string")return "Other";let e=t.toLowerCase();return e.includes("chatgpt-user")||e.includes("gptbot")||e.includes("oai-searchbot")||e.includes("openai")?"ChatGPT":e.includes("claudebot")||e.includes("claude-user")||e.includes("claude-searchbot")||e.includes("claude-web")||e.includes("anthropic")?"Claude":e.includes("perplexitybot")||e.includes("perplexity-user")?"Perplexity":e.includes("ccbot")?"Common Crawl":e.includes("google-extended")||e.includes("googlebot")||e.includes("google-cloudvertexbot")||e.includes("google-agent")||e.includes("googleagent-mariner")||e.includes("gemini-deep-research")?"Google":e.includes("applebot")?"Apple":e.includes("bingbot")?"Bing":e.includes("bytespider")?"Bytespider":e.includes("amazonbot")||e.includes("amzn-searchbot")||e.includes("novaact")?"Amazon":e.includes("meta-externalagent")||e.includes("meta-externalfetcher")||e.includes("meta-webindexer")||e.includes("facebookbot")?"Meta":e.includes("mistralai-user")?"Mistral":e.includes("duckassistbot")?"DuckDuckGo":e.includes("youbot")?"You.com":e.includes("diffbot")?"Diffbot":e.includes("ai2bot")?"AI2":e.includes("cohere")?"Cohere":e.includes("cursor")?"Cursor":e.includes("windsurf")?"Windsurf":e.includes("deepseek")?"DeepSeek":e.includes("pangubot")?"Huawei":e.includes("webzio")||e.includes("omgili")?"Webz.io":e.includes("timpibot")?"Timpi":e.includes("grok")||e.includes("xai-")?"xAI":e.includes("manus-user")?"Manus":e.includes("quillbot")?"QuillBot":e.includes("azureai-searchbot")?"Microsoft":e.includes("mycentralaiscraperbot")?"MyCentralAI":e.includes("petalbot")?"PetalBot":e.includes("ahrefsbot")?"Ahrefs":e.includes("semrushbot")?"Semrush":e.includes("mj12bot")?"Majestic":e.includes("dotbot")||e.includes("rogerbot")?"Moz":e.includes("screaming frog")?"Screaming Frog":e.includes("sitebulb")?"Sitebulb":e.includes("linkfluence")?"Linkfluence":e.includes("dataforseo")?"DataForSEO":e.includes("serpstatbot")?"Serpstat":e.includes("uptimerobot")?"UptimeRobot":e.includes("pingdom")?"Pingdom":e.includes("statuscake")?"StatusCake":e.includes("newrelicpinger")?"New Relic":e.includes("datadogagent")||e.includes("datadog")?"Datadog":e.includes("slackbot")?"Slack":e.includes("twitterbot")?"Twitter":e.includes("linkedinbot")?"LinkedIn":e.includes("discordbot")?"Discord":e.includes("telegrambot")?"Telegram":e.includes("whatsapp")?"WhatsApp":e.includes("linkupbot")?"Linkup":e.includes("sogou")?"Sogou":e.includes("yandexbot")?"Yandex":e.includes("baiduspider")?"Baidu":e.includes("facebookexternalhit")?"Facebook":e.includes("com.apple.webkit")?"Apple URL Preview":e.includes("ohdear")?"Oh Dear":e.includes("scrapy")?"Scrapy":e.includes("headlesschrome")?"Headless Chrome":e.includes("phantomjs")?"PhantomJS":e.includes("wget")?"wget":e.includes("httpie")?"HTTPie":e.includes("guzzlehttp")?"Guzzle":e.includes("electron/")?"Electron":/curl\//.test(e)?"curl":/axios\//.test(e)?"axios":/(?:^|[\s(])got(?:\/|[\s(])/.test(e)?"got":/\bcolly\b/.test(e)?"colly":/node-fetch\//.test(e)?"node-fetch":/python-requests\//.test(e)?"python-requests":/go-http-client\//.test(e)?"Go http client":/okhttp\//.test(e)?"OkHttp":/aiohttp\//.test(e)?"aiohttp":/deno\//.test(e)?"Deno":e.includes("mozilla")||e.includes("chrome")||e.includes("safari")||e.includes("firefox")?"Browser":"Other"}function M(t){if(!t||typeof t!="string")return "Other";let e=t.match(/compatible;\s*([^/;\s]+)(?:\/[^\s;]*)?/i);return e&&e[1]?e[1].trim():t.trim().split("/")[0]?.trim().split(/\s+/)[0]?.trim()||"Other"}function b(t){let e=[],r=(t.headers.get("user-agent")||"").toLowerCase();if(!(r.includes("mozilla")||r.includes("chrome")||r.includes("safari")||r.includes("firefox")))return {score:0,signals:[],likely:false};t.headers.get("accept-language")||e.push("missing-accept-language"),t.headers.get("sec-fetch-mode")||e.push("missing-sec-fetch-mode");let n=t.headers.get("sec-ch-ua");n?n.toLowerCase().includes("headlesschrome")&&e.push("headless-chrome-hint"):e.push("missing-sec-ch-ua");let i=t.headers.get("accept")||"";(!i||i==="*/*")&&e.push("missing-or-bare-accept"),(t.headers.get("connection")||"").toLowerCase()==="close"&&e.push("connection-close");let s=e.length;return {score:s,signals:e,likely:s>=2}}function v(t){let e=T(t),r=f(t),o=m(t),n;return r?n="declared-crawler":o?n="coding-agent-hint":e==="Browser"?n="browser":n="other",{kind:n,label:e,isAiBot:r,codingAgentHint:o}}function p(t){let e=t.headers.get("user-agent")||"",r=v(e),o=b(t),n=r.kind,i=r.label;return n==="browser"&&o.likely&&(n="headless-likely",i="Headless"),{...r,kind:n,label:i,headless:o}}var g=class extends Error{constructor(e){super(e),this.name="HashSecretError";}};function A(){let t=globalThis.crypto;if(!t?.subtle)throw new g("Web Crypto is unavailable. agent-analytics requires Node >= 20, or any runtime exposing globalThis.crypto.subtle (Vercel Edge, Cloudflare Workers, Deno, browsers).");return t.subtle}var E=new Map;function N(t){let e=E.get(t);return e||(e=A().importKey("raw",new TextEncoder().encode(t),{name:"HMAC",hash:"SHA-256"},false,["sign"]),E.set(t,e)),e}async function x(t,e){if(typeof e!="string"||e.length===0)throw new g("hashId requires a non-empty secret");let r=await A().sign("HMAC",await N(e),new TextEncoder().encode(t)),o=new Uint8Array(r,0,8),n="";for(let i of o)n+=i.toString(16).padStart(2,"0");return "anon_"+n}function w(){let t=new Uint8Array(32);A(),globalThis.crypto.getRandomValues(t);let e="";for(let r of t)e+=r.toString(16).padStart(2,"0");return e}var k,I=false;function z(t){if(t)return t;let e=typeof process<"u"?process.env?.AGENT_ANALYTICS_ID_SECRET:void 0;return e||(k||(k=w(),I||(I=true,console.warn("[agent-analytics] No idSecret or AGENT_ANALYTICS_ID_SECRET set. Using a per-instance random secret: distinctIds will not correlate across instances or deploys."))),k)}async function O(t,e){let r=t.headers.get("user-agent")||"",o=e.onlyBots??false,n=e.skipBrowsers??false;if(!(o&&!f(r))&&!(n&&!f(r)&&!m(r)&&!b(t).likely))try{let i="/",s="";try{let C=new URL(t.url);i=C.pathname,s=C.origin;}catch{i=t.url||"/";}let a=e.origin??s,y=(t.headers.get("x-forwarded-for")||"").split(",")[0]?.trim()??"",h=t.headers.get("referer"),R=e.captureCountry&&(t.headers.get("x-vercel-ip-country")||t.headers.get("cf-ipcountry")||t.headers.get("x-country-code"))||null,_=e.captureGeo?U(t):null,c=p(t),d=e.verify?e.verify(t):null,D=c.kind==="headless-likely"||c.kind==="browser",H=await x(`${y}:${r}`,z(e.idSecret)),G={event:e.eventName??"agent_visit",distinctId:H,timestamp:new Date().toISOString(),properties:{...e.properties,$process_person_profile:!1,$current_url:a?`${a}${i}`:i,path:i,method:t.method,...e.captureCountry?{country_code:R}:{},..._??{},...e.captureIp?{client_ip:y||null}:{},user_agent:r,is_ai_bot:c.isAiBot,bot_name:c.label,ua_category:c.kind,coding_agent_hint:c.codingAgentHint,...D?{headless_score:c.headless?.score??0,headless_likely:c.headless?.likely??!1}:{},...d?{bot_verified:d.verified,bot_verification:d.verdict,...d.reason?{bot_verification_reason:d.reason}:{}}:{},referer:h,source:e.source??null}};await e.analytics.capture(G);}catch(i){e.onError?.(i instanceof Error?i:new Error(String(i)));}}function U(t){let e=n=>{if(!n)return "";try{return decodeURIComponent(n)}catch{return n}},r=[["region",e(t.headers.get("x-vercel-ip-country-region"))],["city",e(t.headers.get("x-vercel-ip-city"))],["latitude",t.headers.get("x-vercel-ip-latitude")??""],["longitude",t.headers.get("x-vercel-ip-longitude")??""],["timezone",t.headers.get("x-vercel-ip-timezone")??""]],o={};for(let[n,i]of r)i&&(o[n]=i);return o}var u=class extends Error{status;body;constructor(e,r,o){super(e),this.name="CaptureTransportError",this.status=r,this.body=o;}};var L=/ChatGPT-User|OAI-SearchBot|Claude-User|Claude-SearchBot|Perplexity-User|claude-code|DuckAssistBot|MistralAI-User|Gemini-Deep-Research|Manus-User|YouBot/i,$=/GPTBot|ClaudeBot|Claude-Web|CCBot|Bytespider|Amazonbot|Amzn-SearchBot|Meta-ExternalAgent|meta-externalfetcher|meta-webindexer|FacebookBot|Google-Extended|Applebot-Extended|AI2Bot|Diffbot|omgili|Webzio-Extended|Timpibot|PanguBot|cohere|DeepSeek|Grok|quillbot|MyCentralAIScraperBot|NovaAct|AzureAI-SearchBot|Google-CloudVertexBot/i,j=/bingbot|Googlebot|DuckDuckBot|YandexBot|Baiduspider|PetalBot|Sogou|Applebot(?!-Extended)/i;function P(t){let e=t??"";return e?L.test(e)?"retrieval":$.test(e)?"training":j.test(e)?"search":"unknown":"unknown"}function V(t,e={}){let r=t.headers.get("user-agent")||"",o=p(t),n=o.label,i=P(r);if(i==="unknown"&&o.codingAgentHint&&(i="tooling"),e.allowList?.some(h=>h===n||r.toLowerCase().includes(h.toLowerCase())))return {action:"allow",intent:i,label:n,reason:"on allowList"};let a;return e.verify&&(a=e.verify(t).verdict,a==="spoofed")?{action:"block",intent:i,label:n,verification:a,reason:`${n} claimed but client IP is outside its published ranges`}:{action:i==="training"?e.onTraining??"meter":i==="retrieval"?e.onRetrieval??"allow":i==="search"?e.onSearch??"allow":i==="tooling"?e.onTooling??"allow":"allow",intent:i,label:n,...a?{verification:a}:{},reason:{retrieval:"a person is waiting on this answer",training:"bulk corpus collection",search:"search index crawler",tooling:"coding agent or HTTP client",unknown:"not a recognised agent"}[i]}}function W(t){let e=t.host??"https://us.i.posthog.com",r=(/^https?:\/\//.test(e)?e:`https://${e}`).replace(/\/$/,""),o=(t.path??"/i/v0/e/").replace(/^(?!\/)/,"/"),n=`${r}${o}`,i=t.fetchImpl??fetch;return {async capture(s){let a={api_key:t.apiKey,event:s.event,distinct_id:s.distinctId,timestamp:s.timestamp,properties:s.properties},l=await i(n,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(a),keepalive:true,signal:AbortSignal.timeout(t.timeoutMs??3e3)});if(!l.ok)throw new u(`PostHog capture failed: ${l.status} ${l.statusText}`,l.status,await l.text().catch(()=>{}))}}}function K(t){let e=t.fetchImpl??fetch,r=t.transform??(o=>o);return {async capture(o){let n=await e(t.url,{method:"POST",headers:{"Content-Type":"application/json",...t.headers??{}},body:JSON.stringify(r(o)),keepalive:true,signal:AbortSignal.timeout(t.timeoutMs??3e3)});if(!n.ok)throw new u(`Webhook capture failed: ${n.status} ${n.statusText}`,n.status,await n.text().catch(()=>{}))}}}function F(t){return {capture:t}}
2
+ exports.AI_BOT_PATTERN=B;exports.CaptureTransportError=u;exports.HTTP_CLIENT_PATTERN=S;exports.HashSecretError=g;exports.agentIntent=P;exports.agentPolicy=V;exports.classifyAgent=v;exports.classifyRequest=p;exports.customAnalytics=F;exports.detectHeadless=b;exports.firstUserAgentProduct=M;exports.hashId=x;exports.isAiBot=f;exports.isHttpClient=m;exports.parseBotName=T;exports.posthogAnalytics=W;exports.randomSecret=w;exports.trackVisit=O;exports.webhookAnalytics=K;//# sourceMappingURL=index.cjs.map
901
3
  //# sourceMappingURL=index.cjs.map