/**
 * FileSystemBedrockMemoryReader — concrete adapter for IBedrockMemoryReader.
 *
 * Walks `<cwd>/.bedrock/` recursively, returns a typed BedrockMemorySnapshot
 * for the BedrockMemoryPanel visualization. The walk is shallow on errors:
 * a missing or unreadable directory yields a `present: false` snapshot
 * rather than a thrown exception, so the UI can render a clean empty state
 * regardless of host filesystem quirks.
 *
 * Cross-platform notes (per packages/CLAUDE.md):
 *   - `path.join`/`path.relative` used throughout — no string concat.
 *   - Stored relative paths are normalized to forward slashes for cross-OS
 *     comparability and stable rendering on the web client.
 *   - File reads use `node:fs/promises` only; no subprocess spawning.
 */
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { promises as fs } from 'node:fs';
import { join, relative, sep } from 'node:path';
import { injectable } from 'tsyringe';
const BEDROCK_DIR = '.bedrock';
const DEFAULT_PREVIEW_BYTES = 256;
let FileSystemBedrockMemoryReader = class FileSystemBedrockMemoryReader {
    async read(opts) {
        const root = join(opts.cwd, BEDROCK_DIR);
        const empty = {
            cwd: opts.cwd,
            present: false,
            files: [],
            totalBytes: BigInt(0),
        };
        let present;
        try {
            const stat = await fs.stat(root);
            present = stat.isDirectory();
        }
        catch {
            return empty;
        }
        if (!present)
            return empty;
        const previewBytes = opts.previewBytes ?? DEFAULT_PREVIEW_BYTES;
        const files = [];
        try {
            await walk(root, root, previewBytes, files);
        }
        catch {
            // Partial walk — fall through with whatever we collected.
        }
        files.sort((a, b) => a.path.localeCompare(b.path));
        const totalBytes = files.reduce((acc, f) => acc + BigInt(typeof f.sizeBytes === 'bigint' ? f.sizeBytes : Number(f.sizeBytes)), BigInt(0));
        let mostRecent;
        for (const f of files) {
            const modified = f.modifiedAt instanceof Date ? f.modifiedAt : new Date(f.modifiedAt);
            if (!mostRecent || modified.getTime() > mostRecent.getTime()) {
                mostRecent = modified;
            }
        }
        return {
            cwd: opts.cwd,
            present: true,
            files,
            totalBytes,
            ...(mostRecent ? { mostRecentlyModifiedAt: mostRecent } : {}),
        };
    }
};
FileSystemBedrockMemoryReader = __decorate([
    injectable()
], FileSystemBedrockMemoryReader);
export { FileSystemBedrockMemoryReader };
async function walk(root, current, previewBytes, out) {
    let entries;
    try {
        entries = await fs.readdir(current, { withFileTypes: true });
    }
    catch {
        return;
    }
    for (const entry of entries) {
        if (entry.name.startsWith('.') && current !== root)
            continue;
        const abs = join(current, entry.name);
        if (entry.isDirectory()) {
            await walk(root, abs, previewBytes, out);
            continue;
        }
        if (!entry.isFile())
            continue;
        let stat;
        try {
            stat = await fs.stat(abs);
        }
        catch {
            continue;
        }
        let preview;
        if (previewBytes > 0) {
            try {
                const buf = await fs.readFile(abs);
                preview = buf.subarray(0, previewBytes).toString('utf8');
            }
            catch {
                preview = undefined;
            }
        }
        const rel = relative(root, abs).split(sep).join('/');
        out.push({
            path: rel,
            sizeBytes: BigInt(stat.size),
            modifiedAt: stat.mtime,
            ...(preview !== undefined ? { preview } : {}),
        });
    }
}
