"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.handleGetBuiltinSnippets = handleGetBuiltinSnippets;
exports.handleGetRtwsSnippets = handleGetRtwsSnippets;
exports.handleGetSnippetCatalog = handleGetSnippetCatalog;
exports.handleSaveRtwsSnippet = handleSaveRtwsSnippet;
exports.handleCreateRtwsSnippetGroup = handleCreateRtwsSnippetGroup;
exports.handleToolsetManual = handleToolsetManual;
exports.handleRenderMcpPromptSnippet = handleRenderMcpPromptSnippet;
const promises_1 = __importDefault(require("fs/promises"));
const path_1 = __importDefault(require("path"));
const yaml_1 = __importDefault(require("yaml"));
const log_1 = require("../log");
const resources_1 = require("../mcp/resources");
const supervisor_1 = require("../mcp/supervisor");
const rtws_1 = require("../rtws");
require("../tools/builtins");
const log = (0, log_1.createLogger)('snippets-routes');
function isRecord(value) {
    return typeof value === 'object' && value !== null && !Array.isArray(value);
}
function requireNonEmptyString(value) {
    return typeof value === 'string' && value.trim() !== '' ? value : null;
}
function parseSaveRtwsPromptTemplateRequest(raw) {
    if (!isRecord(raw))
        return null;
    const groupKey = requireNonEmptyString(raw['groupKey']);
    const uiLanguageRaw = raw['uiLanguage'];
    const uiLanguage = uiLanguageRaw === 'zh' || uiLanguageRaw === 'en' ? uiLanguageRaw : null;
    const name = requireNonEmptyString(raw['name']);
    const content = requireNonEmptyString(raw['content']);
    if (!groupKey || !uiLanguage || !name || !content)
        return null;
    const fileNameRaw = raw['fileName'];
    const fileName = typeof fileNameRaw === 'string' && fileNameRaw.trim() !== '' ? fileNameRaw : undefined;
    const descriptionRaw = raw['description'];
    const description = typeof descriptionRaw === 'string' && descriptionRaw.trim() !== '' ? descriptionRaw : undefined;
    return { name, uiLanguage, fileName, description, content, groupKey };
}
function parseCreateRtwsSnippetGroupRequest(raw) {
    if (!isRecord(raw))
        return null;
    const title = requireNonEmptyString(raw['title']);
    const uiLanguageRaw = raw['uiLanguage'];
    const uiLanguage = uiLanguageRaw === 'zh' || uiLanguageRaw === 'en' ? uiLanguageRaw : null;
    if (!title || !uiLanguage)
        return null;
    return { title: title.trim(), uiLanguage };
}
function parseRenderMcpPromptSnippetRequest(raw) {
    if (!isRecord(raw))
        return null;
    const promptId = requireNonEmptyString(raw['promptId']);
    if (!promptId)
        return null;
    const argsRaw = raw['arguments'];
    if (argsRaw === undefined)
        return { promptId };
    if (!isRecord(argsRaw))
        return null;
    const args = {};
    for (const [key, value] of Object.entries(argsRaw)) {
        if (typeof value !== 'string')
            return null;
        args[key] = value;
    }
    return { promptId, arguments: args };
}
function buildRtwsTemplateTokenFromName(name) {
    return sanitizeRtwsTemplateFileName(name);
}
function buildRtwsTemplateTokenFromFileName(fileName) {
    return sanitizeRtwsTemplateFileName(fileName);
}
function parseCatalogYaml(rawText) {
    try {
        const parsed = yaml_1.default.parse(rawText);
        if (!isRecord(parsed))
            return null;
        const out = {};
        for (const [k, v] of Object.entries(parsed)) {
            if (!isRecord(v))
                continue;
            out[k] = {
                name: typeof v['name'] === 'string' ? v['name'] : undefined,
                'name-zh': typeof v['name-zh'] === 'string' ? v['name-zh'] : undefined,
                snippets: v['snippets'],
            };
        }
        return out;
    }
    catch {
        return null;
    }
}
async function loadCatalogFromPath(abs) {
    try {
        const raw = await promises_1.default.readFile(abs, 'utf-8');
        return parseCatalogYaml(raw);
    }
    catch {
        return null;
    }
}
function stripLangSuffixFromSnippetId(id) {
    if (id.endsWith('.zh.md'))
        return id.slice(0, -'.zh.md'.length);
    if (id.endsWith('.en.md'))
        return id.slice(0, -'.en.md'.length);
    if (id.endsWith('.md'))
        return id.slice(0, -'.md'.length);
    return id;
}
function detectSnippetLanguageFromPath(filePath) {
    if (typeof filePath !== 'string')
        return null;
    const lowered = filePath.replace(/\\/g, '/').toLowerCase();
    if (lowered.endsWith('.zh.md'))
        return 'zh';
    if (lowered.endsWith('.en.md'))
        return 'en';
    return null;
}
function pickBestSnippetVariant(candidates, uiLanguage) {
    const first = candidates[0] ?? null;
    if (!first)
        return null;
    if (!uiLanguage)
        return first;
    for (const tpl of candidates) {
        if (detectSnippetLanguageFromPath(tpl.path) === uiLanguage)
            return tpl;
    }
    for (const tpl of candidates) {
        if (detectSnippetLanguageFromPath(tpl.path) === null)
            return tpl;
    }
    return first;
}
async function buildSnippetCatalog(uiLanguage) {
    const builtin = await readBuiltinSnippets();
    const rtws = await readRtwsSnippets();
    const mcpPromptGroups = buildMcpPromptSnippetGroups();
    const serverRoot = path_1.default.resolve(__dirname, '..', '..');
    const builtinCatalogAbs = path_1.default.resolve(serverRoot, 'dist', 'snippets', 'catalog.yaml');
    const builtinCatalogFallbackAbs = path_1.default.resolve(serverRoot, 'snippets', 'catalog.yaml');
    const rtwsRoot = (0, rtws_1.domindsRtwsRootAbs)();
    const rtwsCatalogAbs = path_1.default.resolve(rtwsRoot, '.minds', 'snippets', 'catalog.yaml');
    const builtinCatalog = (await loadCatalogFromPath(builtinCatalogAbs)) ??
        (await loadCatalogFromPath(builtinCatalogFallbackAbs));
    const rtwsCatalog = await loadCatalogFromPath(rtwsCatalogAbs);
    if (!builtinCatalog && !rtwsCatalog) {
        return [
            {
                key: 'all',
                titleI18n: { en: 'All', zh: '全部' },
                templates: [...builtin, ...rtws],
            },
            ...mcpPromptGroups,
        ];
    }
    const builtinByToken = new Map();
    for (const tpl of builtin) {
        const p = typeof tpl.path === 'string' ? tpl.path : '';
        if (!p.startsWith('snippets/'))
            continue;
        const noExt = stripLangSuffixFromSnippetId(p);
        const token = noExt.replace(/^snippets\//, '');
        const prev = builtinByToken.get(token);
        if (prev) {
            prev.push(tpl);
        }
        else {
            builtinByToken.set(token, [tpl]);
        }
    }
    const rtwsByGroupAndToken = new Map();
    for (const tpl of rtws) {
        const p = typeof tpl.path === 'string' ? tpl.path : '';
        if (!p.startsWith('.minds/snippets/'))
            continue;
        const rel = p.slice('.minds/snippets/'.length);
        const parts = rel.split('/').filter((x) => x !== '');
        const groupKey = parts[0];
        const rest = parts.slice(1).join('/');
        if (!groupKey || !rest)
            continue;
        const token = stripLangSuffixFromSnippetId(rest);
        const k = `${groupKey}/${token}`;
        const prev = rtwsByGroupAndToken.get(k);
        if (prev) {
            prev.push(tpl);
        }
        else {
            rtwsByGroupAndToken.set(k, [tpl]);
        }
    }
    const keys = [];
    if (builtinCatalog) {
        keys.push(...Object.keys(builtinCatalog));
    }
    if (rtwsCatalog) {
        for (const k of Object.keys(rtwsCatalog)) {
            if (!keys.includes(k))
                keys.push(k);
        }
    }
    const groups = [];
    for (const groupKey of keys) {
        const metaBuiltin = builtinCatalog ? builtinCatalog[groupKey] : undefined;
        const metaRtws = rtwsCatalog ? rtwsCatalog[groupKey] : undefined;
        const titleEn = metaRtws?.name ?? metaBuiltin?.name ?? groupKey;
        const titleZh = metaRtws?.['name-zh'] ??
            metaBuiltin?.['name-zh'] ??
            metaRtws?.name ??
            metaBuiltin?.name ??
            groupKey;
        const templates = [];
        if (metaBuiltin && Array.isArray(metaBuiltin.snippets)) {
            for (const raw of metaBuiltin.snippets) {
                if (typeof raw !== 'string')
                    continue;
                const token = raw.trim();
                if (!token)
                    continue;
                const candidates = builtinByToken.get(token) ?? [];
                const tpl = pickBestSnippetVariant(candidates, uiLanguage);
                if (tpl)
                    templates.push(tpl);
            }
        }
        if (metaRtws && Array.isArray(metaRtws.snippets)) {
            for (const raw of metaRtws.snippets) {
                if (typeof raw !== 'string')
                    continue;
                const token = raw.trim();
                if (!token)
                    continue;
                const candidates = rtwsByGroupAndToken.get(`${groupKey}/${token}`) ?? [];
                const tpl = pickBestSnippetVariant(candidates, uiLanguage);
                if (tpl)
                    templates.push(tpl);
            }
        }
        // Keep empty groups so the UI can show newly-created rtws groups before adding snippets.
        // If an rtws template uses the same display name as a builtin template,
        // prefer the rtws version to support "override" via same-name saves.
        const rtwsNames = new Set();
        for (const tpl of templates) {
            if (tpl.source === 'rtws')
                rtwsNames.add(tpl.name);
        }
        const filtered = [];
        const seenNames = new Set();
        for (const tpl of templates) {
            if (tpl.source === 'builtin' && rtwsNames.has(tpl.name)) {
                continue;
            }
            if (seenNames.has(tpl.name)) {
                continue;
            }
            seenNames.add(tpl.name);
            filtered.push(tpl);
        }
        groups.push({ key: groupKey, titleI18n: { en: titleEn, zh: titleZh }, templates: filtered });
    }
    if (groups.length === 0) {
        return [
            {
                key: 'all',
                titleI18n: { en: 'All', zh: '全部' },
                templates: [...builtin, ...rtws],
            },
            ...mcpPromptGroups,
        ];
    }
    return [...groups, ...mcpPromptGroups];
}
function buildMcpPromptSnippetGroups() {
    const byServer = new Map();
    for (const prompt of (0, resources_1.listMcpPrompts)()) {
        const list = byServer.get(prompt.serverId) ?? [];
        list.push({
            id: `mcp_prompt:${prompt.id}`,
            name: prompt.title,
            description: prompt.description,
            content: '',
            source: 'mcp_prompt',
            readonly: true,
            mcpPrompt: {
                serverId: prompt.serverId,
                promptId: prompt.id,
                name: prompt.name,
                arguments: prompt.arguments,
            },
        });
        byServer.set(prompt.serverId, list);
    }
    return [...byServer.entries()]
        .sort((a, b) => a[0].localeCompare(b[0]))
        .map(([serverId, templates]) => ({
        key: `mcp:${serverId}`,
        titleI18n: { en: `MCP Prompts: ${serverId}`, zh: `MCP 提示词：${serverId}` },
        templates: templates.sort((a, b) => a.name.localeCompare(b.name)),
    }));
}
async function ensureRtwsCatalogGroup(snippetsDirAbs, request) {
    const title = request.title.trim();
    if (title === '')
        return { success: false, error: 'Missing title' };
    const base = sanitizeRtwsTemplateFileName(title);
    if (base === 'all') {
        return { success: false, error: "Group key 'all' is reserved" };
    }
    const catalogAbs = path_1.default.resolve(snippetsDirAbs, 'catalog.yaml');
    let catalog = {};
    try {
        const raw = await promises_1.default.readFile(catalogAbs, 'utf-8');
        const parsed = parseCatalogYaml(raw);
        if (parsed)
            catalog = parsed;
    }
    catch {
        // ignore
    }
    let groupKey = base;
    if (isRecord(catalog[groupKey])) {
        // Auto-suffix for uniqueness.
        for (let i = 2; i < 1000; i += 1) {
            const candidate = `${base}-${i}`;
            if (!isRecord(catalog[candidate])) {
                groupKey = candidate;
                break;
            }
        }
        if (groupKey === base) {
            return { success: false, error: 'Failed to allocate unique group key' };
        }
    }
    const meta = {
        snippets: [],
    };
    if (request.uiLanguage === 'zh') {
        meta['name-zh'] = title;
        meta['name'] = title;
    }
    else {
        meta['name'] = title;
        meta['name-zh'] = title;
    }
    catalog[groupKey] = meta;
    await promises_1.default.mkdir(snippetsDirAbs, { recursive: true });
    await promises_1.default.writeFile(catalogAbs, yaml_1.default.stringify(catalog), 'utf-8');
    return { success: true, groupKey };
}
function parseToolsetManualRequest(raw) {
    if (!isRecord(raw))
        return null;
    const toolsetId = requireNonEmptyString(raw['toolsetId']);
    const uiLanguageRaw = raw['uiLanguage'];
    const uiLanguage = uiLanguageRaw === 'zh' || uiLanguageRaw === 'en' ? uiLanguageRaw : null;
    if (!toolsetId || !uiLanguage)
        return null;
    const topic = typeof raw['topic'] === 'string' && raw['topic'].trim() !== ''
        ? raw['topic'].trim()
        : undefined;
    const topicsValue = raw['topics'];
    if (topicsValue === undefined) {
        return { toolsetId, topic, uiLanguage, topics: undefined };
    }
    if (!Array.isArray(topicsValue))
        return null;
    const topics = [];
    for (const v of topicsValue) {
        if (typeof v !== 'string')
            return null;
        topics.push(v);
    }
    return { toolsetId, topic, uiLanguage, topics };
}
function safeTemplateIdFromPath(relPath) {
    return relPath.replace(/\\/g, '/');
}
function stripOptionalBom(text) {
    return text.charCodeAt(0) === 0xfeff ? text.slice(1) : text;
}
function parseFrontmatter(rawText) {
    const normalized = stripOptionalBom(rawText).replace(/\r\n/g, '\n');
    const m = normalized.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
    if (!m)
        return { kind: 'none', body: rawText };
    const fmText = m[1] ?? '';
    const body = m[2] ?? '';
    try {
        const parsed = yaml_1.default.parse(fmText);
        if (!isRecord(parsed))
            return { kind: 'none', body };
        const name = typeof parsed['name'] === 'string' ? parsed['name'] : undefined;
        const description = typeof parsed['description'] === 'string' ? parsed['description'] : undefined;
        return { kind: 'parsed', body, name, description };
    }
    catch {
        return { kind: 'none', body };
    }
}
function safeBasenameToName(filename) {
    const base = filename.replace(/\.md$/i, '').trim();
    return base === '' ? filename : base;
}
function ensureInsideDir(dirAbs, candidateAbs) {
    const relative = path_1.default.relative(dirAbs, candidateAbs);
    return relative === '' || (!relative.startsWith('..') && !path_1.default.isAbsolute(relative));
}
async function listMarkdownFilesRecursively(dirAbs) {
    const out = [];
    const walk = async (abs) => {
        let entries;
        try {
            entries = await promises_1.default.readdir(abs, { withFileTypes: true });
        }
        catch {
            return;
        }
        for (const ent of entries) {
            const childAbs = path_1.default.join(abs, ent.name);
            if (ent.isDirectory()) {
                await walk(childAbs);
                continue;
            }
            if (ent.isFile() && ent.name.toLowerCase().endsWith('.md')) {
                out.push(childAbs);
            }
        }
    };
    await walk(dirAbs);
    return out;
}
async function readBuiltinSnippets() {
    const serverRoot = path_1.default.resolve(__dirname, '..', '..');
    const candidates = [
        path_1.default.resolve(serverRoot, 'dist', 'snippets'),
        path_1.default.resolve(serverRoot, 'snippets'),
    ];
    let snippetsDir = null;
    for (const dir of candidates) {
        try {
            const st = await promises_1.default.stat(dir);
            if (st.isDirectory()) {
                snippetsDir = dir;
                break;
            }
        }
        catch {
            // ignore
        }
    }
    if (!snippetsDir)
        return [];
    const files = await listMarkdownFilesRecursively(snippetsDir);
    const templates = [];
    for (const abs of files) {
        if (path_1.default.basename(abs).toLowerCase() === 'readme.md')
            continue;
        try {
            const raw = await promises_1.default.readFile(abs, 'utf-8');
            const parsed = parseFrontmatter(raw);
            const rel = path_1.default.relative(snippetsDir, abs).replace(/\\/g, '/');
            templates.push({
                id: `builtin:${safeTemplateIdFromPath(rel)}`,
                name: parsed.kind === 'parsed' && parsed.name
                    ? parsed.name
                    : safeBasenameToName(path_1.default.basename(abs)),
                description: parsed.kind === 'parsed' ? parsed.description : undefined,
                content: parsed.kind === 'parsed' ? parsed.body : raw,
                source: 'builtin',
                path: `snippets/${rel}`,
            });
        }
        catch {
            // ignore unreadable file
        }
    }
    return templates;
}
async function readRtwsSnippets() {
    const rtwsRoot = (0, rtws_1.domindsRtwsRootAbs)();
    const snippetsDir = path_1.default.resolve(rtwsRoot, '.minds', 'snippets');
    const files = await listMarkdownFilesRecursively(snippetsDir);
    const templates = [];
    for (const abs of files) {
        if (path_1.default.basename(abs).toLowerCase() === 'catalog.yaml')
            continue;
        try {
            const raw = await promises_1.default.readFile(abs, 'utf-8');
            const parsed = parseFrontmatter(raw);
            const rel = path_1.default.relative(snippetsDir, abs).replace(/\\/g, '/');
            templates.push({
                id: `rtws:${safeTemplateIdFromPath(rel)}`,
                name: parsed.kind === 'parsed' && parsed.name
                    ? parsed.name
                    : safeBasenameToName(path_1.default.basename(abs)),
                description: parsed.kind === 'parsed' ? parsed.description : undefined,
                content: parsed.kind === 'parsed' ? parsed.body : raw,
                source: 'rtws',
                path: `.minds/snippets/${rel}`,
            });
        }
        catch {
            // ignore
        }
    }
    return templates;
}
function sanitizeRtwsTemplateFileName(name) {
    const trimmed = name.trim();
    const base = trimmed.replace(/[^a-zA-Z0-9\-_\u4e00-\u9fff]+/g, '-').replace(/-+/g, '-');
    const safe = base.replace(/^[-_]+/, '').replace(/[-_]+$/, '');
    return safe === '' ? 'prompt' : safe;
}
async function upsertRtwsCatalogEntry(snippetsDirAbs, groupKey, token) {
    const catalogAbs = path_1.default.resolve(snippetsDirAbs, 'catalog.yaml');
    let catalog = {};
    try {
        const raw = await promises_1.default.readFile(catalogAbs, 'utf-8');
        const parsed = parseCatalogYaml(raw);
        if (parsed)
            catalog = parsed;
    }
    catch {
        // ignore
    }
    const existing = catalog[groupKey];
    const meta = isRecord(existing) ? { ...existing } : {};
    const prevSnippets = meta['snippets'];
    const snippets = [];
    if (Array.isArray(prevSnippets)) {
        for (const item of prevSnippets) {
            if (typeof item === 'string' && item.trim() !== '')
                snippets.push(item.trim());
        }
    }
    if (!snippets.includes(token))
        snippets.push(token);
    meta['snippets'] = snippets;
    catalog[groupKey] = meta;
    await promises_1.default.mkdir(snippetsDirAbs, { recursive: true });
    await promises_1.default.writeFile(catalogAbs, yaml_1.default.stringify(catalog), 'utf-8');
}
async function handleGetBuiltinSnippets() {
    try {
        const templates = await readBuiltinSnippets();
        return { success: true, templates };
    }
    catch (error) {
        log.error('Failed to read builtin snippets', error);
        return { success: false, error: 'Failed to load builtin snippets' };
    }
}
async function handleGetRtwsSnippets() {
    try {
        const templates = await readRtwsSnippets();
        return { success: true, templates };
    }
    catch (error) {
        log.error('Failed to read rtws snippets', error);
        return { success: false, error: 'Failed to load rtws snippets' };
    }
}
async function handleGetSnippetCatalog(uiLanguage = null) {
    try {
        const groups = await buildSnippetCatalog(uiLanguage);
        return { success: true, groups };
    }
    catch (error) {
        log.error('Failed to build snippet catalog', error);
        return { success: false, error: 'Failed to load snippet catalog' };
    }
}
async function handleSaveRtwsSnippet(rawBody) {
    let parsed;
    try {
        parsed = rawBody ? JSON.parse(rawBody) : {};
    }
    catch {
        return { success: false, error: 'Invalid JSON body' };
    }
    const req = parseSaveRtwsPromptTemplateRequest(parsed);
    if (!req)
        return { success: false, error: 'Invalid request body' };
    const rtwsRoot = (0, rtws_1.domindsRtwsRootAbs)();
    const snippetsDir = path_1.default.resolve(rtwsRoot, '.minds', 'snippets');
    const safeName = typeof req.fileName === 'string' && req.fileName.trim() !== ''
        ? sanitizeRtwsTemplateFileName(req.fileName)
        : sanitizeRtwsTemplateFileName(req.name);
    const langSuffix = req.uiLanguage;
    const fileBasename = safeName.endsWith(`.${langSuffix}`) ? safeName : `${safeName}.${langSuffix}`;
    const groupKey = sanitizeRtwsTemplateFileName(req.groupKey);
    const fileAbs = path_1.default.resolve(snippetsDir, groupKey, `${fileBasename}.md`);
    if (!ensureInsideDir(snippetsDir, fileAbs)) {
        return { success: false, error: 'Invalid template name' };
    }
    try {
        await promises_1.default.mkdir(path_1.default.dirname(fileAbs), { recursive: true });
        const headerData = { name: req.name.trim() };
        if (typeof req.description === 'string' && req.description.trim() !== '') {
            headerData['description'] = req.description.trim();
        }
        const header = yaml_1.default.stringify(headerData).trimEnd();
        const serialized = `---\n${header}\n---\n\n${req.content.trimEnd()}\n`;
        await promises_1.default.writeFile(fileAbs, serialized, 'utf-8');
        await upsertRtwsCatalogEntry(snippetsDir, groupKey, typeof req.fileName === 'string' && req.fileName.trim() !== ''
            ? buildRtwsTemplateTokenFromFileName(req.fileName)
            : buildRtwsTemplateTokenFromName(req.name));
        const rel = path_1.default.relative(snippetsDir, fileAbs).replace(/\\/g, '/');
        return {
            success: true,
            template: {
                id: `rtws:${safeTemplateIdFromPath(rel)}`,
                name: req.name.trim(),
                description: typeof req.description === 'string' ? req.description : undefined,
                content: req.content,
                source: 'rtws',
                path: `.minds/snippets/${rel}`,
            },
        };
    }
    catch (error) {
        log.error('Failed to save rtws snippet', error);
        return { success: false, error: 'Failed to save snippet template' };
    }
}
async function handleCreateRtwsSnippetGroup(rawBody) {
    let parsed;
    try {
        parsed = rawBody ? JSON.parse(rawBody) : {};
    }
    catch {
        return { success: false, error: 'Invalid JSON body' };
    }
    const req = parseCreateRtwsSnippetGroupRequest(parsed);
    if (!req)
        return { success: false, error: 'Invalid request body' };
    const rtwsRoot = (0, rtws_1.domindsRtwsRootAbs)();
    const snippetsDir = path_1.default.resolve(rtwsRoot, '.minds', 'snippets');
    try {
        return await ensureRtwsCatalogGroup(snippetsDir, req);
    }
    catch (error) {
        log.error('Failed to create rtws snippet group', error);
        return { success: false, error: 'Failed to create snippet group' };
    }
}
async function handleToolsetManual(rawBody) {
    let parsed;
    try {
        parsed = rawBody ? JSON.parse(rawBody) : {};
    }
    catch {
        return { success: false, error: 'Invalid JSON body' };
    }
    const req = parseToolsetManualRequest(parsed);
    if (!req)
        return { success: false, error: 'Invalid request body' };
    try {
        const { renderToolsetManualContent } = await import('../tools/toolset-manual.js');
        const markdown = await renderToolsetManualContent({
            toolsetId: req.toolsetId,
            language: req.uiLanguage,
            ...(req.topic ? { topic: req.topic } : {}),
            ...(req.topics ? { topics: req.topics } : {}),
        });
        return { success: true, markdown: String(markdown) };
    }
    catch (error) {
        const msg = error instanceof Error ? error.message : 'Failed to load toolset manual';
        log.error('Failed to call man tool', error);
        return { success: false, error: msg };
    }
}
async function handleRenderMcpPromptSnippet(rawBody) {
    try {
        const parsed = JSON.parse(rawBody || '{}');
        const req = parseRenderMcpPromptSnippetRequest(parsed);
        if (!req)
            return { success: false, error: 'Invalid MCP prompt render request' };
        const prompt = (0, resources_1.getMcpPrompt)(req.promptId);
        if (!prompt)
            return { success: false, error: `MCP prompt not found: ${req.promptId}` };
        const content = await (0, supervisor_1.withMcpCatalogClient)(prompt.serverId, async (client) => {
            return await (0, resources_1.renderMcpPrompt)({
                serverId: prompt.serverId,
                client,
                promptName: prompt.name,
                arguments: req.arguments,
            });
        });
        return { success: true, content };
    }
    catch (error) {
        const msg = error instanceof Error ? error.message : 'Failed to render MCP prompt';
        log.error('Failed to render MCP prompt snippet', error);
        return { success: false, error: msg };
    }
}
