// ElizaOS guard: run ScanPay before an Eliza agent executes generated code. // Uses the prepaid credit pack (POST /api/v1/credits-micro -> X-API-Key), so the agent // does not need a per-call x402 client. Or use @x402/fetch with wrapFetchWithPaymentFromConfig. import type { Action } from "@elizaos/core"; const SCANPAY = "https://scanpay-edge.alextaghiashvili.workers.dev"; export const scanpayGuard: Action = { name: "SCANPAY_GUARD", description: "Before running generated Python/JS/TS, scan it for dangerous constructs.", similes: ["scan code", "security check before execution"], validate: async (_runtime, message) => /```|def |function |eval\(/.test(message.content.text ?? ""), handler: async (_runtime, message) => { const code = String(message.content.text ?? ""); const res = await fetch(SCANPAY + "/api/v1/key/scan", { method: "POST", headers: { "Content-Type": "application/json", "X-API-Key": process.env.SCANPAY_API_KEY ?? "" }, body: JSON.stringify({ source_code: code, language: code.includes("function") ? "javascript" : "python" }), }); const data = await res.json(); if (res.status === 402) return { text: "No ScanPay credits left — buy POST /api/v1/credits-micro ($0.10/5 scans)." }; const blocked = (data.findings ?? []).some((f: any) => f.severity === "critical" || f.severity === "high"); return { text: blocked ? `BLOCK: ${data.findings_count} finding(s), max ${data.max_severity}. Do not execute.` : `PASS: ${data.findings_count} finding(s). Safe enough to continue.`, metadata: { findings: data.findings }, }; }, };