
import { __decorate, __param } from '../../../../../../../../../external/tslib/tslib.es6.js';
import { URI } from '../../../../../../base/common/uri.js';
import { isAbsolute } from '../../../../../../base/common/path.js';
import { ResourceSet } from '../../../../../../base/common/map.js';
import { localize } from '../../../../../../nls.js';
import { FileOperationError, FileOperationResult } from '../../../../../../platform/files/common/files.js';
import { IFileService } from '../../../../../../platform/files/common/files.service.js';
import { PromptsConfig, getPromptFileLocationsConfigKey, isTildePath } from '../config/config.js';
import { joinPath, dirname, isEqual, basename, isEqualOrParent } from '../../../../../../base/common/resources.js';
import { IWorkspaceContextService } from '../../../../../../platform/workspace/common/workspace.service.js';
import { IConfigurationService } from '../../../../../../platform/configuration/common/configuration.service.js';
import { getPromptFileDefaultLocations, getPromptFileType, getPromptFileExtension, LEGACY_MODE_FILE_EXTENSION, AGENTS_SOURCE_FOLDER, getCleanPromptName, AGENT_FILE_EXTENSION, SKILL_FILENAME } from '../config/promptFileLocations.js';
import { PromptFileSource, PromptsType } from '../promptTypes.js';
import { IWorkbenchEnvironmentService } from '../../../../../services/environment/common/environmentService.service.js';
import { Schemas } from '../../../../../../base/common/network.js';
import { getExcludes, QueryType } from '../../../../../services/search/common/search.js';
import { ISearchService } from '../../../../../services/search/common/search.service.js';
import { CancellationTokenSource } from '../../../../../../base/common/cancellation.js';
import { isCancellationError } from '../../../../../../base/common/errors.js';
import { PromptsStorage, AgentInstructionFileType } from '../service/promptsService.js';
import { IUserDataProfileService } from '../../../../../services/userDataProfile/common/userDataProfile.service.js';
import { Event, Emitter } from '../../../../../../base/common/event.js';
import { DisposableStore } from '../../../../../../base/common/lifecycle.js';
import { ILogService } from '../../../../../../platform/log/common/log.service.js';
import { IPathService } from '../../../../../services/path/common/pathService.service.js';
import { equalsIgnoreCase } from '../../../../../../base/common/strings.js';
import { IWorkspaceTrustManagementService } from '../../../../../../platform/workspace/common/workspaceTrust.service.js';
import { AGENT_HOST_SCHEME } from '../../../../../../platform/agentHost/common/agentHostUri.js';

