/*
 * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.
 */
import * as z from "zod";
import { CloudinarySMDCore } from "../core.js";
import { ServerRegion$zodSchema } from "../lib/config.js";
import { mcpScopes } from "./scopes.js";
import { valueToBase64 } from "./shared.js";
const VALID_ANNOTATIONS = [
    "readOnly",
    "destructive",
    "idempotent",
    "openWorld",
];
const annotationToKey = {
    readOnly: "readOnlyHint",
    destructive: "destructiveHint",
    idempotent: "idempotentHint",
    openWorld: "openWorldHint",
};
export function buildAnnotationFilter(annotations) {
    const filter = {};
    if (!annotations || annotations.length === 0) {
        return filter;
    }
    for (const a of annotations) {
        if (!VALID_ANNOTATIONS.includes(a)) {
            throw new Error(`Invalid annotation filter: "${a}". Valid values are: ${VALID_ANNOTATIONS.join(", ")}`);
        }
    }
    for (const name of VALID_ANNOTATIONS) {
        filter[annotationToKey[name]] = annotations.includes(name);
    }
    return filter;
}
// Optional function to assist with formatting tool results
export async function formatResult(response) {
    let content = [];
    const contentType = response?.headers.get("content-type") ?? "";
    if (contentType.startsWith("image/")) {
        const data = await valueToBase64(await response.arrayBuffer());
        content = data == null
            ? []
            : [{ type: "image", data, mimeType: contentType }];
    }
    else if (contentType.startsWith("audio/")) {
        const data = await valueToBase64(await response.arrayBuffer());
        content = data == null
            ? []
            : [{ type: "audio", data, mimeType: contentType }];
    }
    else {
        const text = await response.text();
        content = [{ type: "text", text }];
    }
    return response.ok ? { content } : { content, isError: true };
}
export function createRegisterTool(logger, server, getSDK, allowedScopes, allowedTools, dynamic, annotationFilter) {
    const tools = [];
    const toolMap = new Map();
    const registerTool = (tool) => {
        if (allowedTools && !allowedTools.has(tool.name)) {
            return;
        }
        const scopes = tool.scopes ?? [];
        if (allowedScopes.size > 0 && scopes.length === 0) {
            return;
        }
        if (allowedScopes.size > 0
            && !scopes.every((s) => allowedScopes.has(s))) {
            return;
        }
        if (annotationFilter) {
            const a = tool.annotations;
            if (annotationFilter.readOnlyHint !== undefined
                && a.readOnlyHint !== annotationFilter.readOnlyHint) {
                return;
            }
            if (annotationFilter.destructiveHint !== undefined
                && a.destructiveHint !== annotationFilter.destructiveHint) {
                return;
            }
            if (annotationFilter.idempotentHint !== undefined
                && a.idempotentHint !== annotationFilter.idempotentHint) {
                return;
            }
            if (annotationFilter.openWorldHint !== undefined
                && a.openWorldHint !== annotationFilter.openWorldHint) {
                return;
            }
        }
        toolMap.set(tool.name, tool);
        if (dynamic) {
            logger.debug("Collected tool for dynamic mode", { name: tool.name });
            tools.push({ name: tool.name, description: tool.description });
            return;
        }
        if (tool.args) {
            server.registerTool(tool.name, {
                description: tool.description,
                inputSchema: tool.args,
                annotations: tool.annotations,
            }, async (args, ctx) => {
                return tool.tool(getSDK(), args, ctx);
            });
        }
        else {
            server.registerTool(tool.name, {
                description: tool.description,
                annotations: tool.annotations,
            }, async (ctx) => {
                return tool.tool(getSDK(), ctx);
            });
        }
        logger.debug("Registered tool", { name: tool.name });
        tools.push({ name: tool.name, description: tool.description });
    };
    return [registerTool, tools, toolMap];
}
function matchesSearchTerms(terms, name, def) {
    if (terms.length === 0) {
        return true;
    }
    const nameLower = name.toLowerCase();
    const descLower = def.description.toLowerCase();
    const scopesLower = def.scopes?.flatMap((s) => {
        return typeof s === "string" ? [s.toLowerCase()] : [];
    }) || [];
    return terms.some((term) => nameLower.includes(term)
        || descLower.includes(term)
        || scopesLower.some((s) => s.includes(term)));
}
export function registerDynamicTools(logger, server, getSDK, toolMap, allowedScopes) {
    // 1. list_tools
    server.registerTool("list_tools", {
        description: "List available tools. Optionally filter by search terms that match against tool name, description, and scopes.",
        inputSchema: {
            search_terms: z.array(z.string()).optional().describe([
                "Filter the list of tools.",
                "Each term is matched case-insensitively as a substring against tool name, description, and scopes.",
                "Multiple terms are combined with a logical OR: a tool is included if ANY term matches ANY field.",
                "If not provided, all tools are returned.",
            ].join("\n")),
        },
        annotations: {
            title: "List Tools",
            readOnlyHint: true,
            destructiveHint: false,
            idempotentHint: true,
            openWorldHint: false,
        },
    }, async (args) => {
        const terms = (args.search_terms ?? []).map((t) => t.toLowerCase());
        const tools = [];
        for (const [name, def] of toolMap) {
            if (!matchesSearchTerms(terms, name, def)) {
                continue;
            }
            tools.push({
                name: name,
                description: def.description,
                scopes: def.scopes,
            });
        }
        return {
            content: [{ type: "text", text: JSON.stringify(tools, null, 2) }],
        };
    });
    logger.debug("Registered dynamic meta-tool", { name: "list_tools" });
    // 2. describe_tool
    server.registerTool("describe_tool_input", {
        description: "Get the input schema for one or more tools. It is a good idea to call this tool first to understand how to successfully call execute_tool.",
        inputSchema: {
            tool_names: z.array(z.string()).describe("The names of the tools to describe"),
        },
        annotations: {
            title: "Describe Tool",
            readOnlyHint: true,
            destructiveHint: false,
            idempotentHint: true,
            openWorldHint: false,
        },
    }, async (args) => {
        const parts = [];
        const unknown = [];
        if (args.tool_names.length === 0) {
            return { content: [{ type: "text", text: "No tool names provided." }] };
        }
        for (const toolName of args.tool_names) {
            const def = toolMap.get(toolName);
            if (!def) {
                unknown.push(toolName);
                continue;
            }
            let schemaText = `<input_schema tool="${toolName}">\n\n`;
            if (def.args) {
                const jsonSchema = z.toJSONSchema(z.object(def.args), {
                    target: "draft-2020-12",
                });
                schemaText += JSON.stringify(jsonSchema, null, 2);
            }
            else {
                schemaText += "This tool takes no input parameters.";
            }
            schemaText += `\n\n</input_schema>`;
            parts.push(schemaText);
        }
        if (unknown.length > 0) {
            parts.push(`Unknown tools: ${unknown.join(", ")}`);
        }
        return { content: [{ type: "text", text: parts.join("\n\n") }] };
    });
    logger.debug("Registered dynamic meta-tool", { name: "describe_tool_input" });
    // 3. execute_tool
    server.registerTool("execute_tool", {
        description: "Execute a tool by name with its arguments. If executing a given tool for the first time, it is recommended to call describe_tool_input first to understand the expected `arguments` shape.",
        inputSchema: {
            name: z.string().describe("The name of the tool to execute"),
            arguments: z.looseObject({}).optional().describe("Arguments for the target tool as a JSON object, matching the schema returned by describe_tool_input."),
        },
        annotations: {
            title: "Execute Tool",
            readOnlyHint: false,
            destructiveHint: true,
            idempotentHint: false,
            openWorldHint: true,
        },
    }, async (args, ctx) => {
        const def = toolMap.get(args.name);
        if (!def) {
            return {
                content: [{ type: "text", text: `Unknown tool: ${args.name}` }],
                isError: true,
            };
        }
        let validatedInput = {};
        if (def.args) {
            const vres = z.object(def.args).safeParse(args.arguments ?? {});
            if (vres.success) {
                validatedInput = vres.data;
            }
            else {
                const issues = z.prettifyError(vres.error);
                return {
                    content: [{
                            type: "text",
                            text: `Invalid input for tool ${args.name}:\n<issues>\n${issues}\n</issues>`,
                        }],
                    isError: true,
                };
            }
        }
        try {
            if (def.args) {
                return await def.tool(getSDK(), validatedInput, ctx);
            }
            else {
                return await def.tool(getSDK(), ctx);
            }
        }
        catch (error) {
            const message = error instanceof Error ? error.message : String(error);
            return {
                content: [{
                        type: "text",
                        text: `Error executing tool ${args.name}: ${message}`,
                    }],
                isError: true,
            };
        }
    });
    logger.debug("Registered dynamic meta-tool", { name: "execute_tool" });
    // 4. list_scopes (only when the server has scopes defined)
    if (mcpScopes.length > 0) {
        const scopes = allowedScopes.size > 0
            ? [...allowedScopes].sort()
            : [...mcpScopes];
        server.registerTool("list_scopes", {
            description: [
                "List the scopes available on this server.",
                "Scopes are categories that group related tools together.",
                "They can be used as search terms when filtering the list of tools.",
            ].join("\n"),
            annotations: {
                title: "List Scopes",
                readOnlyHint: true,
                destructiveHint: false,
                idempotentHint: true,
                openWorldHint: false,
            },
        }, async () => {
            const lines = scopes.map((s) => `- ${s}`);
            return { content: [{ type: "text", text: lines.join("\n") }] };
        });
        logger.debug("Registered dynamic meta-tool", { name: "list_scopes" });
    }
}
function resolveHeader(headers, headerName, schema, cliFlagValue, disableStaticAuth) {
    const val = headers.get(headerName);
    if (val != null) {
        return schema.parse(val);
    }
    return disableStaticAuth ? undefined : schema.parse(cliFlagValue);
}
export function buildSDK(headers, cliFlags, disableStaticAuth, logger) {
    const flags = {
        ...cliFlags,
        "api-key": resolveHeader(headers, "api-key", z.string(), cliFlags["api-key"], disableStaticAuth),
        "api-secret": resolveHeader(headers, "api-secret", z.string(), cliFlags["api-secret"], disableStaticAuth),
        "oauth2": resolveHeader(headers, "oauth2", z.string(), cliFlags["oauth2"], disableStaticAuth),
    };
    return new CloudinarySMDCore({
        security: {
            cloudinaryAuth: flags["api-key"] != null && flags["api-secret"] != null
                ? {
                    api_key: flags["api-key"] ?? "",
                    api_secret: flags["api-secret"] ?? "",
                }
                : void 0,
            oauth2: flags.oauth2 ?? "",
        },
        serverURL: cliFlags["server-url"],
        cloud_name: resolveHeader(headers, "cloud-name", z.string(), cliFlags["cloud-name"], disableStaticAuth),
        serverIdx: cliFlags["server-index"],
        region: resolveHeader(headers, "region", ServerRegion$zodSchema, cliFlags.region, disableStaticAuth),
        host: resolveHeader(headers, "api-host", z.string(), cliFlags["api-host"], disableStaticAuth),
        debugLogger: logger.level === "debug"
            ? {
                log: (...args) => console.log(...args),
                group: (...args) => console.group(...args),
                groupEnd: (...args) => console.groupEnd(...args),
            }
            : undefined,
    });
}
//# sourceMappingURL=tools.js.map