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