import path from 'node:path';
import { appendToolDefinitionsToPrompt } from '../ai-sdk-client/tools/system-prompt-assembler.js';
import { getAppConfig } from '../config/index.js';
import { loadPreferences, savePreferences } from '../config/preferences.js';
import { resolveTune } from '../config/tune.js';
import { runPlainConversation } from '../plain/conversation.js';
import { initializePlain } from '../plain/initialize.js';
import { color, writeBoot, writeError, writeLine, writeStatus, } from '../plain/writer.js';
import { getTuneToolMode } from '../types/config.js';
import { formatError } from '../utils/error-formatter.js';
import { buildSystemPrompt, setLastBuiltPrompt } from '../utils/prompt-builder.js';
import { getShutdownManager } from '../utils/shutdown/index.js';
/**
 * Headless equivalent of `nanocoder run "..."`. Skips Ink entirely:
 * the LLM, tool, MCP, and subagent stacks all initialize without React,
 * and the conversation loop streams to stdout via plain process.stdout.
 *
 * Exit codes:
 *   0  conversation completed naturally
 *   1  initialization or generation error
 *   2  tool approval was required (matches the Ink `run` behavior in
 *      `useNonInteractiveMode`)
 */
export async function runPlainShell(options) {
    const { prompt, developmentMode, cliProvider, cliModel, trustDirectory } = options;
    if (!ensureDirectoryTrust(trustDirectory)) {
        await shutdown(1);
        return;
    }
    let init;
    try {
        init = await initializePlain({ cliProvider, cliModel });
    }
    catch (error) {
        writeError(formatError(error));
        await shutdown(1);
        return;
    }
    const { client, toolManager, provider, model } = init;
    writeBoot(provider, model, developmentMode);
    const tune = resolveTune(getAppConfig(), undefined, loadPreferences());
    const tuneToolMode = getTuneToolMode(tune);
    const toolsDisabled = tuneToolMode !== 'native' || isToolCallingDisabled(provider, model);
    const fallbackToolFormat = tuneToolMode === 'json' ? 'json' : 'xml';
    const availableNames = toolManager.getAvailableToolNames(tune, developmentMode, undefined, model);
    const basePrompt = buildSystemPrompt(developmentMode, tune, availableNames, toolsDisabled, getAppConfig().systemPrompt, model);
    const toolsForPrompt = toolsDisabled
        ? toolManager.getFilteredTools(availableNames)
        : {};
    const systemContent = appendToolDefinitionsToPrompt(basePrompt, toolsDisabled, fallbackToolFormat, toolsForPrompt);
    setLastBuiltPrompt(systemContent);
    const systemMessage = { role: 'system', content: systemContent };
    const initialMessages = [{ role: 'user', content: prompt }];
    const abortController = new AbortController();
    const sigint = () => abortController.abort();
    process.on('SIGINT', sigint);
    const nonInteractiveAlwaysAllow = getAppConfig().alwaysAllow ?? [];
    writeLine();
    const outcome = await runPlainConversation({
        client,
        toolManager,
        systemMessage,
        initialMessages,
        developmentMode,
        nonInteractiveAlwaysAllow,
        abortSignal: abortController.signal,
        tune,
        model,
    });
    process.off('SIGINT', sigint);
    switch (outcome.kind) {
        case 'success':
            await shutdown(0);
            return;
        case 'tool-approval-required':
            writeError(`Tool approval required for: ${outcome.toolNames.join(', ')}. ` +
                `Re-run with --mode auto-accept or --mode yolo, or add the tools to ` +
                `agents.config.json "alwaysAllow".`);
            await shutdown(2);
            return;
        case 'error':
            writeError(outcome.message);
            await shutdown(1);
            return;
    }
}
function isToolCallingDisabled(provider, model) {
    const config = getAppConfig();
    const providerConfig = config.providers?.find(p => p.name === provider);
    if (!providerConfig)
        return false;
    return providerConfig.disableToolModels?.includes(model) ?? false;
}
function ensureDirectoryTrust(trustDirectoryFlag) {
    if (trustDirectoryFlag)
        return true;
    const cwd = path.resolve(process.cwd());
    const preferences = loadPreferences();
    const trusted = (preferences.trustedDirectories ?? []).some(dir => path.resolve(dir) === cwd);
    if (trusted)
        return true;
    if (process.env.NANOCODER_TRUST_DIRECTORY === '1') {
        const updated = preferences.trustedDirectories ?? [];
        updated.push(cwd);
        savePreferences({ ...preferences, trustedDirectories: updated });
        writeStatus(`Marked ${cwd} as trusted (NANOCODER_TRUST_DIRECTORY=1).`);
        return true;
    }
    writeError(`Directory ${cwd} is not trusted. Pass --trust-directory or set ` +
        `NANOCODER_TRUST_DIRECTORY=1 to bypass the disclaimer for this run.`);
    return false;
}
async function shutdown(code) {
    if (code === 0) {
        writeLine();
        writeStatus(color('green', 'done'));
    }
    await getShutdownManager().gracefulShutdown(code);
}
//# sourceMappingURL=shell.js.map