@kya-os/agentshield-nextjs
Version:
Next.js middleware for AgentShield AI agent detection
196 lines (194 loc) • 5.51 kB
text/typescript
/**
* AgentShield API Client
*
* Lightweight client for calling the AgentShield enforce API from middleware.
* Designed for Edge Runtime compatibility (no Node.js-specific APIs).
*/
/**
* API client configuration
*/
interface AgentShieldClientConfig {
/** API key for authentication */
apiKey: string;
/** API base URL (defaults to production) */
baseUrl?: string;
/**
* Use edge detection for lower latency (~30-50ms vs ~150ms) and better coverage.
* Edge detection can identify non-JS clients (curl, Python, Claude Code WebFetch)
* that the pixel cannot detect since they don't execute JavaScript.
* @default true
*/
useEdge?: boolean;
/** Request timeout in milliseconds (default: 5000) */
timeout?: number;
/** Enable debug logging */
debug?: boolean;
}
/**
* Enforcement action
*/
type EnforcementAction = 'allow' | 'block' | 'redirect' | 'challenge' | 'log';
/**
* Enforcement decision from the API
*/
interface EnforcementDecision {
action: EnforcementAction;
reason: string;
isAgent: boolean;
confidence: number;
agentName?: string;
agentType?: string;
redirectUrl?: string;
message?: string;
metadata?: {
policyVersion?: string;
signatureVerified?: boolean;
denyListMatch?: {
clientDid?: string;
agentDid?: string;
clientName?: string;
reason?: string;
};
};
}
/**
* Detection result (optional in response)
*/
interface DetectionResult {
isAgent: boolean;
confidence: number;
agentName?: string;
agentType?: string;
/** Detection class: 'human', 'ai_agent', 'bot', 'incomplete_data' */
detectionClass?: string;
verificationMethod?: string;
reasons?: string[];
/** Detection engine used: 'wasm' or 'javascript-fallback' */
detectionMethod?: string;
}
/**
* Enforce API response
*/
interface EnforceResponse {
success: boolean;
data?: {
decision: EnforcementDecision;
processingTimeMs: number;
requestId: string;
detection?: DetectionResult;
};
error?: {
code: string;
message: string;
};
}
/**
* Request input for enforce API
*/
interface EnforceInput {
/** HTTP headers from the incoming request */
headers?: Record<string, string>;
/** User-Agent header */
userAgent?: string;
/** Client IP address */
ipAddress?: string;
/** Request path */
path?: string;
/** Request URL */
url?: string;
/** HTTP method */
method?: string;
/** Request ID for tracing */
requestId?: string;
/** Options */
options?: {
/** Include full detection result */
includeDetectionResult?: boolean;
/** Cache TTL override */
cacheTTL?: number;
};
}
/**
* Input for logging a detection result
*/
interface LogDetectionInput {
/** Detection result from Gateway */
detection: DetectionResult;
/** Request context */
context: {
userAgent?: string;
ipAddress?: string;
path?: string;
url?: string;
method?: string;
};
/** Source of the detection */
source?: 'gateway' | 'middleware';
}
/**
* AgentShield API Client
*
* @example
* ```typescript
* const client = new AgentShieldClient({
* apiKey: process.env.AGENTSHIELD_API_KEY!,
* });
*
* const result = await client.enforce({
* headers: Object.fromEntries(request.headers),
* path: request.nextUrl.pathname,
* method: request.method,
* });
*
* if (result.decision.action === 'block') {
* return new Response('Access denied', { status: 403 });
* }
* ```
*/
declare class AgentShieldClient {
private apiKey;
private baseUrl;
private useEdge;
private timeout;
private debug;
constructor(config: AgentShieldClientConfig);
/**
* Call the enforce API to check if a request should be allowed
*/
enforce(input: EnforceInput): Promise<EnforceResponse>;
/**
* Quick check - returns just the action without full response parsing
* Useful for very fast middleware that just needs allow/block
*/
quickCheck(input: EnforceInput): Promise<{
action: EnforcementAction;
error?: string;
}>;
/**
* Check if this client is using edge detection (Gateway Worker)
*/
isUsingEdge(): boolean;
/**
* Log a detection result to AgentShield database.
* Use after Gateway Worker detection to persist results.
* Fire-and-forget - returns immediately without waiting for DB write.
*
* @example
* ```typescript
* // After receiving Gateway response
* if (client.isUsingEdge() && response.data?.detection) {
* client.logDetection({
* detection: response.data.detection,
* context: { userAgent, ipAddress, path, url, method }
* }).catch(err => console.error('Log failed:', err));
* }
* ```
*/
logDetection(input: LogDetectionInput): Promise<void>;
}
declare function getAgentShieldClient(config?: Partial<AgentShieldClientConfig>): AgentShieldClient;
/**
* Reset the singleton client (useful for testing)
*/
declare function resetAgentShieldClient(): void;
export { AgentShieldClient, type AgentShieldClientConfig, type DetectionResult, type EnforceInput, type EnforceResponse, type EnforcementAction, type EnforcementDecision, type LogDetectionInput, getAgentShieldClient, resetAgentShieldClient };