// Force strict mode and setup for ESM
"use strict";
import {
  require_semver
} from "./chunk-DP3IHZGG.js";
import {
  getNpmCliPath
} from "./chunk-5R6QYKY6.js";
import "./chunk-URK542T4.js";
import "./chunk-QQOPXQYM.js";
import "./chunk-TWPJO254.js";
import "./chunk-H6XPXXMH.js";
import "./chunk-5M6IDOMF.js";
import "./chunk-UPUG4GXM.js";
import "./chunk-64LQLPL7.js";
import "./chunk-2LQTH543.js";
import {
  require_proper_lockfile
} from "./chunk-KRXPRVGL.js";
import "./chunk-GNCIZTNJ.js";
import "./chunk-CVHIL5IG.js";
import "./chunk-IRH27ZC2.js";
import "./chunk-QHWCP53L.js";
import "./chunk-PONHVBRT.js";
import "./chunk-T26EAKDL.js";
import "./chunk-6PVPNMXU.js";
import "./chunk-CPBF7KYF.js";
import "./chunk-6QIGFD5W.js";
import "./chunk-XWWKIXVD.js";
import "./chunk-75GFAX4R.js";
import "./chunk-OKF7JF3R.js";
import "./chunk-JSD33JG6.js";
import "./chunk-S6LOFUVP.js";
import "./chunk-JCW2R7WC.js";
import "./chunk-2DN4J57Y.js";
import "./chunk-ZPJWUGCS.js";
import "./chunk-2LKVPASC.js";
import "./chunk-NAVJD2PQ.js";
import "./chunk-LW3RFMG7.js";
import "./chunk-W4MIWP6M.js";
import "./chunk-DGEIYUC3.js";
import "./chunk-MPHPFVKK.js";
import "./chunk-GLNBDYUX.js";
import "./chunk-DJ2GSRLV.js";
import "./chunk-6D2RWQMA.js";
import "./chunk-75MIQ3LV.js";
import "./chunk-2J3OJGTL.js";
import "./chunk-P3QQPMQA.js";
import "./chunk-RPLGZJV2.js";
import "./chunk-GLCZKT5V.js";
import "./chunk-DZLYR4U3.js";
import "./chunk-NKHOVMWF.js";
import "./chunk-VGC4I5JJ.js";
import "./chunk-SGFT55XI.js";
import "./chunk-Y4IHBGBP.js";
import "./chunk-Y6AXW2OG.js";
import "./chunk-2M3XQKPR.js";
import "./chunk-46UV252V.js";
import "./chunk-ZBVS26BY.js";
import "./chunk-WZRWHXFE.js";
import "./chunk-A3NDJ5SB.js";
import "./chunk-7XATOOE7.js";
import "./chunk-BGTQCTQW.js";
import "./chunk-W4RQUHY3.js";
import "./chunk-S7W2GKIO.js";
import {
  Storage
} from "./chunk-UHUSJ6X7.js";
import "./chunk-VOQXFAY5.js";
import "./chunk-75DOP5OR.js";
import "./chunk-DMTGGOSA.js";
import "./chunk-YQ3U5MUC.js";
import "./chunk-AMDSOFFV.js";
import "./chunk-QUGAUQGJ.js";
import {
  init_esbuild_shims
} from "./chunk-5O2XNYP6.js";
import {
  __name,
  __toESM
} from "./chunk-J2S4EL5Y.js";

