@apideck/agent-analytics 0.15.0 → 0.17.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 +62 -4
- package/dist/firewall.cjs +4 -0
- package/dist/firewall.cjs.map +1 -0
- package/dist/firewall.d.cts +145 -0
- package/dist/firewall.d.ts +145 -0
- package/dist/firewall.js +4 -0
- package/dist/firewall.js.map +1 -0
- package/dist/gateway-BuF0-FG_.d.ts +317 -0
- package/dist/gateway-f52pV_qP.d.cts +317 -0
- package/dist/index.cjs +2 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -625
- package/dist/index.d.ts +5 -625
- package/dist/index.js +2 -10
- 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-ByqnGK1b.d.ts +105 -0
- package/dist/policy-CEJ-j-Lz.d.cts +105 -0
- package/package.json +13 -2
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { B as BotVerificationLike } from './types-Dw43eu7D.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* What to do with an agent request.
|
|
5
|
+
*
|
|
6
|
+
* - `'allow'` — serve it, free. Humans, search crawlers, and the retrieval
|
|
7
|
+
* agents you *want* reading your site.
|
|
8
|
+
* - `'meter'` — serve it, but count it as billable. Bulk corpus collection.
|
|
9
|
+
* - `'charge'` — don't serve it until it pays (HTTP 402).
|
|
10
|
+
* - `'block'` — refuse. Failed identity verification, mostly.
|
|
11
|
+
*/
|
|
12
|
+
type AgentAction = 'allow' | 'meter' | 'charge' | 'block';
|
|
13
|
+
/**
|
|
14
|
+
* Why an agent fetched the page. This is the distinction the whole module
|
|
15
|
+
* exists for, and no other signal on the request carries it.
|
|
16
|
+
*
|
|
17
|
+
* - `'retrieval'` — a person asked a question and the assistant went to read
|
|
18
|
+
* the page for them. This is *demand*: the agent is a distribution channel,
|
|
19
|
+
* and charging for it is charging for your own marketing.
|
|
20
|
+
* - `'training'` — bulk corpus collection for model training. You get nothing
|
|
21
|
+
* back per fetch, which is where a price makes sense.
|
|
22
|
+
* - `'search'` — index crawlers, traditional and AI-native. Blocking these
|
|
23
|
+
* costs you organic traffic or citations in an assistant's answer.
|
|
24
|
+
* - `'preview'` — link unfurlers. Someone pasted your URL into Slack, iMessage
|
|
25
|
+
* or a tweet and the platform fetched it to render a card. No model involved,
|
|
26
|
+
* but blocking it means your links look broken wherever they get shared.
|
|
27
|
+
* - `'tooling'` — coding agents and HTTP clients. Usually developers using
|
|
28
|
+
* your docs; treat like retrieval unless you see abuse.
|
|
29
|
+
* - `'unknown'` — everything else, including real browsers.
|
|
30
|
+
*/
|
|
31
|
+
type AgentIntent = 'retrieval' | 'training' | 'search' | 'preview' | 'tooling' | 'unknown';
|
|
32
|
+
interface AgentDecision {
|
|
33
|
+
action: AgentAction;
|
|
34
|
+
intent: AgentIntent;
|
|
35
|
+
/** Vendor label, same string `parseBotName` returns. */
|
|
36
|
+
label: string;
|
|
37
|
+
/** Identity verdict, when a verifier was supplied. */
|
|
38
|
+
verification?: string;
|
|
39
|
+
/** Short human-readable justification — log it, don't parse it. */
|
|
40
|
+
reason: string;
|
|
41
|
+
}
|
|
42
|
+
interface AgentPolicyOptions {
|
|
43
|
+
/**
|
|
44
|
+
* Identity verifier. Import `verifyRequest` from
|
|
45
|
+
* `@apideck/agent-analytics/verify` and pass it here to have a `spoofed`
|
|
46
|
+
* verdict produce `'block'`.
|
|
47
|
+
*
|
|
48
|
+
* Injected rather than imported so the published IP range tables only reach
|
|
49
|
+
* bundles that use them. Only meaningful when your edge controls
|
|
50
|
+
* `x-forwarded-for`: behind a proxy that forwards a client-supplied header,
|
|
51
|
+
* an attacker picks their own verdict.
|
|
52
|
+
*/
|
|
53
|
+
verify?: (req: Request) => BotVerificationLike;
|
|
54
|
+
/**
|
|
55
|
+
* A verification already computed elsewhere. Use this when your verifier is
|
|
56
|
+
* async — {@link verifyWebBotAuth} fetches a key directory, so the natural
|
|
57
|
+
* verifier from `@apideck/agent-analytics/verify` returns a promise and
|
|
58
|
+
* cannot be passed to `verify` on this synchronous function.
|
|
59
|
+
*
|
|
60
|
+
* {@link paymentGate} does this for you: it awaits the verifier and forwards
|
|
61
|
+
* the result here.
|
|
62
|
+
*/
|
|
63
|
+
verification?: BotVerificationLike;
|
|
64
|
+
/** What to do with bulk training crawlers. Defaults to `'meter'`. */
|
|
65
|
+
onTraining?: AgentAction;
|
|
66
|
+
/** What to do with retrieval agents. Defaults to `'allow'` — see AgentIntent. */
|
|
67
|
+
onRetrieval?: AgentAction;
|
|
68
|
+
/** What to do with search indexers. Defaults to `'allow'`. */
|
|
69
|
+
onSearch?: AgentAction;
|
|
70
|
+
/**
|
|
71
|
+
* What to do with link unfurlers. Defaults to `'allow'` — gating these does
|
|
72
|
+
* not earn you anything, it just makes your links render as bare URLs.
|
|
73
|
+
*/
|
|
74
|
+
onPreview?: AgentAction;
|
|
75
|
+
/** What to do with coding agents and HTTP clients. Defaults to `'allow'`. */
|
|
76
|
+
onTooling?: AgentAction;
|
|
77
|
+
/** Vendor labels or UA substrings always allowed, whatever the intent. */
|
|
78
|
+
allowList?: readonly string[];
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Classify why an agent is here, from its user agent alone.
|
|
82
|
+
*
|
|
83
|
+
* This must return exactly what {@link agentPolicy} reports for the same UA.
|
|
84
|
+
* It previously did not: the `tooling` promotion for HTTP-library UAs lived
|
|
85
|
+
* only inside `agentPolicy`, so `agentIntent('curl/8.4.0')` said `'unknown'`
|
|
86
|
+
* while the policy said `'tooling'` — two exported functions disagreeing on
|
|
87
|
+
* every HTTP client, with no way for a caller to know which was right. The
|
|
88
|
+
* invariant is pinned by a test.
|
|
89
|
+
*/
|
|
90
|
+
declare function agentIntent(userAgent: string | null | undefined): AgentIntent;
|
|
91
|
+
/**
|
|
92
|
+
* Decide what to do with a request. Pure classification plus policy — no
|
|
93
|
+
* payment rails, no network calls, nothing to configure beyond the four
|
|
94
|
+
* intent knobs.
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```ts
|
|
98
|
+
* const decision = agentPolicy(req, { verify: true, onTraining: 'charge' })
|
|
99
|
+
* if (decision.action === 'block') return new Response(null, { status: 403 })
|
|
100
|
+
* if (decision.action === 'charge') return paymentRequired(decision)
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
declare function agentPolicy(req: Request, opts?: AgentPolicyOptions): AgentDecision;
|
|
104
|
+
|
|
105
|
+
export { type AgentIntent as A, type AgentAction as a, type AgentDecision as b, type AgentPolicyOptions as c, agentIntent as d, agentPolicy as e };
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { B as BotVerificationLike } from './types-Dw43eu7D.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* What to do with an agent request.
|
|
5
|
+
*
|
|
6
|
+
* - `'allow'` — serve it, free. Humans, search crawlers, and the retrieval
|
|
7
|
+
* agents you *want* reading your site.
|
|
8
|
+
* - `'meter'` — serve it, but count it as billable. Bulk corpus collection.
|
|
9
|
+
* - `'charge'` — don't serve it until it pays (HTTP 402).
|
|
10
|
+
* - `'block'` — refuse. Failed identity verification, mostly.
|
|
11
|
+
*/
|
|
12
|
+
type AgentAction = 'allow' | 'meter' | 'charge' | 'block';
|
|
13
|
+
/**
|
|
14
|
+
* Why an agent fetched the page. This is the distinction the whole module
|
|
15
|
+
* exists for, and no other signal on the request carries it.
|
|
16
|
+
*
|
|
17
|
+
* - `'retrieval'` — a person asked a question and the assistant went to read
|
|
18
|
+
* the page for them. This is *demand*: the agent is a distribution channel,
|
|
19
|
+
* and charging for it is charging for your own marketing.
|
|
20
|
+
* - `'training'` — bulk corpus collection for model training. You get nothing
|
|
21
|
+
* back per fetch, which is where a price makes sense.
|
|
22
|
+
* - `'search'` — index crawlers, traditional and AI-native. Blocking these
|
|
23
|
+
* costs you organic traffic or citations in an assistant's answer.
|
|
24
|
+
* - `'preview'` — link unfurlers. Someone pasted your URL into Slack, iMessage
|
|
25
|
+
* or a tweet and the platform fetched it to render a card. No model involved,
|
|
26
|
+
* but blocking it means your links look broken wherever they get shared.
|
|
27
|
+
* - `'tooling'` — coding agents and HTTP clients. Usually developers using
|
|
28
|
+
* your docs; treat like retrieval unless you see abuse.
|
|
29
|
+
* - `'unknown'` — everything else, including real browsers.
|
|
30
|
+
*/
|
|
31
|
+
type AgentIntent = 'retrieval' | 'training' | 'search' | 'preview' | 'tooling' | 'unknown';
|
|
32
|
+
interface AgentDecision {
|
|
33
|
+
action: AgentAction;
|
|
34
|
+
intent: AgentIntent;
|
|
35
|
+
/** Vendor label, same string `parseBotName` returns. */
|
|
36
|
+
label: string;
|
|
37
|
+
/** Identity verdict, when a verifier was supplied. */
|
|
38
|
+
verification?: string;
|
|
39
|
+
/** Short human-readable justification — log it, don't parse it. */
|
|
40
|
+
reason: string;
|
|
41
|
+
}
|
|
42
|
+
interface AgentPolicyOptions {
|
|
43
|
+
/**
|
|
44
|
+
* Identity verifier. Import `verifyRequest` from
|
|
45
|
+
* `@apideck/agent-analytics/verify` and pass it here to have a `spoofed`
|
|
46
|
+
* verdict produce `'block'`.
|
|
47
|
+
*
|
|
48
|
+
* Injected rather than imported so the published IP range tables only reach
|
|
49
|
+
* bundles that use them. Only meaningful when your edge controls
|
|
50
|
+
* `x-forwarded-for`: behind a proxy that forwards a client-supplied header,
|
|
51
|
+
* an attacker picks their own verdict.
|
|
52
|
+
*/
|
|
53
|
+
verify?: (req: Request) => BotVerificationLike;
|
|
54
|
+
/**
|
|
55
|
+
* A verification already computed elsewhere. Use this when your verifier is
|
|
56
|
+
* async — {@link verifyWebBotAuth} fetches a key directory, so the natural
|
|
57
|
+
* verifier from `@apideck/agent-analytics/verify` returns a promise and
|
|
58
|
+
* cannot be passed to `verify` on this synchronous function.
|
|
59
|
+
*
|
|
60
|
+
* {@link paymentGate} does this for you: it awaits the verifier and forwards
|
|
61
|
+
* the result here.
|
|
62
|
+
*/
|
|
63
|
+
verification?: BotVerificationLike;
|
|
64
|
+
/** What to do with bulk training crawlers. Defaults to `'meter'`. */
|
|
65
|
+
onTraining?: AgentAction;
|
|
66
|
+
/** What to do with retrieval agents. Defaults to `'allow'` — see AgentIntent. */
|
|
67
|
+
onRetrieval?: AgentAction;
|
|
68
|
+
/** What to do with search indexers. Defaults to `'allow'`. */
|
|
69
|
+
onSearch?: AgentAction;
|
|
70
|
+
/**
|
|
71
|
+
* What to do with link unfurlers. Defaults to `'allow'` — gating these does
|
|
72
|
+
* not earn you anything, it just makes your links render as bare URLs.
|
|
73
|
+
*/
|
|
74
|
+
onPreview?: AgentAction;
|
|
75
|
+
/** What to do with coding agents and HTTP clients. Defaults to `'allow'`. */
|
|
76
|
+
onTooling?: AgentAction;
|
|
77
|
+
/** Vendor labels or UA substrings always allowed, whatever the intent. */
|
|
78
|
+
allowList?: readonly string[];
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Classify why an agent is here, from its user agent alone.
|
|
82
|
+
*
|
|
83
|
+
* This must return exactly what {@link agentPolicy} reports for the same UA.
|
|
84
|
+
* It previously did not: the `tooling` promotion for HTTP-library UAs lived
|
|
85
|
+
* only inside `agentPolicy`, so `agentIntent('curl/8.4.0')` said `'unknown'`
|
|
86
|
+
* while the policy said `'tooling'` — two exported functions disagreeing on
|
|
87
|
+
* every HTTP client, with no way for a caller to know which was right. The
|
|
88
|
+
* invariant is pinned by a test.
|
|
89
|
+
*/
|
|
90
|
+
declare function agentIntent(userAgent: string | null | undefined): AgentIntent;
|
|
91
|
+
/**
|
|
92
|
+
* Decide what to do with a request. Pure classification plus policy — no
|
|
93
|
+
* payment rails, no network calls, nothing to configure beyond the four
|
|
94
|
+
* intent knobs.
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```ts
|
|
98
|
+
* const decision = agentPolicy(req, { verify: true, onTraining: 'charge' })
|
|
99
|
+
* if (decision.action === 'block') return new Response(null, { status: 403 })
|
|
100
|
+
* if (decision.action === 'charge') return paymentRequired(decision)
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
declare function agentPolicy(req: Request, opts?: AgentPolicyOptions): AgentDecision;
|
|
104
|
+
|
|
105
|
+
export { type AgentIntent as A, type AgentAction as a, type AgentDecision as b, type AgentPolicyOptions as c, agentIntent as d, agentPolicy as e };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apideck/agent-analytics",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0",
|
|
4
4
|
"description": "Track AI agent and bot traffic to your Next.js / Vercel app — PostHog, webhooks, or any custom analytics backend. Detects Claude, ChatGPT, Perplexity, Google-Extended, and more.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -43,6 +43,16 @@
|
|
|
43
43
|
"import": "./dist/verify.js",
|
|
44
44
|
"require": "./dist/verify.cjs"
|
|
45
45
|
},
|
|
46
|
+
"./payments": {
|
|
47
|
+
"types": "./dist/pay.d.ts",
|
|
48
|
+
"import": "./dist/pay.js",
|
|
49
|
+
"require": "./dist/pay.cjs"
|
|
50
|
+
},
|
|
51
|
+
"./firewall": {
|
|
52
|
+
"types": "./dist/firewall.d.ts",
|
|
53
|
+
"import": "./dist/firewall.js",
|
|
54
|
+
"require": "./dist/firewall.cjs"
|
|
55
|
+
},
|
|
46
56
|
"./posthog": {
|
|
47
57
|
"types": "./dist/adapters/posthog.d.ts",
|
|
48
58
|
"import": "./dist/adapters/posthog.js",
|
|
@@ -70,7 +80,8 @@
|
|
|
70
80
|
"test:integration": "vitest run test/integration.test.ts",
|
|
71
81
|
"test:watch": "vitest",
|
|
72
82
|
"typecheck": "tsc --noEmit",
|
|
73
|
-
"prepublishOnly": "npm run build"
|
|
83
|
+
"prepublishOnly": "npm run build",
|
|
84
|
+
"size": "node scripts/check-size.mjs"
|
|
74
85
|
},
|
|
75
86
|
"devDependencies": {
|
|
76
87
|
"@types/node": "^20.14.0",
|