UNPKG

@kya-os/agentshield-nextjs

Version:

Next.js middleware for AgentShield AI agent detection

196 lines (195 loc) 6.33 kB
// src/api-client.ts var DEFAULT_BASE_URL = "https://kya.vouched.id"; var EDGE_DETECT_URL = "https://detect.checkpoint-gateway.ai"; var DEFAULT_TIMEOUT = 5e3; var AgentShieldClient = class { apiKey; baseUrl; useEdge; timeout; debug; constructor(config) { if (!config.apiKey) { throw new Error("AgentShield API key is required"); } this.apiKey = config.apiKey; this.useEdge = config.useEdge !== false; this.baseUrl = config.baseUrl || (this.useEdge ? EDGE_DETECT_URL : DEFAULT_BASE_URL); this.timeout = config.timeout || DEFAULT_TIMEOUT; this.debug = config.debug || false; } /** * Call the enforce API to check if a request should be allowed */ async enforce(input) { const startTime = Date.now(); try { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), this.timeout); try { const endpoint = this.useEdge ? `${this.baseUrl}/__detect/enforce` : `${this.baseUrl}/api/v1/enforce`; const response = await fetch(endpoint, { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${this.apiKey}`, "X-Request-ID": input.requestId || crypto.randomUUID() }, body: JSON.stringify(input), signal: controller.signal }); clearTimeout(timeoutId); const data = await response.json(); if (this.debug) { console.log("[AgentShield] Enforce response:", { status: response.status, action: data.data?.decision.action, processingTimeMs: Date.now() - startTime }); } if (!response.ok) { return { success: false, error: { code: `HTTP_${response.status}`, message: data.error?.message || `HTTP error: ${response.status}` } }; } return data; } catch (error) { clearTimeout(timeoutId); throw error; } } catch (error) { if (error instanceof Error && error.name === "AbortError") { if (this.debug) { console.warn("[AgentShield] Request timed out"); } return { success: false, error: { code: "TIMEOUT", message: `Request timed out after ${this.timeout}ms` } }; } if (this.debug) { console.error("[AgentShield] Request failed:", error); } return { success: false, error: { code: "NETWORK_ERROR", message: error instanceof Error ? error.message : "Network request failed" } }; } } /** * Quick check - returns just the action without full response parsing * Useful for very fast middleware that just needs allow/block */ async quickCheck(input) { const result = await this.enforce(input); if (!result.success || !result.data) { return { action: "allow", error: result.error?.message }; } return { action: result.data.decision.action }; } /** * Check if this client is using edge detection (Gateway Worker) */ isUsingEdge() { return this.useEdge; } /** * 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)); * } * ``` */ async logDetection(input) { const logEndpoint = this.useEdge ? `${DEFAULT_BASE_URL}/api/v1/log-detection` : `${this.baseUrl}/api/v1/log-detection`; try { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), this.timeout); try { const response = await fetch(logEndpoint, { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${this.apiKey}` }, body: JSON.stringify({ detection: { isAgent: input.detection.isAgent, confidence: input.detection.confidence, agentName: input.detection.agentName, agentType: input.detection.agentType, detectionClass: input.detection.detectionClass, verificationMethod: input.detection.verificationMethod, reasons: input.detection.reasons }, context: input.context, source: input.source || "gateway" }), signal: controller.signal }); clearTimeout(timeoutId); if (!response.ok && this.debug) { console.warn("[AgentShield] Log detection returned non-2xx:", response.status); } } catch (error) { clearTimeout(timeoutId); throw error; } } catch (error) { if (this.debug) { console.error("[AgentShield] Log detection failed:", error); } throw error; } } }; var clientInstance = null; function getAgentShieldClient(config) { if (!clientInstance) { const apiKey = config?.apiKey || process.env.AGENTSHIELD_API_KEY; if (!apiKey) { throw new Error( "AgentShield API key is required. Set AGENTSHIELD_API_KEY environment variable or pass apiKey in config." ); } clientInstance = new AgentShieldClient({ apiKey, baseUrl: config?.baseUrl || process.env.AGENTSHIELD_API_URL, // Default to edge detection unless explicitly disabled useEdge: config?.useEdge ?? process.env.AGENTSHIELD_USE_EDGE !== "false", timeout: config?.timeout, debug: config?.debug || process.env.AGENTSHIELD_DEBUG === "true" }); } return clientInstance; } function resetAgentShieldClient() { clientInstance = null; } export { AgentShieldClient, getAgentShieldClient, resetAgentShieldClient }; //# sourceMappingURL=api-client.mjs.map //# sourceMappingURL=api-client.mjs.map