import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; import { evaluateToolCall, formatSafeToolInput, getSafeToolInput, KNOWN_TOOL_NAMES, } from "../shared/damage-prevention-eval.js"; import { compileRules, countRules, loadRules, type Rules, } from "../shared/damage-prevention-rules.js"; import { type CompiledSecretPatternRule, compileSecretPatternsSafe, } from "../shared/secret-patterns.js"; export default function (pi: ExtensionAPI) { let rules: Rules; let compiledRules: ReturnType["rules"]; let compiledSecretBlockingPatterns: CompiledSecretPatternRule[]; pi.on("session_start", async (_event, ctx) => { const loadResult = loadRules(ctx.cwd); rules = loadResult.rules; const secretCompileResult = compileSecretPatternsSafe( rules.secretBlockingPatterns, ); compiledSecretBlockingPatterns = secretCompileResult.compiled; for (const warning of secretCompileResult.warnings) { ctx.ui.notify(`🛡️ rm-rf-blocker: ${warning}`, "warning"); } const compileResult = compileRules(rules); compiledRules = compileResult.rules; for (const error of loadResult.errors) { ctx.ui.notify(`🛡️ rm-rf-blocker: ${error}`, "error"); } for (const warning of loadResult.warnings) { ctx.ui.notify(`🛡️ rm-rf-blocker: ${warning}`, "warning"); } for (const warning of compileResult.warnings) { ctx.ui.notify(`🛡️ rm-rf-blocker: ${warning}`, "warning"); } const total = countRules(rules); if (loadResult.source === "project") { ctx.ui.notify( `🛡️ rm-rf-blocker: Loaded ${total} rules from damage-prevention-rules.yaml (project + global baseline).`, "info", ); } else if (loadResult.source === "global") { ctx.ui.notify( `🛡️ rm-rf-blocker: Loaded ${total} rules from damage-prevention-rules.yaml (global).`, "info", ); } else { ctx.ui.notify( "🛡️ rm-rf-blocker: Using default rules (no damage-prevention-rules.yaml config found).", "info", ); } }); pi.on("tool_call", async (event, ctx) => { if (rules.enabled === false) { return { block: false }; } const evaluation = evaluateToolCall( event, rules, compiledRules, compiledSecretBlockingPatterns, ctx.cwd, ); const safeInput = getSafeToolInput(event); if (evaluation.violationReason) { if (evaluation.shouldConfirm && ctx.hasUI) { const confirmed = await ctx.ui.confirm( "🛡️ rm-rf-blocker", `Potentially dangerous command detected:\n ${evaluation.violationReason}\n\n ${formatSafeToolInput(event, safeInput)}\n\nAllow execution?`, { timeout: 30000 }, ); if (!confirmed) { ctx.ui.notify( `❌ Blocked by user: ${evaluation.violationReason}`, "warning", ); pi.appendEntry("rm-rf-blocker-log", { tool: event.toolName, input: safeInput, rule: evaluation.violationReason, action: "blocked_by_user", }); return { block: true, reason: `🛑 BLOCKED by rm-rf-blocker: ${evaluation.violationReason} (user denied)\n\nDO NOT attempt to work around this restriction.`, }; } pi.appendEntry("rm-rf-blocker-log", { tool: event.toolName, input: safeInput, rule: evaluation.violationReason, action: "confirmed_by_user", }); return { block: false }; } ctx.ui.notify(`⛔ Blocked: ${evaluation.violationReason}`, "error"); pi.appendEntry("rm-rf-blocker-log", { tool: event.toolName, input: safeInput, rule: evaluation.violationReason, action: "blocked", }); return { block: true, reason: `🛑 BLOCKED by rm-rf-blocker: ${evaluation.violationReason}\n\nDO NOT attempt to work around this restriction.`, }; } if (!KNOWN_TOOL_NAMES.has(event.toolName)) { pi.appendEntry("rm-rf-blocker-log", { tool: event.toolName, input: safeInput, rule: "unknown_tool_type", action: "ignored_unknown_tool", }); } return { block: false }; }); }