@apideck/agent-analytics 0.15.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 +35 -3
- 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 -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-B3AakjOJ.d.cts +96 -0
- package/dist/policy-DMTBUe4F.d.ts +96 -0
- package/package.json +13 -2
|
@@ -0,0 +1,96 @@
|
|
|
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'` — classic index crawlers. Blocking these costs you SEO.
|
|
23
|
+
* - `'tooling'` — coding agents and HTTP clients. Usually developers using
|
|
24
|
+
* your docs; treat like retrieval unless you see abuse.
|
|
25
|
+
* - `'unknown'` — everything else, including real browsers.
|
|
26
|
+
*/
|
|
27
|
+
type AgentIntent = 'retrieval' | 'training' | 'search' | 'tooling' | 'unknown';
|
|
28
|
+
interface AgentDecision {
|
|
29
|
+
action: AgentAction;
|
|
30
|
+
intent: AgentIntent;
|
|
31
|
+
/** Vendor label, same string `parseBotName` returns. */
|
|
32
|
+
label: string;
|
|
33
|
+
/** Identity verdict, when a verifier was supplied. */
|
|
34
|
+
verification?: string;
|
|
35
|
+
/** Short human-readable justification — log it, don't parse it. */
|
|
36
|
+
reason: string;
|
|
37
|
+
}
|
|
38
|
+
interface AgentPolicyOptions {
|
|
39
|
+
/**
|
|
40
|
+
* Identity verifier. Import `verifyRequest` from
|
|
41
|
+
* `@apideck/agent-analytics/verify` and pass it here to have a `spoofed`
|
|
42
|
+
* verdict produce `'block'`.
|
|
43
|
+
*
|
|
44
|
+
* Injected rather than imported so the published IP range tables only reach
|
|
45
|
+
* bundles that use them. Only meaningful when your edge controls
|
|
46
|
+
* `x-forwarded-for`: behind a proxy that forwards a client-supplied header,
|
|
47
|
+
* an attacker picks their own verdict.
|
|
48
|
+
*/
|
|
49
|
+
verify?: (req: Request) => BotVerificationLike;
|
|
50
|
+
/**
|
|
51
|
+
* A verification already computed elsewhere. Use this when your verifier is
|
|
52
|
+
* async — {@link verifyWebBotAuth} fetches a key directory, so the natural
|
|
53
|
+
* verifier from `@apideck/agent-analytics/verify` returns a promise and
|
|
54
|
+
* cannot be passed to `verify` on this synchronous function.
|
|
55
|
+
*
|
|
56
|
+
* {@link paymentGate} does this for you: it awaits the verifier and forwards
|
|
57
|
+
* the result here.
|
|
58
|
+
*/
|
|
59
|
+
verification?: BotVerificationLike;
|
|
60
|
+
/** What to do with bulk training crawlers. Defaults to `'meter'`. */
|
|
61
|
+
onTraining?: AgentAction;
|
|
62
|
+
/** What to do with retrieval agents. Defaults to `'allow'` — see AgentIntent. */
|
|
63
|
+
onRetrieval?: AgentAction;
|
|
64
|
+
/** What to do with search indexers. Defaults to `'allow'`. */
|
|
65
|
+
onSearch?: AgentAction;
|
|
66
|
+
/** What to do with coding agents and HTTP clients. Defaults to `'allow'`. */
|
|
67
|
+
onTooling?: AgentAction;
|
|
68
|
+
/** Vendor labels or UA substrings always allowed, whatever the intent. */
|
|
69
|
+
allowList?: readonly string[];
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Classify why an agent is here, from its user agent alone.
|
|
73
|
+
*
|
|
74
|
+
* This must return exactly what {@link agentPolicy} reports for the same UA.
|
|
75
|
+
* It previously did not: the `tooling` promotion for HTTP-library UAs lived
|
|
76
|
+
* only inside `agentPolicy`, so `agentIntent('curl/8.4.0')` said `'unknown'`
|
|
77
|
+
* while the policy said `'tooling'` — two exported functions disagreeing on
|
|
78
|
+
* every HTTP client, with no way for a caller to know which was right. The
|
|
79
|
+
* invariant is pinned by a test.
|
|
80
|
+
*/
|
|
81
|
+
declare function agentIntent(userAgent: string | null | undefined): AgentIntent;
|
|
82
|
+
/**
|
|
83
|
+
* Decide what to do with a request. Pure classification plus policy — no
|
|
84
|
+
* payment rails, no network calls, nothing to configure beyond the four
|
|
85
|
+
* intent knobs.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```ts
|
|
89
|
+
* const decision = agentPolicy(req, { verify: true, onTraining: 'charge' })
|
|
90
|
+
* if (decision.action === 'block') return new Response(null, { status: 403 })
|
|
91
|
+
* if (decision.action === 'charge') return paymentRequired(decision)
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
declare function agentPolicy(req: Request, opts?: AgentPolicyOptions): AgentDecision;
|
|
95
|
+
|
|
96
|
+
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,96 @@
|
|
|
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'` — classic index crawlers. Blocking these costs you SEO.
|
|
23
|
+
* - `'tooling'` — coding agents and HTTP clients. Usually developers using
|
|
24
|
+
* your docs; treat like retrieval unless you see abuse.
|
|
25
|
+
* - `'unknown'` — everything else, including real browsers.
|
|
26
|
+
*/
|
|
27
|
+
type AgentIntent = 'retrieval' | 'training' | 'search' | 'tooling' | 'unknown';
|
|
28
|
+
interface AgentDecision {
|
|
29
|
+
action: AgentAction;
|
|
30
|
+
intent: AgentIntent;
|
|
31
|
+
/** Vendor label, same string `parseBotName` returns. */
|
|
32
|
+
label: string;
|
|
33
|
+
/** Identity verdict, when a verifier was supplied. */
|
|
34
|
+
verification?: string;
|
|
35
|
+
/** Short human-readable justification — log it, don't parse it. */
|
|
36
|
+
reason: string;
|
|
37
|
+
}
|
|
38
|
+
interface AgentPolicyOptions {
|
|
39
|
+
/**
|
|
40
|
+
* Identity verifier. Import `verifyRequest` from
|
|
41
|
+
* `@apideck/agent-analytics/verify` and pass it here to have a `spoofed`
|
|
42
|
+
* verdict produce `'block'`.
|
|
43
|
+
*
|
|
44
|
+
* Injected rather than imported so the published IP range tables only reach
|
|
45
|
+
* bundles that use them. Only meaningful when your edge controls
|
|
46
|
+
* `x-forwarded-for`: behind a proxy that forwards a client-supplied header,
|
|
47
|
+
* an attacker picks their own verdict.
|
|
48
|
+
*/
|
|
49
|
+
verify?: (req: Request) => BotVerificationLike;
|
|
50
|
+
/**
|
|
51
|
+
* A verification already computed elsewhere. Use this when your verifier is
|
|
52
|
+
* async — {@link verifyWebBotAuth} fetches a key directory, so the natural
|
|
53
|
+
* verifier from `@apideck/agent-analytics/verify` returns a promise and
|
|
54
|
+
* cannot be passed to `verify` on this synchronous function.
|
|
55
|
+
*
|
|
56
|
+
* {@link paymentGate} does this for you: it awaits the verifier and forwards
|
|
57
|
+
* the result here.
|
|
58
|
+
*/
|
|
59
|
+
verification?: BotVerificationLike;
|
|
60
|
+
/** What to do with bulk training crawlers. Defaults to `'meter'`. */
|
|
61
|
+
onTraining?: AgentAction;
|
|
62
|
+
/** What to do with retrieval agents. Defaults to `'allow'` — see AgentIntent. */
|
|
63
|
+
onRetrieval?: AgentAction;
|
|
64
|
+
/** What to do with search indexers. Defaults to `'allow'`. */
|
|
65
|
+
onSearch?: AgentAction;
|
|
66
|
+
/** What to do with coding agents and HTTP clients. Defaults to `'allow'`. */
|
|
67
|
+
onTooling?: AgentAction;
|
|
68
|
+
/** Vendor labels or UA substrings always allowed, whatever the intent. */
|
|
69
|
+
allowList?: readonly string[];
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Classify why an agent is here, from its user agent alone.
|
|
73
|
+
*
|
|
74
|
+
* This must return exactly what {@link agentPolicy} reports for the same UA.
|
|
75
|
+
* It previously did not: the `tooling` promotion for HTTP-library UAs lived
|
|
76
|
+
* only inside `agentPolicy`, so `agentIntent('curl/8.4.0')` said `'unknown'`
|
|
77
|
+
* while the policy said `'tooling'` — two exported functions disagreeing on
|
|
78
|
+
* every HTTP client, with no way for a caller to know which was right. The
|
|
79
|
+
* invariant is pinned by a test.
|
|
80
|
+
*/
|
|
81
|
+
declare function agentIntent(userAgent: string | null | undefined): AgentIntent;
|
|
82
|
+
/**
|
|
83
|
+
* Decide what to do with a request. Pure classification plus policy — no
|
|
84
|
+
* payment rails, no network calls, nothing to configure beyond the four
|
|
85
|
+
* intent knobs.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```ts
|
|
89
|
+
* const decision = agentPolicy(req, { verify: true, onTraining: 'charge' })
|
|
90
|
+
* if (decision.action === 'block') return new Response(null, { status: 403 })
|
|
91
|
+
* if (decision.action === 'charge') return paymentRequired(decision)
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
declare function agentPolicy(req: Request, opts?: AgentPolicyOptions): AgentDecision;
|
|
95
|
+
|
|
96
|
+
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.16.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",
|