// Force strict mode and setup for ESM
"use strict";
import {
  registerMcpHotReload
} from "./chunk-HDK7G5SO.js";
import {
  startEarlyStartupPrefetches
} from "./chunk-SAXYK2RC.js";
import {
  ExtensionRefreshState,
  appEvents,
  buildDisabledSkillNamesProvider,
  isDebugMode,
  isValidSessionId,
  loadCliConfig,
  loadSandboxConfig,
  parseArguments,
  validateAuthMethod
} from "./chunk-RF3WVEV7.js";
import {
  CUSTOM_SANDBOX_IMAGE_ENV_VAR,
  HOST_UPDATE_RELAUNCH_ENV_VAR,
  RELAUNCH_EXIT_CODE,
  SKIP_UPDATE_CHECK_ENV_VAR,
  UPDATE_COMPLETE_EXIT_CODE,
  UPDATE_ON_EXIT_MESSAGE,
  UPDATE_RELAUNCH_EXIT_CODE
} from "./chunk-2XXBJXNM.js";
import "./chunk-TEEROMQB.js";
import {
  getHeadlessYoloSafetyWarning
} from "./chunk-6H67XLET.js";
import {
  isAcpStartupProfilerEnabled,
  markAcpStartup,
  recordAcpConfigStartupEvent
} from "./chunk-M744OFVE.js";
import "./chunk-AF2R7E6T.js";
import "./chunk-ZJBZXSVZ.js";
import "./chunk-DYA25Y7U.js";
import {
  sanitizeTerminalText
} from "./chunk-4NFY2S7N.js";
import "./chunk-2MIN6GRR.js";
import "./chunk-QHTIBUWB.js";
import "./chunk-3Z43GZUQ.js";
import "./chunk-RXFQM6FQ.js";
import "./chunk-JELIWHXD.js";
import "./chunk-Z4X5MTRT.js";
import "./chunk-TLVPVIPV.js";
import "./chunk-DE4MB5JC.js";
import "./chunk-57OAHC2Y.js";
import "./chunk-GLWP3FDB.js";
import "./chunk-XCGIMOLN.js";
import "./chunk-AG7ZRXUG.js";
import "./chunk-LGT3YMLN.js";
import "./chunk-X6WUYMOV.js";
import "./chunk-VWOVHOTT.js";
import "./chunk-V6WHFGST.js";
import "./chunk-UKZEXS6K.js";
import "./chunk-6PLDPT2C.js";
import "./chunk-FYJ7W2PI.js";
import "./chunk-QONSRAEV.js";
import "./chunk-24ER7UV4.js";
import "./chunk-ALMR3E6Q.js";
import "./chunk-BK2UNYWD.js";
import "./chunk-M5GB774H.js";
import "./chunk-XC2VAFVZ.js";
import "./chunk-WUC6ZFXO.js";
import "./chunk-DIEFUBV6.js";
import "./chunk-UDXSXLER.js";
import "./chunk-BDBMEX5J.js";
import {
  createMinimalSettings,
  getFlattenedSchema,
  getSettingsWarnings,
  getUserSettingsDir,
  initializeLlmOutputLanguage,
  loadSettings
} from "./chunk-P7RKN76O.js";
import "./chunk-RKUWKYED.js";
import "./chunk-GOXKNSDZ.js";
import "./chunk-IDS7MSUP.js";
import {
  initializeI18n,
  resolveLanguageSetting
} from "./chunk-FAH5P34O.js";
import {
  SETTINGS_DIRECTORY_NAME,
  preResolveHomeEnvOverrides
} from "./chunk-XY77A4MO.js";
import {
  ENV_CORRUPTED_PATH,
  ENV_WAS_RECOVERED
} from "./chunk-6PEXNQTX.js";
import {
  getInstallationInfo
} from "./chunk-23WQ62YW.js";
import "./chunk-BKXTHMOZ.js";
import "./chunk-VJNBRRZG.js";
import "./chunk-OAW4O3MF.js";
import "./chunk-ALGGS7UH.js";
import "./chunk-MR3PXB6E.js";
import "./chunk-XFSFZCM5.js";
import {
  GitWorktreeService,
  QWEN_CODE_SIMPLE_ENV_VAR,
  SessionService,
  canUseRipgrep,
  isBareMode,
  isSessionRuntimeActive,
  persistSessionUsage,
  readWorktreeSession,
  readWorktreeSessionMarker,
  require_shell_quote,
  resolveBundleDir,
  setStartupEventSink,
  watch,
  worktreeBranchForSlug,
  writeWorktreeSession,
  writeWorktreeSessionMarker
} from "./chunk-VDNAD6JC.js";
import "./chunk-GOFAQQZA.js";
import "./chunk-5M6IDOMF.js";
import "./chunk-TWPJO254.js";
import "./chunk-H6XPXXMH.js";
import "./chunk-VA5NLVPT.js";
import "./chunk-I7JDGNG6.js";
import "./chunk-A6SX5TAH.js";
import "./chunk-33FNCQSY.js";
import "./chunk-6PVPNMXU.js";
import "./chunk-QP2X3YUW.js";
import "./chunk-IRH27ZC2.js";
import "./chunk-QHWCP53L.js";
import "./chunk-MOHAWIAW.js";
import "./chunk-X6QNZOTC.js";
import "./chunk-O6GEWCJA.js";
import "./chunk-T26EAKDL.js";
import "./chunk-ZPJWUGCS.js";
import "./chunk-CPBF7KYF.js";
import "./chunk-MISUEWB4.js";
import "./chunk-KRXPRVGL.js";
import "./chunk-A5YZ3FA2.js";
import "./chunk-YAVY33G4.js";
import "./chunk-2UISUFHQ.js";
import "./chunk-HFVW54NL.js";
import "./chunk-TZTBZ25J.js";
import "./chunk-S6LOFUVP.js";
import "./chunk-SRY26X4H.js";
import "./chunk-K623ENWT.js";
import "./chunk-AQ37AY7B.js";
import "./chunk-432XCUHF.js";
import "./chunk-XC656O42.js";
import "./chunk-NAVJD2PQ.js";
import "./chunk-QYPT3QUD.js";
import "./chunk-QMBEW7EW.js";
import "./chunk-DGEIYUC3.js";
import "./chunk-MPHPFVKK.js";
import "./chunk-GLNBDYUX.js";
import "./chunk-DJ2GSRLV.js";
import "./chunk-5CPNLKAW.js";
import "./chunk-RPYYTL7E.js";
import "./chunk-2J3OJGTL.js";
import "./chunk-P3QQPMQA.js";
import "./chunk-6O5DVH27.js";
import "./chunk-GLCZKT5V.js";
import "./chunk-2DNKEBXY.js";
import {
  PRIVATE_ACP_CAPABILITY_ENV,
  logUserPrompt,
  uiTelemetryService
} from "./chunk-N7ZZBTIU.js";
import "./chunk-VGC4I5JJ.js";
import "./chunk-E4WHKETF.js";
import "./chunk-UEJESCS7.js";
import "./chunk-CFDR3GNL.js";
import "./chunk-O4Z6JR7D.js";
import "./chunk-46UV252V.js";
import "./chunk-ZBVS26BY.js";
import "./chunk-BFHXDAR7.js";
import "./chunk-TYERNYH4.js";
import "./chunk-UH7Z7Y45.js";
import "./chunk-O2ZYHG33.js";
import "./chunk-W4RQUHY3.js";
import "./chunk-G7XXKQYS.js";
import {
  FatalSandboxError,
  Storage,
  createDebugLogger,
  getErrorMessage,
  isDebugLogFileEnabled,
  isDebugLoggingDegraded,
  isSubpath
} from "./chunk-3RXUYQJI.js";
import "./chunk-VOQXFAY5.js";
import {
  handleUncaughtException,
  isExpectedPtyRaceError
} from "./chunk-QL4TN4HS.js";
import {
  cleanupCheckpoints,
  registerCleanup,
  runExitCleanup
} from "./chunk-3D43T7XT.js";
import {
  finalizeStartupProfile,
  isStartupProfilerEnabled,
  profileCheckpoint,
  recordStartupEvent,
  setInteractiveMode
} from "./chunk-QSWDGAIC.js";
import "./chunk-Q7YDKOGY.js";
import {
  writeStderrLine,
  writeStderrLineSafe
} from "./chunk-OWAK7LMW.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/gemini.tsx
init_esbuild_shims();
import dns from "node:dns";
import fs7 from "node:fs";
import os4 from "node:os";
import path8 from "node:path";
import v8 from "node:v8";

// packages/cli/src/config/settingsWatcher.ts
init_esbuild_shims();
import * as fs from "node:fs";
import * as path from "node:path";
var debugLogger = createDebugLogger("SETTINGS_WATCHER");
function collectChangedKeys(before, after, prefix = "") {
  const changed = [];
  const keys = /* @__PURE__ */ new Set([...Object.keys(before), ...Object.keys(after)]);
  for (const key of keys) {
    const keyPath = prefix ? `${prefix}.${key}` : key;
    const beforeValue = before[key];
    const afterValue = after[key];
    if (isPlainObject(beforeValue) && isPlainObject(afterValue)) {
      changed.push(...collectChangedKeys(beforeValue, afterValue, keyPath));
    } else if (JSON.stringify(beforeValue) !== JSON.stringify(afterValue)) {
      changed.push(keyPath);
    }
  }
  return changed;
}
__name(collectChangedKeys, "collectChangedKeys");
function isPlainObject(value) {
  return typeof value === "object" && value !== null && !Array.isArray(value);
}
__name(isPlainObject, "isPlainObject");
function isRestartRequiredKey(changedPath) {
  const flattened = getFlattenedSchema();
  const parts = changedPath.split(".");
  for (let i = parts.length; i > 0; i--) {
    const candidate = parts.slice(0, i).join(".");
    const definition = flattened[candidate];
    if (definition) return definition.requiresRestart === true;
  }
  return false;
}
__name(isRestartRequiredKey, "isRestartRequiredKey");
var SettingsWatcher = class _SettingsWatcher {
  static {
    __name(this, "SettingsWatcher");
  }
  settings;
  watchers = /* @__PURE__ */ new Map();
  /**
   * Per-scope watch stage. `bootstrap` watches the parent directory waiting
   * for the missing `.qwen` dir to appear; `target` watches `.qwen` itself.
   */
  watchStage = /* @__PURE__ */ new Map();
  /**
   * Per-scope generation token. Bumped on every promote/demote so that a
   * stale `'all'` callback from a watcher being torn down (chokidar `close()`
   * is async) becomes a no-op instead of stacking watchers.
   */
  watchGeneration = /* @__PURE__ */ new Map();
  changeListeners = /* @__PURE__ */ new Set();
  refreshTimer = null;
  pendingScopeChanges = /* @__PURE__ */ new Set();
  processing = false;
  started = false;
  static DEBOUNCE_MS = 300;
  static LISTENER_TIMEOUT_MS = 3e4;
  constructor(settings) {
    this.settings = settings;
  }
  startWatching() {
    if (this.started) return;
    this.started = true;
    for (const { scope, settingsPath } of this.getScopePaths()) {
      if (!settingsPath) continue;
      const dir = path.dirname(settingsPath);
      if (fs.existsSync(dir)) {
        this.watchTargetDir(scope, settingsPath);
      } else {
        this.watchParentForDir(scope, settingsPath);
      }
    }
  }
  /**
   * Watches the resolved `.qwen` directory for changes to `settings.json`.
   * If `.qwen` itself is removed, demotes back to a parent bootstrap watcher
   * so a later re-creation is still caught.
   */
  watchTargetDir(scope, settingsPath) {
    const dir = path.dirname(settingsPath);
    const targetBasename = path.basename(settingsPath);
    const gen = this.bumpGeneration(scope);
    try {
      const watcher = watch(dir, {
        ignoreInitial: true,
        depth: 0,
        ignored: /* @__PURE__ */ __name((filePath, stats) => {
          if (stats && !stats.isFile() && !stats.isDirectory()) return true;
          return false;
        }, "ignored")
      }).on("all", (event, changedPath) => {
        if (this.watchGeneration.get(scope) !== gen) return;
        if (event === "unlinkDir" && changedPath === dir) {
          void this.demoteScope(scope, settingsPath);
          return;
        }
        if (path.basename(changedPath) !== targetBasename) return;
        this.scheduleRefresh(scope);
      }).on("error", (error) => {
        debugLogger.warn(`Settings watcher error for ${dir}:`, error);
      });
      this.watchers.set(scope, watcher);
      this.watchStage.set(scope, "target");
    } catch (error) {
      debugLogger.warn(
        `Failed to start settings watcher for ${scope} (${dir}):`,
        error
      );
    }
  }
  /**
   * Bootstrap watcher: monitors the parent directory (depth 0) with a strict
   * predicate that only allows the `.qwen` entry through, so unrelated
   * top-level churn is suppressed and the project tree is never recursed.
   * Promotes to a target watcher once `.qwen` appears.
   */
  watchParentForDir(scope, settingsPath) {
    const dir = path.dirname(settingsPath);
    const parentDir = path.dirname(dir);
    const dirBasename = path.basename(dir);
    const gen = this.bumpGeneration(scope);
    try {
      const watcher = watch(parentDir, {
        ignoreInitial: true,
        depth: 0,
        ignored: /* @__PURE__ */ __name((filePath) => filePath !== parentDir && path.basename(filePath) !== dirBasename, "ignored")
      }).on("all", (_event, changedPath) => {
        if (this.watchGeneration.get(scope) !== gen) return;
        if (path.basename(changedPath) !== dirBasename) return;
        void this.promoteScope(scope, settingsPath);
      }).on("error", (error) => {
        debugLogger.warn(
          `Settings bootstrap watcher error for ${parentDir}:`,
          error
        );
      });
      this.watchers.set(scope, watcher);
      this.watchStage.set(scope, "bootstrap");
    } catch (error) {
      debugLogger.warn(
        `Failed to start settings bootstrap watcher for ${scope} (${parentDir}):`,
        error
      );
      return;
    }
    if (fs.existsSync(dir)) {
      void this.promoteScope(scope, settingsPath);
    }
  }
  /** Swaps a scope's bootstrap watcher for a target watcher on `.qwen`. */
  async promoteScope(scope, settingsPath) {
    if (this.watchStage.get(scope) !== "bootstrap") return;
    await this.replaceWatcher(scope);
    if (!this.started) return;
    this.watchTargetDir(scope, settingsPath);
    this.scheduleRefresh(scope);
  }
  /** Swaps a scope's target watcher back to a parent bootstrap watcher. */
  async demoteScope(scope, settingsPath) {
    if (this.watchStage.get(scope) !== "target") return;
    await this.replaceWatcher(scope);
    if (!this.started) return;
    this.watchParentForDir(scope, settingsPath);
    this.scheduleRefresh(scope);
  }
  /**
   * Bumps the scope generation and closes its current watcher, clearing the
   * map entries before the caller opens the next watcher. Bumping first makes
   * any in-flight callback from the closing watcher a no-op.
   */
  async replaceWatcher(scope) {
    this.bumpGeneration(scope);
    const watcher = this.watchers.get(scope);
    this.watchers.delete(scope);
    this.watchStage.delete(scope);
    if (watcher) {
      try {
        await watcher.close();
      } catch (err) {
        debugLogger.warn("Settings watcher close error:", err);
      }
    }
  }
  bumpGeneration(scope) {
    const next = (this.watchGeneration.get(scope) ?? 0) + 1;
    this.watchGeneration.set(scope, next);
    return next;
  }
  stopWatching() {
    if (!this.started) return;
    this.started = false;
    for (const [, watcher] of this.watchers) {
      watcher.close().catch((err) => {
        debugLogger.warn("Settings watcher close error:", err);
      });
    }
    this.watchers.clear();
    this.watchStage.clear();
    for (const scope of this.watchGeneration.keys()) {
      this.bumpGeneration(scope);
    }
    if (this.refreshTimer) {
      clearTimeout(this.refreshTimer);
      this.refreshTimer = null;
    }
    this.pendingScopeChanges.clear();
  }
  addChangeListener(listener) {
    this.changeListeners.add(listener);
    return () => {
      this.changeListeners.delete(listener);
    };
  }
  getScopePaths() {
    const paths = [
      {
        scope: "User" /* User */,
        settingsPath: this.settings.user.path
      }
    ];
    if (this.settings.workspaceSettingsActive) {
      paths.push({
        scope: "Workspace" /* Workspace */,
        settingsPath: this.settings.workspace.path
      });
    }
    return paths;
  }
  scheduleRefresh(scope) {
    this.pendingScopeChanges.add(scope);
    if (this.refreshTimer) clearTimeout(this.refreshTimer);
    this.refreshTimer = setTimeout(() => {
      this.refreshTimer = null;
      void this.drainPendingChanges().catch((err) => {
        debugLogger.warn("Settings watcher refresh error:", err);
      });
    }, _SettingsWatcher.DEBOUNCE_MS);
  }
  async drainPendingChanges() {
    if (this.processing) return;
    this.processing = true;
    try {
      while (this.pendingScopeChanges.size > 0) {
        const scopes = new Set(this.pendingScopeChanges);
        this.pendingScopeChanges.clear();
        await this.handleChange(scopes);
      }
    } finally {
      this.processing = false;
    }
  }
  async handleChange(changedScopes) {
    const events = [];
    for (const scope of changedScopes) {
      const file = this.settings.forScope(scope);
      const before = structuredClone(file.settings ?? {});
      const existedBefore = file.rawJson !== void 0;
      this.settings.reloadScopeFromDisk(scope);
      const after = file.settings ?? {};
      const existsNow = file.rawJson !== void 0;
      const changedKeys = collectChangedKeys(before, after);
      if (changedKeys.length === 0) {
        continue;
      }
      const hasHotReloadableChange = changedKeys.some(
        (key) => !isRestartRequiredKey(key)
      );
      if (!hasHotReloadableChange) {
        continue;
      }
      events.push({
        scope,
        path: file.path,
        changeType: !existedBefore && existsNow ? "created" : existedBefore && !existsNow ? "deleted" : "modified"
      });
    }
    if (events.length > 0) {
      await this.notifyListeners(events);
    }
  }
  async notifyListeners(events) {
    const TIMEOUT_MS = _SettingsWatcher.LISTENER_TIMEOUT_MS;
    const withTimeout = /* @__PURE__ */ __name((p) => {
      let timerId;
      const timeoutPromise = new Promise((_, reject) => {
        timerId = setTimeout(
          () => reject(
            new Error(
              `settings change listener timeout after ${TIMEOUT_MS}ms`
            )
          ),
          TIMEOUT_MS
        );
        if (typeof timerId === "object" && timerId !== null && "unref" in timerId) {
          timerId.unref();
        }
      });
      return Promise.race([p, timeoutPromise]).finally(() => {
        if (timerId !== void 0) clearTimeout(timerId);
      });
    }, "withTimeout");
    const results = await Promise.allSettled(
      Array.from(this.changeListeners).map(
        (listener) => withTimeout(Promise.resolve().then(() => listener(events)))
      )
    );
    for (const result of results) {
      if (result.status === "rejected") {
        debugLogger.warn("Settings change listener error:", result.reason);
      }
    }
  }
};

