@knownagents/sdk 1.6.0 → 1.8.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # Known Agents SDK
2
2
 
3
- [![NPM version](https://img.shields.io/npm/v/@knownagents/sdk.svg)](https://npmjs.org/package/@knownagents/sdk) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/@knownagents/sdk)
3
+ [![NPM version](https://img.shields.io/npm/v/@knownagents/sdk.svg)](https://npmjs.org/package/@knownagents/sdk)
4
4
 
5
5
  This library provides convenient access to [Known Agents](https://knownagents.com/) from server-side TypeScript or JavaScript.
6
6
 
@@ -29,7 +29,13 @@ Get realtime insight into the hidden ecosystem of [crawlers, scrapers, AI agents
29
29
  To collect this data, call `trackVisit` for each incoming request in the endpoints where you serve your pages.
30
30
 
31
31
  ```ts
32
- knownAgents.trackVisit(incomingRequest)
32
+ knownAgents.trackVisit(request)
33
+ ```
34
+
35
+ For richer analytics, include the response and duration:
36
+
37
+ ```ts
38
+ knownAgents.trackVisit(request, response, responseDurationInMilliseconds)
33
39
  ```
34
40
 
35
41
  ### Use Middleware if Possible
@@ -46,7 +52,13 @@ const app = express()
46
52
  const knownAgents = new KnownAgents("YOUR_ACCESS_TOKEN")
47
53
 
48
54
  app.use((req, res, next) => {
49
- knownAgents.trackVisit(req)
55
+ const start = Date.now()
56
+
57
+ res.on('finish', () => {
58
+ const duration = Date.now() - start
59
+ knownAgents.trackVisit(req, res, duration)
60
+ })
61
+
50
62
  next()
51
63
  })
52
64
 
@@ -69,10 +81,10 @@ If your website is correctly connected, you should see visits from the Known Age
69
81
 
70
82
  Protect sensitive content from unwanted access and scraping. Generate a continuously updating robots.txt that stays up to date with [all current and future bots](https://knownagents.com/agents) in the specified categories automatically.
71
83
 
72
- Use the `generateRobotsTxt` function. Select which `AgentType`s you want to block, and a string specifying which URLs are disallowed (e.g. `"/"` to disallow all paths).
84
+ Use the `generateRobotsTXT` function. Select which `AgentType`s you want to block, and a string specifying which URLs are disallowed (e.g. `"/"` to disallow all paths).
73
85
 
74
86
  ```ts
75
- const robotsTxt = await knownAgents.generateRobotsTxt([
87
+ const robotsTxt = await knownAgents.generateRobotsTXT([
76
88
  AgentType.AIDataScraper,
77
89
  AgentType.Scraper,
78
90
  AgentType.IntelligenceGatherer,
@@ -82,7 +94,36 @@ const robotsTxt = await knownAgents.generateRobotsTxt([
82
94
 
83
95
  ```
84
96
 
85
- The return value is a plain text robots.txt string. Generate a `robotsTXT` periodically (e.g. once per day), then cache and serve it from your website's `/robots.txt` endpoint.
97
+ The return value is a plain text robots.txt string. Generate a `robotsTxt` periodically (e.g. once per day), then cache and serve it from your website's `/robots.txt` endpoint.
98
+
99
+ ## How To Use Agent Verification ([Full Docs](https://knownagents.com/docs/verification))
100
+
101
+ Use the `verifyAgent` function to [identify](https://knownagents.com/agents) and verify agents from network requests using Web Bot Auth (HTTP message signatures), IP matching, or other available methods.
102
+
103
+ Call `verifyAgent` with the incoming request.
104
+
105
+ ```ts
106
+ const verification = await knownAgents.verifyAgent(request)
107
+
108
+ if (verification.result === "verified") {
109
+ // Agent is legitimate
110
+ } else if (verification.result === "verification_failed") {
111
+ // Agent is not legitimate
112
+ }
113
+ ```
114
+
115
+ The function returns an object with the following fields:
116
+
117
+ - `result`: The verification result:
118
+ - `"verified"`: The agent is identified and verified
119
+ - `"verification_failed"`: The agent was identified but could not be verified
120
+ - `"unknown_agent"`: The agent is not in our database
121
+ - `"not_verifiable"`: The agent cannot be verified (no verification method available)
122
+ - `agent_id`: The unique ID of the agent (if identified)
123
+ - `agent_token`: The name of the agent (e.g. `"Googlebot"`) (if identified)
124
+ - `agent_url`: The documentation URL of the agent (if identified)
125
+ - `agent_type_name`: The type of agent (e.g. `"AI Agent"`) (if identified)
126
+ - `operator_name`: The company behind the agent (e.g. `"Google"`) (if identified)
86
127
 
87
128
  ## Requirements
88
129
 
package/dist/index.d.ts CHANGED
@@ -1,12 +1,33 @@
1
- import { IncomingMessage } from "http";
1
+ import { IncomingMessage, ServerResponse } from "http";
2
2
  export interface Request {
3
- /** The path of the request's URL (e.g. "/about") */
3
+ /** The URL of the request, including the path and query string (e.g. "/about?foo=bar") */
4
4
  path: string;
5
5
  /** The request's HTTP method (e.g. "GET", "POST") */
6
6
  method: string;
7
7
  /** The request's HTTP headers */
8
8
  headers: Record<string, string | string[] | undefined>;
9
9
  }
10
+ export interface Response {
11
+ /** The HTTP response status code */
12
+ statusCode: number;
13
+ }
14
+ /**
15
+ * The result of an agent verification check.
16
+ */
17
+ export interface VerificationResult {
18
+ /** The verification result */
19
+ result: "verified" | "verification_failed" | "unknown_agent" | "not_verifiable";
20
+ /** The unique ID of the agent (if identified) */
21
+ agent_id?: string;
22
+ /** The name of the agent (e.g. "Googlebot") (if identified) */
23
+ agent_token?: string;
24
+ /** The documentation URL of the agent (if identified) */
25
+ agent_url?: string;
26
+ /** The type of agent (e.g. "AI Agent") (if identified) */
27
+ agent_type_name?: string;
28
+ /** The company behind the agent (e.g. "Google") (if identified) */
29
+ operator_name?: string;
30
+ }
10
31
  /**
11
32
  * Agent types that can be controlled with robots.txt rules.
12
33
  */
@@ -37,10 +58,11 @@ export declare class KnownAgents {
37
58
  /**
38
59
  * Tracks an agent visit in Known Agents agent analytics.
39
60
  *
40
- * @param visitRequest - The incoming visit request.
61
+ * @param request - The incoming request.
62
+ * @param response - The outgoing response (optional).
63
+ * @param responseDurationInMilliseconds - The response duration in milliseconds (optional).
41
64
  */
42
- trackVisit(request: Request): void;
43
- trackVisit(request: IncomingMessage): void;
65
+ trackVisit(request: Request | IncomingMessage, response?: Response | ServerResponse, responseDurationInMilliseconds?: number): void;
44
66
  /**
45
67
  * Generates a `robots.txt` file that disallows the specified agent types.
46
68
  * Cache and serve this string at your website’s `/robots.txt` endpoint.
@@ -50,7 +72,15 @@ export declare class KnownAgents {
50
72
  * @returns The generated `robots.txt` as a string.
51
73
  * @throws If the API call fails or returns a non-200 status.
52
74
  */
53
- generateRobotsTxt(agentTypes: AgentType[], disallow?: string): Promise<string>;
75
+ generateRobotsTXT(agentTypes: AgentType[], disallow?: string): Promise<string>;
76
+ /**
77
+ * Verifies if an agent request is legitimate by checking it against Known Agents.
78
+ *
79
+ * @param request - The incoming request.
80
+ * @returns A promise that resolves to the verification result.
81
+ * @throws If the API call fails or returns a non-200 status.
82
+ */
83
+ verifyAgent(request: Request | IncomingMessage): Promise<VerificationResult>;
54
84
  private filterHeaders;
55
85
  }
56
86
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,MAAM,CAAA;AAItC,MAAM,WAAW,OAAO;IACpB,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAA;IACZ,qDAAqD;IACrD,MAAM,EAAE,MAAM,CAAA;IACd,iCAAiC;IACjC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAA;CACzD;AAED;;GAEG;AACH,oBAAY,SAAS;IACjB,OAAO,aAAa;IACpB,WAAW,iBAAiB;IAC5B,aAAa,oBAAoB;IACjC,eAAe,sBAAsB;IACrC,QAAQ,aAAa;IACrB,eAAe,qBAAqB;IACpC,OAAO,YAAY;IACnB,aAAa,mBAAmB;IAChC,oBAAoB,0BAA0B;IAC9C,OAAO,YAAY;IACnB,UAAU,gBAAgB;IAC1B,mBAAmB,0BAA0B;IAC7C,eAAe,qBAAqB;IACpC,mBAAmB,0BAA0B;CAChD;AAED,qBAAa,WAAW;IACpB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAQ;IAEpC;;;;OAIG;gBACS,WAAW,EAAE,MAAM;IAI/B;;;;OAIG;IACH,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAClC,UAAU,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI;IAyB1C;;;;;;;;OAQG;IACG,iBAAiB,CAAC,UAAU,EAAE,SAAS,EAAE,EAAE,QAAQ,GAAE,MAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAuBzF,OAAO,CAAC,aAAa;CAcxB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,MAAM,CAAA;AAItD,MAAM,WAAW,OAAO;IACpB,0FAA0F;IAC1F,IAAI,EAAE,MAAM,CAAA;IACZ,qDAAqD;IACrD,MAAM,EAAE,MAAM,CAAA;IACd,iCAAiC;IACjC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAA;CACzD;AAED,MAAM,WAAW,QAAQ;IACrB,oCAAoC;IACpC,UAAU,EAAE,MAAM,CAAA;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAC/B,8BAA8B;IAC9B,MAAM,EAAE,UAAU,GAAG,qBAAqB,GAAG,eAAe,GAAG,gBAAgB,CAAA;IAC/E,iDAAiD;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,+DAA+D;IAC/D,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,0DAA0D;IAC1D,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,mEAAmE;IACnE,aAAa,CAAC,EAAE,MAAM,CAAA;CACzB;AAED;;GAEG;AACH,oBAAY,SAAS;IACjB,OAAO,aAAa;IACpB,WAAW,iBAAiB;IAC5B,aAAa,oBAAoB;IACjC,eAAe,sBAAsB;IACrC,QAAQ,aAAa;IACrB,eAAe,qBAAqB;IACpC,OAAO,YAAY;IACnB,aAAa,mBAAmB;IAChC,oBAAoB,0BAA0B;IAC9C,OAAO,YAAY;IACnB,UAAU,gBAAgB;IAC1B,mBAAmB,0BAA0B;IAC7C,eAAe,qBAAqB;IACpC,mBAAmB,0BAA0B;CAChD;AAED,qBAAa,WAAW;IACpB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAQ;IAEpC;;;;OAIG;gBACS,WAAW,EAAE,MAAM;IAI/B;;;;;;OAMG;IACH,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,eAAe,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,cAAc,EAAE,8BAA8B,CAAC,EAAE,MAAM,GAAG,IAAI;IAqBnI;;;;;;;;OAQG;IACG,iBAAiB,CAAC,UAAU,EAAE,SAAS,EAAE,EAAE,QAAQ,GAAE,MAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAqBzF;;;;;;OAMG;IACG,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,eAAe,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAuBlF,OAAO,CAAC,aAAa;CAcxB"}
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.KnownAgents = exports.AgentType = void 0;
4
- const NODE_PACKAGE_VERSION = "1.3.0";
4
+ const NODE_PACKAGE_VERSION = "1.8.0";
5
5
  /**
6
6
  * Agent types that can be controlled with robots.txt rules.
7
7
  */
@@ -31,12 +31,14 @@ class KnownAgents {
31
31
  constructor(accessToken) {
32
32
  this.accessToken = accessToken;
33
33
  }
34
- trackVisit(visitRequest) {
35
- const request = "path" in visitRequest ? visitRequest : {
36
- path: visitRequest.url ? new URL(visitRequest.url, "https://example.org/").pathname : "/",
37
- method: visitRequest.method ?? "GET",
38
- headers: visitRequest.headers
39
- };
34
+ /**
35
+ * Tracks an agent visit in Known Agents agent analytics.
36
+ *
37
+ * @param request - The incoming request.
38
+ * @param response - The outgoing response (optional).
39
+ * @param responseDurationInMilliseconds - The response duration in milliseconds (optional).
40
+ */
41
+ trackVisit(request, response, responseDurationInMilliseconds) {
40
42
  fetch("https://api.knownagents.com/visits", {
41
43
  method: "POST",
42
44
  headers: {
@@ -44,10 +46,13 @@ class KnownAgents {
44
46
  "Content-Type": "application/json"
45
47
  },
46
48
  body: JSON.stringify({
47
- request_path: request.path,
49
+ request_path: "path" in request ? request.path : request.url,
48
50
  request_method: request.method,
49
51
  request_headers: this.filterHeaders(request.headers),
50
- node_package_version: NODE_PACKAGE_VERSION
52
+ response_status_code: response?.statusCode,
53
+ response_duration_in_milliseconds: responseDurationInMilliseconds,
54
+ node_package_version: NODE_PACKAGE_VERSION,
55
+ created: new Date().toISOString()
51
56
  })
52
57
  }).catch(error => {
53
58
  console.error(`Known Agents failed to track visit: ${error.message}`);
@@ -62,7 +67,7 @@ class KnownAgents {
62
67
  * @returns The generated `robots.txt` as a string.
63
68
  * @throws If the API call fails or returns a non-200 status.
64
69
  */
65
- async generateRobotsTxt(agentTypes, disallow = "/") {
70
+ async generateRobotsTXT(agentTypes, disallow = "/") {
66
71
  const response = await fetch("https://api.knownagents.com/robots-txts", {
67
72
  method: "POST",
68
73
  headers: {
@@ -82,6 +87,33 @@ class KnownAgents {
82
87
  throw new Error(`Known Agents failed to generate robots.txt: ${response.status} ${response.statusText}`);
83
88
  }
84
89
  }
90
+ /**
91
+ * Verifies if an agent request is legitimate by checking it against Known Agents.
92
+ *
93
+ * @param request - The incoming request.
94
+ * @returns A promise that resolves to the verification result.
95
+ * @throws If the API call fails or returns a non-200 status.
96
+ */
97
+ async verifyAgent(request) {
98
+ const response = await fetch("https://api.knownagents.com/agent-verifications", {
99
+ method: "POST",
100
+ headers: {
101
+ "Authorization": `Bearer ${this.accessToken}`,
102
+ "Content-Type": "application/json"
103
+ },
104
+ body: JSON.stringify({
105
+ request_path: "path" in request ? request.path : request.url,
106
+ request_headers: this.filterHeaders(request.headers),
107
+ node_package_version: NODE_PACKAGE_VERSION
108
+ })
109
+ });
110
+ if (response.ok) {
111
+ return await response.json();
112
+ }
113
+ else {
114
+ throw new Error(`Known Agents failed to verify agent: ${response.status} ${response.statusText}`);
115
+ }
116
+ }
85
117
  // Helpers
86
118
  filterHeaders(headers) {
87
119
  const excludedHeaders = new Set([
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@knownagents/sdk",
3
- "version": "1.6.0",
4
- "description": "The official Node.js SDK for Known Agents: AI agent analytics (bot traffic), LLM referral tracking, automatic robots.txt",
3
+ "version": "1.8.0",
4
+ "description": "The official Node.js SDK for Known Agents: AI agent analytics (bot traffic), LLM referral tracking, automatic robots.txt, agent verification",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -13,13 +13,22 @@
13
13
  "ai scrapers",
14
14
  "ai crawlers",
15
15
  "ai bots",
16
+ "bot detection",
17
+ "crawler detection",
18
+ "llm analytics",
16
19
  "robots.txt",
17
20
  "automatic robots.txt",
18
21
  "robots.txt generator",
19
22
  "web scraping",
20
23
  "ai blocking",
21
24
  "bot blocking",
22
- "block ai bots",
25
+ "agent verification",
26
+ "bot verification",
27
+ "verify ai agents",
28
+ "web bot auth",
29
+ "http signatures",
30
+ "security",
31
+ "typescript",
23
32
  "express middleware"
24
33
  ],
25
34
  "main": "dist/index.js",
package/src/index.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { IncomingMessage } from "http"
1
+ import { IncomingMessage, ServerResponse } from "http"
2
2
 
3
- const NODE_PACKAGE_VERSION = "1.3.0"
3
+ const NODE_PACKAGE_VERSION = "1.8.0"
4
4
 
5
5
  export interface Request {
6
- /** The path of the request's URL (e.g. "/about") */
6
+ /** The URL of the request, including the path and query string (e.g. "/about?foo=bar") */
7
7
  path: string
8
8
  /** The request's HTTP method (e.g. "GET", "POST") */
9
9
  method: string
@@ -11,6 +11,29 @@ export interface Request {
11
11
  headers: Record<string, string | string[] | undefined>
12
12
  }
13
13
 
14
+ export interface Response {
15
+ /** The HTTP response status code */
16
+ statusCode: number
17
+ }
18
+
19
+ /**
20
+ * The result of an agent verification check.
21
+ */
22
+ export interface VerificationResult {
23
+ /** The verification result */
24
+ result: "verified" | "verification_failed" | "unknown_agent" | "not_verifiable"
25
+ /** The unique ID of the agent (if identified) */
26
+ agent_id?: string
27
+ /** The name of the agent (e.g. "Googlebot") (if identified) */
28
+ agent_token?: string
29
+ /** The documentation URL of the agent (if identified) */
30
+ agent_url?: string
31
+ /** The type of agent (e.g. "AI Agent") (if identified) */
32
+ agent_type_name?: string
33
+ /** The company behind the agent (e.g. "Google") (if identified) */
34
+ operator_name?: string
35
+ }
36
+
14
37
  /**
15
38
  * Agent types that can be controlled with robots.txt rules.
16
39
  */
@@ -46,17 +69,11 @@ export class KnownAgents {
46
69
  /**
47
70
  * Tracks an agent visit in Known Agents agent analytics.
48
71
  *
49
- * @param visitRequest - The incoming visit request.
72
+ * @param request - The incoming request.
73
+ * @param response - The outgoing response (optional).
74
+ * @param responseDurationInMilliseconds - The response duration in milliseconds (optional).
50
75
  */
51
- trackVisit(request: Request): void
52
- trackVisit(request: IncomingMessage): void
53
- trackVisit(visitRequest: Request | IncomingMessage): void {
54
- const request: Request = "path" in visitRequest ? visitRequest : {
55
- path: visitRequest.url ? new URL(visitRequest.url, "https://example.org/").pathname : "/",
56
- method: visitRequest.method ?? "GET",
57
- headers: visitRequest.headers
58
- }
59
-
76
+ trackVisit(request: Request | IncomingMessage, response?: Response | ServerResponse, responseDurationInMilliseconds?: number): void {
60
77
  fetch("https://api.knownagents.com/visits", {
61
78
  method: "POST",
62
79
  headers: {
@@ -64,16 +81,19 @@ export class KnownAgents {
64
81
  "Content-Type": "application/json"
65
82
  },
66
83
  body: JSON.stringify({
67
- request_path: request.path,
84
+ request_path: "path" in request ? request.path : request.url,
68
85
  request_method: request.method,
69
86
  request_headers: this.filterHeaders(request.headers),
70
- node_package_version: NODE_PACKAGE_VERSION
87
+ response_status_code: response?.statusCode,
88
+ response_duration_in_milliseconds: responseDurationInMilliseconds,
89
+ node_package_version: NODE_PACKAGE_VERSION,
90
+ created: new Date().toISOString()
71
91
  })
72
92
  }).catch(error => {
73
93
  console.error(`Known Agents failed to track visit: ${error.message}`)
74
94
  })
75
95
  }
76
-
96
+
77
97
  /**
78
98
  * Generates a `robots.txt` file that disallows the specified agent types.
79
99
  * Cache and serve this string at your website’s `/robots.txt` endpoint.
@@ -83,7 +103,7 @@ export class KnownAgents {
83
103
  * @returns The generated `robots.txt` as a string.
84
104
  * @throws If the API call fails or returns a non-200 status.
85
105
  */
86
- async generateRobotsTxt(agentTypes: AgentType[], disallow: string = "/"): Promise<string> {
106
+ async generateRobotsTXT(agentTypes: AgentType[], disallow: string = "/"): Promise<string> {
87
107
  const response = await fetch("https://api.knownagents.com/robots-txts", {
88
108
  method: "POST",
89
109
  headers: {
@@ -103,6 +123,34 @@ export class KnownAgents {
103
123
  throw new Error(`Known Agents failed to generate robots.txt: ${response.status} ${response.statusText}`)
104
124
  }
105
125
  }
126
+
127
+ /**
128
+ * Verifies if an agent request is legitimate by checking it against Known Agents.
129
+ *
130
+ * @param request - The incoming request.
131
+ * @returns A promise that resolves to the verification result.
132
+ * @throws If the API call fails or returns a non-200 status.
133
+ */
134
+ async verifyAgent(request: Request | IncomingMessage): Promise<VerificationResult> {
135
+ const response = await fetch("https://api.knownagents.com/agent-verifications", {
136
+ method: "POST",
137
+ headers: {
138
+ "Authorization": `Bearer ${this.accessToken}`,
139
+ "Content-Type": "application/json"
140
+ },
141
+ body: JSON.stringify({
142
+ request_path: "path" in request ? request.path : request.url,
143
+ request_headers: this.filterHeaders(request.headers),
144
+ node_package_version: NODE_PACKAGE_VERSION
145
+ })
146
+ })
147
+
148
+ if (response.ok) {
149
+ return await response.json()
150
+ } else {
151
+ throw new Error(`Known Agents failed to verify agent: ${response.status} ${response.statusText}`)
152
+ }
153
+ }
106
154
 
107
155
  // Helpers
108
156