import { accessSync, constants, existsSync } from "node:fs";
import { dirname, resolve } from "node:path";
import { delimiter } from "node:path";
import { fileURLToPath } from "node:url";
const AST_GREP_PACKAGE_REL = "packages/ast-grep-mcp";
const LSP_PACKAGE_REL = "packages/lsp-tools-mcp";
const DIST_CLI_REL = "dist/cli.js";
const SOURCE_CLI_REL = "src/cli.ts";
export function createSeedMcpDefaults(config, cwd) {
    const disabled = new Set(config.disabled_mcps);
    const builtin = config.mcp.builtin;
    const mcps = {};
    if (!disabled.has("context7") && builtin.context7 === true) {
        mcps.context7 = {
            type: "remote",
            url: "https://mcp.context7.com/mcp",
            enabled: true,
            ...(process.env.CONTEXT7_API_KEY ? { headers: { Authorization: `Bearer ${process.env.CONTEXT7_API_KEY}` } } : {}),
            oauth: false,
        };
    }
    if (!disabled.has("grep_app") && builtin.grep_app !== false) {
        mcps.grep_app = {
            type: "remote",
            url: "https://mcp.grep.app",
            enabled: builtin.grep_app === true || process.env.SEED_ENABLE_GREP_APP === "1",
            oauth: false,
        };
    }
    if (!disabled.has("websearch") && builtin.websearch !== false) {
        const websearch = createWebsearchMcp(builtin.websearch);
        if (websearch)
            mcps.websearch = websearch;
    }
    if (!disabled.has("lsp") && builtin.lsp !== false) {
        const lsp = resolveLocalMcpCli(cwd, LSP_PACKAGE_REL);
        mcps.lsp = {
            type: "local",
            command: lsp.command,
            enabled: builtin.lsp === true && lsp.exists,
            environment: {
                LSP_TOOLS_MCP_PROJECT_CONFIG: ".opencode/lsp.json",
                SEED_MCP_DIAGNOSTIC: lsp.diagnostic,
            },
        };
    }
    if (!disabled.has("ast_grep") && builtin.ast_grep !== false) {
        const astGrep = resolveLocalMcpCli(cwd, AST_GREP_PACKAGE_REL);
        mcps.ast_grep = {
            type: "local",
            command: astGrep.command,
            enabled: builtin.ast_grep === true && astGrep.exists,
            environment: {
                OMO_AST_GREP_WORKSPACE: cwd,
                OMO_AST_GREP_DISABLED_TOOLS: "",
                SEED_MCP_DIAGNOSTIC: astGrep.diagnostic,
            },
        };
    }
    return mcps;
}
export function mergeMcpConfig(userMcp, seedMcp) {
    const merged = { ...seedMcp, ...(userMcp ?? {}) };
    for (const [name, entry] of Object.entries(userMcp ?? {})) {
        if (isDisabledMcp(entry))
            merged[name] = { enabled: false };
    }
    return merged;
}
function createWebsearchMcp(mode) {
    if (process.env.TAVILY_API_KEY) {
        return {
            type: "remote",
            url: "https://mcp.tavily.com/mcp/",
            enabled: true,
            headers: { Authorization: `Bearer ${process.env.TAVILY_API_KEY}` },
            oauth: false,
        };
    }
    if (process.env.EXA_API_KEY) {
        return {
            type: "remote",
            url: "https://mcp.exa.ai/mcp?tools=web_search_exa",
            enabled: true,
            headers: { Authorization: `Bearer ${process.env.EXA_API_KEY}` },
            oauth: false,
        };
    }
    if (mode === true) {
        return {
            type: "remote",
            url: "https://mcp.exa.ai/mcp?tools=web_search_exa",
            enabled: false,
            oauth: false,
        };
    }
    return undefined;
}
function isDisabledMcp(value) {
    return typeof value === "object" && value !== null && value.enabled === false;
}
function resolveLocalMcpCli(cwd, packageRel) {
    const node = resolveExecutable("node");
    const bun = resolveExecutable("bun");
    const roots = candidateRoots(cwd);
    for (const root of roots) {
        const dist = resolve(root, packageRel, DIST_CLI_REL);
        if (node.available && existsSync(dist)) {
            return {
                command: [node.command, dist, "mcp"],
                path: dist,
                exists: true,
                diagnostic: `resolved ${packageRel}/${DIST_CLI_REL}`,
            };
        }
    }
    for (const root of roots) {
        const source = resolve(root, packageRel, SOURCE_CLI_REL);
        if (bun.available && existsSync(source)) {
            return {
                command: [bun.command, source, "mcp"],
                path: source,
                exists: true,
                diagnostic: `resolved ${packageRel}/${SOURCE_CLI_REL}`,
            };
        }
    }
    const diagnosticRoot = roots[0] ?? cwd;
    const expectedPath = resolve(diagnosticRoot, packageRel, DIST_CLI_REL);
    const runtime = node.available ? node : bun;
    return {
        command: [runtime.command, expectedPath, "mcp"],
        path: expectedPath,
        exists: false,
        diagnostic: runtime.available
            ? `disabled: ${packageRel}/${DIST_CLI_REL} was not found`
            : `disabled: neither node nor bun was found on PATH`,
    };
}
function candidateRoots(cwd) {
    const roots = new Set();
    addAncestors(resolve(cwd), roots);
    const moduleDirectory = moduleDir();
    if (moduleDirectory)
        addAncestors(moduleDirectory, roots);
    return [...roots];
}
function addAncestors(start, roots) {
    let current = start;
    while (true) {
        roots.add(current);
        const parent = resolve(current, "..");
        if (parent === current)
            return;
        current = parent;
    }
}
function moduleDir() {
    try {
        return dirname(fileURLToPath(import.meta.url));
    }
    catch {
        return undefined;
    }
}
function resolveExecutable(command) {
    if (command.includes("/"))
        return { command, available: executableExists(command) };
    for (const directory of (process.env.PATH ?? "").split(delimiter)) {
        if (!directory)
            continue;
        const candidate = resolve(directory, command);
        if (executableExists(candidate))
            return { command: candidate, available: true };
    }
    return { command, available: false };
}
function executableExists(file) {
    try {
        accessSync(file, constants.X_OK);
        return true;
    }
    catch {
        return false;
    }
}
//# sourceMappingURL=index.js.map