"use strict";
const errors = require("./errors-CHx_k7HS.cjs");
const paths = require("./paths-C6z4_Obm.cjs");
const vscode = require("vscode");
require("node-machine-id");
const fs = require("fs");
const path = require("path");
const zod = require("zod");
const resolveRegistryEntries = require("./resolve-registry-entries-C7jM70XK.cjs");
const JSONC = require("comment-json");
function _interopNamespaceDefault(e) {
  const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
  if (e) {
    for (const k in e) {
      if (k !== "default") {
        const d = Object.getOwnPropertyDescriptor(e, k);
        Object.defineProperty(n, k, d.get ? d : {
          enumerable: true,
          get: () => e[k]
        });
      }
    }
  }
  n.default = e;
  return Object.freeze(n);
}
const vscode__namespace = /* @__PURE__ */ _interopNamespaceDefault(vscode);
const fs__namespace = /* @__PURE__ */ _interopNamespaceDefault(fs);
const path__namespace = /* @__PURE__ */ _interopNamespaceDefault(path);
const JSONC__namespace = /* @__PURE__ */ _interopNamespaceDefault(JSONC);
const OAuthConfigSchema = zod.z.object({
  /** Pre-registered OAuth client ID. When provided, skips Dynamic Client Registration (DCR). */
  clientId: zod.z.string().optional(),
  /** Custom redirect URI for OAuth callback (e.g., "127.0.0.1:8080"). If not specified, a random port is used. */
  redirectUri: zod.z.string().optional()
});
const MCPOptionsSchema = zod.z.object({
  // Local (STDIO) options
  command: zod.z.string().optional(),
  args: zod.z.array(zod.z.string()).optional(),
  env: zod.z.record(zod.z.string()).optional(),
  cwd: zod.z.string().optional(),
  // Remote (StreamableHTTP / SSE) options
  url: zod.z.string().optional(),
  headers: zod.z.record(zod.z.string()).optional(),
  // Common options
  type: zod.z.string().optional(),
  timeout: zod.z.number().positive().optional(),
  disabled: zod.z.boolean().default(false),
  autoApprove: zod.z.array(zod.z.string()).optional(),
  disabledTools: zod.z.array(zod.z.string()).optional(),
  /** OAuth configuration for servers requiring pre-registered clients or custom redirect URIs. */
  oauth: OAuthConfigSchema.optional(),
  /** OAuth scopes to request during authorization (e.g., ["search:read", "channels:read"]). */
  oauthScopes: zod.z.array(zod.z.string()).optional()
});
const MCPJsonConfigSchema = zod.z.object({
  mcpServers: zod.z.record(MCPOptionsSchema),
  powers: zod.z.object({
    mcpServers: zod.z.record(MCPOptionsSchema)
  }).optional()
});
function isHttpsOrLocalhost(urlString) {
  try {
    const url = new URL(urlString);
    if (url.protocol === "https:") {
      return true;
    }
    const hostname = url.hostname;
    return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1" || hostname === "[::1]";
  } catch {
    return false;
  }
}
const APPROVED_ENV_VARS_KEY = "mcpApprovedEnvVars";
let hasShownWarningThisSession = false;
const globalUnapprovedVarsFound = /* @__PURE__ */ new Set();
async function showUnapprovedVarsWarningIfNeeded() {
  if (globalUnapprovedVarsFound.size > 0 && !hasShownWarningThisSession) {
    hasShownWarningThisSession = true;
    const unapprovedVars = Array.from(globalUnapprovedVarsFound);
    errors.mcpLogger.warn(`Found unapproved environment variables in MCP config: ${unapprovedVars.join(", ")}`);
    const message = `🔒 Security Warning: Your MCP configuration contains environment variables that have not been approved: ${unapprovedVars.join(", ")}. These variables will not be expanded unless you approve them. Expanding untrusted environment variables could pose security risks.`;
    const selection = await vscode__namespace.window.showErrorMessage(message, "Approve & Allow");
    if (selection === "Approve & Allow") {
      const currentApproved = vscode__namespace.workspace.getConfiguration("kiroAgent").get(APPROVED_ENV_VARS_KEY, []);
      const updatedApproved = [.../* @__PURE__ */ new Set([...currentApproved, ...unapprovedVars])];
      await vscode__namespace.workspace.getConfiguration("kiroAgent").update(APPROVED_ENV_VARS_KEY, updatedApproved, vscode__namespace.ConfigurationTarget.Global);
      errors.mcpLogger.info(`User approved environment variables: ${unapprovedVars.join(", ")}`);
      hasShownWarningThisSession = false;
      const configLocation = paths.getActiveMcpConfigLocation(getWorkspaceDirs());
      const allConfigPaths = [
        ...configLocation.workspaceConfigPaths,
        ...configLocation.userConfigPath ? [configLocation.userConfigPath] : []
      ];
      for (const configPath of allConfigPaths) {
        try {
          const now = /* @__PURE__ */ new Date();
          fs__namespace.utimesSync(configPath, now, now);
        } catch (e) {
          errors.mcpLogger.error(
            `Failed to trigger config reload for ${configPath}: ${e instanceof Error ? e.message : String(e)}`
          );
        }
      }
      await vscode__namespace.window.showInformationMessage(
        "✅ Variables approved. Environment variables are now being expanded and MCP servers are reconnecting."
      );
    }
  }
}
function loadPowersMcpConfig() {
  const userConfigPath = path__namespace.join(paths.getHomeKiroPath(), "settings", "mcp.json");
  if (!fs__namespace.existsSync(userConfigPath)) {
    return null;
  }
  try {
    const rawContent = fs__namespace.readFileSync(userConfigPath, "utf-8");
    const parsed = JSONC__namespace.parse(rawContent);
    if (parsed && typeof parsed === "object" && "powers" in parsed && parsed.powers && typeof parsed.powers === "object" && "mcpServers" in parsed.powers && typeof parsed.powers.mcpServers === "object") {
      const expandedPowers = expandEnvironmentVariables(parsed.powers);
      const expandedPowersTyped = expandedPowers;
      const powersConfigToValidate = {
        mcpServers: expandedPowersTyped.mcpServers
      };
      const result = MCPJsonConfigSchema.safeParse(powersConfigToValidate);
      if (result.success) {
        const validServers = {};
        Object.entries(result.data.mcpServers).forEach((entry) => {
          const validationResult = deepValidateMCPServerOptions(entry[0], entry[1]);
          if (validationResult.isValid) {
            validServers[entry[0]] = entry[1];
          } else {
            errors.mcpLogger.warn(validationResult.invalidMessage || "", entry[0]);
            void surfaceConfigError(validationResult.invalidMessage || "", "powers", userConfigPath);
          }
        });
        const serverNames = Object.keys(validServers);
        errors.mcpLogger.debug(
          `[Powers Debug] loadPowersMcpConfig found ${serverNames.length} valid power servers: ${serverNames.join(", ")}`
        );
        return { mcpServers: validServers };
      } else {
        void surfaceConfigError(`Invalid powers config format: ${result.error.message}`, "powers", userConfigPath);
        return null;
      }
    }
    errors.mcpLogger.warn("[Powers Debug] No powers.mcpServers section found in user mcp.json");
    return null;
  } catch (error) {
    const errorMsg = `Error loading powers config: ${error instanceof Error ? error.message : String(error)}`;
    errors.mcpLogger.error("[Powers Debug] " + errorMsg);
    void surfaceConfigError(errorMsg, "powers", userConfigPath);
    return null;
  }
}
const mcpServerSources = /* @__PURE__ */ new Map();
function loadMcpConfig() {
  globalUnapprovedVarsFound.clear();
  hasShownWarningThisSession = false;
  mcpServerSources.clear();
  const configLocation = paths.getActiveMcpConfigLocation(getWorkspaceDirs());
  const userConfig = loadIndividualMcpConfig("user", configLocation.userConfigPath);
  const workspaceConfigs = configLocation.workspaceConfigPaths.map(
    (path2) => loadIndividualMcpConfig("workspace", path2)
  );
  const powersConfig = loadPowersMcpConfig();
  const finalConfig = {
    mcpServers: {}
  };
  if (userConfig) {
    for (const serverName of Object.keys(userConfig.mcpServers)) {
      finalConfig.mcpServers[serverName] = userConfig.mcpServers[serverName];
      mcpServerSources.set(serverName, "user");
    }
  }
  for (const workspaceConfig of workspaceConfigs) {
    if (workspaceConfig) {
      for (const serverName of Object.keys(workspaceConfig.mcpServers)) {
        finalConfig.mcpServers[serverName] = workspaceConfig.mcpServers[serverName];
        mcpServerSources.set(serverName, "workspace");
      }
    }
  }
  if (powersConfig) {
    for (const serverName of Object.keys(powersConfig.mcpServers)) {
      finalConfig.mcpServers[serverName] = powersConfig.mcpServers[serverName];
      mcpServerSources.set(serverName, "power");
    }
  }
  if (Object.keys(finalConfig.mcpServers).length === 0) {
    return null;
  }
  const powerServers = Array.from(mcpServerSources.entries()).filter(([_, source]) => source === "power").map(([name, _]) => name);
  if (powerServers.length > 0) {
    errors.mcpLogger.debug(`[Powers Debug] Loaded ${powerServers.length} power MCP servers: ${powerServers.join(", ")}`);
  }
  void showUnapprovedVarsWarningIfNeeded();
  return finalConfig;
}
function expandEnvironmentVariables(value, options) {
  if (typeof value === "string") {
    const expandAll = options?.expandAll === true;
    const fallbackToEmpty = options?.fallbackToEmpty === true;
    const envOverride = options?.env;
    const approvedVars = expandAll ? void 0 : vscode__namespace.workspace.getConfiguration("kiroAgent").get(APPROVED_ENV_VARS_KEY, []);
    return value.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g, (match, varName) => {
      if (approvedVars && !approvedVars.includes(varName)) {
        globalUnapprovedVarsFound.add(varName);
        return match;
      }
      const envValue = envOverride?.[varName] ?? process.env[varName];
      if (envValue !== void 0) {
        if (envValue.trim().startsWith("()")) {
          return fallbackToEmpty ? "" : match;
        }
        errors.mcpLogger.debug(`Expanded environment variable: ${varName}`);
        return envValue;
      }
      return fallbackToEmpty ? "" : match;
    });
  }
  if (Array.isArray(value)) {
    return value.map((item) => expandEnvironmentVariables(item, options));
  }
  if (value && typeof value === "object") {
    const expanded = {};
    for (const [key, val] of Object.entries(value)) {
      expanded[key] = expandEnvironmentVariables(val, options);
    }
    return expanded;
  }
  return value;
}
function loadIndividualMcpConfig(sourceName, path2) {
  if (!path2) return null;
  try {
    const configContent = fs__namespace.readFileSync(path2, "utf8");
    const parsedJson = JSONC__namespace.parse(configContent);
    const expandedJson = expandEnvironmentVariables(parsedJson);
    const result = MCPJsonConfigSchema.safeParse(expandedJson);
    if (result.success) {
      const validServers = {};
      Object.entries(result.data.mcpServers).forEach((entry) => {
        const validationResult = deepValidateMCPServerOptions(entry[0], entry[1]);
        if (validationResult.isValid) {
          validServers[entry[0]] = entry[1];
        } else {
          errors.mcpLogger.warn(validationResult.invalidMessage || "", entry[0]);
          void surfaceConfigError(validationResult.invalidMessage || "", sourceName, path2);
        }
      });
      return {
        mcpServers: validServers,
        powers: result.data.powers
      };
    } else {
      void surfaceConfigError(
        `Invalid mcp.json format in ${sourceName} directory: ${result.error.message}`,
        sourceName,
        path2
      );
      return null;
    }
  } catch (e) {
    void surfaceConfigError(
      `Error loading mcp.json from ${sourceName} directory: ${e instanceof Error ? e.message : String(e)}`,
      sourceName,
      path2
    );
    return null;
  }
}
async function surfaceConfigError(errorMsg, sourceName, configPath) {
  errors.mcpLogger.error(errorMsg);
  const selection = await vscode__namespace.window.showErrorMessage(errorMsg, "Ask Kiro", "Open Settings");
  if (selection === "Ask Kiro") {
    const message = `I'm getting this MCP configuration error: "${errorMsg}". Can you help me fix it?`;
    void vscode__namespace.commands.executeCommand("kiroAgent.focusChatInput", { prompt: message, clear: true });
    void vscode__namespace.commands.executeCommand("kiroAgent.userInputFocusNoSubmit", message);
  } else if (selection === "Open Settings") {
    if (sourceName === "workspace") {
      await vscode__namespace.commands.executeCommand("kiroAgent.openWorkspaceMcpConfig", false, configPath);
    } else {
      await vscode__namespace.commands.executeCommand("kiroAgent.openUserMcpConfig", false);
    }
  }
}
function deepValidateMCPServerOptions(serverName, options) {
  if (options.type === "registry") {
    const result = resolveRegistryEntries.RegistryServerConfigEntrySchema.safeParse(options);
    if (!result.success) {
      return {
        isValid: false,
        invalidMessage: `Invalid registry config for MCP Server ${serverName}: ${result.error.message}`
      };
    }
    return { isValid: true };
  }
  if (!options.disabled && !(options.command || options.url)) {
    return {
      isValid: false,
      invalidMessage: `Enabled MCP Server ${serverName} must specify a command or URL, ignoring.`
    };
  }
  if (options.url) {
    try {
      new URL(options.url);
    } catch {
      return {
        isValid: false,
        invalidMessage: `Invalid MCP Server ${serverName} URL: ${options.url}, ignoring.`
      };
    }
    if (!isHttpsOrLocalhost(options.url)) {
      return {
        isValid: false,
        invalidMessage: `Remote MCP Servers must use https or localhost, ignoring.`
      };
    }
  }
  return {
    isValid: true
  };
}
async function addMCPServerConfig(serverName, config) {
  await vscode__namespace.commands.executeCommand("kiroAgent.openUserMcpConfig");
  const userConfigLocation = paths.getActiveMcpConfigLocation(getWorkspaceDirs());
  if (!userConfigLocation.userConfigPath) {
    void vscode__namespace.window.showErrorMessage("Failed to create User MCP server config");
    return;
  }
  const currentConfig = loadIndividualMcpConfig("user", userConfigLocation.userConfigPath);
  if (!currentConfig) {
    return;
  }
  if (serverName in currentConfig.mcpServers) {
    void vscode__namespace.window.showErrorMessage(`MCP Server ${serverName} already exists in user config`);
    return;
  }
  let newServerConfig;
  try {
    const parsed = JSONC__namespace.parse(config);
    if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
      throw new Error(`Invalid JSON object: ${config}`);
    }
    newServerConfig = {
      ...parsed,
      disabled: true
    };
  } catch (e) {
    void vscode__namespace.window.showErrorMessage(`Invalid MCP server config: ${e instanceof Error ? e.message : String(e)}`);
    return;
  }
  const newConfig = {
    ...currentConfig,
    mcpServers: {
      ...currentConfig.mcpServers,
      [serverName]: newServerConfig
    }
  };
  fs__namespace.writeFileSync(userConfigLocation.userConfigPath, JSONC__namespace.stringify(newConfig, null, 2));
  const selection = await vscode__namespace.window.showInformationMessage(
    `MCP Server "${serverName}" added to user config, would you like to enable it?`,
    "Enable"
  );
  if (selection === "Enable") {
    setMCPServerDisabled(serverName, false);
  }
}
function setMCPServerDisabled(serverName, disabled) {
  const disableServerTransform = (options) => {
    return { ...options, disabled };
  };
  applyServerConfigTransform(serverName, disableServerTransform);
}
function enableMCPTools(serverName, toolNames) {
  const enableToolsTransform = (options) => {
    const currentDisabledTools = options.disabledTools || [];
    const updatedDisabledTools = currentDisabledTools.filter((val) => !toolNames.includes(val));
    return {
      ...options,
      disabledTools: updatedDisabledTools
    };
  };
  applyServerConfigTransform(serverName, enableToolsTransform);
}
function disableMCPTools(serverName, toolNames) {
  const disableToolsTransform = (options) => {
    const currentDisabledTools = options.disabledTools || [];
    const toolsToDisable = toolNames.filter((it) => !currentDisabledTools.includes(it));
    const updatedDisabledTools = currentDisabledTools.concat(toolsToDisable);
    return {
      ...options,
      disabledTools: updatedDisabledTools
    };
  };
  applyServerConfigTransform(serverName, disableToolsTransform);
}
async function addMCPToolToAutoApproveConfig(serverName, toolName) {
  const autoApproveToolsTransform = (options) => {
    return {
      ...options,
      autoApprove: (options.autoApprove || []).concat(toolName)
    };
  };
  applyServerConfigTransform(serverName, autoApproveToolsTransform);
  const addedMessage = `Tool ${toolName} added to auto-approve list`;
  errors.mcpLogger.info(addedMessage, serverName);
  const selection = await vscode__namespace.window.showInformationMessage(addedMessage, "Open Settings");
  if (selection === "Open Settings") {
    const matchingConfig = findConfigFileForServer(serverName);
    if (matchingConfig.sourceName === "workspace") {
      await vscode__namespace.commands.executeCommand("kiroAgent.openWorkspaceMcpConfig");
    } else {
      await vscode__namespace.commands.executeCommand("kiroAgent.openUserMcpConfig");
    }
  }
}
function applyServerConfigTransform(serverName, transform) {
  const matchingConfig = findConfigFileForServer(serverName);
  const rawContent = fs__namespace.readFileSync(matchingConfig.path, "utf-8");
  const parsed = JSONC__namespace.parse(rawContent);
  const fullConfig = parsed && typeof parsed === "object" ? parsed : {};
  if (matchingConfig.sourceName === "powers") {
    if (!fullConfig.powers) {
      fullConfig.powers = { mcpServers: {} };
    }
    if (!fullConfig.powers.mcpServers) {
      fullConfig.powers.mcpServers = {};
    }
    const existingConfig = fullConfig.powers.mcpServers[serverName] ?? {};
    fullConfig.powers.mcpServers[serverName] = transform(existingConfig);
  } else {
    if (!fullConfig.mcpServers) {
      fullConfig.mcpServers = {};
    }
    const existingConfig = fullConfig.mcpServers[serverName] ?? {};
    fullConfig.mcpServers[serverName] = transform(existingConfig);
  }
  fs__namespace.writeFileSync(matchingConfig.path, JSONC__namespace.stringify(fullConfig, null, 2));
}
function findConfigFileForServer(serverName) {
  const configLocation = paths.getActiveMcpConfigLocation(getWorkspaceDirs());
  if (!configLocation.userConfigPath && configLocation.workspaceConfigPaths.length === 0) {
    throw new Error("No MCP config file found");
  }
  for (let i = configLocation.workspaceConfigPaths.length - 1; i >= 0; i--) {
    const workspacePath = configLocation.workspaceConfigPaths[i];
    const config = loadIndividualMcpConfig("workspace", workspacePath);
    if (config && serverName in config.mcpServers) {
      return { path: workspacePath, config, sourceName: "workspace" };
    }
  }
  if (configLocation.userConfigPath) {
    const config = loadIndividualMcpConfig("user", configLocation.userConfigPath);
    if (config && serverName in config.mcpServers) {
      return { path: configLocation.userConfigPath, config, sourceName: "user" };
    }
    const rawContent = fs__namespace.readFileSync(configLocation.userConfigPath, "utf-8");
    const parsed = JSONC__namespace.parse(rawContent);
    const fullConfig = parsed && typeof parsed === "object" ? parsed : {};
    if (fullConfig.powers?.mcpServers?.[serverName]) {
      const powersConfig = { mcpServers: fullConfig.powers.mcpServers };
      return { path: configLocation.userConfigPath, config: powersConfig, sourceName: "powers" };
    }
  }
  throw new Error(`Server ${serverName} not found in any MCP config file`);
}
function getWorkspaceDirs() {
  const workspaceFolders = vscode__namespace.workspace.workspaceFolders;
  return workspaceFolders?.map((folder) => folder.uri.fsPath);
}
function resetApprovedEnvVars() {
  void vscode__namespace.workspace.getConfiguration("kiroAgent").update(APPROVED_ENV_VARS_KEY, [], vscode__namespace.ConfigurationTarget.Global);
  hasShownWarningThisSession = false;
  errors.mcpLogger.info("Reset approved environment variables list");
}
exports.MCPJsonConfigSchema = MCPJsonConfigSchema;
exports.MCPOptionsSchema = MCPOptionsSchema;
exports.OAuthConfigSchema = OAuthConfigSchema;
exports.addMCPServerConfig = addMCPServerConfig;
exports.addMCPToolToAutoApproveConfig = addMCPToolToAutoApproveConfig;
exports.deepValidateMCPServerOptions = deepValidateMCPServerOptions;
exports.disableMCPTools = disableMCPTools;
exports.enableMCPTools = enableMCPTools;
exports.expandEnvironmentVariables = expandEnvironmentVariables;
exports.findConfigFileForServer = findConfigFileForServer;
exports.isHttpsOrLocalhost = isHttpsOrLocalhost;
exports.loadMcpConfig = loadMcpConfig;
exports.mcpServerSources = mcpServerSources;
exports.resetApprovedEnvVars = resetApprovedEnvVars;
exports.setMCPServerDisabled = setMCPServerDisabled;
