UNPKG

@kya-os/agentshield-nextjs

Version:

Next.js middleware for AgentShield AI agent detection

127 lines (123 loc) 3.92 kB
import { NextRequest, NextResponse } from 'next/server'; import { EnforcementDecision } from './api-client.js'; /** * API-based AgentShield Middleware for Next.js * * This middleware uses the AgentShield API for detection and enforcement, * instead of running detection locally. This approach: * * 1. Works reliably in Edge Runtime (no WASM loading issues) * 2. Ensures consistent detection across all platforms * 3. Applies centralized policies from the dashboard * 4. Supports deny lists, thresholds, and path rules * * @example * ```typescript * // middleware.ts * import { withAgentShield } from '@kya-os/agentshield-nextjs/api-middleware'; * * export default withAgentShield({ * apiKey: process.env.AGENTSHIELD_API_KEY!, * // Optional overrides: * onBlock: 'redirect', // 'block' | 'redirect' | 'challenge' * redirectUrl: '/blocked', * skipPaths: ['/api/health', '/_next/*'], * }); * * export const config = { * matcher: ['/((?!_next/static|favicon.ico).*)'], * }; * ``` */ /** * Middleware configuration */ interface AgentShieldMiddlewareConfig { /** API key (or use AGENTSHIELD_API_KEY env var) */ apiKey?: string; /** API base URL (defaults to production) */ apiUrl?: 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. * Set to false to use the Vercel API instead. * @default true */ useEdge?: boolean; /** Request timeout in ms (default: 5000) */ timeout?: number; /** * Action to take when an agent should be blocked * - 'block': Return 403 response * - 'redirect': Redirect to redirectUrl * - 'challenge': Show a challenge page (future) * Default: uses policy from dashboard */ onBlock?: 'block' | 'redirect' | 'challenge'; /** * URL to redirect to when blocking (if onBlock is 'redirect') * Default: uses redirectUrl from dashboard policy */ redirectUrl?: string; /** * Custom blocked response */ blockedResponse?: { status?: number; message?: string; headers?: Record<string, string>; }; /** * Paths to skip (in addition to dashboard policy) * Supports glob patterns: '/api/*', '/_next/*' */ skipPaths?: string[]; /** * Only enforce on these paths (overrides dashboard policy) */ includePaths?: string[]; /** * Callback when an agent is detected */ onAgentDetected?: (request: NextRequest, decision: EnforcementDecision) => void | Promise<void>; /** * Callback to customize the blocked response */ customBlockedResponse?: (request: NextRequest, decision: EnforcementDecision) => NextResponse | Promise<NextResponse>; /** * Whether to fail open (allow) on API errors * Default: true (recommended for production) */ failOpen?: boolean; /** * Enable debug logging */ debug?: boolean; } /** * Create AgentShield middleware with API-based detection * * @example * ```typescript * // middleware.ts * import { withAgentShield } from '@kya-os/agentshield-nextjs/api-middleware'; * * export default withAgentShield({ * onBlock: 'block', * skipPaths: ['/api/health'], * }); * ``` */ declare function withAgentShield(config?: AgentShieldMiddlewareConfig): (request: NextRequest) => Promise<NextResponse>; /** * Convenience export for simple setup * * @example * ```typescript * // middleware.ts * export { agentShieldMiddleware as default } from '@kya-os/agentshield-nextjs/api-middleware'; * ``` */ declare const agentShieldMiddleware: (request: NextRequest) => Promise<NextResponse>; export { type AgentShieldMiddlewareConfig, agentShieldMiddleware, withAgentShield };