// packages/cli/src/config/lsp-config-watcher.ts
init_esbuild_shims();
import * as fs2 from "node:fs";
import * as path2 from "node:path";
var debugLogger2 = createDebugLogger("LSP_CONFIG_WATCHER");
var LspConfigWatcher = class _LspConfigWatcher {
  constructor(workspaceRoot) {
    this.workspaceRoot = workspaceRoot;
    this.configPath = path2.join(workspaceRoot, ".lsp.json");
    this.lastSnapshot = this.readSnapshot();
  }
  static {
    __name(this, "LspConfigWatcher");
  }
  watcher;
  listener;
  refreshTimer = null;
  activeDrain;
  processing = false;
  pending = false;
  started = false;
  lastSnapshot;
  configPath;
  static DEBOUNCE_MS = 300;
  static LISTENER_TIMEOUT_MS = 3e4;
  startWatching(listener) {
    if (this.started) return;
    debugLogger2.info(`Starting LSP config watcher for ${this.configPath}`);
    try {
      const watcher = watch(this.workspaceRoot, {
        ignoreInitial: true,
        depth: 0
      }).on("all", (_event, changedPath) => {
        if (path2.basename(changedPath) !== ".lsp.json") return;
        this.scheduleRefresh();
      }).on("error", (error) => {
        debugLogger2.warn(
          `LSP config watcher error for ${this.workspaceRoot}:`,
          error
        );
      });
      this.watcher = watcher;
      this.listener = listener;
      this.started = true;
    } catch (error) {
      this.watcher = void 0;
      this.listener = void 0;
      this.started = false;
      debugLogger2.warn(
        `Failed to start LSP config watcher for ${this.workspaceRoot}:`,
        error
      );
    }
  }
  async stopWatching() {
    if (!this.started) return;
    this.started = false;
    debugLogger2.info(`Stopping LSP config watcher for ${this.configPath}`);
    if (this.refreshTimer) {
      clearTimeout(this.refreshTimer);
      this.refreshTimer = null;
    }
    this.pending = false;
    await this.activeDrain;
    this.listener = void 0;
    try {
      await this.watcher?.close();
    } catch (error) {
      debugLogger2.warn("LSP config watcher close error:", error);
    }
    this.watcher = void 0;
  }
  scheduleRefresh() {
    if (!this.started) return;
    this.pending = true;
    if (this.refreshTimer) clearTimeout(this.refreshTimer);
    this.refreshTimer = setTimeout(() => {
      this.refreshTimer = null;
      if (this.processing) return;
      const activeDrain = this.drainPendingChange().catch((error) => {
        debugLogger2.warn("LSP config watcher refresh error:", error);
      });
      this.activeDrain = activeDrain;
      void activeDrain.finally(() => {
        if (this.activeDrain === activeDrain) {
          this.activeDrain = void 0;
        }
      });
    }, _LspConfigWatcher.DEBOUNCE_MS);
    if (typeof this.refreshTimer === "object" && this.refreshTimer !== null && "unref" in this.refreshTimer) {
      this.refreshTimer.unref();
    }
  }
  /** Drains debounced changes one at a time while preserving a trailing update. */
  async drainPendingChange() {
    if (this.processing) return;
    this.processing = true;
    try {
      while (this.pending) {
        this.pending = false;
        await this.handleChange();
      }
    } finally {
      this.processing = false;
    }
  }
  /**
   * Compares the previous and current semantic snapshots.
   *
   * Invalid JSON emits an `invalid` event for user feedback but does not report
   * a runtime config change; the caller must keep the existing LSP state.
   */
  async handleChange() {
    const before = this.lastSnapshot;
    const after = this.readSnapshot();
    if (after.exists && after.canonical === void 0) {
      debugLogger2.warn(
        `Invalid .lsp.json; keeping existing LSP runtime state.`
      );
      const notified2 = await this.notifyListener({
        path: this.configPath,
        changeType: "invalid",
        error: after.error ?? "Invalid JSON in .lsp.json; existing LSP runtime state is unchanged."
      });
      if (notified2) {
        this.lastSnapshot = after;
      }
      return;
    }
    const changed = before.exists !== after.exists || before.canonical !== after.canonical;
    if (!changed) {
      this.lastSnapshot = after;
      return;
    }
    const event = {
      path: this.configPath,
      changeType: !before.exists && after.exists ? "created" : before.exists && !after.exists ? "deleted" : "modified"
    };
    debugLogger2.info(`LSP config changed: ${event.changeType} ${event.path}`);
    const notified = await this.notifyListener(event);
    if (notified) {
      this.lastSnapshot = after;
    }
  }
  /**
   * Reads `.lsp.json` as a single operation. ENOENT is treated as deletion so a
   * file removed during a filesystem race still reconciles servers to empty.
   */
  readSnapshot() {
    let raw;
    try {
      raw = fs2.readFileSync(this.configPath, "utf-8");
    } catch (error) {
      if (error.code === "ENOENT") {
        return { exists: false };
      }
      debugLogger2.warn("Failed to read .lsp.json:", error);
      return {
        exists: true,
        error: "Failed to read .lsp.json; existing LSP runtime state is unchanged."
      };
    }
    try {
      const parsed = JSON.parse(raw);
      return { exists: true, canonical: canonicalize(parsed) };
    } catch (error) {
      debugLogger2.warn("Failed to parse .lsp.json:", error);
      return {
        exists: true,
        error: "Invalid JSON in .lsp.json; existing LSP runtime state is unchanged."
      };
    }
  }
  /**
   * Runs the listener with timeout isolation so a hung reload cannot stall CLI.
   *
   * Returns whether the listener completed successfully; callers use this to
   * decide whether the semantic snapshot can advance or should be retried.
   */
  async notifyListener(event) {
    if (!this.listener) return true;
    const TIMEOUT_MS = _LspConfigWatcher.LISTENER_TIMEOUT_MS;
    let timerId;
    const timeoutPromise = new Promise((_, reject) => {
      timerId = setTimeout(
        () => reject(
          new Error(
            `LSP config change listener timeout after ${TIMEOUT_MS}ms`
          )
        ),
        TIMEOUT_MS
      );
      if (typeof timerId === "object" && timerId !== null && "unref" in timerId) {
        timerId.unref();
      }
    });
    const listenerPromise = Promise.resolve().then(
      () => this.listener?.(event)
    );
    try {
      await Promise.race([listenerPromise, timeoutPromise]);
      return true;
    } catch (error) {
      debugLogger2.warn("LSP config change listener error:", error);
      return false;
    } finally {
      if (timerId !== void 0) clearTimeout(timerId);
      void listenerPromise.catch(() => void 0);
    }
  }
};
function canonicalize(value) {
  return JSON.stringify(sortJsonValue(value));
}
__name(canonicalize, "canonicalize");
function sortJsonValue(value) {
  if (Array.isArray(value)) {
    return value.map(sortJsonValue);
  }
  if (value && typeof value === "object") {
    const sorted = /* @__PURE__ */ Object.create(null);
    for (const key of Object.keys(value).sort()) {
      sorted[key] = sortJsonValue(value[key]);
    }
    return sorted;
  }
  return value;
}
__name(sortJsonValue, "sortJsonValue");

