"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.LOCAL_INSTRUCTION_FILENAME = exports.INSTRUCTION_FILE_NAMES = void 0;
exports.readInstructionSet = readInstructionSet;
exports.readInstructionSetFromRuntime = readInstructionSetFromRuntime;
exports.gatherInstructionSets = gatherInstructionSets;
const fs = __importStar(require("fs/promises"));
const path = __importStar(require("path"));
const helpers_1 = require("../../utils/runtime/helpers");
/**
 * Instruction file names to search for, in priority order.
 * The first file found in a directory is used as the base instruction set.
 */
exports.INSTRUCTION_FILE_NAMES = ["AGENTS.md", "AGENT.md", "CLAUDE.md"];
/**
 * Local instruction file suffix. If a base instruction file is found,
 * we also look for a matching .local.md variant in the same directory.
 *
 * Example: If AGENTS.md exists, we also check for AGENTS.local.md
 */
exports.LOCAL_INSTRUCTION_FILENAME = "AGENTS.local.md";
/**
 * Create a FileReader for local filesystem access.
 */
function createLocalFileReader() {
    return {
        readFile: (filePath) => fs.readFile(filePath, "utf-8"),
    };
}
/**
 * Create a FileReader for Runtime-based access (supports SSH).
 */
function createRuntimeFileReader(runtime) {
    return {
        readFile: (filePath) => (0, helpers_1.readFileString)(runtime, filePath),
    };
}
/**
 * Read the first available file from a list using the provided file reader.
 *
 * @param reader - FileReader abstraction (local or runtime)
 * @param directory - Directory to search in
 * @param filenames - List of filenames to try, in priority order
 * @returns Content of the first file found, or null if none exist
 */
async function readFirstAvailableFile(reader, directory, filenames) {
    for (const filename of filenames) {
        try {
            return await reader.readFile(path.join(directory, filename));
        }
        catch {
            continue; // File doesn't exist, try next
        }
    }
    return null;
}
/**
 * Read a base file with optional local variant using the provided file reader.
 *
 * @param reader - FileReader abstraction (local or runtime)
 * @param directory - Directory to search
 * @param baseFilenames - Base filenames to try in priority order
 * @param localFilename - Optional local filename to append if present
 * @returns Combined content or null if no base file exists
 */
async function readFileWithLocalVariant(reader, directory, baseFilenames, localFilename) {
    const baseContent = await readFirstAvailableFile(reader, directory, baseFilenames);
    if (!baseContent)
        return null;
    if (!localFilename)
        return baseContent;
    try {
        const localContent = await reader.readFile(path.join(directory, localFilename));
        return `${baseContent}\n\n${localContent}`;
    }
    catch {
        return baseContent; // Local variant missing, return base only
    }
}
/**
 * Read an instruction set from a local directory.
 *
 * An instruction set consists of:
 * 1. A base instruction file (AGENTS.md → AGENT.md → CLAUDE.md, first found wins)
 * 2. An optional local instruction file (AGENTS.local.md)
 *
 * If both exist, they are concatenated with a blank line separator.
 *
 * @param directory - Directory to search for instruction files
 * @returns Combined instruction content, or null if no base file exists
 */
async function readInstructionSet(directory) {
    if (!directory)
        return null;
    const reader = createLocalFileReader();
    return readFileWithLocalVariant(reader, path.resolve(directory), exports.INSTRUCTION_FILE_NAMES, exports.LOCAL_INSTRUCTION_FILENAME);
}
/**
 * Read an instruction set from a workspace using Runtime abstraction.
 * Supports both local and remote (SSH) workspaces.
 *
 * @param runtime - Runtime instance (may be local or SSH)
 * @param directory - Directory to search for instruction files
 * @returns Combined instruction content, or null if no base file exists
 */
async function readInstructionSetFromRuntime(runtime, directory) {
    const reader = createRuntimeFileReader(runtime);
    return readFileWithLocalVariant(reader, directory, exports.INSTRUCTION_FILE_NAMES, exports.LOCAL_INSTRUCTION_FILENAME);
}
/**
 * Searches for instruction files across multiple directories in priority order.
 *
 * Each directory is searched for a complete instruction set (base + local).
 * All found instruction sets are returned as separate segments.
 *
 * This allows for layered instructions where:
 * - Global instructions (~/.cmux/AGENTS.md) apply to all projects
 * - Project instructions (workspace/AGENTS.md) add project-specific context
 *
 * @param directories - List of directories to search, in priority order
 * @returns Array of instruction segments (one per directory with instructions)
 */
async function gatherInstructionSets(directories) {
    const segments = [];
    for (const directory of directories) {
        const instructionSet = await readInstructionSet(directory);
        if (instructionSet) {
            segments.push(instructionSet);
        }
    }
    return segments;
}
//# sourceMappingURL=instructionFiles.js.map