const require = (await import('node:module')).createRequire(import.meta.url); const __chunk_filename = (await import('node:url')).fileURLToPath(import.meta.url); const __chunk_dirname = (await import('node:path')).dirname(__chunk_filename);
import {
  runExitCleanup
} from "./chunk-WFJ6GMMM.js";
import {
  RELEASE_CHANNEL_STABILITY,
  getChannelFromVersion,
  isGitRepository
} from "./chunk-DQ7NBN5H.js";
import {
  debugLogger
} from "./chunk-N6QYTC2T.js";

// packages/cli/src/utils/installationInfo.ts
import * as fs from "node:fs";
import * as path from "node:path";
import * as childProcess from "node:child_process";
import process2 from "node:process";
var isDevelopment = process2.env["NODE_ENV"] === "development";
function getInstallationInfo(projectRoot, isAutoUpdateEnabled) {
  const cliPath = process2.argv[1];
  if (!cliPath) {
    return { packageManager: "unknown" /* UNKNOWN */, isGlobal: false };
  }
  try {
    if (process2.env["IS_BINARY"] === "true") {
      return {
        packageManager: "binary" /* BINARY */,
        isGlobal: true,
        updateMessage: "Running as a standalone binary. Please update by downloading the latest version from GitHub."
      };
    }
    const realPath = fs.realpathSync(cliPath).replace(/\\/g, "/");
    const normalizedProjectRoot = projectRoot?.replace(/\\/g, "/");
    const isGit = isGitRepository(process2.cwd());
    if (isGit && normalizedProjectRoot && realPath.startsWith(normalizedProjectRoot) && !realPath.includes("/node_modules/")) {
      return {
        packageManager: "unknown" /* UNKNOWN */,
        // Not managed by a package manager in this sense
        isGlobal: false,
        updateMessage: 'Running from a local git clone. Please update with "git pull".'
      };
    }
    if (realPath.includes("/.npm/_npx") || realPath.includes("/npm/_npx")) {
      return {
        packageManager: "npx" /* NPX */,
        isGlobal: false,
        updateMessage: "Running via npx, update not applicable."
      };
    }
    if (realPath.includes("/.pnpm/_pnpx") || realPath.includes("/.cache/pnpm/dlx")) {
      return {
        packageManager: "pnpx" /* PNPX */,
        isGlobal: false,
        updateMessage: "Running via pnpx, update not applicable."
      };
    }
    if (process2.platform === "darwin") {
      try {
        const brewPrefix = childProcess.execSync("brew --prefix gemini-cli", {
          encoding: "utf8",
          stdio: ["ignore", "pipe", "ignore"]
        }).trim();
        const brewRealPath = fs.realpathSync(brewPrefix);
        if (realPath.startsWith(brewRealPath)) {
          return {
            packageManager: "homebrew" /* HOMEBREW */,
            isGlobal: true,
            updateMessage: 'Installed via Homebrew. Please update with "brew upgrade gemini-cli".'
          };
        }
      } catch {
      }
    }
    if (realPath.includes("/.pnpm/global") || realPath.includes("/.local/share/pnpm")) {
      const updateCommand2 = "pnpm add -g @google/gemini-cli@latest";
      return {
        packageManager: "pnpm" /* PNPM */,
        isGlobal: true,
        updateCommand: updateCommand2,
        updateMessage: isAutoUpdateEnabled ? "Installed with pnpm. Attempting to automatically update now..." : `Please run ${updateCommand2} to update`
      };
    }
    if (realPath.includes("/.yarn/global")) {
      const updateCommand2 = "yarn global add @google/gemini-cli@latest";
      return {
        packageManager: "yarn" /* YARN */,
        isGlobal: true,
        updateCommand: updateCommand2,
        updateMessage: isAutoUpdateEnabled ? "Installed with yarn. Attempting to automatically update now..." : `Please run ${updateCommand2} to update`
      };
    }
    if (realPath.includes("/.bun/install/cache")) {
      return {
        packageManager: "bunx" /* BUNX */,
        isGlobal: false,
        updateMessage: "Running via bunx, update not applicable."
      };
    }
    if (realPath.includes("/.bun/install/global")) {
      const updateCommand2 = "bun add -g @google/gemini-cli@latest";
      return {
        packageManager: "bun" /* BUN */,
        isGlobal: true,
        updateCommand: updateCommand2,
        updateMessage: isAutoUpdateEnabled ? "Installed with bun. Attempting to automatically update now..." : `Please run ${updateCommand2} to update`
      };
    }
    if (normalizedProjectRoot && realPath.startsWith(`${normalizedProjectRoot}/node_modules`)) {
      let pm = "npm" /* NPM */;
      if (fs.existsSync(path.join(projectRoot, "yarn.lock"))) {
        pm = "yarn" /* YARN */;
      } else if (fs.existsSync(path.join(projectRoot, "pnpm-lock.yaml"))) {
        pm = "pnpm" /* PNPM */;
      } else if (fs.existsSync(path.join(projectRoot, "bun.lockb"))) {
        pm = "bun" /* BUN */;
      }
      return {
        packageManager: pm,
        isGlobal: false,
        updateMessage: "Locally installed. Please update via your project's package.json."
      };
    }
    const updateCommand = "npm install -g @google/gemini-cli@latest";
    return {
      packageManager: "npm" /* NPM */,
      isGlobal: true,
      updateCommand,
      updateMessage: isAutoUpdateEnabled ? "Installed with npm. Attempting to automatically update now..." : `Please run ${updateCommand} to update`
    };
  } catch (error) {
    debugLogger.log(error);
    return { packageManager: "unknown" /* UNKNOWN */, isGlobal: false };
  }
}