// packages/cli/src/config/extension-file-watcher.ts
init_esbuild_shims();
import * as fs3 from "node:fs";
import * as path3 from "node:path";
var debugLogger3 = createDebugLogger("EXTENSION_FILE_WATCHER");
var TOP_LEVEL_FILES = /* @__PURE__ */ new Set(["extension-enablement.json"]);
var EXTENSION_FILES = /* @__PURE__ */ new Set([
  "qwen-extension.json",
  ".qwen-extension-install.json"
]);
var AUTO_REFRESH_DIRS = /* @__PURE__ */ new Set(["commands", "skills", "agents"]);
var STALE_DIRS = /* @__PURE__ */ new Set(["hooks"]);
var ExtensionFileWatcher = class {
  constructor(config, extensionsDir = Storage.getUserExtensionsDir(), refreshState = new ExtensionRefreshState(), storeStatePath) {
    this.config = config;
    this.extensionsDir = extensionsDir;
    this.refreshState = refreshState;
    this.storeStatePath = storeStatePath ?? path3.join(
      path3.dirname(this.extensionsDir),
      "extension-store",
      "state.json"
    );
    this.observedStoreGeneration = this.readStoreGeneration();
  }
  static {
    __name(this, "ExtensionFileWatcher");
  }
  watcher;
  bootstrapWatcher;
  mutationListenerDisposer;
  mutationSuppressionEnds = /* @__PURE__ */ new Map();
  staleFiles = /* @__PURE__ */ new Set();
  watching = false;
  watchGeneration = 0;
  storeStatePath;
  generationPoller;
  observedStoreGeneration;
  startWatching() {
    this.stopWatching();
    this.watching = true;
    const generation = ++this.watchGeneration;
    this.subscribeExtensionManagerMutations();
    this.staleFiles = this.getStaleFiles();
    const roots = this.getWatchRoots();
    if (roots.length > 0) {
      this.watcher = watch(roots, {
        ignoreInitial: true,
        followSymlinks: false,
        awaitWriteFinish: {
          stabilityThreshold: 200,
          pollInterval: 50
        },
        ignored: /* @__PURE__ */ __name((filePath) => this.isIgnored(filePath), "ignored")
      }).on("all", (event, changedPath) => {
        if (generation !== this.watchGeneration) return;
        const resolvedPath = path3.resolve(changedPath);
        const action = this.getRefreshAction(
          event,
          resolvedPath
        );
        let marked = false;
        if (action === "auto") {
          marked = this.refreshState.markExtensionContentChanged(
            "extension content files changed"
          );
        } else if (action === "stale") {
          marked = this.refreshState.markExtensionsChanged(
            "extension files changed"
          );
        }
        debugLogger3.debug("Extension file event classified", {
          event,
          path: resolvedPath,
          action,
          marked
        });
      }).on("error", (error) => {
        debugLogger3.warn("Extension file watcher error:", error);
      });
    }
    if (!fs3.existsSync(this.extensionsDir)) {
      this.watchExtensionsParent();
    }
    this.startGenerationPolling();
  }
  stopWatching() {
    const watcher = this.watcher;
    const bootstrapWatcher = this.bootstrapWatcher;
    this.watcher = void 0;
    this.bootstrapWatcher = void 0;
    this.watching = false;
    this.watchGeneration++;
    if (this.generationPoller) clearInterval(this.generationPoller);
    this.generationPoller = void 0;
    this.mutationListenerDisposer?.();
    this.mutationListenerDisposer = void 0;
    this.endPendingMutationSuppressions();
    watcher?.close().catch((error) => {
      debugLogger3.warn("Extension file watcher close error:", error);
    });
    bootstrapWatcher?.close().catch((error) => {
      debugLogger3.warn("Extension bootstrap watcher close error:", error);
    });
  }
  restartWatching() {
    this.startWatching();
  }
  getWatchRoots() {
    const roots = /* @__PURE__ */ new Set();
    if (fs3.existsSync(this.extensionsDir)) {
      roots.add(this.extensionsDir);
    }
    roots.add(this.storeStatePath);
    for (const extension of this.config.getActiveExtensions()) {
      if (extension.installMetadata?.type === "link") {
        const rawSource = extension.installMetadata.source;
        const source = rawSource ? path3.resolve(rawSource) : void 0;
        if (source && fs3.existsSync(source)) {
          roots.add(source);
        }
      }
    }
    return [...roots];
  }
  getStaleFiles() {
    const files = /* @__PURE__ */ new Set();
    for (const extension of this.config.getActiveExtensions()) {
      for (const filePath of extension.contextFiles) {
        files.add(path3.resolve(filePath));
      }
      const configured = extension.config.contextFileName;
      const names = configured === void 0 ? ["QWEN.md"] : Array.isArray(configured) ? configured : [configured];
      for (const name of names) {
        files.add(path3.resolve(extension.path, name));
      }
      this.addManifestFileReference(
        files,
        extension.path,
        extension.config.hooks
      );
      this.addManifestFileReference(
        files,
        extension.path,
        extension.config.lspServers
      );
    }
    return files;
  }
  addManifestFileReference(files, extensionPath, value) {
    if (typeof value !== "string") return;
    files.add(
      path3.isAbsolute(value) ? path3.resolve(value) : path3.resolve(extensionPath, value)
    );
  }
  watchExtensionsParent() {
    this.closeBootstrapWatcher();
    const parentDir = path3.dirname(this.extensionsDir);
    const dirBasename = path3.basename(this.extensionsDir);
    const generation = this.watchGeneration;
    this.bootstrapWatcher = watch(parentDir, {
      ignoreInitial: true,
      followSymlinks: false,
      depth: 0,
      ignored: /* @__PURE__ */ __name((filePath) => filePath !== parentDir && path3.basename(filePath) !== dirBasename, "ignored")
    }).on("all", (_event, changedPath) => {
      if (generation !== this.watchGeneration) return;
      if (path3.basename(changedPath) !== dirBasename) return;
      if (!fs3.existsSync(this.extensionsDir)) return;
      this.refreshState.markExtensionsChanged("extension directory created");
      queueMicrotask(() => {
        if (this.watching) {
          this.restartWatching();
        }
      });
    }).on("error", (error) => {
      debugLogger3.warn("Extension bootstrap watcher error:", error);
    });
  }
  getRefreshAction(event, changedPath) {
    if (changedPath === path3.resolve(this.storeStatePath)) {
      const generation = this.readStoreGeneration();
      if (generation !== void 0) {
        this.markStoreGenerationChanged(generation, true);
      } else {
        this.refreshState.markExtensionsChanged(
          "extension store generation changed"
        );
      }
      return false;
    }
    if (this.staleFiles.has(changedPath)) {
      return "stale";
    }
    if (changedPath === path3.resolve(this.extensionsDir)) {
      if (event === "unlinkDir") {
        this.watchExtensionsParent();
        return "stale";
      }
      return false;
    }
    if (isSubpath(this.extensionsDir, changedPath)) {
      return this.getUserExtensionRefreshAction(event, changedPath);
    }
    return this.getLinkedExtensionRefreshAction(changedPath);
  }
  getUserExtensionRefreshAction(event, changedPath) {
    const relative2 = path3.relative(this.extensionsDir, changedPath);
    const parts = relative2.split(path3.sep).filter(Boolean);
    if (parts.length === 1) {
      if (TOP_LEVEL_FILES.has(parts[0])) return "stale";
      if (event === "addDir" || event === "unlinkDir") return "stale";
      return false;
    }
    if (!fs3.existsSync(
      path3.join(this.extensionsDir, parts[0], "qwen-extension.json")
    )) {
      return "stale";
    }
    const runtimePath = parts.slice(1);
    return this.getRuntimePathRefreshAction(runtimePath);
  }
  getLinkedExtensionRefreshAction(changedPath) {
    for (const extension of this.config.getActiveExtensions()) {
      if (extension.installMetadata?.type !== "link") continue;
      const rawSource = extension.installMetadata.source;
      const source = rawSource ? path3.resolve(rawSource) : void 0;
      if (!source || !isSubpath(source, changedPath)) continue;
      const relative2 = path3.relative(source, changedPath);
      const parts = relative2.split(path3.sep).filter(Boolean);
      return parts.length === 0 ? "stale" : this.getRuntimePathRefreshAction(parts);
    }
    return false;
  }
  getRuntimePathRefreshAction(parts) {
    if (EXTENSION_FILES.has(parts[0]) || STALE_DIRS.has(parts[0])) {
      return "stale";
    }
    if (AUTO_REFRESH_DIRS.has(parts[0])) {
      return "auto";
    }
    return false;
  }
  isIgnored(filePath) {
    const normalized = filePath.replace(/\\/g, "/");
    const searchablePath = `/${normalized}/`;
    if (searchablePath.includes("/node_modules/") || searchablePath.includes("/.git/")) {
      return true;
    }
    const basename4 = normalized.split("/").pop() ?? "";
    return basename4 === ".DS_Store" || basename4.endsWith("~") || basename4.endsWith(".swp") || basename4.endsWith(".tmp");
  }
  subscribeExtensionManagerMutations() {
    const manager = this.config.getExtensionManager();
    this.mutationListenerDisposer = manager.addMutationListener(
      (event) => {
        if (event.phase === "start") {
          this.mutationSuppressionEnds.set(
            event.id,
            this.refreshState.beginSuppression(
              () => this.restartAfterMutation()
            )
          );
          return;
        }
        const endSuppression = this.mutationSuppressionEnds.get(event.id);
        if (!endSuppression) {
          return;
        }
        this.mutationSuppressionEnds.delete(event.id);
        endSuppression();
      }
    );
  }
  endPendingMutationSuppressions() {
    const endSuppressions = [...this.mutationSuppressionEnds.values()];
    this.mutationSuppressionEnds.clear();
    for (const endSuppression of endSuppressions) {
      endSuppression();
    }
  }
  restartAfterMutation() {
    if (this.watching) {
      this.restartWatching();
    }
  }
  closeBootstrapWatcher() {
    const bootstrapWatcher = this.bootstrapWatcher;
    this.bootstrapWatcher = void 0;
    bootstrapWatcher?.close().catch((error) => {
      debugLogger3.warn("Extension bootstrap watcher close error:", error);
    });
  }
  startGenerationPolling() {
    if (this.generationPoller) clearInterval(this.generationPoller);
    this.pollStoreGeneration();
    this.generationPoller = setInterval(
      () => this.pollStoreGeneration(),
      3e4
    );
    this.generationPoller.unref?.();
  }
  pollStoreGeneration() {
    const generation = this.readStoreGeneration();
    if (generation === void 0) return;
    this.markStoreGenerationChanged(generation);
  }
  markStoreGenerationChanged(generation, force = false) {
    const previous = this.observedStoreGeneration;
    if (previous === void 0) {
      this.observedStoreGeneration = generation;
      return;
    }
    if (!force && previous === generation) return;
    if (this.refreshState.isSuppressed()) return;
    const marked = this.refreshState.markExtensionsChanged(
      "extension store generation changed"
    );
    if (marked || this.refreshState.needsExtensionRefresh()) {
      this.observedStoreGeneration = generation;
    }
  }
  readStoreGeneration() {
    try {
      const parsed = JSON.parse(
        fs3.readFileSync(this.storeStatePath, "utf8")
      );
      return typeof parsed.generation === "number" ? parsed.generation : void 0;
    } catch {
      return void 0;
    }
  }
};

// packages/cli/src/startup/worktreeStartup.ts
init_esbuild_shims();
import * as path4 from "node:path";
var debugLogger4 = createDebugLogger("WORKTREE_STARTUP");
var DETACHED_HEAD = "HEAD";
async function setupStartupWorktree(rawInput, options) {
  if (rawInput === void 0) return null;
  const trimmed = rawInput.trim();
  const launchCwd = process.cwd();
  const probe = new GitWorktreeService(launchCwd);
  const gitCheck = await probe.checkGitAvailable();
  if (!gitCheck.available) {
    return {
      ok: false,
      error: `--worktree: ${gitCheck.error ?? "git is not available on PATH."}`
    };
  }
  if (/[\\/]\.qwen[\\/]worktrees[\\/]/.test(launchCwd)) {
    return {
      ok: false,
      error: `--worktree: cannot start a new worktree from inside another worktree (cwd: ${launchCwd}). Run from the main checkout.`
    };
  }
  const rawRepoRoot = await probe.getRepoTopLevel();
  if (rawRepoRoot === null) {
    return {
      ok: false,
      error: `--worktree: ${launchCwd} is not a git repository. Run \`git init\` first or relaunch from inside one.`
    };
  }
  const repoRoot = path4.resolve(rawRepoRoot);
  const service = repoRoot === launchCwd ? probe : new GitWorktreeService(repoRoot);
  const prNumber = GitWorktreeService.parsePRReference(trimmed);
  const isPullRequest = prNumber !== null;
  let slug;
  if (prNumber !== null) {
    slug = `pr-${prNumber}`;
  } else if (trimmed.length === 0) {
    slug = GitWorktreeService.generateAutoSlug();
  } else {
    const validation = GitWorktreeService.validateUserWorktreeSlug(trimmed);
    if (validation) {
      return { ok: false, error: `--worktree: ${validation}` };
    }
    slug = trimmed;
  }
  const [originalBranchRaw, originalHeadCommit] = await Promise.all([
    service.getCurrentBranch().catch(() => void 0),
    service.getCurrentCommitHash().catch(() => "")
  ]);
  const originalBranch = originalBranchRaw && originalBranchRaw !== DETACHED_HEAD ? originalBranchRaw : void 0;
  const expectedWorktreePath = service.getUserWorktreePath(slug);
  const expectedBranch = worktreeBranchForSlug(slug);
  let registered = null;
  try {
    registered = await service.getRegisteredWorktreeBranch(expectedWorktreePath);
  } catch {
    registered = null;
  }
  if (registered !== null) {
    if (registered.branch !== expectedBranch) {
      return {
        ok: false,
        error: `--worktree: ${expectedWorktreePath} is already a git worktree, but its branch is ${registered.branch} (expected ${expectedBranch}). Refusing to re-attach. Resolve the conflict manually (e.g. \`git worktree remove ${expectedWorktreePath}\`).`
      };
    }
    const worktreePath2 = path4.resolve(expectedWorktreePath);
    try {
      process.chdir(worktreePath2);
    } catch (error) {
      return {
        ok: false,
        error: `--worktree: failed to chdir into ${worktreePath2} (${error instanceof Error ? error.message : String(error)}).`
      };
    }
    debugLogger4.debug(
      `setupStartupWorktree: re-attached to existing worktree at ${worktreePath2} (branch=${registered.branch})`
    );
    return {
      ok: true,
      context: {
        worktreePath: worktreePath2,
        slug,
        branch: registered.branch,
        repoRoot,
        originalBranch: originalBranch ?? DETACHED_HEAD,
        originalHeadCommit: registered.headCommit,
        isPullRequest,
        wasReattached: true
      }
    };
  }
  let pullRequestHeadSha = null;
  if (prNumber !== null) {
    const fetchRes = await service.fetchPullRequestRef(prNumber);
    if (!fetchRes.success) {
      return { ok: false, error: `--worktree: ${fetchRes.error}` };
    }
    pullRequestHeadSha = await service.resolveRef("FETCH_HEAD");
    if (pullRequestHeadSha === null) {
      return {
        ok: false,
        error: `--worktree: fetched PR #${prNumber} but FETCH_HEAD did not resolve to a commit SHA. Refusing to proceed (the worktree would otherwise branch off an unknown commit).`
      };
    }
  }
  const baseRef = isPullRequest ? pullRequestHeadSha : originalBranch;
  const result = await service.createUserWorktree(slug, baseRef, {
    symlinkDirectories: options?.symlinkDirectories
  });
  if (!result.success || !result.worktree) {
    return {
      ok: false,
      error: `--worktree: ${result.error ?? "failed to create worktree."}`
    };
  }
  const worktreePath = path4.resolve(result.worktree.path);
  try {
    process.chdir(worktreePath);
  } catch (error) {
    return {
      ok: false,
      error: `--worktree: created worktree at ${worktreePath} but failed to chdir into it (${error instanceof Error ? error.message : String(error)}). Run \`cd ${worktreePath}\` manually.`
    };
  }
  return {
    ok: true,
    context: {
      worktreePath,
      slug,
      branch: result.worktree.branch,
      repoRoot,
      originalBranch: originalBranch ?? DETACHED_HEAD,
      // For PR worktrees, the worktree's HEAD starts at the fetched PR
      // tip — not at the parent repo's HEAD. Use the SHA we locked in
      // post-fetch so the exit-dialog rev-list counts only the user's
      // new commits, not the entire PR history.
      originalHeadCommit: isPullRequest ? pullRequestHeadSha : originalHeadCommit,
      isPullRequest,
      wasReattached: false
    }
  };
}
__name(setupStartupWorktree, "setupStartupWorktree");
async function persistStartupWorktreeSidecar(config, context) {
  const sessionId = config.getSessionId();
  const sidecarPath = config.getSessionService().getWorktreeSessionPath(sessionId);
  let overrodeResumedWorktree = false;
  let overriddenSlug;
  let previous = null;
  try {
    previous = await readWorktreeSession(sidecarPath);
  } catch (error) {
    debugLogger4.warn(
      `persistStartupWorktreeSidecar: failed to read existing sidecar at ${sidecarPath} \u2014 treating as "no previous worktree" and proceeding: ${error}`
    );
    previous = null;
  }
  if (previous && previous.slug !== context.slug) {
    overrodeResumedWorktree = true;
    overriddenSlug = previous.slug;
  }
  let shouldWriteMarker = !context.wasReattached;
  if (context.wasReattached) {
    const owner = await readWorktreeSessionMarker(context.worktreePath);
    if (owner === null || owner === sessionId) {
      shouldWriteMarker = true;
    } else {
      const ownerActive = await isSessionRuntimeActive(owner, [
        context.repoRoot,
        context.worktreePath
      ]).catch((error) => {
        debugLogger4.warn(
          `persistStartupWorktreeSidecar: failed to check owner runtime ${owner}: ${error}`
        );
        return true;
      });
      shouldWriteMarker = !ownerActive;
    }
  }
  if (shouldWriteMarker) {
    await writeWorktreeSessionMarker(context.worktreePath, sessionId).catch(
      () => {
      }
    );
  }
  await writeWorktreeSession(sidecarPath, {
    slug: context.slug,
    worktreePath: context.worktreePath,
    worktreeBranch: context.branch,
    originalCwd: context.repoRoot,
    originalBranch: context.originalBranch,
    originalHeadCommit: context.originalHeadCommit
  });
  return { overrodeResumedWorktree, overriddenSlug, sidecarPath };
}
__name(persistStartupWorktreeSidecar, "persistStartupWorktreeSidecar");
function buildStartupWorktreeNotice(context, override) {
  const verb = context.wasReattached ? "Re-attached to worktree" : "Active worktree";
  const base = `[Startup] ${verb}: "${context.slug}" at ${context.worktreePath} (branch: ${context.branch}). Continue using this path for all file operations.`;
  if (override?.overrodeResumedWorktree && override.overriddenSlug) {
    return `${base}
Note: --worktree overrode the resumed session's previous worktree "${override.overriddenSlug}". That worktree directory was left intact; re-attach with \`qwen --worktree ${override.overriddenSlug}\` if needed.`;
  }
  return base;
}
__name(buildStartupWorktreeNotice, "buildStartupWorktreeNotice");

