@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.
@@ -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.15.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",