/**
 * Mode switching policy shared by tools and slash commands.
 *
 * The switch_mode tool is only one delivery surface for this behavior.
 * The actual mode registry, validation, confirmation, and side effects live here.
 */
import chalk from 'chalk';
import { getCurrentMode, MODE, setCurrentMode } from '../../mode-names.js';
import { getMode, getModeNames } from './index.js';
export function requiresModeSwitchConfirmation(currentMode, targetMode) {
    return ((currentMode === MODE.ACTION && targetMode === MODE.PLAN) ||
        (currentMode === MODE.PLAN && targetMode === MODE.ACTION));
}
function formatModeName(mode) {
    return mode.length > 0 ? mode.charAt(0).toUpperCase() + mode.slice(1) : mode;
}
async function confirmModeSwitch(currentMode, targetMode, reason, ctx) {
    if (!ctx?.hasUI)
        return true;
    const title = chalk.green(`Switch from ${formatModeName(currentMode)} to ${formatModeName(targetMode)}`);
    const trimmedReason = reason?.trim();
    const message = trimmedReason ? `${title}\n\n${trimmedReason}` : title;
    return (await ctx.ui.select(message, ['Confirm', 'Cancel'])) === 'Confirm';
}
function applyModeSwitch(session, target, settings) {
    const previousMode = getCurrentMode();
    setCurrentMode(target.name);
    session.applyMode([...target.tools], target.systemPrompt, target.name);
    // Installation mode always auto-approves edits; restore user default only
    // when leaving installation mode (so a user-toggled yolo mode is preserved).
    if (settings) {
        if (target.name === MODE.INSTALLATION) {
            settings.setAutoApprove(true);
        }
        else if (previousMode === MODE.INSTALLATION) {
            settings.setAutoApprove(settings.getAutoApproveDefault());
        }
    }
    // Snapshot the new system prompt + tools into the session trace so the
    // JSONL reflects the mode switch (otherwise only the initial prompt is recorded).
    session.sessionManager.appendSystemPrompt(session.systemPrompt);
    session.sessionManager.appendToolDefinitions(session.agent.state.tools.map((tool) => ({
        name: tool.name,
        description: tool.description,
        parameters: tool.parameters
    })));
}
export async function switchMode(session, modeName, opts = {}) {
    const { settings, reason, ctx, confirm, force } = opts;
    const currentMode = getCurrentMode();
    if (modeName === currentMode) {
        return { ok: false, message: `Already in ${currentMode} mode.` };
    }
    const target = getMode(modeName);
    if (!target) {
        return {
            ok: false,
            message: `Unknown mode "${modeName}". Available: ${getModeNames().join(', ')}`
        };
    }
    // Manage is a sink for the tool/agent path. User-initiated switches (force=true)
    // can always leave any mode.
    if (currentMode === MODE.MANAGE && !force) {
        return {
            ok: false,
            message: `Cannot switch from ${currentMode} to ${modeName}. Allowed: none`
        };
    }
    // Enforce switchTo constraints (tool path only — slash commands bypass).
    if (!force) {
        const current = getMode(currentMode);
        const allowedTargets = current?.switchTo ?? [];
        if (!allowedTargets.includes(modeName)) {
            return {
                ok: false,
                message: `Cannot switch from ${currentMode} to ${modeName}. Allowed: ${allowedTargets.join(', ') || 'none'}`
            };
        }
    }
    if (requiresModeSwitchConfirmation(currentMode, target.name)) {
        const confirmed = confirm
            ? await confirm({ currentMode, targetMode: target.name, reason, ctx })
            : await confirmModeSwitch(currentMode, target.name, reason, ctx);
        if (!confirmed) {
            return { ok: false, message: 'User cancelled the mode switch.' };
        }
    }
    applyModeSwitch(session, target, settings);
    const reasonText = reason ? `\nReason: ${reason}` : '';
    return { ok: true, message: `Switched to ${target.name} mode.${reasonText}` };
}
//# sourceMappingURL=switch-mode.js.map