// packages/cli/src/utils/readStdin.ts
init_esbuild_shims();
function takeUtf8Prefix(value, maxBytes) {
  let bytes = 0;
  let end = 0;
  for (const char of value) {
    const charBytes = Buffer.byteLength(char, "utf8");
    if (bytes + charBytes > maxBytes) {
      break;
    }
    bytes += charBytes;
    end += char.length;
  }
  return value.slice(0, end);
}
__name(takeUtf8Prefix, "takeUtf8Prefix");
async function readStdin() {
  const MAX_STDIN_SIZE = 8 * 1024 * 1024;
  return new Promise((resolve3, reject) => {
    let data = "";
    let totalSize = 0;
    let settled = false;
    process.stdin.setEncoding("utf8");
    const pipedInputShouldBeAvailableInMs = 500;
    let pipedInputTimerId = setTimeout(() => {
      onEnd();
    }, pipedInputShouldBeAvailableInMs);
    const onReadable = /* @__PURE__ */ __name(() => {
      let chunk;
      while ((chunk = process.stdin.read()) !== null) {
        if (pipedInputTimerId) {
          clearTimeout(pipedInputTimerId);
          pipedInputTimerId = null;
        }
        const chunkSize = Buffer.byteLength(chunk, "utf8");
        if (totalSize + chunkSize > MAX_STDIN_SIZE) {
          const remainingSize = MAX_STDIN_SIZE - totalSize;
          const prefix = takeUtf8Prefix(chunk, remainingSize);
          data += prefix;
          totalSize += Buffer.byteLength(prefix, "utf8");
          writeStderrLine(
            `Warning: stdin input truncated to ${MAX_STDIN_SIZE} bytes.`
          );
          finish();
          process.stdin.destroy();
          return;
        }
        data += chunk;
        totalSize += chunkSize;
      }
    }, "onReadable");
    const finish = /* @__PURE__ */ __name(() => {
      if (settled) return;
      settled = true;
      cleanup();
      resolve3(data);
    }, "finish");
    const onEnd = /* @__PURE__ */ __name(() => {
      finish();
    }, "onEnd");
    const onError = /* @__PURE__ */ __name((err) => {
      if (settled) return;
      settled = true;
      cleanup();
      reject(err);
    }, "onError");
    const cleanup = /* @__PURE__ */ __name(() => {
      if (pipedInputTimerId) {
        clearTimeout(pipedInputTimerId);
        pipedInputTimerId = null;
      }
      process.stdin.removeListener("readable", onReadable);
      process.stdin.removeListener("end", onEnd);
      process.stdin.removeListener("error", onError);
    }, "cleanup");
    process.stdin.on("readable", onReadable);
    process.stdin.on("end", onEnd);
    process.stdin.on("error", onError);
  });
}
__name(readStdin, "readStdin");

// packages/cli/src/utils/relaunch.ts
init_esbuild_shims();
import { spawn } from "node:child_process";
async function relaunchOnExitCode(runner, options) {
  while (true) {
    try {
      const exitCode = await runner();
      if (exitCode === UPDATE_RELAUNCH_EXIT_CODE && options?.onUpdateRelaunch) {
        const updatedExitCode = await options.onUpdateRelaunch(true);
        process.exit(updatedExitCode);
      }
      if (exitCode !== RELAUNCH_EXIT_CODE) {
        process.exit(exitCode);
      }
    } catch (error) {
      process.stdin.resume();
      writeStderrLine("Fatal error: Failed to relaunch the CLI process.");
      writeStderrLine(error instanceof Error ? error.message : String(error));
      process.exit(1);
    }
  }
}
__name(relaunchOnExitCode, "relaunchOnExitCode");
async function relaunchAppInChildProcess(additionalNodeArgs, additionalScriptArgs, options) {
  if (process.env["QWEN_CODE_NO_RELAUNCH"]) {
    return;
  }
  const runner = /* @__PURE__ */ __name(() => {
    let updateOnExitRequested = false;
    const script = process.argv[1];
    const scriptArgs = process.argv.slice(2);
    const nodeArgs = [
      ...process.execArgv,
      ...additionalNodeArgs,
      script,
      ...additionalScriptArgs,
      ...scriptArgs
    ];
    const newEnv = {
      ...process.env,
      ...options?.childEnv,
      QWEN_CODE_NO_RELAUNCH: "true"
    };
    if (newEnv["QWEN_CODE_SCRUB_ELECTRON_RUN_AS_NODE"] === "1") {
      newEnv["ELECTRON_RUN_AS_NODE"] = "1";
    }
    process.stdin.pause();
    const child = spawn(process.execPath, nodeArgs, {
      stdio: ["inherit", "inherit", "inherit", "ipc"],
      env: newEnv
    });
    child.on("message", (message) => {
      if (typeof message === "object" && message !== null && "type" in message && message.type === UPDATE_ON_EXIT_MESSAGE) {
        updateOnExitRequested = true;
      }
    });
    try {
      options?.afterSpawn?.();
    } catch (err) {
      child.kill();
      throw err;
    }
    return new Promise((resolve3, reject) => {
      child.on("error", reject);
      child.on("close", (code) => {
        process.stdin.resume();
        const exitCode = code ?? 1;
        if (exitCode === 0 && updateOnExitRequested && options?.onUpdateRelaunch) {
          updateOnExitRequested = false;
          void Promise.resolve(options.onUpdateRelaunch(false)).then(
            (updatedExitCode) => resolve3(updatedExitCode),
            reject
          );
          return;
        }
        resolve3(exitCode);
      });
    });
  }, "runner");
  await relaunchOnExitCode(runner, options);
}
__name(relaunchAppInChildProcess, "relaunchAppInChildProcess");

// packages/cli/src/utils/sandbox.ts
init_esbuild_shims();
var import_shell_quote = __toESM(require_shell_quote(), 1);
import { exec, execSync, spawn as spawn2 } from "node:child_process";
import os2 from "node:os";
import path6 from "node:path";
import fs4 from "node:fs";
import { promisify } from "node:util";
import { randomBytes } from "node:crypto";

// packages/cli/src/utils/sandboxImageName.ts
init_esbuild_shims();
function parseSandboxImageName(image) {
  const imageWithoutDigest = image.split("@")[0] ?? image;
  const lastSlash = imageWithoutDigest.lastIndexOf("/");
  const lastColon = imageWithoutDigest.lastIndexOf(":");
  const hasTag = lastColon > lastSlash;
  const fullName = hasTag ? imageWithoutDigest.slice(0, lastColon) : imageWithoutDigest;
  const tag = hasTag ? imageWithoutDigest.slice(lastColon + 1) : void 0;
  const name = fullName.split("/").at(-1) || "unknown-image";
  return tag ? `${name}-${tag}` : name;
}
__name(parseSandboxImageName, "parseSandboxImageName");

// packages/cli/src/utils/sandbox-path.ts
init_esbuild_shims();
import path5 from "node:path";
function isContainerPathWithinWorkdir(containerWorkdir, containerPath) {
  const normalize = /* @__PURE__ */ __name((value) => {
    const normalized = path5.posix.normalize(value.replace(/\\/g, "/")).replace(/\/+$/, "").toLowerCase();
    return normalized || "/";
  }, "normalize");
  const normalizedWorkdir = normalize(containerWorkdir);
  const normalizedPath = normalize(containerPath);
  if (normalizedWorkdir === "/") {
    return normalizedPath.startsWith("/");
  }
  return normalizedPath === normalizedWorkdir || normalizedPath.startsWith(`${normalizedWorkdir}/`);
}
__name(isContainerPathWithinWorkdir, "isContainerPathWithinWorkdir");

// packages/cli/src/utils/sandboxMounts.ts
init_esbuild_shims();
import os from "node:os";
function parseSandboxMountSpec(rawMount, platform = os.platform()) {
  const mount = rawMount.trim();
  const mountSeparator = platform === "win32" && /^[A-Za-z]:[\\/]/.test(mount) ? mount.indexOf(":", 2) : mount.indexOf(":");
  const from = mountSeparator === -1 ? mount : mount.slice(0, mountSeparator);
  const rest = mountSeparator === -1 ? "" : mount.slice(mountSeparator + 1);
  const [toPart, optsPart] = rest.split(":");
  return {
    from,
    to: toPart || from,
    opts: optsPart || "ro"
  };
}
__name(parseSandboxMountSpec, "parseSandboxMountSpec");