// packages/cli/src/utils/managed-npm-update.ts
init_esbuild_shims();
var import_proper_lockfile = __toESM(require_proper_lockfile(), 1);
var import_semver = __toESM(require_semver(), 1);
import { execFile, execFileSync, spawn } from "node:child_process";
import { createHash } from "node:crypto";
import * as fs from "node:fs";
import * as fsPromises from "node:fs/promises";
import * as path from "node:path";
import { promisify } from "node:util";
var PACKAGE_NAME = "@qwen-code/qwen-code";
var execFileAsync = promisify(execFile);
function assertVersion(version) {
  if (import_semver.default.valid(version) !== version) {
    throw new Error(`Invalid update version: ${version}`);
  }
}
__name(assertVersion, "assertVersion");
function packageDir(prefix) {
  return path.join(prefix, "node_modules", "@qwen-code", "qwen-code");
}
__name(packageDir, "packageDir");
function resolveBootstrapPath(bootstrapPath) {
  if (!bootstrapPath) {
    throw new Error("Unable to identify the Qwen Code npm launcher");
  }
  return fs.realpathSync(bootstrapPath);
}
__name(resolveBootstrapPath, "resolveBootstrapPath");
function launcherId(bootstrapPath) {
  return createHash("sha256").update(bootstrapPath).digest("hex").slice(0, 16);
}
__name(launcherId, "launcherId");
function processDoesNotExist(pidText) {
  const pid = Number(pidText);
  if (!Number.isSafeInteger(pid)) return false;
  try {
    process.kill(pid, 0);
    return false;
  } catch (error) {
    return error.code === "ESRCH";
  }
}
__name(processDoesNotExist, "processDoesNotExist");
function readDirectoryEntries(directory) {
  try {
    return fs.readdirSync(directory, { withFileTypes: true });
  } catch {
    return [];
  }
}
__name(readDirectoryEntries, "readDirectoryEntries");
function cleanupOrphanedManagedNpmUpdateArtifacts(launcherRoot, versionsDir) {
  for (const entry of readDirectoryEntries(versionsDir)) {
    const match = /^\.(.+)-([1-9]\d*)-[A-Za-z0-9]{6}$/.exec(entry.name);
    if (!entry.isDirectory() || entry.isSymbolicLink() || !match || import_semver.default.valid(match[1]) !== match[1] || !processDoesNotExist(match[2])) {
      continue;
    }
    try {
      fs.rmSync(path.join(versionsDir, entry.name), {
        recursive: true,
        force: true
      });
    } catch {
      continue;
    }
  }
  for (const entry of readDirectoryEntries(launcherRoot)) {
    const match = /^active\.json\.([1-9]\d*)$/.exec(entry.name);
    if (!entry.isFile() || entry.isSymbolicLink() || !match || !processDoesNotExist(match[1])) {
      continue;
    }
    try {
      fs.rmSync(path.join(launcherRoot, entry.name), { force: true });
    } catch {
      continue;
    }
  }
}
__name(cleanupOrphanedManagedNpmUpdateArtifacts, "cleanupOrphanedManagedNpmUpdateArtifacts");
function resolveNpmGlobalConfigPath() {
  const configured = process.env["NPM_CONFIG_GLOBALCONFIG"];
  if (configured) return path.resolve(configured);
  const output = execFileSync(
    process.execPath,
    [
      getNpmCliPath(process.execPath, process.platform),
      "config",
      "get",
      "globalconfig",
      "--global"
    ],
    { encoding: "utf8", timeout: 1e4 }
  ).trim();
  if (!output || output === "null" || output === "undefined") {
    throw new Error("Unable to resolve the global npm configuration");
  }
  return output;
}
__name(resolveNpmGlobalConfigPath, "resolveNpmGlobalConfigPath");
function readBaseInstallation(bootstrapPath) {
  const manifest = JSON.parse(
    fs.readFileSync(
      path.join(path.dirname(bootstrapPath), "package.json"),
      "utf8"
    )
  );
  if (manifest.name !== PACKAGE_NAME || typeof manifest.version !== "string") {
    throw new Error("Unable to identify the base Qwen Code npm installation");
  }
  return {
    version: manifest.version,
    ctimeMs: fs.statSync(bootstrapPath).ctimeMs
  };
}
__name(readBaseInstallation, "readBaseInstallation");
async function validateInstallation(prefix, version) {
  const root = packageDir(prefix);
  const manifest = JSON.parse(
    await fsPromises.readFile(path.join(root, "package.json"), "utf8")
  );
  if (manifest.name !== PACKAGE_NAME || manifest.version !== version) {
    throw new Error(
      `Installed package did not match ${PACKAGE_NAME}@${version}`
    );
  }
  await fsPromises.access(path.join(root, "cli.js"));
}
__name(validateInstallation, "validateInstallation");
async function smokeTest(prefix) {
  const env = { ...process.env };
  delete env["CLI_VERSION"];
  delete env["QWEN_CODE_RELAUNCH_ARGS"];
  await execFileAsync(
    process.execPath,
    [path.join(packageDir(prefix), "cli-entry.js"), "--help"],
    { encoding: "utf8", env, timeout: 1e4 }
  );
}
__name(smokeTest, "smokeTest");
async function readActiveVersion(activeFile, expected) {
  try {
    const active = JSON.parse(
      await fsPromises.readFile(activeFile, "utf8")
    );
    return typeof active.version === "string" && import_semver.default.valid(active.version) !== null && active.bootstrap === expected.bootstrap && active.baseVersion === expected.baseVersion && active.bootstrapCtimeMs === expected.bootstrapCtimeMs ? active.version : null;
  } catch {
    return null;
  }
}
__name(readActiveVersion, "readActiveVersion");
function prepareManagedNpmUpdate(version, bootstrapPath = process.env["QWEN_CODE_CLI"], updateRoot = process.env["QWEN_CODE_MANAGED_NPM_ROOT"] ?? path.join(Storage.getGlobalQwenDir(), "updates", "npm")) {
  assertVersion(version);
  const resolvedBootstrapPath = resolveBootstrapPath(bootstrapPath);
  const base = readBaseInstallation(resolvedBootstrapPath);
  const npmGlobalConfigPath = resolveNpmGlobalConfigPath();
  const launcherRoot = path.join(updateRoot, launcherId(resolvedBootstrapPath));
  const versionsDir = path.join(launcherRoot, "versions");
  fs.mkdirSync(versionsDir, { recursive: true });
  cleanupOrphanedManagedNpmUpdateArtifacts(launcherRoot, versionsDir);
  const stagingDir = fs.mkdtempSync(
    path.join(versionsDir, `.${version}-${process.pid}-`)
  );
  return {
    stagingDir,
    versionDir: path.join(versionsDir, version),
    launcherRoot,
    baseVersion: base.version,
    bootstrapCtimeMs: base.ctimeMs,
    installArgs: [
      "install",
      "--globalconfig",
      npmGlobalConfigPath,
      "--prefix",
      stagingDir,
      "--global=false",
      "--no-save",
      "--package-lock=false",
      "--no-audit",
      "--no-fund",
      `${PACKAGE_NAME}@${version}`
    ]
  };
}
__name(prepareManagedNpmUpdate, "prepareManagedNpmUpdate");
async function installManagedNpmUpdate(version, bootstrapPath = process.env["QWEN_CODE_CLI"], updateRoot = process.env["QWEN_CODE_MANAGED_NPM_ROOT"] ?? path.join(Storage.getGlobalQwenDir(), "updates", "npm"), spawnFn = spawn) {
  const update = prepareManagedNpmUpdate(version, bootstrapPath, updateRoot);
  const env = { ...process.env };
  for (const key of ["NPM_CONFIG_USERCONFIG", "npm_config_userconfig"]) {
    const configured = env[key];
    if (configured) env[key] = path.resolve(configured);
  }
  try {
    await new Promise((resolve2, reject) => {
      const child = spawnFn(
        process.execPath,
        [
          getNpmCliPath(process.execPath, process.platform),
          ...update.installArgs
        ],
        {
          cwd: update.stagingDir,
          env,
          stdio: ["ignore", "ignore", "inherit"],
          timeout: 10 * 6e4,
          windowsHide: true
        }
      );
      child.once("error", reject);
      child.once("close", (code) => {
        if (code === 0) resolve2();
        else reject(new Error(`npm install exited with code ${code}`));
      });
    });
    await activateManagedNpmUpdate(update, version, bootstrapPath);
  } catch (error) {
    await cleanupManagedNpmUpdate(update);
    throw error;
  }
}
__name(installManagedNpmUpdate, "installManagedNpmUpdate");
async function activateManagedNpmUpdate(update, version, bootstrapPath = process.env["QWEN_CODE_CLI"]) {
  assertVersion(version);
  const resolvedBootstrapPath = resolveBootstrapPath(bootstrapPath);
  if (path.join(
    path.dirname(update.launcherRoot),
    launcherId(resolvedBootstrapPath)
  ) !== update.launcherRoot) {
    throw new Error("The npm update does not match the active launcher");
  }
  await validateInstallation(update.stagingDir, version);
  await smokeTest(update.stagingDir);
  const activeFile = path.join(update.launcherRoot, "active.json");
  const release = await import_proper_lockfile.default.lock(activeFile, {
    realpath: false,
    stale: 3e4,
    retries: { retries: 50, minTimeout: 20, maxTimeout: 100 }
  });
  try {
    const base = readBaseInstallation(resolvedBootstrapPath);
    if (base.version !== update.baseVersion || base.ctimeMs !== update.bootstrapCtimeMs) {
      throw new Error(
        "The base Qwen Code npm installation changed during update"
      );
    }
    const activeVersion = await readActiveVersion(activeFile, {
      bootstrap: resolvedBootstrapPath,
      baseVersion: base.version,
      bootstrapCtimeMs: base.ctimeMs
    });
    if (activeVersion && import_semver.default.gt(activeVersion, version)) {
      try {
        await validateInstallation(
          path.join(update.launcherRoot, "versions", activeVersion),
          activeVersion
        );
        await cleanupManagedNpmUpdate(update);
        return;
      } catch {
      }
    }
    try {
      await fsPromises.rename(update.stagingDir, update.versionDir);
    } catch (error) {
      if (!fs.existsSync(update.versionDir)) throw error;
      await validateInstallation(update.versionDir, version);
      await cleanupManagedNpmUpdate(update);
    }
    const temporaryActivePath = `${activeFile}.${process.pid}`;
    try {
      await fsPromises.writeFile(
        temporaryActivePath,
        JSON.stringify({
          version,
          bootstrap: resolvedBootstrapPath,
          baseVersion: base.version,
          bootstrapCtimeMs: base.ctimeMs
        }),
        { mode: 384 }
      );
      await fsPromises.rename(temporaryActivePath, activeFile);
    } finally {
      await fsPromises.rm(temporaryActivePath, { force: true });
    }
  } finally {
    await release();
  }
}
__name(activateManagedNpmUpdate, "activateManagedNpmUpdate");
async function cleanupManagedNpmUpdate(update) {
  await fsPromises.rm(update.stagingDir, { recursive: true, force: true }).catch(() => {
  });
}
__name(cleanupManagedNpmUpdate, "cleanupManagedNpmUpdate");
export {
  activateManagedNpmUpdate,
  cleanupManagedNpmUpdate,
  installManagedNpmUpdate,
  prepareManagedNpmUpdate
};
/**
 * @license
 * Copyright 2026 Qwen Code
 * SPDX-License-Identifier: Apache-2.0
 */
