/**
 * File upload metadata tracking for the SXL agent.
 *
 * Maintains a session-scoped list of files uploaded by the user.
 * The agent uses this metadata to know what files are available
 * and injects a summary into the system prompt.
 *
 * Port of LangGraph `FileUploadData` and `add_file_uploads` reducer
 * from `backend/agent/state.py`.
 */
// ─── Dedup merge ────────────────────────────────────────────────────────────
/**
 * Merge new file uploads into an existing array, deduplicating by `name`.
 *
 * When a file with the same name already exists, the newer entry overwrites it.
 * New names are appended.
 *
 * Returns a new array — does not mutate the inputs.
 */
export function mergeFileUploads(existing, incoming) {
    const merged = new Map();
    // Seed with existing entries (preserves order)
    for (const file of existing) {
        merged.set(file.name, file);
    }
    // Overwrite or append incoming entries
    for (const file of incoming) {
        merged.set(file.name, file);
    }
    return Array.from(merged.values());
}
// ─── Sanitization ──────────────────────────────────────────────────────────
/** Maximum length for strings interpolated into the system prompt. */
const MAX_PROMPT_STRING_LENGTH = 255;
/**
 * Sanitize a string before interpolating it into the system prompt.
 *
 * Defends against prompt injection via malicious filenames or MIME types:
 * - Replaces newlines (`\n`, `\r`) with spaces
 * - Strips Markdown control characters (`*`, `#`, `[`, `]`, `` ` ``)
 * - Truncates to {@link MAX_PROMPT_STRING_LENGTH} characters
 */
export function sanitizeForPrompt(str) {
    return (str
        // Collapse all newline variants to a single space
        .replace(/[\r\n]+/g, ' ')
        // Strip Markdown control characters
        .replace(/[*#\[\]`]/g, '')
        // Collapse runs of whitespace produced by stripping
        .replace(/\s{2,}/g, ' ')
        .trim()
        .slice(0, MAX_PROMPT_STRING_LENGTH));
}
// ─── System prompt formatting ───────────────────────────────────────────────
/** Format bytes into a human-readable string (e.g. "1.5 MB"). */
function formatBytes(bytes) {
    if (bytes < 1024)
        return `${bytes} B`;
    if (bytes < 1024 * 1024)
        return `${(bytes / 1024).toFixed(1)} KB`;
    if (bytes < 1024 * 1024 * 1024)
        return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
    return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
}
/**
 * Format file upload metadata into a system prompt section.
 *
 * Returns an empty string when no files are present, so callers can
 * unconditionally append the result.
 */
export function formatFileUploadsContext(files) {
    if (files.length === 0)
        return '';
    const lines = ['## Uploaded Files', '', 'The user has uploaded the following files:'];
    for (const file of files) {
        const safeName = sanitizeForPrompt(file.name);
        const safeMime = sanitizeForPrompt(file.mimeType);
        const parts = [`- **${safeName}**`];
        parts.push(`(${safeMime})`);
        if (file.fileSize != null) {
            parts.push(`— ${formatBytes(file.fileSize)}`);
        }
        lines.push(parts.join(' '));
    }
    return '\n\n' + lines.join('\n');
}
//# sourceMappingURL=file-uploads.js.map