// packages/cli/src/utils/sandbox.ts
var execAsync = promisify(exec);
function getContainerPath(hostPath) {
  if (os2.platform() !== "win32") {
    return hostPath;
  }
  const withForwardSlashes = hostPath.replace(/\\/g, "/");
  const match = withForwardSlashes.match(/^([A-Z]):\/(.*)/i);
  if (match) {
    return `/${match[1].toLowerCase()}/${match[2]}`;
  }
  return hostPath;
}
__name(getContainerPath, "getContainerPath");
function ensureDirectoryAndGetRealPath(dir) {
  if (!fs4.existsSync(dir)) {
    fs4.mkdirSync(dir, { recursive: true });
  }
  return fs4.realpathSync(dir);
}
__name(ensureDirectoryAndGetRealPath, "ensureDirectoryAndGetRealPath");
var LOCAL_DEV_SANDBOX_IMAGE_NAME = "qwen-code-sandbox";
var SANDBOX_NETWORK_NAME = "qwen-code-sandbox";
var SANDBOX_PROXY_NAME = "qwen-code-sandbox-proxy";
var BUILTIN_SEATBELT_PROFILES = [
  "permissive-open",
  "permissive-closed",
  "permissive-proxied",
  "restrictive-open",
  "restrictive-closed",
  "restrictive-proxied"
];
function getSandboxPassthroughEnvArgs(env = process.env) {
  return [
    "QWEN_DEBUG_LOG_FILE",
    "QWEN_CODE_LEGACY_MCP_BLOCKING",
    SKIP_UPDATE_CHECK_ENV_VAR,
    CUSTOM_SANDBOX_IMAGE_ENV_VAR,
    HOST_UPDATE_RELAUNCH_ENV_VAR
  ].flatMap(
    (envVar) => env[envVar] === void 0 ? [] : ["--env", `${envVar}=${env[envVar]}`]
  );
}
__name(getSandboxPassthroughEnvArgs, "getSandboxPassthroughEnvArgs");
function resolveSeatbeltProfileFile(profile, importMetaUrl = import.meta.url) {
  if (!BUILTIN_SEATBELT_PROFILES.includes(profile)) {
    return path6.join(SETTINGS_DIRECTORY_NAME, `sandbox-macos-${profile}.sb`);
  }
  return path6.join(
    resolveBundleDir(importMetaUrl),
    `sandbox-macos-${profile}.sb`
  );
}
__name(resolveSeatbeltProfileFile, "resolveSeatbeltProfileFile");
async function shouldUseCurrentUserInSandbox() {
  const envVar = process.env["SANDBOX_SET_UID_GID"]?.toLowerCase().trim();
  if (envVar === "1" || envVar === "true") {
    return true;
  }
  if (envVar === "0" || envVar === "false") {
    return false;
  }
  if (os2.platform() === "linux") {
    const debugEnv = [process.env["DEBUG"], process.env["DEBUG_MODE"]].some(
      (v) => v === "true" || v === "1"
    );
    if (debugEnv) {
      writeStderrLine(
        "INFO: Using current user UID/GID in Linux sandbox. Set SANDBOX_SET_UID_GID=false to disable."
      );
    }
    return true;
  }
  return false;
}
__name(shouldUseCurrentUserInSandbox, "shouldUseCurrentUserInSandbox");
function ports() {
  return (process.env["SANDBOX_PORTS"] ?? "").split(",").filter((p) => p.trim()).map((p) => p.trim());
}
__name(ports, "ports");
function entrypoint(workdir, cliArgs) {
  const isWindows = os2.platform() === "win32";
  const containerWorkdir = getContainerPath(workdir);
  const shellCmds = [];
  const pathSeparator = isWindows ? ";" : ":";
  let pathSuffix = "";
  if (process.env["PATH"]) {
    const paths = process.env["PATH"].split(pathSeparator);
    for (const p of paths) {
      const containerPath = getContainerPath(p);
      if (isContainerPathWithinWorkdir(containerWorkdir, containerPath)) {
        pathSuffix += `:${containerPath}`;
      }
    }
  }
  if (pathSuffix) {
    shellCmds.push(`export PATH="$PATH${pathSuffix}";`);
  }
  let pythonPathSuffix = "";
  if (process.env["PYTHONPATH"]) {
    const paths = process.env["PYTHONPATH"].split(pathSeparator);
    for (const p of paths) {
      const containerPath = getContainerPath(p);
      if (isContainerPathWithinWorkdir(containerWorkdir, containerPath)) {
        pythonPathSuffix += `:${containerPath}`;
      }
    }
  }
  if (pythonPathSuffix) {
    shellCmds.push(`export PYTHONPATH="$PYTHONPATH${pythonPathSuffix}";`);
  }
  const projectSandboxBashrc = path6.join(
    SETTINGS_DIRECTORY_NAME,
    "sandbox.bashrc"
  );
  if (fs4.existsSync(projectSandboxBashrc)) {
    shellCmds.push(`source ${getContainerPath(projectSandboxBashrc)};`);
  }
  ports().forEach(
    (p) => shellCmds.push(
      `socat TCP4-LISTEN:${p},bind=$(hostname -i),fork,reuseaddr TCP4:127.0.0.1:${p} 2> /dev/null &`
    )
  );
  const quotedCliArgs = cliArgs.slice(2).map((arg) => (0, import_shell_quote.quote)([arg]));
  const cliCmd = false ? process.env["DEBUG"] ? "npm run debug --" : "npm rebuild && npm run start --" : process.env["DEBUG"] ? `node --inspect-brk=0.0.0.0:${process.env["DEBUG_PORT"] || "9229"} $(which qwen)` : "qwen";
  const args = [...shellCmds, cliCmd, ...quotedCliArgs];
  return ["bash", "-c", args.join(" ")];
}
__name(entrypoint, "entrypoint");
async function start_sandbox(config, nodeArgs = [], cliConfig, cliArgs = [], childEnv) {
  if (config.command === "sandbox-exec") {
    if (process.env["BUILD_SANDBOX"]) {
      throw new FatalSandboxError(
        "Cannot BUILD_SANDBOX when using macOS Seatbelt"
      );
    }
    const profile = process.env["SEATBELT_PROFILE"] ??= "permissive-open";
    const profileFile = resolveSeatbeltProfileFile(profile);
    if (!fs4.existsSync(profileFile)) {
      throw new FatalSandboxError(
        `Missing macos seatbelt profile file '${profileFile}'`
      );
    }
    writeStderrLine(`using macos seatbelt (profile: ${profile}) ...`);
    const nodeOptions = [
      ...process.env["DEBUG"] ? ["--inspect-brk"] : [],
      ...nodeArgs
    ].join(" ");
    const qwenDir = Storage.getGlobalQwenDir();
    const runtimeDir = Storage.getRuntimeBaseDir();
    fs4.mkdirSync(qwenDir, { recursive: true });
    fs4.mkdirSync(runtimeDir, { recursive: true });
    const args2 = [
      "-D",
      `TARGET_DIR=${fs4.realpathSync(process.cwd())}`,
      "-D",
      `TMP_DIR=${fs4.realpathSync(os2.tmpdir())}`,
      "-D",
      `HOME_DIR=${fs4.realpathSync(os2.homedir())}`,
      "-D",
      `CACHE_DIR=${fs4.realpathSync(execSync(`getconf DARWIN_USER_CACHE_DIR`).toString().trim())}`,
      "-D",
      `QWEN_DIR=${fs4.realpathSync(qwenDir)}`,
      "-D",
      `RUNTIME_DIR=${fs4.realpathSync(runtimeDir)}`
    ];
    const MAX_INCLUDE_DIRS = 5;
    const targetDir = fs4.realpathSync(cliConfig?.getTargetDir() || "");
    const includedDirs = [];
    if (cliConfig) {
      const workspaceContext = cliConfig.getWorkspaceContext();
      const directories = workspaceContext.getDirectories();
      for (const dir of directories) {
        const realDir = fs4.realpathSync(dir);
        if (realDir !== targetDir) {
          includedDirs.push(realDir);
        }
      }
    }
    for (let i = 0; i < MAX_INCLUDE_DIRS; i++) {
      let dirPath = "/dev/null";
      if (i < includedDirs.length) {
        dirPath = includedDirs[i];
      }
      args2.push("-D", `INCLUDE_DIR_${i}=${dirPath}`);
    }
    const finalArgv = cliArgs;
    args2.push(
      "-f",
      profileFile,
      "sh",
      "-c",
      [
        ...process.env["QWEN_CODE_SCRUB_ELECTRON_RUN_AS_NODE"] === "1" ? ["ELECTRON_RUN_AS_NODE=1"] : [],
        `SANDBOX=sandbox-exec`,
        `NODE_OPTIONS="${nodeOptions}"`,
        ...finalArgv.map((arg) => (0, import_shell_quote.quote)([arg]))
      ].join(" ")
    );
    const proxyCommand2 = process.env["QWEN_SANDBOX_PROXY_COMMAND"];
    let proxyProcess2 = void 0;
    let sandboxProcess2 = void 0;
    const sandboxEnv = { ...process.env };
    if (proxyCommand2) {
      const proxy = process.env["HTTPS_PROXY"] || process.env["https_proxy"] || process.env["HTTP_PROXY"] || process.env["http_proxy"] || "http://localhost:8877";
      sandboxEnv["HTTPS_PROXY"] = proxy;
      sandboxEnv["https_proxy"] = proxy;
      sandboxEnv["HTTP_PROXY"] = proxy;
      sandboxEnv["http_proxy"] = proxy;
      const noProxy = process.env["NO_PROXY"] || process.env["no_proxy"];
      if (noProxy) {
        sandboxEnv["NO_PROXY"] = noProxy;
        sandboxEnv["no_proxy"] = noProxy;
      }
      proxyProcess2 = spawn2("bash", ["-c", proxyCommand2], {
        stdio: ["ignore", "pipe", "pipe"],
        detached: true
      });
      const stopProxy = /* @__PURE__ */ __name(() => {
        writeStderrLine("stopping proxy ...");
        if (proxyProcess2?.pid) {
          process.kill(-proxyProcess2.pid, "SIGTERM");
        }
      }, "stopProxy");
      process.on("exit", stopProxy);
      process.on("SIGINT", stopProxy);
      process.on("SIGTERM", stopProxy);
      proxyProcess2.stderr?.on("data", (data) => {
        writeStderrLine(data.toString());
      });
      proxyProcess2.on("close", (code, signal) => {
        if (sandboxProcess2?.pid) {
          process.kill(-sandboxProcess2.pid, "SIGTERM");
        }
        throw new FatalSandboxError(
          `Proxy command '${proxyCommand2}' exited with code ${code}, signal ${signal}`
        );
      });
      writeStderrLine("waiting for proxy to start ...");
      await execAsync(
        `until timeout 0.25 curl -s http://localhost:8877; do sleep 0.25; done`
      );
    }
    process.stdin.pause();
    sandboxProcess2 = spawn2(config.command, args2, {
      stdio: "inherit",
      ...childEnv ? { env: { ...process.env, ...childEnv } } : {}
    });
    return new Promise((resolve3, reject) => {
      sandboxProcess2?.on("error", reject);
      sandboxProcess2?.on("close", (code) => {
        process.stdin.resume();
        resolve3(code ?? 1);
      });
    });
  }
  writeStderrLine(`hopping into sandbox (command: ${config.command}) ...`);
  const gcPath = fs4.realpathSync(process.argv[1]);
  const projectSandboxDockerfile = path6.join(
    SETTINGS_DIRECTORY_NAME,
    "sandbox.Dockerfile"
  );
  const isCustomProjectSandbox = fs4.existsSync(projectSandboxDockerfile);
  const image = config.image;
  const workdir = path6.resolve(process.cwd());
  const containerWorkdir = getContainerPath(workdir);
  if (process.env["BUILD_SANDBOX"]) {
    if (!gcPath.includes("qwen-code/packages/")) {
      throw new FatalSandboxError(
        "Cannot build sandbox using installed Qwen Code binary; run `npm link ./packages/cli` under QwenCode-cli repo to switch to linked binary."
      );
    } else {
      writeStderrLine("building sandbox ...");
      const gcRoot = gcPath.split("/packages/")[0];
      let buildArgs = "";
      const projectSandboxDockerfile2 = path6.join(
        SETTINGS_DIRECTORY_NAME,
        "sandbox.Dockerfile"
      );
      if (isCustomProjectSandbox) {
        writeStderrLine(`using ${projectSandboxDockerfile2} for sandbox`);
        buildArgs += `-f ${path6.resolve(projectSandboxDockerfile2)} -i ${image}`;
      }
      execSync(
        `cd ${gcRoot} && node scripts/build_sandbox.js -s ${buildArgs}`,
        {
          stdio: "inherit",
          env: {
            ...process.env,
            QWEN_SANDBOX: config.command
            // in case sandbox is enabled via flags (see config.ts under cli package)
          }
        }
      );
    }
  }
  if (!await ensureSandboxImageIsPresent(config.command, image)) {
    const remedy = image === LOCAL_DEV_SANDBOX_IMAGE_NAME ? "Try running `npm run build:all` or `npm run build:sandbox` under the qwen-code repo to build it locally, or check the image name and your network connection." : "Please check the image name, your network connection, or notify qwen-code-dev@service.alibaba.com if the issue persists.";
    throw new FatalSandboxError(
      `Sandbox image '${image}' is missing or could not be pulled. ${remedy}`
    );
  }
  const args = ["run", "-i", "--rm", "--init", "--workdir", containerWorkdir];
  if (process.env["SANDBOX_FLAGS"]) {
    const flags = (0, import_shell_quote.parse)(process.env["SANDBOX_FLAGS"], process.env).filter(
      (f) => typeof f === "string"
    );
    args.push(...flags);
  }
  if (process.stdin.isTTY) {
    args.push("-t");
  }
  args.push("--add-host", "host.docker.internal:host-gateway");
  args.push("--volume", `${workdir}:${containerWorkdir}`);
  const userSettingsDirOnHost = getUserSettingsDir();
  const runtimeBaseDirOnHost = Storage.getRuntimeBaseDir();
  const userSettingsDirRealPath = ensureDirectoryAndGetRealPath(
    userSettingsDirOnHost
  );
  const runtimeBaseDirRealPath = ensureDirectoryAndGetRealPath(runtimeBaseDirOnHost);
  const userSettingsDirInSandbox = getContainerPath(
    `/home/node/${SETTINGS_DIRECTORY_NAME}`
  );
  const userSettingsDirContainerPath = getContainerPath(
    userSettingsDirRealPath
  );
  const runtimeBaseDirContainerPath = getContainerPath(runtimeBaseDirRealPath);
  const runtimeCoveredByUserSettings = isSubpath(
    userSettingsDirRealPath,
    runtimeBaseDirRealPath
  );
  const userSettingsCoveredByRuntime = isSubpath(
    runtimeBaseDirRealPath,
    userSettingsDirRealPath
  );
  const runtimeSameAsUserSettings = runtimeCoveredByUserSettings && userSettingsCoveredByRuntime;
  args.push(
    "--volume",
    `${userSettingsDirRealPath}:${userSettingsDirInSandbox}`
  );
  if ((!userSettingsCoveredByRuntime || runtimeSameAsUserSettings) && userSettingsDirInSandbox !== userSettingsDirContainerPath) {
    args.push(
      "--volume",
      `${userSettingsDirRealPath}:${userSettingsDirContainerPath}`
    );
  }
  args.push("--env", `QWEN_HOME=${userSettingsDirContainerPath}`);
  if (!runtimeCoveredByUserSettings) {
    args.push(
      "--volume",
      `${runtimeBaseDirRealPath}:${runtimeBaseDirContainerPath}`
    );
  }
  if (!runtimeSameAsUserSettings) {
    args.push("--env", `QWEN_RUNTIME_DIR=${runtimeBaseDirContainerPath}`);
  }
  args.push("--volume", `${os2.tmpdir()}:${getContainerPath(os2.tmpdir())}`);
  const gcloudConfigDir = path6.join(os2.homedir(), ".config", "gcloud");
  if (fs4.existsSync(gcloudConfigDir)) {
    args.push(
      "--volume",
      `${gcloudConfigDir}:${getContainerPath(gcloudConfigDir)}:ro`
    );
  }
  if (process.env["GOOGLE_APPLICATION_CREDENTIALS"]) {
    const adcFile = process.env["GOOGLE_APPLICATION_CREDENTIALS"];
    if (fs4.existsSync(adcFile)) {
      args.push("--volume", `${adcFile}:${getContainerPath(adcFile)}:ro`);
      args.push(
        "--env",
        `GOOGLE_APPLICATION_CREDENTIALS=${getContainerPath(adcFile)}`
      );
    }
  }
  if (process.env["SANDBOX_MOUNTS"]) {
    for (let mount of process.env["SANDBOX_MOUNTS"].split(",")) {
      if (mount.trim()) {
        const { from, to, opts } = parseSandboxMountSpec(mount);
        mount = `${from}:${to}:${opts}`;
        if (!path6.isAbsolute(from)) {
          throw new FatalSandboxError(
            `Path '${from}' listed in SANDBOX_MOUNTS must be absolute`
          );
        }
        if (!fs4.existsSync(from)) {
          throw new FatalSandboxError(
            `Missing mount path '${from}' listed in SANDBOX_MOUNTS`
          );
        }
        writeStderrLine(`SANDBOX_MOUNTS: ${from} -> ${to} (${opts})`);
        args.push("--volume", mount);
      }
    }
  }
  ports().forEach((p) => args.push("--publish", `${p}:${p}`));
  if (process.env["DEBUG"]) {
    const debugPort = process.env["DEBUG_PORT"] || "9229";
    args.push(`--publish`, `${debugPort}:${debugPort}`);
  }
  const proxyCommand = process.env["QWEN_SANDBOX_PROXY_COMMAND"];
  if (proxyCommand) {
    let proxy = process.env["HTTPS_PROXY"] || process.env["https_proxy"] || process.env["HTTP_PROXY"] || process.env["http_proxy"] || "http://localhost:8877";
    proxy = proxy.replace("localhost", SANDBOX_PROXY_NAME);
    if (proxy) {
      args.push("--env", `HTTPS_PROXY=${proxy}`);
      args.push("--env", `https_proxy=${proxy}`);
      args.push("--env", `HTTP_PROXY=${proxy}`);
      args.push("--env", `http_proxy=${proxy}`);
    }
    const noProxy = process.env["NO_PROXY"] || process.env["no_proxy"];
    if (noProxy) {
      args.push("--env", `NO_PROXY=${noProxy}`);
      args.push("--env", `no_proxy=${noProxy}`);
    }
    if (proxy) {
      execSync(
        `${config.command} network inspect ${SANDBOX_NETWORK_NAME} || ${config.command} network create --internal ${SANDBOX_NETWORK_NAME}`
      );
      args.push("--network", SANDBOX_NETWORK_NAME);
      if (proxyCommand) {
        execSync(
          `${config.command} network inspect ${SANDBOX_PROXY_NAME} || ${config.command} network create ${SANDBOX_PROXY_NAME}`
        );
      }
    }
  }
  const imageName = parseSandboxImageName(image);
  const isIntegrationTest = process.env["QWEN_CODE_INTEGRATION_TEST"] === "true";
  let containerName;
  if (isIntegrationTest) {
    containerName = `qwen-code-integration-test-${randomBytes(4).toString(
      "hex"
    )}`;
    writeStderrLine(`ContainerName: ${containerName}`);
  } else {
    let index = 0;
    const containerNameCheck = execSync(
      `${config.command} ps -a --format "{{.Names}}"`
    ).toString().trim();
    while (containerNameCheck.includes(`${imageName}-${index}`)) {
      index++;
    }
    containerName = `${imageName}-${index}`;
    writeStderrLine(`ContainerName (regular): ${containerName}`);
  }
  args.push("--name", containerName, "--hostname", containerName);
  if (process.env["QWEN_CODE_TEST_VAR"]) {
    args.push(
      "--env",
      `QWEN_CODE_TEST_VAR=${process.env["QWEN_CODE_TEST_VAR"]}`
    );
  }
  args.push(...getSandboxPassthroughEnvArgs());
  if (process.env["QWEN_CODE_MCP_APPROVALS_PATH"]) {
    args.push(
      "--env",
      `QWEN_CODE_MCP_APPROVALS_PATH=${getContainerPath(
        process.env["QWEN_CODE_MCP_APPROVALS_PATH"]
      )}`
    );
  }
  if (process.env["GEMINI_API_KEY"]) {
    args.push("--env", `GEMINI_API_KEY=${process.env["GEMINI_API_KEY"]}`);
  }
  if (process.env["GOOGLE_API_KEY"]) {
    args.push("--env", `GOOGLE_API_KEY=${process.env["GOOGLE_API_KEY"]}`);
  }
  if (process.env["OPENAI_API_KEY"]) {
    args.push("--env", `OPENAI_API_KEY=${process.env["OPENAI_API_KEY"]}`);
  }
  if (process.env["OPENAI_BASE_URL"]) {
    args.push("--env", `OPENAI_BASE_URL=${process.env["OPENAI_BASE_URL"]}`);
  }
  if (process.env["OPENAI_MODEL"]) {
    args.push("--env", `OPENAI_MODEL=${process.env["OPENAI_MODEL"]}`);
  }
  if (process.env["GOOGLE_GENAI_USE_VERTEXAI"]) {
    args.push(
      "--env",
      `GOOGLE_GENAI_USE_VERTEXAI=${process.env["GOOGLE_GENAI_USE_VERTEXAI"]}`
    );
  }
  if (process.env["GOOGLE_GENAI_USE_GCA"]) {
    args.push(
      "--env",
      `GOOGLE_GENAI_USE_GCA=${process.env["GOOGLE_GENAI_USE_GCA"]}`
    );
  }
  if (process.env["GOOGLE_CLOUD_PROJECT"]) {
    args.push(
      "--env",
      `GOOGLE_CLOUD_PROJECT=${process.env["GOOGLE_CLOUD_PROJECT"]}`
    );
  }
  if (process.env["GOOGLE_CLOUD_LOCATION"]) {
    args.push(
      "--env",
      `GOOGLE_CLOUD_LOCATION=${process.env["GOOGLE_CLOUD_LOCATION"]}`
    );
  }
  if (process.env["GEMINI_MODEL"]) {
    args.push("--env", `GEMINI_MODEL=${process.env["GEMINI_MODEL"]}`);
  }
  if (process.env["TERM"]) {
    args.push("--env", `TERM=${process.env["TERM"]}`);
  }
  if (process.env["COLORTERM"]) {
    args.push("--env", `COLORTERM=${process.env["COLORTERM"]}`);
  }
  for (const envVar of [
    "QWEN_CODE_IDE_SERVER_PORT",
    "QWEN_CODE_IDE_WORKSPACE_PATH",
    "TERM_PROGRAM"
  ]) {
    if (process.env[envVar]) {
      args.push("--env", `${envVar}=${process.env[envVar]}`);
    }
  }
  const virtualEnv = process.env["VIRTUAL_ENV"];
  if (virtualEnv && isContainerPathWithinWorkdir(
    getContainerPath(workdir),
    getContainerPath(virtualEnv)
  )) {
    const sandboxVenvPath = path6.resolve(
      SETTINGS_DIRECTORY_NAME,
      "sandbox.venv"
    );
    if (!fs4.existsSync(sandboxVenvPath)) {
      fs4.mkdirSync(sandboxVenvPath, { recursive: true });
    }
    args.push("--volume", `${sandboxVenvPath}:${getContainerPath(virtualEnv)}`);
    args.push("--env", `VIRTUAL_ENV=${getContainerPath(virtualEnv)}`);
  }
  if (process.env["SANDBOX_ENV"]) {
    for (let env of process.env["SANDBOX_ENV"].split(",")) {
      if (env = env.trim()) {
        if (env.includes("=")) {
          writeStderrLine(`SANDBOX_ENV: ${env}`);
          args.push("--env", env);
        } else {
          throw new FatalSandboxError(
            "SANDBOX_ENV must be a comma-separated list of key=value pairs"
          );
        }
      }
    }
  }
  for (const name of Object.keys(childEnv ?? {})) {
    args.push("--env", name);
  }
  const existingNodeOptions = process.env["NODE_OPTIONS"] || "";
  const allNodeOptions = [
    ...existingNodeOptions ? [existingNodeOptions] : [],
    ...nodeArgs
  ].join(" ");
  if (allNodeOptions.length > 0) {
    args.push("--env", `NODE_OPTIONS="${allNodeOptions}"`);
  }
  args.push("--env", `SANDBOX=${containerName}`);
  if (config.command === "podman") {
    const emptyAuthFilePath = path6.join(os2.tmpdir(), "empty_auth.json");
    fs4.writeFileSync(emptyAuthFilePath, "{}", "utf-8");
    args.push("--authfile", emptyAuthFilePath);
  }
  let userFlag = "";
  const finalEntrypoint = entrypoint(workdir, cliArgs);
  const useCurrentUser = await shouldUseCurrentUserInSandbox();
  if (useCurrentUser) {
    args.push("--user", "root");
    const uid = execSync("id -u").toString().trim();
    const gid = execSync("id -g").toString().trim();
    const username = "qwen";
    const homeDir = getContainerPath(os2.homedir());
    const setupUserCommands = [
      // Use -f with groupadd to avoid errors if the group already exists.
      `groupadd -f -g ${gid} ${username}`,
      // Create user only if it doesn't exist. Use -o for non-unique UID.
      `id -u ${username} &>/dev/null || useradd -o -u ${uid} -g ${gid} -d ${homeDir} -s /bin/bash ${username}`
    ].join(" && ");
    const originalCommand = finalEntrypoint[2];
    const escapedOriginalCommand = originalCommand.replace(/'/g, "'\\''");
    const suCommand = `su -p ${username} -c '${escapedOriginalCommand}'`;
    finalEntrypoint[2] = `${setupUserCommands} && ${suCommand}`;
    userFlag = `--user ${uid}:${gid}`;
    args.push("--env", `HOME=${os2.homedir()}`);
  } else if (isIntegrationTest) {
    args.push("--user", "root");
    userFlag = "--user root";
  }
  args.push(image);
  args.push(...finalEntrypoint);
  let proxyProcess = void 0;
  let sandboxProcess = void 0;
  if (proxyCommand) {
    const proxyContainerCommand = `${config.command} run --rm --init ${userFlag} --name ${SANDBOX_PROXY_NAME} --network ${SANDBOX_PROXY_NAME} -p 8877:8877 -v ${process.cwd()}:${workdir} --workdir ${workdir} ${image} ${proxyCommand}`;
    const isWindows = os2.platform() === "win32";
    const proxyShell = isWindows ? "cmd.exe" : "bash";
    const proxyShellArgs = isWindows ? ["/c", proxyContainerCommand] : ["-c", proxyContainerCommand];
    proxyProcess = spawn2(proxyShell, proxyShellArgs, {
      stdio: ["ignore", "pipe", "pipe"],
      detached: true
    });
    const stopProxy = /* @__PURE__ */ __name(() => {
      writeStderrLine("stopping proxy container ...");
      execSync(`${config.command} rm -f ${SANDBOX_PROXY_NAME}`);
    }, "stopProxy");
    process.on("exit", stopProxy);
    process.on("SIGINT", stopProxy);
    process.on("SIGTERM", stopProxy);
    proxyProcess.stderr?.on("data", (data) => {
      writeStderrLine(data.toString().trim());
    });
    proxyProcess.on("close", (code, signal) => {
      if (sandboxProcess?.pid) {
        process.kill(-sandboxProcess.pid, "SIGTERM");
      }
      throw new FatalSandboxError(
        `Proxy container command '${proxyContainerCommand}' exited with code ${code}, signal ${signal}`
      );
    });
    writeStderrLine("waiting for proxy to start ...");
    await execAsync(
      `until timeout 0.25 curl -s http://localhost:8877; do sleep 0.25; done`
    );
    await execAsync(
      `${config.command} network connect ${SANDBOX_NETWORK_NAME} ${SANDBOX_PROXY_NAME}`
    );
  }
  process.stdin.pause();
  sandboxProcess = spawn2(config.command, args, {
    stdio: "inherit",
    ...childEnv ? { env: { ...process.env, ...childEnv } } : {}
  });
  return new Promise((resolve3, reject) => {
    sandboxProcess.on("error", (err) => {
      writeStderrLine(`Sandbox process error: ${err}`);
      reject(err);
    });
    sandboxProcess?.on("close", (code, signal) => {
      process.stdin.resume();
      if (code !== 0 && code !== null) {
        writeStderrLine(
          `Sandbox process exited with code: ${code}, signal: ${signal}`
        );
      }
      resolve3(code ?? 1);
    });
  });
}
__name(start_sandbox, "start_sandbox");
async function imageExists(sandbox, image) {
  return new Promise((resolve3) => {
    const args = ["images", "-q", image];
    const checkProcess = spawn2(sandbox, args);
    let stdoutData = "";
    if (checkProcess.stdout) {
      checkProcess.stdout.on("data", (data) => {
        stdoutData += data.toString();
      });
    }
    checkProcess.on("error", (err) => {
      writeStderrLine(
        `Failed to start '${sandbox}' command for image check: ${err.message}`
      );
      resolve3(false);
    });
    checkProcess.on("close", () => {
      resolve3(stdoutData.trim() !== "");
    });
  });
}
__name(imageExists, "imageExists");
async function pullImage(sandbox, image) {
  writeStderrLine(`Attempting to pull image ${image} using ${sandbox}...`);
  return new Promise((resolve3) => {
    const args = ["pull", image];
    const pullProcess = spawn2(sandbox, args, { stdio: "pipe" });
    let stderrData = "";
    const onStdoutData = /* @__PURE__ */ __name((data) => {
      writeStderrLine(data.toString().trim());
    }, "onStdoutData");
    const onStderrData = /* @__PURE__ */ __name((data) => {
      stderrData += data.toString();
      writeStderrLine(data.toString().trim());
    }, "onStderrData");
    const onError = /* @__PURE__ */ __name((err) => {
      writeStderrLine(
        `Failed to start '${sandbox} pull ${image}' command: ${err.message}`
      );
      cleanup();
      resolve3(false);
    }, "onError");
    const onClose = /* @__PURE__ */ __name((code) => {
      if (code === 0) {
        writeStderrLine(`Successfully pulled image ${image}.`);
        cleanup();
        resolve3(true);
      } else {
        writeStderrLine(
          `Failed to pull image ${image}. '${sandbox} pull ${image}' exited with code ${code}.`
        );
        if (stderrData.trim()) {
        }
        cleanup();
        resolve3(false);
      }
    }, "onClose");
    const cleanup = /* @__PURE__ */ __name(() => {
      if (pullProcess.stdout) {
        pullProcess.stdout.removeListener("data", onStdoutData);
      }
      if (pullProcess.stderr) {
        pullProcess.stderr.removeListener("data", onStderrData);
      }
      pullProcess.removeListener("error", onError);
      pullProcess.removeListener("close", onClose);
      if (pullProcess.connected) {
        pullProcess.disconnect();
      }
    }, "cleanup");
    if (pullProcess.stdout) {
      pullProcess.stdout.on("data", onStdoutData);
    }
    if (pullProcess.stderr) {
      pullProcess.stderr.on("data", onStderrData);
    }
    pullProcess.on("error", onError);
    pullProcess.on("close", onClose);
  });
}
__name(pullImage, "pullImage");
async function ensureSandboxImageIsPresent(sandbox, image) {
  writeStderrLine(`Checking for sandbox image: ${image}`);
  if (await imageExists(sandbox, image)) {
    writeStderrLine(`Sandbox image ${image} found locally.`);
    return true;
  }
  writeStderrLine(`Sandbox image ${image} not found locally.`);
  if (image === LOCAL_DEV_SANDBOX_IMAGE_NAME) {
    return false;
  }
  if (await pullImage(sandbox, image)) {
    if (await imageExists(sandbox, image)) {
      writeStderrLine(`Sandbox image ${image} is now available after pulling.`);
      return true;
    } else {
      writeStderrLine(
        `Sandbox image ${image} still not found after a pull attempt. This might indicate an issue with the image name or registry, or the pull command reported success but failed to make the image available.`
      );
      return false;
    }
  }
  writeStderrLine(
    `Failed to obtain sandbox image ${image} after check and pull attempt.`
  );
  return false;
}
__name(ensureSandboxImageIsPresent, "ensureSandboxImageIsPresent");

// packages/cli/src/utils/startupWarnings.ts
init_esbuild_shims();
import fs5 from "node:fs/promises";
import os3 from "node:os";
import { join as pathJoin } from "node:path";
var warningsFilePath = pathJoin(os3.tmpdir(), "qwen-code-warnings.txt");
async function getStartupWarnings() {
  try {
    await fs5.access(warningsFilePath);
    const warningsContent = await fs5.readFile(warningsFilePath, "utf-8");
    const warnings = warningsContent.split("\n").filter((line) => line.trim() !== "");
    try {
      await fs5.unlink(warningsFilePath);
    } catch {
      warnings.push("Warning: Could not delete temporary warnings file.");
    }
    return warnings;
  } catch (err) {
    if (err instanceof Error && "code" in err && err.code === "ENOENT") {
      return [];
    }
    return [`Error checking/reading warnings file: ${getErrorMessage(err)}`];
  }
}
__name(getStartupWarnings, "getStartupWarnings");

// packages/cli/src/utils/userStartupWarnings.ts
init_esbuild_shims();
import fs6 from "node:fs/promises";
import path7 from "node:path";
var rootDirectoryCheck = {
  id: "root-directory",
  check: /* @__PURE__ */ __name(async (options) => {
    try {
      const workspaceRealPath = await fs6.realpath(options.workspaceRoot);
      const errorMessage = "Warning: You are running Qwen Code in the root directory. Your entire folder structure will be used for context. It is strongly recommended to run in a project-specific directory.";
      if (path7.dirname(workspaceRealPath) === workspaceRealPath) {
        return errorMessage;
      }
      return null;
    } catch (_err) {
      return "Could not verify the current directory due to a file system error.";
    }
  }, "check")
};
var ripgrepAvailabilityCheck = {
  id: "ripgrep-availability",
  check: /* @__PURE__ */ __name(async (options) => {
    if (!options.useRipgrep) {
      return null;
    }
    try {
      const isAvailable = await canUseRipgrep(options.useBuiltinRipgrep);
      if (!isAvailable) {
        return "Ripgrep not available: Please install ripgrep globally to enable faster file content search. Falling back to built-in grep.";
      }
      return null;
    } catch (error) {
      return `Ripgrep not available: ${error instanceof Error ? error.message : "Unknown error"}. Falling back to built-in grep.`;
    }
  }, "check")
};
var WARNING_CHECKS = [
  rootDirectoryCheck,
  ripgrepAvailabilityCheck
];
async function getUserStartupWarnings(options) {
  const results = await Promise.all(
    WARNING_CHECKS.map((check) => check.check(options))
  );
  return results.filter((msg) => msg !== null);
}
__name(getUserStartupWarnings, "getUserStartupWarnings");

// packages/cli/src/utils/warningHandler.ts
init_esbuild_shims();
var SUPPRESSED_WARNINGS = [
  /MaxListenersExceededWarning.*AbortSignal/
];
function isSuppressed(warning) {
  const text = `${warning.name}: ${warning.message}`;
  return SUPPRESSED_WARNINGS.some((re) => re.test(text));
}
__name(isSuppressed, "isSuppressed");
function isDebugMode2() {
  if (false) return true;
  const truthy = /* @__PURE__ */ __name((v) => !!v && v !== "0" && v.toLowerCase() !== "false", "truthy");
  return truthy(process.env["DEBUG"]) || truthy(process.env["QWEN_DEBUG"]);
}
__name(isDebugMode2, "isDebugMode");
var installedHandler = null;
function initializeWarningHandler() {
  if (installedHandler) return;
  const priorListeners = [...process.listeners("warning")];
  installedHandler = /* @__PURE__ */ __name((warning) => {
    if (!isDebugMode2() && isSuppressed(warning)) return;
    for (const fn of priorListeners) {
      try {
        fn(warning);
      } catch {
      }
    }
  }, "installedHandler");
  process.removeAllListeners("warning");
  process.on("warning", installedHandler);
}
__name(initializeWarningHandler, "initializeWarningHandler");

// packages/cli/src/gemini.tsx
var debugLogger5 = createDebugLogger("STARTUP");
function clearCorruptionEnvVars() {
  delete process.env[ENV_CORRUPTED_PATH];
  delete process.env[ENV_WAS_RECOVERED];
}
__name(clearCorruptionEnvVars, "clearCorruptionEnvVars");
function validateDnsResolutionOrder(order) {
  const defaultValue = "ipv4first";
  if (order === void 0) {
    return defaultValue;
  }
  if (order === "ipv4first" || order === "verbatim") {
    return order;
  }
  writeStderrLine(
    `Invalid value for dnsResolutionOrder in settings: "${order}". Using default "${defaultValue}".`
  );
  return defaultValue;
}
__name(validateDnsResolutionOrder, "validateDnsResolutionOrder");
function getNodeMemoryArgs(isDebugMode3) {
  const totalMemoryMB = os4.totalmem() / (1024 * 1024);
  const heapStats = v8.getHeapStatistics();
  const currentMaxOldSpaceSizeMb = Math.floor(
    heapStats.heap_size_limit / 1024 / 1024
  );
  const targetMaxOldSpaceSizeInMB = Math.floor(totalMemoryMB * 0.5);
  if (isDebugMode3) {
    writeStderrLine(
      `Current heap size ${currentMaxOldSpaceSizeMb.toFixed(2)} MB`
    );
  }
  if (process.env["QWEN_CODE_NO_RELAUNCH"]) {
    return [];
  }
  if (targetMaxOldSpaceSizeInMB > currentMaxOldSpaceSizeMb) {
    if (isDebugMode3) {
      writeStderrLine(
        `Need to relaunch with more memory: ${targetMaxOldSpaceSizeInMB.toFixed(2)} MB`
      );
    }
    return [`--max-old-space-size=${targetMaxOldSpaceSizeInMB}`];
  }
  return [];
}
__name(getNodeMemoryArgs, "getNodeMemoryArgs");
var uncaughtExceptionHandler;
function setupUncaughtExceptionHandler(config) {
  process.removeListener("uncaughtException", handleUncaughtException);
  if (uncaughtExceptionHandler) {
    process.removeListener("uncaughtException", uncaughtExceptionHandler);
  }
  uncaughtExceptionHandler = /* @__PURE__ */ __name((rawError) => {
    if (isExpectedPtyRaceError(rawError)) {
      return;
    }
    const error = rawError instanceof Error ? rawError : new Error(String(rawError));
    const timestamp = (/* @__PURE__ */ new Date()).toISOString();
    const line = `${timestamp} [ERROR] [STARTUP] [UNCAUGHT_EXCEPTION] ${error.message}
${error.stack ?? ""}
`;
    let logged = false;
    try {
      const logPath = Storage.getDebugLogPath(config.getSessionId());
      fs7.mkdirSync(path8.dirname(logPath), { recursive: true });
      fs7.appendFileSync(logPath, line, "utf8");
      logged = true;
    } catch {
    }
    if (process.stdout.isTTY) {
      try {
        process.stdout.write("\x1B[?1049l");
        process.stdout.write("\x1B[?25h");
      } catch {
      }
    }
    writeStderrLineSafe(
      `
Fatal: uncaught exception${logged ? " (logged to debug file)" : ""}
${sanitizeTerminalText(error.stack ?? error.message)}`
    );
    process.exit(1);
  }, "uncaughtExceptionHandler");
  process.on("uncaughtException", uncaughtExceptionHandler);
}
__name(setupUncaughtExceptionHandler, "setupUncaughtExceptionHandler");
function setupUnhandledRejectionHandler() {
  let unhandledRejectionOccurred = false;
  process.on("unhandledRejection", (reason, _promise) => {
    const errorMessage = `=========================================
This is an unexpected error. Please file a bug report using the /bug tool.
CRITICAL: Unhandled Promise Rejection!
=========================================
Reason: ${reason}${reason instanceof Error && reason.stack ? `
Stack trace:
${reason.stack}` : ""}`;
    debugLogger5.error(errorMessage);
    appEvents.emit("log-error" /* LogError */, errorMessage);
    if (!unhandledRejectionOccurred) {
      unhandledRejectionOccurred = true;
      appEvents.emit("open-debug-console" /* OpenDebugConsole */);
    }
  });
}
__name(setupUnhandledRejectionHandler, "setupUnhandledRejectionHandler");
function getSignalExitCode(signal) {
  if (signal === "SIGINT") return 130;
  if (signal === "SIGHUP") return 129;
  return 143;
}
__name(getSignalExitCode, "getSignalExitCode");
var SIGINT_EXIT_CONFIRM_WINDOW_MS = 1e3;
var SIGINT_RERAISE_IGNORE_MS = 50;
function installInteractiveSignalHandlers(wasRaw) {
  let cleanupStarted = false;
  let lastSigintAt = 0;
  const swallowSignalDuringCleanup = /* @__PURE__ */ __name(() => {
  }, "swallowSignalDuringCleanup");
  const beginExit = /* @__PURE__ */ __name((signal) => {
    if (process.stdin.isTTY) {
      process.stdin.setRawMode(wasRaw);
    }
    if (cleanupStarted) {
      return;
    }
    cleanupStarted = true;
    process.on("SIGINT", swallowSignalDuringCleanup);
    void runExitCleanup().catch((error) => {
      debugLogger5.error(`Error during ${signal} cleanup:`, error);
    }).finally(() => {
      process.exit(getSignalExitCode(signal));
    });
  }, "beginExit");
  const handleSigterm = /* @__PURE__ */ __name(() => {
    beginExit("SIGTERM");
  }, "handleSigterm");
  const handleSighup = /* @__PURE__ */ __name(() => {
    beginExit("SIGHUP");
  }, "handleSighup");
  const handleSigint = /* @__PURE__ */ __name(() => {
    if (cleanupStarted) {
      return;
    }
    const now = Date.now();
    const sincePrevious = now - lastSigintAt;
    if (sincePrevious <= SIGINT_RERAISE_IGNORE_MS) {
      return;
    }
    if (sincePrevious <= SIGINT_EXIT_CONFIRM_WINDOW_MS) {
      beginExit("SIGINT");
      return;
    }
    lastSigintAt = now;
    writeStderrLine("Press Ctrl+C again to exit.");
  }, "handleSigint");
  process.on("SIGTERM", handleSigterm);
  process.on("SIGINT", handleSigint);
  process.on("SIGHUP", handleSighup);
  return () => {
    process.removeListener("SIGTERM", handleSigterm);
    process.removeListener("SIGINT", handleSigint);
    process.removeListener("SIGHUP", handleSighup);
  };
}
__name(installInteractiveSignalHandlers, "installInteractiveSignalHandlers");
async function main() {
  profileCheckpoint("main_entry");
  const acpStartupProfilerEnabled = isAcpStartupProfilerEnabled();
  const startupProfilerEnabled = isStartupProfilerEnabled();
  if (startupProfilerEnabled || acpStartupProfilerEnabled) {
    setStartupEventSink((name, attrs) => {
      if (startupProfilerEnabled) recordStartupEvent(name, attrs);
      if (acpStartupProfilerEnabled) recordAcpConfigStartupEvent(name);
    });
  }
  setupUnhandledRejectionHandler();
  initializeWarningHandler();
  const privateAcpParentCapability = process.env[PRIVATE_ACP_CAPABILITY_ENV];
  delete process.env[PRIVATE_ACP_CAPABILITY_ENV];
  if (process.argv.includes("--bare")) {
    process.env[QWEN_CODE_SIMPLE_ENV_VAR] = "1";
  }
  preResolveHomeEnvOverrides();
  markAcpStartup("argsParseStart");
  let argv = await parseArguments();
  markAcpStartup("argsParseEnd");
  profileCheckpoint("after_parse_arguments");
  const isAcpMode = argv.acp || argv.experimentalAcp;
  const privateAcpChildEnv = isAcpMode && privateAcpParentCapability !== void 0 ? { [PRIVATE_ACP_CAPABILITY_ENV]: privateAcpParentCapability } : void 0;
  if ((argv.acp || argv.experimentalAcp) && process.env["QWEN_CODE_SCRUB_ELECTRON_RUN_AS_NODE"] === "1") {
    delete process.env["ELECTRON_RUN_AS_NODE"];
    if (process.env["QWEN_CODE_NO_RELAUNCH"] || process.env["SANDBOX"]) {
      delete process.env["QWEN_CODE_SCRUB_ELECTRON_RUN_AS_NODE"];
    }
  }
  if (isBareMode(argv.bare)) {
    process.env[QWEN_CODE_SIMPLE_ENV_VAR] = "1";
  }
  markAcpStartup("settingsLoadStart");
  const settings = isBareMode(argv.bare) ? createMinimalSettings() : loadSettings();
  markAcpStartup("settingsLoadEnd");
  if (settings.corruptedPath) {
    process.env[ENV_CORRUPTED_PATH] = settings.corruptedPath;
    process.env[ENV_WAS_RECOVERED] = settings.wasRecovered ? "1" : "0";
  }
  await cleanupCheckpoints();
  profileCheckpoint("after_load_settings");
  const settingsWarnings = getSettingsWarnings(settings);
  for (const warning of settingsWarnings) {
    writeStderrLine(warning);
  }
  if (settings.corruptedPath) {
    writeStderrLine(
      "Warning: Settings file had invalid JSON and was reset. A copy of the corrupted file has been saved at: " + settings.corruptedPath
    );
  }
  if (argv.listExtensions) {
    await initializeI18n(
      resolveLanguageSetting(settings.merged.general?.language)
    );
    const { handleList: handleListExtensions } = await import("./list-FY6VFXMP.js");
    await handleListExtensions();
    process.exit(0);
  }
  if (argv.promptInteractive && !process.stdin.isTTY) {
    writeStderrLine(
      "Error: The --prompt-interactive flag cannot be used when input is piped from stdin."
    );
    process.exit(1);
  }
  const isDebugMode3 = isDebugMode(argv);
  dns.setDefaultResultOrder(
    validateDnsResolutionOrder(settings.merged.advanced?.dnsResolutionOrder)
  );
  const { themeManager, AUTO_THEME_NAME } = await import("./theme-manager-LCBWNHLB.js");
  themeManager.loadCustomThemes(settings.merged.ui?.customThemes);
  const configuredTheme = settings.merged.ui?.theme;
  if (configuredTheme && configuredTheme !== AUTO_THEME_NAME) {
    if (!themeManager.setActiveTheme(configuredTheme)) {
      writeStderrLine(`Warning: Theme "${configuredTheme}" not found.`);
    }
  } else {
    themeManager.setActiveTheme(AUTO_THEME_NAME);
  }
  if (!process.env["SANDBOX"]) {
    const memoryArgs = settings.merged.advanced?.autoConfigureMemory ? getNodeMemoryArgs(isDebugMode3) : [];
    const updateProjectRoot = process.cwd();
    const onUpdateRelaunch = /* @__PURE__ */ __name(async (relaunchOnFailure) => {
      await initializeI18n(
        resolveLanguageSetting(settings.merged.general?.language)
      );
      const { updateBeforeRelaunch } = await import("./update-relaunch-I3MPIRLB.js");
      const shouldRelaunch = await updateBeforeRelaunch(
        settings,
        updateProjectRoot,
        relaunchOnFailure
      );
      return shouldRelaunch ? UPDATE_COMPLETE_EXIT_CODE : 0;
    }, "onUpdateRelaunch");
    const sandboxConfig = await loadSandboxConfig(settings.merged, argv);
    const customSandboxImage = argv.sandboxImage ?? process.env["QWEN_SANDBOX_IMAGE"] ?? settings.merged.tools?.sandboxImage;
    if (sandboxConfig && sandboxConfig.command !== "sandbox-exec" && customSandboxImage) {
      process.env[CUSTOM_SANDBOX_IMAGE_ENV_VAR] = sandboxConfig.image;
    } else if (sandboxConfig && sandboxConfig.command !== "sandbox-exec") {
      const hostInstallationInfo = getInstallationInfo(updateProjectRoot, true);
      process.env[HOST_UPDATE_RELAUNCH_ENV_VAR] = String(
        Boolean(
          hostInstallationInfo.updateCommand || hostInstallationInfo.isStandalone && hostInstallationInfo.standaloneDir
        )
      );
    }
    if (sandboxConfig) {
      const partialConfig = await loadCliConfig(
        settings.merged,
        argv,
        void 0,
        [],
        // Pass separated hooks for proper source attribution
        {
          userHooks: settings.getUserHooks(),
          projectHooks: settings.getProjectHooks()
        },
        buildDisabledSkillNamesProvider(settings)
      );
      if (!settings.merged.security?.auth?.useExternal) {
        try {
          const authType = partialConfig.getModelsConfig().getCurrentAuthType();
          if (authType) {
            const err = validateAuthMethod(authType, partialConfig);
            if (err) {
              throw new Error(err);
            }
            await partialConfig.refreshAuth(authType);
          }
        } catch (err) {
          writeStderrLine(`Error authenticating: ${err}`);
          process.exit(1);
        }
      }
      const inputFormat = argv.inputFormat;
      const isAcpMode2 = argv.acp || argv.experimentalAcp;
      let stdinData = "";
      if (!process.stdin.isTTY && inputFormat !== "stream-json" && !isAcpMode2) {
        stdinData = await readStdin();
      }
      const injectStdinIntoArgs = /* @__PURE__ */ __name((args, stdinData2) => {
        const finalArgs = [...args];
        if (stdinData2) {
          const promptIndex = finalArgs.findIndex(
            (arg) => arg === "--prompt" || arg === "-p"
          );
          if (promptIndex > -1 && finalArgs.length > promptIndex + 1) {
            finalArgs[promptIndex + 1] = `${stdinData2}

${finalArgs[promptIndex + 1]}`;
          } else {
            finalArgs.push("--prompt", stdinData2);
          }
        }
        return finalArgs;
      }, "injectStdinIntoArgs");
      const injectSandboxSessionIdIntoArgs = /* @__PURE__ */ __name((args, sessionId2) => {
        const separatorIndex = args.indexOf("--");
        const cliArgs = separatorIndex < 0 ? args : args.slice(0, separatorIndex);
        const hasArg = /* @__PURE__ */ __name((names) => cliArgs.some(
          (arg) => names.some((name) => arg === name || arg.startsWith(`${name}=`))
        ), "hasArg");
        if (hasArg(["--session-id", "--sandbox-session-id"]) || hasArg(["--continue", "-c"]) || hasArg(["--resume", "-r"])) {
          return args;
        }
        const sessionArgs = ["--sandbox-session-id", sessionId2];
        if (separatorIndex < 0) {
          return [...args, ...sessionArgs];
        }
        return [...cliArgs, ...sessionArgs, ...args.slice(separatorIndex)];
      }, "injectSandboxSessionIdIntoArgs");
      const sessionId = partialConfig.getSessionId();
      const sandboxArgs = sessionId ? injectSandboxSessionIdIntoArgs(
        injectStdinIntoArgs(process.argv, stdinData),
        sessionId
      ) : injectStdinIntoArgs(process.argv, stdinData);
      await relaunchOnExitCode(
        () => start_sandbox(
          sandboxConfig,
          memoryArgs,
          partialConfig,
          sandboxArgs,
          privateAcpChildEnv
        ),
        {
          onUpdateRelaunch
        }
      );
      process.exit(0);
    } else {
      await relaunchAppInChildProcess(memoryArgs, [], {
        afterSpawn: clearCorruptionEnvVars,
        childEnv: privateAcpChildEnv,
        onUpdateRelaunch
      });
    }
  }
  if (argv.worktree !== void 0) {
    const launchCwdForPaths = process.cwd();
    const looksLikeInlineJson = /* @__PURE__ */ __name((v) => {
      const t = v.trim();
      return t.startsWith("{") || t.startsWith("[");
    }, "looksLikeInlineJson");
    const resolveIfPath = /* @__PURE__ */ __name((v) => {
      if (typeof v !== "string" || v.length === 0) return v;
      if (looksLikeInlineJson(v)) return v;
      return path8.resolve(launchCwdForPaths, v);
    }, "resolveIfPath");
    argv.mcpConfig = resolveIfPath(argv.mcpConfig);
    argv.openaiLoggingDir = resolveIfPath(argv.openaiLoggingDir);
    argv.jsonFile = resolveIfPath(argv.jsonFile);
    argv.inputFile = resolveIfPath(argv.inputFile);
    argv.telemetryOutfile = resolveIfPath(argv.telemetryOutfile);
    if (Array.isArray(argv.includeDirectories)) {
      argv.includeDirectories = argv.includeDirectories.map(
        (d) => typeof d === "string" && d.length > 0 ? path8.resolve(launchCwdForPaths, d) : d
      );
    }
    if (typeof argv.jsonSchema === "string") {
      const trimmedSchema = argv.jsonSchema.trim();
      if (trimmedSchema.startsWith("@")) {
        const rel = trimmedSchema.slice(1);
        if (rel.length > 0 && !path8.isAbsolute(rel)) {
          argv.jsonSchema = "@" + path8.resolve(launchCwdForPaths, rel);
        }
      }
    }
  }
  let startupWorktreeContext = null;
  if (argv.worktree !== void 0 && (argv.acp || argv.experimentalAcp)) {
    writeStderrLine(
      "--worktree cannot be combined with --acp / --experimental-acp. Pass the worktree path as the cwd of the ACP loadSession / newSession request instead."
    );
    process.exit(1);
  }
  {
    const startupRes = await setupStartupWorktree(argv.worktree, {
      symlinkDirectories: settings.merged.worktree?.symlinkDirectories
    });
    if (startupRes !== null) {
      if (!startupRes.ok) {
        writeStderrLine(startupRes.error);
        process.exit(1);
      }
      startupWorktreeContext = startupRes.context;
    }
  }
  if (argv.resume !== void 0) {
    Storage.setRuntimeBaseDir(
      settings.merged.advanced?.runtimeOutputDir,
      process.cwd()
    );
    let resolvedSessionId;
    if (argv.resume === "") {
      const { showResumeSessionPicker } = await import("./StandaloneSessionPicker-TBDFVCO2.js");
      resolvedSessionId = await showResumeSessionPicker();
    } else if (!isValidSessionId(argv.resume)) {
      const sessionService = new SessionService(process.cwd());
      const matches = await sessionService.findSessionsByTitle(argv.resume);
      if (matches.length === 1) {
        resolvedSessionId = matches[0].sessionId;
      } else if (matches.length > 1) {
        writeStderrLine(
          `Multiple sessions found with title "${argv.resume}". Please select one:`
        );
        const { showResumeSessionPicker } = await import("./StandaloneSessionPicker-TBDFVCO2.js");
        resolvedSessionId = await showResumeSessionPicker(
          process.cwd(),
          matches
        );
      }
    }
    if (resolvedSessionId !== void 0) {
      argv = { ...argv, resume: resolvedSessionId };
    } else if (argv.resume === "" || !isValidSessionId(argv.resume)) {
      if (argv.resume !== "") {
        writeStderrLine(`No saved session found with title "${argv.resume}".`);
        process.exit(1);
      } else {
        process.exit(0);
      }
    }
  }
  profileCheckpoint("after_sandbox_check");
  if (!isBareMode(argv.bare)) {
    initializeLlmOutputLanguage(settings.merged.general?.outputLanguage);
  }
  {
    const settingsWatcher = isBareMode(argv.bare) ? void 0 : new SettingsWatcher(settings);
    settingsWatcher?.startWatching();
    markAcpStartup("configConstructionStart");
    const config = await loadCliConfig(
      settings.merged,
      argv.acp || argv.experimentalAcp ? { ...argv, chatRecording: false } : argv,
      process.cwd(),
      argv.extensions,
      // Pass separated hooks for proper source attribution
      {
        userHooks: settings.getUserHooks(),
        projectHooks: settings.getProjectHooks()
      },
      buildDisabledSkillNamesProvider(settings),
      void 0,
      settingsWatcher
    );
    markAcpStartup("configConstructionEnd");
    profileCheckpoint("after_load_cli_config");
    if (settingsWatcher) {
      const disposeMcpHotReload = registerMcpHotReload(
        settingsWatcher,
        settings,
        config,
        config.getTopTierMcpServers()
      );
      registerCleanup(disposeMcpHotReload);
    }
    registerLspHotReload(config, registerCleanup);
    const extensionRefreshState = new ExtensionRefreshState();
    const extensionFileWatcher = isBareMode(argv.bare) || config.isSafeMode() ? void 0 : new ExtensionFileWatcher(config, void 0, extensionRefreshState);
    extensionFileWatcher?.startWatching();
    if (extensionFileWatcher) {
      const restartExtensionWatcher = /* @__PURE__ */ __name(() => extensionFileWatcher.restartWatching(), "restartExtensionWatcher");
      extensionRefreshState.on(
        "extensions-reloaded" /* ExtensionsReloaded */,
        restartExtensionWatcher
      );
      registerCleanup(() => {
        extensionRefreshState.off(
          "extensions-reloaded" /* ExtensionsReloaded */,
          restartExtensionWatcher
        );
        extensionFileWatcher.stopWatching();
      });
    }
    if (startupWorktreeContext) {
      config.setPendingStartupWorktreeNotice(
        buildStartupWorktreeNotice(startupWorktreeContext)
      );
      try {
        const startupWorktreePersist = await persistStartupWorktreeSidecar(
          config,
          startupWorktreeContext
        );
        if (startupWorktreePersist.overrodeResumedWorktree) {
          writeStderrLine(
            `--worktree overrode the resumed session's previous worktree "${startupWorktreePersist.overriddenSlug ?? "(unknown)"}". That worktree directory was left intact on disk.`
          );
        }
        config.setPendingStartupWorktreeNotice(
          buildStartupWorktreeNotice(
            startupWorktreeContext,
            startupWorktreePersist
          )
        );
      } catch (error) {
        debugLogger5.warn(
          `--worktree sidecar persist failed (non-fatal, notice preserved): ${error instanceof Error ? error.message : String(error)}`
        );
      }
    }
    registerCleanup(() => {
      try {
        const metrics = uiTelemetryService.getMetrics();
        const hasActivity = Object.values(metrics.models).some(
          (m) => m.api.totalRequests > 0
        );
        if (!hasActivity) return;
        persistSessionUsage({
          sessionId: config.getSessionId(),
          startTime: uiTelemetryService.getSessionStartTime(),
          endTime: /* @__PURE__ */ new Date(),
          project: config.getProjectRoot(),
          metrics
        });
      } catch {
      }
    });
    registerCleanup(() => config.shutdown());
    setupUncaughtExceptionHandler(config);
    startEarlyStartupPrefetches(config);
    const wasRaw = process.stdin.isRaw;
    let kittyProtocolDetectionComplete;
    let themeAutoDetectionComplete;
    if (config.isInteractive()) {
      registerCleanup(installInteractiveSignalHandlers(wasRaw));
    }
    if (config.isInteractive() && !wasRaw && process.stdin.isTTY) {
      const { startEarlyInputCapture, stopAndGetCapturedInput } = await import("./earlyInputCapture-JAKE2YML.js");
      const { detectAndEnableKittyProtocol } = await import("./kittyProtocolDetector-BFLAKYXH.js");
      process.stdin.setRawMode(true);
      startEarlyInputCapture();
      registerCleanup(() => stopAndGetCapturedInput());
      kittyProtocolDetectionComplete = detectAndEnableKittyProtocol();
      if (!configuredTheme || configuredTheme === AUTO_THEME_NAME) {
        themeAutoDetectionComplete = themeManager.resolveAutoThemeAsync().catch((err) => {
          debugLogger5.warn("Async theme auto-detection failed:", err);
        });
      }
    }
    if (config.isInteractive()) {
      const { setMaxSizedBoxDebugging } = await import("./MaxSizedBox-V7TPJ74G.js");
      setMaxSizedBoxDebugging(isDebugMode3);
    }
    const inputFormat = process.stdin.isTTY ? "text" /* TEXT */ : typeof config.getInputFormat === "function" ? config.getInputFormat() : "text" /* TEXT */;
    const { initializeApp } = await import("./initializer-KQWM74NL.js");
    let input = config.getQuestion();
    const hasRemoteInput = Boolean(config.getInputFile?.());
    const deferIdeConnection = config.isInteractive() && !config.getExperimentalZedIntegration() && !input && !hasRemoteInput;
    markAcpStartup("appInitializationStart");
    const initializationResult = await initializeApp(config, settings, {
      deferIdeConnection
    });
    markAcpStartup("appInitializationEnd");
    profileCheckpoint("after_initialize_app");
    if (config.getExperimentalZedIntegration()) {
      markAcpStartup("acpImportStart");
      const { runAcpAgent } = await import("./acpAgent-S5WBGKGR.js");
      markAcpStartup("acpImportEnd");
      await runAcpAgent(config, settings, argv, {
        privateParentCapability: isAcpMode ? privateAcpParentCapability : void 0
      });
      await runExitCleanup();
      process.exit(0);
    }
    const startupWarnings = [
      .../* @__PURE__ */ new Set([
        ...config.isSafeMode() ? [
          "\u26A0 SAFE MODE \u2014 all customizations disabled (hooks, extensions, skills, MCP servers, QWEN.md). Restart without --safe-mode to resume normal operation."
        ] : [],
        ...await getStartupWarnings(),
        ...await getUserStartupWarnings({
          workspaceRoot: process.cwd(),
          useRipgrep: settings.merged.tools?.useRipgrep ?? true,
          useBuiltinRipgrep: settings.merged.tools?.useBuiltinRipgrep ?? true
        }),
        ...getSettingsWarnings(settings),
        ...config.getWarnings(),
        ...config.getModelsConfig().getCurrentAuthType() === "qwen-oauth" /* QWEN_OAUTH */ ? [
          "Qwen OAuth free tier was discontinued on 2026-04-15. Run /auth to switch to Coding Plan or another provider."
        ] : []
      ])
    ];
    const emittedStartupWarnings = new Set(startupWarnings);
    for (const warning of startupWarnings) {
      writeStderrLine(warning);
    }
    profileCheckpoint("before_render");
    if (config.isInteractive()) {
      if (config.getJsonSchema?.()) {
        writeStderrLine(
          "Error: --json-schema is a headless-only flag. Provide a one-shot prompt via -p / --prompt or pipe one in via stdin."
        );
        await runExitCleanup();
        process.exit(1);
      }
      setInteractiveMode(true);
      await kittyProtocolDetectionComplete;
      await themeAutoDetectionComplete;
      const { startInteractiveUI } = await import("./startInteractiveUI-VQCI4UHT.js");
      await startInteractiveUI(
        config,
        settings,
        startupWarnings,
        process.cwd(),
        initializationResult,
        {
          postRenderConnectIde: deferIdeConnection,
          extensionRefreshState
        }
      );
      clearCorruptionEnvVars();
      return;
    }
    clearCorruptionEnvVars();
    if (config.getDebugMode()) {
      writeStderrLine("Debug mode enabled");
      if (isDebugLogFileEnabled()) {
        writeStderrLine(
          `Logging to: ${Storage.getDebugLogPath(config.getSessionId())}`
        );
      } else {
        writeStderrLine("Debug log file disabled by QWEN_DEBUG_LOG_FILE");
      }
      if (isDebugLoggingDegraded()) {
        writeStderrLine(
          "Warning: Debug logging is degraded (write failures occurred)"
        );
      }
    }
    if (!config.isInteractive()) {
      const yoloWarning = getHeadlessYoloSafetyWarning(config);
      if (yoloWarning) writeStderrLine(yoloWarning);
    }
    if (inputFormat !== "stream-json" /* STREAM_JSON */) {
      profileCheckpoint("config_initialize_start");
      await config.initialize();
      for (const warning of config.getWarnings()) {
        if (emittedStartupWarnings.has(warning)) continue;
        emittedStartupWarnings.add(warning);
        writeStderrLine(warning);
      }
      profileCheckpoint("config_initialize_end");
      await config.waitForMcpReady();
      const failedMcpServers = typeof config.getFailedMcpServerNames === "function" ? config.getFailedMcpServerNames() : [];
      if (failedMcpServers.length > 0) {
        writeStderrLine(
          `Warning: MCP server(s) failed to start: ${failedMcpServers.join(", ")}. Continuing with built-in tools and any servers that did connect. Re-run with QWEN_CODE_DEBUG=1 to see per-server reasons.`
        );
      }
      finalizeStartupProfile(config.getSessionId());
    }
    if (inputFormat !== "stream-json" /* STREAM_JSON */ && !process.stdin.isTTY) {
      const stdinData = await readStdin();
      if (stdinData) {
        input = `${stdinData}

${input}`;
      }
    }
    const { validateNonInteractiveAuth } = await import("./validateNonInterActiveAuth-DGVXMM23.js");
    const nonInteractiveConfig = await validateNonInteractiveAuth(
      settings.merged.security?.auth?.useExternal,
      config,
      settings
    );
    const prompt_id = createNonInteractivePromptId(config.getSessionId());
    if (inputFormat === "stream-json" /* STREAM_JSON */) {
      const trimmedInput = (input ?? "").trim();
      const { runNonInteractiveStreamJson } = await import("./session-XFRX4HF2.js");
      await runNonInteractiveStreamJson(
        nonInteractiveConfig,
        trimmedInput.length > 0 ? trimmedInput : "",
        settings
      );
      await runExitCleanup();
      process.exit(process.exitCode ?? 0);
    }
    if (!input) {
      writeStderrLine(
        `No input provided via stdin. Input can be provided by piping data into gemini or using the --prompt option.`
      );
      process.exit(1);
    }
    logUserPrompt(config, {
      "event.name": "user_prompt",
      "event.timestamp": (/* @__PURE__ */ new Date()).toISOString(),
      prompt: input,
      prompt_id,
      auth_type: config.getContentGeneratorConfig()?.authType,
      prompt_length: input.length
    });
    debugLogger5.debug(`Session ID: ${config.getSessionId()}`);
    const { runNonInteractive } = await import("./nonInteractiveCli-CK7PHMWC.js");
    const exitCode = await runNonInteractive(
      nonInteractiveConfig,
      settings,
      input,
      prompt_id
    );
    await runExitCleanup();
    process.exit(exitCode);
  }
}
__name(main, "main");
function createNonInteractivePromptId(sessionId) {
  return `${sessionId}########0`;
}
__name(createNonInteractivePromptId, "createNonInteractivePromptId");
function registerLspHotReload(config, registerCleanup2) {
  const lspClient = config.getLspClient?.();
  const runtimeConfig = config;
  const reinitializeLsp = runtimeConfig.reinitializeLsp;
  if (config.isLspEnabled?.() !== true || !lspClient?.reinitialize || !reinitializeLsp) {
    return;
  }
  const lspConfigWatcher = new LspConfigWatcher(config.getProjectRoot());
  debugLogger5.info(
    `Registering LSP config hot reload watcher for ${config.getProjectRoot()}`
  );
  lspConfigWatcher.startWatching(async (event) => {
    if (event.changeType === "invalid") {
      debugLogger5.warn(`Invalid LSP config file ${event.path}: ${event.error}`);
      appEvents.emit("log-error" /* LogError */, event.error);
      return;
    }
    debugLogger5.info(
      `Reloading LSP server settings: changeType=${event.changeType}, path=${event.path}`
    );
    let errorReported = false;
    try {
      const result = await reinitializeLsp();
      if (result) {
        const failedServers = getRuntimeReloadFailedNames(result.reconcile);
        debugLogger5.info(
          `Reloaded LSP server settings: added=${formatRuntimeReloadNames(
            result.reconcile.added
          )}, removed=${formatRuntimeReloadNames(
            result.reconcile.removed
          )}, restarted=${formatRuntimeReloadNames(
            result.reconcile.restarted
          )}, unchanged=${formatRuntimeReloadNames(
            result.reconcile.unchanged
          )}, failed=${formatRuntimeReloadNames(
            failedServers
          )}, skipped=${formatRuntimeReloadNames(
            result.skipped.map((server) => server.name)
          )}`
        );
        if (failedServers.length > 0) {
          appEvents.emit("lsp-status-changed" /* LspStatusChanged */);
          const changedServers = [
            ...result.reconcile.added,
            ...result.reconcile.removed,
            ...result.reconcile.restarted
          ];
          const message = `LSP reload partially completed: changed=${formatRuntimeReloadNames(
            changedServers
          )}, failed=${formatRuntimeReloadNames(
            failedServers
          )}. Run with --debug for details.`;
          appEvents.emit("log-error" /* LogError */, message);
          errorReported = true;
          throw new Error(message);
        }
      } else {
        debugLogger5.info(
          "Skipped LSP server settings reload because LSP is disabled or no client is available"
        );
      }
      appEvents.emit("lsp-status-changed" /* LspStatusChanged */);
    } catch (error) {
      debugLogger5.warn("Failed to reload LSP server settings:", error);
      if (!errorReported) {
        const message = error instanceof Error ? `Failed to reload LSP server settings: ${error.message}. Some LSP servers may have been partially updated. Run with --debug for details.` : "Failed to reload LSP server settings; some LSP servers may have been partially updated. Run with --debug for details.";
        appEvents.emit("log-error" /* LogError */, message);
      }
      throw error;
    }
  });
  registerCleanup2(() => lspConfigWatcher.stopWatching());
}
__name(registerLspHotReload, "registerLspHotReload");
function formatRuntimeReloadNames(names) {
  return names.length === 0 ? "<none>" : names.join(",");
}
__name(formatRuntimeReloadNames, "formatRuntimeReloadNames");
function getRuntimeReloadFailedNames(reconcile) {
  return reconcile.failed ?? [];
}
__name(getRuntimeReloadFailedNames, "getRuntimeReloadFailedNames");
export {
  createNonInteractivePromptId,
  main,
  registerLspHotReload,
  setupUncaughtExceptionHandler,
  setupUnhandledRejectionHandler,
  validateDnsResolutionOrder
};
/**
 * @license
 * Copyright 2025 Qwen
 * SPDX-License-Identifier: Apache-2.0
 */
/**
 * @license
 * Copyright 2025 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