const MAX_INSTRUCTIONS_RECURSION_DEPTH = 5;
let PromptFilesLocator = class PromptFilesLocator {
    constructor(
        fileService,
        configService,
        workspaceService,
        environmentService,
        searchService,
        userDataService,
        logService,
        pathService,
        workspaceTrustManagementService
    ) {
        this.fileService = fileService;
        this.configService = configService;
        this.workspaceService = workspaceService;
        this.environmentService = environmentService;
        this.searchService = searchService;
        this.userDataService = userDataService;
        this.logService = logService;
        this.pathService = pathService;
        this.workspaceTrustManagementService = workspaceTrustManagementService;
        const userDataPromptsHome = this.userDataService.currentProfile.promptsHome;
        this.userDataFolder = {
            uri: userDataPromptsHome,
            searchRoot: userDataPromptsHome,
            filePattern: undefined,
            source: PromptFileSource.UserData,
            storage: PromptsStorage.user,
            displayPath: ( localize(8326, "User Data")),
            isDefault: true
        };
    }
    getWorkspaceFolders() {
        return this.workspaceService.getWorkspace().folders.filter(f => f.uri.scheme !== AGENT_HOST_SCHEME);
    }
    getWorkspaceFolder(resource) {
        return this.workspaceService.getWorkspaceFolder(resource) ?? undefined;
    }
    onDidChangeWorkspaceFolders() {
        return ( Event.map(this.workspaceService.onDidChangeWorkspaceFolders, () => undefined));
    }
    getPromptSourceFolders(type) {
        return PromptsConfig.promptSourceFolders(this.configService, type);
    }
    getDefaultSourceFolders(type) {
        return getPromptFileDefaultLocations(type);
    }
    async getWorkspaceFolderRoots(includeParents, logger) {
        const workspaceFolders = this.getWorkspaceFolders();
        if (includeParents) {
            const roots = ( new ResourceSet());
            const userHome = await this.pathService.userHome();
            for (const workspaceFolder of workspaceFolders) {
                roots.add(workspaceFolder.uri);
                const parents = await this.findParentRepoFolders(workspaceFolder.uri, userHome, roots, logger);
                for (const parent of parents) {
                    roots.add(parent);
                }
            }
            return [...roots];
        }
        return ( workspaceFolders.map(f => f.uri));
    }
    async findParentRepoFolders(folderUri, userHome, seen, logger) {
        const candidates = [];
        let current = folderUri;
        while (true) {
            try {
                const isRepoRoot = await this.fileService.exists(joinPath(current, ".git"));
                if (isRepoRoot) {
                    if ((await this.workspaceTrustManagementService.getUriTrustInfo(current)).trusted) {
                        candidates.push(current);
                        return candidates;
                    }
                    logger?.logInfo(`Repository root found at ${( current.toString())}, but it is not trusted. Skipping parent folder inclusion for this workspace folder.`);
                    return [];
                }
            } catch (e) {
                const msg = e instanceof Error ? e.message : String(e);
                logger?.logInfo(`No repository root found for folder ${( folderUri.toString())}. Error accessing ${joinPath(current, ".git")}: ${msg}.`);
                return [];
            }
            candidates.push(current);
            const parent = dirname(current);
            if (isEqual(current, parent) || current.path === "/" || isEqual(userHome, parent) || ( seen.has(parent))) {
                break;
            }
            current = parent;
        }
        logger?.logInfo(`No repository root found for folder ${( folderUri.toString())}.`);
        return [];
    }
    async listFiles(type, storage, token) {
        if (storage !== PromptsStorage.user && storage !== PromptsStorage.local) {
            throw ( new Error(`Unsupported prompt file storage: ${storage}`));
        }
        const configuredLocations = this.getPromptSourceFolders(type);
        const absoluteLocations = await this.toAbsoluteLocations(type, configuredLocations.filter(loc => loc.storage === storage));
        if (storage === PromptsStorage.user && (type === PromptsType.agent || type === PromptsType.instructions || type === PromptsType.prompt)) {
            absoluteLocations.push(this.userDataFolder);
        }
        const paths = ( new ResourceSet());
        for (const {
            searchRoot,
            filePattern
        } of absoluteLocations) {
            const files = (filePattern === undefined) ?
            await this.resolveFilesAtLocation(searchRoot, type, token) : await this.searchFilesInLocation(searchRoot, filePattern, token);
            for (const file of files) {
                if (getPromptFileType(file) === type) {
                    paths.add(file);
                }
            }
            if (token.isCancellationRequested) {
                return [];
            }
        }
        return [...paths];
    }
    createFilesUpdatedEvent(type) {
        const disposables = ( new DisposableStore());
        const eventEmitter = disposables.add(( new Emitter()));
        const token = disposables.add(( new CancellationTokenSource())).token;
        const externalFolderWatchers = disposables.add(( new DisposableStore()));
        const key = getPromptFileLocationsConfigKey(type);
        const userDataFolder = this.userDataService.currentProfile.promptsHome;
        let parentFolders = [];
        const updateExternalFolderWatchers = () => {
            externalFolderWatchers.clear();
            for (const folder of parentFolders) {
                if (!this.getWorkspaceFolder(folder.searchRoot)) {
                    const recursive = folder.filePattern !== undefined || type === PromptsType.instructions;
                    externalFolderWatchers.add(this.fileService.watch(folder.searchRoot, {
                        recursive,
                        excludes: []
                    }));
                }
            }
        };
        const update = async () => {
            try {
                const configuredLocations = this.getPromptSourceFolders(type);
                parentFolders = await this.toAbsoluteLocations(type, configuredLocations, undefined);
                if (token.isCancellationRequested) {
                    return;
                }
                updateExternalFolderWatchers();
            } catch (err) {
                this.logService.error(`Error updating prompt file watchers after config change:`, err);
            }
        };
        disposables.add(this.configService.onDidChangeConfiguration(e => {
            if (e.affectsConfiguration(key) || e.affectsConfiguration(PromptsConfig.USE_CUSTOMIZATIONS_IN_PARENT_REPOS)) {
                void update();
                eventEmitter.fire();
            }
        }));
        disposables.add(this.onDidChangeWorkspaceFolders()(() => {
            void update();
            eventEmitter.fire();
        }));
        disposables.add(this.workspaceTrustManagementService.onDidChangeTrustedFolders(() => {
            void update();
            eventEmitter.fire();
        }));
        disposables.add(this.fileService.onDidFilesChange(e => {
            if (e.affects(userDataFolder)) {
                eventEmitter.fire();
                return;
            }
            if (( parentFolders.some(folder => e.affects(folder.searchRoot)))) {
                eventEmitter.fire();
                return;
            }
        }));
        disposables.add(this.fileService.watch(userDataFolder));
        void update();
        return {
            event: eventEmitter.event,
            dispose: () => disposables.dispose()
        };
    }
    async getHookSourceFolders() {
        const configuredLocations = this.getPromptSourceFolders(PromptsType.hook);
        const allowedHookFolders = configuredLocations.filter(loc => !loc.path.startsWith(".claude/") && !loc.path.includes("/.claude/"));
        const absoluteLocations = await this.toAbsoluteLocations(PromptsType.hook, allowedHookFolders);
        const seen = ( new ResourceSet());
        const result = [];
        for (const location of absoluteLocations) {
            if (!( seen.has(location.searchRoot))) {
                seen.add(location.searchRoot);
                result.push({
                    ...location,
                    uri: location.searchRoot,
                    filePattern: undefined
                });
            }
        }
        return result;
    }
    async getConfigBasedSourceFolders(type) {
        const configuredLocations = this.getPromptSourceFolders(type);
        const absoluteLocations = await this.toAbsoluteLocations(type, configuredLocations);
        if (type !== PromptsType.prompt && type !== PromptsType.instructions) {
            return ( absoluteLocations.map(l => l.uri));
        }
        const result = ( new ResourceSet());
        for (const absoluteLocation of absoluteLocations) {
            let location = absoluteLocation.uri;
            const baseName = basename(location);
            const filePatterns = ["*.md", `*${getPromptFileExtension(type)}`];
            for (const filePattern of filePatterns) {
                if (baseName === filePattern) {
                    location = dirname(location);
                    continue;
                }
            }
            if (baseName === "*") {
                location = dirname(location);
            }
            if (isValidGlob(location.path) === true) {
                continue;
            }
            result.add(location);
        }
        return [...result];
    }
    async getResolvedSourceFolders(type) {
        const absoluteLocations = await this.getLocalStorageFolders(type);
        const localFolders = absoluteLocations.filter(loc => loc.storage === PromptsStorage.local);
        const userFolders = absoluteLocations.filter(loc => loc.storage === PromptsStorage.user);
        return this.dedupeSourceFolders([...localFolders, ...userFolders]);
    }
    async getSourceFoldersInDiscoveryOrder(type) {
        const absoluteLocations = await this.getLocalStorageFolders(type);
        const userFolders = absoluteLocations.filter(loc => loc.storage === PromptsStorage.user);
        const localFolders = absoluteLocations.filter(loc => loc.storage === PromptsStorage.local);
        return this.dedupeSourceFolders([...userFolders, ...localFolders]);
    }
    async getLocalStorageFolders(type) {
        const configuredLocations = this.getPromptSourceFolders(type);
        const defaultFolders = this.getDefaultSourceFolders(type);
        const allFolders = [...defaultFolders, ...configuredLocations.filter(loc => !( defaultFolders.some(df => df.path === loc.path)))];
        const absoluteLocations = await this.toAbsoluteLocations(type, allFolders, defaultFolders);
        if (type === PromptsType.agent || type === PromptsType.instructions || type === PromptsType.prompt) {
            absoluteLocations.push(this.userDataFolder);
        }
        return absoluteLocations;
    }
    dedupeSourceFolders(folders) {
        const seen = ( new ResourceSet());
        const result = [];
        for (const folder of folders) {
            if (!( seen.has(folder.uri))) {
                seen.add(folder.uri);
                result.push(folder);
            }
        }
        return result;
    }
    async toAbsoluteLocations(type, configuredLocations, defaultLocations) {
        const result = [];
        const seen = ( new ResourceSet());
        const userHome = await this.pathService.userHome();
        const rootFolders = await this.getWorkspaceFolderRoots(
            this.configService.getValue(PromptsConfig.USE_CUSTOMIZATIONS_IN_PARENT_REPOS) === true
        );
        const defaultPaths = ( new Set(defaultLocations?.map(loc => loc.path)));
        const validLocations = configuredLocations.filter(sourceFolder => {
            if (type === PromptsType.instructions || type === PromptsType.prompt) {
                const path = sourceFolder.path;
                if (hasGlobPattern(path)) {
                    if (type === PromptsType.prompt) {
                        this.logService.warn(
                            `[Deprecated] Glob patterns (* and **) in prompt file locations are deprecated: "${path}". Consider using explicit paths instead.`
                        );
                    } else if (type === PromptsType.instructions) {
                        this.logService.info(
                            `Glob patterns (* and **) detected in instruction file location: "${path}". Consider using explicit paths for better performance.`
                        );
                    }
                }
                return true;
            }
            const configuredLocation = sourceFolder.path;
            if (!isValidPromptFolderPath(configuredLocation)) {
                this.logService.warn(
                    `Skipping invalid path (glob patterns and absolute paths not supported): ${configuredLocation}`
                );
                return false;
            }
            return true;
        });
        for (const sourceFolder of validLocations) {
            const configuredLocation = sourceFolder.path;
            const isDefault = defaultPaths?.has(configuredLocation);
            try {
                if (isTildePath(configuredLocation)) {
                    const uri = joinPath(userHome, configuredLocation.substring(2));
                    if (!( seen.has(uri))) {
                        seen.add(uri);
                        const {
                            searchRoot,
                            filePattern
                        } = resolveSearchLocation(type, uri);
                        result.push({
                            uri,
                            searchRoot: searchRoot,
                            filePattern,
                            source: sourceFolder.source,
                            storage: sourceFolder.storage,
                            displayPath: configuredLocation,
                            isDefault
                        });
                    }
                    continue;
                }
                if (isAbsolute(configuredLocation)) {
                    let uri = URI.file(configuredLocation);
                    const remoteAuthority = this.environmentService.remoteAuthority;
                    if (remoteAuthority) {
                        uri = uri.with({
                            scheme: Schemas.vscodeRemote,
                            authority: remoteAuthority
                        });
                    }
                    if (!( seen.has(uri))) {
                        seen.add(uri);
                        const {
                            searchRoot,
                            filePattern
                        } = resolveSearchLocation(type, uri);
                        result.push({
                            uri,
                            searchRoot: searchRoot,
                            filePattern,
                            source: sourceFolder.source,
                            storage: sourceFolder.storage,
                            displayPath: configuredLocation,
                            isDefault
                        });
                    }
                } else {
                    for (const folder of rootFolders) {
                        const absolutePath = joinPath(folder, configuredLocation);
                        if (!( seen.has(absolutePath))) {
                            seen.add(absolutePath);
                            const {
                                searchRoot,
                                filePattern
                            } = resolveSearchLocation(type, absolutePath);
                            result.push({
                                uri: absolutePath,
                                searchRoot: searchRoot,
                                filePattern,
                                source: sourceFolder.source,
                                storage: sourceFolder.storage,
                                displayPath: configuredLocation,
                                isDefault
                            });
                        }
                    }
                }
            } catch (error) {
                this.logService.error(`Failed to resolve prompt file location: ${configuredLocation}`, error);
            }
        }
        return result;
    }
    async resolveFilesAtLocation(location, type, token, depth = 0) {
        if (type === PromptsType.skill) {
            return this.findAgentSkillsInFolder(location, token);
        }
        const isWorkspaceRoot = depth === 0 && ( this.getWorkspaceFolders().some(f => isEqual(f.uri, location)));
        const recursive = type === PromptsType.instructions && !isWorkspaceRoot && !hasGlobPattern(location.path) && depth < MAX_INSTRUCTIONS_RECURSION_DEPTH;
        try {
            const info = await this.fileService.resolve(location);
            if (token.isCancellationRequested) {
                return [];
            }
            if (info.isFile) {
                return [info.resource];
            } else if (info.isDirectory && info.children) {
                const result = [];
                for (const child of info.children) {
                    if (child.isFile) {
                        result.push(child.resource);
                    } else if (recursive && child.isDirectory) {
                        const subFiles = await this.resolveFilesAtLocation(child.resource, type, token, depth + 1);
                        result.push(...subFiles);
                    }
                }
                return result;
            }
        } catch (e) {
            if (e instanceof FileOperationError && e.fileOperationResult === FileOperationResult.FILE_NOT_FOUND)
                ; else {
                this.logService.error(`Failed to resolve files at location: ${( location.toString())}`, e);
            }
        }
        return [];
    }
    async searchFilesInLocation(folder, filePattern, token) {
        if (!this.searchService.schemeHasFileSearchProvider(folder.scheme)) {
            this.logService.warn(
                `[PromptFilesLocator] No FileSearchProvider available for scheme '${folder.scheme}'. Cannot search for pattern '${filePattern}' in ${( folder.toString())}`
            );
            return [];
        }
        const disregardIgnoreFiles = this.configService.getValue("explorer.excludeGitIgnore");
        const workspaceRoot = this.getWorkspaceFolder(folder);
        const getExcludePattern = folder => getExcludes(this.configService.getValue({
            resource: folder
        })) || {};
        const searchOptions = {
            folderQueries: [{
                folder,
                disregardIgnoreFiles
            }],
            type: QueryType.File,
            shouldGlobMatchFilePattern: true,
            excludePattern: workspaceRoot ? getExcludePattern(workspaceRoot.uri) : undefined,
            ignoreGlobCase: true,
            sortByScore: true,
            filePattern
        };
        try {
            const searchResult = await this.searchService.fileSearch(searchOptions, token);
            if (token.isCancellationRequested) {
                return [];
            }
            return ( searchResult.results.map(r => r.resource));
        } catch (e) {
            if (!isCancellationError(e)) {
                throw e;
            }
        }
        return [];
    }
    async findAgentMDsInWorkspace(token) {
        const result = await Promise.all(( this.getWorkspaceFolders().map(folder => this.findAgentMDsInFolder(folder.uri, token))));
        return result.flat(1);
    }
    async findAgentMDsInFolder(folder, token) {
        if (this.searchService.schemeHasFileSearchProvider(folder.scheme)) {
            const disregardIgnoreFiles = this.configService.getValue("explorer.excludeGitIgnore");
            const getExcludePattern = folder => getExcludes(this.configService.getValue({
                resource: folder
            })) || {};
            const searchOptions = {
                folderQueries: [{
                    folder,
                    disregardIgnoreFiles
                }],
                type: QueryType.File,
                shouldGlobMatchFilePattern: true,
                excludePattern: getExcludePattern(folder),
                filePattern: "**/AGENTS.md",
                ignoreGlobCase: true
            };
            try {
                const searchResult = await this.searchService.fileSearch(searchOptions, token);
                if (token.isCancellationRequested) {
                    return [];
                }
                const results = [];
                for (const r of searchResult.results) {
                    const realPath = undefined;
                    results.push({
                        uri: r.resource,
                        realPath,
                        type: AgentInstructionFileType.agentsMd
                    });
                }
                return results;
            } catch (e) {
                if (!isCancellationError(e)) {
                    throw e;
                }
            }
            return [];
        } else {
            return this.findAgentMDsUsingFileService(folder, token);
        }
    }
    async findAgentMDsUsingFileService(folder, token) {
        const result = [];
        const agentsMdFileName = "agents.md";
        const traverse = async uri => {
            if (token.isCancellationRequested) {
                return;
            }
            try {
                const stat = await this.fileService.resolve(uri);
                if (stat.isFile && stat.name.toLowerCase() === agentsMdFileName) {
                    const realPath = stat.isSymbolicLink ? await this.fileService.realpath(stat.resource) : undefined;
                    result.push({
                        uri: stat.resource,
                        realPath,
                        type: AgentInstructionFileType.agentsMd
                    });
                } else if (stat.isDirectory && stat.children) {
                    for (const child of stat.children) {
                        await traverse(child.resource);
                    }
                }
            } catch (error) {
                this.logService.trace(`[PromptFilesLocator] Error traversing ${( uri.toString())}: ${error}`);
            }
        };
        await traverse(folder);
        return result;
    }
    async findFilesInRoots(roots, folder, paths, token, result = []) {
        const toResolve = ( roots.map(root => ({
            resource: folder !== undefined ? joinPath(root, folder) : root
        })));
        const resolvedRoots = await this.fileService.resolveAll(toResolve);
        if (token.isCancellationRequested) {
            return result;
        }
        for (const root of resolvedRoots) {
            if (root.success && root.stat?.children) {
                for (const child of root.stat.children) {
                    if (child.isFile) {
                        const matchingPath = paths.find(p => equalsIgnoreCase(p.fileName, child.name));
                        if (matchingPath) {
                            const realPath = child.isSymbolicLink ? await this.fileService.realpath(child.resource) : undefined;
                            result.push({
                                uri: child.resource,
                                realPath,
                                type: matchingPath.type
                            });
                        }
                    }
                }
            }
        }
        return result;
    }
    getAgentFileURIFromModeFile(oldURI) {
        if (oldURI.path.endsWith(LEGACY_MODE_FILE_EXTENSION)) {
            let newLocation;
            const workspaceFolder = this.getWorkspaceFolder(oldURI);
            if (workspaceFolder) {
                newLocation = joinPath(
                    workspaceFolder.uri,
                    AGENTS_SOURCE_FOLDER,
                    getCleanPromptName(oldURI) + AGENT_FILE_EXTENSION
                );
            } else if (isEqualOrParent(oldURI, this.userDataService.currentProfile.promptsHome)) {
                newLocation = joinPath(
                    this.userDataService.currentProfile.promptsHome,
                    getCleanPromptName(oldURI) + AGENT_FILE_EXTENSION
                );
            }
            return newLocation;
        }
        return undefined;
    }
    async findAgentSkillsInFolder(uri, token) {
        try {
            const result = [];
            const stat = await this.fileService.resolve(uri);
            if (stat.isDirectory && stat.children) {
                for (const child of stat.children) {
                    try {
                        if (token.isCancellationRequested) {
                            return [];
                        }
                        if (child.isDirectory) {
                            const skillFile = joinPath(child.resource, SKILL_FILENAME);
                            const skillStat = await this.fileService.resolve(skillFile);
                            if (skillStat.isFile) {
                                result.push(skillStat.resource);
                            }
                        }
                    } catch (error) {}
                }
            }
            return result;
        } catch (e) {
            if (!isCancellationError(e)) {
                this.logService.trace(`[PromptFilesLocator] Error searching for skills in ${( uri.toString())}: ${e}`);
            }
            return [];
        }
    }
    async findAgentSkills(token) {
        const configuredLocations = this.getPromptSourceFolders(PromptsType.skill);
        const absoluteLocations = await this.toAbsoluteLocations(PromptsType.skill, configuredLocations);
        const allResults = [];
        for (const {
            uri,
            source,
            storage
        } of absoluteLocations) {
            if (token.isCancellationRequested) {
                return [];
            }
            const results = await this.findAgentSkillsInFolder(uri, token);
            for (const skillUri of results) {
                allResults.push({
                    uri: skillUri,
                    source,
                    storage,
                    type: PromptsType.skill
                });
            }
        }
        return allResults;
    }
};
PromptFilesLocator = ( __decorate([( __param(0, IFileService)), ( __param(1, IConfigurationService)), ( __param(2, IWorkspaceContextService)), ( __param(3, IWorkbenchEnvironmentService)), ( __param(4, ISearchService)), ( __param(5, IUserDataProfileService)), ( __param(6, ILogService)), ( __param(7, IPathService)), ( __param(8, IWorkspaceTrustManagementService))], PromptFilesLocator));
function hasGlobPattern(path) {
    return path.includes("*");
}
function isValidGlob(pattern) {
    let squareBrackets = false;
    let squareBracketsCount = 0;
    let curlyBrackets = false;
    let curlyBracketsCount = 0;
    let previousCharacter;
    for (const char of pattern) {
        if (previousCharacter === "\\") {
            previousCharacter = char;
            continue;
        }
        if (char === "*") {
            return true;
        }
        if (char === "?") {
            return true;
        }
        if (char === "[") {
            squareBrackets = true;
            squareBracketsCount++;
            previousCharacter = char;
            continue;
        }
        if (char === "]") {
            squareBrackets = true;
            squareBracketsCount--;
            previousCharacter = char;
            continue;
        }
        if (char === "{") {
            curlyBrackets = true;
            curlyBracketsCount++;
            continue;
        }
        if (char === "}") {
            curlyBrackets = true;
            curlyBracketsCount--;
            previousCharacter = char;
            continue;
        }
        previousCharacter = char;
    }
    if (squareBrackets && (squareBracketsCount === 0)) {
        return true;
    }
    if (curlyBrackets && (curlyBracketsCount === 0)) {
        return true;
    }
    return false;
}
function resolveSearchLocation(type, location) {
    if (type !== PromptsType.instructions && type !== PromptsType.prompt) {
        return {
            searchRoot: location
        };
    }
    const segments = location.path.split("/");
    let i = 0;
    while (i < segments.length && isValidGlob(segments[i]) === false) {
        i++;
    }
    if (i === segments.length) {
        return {
            searchRoot: location
        };
    }
    const parent = location.with({
        path: segments.slice(0, i).join("/")
    });
    if (i === segments.length - 1 && segments[i] === "*" || segments[i] === ``) {
        return {
            searchRoot: parent
        };
    }
    return {
        searchRoot: parent,
        filePattern: segments.slice(i).join("/")
    };
}
const VALID_PROMPT_FOLDER_PATTERN = "^(?![A-Za-z]:[\\\\/])(?!/)(?!~(?!/))(?!.*\\\\)(?!.*[*?\\[\\]{}]).*\\S.*$";
const VALID_PROMPT_FOLDER_REGEX = ( new RegExp(VALID_PROMPT_FOLDER_PATTERN));
function isValidPromptFolderPath(path) {
    return VALID_PROMPT_FOLDER_REGEX.test(path);
}

export { PromptFilesLocator, VALID_PROMPT_FOLDER_PATTERN, hasGlobPattern, isValidGlob, isValidPromptFolderPath };
