@apideck/agent-analytics 0.14.0 → 0.16.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/README.md +144 -0
- package/dist/adapters/posthog.cjs +2 -2
- package/dist/adapters/posthog.cjs.map +1 -1
- package/dist/adapters/posthog.js +2 -2
- package/dist/adapters/posthog.js.map +1 -1
- package/dist/firewall.cjs +4 -0
- package/dist/firewall.cjs.map +1 -0
- package/dist/firewall.d.cts +115 -0
- package/dist/firewall.d.ts +115 -0
- package/dist/firewall.js +4 -0
- package/dist/firewall.js.map +1 -0
- package/dist/gateway-CYTQwayu.d.cts +317 -0
- package/dist/gateway-YJL5J0LR.d.ts +317 -0
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -76
- package/dist/index.d.ts +5 -76
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/pay.cjs +8 -0
- package/dist/pay.cjs.map +1 -0
- package/dist/pay.d.cts +112 -0
- package/dist/pay.d.ts +112 -0
- package/dist/pay.js +8 -0
- package/dist/pay.js.map +1 -0
- package/dist/policy-B3AakjOJ.d.cts +96 -0
- package/dist/policy-DMTBUe4F.d.ts +96 -0
- package/package.json +15 -2
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
import { b as AgentDecision, c as AgentPolicyOptions } from './policy-DMTBUe4F.js';
|
|
2
|
+
import { B as BotVerificationLike } from './types-Dw43eu7D.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Charge for training crawls. **EXPERIMENTAL.**
|
|
6
|
+
*
|
|
7
|
+
* The protocols this speaks are weeks old and moving. x402 and MPP are both
|
|
8
|
+
* live but their specs are unstable, MPP's settlement-confirmation header was
|
|
9
|
+
* not pinned publicly at the time of writing, and no agent in our production
|
|
10
|
+
* traffic has yet presented a payment credential. Expect this API to change
|
|
11
|
+
* without a major version while that settles — everything else in the package
|
|
12
|
+
* is stable, this is not.
|
|
13
|
+
*
|
|
14
|
+
* Today the industry's answer to bulk AI crawling is `Disallow` — over 2.5
|
|
15
|
+
* million sites block AI training in robots.txt. That leaves money on the
|
|
16
|
+
* table and depends on the crawler's goodwill to work at all.
|
|
17
|
+
*
|
|
18
|
+
* The alternative is to let them train and price it. That only works if you
|
|
19
|
+
* can tell training from retrieval, because they have opposite economics: a
|
|
20
|
+
* `GPTBot` fetch is corpus collection you get nothing back for, while a
|
|
21
|
+
* `ChatGPT-User` fetch is a person asking about you — charging for the second
|
|
22
|
+
* is charging for your own distribution. {@link agentPolicy} draws that line;
|
|
23
|
+
* this module turns a `'charge'` decision into the HTTP challenge.
|
|
24
|
+
*
|
|
25
|
+
* Two protocols, one status code. Both settle at the HTTP layer and both use
|
|
26
|
+
* 402, but the framing differs:
|
|
27
|
+
*
|
|
28
|
+
* x402 PAYMENT-REQUIRED: <base64 JSON> -> PAYMENT-SIGNATURE
|
|
29
|
+
* MPP WWW-Authenticate: Payment id="…" -> Authorization: Payment …
|
|
30
|
+
*
|
|
31
|
+
* MPP reuses standard HTTP authentication framing; x402 defines its own
|
|
32
|
+
* headers. They do not collide, so a single 402 can advertise both and let the
|
|
33
|
+
* agent pick — which is what {@link paymentRequired} does when given both.
|
|
34
|
+
*
|
|
35
|
+
* Scope: this emits the 402 and reads the client's payment header. It does not
|
|
36
|
+
* settle anything. Settlement belongs to an x402 facilitator or Stripe's MPP —
|
|
37
|
+
* a library that held money would inherit PCI scope and stop being something
|
|
38
|
+
* you can drop into middleware.
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* One way a client may pay. Field names follow x402's `PaymentRequirements`;
|
|
43
|
+
* values are yours — the library never invents an amount, network or asset.
|
|
44
|
+
*/
|
|
45
|
+
interface PaymentRequirements {
|
|
46
|
+
scheme: string;
|
|
47
|
+
network: string;
|
|
48
|
+
maxAmountRequired: string;
|
|
49
|
+
resource: string;
|
|
50
|
+
description?: string;
|
|
51
|
+
mimeType?: string;
|
|
52
|
+
payTo: string;
|
|
53
|
+
maxTimeoutSeconds?: number;
|
|
54
|
+
asset: string;
|
|
55
|
+
extra?: Record<string, unknown>;
|
|
56
|
+
}
|
|
57
|
+
/** Which settlement protocol a challenge speaks. */
|
|
58
|
+
type PaymentProtocol = 'x402' | 'mpp';
|
|
59
|
+
/** x402: base64 JSON in a `PAYMENT-REQUIRED` header. */
|
|
60
|
+
interface X402Challenge {
|
|
61
|
+
protocol: 'x402';
|
|
62
|
+
/** Accepted payment methods, in preference order. At least one. */
|
|
63
|
+
accepts: readonly PaymentRequirements[];
|
|
64
|
+
/** Protocol version. Defaults to 1. */
|
|
65
|
+
x402Version?: number;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* MPP: an RFC 9110 `WWW-Authenticate: Payment` challenge.
|
|
69
|
+
*
|
|
70
|
+
* Field values are yours. `request` carries the encoded challenge payload your
|
|
71
|
+
* MPP provider generates — the library does not construct or price it.
|
|
72
|
+
*/
|
|
73
|
+
interface MppChallenge {
|
|
74
|
+
protocol: 'mpp';
|
|
75
|
+
/** Challenge identifier. */
|
|
76
|
+
id: string;
|
|
77
|
+
/** Authentication realm. */
|
|
78
|
+
realm: string;
|
|
79
|
+
/** Payment method, e.g. `'tempo'`. */
|
|
80
|
+
method: string;
|
|
81
|
+
/** Transaction intent, e.g. `'charge'`. */
|
|
82
|
+
intent?: string;
|
|
83
|
+
/** Encoded challenge data from your provider. */
|
|
84
|
+
request?: string;
|
|
85
|
+
}
|
|
86
|
+
type PaymentChallenge = X402Challenge | MppChallenge;
|
|
87
|
+
interface PaymentChallengeOptions {
|
|
88
|
+
/**
|
|
89
|
+
* Challenges to advertise. Supplying both an x402 and an MPP challenge is
|
|
90
|
+
* valid and usually correct: they use non-colliding headers, so one 402 can
|
|
91
|
+
* offer both and the agent takes whichever it speaks.
|
|
92
|
+
*/
|
|
93
|
+
challenges: readonly PaymentChallenge[];
|
|
94
|
+
/**
|
|
95
|
+
* `Content-Signal` to send with the challenge. Defaults to
|
|
96
|
+
* `search=yes, ai-input=yes, ai-train=paid` — the whole point being that
|
|
97
|
+
* training is available rather than forbidden.
|
|
98
|
+
*/
|
|
99
|
+
contentSignal?: string;
|
|
100
|
+
/** Extra response headers. */
|
|
101
|
+
headers?: Record<string, string>;
|
|
102
|
+
/** Human-readable body. Agents read the header; people read logs. */
|
|
103
|
+
body?: string;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Build a 402 challenge.
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```ts
|
|
110
|
+
* const decision = agentPolicy(req, { onTraining: 'charge' })
|
|
111
|
+
* if (decision.action === 'charge') {
|
|
112
|
+
* return paymentRequired({
|
|
113
|
+
* challenges: [
|
|
114
|
+
* {
|
|
115
|
+
* protocol: 'x402',
|
|
116
|
+
* accepts: [{
|
|
117
|
+
* scheme: 'exact',
|
|
118
|
+
* network: 'base',
|
|
119
|
+
* maxAmountRequired: '1000', // your price, your units
|
|
120
|
+
* resource: req.url,
|
|
121
|
+
* payTo: process.env.WALLET!,
|
|
122
|
+
* asset: process.env.USDC!
|
|
123
|
+
* }]
|
|
124
|
+
* },
|
|
125
|
+
* { protocol: 'mpp', id: challengeId, realm: 'example.com', method: 'tempo', intent: 'charge' }
|
|
126
|
+
* ]
|
|
127
|
+
* })
|
|
128
|
+
* }
|
|
129
|
+
* ```
|
|
130
|
+
*/
|
|
131
|
+
declare function paymentRequired(opts: PaymentChallengeOptions): Response;
|
|
132
|
+
/** A payment credential the client sent back, and which protocol it speaks. */
|
|
133
|
+
interface SubmittedPayment {
|
|
134
|
+
protocol: PaymentProtocol;
|
|
135
|
+
/** Raw header value, for handing to a facilitator. */
|
|
136
|
+
value: string;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Read the client's payment credential, whichever protocol it used.
|
|
140
|
+
*
|
|
141
|
+
* x402 sends `PAYMENT-SIGNATURE`; MPP sends `Authorization: Payment …`. The
|
|
142
|
+
* `Payment` scheme check matters — a site behind normal auth will also have a
|
|
143
|
+
* Bearer or Basic `Authorization` header, and mistaking that for a payment
|
|
144
|
+
* would be a security-relevant confusion.
|
|
145
|
+
*/
|
|
146
|
+
declare function paymentPayload(req: Request): SubmittedPayment | null;
|
|
147
|
+
/**
|
|
148
|
+
* True when the client attached a payment credential — i.e. this is the retry
|
|
149
|
+
* after a 402, not a fresh unpaid request.
|
|
150
|
+
*
|
|
151
|
+
* Presence is not proof. Hand the value to your facilitator to verify and
|
|
152
|
+
* settle; only then serve the resource.
|
|
153
|
+
*/
|
|
154
|
+
declare function hasPaymentPayload(req: Request): boolean;
|
|
155
|
+
/**
|
|
156
|
+
* Attach a facilitator's settlement result to a successful response.
|
|
157
|
+
*
|
|
158
|
+
* x402 defines `PAYMENT-RESPONSE` for this. MPP's public spec did not pin a
|
|
159
|
+
* settlement-confirmation header at the time of writing, so pass `header` to
|
|
160
|
+
* name whatever your provider expects rather than have the library guess.
|
|
161
|
+
*/
|
|
162
|
+
declare function withSettlement(res: Response, settlement: unknown, opts?: {
|
|
163
|
+
header?: string;
|
|
164
|
+
}): Response;
|
|
165
|
+
/**
|
|
166
|
+
* Convenience: turn an {@link AgentDecision} straight into a response, or
|
|
167
|
+
* `null` when the request should simply be served.
|
|
168
|
+
*
|
|
169
|
+
* Returns 403 for `'block'`, a 402 challenge for `'charge'`, and `null` for
|
|
170
|
+
* `'allow'` and `'meter'` — metering is an accounting concern, not a gate, so
|
|
171
|
+
* the request still gets served while `trackVisit` records it.
|
|
172
|
+
*/
|
|
173
|
+
declare function respondToDecision(decision: AgentDecision, opts: PaymentChallengeOptions): Response | null;
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* The paid-access gate: policy decides *whether* to charge, a gateway decides
|
|
177
|
+
* *how*. **EXPERIMENTAL** — see `payments.ts`. The classification and policy
|
|
178
|
+
* layers underneath are stable; the payment surface is not.
|
|
179
|
+
*
|
|
180
|
+
* The split matters. We own classification — telling a training crawl from a
|
|
181
|
+
* retrieval fetch, which is the part nobody else does and the part that makes
|
|
182
|
+
* charging sane. Settlement is somebody else's job: Stripe's MPP SDK, an x402
|
|
183
|
+
* facilitator, whatever comes next. A library that held money would inherit PCI
|
|
184
|
+
* scope and stop being something you drop into middleware.
|
|
185
|
+
*
|
|
186
|
+
* So gateways are injected, exactly like analytics adapters, and this module
|
|
187
|
+
* takes no dependency on Stripe or any chain.
|
|
188
|
+
*/
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Outcome of handing a request to a payment gateway.
|
|
192
|
+
*
|
|
193
|
+
* - `challenge` — respond with this. The client has not paid.
|
|
194
|
+
* - `paid` — settled; serve the resource. `receipt` decorates the response with
|
|
195
|
+
* whatever proof the protocol expects.
|
|
196
|
+
*/
|
|
197
|
+
type GatewayResult = {
|
|
198
|
+
status: 'challenge';
|
|
199
|
+
response: Response;
|
|
200
|
+
} | {
|
|
201
|
+
status: 'paid';
|
|
202
|
+
receipt?: (res: Response) => Response;
|
|
203
|
+
};
|
|
204
|
+
interface PaymentGateway {
|
|
205
|
+
handle(req: Request): Promise<GatewayResult>;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Wrap Stripe's MPP SDK.
|
|
209
|
+
*
|
|
210
|
+
* `Mppx.compose(...)` returns a handler that either yields a 402 with a
|
|
211
|
+
* `.challenge` response, or a settled result with `.withReceipt(res)`. This
|
|
212
|
+
* adapts that shape without importing it — pass the composed handler in.
|
|
213
|
+
*
|
|
214
|
+
* @example
|
|
215
|
+
* ```ts
|
|
216
|
+
* const mppx = Mppx.create({ methods: [...], secretKey })
|
|
217
|
+
* const handler = Mppx.compose(
|
|
218
|
+
* mppx.tempo.charge({ amount: '0.01', recipient }),
|
|
219
|
+
* mppx.stripe.charge({ amount: '0.50', currency: 'usd' })
|
|
220
|
+
* )
|
|
221
|
+
* const gateway = mppxGateway(handler)
|
|
222
|
+
* ```
|
|
223
|
+
*/
|
|
224
|
+
declare function mppxGateway(handler: (req: Request) => Promise<MppxResponse> | MppxResponse): PaymentGateway;
|
|
225
|
+
/** The subset of Stripe's MPP response we rely on. Structural, not imported. */
|
|
226
|
+
interface MppxResponse {
|
|
227
|
+
status: number;
|
|
228
|
+
challenge: Response;
|
|
229
|
+
withReceipt?: (res: Response) => Response;
|
|
230
|
+
}
|
|
231
|
+
interface X402GatewayOptions extends PaymentChallengeOptions {
|
|
232
|
+
/**
|
|
233
|
+
* Verify and settle a `PAYMENT-SIGNATURE` payload with your facilitator.
|
|
234
|
+
* Resolve truthy to serve the resource, falsy to re-challenge.
|
|
235
|
+
*/
|
|
236
|
+
settle: (payload: string, req: Request) => Promise<boolean> | boolean;
|
|
237
|
+
/** Attach the facilitator's settlement result to the served response. */
|
|
238
|
+
receipt?: (res: Response) => Response;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Gateway using this library's own challenge builder plus a facilitator you
|
|
242
|
+
* supply. For x402, or for MPP if you are not using Stripe's SDK.
|
|
243
|
+
*/
|
|
244
|
+
declare function x402Gateway(opts: X402GatewayOptions): PaymentGateway;
|
|
245
|
+
/** One unit of billable agent traffic. */
|
|
246
|
+
interface MeterRecord {
|
|
247
|
+
decision: AgentDecision;
|
|
248
|
+
/** Units consumed. One request is one unit unless you price by bytes or tokens. */
|
|
249
|
+
units: number;
|
|
250
|
+
path: string;
|
|
251
|
+
method: string;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Where billable usage goes.
|
|
255
|
+
*
|
|
256
|
+
* Metering is the model to ship first: it needs no crawler cooperation, works
|
|
257
|
+
* today, and produces the number you would negotiate a licence with. Charging
|
|
258
|
+
* per request is what the protocols define but not what a training sweep can
|
|
259
|
+
* actually do — no crawler in the wild retries a 402.
|
|
260
|
+
*/
|
|
261
|
+
interface Meter {
|
|
262
|
+
record(entry: MeterRecord): Promise<void> | void;
|
|
263
|
+
}
|
|
264
|
+
interface PaymentGateOptions extends Omit<AgentPolicyOptions, 'verify'> {
|
|
265
|
+
gateway: PaymentGateway;
|
|
266
|
+
/**
|
|
267
|
+
* Sink for billable traffic. Called for every `'meter'` decision — serve the
|
|
268
|
+
* request, count it, bill out of band.
|
|
269
|
+
*
|
|
270
|
+
* Errors are swallowed: a metering failure must not turn into a failed
|
|
271
|
+
* response, for the same reason analytics failures do not.
|
|
272
|
+
*/
|
|
273
|
+
meter?: Meter;
|
|
274
|
+
/**
|
|
275
|
+
* Identity verifier, sync or async. Unlike {@link agentPolicy}'s option this
|
|
276
|
+
* accepts a promise, because `paymentGate` is already async and can await it.
|
|
277
|
+
* That matters: `combinedVerifier()` and `webBotAuthVerifier()` are async by
|
|
278
|
+
* necessity — Web Bot Auth fetches the signer's key directory — so without
|
|
279
|
+
* this they could not be used with policy or payments at all.
|
|
280
|
+
*/
|
|
281
|
+
verify?: (req: Request) => BotVerificationLike | Promise<BotVerificationLike>;
|
|
282
|
+
/**
|
|
283
|
+
* Called for every decision, paid or not — wire it to your metering so
|
|
284
|
+
* `'meter'` traffic is actually counted rather than merely allowed.
|
|
285
|
+
*/
|
|
286
|
+
onDecision?: (decision: AgentDecision) => void;
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Full gate: classify, decide, and either let the request through or return the
|
|
290
|
+
* response it should get instead.
|
|
291
|
+
*
|
|
292
|
+
* Returns `null` when the request should be served normally. That covers
|
|
293
|
+
* `'allow'`, `'meter'` (accounting, not a gate) and any request that has already
|
|
294
|
+
* paid — in which case `receipt` is handed back so you can decorate the response
|
|
295
|
+
* you were going to send anyway.
|
|
296
|
+
*
|
|
297
|
+
* @example
|
|
298
|
+
* ```ts
|
|
299
|
+
* const gate = await paymentGate(req, {
|
|
300
|
+
* onTraining: 'charge',
|
|
301
|
+
* verify: combinedVerifier(),
|
|
302
|
+
* gateway: mppxGateway(handler),
|
|
303
|
+
* onDecision: (d) => void trackVisit(req, { analytics, properties: { action: d.action } })
|
|
304
|
+
* })
|
|
305
|
+
* if (gate.response) return gate.response
|
|
306
|
+
* return gate.decorate(await serve(req))
|
|
307
|
+
* ```
|
|
308
|
+
*/
|
|
309
|
+
declare function paymentGate(req: Request, opts: PaymentGateOptions): Promise<{
|
|
310
|
+
decision: AgentDecision;
|
|
311
|
+
/** Respond with this instead of serving, when set. */
|
|
312
|
+
response: Response | null;
|
|
313
|
+
/** Wrap the response you were going to send. Identity when nothing to add. */
|
|
314
|
+
decorate: (res: Response) => Response;
|
|
315
|
+
}>;
|
|
316
|
+
|
|
317
|
+
export { type GatewayResult as G, type Meter as M, type PaymentChallenge as P, type SubmittedPayment as S, type X402Challenge as X, type MeterRecord as a, type MppChallenge as b, type MppxResponse as c, type PaymentChallengeOptions as d, type PaymentGateOptions as e, type PaymentGateway as f, type PaymentProtocol as g, type PaymentRequirements as h, type X402GatewayOptions as i, hasPaymentPayload as j, paymentPayload as k, paymentRequired as l, mppxGateway as m, paymentGate as p, respondToDecision as r, withSettlement as w, x402Gateway as x };
|
package/dist/index.cjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
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?await 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=
|
|
1
|
+
'use strict';var S=/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,T=/axios\/|curl\/|(?:^|[\s(])got(?:\/|[\s(])|\bcolly\b|Electron\/|node-fetch\/|python-requests\/|Go-http-client\/|okhttp\/|aiohttp\/|Deno\//i;function h(t){return t?S.test(t):false}function p(t){return t?T.test(t):false}function v(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 A(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 P(t){let e=v(t),r=h(t),o=p(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 m(t){let e=t.headers.get("user-agent")||"",r=P(e),o=A(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 y=class extends Error{constructor(e){super(e),this.name="HashSecretError";}};function x(){let t=globalThis.crypto;if(!t?.subtle)throw new y("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 O(t){let e=E.get(t);return e||(e=x().importKey("raw",new TextEncoder().encode(t),{name:"HMAC",hash:"SHA-256"},false,["sign"]),E.set(t,e)),e}async function w(t,e){if(typeof e!="string"||e.length===0)throw new y("hashId requires a non-empty secret");let r=await x().sign("HMAC",await O(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 k(){let t=new Uint8Array(32);x(),globalThis.crypto.getRandomValues(t);let e="";for(let r of t)e+=r.toString(16).padStart(2,"0");return e}var C,I=false;function N(t){if(t)return t;let e=typeof process<"u"?process.env?.AGENT_ANALYTICS_ID_SECRET:void 0;return e||(C||(C=k(),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."))),C)}async function z(t,e){let r=t.headers.get("user-agent")||"",o=e.onlyBots??false,n=e.skipBrowsers??false;if(!(o&&!h(r))&&!(n&&!h(r)&&!p(r)&&!A(t).likely))try{let i="/",s="";try{let B=new URL(t.url);i=B.pathname,s=B.origin;}catch{i=t.url||"/";}let c=e.origin??s,f=(t.headers.get("x-forwarded-for")||"").split(",")[0]?.trim()??"",l=t.headers.get("referer"),b=e.captureCountry&&(t.headers.get("x-vercel-ip-country")||t.headers.get("cf-ipcountry")||t.headers.get("x-country-code"))||null,_=e.captureGeo?L(t):null,u=m(t),g=e.verify?await e.verify(t):null,D=u.kind==="headless-likely"||u.kind==="browser",G=await w(`${f}:${r}`,N(e.idSecret)),H={event:e.eventName??"agent_visit",distinctId:G,timestamp:new Date().toISOString(),properties:{...e.properties,$process_person_profile:!1,$current_url:c?`${c}${i}`:i,path:i,method:t.method,...e.captureCountry?{country_code:b}:{},..._??{},...e.captureIp?{client_ip:f||null}:{},user_agent:r,is_ai_bot:u.isAiBot,bot_name:u.label,ua_category:u.kind,coding_agent_hint:u.codingAgentHint,...D?{headless_score:u.headless?.score??0,headless_likely:u.headless?.likely??!1}:{},...g?{bot_verified:g.verified,bot_verification:g.verdict,...g.reason?{bot_verification_reason:g.reason}:{}}:{},referer:l,source:e.source??null}};await e.analytics.capture(H);}catch(i){e.onError?.(i instanceof Error?i:new Error(String(i)));}}function L(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 d=class extends Error{status;body;constructor(e,r,o){super(e),this.name="CaptureTransportError",this.status=r,this.body=o;}};var U=/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 R(t){let e=t??"";return e?U.test(e)?"retrieval":$.test(e)?"training":j.test(e)?"search":p(e)?"tooling":"unknown":"unknown"}function V(t,e={}){let r=t.headers.get("user-agent")||"",n=m(t).label,i=R(r);if(e.allowList?.some(b=>b===n||r.toLowerCase().includes(b.toLowerCase())))return {action:"allow",intent:i,label:n,reason:"on allowList"};let c=e.verification??(e.verify?e.verify(t):void 0),a;return c&&(a=c.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 c=s.properties.user_agent,a=s.properties.client_ip,f={api_key:t.apiKey,event:s.event,distinct_id:s.distinctId,timestamp:s.timestamp,properties:{...s.properties,...typeof c=="string"&&c?{$raw_user_agent:c}:{},...typeof a=="string"&&a?{$ip:a}:{}}},l=await i(n,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(f),keepalive:true,signal:AbortSignal.timeout(t.timeoutMs??3e3)});if(!l.ok)throw new d(`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 d(`Webhook capture failed: ${n.status} ${n.statusText}`,n.status,await n.text().catch(()=>{}))}}}function F(t){return {capture:t}}
|
|
2
|
+
exports.AI_BOT_PATTERN=S;exports.CaptureTransportError=d;exports.HTTP_CLIENT_PATTERN=T;exports.HashSecretError=y;exports.agentIntent=R;exports.agentPolicy=V;exports.classifyAgent=P;exports.classifyRequest=m;exports.customAnalytics=F;exports.detectHeadless=A;exports.firstUserAgentProduct=M;exports.hashId=w;exports.isAiBot=h;exports.isHttpClient=p;exports.parseBotName=v;exports.posthogAnalytics=W;exports.randomSecret=k;exports.trackVisit=z;exports.webhookAnalytics=K;//# sourceMappingURL=index.cjs.map
|
|
3
3
|
//# sourceMappingURL=index.cjs.map
|