/** Commands we refuse outright, even with --yolo. */
const DENYLIST = [
    /\brm\s+(-[a-z]*[rf][a-z]*\s+)+\/(\s|$)/i, // rm -rf /
    /\bmkfs\b/i,
    /\bdd\s+.*of=\/dev\//i,
    /\bshutdown\b|\breboot\b|\bhalt\b/i,
    /:\(\)\s*\{\s*:\|:&\s*\};:/, // fork bomb
    /\bchmod\s+(-[a-z]+\s+)*777\s+\//i,
];
export function isDenied(toolName, input) {
    if (toolName !== 'bash')
        return null;
    const cmd = String(input?.command ?? '');
    for (const re of DENYLIST) {
        if (re.test(cmd))
            return `command blocked by CheapCode's denylist: ${re}`;
    }
    return null;
}
export class PermissionGate {
    handler;
    yolo;
    alwaysAllowed = new Set();
    constructor(handler, yolo) {
        this.handler = handler;
        this.yolo = yolo;
    }
    /** Returns null if allowed, or a refusal message for the model if denied. */
    async check(tool, input) {
        const denied = isDenied(tool.name, input);
        if (denied)
            return denied;
        if (tool.readOnly || this.yolo || this.alwaysAllowed.has(tool.name))
            return null;
        const decision = await this.handler(tool, tool.summarize(input));
        if (decision === 'always') {
            this.alwaysAllowed.add(tool.name);
            return null;
        }
        if (decision === 'yes')
            return null;
        return 'The user denied this tool call. Ask them how to proceed if unclear.';
    }
}
