@kya-os/agentshield-nextjs 0.3.3 → 0.3.5
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 +21 -369
- package/index.js +9 -0
- package/package.json +7 -141
- package/EDGE_RUNTIME_WASM_SETUP.md +0 -348
- package/bin/setup-edge-wasm.js +0 -525
- package/dist/.tsbuildinfo +0 -1
- package/dist/api-client.d.mts +0 -196
- package/dist/api-client.d.ts +0 -196
- package/dist/api-client.js +0 -200
- package/dist/api-client.js.map +0 -1
- package/dist/api-client.mjs +0 -196
- package/dist/api-client.mjs.map +0 -1
- package/dist/api-middleware.d.mts +0 -140
- package/dist/api-middleware.d.ts +0 -140
- package/dist/api-middleware.js +0 -511
- package/dist/api-middleware.js.map +0 -1
- package/dist/api-middleware.mjs +0 -508
- package/dist/api-middleware.mjs.map +0 -1
- package/dist/create-middleware.d.mts +0 -17
- package/dist/create-middleware.d.ts +0 -17
- package/dist/create-middleware.js +0 -1381
- package/dist/create-middleware.js.map +0 -1
- package/dist/create-middleware.mjs +0 -1358
- package/dist/create-middleware.mjs.map +0 -1
- package/dist/edge/index.d.mts +0 -110
- package/dist/edge/index.d.ts +0 -110
- package/dist/edge/index.js +0 -277
- package/dist/edge/index.js.map +0 -1
- package/dist/edge/index.mjs +0 -275
- package/dist/edge/index.mjs.map +0 -1
- package/dist/edge-detector-wrapper.d.mts +0 -34
- package/dist/edge-detector-wrapper.d.ts +0 -34
- package/dist/edge-detector-wrapper.js +0 -596
- package/dist/edge-detector-wrapper.js.map +0 -1
- package/dist/edge-detector-wrapper.mjs +0 -574
- package/dist/edge-detector-wrapper.mjs.map +0 -1
- package/dist/edge-runtime-loader.d.mts +0 -50
- package/dist/edge-runtime-loader.d.ts +0 -50
- package/dist/edge-runtime-loader.js +0 -204
- package/dist/edge-runtime-loader.js.map +0 -1
- package/dist/edge-runtime-loader.mjs +0 -201
- package/dist/edge-runtime-loader.mjs.map +0 -1
- package/dist/edge-wasm-middleware.d.mts +0 -68
- package/dist/edge-wasm-middleware.d.ts +0 -68
- package/dist/edge-wasm-middleware.js +0 -318
- package/dist/edge-wasm-middleware.js.map +0 -1
- package/dist/edge-wasm-middleware.mjs +0 -315
- package/dist/edge-wasm-middleware.mjs.map +0 -1
- package/dist/enhanced-middleware.d.mts +0 -153
- package/dist/enhanced-middleware.d.ts +0 -153
- package/dist/enhanced-middleware.js +0 -1082
- package/dist/enhanced-middleware.js.map +0 -1
- package/dist/enhanced-middleware.mjs +0 -1080
- package/dist/enhanced-middleware.mjs.map +0 -1
- package/dist/index.d.mts +0 -24
- package/dist/index.d.ts +0 -24
- package/dist/index.js +0 -2717
- package/dist/index.js.map +0 -1
- package/dist/index.mjs +0 -2662
- package/dist/index.mjs.map +0 -1
- package/dist/middleware.d.mts +0 -21
- package/dist/middleware.d.ts +0 -21
- package/dist/middleware.js +0 -1362
- package/dist/middleware.js.map +0 -1
- package/dist/middleware.mjs +0 -1339
- package/dist/middleware.mjs.map +0 -1
- package/dist/nodejs-wasm-loader.d.mts +0 -25
- package/dist/nodejs-wasm-loader.d.ts +0 -25
- package/dist/nodejs-wasm-loader.js +0 -78
- package/dist/nodejs-wasm-loader.js.map +0 -1
- package/dist/nodejs-wasm-loader.mjs +0 -68
- package/dist/nodejs-wasm-loader.mjs.map +0 -1
- package/dist/policy.d.mts +0 -162
- package/dist/policy.d.ts +0 -162
- package/dist/policy.js +0 -189
- package/dist/policy.js.map +0 -1
- package/dist/policy.mjs +0 -165
- package/dist/policy.mjs.map +0 -1
- package/dist/session-tracker.d.mts +0 -55
- package/dist/session-tracker.d.ts +0 -55
- package/dist/session-tracker.js +0 -170
- package/dist/session-tracker.js.map +0 -1
- package/dist/session-tracker.mjs +0 -167
- package/dist/session-tracker.mjs.map +0 -1
- package/dist/signature-verifier.d.mts +0 -33
- package/dist/signature-verifier.d.ts +0 -33
- package/dist/signature-verifier.js +0 -386
- package/dist/signature-verifier.js.map +0 -1
- package/dist/signature-verifier.mjs +0 -362
- package/dist/signature-verifier.mjs.map +0 -1
- package/dist/types-DVmy9NE3.d.mts +0 -105
- package/dist/types-DVmy9NE3.d.ts +0 -105
- package/dist/wasm-middleware.d.mts +0 -63
- package/dist/wasm-middleware.d.ts +0 -63
- package/dist/wasm-middleware.js +0 -98
- package/dist/wasm-middleware.js.map +0 -1
- package/dist/wasm-middleware.mjs +0 -95
- package/dist/wasm-middleware.mjs.map +0 -1
- package/dist/wasm-setup.d.mts +0 -46
- package/dist/wasm-setup.d.ts +0 -46
- package/dist/wasm-setup.js +0 -157
- package/dist/wasm-setup.js.map +0 -1
- package/dist/wasm-setup.mjs +0 -148
- package/dist/wasm-setup.mjs.map +0 -1
- package/templates/middleware-wasm-100.ts +0 -151
- package/wasm/agentshield_wasm.d.ts +0 -479
- package/wasm/agentshield_wasm.js +0 -1536
- package/wasm/agentshield_wasm_bg.wasm +0 -0
- package/wasm/package.json +0 -30
- package/wasm.d.ts +0 -21
package/dist/api-client.d.ts
DELETED
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
import { EnforcementAction } from '@kya-os/agentshield-shared';
|
|
2
|
-
export { EnforcementAction } from '@kya-os/agentshield-shared';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* AgentShield API Client
|
|
6
|
-
*
|
|
7
|
-
* Lightweight client for calling the AgentShield enforce API from middleware.
|
|
8
|
-
* Designed for Edge Runtime compatibility (no Node.js-specific APIs).
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* API client configuration
|
|
13
|
-
*/
|
|
14
|
-
interface AgentShieldClientConfig {
|
|
15
|
-
/** API key for authentication */
|
|
16
|
-
apiKey: string;
|
|
17
|
-
/** API base URL (defaults to production) */
|
|
18
|
-
baseUrl?: string;
|
|
19
|
-
/**
|
|
20
|
-
* Use edge detection for lower latency (~30-50ms vs ~150ms) and better coverage.
|
|
21
|
-
* Edge detection can identify non-JS clients (curl, Python, Claude Code WebFetch)
|
|
22
|
-
* that the pixel cannot detect since they don't execute JavaScript.
|
|
23
|
-
* @default true
|
|
24
|
-
*/
|
|
25
|
-
useEdge?: boolean;
|
|
26
|
-
/** Request timeout in milliseconds (default: 5000) */
|
|
27
|
-
timeout?: number;
|
|
28
|
-
/** Enable debug logging */
|
|
29
|
-
debug?: boolean;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Enforcement decision from the API
|
|
34
|
-
*/
|
|
35
|
-
interface EnforcementDecision {
|
|
36
|
-
action: EnforcementAction;
|
|
37
|
-
reason: string;
|
|
38
|
-
isAgent: boolean;
|
|
39
|
-
confidence: number;
|
|
40
|
-
agentName?: string;
|
|
41
|
-
agentType?: string;
|
|
42
|
-
redirectUrl?: string;
|
|
43
|
-
message?: string;
|
|
44
|
-
metadata?: {
|
|
45
|
-
policyVersion?: string;
|
|
46
|
-
signatureVerified?: boolean;
|
|
47
|
-
denyListMatch?: {
|
|
48
|
-
clientDid?: string;
|
|
49
|
-
agentDid?: string;
|
|
50
|
-
clientName?: string;
|
|
51
|
-
reason?: string;
|
|
52
|
-
};
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Detection result (optional in response)
|
|
57
|
-
*/
|
|
58
|
-
interface DetectionResult {
|
|
59
|
-
isAgent: boolean;
|
|
60
|
-
confidence: number;
|
|
61
|
-
agentName?: string;
|
|
62
|
-
agentType?: string;
|
|
63
|
-
/** Detection class: 'human', 'ai_agent', 'bot', 'incomplete_data' */
|
|
64
|
-
detectionClass?: string;
|
|
65
|
-
verificationMethod?: string;
|
|
66
|
-
reasons?: string[];
|
|
67
|
-
/** Detection engine used: 'wasm' or 'javascript-fallback' */
|
|
68
|
-
detectionMethod?: string;
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Enforce API response
|
|
72
|
-
*/
|
|
73
|
-
interface EnforceResponse {
|
|
74
|
-
success: boolean;
|
|
75
|
-
data?: {
|
|
76
|
-
decision: EnforcementDecision;
|
|
77
|
-
processingTimeMs: number;
|
|
78
|
-
requestId: string;
|
|
79
|
-
detection?: DetectionResult;
|
|
80
|
-
};
|
|
81
|
-
error?: {
|
|
82
|
-
code: string;
|
|
83
|
-
message: string;
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Request input for enforce API
|
|
88
|
-
*/
|
|
89
|
-
interface EnforceInput {
|
|
90
|
-
/** HTTP headers from the incoming request */
|
|
91
|
-
headers?: Record<string, string>;
|
|
92
|
-
/** User-Agent header */
|
|
93
|
-
userAgent?: string;
|
|
94
|
-
/** Client IP address */
|
|
95
|
-
ipAddress?: string;
|
|
96
|
-
/** Request path */
|
|
97
|
-
path?: string;
|
|
98
|
-
/** Request URL */
|
|
99
|
-
url?: string;
|
|
100
|
-
/** HTTP method */
|
|
101
|
-
method?: string;
|
|
102
|
-
/** Request ID for tracing */
|
|
103
|
-
requestId?: string;
|
|
104
|
-
/** Options */
|
|
105
|
-
options?: {
|
|
106
|
-
/** Include full detection result */
|
|
107
|
-
includeDetectionResult?: boolean;
|
|
108
|
-
/** Cache TTL override */
|
|
109
|
-
cacheTTL?: number;
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
/**
|
|
113
|
-
* Input for logging a detection result
|
|
114
|
-
*/
|
|
115
|
-
interface LogDetectionInput {
|
|
116
|
-
/** Detection result from Gateway */
|
|
117
|
-
detection: DetectionResult;
|
|
118
|
-
/** Request context */
|
|
119
|
-
context: {
|
|
120
|
-
userAgent?: string;
|
|
121
|
-
ipAddress?: string;
|
|
122
|
-
path?: string;
|
|
123
|
-
url?: string;
|
|
124
|
-
method?: string;
|
|
125
|
-
};
|
|
126
|
-
/** Source of the detection */
|
|
127
|
-
source?: 'gateway' | 'middleware';
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* AgentShield API Client
|
|
131
|
-
*
|
|
132
|
-
* @example
|
|
133
|
-
* ```typescript
|
|
134
|
-
* const client = new AgentShieldClient({
|
|
135
|
-
* apiKey: process.env.AGENTSHIELD_API_KEY!,
|
|
136
|
-
* });
|
|
137
|
-
*
|
|
138
|
-
* const result = await client.enforce({
|
|
139
|
-
* headers: Object.fromEntries(request.headers),
|
|
140
|
-
* path: request.nextUrl.pathname,
|
|
141
|
-
* method: request.method,
|
|
142
|
-
* });
|
|
143
|
-
*
|
|
144
|
-
* if (result.decision.action === 'block') {
|
|
145
|
-
* return new Response('Access denied', { status: 403 });
|
|
146
|
-
* }
|
|
147
|
-
* ```
|
|
148
|
-
*/
|
|
149
|
-
declare class AgentShieldClient {
|
|
150
|
-
private apiKey;
|
|
151
|
-
private baseUrl;
|
|
152
|
-
private useEdge;
|
|
153
|
-
private timeout;
|
|
154
|
-
private debug;
|
|
155
|
-
constructor(config: AgentShieldClientConfig);
|
|
156
|
-
/**
|
|
157
|
-
* Call the enforce API to check if a request should be allowed
|
|
158
|
-
*/
|
|
159
|
-
enforce(input: EnforceInput): Promise<EnforceResponse>;
|
|
160
|
-
/**
|
|
161
|
-
* Quick check - returns just the action without full response parsing
|
|
162
|
-
* Useful for very fast middleware that just needs allow/block
|
|
163
|
-
*/
|
|
164
|
-
quickCheck(input: EnforceInput): Promise<{
|
|
165
|
-
action: EnforcementAction;
|
|
166
|
-
error?: string;
|
|
167
|
-
}>;
|
|
168
|
-
/**
|
|
169
|
-
* Check if this client is using edge detection (Gateway Worker)
|
|
170
|
-
*/
|
|
171
|
-
isUsingEdge(): boolean;
|
|
172
|
-
/**
|
|
173
|
-
* Log a detection result to AgentShield database.
|
|
174
|
-
* Use after Gateway Worker detection to persist results.
|
|
175
|
-
* Fire-and-forget - returns immediately without waiting for DB write.
|
|
176
|
-
*
|
|
177
|
-
* @example
|
|
178
|
-
* ```typescript
|
|
179
|
-
* // After receiving Gateway response
|
|
180
|
-
* if (client.isUsingEdge() && response.data?.detection) {
|
|
181
|
-
* client.logDetection({
|
|
182
|
-
* detection: response.data.detection,
|
|
183
|
-
* context: { userAgent, ipAddress, path, url, method }
|
|
184
|
-
* }).catch(err => console.error('Log failed:', err));
|
|
185
|
-
* }
|
|
186
|
-
* ```
|
|
187
|
-
*/
|
|
188
|
-
logDetection(input: LogDetectionInput): Promise<void>;
|
|
189
|
-
}
|
|
190
|
-
declare function getAgentShieldClient(config?: Partial<AgentShieldClientConfig>): AgentShieldClient;
|
|
191
|
-
/**
|
|
192
|
-
* Reset the singleton client (useful for testing)
|
|
193
|
-
*/
|
|
194
|
-
declare function resetAgentShieldClient(): void;
|
|
195
|
-
|
|
196
|
-
export { AgentShieldClient, type AgentShieldClientConfig, type DetectionResult, type EnforceInput, type EnforceResponse, type EnforcementDecision, type LogDetectionInput, getAgentShieldClient, resetAgentShieldClient };
|
package/dist/api-client.js
DELETED
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
// src/api-client.ts
|
|
4
|
-
var DEFAULT_BASE_URL = "https://kya.vouched.id";
|
|
5
|
-
var EDGE_DETECT_URL = "https://detect.checkpoint-gateway.ai";
|
|
6
|
-
var DEFAULT_TIMEOUT = 5e3;
|
|
7
|
-
var AgentShieldClient = class {
|
|
8
|
-
apiKey;
|
|
9
|
-
baseUrl;
|
|
10
|
-
useEdge;
|
|
11
|
-
timeout;
|
|
12
|
-
debug;
|
|
13
|
-
constructor(config) {
|
|
14
|
-
if (!config.apiKey) {
|
|
15
|
-
throw new Error("AgentShield API key is required");
|
|
16
|
-
}
|
|
17
|
-
this.apiKey = config.apiKey;
|
|
18
|
-
this.useEdge = config.useEdge !== false;
|
|
19
|
-
this.baseUrl = config.baseUrl || (this.useEdge ? EDGE_DETECT_URL : DEFAULT_BASE_URL);
|
|
20
|
-
this.timeout = config.timeout || DEFAULT_TIMEOUT;
|
|
21
|
-
this.debug = config.debug || false;
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Call the enforce API to check if a request should be allowed
|
|
25
|
-
*/
|
|
26
|
-
async enforce(input) {
|
|
27
|
-
const startTime = Date.now();
|
|
28
|
-
try {
|
|
29
|
-
const controller = new AbortController();
|
|
30
|
-
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
31
|
-
try {
|
|
32
|
-
const endpoint = this.useEdge ? `${this.baseUrl}/__detect/enforce` : `${this.baseUrl}/api/v1/enforce`;
|
|
33
|
-
const response = await fetch(endpoint, {
|
|
34
|
-
method: "POST",
|
|
35
|
-
headers: {
|
|
36
|
-
"Content-Type": "application/json",
|
|
37
|
-
Authorization: `Bearer ${this.apiKey}`,
|
|
38
|
-
"X-Request-ID": input.requestId || crypto.randomUUID()
|
|
39
|
-
},
|
|
40
|
-
body: JSON.stringify(input),
|
|
41
|
-
signal: controller.signal
|
|
42
|
-
});
|
|
43
|
-
clearTimeout(timeoutId);
|
|
44
|
-
const data = await response.json();
|
|
45
|
-
if (this.debug) {
|
|
46
|
-
console.log("[AgentShield] Enforce response:", {
|
|
47
|
-
status: response.status,
|
|
48
|
-
action: data.data?.decision.action,
|
|
49
|
-
processingTimeMs: Date.now() - startTime
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
if (!response.ok) {
|
|
53
|
-
return {
|
|
54
|
-
success: false,
|
|
55
|
-
error: {
|
|
56
|
-
code: `HTTP_${response.status}`,
|
|
57
|
-
message: data.error?.message || `HTTP error: ${response.status}`
|
|
58
|
-
}
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
return data;
|
|
62
|
-
} catch (error) {
|
|
63
|
-
clearTimeout(timeoutId);
|
|
64
|
-
throw error;
|
|
65
|
-
}
|
|
66
|
-
} catch (error) {
|
|
67
|
-
if (error instanceof Error && error.name === "AbortError") {
|
|
68
|
-
if (this.debug) {
|
|
69
|
-
console.warn("[AgentShield] Request timed out");
|
|
70
|
-
}
|
|
71
|
-
return {
|
|
72
|
-
success: false,
|
|
73
|
-
error: {
|
|
74
|
-
code: "TIMEOUT",
|
|
75
|
-
message: `Request timed out after ${this.timeout}ms`
|
|
76
|
-
}
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
if (this.debug) {
|
|
80
|
-
console.error("[AgentShield] Request failed:", error);
|
|
81
|
-
}
|
|
82
|
-
return {
|
|
83
|
-
success: false,
|
|
84
|
-
error: {
|
|
85
|
-
code: "NETWORK_ERROR",
|
|
86
|
-
message: error instanceof Error ? error.message : "Network request failed"
|
|
87
|
-
}
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Quick check - returns just the action without full response parsing
|
|
93
|
-
* Useful for very fast middleware that just needs allow/block
|
|
94
|
-
*/
|
|
95
|
-
async quickCheck(input) {
|
|
96
|
-
const result = await this.enforce(input);
|
|
97
|
-
if (!result.success || !result.data) {
|
|
98
|
-
return {
|
|
99
|
-
action: "allow",
|
|
100
|
-
error: result.error?.message
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
return {
|
|
104
|
-
action: result.data.decision.action
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* Check if this client is using edge detection (Gateway Worker)
|
|
109
|
-
*/
|
|
110
|
-
isUsingEdge() {
|
|
111
|
-
return this.useEdge;
|
|
112
|
-
}
|
|
113
|
-
/**
|
|
114
|
-
* Log a detection result to AgentShield database.
|
|
115
|
-
* Use after Gateway Worker detection to persist results.
|
|
116
|
-
* Fire-and-forget - returns immediately without waiting for DB write.
|
|
117
|
-
*
|
|
118
|
-
* @example
|
|
119
|
-
* ```typescript
|
|
120
|
-
* // After receiving Gateway response
|
|
121
|
-
* if (client.isUsingEdge() && response.data?.detection) {
|
|
122
|
-
* client.logDetection({
|
|
123
|
-
* detection: response.data.detection,
|
|
124
|
-
* context: { userAgent, ipAddress, path, url, method }
|
|
125
|
-
* }).catch(err => console.error('Log failed:', err));
|
|
126
|
-
* }
|
|
127
|
-
* ```
|
|
128
|
-
*/
|
|
129
|
-
async logDetection(input) {
|
|
130
|
-
const logEndpoint = this.useEdge ? `${DEFAULT_BASE_URL}/api/v1/log-detection` : `${this.baseUrl}/api/v1/log-detection`;
|
|
131
|
-
try {
|
|
132
|
-
const controller = new AbortController();
|
|
133
|
-
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
134
|
-
try {
|
|
135
|
-
const response = await fetch(logEndpoint, {
|
|
136
|
-
method: "POST",
|
|
137
|
-
headers: {
|
|
138
|
-
"Content-Type": "application/json",
|
|
139
|
-
Authorization: `Bearer ${this.apiKey}`
|
|
140
|
-
},
|
|
141
|
-
body: JSON.stringify({
|
|
142
|
-
detection: {
|
|
143
|
-
isAgent: input.detection.isAgent,
|
|
144
|
-
confidence: input.detection.confidence,
|
|
145
|
-
agentName: input.detection.agentName,
|
|
146
|
-
agentType: input.detection.agentType,
|
|
147
|
-
detectionClass: input.detection.detectionClass,
|
|
148
|
-
verificationMethod: input.detection.verificationMethod,
|
|
149
|
-
reasons: input.detection.reasons
|
|
150
|
-
},
|
|
151
|
-
context: input.context,
|
|
152
|
-
source: input.source || "gateway"
|
|
153
|
-
}),
|
|
154
|
-
signal: controller.signal
|
|
155
|
-
});
|
|
156
|
-
clearTimeout(timeoutId);
|
|
157
|
-
if (!response.ok && this.debug) {
|
|
158
|
-
console.warn("[AgentShield] Log detection returned non-2xx:", response.status);
|
|
159
|
-
}
|
|
160
|
-
} catch (error) {
|
|
161
|
-
clearTimeout(timeoutId);
|
|
162
|
-
throw error;
|
|
163
|
-
}
|
|
164
|
-
} catch (error) {
|
|
165
|
-
if (this.debug) {
|
|
166
|
-
console.error("[AgentShield] Log detection failed:", error);
|
|
167
|
-
}
|
|
168
|
-
throw error;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
};
|
|
172
|
-
var clientInstance = null;
|
|
173
|
-
function getAgentShieldClient(config) {
|
|
174
|
-
if (!clientInstance) {
|
|
175
|
-
const apiKey = config?.apiKey || process.env.AGENTSHIELD_API_KEY;
|
|
176
|
-
if (!apiKey) {
|
|
177
|
-
throw new Error(
|
|
178
|
-
"AgentShield API key is required. Set AGENTSHIELD_API_KEY environment variable or pass apiKey in config."
|
|
179
|
-
);
|
|
180
|
-
}
|
|
181
|
-
clientInstance = new AgentShieldClient({
|
|
182
|
-
apiKey,
|
|
183
|
-
baseUrl: config?.baseUrl || process.env.AGENTSHIELD_API_URL,
|
|
184
|
-
// Default to edge detection unless explicitly disabled
|
|
185
|
-
useEdge: config?.useEdge ?? process.env.AGENTSHIELD_USE_EDGE !== "false",
|
|
186
|
-
timeout: config?.timeout,
|
|
187
|
-
debug: config?.debug || process.env.AGENTSHIELD_DEBUG === "true"
|
|
188
|
-
});
|
|
189
|
-
}
|
|
190
|
-
return clientInstance;
|
|
191
|
-
}
|
|
192
|
-
function resetAgentShieldClient() {
|
|
193
|
-
clientInstance = null;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
exports.AgentShieldClient = AgentShieldClient;
|
|
197
|
-
exports.getAgentShieldClient = getAgentShieldClient;
|
|
198
|
-
exports.resetAgentShieldClient = resetAgentShieldClient;
|
|
199
|
-
//# sourceMappingURL=api-client.js.map
|
|
200
|
-
//# sourceMappingURL=api-client.js.map
|
package/dist/api-client.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/api-client.ts"],"names":[],"mappings":"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","file":"api-client.js","sourcesContent":["/**\n * AgentShield API Client\n *\n * Lightweight client for calling the AgentShield enforce API from middleware.\n * Designed for Edge Runtime compatibility (no Node.js-specific APIs).\n */\n\nimport type { EnforcementAction } from '@kya-os/agentshield-shared';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * API client configuration\n */\nexport interface AgentShieldClientConfig {\n /** API key for authentication */\n apiKey: string;\n /** API base URL (defaults to production) */\n baseUrl?: string;\n /**\n * Use edge detection for lower latency (~30-50ms vs ~150ms) and better coverage.\n * Edge detection can identify non-JS clients (curl, Python, Claude Code WebFetch)\n * that the pixel cannot detect since they don't execute JavaScript.\n * @default true\n */\n useEdge?: boolean;\n /** Request timeout in milliseconds (default: 5000) */\n timeout?: number;\n /** Enable debug logging */\n debug?: boolean;\n}\n\n/**\n * Enforcement action — re-exported from `@kya-os/agentshield-shared`\n * so consumers of this package can keep importing it from the same\n * place. The canonical 6-value union is defined in\n * `packages/agentshield-shared/src/policy/constants.ts`. `'instruct'`\n * tells the middleware to emit a 401 with an MCP-I Link header\n * pointing the agent at a connect/consent URL.\n */\nexport type { EnforcementAction };\n\n/**\n * Enforcement decision from the API\n */\nexport interface EnforcementDecision {\n action: EnforcementAction;\n reason: string;\n isAgent: boolean;\n confidence: number;\n agentName?: string;\n agentType?: string;\n redirectUrl?: string;\n message?: string;\n metadata?: {\n policyVersion?: string;\n signatureVerified?: boolean;\n denyListMatch?: {\n clientDid?: string;\n agentDid?: string;\n clientName?: string;\n reason?: string;\n };\n };\n}\n\n/**\n * Detection result (optional in response)\n */\nexport interface DetectionResult {\n isAgent: boolean;\n confidence: number;\n agentName?: string;\n agentType?: string;\n /** Detection class: 'human', 'ai_agent', 'bot', 'incomplete_data' */\n detectionClass?: string;\n verificationMethod?: string;\n reasons?: string[];\n /** Detection engine used: 'wasm' or 'javascript-fallback' */\n detectionMethod?: string;\n}\n\n/**\n * Enforce API response\n */\nexport interface EnforceResponse {\n success: boolean;\n data?: {\n decision: EnforcementDecision;\n processingTimeMs: number;\n requestId: string;\n detection?: DetectionResult;\n };\n error?: {\n code: string;\n message: string;\n };\n}\n\n/**\n * Request input for enforce API\n */\nexport interface EnforceInput {\n /** HTTP headers from the incoming request */\n headers?: Record<string, string>;\n /** User-Agent header */\n userAgent?: string;\n /** Client IP address */\n ipAddress?: string;\n /** Request path */\n path?: string;\n /** Request URL */\n url?: string;\n /** HTTP method */\n method?: string;\n /** Request ID for tracing */\n requestId?: string;\n /** Options */\n options?: {\n /** Include full detection result */\n includeDetectionResult?: boolean;\n /** Cache TTL override */\n cacheTTL?: number;\n };\n}\n\n/**\n * Input for logging a detection result\n */\nexport interface LogDetectionInput {\n /** Detection result from Gateway */\n detection: DetectionResult;\n /** Request context */\n context: {\n userAgent?: string;\n ipAddress?: string;\n path?: string;\n url?: string;\n method?: string;\n };\n /** Source of the detection */\n source?: 'gateway' | 'middleware';\n}\n\n// ============================================================================\n// Client Implementation\n// ============================================================================\n\nconst DEFAULT_BASE_URL = 'https://kya.vouched.id';\nconst EDGE_DETECT_URL = 'https://detect.checkpoint-gateway.ai';\nconst DEFAULT_TIMEOUT = 5000;\n\n/**\n * AgentShield API Client\n *\n * @example\n * ```typescript\n * const client = new AgentShieldClient({\n * apiKey: process.env.AGENTSHIELD_API_KEY!,\n * });\n *\n * const result = await client.enforce({\n * headers: Object.fromEntries(request.headers),\n * path: request.nextUrl.pathname,\n * method: request.method,\n * });\n *\n * if (result.decision.action === 'block') {\n * return new Response('Access denied', { status: 403 });\n * }\n * ```\n */\nexport class AgentShieldClient {\n private apiKey: string;\n private baseUrl: string;\n private useEdge: boolean;\n private timeout: number;\n private debug: boolean;\n\n constructor(config: AgentShieldClientConfig) {\n if (!config.apiKey) {\n throw new Error('AgentShield API key is required');\n }\n\n this.apiKey = config.apiKey;\n // Default to edge detection for better coverage (detects non-JS clients)\n this.useEdge = config.useEdge !== false; // true by default\n this.baseUrl = config.baseUrl || (this.useEdge ? EDGE_DETECT_URL : DEFAULT_BASE_URL);\n this.timeout = config.timeout || DEFAULT_TIMEOUT;\n this.debug = config.debug || false;\n }\n\n /**\n * Call the enforce API to check if a request should be allowed\n */\n async enforce(input: EnforceInput): Promise<EnforceResponse> {\n const startTime = Date.now();\n\n try {\n // Create abort controller for timeout\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n // Use edge endpoint or Vercel API based on configuration\n const endpoint = this.useEdge\n ? `${this.baseUrl}/__detect/enforce`\n : `${this.baseUrl}/api/v1/enforce`;\n\n const response = await fetch(endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.apiKey}`,\n 'X-Request-ID': input.requestId || crypto.randomUUID(),\n },\n body: JSON.stringify(input),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n // Parse response\n const data = (await response.json()) as EnforceResponse;\n\n if (this.debug) {\n console.log('[AgentShield] Enforce response:', {\n status: response.status,\n action: data.data?.decision.action,\n processingTimeMs: Date.now() - startTime,\n });\n }\n\n // Handle non-2xx responses\n if (!response.ok) {\n return {\n success: false,\n error: {\n code: `HTTP_${response.status}`,\n message: data.error?.message || `HTTP error: ${response.status}`,\n },\n };\n }\n\n return data;\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n } catch (error) {\n // Handle timeout\n if (error instanceof Error && error.name === 'AbortError') {\n if (this.debug) {\n console.warn('[AgentShield] Request timed out');\n }\n return {\n success: false,\n error: {\n code: 'TIMEOUT',\n message: `Request timed out after ${this.timeout}ms`,\n },\n };\n }\n\n // Handle network errors\n if (this.debug) {\n console.error('[AgentShield] Request failed:', error);\n }\n\n return {\n success: false,\n error: {\n code: 'NETWORK_ERROR',\n message: error instanceof Error ? error.message : 'Network request failed',\n },\n };\n }\n }\n\n /**\n * Quick check - returns just the action without full response parsing\n * Useful for very fast middleware that just needs allow/block\n */\n async quickCheck(input: EnforceInput): Promise<{\n action: EnforcementAction;\n error?: string;\n }> {\n const result = await this.enforce(input);\n\n if (!result.success || !result.data) {\n // On error, default to allow (fail-open)\n return {\n action: 'allow',\n error: result.error?.message,\n };\n }\n\n return {\n action: result.data.decision.action,\n };\n }\n\n /**\n * Check if this client is using edge detection (Gateway Worker)\n */\n isUsingEdge(): boolean {\n return this.useEdge;\n }\n\n /**\n * Log a detection result to AgentShield database.\n * Use after Gateway Worker detection to persist results.\n * Fire-and-forget - returns immediately without waiting for DB write.\n *\n * @example\n * ```typescript\n * // After receiving Gateway response\n * if (client.isUsingEdge() && response.data?.detection) {\n * client.logDetection({\n * detection: response.data.detection,\n * context: { userAgent, ipAddress, path, url, method }\n * }).catch(err => console.error('Log failed:', err));\n * }\n * ```\n */\n async logDetection(input: LogDetectionInput): Promise<void> {\n // Don't await - fire and forget\n // Use the base URL (not edge) for logging since this goes to the main API\n const logEndpoint = this.useEdge\n ? `${DEFAULT_BASE_URL}/api/v1/log-detection`\n : `${this.baseUrl}/api/v1/log-detection`;\n\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(logEndpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify({\n detection: {\n isAgent: input.detection.isAgent,\n confidence: input.detection.confidence,\n agentName: input.detection.agentName,\n agentType: input.detection.agentType,\n detectionClass: input.detection.detectionClass,\n verificationMethod: input.detection.verificationMethod,\n reasons: input.detection.reasons,\n },\n context: input.context,\n source: input.source || 'gateway',\n }),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok && this.debug) {\n console.warn('[AgentShield] Log detection returned non-2xx:', response.status);\n }\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n } catch (error) {\n // Silently fail for fire-and-forget, but log in debug mode\n if (this.debug) {\n console.error('[AgentShield] Log detection failed:', error);\n }\n // Re-throw so caller can catch if needed\n throw error;\n }\n }\n}\n\n/**\n * Create a singleton client instance\n *\n * @example\n * ```typescript\n * // In middleware.ts\n * import { getAgentShieldClient } from '@kya-os/agentshield-nextjs';\n *\n * const client = getAgentShieldClient();\n * ```\n */\nlet clientInstance: AgentShieldClient | null = null;\n\nexport function getAgentShieldClient(config?: Partial<AgentShieldClientConfig>): AgentShieldClient {\n if (!clientInstance) {\n const apiKey = config?.apiKey || process.env.AGENTSHIELD_API_KEY;\n\n if (!apiKey) {\n throw new Error(\n 'AgentShield API key is required. Set AGENTSHIELD_API_KEY environment variable or pass apiKey in config.'\n );\n }\n\n clientInstance = new AgentShieldClient({\n apiKey,\n baseUrl: config?.baseUrl || process.env.AGENTSHIELD_API_URL,\n // Default to edge detection unless explicitly disabled\n useEdge: config?.useEdge ?? process.env.AGENTSHIELD_USE_EDGE !== 'false',\n timeout: config?.timeout,\n debug: config?.debug || process.env.AGENTSHIELD_DEBUG === 'true',\n });\n }\n\n return clientInstance;\n}\n\n/**\n * Reset the singleton client (useful for testing)\n */\nexport function resetAgentShieldClient(): void {\n clientInstance = null;\n}\n"]}
|
package/dist/api-client.mjs
DELETED
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
// src/api-client.ts
|
|
2
|
-
var DEFAULT_BASE_URL = "https://kya.vouched.id";
|
|
3
|
-
var EDGE_DETECT_URL = "https://detect.checkpoint-gateway.ai";
|
|
4
|
-
var DEFAULT_TIMEOUT = 5e3;
|
|
5
|
-
var AgentShieldClient = class {
|
|
6
|
-
apiKey;
|
|
7
|
-
baseUrl;
|
|
8
|
-
useEdge;
|
|
9
|
-
timeout;
|
|
10
|
-
debug;
|
|
11
|
-
constructor(config) {
|
|
12
|
-
if (!config.apiKey) {
|
|
13
|
-
throw new Error("AgentShield API key is required");
|
|
14
|
-
}
|
|
15
|
-
this.apiKey = config.apiKey;
|
|
16
|
-
this.useEdge = config.useEdge !== false;
|
|
17
|
-
this.baseUrl = config.baseUrl || (this.useEdge ? EDGE_DETECT_URL : DEFAULT_BASE_URL);
|
|
18
|
-
this.timeout = config.timeout || DEFAULT_TIMEOUT;
|
|
19
|
-
this.debug = config.debug || false;
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Call the enforce API to check if a request should be allowed
|
|
23
|
-
*/
|
|
24
|
-
async enforce(input) {
|
|
25
|
-
const startTime = Date.now();
|
|
26
|
-
try {
|
|
27
|
-
const controller = new AbortController();
|
|
28
|
-
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
29
|
-
try {
|
|
30
|
-
const endpoint = this.useEdge ? `${this.baseUrl}/__detect/enforce` : `${this.baseUrl}/api/v1/enforce`;
|
|
31
|
-
const response = await fetch(endpoint, {
|
|
32
|
-
method: "POST",
|
|
33
|
-
headers: {
|
|
34
|
-
"Content-Type": "application/json",
|
|
35
|
-
Authorization: `Bearer ${this.apiKey}`,
|
|
36
|
-
"X-Request-ID": input.requestId || crypto.randomUUID()
|
|
37
|
-
},
|
|
38
|
-
body: JSON.stringify(input),
|
|
39
|
-
signal: controller.signal
|
|
40
|
-
});
|
|
41
|
-
clearTimeout(timeoutId);
|
|
42
|
-
const data = await response.json();
|
|
43
|
-
if (this.debug) {
|
|
44
|
-
console.log("[AgentShield] Enforce response:", {
|
|
45
|
-
status: response.status,
|
|
46
|
-
action: data.data?.decision.action,
|
|
47
|
-
processingTimeMs: Date.now() - startTime
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
if (!response.ok) {
|
|
51
|
-
return {
|
|
52
|
-
success: false,
|
|
53
|
-
error: {
|
|
54
|
-
code: `HTTP_${response.status}`,
|
|
55
|
-
message: data.error?.message || `HTTP error: ${response.status}`
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
return data;
|
|
60
|
-
} catch (error) {
|
|
61
|
-
clearTimeout(timeoutId);
|
|
62
|
-
throw error;
|
|
63
|
-
}
|
|
64
|
-
} catch (error) {
|
|
65
|
-
if (error instanceof Error && error.name === "AbortError") {
|
|
66
|
-
if (this.debug) {
|
|
67
|
-
console.warn("[AgentShield] Request timed out");
|
|
68
|
-
}
|
|
69
|
-
return {
|
|
70
|
-
success: false,
|
|
71
|
-
error: {
|
|
72
|
-
code: "TIMEOUT",
|
|
73
|
-
message: `Request timed out after ${this.timeout}ms`
|
|
74
|
-
}
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
if (this.debug) {
|
|
78
|
-
console.error("[AgentShield] Request failed:", error);
|
|
79
|
-
}
|
|
80
|
-
return {
|
|
81
|
-
success: false,
|
|
82
|
-
error: {
|
|
83
|
-
code: "NETWORK_ERROR",
|
|
84
|
-
message: error instanceof Error ? error.message : "Network request failed"
|
|
85
|
-
}
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* Quick check - returns just the action without full response parsing
|
|
91
|
-
* Useful for very fast middleware that just needs allow/block
|
|
92
|
-
*/
|
|
93
|
-
async quickCheck(input) {
|
|
94
|
-
const result = await this.enforce(input);
|
|
95
|
-
if (!result.success || !result.data) {
|
|
96
|
-
return {
|
|
97
|
-
action: "allow",
|
|
98
|
-
error: result.error?.message
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
return {
|
|
102
|
-
action: result.data.decision.action
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* Check if this client is using edge detection (Gateway Worker)
|
|
107
|
-
*/
|
|
108
|
-
isUsingEdge() {
|
|
109
|
-
return this.useEdge;
|
|
110
|
-
}
|
|
111
|
-
/**
|
|
112
|
-
* Log a detection result to AgentShield database.
|
|
113
|
-
* Use after Gateway Worker detection to persist results.
|
|
114
|
-
* Fire-and-forget - returns immediately without waiting for DB write.
|
|
115
|
-
*
|
|
116
|
-
* @example
|
|
117
|
-
* ```typescript
|
|
118
|
-
* // After receiving Gateway response
|
|
119
|
-
* if (client.isUsingEdge() && response.data?.detection) {
|
|
120
|
-
* client.logDetection({
|
|
121
|
-
* detection: response.data.detection,
|
|
122
|
-
* context: { userAgent, ipAddress, path, url, method }
|
|
123
|
-
* }).catch(err => console.error('Log failed:', err));
|
|
124
|
-
* }
|
|
125
|
-
* ```
|
|
126
|
-
*/
|
|
127
|
-
async logDetection(input) {
|
|
128
|
-
const logEndpoint = this.useEdge ? `${DEFAULT_BASE_URL}/api/v1/log-detection` : `${this.baseUrl}/api/v1/log-detection`;
|
|
129
|
-
try {
|
|
130
|
-
const controller = new AbortController();
|
|
131
|
-
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
132
|
-
try {
|
|
133
|
-
const response = await fetch(logEndpoint, {
|
|
134
|
-
method: "POST",
|
|
135
|
-
headers: {
|
|
136
|
-
"Content-Type": "application/json",
|
|
137
|
-
Authorization: `Bearer ${this.apiKey}`
|
|
138
|
-
},
|
|
139
|
-
body: JSON.stringify({
|
|
140
|
-
detection: {
|
|
141
|
-
isAgent: input.detection.isAgent,
|
|
142
|
-
confidence: input.detection.confidence,
|
|
143
|
-
agentName: input.detection.agentName,
|
|
144
|
-
agentType: input.detection.agentType,
|
|
145
|
-
detectionClass: input.detection.detectionClass,
|
|
146
|
-
verificationMethod: input.detection.verificationMethod,
|
|
147
|
-
reasons: input.detection.reasons
|
|
148
|
-
},
|
|
149
|
-
context: input.context,
|
|
150
|
-
source: input.source || "gateway"
|
|
151
|
-
}),
|
|
152
|
-
signal: controller.signal
|
|
153
|
-
});
|
|
154
|
-
clearTimeout(timeoutId);
|
|
155
|
-
if (!response.ok && this.debug) {
|
|
156
|
-
console.warn("[AgentShield] Log detection returned non-2xx:", response.status);
|
|
157
|
-
}
|
|
158
|
-
} catch (error) {
|
|
159
|
-
clearTimeout(timeoutId);
|
|
160
|
-
throw error;
|
|
161
|
-
}
|
|
162
|
-
} catch (error) {
|
|
163
|
-
if (this.debug) {
|
|
164
|
-
console.error("[AgentShield] Log detection failed:", error);
|
|
165
|
-
}
|
|
166
|
-
throw error;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
};
|
|
170
|
-
var clientInstance = null;
|
|
171
|
-
function getAgentShieldClient(config) {
|
|
172
|
-
if (!clientInstance) {
|
|
173
|
-
const apiKey = config?.apiKey || process.env.AGENTSHIELD_API_KEY;
|
|
174
|
-
if (!apiKey) {
|
|
175
|
-
throw new Error(
|
|
176
|
-
"AgentShield API key is required. Set AGENTSHIELD_API_KEY environment variable or pass apiKey in config."
|
|
177
|
-
);
|
|
178
|
-
}
|
|
179
|
-
clientInstance = new AgentShieldClient({
|
|
180
|
-
apiKey,
|
|
181
|
-
baseUrl: config?.baseUrl || process.env.AGENTSHIELD_API_URL,
|
|
182
|
-
// Default to edge detection unless explicitly disabled
|
|
183
|
-
useEdge: config?.useEdge ?? process.env.AGENTSHIELD_USE_EDGE !== "false",
|
|
184
|
-
timeout: config?.timeout,
|
|
185
|
-
debug: config?.debug || process.env.AGENTSHIELD_DEBUG === "true"
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
return clientInstance;
|
|
189
|
-
}
|
|
190
|
-
function resetAgentShieldClient() {
|
|
191
|
-
clientInstance = null;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
export { AgentShieldClient, getAgentShieldClient, resetAgentShieldClient };
|
|
195
|
-
//# sourceMappingURL=api-client.mjs.map
|
|
196
|
-
//# sourceMappingURL=api-client.mjs.map
|
package/dist/api-client.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/api-client.ts"],"names":[],"mappings":"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","file":"api-client.mjs","sourcesContent":["/**\n * AgentShield API Client\n *\n * Lightweight client for calling the AgentShield enforce API from middleware.\n * Designed for Edge Runtime compatibility (no Node.js-specific APIs).\n */\n\nimport type { EnforcementAction } from '@kya-os/agentshield-shared';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * API client configuration\n */\nexport interface AgentShieldClientConfig {\n /** API key for authentication */\n apiKey: string;\n /** API base URL (defaults to production) */\n baseUrl?: string;\n /**\n * Use edge detection for lower latency (~30-50ms vs ~150ms) and better coverage.\n * Edge detection can identify non-JS clients (curl, Python, Claude Code WebFetch)\n * that the pixel cannot detect since they don't execute JavaScript.\n * @default true\n */\n useEdge?: boolean;\n /** Request timeout in milliseconds (default: 5000) */\n timeout?: number;\n /** Enable debug logging */\n debug?: boolean;\n}\n\n/**\n * Enforcement action — re-exported from `@kya-os/agentshield-shared`\n * so consumers of this package can keep importing it from the same\n * place. The canonical 6-value union is defined in\n * `packages/agentshield-shared/src/policy/constants.ts`. `'instruct'`\n * tells the middleware to emit a 401 with an MCP-I Link header\n * pointing the agent at a connect/consent URL.\n */\nexport type { EnforcementAction };\n\n/**\n * Enforcement decision from the API\n */\nexport interface EnforcementDecision {\n action: EnforcementAction;\n reason: string;\n isAgent: boolean;\n confidence: number;\n agentName?: string;\n agentType?: string;\n redirectUrl?: string;\n message?: string;\n metadata?: {\n policyVersion?: string;\n signatureVerified?: boolean;\n denyListMatch?: {\n clientDid?: string;\n agentDid?: string;\n clientName?: string;\n reason?: string;\n };\n };\n}\n\n/**\n * Detection result (optional in response)\n */\nexport interface DetectionResult {\n isAgent: boolean;\n confidence: number;\n agentName?: string;\n agentType?: string;\n /** Detection class: 'human', 'ai_agent', 'bot', 'incomplete_data' */\n detectionClass?: string;\n verificationMethod?: string;\n reasons?: string[];\n /** Detection engine used: 'wasm' or 'javascript-fallback' */\n detectionMethod?: string;\n}\n\n/**\n * Enforce API response\n */\nexport interface EnforceResponse {\n success: boolean;\n data?: {\n decision: EnforcementDecision;\n processingTimeMs: number;\n requestId: string;\n detection?: DetectionResult;\n };\n error?: {\n code: string;\n message: string;\n };\n}\n\n/**\n * Request input for enforce API\n */\nexport interface EnforceInput {\n /** HTTP headers from the incoming request */\n headers?: Record<string, string>;\n /** User-Agent header */\n userAgent?: string;\n /** Client IP address */\n ipAddress?: string;\n /** Request path */\n path?: string;\n /** Request URL */\n url?: string;\n /** HTTP method */\n method?: string;\n /** Request ID for tracing */\n requestId?: string;\n /** Options */\n options?: {\n /** Include full detection result */\n includeDetectionResult?: boolean;\n /** Cache TTL override */\n cacheTTL?: number;\n };\n}\n\n/**\n * Input for logging a detection result\n */\nexport interface LogDetectionInput {\n /** Detection result from Gateway */\n detection: DetectionResult;\n /** Request context */\n context: {\n userAgent?: string;\n ipAddress?: string;\n path?: string;\n url?: string;\n method?: string;\n };\n /** Source of the detection */\n source?: 'gateway' | 'middleware';\n}\n\n// ============================================================================\n// Client Implementation\n// ============================================================================\n\nconst DEFAULT_BASE_URL = 'https://kya.vouched.id';\nconst EDGE_DETECT_URL = 'https://detect.checkpoint-gateway.ai';\nconst DEFAULT_TIMEOUT = 5000;\n\n/**\n * AgentShield API Client\n *\n * @example\n * ```typescript\n * const client = new AgentShieldClient({\n * apiKey: process.env.AGENTSHIELD_API_KEY!,\n * });\n *\n * const result = await client.enforce({\n * headers: Object.fromEntries(request.headers),\n * path: request.nextUrl.pathname,\n * method: request.method,\n * });\n *\n * if (result.decision.action === 'block') {\n * return new Response('Access denied', { status: 403 });\n * }\n * ```\n */\nexport class AgentShieldClient {\n private apiKey: string;\n private baseUrl: string;\n private useEdge: boolean;\n private timeout: number;\n private debug: boolean;\n\n constructor(config: AgentShieldClientConfig) {\n if (!config.apiKey) {\n throw new Error('AgentShield API key is required');\n }\n\n this.apiKey = config.apiKey;\n // Default to edge detection for better coverage (detects non-JS clients)\n this.useEdge = config.useEdge !== false; // true by default\n this.baseUrl = config.baseUrl || (this.useEdge ? EDGE_DETECT_URL : DEFAULT_BASE_URL);\n this.timeout = config.timeout || DEFAULT_TIMEOUT;\n this.debug = config.debug || false;\n }\n\n /**\n * Call the enforce API to check if a request should be allowed\n */\n async enforce(input: EnforceInput): Promise<EnforceResponse> {\n const startTime = Date.now();\n\n try {\n // Create abort controller for timeout\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n // Use edge endpoint or Vercel API based on configuration\n const endpoint = this.useEdge\n ? `${this.baseUrl}/__detect/enforce`\n : `${this.baseUrl}/api/v1/enforce`;\n\n const response = await fetch(endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.apiKey}`,\n 'X-Request-ID': input.requestId || crypto.randomUUID(),\n },\n body: JSON.stringify(input),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n // Parse response\n const data = (await response.json()) as EnforceResponse;\n\n if (this.debug) {\n console.log('[AgentShield] Enforce response:', {\n status: response.status,\n action: data.data?.decision.action,\n processingTimeMs: Date.now() - startTime,\n });\n }\n\n // Handle non-2xx responses\n if (!response.ok) {\n return {\n success: false,\n error: {\n code: `HTTP_${response.status}`,\n message: data.error?.message || `HTTP error: ${response.status}`,\n },\n };\n }\n\n return data;\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n } catch (error) {\n // Handle timeout\n if (error instanceof Error && error.name === 'AbortError') {\n if (this.debug) {\n console.warn('[AgentShield] Request timed out');\n }\n return {\n success: false,\n error: {\n code: 'TIMEOUT',\n message: `Request timed out after ${this.timeout}ms`,\n },\n };\n }\n\n // Handle network errors\n if (this.debug) {\n console.error('[AgentShield] Request failed:', error);\n }\n\n return {\n success: false,\n error: {\n code: 'NETWORK_ERROR',\n message: error instanceof Error ? error.message : 'Network request failed',\n },\n };\n }\n }\n\n /**\n * Quick check - returns just the action without full response parsing\n * Useful for very fast middleware that just needs allow/block\n */\n async quickCheck(input: EnforceInput): Promise<{\n action: EnforcementAction;\n error?: string;\n }> {\n const result = await this.enforce(input);\n\n if (!result.success || !result.data) {\n // On error, default to allow (fail-open)\n return {\n action: 'allow',\n error: result.error?.message,\n };\n }\n\n return {\n action: result.data.decision.action,\n };\n }\n\n /**\n * Check if this client is using edge detection (Gateway Worker)\n */\n isUsingEdge(): boolean {\n return this.useEdge;\n }\n\n /**\n * Log a detection result to AgentShield database.\n * Use after Gateway Worker detection to persist results.\n * Fire-and-forget - returns immediately without waiting for DB write.\n *\n * @example\n * ```typescript\n * // After receiving Gateway response\n * if (client.isUsingEdge() && response.data?.detection) {\n * client.logDetection({\n * detection: response.data.detection,\n * context: { userAgent, ipAddress, path, url, method }\n * }).catch(err => console.error('Log failed:', err));\n * }\n * ```\n */\n async logDetection(input: LogDetectionInput): Promise<void> {\n // Don't await - fire and forget\n // Use the base URL (not edge) for logging since this goes to the main API\n const logEndpoint = this.useEdge\n ? `${DEFAULT_BASE_URL}/api/v1/log-detection`\n : `${this.baseUrl}/api/v1/log-detection`;\n\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(logEndpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify({\n detection: {\n isAgent: input.detection.isAgent,\n confidence: input.detection.confidence,\n agentName: input.detection.agentName,\n agentType: input.detection.agentType,\n detectionClass: input.detection.detectionClass,\n verificationMethod: input.detection.verificationMethod,\n reasons: input.detection.reasons,\n },\n context: input.context,\n source: input.source || 'gateway',\n }),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok && this.debug) {\n console.warn('[AgentShield] Log detection returned non-2xx:', response.status);\n }\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n } catch (error) {\n // Silently fail for fire-and-forget, but log in debug mode\n if (this.debug) {\n console.error('[AgentShield] Log detection failed:', error);\n }\n // Re-throw so caller can catch if needed\n throw error;\n }\n }\n}\n\n/**\n * Create a singleton client instance\n *\n * @example\n * ```typescript\n * // In middleware.ts\n * import { getAgentShieldClient } from '@kya-os/agentshield-nextjs';\n *\n * const client = getAgentShieldClient();\n * ```\n */\nlet clientInstance: AgentShieldClient | null = null;\n\nexport function getAgentShieldClient(config?: Partial<AgentShieldClientConfig>): AgentShieldClient {\n if (!clientInstance) {\n const apiKey = config?.apiKey || process.env.AGENTSHIELD_API_KEY;\n\n if (!apiKey) {\n throw new Error(\n 'AgentShield API key is required. Set AGENTSHIELD_API_KEY environment variable or pass apiKey in config.'\n );\n }\n\n clientInstance = new AgentShieldClient({\n apiKey,\n baseUrl: config?.baseUrl || process.env.AGENTSHIELD_API_URL,\n // Default to edge detection unless explicitly disabled\n useEdge: config?.useEdge ?? process.env.AGENTSHIELD_USE_EDGE !== 'false',\n timeout: config?.timeout,\n debug: config?.debug || process.env.AGENTSHIELD_DEBUG === 'true',\n });\n }\n\n return clientInstance;\n}\n\n/**\n * Reset the singleton client (useful for testing)\n */\nexport function resetAgentShieldClient(): void {\n clientInstance = null;\n}\n"]}
|