/**
 * @license
 * Copyright 2025 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import fs from 'node:fs';
import path from 'node:path';
import process from 'node:process';
import { GEMINI_DIR } from '../utils/paths.js';
import { ApprovalMode } from '../policy/types.js';
import * as snippets from './snippets.js';
import { resolvePathFromEnv, applySubstitutions, isSectionEnabled, } from './utils.js';
import { CodebaseInvestigatorAgent } from '../agents/codebase-investigator.js';
import { isGitRepository } from '../utils/gitUtils.js';
import { PLAN_MODE_TOOLS, WRITE_TODOS_TOOL_NAME, READ_FILE_TOOL_NAME, } from '../tools/tool-names.js';
import { resolveModel, isPreviewModel } from '../config/models.js';
/**
 * Orchestrates prompt generation by gathering context and building options.
 */
export class PromptProvider {
    /**
     * Generates the core system prompt.
     */
    getCoreSystemPrompt(config, userMemory, interactiveOverride) {
        const systemMdResolution = resolvePathFromEnv(process.env['GEMINI_SYSTEM_MD']);
        const interactiveMode = interactiveOverride ?? config.isInteractive();
        const approvalMode = config.getApprovalMode?.() ?? ApprovalMode.DEFAULT;
        const isPlanMode = approvalMode === ApprovalMode.PLAN;
        const skills = config.getSkillManager().getSkills();
        const toolNames = config.getToolRegistry().getAllToolNames();
        const desiredModel = resolveModel(config.getActiveModel(), config.getPreviewFeatures());
        const isGemini3 = isPreviewModel(desiredModel);
        // --- Context Gathering ---
        const planOptions = isPlanMode
            ? {
                planModeToolsList: PLAN_MODE_TOOLS.filter((t) => new Set(toolNames).has(t))
                    .map((t) => `- \`${t}\``)
                    .join('\n'),
                plansDir: config.storage.getProjectTempPlansDir(),
            }
            : undefined;
        let basePrompt;
        // --- Template File Override ---
        if (systemMdResolution.value && !systemMdResolution.isDisabled) {
            let systemMdPath = path.resolve(path.join(GEMINI_DIR, 'system.md'));
            if (!systemMdResolution.isSwitch) {
                systemMdPath = systemMdResolution.value;
            }
            if (!fs.existsSync(systemMdPath)) {
                throw new Error(`missing system prompt file '${systemMdPath}'`);
            }
            basePrompt = fs.readFileSync(systemMdPath, 'utf8');
            const skillsPrompt = snippets.renderAgentSkills(skills.map((s) => ({
                name: s.name,
                description: s.description,
                location: s.location,
            })));
            basePrompt = applySubstitutions(basePrompt, config, skillsPrompt);
        }
        else {
            // --- Standard Composition ---
            const options = {
                preamble: this.withSection('preamble', () => ({
                    interactive: interactiveMode,
                })),
                coreMandates: this.withSection('coreMandates', () => ({
                    interactive: interactiveMode,
                    isGemini3,
                    hasSkills: skills.length > 0,
                })),
                agentContexts: this.withSection('agentContexts', () => config.getAgentRegistry().getDirectoryContext()),
                agentSkills: this.withSection('agentSkills', () => skills.map((s) => ({
                    name: s.name,
                    description: s.description,
                    location: s.location,
                })), skills.length > 0),
                hookContext: isSectionEnabled('hookContext') || undefined,
                primaryWorkflows: this.withSection('primaryWorkflows', () => ({
                    interactive: interactiveMode,
                    enableCodebaseInvestigator: toolNames.includes(CodebaseInvestigatorAgent.name),
                    enableWriteTodosTool: toolNames.includes(WRITE_TODOS_TOOL_NAME),
                }), !isPlanMode),
                operationalGuidelines: this.withSection('operationalGuidelines', () => ({
                    interactive: interactiveMode,
                    isGemini3,
                    enableShellEfficiency: config.getEnableShellOutputEfficiency(),
                })),
                sandbox: this.withSection('sandbox', () => getSandboxMode()),
                gitRepo: this.withSection('git', () => ({ interactive: interactiveMode }), isGitRepository(process.cwd()) ? true : false),
                finalReminder: this.withSection('finalReminder', () => ({
                    readFileToolName: READ_FILE_TOOL_NAME,
                })),
            };
            basePrompt = snippets.getCoreSystemPrompt(options);
        }
        // --- Finalization (Shell) ---
        const finalPrompt = snippets.renderFinalShell(basePrompt, userMemory, planOptions);
        // Sanitize erratic newlines from composition
        const sanitizedPrompt = finalPrompt.replace(/\n{3,}/g, '\n\n');
        // Write back to file if requested
        this.maybeWriteSystemMd(sanitizedPrompt, systemMdResolution, path.resolve(path.join(GEMINI_DIR, 'system.md')));
        return sanitizedPrompt;
    }
    getCompressionPrompt() {
        return snippets.getCompressionPrompt();
    }
    withSection(key, factory, guard = true) {
        return guard && isSectionEnabled(key) ? factory() : undefined;
    }
    maybeWriteSystemMd(basePrompt, resolution, defaultPath) {
        const writeSystemMdResolution = resolvePathFromEnv(process.env['GEMINI_WRITE_SYSTEM_MD']);
        if (writeSystemMdResolution.value && !writeSystemMdResolution.isDisabled) {
            const writePath = writeSystemMdResolution.isSwitch
                ? defaultPath
                : writeSystemMdResolution.value;
            fs.mkdirSync(path.dirname(writePath), { recursive: true });
            fs.writeFileSync(writePath, basePrompt);
        }
    }
}
// --- Internal Context Helpers ---
function getSandboxMode() {
    if (process.env['SANDBOX'] === 'sandbox-exec')
        return 'macos-seatbelt';
    if (process.env['SANDBOX'])
        return 'generic';
    return 'outside';
}
//# sourceMappingURL=promptProvider.js.map