import { readdir, realpath, stat } from "node:fs/promises";
import path from "node:path";
const DEFAULT_LIMIT = 30;
const MAX_LIMIT = 100;
const DEFAULT_MAX_DEPTH = 12;
const DEFAULT_MAX_DIRECTORIES_SCANNED = 20000;
const DIRECTORY_LIST_CACHE_TTL_MS = 8000;
const DIRECTORY_LIST_CACHE_MAX_ENTRIES = 4000;
const directoryListCache = new Map();
const workspaceEntryListCache = new Map();
const NO_SEGMENT_INDEX = Number.MAX_SAFE_INTEGER;
const NO_MATCH_OFFSET = Number.MAX_SAFE_INTEGER;
const NO_FUZZY_SCORE = Number.MAX_SAFE_INTEGER;
const NO_WORKSPACE_MATCH_TIER = 5;
const WORKSPACE_IGNORED_DIRECTORY_NAMES = new Set([
    "node_modules",
    "dist",
    "build",
    "target",
    "out",
    "coverage",
    "vendor",
    "__pycache__",
]);
export async function searchHomeDirectories(options) {
    const query = options.query.trim();
    if (!query) {
        return [];
    }
    const limit = normalizeLimit(options.limit);
    const homeRoot = await resolveDirectory(options.homeDir);
    if (!homeRoot) {
        return [];
    }
    const queryParts = normalizeQueryParts(query, homeRoot);
    if (!queryParts) {
        return [];
    }
    if (queryParts.isPathQuery) {
        return searchWithinParentDirectory({
            homeRoot,
            parentPart: queryParts.parentPart,
            searchTerm: queryParts.searchTerm,
            limit,
        });
    }
    return searchAcrossHomeTree({
        homeRoot,
        searchTerm: queryParts.searchTerm,
        limit,
        maxDepth: options.maxDepth ?? DEFAULT_MAX_DEPTH,
        maxDirectoriesScanned: options.maxDirectoriesScanned ?? DEFAULT_MAX_DIRECTORIES_SCANNED,
    });
}
export async function searchWorkspaceEntries(options) {
    const limit = normalizeLimit(options.limit);
    const includeDirectories = options.includeDirectories ?? true;
    const includeFiles = options.includeFiles ?? false;
    if (!includeDirectories && !includeFiles) {
        return [];
    }
    const workspaceRoot = await resolveDirectory(options.cwd);
    if (!workspaceRoot) {
        return [];
    }
    const queryParts = normalizeWorkspaceQueryParts(options.query, workspaceRoot);
    if (!queryParts) {
        return [];
    }
    const matchMode = options.matchMode ?? "fuzzy";
    if (queryParts.isPathQuery && matchMode !== "suffix") {
        return searchWorkspaceWithinParentDirectory({
            workspaceRoot,
            parentPart: queryParts.parentPart,
            searchTerm: queryParts.searchTerm,
            limit,
            includeDirectories,
            includeFiles,
        });
    }
    const searchTerm = matchMode === "suffix"
        ? [queryParts.parentPart, queryParts.searchTerm].filter(Boolean).join("/")
        : queryParts.searchTerm;
    return searchWorkspaceAcrossTree({
        workspaceRoot,
        searchTerm,
        limit,
        includeDirectories,
        includeFiles,
        matchMode,
        maxDepth: options.maxDepth ?? DEFAULT_MAX_DEPTH,
        maxEntriesScanned: options.maxEntriesScanned ?? DEFAULT_MAX_DIRECTORIES_SCANNED,
    });
}
function normalizeLimit(limit) {
    const candidate = limit ?? DEFAULT_LIMIT;
    if (!Number.isFinite(candidate)) {
        return DEFAULT_LIMIT;
    }
    const bounded = Math.trunc(candidate);
    return Math.max(1, Math.min(MAX_LIMIT, bounded));
}
async function searchWithinParentDirectory(input) {
    const parentPath = path.resolve(input.homeRoot, input.parentPart || ".");
    const parentRoot = await resolveDirectory(parentPath);
    if (!parentRoot || !isPathInsideRoot(input.homeRoot, parentRoot)) {
        return [];
    }
    const searchLower = input.searchTerm.toLowerCase();
    const ranked = [];
    const entries = await listChildDirectories({
        directory: parentRoot,
        homeRoot: input.homeRoot,
    });
    for (const entry of entries) {
        if (searchLower && !entry.name.toLowerCase().includes(searchLower)) {
            continue;
        }
        ranked.push(rankDirectory({
            absolutePath: entry.absolutePath,
            homeRoot: input.homeRoot,
            searchLower,
        }));
    }
    return dedupeAndSort(ranked).slice(0, input.limit);
}
async function searchAcrossHomeTree(input) {
    const queue = [
        { directory: input.homeRoot, depth: 0 },
    ];
    const visited = new Set([input.homeRoot]);
    const ranked = [];
    let scanned = 0;
    const searchLower = input.searchTerm.toLowerCase();
    for (let queueIndex = 0; queueIndex < queue.length && scanned < input.maxDirectoriesScanned; queueIndex += 1) {
        const current = queue[queueIndex];
        if (!current)
            continue;
        const entries = await listChildDirectories({
            directory: current.directory,
            homeRoot: input.homeRoot,
        });
        for (const entry of entries) {
            const resolvedCandidate = entry.absolutePath;
            if (visited.has(resolvedCandidate)) {
                continue;
            }
            visited.add(resolvedCandidate);
            scanned += 1;
            const relativePath = normalizeRelativePath(input.homeRoot, resolvedCandidate);
            if (relativePath.toLowerCase().includes(searchLower) ||
                entry.name.toLowerCase().includes(searchLower)) {
                ranked.push(rankDirectory({
                    absolutePath: resolvedCandidate,
                    homeRoot: input.homeRoot,
                    searchLower,
                }));
            }
            if (current.depth < input.maxDepth && scanned < input.maxDirectoriesScanned) {
                queue.push({ directory: resolvedCandidate, depth: current.depth + 1 });
            }
        }
    }
    return dedupeAndSort(ranked).slice(0, input.limit);
}
async function searchWorkspaceWithinParentDirectory(input) {
    const parentPath = path.resolve(input.workspaceRoot, input.parentPart || ".");
    const parentRoot = await resolveDirectory(parentPath);
    if (!parentRoot || !isPathInsideRoot(input.workspaceRoot, parentRoot)) {
        return [];
    }
    const searchLower = input.searchTerm.toLowerCase();
    const ranked = [];
    const entries = await listWorkspaceChildEntries({
        directory: parentRoot,
        workspaceRoot: input.workspaceRoot,
    });
    for (const entry of entries) {
        if (entry.kind === "directory" && !input.includeDirectories) {
            continue;
        }
        if (entry.kind === "file" && !input.includeFiles) {
            continue;
        }
        const rankedEntry = rankWorkspaceEntry({
            absolutePath: entry.absolutePath,
            kind: entry.kind,
            workspaceRoot: input.workspaceRoot,
            searchLower,
        });
        if (searchLower && rankedEntry.matchTier === NO_WORKSPACE_MATCH_TIER) {
            continue;
        }
        ranked.push(rankedEntry);
    }
    return dedupeAndSortWorkspaceEntries(ranked).slice(0, input.limit);
}
async function searchWorkspaceAcrossTree(input) {
    const queue = [
        { directory: input.workspaceRoot, depth: 0 },
    ];
    const visited = new Set([input.workspaceRoot]);
    const ranked = [];
    let scanned = 0;
    const searchLower = input.searchTerm.toLowerCase();
    for (let queueIndex = 0; queueIndex < queue.length && scanned < input.maxEntriesScanned; queueIndex += 1) {
        const current = queue[queueIndex];
        if (!current)
            continue;
        const entries = await listWorkspaceChildEntries({
            directory: current.directory,
            workspaceRoot: input.workspaceRoot,
        });
        for (const entry of entries) {
            scanned += 1;
            if (entry.kind === "directory") {
                if (!visited.has(entry.absolutePath) &&
                    current.depth < input.maxDepth &&
                    scanned < input.maxEntriesScanned) {
                    visited.add(entry.absolutePath);
                    queue.push({
                        directory: entry.absolutePath,
                        depth: current.depth + 1,
                    });
                }
            }
            if (entry.kind === "directory" && !input.includeDirectories) {
                continue;
            }
            if (entry.kind === "file" && !input.includeFiles) {
                continue;
            }
            if (input.matchMode === "suffix" &&
                !workspaceEntryMatchesSuffixQuery({
                    absolutePath: entry.absolutePath,
                    workspaceRoot: input.workspaceRoot,
                    query: input.searchTerm,
                })) {
                continue;
            }
            const rankedEntry = rankWorkspaceEntry({
                absolutePath: entry.absolutePath,
                kind: entry.kind,
                workspaceRoot: input.workspaceRoot,
                searchLower,
            });
            if (input.matchMode !== "suffix" &&
                searchLower &&
                rankedEntry.matchTier === NO_WORKSPACE_MATCH_TIER) {
                continue;
            }
            ranked.push(rankedEntry);
        }
    }
    return dedupeAndSortWorkspaceEntries(ranked).slice(0, input.limit);
}
function workspaceEntryMatchesSuffixQuery(input) {
    const querySegments = input.query
        .trim()
        .replace(/\\/g, "/")
        .replace(/^\.\/+/, "")
        .split("/")
        .filter(Boolean)
        .map((segment) => segment.toLowerCase());
    if (querySegments.length === 0) {
        return false;
    }
    const pathSegments = normalizeRelativePath(input.workspaceRoot, input.absolutePath)
        .split("/")
        .filter(Boolean)
        .map((segment) => segment.toLowerCase());
    if (querySegments.length > pathSegments.length) {
        return false;
    }
    const offset = pathSegments.length - querySegments.length;
    return querySegments.every((segment, index) => pathSegments[offset + index] === segment);
}
function dedupeAndSortWorkspaceEntries(rankedEntries) {
    const byPath = new Map();
    for (const entry of rankedEntries) {
        const key = `${entry.kind}:${entry.relativePath}`;
        const existing = byPath.get(key);
        if (!existing || compareRankedWorkspaceEntries(entry, existing) < 0) {
            byPath.set(key, entry);
        }
    }
    return Array.from(byPath.values())
        .sort(compareRankedWorkspaceEntries)
        .map((entry) => ({
        path: entry.relativePath,
        kind: entry.kind,
    }));
}
function compareRankedWorkspaceEntries(left, right) {
    if (left.matchTier !== right.matchTier) {
        return left.matchTier - right.matchTier;
    }
    if (left.segmentIndex !== right.segmentIndex) {
        return left.segmentIndex - right.segmentIndex;
    }
    if (left.matchOffset !== right.matchOffset) {
        return left.matchOffset - right.matchOffset;
    }
    if (left.fuzzyScore !== right.fuzzyScore) {
        return left.fuzzyScore - right.fuzzyScore;
    }
    if (left.depth !== right.depth) {
        return left.depth - right.depth;
    }
    if (left.kind !== right.kind) {
        return left.kind === "directory" ? -1 : 1;
    }
    return left.relativePath.localeCompare(right.relativePath);
}
function dedupeAndSort(ranked) {
    const byPath = new Map();
    for (const entry of ranked) {
        const existing = byPath.get(entry.absolutePath);
        if (!existing || compareRankedDirectories(entry, existing) < 0) {
            byPath.set(entry.absolutePath, entry);
        }
    }
    return Array.from(byPath.values())
        .sort(compareRankedDirectories)
        .map((entry) => entry.absolutePath);
}
function compareRankedDirectories(left, right) {
    if (left.matchTier !== right.matchTier) {
        return left.matchTier - right.matchTier;
    }
    if (left.segmentIndex !== right.segmentIndex) {
        return left.segmentIndex - right.segmentIndex;
    }
    if (left.matchOffset !== right.matchOffset) {
        return left.matchOffset - right.matchOffset;
    }
    if (left.depth !== right.depth) {
        return left.depth - right.depth;
    }
    return left.absolutePath.localeCompare(right.absolutePath);
}
function rankDirectory(input) {
    const relative = normalizeRelativePath(input.homeRoot, input.absolutePath);
    const relativeLower = relative.toLowerCase();
    const depth = relative === "." ? 0 : relative.split("/").length;
    const searchLower = input.searchLower;
    if (!searchLower) {
        return {
            absolutePath: input.absolutePath,
            matchTier: 3,
            segmentIndex: NO_SEGMENT_INDEX,
            matchOffset: 0,
            depth,
        };
    }
    const segments = relativeLower === "." ? [] : relativeLower.split("/");
    const exactSegmentIndex = findSegmentMatchIndex(segments, (segment) => segment === searchLower);
    const prefixSegmentIndex = findSegmentMatchIndex(segments, (segment) => segment.startsWith(searchLower));
    const partialSegmentIndex = findSegmentMatchIndex(segments, (segment) => segment.includes(searchLower));
    const matchOffset = relativeLower.indexOf(searchLower);
    let matchTier = 4;
    let segmentIndex = NO_SEGMENT_INDEX;
    if (exactSegmentIndex >= 0) {
        matchTier = 0;
        segmentIndex = exactSegmentIndex;
    }
    else if (prefixSegmentIndex >= 0) {
        matchTier = 1;
        segmentIndex = prefixSegmentIndex;
    }
    else if (partialSegmentIndex >= 0) {
        matchTier = 2;
        segmentIndex = partialSegmentIndex;
    }
    else if (relativeLower.startsWith(searchLower)) {
        matchTier = 3;
    }
    return {
        absolutePath: input.absolutePath,
        matchTier,
        segmentIndex,
        matchOffset: matchOffset >= 0 ? matchOffset : NO_MATCH_OFFSET,
        depth,
    };
}
function rankWorkspaceEntry(input) {
    const relativePath = normalizeRelativePath(input.workspaceRoot, input.absolutePath);
    const relativeLower = relativePath.toLowerCase();
    const depth = relativePath === "." ? 0 : relativePath.split("/").length;
    const searchLower = input.searchLower;
    if (!searchLower) {
        return {
            relativePath,
            kind: input.kind,
            matchTier: 3,
            segmentIndex: NO_SEGMENT_INDEX,
            matchOffset: 0,
            fuzzyScore: NO_FUZZY_SCORE,
            depth,
        };
    }
    const segments = relativeLower === "." ? [] : relativeLower.split("/");
    const exactSegmentIndex = findSegmentMatchIndex(segments, (segment) => segment === searchLower);
    const prefixSegmentIndex = findSegmentMatchIndex(segments, (segment) => segment.startsWith(searchLower));
    const partialSegmentIndex = findSegmentMatchIndex(segments, (segment) => segment.includes(searchLower));
    const matchOffset = relativeLower.indexOf(searchLower);
    const basename = segments.at(-1) ?? "";
    const fuzzyScore = scoreFuzzySubsequence(searchLower, basename);
    let matchTier = NO_WORKSPACE_MATCH_TIER;
    let segmentIndex = NO_SEGMENT_INDEX;
    if (exactSegmentIndex >= 0) {
        matchTier = 0;
        segmentIndex = exactSegmentIndex;
    }
    else if (prefixSegmentIndex >= 0) {
        matchTier = 1;
        segmentIndex = prefixSegmentIndex;
    }
    else if (partialSegmentIndex >= 0) {
        matchTier = 2;
        segmentIndex = partialSegmentIndex;
    }
    else if (relativeLower.startsWith(searchLower)) {
        matchTier = 3;
    }
    else if (fuzzyScore !== null) {
        matchTier = 4;
    }
    return {
        relativePath,
        kind: input.kind,
        matchTier,
        segmentIndex,
        matchOffset: matchOffset >= 0 ? matchOffset : NO_MATCH_OFFSET,
        fuzzyScore: fuzzyScore ?? NO_FUZZY_SCORE,
        depth,
    };
}
function scoreFuzzySubsequence(query, candidate) {
    if (!query) {
        return 0;
    }
    let queryIndex = 0;
    let firstMatchIndex = -1;
    let previousMatchIndex = -1;
    let gapScore = 0;
    for (let candidateIndex = 0; candidateIndex < candidate.length && queryIndex < query.length; candidateIndex += 1) {
        if (candidate[candidateIndex] !== query[queryIndex]) {
            continue;
        }
        if (firstMatchIndex === -1) {
            firstMatchIndex = candidateIndex;
        }
        if (previousMatchIndex >= 0) {
            gapScore += candidateIndex - previousMatchIndex - 1;
        }
        previousMatchIndex = candidateIndex;
        queryIndex += 1;
    }
    if (queryIndex !== query.length || firstMatchIndex === -1) {
        return null;
    }
    return firstMatchIndex + gapScore;
}
function findSegmentMatchIndex(segments, predicate) {
    for (let index = 0; index < segments.length; index += 1) {
        const segment = segments[index];
        if (!segment) {
            continue;
        }
        if (predicate(segment)) {
            return index;
        }
    }
    return -1;
}
function normalizeRelativePath(homeRoot, absolutePath) {
    const relative = path.relative(homeRoot, absolutePath);
    if (!relative) {
        return ".";
    }
    return relative.split(path.sep).join("/");
}
function isPathInsideRoot(root, target) {
    const relative = path.relative(root, target);
    return relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative));
}
function normalizeQueryParts(query, homeRoot) {
    const typedQuery = query.trim().replace(/\\/g, "/");
    let normalized = typedQuery;
    if (!normalized) {
        return null;
    }
    // Only treat the query as a literal path when the user explicitly roots it
    // with ~, ~/, ./, or an absolute path. Bare queries like "faro/main" are
    // search terms, not paths.
    let isRooted = false;
    if (normalized.startsWith("~")) {
        isRooted = true;
        normalized = normalized.slice(1);
        if (normalized.startsWith("/")) {
            normalized = normalized.slice(1);
        }
    }
    if (path.isAbsolute(normalized)) {
        isRooted = true;
        const absolute = path.resolve(normalized);
        if (!isPathInsideRoot(homeRoot, absolute)) {
            return null;
        }
        normalized = normalizeRelativePath(homeRoot, absolute);
    }
    if (normalized.startsWith("./")) {
        isRooted = true;
    }
    normalized = normalized.replace(/^\.\/+/, "").replace(/\/{2,}/g, "/");
    if (!normalized) {
        // Treat "~" and "~/" as a request to browse the home root.
        if (typedQuery === "~" || typedQuery === "~/") {
            return {
                isPathQuery: true,
                parentPart: "",
                searchTerm: "",
            };
        }
        return null;
    }
    const isPathQuery = isRooted && normalized.includes("/");
    if (!isPathQuery) {
        return {
            isPathQuery: false,
            parentPart: "",
            searchTerm: normalized,
        };
    }
    const slashIndex = normalized.lastIndexOf("/");
    const parentPart = normalized.slice(0, slashIndex);
    const searchTerm = normalized.slice(slashIndex + 1);
    return {
        isPathQuery: true,
        parentPart,
        searchTerm,
    };
}
function normalizeWorkspaceQueryParts(query, workspaceRoot) {
    let normalized = query.trim().replace(/\\/g, "/");
    if (path.isAbsolute(normalized)) {
        const absolute = path.resolve(normalized);
        if (!isPathInsideRoot(workspaceRoot, absolute)) {
            return null;
        }
        normalized = normalizeRelativePath(workspaceRoot, absolute);
    }
    normalized = normalized.replace(/^\.\/+/, "").replace(/\/{2,}/g, "/");
    if (!normalized) {
        return {
            isPathQuery: true,
            parentPart: "",
            searchTerm: "",
        };
    }
    const isPathQuery = normalized.includes("/");
    const slashIndex = normalized.lastIndexOf("/");
    const parentPart = slashIndex >= 0 ? normalized.slice(0, slashIndex) : "";
    const searchTerm = slashIndex >= 0 ? normalized.slice(slashIndex + 1) : normalized;
    return {
        isPathQuery,
        parentPart,
        searchTerm,
    };
}
async function resolveDirectory(inputPath) {
    try {
        const resolved = await realpath(path.resolve(inputPath));
        const stats = await stat(resolved);
        if (!stats.isDirectory()) {
            return null;
        }
        return resolved;
    }
    catch {
        return null;
    }
}
async function listChildDirectories(input) {
    const now = Date.now();
    const cached = directoryListCache.get(input.directory);
    if (cached && cached.expiresAt > now) {
        return cached.entries;
    }
    const dirents = await readdir(input.directory, { withFileTypes: true }).catch(() => []);
    const candidates = dirents.filter((dirent) => !isHiddenDirectoryName(dirent.name) && (dirent.isDirectory() || dirent.isSymbolicLink()));
    const resolved = await Promise.all(candidates.map(async (dirent) => {
        const candidatePath = path.join(input.directory, dirent.name);
        const absolutePath = await resolveDirectoryCandidate({
            candidatePath,
            dirent,
            homeRoot: input.homeRoot,
        });
        return absolutePath ? { name: dirent.name, absolutePath } : null;
    }));
    const entries = resolved.filter((entry) => entry !== null);
    setDirectoryListCache(input.directory, {
        expiresAt: now + DIRECTORY_LIST_CACHE_TTL_MS,
        entries,
    });
    return entries;
}
async function listWorkspaceChildEntries(input) {
    const now = Date.now();
    const cached = workspaceEntryListCache.get(input.directory);
    if (cached && cached.expiresAt > now) {
        return cached.entries;
    }
    const dirents = await readdir(input.directory, { withFileTypes: true }).catch(() => []);
    const candidates = dirents.filter((dirent) => !isHiddenDirectoryName(dirent.name) && !isIgnoredWorkspaceDirectoryName(dirent.name));
    const resolved = await Promise.all(candidates.map(async (dirent) => {
        const candidatePath = path.join(input.directory, dirent.name);
        const entry = await resolveWorkspaceCandidate({
            candidatePath,
            dirent,
            workspaceRoot: input.workspaceRoot,
        });
        return entry
            ? { name: dirent.name, absolutePath: entry.absolutePath, kind: entry.kind }
            : null;
    }));
    const entries = resolved.filter((entry) => entry !== null);
    setWorkspaceEntryListCache(input.directory, {
        expiresAt: now + DIRECTORY_LIST_CACHE_TTL_MS,
        entries,
    });
    return entries;
}
async function resolveDirectoryCandidate(input) {
    if (input.dirent.isDirectory()) {
        const resolved = path.resolve(input.candidatePath);
        return isPathInsideRoot(input.homeRoot, resolved) ? resolved : null;
    }
    const resolved = await resolveDirectory(input.candidatePath);
    if (!resolved || !isPathInsideRoot(input.homeRoot, resolved)) {
        return null;
    }
    return resolved;
}
async function resolveWorkspaceCandidate(input) {
    if (input.dirent.isDirectory()) {
        const resolved = path.resolve(input.candidatePath);
        if (!isPathInsideRoot(input.workspaceRoot, resolved)) {
            return null;
        }
        return { absolutePath: resolved, kind: "directory" };
    }
    if (input.dirent.isFile()) {
        const resolved = path.resolve(input.candidatePath);
        if (!isPathInsideRoot(input.workspaceRoot, resolved)) {
            return null;
        }
        return { absolutePath: resolved, kind: "file" };
    }
    if (!input.dirent.isSymbolicLink()) {
        return null;
    }
    try {
        const resolved = await realpath(input.candidatePath);
        if (!isPathInsideRoot(input.workspaceRoot, resolved)) {
            return null;
        }
        const stats = await stat(resolved);
        if (stats.isDirectory()) {
            return { absolutePath: resolved, kind: "directory" };
        }
        if (stats.isFile()) {
            return { absolutePath: resolved, kind: "file" };
        }
        return null;
    }
    catch {
        return null;
    }
}
function isHiddenDirectoryName(name) {
    return name.startsWith(".");
}
function isIgnoredWorkspaceDirectoryName(name) {
    return WORKSPACE_IGNORED_DIRECTORY_NAMES.has(name);
}
function setDirectoryListCache(cacheKey, entry) {
    directoryListCache.set(cacheKey, entry);
    pruneDirectoryListCache();
}
function setWorkspaceEntryListCache(cacheKey, entry) {
    workspaceEntryListCache.set(cacheKey, entry);
    pruneWorkspaceEntryListCache();
}
function pruneDirectoryListCache() {
    if (directoryListCache.size <= DIRECTORY_LIST_CACHE_MAX_ENTRIES) {
        return;
    }
    const now = Date.now();
    for (const [cacheKey, entry] of directoryListCache) {
        if (entry.expiresAt <= now) {
            directoryListCache.delete(cacheKey);
        }
    }
    while (directoryListCache.size > DIRECTORY_LIST_CACHE_MAX_ENTRIES) {
        const oldestKey = directoryListCache.keys().next().value;
        if (!oldestKey) {
            return;
        }
        directoryListCache.delete(oldestKey);
    }
}
function pruneWorkspaceEntryListCache() {
    if (workspaceEntryListCache.size <= DIRECTORY_LIST_CACHE_MAX_ENTRIES) {
        return;
    }
    const now = Date.now();
    for (const [cacheKey, entry] of workspaceEntryListCache) {
        if (entry.expiresAt <= now) {
            workspaceEntryListCache.delete(cacheKey);
        }
    }
    while (workspaceEntryListCache.size > DIRECTORY_LIST_CACHE_MAX_ENTRIES) {
        const oldestKey = workspaceEntryListCache.keys().next().value;
        if (!oldestKey) {
            return;
        }
        workspaceEntryListCache.delete(oldestKey);
    }
}
//# sourceMappingURL=directory-suggestions.js.map