// packages/cli/src/utils/updateEventEmitter.ts
import { EventEmitter } from "node:events";
var updateEventEmitter = new EventEmitter();

// packages/cli/src/utils/spawnWrapper.ts
import { spawn } from "node:child_process";
var spawnWrapper = spawn;

// packages/cli/src/utils/handleAutoUpdate.ts
var _updateInProgress = false;
async function waitForUpdateCompletion(timeoutMs = 3e4) {
  if (!_updateInProgress) {
    return;
  }
  debugLogger.log(
    "\nGemini CLI is waiting for a background update to complete before restarting..."
  );
  return new Promise((resolve) => {
    if (!_updateInProgress) {
      resolve();
      return;
    }
    const timer = setTimeout(cleanup, timeoutMs);
    function cleanup() {
      clearTimeout(timer);
      updateEventEmitter.off("update-success", cleanup);
      updateEventEmitter.off("update-failed", cleanup);
      resolve();
    }
    updateEventEmitter.once("update-success", cleanup);
    updateEventEmitter.once("update-failed", cleanup);
  });
}
function handleAutoUpdate(info, settings, projectRoot, isSandboxEnabled, spawnFn = spawnWrapper) {
  if (!info) {
    return;
  }
  if (isSandboxEnabled) {
    updateEventEmitter.emit("update-info", {
      message: `${info.message}
Automatic update is not available in sandbox mode.`
    });
    return;
  }
  if (!settings.merged.general.enableAutoUpdateNotification) {
    return;
  }
  const installationInfo = getInstallationInfo(
    projectRoot,
    settings.merged.general.enableAutoUpdate
  );
  if ([
    "npx" /* NPX */,
    "pnpx" /* PNPX */,
    "bunx" /* BUNX */,
    "binary" /* BINARY */
  ].includes(installationInfo.packageManager)) {
    return;
  }
  let combinedMessage = info.message;
  if (installationInfo.updateMessage) {
    combinedMessage += `
${installationInfo.updateMessage}`;
  }
  if (!installationInfo.updateCommand || !settings.merged.general.enableAutoUpdate) {
    updateEventEmitter.emit("update-received", {
      ...info,
      message: combinedMessage,
      isUpdating: false
    });
    return;
  }
  updateEventEmitter.emit("update-received", {
    ...info,
    message: combinedMessage,
    isUpdating: true
  });
  if (_updateInProgress) {
    return;
  }
  const currentVersion = info.update.current;
  if (!currentVersion) {
    debugLogger.warn(
      "Update check: current version is missing. Skipping automatic update for safety."
    );
    return;
  }
  const currentChannel = getChannelFromVersion(currentVersion);
  const targetChannel = getChannelFromVersion(info.update.latest);
  if (RELEASE_CHANNEL_STABILITY[targetChannel] < RELEASE_CHANNEL_STABILITY[currentChannel]) {
    return;
  }
  const isNightly = info.update.latest.includes("nightly");
  const updateCommand = installationInfo.updateCommand.replace(
    "@latest",
    isNightly ? "@nightly" : `@${info.update.latest}`
  );
  const updateProcess = spawnFn(updateCommand, {
    stdio: "ignore",
    shell: true,
    detached: true
  });
  _updateInProgress = true;
  updateProcess.unref();
  updateProcess.on("close", (code) => {
    _updateInProgress = false;
    if (code === 0) {
      updateEventEmitter.emit("update-success", {
        message: "Update successful! The new version will be used on your next run."
      });
    } else {
      updateEventEmitter.emit("update-failed", {
        message: `Automatic update failed. Please try updating manually:

${updateCommand}`
      });
    }
  });
  updateProcess.on("error", (err) => {
    _updateInProgress = false;
    updateEventEmitter.emit("update-failed", {
      message: `Automatic update failed. Please try updating manually. (error: ${err.message})

${updateCommand}`
    });
  });
  return updateProcess;
}
function setUpdateHandler(addItem, setUpdateInfo) {
  let successfullyInstalled = false;
  const handleUpdateReceived = (info) => {
    setUpdateInfo(info);
    const savedMessage = info.message;
    setTimeout(() => {
      if (!successfullyInstalled) {
        addItem(
          {
            type: "info" /* INFO */,
            text: savedMessage
          },
          Date.now()
        );
      }
      setUpdateInfo(null);
    }, 6e4);
  };
  const handleUpdateFailed = (data) => {
    setUpdateInfo(null);
    addItem(
      {
        type: "error" /* ERROR */,
        text: data?.message || `Automatic update failed. Please try updating manually`
      },
      Date.now()
    );
  };
  const handleUpdateSuccess = () => {
    successfullyInstalled = true;
    setUpdateInfo(null);
    addItem(
      {
        type: "info" /* INFO */,
        text: `Update successful! The new version will be used on your next run.`
      },
      Date.now()
    );
  };
  const handleUpdateInfo = (data) => {
    addItem(
      {
        type: "info" /* INFO */,
        text: data.message
      },
      Date.now()
    );
  };
  updateEventEmitter.on("update-received", handleUpdateReceived);
  updateEventEmitter.on("update-failed", handleUpdateFailed);
  updateEventEmitter.on("update-success", handleUpdateSuccess);
  updateEventEmitter.on("update-info", handleUpdateInfo);
  return () => {
    updateEventEmitter.off("update-received", handleUpdateReceived);
    updateEventEmitter.off("update-failed", handleUpdateFailed);
    updateEventEmitter.off("update-success", handleUpdateSuccess);
    updateEventEmitter.off("update-info", handleUpdateInfo);
  };
}

