/**
 * Permission Modes
 *
 * Five-tier permission system: default, plan, acceptEdits, dontAsk, bypassPermissions.
 * With managed setting to disable bypass, subagent-specific modes, and pattern-based allowlists.
 */
import { logger } from '../utils/logger.js';
// ============================================================================
// Tool Classifications
// ============================================================================
const READ_ONLY_TOOLS = new Set([
    'view_file',
    'read_file',
    'search',
    'list_files',
    'grep',
    'glob',
    'git_log',
    'git_status',
    'git_diff',
]);
const EDIT_TOOLS = new Set([
    'str_replace_editor',
    'create_file',
    'write_file',
    'edit_file',
    'apply_patch',
    'multi_edit',
]);
const DESTRUCTIVE_TOOLS = new Set([
    'bash',
    'delete_file',
    'rm',
    'git_reset',
    'git_checkout',
]);
// ============================================================================
// Permission Mode Manager
// ============================================================================
export class PermissionModeManager {
    config;
    allowedPatterns = [];
    constructor(config) {
        this.config = {
            mode: config?.mode || 'default',
            disableBypass: config?.disableBypass ?? false,
            subagentMode: config?.subagentMode,
        };
    }
    /**
     * Set the permission mode
     * Returns false if trying to set bypassPermissions when it's disabled
     */
    setMode(mode) {
        if (mode === 'bypassPermissions' && this.config.disableBypass) {
            logger.warn('Cannot enable bypassPermissions: disabled by managed setting');
            return false;
        }
        this.config.mode = mode;
        logger.info(`Permission mode set to: ${mode}`);
        return true;
    }
    getMode() {
        return this.config.mode;
    }
    /**
     * Check permission for an action
     */
    checkPermission(action, toolName) {
        // Check pattern allowlist first
        if (this.isPatternAllowed(action)) {
            return { allowed: true, reason: 'Matched allowed pattern', prompted: false };
        }
        switch (this.config.mode) {
            case 'default':
                return this.checkDefault(action, toolName);
            case 'plan':
                return this.checkPlan(action, toolName);
            case 'acceptEdits':
                return this.checkAcceptEdits(action, toolName);
            case 'dontAsk':
                return this.checkDontAsk(action, toolName);
            case 'bypassPermissions':
                return this.checkBypass(action, toolName);
            default:
                return this.checkDefault(action, toolName);
        }
    }
    /**
     * Default mode: prompt for everything except read-only
     */
    checkDefault(_action, toolName) {
        if (this.isReadOnlyTool(toolName)) {
            return { allowed: true, reason: 'Read-only tool auto-approved', prompted: false };
        }
        return { allowed: true, reason: 'Requires user confirmation', prompted: true };
    }
    /**
     * Plan mode: only allow read-only tools, block edits and destructive
     */
    checkPlan(_action, toolName) {
        if (this.isReadOnlyTool(toolName)) {
            return { allowed: true, reason: 'Read-only tool allowed in plan mode', prompted: false };
        }
        return { allowed: false, reason: 'Only read-only tools allowed in plan mode', prompted: false };
    }
    /**
     * Accept edits mode: auto-approve read and edit tools, prompt for destructive
     */
    checkAcceptEdits(_action, toolName) {
        if (this.isReadOnlyTool(toolName)) {
            return { allowed: true, reason: 'Read-only tool auto-approved', prompted: false };
        }
        if (this.isEditTool(toolName)) {
            return { allowed: true, reason: 'Edit tool auto-approved in acceptEdits mode', prompted: false };
        }
        if (this.isDestructiveTool(toolName)) {
            return { allowed: true, reason: 'Destructive tool requires confirmation', prompted: true };
        }
        return { allowed: true, reason: 'Requires confirmation', prompted: true };
    }
    /**
     * Don't ask mode: auto-approve everything except destructive
     */
    checkDontAsk(_action, toolName) {
        if (this.isDestructiveTool(toolName)) {
            return { allowed: true, reason: 'Destructive tool requires confirmation in dontAsk mode', prompted: true };
        }
        return { allowed: true, reason: 'Auto-approved in dontAsk mode', prompted: false };
    }
    /**
     * Bypass mode: auto-approve everything
     */
    checkBypass(_action, _toolName) {
        return { allowed: true, reason: 'All operations auto-approved in bypass mode', prompted: false };
    }
    /**
     * Tool classification
     */
    isReadOnlyTool(toolName) {
        return READ_ONLY_TOOLS.has(toolName);
    }
    isEditTool(toolName) {
        return EDIT_TOOLS.has(toolName);
    }
    isDestructiveTool(toolName) {
        return DESTRUCTIVE_TOOLS.has(toolName);
    }
    /**
     * Add an allowed pattern
     */
    addAllowedPattern(pattern) {
        if (!this.allowedPatterns.includes(pattern)) {
            this.allowedPatterns.push(pattern);
        }
    }
    /**
     * Check if an action matches any allowed pattern
     */
    isPatternAllowed(action) {
        return this.allowedPatterns.some(pattern => {
            // Convert glob-like pattern to regex
            const regex = pattern
                .replace(/[.+^${}()|[\]\\]/g, '\\$&')
                .replace(/\*/g, '.*');
            return new RegExp(`^${regex}$`).test(action);
        });
    }
    /**
     * Set subagent mode
     */
    setSubagentMode(mode) {
        this.config.subagentMode = mode;
        logger.info(`Subagent permission mode set to: ${mode}`);
    }
    getSubagentMode() {
        return this.config.subagentMode || this.config.mode;
    }
    /**
     * Set bypass disabled (managed setting)
     */
    setBypassDisabled(disabled) {
        this.config.disableBypass = disabled;
        // If bypass was active and we're disabling it, revert to default
        if (disabled && this.config.mode === 'bypassPermissions') {
            this.config.mode = 'default';
            logger.warn('Bypass was active but has been disabled, reverting to default mode');
        }
        logger.info(`Bypass disabled: ${disabled}`);
    }
    isBypassDisabled() {
        return this.config.disableBypass;
    }
}
//# sourceMappingURL=permission-modes.js.map