import { isMCPItemType } from '../utils/type-predicates.js';
import { basicSearch } from '../utils/basic-search.js';
/**
 * MCP context provider.
 * Syntax: #[[mcp:type:server-name:identifier]]
 *
 * The identifier segment is type-dependent: URI for resources, URI template for resource
 * templates, and prompt name for prompts (prompts have no URI in the MCP spec).
 *
 * Every getItems() call fetches the full list fresh from the extension side,
 * replacing the cached snapshot used by search().
 */
export class MCPContextProvider {
    resolvers;
    listItems;
    id = 'mcp';
    name = 'MCP';
    description = 'Reference an MCP resource or prompt';
    cache = new Map();
    constructor(resolvers, listItems) {
        this.resolvers = resolvers;
        this.listItems = listItems;
    }
    /**
     * Resolves the MCP resource or prompt for the given query path.
     *
     * There may be additional arguments passed in to the resolution via query string (e.g. ?foo=bar)
     */
    async resolveContent(query) {
        const [type, serverName, ...rest] = query.split(':');
        const identifierWithParams = rest.join(':');
        const [identifier, ...paramString] = identifierWithParams.split('?');
        if (!type || !serverName || !identifier || paramString.length > 1 || !isMCPItemType(type)) {
            return `Malformed query while processing MCP context: ${query}`;
        }
        const [params] = paramString;
        const args = params ? Object.fromEntries(new URLSearchParams(params)) : undefined;
        if (type === 'prompt') {
            const contextItem = this.cache.get(`${type}:${serverName}:${identifier}`);
            const promptName = contextItem?.metadata?.promptName;
            if (!promptName) {
                return `Prompt without name found while processing MCP context: ${query}`;
            }
            const result = await this.resolvers.mcpPromptResolver(serverName, promptName, args);
            if (result instanceof Error) {
                return result.message;
            }
            if (!result) {
                return `No prompt found for ${serverName} and prompt ${promptName}`;
            }
            return result.messages
                .map((msg) => {
                if (typeof msg.content === 'string') {
                    return msg.content;
                }
                if (msg.content.type === 'text' && msg.content.text) {
                    return msg.content.text;
                }
                if (msg.content.type === 'resource' && msg.content.resource.text) {
                    return msg.content.resource.text;
                }
                return '';
            })
                .filter((text) => text.length > 0)
                .join('\n\n');
        }
        const resolvedUri = type === 'resourceTemplate' ? this.expandUriTemplate(identifier, args ?? {}) : identifier;
        const contents = await this.resolvers.mcpResourceResolver(serverName, resolvedUri);
        if (contents instanceof Error) {
            return contents.message;
        }
        if (!contents?.length) {
            return `No resource found for ${serverName} at ${resolvedUri}`;
        }
        return contents
            .map((resource) => {
            if (resource.text) {
                return resource.text;
            }
            if (resource.blob) {
                const { mimeType } = resource;
                if ((mimeType && mimeType.startsWith('text/')) || mimeType === 'application/json') {
                    return Buffer.from(resource.blob, 'base64').toString('utf-8');
                }
            }
            return '';
        })
            .filter((text) => text.length > 0)
            .join('\n\n');
    }
    expandUriTemplate(template, args) {
        return template.replace(/\{([^}]+)\}/g, (_, key) => encodeURIComponent(args[key] ?? ''));
    }
    /** Fetches the current MCP items and replaces the cached snapshot. */
    async getItems() {
        const items = await this.listItems();
        for (const item of items) {
            const identifier = this.getIdentifier(item);
            this.cache.set(`${item.type}:${item.serverName}:${identifier}`, this.transformItem(item));
        }
        return Array.from(this.cache.values());
    }
    /** Substring search across the last cached result. */
    search(query) {
        return basicSearch(Array.from(this.cache.values()), query);
    }
    transformItem(item) {
        const { description, name, serverName, type } = item;
        const identifier = this.getIdentifier(item);
        const contextItem = {
            name: `[${serverName}] ${name}`,
            description,
            query: `${type}:${serverName}:${identifier}`,
        };
        if (type === 'prompt') {
            contextItem.metadata = {
                promptName: item.promptName,
                arguments: item.arguments,
            };
        }
        if (type === 'resourceTemplate') {
            contextItem.metadata = {
                arguments: item.arguments,
            };
        }
        return contextItem;
    }
    /**
     * Returns the unique identifier for an MCP item within its server+type namespace.
     * Resources use their URI, resource templates use their URI template, and prompts
     * use their prompt name — because prompts have no URI (it's always an empty string).
     */
    getIdentifier(item) {
        if (item.type === 'prompt')
            return item.promptName;
        if (item.type === 'resourceTemplate')
            return item.uriTemplate;
        return item.uri;
    }
}
//# sourceMappingURL=mcp.js.map