// packages/cli/src/utils/processUtils.ts
var RELAUNCH_EXIT_CODE = 199;
var isRelaunching = false;
async function relaunchApp() {
  if (isRelaunching) return;
  isRelaunching = true;
  await waitForUpdateCompletion();
  await runExitCleanup();
  process.exit(RELAUNCH_EXIT_CODE);
}
function isStandardSea() {
  return process.argv[0] !== process.argv[1] && (process.env["IS_BINARY"] === "true" || process.isSea?.() === true);
}
function getScriptArgs() {
  return process.argv.slice(isStandardSea() ? 1 : 2);
}
function isSeaEnvironment() {
  return process.env["IS_BINARY"] === "true" || process.isSea?.() === true || process.argv[0] === process.argv[1];
}
function getSpawnConfig(nodeArgs, scriptArgs) {
  const isBinary = isSeaEnvironment();
  const newEnv = {
    ...process.env,
    GEMINI_CLI_NO_RELAUNCH: "true"
  };
  const finalSpawnArgs = [];
  if (isBinary) {
    if (nodeArgs.length > 0) {
      for (const arg of nodeArgs) {
        if (/[\s"'\\]/.test(arg)) {
          throw new Error(
            `Unsupported node argument for SEA relaunch: ${arg}. Complex escaping is not supported.`
          );
        }
      }
      const existingNodeOptions = process.env["NODE_OPTIONS"] || "";
      newEnv["NODE_OPTIONS"] = `${existingNodeOptions} ${nodeArgs.join(" ")}`.trim();
    }
    finalSpawnArgs.push(process.execPath, ...scriptArgs);
  } else {
    finalSpawnArgs.push(
      ...process.execArgv,
      ...nodeArgs,
      process.argv[1],
      ...scriptArgs
    );
  }
  return {
    spawnArgs: finalSpawnArgs,
    env: newEnv
  };
}

export {
  isDevelopment,
  handleAutoUpdate,
  setUpdateHandler,
  RELAUNCH_EXIT_CODE,
  relaunchApp,
  getScriptArgs,
  getSpawnConfig
};
/**
 * @license
 * Copyright 2025 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
